📄 laymgr.cpp
字号:
--*/
BOOL KeybdDriverSetMode(
INT iPddId, // @parm Id of the keyboard to set the information.
INT iIndex, // @parm Id of info to set.
LPVOID lpInput // @parm Input buffer.
)
{
BOOL fRet = FALSE;
LockConfig();
if ( lpInput == NULL ) {
SetLastError(ERROR_INVALID_PARAMETER);
goto leave;
}
switch ( iIndex )
{
case KBDI_AUTOREPEAT_INFO_ID:
{
struct KBDI_AUTOREPEAT_INFO *pInfo =
(struct KBDI_AUTOREPEAT_INFO*) lpInput;
if ( pInfo -> CurrentInitialDelay > KBD_AUTO_REPEAT_INITIAL_DELAY_MAX ) {
// RETAILMSG(1,
// (TEXT("Initial delay too large, using %d\r\n"),
// KBD_AUTO_REPEAT_INITIAL_DELAY_MAX));
v_AutoRepeatInitialDelay = KBD_AUTO_REPEAT_INITIAL_DELAY_MAX;
}
else if ( pInfo -> CurrentInitialDelay < KBD_AUTO_REPEAT_INITIAL_DELAY_MIN ) {
// RETAILMSG(1,
// (TEXT("Initial delay too small, using %d\r\n"),
// KBD_AUTO_REPEAT_INITIAL_DELAY_MIN));
v_AutoRepeatInitialDelay = KBD_AUTO_REPEAT_INITIAL_DELAY_MIN;
}
else {
v_AutoRepeatInitialDelay = pInfo -> CurrentInitialDelay;
}
if ( pInfo -> CurrentRepeatRate > KBD_AUTO_REPEAT_KEYS_PER_SEC_MAX ) {
// RETAILMSG(1,
// (TEXT("Initial repeat rate too large, using %d\r\n"),
// KBD_AUTO_REPEAT_KEYS_PER_SEC_MAX));
v_AutoRepeatKeysPerSec = KBD_AUTO_REPEAT_KEYS_PER_SEC_MAX;
}
else if ( ( pInfo -> CurrentRepeatRate < KBD_AUTO_REPEAT_KEYS_PER_SEC_MIN ) &&
( pInfo -> CurrentRepeatRate != 0 ) ) {
// RETAILMSG(1,
// (TEXT("Initial repeat rate too small, using %d\r\n"),
// KBD_AUTO_REPEAT_KEYS_PER_SEC_MIN));
v_AutoRepeatKeysPerSec = KBD_AUTO_REPEAT_KEYS_PER_SEC_MIN;
}
else {
v_AutoRepeatKeysPerSec = pInfo -> CurrentRepeatRate;
}
// Now send the new repeat rate off to any external keyboards
struct KBDI_AUTOREPEAT_INFO AutoRepeatInfo = {
v_AutoRepeatInitialDelay, v_AutoRepeatKeysPerSec
};
BroadcastToKeyboards(IOCTL_KBD_SET_AUTOREPEAT, &AutoRepeatInfo,
sizeof(AutoRepeatInfo));
}
break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
goto leave;
}
fRet = TRUE;
leave:
UnlockConfig();
return fRet;
}
#ifdef DEBUG
// Verify function declaration against the typedef.
static PFN_KEYBD_DRIVER_SET_MODE v_pfnSetModeTest = KeybdDriverSetMode;
#endif
extern "C"
/*++
@doc EXTERNAL DRIVERS
@func
System power state change notification.
@comm This routine is called in a kernel context and may not make any
system calls whatsoever. It may read and write its own memory and that's
about it.
@comm Resets the auto-repeat state and calls the <f KeybdPdd_PowerHandler> routine.
--*/
void KeybdDriverPowerHandler(
BOOL fOff // @parm TRUE, the system is powering off; FALSE, the system is powering up.
)
{
v_AutoRepeatState = AR_WAIT_FOR_ANY;
for (UINT uiCurrPdd = 0; uiCurrPdd < g_cPdds; ++uiCurrPdd)
{
PKEYBD_PDD_INFO pKeybdPddInfo = pKeybdPddInfoFromId(uiCurrPdd);
if (pKeybdPddInfo->fValid == TRUE)
{
PKEYBD_PDD pKeybdPdd = pKeybdPddInfo->pKeybdPdd;
PREFAST_DEBUGCHK(pKeybdPdd != NULL);
if (pKeybdPdd->pfnPowerHandler != NULL) {
(*pKeybdPdd->pfnPowerHandler)(uiCurrPdd, fOff);
}
}
}
return;
}
#ifdef DEBUG
// Verify function declaration against the typedef.
static PFN_KEYBD_DRIVER_POWER_HANDLER v_pfnPowerHandler =
KeybdDriverPowerHandler;
#endif
//----------------------------------------------------------------------------
//
// Keybd_EventFlags
//
// Create the flags parameter for keybd_event.
//
//----------------------------------------------------------------------------
static
DWORD
Keybd_EventFlags(
UINT32 uiVKey,
UINT32 uiScanCode,
KEY_STATE_FLAGS KeyStateFlags,
BOOL fRepeat
)
{
DWORD dwFlags = 0;
// The key is extended if it matches 0x0000e0xx (not 0xe1xxxx)
if ((uiScanCode & 0xFFFFFF00) == 0xE000) {
dwFlags |= KEYEVENTF_EXTENDEDKEY;
}
if ( (fRepeat == TRUE) &&
((uiVKey & KEYBD_DEVICE_SILENT_REPEAT) != 0) )
{
dwFlags |= KEYEVENTF_SILENT;
}
if ((KeyStateFlags & KeyStateDownFlag) == 0) {
dwFlags |= KEYEVENTF_KEYUP;
}
return dwFlags;
}
//----------------------------------------------------------------------------
//
// CallDLRemapFn
//
// Call external remap function.
//
// Returns 0 if there are no remapped events or if there is an error.
//
//----------------------------------------------------------------------------
static
UINT
CallDLRemapFn(
PFN_KEYBD_REMAP pfnRemapKey,
const KEYBD_EVENT *pKbdEvents,
UINT cKbdEvents,
KEYBD_EVENT *pRmpKbdEvents,
UINT cMaxRmpKbdEvents
)
{
UINT cEvents;
DEBUGCHK(pfnRemapKey != NULL);
DEBUGCHK( (pKbdEvents != NULL) || (pRmpKbdEvents == NULL) );
__try {
cEvents = (*pfnRemapKey)(pKbdEvents, cKbdEvents,
pRmpKbdEvents, cMaxRmpKbdEvents);
}
__except(EXCEPTION_EXECUTE_HANDLER) {
RETAILMSG(1, (_T("Keyboard: Exception in device layout remapping function\r\n")));
cEvents = 0;
}
return cEvents;
}
//----------------------------------------------------------------------------
//
// SendRemappedEvent
//
// Remap the key and send it to GWE.
//
//----------------------------------------------------------------------------
static
VOID
SendRemappedEvent(
UINT32 uiVKey,
UINT32 uiScanCode,
KEY_STATE_FLAGS KeyStateFlags,
BOOL fRepeat,
DEVICE_LAYOUT_INFO *pdli
)
{
SETFNAME(_T("SendRemappedEvent"));
PREFAST_DEBUGCHK(pdli != NULL);
const DEVICE_LAYOUT *pdl = &pdli->dl;
KEYBD_EVENT rgKbdEvent[ALTGR_MAPPING] = { uiVKey, uiScanCode, KeyStateFlags };
KEYBD_EVENT *pKbdEvent = NULL; // Final list to use
UINT cEvents = 1;
DEBUGCHK(IsLocked() == TRUE);
if ( (uiVKey == VK_RMENU) && (g_ili.il.fLocaleFlags & KLLF_ALTGR) ) {
// Add in the control key for AltGr
const KEYBD_EVENT c_KbdEventLControl = { VK_LCONTROL, uiScanCode, KeyStateFlags };
rgKbdEvent[cEvents] = rgKbdEvent[0];
rgKbdEvent[0] = c_KbdEventLControl;
++cEvents;
}
// Verify that our pdli->cMaxRmpKbdEvents was calculated properly.
DEBUGCHK(cEvents <= ALTGR_MAPPING);
if (pdl->pfnRemapKey) {
// Which remapping buffer do we use?
if (pdli->pKbdEvents) {
pKbdEvent = pdli->pKbdEvents;
}
else {
pKbdEvent = pdli->rgKbdEvent;
}
cEvents = CallDLRemapFn(pdl->pfnRemapKey, rgKbdEvent, cEvents,
pKbdEvent, pdli->cMaxRmpKbdEvents);
if (cEvents > pdli->cMaxRmpKbdEvents) {
ERRORMSG(1, (_T("Keyboard: Remapping function returned too many events\r\n")));
cEvents = 0;
}
}
else {
pKbdEvent = rgKbdEvent;
}
PREFAST_DEBUGCHK(pKbdEvent != NULL);
for (UINT uiIdx = 0; uiIdx < cEvents; ++uiIdx)
{
UINT32 uiCurrVk = pKbdEvent[uiIdx].uiVk;
UINT32 uiCurrSc = pKbdEvent[uiIdx].uiSc;
DEBUGMSG(ZONE_DEVICELAYOUT, (_T("%s: VK: 0x%08x SC: 0x%08x Shift Flags: 0x%08x\r\n"),
pszFname, uiCurrVk, uiCurrSc, pKbdEvent[uiIdx].KeyStateFlags));
DWORD dwFlags = Keybd_EventFlags(uiCurrVk, uiCurrSc,
pKbdEvent[uiIdx].KeyStateFlags, fRepeat);
keybd_event((BYTE) uiCurrVk, (BYTE) uiCurrSc, dwFlags, 0);
}
}
#define LAYOUT_HAS_KOREAN_KEYS(hkl) ( ( (hkl) == 0x0412 ) || ( (hkl) == 0x0409 ) )
//----------------------------------------------------------------------------
//
// WillKeyUp
//
// Returns FALSE if the key will not send a keyup. Currently, this is
// only known to occur for two Korean keys.
//
//----------------------------------------------------------------------------
static
BOOL
WillKeyUp(
UINT32 uiVKey,
const DEVICE_LAYOUT_INFO *pdli
)
{
PREFAST_DEBUGCHK(pdli != NULL);
DEBUGCHK(IsLocked() == TRUE);
BOOL fRet = TRUE;
// Some Korean specific keys only generate a key
// down when pressed.
if ( LAYOUT_HAS_KOREAN_KEYS((UINT) pdli->hkl) &&
(uiVKey == VK_HANJA || uiVKey == VK_HANGUL))
{
fRet = FALSE;
}
return fRet;
}
//----------------------------------------------------------------------------
//
// KeybdEventThreadProc
//
// Receives the keyboard event sent from PDDs to KeybdEventCallback. Will
// handle auto repeat.
//
//----------------------------------------------------------------------------
DWORD
WINAPI
KeybdEventThreadProc(
LPVOID
)
{
SETFNAME(_T("KeybdEventThreadProc"));
static const BOOL bRepeatForever = TRUE;
static UINT32 v_AutoRepeatVKey;
static UINT32 v_AutoRepeatScanCode;
static KEY_STATE_FLAGS v_AutoRepeatKeyStateFlags;
static UINT v_AutoRepeatPddId;
UINT uiPddId;
UINT32 uiScanCode;
BOOL fKeyUp;
DEVICE_LAYOUT_INFO *pdli = NULL;
const DEVICE_LAYOUT *pdl = NULL;
UINT32 uiVKey;
KEY_STATE_FLAGS KeyStateFlags;
DWORD AutoRepeatKeysPerSec;
long AutoRepeatTimeout;
BOOL fSendAutoRepeatKey;
DWORD MRKeyTimeForPolling = 0; //Get rid of compiler uninitialized variable warning.
DWORD dwWait;
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
AutoRepeatTimeout = INFINITE;
while (bRepeatForever)
{
fSendAutoRepeatKey = FALSE;
AutoRepeatKeysPerSec = v_AutoRepeatKeysPerSec;
// 0 keys per second => auto repeat disabled.
if ( AutoRepeatKeysPerSec == 0 )
v_AutoRepeatState = AR_WAIT_FOR_ANY;
if ( v_AutoRepeatState == AR_WAIT_FOR_ANY )
{
AutoRepeatTimeout = INFINITE;
}
else if ( v_AutoRepeatState == AR_INITIAL_DELAY )
{
AutoRepeatTimeout = v_AutoRepeatInitialDelay;
}
else if ( v_AutoRepeatState == AR_AUTO_PARTIAL )
{
long lTemp = AutoRepeatTimeout - (GetTickCount() - MRKeyTimeForPolling);
AutoRepeatTimeout = (lTemp > 0) ? lTemp : 0;
}
else
{
AutoRepeatTimeout = 1000/AutoRepeatKeysPerSec;
}
MRKeyTimeForPolling = GetTickCount();
dwWait = WaitForSingleObject(g_hevBeginEvent, AutoRepeatTimeout);
LockConfig();
if ( dwWait == WAIT_TIMEOUT )
{
/* On power off, the v_AutoRepeatState is set to AR_WAIT_FOR_ANY, but we
cannot reset the WaitForSingleObject timeout value. This means that when
we power on, we could (and probably will) come back from the wait with a
wait timeout status. In this case, we do nothing and come back around to
wait again with the proper timeout. */
if ( v_AutoRepeatState == AR_WAIT_FOR_ANY )
; // do nothing
else if ( v_AutoRepeatState == AR_INITIAL_DELAY )
{
fSendAutoRepeatKey = TRUE;
v_AutoRepeatState = AR_AUTOREPEATING;
}
else if ( v_AutoRepeatState == AR_AUTO_PARTIAL )
{
fSendAutoRepeatKey = TRUE;
v_AutoRepeatState = AR_AUTOREPEATING;
}
else
{
fSendAutoRepeatKey = TRUE;
}
if ( fSendAutoRepeatKey )
{
pdli = pDLIFromPDDIndex(v_AutoRepeatPddId);
pdl = &pdli->dl;
DEBUGCHK(ValidateDeviceLayout(pdl));
SendRemappedEvent(v_AutoRepeatVKey, v_AutoRepeatScanCode,
v_AutoRepeatKeyStateFlags, TRUE, pdli);
}
}
else
{
// We got a keyboard interrupt but there may or may not be key events.
DEBUGCHK(g_PrivateKeybdEvent.fValid == TRUE);
uiPddId = g_PrivateKeybdEvent.uiPddId;
uiScanCode = g_PrivateKeybdEvent.uiScanCode;
fKeyUp = g_PrivateKeybdEvent.fKeyUp;
#ifdef DEBUG
memset(&g_PrivateKeybdEvent, 0xcd, sizeof(g_PrivateKeybdEvent));
g_PrivateKeybdEvent.fValid = FALSE;
#endif
// Release KeybdEventCallback()
SetEvent(g_hevEndEvent);
pdli = pDLIFromPDDIndex(uiPddId);
DEBUGCHK(pKeybdPddInfoFromId(uiPddId)->fValid);
if (pdli->hkl == INVALID_HKL) {
ERRORMSG(1, (_T("Keyboard: Keypress ignored since Device Layout is not set\r\n")));
}
else {
pdl = &pdli->dl;
DEBUGCHK(Valida
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -