From c33a404dc13a69086114472fc7713a23c55c7496 Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Fri, 3 Mar 2023 18:16:46 +0100 Subject: [PATCH] Add ToggleKeybinds action This can be used to better control Virtual Machines, VNC clients, nested compositors or similar. All keybinds other than ToggleKeybinds itself are disabled when first called, a 2nd call will restore handling of all keybinds. Fixes #738 Fixes #810 --- docs/labwc-actions.5.scd | 6 ++++++ include/action.h | 2 ++ include/labwc.h | 3 +++ src/action.c | 21 ++++++++++++++++++++- src/keyboard.c | 4 ++++ 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd index 98c246d1..72e81d6e 100644 --- a/docs/labwc-actions.5.scd +++ b/docs/labwc-actions.5.scd @@ -74,6 +74,12 @@ Actions are used in menus and keyboard/mouse bindings. ** Toggle always-on-top of focused window. +** + Stop handling keybinds other than ToggleKeybinds itself. + This can be used to allow A-Tab and similar keybinds to be delivered + to Virtual Machines, VNC clients or nested compositors. + A second call will restore all original keybinds. + ** 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 diff --git a/include/action.h b/include/action.h index 326f96d5..96697597 100644 --- a/include/action.h +++ b/include/action.h @@ -22,6 +22,8 @@ struct action *action_create(const char *action_name); void action_arg_add_str(struct action *action, char *key, const char *value); void action_arg_from_xml_node(struct action *action, char *nodename, char *content); +bool actions_contain_toggle_keybinds(struct wl_list *action_list); + void actions_run(struct view *activator, struct server *server, struct wl_list *actions, uint32_t resize_edges); void action_list_free(struct wl_list *action_list); diff --git a/include/labwc.h b/include/labwc.h index d038963f..378e1e20 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -121,6 +121,9 @@ struct seat { struct wlr_idle *wlr_idle; struct wlr_idle_inhibit_manager_v1 *wlr_idle_inhibit_manager; + /* In support for ToggleKeybinds */ + bool inhibit_keybinds; + /* Used to hide the workspace OSD after switching workspaces */ struct wl_event_source *workspace_osd_timer; bool workspace_osd_shown_by_modifier; diff --git a/src/action.c b/src/action.c index 5c36e00b..61f6612f 100644 --- a/src/action.c +++ b/src/action.c @@ -59,7 +59,8 @@ enum action_type { ACTION_TYPE_RESIZE, ACTION_TYPE_GO_TO_DESKTOP, ACTION_TYPE_SEND_TO_DESKTOP, - ACTION_TYPE_SNAP_TO_REGION + ACTION_TYPE_SNAP_TO_REGION, + ACTION_TYPE_TOGGLE_KEYBINDS, }; const char *action_names[] = { @@ -88,6 +89,7 @@ const char *action_names[] = { "GoToDesktop", "SendToDesktop", "SnapToRegion", + "ToggleKeybinds", NULL }; @@ -169,6 +171,18 @@ action_create(const char *action_name) return action; } +bool +actions_contain_toggle_keybinds(struct wl_list *action_list) +{ + struct action *action; + wl_list_for_each(action, action_list, link) { + if (action->type == ACTION_TYPE_TOGGLE_KEYBINDS) { + return true; + } + } + return false; +} + void action_list_free(struct wl_list *action_list) { struct action_arg *arg, *arg_tmp; @@ -451,6 +465,11 @@ actions_run(struct view *activator, struct server *server, wlr_log(WLR_ERROR, "Invalid SnapToRegion id: '%s'", region_name); } break; + case ACTION_TYPE_TOGGLE_KEYBINDS: + server->seat.inhibit_keybinds = !server->seat.inhibit_keybinds; + wlr_log(WLR_DEBUG, "%s keybinds", + server->seat.inhibit_keybinds ? "Disabled" : "Enabled"); + break; case ACTION_TYPE_INVALID: wlr_log(WLR_ERROR, "Not executing unknown action"); break; diff --git a/src/keyboard.c b/src/keyboard.c index 6a6dd2f7..a0edc024 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -86,6 +86,10 @@ handle_keybinding(struct server *server, uint32_t modifiers, xkb_keysym_t sym) if (modifiers ^ keybind->modifiers) { continue; } + if (server->seat.inhibit_keybinds + && !actions_contain_toggle_keybinds(&keybind->actions)) { + continue; + } for (size_t i = 0; i < keybind->keysyms_len; i++) { if (xkb_keysym_to_lower(sym) == keybind->keysyms[i]) { key_state_store_pressed_keys_as_bound();