From e5927094d18ba991c4200c031cc6392736145e73 Mon Sep 17 00:00:00 2001 From: Zedhugh Chen Date: Sat, 22 Nov 2025 22:22:54 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E5=BF=AB=E6=8D=B7=E9=94=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CMakeLists.txt | 1 + src/action.c | 10 ++++++++++ src/action.h | 16 +++++++++++++--- src/default_config.h | 7 +++++++ src/event.c | 13 +++++++++++-- src/wm.c | 25 ++++++++++++++++++++++++- src/wm.h | 2 ++ src/xwindow.c | 22 ++++++++++++++++++++++ src/xwindow.h | 3 +++ 9 files changed, 93 insertions(+), 6 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d95ba2a..4e8cf7e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -46,6 +46,7 @@ pkg_check_modules(deps REQUIRED xcb xcb-aux xcb-cursor + xcb-keysyms xcb-randr xcb-xfixes xcb-xinerama diff --git a/src/action.c b/src/action.c index fbf12ee..eb4f92d 100644 --- a/src/action.c +++ b/src/action.c @@ -1,8 +1,18 @@ #include "action.h" +#include +#include + #include "monitor.h" #include "wm.h" void select_tag_of_current_monitor(const user_action_arg_t *arg) { monitor_select_tag(wm.current_monitor, arg->ui); } + +void spawn(const user_action_arg_t *arg) { + const char *cmd = (const char *)arg->ptr; + if (cmd == nullptr || strlen(cmd) == 0) return; + + g_spawn_command_line_async((const char *)arg->ptr, nullptr); +} diff --git a/src/action.h b/src/action.h index 8659b79..f0f472a 100644 --- a/src/action.h +++ b/src/action.h @@ -7,7 +7,7 @@ typedef union user_action_arg_t { bool b; int32_t i; uint32_t ui; - void *ptr; + const void *ptr; } user_action_arg_t; typedef enum click_area_t { @@ -24,6 +24,8 @@ typedef enum modifier_t { modifier_any = XCB_MOD_MASK_ANY, } modifier_t; +typedef uint16_t modifier_value_t; + typedef enum button_index_t { button_any = XCB_BUTTON_INDEX_ANY, button_left = XCB_BUTTON_INDEX_1, @@ -32,11 +34,19 @@ typedef enum button_index_t { } button_index_t; typedef struct button_t { - click_area_t click_area; - modifier_t modifiers; + click_area_t click_area : 16; + modifier_value_t modifiers; button_index_t button; void (*func)(const user_action_arg_t *arg); const user_action_arg_t arg; } button_t; +typedef struct keyboard_t { + modifier_value_t modifiers; + xcb_keysym_t keysym; + void (*func)(const user_action_arg_t *arg); + const user_action_arg_t arg; +} keyboard_t; + void select_tag_of_current_monitor(const user_action_arg_t *arg); +void spawn(const user_action_arg_t *arg); diff --git a/src/default_config.h b/src/default_config.h index dcf6410..9b25158 100644 --- a/src/default_config.h +++ b/src/default_config.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "action.h" @@ -23,3 +24,9 @@ static const char *const active_tag_color = "#eeeeee"; static const button_t button_list[] = { {click_tag, modifier_none, button_left, select_tag_of_current_monitor, {0}}, }; + +static const char launcher[] = + "rofi -show combi -modes window,drun,run,ssh,combi,windowcd"; +static const keyboard_t key_list[] = { + {modifier_super, XK_p, spawn, {.ptr = launcher}}, +}; diff --git a/src/event.c b/src/event.c index 57d83a7..9b4c6a8 100644 --- a/src/event.c +++ b/src/event.c @@ -2,9 +2,9 @@ #include #include -#include #include #include +#include #include #include "action.h" @@ -46,7 +46,16 @@ static void button_press(xcb_button_press_event_t *ev) { } } -static void key_press(xcb_key_press_event_t *ev) { printf("key press\n"); } +static void key_press(xcb_key_press_event_t *ev) { + xcb_keysym_t keysym = xcb_key_press_lookup_keysym(wm.key_symbols, ev, 0); + for (int i = 0; i < countof(key_list); i++) { + keyboard_t key = key_list[i]; + if (keysym == key.keysym && ev->state == key.modifiers && key.func) { + key.func(&key.arg); + return; + } + } +} static void handle_xcb_event(xcb_generic_event_t *event) { uint8_t event_type = XCB_EVENT_RESPONSE_TYPE(event); diff --git a/src/wm.c b/src/wm.c index 78c7d63..3fce2d9 100644 --- a/src/wm.c +++ b/src/wm.c @@ -12,10 +12,12 @@ #include #include #include +#include #include #include #include +#include "action.h" #include "backtrace.h" #include "buffer.h" #include "color.h" @@ -36,6 +38,7 @@ static void wm_scan_clients(void); static void wm_clean(void); static void wm_setup(void); static void wm_init_color_set(void); +static void wm_setup_keybindings(void); wm_t wm; @@ -265,6 +268,8 @@ void wm_clean(void) { } xcursor_clean(); + xcb_ungrab_key(wm.xcb_conn, XCB_GRAB_ANY, wm.screen->root, modifier_any); + xcb_key_symbols_free(wm.key_symbols); xcb_disconnect(wm.xcb_conn); } @@ -285,7 +290,15 @@ static void wm_setup(void) { monitor_draw_bar(m); } - xwindow_change_cursor(wm.screen->root, cursor_normal); + xcb_params_cw_t params = { + .cursor = xcursor_get_xcb_cursor(cursor_normal), + .event_mask = + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_KEY_PRESS, + }; + xcb_aux_change_window_attributes(wm.xcb_conn, wm.screen->root, XCB_CW_CURSOR, + ¶ms); + + wm_setup_keybindings(); xcb_flush(wm.xcb_conn); } @@ -297,6 +310,16 @@ void wm_init_color_set(void) { color_parse(active_tag_color, &wm.color_set.active_tag_color); } +void wm_setup_keybindings(void) { + if (wm.key_symbols) { + xcb_key_symbols_free(wm.key_symbols); + p_delete(&wm.key_symbols); + } + + wm.key_symbols = xcb_key_symbols_alloc(wm.xcb_conn); + xwindow_grab_keys(wm.screen->root, key_list, countof(key_list)); +} + void wm_restart(void) { wm_atexit(true); execvp(cmd_argv[0], cmd_argv); diff --git a/src/wm.h b/src/wm.h index 74e26ee..784448a 100644 --- a/src/wm.h +++ b/src/wm.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "types.h" @@ -19,6 +20,7 @@ typedef struct wm_t { xcb_connection_t *xcb_conn; xcb_screen_t *screen; + xcb_key_symbols_t *key_symbols; int default_screen; bool have_xfixes; bool have_xinerama; diff --git a/src/xwindow.c b/src/xwindow.c index 8aca2db..9d54e2f 100644 --- a/src/xwindow.c +++ b/src/xwindow.c @@ -1,7 +1,11 @@ #include "xwindow.h" +#include #include +#include +#include +#include "action.h" #include "utils.h" #include "wm.h" #include "xcursor.h" @@ -105,3 +109,21 @@ void xwindow_change_cursor(xcb_window_t window, cursor_t cursor) { xcb_params_cw_t params = {.cursor = xcursor_get_xcb_cursor(cursor)}; xcb_aux_change_window_attributes(wm.xcb_conn, window, XCB_CW_CURSOR, ¶ms); } + +void xwindow_grab_keys(xcb_window_t window, const keyboard_t *keys, + int keys_length) { + xcb_connection_t *conn = wm.xcb_conn; + xcb_ungrab_key(conn, XCB_GRAB_ANY, window, modifier_any); + + xcb_grab_mode_t mode = XCB_GRAB_MODE_ASYNC; + for (int i = 0; i < keys_length; i++) { + xcb_keycode_t *keycodes = + xcb_key_symbols_get_keycode(wm.key_symbols, keys[i].keysym); + if (keycodes) { + for (xcb_keycode_t *kc = keycodes; *kc != XCB_NO_SYMBOL; kc++) { + xcb_grab_key(conn, true, window, keys[i].modifiers, *kc, mode, mode); + } + p_delete(&keycodes); + } + } +} diff --git a/src/xwindow.h b/src/xwindow.h index dd2af65..3373778 100644 --- a/src/xwindow.h +++ b/src/xwindow.h @@ -3,6 +3,7 @@ #include #include +#include "action.h" #include "xcursor.h" typedef struct visual_t { @@ -12,3 +13,5 @@ typedef struct visual_t { visual_t *xwindow_get_xcb_visual(bool prefer_alpha); void xwindow_change_cursor(xcb_window_t window, cursor_t cursor); +void xwindow_grab_keys(xcb_window_t window, const keyboard_t *keys, + int keys_length);