mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-23 00:37:41 +00:00
174 lines
4.4 KiB
C++
174 lines
4.4 KiB
C++
/*
|
|
* Keyman is copyright (C) SIL Global. MIT License.
|
|
*
|
|
* Track Windows use of Left Control + Right Alt emulation for Right Alt key
|
|
*/
|
|
|
|
#include "pch.h"
|
|
#include "kbd.h" /* DDK kbdlayout */
|
|
|
|
#ifndef _WIN64
|
|
BOOL IsWow64();
|
|
|
|
// Note that this has been simplified to remove types as we do not need any data
|
|
// other than the flag fLocaleFlags.
|
|
typedef struct tagKbdLayer_WOW64 {
|
|
/*
|
|
* Modifier keys
|
|
*/
|
|
DWORD pCharModifiers;
|
|
DWORD filler1;
|
|
|
|
/*
|
|
* Characters
|
|
*/
|
|
DWORD pVkToWcharTable; // ptr to tbl of ptrs to tbl
|
|
DWORD filler2;
|
|
|
|
/*
|
|
* Diacritics
|
|
*/
|
|
DWORD pDeadKey;
|
|
DWORD filler3;
|
|
|
|
/*
|
|
* Names of Keys
|
|
*/
|
|
DWORD pKeyNames;
|
|
DWORD filler4;
|
|
DWORD pKeyNamesExt;
|
|
DWORD filler5;
|
|
DWORD pKeyNamesDead;
|
|
DWORD filler6;
|
|
|
|
/*
|
|
* Scan codes to Virtual Keys
|
|
*/
|
|
DWORD pusVSCtoVK;
|
|
DWORD filler7;
|
|
DWORD bMaxVSCtoVK;
|
|
DWORD filler8;
|
|
DWORD pVSCtoVK_E0; // Scancode has E0 prefix
|
|
DWORD filler9;
|
|
DWORD pVSCtoVK_E1; // Scancode has E1 prefix
|
|
DWORD fillerA;
|
|
|
|
/*
|
|
* Locale-specific special processing
|
|
*/
|
|
DWORD fLocaleFlags;
|
|
DWORD fillerB;
|
|
} KBDTABLES_WOW64, *PKBDTABLES_WOW64;
|
|
|
|
typedef PKBDTABLES_WOW64 (WINAPI *PKBDLAYERDESCRIPTORWOW64FUNC)(VOID);
|
|
|
|
#endif
|
|
|
|
HMODULE LoadKbdLibrary(const char* keyboardLayoutName);
|
|
BOOL ReadAltGrFlagFromKbdDll(const char *keyboardLayoutName, BOOL& result);
|
|
|
|
typedef PKBDTABLES (WINAPI *PKBDLAYERDESCRIPTORFUNC)(VOID);
|
|
|
|
static HKL lastActiveHkl = 0;
|
|
static BOOL altGrFlag;
|
|
|
|
/**
|
|
* Checks whether the active Windows system keyboard has mappings for RightAlt,
|
|
* according to the flag KLLF_ALTGR from KBD.h, which implies that
|
|
* LeftCtrl+RightAlt will be generated.
|
|
|
|
* Background: when a Windows system keyboard that maps RightAlt (AltGr) is
|
|
* active, Windows will internally generate LeftCtrl+RightAlt events when the
|
|
* RightAlt key is pressed, so we need to recognize this and mask out the Left
|
|
* Control modifier state when it happens.
|
|
*/
|
|
|
|
BOOL KeyboardGivesCtrlRAltForRAlt() {
|
|
HKL hkl = GetKeyboardLayout(0);
|
|
|
|
if(hkl != lastActiveHkl) {
|
|
lastActiveHkl = hkl;
|
|
|
|
char keyboardLayoutName[KL_NAMELENGTH+1];
|
|
GetKeyboardLayoutName(keyboardLayoutName);
|
|
|
|
ReadAltGrFlagFromKbdDll(keyboardLayoutName, altGrFlag);
|
|
}
|
|
|
|
return altGrFlag;
|
|
}
|
|
|
|
BOOL ReadAltGrFlagFromKbdDll(const char *keyboardLayoutName, BOOL& result) {
|
|
BOOL success = FALSE;
|
|
result = FALSE;
|
|
|
|
HMODULE hKbdLibrary = LoadKbdLibrary(keyboardLayoutName);
|
|
if(!hKbdLibrary) {
|
|
SendDebugMessageFormat("Exit -- could not load library (error=%d)", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
#ifndef _WIN64
|
|
// In a WOW64 process (i.e. 32 bit process on a 64 bit architecture), the
|
|
// KBDTABLES structure returned from a keyboard DLL is 64-bit aligned, so we
|
|
// need to account for that.
|
|
if(IsWow64()) {
|
|
// 64 bit structure in 32 bit process!
|
|
PKBDLAYERDESCRIPTORWOW64FUNC KbdLayerDescriptorFunc = (PKBDLAYERDESCRIPTORWOW64FUNC) GetProcAddress(hKbdLibrary, "KbdLayerDescriptor");
|
|
if(KbdLayerDescriptorFunc) {
|
|
PKBDTABLES_WOW64 KbdTables = (*KbdLayerDescriptorFunc)();
|
|
if(KbdTables) {
|
|
result = (KbdTables->fLocaleFlags & KLLF_ALTGR) ? TRUE : FALSE;
|
|
success = TRUE;
|
|
}
|
|
}
|
|
} else {
|
|
#else
|
|
{
|
|
#endif
|
|
// Native architecture - 32 bit structure in 32 bit process, or 64 bit structure in 64 bit process
|
|
PKBDLAYERDESCRIPTORFUNC KbdLayerDescriptorFunc = (PKBDLAYERDESCRIPTORFUNC) GetProcAddress(hKbdLibrary, "KbdLayerDescriptor");
|
|
if(KbdLayerDescriptorFunc) {
|
|
PKBDTABLES KbdTables = (*KbdLayerDescriptorFunc)();
|
|
if(KbdTables) {
|
|
result = (KbdTables->fLocaleFlags & KLLF_ALTGR) ? TRUE : FALSE;
|
|
success = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
FreeLibrary(hKbdLibrary);
|
|
|
|
return success;
|
|
}
|
|
|
|
HMODULE LoadKbdLibrary(const char* keyboardLayoutName) {
|
|
char registryKey[128], layoutFile[MAX_PATH+1];
|
|
|
|
RegistryReadOnly r(HKEY_LOCAL_MACHINE);
|
|
|
|
wsprintf(registryKey, "System\\CurrentControlSet\\Control\\keyboard layouts\\%s", keyboardLayoutName);
|
|
if(!r.OpenKeyReadOnly(registryKey)) {
|
|
return FALSE;
|
|
}
|
|
if(!r.ReadString("Layout File", layoutFile, sizeof(layoutFile)/sizeof(layoutFile[0]))) {
|
|
return FALSE;
|
|
}
|
|
|
|
return LoadLibrary(layoutFile);
|
|
}
|
|
|
|
BOOL fStored = FALSE;
|
|
BOOL bIsWow64 = FALSE;
|
|
|
|
BOOL IsWow64() {
|
|
if(fStored) {
|
|
return bIsWow64;
|
|
}
|
|
if(!IsWow64Process(GetCurrentProcess(), &bIsWow64)) {
|
|
// Assume 32 bit machine on failure
|
|
bIsWow64 = FALSE;
|
|
}
|
|
fStored = TRUE;
|
|
return bIsWow64;
|
|
}
|