Instead, set ctx.type = LAB_NODE_LAYER_SURFACE for both layer-surfaces
and layer-subsurfaces.
This patch preserves the existing behaviors:
- Pressing a subsurface of an on-demand layer-surface gives pointer
focus to the subsurface, but gives keyboard focus to the parent
layer-surface (related: a5fcbfaf).
- Pressing a subsurface of a layer-surface doesn't close a popup
(related: a89bcc3c).
struct ssd_part and struct node_descriptor seem to have essentially the
same purpose: tag a wlr_scene_node with some extra data indicating what
we're using it for.
Also, as with enum ssd_part_type (now lab_node_type), ssd_part is used
for several types of nodes that are not part of SSD.
So instead of the current chaining (node_descriptor -> ssd_part), let's
flatten/unify the two structs.
In detail:
- First, merge node_descriptor_type into lab_node_type.
- Add a separate view pointer in node_descriptor, since in the case of
SSD buttons we need separate view and button data pointers.
- Rename ssd_part_button to simply ssd_button. It no longer contains
an ssd_part as base.
- Add node_try_ssd_button_from_node() which replaces
node_ssd_part_from_node() + button_try_from_ssd_part().
- Factor out ssd_button_free() to be called in node descriptor destroy.
- Finally, get_cursor_context() needs a little reorganization to handle
the unified structs.
Overall, this simplifies the code a bit, and in my opinion makes it
easier to understand. No functional change intended.
ssd_part_type contains several node types that are not actually part of
server-side decorations (ROOT, MENU, OSD, etc.)
Rename it accordingly and move it to a common location, along with some
related conversion/comparison functions.
view_restore_to() (which is just set_maximized() + view_move_resize())
hasn't aged well and doesn't line up with typical usage anymore:
- it's missing view_set_untiled(), which has to be called separately
- it always forces view_move_resize() even when that's not needed
- it doesn't allow un-maximizing only one axis (see next commit)
- the fullscreen check is unnecessary (already checked in callers)
Eliminate it and just expose view_set_maximized() instead.
No functional change intended in this commit.
- add LAB_WINDOW_TYPE_INVALID in place of literal -1
- document more clearly that enum lab_view_criteria is a bitset
- other one-off replacements of integer values/types for consistency
Note: variables of type enum lab_view_criteria are already used
extensively throughout the code to contain combinations of the declared
enum values. I am not introducing any new usage here, just changing the
single uint32_t to be consistent with all the other usages.
I like the new common/edge.h. I don't like how inconsistently we use it.
Current situation:
- enum wlr_edges and wlr_direction are designed to be used as bitset,
and are defined compatibly
- enum lab_edge is *also* designed to be used as bitset, but
incompatible with the others (LEFT/RIGHT come before UP/DOWN)
- we use an inconsistent mix of all three *AND* uint32_t (usually with
the WLR_EDGE constants rather than the LAB_EDGE constants), and
convert between them on an ad-hoc basis, sometimes implicitly
Let's clean this up:
- reorder enum lab_edge to be compatible with the two wlr enums
(check this by static_assert)
- use TOP/BOTTOM naming rather than UP/DOWN (matches wlr_edges)
- add constants for the remaining possible combinations of the 4 edges
- use lab_edge for all internal edge/direction fields, consistently
- add lab_edge_is_cardinal() as a sanity check before casting to
enum wlr_direction, and then eliminate all of direction.c/h
Instead of "enum wlr_edges direction", we now have
"enum lab_edge direction" which is not that much better. At least we
are now clear that we're overloading one enum with two meanings.
This is a common practice in C projects, which simply enforces that
each header must compile cleanly without implicit dependencies on
other headers (see also the previous commit).
Hi-res mice produces mulitple scroll events with `delta_discrete` != 0
during a single "click". This patch makes them trigger `Scroll` actions
only when the accumulated `delta_discrete` exceeds 120 (= 1 click).
See https://lists.freedesktop.org/archives/wayland-devel/2019-April/040377.html
for how hi-res scroll events are reported.
Omit cursor notifications from a pointer when a tablet
tool (stylus/pen) is in proximity. This is equivalent
to `handle_request_set_cursor()` and prevents a resize
cursor for out-of-surface scrolling with a tablet tool in
recent GTK4 (which uses the cursor shape protocol).
Before this patch, when followMouse and followMouseRequiresMovement are
both yes, we set the keyboard focus when the cursor moves within an
unfocused surface. However, kwin, xfwm4 and openbox all set keyboard focus
only when the cursor enters a surface.
This ensures all event listeners are removed before the emitting
wlroots object is being destroyed. This will be enforced with asserts
in wlroots 0.19 but there is no reason to not do it right now either.
This change in wlroots 0.19 is implemented via commit
8f56f7ca43257cc05c7c4eb57a0f541e05cf9a79
"Assert (almost all) signals have no attached listeners on destroy"
This commit moves the check against server->input_mode from the callers
of desktop_focus_view() into desktop_focus_view() itself. This
eliminates code duplications and makes it harder to mess up the window
stacking order while window switching.
I also added the same check in view_minimize() so that minimize requests
from panels never messes up the window stacking order (I think only this
should be described in the release note).
This commit restores the check removed in 7a6ecca.
Without the check, if followMouse="yes" and
followMouseRequiresMovement="no", osd_update() => cursor_update_focus() =>
desktop_focus_view() unexpectedly un-minimizes the window on cursor even
when the window is just a preview of window switcher. This caused some
strange behavior that a minimized window selected with window switcher is
immediately hidden after finishing window switching.
The protocol states that the wl_pointer motion coordinates must be
relative to the focused surface (e.g. the surface that last received
a wl_pointer enter event).
Before this patch, the coordinates were relative to the toplevel
surface instead, resulting in subsurface events having the wrong
coordinates when pressing a button over a subsurface and moving
the cursor outside of that subsurface.
Fixes: #2542
Prior to this commit, when we receive fine-grained scroll events from
touchpads that are bound to any mousebind, we leaked the scroll events to
the client unless the accumulated scroll delta exceeds the fixed threshold.
This was annoying for example when a user wants to ZoomIn/Out with
W-Up/Down mousebinds with a touchpad.
So this commit fixes it by not leaking the scroll events nor executing
actions when the accumulated delta doesn't exceed the threshold.
And make mousebind handlers use that one.
Also remove keyboard_any_modifiers_pressed() and replace its usage
with the new function.
Without this patch we would only request the modifier state of the
keyboard group which makes mousebinds involving keyboard modifiers
break for virtual keyboards like when using wayvnc. Same story for
hiding the workspace overlay or snapping to regions.
Fixes: #2511
On reconfigure, we should send wl_pointer.{leave,enter} events if the
cursor is on an application surface to let the application update the
cursor, but bad788cc prevented these events from being sent.
This commit cleans up the comments and cruft from e45fe08.
Background:
- With e45fe08, the keyboard focus is always moved to the switched window
on finishing window switcher, even with <focus followMouse="yes">.
Since followMouseRequiresMovement was not implemented at that time
(behaved like it was always "no"), e45fe08 was necessary to allow users
users who use followMouse="yes" to move the keyboard focus with window
switcher.
- 9a9e20d added followMouseRequiresMovement, but it kept the behavior
described above even with followMouse="yes" and
followMouseRequiresMovement="no".
- 398b80b accidentally invalidated e45fe08, which means the keyboard focus
is now always moved to the window below the cursor on finishing window
switcher with followMouse="yes" and followMouseRequiresMovement="no".
Although the invalidation was a accident, I think always setting the
keyboard focus on the window below the cursor is what users expect from
followMouse="yes" and followMouseRequiresMovement="no".
The previous revert fixed the problem of stuck modifier keys with
keybinds in Blender, but made Firefox show its menu bar with Alt-*
keybinds. This is fundamentally inevitable due to the limitation of
wayland protocol, but at least for the default Alt-Tab keybind for
window switcher, we can mitigate this problem by clearing the keyboard
focus when the window switcher is activated. This is what KWin does, and
we decided to follow that.
So in this commit, keyboard and pointer focus are temporarily cleared
while Move/Resize, window switcher and menu interactions and restored
after them. We slightly deviate from KWin as KWin doesn't clear the
keyboard focus while Move/Resize, but it solves our existing problem
that Firefox shows its menu bar after dragging it with default Alt-Drag
mousebind, and this is what Mutter does.
We considered other solutions, but they don't work well:
1. Send wl_keyboard.{leave,enter} every time keybinds/mousebinds are
triggered. This solves the Firefox's menu bar problem, but that
sounds like a workaround and sending unnecessary events every time is
not desirable.
2. Send release events for both modifiers and keys even when they are
bound to keybinds. This is what Mutter is doing, but it looks like an
implementation issue and violates wayland protocol.
Before this commit, the pointer focus is cleared when a menu is closed
by clicking its border. This is because get_cursor_context() returns
type=LAB_SSD_NONE when the cursor is on the menu border and
cursor_update_common() clears the pointer focus. This commit fixes this
by replacing cursor_update_common() with cursor_update_focus(), which
calls get_cursor_context() again after the menu scene-node is hidden.
When `wlr_seat_pointer_notify_button()` is called on a button press event,
that funtion must also be called on the subsequent button release event
because otherwise wlroots thinks the button is kept pressed and it
causes issues with validating DnD requests from clients, where only one
button must be pressed. This was the case when a CSD client opens a
client-menu via `show_window_menu` request after pressing its window with
the right button because we were always not notifying button release
events while a menu is open.
So let's keep track of bound (pressed but not notified) buttons and notify
button release events only when the button is not bound, like we are doing
for key-state.
For `Drag` mousebinds, `pressed_in_context` is set by
`cursor_process_button_press()` and cleared by `cursor_process_motion()`
which runs actions bound to them. However, when `cursor_process_motion()`
is called while interactive move/resize, it doesn't clear
`pressed_in_context` due to the early-return and the `Drag` mousebinds are
unexpectedly executed on another call to `cursor_process_motion()` after
the interactive move/resize is finished by button release, even when the
button is not pressed.
So this commit fixes it by always clearing `pressed_in_context` on button
releases.
Before this commit, we assumed `ShowMenu` action is not bound to any
buttons other than window menu button and always place the client-menu
under the window-menu button when atCursor="no". Also, it was going to be
difficult to distinguish whether the action is executed from the window
menu button or the window icon, which will be added soon.
This commit fixes it to open the menu under the actually-clicked button by
passing `cursor_context` to `actions_run()`, with some refactoring:
- `seat->pressed.resize_edges` is removed and it's calculated from the
cursor position and `seat->pressed.type` just before running Resize
action. This slightly changes the existing logic to determine the
resizing edges with Alt-Right + Drag mousebinding, but
`seat->pressed.type` is still stored on button press so it doesn't bring
back the issue #543.
- `seat->pressed.toplevel` is removed and `get_toplevel()` in
`update_pressed_surface()` may be called more often, but its overhead
will be negligible.
When labwc un-tiles views, it generally changes their size, which sends
a configure request to the client. However, because the view has been
disabled in the wlroots scene, it will not receive and process the
configure when labwc expects. Instead, the handling will be deferred
until the user unshades the view at some arbitrary time in the future,
resulting in labwc registering complains like
[../src/xdg.c:239] client did not respond to configure request in 100 ms
Furthermore, the reconfigure will still generally produce flicker (as
the view opens in its tiled size and then jumps to its natural
geometry). Because skipping the unshade might cause client problems and
doesn't eliminate the problem it sought to resolve, let's revert this.
This reverts commit 2e19bd4d5b.
Applies drag resistance unidirectionally for horizontally/vertically
maximized windows, allowing them to be dragged without being untiled
immediately. When the distance of cursor movement orthogonal to the
maximized direction exceeds <resistance><unMaximizeThreshold>.
While dragging a horizontally/vertically maximized window, edge/region
snapping is disabled to prevent unintentional snapping and overlays.
This commit also includes some refactoring to simplify the logic.