From 56f211480f151c9b766665c502c0d8636f0ea4c0 Mon Sep 17 00:00:00 2001 From: Zedhugh Chen Date: Sat, 25 Apr 2026 07:53:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(core/binding):=20=E5=AE=9E=E7=8E=B0=20pars?= =?UTF-8?q?e=5Fkey=5Fsequence=20=E5=87=BD=E6=95=B0=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E6=8C=89=E9=94=AE=E5=BA=8F=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 1 + src/core/binding.c | 83 ++++++++++++++++++++++++++++++++++++- src/core/event.h | 7 ---- src/core/types.h | 11 +++++ tests/config/CMakeLists.txt | 1 + 5 files changed, 94 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a9597e..61394ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,7 @@ pkg_check_modules(deps REQUIRED xcb-xinerama xcb-xkb xcb-xrm + xkbcommon xkbcommon-x11 cairo diff --git a/src/core/binding.c b/src/core/binding.c index 17e23ee..e3fed1c 100644 --- a/src/core/binding.c +++ b/src/core/binding.c @@ -1,13 +1,16 @@ #include "core/binding.h" +#include #include #include +#include #include #include #include #include #include "base/array.h" +#include "base/macros.h" #include "base/memory.h" #include "core/event.h" @@ -71,23 +74,99 @@ binding_table_get_mode(binding_table_t *table, zdwm_binding_mode_id_t mode_id) { return nullptr; } +typedef struct mod_entry_t { + const char *name; + modifier_mask_t mask; +} mod_entry_t; + +static const mod_entry_t mod_table[] = { + {"Shift", ZDWM_MOD_SHIFT}, + {"Control", ZDWM_MOD_CONTROL}, + {"Mod1", ZDWM_MOD_1}, + {"Mod2", ZDWM_MOD_2}, + {"Mod3", ZDWM_MOD_3}, + {"Mod4", ZDWM_MOD_4}, + {"Mod5", ZDWM_MOD_5}, +}; + +static modifier_mask_t lookup_modifier(const char *name, size_t len) { + for (size_t i = 0; i < countof(mod_table); ++i) { + if (strlen(mod_table[i].name) == len && + strncmp(name, mod_table[i].name, len) == 0) { + return mod_table[i].mask; + } + } + return ZDWM_MOD_NONE; +} + /** * @brief 解析按键序列 * * @details 按键序列不合法解析失败,解析成功会设置 modifiers 与 keysym 对应的值 * + * @notice + * 1. modifier 仅支持 Mod1 ~ Mod5, Control, Shift + * 2. 必须保证一个且仅能有一个除 modifier 外的按键 + * 3. 按键序列通过 + 链接 + * 4. + 前后可以有多个空格 + * 5. 两个 + 之间必须有内容,如 "++", " + + " + * 6. 不能以 + 开头和结尾 + * 7. 按键符号必须能被 xkbcommon 解析,否则按键序列也不合法 + * * @param key_sequence 按键序列 * @param modifiers 返回修饰键的指针 * @param keysym 返回按键符号的指针 * * @return 解析成功返回 true 否则返回 false */ -bool parse_key_sequence( +static bool parse_key_sequence( const char *key_sequence, modifier_mask_t *modifiers, xkb_keysym_t *keysym ) { - /* TODO: */ + if (!key_sequence || !modifiers || !keysym) return false; + + modifier_mask_t mods = ZDWM_MOD_NONE; + xkb_keysym_t key = XKB_KEY_NoSymbol; + + const char *p = key_sequence; + const char *end = key_sequence + strlen(key_sequence); + + while (p < end) { + const char *plus = strchr(p, '+'); + const char *seg_end = plus ? plus : end; + + const char *s = p; + while (s < seg_end && isspace((unsigned char)*s)) ++s; + + const char *e = seg_end; + while (e > s && isspace((unsigned char)*(e - 1))) --e; + + if (s == e) return false; + + if (plus) { + modifier_mask_t mod = lookup_modifier(s, (size_t)(e - s)); + if (mod == ZDWM_MOD_NONE) return false; + mods |= mod; + p = plus + 1; + } else { + char key_buf[64]; + size_t key_len = (size_t)(e - s); + if (key_len >= sizeof(key_buf)) return false; + memcpy(key_buf, s, key_len); + key_buf[key_len] = '\0'; + + key = xkb_keysym_from_name(key_buf, XKB_KEYSYM_CASE_INSENSITIVE); + if (key == XKB_KEY_NoSymbol) { + return false; + } else { + *modifiers = mods; + *keysym = key; + return true; + } + } + } + return false; } diff --git a/src/core/event.h b/src/core/event.h index 6a70049..9f01c34 100644 --- a/src/core/event.h +++ b/src/core/event.h @@ -20,13 +20,6 @@ typedef enum event_type_t { ZDWM_EVENT_CONFIGURE_REQUEST, } event_type_t; -typedef enum modifier_bit_t { - ZDWM_MOD_SHIFT = 1u << 0, - ZDWM_MOD_CTRL = 1u << 1, - ZDWM_MOD_ALT = 1u << 2, - ZDWM_MOD_SUPER = 1u << 3, -} modifier_bit_t; - typedef uint32_t modifier_mask_t; typedef uint32_t keysym_t; diff --git a/src/core/types.h b/src/core/types.h index 40f9a15..f8ef791 100644 --- a/src/core/types.h +++ b/src/core/types.h @@ -48,3 +48,14 @@ typedef enum cross_output_policy_t { ZDWM_CROSS_OUTPUT_KEEP_WORKSPACE, ZDWM_CROSS_OUTPUT_MOVE_TO_TARGET_WORKSPACE, } cross_output_policy_t; + +typedef enum modifier_bit_t { + ZDWM_MOD_NONE = 0u, + ZDWM_MOD_SHIFT = 1u << 0, + ZDWM_MOD_CONTROL = 1u << 1, + ZDWM_MOD_1 = 1u << 2, + ZDWM_MOD_2 = 1u << 3, + ZDWM_MOD_3 = 1u << 4, + ZDWM_MOD_4 = 1u << 5, + ZDWM_MOD_5 = 1u << 6, +} modifier_bit_t; diff --git a/tests/config/CMakeLists.txt b/tests/config/CMakeLists.txt index a1a276c..440ae08 100644 --- a/tests/config/CMakeLists.txt +++ b/tests/config/CMakeLists.txt @@ -63,6 +63,7 @@ target_include_directories(${RUNTIME_CONFIG_TEST_APP_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) target_link_libraries(${RUNTIME_CONFIG_TEST_APP_NAME} + PRIVATE ${deps_xkbcommon_MODULE_NAME} PRIVATE ${CMAKE_DL_LIBS} ) add_dependencies(${RUNTIME_CONFIG_TEST_APP_NAME}