diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd index bc9929b9..f406b887 100644 --- a/docs/labwc-actions.5.scd +++ b/docs/labwc-actions.5.scd @@ -340,6 +340,19 @@ Actions are used in menus and keyboard/mouse bindings. decorations (including those for which the server-side titlebar has been hidden) are not eligible for shading. +** + Warp the cursor to a position relative to the active output or window. + + *to* [output|window] Specifies the target area of the warp. + Default is "output" + *x* [center|value] Specifies the horizontal warp position within the target area. + "center": Moves the cursor to the horizontal center of the target area. + Positive or negative integers warp the cursor to a position offset by the specified + number of pixels from the left or right edge of the target area respectively. + Default is "center" + *y* [center|value] Equivalent for the vertical warp position within the target area. + Default is "center" + **++ **++ ** diff --git a/include/labwc.h b/include/labwc.h index 6e5d7fdd..f8c46637 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -458,7 +458,6 @@ void desktop_focus_view_or_surface(struct seat *seat, struct view *view, void desktop_arrange_all_views(struct server *server); void desktop_focus_output(struct output *output); -void warp_cursor(struct view *view); struct view *desktop_topmost_focusable_view(struct server *server); /** diff --git a/src/action.c b/src/action.c index ce4f077f..2a789b2c 100644 --- a/src/action.c +++ b/src/action.c @@ -121,7 +121,8 @@ enum action_type { ACTION_TYPE_TOGGLE_TABLET_MOUSE_EMULATION, ACTION_TYPE_TOGGLE_MAGNIFY, ACTION_TYPE_ZOOM_IN, - ACTION_TYPE_ZOOM_OUT + ACTION_TYPE_ZOOM_OUT, + ACTION_TYPE_WARP_CURSOR, }; const char *action_names[] = { @@ -186,6 +187,7 @@ const char *action_names[] = { "ToggleMagnify", "ZoomIn", "ZoomOut", + "WarpCursor", NULL }; @@ -475,6 +477,12 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char goto cleanup; } break; + case ACTION_TYPE_WARP_CURSOR: + if (!strcmp(argument, "to") || !strcmp(argument, "x") || !strcmp(argument, "y")) { + action_arg_add_str(action, argument, content); + goto cleanup; + } + break; } wlr_log(WLR_ERROR, "Invalid argument for action %s: '%s'", @@ -824,6 +832,43 @@ get_target_output(struct output *output, struct server *server, return target; } +static void +warp_cursor(struct view *view, struct output *output, const char *to, const char *x, const char *y) +{ + struct wlr_box target_area = {0}; + int goto_x; + int goto_y; + + if (!strcasecmp(to, "output") && output) { + target_area = output_usable_area_in_layout_coords(output); + } else if (!strcasecmp(to, "window") && view) { + target_area = view->current; + } else { + wlr_log(WLR_ERROR, "Invalid argument for action WarpCursor: 'to' (%s)", to); + } + + if (!strcasecmp(x, "center")) { + goto_x = target_area.x + target_area.width / 2; + } else { + int offset_x = atoi(x); + goto_x = offset_x >= 0 ? + target_area.x + offset_x : + target_area.x + target_area.width + offset_x; + } + + if (!strcasecmp(y, "center")) { + goto_y = target_area.y + target_area.height / 2; + } else { + int offset_y = atoi(y); + goto_y = offset_y >= 0 ? + target_area.y + offset_y : + target_area.y + target_area.height + offset_y; + } + + wlr_cursor_warp(output->server->seat.cursor, NULL, goto_x, goto_y); + cursor_update_focus(output->server); +} + void actions_run(struct view *activator, struct server *server, struct wl_list *actions, struct cursor_context *cursor_ctx) @@ -1287,6 +1332,16 @@ actions_run(struct view *activator, struct server *server, case ACTION_TYPE_ZOOM_OUT: magnify_set_scale(server, MAGNIFY_DECREASE); break; + case ACTION_TYPE_WARP_CURSOR: + { + const char *to = action_get_str(action, "to", "output"); + const char *x = action_get_str(action, "x", "center"); + const char *y = action_get_str(action, "y", "center"); + struct output *output = output_nearest_to_cursor(server); + + warp_cursor(view, output, to, x, y); + } + break; case ACTION_TYPE_INVALID: wlr_log(WLR_ERROR, "Not executing unknown action"); break;