From df7499fcc1fbd6c825cabf19bbed379688416125 Mon Sep 17 00:00:00 2001 From: qianouyang Date: Fri, 30 Sep 2011 07:30:20 +0000 Subject: [PATCH] 1. Add Partial Keystroke Support in Nt32 WinNTGopDxe driver. See the Uefi2.3.1a chapter 11.2 2. Fix the bug of "NT32 Keyboard driver don't support the ALT+ValueKey". Signed-off-by: qianouyang Reviewed-by: niruiyu vanjeff git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12496 6f19259b-4bc3-4df7-8a09-765794883524 --- Nt32Pkg/WinNtGopDxe/WinNtGop.h | 19 +- Nt32Pkg/WinNtGopDxe/WinNtGopInput.c | 276 ++++++++++++++----------- Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c | 290 ++++++++++++++++----------- 3 files changed, 344 insertions(+), 241 deletions(-) diff --git a/Nt32Pkg/WinNtGopDxe/WinNtGop.h b/Nt32Pkg/WinNtGopDxe/WinNtGop.h index 3490de06ca..dd53591041 100644 --- a/Nt32Pkg/WinNtGopDxe/WinNtGop.h +++ b/Nt32Pkg/WinNtGopDxe/WinNtGop.h @@ -46,13 +46,13 @@ Abstract: // // WM_SYSKEYDOWN/WM_SYSKEYUP Notification // lParam -// bit 24: Specifies whether the key is an extended key, -// such as the right-hand ALT and CTRL keys that appear on -// an enhanced 101- or 102-key keyboard. +// bit 24: Specifies whether the key is an extended key, +// such as the right-hand ALT and CTRL keys that appear on +// an enhanced 101- or 102-key keyboard. // The value is 1 if it is an extended key; otherwise, it is 0. -// bit 29:Specifies the context code. -// The value is 1 if the ALT key is down while the key is pressed/released; -// it is 0 if the WM_SYSKEYDOWN message is posted to the active window +// bit 29:Specifies the context code. +// The value is 1 if the ALT key is down while the key is pressed/released; +// it is 0 if the WM_SYSKEYDOWN message is posted to the active window // because no window has the keyboard focus. #define GOP_EXTENDED_KEY (0x1 << 24) #define GOP_ALT_KEY_PRESSED (0x1 << 29) @@ -132,7 +132,7 @@ typedef struct { EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FillLine; // - // Keyboard Queue used by Simple Text In. + // Keyboard Queue used by Simple Text In. // QueueForRead: WinProc thread adds, and main thread removes. // QueueForNotify: WinProc thread adds, and timer thread removes. // @@ -143,7 +143,7 @@ typedef struct { EFI_KEY_STATE KeyState; LIST_ENTRY NotifyList; BOOLEAN LeftShift; - BOOLEAN RightShift; + BOOLEAN RightShift; BOOLEAN LeftAlt; BOOLEAN RightAlt; BOOLEAN LeftCtrl; @@ -151,10 +151,11 @@ typedef struct { BOOLEAN LeftLogo; BOOLEAN RightLogo; BOOLEAN Menu; - BOOLEAN SysReq; + BOOLEAN SysReq; BOOLEAN NumLock; BOOLEAN ScrollLock; BOOLEAN CapsLock; + BOOLEAN IsPartialKeySupport; EFI_EVENT TimerEvent; } GOP_PRIVATE_DATA; diff --git a/Nt32Pkg/WinNtGopDxe/WinNtGopInput.c b/Nt32Pkg/WinNtGopDxe/WinNtGopInput.c index 5defc1601c..cc05a5d1b8 100644 --- a/Nt32Pkg/WinNtGopDxe/WinNtGopInput.c +++ b/Nt32Pkg/WinNtGopDxe/WinNtGopInput.c @@ -133,6 +133,16 @@ GopPrivateDeleteQ ( CopyMem (Key, &Queue->Q[Queue->Front], sizeof (EFI_KEY_DATA)); Queue->Front = (Queue->Front + 1) % MAX_Q; + if (Key->Key.ScanCode == SCAN_NULL && Key->Key.UnicodeChar == CHAR_NULL) { + if (!Private->IsPartialKeySupport) { + // + // If partial keystrok is not enabled, don't return the partial keystroke. + // + Private->WinNtThunk->LeaveCriticalSection (&Queue->Cs); + ZeroMem (Key, sizeof (EFI_KEY_DATA)); + return EFI_NOT_READY; + } + } Private->WinNtThunk->LeaveCriticalSection (&Queue->Cs); return EFI_SUCCESS; } @@ -170,36 +180,36 @@ Routine Description: Arguments: - RegsiteredData - A pointer to a buffer that is filled in with the keystroke + RegsiteredData - A pointer to a buffer that is filled in with the keystroke state data for the key that was registered. - InputData - A pointer to a buffer that is filled in with the keystroke + InputData - A pointer to a buffer that is filled in with the keystroke state data for the key that was pressed. Returns: TRUE - Key be pressed matches a registered key. - FLASE - Match failed. - + FLASE - Match failed. + --*/ { ASSERT (RegsiteredData != NULL && InputData != NULL); - + if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) || (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) { - return FALSE; - } - + return FALSE; + } + // // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored. // if (RegsiteredData->KeyState.KeyShiftState != 0 && RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) { - return FALSE; - } + return FALSE; + } if (RegsiteredData->KeyState.KeyToggleState != 0 && RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) { - return FALSE; - } - + return FALSE; + } + return TRUE; } @@ -219,29 +229,29 @@ Routine Description: Arguments: Private - The private structure of WinNt Gop device. - KeyData - A pointer to a buffer that is filled in with the keystroke + KeyData - A pointer to a buffer that is filled in with the keystroke state data for the key that was pressed. Returns: EFI_SUCCESS - The status light is updated successfully. ---*/ -{ +--*/ +{ LIST_ENTRY *Link; WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify; - + for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { CurrentNotify = CR ( - Link, - WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY, - NotifyEntry, + Link, + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY, + NotifyEntry, WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE ); if (GopPrivateIsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { CurrentNotify->KeyNotificationFn (KeyData); } - } + } } VOID @@ -299,7 +309,7 @@ GopPrivateAddKey ( } if (Private->LeftShift) { KeyData.KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED; - } + } if (Private->RightShift) { KeyData.KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED; } @@ -314,7 +324,7 @@ GopPrivateAddKey ( } if (Private->SysReq) { KeyData.KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED; - } + } if (Private->CapsLock) { KeyData.KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE; } @@ -324,11 +334,14 @@ GopPrivateAddKey ( if (Private->ScrollLock) { KeyData.KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE; } - + if (Private->IsPartialKeySupport) { + KeyData.KeyState.KeyToggleState |= EFI_KEY_STATE_EXPOSED; + } + // // Convert Ctrl+[1-26] to Ctrl+[A-Z] // - if ((Private->LeftCtrl || Private->RightCtrl) && + if ((Private->LeftCtrl || Private->RightCtrl) && (KeyData.Key.UnicodeChar >= 1) && (KeyData.Key.UnicodeChar <= 26) ) { if ((Private->LeftShift || Private->RightShift) == Private->CapsLock) { @@ -382,16 +395,16 @@ Returns: EFI_SUCCESS - The status light is updated successfully. ---*/ -{ +--*/ +{ // - // BUGBUG:Only SendInput/keybd_event function can toggle + // BUGBUG:Only SendInput/keybd_event function can toggle // NumLock, CapsLock and ScrollLock keys. // Neither of these functions is included in EFI_WIN_NT_THUNK_PROTOCOL. // Thus, return immediately without operation. // return EFI_SUCCESS; - + } @@ -441,11 +454,12 @@ Returns: Private->RightLogo = FALSE; Private->Menu = FALSE; Private->SysReq = FALSE; - + Private->CapsLock = FALSE; Private->NumLock = FALSE; Private->ScrollLock = FALSE; - + Private->IsPartialKeySupport = FALSE; + Private->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID; Private->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID; @@ -465,25 +479,25 @@ GopPrivateReadKeyStrokeWorker ( /*++ Routine Description: - Reads the next keystroke from the input device. The WaitForKey Event can + Reads the next keystroke from the input device. The WaitForKey Event can be used to test for existance of a keystroke via WaitForEvent () call. Arguments: Private - The private structure of WinNt Gop device. - KeyData - A pointer to a buffer that is filled in with the keystroke + KeyData - A pointer to a buffer that is filled in with the keystroke state data for the key that was pressed. Returns: EFI_SUCCESS - The keystroke information was returned. EFI_NOT_READY - There was no keystroke data availiable. - EFI_DEVICE_ERROR - The keystroke information was not returned due to + EFI_DEVICE_ERROR - The keystroke information was not returned due to hardware errors. - EFI_INVALID_PARAMETER - KeyData is NULL. + EFI_INVALID_PARAMETER - KeyData is NULL. --*/ { EFI_STATUS Status; - EFI_TPL OldTpl; + EFI_TPL OldTpl; if (KeyData == NULL) { return EFI_INVALID_PARAMETER; @@ -507,10 +521,14 @@ GopPrivateReadKeyStrokeWorker ( Status = GopPrivateDeleteQ (Private, &Private->QueueForRead, KeyData); if (!EFI_ERROR (Status)) { // - // Leave critical section and return + // If partial keystroke is not enabled, check whether it is value key. If not return + // EFI_NOT_READY. // - gBS->RestoreTPL (OldTpl); - return EFI_SUCCESS; + if (!Private->IsPartialKeySupport) { + if (KeyData->Key.ScanCode == SCAN_NULL && KeyData->Key.UnicodeChar == CHAR_NULL) { + Status = EFI_NOT_READY; + } + } } } @@ -574,15 +592,22 @@ WinNtGopSimpleTextInReadKeyStroke ( EFI_KEY_DATA KeyData; Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This); - - Status = GopPrivateReadKeyStrokeWorker (Private, &KeyData); - if (EFI_ERROR (Status)) { - return Status; - } - - CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); - - return EFI_SUCCESS; + // + // Considering if the partial keystroke is enabled, there maybe a partial + // keystroke in the queue, so here skip the partial keystroke and get the + // next key from the queue + // + while (1) { + Status = GopPrivateReadKeyStrokeWorker (Private, &KeyData); + if (EFI_ERROR (Status)) { + return Status; + } + if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) { + continue; + } + CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); + return EFI_SUCCESS; + } } @@ -605,6 +630,7 @@ WinNtGopSimpleTextInWaitForKey ( GOP_PRIVATE_DATA *Private; EFI_STATUS Status; EFI_TPL OldTpl; + EFI_KEY_DATA KeyData; Private = (GOP_PRIVATE_DATA *) Context; @@ -612,26 +638,40 @@ WinNtGopSimpleTextInWaitForKey ( // Enter critical section // OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - + // // Call hot key callback before telling caller there is a key available // WinNtGopSimpleTextInTimerHandler (NULL, Private); - - Status = GopPrivateCheckQ (&Private->QueueForRead); - if (!EFI_ERROR (Status)) { - // - // If a there is a key in the queue signal our event. - // - gBS->SignalEvent (Event); - } else { - // - // We need to sleep or NT will schedule this thread with such high - // priority that WinProc thread will never run and we will not see - // keyboard input. This Sleep makes the syste run 10x faster, so don't - // remove it. - // - Private->WinNtThunk->Sleep (1); + + // + // WaitforKey doesn't suppor the partial key. + // Considering if the partial keystroke is enabled, there maybe a partial + // keystroke in the queue, so here skip the partial keystroke and get the + // next key from the queue + // + while (1) { + Status = GopPrivateCheckQ (&Private->QueueForRead); + if (!EFI_ERROR (Status)) { + // + // If a there is a key in the queue and it is not partial keystroke, signal event. + // + if (Private->QueueForRead.Q[Private->QueueForRead.Front].Key.ScanCode == SCAN_NULL && + Private->QueueForRead.Q[Private->QueueForRead.Front].Key.UnicodeChar == CHAR_NULL) { + GopPrivateDeleteQ (Private,&Private->QueueForRead,&KeyData); + continue; + } + gBS->SignalEvent (Event); + } else { + // + // We need to sleep or NT will schedule this thread with such high + // priority that WinProc thread will never run and we will not see + // keyboard input. This Sleep makes the syste run 10x faster, so don't + // remove it. + // + Private->WinNtThunk->Sleep (1); + } + break; } // @@ -667,7 +707,7 @@ WinNtGopSimpleTextInExResetEx ( GOP_PRIVATE_DATA *Private; Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); - + return GopPrivateResetWorker (Private); } @@ -680,20 +720,20 @@ WinNtGopSimpleTextInExReadKeyStrokeEx ( /*++ Routine Description: - Reads the next keystroke from the input device. The WaitForKey Event can + Reads the next keystroke from the input device. The WaitForKey Event can be used to test for existance of a keystroke via WaitForEvent () call. Arguments: This - Protocol instance pointer. - KeyData - A pointer to a buffer that is filled in with the keystroke + KeyData - A pointer to a buffer that is filled in with the keystroke state data for the key that was pressed. Returns: EFI_SUCCESS - The keystroke information was returned. EFI_NOT_READY - There was no keystroke data availiable. - EFI_DEVICE_ERROR - The keystroke information was not returned due to + EFI_DEVICE_ERROR - The keystroke information was not returned due to hardware errors. - EFI_INVALID_PARAMETER - KeyData is NULL. + EFI_INVALID_PARAMETER - KeyData is NULL. --*/ { @@ -704,7 +744,7 @@ WinNtGopSimpleTextInExReadKeyStrokeEx ( } Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); - + return GopPrivateReadKeyStrokeWorker (Private, KeyData); } @@ -722,17 +762,17 @@ WinNtGopSimpleTextInExSetState ( Arguments: This - Protocol instance pointer. - KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the + KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the state for the input device. - - Returns: + + Returns: EFI_SUCCESS - The device state was set successfully. - EFI_DEVICE_ERROR - The device is not functioning correctly and could + EFI_DEVICE_ERROR - The device is not functioning correctly and could not have the setting adjusted. EFI_UNSUPPORTED - The device does not have the ability to set its state. - EFI_INVALID_PARAMETER - KeyToggleState is NULL. + EFI_INVALID_PARAMETER - KeyToggleState is NULL. ---*/ +--*/ { EFI_STATUS Status; GOP_PRIVATE_DATA *Private; @@ -745,31 +785,35 @@ WinNtGopSimpleTextInExSetState ( if (((Private->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) || ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) { - return EFI_UNSUPPORTED; + return EFI_UNSUPPORTED; } - Private->ScrollLock = FALSE; - Private->NumLock = FALSE; - Private->CapsLock = FALSE; + Private->ScrollLock = FALSE; + Private->NumLock = FALSE; + Private->CapsLock = FALSE; + Private->IsPartialKeySupport = FALSE; if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) { Private->ScrollLock = TRUE; - } + } if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) { Private->NumLock = TRUE; } if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) { Private->CapsLock = TRUE; } + if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) { + Private->IsPartialKeySupport = TRUE; + } - Status = GopPrivateUpdateStatusLight (Private); + Status = GopPrivateUpdateStatusLight (Private); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } Private->KeyState.KeyToggleState = *KeyToggleState; return EFI_SUCCESS; - + } EFI_STATUS @@ -787,23 +831,23 @@ WinNtGopSimpleTextInExRegisterKeyNotify ( Arguments: This - Protocol instance pointer. - KeyData - A pointer to a buffer that is filled in with the keystroke + KeyData - A pointer to a buffer that is filled in with the keystroke information data for the key that was pressed. - KeyNotificationFunction - Points to the function to be called when the key - sequence is typed specified by KeyData. - NotifyHandle - Points to the unique handle assigned to the registered notification. + KeyNotificationFunction - Points to the function to be called when the key + sequence is typed specified by KeyData. + NotifyHandle - Points to the unique handle assigned to the registered notification. Returns: EFI_SUCCESS - The notification function was registered successfully. EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures. - EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. - ---*/ + EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. + +--*/ { GOP_PRIVATE_DATA *Private; WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify; LIST_ENTRY *Link; - WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *NewNotify; + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *NewNotify; if (KeyData == NULL || KeyNotificationFunction == NULL || NotifyHandle == NULL) { return EFI_INVALID_PARAMETER; @@ -816,37 +860,37 @@ WinNtGopSimpleTextInExRegisterKeyNotify ( // for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { CurrentNotify = CR ( - Link, - WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY, - NotifyEntry, + Link, + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY, + NotifyEntry, WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE ); - if (GopPrivateIsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { + if (GopPrivateIsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { *NotifyHandle = CurrentNotify->NotifyHandle; return EFI_SUCCESS; } } - } - + } + // // Allocate resource to save the notification function - // + // NewNotify = (WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *) AllocateZeroPool (sizeof (WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY)); if (NewNotify == NULL) { return EFI_OUT_OF_RESOURCES; } - NewNotify->Signature = WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE; + NewNotify->Signature = WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE; NewNotify->KeyNotificationFn = KeyNotificationFunction; NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify; CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA)); InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry); - *NotifyHandle = NewNotify->NotifyHandle; - + *NotifyHandle = NewNotify->NotifyHandle; + return EFI_SUCCESS; - + } EFI_STATUS @@ -861,14 +905,14 @@ WinNtGopSimpleTextInExUnregisterKeyNotify ( Remove a registered notification function from a particular keystroke. Arguments: - This - Protocol instance pointer. + This - Protocol instance pointer. NotificationHandle - The handle of the notification function being unregistered. Returns: EFI_SUCCESS - The notification function was unregistered successfully. EFI_INVALID_PARAMETER - The NotificationHandle is invalid. - ---*/ + +--*/ { GOP_PRIVATE_DATA *Private; LIST_ENTRY *Link; @@ -876,28 +920,28 @@ WinNtGopSimpleTextInExUnregisterKeyNotify ( if (NotificationHandle == NULL) { return EFI_INVALID_PARAMETER; - } + } if (((WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *) NotificationHandle)->Signature != WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE) { return EFI_INVALID_PARAMETER; - } + } Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { CurrentNotify = CR ( - Link, - WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY, - NotifyEntry, + Link, + WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY, + NotifyEntry, WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE - ); + ); if (CurrentNotify->NotifyHandle == NotificationHandle) { // // Remove the notification function from NotifyList and free resources // - RemoveEntryList (&CurrentNotify->NotifyEntry); + RemoveEntryList (&CurrentNotify->NotifyEntry); - gBS->FreePool (CurrentNotify); + gBS->FreePool (CurrentNotify); return EFI_SUCCESS; } } @@ -941,7 +985,7 @@ WinNtGopInitializeSimpleTextInForWindow ( &Private->SimpleTextIn.WaitForKey ); - + Private->SimpleTextInEx.Reset = WinNtGopSimpleTextInExResetEx; Private->SimpleTextInEx.ReadKeyStrokeEx = WinNtGopSimpleTextInExReadKeyStrokeEx; Private->SimpleTextInEx.SetState = WinNtGopSimpleTextInExSetState; @@ -949,7 +993,7 @@ WinNtGopInitializeSimpleTextInForWindow ( Private->SimpleTextInEx.UnregisterKeyNotify = WinNtGopSimpleTextInExUnregisterKeyNotify; Private->SimpleTextInEx.Reset (&Private->SimpleTextInEx, FALSE); - + InitializeListHead (&Private->NotifyList); Status = gBS->CreateEvent ( @@ -972,7 +1016,7 @@ WinNtGopInitializeSimpleTextInForWindow ( &Private->TimerEvent ); ASSERT_EFI_ERROR (Status); - + Status = gBS->SetTimer ( Private->TimerEvent, TimerPeriodic, diff --git a/Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c b/Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c index f9f2e0dd0c..85848aa6ce 100644 --- a/Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c +++ b/Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c @@ -52,106 +52,154 @@ KillNtGopThread ( IN VOID *Context ); -VOID +BOOLEAN WinNtGopConvertParamToEfiKeyShiftState ( IN GOP_PRIVATE_DATA *Private, IN WPARAM *wParam, + IN LPARAM *lParam, IN BOOLEAN Flag ) { switch (*wParam) { // // BUGBUG: Only GetAsyncKeyState() and GetKeyState() can distinguish - // left and right Ctrl, and Shift key. - // Neither of the two is defined in EFI_WIN_NT_THUNK_PROTOCOL. + // left and right Ctrl, and Shift key. + // Neither of the two is defined in EFI_WIN_NT_THUNK_PROTOCOL. // Therefor, we can not set the correct Shift state here. - // - case VK_SHIFT: - Private->LeftShift = Flag; - break; + // + case VK_SHIFT: + if ((*lParam & GOP_EXTENDED_KEY) == GOP_EXTENDED_KEY) { + Private->RightShift = Flag; + } else { + Private->LeftShift = Flag; + } + return TRUE; + + case VK_LSHIFT: + Private->LeftShift = Flag; + return TRUE; + + case VK_RSHIFT: + Private->RightShift = Flag; + return TRUE; + case VK_CONTROL: - Private->LeftCtrl = Flag; - break; - case VK_LWIN: + if ((*lParam & GOP_EXTENDED_KEY) == GOP_EXTENDED_KEY) { + Private->RightCtrl= Flag; + } else { + Private->LeftCtrl = Flag; + } + return TRUE; + + case VK_LCONTROL: + Private->LeftCtrl = Flag; + return TRUE; + + case VK_RCONTROL: + Private->RightCtrl = Flag; + return TRUE; + + case VK_LWIN: Private->LeftLogo = Flag; - break; - case VK_RWIN: + return TRUE; + + case VK_RWIN: Private->RightLogo = Flag; - break; - case VK_APPS: + return TRUE; + + case VK_APPS: Private->Menu = Flag; - break; + return TRUE; // // BUGBUG: PrintScreen/SysRq can not trigger WM_KEYDOWN message, // so SySReq shift state is not supported here. // - case VK_PRINT: + case VK_PRINT: Private->SysReq = Flag; - break; + return TRUE; + // + // For Alt Keystroke. + // + case VK_MENU: + if ((*lParam & GOP_EXTENDED_KEY) == GOP_EXTENDED_KEY) { + Private->RightAlt = Flag; + } else { + Private->LeftAlt = Flag; + } + return TRUE; + + default: + return FALSE; } } -VOID +BOOLEAN WinNtGopConvertParamToEfiKey ( IN GOP_PRIVATE_DATA *Private, IN WPARAM *wParam, + IN LPARAM *lParam, IN EFI_INPUT_KEY *Key ) { + BOOLEAN Flag; + Flag = FALSE; switch (*wParam) { - case VK_HOME: Key->ScanCode = SCAN_HOME; break; - case VK_END: Key->ScanCode = SCAN_END; break; - case VK_LEFT: Key->ScanCode = SCAN_LEFT; break; - case VK_RIGHT: Key->ScanCode = SCAN_RIGHT; break; - case VK_UP: Key->ScanCode = SCAN_UP; break; - case VK_DOWN: Key->ScanCode = SCAN_DOWN; break; - case VK_DELETE: Key->ScanCode = SCAN_DELETE; break; - case VK_INSERT: Key->ScanCode = SCAN_INSERT; break; - case VK_PRIOR: Key->ScanCode = SCAN_PAGE_UP; break; - case VK_NEXT: Key->ScanCode = SCAN_PAGE_DOWN; break; - case VK_ESCAPE: Key->ScanCode = SCAN_ESC; break; - - case VK_F1: Key->ScanCode = SCAN_F1; break; - case VK_F2: Key->ScanCode = SCAN_F2; break; - case VK_F3: Key->ScanCode = SCAN_F3; break; - case VK_F4: Key->ScanCode = SCAN_F4; break; - case VK_F5: Key->ScanCode = SCAN_F5; break; - case VK_F6: Key->ScanCode = SCAN_F6; break; - case VK_F7: Key->ScanCode = SCAN_F7; break; - case VK_F8: Key->ScanCode = SCAN_F8; break; - case VK_F9: Key->ScanCode = SCAN_F9; break; - case VK_F11: Key->ScanCode = SCAN_F11; break; - case VK_F12: Key->ScanCode = SCAN_F12; break; + case VK_HOME: Key->ScanCode = SCAN_HOME; Flag = TRUE; break; + case VK_END: Key->ScanCode = SCAN_END; Flag = TRUE; break; + case VK_LEFT: Key->ScanCode = SCAN_LEFT; Flag = TRUE; break; + case VK_RIGHT: Key->ScanCode = SCAN_RIGHT; Flag = TRUE; break; + case VK_UP: Key->ScanCode = SCAN_UP; Flag = TRUE; break; + case VK_DOWN: Key->ScanCode = SCAN_DOWN; Flag = TRUE; break; + case VK_DELETE: Key->ScanCode = SCAN_DELETE; Flag = TRUE; break; + case VK_INSERT: Key->ScanCode = SCAN_INSERT; Flag = TRUE; break; + case VK_PRIOR: Key->ScanCode = SCAN_PAGE_UP; Flag = TRUE; break; + case VK_NEXT: Key->ScanCode = SCAN_PAGE_DOWN; Flag = TRUE; break; + case VK_ESCAPE: Key->ScanCode = SCAN_ESC; Flag = TRUE; break; - case VK_F13: Key->ScanCode = SCAN_F13; break; - case VK_F14: Key->ScanCode = SCAN_F14; break; - case VK_F15: Key->ScanCode = SCAN_F15; break; - case VK_F16: Key->ScanCode = SCAN_F16; break; - case VK_F17: Key->ScanCode = SCAN_F17; break; - case VK_F18: Key->ScanCode = SCAN_F18; break; - case VK_F19: Key->ScanCode = SCAN_F19; break; - case VK_F20: Key->ScanCode = SCAN_F20; break; - case VK_F21: Key->ScanCode = SCAN_F21; break; - case VK_F22: Key->ScanCode = SCAN_F22; break; - case VK_F23: Key->ScanCode = SCAN_F23; break; - case VK_F24: Key->ScanCode = SCAN_F24; break; - case VK_PAUSE: Key->ScanCode = SCAN_PAUSE; break; + case VK_F1: Key->ScanCode = SCAN_F1; Flag = TRUE; break; + case VK_F2: Key->ScanCode = SCAN_F2; Flag = TRUE; break; + case VK_F3: Key->ScanCode = SCAN_F3; Flag = TRUE; break; + case VK_F4: Key->ScanCode = SCAN_F4; Flag = TRUE; break; + case VK_F5: Key->ScanCode = SCAN_F5; Flag = TRUE; break; + case VK_F6: Key->ScanCode = SCAN_F6; Flag = TRUE; break; + case VK_F7: Key->ScanCode = SCAN_F7; Flag = TRUE; break; + case VK_F8: Key->ScanCode = SCAN_F8; Flag = TRUE; break; + case VK_F9: Key->ScanCode = SCAN_F9; Flag = TRUE; break; + case VK_F11: Key->ScanCode = SCAN_F11; Flag = TRUE; break; + case VK_F12: Key->ScanCode = SCAN_F12; Flag = TRUE; break; + + case VK_F13: Key->ScanCode = SCAN_F13; Flag = TRUE; break; + case VK_F14: Key->ScanCode = SCAN_F14; Flag = TRUE; break; + case VK_F15: Key->ScanCode = SCAN_F15; Flag = TRUE; break; + case VK_F16: Key->ScanCode = SCAN_F16; Flag = TRUE; break; + case VK_F17: Key->ScanCode = SCAN_F17; Flag = TRUE; break; + case VK_F18: Key->ScanCode = SCAN_F18; Flag = TRUE; break; + case VK_F19: Key->ScanCode = SCAN_F19; Flag = TRUE; break; + case VK_F20: Key->ScanCode = SCAN_F20; Flag = TRUE; break; + case VK_F21: Key->ScanCode = SCAN_F21; Flag = TRUE; break; + case VK_F22: Key->ScanCode = SCAN_F22; Flag = TRUE; break; + case VK_F23: Key->ScanCode = SCAN_F23; Flag = TRUE; break; + case VK_F24: Key->ScanCode = SCAN_F24; Flag = TRUE; break; + case VK_PAUSE: Key->ScanCode = SCAN_PAUSE; Flag = TRUE; break; // // Set toggle state - // - case VK_NUMLOCK: + // + case VK_NUMLOCK: Private->NumLock = (BOOLEAN)(!Private->NumLock); + Flag = TRUE; break; case VK_SCROLL: Private->ScrollLock = (BOOLEAN)(!Private->ScrollLock); - break; + Flag = TRUE; + break; case VK_CAPITAL: Private->CapsLock = (BOOLEAN)(!Private->CapsLock); - break; + Flag = TRUE; + break; } - WinNtGopConvertParamToEfiKeyShiftState (Private, wParam, TRUE); + return (WinNtGopConvertParamToEfiKeyShiftState (Private, wParam, lParam, TRUE)) == TRUE ? TRUE : Flag; } @@ -616,6 +664,7 @@ WinNtGopThreadWindowProc ( PAINTSTRUCT PaintStruct; LPARAM Index; EFI_INPUT_KEY Key; + BOOLEAN AltIsPress; // // BugBug - if there are two instances of this DLL in memory (such as is @@ -630,6 +679,7 @@ WinNtGopThreadWindowProc ( // This works since each Gop protocol has a unique Private data instance and // a unique thread. // + AltIsPress = FALSE; Private = mWinNt->TlsGetValue (mTlsIndex); ASSERT (NULL != Private); @@ -689,92 +739,100 @@ WinNtGopThreadWindowProc ( // // F10 and the ALT key do not create a WM_KEYDOWN message, thus this special case - // WM_SYSKEYDOWN is posted when F10 is pressed or + // WM_SYSKEYDOWN is posted when F10 is pressed or // holds down ALT key and then presses another key. // case WM_SYSKEYDOWN: - Key.ScanCode = 0; + + Key.ScanCode = 0; + Key.UnicodeChar = CHAR_NULL; switch (wParam) { case VK_F10: Key.ScanCode = SCAN_F10; - Key.UnicodeChar = 0; + Key.UnicodeChar = CHAR_NULL; GopPrivateAddKey (Private, Key); return 0; } - if ((lParam & GOP_ALT_KEY_PRESSED) == GOP_ALT_KEY_PRESSED) { - // - // ALT is pressed with another key pressed - // - WinNtGopConvertParamToEfiKey (Private, &wParam, &Key); - - if ((lParam & GOP_EXTENDED_KEY) == GOP_EXTENDED_KEY) { - Private->RightAlt = TRUE; - } else { + // + // If ALT or ALT + modifier key is pressed. + // + if (WinNtGopConvertParamToEfiKey (Private, &wParam, &lParam, &Key)) { + if (Key.ScanCode != 0){ + // + // If ALT is pressed with other ScanCode. + // Always revers the left Alt for simple. + // Private->LeftAlt = TRUE; } - - if (Private->RightAlt && Private->LeftAlt) { - Private->LeftAlt = FALSE; - } - } - - if (Key.ScanCode != 0) { - Key.UnicodeChar = 0; GopPrivateAddKey (Private, Key); - } - - return 0; - - case WM_SYSKEYUP: - if ((lParam & GOP_ALT_KEY_PRESSED) == GOP_ALT_KEY_PRESSED) { // - // ALT is pressed with another key released - // - WinNtGopConvertParamToEfiKeyShiftState (Private, &wParam, FALSE); - // - // Actually ALT key is still held down here. - // Change the ALT key state when another key is released - // by user because we did not find a better solution to - // get a released ALT key. + // When Alt is released there is no windoes message, so + // clean it after using it. // Private->RightAlt = FALSE; - Private->LeftAlt = FALSE; + Private->LeftAlt = FALSE; + return 0; } + AltIsPress = TRUE; - return 0; - - - case WM_KEYDOWN: - Key.ScanCode = 0; - WinNtGopConvertParamToEfiKey (Private, &wParam, &Key); - if (Key.ScanCode != 0) { - Key.UnicodeChar = 0; - GopPrivateAddKey (Private, Key); - } - - return 0; - - case WM_KEYUP: - WinNtGopConvertParamToEfiKeyShiftState (Private, &wParam, FALSE); - return 0; - - case WM_CHAR: + case WM_CHAR: // // The ESC key also generate WM_CHAR. // if (wParam == 0x1B) { - return 0; - } + return 0; + } + if (AltIsPress == TRUE) { + // + // If AltIsPress is true that means the Alt key is pressed. + // + Private->LeftAlt = TRUE; + } for (Index = 0; Index < (lParam & 0xffff); Index++) { if (wParam != 0) { Key.UnicodeChar = (CHAR16) wParam; - Key.ScanCode = 0; - GopPrivateAddKey (Private, Key); + Key.ScanCode = SCAN_NULL; + GopPrivateAddKey (Private, Key); } } + if (AltIsPress == TRUE) { + // + // When Alt is released there is no windoes message, so + // clean it after using it. + // + Private->LeftAlt = FALSE; + Private->RightAlt = FALSE; + } + return 0; + case WM_SYSKEYUP: + // + // ALT is pressed with another key released + // + WinNtGopConvertParamToEfiKeyShiftState (Private, &wParam, &lParam, FALSE); + return 0; + + case WM_KEYDOWN: + Key.ScanCode = SCAN_NULL; + // + // A value key press will cause a WM_KEYDOWN first, then cause a WM_CHAR + // So if there is no modifier key updated, skip the WM_KEYDOWN even. + // + if (WinNtGopConvertParamToEfiKey (Private, &wParam, &lParam, &Key)) { + if (Key.ScanCode != SCAN_NULL) { + Key.UnicodeChar = CHAR_NULL; + } + // + // Support the partial keystroke, add all keydown event into the queue. + // + GopPrivateAddKey (Private, Key); + } + return 0; + + case WM_KEYUP: + WinNtGopConvertParamToEfiKeyShiftState (Private, &wParam, &lParam, FALSE); return 0; case WM_CLOSE: