From f3b8be8cf182f24daafe95675ca9b69f676b0dff Mon Sep 17 00:00:00 2001 From: Zedhugh Chen Date: Sun, 26 Apr 2026 19:03:18 +0800 Subject: [PATCH] =?UTF-8?q?feat(backend/X11):=20=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E6=8C=89=E9=94=AE=E6=8A=93=E5=8F=96=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/x11/backend.c | 12 +++++++++ src/backend/x11/internal.h | 2 ++ src/backend/x11/window.c | 52 ++++++++++++++++++++++++++++++++++++++ src/backend/x11/window.h | 8 ++++++ src/core/binding.c | 2 +- src/core/event.h | 3 --- src/core/plan.h | 12 +++++++++ src/core/types.h | 3 +++ 8 files changed, 90 insertions(+), 4 deletions(-) diff --git a/src/backend/x11/backend.c b/src/backend/x11/backend.c index 5e9a4f8..b1f11d5 100644 --- a/src/backend/x11/backend.c +++ b/src/backend/x11/backend.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -160,6 +161,8 @@ backend_t *backend_create(const char *display_name) { backend->have_xfixes = false; } + backend->key_symbols = xcb_key_symbols_alloc(conn); + atoms_init(backend); create_wm_check_window(backend); create_no_focus_window(backend); @@ -456,6 +459,12 @@ find_or_push_configure(window_configure_list_t *configs, xcb_window_t window) { return cfg; } +static void +backend_bind_key(backend_t *backend, const effect_bind_key_t *bind_key) { + auto root = backend->screen->root; + window_grab_keys(backend, root, bind_key->keys, bind_key->count); +} + static void backend_merge_effects( backend_t *backend, const effect_t *effects, @@ -517,6 +526,9 @@ static void backend_merge_effects( backend_restack_windows(backend, &e->as.restack_windows); backend_change_window_list(backend, true, &e->as.restack_windows); break; + case ZDWM_EFFECT_BIND_KEY: + backend_bind_key(backend, &e->as.bind_key); + break; } } } diff --git a/src/backend/x11/internal.h b/src/backend/x11/internal.h index fed2702..2f27550 100644 --- a/src/backend/x11/internal.h +++ b/src/backend/x11/internal.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #define ATOM_LIST(X) \ @@ -76,6 +77,7 @@ typedef struct window_list_t { } window_list_t; struct backend_t { + xcb_key_symbols_t *key_symbols; xcb_connection_t *conn; xcb_screen_t *screen; int screenp; diff --git a/src/backend/x11/window.c b/src/backend/x11/window.c index a122d37..178b6a8 100644 --- a/src/backend/x11/window.c +++ b/src/backend/x11/window.c @@ -4,11 +4,14 @@ #include #include #include +#include #include #include "base/array.h" +#include "base/macros.h" #include "base/memory.h" #include "core/backend.h" +#include "core/types.h" #include "internal.h" static char *window_get_text_property( @@ -326,3 +329,52 @@ void window_list_reset(window_list_t *window_list) { p_clear(window_list->windows, window_list->count); window_list->count = 0; } + +static uint16_t get_xcb_modifier(modifier_mask_t modifiers) { + typedef struct modifier_map_t { + modifier_bit_t modifier; + xcb_mod_mask_t mask; + } modifier_map_t; + static constexpr modifier_map_t modifier_map[] = { + {ZDWM_MOD_SHIFT, XCB_MOD_MASK_SHIFT}, + {ZDWM_MOD_CONTROL, XCB_MOD_MASK_CONTROL}, + {ZDWM_MOD_1, XCB_MOD_MASK_1}, + {ZDWM_MOD_2, XCB_MOD_MASK_2}, + {ZDWM_MOD_3, XCB_MOD_MASK_3}, + {ZDWM_MOD_4, XCB_MOD_MASK_4}, + {ZDWM_MOD_5, XCB_MOD_MASK_5}, + }; + + uint16_t mods = ZDWM_MOD_NONE; + for (size_t i = 0; i < countof(modifier_map); ++i) { + auto item = &modifier_map[i]; + if (modifiers & item->modifier) mods |= item->mask; + } + return mods; +} + +void window_grab_keys( + backend_t *backend, + xcb_window_t window, + const key_bind_t *keys, + size_t count +) { + auto conn = backend->conn; + auto key_symbols = backend->key_symbols; + + xcb_ungrab_key(conn, XCB_GRAB_ANY, window, XCB_MOD_MASK_ANY); + + xcb_grab_mode_t mode = XCB_GRAB_MODE_ASYNC; + + for (size_t i = 0; i < count; ++i) { + auto key = &keys[i]; + auto keycodes = xcb_key_symbols_get_keycode(key_symbols, keys->keysym); + if (!keycodes) continue; + + auto modifiers = get_xcb_modifier(key->modifiers); + for (auto keycode = keycodes; *keycode != XCB_NO_SYMBOL; ++keycode) { + xcb_grab_key(conn, true, window, modifiers, *keycode, mode, mode); + } + p_delete(&keycodes); + } +} diff --git a/src/backend/x11/window.h b/src/backend/x11/window.h index 79bc61d..43e463e 100644 --- a/src/backend/x11/window.h +++ b/src/backend/x11/window.h @@ -7,6 +7,7 @@ #include #include "core/backend.h" +#include "core/plan.h" #include "internal.h" typedef struct atoms_t atoms_t; @@ -87,3 +88,10 @@ void window_clean_event_mask(xcb_connection_t *conn, xcb_window_t window); void window_list_push(window_list_t *window_list, xcb_window_t window); void window_list_reset(window_list_t *window_list); + +void window_grab_keys( + backend_t *backend, + xcb_window_t window, + const key_bind_t *keys, + size_t count +); diff --git a/src/core/binding.c b/src/core/binding.c index e3fed1c..5813e53 100644 --- a/src/core/binding.c +++ b/src/core/binding.c @@ -12,7 +12,7 @@ #include "base/array.h" #include "base/macros.h" #include "base/memory.h" -#include "core/event.h" +#include "core/types.h" typedef struct key_binding_t { const char *key_str; diff --git a/src/core/event.h b/src/core/event.h index 9f01c34..7c4fd54 100644 --- a/src/core/event.h +++ b/src/core/event.h @@ -20,9 +20,6 @@ typedef enum event_type_t { ZDWM_EVENT_CONFIGURE_REQUEST, } event_type_t; -typedef uint32_t modifier_mask_t; -typedef uint32_t keysym_t; - typedef struct key_press_event_t { modifier_mask_t modifiers; keysym_t keysym; diff --git a/src/core/plan.h b/src/core/plan.h index cdabaef..cb9fcf0 100644 --- a/src/core/plan.h +++ b/src/core/plan.h @@ -16,6 +16,7 @@ typedef enum effect_type_t { ZDWM_EFFECT_CHANGE_BORDER_WIDTH, ZDWM_EFFECT_CHANGE_WINDOW_LIST, ZDWM_EFFECT_RESTACK_WINDOWS, + ZDWM_EFFECT_BIND_KEY, } effect_type_t; typedef struct effect_only_window_id_t { @@ -48,6 +49,16 @@ typedef struct effect_window_list_t { size_t count; } effect_window_list_t; +typedef struct key_bind_t { + modifier_mask_t modifiers; + keysym_t keysym; +} key_bind_t; + +typedef struct effect_bind_key_t { + const key_bind_t *keys; + size_t count; +} effect_bind_key_t; + typedef struct effect_t { effect_type_t type; union { @@ -61,6 +72,7 @@ typedef struct effect_t { effect_change_border_width_t change_border_width; effect_window_list_t change_window_list; effect_window_list_t restack_windows; + effect_bind_key_t bind_key; } as; } effect_t; diff --git a/src/core/types.h b/src/core/types.h index f8ef791..4a80689 100644 --- a/src/core/types.h +++ b/src/core/types.h @@ -17,6 +17,9 @@ typedef zdwm_rule_match_t rule_match_t; typedef zdwm_rule_action_t rule_action_t; /* clang-format on */ +typedef uint32_t modifier_mask_t; +typedef uint32_t keysym_t; + #define ZDWM_OUTPUT_ID_INVALID ((output_id_t)UINT32_MAX) typedef struct point_t {