]> git.mdlowis.com Git - proto/labwc.git/commitdiff
Add FocusOutput action
authorConsolatis <35009135+Consolatis@users.noreply.github.com>
Sun, 5 Mar 2023 16:16:23 +0000 (17:16 +0100)
committerJohan Malm <johanmalm@users.noreply.github.com>
Mon, 6 Mar 2023 21:58:11 +0000 (21:58 +0000)
Fixes #806

Suggested-by: @EysseW
Tested-by: @EysseW
docs/labwc-actions.5.scd
include/labwc.h
src/action.c
src/desktop.c
src/output.c

index 72e81d6e6b905e21a5ffa44a5328b3683eeb7dd4..b5e7d2bc3e9e4137c69229f51a829cfd8ff4c07a 100644 (file)
@@ -80,6 +80,11 @@ Actions are used in menus and keyboard/mouse bindings.
        to Virtual Machines, VNC clients or nested compositors.
        A second call will restore all original keybinds.
 
+*<action name="FocusOutput" output="HDMI-A-1" />*
+       Give focus to topmost window on given output and warp the cursor
+       to the center of the window. If the given output does not contain
+       any windows, the cursor is centered on the given output.
+
 *<action name="GoToDesktop" to="value" />*
        Switch to workspace. Supported values are "last", "left", "right" or the
        full name of a workspace or its index (starting at 1) as configured in
index 378e1e2077f4955df7239c12c6cae9a2a55d11bb..d71e00f0f545b6fbf7b812a797ac9b5a036ac84a 100644 (file)
@@ -372,6 +372,7 @@ void desktop_move_to_front(struct view *view);
 void desktop_move_to_back(struct view *view);
 void desktop_focus_and_activate_view(struct seat *seat, struct view *view);
 void desktop_arrange_all_views(struct server *server);
+void desktop_focus_output(struct output *output);
 
 enum lab_cycle_dir {
        LAB_CYCLE_DIR_NONE,
@@ -418,6 +419,7 @@ void output_init(struct server *server);
 void output_manager_init(struct server *server);
 struct output *output_from_wlr_output(struct server *server,
        struct wlr_output *wlr_output);
+struct output *output_from_name(struct server *server, const char *name);
 struct output *output_nearest_to(struct server *server, int lx, int ly);
 struct output *output_nearest_to_cursor(struct server *server);
 bool output_is_usable(struct output *output);
index 61f6612f61a44d85165f9df1aac65b4477ea632b..96b02145b5e1bfa0e1236388510662f2aaf79172 100644 (file)
@@ -61,6 +61,7 @@ enum action_type {
        ACTION_TYPE_SEND_TO_DESKTOP,
        ACTION_TYPE_SNAP_TO_REGION,
        ACTION_TYPE_TOGGLE_KEYBINDS,
+       ACTION_TYPE_FOCUS_OUTPUT,
 };
 
 const char *action_names[] = {
@@ -90,6 +91,7 @@ const char *action_names[] = {
        "SendToDesktop",
        "SnapToRegion",
        "ToggleKeybinds",
+       "FocusOutput",
        NULL
 };
 
@@ -119,6 +121,9 @@ action_arg_from_xml_node(struct action *action, char *nodename, char *content)
        } else if (!strcmp(nodename, "region.action")) {
                /* SnapToRegion */
                action_arg_add_str(action, NULL, content);
+       } else if (!strcmp(nodename, "output.action")) {
+               /* FocusOutput */
+               action_arg_add_str(action, NULL, content);
        }
 }
 
@@ -470,6 +475,14 @@ actions_run(struct view *activator, struct server *server,
                        wlr_log(WLR_DEBUG, "%s keybinds",
                                server->seat.inhibit_keybinds ? "Disabled" : "Enabled");
                        break;
+               case ACTION_TYPE_FOCUS_OUTPUT:
+                       if (!arg) {
+                               wlr_log(WLR_ERROR, "Missing argument for FocusOutput");
+                               break;
+                       }
+                       const char *output_name = action_str_from_arg(arg);
+                       desktop_focus_output(output_from_name(server, output_name));
+                       break;
                case ACTION_TYPE_INVALID:
                        wlr_log(WLR_ERROR, "Not executing unknown action");
                        break;
index 5c7151fc8312ad51a9ae6cd0a5ff6e250e3a4c17..3b871f517d5e25fab5c236c008dbc7fa948ec164 100644 (file)
@@ -268,6 +268,46 @@ desktop_focus_topmost_mapped_view(struct server *server)
        desktop_move_to_front(view);
 }
 
+void
+desktop_focus_output(struct output *output)
+{
+       if (!output_is_usable(output) || output->server->input_mode
+                       != LAB_INPUT_STATE_PASSTHROUGH) {
+               return;
+       }
+       struct view *view;
+       struct wlr_scene_node *node;
+       struct wlr_output_layout *layout = output->server->output_layout;
+       struct wl_list *list_head =
+               &output->server->workspace_current->tree->children;
+       wl_list_for_each_reverse(node, list_head, link) {
+               if (!node->data) {
+                       continue;
+               }
+               view = node_view_from_node(node);
+               if (!isfocusable(view)) {
+                       continue;
+               }
+               if (wlr_output_layout_intersects(layout,
+                               output->wlr_output, &view->current)) {
+                       desktop_focus_and_activate_view(&output->server->seat, view);
+                       wlr_cursor_warp(output->server->seat.cursor, NULL,
+                               view->current.x + view->current.width / 2,
+                               view->current.y + view->current.height / 2);
+                       cursor_update_focus(output->server);
+                       return;
+               }
+       }
+       /* No view found on desired output */
+       struct wlr_box layout_box;
+       wlr_output_layout_get_box(output->server->output_layout,
+               output->wlr_output, &layout_box);
+       wlr_cursor_warp(output->server->seat.cursor, NULL,
+               layout_box.x + output->usable_area.x + output->usable_area.width / 2,
+               layout_box.y + output->usable_area.y + output->usable_area.height / 2);
+       cursor_update_focus(output->server);
+}
+
 static struct wlr_surface *
 get_surface_from_layer_node(struct wlr_scene_node *node)
 {
index 3684ec0a30b86793a722f4f2e4ecabe393059137..1183add484e21d5c06cb399651b05469bbbcdca3 100644 (file)
@@ -8,6 +8,7 @@
 
 #define _POSIX_C_SOURCE 200809L
 #include <assert.h>
+#include <strings.h>
 #include <wlr/types/wlr_buffer.h>
 #include <wlr/types/wlr_drm_lease_v1.h>
 #include <wlr/types/wlr_output.h>
@@ -458,6 +459,21 @@ output_from_wlr_output(struct server *server, struct wlr_output *wlr_output)
        return NULL;
 }
 
+struct output *
+output_from_name(struct server *server, const char *name)
+{
+       struct output *output;
+       wl_list_for_each(output, &server->outputs, link) {
+               if (!output_is_usable(output) || !output->wlr_output->name) {
+                       continue;
+               }
+               if (!strcasecmp(name, output->wlr_output->name)) {
+                       return output;
+               }
+       }
+       return NULL;
+}
+
 struct output *
 output_nearest_to(struct server *server, int lx, int ly)
 {