]> git.mdlowis.com Git - proto/labwc.git/commitdiff
Refactor the logic of placing client-menu with ShowMenu action
authortokyo4j <hrak1529@gmail.com>
Fri, 20 Sep 2024 16:11:27 +0000 (01:11 +0900)
committerJohan Malm <johanmalm@users.noreply.github.com>
Sat, 21 Sep 2024 17:07:34 +0000 (18:07 +0100)
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.

12 files changed:
include/action.h
include/labwc.h
include/ssd.h
src/action.c
src/input/cursor.c
src/input/keyboard.c
src/input/tablet.c
src/input/touch.c
src/menu/menu.c
src/seat.c
src/ssd/ssd.c
src/window-rules.c

index 799c15cedc93df0a57db322282d5aaba3708ebf6..7130d7011c230b78a1cdc02ad25a7a80ce7599ae 100644 (file)
@@ -7,6 +7,7 @@
 
 struct view;
 struct server;
+struct cursor_context;
 
 struct action {
        struct wl_list link; /*
@@ -34,8 +35,16 @@ void action_arg_from_xml_node(struct action *action, const char *nodename, const
 
 bool actions_contain_toggle_keybinds(struct wl_list *action_list);
 
+/**
+ * actions_run() - Run actions.
+ * @activator: Target view to apply actions (e.g. Maximize, Focus etc.).
+ * NULL is allowed, in which case the focused/hovered view is used.
+ * @ctx: Set for action invocations via mousebindings. Used to get the
+ * direction of resize or the position of the window menu button for ShowMenu
+ * action.
+ */
 void actions_run(struct view *activator, struct server *server,
-       struct wl_list *actions, uint32_t resize_edges);
+       struct wl_list *actions, struct cursor_context *ctx);
 
 void action_free(struct action *action);
 void action_list_free(struct wl_list *action_list);
index 93cb4038f7c082545134585973669615d253c281..93eaf0c263bc47db3bf03352e41dc4c73dd82da9 100644 (file)
@@ -129,9 +129,8 @@ struct seat {
        struct input_method_relay *input_method_relay;
 
        /**
-        * pressed view/surface/node will usually be NULL and is only set on
-        * button press while the mouse is over a view or surface, and reset
-        * to NULL on button release.
+        * This is usually zeroed and is only set on button press while the
+        * mouse is over a view or surface, and zeroed 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.
         *
@@ -144,13 +143,7 @@ struct seat {
         *
         * 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 cursor_context pressed;
 
        struct {
                bool active;
@@ -492,9 +485,7 @@ void seat_focus_surface(struct seat *seat, struct wlr_surface *surface);
 void seat_focus_lock_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, uint32_t resize_edges);
+void seat_set_pressed(struct seat *seat, struct cursor_context *ctx);
 void seat_reset_pressed(struct seat *seat);
 void seat_output_layout_changed(struct seat *seat);
 
index 701f24eb5d0a31055e5085f1950d85c78802a3c1..4a62d06aea8c8f29f2543aea01d2db54e056ed05 100644 (file)
@@ -27,6 +27,7 @@ enum ssd_part_type {
        LAB_SSD_BUTTON_WINDOW_MENU,
        LAB_SSD_BUTTON_SHADE,
        LAB_SSD_BUTTON_OMNIPRESENT,
+       LAB_SSD_BUTTON, /* only for internal use */
        LAB_SSD_PART_TITLEBAR,
        LAB_SSD_PART_TITLEBAR_CORNER_RIGHT,
        LAB_SSD_PART_TITLEBAR_CORNER_LEFT,
index a543538749c6baf1372648554fe17ac0458fb276..07b2fb3f1b446dc633c6a56c1915ffc6e5308198 100644 (file)
@@ -617,40 +617,8 @@ action_list_free(struct wl_list *action_list)
        }
 }
 
-static int
-get_window_menu_button_offset(struct server *server, struct view *view)
-{
-       int padding_width = server->theme->padding_width;
-       int button_width = server->theme->window_button_width;
-       int button_spacing = server->theme->window_button_spacing;
-
-       struct title_button *b;
-
-       int offset = padding_width;
-       wl_list_for_each(b, &rc.title_buttons_left, link) {
-               if (b->type == LAB_SSD_BUTTON_WINDOW_MENU) {
-                       return offset;
-               } else {
-                       offset += button_width + button_spacing;
-               }
-       }
-
-       offset = view->current.width - padding_width;
-       wl_list_for_each_reverse(b, &rc.title_buttons_right, link) {
-               if (b->type == LAB_SSD_BUTTON_WINDOW_MENU) {
-                       offset -= button_width;
-                       return offset;
-               } else {
-                       offset -= button_width + button_spacing;
-               }
-       }
-
-       /* no menu button */
-       return 0;
-}
-
 static void
