From 95c6279bdd96eb48d56c9ba3cb1138aa18820ab7 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 18 May 2025 14:30:33 +0530 Subject: [PATCH] Implement --grab-keyboard Currently works on Wayland. --- docs/changelog.rst | 2 ++ kittens/panel/main.py | 2 ++ kittens/quick_access_terminal/main.go | 3 +++ kittens/quick_access_terminal/main.py | 4 +++- kitty/boss.py | 7 ++----- kitty/keys.py | 1 + kitty/main.py | 3 +++ kitty/simple_cli_definitions.py | 24 +++++++++++++++++++++--- 8 files changed, 37 insertions(+), 9 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 78354f127..bd1415536 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -111,6 +111,8 @@ Detailed list of changes - Fix :opt:`remember_window_position` not working because of a stupid typo (:iss:`8646`) +- A new :option:`kitty --grab-keyboard` that can be used to grab the keyboard so that global shortcuts are sent to kitty instead + 0.42.1 [2025-05-17] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/kittens/panel/main.py b/kittens/panel/main.py index d61e17779..4ec9d1e35 100644 --- a/kittens/panel/main.py +++ b/kittens/panel/main.py @@ -161,6 +161,8 @@ def actual_main(sys_args: list[str]) -> None: sys.argv.extend(('--name', args.name)) if args.start_as_hidden: sys.argv.append('--start-as=hidden') + if args.grab_keyboard: + sys.argv.append('--grab-keyboard') for override in args.override: sys.argv.extend(('--override', override)) sys.argv.append('--override=linux_display_server=auto') diff --git a/kittens/quick_access_terminal/main.go b/kittens/quick_access_terminal/main.go index 2cd93f1f9..262676022 100644 --- a/kittens/quick_access_terminal/main.go +++ b/kittens/quick_access_terminal/main.go @@ -74,6 +74,9 @@ func main(cmd *cli.Command, opts *Options, args []string) (rc int, err error) { if conf.Start_as_hidden { argv = append(argv, `--start-as-hidden`) } + if conf.Grab_keyboard { + argv = append(argv, `--grab-keyboard`) + } if conf.Hide_on_focus_loss { argv = append(argv, `--hide-on-focus-loss`) } diff --git a/kittens/quick_access_terminal/main.py b/kittens/quick_access_terminal/main.py index 5a83f6439..f95f4176d 100644 --- a/kittens/quick_access_terminal/main.py +++ b/kittens/quick_access_terminal/main.py @@ -5,7 +5,7 @@ import sys from kitty.conf.types import Definition from kitty.constants import appname -from kitty.simple_cli_definitions import CONFIG_HELP +from kitty.simple_cli_definitions import CONFIG_HELP, grab_keyboard_docs help_text = 'A quick access terminal window that you can bring up instantly with a keypress or a command.' @@ -45,6 +45,8 @@ Hide the window when it loses keyboard focus automatically. Using this option will force :opt:`focus_policy` to :code:`on-demand`. ''') +opt('grab_keyboard', 'no', option_type='to_bool', long_text=grab_keyboard_docs) + opt('margin_left', '0', option_type='int', long_text='Set the left margin for the window, in pixels. Has no effect for windows on the right edge of the screen.') diff --git a/kitty/boss.py b/kitty/boss.py index babb6c89e..d0e37fe24 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -123,6 +123,7 @@ from .options.utils import MINIMUM_FONT_SIZE, KeyboardMode, KeyDefinition from .os_window_size import initial_window_size_func from .session import Session, create_sessions, get_os_window_sizing_data from .shaders import load_shader_programs +from .simple_cli_definitions import grab_keyboard_docs from .tabs import SpecialWindow, SpecialWindowInstance, Tab, TabDict, TabManager from .types import _T, AsyncResponse, LayerShellConfig, SingleInstanceData, WindowSystemMouseEvent, ac from .typing_compat import PopenType, TypedDict @@ -3204,11 +3205,7 @@ class Boss: continue window.screen.clear_selection() - @ac('misc', ''' - Grab the keyboard. This means global shortcuts defined in the OS will be handled in kitty instead. How well this - works depends on the OS/window manager/desktop environment. On Wayland it works only if the compositor implements - the :link:`inhibit-keyboard-shortcuts protocol `. - ''') + @ac('misc', grab_keyboard_docs) def grab_keyboard(self) -> None: grab_keyboard(True) diff --git a/kitty/keys.py b/kitty/keys.py index 7b8a1786d..24cbcdc2f 100644 --- a/kitty/keys.py +++ b/kitty/keys.py @@ -160,6 +160,7 @@ class Mappings: key_action = get_shortcut(mode.keymap, ev) if key_action is None and self.global_shortcuts_map and (global_key_action := get_shortcut(self.global_shortcuts_map, ev)) is not None: if grab_keyboard(None): + # the shortcuts in the global menubar will have been bypassed so trigger them here key_action = global_key_action else: return True diff --git a/kitty/main.py b/kitty/main.py index cc4784ad1..6ffc41344 100644 --- a/kitty/main.py +++ b/kitty/main.py @@ -42,6 +42,7 @@ from .fast_data_types import ( glfw_get_monitor_workarea, glfw_init, glfw_terminate, + grab_keyboard, is_layer_shell_supported, load_png_data, mask_kitty_signals_process_wide, @@ -256,6 +257,8 @@ def _run_app(opts: Options, args: CLIOptions, bad_lines: Sequence[BadLine] = (), if _is_panel_kitten and not is_layer_shell_supported(): raise SystemExit('Cannot create panels as the window manager/compositor does not support the neccessary protocols') pos_x, pos_y = None, None + if args.grab_keyboard: + grab_keyboard(True) with cached_values_for(run_app.cached_values_name) as cached_values: if not _is_panel_kitten and not is_wayland(): if opts.remember_window_position: diff --git a/kitty/simple_cli_definitions.py b/kitty/simple_cli_definitions.py index 6e7175f1e..0d37eef8f 100644 --- a/kitty/simple_cli_definitions.py +++ b/kitty/simple_cli_definitions.py @@ -323,6 +323,13 @@ def generate_c_parsers() -> Iterator[str]: # kitty CLI spec {{{ +grab_keyboard_docs = """\ +Grab the keyboard. This means global shortcuts defined in the OS will be passed to kitty instead. Useful if +you want to create an OS modal window. How well this +works depends on the OS/window manager/desktop environment. On Wayland it works only if the compositor implements +the :link:`inhibit-keyboard-shortcuts protocol `. +""" + listen_on_defn = f'''\ --listen-on completion=type:special group:complete_kitty_listen_on @@ -484,6 +491,11 @@ See also :opt:`remember_window_position` to have kitty automatically try to restore the previous window position. +--grab-keyboard +type=bool-set +{grab_keyboard_docs} + + # Debugging options --version -v @@ -539,8 +551,9 @@ type=bool-set ''' setattr(kitty_options_spec, 'ans', OPTIONS.format( appname=appname, conf_name=appname, listen_on_defn=listen_on_defn, - config_help=CONFIG_HELP.format(appname=appname, conf_name=appname), - )) + grab_keyboard_docs=grab_keyboard_docs, + config_help=CONFIG_HELP.format(appname=appname, conf_name=appname + ))) ans: str = getattr(kitty_options_spec, 'ans') return ans # }}} @@ -675,6 +688,11 @@ to :code:`on-demand`. Note that on Wayland, depending on the compositor, this ca becoming visible. +--grab-keyboard +type=bool-set +{grab_keyboard_docs} + + --exclusive-zone type=int default={exclusive_zone} @@ -740,7 +758,7 @@ Path to a log file to store STDOUT/STDERR when using :option:`--detach` --debug-rendering type=bool-set For internal debugging use. -'''.format(appname=appname, listen_on_defn=listen_on_defn, **d) +'''.format(appname=appname, listen_on_defn=listen_on_defn, grab_keyboard_docs=grab_keyboard_docs, **d) # }}}