]> git.mdlowis.com Git - proto/labwc.git/commitdiff
cursor: Store view + resize edges for move/resize in press event
authorJohn Lindgren <john@jlindgren.net>
Thu, 15 Sep 2022 03:09:36 +0000 (23:09 -0400)
committerConsolatis <35009135+Consolatis@users.noreply.github.com>
Thu, 15 Sep 2022 04:13:27 +0000 (06:13 +0200)
v2: Restore previous behavior for keybinds

include/labwc.h
src/action.c
src/cursor.c
src/seat.c
src/view.c

index 8dae3cf94ba16a87e57dac997bad9c69ea554eeb..e422d4b81ed864cafac08b5587a39e5f8cae2774 100644 (file)
@@ -103,19 +103,22 @@ struct seat {
 
        /**
         * pressed view/surface/node will usually be NULL and is only set on
-        * button press while the mouse is over a surface and reset to NULL on
-        * button release.
+        * button press while the mouse is over a view or 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.
+        *
+        * Both (view && !surface) and (surface && !view) are possible.
         */
        struct {
                struct view *view;
                struct wlr_scene_node *node;
                struct wlr_surface *surface;
                struct wlr_surface *toplevel;
+               uint32_t resize_edges;
        } pressed;
 
        struct wl_client *active_client_while_inhibited;
@@ -569,7 +572,7 @@ 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_set_pressed(struct seat *seat, struct view *view,
        struct wlr_scene_node *node, struct wlr_surface *surface,
-       struct wlr_surface *toplevel);
+       struct wlr_surface *toplevel, uint32_t resize_edges);
 void seat_reset_pressed(struct seat *seat);
 
 void interactive_begin(struct view *view, enum input_mode mode,
index d6782c02dc6d6a717928dfb07c2e57266623a51d..9eb81cf7c47be280226d78a1f9ad748e2994825a 100644 (file)
@@ -166,9 +166,23 @@ show_menu(struct server *server, struct view *view, const char *menu_name)
 }
 
 static struct view *
-activator_or_focused_view(struct view *activator, struct server *server)
+view_for_action(struct view *activator, struct server *server,
+       struct action *action)
 {
-       return activator ? activator : desktop_focused_view(server);
+       /* View is explicitly specified for mousebinds */
+       if (activator) {
+               return activator;
+       }
+
+       /* Select view based on action type for keybinds */
+       switch (action->type) {
+       case ACTION_TYPE_FOCUS:
+       case ACTION_TYPE_MOVE:
+       case ACTION_TYPE_RESIZE:
+               return get_cursor_context(server).view;
+       default:
+               return desktop_focused_view(server);
+       }
 }
 
 void
