From cc0e2769d9496b601be3cd502f73f3340ce6873c Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Tue, 24 May 2022 13:02:51 +0200 Subject: [PATCH] src/cursor.c: Fix branch condition for out-of-view selecting/dragging Instead of using the stored view for comparison use the actual surface. Before this patch, there were situations where the branch intended for out-of-window text selection / scrollbar dragging was used even though the cursor never left the surface. Partly fixes #340 Fixes #347 Backport of 6dd290afc9fd009a6631df4a057f385d1c01a403 --- include/labwc.h | 11 +++++++---- src/cursor.c | 26 +++++++++++++++++--------- src/xdg.c | 5 +++-- src/xwayland.c | 5 +++-- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/include/labwc.h b/include/labwc.h index ff74ef72..2a081a89 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -80,16 +80,19 @@ struct seat { struct wlr_layer_surface_v1 *focused_layer; /** - * active_view will usually be NULL and is only set on button press - * while the mouse is over a view surface and reset to NULL on button - * release. + * pressed view/surface will usually be NULL and is only set on button + * press while the mouse is over a view surface and reset to NULL on + * button release. * It is used to send cursor motion events to a surface even though * the cursor has left the surface in the meantime. * * This allows to keep dragging a scrollbar or selecting text even * when moving outside of the window. */ - struct view *active_view; + struct { + struct view *view; + struct wlr_surface *surface; + } pressed; struct wl_client *active_client_while_inhibited; struct wl_list inputs; diff --git a/src/cursor.c b/src/cursor.c index 94c79f0d..0c946c52 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -296,22 +296,27 @@ process_cursor_motion(struct server *server, uint32_t time) last_button_hover = LAB_SSD_NONE; } - if (server->seat.active_view && !server->seat.drag_icon) { + if (server->seat.pressed.surface && + server->seat.pressed.surface != surface && + !server->seat.drag_icon) { /* * Button has been pressed while over a view surface * and is still held down. Just send the adjusted motion * events to the focused surface so we can keep scrolling * or selecting text even if the cursor moves outside of * the surface. + * + * TODO: This seems to miss calculations for invisible CSD borders. + * Tracked at https://github.com/labwc/labwc/issues/340 */ - view = server->seat.active_view; - double sx = server->seat.cursor->x - view->x; - double sy = server->seat.cursor->y - view->y; + view = server->seat.pressed.view; + sx = server->seat.cursor->x - view->x; + sy = server->seat.cursor->y - view->y; sx = sx < 0 ? 0 : (sx > view->w ? view->w : sx); sy = sy < 0 ? 0 : (sy > view->h ? view->h : sy); wlr_seat_pointer_notify_motion(server->seat.seat, time, sx, sy); - } else if (surface && - !input_inhibit_blocks_surface(&server->seat, surface->resource)) { + } else if (surface && !input_inhibit_blocks_surface( + &server->seat, surface->resource)) { bool focus_changed = wlr_seat->pointer_state.focused_surface != surface; /* @@ -362,7 +367,8 @@ start_drag(struct wl_listener *listener, void *data) { struct seat *seat = wl_container_of(listener, seat, start_drag); struct wlr_drag *wlr_drag = data; - seat->active_view = NULL; + seat->pressed.view = NULL; + seat->pressed.surface = NULL; seat->drag_icon = wlr_drag->icon; wl_signal_add(&seat->drag_icon->events.destroy, &seat->destroy_drag); } @@ -669,7 +675,8 @@ cursor_button(struct wl_listener *listener, void *data) /* handle _release_ */ if (event->state == WLR_BUTTON_RELEASED) { - server->seat.active_view = NULL; + server->seat.pressed.view = NULL; + server->seat.pressed.surface = NULL; if (server->input_mode == LAB_INPUT_STATE_MENU) { return; @@ -705,7 +712,8 @@ cursor_button(struct wl_listener *listener, void *data) /* Handle _press */ if (view_area == LAB_SSD_CLIENT) { - server->seat.active_view = view; + server->seat.pressed.view = view; + server->seat.pressed.surface = surface; } if (server->input_mode == LAB_INPUT_STATE_MENU) { diff --git a/src/xdg.c b/src/xdg.c index 412e799b..9de3dbea 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -96,8 +96,9 @@ handle_destroy(struct wl_listener *listener, void *data) wlr_foreign_toplevel_handle_v1_destroy(view->toplevel_handle); } interactive_end(view); - if (view->server->seat.active_view == view) { - view->server->seat.active_view = NULL; + if (view->server->seat.pressed.view == view) { + view->server->seat.pressed.view = NULL; + view->server->seat.pressed.surface = NULL; } wl_list_remove(&view->link); wl_list_remove(&view->destroy.link); diff --git a/src/xwayland.c b/src/xwayland.c index 3ad89a42..c9e897fe 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -88,8 +88,9 @@ handle_destroy(struct wl_listener *listener, void *data) wlr_foreign_toplevel_handle_v1_destroy(view->toplevel_handle); } interactive_end(view); - if (view->server->seat.active_view == view) { - view->server->seat.active_view = NULL; + if (view->server->seat.pressed.view == view) { + view->server->seat.pressed.view = NULL; + view->server->seat.pressed.surface = NULL; } view->xwayland_surface = NULL; wl_list_remove(&view->link);