]> git.proxmox.com Git - mirror_edk2.git/commitdiff
1. Add Partial Keystroke Support in Nt32 WinNTGopDxe driver. See the Uefi2.3.1a chapt...
authorqianouyang <qianouyang@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 30 Sep 2011 07:30:20 +0000 (07:30 +0000)
committerqianouyang <qianouyang@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 30 Sep 2011 07:30:20 +0000 (07:30 +0000)
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
Nt32Pkg/WinNtGopDxe/WinNtGopInput.c
Nt32Pkg/WinNtGopDxe/WinNtGopScreen.c

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