Implement --grab-keyboard

Currently works on Wayland.
This commit is contained in:
Kovid Goyal 2025-05-18 14:30:33 +05:30
parent cc4d4eeaca
commit 95c6279bdd
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
8 changed files with 37 additions and 9 deletions

View file

@ -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]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -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')

View file

@ -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`)
}

View file

@ -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.')

View file

@ -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 <https://wayland.app/protocols/keyboard-shortcuts-inhibit-unstable-v1>`.
''')
@ac('misc', grab_keyboard_docs)
def grab_keyboard(self) -> None:
grab_keyboard(True)

View file

@ -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

View file

@ -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:

View file

@ -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 <https://wayland.app/protocols/keyboard-shortcuts-inhibit-unstable-v1>`.
"""
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)
# }}}