mirror of
https://github.com/labwc/labwc.git
synced 2025-11-05 13:29:58 -05:00
Refactor the logic of placing client-menu with ShowMenu action
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.
This commit is contained in:
parent
d29464bac7
commit
25f5cdd3a6
12 changed files with 67 additions and 109 deletions
74
src/action.c
74
src/action.c
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
24
src/seat.c
24
src/seat.c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue