From 271fccb39b2c6d2fad8a6aaebdaf226b01e3fcf1 Mon Sep 17 00:00:00 2001 From: impressionyang Date: Thu, 11 Jun 2026 13:45:18 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20CapsLock=20?= =?UTF-8?q?=E9=95=BF=E6=8C=89=E6=9D=BE=E5=BC=80=E5=90=8E=E6=9C=AA=E6=81=A2?= =?UTF-8?q?=E5=A4=8D=E5=A4=A7=E5=B0=8F=E5=86=99=E7=8A=B6=E6=80=81=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 长按松开后调用 simulateCapsLock 模拟一次 CapsLock 按键恢复原始状态 - 新增 simulateKeysym 方法,正确处理 X11 keysym → keycode 转换 - Windows 端添加 X11 keysym → VK 虚拟键码映射 Co-Authored-By: Claude Opus 4.7 --- src/core/voice_input_service.cpp | 7 ++++--- src/core/wayland_text_injector.cpp | 13 +++++++++++++ src/core/wayland_text_injector.h | 3 +++ src/core/win_text_injector.cpp | 23 +++++++++++++++++++++++ src/core/win_text_injector.h | 3 +++ 5 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/core/voice_input_service.cpp b/src/core/voice_input_service.cpp index 5241e81..d0a43cb 100644 --- a/src/core/voice_input_service.cpp +++ b/src/core/voice_input_service.cpp @@ -152,6 +152,8 @@ void VoiceInputService::onHotkeyDeactivated() { } else { // 长按 → 停止录音并转写 stopRecordingAndTranscribe(); + // 恢复 CapsLock 原始状态(系统已处理了一次 CapsLock 切换) + simulateCapsLock(); } longPressDetected_ = false; @@ -213,9 +215,8 @@ void VoiceInputService::onRecognitionComplete(const QString& text) { void VoiceInputService::simulateCapsLock() { if (impl_->injector && impl_->injector->isInitialized()) { - // CapsLock keysym = 0xffe5 - unsigned int capslockKeysym = 0xffe5; - impl_->injector->simulateKeycode(capslockKeysym); + // XK_Caps_Lock = 0xffe5,使用 simulateKeysym 自动转换为 keycode + impl_->injector->simulateKeysym(0xffe5); LOG_DEBUG(kTag, "模拟 CapsLock 按键已注入"); } else { LOG_WARNING(kTag, "文本注入器未初始化,无法模拟 CapsLock"); diff --git a/src/core/wayland_text_injector.cpp b/src/core/wayland_text_injector.cpp index 07cee05..ce50c85 100644 --- a/src/core/wayland_text_injector.cpp +++ b/src/core/wayland_text_injector.cpp @@ -178,4 +178,17 @@ bool WaylandTextInjector::simulateKeycode(unsigned int keycode) { return true; } +bool WaylandTextInjector::simulateKeysym(unsigned long keysym) { + if (!impl_->display || !impl_->XKeysymToKeycode) return false; + + unsigned int keycode = impl_->XKeysymToKeycode(impl_->display, keysym); + if (keycode == 0) { + LOG_WARNING(kTag, QString("keysym 0x%1 无法转换为 keycode").arg(keysym, 0, 16)); + return false; + } + + LOG_DEBUG(kTag, QString("模拟 keysym 0x%1 → keycode %2").arg(keysym, 0, 16).arg(keycode)); + return simulateKeycode(keycode); +} + } // namespace impress diff --git a/src/core/wayland_text_injector.h b/src/core/wayland_text_injector.h index 171bb0d..79819ea 100644 --- a/src/core/wayland_text_injector.h +++ b/src/core/wayland_text_injector.h @@ -30,6 +30,9 @@ public: /** @brief 模拟 X11 keycode 按下+释放(用于 CapsLock 等系统按键) */ bool simulateKeycode(unsigned int keycode); + /** @brief 模拟 keysym 按下+释放(自动转换为 keycode) */ + bool simulateKeysym(unsigned long keysym); + signals: void error(const QString& message); diff --git a/src/core/win_text_injector.cpp b/src/core/win_text_injector.cpp index 2abdaed..b69105a 100644 --- a/src/core/win_text_injector.cpp +++ b/src/core/win_text_injector.cpp @@ -111,4 +111,27 @@ bool WaylandTextInjector::simulateKeycode(unsigned int keycode) { #endif } +bool WaylandTextInjector::simulateKeysym(unsigned long keysym) { +#ifdef Q_OS_WIN + // X11 keysym → Windows Virtual Key 映射 + WORD vk = 0; + switch (keysym) { + case 0xffe5: vk = 0x14; break; // XK_Caps_Lock → VK_CAPITAL + case 0xffe1: vk = 0x10; break; // XK_Shift_L → VK_SHIFT + case 0xffe2: vk = 0x10; break; // XK_Shift_R → VK_SHIFT + case 0xffe3: vk = 0x11; break; // XK_Control_L → VK_CONTROL + case 0xffe4: vk = 0x11; break; // XK_Control_R → VK_CONTROL + case 0xffe9: vk = 0x12; break; // XK_Alt_L → VK_MENU + case 0xffea: vk = 0x12; break; // XK_Alt_R → VK_MENU + default: + LOG_WARNING(kTag, QString("不支持的 keysym 映射: 0x%1").arg(keysym, 0, 16)); + return false; + } + return simulateKeycode(vk); +#else + (void)keysym; + return false; +#endif +} + } // namespace impress diff --git a/src/core/win_text_injector.h b/src/core/win_text_injector.h index 46809c2..3fc843b 100644 --- a/src/core/win_text_injector.h +++ b/src/core/win_text_injector.h @@ -29,6 +29,9 @@ public: /** @brief 模拟 keycode 按下+释放(Windows 使用虚拟键码) */ bool simulateKeycode(unsigned int keycode); + /** @brief 模拟 keysym 按下+释放(X11 keysym,自动映射为 Windows VK 键码) */ + bool simulateKeysym(unsigned long keysym); + signals: void error(const QString& message);