]> git.proxmox.com Git - mirror_edk2.git/blame - EmulatorPkg/Win/Host/WinGopInput.c
WinHost: Add SimplePointer support
[mirror_edk2.git] / EmulatorPkg / Win / Host / WinGopInput.c
CommitLineData
7a465451
RN
1/** @file\r
2\r
3Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
e3ba31da 4SPDX-License-Identifier: BSD-2-Clause-Patent\r
7a465451
RN
5\r
6Module Name:\r
7\r
8 WinGopInput.c\r
9\r
10Abstract:\r
11\r
12 This file produces the Simple Text In for an Gop window.\r
13\r
14 This stuff is linked at the hip to the Window, since the window\r
15 processing is done in a thread kicked off in WinNtGopImplementation.c\r
16\r
17 Since the window information is processed in an other thread we need\r
18 a keyboard Queue to pass data about. The Simple Text In code just\r
19 takes data off the Queue. The WinProc message loop takes keyboard input\r
20 and places it in the Queue.\r
21\r
22\r
23**/\r
24\r
25\r
26#include "WinGop.h"\r
27\r
28\r
29/**\r
30 TODO: Add function description\r
31\r
32 @param Private TODO: add argument description\r
33\r
34 @retval EFI_SUCCESS TODO: Add description for return value\r
35\r
36**/\r
37EFI_STATUS\r
38GopPrivateCreateQ (\r
39 IN GRAPHICS_PRIVATE_DATA *Private,\r
40 IN GOP_QUEUE_FIXED *Queue\r
41 )\r
42{\r
43 InitializeCriticalSection (&Queue->Cs);\r
44 Queue->Front = 0;\r
45 Queue->Rear = 0;\r
46 return EFI_SUCCESS;\r
47}\r
48\r
49\r
50/**\r
51 TODO: Add function description\r
52\r
53 @param Private TODO: add argument description\r
54\r
55 @retval EFI_SUCCESS TODO: Add description for return value\r
56\r
57**/\r
58EFI_STATUS\r
59GopPrivateDestroyQ (\r
60 IN GRAPHICS_PRIVATE_DATA *Private,\r
61 IN GOP_QUEUE_FIXED *Queue\r
62 )\r
63{\r
64 Queue->Front = 0;\r
65 Queue->Rear = 0;\r
66 DeleteCriticalSection (&Queue->Cs);\r
67 return EFI_SUCCESS;\r
68}\r
69\r
70\r
71/**\r
72 TODO: Add function description\r
73\r
74 @param Private TODO: add argument description\r
75 @param Key TODO: add argument description\r
76\r
77 @retval EFI_NOT_READY TODO: Add description for return value\r
78 @retval EFI_SUCCESS TODO: Add description for return value\r
79\r
80**/\r
81EFI_STATUS\r
82GopPrivateAddQ (\r
83 IN GRAPHICS_PRIVATE_DATA *Private,\r
84 IN GOP_QUEUE_FIXED *Queue,\r
85 IN EFI_KEY_DATA *KeyData\r
86 )\r
87{\r
88 EnterCriticalSection (&Queue->Cs);\r
89\r
90 if ((Queue->Rear + 1) % MAX_Q == Queue->Front) {\r
91 LeaveCriticalSection (&Queue->Cs);\r
92 return EFI_NOT_READY;\r
93 }\r
94\r
95 CopyMem (&Queue->Q[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA));\r
96 Queue->Rear = (Queue->Rear + 1) % MAX_Q;\r
97\r
98 LeaveCriticalSection (&Queue->Cs);\r
99 return EFI_SUCCESS;\r
100}\r
101\r
102\r
103/**\r
104 TODO: Add function description\r
105\r
106 @param Private TODO: add argument description\r
107 @param Key TODO: add argument description\r
108\r
109 @retval EFI_NOT_READY TODO: Add description for return value\r
110 @retval EFI_SUCCESS TODO: Add description for return value\r
111\r
112**/\r
113EFI_STATUS\r
114GopPrivateDeleteQ (\r
115 IN GRAPHICS_PRIVATE_DATA *Private,\r
116 IN GOP_QUEUE_FIXED *Queue,\r
117 OUT EFI_KEY_DATA *Key\r
118 )\r
119{\r
120 EnterCriticalSection (&Queue->Cs);\r
121\r
122 if (Queue->Front == Queue->Rear) {\r
123 LeaveCriticalSection (&Queue->Cs);\r
124 return EFI_NOT_READY;\r
125 }\r
126\r
127 CopyMem (Key, &Queue->Q[Queue->Front], sizeof (EFI_KEY_DATA));\r
128 Queue->Front = (Queue->Front + 1) % MAX_Q;\r
129\r
130 if (Key->Key.ScanCode == SCAN_NULL && Key->Key.UnicodeChar == CHAR_NULL) {\r
131 if (!Private->IsPartialKeySupport) {\r
132 //\r
133 // If partial keystrok is not enabled, don't return the partial keystroke.\r
134 //\r
135 LeaveCriticalSection (&Queue->Cs);\r
136 ZeroMem (Key, sizeof (EFI_KEY_DATA));\r
137 return EFI_NOT_READY;\r
138 }\r
139 }\r
140 LeaveCriticalSection (&Queue->Cs);\r
141 return EFI_SUCCESS;\r
142}\r
143\r
144\r
145/**\r
146 TODO: Add function description\r
147\r
148 @param Private TODO: add argument description\r
149\r
150 @retval EFI_NOT_READY TODO: Add description for return value\r
151 @retval EFI_SUCCESS TODO: Add description for return value\r
152\r
153**/\r
154EFI_STATUS\r
155GopPrivateCheckQ (\r
156 IN GOP_QUEUE_FIXED *Queue\r
157 )\r
158{\r
159 if (Queue->Front == Queue->Rear) {\r
160 return EFI_NOT_READY;\r
161 }\r
162\r
163 return EFI_SUCCESS;\r
164}\r
165\r
166/**\r
167 Initialize the key state.\r
168\r
169 @param Private The GOP_PRIVATE_DATA instance.\r
170 @param KeyState A pointer to receive the key state information.\r
171**/\r
172VOID\r
173InitializeKeyState (\r
174 IN GRAPHICS_PRIVATE_DATA *Private,\r
175 IN EFI_KEY_STATE *KeyState\r
176 )\r
177{\r
178 KeyState->KeyShiftState = EFI_SHIFT_STATE_VALID;\r
179 KeyState->KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
180\r
181 //\r
182 // Record Key shift state and toggle state\r
183 //\r
184 if (Private->LeftCtrl) {\r
185 KeyState->KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;\r
186 }\r
187 if (Private->RightCtrl) {\r
188 KeyState->KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;\r
189 }\r
190 if (Private->LeftAlt) {\r
191 KeyState->KeyShiftState |= EFI_LEFT_ALT_PRESSED;\r
192 }\r
193 if (Private->RightAlt) {\r
194 KeyState->KeyShiftState |= EFI_RIGHT_ALT_PRESSED;\r
195 }\r
196 if (Private->LeftShift) {\r
197 KeyState->KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;\r
198 }\r
199 if (Private->RightShift) {\r
200 KeyState->KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;\r
201 }\r
202 if (Private->LeftLogo) {\r
203 KeyState->KeyShiftState |= EFI_LEFT_LOGO_PRESSED;\r
204 }\r
205 if (Private->RightLogo) {\r
206 KeyState->KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;\r
207 }\r
208 if (Private->Menu) {\r
209 KeyState->KeyShiftState |= EFI_MENU_KEY_PRESSED;\r
210 }\r
211 if (Private->SysReq) {\r
212 KeyState->KeyShiftState |= EFI_SYS_REQ_PRESSED;\r
213 }\r
214 if (Private->CapsLock) {\r
215 KeyState->KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r
216 }\r
217 if (Private->NumLock) {\r
218 KeyState->KeyToggleState |= EFI_NUM_LOCK_ACTIVE;\r
219 }\r
220 if (Private->ScrollLock) {\r
221 KeyState->KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;\r
222 }\r
223 if (Private->IsPartialKeySupport) {\r
224 KeyState->KeyToggleState |= EFI_KEY_STATE_EXPOSED;\r
225 }\r
226}\r
227\r
228/**\r
229 TODO: Add function description\r
230\r
231 @param Private TODO: add argument description\r
232 @param Key TODO: add argument description\r
233\r
234 @retval EFI_NOT_READY TODO: Add description for return value\r
235 @retval EFI_SUCCESS TODO: Add description for return value\r
236\r
237**/\r
238EFI_STATUS\r
239GopPrivateAddKey (\r
240 IN GRAPHICS_PRIVATE_DATA *Private,\r
241 IN EFI_INPUT_KEY Key\r
242 )\r
243{\r
244 EFI_KEY_DATA KeyData;\r
245\r
246 KeyData.Key = Key;\r
247 InitializeKeyState (Private, &KeyData.KeyState);\r
248\r
249 //\r
250 // Convert Ctrl+[1-26] to Ctrl+[A-Z]\r
251 //\r
252 if ((Private->LeftCtrl || Private->RightCtrl) &&\r
253 (KeyData.Key.UnicodeChar >= 1) && (KeyData.Key.UnicodeChar <= 26)\r
254 ) {\r
255 if ((Private->LeftShift || Private->RightShift) == Private->CapsLock) {\r
256 KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar + L'a' - 1);\r
257 } else {\r
258 KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar + L'A' - 1);\r
259 }\r
260 }\r
261\r
262 //\r
263 // Unmask the Shift bit for printable char\r
264 //\r
265 if (((KeyData.Key.UnicodeChar >= L'a') && (KeyData.Key.UnicodeChar <= L'z')) ||\r
266 ((KeyData.Key.UnicodeChar >= L'A') && (KeyData.Key.UnicodeChar <= L'Z'))\r
267 ) {\r
268 KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);\r
269 }\r
270\r
271 GopPrivateAddQ (Private, &Private->QueueForRead, &KeyData);\r
272 if (Private->MakeRegisterdKeyCallback != NULL) {\r
273 Private->MakeRegisterdKeyCallback (Private->RegisterdKeyCallbackContext, &KeyData);\r
274 }\r
275\r
276 return EFI_SUCCESS;\r
277}\r
278\r
279\r
280EFI_STATUS\r
281EFIAPI\r
282WinNtWndCheckKey (\r
283 IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo\r
284 )\r
285{\r
286 GRAPHICS_PRIVATE_DATA *Private;\r
287\r
288 Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);\r
289\r
290 return GopPrivateCheckQ (&Private->QueueForRead);\r
291\r
292}\r
293EFI_STATUS\r
294EFIAPI\r
295WinNtWndGetKey (\r
296 IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r
297 IN EFI_KEY_DATA *KeyData\r
298 )\r
299/*++\r
300\r
301 Routine Description:\r
302 Reads the next keystroke from the input device. The WaitForKey Event can\r
303 be used to test for existance of a keystroke via WaitForEvent () call.\r
304\r
305 Arguments:\r
306 Private - The private structure of WinNt Gop device.\r
307 KeyData - A pointer to a buffer that is filled in with the keystroke\r
308 state data for the key that was pressed.\r
309\r
310 Returns:\r
311 EFI_SUCCESS - The keystroke information was returned.\r
312 EFI_NOT_READY - There was no keystroke data availiable.\r
313 EFI_DEVICE_ERROR - The keystroke information was not returned due to\r
314 hardware errors.\r
315 EFI_INVALID_PARAMETER - KeyData is NULL.\r
316\r
317--*/\r
318{\r
319 EFI_STATUS Status;\r
320 GRAPHICS_PRIVATE_DATA *Private;\r
321\r
322 Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);\r
323\r
324 ZeroMem (&KeyData->Key, sizeof (KeyData->Key));\r
325 InitializeKeyState (Private, &KeyData->KeyState);\r
326\r
327 Status = GopPrivateCheckQ (&Private->QueueForRead);\r
328 if (!EFI_ERROR (Status)) {\r
329 //\r
330 // If a Key press exists try and read it.\r
331 //\r
332 Status = GopPrivateDeleteQ (Private, &Private->QueueForRead, KeyData);\r
333 if (!EFI_ERROR (Status)) {\r
334 //\r
335 // If partial keystroke is not enabled, check whether it is value key. If not return\r
336 // EFI_NOT_READY.\r
337 //\r
338 if (!Private->IsPartialKeySupport) {\r
339 if (KeyData->Key.ScanCode == SCAN_NULL && KeyData->Key.UnicodeChar == CHAR_NULL) {\r
340 Status = EFI_NOT_READY;\r
341 }\r
342 }\r
343 }\r
344 }\r
345\r
346 return Status;\r
347\r
348}\r
349\r
350EFI_STATUS\r
351EFIAPI\r
352WinNtWndKeySetState (\r
353 IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r
354 IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
355 )\r
356{\r
357 GRAPHICS_PRIVATE_DATA *Private;\r
358\r
359 Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);\r
e3c96c39
RN
360 Private->ScrollLock = FALSE;\r
361 Private->NumLock = FALSE;\r
362 Private->CapsLock = FALSE;\r
363 Private->IsPartialKeySupport = FALSE;\r
364\r
365 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
366 Private->ScrollLock = TRUE;\r
367 }\r
368 if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {\r
369 Private->NumLock = TRUE;\r
370 }\r
371 if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
372 Private->CapsLock = TRUE;\r
373 }\r
374 if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) {\r
375 Private->IsPartialKeySupport = TRUE;\r
376 }\r
7a465451
RN
377 Private->KeyState.KeyToggleState = *KeyToggleState;\r
378 return EFI_SUCCESS;\r
379}\r
380\r
381\r
382EFI_STATUS\r
383EFIAPI\r
384WinNtWndRegisterKeyNotify (\r
385 IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r
386 IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeCallBack,\r
387 IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakCallBack,\r
388 IN VOID *Context\r
389 )\r
390{\r
391 GRAPHICS_PRIVATE_DATA *Private;\r
392\r
393 Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);\r
394\r
395 Private->MakeRegisterdKeyCallback = MakeCallBack;\r
396 Private->BreakRegisterdKeyCallback = BreakCallBack;\r
397 Private->RegisterdKeyCallbackContext = Context;\r
398\r
399 return EFI_SUCCESS;\r
400}\r
401\r
402EFI_STATUS\r
403EFIAPI\r
404WinNtWndCheckPointer (\r
405 IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo\r
406 )\r
407{\r
408 GRAPHICS_PRIVATE_DATA *Private;\r
409\r
410 Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);\r
411\r
109197ee
MH
412 if (!Private->PointerStateChanged) {\r
413 return EFI_NOT_READY;\r
414 }\r
7a465451 415\r
109197ee
MH
416 return EFI_SUCCESS;\r
417}\r
7a465451
RN
418\r
419EFI_STATUS\r
420EFIAPI\r
421WinNtWndGetPointerState (\r
422 IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r
423 IN EFI_SIMPLE_POINTER_STATE *State\r
424 )\r
425{\r
426 GRAPHICS_PRIVATE_DATA *Private;\r
427\r
428 Private = GRAPHICS_PRIVATE_DATA_FROM_THIS (GraphicsIo);\r
429\r
109197ee
MH
430 if (!Private->PointerStateChanged) {\r
431 return EFI_NOT_READY;\r
432 }\r
433\r
434 State->RelativeMovementX = Private->PointerState.RelativeMovementX;\r
435 State->RelativeMovementY = Private->PointerState.RelativeMovementY;\r
436 State->RelativeMovementZ = Private->PointerState.RelativeMovementZ;\r
437 State->LeftButton = Private->PointerState.LeftButton;\r
438 State->RightButton = Private->PointerState.RightButton;\r
439\r
440 Private->PointerState.RelativeMovementX = 0;\r
441 Private->PointerState.RelativeMovementY = 0;\r
442 Private->PointerState.RelativeMovementZ = 0;\r
443\r
444 Private->PointerStateChanged = FALSE;\r
445\r
446 return EFI_SUCCESS;\r
7a465451 447}\r