tokyo4j [Mon, 6 May 2024 14:53:18 +0000 (23:53 +0900)]
seat: prevent Chromium from crashing when active keyboard is gone
Chromium (and slurp) expect wl_keyboard.keymap event to be sent before
wl_keyboard.modifiers event. Normally, wl_keyboard.keymap event is sent
on the client first obtains wl_keyboard with wl_seat.get_keyboard
request.
However, after the active (especially virtual) keyboard is destroyed,
wlroots doesn't respond to wl_seat.get_keyboard request with
wl_keyboard.keymap event since there's no active keyboard on the seat.
Therefore, if we run commands like "sleep 2; wtype hello; chromium", the
active keyboard is destroyed when wtype finishes and
wl_keyboard.modifiers event is sent to Chromium when Chromium first maps
the surface and the keyboard focus is moved to it, then Chromium crashes.
With slurp, fcitx5 and multi-monitor setup, a similar thing happens.
When slurp first creates the layer-shell surfaces, the focus moves to it
(without wl_keyboard.enter though), and fcitx5 is transiently deactivated
and it destroys the virtual keyboard. Then when slurp maps those
surfaces, the focus moves between them again and wl_keyboard.modifiers
event is sent, thus slurp crashes.
So with this commit, when the active keyboard on the seat is destroyed,
the keyboard from the keyboard group is set to the seat instead so
wlroots can respond to wl_seat.get_keyboard request with
wl_keyboard.keymap.
Clients can ignore the requsted geometry and negative widths could be
passed to `wlr_scene_rect_set_size()` in `ssd_titlebar_update()` or in
`ssd_border_update()`.
cursor: do action/close menu in successive press & release
In OpenBox, when cursor button is pressed to open menu, a subsequent
cursor button release can perform actions or close the menu.
This commit makes labwc follow that behavior.
David Turner [Mon, 22 Apr 2024 18:27:53 +0000 (19:27 +0100)]
ssd: add window drop-shadows (#1648)
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.
overlay: allow to draw both/either of filled/outlined rectangle
Filled/outlined rectangles shown as snapping overlay are now enabled/disabled
independently with `snapping.overlay.[region|edge].bg.enabled` and
`snapping.overlay.[region|edge].border.enabled`.
To keep the default behavior, `*.bg.enabled` is yes and `*.border.enabled` is
no for hardware-based renderers, while `*.bg.enabled` is no and
`*.border.enabled` is yes for software-based (pixman) renderer.
Users can now use a filled rectangle as an overlay even with pixman renderer.
However, this may severely impact performance when used with translucent
`snapping.overlay.[region|edge].bg.color`.
This commit includes a refactor to use substruct `theme_snapping_overlay`
inside `theme` in order to pass it to `create_overlay_rect()` in a cleaner way.
Breaking changes is:
- `snapping.overlay.[region|edge].fill` is now removed.
Replace "preview" in rc.xml and themerc with "overlay" since "preview" sounds
like it shows the window content.
Breaking changes are:
- `snapping.preview.*` in themerc is now replaced with `snapping.overlay`.
- `<snapping><preview>` in rc.xml is now replaced with `<snapping><overlay>`.
Before this patch, labwc would happily kill itself when the user
called the `Kill` action when any xwayland view had focus.
The reason this happened was that wlroots creates the xwayland
wayland client via socketpair() and thus a lookup of the pid
of the socket connection would return the pid of labwc itself.
This patch fixes that by implementing different pid lookup
mechanisms based on the view implementation backend.
This allows to ignore X11 client side configure requests
like positioning and resizing and can be used to fight
some X11 applications that persist to have their windows
spawn at specific places and sizes.
IME: prevent virtual keyboard from unintentionally releasing modifiers (#1721)
When Fcitx5 is activated, it creates a virtual keyboard to send keycodes to
applications, then creates a keyboard grab to capture keycodes the user typed.
Before this commit, we set keyboard grab's modifiers to that of currently
active keyboard, which is the virtual keyboard created in the case described
above. However, since the modifiers of the virtual keyboard is empty at first,
we actually set empty modifiers, even when the user is pressing modifiers.
Then, Fcitx5 assumes no modifiers is pressed and redirect the modifier state
back to the compositor via the virtual keyboard. As a result, when the focus
is switched between windows by workspace-switcher, the workspace-switcher is
immediately terminated.
To fix this issue, with this commit, the modifier state of the currently active
keyboard is not set to the keyboard grab if the keyboard is a virtual keyboard
created by the same input-method client.
John Lindgren [Thu, 18 Apr 2024 01:25:40 +0000 (21:25 -0400)]
add .clang-format (with a disclaimer)
.clang-format gets picked up nowadays by some IDEs (tested Qt Creator)
for auto-formatting aids. With the large caveat that it's not 100%
accurate to labwc's preferred coding style, I've found that this config
gets it right 90% of the time, which is enough to be helpful.
I added a prominent disclaimer comment to the top of the file to warn
people away from relying completely on clang-format. This isn't meant
to replace manual attention to formatting details (or to replace
./scripts/check) but I think it doesn't hurt.
Consolatis [Sat, 16 Mar 2024 18:03:06 +0000 (19:03 +0100)]
treewide: properly clear the buffer
Before this patch, the OSD would repeat the last buffer
content in case the new buffer content would be empty.
This was mostly happening for the `title` OSD field that is intended
to be empty when it matches the app_id / WM_CLASS of the application.
Due to only buffer.len being reset but its internal allocations being
untouched, buffer.buf would still carry the old data.
This patch fixes it by also overwriting the first byte in the buffer
allocation with '\0' via the new `buf_clear()` function.
Do the same for buf_expand_shell_variables() although that one should
have been fine before as it always writes new data to the buffer.
Johan Malm [Sat, 9 Mar 2024 17:12:54 +0000 (17:12 +0000)]
Add -S|--session <command> option
...to start <command> on startup and to terminate the compositor when
<command> exits.
This is useful for session management as it allows the session client (for
example `lxqt-session`) to terminate labwc - be exiting itself.
Under X, xinit starts the server and keeps it alive for as long as
lxqt-session runs. Thus either the session client starts the Window
Manager, or the Window Manager can be launched independently first. On
Wayland, the Compositor is both Display Server and Window Manager, so the
described session management mechanisms do not work because the Compositor
needs to be running before the session can function.
As some session clients support both X11 and Wayland, this command line
option avoids re-writes and fragmentation.
snap: cache and ignore last-snapped edge when growing or shrinking
When growing or shrinking a view by snapping to an edge, a client may
ignore the requested size and instead keep its original size or
substitute a different (possibly constrained) size. In this case, the
view may not actually contact the snapped edge, and a subsequent snap
attempt will just keep re-trying (and failing) to contact the same ege.
To mitigate this, remember the last-snapped view, snapping direction and
offset of the snapping edge in snap.c; when re-attempting a snap for the
same view in the same direction, ignore the edge that was last "hit", to
allow snapping to progress beyond the problematic edge.
This fixes an issue detected by the static analyzer.
It currently is not a real bug but it could become
one in the future if `add_toggled_icon()` is called
before `add_scene_button()`.
Rather than having `add_toggled_icon()` go through
the list, find the root button and then fetch its
node descriptor just supply the button as argument.
Fill with the background color first only if the background color is
opaque. This is necessary for subpixel rendering to work properly (it
does not work on top of transparency).
However, if the background color is not opaque, leave the buffer
unfilled (completely transparent) since the background is already
rendered by the scene element underneath. In this case we have to
disable subpixel rendering.
wlr_scene_rects expect their color to be pre-multiplied
while cairo_set_source_rgba() expects them to not be
pre-multiplied. With this patch we now use premultiplied
colors internally by default and then reverse it when
setting cairo colors.
This ensures the titlebar uses a consistent color in case
it was defined with some transparency by the user.
Johan Malm [Sat, 6 Apr 2024 20:46:17 +0000 (21:46 +0100)]
cursor: fix dnd bug
...where dnd does not finish properly on cursor-button-release if there
is no surface under the cursor such as on the desktop when no background
client is running.
cursor: send release event to CSD client before finishing window dragging
This fixes that, when a CSD window is dragged into below waybar and the cursor
button is released, the cursor focus is moved from the CSD window to waybar and
a release event is sent to waybar, not original CSD window.
Johan Malm [Mon, 25 Mar 2024 21:49:46 +0000 (21:49 +0000)]
cursor: validate double-click against SSD part type
...because click on different parts of a client should not be
interpreted as a double click.
Previously only cursor-button and view were validated to be the same
between clicks. This resulted in, for example a click on the client
surface itself quickly followed by a click on the SSD titlebar being
interpreted as a double-click on the titlebar.
Johan Malm [Sun, 24 Mar 2024 19:31:29 +0000 (19:31 +0000)]
layer: try to set keyboard focus on map
...for the following reasons:
1. We interpret 'normal input-focus semantics' for clients with on-demand
keyboard interactivity to means that a surface receives input focus on
cursor-button-press AND on map (the latter previously missing), just
like a normal window would. In this regard, we do not differentiate
between layers.
2. Most layer-surfaces set the keyboard interactivity at a similar time to
their first (and normally only) map, so the absence of an explicit
attempt to focus on map does not make a difference. However, for a
long-running layer-shell client (such as lxqt-runner) which sets the
interactivity on launch and then maps/unmaps many times throughout its
lifetime, a specific focus-attempt is required on map to avoid the
client itself having to keep resetting its interactivity to grab the
keyboard on map.
3. Compositors like sway and river process focus (for clients with
keyboard-interactivity) in their map-handlers, so this makes for a
common approach.
Johan Malm [Sun, 17 Mar 2024 21:06:46 +0000 (21:06 +0000)]
xwayland: fix segv bug when starting game
...for example `Fall Guys`. It is believed to be caused by setting
override-redirect on an xwayland-surface with a child window, thus
breaking the way root-toplevels are obtained.
```
(threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0)
at pthread_kill.c:44
at pthread_kill.c:78
(fmt=0x7739d9f9bb68 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=assertion@entry=0x5a76573f9222 "root", file=file@entry=0x5a76573f9606 "../labwc/src/view.c", line=line@entry=2013, function=function@entry=0x5a7657400320 <__PRETTY_FUNCTION__.14> "view_move_to_front") at assert.c:94
(assertion=assertion@entry=0x5a76573f9222 "root", file=file@entry=0x5a76573f9606 "../labwc/src/view.c", line=line@entry=2013, function=function@entry=0x5a7657400320 <__PRETTY_FUNCTION__.14> "view_move_to_front") at assert.c:103
at ../labwc/src/view.c:2013
at ../labwc/src/view-impl-common.c:30
at ../labwc/src/xwayland.c:677
at ../wayland-1.22.0/src/wayland-server.c:2241
(signal=signal@entry=0x5a7659025160, data=data@entry=0x5a7659024e90)
at ../wayland-1.22.0/src/wayland-server.c:2241
at ../subprojects/wlroots/types/wlr_compositor.c:493
(cif=cif@entry=0x7ffc74d32530, fn=<optimized out>, rvalue=<optimized out>, avalue=<optimized out>, closure=closure@entry=0x0) at ../src/x86/ffi64.c:673
(cif=cif@entry=0x7ffc74d32530, fn=<optimized out>, rvalue=rvalue@entry=0x0, avalue=avalue@entry=0x7ffc74d32600) at ../src/x86/ffi64.c:710
(closure=closure@entry=0x5a7658f5adc0, target=<optimized out>,
target@entry=0x5a7659025240, opcode=opcode@entry=6, data=<optimized out>,
data@entry=0x5a7658609820, flags=2) at ../wayland-1.22.0/src/connection.c:1025
(fd=<optimized out>, mask=<optimized out>, data=<optimized out>)
at ../wayland-1.22.0/src/wayland-server.c:438
(loop=0x5a7657816e60, timeout=timeout@entry=-1)
at ../wayland-1.22.0/src/event-loop.c:1027
at ../wayland-1.22.0/src/wayland-server.c:1493
at ../labwc/src/main.c:179
```
Johan Malm [Sat, 9 Mar 2024 15:03:26 +0000 (15:03 +0000)]
layer: change focus better on 'none' keyboard-interactivity request
...and on unmap.
Add `try_to_focus_next_layer_or_toplevel()` which does the following
(in order of precedence):
- Give focus to last added overlay/top layer-shell client with exclusive
interactivity on the output nearest the pointer (normally the one where
the users is currently working). The reason for not considering clients
on all outputs is that giving focus to a client on another output may be
confusing to the user.
- Give focus to topmost toplevel if one exists (this was done previously
anyway).
Johan Malm [Sat, 9 Mar 2024 10:48:52 +0000 (10:48 +0000)]
cursor: use layer_try_set_focus() on press
This means that the logic described in 2ff026b will be used when a
layer-surface is pressed on with a cursor button. For example, a surface
with on-demand keyboard interactivity will not steal focus from a client
with exclusive keyboard interactivity.
Johan Malm [Sat, 9 Mar 2024 10:31:47 +0000 (10:31 +0000)]
layer: change logic for giving keyboard-interactivity
Use the following logic:
- Exclusive: Grant regardless of layer (previously it was only given if
in top or overlay layers) AND grant if in the same or higher layer
(nearer overlay) compared with other clients with exclusive
interactivity.
- On-demand: Grant only if no other layer-shell client has exclusive
keyboard interactivity. Previously it was treated the same as
exclusive.
- None: Unset focus if the commit associated with the 'none' came from
the currently focused layer. Previously it was just unset regardless.
John Lindgren [Sun, 17 Mar 2024 20:16:24 +0000 (16:16 -0400)]
xwayland: exclude unfocusable views from wlr-foreign-toplevel
These views (notifications, floating toolbars, etc.) should not be
shown in taskbars/docks/etc. (which are the stated use-case of the
wlr-foreign-toplevel protocol).
John Lindgren [Sun, 17 Mar 2024 02:20:40 +0000 (22:20 -0400)]
common: render text buffers with opaque background
After a roundabout discussion[1] with wlroots devs, it's become apparent
that subpixel text rendering (a.k.a. "ClearType") does not work properly
when rendering over a transparent background, as labwc currently does.
Basically it comes down to the fact that the color of semi-transparent
pixels (which is adjusted redder or bluer to compensate for RGB subpixel
alignment) depends somewhat on background color. When rendering over
transparency, the text engine doesn't know the intended background color
and can't adjust the pixel colors correctly.
With Pango/Cairo, the end result can range from grayscale rendering (no
subpixel rendering at all) to wrong/oversaturated colors (for example,
bright pink pixels when rendering white text on blue background).
This change solves the issue by first filling the text buffer with an
opaque background color before rendering the text over it. Currently,
this is easy since the background is always a solid color. It may be a
little more complex (but doable) if we implement gradients in future.
Note that GTK 4 (and to some degree, recent versions of Microsoft
Windows) avoid this issue by disabling subpixel rendering altogether. I
would much prefer that labwc NOT do this -- it results in noticeably
blurrier text on non-retina LCD screens, which are still common.
Consolatis [Sat, 16 Mar 2024 17:16:44 +0000 (18:16 +0100)]
CI: ensure Void has a font installed
Otherwise the runtime test randomly fails due to
strange pango behavior. This is a workaround for
the issue and not a permanent fix.
A full investigation into pango internals is required
to figure out why `pango_layout_get_extents()` returns
invalid data after the first call. See PR #1627 for a
testcase.