diff --git a/include/action.h b/include/action.h index 799c15ce..7130d701 100644 --- a/include/action.h +++ b/include/action.h @@ -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); diff --git a/include/labwc.h b/include/labwc.h index 93cb4038..93eaf0c2 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -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); diff --git a/include/ssd.h b/include/ssd.h index 701f24eb..4a62d06a 100644 --- a/include/ssd.h +++ b/include/ssd.h @@ -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, diff --git a/src/action.c b/src/action.c index a5435387..07b2fb3f 100644 --- a/src/action.c +++ b/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); } } } diff --git a/src/input/cursor.c b/src/input/cursor.c index 6598c7e7..68636f1a 100644 --- a/src/input/cursor.c +++ b/src/input/cursor.c @@ -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); } } diff --git a/src/input/keyboard.c b/src/input/keyboard.c index ea758296..01557e61 100644 --- a/src/input/keyboard.c +++ b/src/input/keyboard.c @@ -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; } diff --git a/src/input/tablet.c b/src/input/tablet.c index 5563db0c..617af8fd 100644 --- a/src/input/tablet.c +++ b/src/input/tablet.c @@ -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); } } } diff --git a/src/input/touch.c b/src/input/touch.c index 511fba20..f99b013e 100644 --- a/src/input/touch.c +++ b/src/input/touch.c @@ -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); } } diff --git a/src/menu/menu.c b/src/menu/menu.c index 69bc6f39..3f0cf777 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -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; diff --git a/src/seat.c b/src/seat.c index 004b610e..cbfe329b 100644 --- a/src/seat.c +++ b/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 diff --git a/src/ssd/ssd.c b/src/ssd/ssd.c index a54598fe..c1e4e0e5 100644 --- a/src/ssd/ssd.c +++ b/src/ssd/ssd.c @@ -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; diff --git a/src/window-rules.c b/src/window-rules.c index f543f7ec..ce2131f6 100644 --- a/src/window-rules.c +++ b/src/window-rules.c @@ -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); } } }