]> git.mdlowis.com Git - proto/labwc.git/commitdiff
cursor: Fix out-of-surface movement for unmanaged surfaces
authorJohn Lindgren <john@jlindgren.net>
Thu, 1 Sep 2022 21:50:28 +0000 (17:50 -0400)
committerConsolatis <35009135+Consolatis@users.noreply.github.com>
Fri, 2 Sep 2022 03:12:34 +0000 (05:12 +0200)
include/labwc.h
src/cursor.c
src/layers.c
src/seat.c
src/view.c
src/xwayland-unmanaged.c

index c5d78aad23c1a741427090830a7de73c42be21f2..20fe882bd792bfbd6bce29df74d860fa7dae2c09 100644 (file)
@@ -559,6 +559,7 @@ void seat_finish(struct server *server);
 void seat_reconfigure(struct server *server);
 void seat_focus_surface(struct seat *seat, struct wlr_surface *surface);
 void seat_set_focus_layer(struct seat *seat, struct wlr_layer_surface_v1 *layer);
+void seat_reset_pressed(struct seat *seat);
 
 void interactive_begin(struct view *view, enum input_mode mode,
                      uint32_t edges);
index 0479b6564e6e0c9c6860b6f2bf8ea084aa5eb30e..89ea699617aa45510f7349dbdf9c8aff822471ce 100644 (file)
@@ -196,6 +196,42 @@ input_inhibit_blocks_surface(struct seat *seat, struct wl_resource *resource)
                && inhibiting_client != wl_resource_get_client(resource);
 }
 
