From aaf68cf423d718a748b56481fddb37e9186b83ed Mon Sep 17 00:00:00 2001 From: Rasmus Moorats Date: Thu, 23 Sep 2021 17:52:35 +0300 Subject: fix cursor input for layer-shell surfaces previously, fullscreen global containers would grab cursor input even if a shell-layer surface was on top of it related issue: https://github.com/swaywm/sway/issues/6501 --- sway/input/cursor.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'sway/input') diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 1e3e16d6..d8b1abeb 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -83,7 +83,28 @@ static struct wlr_surface *layer_surface_popup_at(struct sway_output *output, struct sway_node *node_at_coords( struct sway_seat *seat, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { - // check for unmanaged views first + // find the output the cursor is on + struct wlr_output *wlr_output = wlr_output_layout_output_at( + root->output_layout, lx, ly); + if (wlr_output == NULL) { + return NULL; + } + struct sway_output *output = wlr_output->data; + if (!output || !output->enabled) { + // output is being destroyed or is being enabled + return NULL; + } + double ox = lx, oy = ly; + wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy); + + // layer surfaces on the overlay layer are rendered on top + if ((*surface = layer_surface_at(output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], + ox, oy, sx, sy))) { + return NULL; + } + + // check for unmanaged views #if HAVE_XWAYLAND struct wl_list *unmanaged = &root->xwayland_unmanaged; struct sway_xwayland_unmanaged *unmanaged_surface; @@ -101,19 +122,6 @@ struct sway_node *node_at_coords( } } #endif - // find the output the cursor is on - struct wlr_output *wlr_output = wlr_output_layout_output_at( - root->output_layout, lx, ly); - if (wlr_output == NULL) { - return NULL; - } - struct sway_output *output = wlr_output->data; - if (!output || !output->enabled) { - // output is being destroyed or is being enabled - return NULL; - } - double ox = lx, oy = ly; - wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy); if (root->fullscreen_global) { // Try fullscreen container @@ -131,11 +139,6 @@ struct sway_node *node_at_coords( return NULL; } - if ((*surface = layer_surface_at(output, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], - ox, oy, sx, sy))) { - return NULL; - } if (ws->fullscreen) { // Try transient containers for (int i = 0; i < ws->floating->length; ++i) { -- cgit v1.2.3 From f2b6d1ec290014674bf2755a3488aef8ab51a182 Mon Sep 17 00:00:00 2001 From: RoastVeg Date: Tue, 9 Jun 2020 16:47:38 +0100 Subject: Handle border width and height on minimum floating sizes This fixes: https://github.com/swaywm/sway/issues/5337 Co-authored-by: Moon Sungjoon --- sway/input/seatop_resize_floating.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'sway/input') diff --git a/sway/input/seatop_resize_floating.c b/sway/input/seatop_resize_floating.c index 8400a4b3..df683026 100644 --- a/sway/input/seatop_resize_floating.c +++ b/sway/input/seatop_resize_floating.c @@ -80,17 +80,25 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { double height = e->ref_height + grow_height; int min_width, max_width, min_height, max_height; floating_calculate_constraints(&min_width, &max_width, - &min_height, &max_height); - width = fmax(min_width + border_width, fmin(width, max_width)); - height = fmax(min_height + border_height, fmin(height, max_height)); + &min_height, &max_height); + width = fmin(width, max_width - border_width); + width = fmax(width, min_width + border_width); + width = fmax(width, 1); + height = fmin(height, max_height - border_height); + height = fmax(height, min_height + border_height); + height = fmax(height, 1); // Apply the view's min/max size if (con->view) { double view_min_width, view_max_width, view_min_height, view_max_height; view_get_constraints(con->view, &view_min_width, &view_max_width, &view_min_height, &view_max_height); - width = fmax(view_min_width + border_width, fmin(width, view_max_width)); - height = fmax(view_min_height + border_height, fmin(height, view_max_height)); + width = fmin(width, view_max_width - border_width); + width = fmax(width, view_min_width + border_width); + width = fmax(width, 1); + height = fmin(height, view_max_height - border_height); + height = fmax(height, view_min_height + border_height); + height = fmax(height, 1); } -- cgit v1.2.3 From a235794a96884fa5619790316251f7d5e53e3d2d Mon Sep 17 00:00:00 2001 From: Thomas Hebb Date: Thu, 6 Jan 2022 03:44:55 -0800 Subject: input/seat: unset has_focus when focus_stack becomes empty We currently track the focus of a seat in two ways: we use a list called focus_stack to track the order in which nodes have been focused, with the first node representing what's currently focused, and we use a variable called has_focus to indicate whether anything has focus--i.e. whether we should actually treat that first node as focused at any given time. In a number of places, we treat has_focus as implying that a focused node exists. If it's true, we attempt to dereference the return value of seat_get_focus(), our helper function for getting the first node in focus_list, with no further checks. But this isn't quite correct with the current implementation of seat_get_focus(): not only does it return NULL when has_focus is false, it also returns NULL when focus_stack contains no items. In most cases, focus_stack never becomes empty and so this doesn't matter at all. Since focus_stack stores a history of focused nodes, we rarely remove nodes from it. The exception to this is when a node itself goes away. In that case, we call seat_node_destroy() to remove it from focus_stack and free it. But we don't unset has_focus if we've removed the final node! This lets us get into a state where has_focus is true but seat_get_focus() returns NULL, leading to a segfault when we try to dereference it. Fix the issue both by updating has_focus in seat_node_destroy() and by adding an assertion in seat_get_focus() that ensures focus_stack and has_focus are in sync, which will make it easier to track down similar issues in the future. Fixes #6395. [1] There's some discussion in #1585 from when this was implemented about whether has_focus is actually necessary; it's possible we could remove it entirely, but for the moment this is the architecture we have. (cherry picked from commit 921b0a863382b70234aeb4bd589c10328e9ff042) --- sway/input/seat.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'sway/input') diff --git a/sway/input/seat.c b/sway/input/seat.c index c5c8459e..ce933b66 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -51,6 +51,16 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) { static void seat_node_destroy(struct sway_seat_node *seat_node) { wl_list_remove(&seat_node->destroy.link); wl_list_remove(&seat_node->link); + + /* + * This is the only time we remove items from the focus stack without + * immediately re-adding them. If we just removed the last thing, + * mark that nothing has focus anymore. + */ + if (wl_list_empty(&seat_node->seat->focus_stack)) { + seat_node->seat->has_focus = false; + } + free(seat_node); } @@ -1415,9 +1425,8 @@ struct sway_node *seat_get_focus(struct sway_seat *seat) { if (!seat->has_focus) { return NULL; } - if (wl_list_empty(&seat->focus_stack)) { - return NULL; - } + sway_assert(!wl_list_empty(&seat->focus_stack), + "focus_stack is empty, but has_focus is true"); struct sway_seat_node *current = wl_container_of(seat->focus_stack.next, current, link); return current->node; -- cgit v1.2.3 From 9a2155eed26d3d73059c39dd68a324f2f43332db Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Mon, 17 Jan 2022 16:53:46 -0500 Subject: input/cursor: count pointer gestures as idle activity Fixes https://github.com/swaywm/sway/issues/6765. (cherry picked from commit fd53f80156cee413a5166fb8e904a11901e45548) --- sway/input/cursor.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sway/input') diff --git a/sway/input/cursor.c b/sway/input/cursor.c index d8b1abeb..322b91fb 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -927,6 +927,7 @@ static void handle_pointer_pinch_begin(struct wl_listener *listener, void *data) struct sway_cursor *cursor = wl_container_of( listener, cursor, pinch_begin); struct wlr_event_pointer_pinch_begin *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_pinch_begin( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->fingers); @@ -936,6 +937,7 @@ static void handle_pointer_pinch_update(struct wl_listener *listener, void *data struct sway_cursor *cursor = wl_container_of( listener, cursor, pinch_update); struct wlr_event_pointer_pinch_update *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_pinch_update( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->dx, event->dy, @@ -946,6 +948,7 @@ static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of( listener, cursor, pinch_end); struct wlr_event_pointer_pinch_end *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_pinch_end( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->cancelled); @@ -964,6 +967,7 @@ static void handle_pointer_swipe_update(struct wl_listener *listener, void *data struct sway_cursor *cursor = wl_container_of( listener, cursor, swipe_update); struct wlr_event_pointer_swipe_update *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_swipe_update( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->dx, event->dy); @@ -973,6 +977,7 @@ static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of( listener, cursor, swipe_end); struct wlr_event_pointer_swipe_end *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_swipe_end( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->cancelled); -- cgit v1.2.3 From 7a5e62036dededd0c161d4d9980f8d9e27627f7e Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Mon, 17 Jan 2022 17:13:26 -0500 Subject: input/cursor: treat swipe begin as idle activity too Accidentally overlooked in fd53f80. (cherry picked from commit 7d1ccafae5a5d2eddfda2f857ea81ce88f141ddc) --- sway/input/cursor.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sway/input') diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 322b91fb..6fddee90 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -958,6 +958,7 @@ static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data) struct sway_cursor *cursor = wl_container_of( listener, cursor, swipe_begin); struct wlr_event_pointer_swipe_begin *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_swipe_begin( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->fingers); -- cgit v1.2.3