mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-02 12:44:01 +02:00
Work on keyboard grabbing functionality
This commit is contained in:
@@ -828,7 +828,7 @@ int _glfwPlatformInit(bool *supports_window_occlusion)
|
||||
{
|
||||
debug_key("---------------- key down -------------------\n");
|
||||
debug_key("%s\n", [[event description] UTF8String]);
|
||||
if (!_glfw.ignoreOSKeyboardProcessing) {
|
||||
if (!_glfw.ignoreOSKeyboardProcessing && !_glfw.keyboard_grabbed) {
|
||||
// first check if there is a global menu bar shortcut
|
||||
if ([[NSApp mainMenu] performKeyEquivalent:event]) {
|
||||
debug_key("keyDown triggered global menu bar action ignoring\n");
|
||||
@@ -1144,3 +1144,4 @@ void _glfwPlatformUpdateTimer(unsigned long long timer_id, monotonic_t interval,
|
||||
}
|
||||
|
||||
void _glfwPlatformInputColorScheme(GLFWColorScheme appearance UNUSED) { }
|
||||
bool _glfwPlatformGrabKeyboard(bool grab UNUSED) { return true; /* directly uses _glfw.keyboard_grabbed */ }
|
||||
|
||||
1
glfw/glfw3.h
vendored
1
glfw/glfw3.h
vendored
@@ -4247,6 +4247,7 @@ GLFWAPI void glfwPostEmptyEvent(void);
|
||||
|
||||
GLFWAPI bool glfwGetIgnoreOSKeyboardProcessing(void);
|
||||
GLFWAPI void glfwSetIgnoreOSKeyboardProcessing(bool enabled);
|
||||
GLFWAPI bool glfwGrabKeyboard(int grab);
|
||||
|
||||
/*! @brief Returns the value of an input option for the specified window.
|
||||
*
|
||||
|
||||
7
glfw/input.c
vendored
7
glfw/input.c
vendored
@@ -684,6 +684,13 @@ GLFWAPI void glfwSetIgnoreOSKeyboardProcessing(bool enabled) {
|
||||
_glfw.ignoreOSKeyboardProcessing = enabled;
|
||||
}
|
||||
|
||||
GLFWAPI bool glfwGrabKeyboard(int grab) {
|
||||
if (grab == 0 || grab == 1) {
|
||||
if (_glfwPlatformGrabKeyboard(grab)) _glfw.keyboard_grabbed = grab;
|
||||
}
|
||||
return _glfw.keyboard_grabbed;
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
|
||||
3
glfw/internal.h
vendored
3
glfw/internal.h
vendored
@@ -616,7 +616,7 @@ struct _GLFWlibrary
|
||||
_GLFWtls contextSlot;
|
||||
_GLFWmutex errorLock;
|
||||
|
||||
bool ignoreOSKeyboardProcessing;
|
||||
bool ignoreOSKeyboardProcessing, keyboard_grabbed;
|
||||
|
||||
struct {
|
||||
bool available;
|
||||
@@ -884,6 +884,7 @@ void _glfwPlatformUpdateTimer(unsigned long long timer_id, monotonic_t interval,
|
||||
void _glfwPlatformRemoveTimer(unsigned long long timer_id);
|
||||
int _glfwPlatformSetWindowBlur(_GLFWwindow* handle, int value);
|
||||
MonitorGeometry _glfwPlatformGetMonitorGeometry(_GLFWmonitor* monitor);
|
||||
bool _glfwPlatformGrabKeyboard(bool grab);
|
||||
|
||||
char* _glfw_strdup(const char* source);
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
"staging/fractional-scale/fractional-scale-v1.xml",
|
||||
"staging/single-pixel-buffer/single-pixel-buffer-v1.xml",
|
||||
"unstable/idle-inhibit/idle-inhibit-unstable-v1.xml",
|
||||
"unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml",
|
||||
"staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml",
|
||||
"staging/xdg-system-bell/xdg-system-bell-v1.xml",
|
||||
"staging/xdg-toplevel-tag/xdg-toplevel-tag-v1.xml",
|
||||
|
||||
7
glfw/wl_init.c
vendored
7
glfw/wl_init.c
vendored
@@ -600,6 +600,9 @@ static void registryHandleGlobal(void* data UNUSED,
|
||||
else if (is(zwp_idle_inhibit_manager_v1)) {
|
||||
_glfw.wl.idle_inhibit_manager = wl_registry_bind(registry, name, &zwp_idle_inhibit_manager_v1_interface, 1);
|
||||
}
|
||||
else if (is(zwp_keyboard_shortcuts_inhibit_manager_v1)) {
|
||||
_glfw.wl.keyboard_shortcuts_inhibit_manager = wl_registry_bind(registry, name, &zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1);
|
||||
}
|
||||
else if (is(xdg_toplevel_icon_manager_v1)) {
|
||||
_glfw.wl.xdg_toplevel_icon_manager_v1 = wl_registry_bind(registry, name, &xdg_toplevel_icon_manager_v1_interface, 1);
|
||||
}
|
||||
@@ -718,7 +721,7 @@ get_compositor_missing_capabilities(void) {
|
||||
C(cursor_shape, wp_cursor_shape_manager_v1); C(layer_shell, zwlr_layer_shell_v1);
|
||||
C(single_pixel_buffer, wp_single_pixel_buffer_manager_v1); C(preferred_scale, has_preferred_buffer_scale);
|
||||
C(idle_inhibit, idle_inhibit_manager); C(icon, xdg_toplevel_icon_manager_v1); C(bell, xdg_system_bell_v1);
|
||||
C(window-tag, xdg_toplevel_tag_manager_v1);
|
||||
C(window-tag, xdg_toplevel_tag_manager_v1); C(keyboard_shortcuts_inhibit, keyboard_shortcuts_inhibit_manager);
|
||||
if (_glfw.wl.xdg_wm_base_version < 6) p += snprintf(p, sizeof(buf) - (p - buf), "%s ", "window-state-suspended");
|
||||
if (_glfw.wl.xdg_wm_base_version < 5) p += snprintf(p, sizeof(buf) - (p - buf), "%s ", "window-capabilities");
|
||||
#undef C
|
||||
@@ -913,6 +916,8 @@ void _glfwPlatformTerminate(void)
|
||||
zwlr_layer_shell_v1_destroy(_glfw.wl.zwlr_layer_shell_v1);
|
||||
if (_glfw.wl.idle_inhibit_manager)
|
||||
zwp_idle_inhibit_manager_v1_destroy(_glfw.wl.idle_inhibit_manager);
|
||||
if (_glfw.wl.keyboard_shortcuts_inhibit_manager)
|
||||
zwp_keyboard_shortcuts_inhibit_manager_v1_destroy(_glfw.wl.keyboard_shortcuts_inhibit_manager);
|
||||
|
||||
if (_glfw.wl.registry)
|
||||
wl_registry_destroy(_glfw.wl.registry);
|
||||
|
||||
3
glfw/wl_platform.h
vendored
3
glfw/wl_platform.h
vendored
@@ -66,6 +66,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
||||
#include "wayland-wlr-layer-shell-unstable-v1-client-protocol.h"
|
||||
#include "wayland-single-pixel-buffer-v1-client-protocol.h"
|
||||
#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
|
||||
#include "wayland-keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h"
|
||||
#include "wayland-xdg-toplevel-icon-v1-client-protocol.h"
|
||||
#include "wayland-xdg-system-bell-v1-client-protocol.h"
|
||||
#include "wayland-xdg-toplevel-tag-v1-client-protocol.h"
|
||||
@@ -290,6 +291,7 @@ typedef struct _GLFWwindowWayland
|
||||
WaylandWindowState toplevel_states;
|
||||
uint32_t decoration_mode;
|
||||
} current, pending;
|
||||
struct zwp_keyboard_shortcuts_inhibitor_v1 *keyboard_shortcuts_inhibitor;
|
||||
} _GLFWwindowWayland;
|
||||
|
||||
typedef enum _GLFWWaylandOfferType
|
||||
@@ -350,6 +352,7 @@ typedef struct _GLFWlibraryWayland
|
||||
struct zwlr_layer_shell_v1* zwlr_layer_shell_v1; uint32_t zwlr_layer_shell_v1_version;
|
||||
struct wp_single_pixel_buffer_manager_v1 *wp_single_pixel_buffer_manager_v1;
|
||||
struct zwp_idle_inhibit_manager_v1* idle_inhibit_manager;
|
||||
struct zwp_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit_manager;
|
||||
|
||||
int compositorVersion;
|
||||
int seatVersion;
|
||||
|
||||
18
glfw/wl_window.c
vendored
18
glfw/wl_window.c
vendored
@@ -1469,6 +1469,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
if (window->id == _glfw.wl.keyRepeatInfo.keyboardFocusId) {
|
||||
_glfw.wl.keyRepeatInfo.keyboardFocusId = 0;
|
||||
}
|
||||
if (window->wl.keyboard_shortcuts_inhibitor)
|
||||
zwp_keyboard_shortcuts_inhibitor_v1_destroy(window->wl.keyboard_shortcuts_inhibitor);
|
||||
|
||||
if (window->wl.temp_buffer_used_during_window_creation)
|
||||
wl_buffer_destroy(window->wl.temp_buffer_used_during_window_creation);
|
||||
@@ -2820,6 +2822,22 @@ _glfwPlatformSetWindowBlur(_GLFWwindow *window, int blur_radius) {
|
||||
return has_blur ? 1 : 0;
|
||||
}
|
||||
|
||||
bool
|
||||
_glfwPlatformGrabKeyboard(bool grab) {
|
||||
if (!_glfw.wl.keyboard_shortcuts_inhibit_manager) return false;
|
||||
for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next) {
|
||||
if (grab) {
|
||||
if (window->wl.keyboard_shortcuts_inhibitor) break;
|
||||
window->wl.keyboard_shortcuts_inhibitor = zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts(_glfw.wl.keyboard_shortcuts_inhibit_manager, window->wl.surface, _glfw.wl.seat);
|
||||
} else {
|
||||
if (!window->wl.keyboard_shortcuts_inhibitor) break;
|
||||
zwp_keyboard_shortcuts_inhibitor_v1_destroy(window->wl.keyboard_shortcuts_inhibitor);
|
||||
window->wl.keyboard_shortcuts_inhibitor = NULL;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW native API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
6
glfw/x11_window.c
vendored
6
glfw/x11_window.c
vendored
@@ -3384,6 +3384,12 @@ _glfwPlatformSetWindowBlur(_GLFWwindow *window, int blur_radius) {
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_glfwPlatformGrabKeyboard(bool grab) {
|
||||
if (grab) _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Grabbing of keyboard is not currently supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW native API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -87,6 +87,7 @@ from .fast_data_types import (
|
||||
get_os_window_size,
|
||||
glfw_get_monitor_workarea,
|
||||
global_font_size,
|
||||
grab_keyboard,
|
||||
is_layer_shell_supported,
|
||||
last_focused_os_window_id,
|
||||
mark_os_window_for_close,
|
||||
@@ -3202,3 +3203,15 @@ class Boss:
|
||||
if wid == exception:
|
||||
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>`.
|
||||
''')
|
||||
def grab_keyboard(self) -> None:
|
||||
grab_keyboard(True)
|
||||
|
||||
@ac('misc', 'Ungrab the keyboard if it was previously grabbed')
|
||||
def ungrab_keyboard(self) -> None:
|
||||
grab_keyboard(False)
|
||||
|
||||
@@ -1748,6 +1748,7 @@ def buffer_keys_in_window(os_window_id: int, tab_id: int, window_id: int, enable
|
||||
def sprite_idx_to_pos(idx: int, xnum: int, ynum: int) -> tuple[int, int, int]: ...
|
||||
def render_box_char(ch: int, width: int, height: int, scale: float = 1.0, dpi_x: float = 96.0, dpi_y: float = 96.0) -> bytes: ...
|
||||
def run_at_exit_cleanup_functions() -> None: ...
|
||||
def grab_keyboard(grab: bool | None) -> bool: ...
|
||||
DecorationTypes = Literal[
|
||||
'curl', 'dashed', 'dotted', 'double', 'straight', 'strikethrough', 'beam_cursor', 'underline_cursor', 'hollow_cursor', 'missing']
|
||||
def render_decoration(
|
||||
|
||||
3
kitty/glfw-wrapper.c
generated
3
kitty/glfw-wrapper.c
generated
@@ -293,6 +293,9 @@ load_glfw(const char* path) {
|
||||
*(void **) (&glfwSetIgnoreOSKeyboardProcessing_impl) = dlsym(handle, "glfwSetIgnoreOSKeyboardProcessing");
|
||||
if (glfwSetIgnoreOSKeyboardProcessing_impl == NULL) fail("Failed to load glfw function glfwSetIgnoreOSKeyboardProcessing with error: %s", dlerror());
|
||||
|
||||
*(void **) (&glfwGrabKeyboard_impl) = dlsym(handle, "glfwGrabKeyboard");
|
||||
if (glfwGrabKeyboard_impl == NULL) fail("Failed to load glfw function glfwGrabKeyboard with error: %s", dlerror());
|
||||
|
||||
*(void **) (&glfwGetInputMode_impl) = dlsym(handle, "glfwGetInputMode");
|
||||
if (glfwGetInputMode_impl == NULL) fail("Failed to load glfw function glfwGetInputMode with error: %s", dlerror());
|
||||
|
||||
|
||||
5
kitty/glfw-wrapper.h
generated
5
kitty/glfw-wrapper.h
generated
@@ -794,6 +794,7 @@ typedef enum {
|
||||
|
||||
#define GLFW_WAYLAND_APP_ID 0x00025001
|
||||
#define GLFW_WAYLAND_BGCOLOR 0x00025002
|
||||
#define GLFW_WAYLAND_WINDOW_TAG 0x00025003
|
||||
/*! @} */
|
||||
|
||||
#define GLFW_NO_API 0
|
||||
@@ -2089,6 +2090,10 @@ typedef void (*glfwSetIgnoreOSKeyboardProcessing_func)(bool);
|
||||
GFW_EXTERN glfwSetIgnoreOSKeyboardProcessing_func glfwSetIgnoreOSKeyboardProcessing_impl;
|
||||
#define glfwSetIgnoreOSKeyboardProcessing glfwSetIgnoreOSKeyboardProcessing_impl
|
||||
|
||||
typedef bool (*glfwGrabKeyboard_func)(int);
|
||||
GFW_EXTERN glfwGrabKeyboard_func glfwGrabKeyboard_impl;
|
||||
#define glfwGrabKeyboard glfwGrabKeyboard_impl
|
||||
|
||||
typedef int (*glfwGetInputMode_func)(GLFWwindow*, int);
|
||||
GFW_EXTERN glfwGetInputMode_func glfwGetInputMode_impl;
|
||||
#define glfwGetInputMode glfwGetInputMode_impl
|
||||
|
||||
@@ -2612,6 +2612,11 @@ set_layer_shell_config(PyObject *self UNUSED, PyObject *args) {
|
||||
return Py_NewRef(set_layer_shell_config_for(window, &lsc) ? Py_True : Py_False);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
grab_keyboard(PyObject *self UNUSED, PyObject *action) {
|
||||
if (action == Py_None) return Py_NewRef(glfwGrabKeyboard(2) ? Py_True : Py_False);
|
||||
return Py_NewRef(glfwGrabKeyboard(PyObject_IsTrue(action)) ? Py_True : Py_False);
|
||||
}
|
||||
|
||||
// Boilerplate {{{
|
||||
|
||||
@@ -2621,6 +2626,7 @@ static PyMethodDef module_methods[] = {
|
||||
METHODB(toggle_os_window_visibility, METH_VARARGS),
|
||||
METHODB(layer_shell_config_for_os_window, METH_O),
|
||||
METHODB(set_layer_shell_config, METH_VARARGS),
|
||||
METHODB(grab_keyboard, METH_O),
|
||||
METHODB(pointer_name_to_css_name, METH_O),
|
||||
{"create_os_window", (PyCFunction)(void (*) (void))(create_os_window), METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
METHODB(set_default_window_icon, METH_VARARGS),
|
||||
|
||||
Reference in New Issue
Block a user