+static void
+process_cursor_motion_out_of_surface(struct server *server, uint32_t time)
+{
+       struct view *view = server->seat.pressed.view;
+       struct wlr_scene_node *node = server->seat.pressed.node;
+       struct wlr_surface *surface = server->seat.pressed.surface;
+       assert(surface);
+       int lx, ly;
+
+       if (view) {
+               lx = view->x;
+               ly = view->y;
+       } else if (node && wlr_surface_is_layer_surface(surface)) {
+               wlr_scene_node_coords(node, &lx, &ly);
+#if HAVE_XWAYLAND
+       } else if (node && node->parent == server->unmanaged_tree) {
+               wlr_scene_node_coords(node, &lx, &ly);
+#endif
+       } else {
+               wlr_log(WLR_ERROR, "Can't detect surface for out-of-surface movement");
+               return;
+       }
+
+       double sx = server->seat.cursor->x - lx;
+       double sy = server->seat.cursor->y - ly;
+       /* Take into account invisible xdg-shell CSD borders */
+       if (view && view->type == LAB_XDG_SHELL_VIEW && view->xdg_surface) {
+               struct wlr_box geo;
+               wlr_xdg_surface_get_geometry(view->xdg_surface, &geo);
+               sx += geo.x;
+               sy += geo.y;
+       }
+
+       wlr_seat_pointer_notify_motion(server->seat.seat, time, sx, sy);
+}
+
 static void
 process_cursor_motion(struct server *server, uint32_t time)
 {
@@ -289,29 +325,7 @@ process_cursor_motion(struct server *server, uint32_t time)
                 * or selecting text even if the cursor moves outside of
                 * the surface.
                 */
-               int lx, ly;
-               view = server->seat.pressed.view;
-               if (view) {
-                       lx = view->x;
-                       ly = view->y;
-               } else if (wlr_surface_is_layer_surface(server->seat.pressed.surface)) {
-                       wlr_scene_node_coords(server->seat.pressed.node, &lx, &ly);
-               } else {
-                       wlr_log(WLR_ERROR, "Can't detect surface for out-of-surface movement");
-                       return;
-               }
-               sx = server->seat.cursor->x - lx;
-               sy = server->seat.cursor->y - ly;
-
-               /* Take into account invisible xdg-shell CSD borders */
-               if (view && view->type == LAB_XDG_SHELL_VIEW
-                               && view->xdg_surface) {
-                       struct wlr_box geo;
-                       wlr_xdg_surface_get_geometry(view->xdg_surface, &geo);
-                       sx += geo.x;
-                       sy += geo.y;
-               }
-               wlr_seat_pointer_notify_motion(server->seat.seat, time, sx, sy);
+               process_cursor_motion_out_of_surface(server, time);
        } else if (surface && !input_inhibit_blocks_surface(
                        &server->seat, surface->resource)) {
                bool focus_changed =
@@ -364,9 +378,7 @@ 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->pressed.view = NULL;
-       seat->pressed.node = NULL;
-       seat->pressed.surface = NULL;
+       seat_reset_pressed(seat);
        seat->drag_icon = wlr_drag->icon;
        if (!seat->drag_icon) {
                wlr_log(WLR_ERROR,
@@ -713,19 +725,17 @@ cursor_button(struct wl_listener *listener, void *data)
 
        /* handle _release_ */
        if (event->state == WLR_BUTTON_RELEASED) {
-               seat->pressed.view = NULL;
-               seat->pressed.node = NULL;
-               if (seat->pressed.surface && seat->pressed.surface != surface) {
+               struct wlr_surface *pressed_surface = seat->pressed.surface;
+               seat_reset_pressed(seat);
+               if (pressed_surface && pressed_surface != surface) {
                        /*
                         * Button released but originally pressed over a different surface.
                         * Just send the release event to the still focused surface.
                         */
                        wlr_seat_pointer_notify_button(seat->seat, event->time_msec,
                                event->button, event->state);
-                       seat->pressed.surface = NULL;
                        return;
                }
-               seat->pressed.surface = NULL;
                if (server->input_mode == LAB_INPUT_STATE_MENU) {
                        if (close_menu) {
                                menu_close_root(server);
index b9d05c2d3196cddcc5557ec84da9a315cfd4a053..a6e2e4bdc08998ef4e57b23e0ebdfff5d3b17e54 100644 (file)
@@ -146,8 +146,7 @@ unmap(struct lab_layer_surface *layer)
                seat_set_focus_layer(seat, NULL);
        }
        if (seat->pressed.surface == layer->scene_layer_surface->layer_surface->surface) {
-               seat->pressed.node = NULL;
-               seat->pressed.surface = NULL;
+               seat_reset_pressed(seat);
        }
 }
 
index 316c503f97a4e8d90b5ef6b9f62b0224fdaf1d78..56edaef31d2735ce29eb91a28f02f6186ed0f44e 100644 (file)
@@ -369,3 +369,11 @@ seat_set_focus_layer(struct seat *seat, struct wlr_layer_surface_v1 *layer)
                seat->focused_layer = layer;
        }
 }
+
+void
+seat_reset_pressed(struct seat *seat)
+{
+       seat->pressed.view = NULL;
+       seat->pressed.node = NULL;
+       seat->pressed.surface = NULL;
+}
index 05f944320646efa6b2baf6912f29ec42618bff21..f1766a919f4426dbb56734b9ffc08fcd977e8746 100644 (file)
@@ -813,8 +813,7 @@ view_destroy(struct view *view)
 
        if (server->seat.pressed.view == view) {
                /* Mouse was pressed on surface and is still pressed */
-               server->seat.pressed.view = NULL;
-               server->seat.pressed.surface = NULL;
+               seat_reset_pressed(&server->seat);
        }
 
        if (server->focused_view == view) {
index ca78722de7718444589d07df01fa69ffc1342fcb..49d535f886d85f2ccb77e8686af14c942feb70f7 100644 (file)
@@ -57,6 +57,8 @@ unmanaged_handle_unmap(struct wl_listener *listener, void *data)
        struct xwayland_unmanaged *unmanaged =
                wl_container_of(listener, unmanaged, unmap);
        struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
+       struct seat *seat = &unmanaged->server->seat;
+
        wl_list_remove(&unmanaged->link);
        wl_list_remove(&unmanaged->set_geometry.link);
 
@@ -64,9 +66,11 @@ unmanaged_handle_unmap(struct wl_listener *listener, void *data)
         * Mark the node as gone so a racing configure event
         * won't try to reposition the node while unmapped.
         */
+       if (unmanaged->node && seat->pressed.node == unmanaged->node) {
+               seat_reset_pressed(seat);
+       }
        unmanaged->node = NULL;
 
-       struct seat *seat = &unmanaged->server->seat;
        if (seat->seat->keyboard_state.focused_surface == xsurface->surface) {
                /*
                 * Try to focus on parent surface