From be55dabdc4c5dab3aba888de1c9248d459529117 Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Fri, 16 Aug 2024 22:15:42 +1000 Subject: [PATCH 1/7] feat(windows): add right modifier key option pt1 --- common/windows/cpp/include/registry.h | 6 +- .../windows/delphi/general/RegistryKeys.pas | 3 +- .../delphi/tools/test-klog/test_klog.dpr | 8 +- .../delphi/tools/test-klog/test_klog.dproj | 4 + windows/src/desktop/kmshell/xml/strings.xml | 5 + windows/src/engine/keyman/UfrmKeyman7Main.pas | 4 +- .../keyman32/k32_lowlevelkeyboardhook.cpp | 96 +++++++------------ .../delphi/general/Keyman.System.Settings.pas | 22 +---- 8 files changed, 53 insertions(+), 95 deletions(-) diff --git a/common/windows/cpp/include/registry.h b/common/windows/cpp/include/registry.h index 67cdfc2f69e..ebaca81c9cf 100644 --- a/common/windows/cpp/include/registry.h +++ b/common/windows/cpp/include/registry.h @@ -123,11 +123,7 @@ /* REGSZ_Keyman_Debug DWORD: Use old non-chiral Win32 API RegisterHotkey instead of left-only hotkeys */ -#define REGSZ_Flag_UseRegisterHotkey "Flag_UseRegisterHotkey" - -/* REGSZ_Flag_UseCachedHotkeyModifierState DWORD: Use old cached modifier state when checking hotkeys; ignores UseRegisterHotkey if FALSE */ - -#define REGSZ_Flag_UseCachedHotkeyModifierState "Flag_UseCachedHotkeyModifierState" +#define REGSZ_Flag_UseRightModifierHotKey "Flag_UseRightModifierHotKey" /* DWORD: Enable/disable deep TSF integration, default enabled; 0 = disabled, 1 = enabled, 2 = default */ diff --git a/common/windows/delphi/general/RegistryKeys.pas b/common/windows/delphi/general/RegistryKeys.pas index 47e7df754a0..8cbd6d7d0a3 100644 --- a/common/windows/delphi/general/RegistryKeys.pas +++ b/common/windows/delphi/general/RegistryKeys.pas @@ -379,8 +379,7 @@ interface SRegKey_KeymanEngineDebug_CU = SRegKey_KeymanEngineRoot_CU + '\Debug'; - SRegValue_Flag_UseRegisterHotkey = 'Flag_UseRegisterHotkey'; - SRegValue_Flag_UseCachedHotkeyModifierState = 'Flag_UseCachedHotkeyModifierState'; + SRegValue_Flag_UseRightModifierHotKey = 'Flag_UseRightModifierHotKey'; SRegValue_Flag_ShouldSerializeInput = 'Flag_ShouldSerializeInput'; SRegValue_Flag_UseAutoStartTask = 'Flag_UseAutoStartTask'; SRegValue_Flag_SyncLanguagesToCloud = 'Flag_SyncLanguagesToCloud'; diff --git a/common/windows/delphi/tools/test-klog/test_klog.dpr b/common/windows/delphi/tools/test-klog/test_klog.dpr index 072042334a0..7f9d0e213aa 100644 --- a/common/windows/delphi/tools/test-klog/test_klog.dpr +++ b/common/windows/delphi/tools/test-klog/test_klog.dpr @@ -7,13 +7,17 @@ uses klog in '..\..\..\..\..\common\windows\delphi\general\klog.pas', VersionInfo in '..\..\..\..\..\common\windows\delphi\general\VersionInfo.pas', ErrorControlledRegistry in '..\..\..\..\..\common\windows\delphi\vcl\ErrorControlledRegistry.pas', - Unicode in '..\..\..\..\..\common\windows\delphi\general\Unicode.pas'; + Unicode in '..\..\..\..\..\common\windows\delphi\general\Unicode.pas', + DebugPaths in '..\..\..\..\..\common\windows\delphi\general\DebugPaths.pas', + RegistryKeys in '..\..\..\..\..\common\windows\delphi\general\RegistryKeys.pas', + KeymanVersion in '..\..\..\..\..\common\windows\delphi\general\KeymanVersion.pas', + KeymanPaths in '..\..\..\..\..\common\windows\delphi\general\KeymanPaths.pas'; begin if KLEnabled then begin writeln('KLog is enabled - disable KLogging before release!'); - ExitCode := 1; + ExitCode := 0; end else begin diff --git a/common/windows/delphi/tools/test-klog/test_klog.dproj b/common/windows/delphi/tools/test-klog/test_klog.dproj index 27d8e8d7d5d..3a7cd7fa050 100644 --- a/common/windows/delphi/tools/test-klog/test_klog.dproj +++ b/common/windows/delphi/tools/test-klog/test_klog.dproj @@ -214,6 +214,10 @@ + + + + Cfg_2 Base diff --git a/windows/src/desktop/kmshell/xml/strings.xml b/windows/src/desktop/kmshell/xml/strings.xml index 1e1df09ce00..8bdb8b0221e 100644 --- a/windows/src/desktop/kmshell/xml/strings.xml +++ b/windows/src/desktop/kmshell/xml/strings.xml @@ -377,6 +377,11 @@ Simulate AltGr with Ctrl+Alt + + + + Simulate AltGr with Ctrl+Alt + diff --git a/windows/src/engine/keyman/UfrmKeyman7Main.pas b/windows/src/engine/keyman/UfrmKeyman7Main.pas index 5034c0e664f..4c14c375ed3 100644 --- a/windows/src/engine/keyman/UfrmKeyman7Main.pas +++ b/windows/src/engine/keyman/UfrmKeyman7Main.pas @@ -2050,7 +2050,7 @@ procedure TfrmKeyman7Main.RegisterHotkeys; language: IKeymanLanguage; id: Integer; begin - if not Reg_GetDebugFlag(SRegValue_Flag_UseRegisterHotkey) then Exit; + if not Reg_GetDebugFlag(SRegValue_Flag_UseRightModifierHotKey) then Exit; TDebugLogClient.Instance.WriteMessage('Enter RegisterHotkeys', []); @@ -2104,7 +2104,7 @@ procedure TfrmKeyman7Main.UnregisterHotkeys; var i, hk: Integer; begin - if not Reg_GetDebugFlag(SRegValue_Flag_UseRegisterHotkey) then Exit; + if not Reg_GetDebugFlag(SRegValue_Flag_UseRightModifierHotKey) then Exit; TDebugLogClient.Instance.WriteMessage('Enter UnregisterHotkeys', []); diff --git a/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp b/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp index 019f88b0737..ce2ab3480e6 100644 --- a/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp +++ b/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp @@ -130,26 +130,16 @@ BOOL IsTouchPanelVisible() { } /* - Cache UseRegisterHotkey debug flag for this session + Cache UseRightModifierHotKey debug flag for this session */ -BOOL UseRegisterHotkey() { - static BOOL flag_UseRegisterHotkey = FALSE; +BOOL UseRightModifierHotKey() { + static BOOL flag_UseRightModifierHotKey = FALSE; static BOOL loaded = FALSE; if (!loaded) { loaded = TRUE; - flag_UseRegisterHotkey = Reg_GetDebugFlag(REGSZ_Flag_UseRegisterHotkey, FALSE); + flag_UseRightModifierHotKey = Reg_GetDebugFlag(REGSZ_Flag_UseRightModifierHotKey, FALSE); } - return flag_UseRegisterHotkey; -} - -BOOL UseCachedHotkeyModifierState() { - static BOOL flag_UseCachedHotkeyModifierState = FALSE; - static BOOL loaded = FALSE; - if (!loaded) { - loaded = TRUE; - flag_UseCachedHotkeyModifierState = Reg_GetDebugFlag(REGSZ_Flag_UseCachedHotkeyModifierState, FALSE); - } - return flag_UseCachedHotkeyModifierState; + return flag_UseRightModifierHotKey; } LRESULT _kmnLowLevelKeyboardProc( @@ -171,58 +161,38 @@ LRESULT _kmnLowLevelKeyboardProc( SendDebugMessageFormat("wparam: %x lparam: %x [vk:%s scan:%x flags:%x extra:%x]", wParam, lParam, Debug_VirtualKey((WORD) hs->vkCode), hs->scanCode, hs->flags, hs->dwExtraInfo); // I4674 - DWORD Flag = 0; - if (!UseCachedHotkeyModifierState()) { - // #5190: Don't cache modifier state because sometimes we won't receive - // modifier change events (e.g. on lock screen) - FHotkeyShiftState = 0; - if (GetKeyState(VK_LCONTROL) < 0) FHotkeyShiftState |= HK_CTRL; - if (GetKeyState(VK_RCONTROL) < 0) FHotkeyShiftState |= HK_RCTRL_INVALID; - if (GetKeyState(VK_LMENU) < 0) FHotkeyShiftState |= HK_ALT; - if (GetKeyState(VK_RMENU) < 0) FHotkeyShiftState |= HK_RALT_INVALID; - if (GetKeyState(VK_LSHIFT) < 0) FHotkeyShiftState |= HK_SHIFT; - if (GetKeyState(VK_RSHIFT) < 0) FHotkeyShiftState |= HK_RSHIFT_INVALID; - //TODO: #8064. Can remove debug message once issue #8064 is resolved - SendDebugMessageFormat("!UseCachedHotkeyModifierState [FHotkeyShiftState:%x Flag:%x]", FHotkeyShiftState, Flag); + if (GetKeyState(VK_LCONTROL) < 0) { + FHotkeyShiftState |= HK_CTRL; } - else if (UseRegisterHotkey()) { - // The old RegisterHotkey pattern does not support chiral modifier keys - switch (hs->vkCode) { - case VK_LCONTROL: - case VK_RCONTROL: - case VK_CONTROL: Flag = HK_CTRL; break; - case VK_LMENU: - case VK_RMENU: - case VK_MENU: Flag = HK_ALT; break; - case VK_LSHIFT: - case VK_RSHIFT: - case VK_SHIFT: Flag = HK_SHIFT; break; - } - //TODO: #8064. Can remove debug message once issue #8064 is resolved - SendDebugMessageFormat("UseRegisterHotkey [FHotkeyShiftState:%x Flag:%x]", FHotkeyShiftState, Flag); + if (GetKeyState(VK_RCONTROL) < 0) { + FHotkeyShiftState |= UseRightModifierHotKey() ? HK_CTRL : HK_RCTRL_INVALID; } - else { - // #4619: We differentiate between Left and Right Ctrl/Shift/Alt. The right modifiers are - // not used for hotkeys, leaving them available for use as keystroke modifiers within a - // Keyman keyboard. But we need to track them anyway, so that a user doesn't press them - // and receive a hotkey event when they shouldn't (e.g. RALT+F4 if the hotkey is F4). - switch (hs->vkCode) { - case VK_LCONTROL: Flag = HK_CTRL; break; - case VK_RCONTROL: Flag = HK_RCTRL_INVALID; break; - case VK_CONTROL: Flag = extended ? HK_RCTRL_INVALID : HK_CTRL; break; - case VK_LMENU: Flag = HK_ALT; break; - case VK_RMENU: Flag = HK_RALT_INVALID; break; - case VK_MENU: Flag = extended ? HK_RALT_INVALID : HK_ALT; break; - case VK_LSHIFT: Flag = HK_SHIFT; break; - case VK_RSHIFT: Flag = HK_RSHIFT_INVALID; break; - case VK_SHIFT: Flag = hs->scanCode == SCANCODE_RSHIFT ? HK_RSHIFT_INVALID : HK_SHIFT; break; - } + if (GetKeyState(VK_CONTROL) < 0) { + FHotkeyShiftState |= (!UseRightModifierHotKey() && extended) ? HK_RCTRL_INVALID : HK_CTRL; + } + + if (GetKeyState(VK_LMENU) < 0) { + FHotkeyShiftState |= HK_ALT; + } + + if (GetKeyState(VK_RMENU) < 0) { + FHotkeyShiftState |= UseRightModifierHotKey() ? HK_ALT : HK_RALT_INVALID; + } + + if (GetKeyState(VK_MENU) < 0) { + FHotkeyShiftState |= (!UseRightModifierHotKey() && extended) ? HK_RALT_INVALID : HK_ALT; + } + + if (GetKeyState(VK_LSHIFT) < 0) { + FHotkeyShiftState |= HK_SHIFT; + } + if (GetKeyState(VK_RSHIFT) < 0) { + FHotkeyShiftState |= UseRightModifierHotKey() ? HK_SHIFT : HK_RSHIFT_INVALID; } - if(Flag != 0) { - if(isUp) FHotkeyShiftState &= ~Flag; - else FHotkeyShiftState |= Flag; + if (GetKeyState(VK_SHIFT) < 0) { + FHotkeyShiftState |= (!UseRightModifierHotKey() && extended) ? HK_RSHIFT_INVALID : HK_SHIFT; } // #7337 Post the modifier state ensuring the serialized queue is in sync @@ -304,7 +274,7 @@ LRESULT _kmnLowLevelKeyboardProc( } BOOL ProcessHotkey(UINT vkCode, BOOL isUp, DWORD ShiftState) { - if (UseRegisterHotkey()) { + if (UseRightModifierHotKey()) { return FALSE; } diff --git a/windows/src/global/delphi/general/Keyman.System.Settings.pas b/windows/src/global/delphi/general/Keyman.System.Settings.pas index b021e56cddf..d8acd9d25a6 100644 --- a/windows/src/global/delphi/general/Keyman.System.Settings.pas +++ b/windows/src/global/delphi/general/Keyman.System.Settings.pas @@ -95,7 +95,7 @@ TKeymanSettings = class(TObjectList) ValueType: kstInteger ); - BaseKeymanSettings: array[0..33] of TKeymanSettingBase = ( + BaseKeymanSettings: array[0..31] of TKeymanSettingBase = ( // TIKE:UTikeDebugMode.TikeDebugMode ( @@ -370,14 +370,6 @@ TKeymanSettings = class(TObjectList) // keyman:TfrmKeyman7Main.RegisterHotkeys, // keyman:TfrmKeyman7Main.UnregisterHotkeys // keyman32:k32_lowlevelkeyboardhook - ( - ID: 'engine.compatibility.old_hotkey_registration'; - Name: SRegValue_Flag_UseRegisterHotkey; - RootKey: HKCU; - Key: SRegKey_KeymanEngineDebug_CU; - Description: 'Set to 1 for old RegisterHotkey pathway'; - ValueType: kstInteger - ), ( ID: 'engine.compatibility.use_keyman_core'; @@ -391,18 +383,6 @@ TKeymanSettings = class(TObjectList) ValueType: kstInteger ), - // keyman32:k32_lowlevelkeyboardhook - ( - ID: 'engine.compatibility.old_cached_hotkey_modifier_state'; - Name: SRegValue_Flag_UseCachedHotkeyModifierState; - RootKey: HKCU; - Key: SRegKey_KeymanEngineDebug_CU; - Description: 'Set to 1 to use a cached modifer state when checking hotkeys; if '+ - 'set to 0 then engine.compatibility.old_hotkey_registration may not '+ - 'work'; - ValueType: kstInteger - ), - // keyman32:keyman32.Initialise_Flag_ShouldSerializeInput ( ID: 'engine.compatibility.serialize_input'; From b7b17686ece2b29c43889131011aa89205401f11 Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Mon, 19 Aug 2024 14:01:43 +1000 Subject: [PATCH 2/7] feat(windows): add rmodifier hk to keyman config UI --- common/windows/cpp/include/registry.h | 6 ++++-- common/windows/delphi/general/RegistryKeys.pas | 2 +- windows/src/desktop/kmshell/xml/strings.xml | 2 +- .../src/engine/keyman32/k32_lowlevelkeyboardhook.cpp | 10 ++++++++-- windows/src/engine/kmcomapi/util/utilkeymanoption.pas | 1 + .../src/global/delphi/general/KeymanOptionNames.pas | 5 ++++- 6 files changed, 19 insertions(+), 7 deletions(-) diff --git a/common/windows/cpp/include/registry.h b/common/windows/cpp/include/registry.h index ebaca81c9cf..c6d1bf85ec1 100644 --- a/common/windows/cpp/include/registry.h +++ b/common/windows/cpp/include/registry.h @@ -110,6 +110,10 @@ #define REGSZ_KeyboardHotkeysAreToggle "hotkeys are toggles" #define REGSZ_DeadkeyConversionMode "deadkey conversion mode" // CU // I4552 #define REGSZ_ZapVirtualKeyCode "zap virtual key code" // LM, defaults to 0x0E (_VK_PREFIX_DEFAULT) +/* Non-chiral use of hotkeys instead of left-only hotkeys */ +#define REGSZ_UseRightModifierHotKey "use right modifier for hotkey" + + /* Debug flags These are all stored in HKCU\Software\Keyman\Debug @@ -121,9 +125,7 @@ #define REGSZ_Flag_ShouldSerializeInput "Flag_ShouldSerializeInput" -/* REGSZ_Keyman_Debug DWORD: Use old non-chiral Win32 API RegisterHotkey instead of left-only hotkeys */ -#define REGSZ_Flag_UseRightModifierHotKey "Flag_UseRightModifierHotKey" /* DWORD: Enable/disable deep TSF integration, default enabled; 0 = disabled, 1 = enabled, 2 = default */ diff --git a/common/windows/delphi/general/RegistryKeys.pas b/common/windows/delphi/general/RegistryKeys.pas index 8cbd6d7d0a3..0553b823065 100644 --- a/common/windows/delphi/general/RegistryKeys.pas +++ b/common/windows/delphi/general/RegistryKeys.pas @@ -115,6 +115,7 @@ interface SRegValue_AltGrCtrlAlt = 'simulate altgr'; // CU SRegValue_KeyboardHotKeysAreToggle = 'hotkeys are toggles'; // CU + SRegValue_UseRightModifierHotKey = 'use right modifier for hotkey'; // CU SRegValue_ReleaseShiftKeysAfterKeyPress = 'release shift keys after key press'; // CU SRegValue_TestKeymanFunctioning = 'test keyman functioning'; // CU, default true @@ -379,7 +380,6 @@ interface SRegKey_KeymanEngineDebug_CU = SRegKey_KeymanEngineRoot_CU + '\Debug'; - SRegValue_Flag_UseRightModifierHotKey = 'Flag_UseRightModifierHotKey'; SRegValue_Flag_ShouldSerializeInput = 'Flag_ShouldSerializeInput'; SRegValue_Flag_UseAutoStartTask = 'Flag_UseAutoStartTask'; SRegValue_Flag_SyncLanguagesToCloud = 'Flag_SyncLanguagesToCloud'; diff --git a/windows/src/desktop/kmshell/xml/strings.xml b/windows/src/desktop/kmshell/xml/strings.xml index 8bdb8b0221e..e15ba789453 100644 --- a/windows/src/desktop/kmshell/xml/strings.xml +++ b/windows/src/desktop/kmshell/xml/strings.xml @@ -380,7 +380,7 @@ - Simulate AltGr with Ctrl+Alt + Right Modifier keys work with Hotkeys diff --git a/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp b/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp index ce2ab3480e6..66d7d943aba 100644 --- a/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp +++ b/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp @@ -135,9 +135,15 @@ BOOL IsTouchPanelVisible() { BOOL UseRightModifierHotKey() { static BOOL flag_UseRightModifierHotKey = FALSE; static BOOL loaded = FALSE; + if (!loaded) { - loaded = TRUE; - flag_UseRightModifierHotKey = Reg_GetDebugFlag(REGSZ_Flag_UseRightModifierHotKey, FALSE); + RegistryReadOnly reg(HKEY_CURRENT_USER); + if (reg.OpenKeyReadOnly(REGSZ_KeymanCU)) { + if (reg.ValueExists(REGSZ_UseRightModifierHotKey)) { + flag_UseRightModifierHotKey = !!reg.ReadInteger(REGSZ_UseRightModifierHotKey); + } + } + loaded = TRUE; // Set loaded to TRUE whether or not the key exists } return flag_UseRightModifierHotKey; } diff --git a/windows/src/engine/kmcomapi/util/utilkeymanoption.pas b/windows/src/engine/kmcomapi/util/utilkeymanoption.pas index ce1b8af33a8..9d9f95465d4 100644 --- a/windows/src/engine/kmcomapi/util/utilkeymanoption.pas +++ b/windows/src/engine/kmcomapi/util/utilkeymanoption.pas @@ -127,6 +127,7 @@ TKeymanOptionInfo = record (opt: koKeyboardHotkeysAreToggle; RegistryName: SRegValue_KeyboardHotkeysAreToggle; OptionType: kotBool; BoolValue: False; GroupName: 'kogGeneral'), (opt: koSwitchLanguageForAllApplications; RegistryName: SRegValue_SwitchLanguageForAllApplications; OptionType: kotBool; BoolValue: True; GroupName: 'kogGeneral'), // I2277 // I4393 (opt: koAltGrCtrlAlt; RegistryName: SRegValue_AltGrCtrlAlt; OptionType: kotBool; BoolValue: False; GroupName: 'kogGeneral'), + (opt: koRightModifierHK; RegistryName: SRegValue_UseRightModifierHotKey; OptionType: kotBool; BoolValue: False; GroupName: 'kogGeneral'), (opt: koShowHints; RegistryName: SRegValue_EnableHints; OptionType: kotBool; BoolValue: True; GroupName: 'kogGeneral'), (opt: koBaseLayout; RegistryName: SRegValue_UnderlyingLayout; OptionType: kotLong; IntValue: 0; GroupName: 'kogGeneral'), diff --git a/windows/src/global/delphi/general/KeymanOptionNames.pas b/windows/src/global/delphi/general/KeymanOptionNames.pas index 27aef82ab55..73356d19cb3 100644 --- a/windows/src/global/delphi/general/KeymanOptionNames.pas +++ b/windows/src/global/delphi/general/KeymanOptionNames.pas @@ -5,7 +5,10 @@ interface type TUtilKeymanOption = ( // General options - koKeyboardHotkeysAreToggle, koAltGrCtrlAlt, koReleaseShiftKeysAfterKeyPress, + koKeyboardHotkeysAreToggle, + koAltGrCtrlAlt, + koRightModifierHK, + koReleaseShiftKeysAfterKeyPress, koShowHints, // I1256 // Startup options koTestKeymanFunctioning, From 65b9e49bac88976beedb9667ab7c010ede2e6cc3 Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Mon, 19 Aug 2024 18:48:06 +1000 Subject: [PATCH 3/7] feat(windows): remove old UseRegisterHotkey --- windows/src/engine/keyman/UfrmKeyman7Main.pas | 2 -- windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp | 3 --- 2 files changed, 5 deletions(-) diff --git a/windows/src/engine/keyman/UfrmKeyman7Main.pas b/windows/src/engine/keyman/UfrmKeyman7Main.pas index 4c14c375ed3..155ab9208c0 100644 --- a/windows/src/engine/keyman/UfrmKeyman7Main.pas +++ b/windows/src/engine/keyman/UfrmKeyman7Main.pas @@ -2050,7 +2050,6 @@ procedure TfrmKeyman7Main.RegisterHotkeys; language: IKeymanLanguage; id: Integer; begin - if not Reg_GetDebugFlag(SRegValue_Flag_UseRightModifierHotKey) then Exit; TDebugLogClient.Instance.WriteMessage('Enter RegisterHotkeys', []); @@ -2104,7 +2103,6 @@ procedure TfrmKeyman7Main.UnregisterHotkeys; var i, hk: Integer; begin - if not Reg_GetDebugFlag(SRegValue_Flag_UseRightModifierHotKey) then Exit; TDebugLogClient.Instance.WriteMessage('Enter UnregisterHotkeys', []); diff --git a/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp b/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp index 66d7d943aba..6d5067516e9 100644 --- a/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp +++ b/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp @@ -280,9 +280,6 @@ LRESULT _kmnLowLevelKeyboardProc( } BOOL ProcessHotkey(UINT vkCode, BOOL isUp, DWORD ShiftState) { - if (UseRightModifierHotKey()) { - return FALSE; - } Hotkeys *hotkeys = Hotkeys::Instance(); // I4641 if (!hotkeys) { From 977d2948e6400e1c3524629818d61ed39ac07581 Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Tue, 20 Aug 2024 10:06:04 +1000 Subject: [PATCH 4/7] feat(windows): fix out of bounds --- windows/src/engine/kmcomapi/util/utilkeymanoption.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/src/engine/kmcomapi/util/utilkeymanoption.pas b/windows/src/engine/kmcomapi/util/utilkeymanoption.pas index 9d9f95465d4..2df38b5c825 100644 --- a/windows/src/engine/kmcomapi/util/utilkeymanoption.pas +++ b/windows/src/engine/kmcomapi/util/utilkeymanoption.pas @@ -121,7 +121,7 @@ TKeymanOptionInfo = record GroupName: string; end; -const KeymanOptionInfo: array[0..15] of TKeymanOptionInfo = ( // I3331 // I3620 // I4552 +const KeymanOptionInfo: array[0..16] of TKeymanOptionInfo = ( // I3331 // I3620 // I4552 // Global options (opt: koKeyboardHotkeysAreToggle; RegistryName: SRegValue_KeyboardHotkeysAreToggle; OptionType: kotBool; BoolValue: False; GroupName: 'kogGeneral'), From 98787afbdcacf7a8e1a4f9e64e929fd3948f7007 Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:15:50 +1000 Subject: [PATCH 5/7] feat(windows): restore removal of klogging --- common/windows/delphi/tools/test-klog/test_klog.dpr | 8 ++------ common/windows/delphi/tools/test-klog/test_klog.dproj | 4 ---- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/common/windows/delphi/tools/test-klog/test_klog.dpr b/common/windows/delphi/tools/test-klog/test_klog.dpr index 7f9d0e213aa..072042334a0 100644 --- a/common/windows/delphi/tools/test-klog/test_klog.dpr +++ b/common/windows/delphi/tools/test-klog/test_klog.dpr @@ -7,17 +7,13 @@ uses klog in '..\..\..\..\..\common\windows\delphi\general\klog.pas', VersionInfo in '..\..\..\..\..\common\windows\delphi\general\VersionInfo.pas', ErrorControlledRegistry in '..\..\..\..\..\common\windows\delphi\vcl\ErrorControlledRegistry.pas', - Unicode in '..\..\..\..\..\common\windows\delphi\general\Unicode.pas', - DebugPaths in '..\..\..\..\..\common\windows\delphi\general\DebugPaths.pas', - RegistryKeys in '..\..\..\..\..\common\windows\delphi\general\RegistryKeys.pas', - KeymanVersion in '..\..\..\..\..\common\windows\delphi\general\KeymanVersion.pas', - KeymanPaths in '..\..\..\..\..\common\windows\delphi\general\KeymanPaths.pas'; + Unicode in '..\..\..\..\..\common\windows\delphi\general\Unicode.pas'; begin if KLEnabled then begin writeln('KLog is enabled - disable KLogging before release!'); - ExitCode := 0; + ExitCode := 1; end else begin diff --git a/common/windows/delphi/tools/test-klog/test_klog.dproj b/common/windows/delphi/tools/test-klog/test_klog.dproj index 3a7cd7fa050..27d8e8d7d5d 100644 --- a/common/windows/delphi/tools/test-klog/test_klog.dproj +++ b/common/windows/delphi/tools/test-klog/test_klog.dproj @@ -214,10 +214,6 @@ - - - - Cfg_2 Base From 3326ac2c6b62b66b0567965b3bb834ee432d9d6c Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:14:57 +1000 Subject: [PATCH 6/7] feat(windows): remove check for non-chiral vkey --- .../keyman32/k32_lowlevelkeyboardhook.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp b/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp index 6d5067516e9..f5fbdb8f301 100644 --- a/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp +++ b/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp @@ -169,15 +169,14 @@ LRESULT _kmnLowLevelKeyboardProc( if (GetKeyState(VK_LCONTROL) < 0) { FHotkeyShiftState |= HK_CTRL; + SendDebugMessageFormat("ProcessHotkey VK_LCONTROL [vkCode:%x isUp:%d FHotkeyShiftState:%x useRight:%d", hs->vkCode, isUp, FHotkeyShiftState, UseRightModifierHotKey()); } if (GetKeyState(VK_RCONTROL) < 0) { FHotkeyShiftState |= UseRightModifierHotKey() ? HK_CTRL : HK_RCTRL_INVALID; + SendDebugMessageFormat("ProcessHotkey VK_RCONTROL [vkCode:%x isUp:%d FHotkeyShiftState:%x useRight:%d", hs->vkCode, isUp, FHotkeyShiftState, UseRightModifierHotKey()); } - if (GetKeyState(VK_CONTROL) < 0) { - FHotkeyShiftState |= (!UseRightModifierHotKey() && extended) ? HK_RCTRL_INVALID : HK_CTRL; - } - + if (GetKeyState(VK_LMENU) < 0) { FHotkeyShiftState |= HK_ALT; } @@ -186,10 +185,6 @@ LRESULT _kmnLowLevelKeyboardProc( FHotkeyShiftState |= UseRightModifierHotKey() ? HK_ALT : HK_RALT_INVALID; } - if (GetKeyState(VK_MENU) < 0) { - FHotkeyShiftState |= (!UseRightModifierHotKey() && extended) ? HK_RALT_INVALID : HK_ALT; - } - if (GetKeyState(VK_LSHIFT) < 0) { FHotkeyShiftState |= HK_SHIFT; } @@ -197,9 +192,9 @@ LRESULT _kmnLowLevelKeyboardProc( FHotkeyShiftState |= UseRightModifierHotKey() ? HK_SHIFT : HK_RSHIFT_INVALID; } - if (GetKeyState(VK_SHIFT) < 0) { - FHotkeyShiftState |= (!UseRightModifierHotKey() && extended) ? HK_RSHIFT_INVALID : HK_SHIFT; - } + //if (GetKeyState(VK_SHIFT) < 0) { + // FHotkeyShiftState |= (!UseRightModifierHotKey() && extended) ? HK_RSHIFT_INVALID : HK_SHIFT; + //} // #7337 Post the modifier state ensuring the serialized queue is in sync // Note that the modifier key may be posted again with WM_KEYMAN_KEY_EVENT, From c48a4a72428626aad3137480cd36b66486297089 Mon Sep 17 00:00:00 2001 From: rc-swag <58423624+rc-swag@users.noreply.github.com> Date: Wed, 21 Aug 2024 11:56:55 +1000 Subject: [PATCH 7/7] feat(windows): Use RegisterHotkey only for chirl mode --- windows/src/engine/keyman/UfrmKeyman7Main.pas | 36 +++++++++++++++++++ windows/src/engine/keyman32/hotkeys.cpp | 10 ++++-- .../keyman32/k32_lowlevelkeyboardhook.cpp | 31 ++++++++++------ 3 files changed, 64 insertions(+), 13 deletions(-) diff --git a/windows/src/engine/keyman/UfrmKeyman7Main.pas b/windows/src/engine/keyman/UfrmKeyman7Main.pas index 155ab9208c0..fbed70b24d0 100644 --- a/windows/src/engine/keyman/UfrmKeyman7Main.pas +++ b/windows/src/engine/keyman/UfrmKeyman7Main.pas @@ -2049,7 +2049,25 @@ procedure TfrmKeyman7Main.RegisterHotkeys; i: Integer; language: IKeymanLanguage; id: Integer; + RegistryErrorControlled: TRegistryErrorControlled;// I2890 + UseRegisterHotKey: Boolean; // Use Win32 API RegisterHotkey begin + RegistryErrorControlled := TRegistryErrorControlled.Create; + try + if RegistryErrorControlled.OpenKeyReadOnly(SRegKey_KeymanEngine_CU) and + RegistryErrorControlled.ValueExists(SRegValue_UseRightModifierHotKey) then + begin + UseRegisterHotKey := RegistryErrorControlled.ReadBool(SRegValue_UseRightModifierHotKey); + end + else + begin + UseRegisterHotKey := False; + end; + finally + RegistryErrorControlled.Free; + end; + + if not UseRegisterHotKey then Exit; TDebugLogClient.Instance.WriteMessage('Enter RegisterHotkeys', []); @@ -2102,7 +2120,25 @@ procedure TfrmKeyman7Main.RegisterHotkeys; procedure TfrmKeyman7Main.UnregisterHotkeys; var i, hk: Integer; + RegistryErrorControlled: TRegistryErrorControlled;// I2890 + UseRegisterHotKey: Boolean; // Use Win32 API RegisterHotkey begin + RegistryErrorControlled := TRegistryErrorControlled.Create; + try + if RegistryErrorControlled.OpenKeyReadOnly(SRegKey_KeymanEngine_CU) and + RegistryErrorControlled.ValueExists(SRegValue_UseRightModifierHotKey) then + begin + UseRegisterHotKey := RegistryErrorControlled.ReadBool(SRegValue_UseRightModifierHotKey); + end + else + begin + UseRegisterHotKey := False; + end; + finally + RegistryErrorControlled.Free; + end; + + if not UseRegisterHotKey then Exit; TDebugLogClient.Instance.WriteMessage('Enter UnregisterHotkeys', []); diff --git a/windows/src/engine/keyman32/hotkeys.cpp b/windows/src/engine/keyman32/hotkeys.cpp index 8327a786498..e7fdbe3d79d 100644 --- a/windows/src/engine/keyman32/hotkeys.cpp +++ b/windows/src/engine/keyman32/hotkeys.cpp @@ -137,9 +137,13 @@ void Hotkeys::Load() { // I4390 Hotkey *Hotkeys::GetHotkey(DWORD hotkey) { - for(int i = 0; i < m_nHotkeys; i++) - if(m_hotkeys[i].HotkeyValue == hotkey) - return &m_hotkeys[i]; + for (int i = 0; i < m_nHotkeys; i++) { + if (m_hotkeys[i].HotkeyValue == hotkey) { + SendDebugMessageFormat( + "LanguageHotkey[%d] = {HotkeyValue: %x, hkl: %x} passed in: %x", i, m_hotkeys[i].HotkeyValue, m_hotkeys[i].hkl, hotkey); + return &m_hotkeys[i]; + } + } return NULL; } diff --git a/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp b/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp index f5fbdb8f301..2bdfae62e39 100644 --- a/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp +++ b/windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp @@ -131,8 +131,10 @@ BOOL IsTouchPanelVisible() { /* Cache UseRightModifierHotKey debug flag for this session + when using right modifier for Hotkeys use the Win32 API + ResisterHotkey functionality */ -BOOL UseRightModifierHotKey() { +BOOL UseRegisterHotkey() { static BOOL flag_UseRightModifierHotKey = FALSE; static BOOL loaded = FALSE; @@ -169,31 +171,33 @@ LRESULT _kmnLowLevelKeyboardProc( if (GetKeyState(VK_LCONTROL) < 0) { FHotkeyShiftState |= HK_CTRL; - SendDebugMessageFormat("ProcessHotkey VK_LCONTROL [vkCode:%x isUp:%d FHotkeyShiftState:%x useRight:%d", hs->vkCode, isUp, FHotkeyShiftState, UseRightModifierHotKey()); + // TODO remove + SendDebugMessageFormat("ProcessHotkey VK_LCONTROL [vkCode:%x isUp:%d FHotkeyShiftState:%x useRight:%d", hs->vkCode, isUp, FHotkeyShiftState, UseRegisterHotkey()); } if (GetKeyState(VK_RCONTROL) < 0) { - FHotkeyShiftState |= UseRightModifierHotKey() ? HK_CTRL : HK_RCTRL_INVALID; - SendDebugMessageFormat("ProcessHotkey VK_RCONTROL [vkCode:%x isUp:%d FHotkeyShiftState:%x useRight:%d", hs->vkCode, isUp, FHotkeyShiftState, UseRightModifierHotKey()); + FHotkeyShiftState |= UseRegisterHotkey() ? HK_CTRL : HK_RCTRL_INVALID; + // TODO remove + SendDebugMessageFormat("ProcessHotkey VK_RCONTROL [vkCode:%x isUp:%d FHotkeyShiftState:%x useRight:%d", hs->vkCode, isUp, FHotkeyShiftState, UseRegisterHotkey()); } - + if (GetKeyState(VK_LMENU) < 0) { FHotkeyShiftState |= HK_ALT; } if (GetKeyState(VK_RMENU) < 0) { - FHotkeyShiftState |= UseRightModifierHotKey() ? HK_ALT : HK_RALT_INVALID; + FHotkeyShiftState |= UseRegisterHotkey() ? HK_ALT : HK_RALT_INVALID; } if (GetKeyState(VK_LSHIFT) < 0) { FHotkeyShiftState |= HK_SHIFT; } if (GetKeyState(VK_RSHIFT) < 0) { - FHotkeyShiftState |= UseRightModifierHotKey() ? HK_SHIFT : HK_RSHIFT_INVALID; + FHotkeyShiftState |= UseRegisterHotkey() ? HK_SHIFT : HK_RSHIFT_INVALID; } //if (GetKeyState(VK_SHIFT) < 0) { - // FHotkeyShiftState |= (!UseRightModifierHotKey() && extended) ? HK_RSHIFT_INVALID : HK_SHIFT; + // FHotkeyShiftState |= (!UseRegisterHotkey() && extended) ? HK_RSHIFT_INVALID : HK_SHIFT; //} // #7337 Post the modifier state ensuring the serialized queue is in sync @@ -275,28 +279,35 @@ LRESULT _kmnLowLevelKeyboardProc( } BOOL ProcessHotkey(UINT vkCode, BOOL isUp, DWORD ShiftState) { - + if (UseRegisterHotkey()){ + return FALSE; + } Hotkeys *hotkeys = Hotkeys::Instance(); // I4641 if (!hotkeys) { + SendDebugMessageFormat("Failed to get Instance"); return FALSE; } Hotkey *hotkey = hotkeys->GetHotkey(ShiftState | vkCode); // I4641 if (!hotkey) { + SendDebugMessageFormat("GetHotkey Null"); return FALSE; } if (isUp) { + SendDebugMessageFormat("Is Up"); return TRUE; } if (hotkey->HotkeyType == hktInterface) { + SendDebugMessageFormat("PostMasterController"); Globals::PostMasterController(wm_keyman_control, MAKELONG(KMC_INTERFACEHOTKEY, hotkey->Target), 0); } else { + SendDebugMessageFormat("ReportKeyboardChanged"); ReportKeyboardChanged(PC_HOTKEYCHANGE, hotkey->hkl == 0 ? TF_PROFILETYPE_INPUTPROCESSOR : TF_PROFILETYPE_KEYBOARDLAYOUT, 0, hotkey->hkl, GUID_NULL, hotkey->profileGUID); } - + SendDebugMessageFormat("PostDummyKeyEvent"); /* Generate a dummy keystroke to block menu activations, etc but let the shift key through */ PostDummyKeyEvent(); // I3301 - this is imperfect because we don't deal with HC_NOREMOVE. But good enough? // I3534 // I4844