struct view;
struct server;
+struct cursor_context;
struct action {
struct wl_list link; /*
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);
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.
*
*
* 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;
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);
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,
}
}
-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)
{
}
/* 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);
+ }
}
/*
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) {
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;
actions = action_get_actionlist(action, branch);
if (actions) {
- actions_run(view, server, actions, 0);
+ actions_run(view, server, actions, NULL);
}
return !strcmp(branch, "then");
}
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");
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,
* 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:
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),
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);
}
struct wl_list *actions;
actions = action_get_actionlist(action, "none");
if (actions) {
- actions_run(view, server, actions, 0);
+ actions_run(view, server, actions, NULL);
}
}
}
}
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;
}
}
* 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);
}
}
}
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);
}
}
/*
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;
}
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;
/* 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) {
/* 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 */
&& 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);
}
}
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);
*/
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;
}
&& mousebind->button == button
&& mousebind->context == LAB_SSD_CLIENT) {
actions_run(view, tool->seat->server,
- &mousebind->actions, 0);
+ &mousebind->actions, NULL);
}
}
}
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);
}
}
*/
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;
}
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);
}
}
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
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;
continue;
}
if (view_matches_criteria(rule, view)) {
- actions_run(view, view->server, &rule->actions, 0);
+ actions_run(view, view->server, &rule->actions, NULL);
}
}
}