@@ -194,7 +208,7 @@ actions_run(struct view *activator, struct server *server,
                 * Refetch view because it may have been changed due to the
                 * previous action
                 */
-               view = activator_or_focused_view(activator, server);
+               view = view_for_action(activator, server, action);
 
                switch (action->type) {
                case ACTION_TYPE_CLOSE:
@@ -275,7 +289,6 @@ actions_run(struct view *activator, struct server *server,
                        }
                        break;
                case ACTION_TYPE_FOCUS:
-                       view = get_cursor_context(server).view;
                        if (view) {
                                desktop_focus_and_activate_view(&server->seat, view);
                        }
@@ -286,7 +299,6 @@ actions_run(struct view *activator, struct server *server,
                        }
                        break;
                case ACTION_TYPE_MOVE:
-                       view = get_cursor_context(server).view;
                        if (view) {
                                interactive_begin(view, LAB_INPUT_STATE_MOVE, 0);
                        }
@@ -297,7 +309,6 @@ actions_run(struct view *activator, struct server *server,
                        }
                        break;
                case ACTION_TYPE_RESIZE:
-                       view = get_cursor_context(server).view;
                        if (view) {
                                interactive_begin(view, LAB_INPUT_STATE_RESIZE,
                                        resize_edges);
index c58bd52f0dbdd61d89f3cb4bb24aa4cefbc967c9..990b312b1124697c95877fb3eea78a379a895bd9 100644 (file)
@@ -255,8 +255,10 @@ update_pressed_surface(struct seat *seat, struct cursor_context *ctx)
        if (seat->pressed.surface && ctx->surface != seat->pressed.surface) {
                struct wlr_surface *toplevel = get_toplevel(ctx->surface);
                if (toplevel && toplevel == seat->pressed.toplevel) {
-                       seat_set_pressed(seat, ctx->view, ctx->node,
-                               ctx->surface, toplevel);
+                       /* No need to recompute resize edges here */
+                       seat_set_pressed(seat, ctx->view,
+                               ctx->node, ctx->surface, toplevel,
+                               seat->pressed.resize_edges);
                        return true;
                }
        }
@@ -424,12 +426,15 @@ process_cursor_motion(struct server *server, uint32_t time)
        wl_list_for_each(mousebind, &rc.mousebinds, link) {
                if (mousebind->mouse_event == MOUSE_ACTION_DRAG
                                && mousebind->pressed_in_context) {
-                       /* Find closest resize edges in case action is Resize */
-                       uint32_t resize_edges =
-                               determine_resize_edges(seat->cursor, &ctx);
-
+                       /*
+                        * Use view and resize edges from the press
+                        * event (not the motion event) to prevent
+                        * moving/resizing the wrong view
+                        */
                        mousebind->pressed_in_context = false;
-                       actions_run(NULL, server, &mousebind->actions, resize_edges);
+                       actions_run(seat->pressed.view,
+                               server, &mousebind->actions,
+                               seat->pressed.resize_edges);
                }
        }
 
@@ -825,9 +830,13 @@ cursor_button(struct wl_listener *listener, void *data)
        }
 
        /* Handle _press */
-       if (ctx.surface) {
+       /* Determine closest resize edges in case action is Resize */
+       resize_edges = determine_resize_edges(seat->cursor, &ctx);
+
+       if (ctx.view || ctx.surface) {
+               /* Store resize edges for later action processing */
                seat_set_pressed(seat, ctx.view, ctx.node, ctx.surface,
-                       get_toplevel(ctx.surface));
+                       get_toplevel(ctx.surface), resize_edges);
        }
 
        if (server->input_mode == LAB_INPUT_STATE_MENU) {
@@ -850,9 +859,6 @@ cursor_button(struct wl_listener *listener, void *data)
                }
        }
 
-       /* Determine closest resize edges in case action is Resize */
-       resize_edges = determine_resize_edges(seat->cursor, &ctx);
-
 mousebindings:
        if (event->state == WLR_BUTTON_RELEASED) {
                triggered_frame_binding |= handle_release_mousebinding(ctx.view,
index 16aaa2561f2410f5acbfcd5a8994ec06f5d4b501..70a240e85ff93fdf63801e4345aed0b27678f354 100644 (file)
@@ -384,27 +384,34 @@ pressed_surface_destroy(struct wl_listener *listener, void *data)
 void
 seat_set_pressed(struct seat *seat, struct view *view,
        struct wlr_scene_node *node, struct wlr_surface *surface,
-       struct wlr_surface *toplevel)
+       struct wlr_surface *toplevel, uint32_t resize_edges)
 {
-       assert(surface);
+       assert(view || surface);
        seat_reset_pressed(seat);
 
        seat->pressed.view = view;
        seat->pressed.node = node;
        seat->pressed.surface = surface;
        seat->pressed.toplevel = toplevel;
-       seat->pressed_surface_destroy.notify = pressed_surface_destroy;
-       wl_signal_add(&surface->events.destroy, &seat->pressed_surface_destroy);
+       seat->pressed.resize_edges = resize_edges;
+
+       if (surface) {
+               seat->pressed_surface_destroy.notify = pressed_surface_destroy;
+               wl_signal_add(&surface->events.destroy,
+                       &seat->pressed_surface_destroy);
+       }
 }
 
 void
 seat_reset_pressed(struct seat *seat)
 {
        if (seat->pressed.surface) {
-               seat->pressed.view = NULL;
-               seat->pressed.node = NULL;
-               seat->pressed.surface = NULL;
-               seat->pressed.toplevel = NULL;
                wl_list_remove(&seat->pressed_surface_destroy.link);
        }
+
+       seat->pressed.view = NULL;
+       seat->pressed.node = NULL;
+       seat->pressed.surface = NULL;
+       seat->pressed.toplevel = NULL;
+       seat->pressed.resize_edges = 0;
 }
index 2976a08799fac36f858fcff90d9e2aa8ea83ca68..615b91d7d9d1ce7e689be8ddd51a53ca1c2eafea 100644 (file)
@@ -820,6 +820,10 @@ view_destroy(struct view *view)
                need_cursor_update = true;
        }
 
+       if (server->seat.pressed.view == view) {
+               seat_reset_pressed(&server->seat);
+       }
+
        osd_on_view_destroy(view);
 
        if (view->scene_tree) {