-show_menu(struct server *server, struct view *view,
+show_menu(struct server *server, struct view *view, struct cursor_context *ctx,
                const char *menu_name, bool at_cursor,
                const char *pos_x, const char *pos_y)
 {
@@ -688,11 +656,15 @@ show_menu(struct server *server, struct view *view,
        }
        /* Place menu in the view corner if desired (and menu is not root-menu) */
        if (!at_cursor && view) {
-               /* push the client menu underneath the window menu button */
-               int offset = is_client_menu
-                       ? get_window_menu_button_offset(server, view) : 0;
-               x = view->current.x + offset;
+               x = view->current.x;
                y = view->current.y;
+               /* Push the client menu underneath the button */
+               if (is_client_menu && ssd_part_contains(
+                               LAB_SSD_BUTTON, ctx->type)) {
+                       assert(ctx->node);
+                       int ly;
+                       wlr_scene_node_coords(ctx->node, &x, &ly);
+               }
        }
 
        /*
@@ -756,7 +728,7 @@ show_menu(struct server *server, struct view *view,
 
 static struct view *
 view_for_action(struct view *activator, struct server *server,
-       struct action *action, uint32_t *resize_edges)
+       struct action *action, struct cursor_context *ctx)
 {
        /* View is explicitly specified for mousebinds */
        if (activator) {
@@ -768,13 +740,8 @@ view_for_action(struct view *activator, struct server *server,
        case ACTION_TYPE_FOCUS:
        case ACTION_TYPE_MOVE:
        case ACTION_TYPE_RESIZE: {
-               struct cursor_context ctx = get_cursor_context(server);
-               if (action->type == ACTION_TYPE_RESIZE) {
-                       /* Select resize edges for the keybind case */
-                       *resize_edges = cursor_get_resize_edges(
-                               server->seat.cursor, &ctx);
-               }
-               return ctx.view;
+               *ctx = get_cursor_context(server);
+               return ctx->view;
        }
        default:
                return server->active_view;
@@ -802,7 +769,7 @@ run_if_action(struct view *view, struct server *server, struct action *action)
 
        actions = action_get_actionlist(action, branch);
        if (actions) {
-               actions_run(view, server, actions, 0);
+               actions_run(view, server, actions, NULL);
        }
        return !strcmp(branch, "then");
 }
@@ -852,7 +819,7 @@ get_target_output(struct output *output, struct server *server,
 
 void
 actions_run(struct view *activator, struct server *server,
-       struct wl_list *actions, uint32_t resize_edges)
+       struct wl_list *actions, struct cursor_context *cursor_ctx)
 {
        if (!actions) {
                wlr_log(WLR_ERROR, "empty actions");
@@ -866,6 +833,10 @@ actions_run(struct view *activator, struct server *server,
        struct action *action;
        struct output *output;
        struct output *target;
+       struct cursor_context ctx = {0};
+       if (cursor_ctx) {
+               ctx = *cursor_ctx;
+       }
 
        wl_list_for_each(action, actions, link) {
                wlr_log(WLR_DEBUG, "Handling action %u: %s", action->type,
@@ -875,8 +846,7 @@ actions_run(struct view *activator, struct server *server,
                 * Refetch view because it may have been changed due to the
                 * previous action
                 */
-               view = view_for_action(activator, server, action,
-                       &resize_edges);
+               view = view_for_action(activator, server, action, &ctx);
 
                switch (action->type) {
                case ACTION_TYPE_CLOSE:
@@ -952,7 +922,7 @@ actions_run(struct view *activator, struct server *server,
                        kill(getpid(), SIGHUP);
                        break;
                case ACTION_TYPE_SHOW_MENU:
-                       show_menu(server, view,
+                       show_menu(server, view, &ctx,
                                action_get_str(action, "menu", NULL),
                                action_get_bool(action, "atCursor", true),
                                action_get_str(action, "x.position", NULL),
@@ -1045,6 +1015,8 @@ actions_run(struct view *activator, struct server *server,
                        break;
                case ACTION_TYPE_RESIZE:
                        if (view) {
+                               uint32_t resize_edges = cursor_get_resize_edges(
+                                       server->seat.cursor, &ctx);
                                interactive_begin(view, LAB_INPUT_STATE_RESIZE,
                                        resize_edges);
                        }
@@ -1199,7 +1171,7 @@ actions_run(struct view *activator, struct server *server,
                                        struct wl_list *actions;
                                        actions = action_get_actionlist(action, "none");
                                        if (actions) {
-                                               actions_run(view, server, actions, 0);
+                                               actions_run(view, server, actions, NULL);
                                        }
                                }
                        }
index 6598c7e79fe43c2510204b75a9e38d802615f4b7..68636f1aa6518ce2db03c47d1f2fcd0f4f68c158 100644 (file)
@@ -400,11 +400,8 @@ 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) {
-                       /* No need to recompute resize edges here */
-                       seat_set_pressed(seat, ctx->view,
-                               ctx->node, ctx->surface, toplevel,
-                               seat->pressed.resize_edges);
+               if (toplevel && toplevel == get_toplevel(seat->pressed.surface)) {
+                       seat_set_pressed(seat, ctx);
                        return true;
                }
        }
@@ -597,9 +594,8 @@ cursor_process_motion(struct server *server, uint32_t time, double *sx, double *
                         * moving/resizing the wrong view
                         */
                        mousebind->pressed_in_context = false;
-                       actions_run(seat->pressed.view,
-                               server, &mousebind->actions,
-                               seat->pressed.resize_edges);
+                       actions_run(seat->pressed.view, server,
+                               &mousebind->actions, &seat->pressed);
                }
        }
 
@@ -904,8 +900,7 @@ handle_release_mousebinding(struct server *server,
                        }
                        consumed_by_frame_context |= mousebind->context == LAB_SSD_FRAME;
                        consumed_by_frame_context |= mousebind->context == LAB_SSD_ALL;
-                       actions_run(ctx->view, server, &mousebind->actions,
-                               /*resize_edges*/ 0);
+                       actions_run(ctx->view, server, &mousebind->actions, ctx);
                }
        }
        /*
@@ -956,7 +951,7 @@ is_double_click(long double_click_speed, uint32_t button,
 
 static bool
 handle_press_mousebinding(struct server *server, struct cursor_context *ctx,
-               uint32_t button, uint32_t resize_edges)
+               uint32_t button)
 {
        if (server->osd_state.cycle_view) {
                return false;
@@ -1005,7 +1000,7 @@ handle_press_mousebinding(struct server *server, struct cursor_context *ctx,
                        }
                        consumed_by_frame_context |= mousebind->context == LAB_SSD_FRAME;
                        consumed_by_frame_context |= mousebind->context == LAB_SSD_ALL;
-                       actions_run(ctx->view, server, &mousebind->actions, resize_edges);
+                       actions_run(ctx->view, server, &mousebind->actions, ctx);
                }
        }
        return consumed_by_frame_context;
@@ -1022,13 +1017,9 @@ cursor_process_button_press(struct seat *seat, uint32_t button, uint32_t time_ms
        /* Used on next button release to check if it can close menu or select menu item */
        press_msec = time_msec;
 
-       /* Determine closest resize edges in case action is Resize */
-       uint32_t resize_edges = cursor_get_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), resize_edges);
+               /* Store cursor context for later action processing */
+               seat_set_pressed(seat, &ctx);
        }
 
        if (server->input_mode == LAB_INPUT_STATE_MENU) {
@@ -1082,7 +1073,7 @@ cursor_process_button_press(struct seat *seat, uint32_t button, uint32_t time_ms
 
        /* Bindings to the Frame context swallow mouse events if activated */
        bool consumed_by_frame_context =
-               handle_press_mousebinding(server, &ctx, button, resize_edges);
+               handle_press_mousebinding(server, &ctx, button);
 
        if (ctx.surface && !consumed_by_frame_context) {
                /* Notify client with pointer focus of button press */
@@ -1330,7 +1321,7 @@ handle_cursor_axis(struct server *server, struct cursor_context *ctx,
                                && modifiers == mousebind->modifiers
                                && mousebind->mouse_event == MOUSE_ACTION_SCROLL) {
                        handled = true;
-                       actions_run(ctx->view, server, &mousebind->actions, /*resize_edges*/ 0);
+                       actions_run(ctx->view, server, &mousebind->actions, ctx);
                }
        }
 
index ea758296b3dc64fc1094368f8dc780d544b67344..01557e618f7ac1d093bf7c9005cb1622bafda780 100644 (file)
@@ -462,7 +462,7 @@ handle_compositor_keybindings(struct keyboard *keyboard,
                                cur_keybind = NULL;
                                return true;
                        }
-                       actions_run(NULL, server, &cur_keybind->actions, 0);
+                       actions_run(NULL, server, &cur_keybind->actions, NULL);
                        return true;
                } else {
                        return handle_key_release(server, event->keycode);
@@ -506,7 +506,7 @@ handle_compositor_keybindings(struct keyboard *keyboard,
                 */
                key_state_store_pressed_key_as_bound(event->keycode);
                if (!cur_keybind->on_release) {
-                       actions_run(NULL, server, &cur_keybind->actions, 0);
+                       actions_run(NULL, server, &cur_keybind->actions, NULL);
                }
                return true;
        }
index 5563db0c4bed2637622caf7091439a44d79f8791..617af8fd68e2b545fe5c0b63cdc631f4b7e152fb 100644 (file)
@@ -581,7 +581,7 @@ handle_tablet_tool_button(struct wl_listener *listener, void *data)
                                                && mousebind->button == button
                                                && mousebind->context == LAB_SSD_CLIENT) {
                                        actions_run(view, tool->seat->server,
-                                               &mousebind->actions, 0);
+                                               &mousebind->actions, NULL);
                                }
                        }
                }
index 511fba20eda23ea7acdfceac9ed0a19f081838be..f99b013ed1b90d1174ab85e31a840fc0409dc00d 100644 (file)
@@ -118,7 +118,7 @@ handle_touch_down(struct wl_listener *listener, void *data)
                        if (mousebind->mouse_event == MOUSE_ACTION_PRESS
                                        && mousebind->button == BTN_LEFT
                                        && mousebind->context == LAB_SSD_CLIENT) {
-                               actions_run(view, seat->server, &mousebind->actions, 0);
+                               actions_run(view, seat->server, &mousebind->actions, NULL);
                        }
                }
 
index 69bc6f39e120491dc24694ceb9c1be5778016a9a..3f0cf777e423766556d701284e6fd18e51ea45f2 100644 (file)
@@ -1591,10 +1591,10 @@ menu_execute_item(struct menuitem *item)
         */
        if (item->id && !strcmp(item->id, "client-list-combined-menu")
                        && item->client_list_view) {
-               actions_run(item->client_list_view, server, &item->actions, 0);
+               actions_run(item->client_list_view, server, &item->actions, NULL);
        } else {
                actions_run(item->parent->triggered_by_view, server,
-                               &item->actions, 0);
+                               &item->actions, NULL);
        }
 
        server->menu_current = NULL;
index 004b610ef797194b2fddfeb7086631cf84abaf6a..cbfe329b66a41fc5793161c3f527a801315e971a 100644 (file)
@@ -722,22 +722,17 @@ 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, uint32_t resize_edges)
+seat_set_pressed(struct seat *seat, struct cursor_context *ctx)
 {
-       assert(view || surface);
+       assert(ctx);
+       assert(ctx->view || ctx->surface);
        seat_reset_pressed(seat);
 
-       seat->pressed.view = view;
-       seat->pressed.node = node;
-       seat->pressed.surface = surface;
-       seat->pressed.toplevel = toplevel;
-       seat->pressed.resize_edges = resize_edges;
+       seat->pressed = *ctx;
 
-       if (surface) {
+       if (ctx->surface) {
                seat->pressed_surface_destroy.notify = pressed_surface_destroy;
-               wl_signal_add(&surface->events.destroy,
+               wl_signal_add(&ctx->surface->events.destroy,
                        &seat->pressed_surface_destroy);
        }
 }
@@ -748,12 +743,7 @@ seat_reset_pressed(struct seat *seat)
        if (seat->pressed.surface) {
                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;
+       seat->pressed = (struct cursor_context){0};
 }
 
 void
index a54598fef14c78c29853508d8267b7e99b2a1080..c1e4e0e512d3d88329b438177066460e6b614cf4 100644 (file)
@@ -310,6 +310,10 @@ ssd_part_contains(enum ssd_part_type whole, enum ssd_part_type candidate)
        if (whole == candidate || whole == LAB_SSD_ALL) {
                return true;
        }
+       if (whole == LAB_SSD_BUTTON) {
+               return candidate >= LAB_SSD_BUTTON_CLOSE
+                       && candidate <= LAB_SSD_BUTTON_OMNIPRESENT;
+       }
        if (whole == LAB_SSD_PART_TITLEBAR) {
                return candidate >= LAB_SSD_BUTTON_CLOSE
                        && candidate <= LAB_SSD_PART_TITLE;
index f543f7ec8f28649e3508d4f7a705e613a3fa4f80..ce2131f64a6aa36c153ee686bf0b38477fd90727 100644 (file)
@@ -52,7 +52,7 @@ window_rules_apply(struct view *view, enum window_rule_event event)
                        continue;
                }
                if (view_matches_criteria(rule, view)) {
-                       actions_run(view, view->server, &rule->actions, 0);
+                       actions_run(view, view->server, &rule->actions, NULL);
                }
        }
 }