Add optional drop-shadows to windows using server-side decoration.
Shadows can be enabled/disabled rc.xml and their appearance configured
in themerc. The default is no shadows to preserve current behaviour.
The shadows are drawn in fixed corner and edge buffers shared between
all windows, the edges are scaled to size depending on the size of each
window. Two sets of buffers are used to give the different appearances
for active and inactive windows. I use separate corner/edge buffers for
a few reasons:
- It avoids needing to store a separate large shadow buffer per window
- It avoids needing to redraw the shadows when the window is being
resized
- Compositing the shadows onto the desktop should be faster as there are
overall fewer pixels to blend, and scaling up the edge buffers only
requires reading a tiny buffer which is then replicated.
This builds on the work of @Consolatis in #1018.
Co-authored-by: Consolatis <35009135+Consolatis@users.noreply.github.com>
Co-authored-by: Andrew J. Hesford <ajh@sideband.org>
This is a useful (if lesser-known) feature of at least a few popular X11
window managers, for example Openbox and XFWM4. Typically right-click on
the maximize button toggles horizontal maximize, while middle-click
toggles vertical maximize.
Support in labwc uses the same configuration syntax as Openbox, where the
Maximize/ToggleMaximize actions have an optional "direction" argument:
horizontal, vertical, or both (default). The default mouse bindings match
the XFWM4 defaults (not sure what Openbox has by default).
Most of the external protocols still assume "maximized" is a Boolean,
which is no longer true internally. For the sake of the outside world,
a view is only "maximized" if maximized in both directions.
Internally, I've taken the following approach:
- SSD code decorates the view as "maximized" (i.e. hiding borders) only
if maximized in both directions.
- Layout code (interactive move/resize, tiling, etc.) generally treats
the view as "maximized" (with the restrictions that entails) if
maximized in either direction. For example, moving a vertically-
maximized view first restores the natural geometry (this differs from
Openbox, which instead allows the view to move only horizontally.)
v2: use enum view_axis for view->maximized
v3:
- update docs
- allow resizing if partly maximized
- add TODOs & corrections noted by Consolatis
Before this patch we were using the internal .enabled flag of the titlebar
tree node. This failed due to ssd_thickness() not having view->ssd assigned
when initially called. Instead of assigning view->ssd within ssd_create()
we just always use the view boolean flag directly. This fixes an issue
where a border-only view that has been snapped to an edge or region would
have a gap in the size of the titlebar on top after a Reconfigure.
Fixes#1083
The previous PR introduced an issue with tiling based actions
like SnapToEdge and SnapToRegion using outdated SSD margin
values when called via keybind while maximized. That resulted
in wrong offsets for the tiled windows.
This commit restores the functionality by forcing a re-calculation
of the SSD margin when changing the maximized state.
Thanks to @Flrian for reporting the issue via IRC.
With the new keepBorder option enabled, the
ToggleDecorations action now has 3 states:
- the first time only disables the titlebar
- the second time disables the whole SSD
- the third time enables the whole SSD again
When the keepBorder action is disabled, the old 2-state
behavior is restored, e.g. the ToggleDecorations action
only toggles between on and off.
Fixes#813
- Store a pointer to the `struct view` in `struct ssd`
- Pass `struct ssd *` instead of `struct view *` to ssd functions
- Add `ssd_get_margin()` convenience function
- Minimize includes in `ssd.h`
- Avoid repetitive `view->ssd.margin` pattern
- Use `struct ssd *` or `const struct ssd *` rather than `struct view *`
where convenient
Part of the motivation is to make it easier to separate `struct ssd`
from `struct view` in a future commit.
- Update `ssd.state` in `ssd_create()` to avoid doing unnecessary work in
the next call to `ssd_update_geometry()`
- Reset `ssd.margin` in `ssd_destroy()` to avoid accidentally using stale
values
- Add `active` argument for consistency with `ssd_set_active()`
- `assert()` that `ssd_create()` is not called twice without an
`ssd_destroy()` in between
Gather related logic from `reload_config_and_theme()` in `server.c` and
`ssd_reload()` in `ssd.c` into a new function, `view_reload_ssd()`.
Also drop the `view->mapped` check since we want to update any view that
has SSD nodes created, mapped or not.
`view_set_decorations()` now calls `ssd_create()` and `ssd_destroy()`
explicitly to enable/disable decorations. As a result, the implicit
enable/disable logic in `ssd_update_geometry()` is no longer needed.
IMHO it encourages better design (by making dependencies more obvious)
to have source file/header file pairs like view.c/view.h, rather than a
monolithic header like labwc.h with everything in it.
I don't think we need to break up all of labwc.h at once, but maybe we
can start pulling it apart bit by bit as it's convenient.
Also:
- Move "struct border" to ssd.h so that view.h can use it without pulling
in all of labwc.h.
- Add a missing required #include within scaled_font_buffer.h (forward
declaration of "struct font" is not enough).
map() in xwayland.c called ssd_create() but did not call
view_apply_maximized_geometry() afterward, resulting in the
decorations being displayed off-screen.
Rather than calling view_apply_maximized_geometry() in more places,
let's reuse the existing call in view_set_decorations(), and extend
ssd_update_geometry() to call ssd_create() when needed.
Corner buttons (WINDOW_MENU and CLOSE) are one more level down in
the scene-tree (see add_scene_button_corner() in ssd_part.c).
This fixes a minor issue where, when right-clicking on the CLOSE
button, the client-menu would be displayed in the wrong location.
... and use Title for the Drag (Move) and DoubleClick (Maximize)
titlebar actions, which are unexpected when the cursor is over one
of the window buttons.