Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(windows): add right modifier included in hotkey optional functionality #12259

Merged
merged 7 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion common/windows/cpp/include/registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
#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 */
/* Default is to only use left modifier in hotkeys trigger */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 This comment is much clearer now

#define REGSZ_AllowRightModifierHotKey "allow right modifier for hotkey"


Expand Down
7 changes: 4 additions & 3 deletions common/windows/delphi/general/RegistryKeys.pas
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,11 @@ interface
SRegValue_ShowWelcome = 'show welcome'; // CU
SRegValue_UseAdvancedInstall = 'use advanced install'; // CU

SRegValue_AltGrCtrlAlt = 'simulate altgr'; // CU
SRegValue_KeyboardHotKeysAreToggle = 'hotkeys are toggles'; // CU
SRegValue_AltGrCtrlAlt = 'simulate altgr'; // CU
SRegValue_KeyboardHotKeysAreToggle = 'hotkeys are toggles'; // CU
SRegValue_AllowRightModifierHotKey = 'allow right modifier for hotkey'; // CU
SRegValue_ReleaseShiftKeysAfterKeyPress = 'release shift keys after key press'; // CU
SRegValue_TestKeymanFunctioning = 'test keyman functioning'; // CU, default true
SRegValue_TestKeymanFunctioning = 'test keyman functioning'; // CU, default true

SRegValue_CreateStartMenuAsSubfolders = 'create start menu as subfolders'; // CU
SRegValue_CreateUninstallEntries = 'create uninstall entries'; // CU
Expand Down
5 changes: 5 additions & 0 deletions windows/src/desktop/kmshell/xml/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,11 @@
<!-- Introduced: 7.0.230.0 -->
<string name="koAltGrCtrlAlt" comment="General options - Ctrl+Alt simulates AltGr on computers without AltGr">Simulate AltGr with Ctrl+Alt</string>

<!-- Context: Configuration Dialog - Options tab -->
<!-- String Type: FormatString -->
<!-- Introduced: 18.0.95 -->
<string name="koRightModifierHK" comment="General options - Right Ctrl Alt and Shift trigger hotkey">Allow right modifier for hotkeys</string>

<!-- Context: Configuration Dialog - Options tab -->
<!-- String Type: FormatString -->
<!-- Introduced: 9.0.480.0 -->
Expand Down
2 changes: 0 additions & 2 deletions windows/src/engine/keyman32/hotkeys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,6 @@ Hotkey *Hotkeys::GetHotkey(DWORD hotkey)
{
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];
}
}
Expand Down
60 changes: 45 additions & 15 deletions windows/src/engine/keyman32/k32_lowlevelkeyboardhook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,25 @@ BOOL IsTouchPanelVisible() {
return touchPanelVisible;
}

/*
Cache AllowRightModifierHotKey for this session
*/
BOOL AllowRightModifierHotKey() {
static BOOL flag_AllowRightModifierHotKey = FALSE;
static BOOL loaded = FALSE;

if (!loaded) {
RegistryReadOnly reg(HKEY_CURRENT_USER);
if (reg.OpenKeyReadOnly(REGSZ_KeymanCU)) {
if (reg.ValueExists(REGSZ_AllowRightModifierHotKey)) {
flag_AllowRightModifierHotKey = !!reg.ReadInteger(REGSZ_AllowRightModifierHotKey);
}
}
loaded = TRUE; // Set loaded to TRUE whether or not the key exists
}
return flag_AllowRightModifierHotKey;
}

LRESULT _kmnLowLevelKeyboardProc(
_In_ int nCode,
_In_ WPARAM wParam,
Expand All @@ -150,16 +169,33 @@ LRESULT _kmnLowLevelKeyboardProc(

// #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]", FHotkeyShiftState);
FHotkeyShiftState = 0;

if (GetKeyState(VK_LCONTROL) < 0) {
FHotkeyShiftState |= HK_CTRL;
}

if (GetKeyState(VK_RCONTROL) < 0) {
FHotkeyShiftState |= AllowRightModifierHotKey() ? HK_CTRL : HK_RCTRL_INVALID;
}

if (GetKeyState(VK_LMENU) < 0) {
FHotkeyShiftState |= HK_ALT;
}

if (GetKeyState(VK_RMENU) < 0) {
FHotkeyShiftState |= AllowRightModifierHotKey() ? HK_ALT : HK_RALT_INVALID;
}

if (GetKeyState(VK_LSHIFT) < 0) {
FHotkeyShiftState |= HK_SHIFT;
}
if (GetKeyState(VK_RSHIFT) < 0) {
FHotkeyShiftState |= AllowRightModifierHotKey() ? HK_SHIFT : HK_RSHIFT_INVALID;
}

//TODO: #8064. Can remove debug message once issue #8064 is resolved
SendDebugMessageFormat("[FHotkeyShiftState:%x]", FHotkeyShiftState);

// #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,
Expand Down Expand Up @@ -243,30 +279,24 @@ BOOL ProcessHotkey(UINT vkCode, BOOL isUp, DWORD ShiftState) {

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

Expand Down
3 changes: 2 additions & 1 deletion windows/src/engine/kmcomapi/util/utilkeymanoption.pas
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,13 @@ 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'),
(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_AllowRightModifierHotKey; 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'),

Expand Down
5 changes: 4 additions & 1 deletion windows/src/global/delphi/general/KeymanOptionNames.pas
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ interface
type
TUtilKeymanOption = (
// General options
koKeyboardHotkeysAreToggle, koAltGrCtrlAlt, koReleaseShiftKeysAfterKeyPress,
koKeyboardHotkeysAreToggle,
koAltGrCtrlAlt,
koRightModifierHK,
koReleaseShiftKeysAfterKeyPress,
koShowHints, // I1256
// Startup options
koTestKeymanFunctioning,
Expand Down
Loading