fix: 修复 CapsLock 长按松开后未恢复大小写状态的问题
- 长按松开后调用 simulateCapsLock 模拟一次 CapsLock 按键恢复原始状态 - 新增 simulateKeysym 方法,正确处理 X11 keysym → keycode 转换 - Windows 端添加 X11 keysym → VK 虚拟键码映射 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
8c2e787a25
commit
271fccb39b
@ -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");
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user