]>
Commit | Line | Data |
---|---|---|
79e4f2a5 RN |
1 | /*++ @file\r |
2 | \r | |
9e3ab94d | 3 | Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>\r |
79e4f2a5 RN |
4 | Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>\r |
5 | \r | |
e3ba31da | 6 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
79e4f2a5 RN |
7 | \r |
8 | **/\r | |
9 | \r | |
10 | #include "Host.h"\r | |
11 | \r | |
12 | #include <sys/ipc.h>\r | |
13 | #include <sys/shm.h>\r | |
14 | \r | |
15 | #include <X11/Xlib.h>\r | |
16 | #include <X11/Xutil.h>\r | |
17 | #include <X11/Xos.h>\r | |
18 | #include <X11/extensions/XShm.h>\r | |
19 | #include <X11/keysym.h>\r | |
20 | #include <X11/cursorfont.h>\r | |
21 | \r | |
22 | #define KEYSYM_LOWER 0\r | |
23 | #define KEYSYM_UPPER 1\r | |
24 | \r | |
79e4f2a5 | 25 | struct uga_drv_shift_mask {\r |
a550d468 MK |
26 | unsigned char shift;\r |
27 | unsigned char size;\r | |
28 | unsigned char csize;\r | |
79e4f2a5 RN |
29 | };\r |
30 | \r | |
a550d468 | 31 | #define NBR_KEYS 32\r |
79e4f2a5 | 32 | typedef struct {\r |
a550d468 | 33 | EMU_GRAPHICS_WINDOW_PROTOCOL GraphicsIo;\r |
79e4f2a5 | 34 | \r |
a550d468 MK |
35 | Display *display;\r |
36 | int screen; // values for window_size in main\r | |
37 | Window win;\r | |
38 | GC gc;\r | |
39 | Visual *visual;\r | |
79e4f2a5 | 40 | \r |
a550d468 MK |
41 | int depth;\r |
42 | unsigned int width;\r | |
43 | unsigned int height;\r | |
44 | unsigned int line_bytes;\r | |
45 | unsigned int pixel_shift;\r | |
46 | unsigned char *image_data;\r | |
79e4f2a5 | 47 | \r |
a550d468 | 48 | struct uga_drv_shift_mask r, g, b;\r |
79e4f2a5 | 49 | \r |
a550d468 MK |
50 | int use_shm;\r |
51 | XShmSegmentInfo xshm_info;\r | |
52 | XImage *image;\r | |
53 | char *Title;\r | |
79e4f2a5 | 54 | \r |
a550d468 MK |
55 | unsigned int key_rd;\r |
56 | unsigned int key_wr;\r | |
57 | unsigned int key_count;\r | |
58 | EFI_KEY_DATA keys[NBR_KEYS];\r | |
79e4f2a5 | 59 | \r |
a550d468 | 60 | EFI_KEY_STATE KeyState;\r |
79e4f2a5 RN |
61 | \r |
62 | EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeRegisterdKeyCallback;\r | |
63 | EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakRegisterdKeyCallback;\r | |
64 | VOID *RegisterdKeyCallbackContext;\r | |
65 | \r | |
a550d468 MK |
66 | int previous_x;\r |
67 | int previous_y;\r | |
68 | EFI_SIMPLE_POINTER_STATE pointer_state;\r | |
69 | int pointer_state_changed;\r | |
79e4f2a5 RN |
70 | } GRAPHICS_IO_PRIVATE;\r |
71 | \r | |
72 | void\r | |
a550d468 MK |
73 | HandleEvents (\r |
74 | IN GRAPHICS_IO_PRIVATE *Drv\r | |
79e4f2a5 RN |
75 | );\r |
76 | \r | |
77 | void\r | |
78 | fill_shift_mask (\r | |
a550d468 MK |
79 | IN struct uga_drv_shift_mask *sm,\r |
80 | IN unsigned long mask\r | |
79e4f2a5 RN |
81 | )\r |
82 | {\r | |
83 | sm->shift = 0;\r | |
a550d468 | 84 | sm->size = 0;\r |
79e4f2a5 RN |
85 | while ((mask & 1) == 0) {\r |
86 | mask >>= 1;\r | |
87 | sm->shift++;\r | |
88 | }\r | |
a550d468 | 89 | \r |
79e4f2a5 RN |
90 | while (mask & 1) {\r |
91 | sm->size++;\r | |
92 | mask >>= 1;\r | |
93 | }\r | |
a550d468 | 94 | \r |
79e4f2a5 RN |
95 | sm->csize = 8 - sm->size;\r |
96 | }\r | |
97 | \r | |
98 | int\r | |
99 | TryCreateShmImage (\r | |
a550d468 | 100 | IN GRAPHICS_IO_PRIVATE *Drv\r |
79e4f2a5 RN |
101 | )\r |
102 | {\r | |
103 | Drv->image = XShmCreateImage (\r | |
a550d468 MK |
104 | Drv->display,\r |
105 | Drv->visual,\r | |
106 | Drv->depth,\r | |
107 | ZPixmap,\r | |
108 | NULL,\r | |
109 | &Drv->xshm_info,\r | |
110 | Drv->width,\r | |
111 | Drv->height\r | |
79e4f2a5 RN |
112 | );\r |
113 | if (Drv->image == NULL) {\r | |
114 | return 0;\r | |
115 | }\r | |
116 | \r | |
117 | switch (Drv->image->bitmap_unit) {\r | |
a550d468 MK |
118 | case 32:\r |
119 | Drv->pixel_shift = 2;\r | |
120 | break;\r | |
121 | case 16:\r | |
122 | Drv->pixel_shift = 1;\r | |
123 | break;\r | |
124 | case 8:\r | |
125 | Drv->pixel_shift = 0;\r | |
126 | break;\r | |
79e4f2a5 RN |
127 | }\r |
128 | \r | |
129 | Drv->xshm_info.shmid = shmget (\r | |
a550d468 MK |
130 | IPC_PRIVATE,\r |
131 | Drv->image->bytes_per_line * Drv->image->height,\r | |
132 | IPC_CREAT | 0777\r | |
133 | );\r | |
79e4f2a5 | 134 | if (Drv->xshm_info.shmid < 0) {\r |
a550d468 | 135 | XDestroyImage (Drv->image);\r |
79e4f2a5 RN |
136 | return 0;\r |
137 | }\r | |
138 | \r | |
139 | Drv->image_data = shmat (Drv->xshm_info.shmid, NULL, 0);\r | |
a550d468 | 140 | if (!Drv->image_data) {\r |
79e4f2a5 | 141 | shmctl (Drv->xshm_info.shmid, IPC_RMID, NULL);\r |
a550d468 | 142 | XDestroyImage (Drv->image);\r |
79e4f2a5 RN |
143 | return 0;\r |
144 | }\r | |
145 | \r | |
a550d468 | 146 | #ifndef __APPLE__\r |
79e4f2a5 RN |
147 | //\r |
148 | // This closes shared memory in real time on OS X. Only closes after folks quit using\r | |
149 | // it on Linux.\r | |
150 | //\r | |
151 | shmctl (Drv->xshm_info.shmid, IPC_RMID, NULL);\r | |
a550d468 | 152 | #endif\r |
79e4f2a5 | 153 | \r |
a550d468 MK |
154 | Drv->xshm_info.shmaddr = (char *)Drv->image_data;\r |
155 | Drv->image->data = (char *)Drv->image_data;\r | |
79e4f2a5 RN |
156 | \r |
157 | if (!XShmAttach (Drv->display, &Drv->xshm_info)) {\r | |
158 | shmdt (Drv->image_data);\r | |
a550d468 | 159 | XDestroyImage (Drv->image);\r |
79e4f2a5 RN |
160 | return 0;\r |
161 | }\r | |
a550d468 | 162 | \r |
79e4f2a5 RN |
163 | return 1;\r |
164 | }\r | |
165 | \r | |
79e4f2a5 RN |
166 | EFI_STATUS\r |
167 | X11Size (\r | |
168 | IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r | |
169 | IN UINT32 Width,\r | |
170 | IN UINT32 Height\r | |
171 | )\r | |
172 | {\r | |
a550d468 MK |
173 | GRAPHICS_IO_PRIVATE *Drv;\r |
174 | XSizeHints size_hints;\r | |
79e4f2a5 RN |
175 | \r |
176 | // Destroy current buffer if created.\r | |
177 | Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r | |
178 | if (Drv->image != NULL) {\r | |
179 | // Before destroy buffer, need to make sure the buffer available for access.\r | |
180 | XDestroyImage (Drv->image);\r | |
181 | \r | |
182 | if (Drv->use_shm) {\r | |
183 | shmdt (Drv->image_data);\r | |
184 | }\r | |
185 | \r | |
186 | Drv->image_data = NULL;\r | |
a550d468 | 187 | Drv->image = NULL;\r |
79e4f2a5 RN |
188 | }\r |
189 | \r | |
a550d468 | 190 | Drv->width = Width;\r |
79e4f2a5 RN |
191 | Drv->height = Height;\r |
192 | XResizeWindow (Drv->display, Drv->win, Width, Height);\r | |
193 | \r | |
194 | // Allocate image.\r | |
a550d468 | 195 | if (XShmQueryExtension (Drv->display) && TryCreateShmImage (Drv)) {\r |
79e4f2a5 RN |
196 | Drv->use_shm = 1;\r |
197 | } else {\r | |
198 | Drv->use_shm = 0;\r | |
199 | if (Drv->depth > 16) {\r | |
200 | Drv->pixel_shift = 2;\r | |
201 | } else if (Drv->depth > 8) {\r | |
202 | Drv->pixel_shift = 1;\r | |
203 | } else {\r | |
204 | Drv->pixel_shift = 0;\r | |
205 | }\r | |
206 | \r | |
207 | Drv->image_data = malloc ((Drv->width * Drv->height) << Drv->pixel_shift);\r | |
a550d468 MK |
208 | Drv->image = XCreateImage (\r |
209 | Drv->display,\r | |
210 | Drv->visual,\r | |
211 | Drv->depth,\r | |
212 | ZPixmap,\r | |
213 | 0,\r | |
214 | (char *)Drv->image_data,\r | |
215 | Drv->width,\r | |
216 | Drv->height,\r | |
217 | 8 << Drv->pixel_shift,\r | |
218 | 0\r | |
219 | );\r | |
79e4f2a5 RN |
220 | }\r |
221 | \r | |
222 | Drv->line_bytes = Drv->image->bytes_per_line;\r | |
223 | \r | |
224 | fill_shift_mask (&Drv->r, Drv->image->red_mask);\r | |
225 | fill_shift_mask (&Drv->g, Drv->image->green_mask);\r | |
226 | fill_shift_mask (&Drv->b, Drv->image->blue_mask);\r | |
227 | \r | |
228 | // Set WM hints.\r | |
a550d468 MK |
229 | size_hints.flags = PSize | PMinSize | PMaxSize;\r |
230 | size_hints.min_width = size_hints.max_width = size_hints.base_width = Width;\r | |
79e4f2a5 RN |
231 | size_hints.min_height = size_hints.max_height = size_hints.base_height = Height;\r |
232 | XSetWMNormalHints (Drv->display, Drv->win, &size_hints);\r | |
233 | \r | |
234 | XMapWindow (Drv->display, Drv->win);\r | |
235 | HandleEvents (Drv);\r | |
236 | return EFI_SUCCESS;\r | |
237 | }\r | |
238 | \r | |
239 | void\r | |
240 | handleKeyEvent (\r | |
a550d468 MK |
241 | IN GRAPHICS_IO_PRIVATE *Drv,\r |
242 | IN XEvent *ev,\r | |
243 | IN BOOLEAN Make\r | |
79e4f2a5 RN |
244 | )\r |
245 | {\r | |
246 | KeySym *KeySym;\r | |
247 | EFI_KEY_DATA KeyData;\r | |
248 | int KeySymArraySize;\r | |
249 | \r | |
250 | if (Make) {\r | |
251 | if (Drv->key_count == NBR_KEYS) {\r | |
252 | return;\r | |
253 | }\r | |
254 | }\r | |
255 | \r | |
256 | // keycode is a physical key on the keyboard\r | |
257 | // KeySym is a mapping of a physical key\r | |
258 | // KeyboardMapping is the array of KeySym for a given keycode. key, shifted key, option key, command key, ...\r | |
259 | //\r | |
260 | // Returns an array of KeySymArraySize of KeySym for the keycode. [0] is lower case, [1] is upper case,\r | |
261 | // [2] and [3] are based on option and command modifiers. The problem we have is command V\r | |
262 | // could be mapped to a crazy Unicode character so the old scheme of returning a string.\r | |
263 | //\r | |
264 | KeySym = XGetKeyboardMapping (Drv->display, ev->xkey.keycode, 1, &KeySymArraySize);\r | |
265 | \r | |
a550d468 MK |
266 | KeyData.Key.ScanCode = 0;\r |
267 | KeyData.Key.UnicodeChar = 0;\r | |
79e4f2a5 RN |
268 | KeyData.KeyState.KeyShiftState = 0;\r |
269 | \r | |
270 | //\r | |
271 | // Skipping EFI_SCROLL_LOCK_ACTIVE & EFI_NUM_LOCK_ACTIVE since they are not on Macs\r | |
272 | //\r | |
273 | if ((ev->xkey.state & LockMask) == 0) {\r | |
274 | Drv->KeyState.KeyToggleState &= ~EFI_CAPS_LOCK_ACTIVE;\r | |
275 | } else {\r | |
276 | if (Make) {\r | |
277 | Drv->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r | |
278 | }\r | |
279 | }\r | |
280 | \r | |
281 | // Skipping EFI_MENU_KEY_PRESSED and EFI_SYS_REQ_PRESSED\r | |
282 | \r | |
283 | switch (*KeySym) {\r | |
a550d468 MK |
284 | case XK_Control_R:\r |
285 | if (Make) {\r | |
286 | Drv->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;\r | |
287 | } else {\r | |
288 | Drv->KeyState.KeyShiftState &= ~EFI_RIGHT_CONTROL_PRESSED;\r | |
289 | }\r | |
79e4f2a5 | 290 | \r |
a550d468 MK |
291 | break;\r |
292 | case XK_Control_L:\r | |
293 | if (Make) {\r | |
294 | Drv->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;\r | |
295 | } else {\r | |
296 | Drv->KeyState.KeyShiftState &= ~EFI_LEFT_CONTROL_PRESSED;\r | |
297 | }\r | |
79e4f2a5 | 298 | \r |
a550d468 | 299 | break;\r |
79e4f2a5 | 300 | \r |
a550d468 MK |
301 | case XK_Shift_R:\r |
302 | if (Make) {\r | |
303 | Drv->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;\r | |
304 | } else {\r | |
305 | Drv->KeyState.KeyShiftState &= ~EFI_RIGHT_SHIFT_PRESSED;\r | |
306 | }\r | |
79e4f2a5 | 307 | \r |
a550d468 MK |
308 | break;\r |
309 | case XK_Shift_L:\r | |
310 | if (Make) {\r | |
311 | Drv->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;\r | |
312 | } else {\r | |
313 | Drv->KeyState.KeyShiftState &= ~EFI_LEFT_SHIFT_PRESSED;\r | |
314 | }\r | |
79e4f2a5 | 315 | \r |
a550d468 | 316 | break;\r |
79e4f2a5 | 317 | \r |
a550d468 MK |
318 | case XK_Mode_switch:\r |
319 | if (Make) {\r | |
320 | Drv->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;\r | |
321 | } else {\r | |
322 | Drv->KeyState.KeyShiftState &= ~EFI_LEFT_ALT_PRESSED;\r | |
323 | }\r | |
79e4f2a5 | 324 | \r |
a550d468 | 325 | break;\r |
79e4f2a5 | 326 | \r |
a550d468 MK |
327 | case XK_Meta_R:\r |
328 | if (Make) {\r | |
329 | Drv->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;\r | |
330 | } else {\r | |
331 | Drv->KeyState.KeyShiftState &= ~EFI_RIGHT_LOGO_PRESSED;\r | |
332 | }\r | |
79e4f2a5 | 333 | \r |
a550d468 MK |
334 | break;\r |
335 | case XK_Meta_L:\r | |
336 | if (Make) {\r | |
337 | Drv->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;\r | |
338 | } else {\r | |
339 | Drv->KeyState.KeyShiftState &= ~EFI_LEFT_LOGO_PRESSED;\r | |
340 | }\r | |
79e4f2a5 | 341 | \r |
a550d468 MK |
342 | break;\r |
343 | \r | |
344 | case XK_KP_Home:\r | |
345 | case XK_Home: KeyData.Key.ScanCode = SCAN_HOME;\r | |
346 | break;\r | |
347 | \r | |
348 | case XK_KP_End:\r | |
349 | case XK_End: KeyData.Key.ScanCode = SCAN_END;\r | |
350 | break;\r | |
351 | \r | |
352 | case XK_KP_Left:\r | |
353 | case XK_Left: KeyData.Key.ScanCode = SCAN_LEFT;\r | |
354 | break;\r | |
355 | \r | |
356 | case XK_KP_Right:\r | |
357 | case XK_Right: KeyData.Key.ScanCode = SCAN_RIGHT;\r | |
358 | break;\r | |
359 | \r | |
360 | case XK_KP_Up:\r | |
361 | case XK_Up: KeyData.Key.ScanCode = SCAN_UP;\r | |
362 | break;\r | |
363 | \r | |
364 | case XK_KP_Down:\r | |
365 | case XK_Down: KeyData.Key.ScanCode = SCAN_DOWN;\r | |
366 | break;\r | |
367 | \r | |
368 | case XK_KP_Delete:\r | |
369 | case XK_Delete: KeyData.Key.ScanCode = SCAN_DELETE;\r | |
370 | break;\r | |
371 | \r | |
372 | case XK_KP_Insert:\r | |
373 | case XK_Insert: KeyData.Key.ScanCode = SCAN_INSERT;\r | |
374 | break;\r | |
375 | \r | |
376 | case XK_KP_Page_Up:\r | |
377 | case XK_Page_Up: KeyData.Key.ScanCode = SCAN_PAGE_UP;\r | |
378 | break;\r | |
379 | \r | |
380 | case XK_KP_Page_Down:\r | |
381 | case XK_Page_Down: KeyData.Key.ScanCode = SCAN_PAGE_DOWN;\r | |
382 | break;\r | |
383 | \r | |
384 | case XK_Escape: KeyData.Key.ScanCode = SCAN_ESC;\r | |
385 | break;\r | |
386 | \r | |
387 | case XK_Pause: KeyData.Key.ScanCode = SCAN_PAUSE;\r | |
388 | break;\r | |
389 | \r | |
390 | case XK_KP_F1:\r | |
391 | case XK_F1: KeyData.Key.ScanCode = SCAN_F1;\r | |
392 | break;\r | |
393 | \r | |
394 | case XK_KP_F2:\r | |
395 | case XK_F2: KeyData.Key.ScanCode = SCAN_F2;\r | |
396 | break;\r | |
397 | \r | |
398 | case XK_KP_F3:\r | |
399 | case XK_F3: KeyData.Key.ScanCode = SCAN_F3;\r | |
400 | break;\r | |
401 | \r | |
402 | case XK_KP_F4:\r | |
403 | case XK_F4: KeyData.Key.ScanCode = SCAN_F4;\r | |
404 | break;\r | |
405 | \r | |
406 | case XK_F5: KeyData.Key.ScanCode = SCAN_F5;\r | |
407 | break;\r | |
408 | case XK_F6: KeyData.Key.ScanCode = SCAN_F6;\r | |
409 | break;\r | |
410 | case XK_F7: KeyData.Key.ScanCode = SCAN_F7;\r | |
411 | break;\r | |
412 | \r | |
413 | // Don't map into X11 by default on a Mac\r | |
414 | // System Preferences->Keyboard->Keyboard Shortcuts can be configured\r | |
415 | // to not use higher function keys as shortcuts and the will show up\r | |
416 | // in X11.\r | |
417 | case XK_F8: KeyData.Key.ScanCode = SCAN_F8;\r | |
418 | break;\r | |
419 | case XK_F9: KeyData.Key.ScanCode = SCAN_F9;\r | |
420 | break;\r | |
421 | case XK_F10: KeyData.Key.ScanCode = SCAN_F10;\r | |
422 | break;\r | |
423 | \r | |
424 | case XK_F11: KeyData.Key.ScanCode = SCAN_F11;\r | |
425 | break;\r | |
426 | case XK_F12: KeyData.Key.ScanCode = SCAN_F12;\r | |
427 | break;\r | |
428 | \r | |
429 | case XK_F13: KeyData.Key.ScanCode = SCAN_F13;\r | |
430 | break;\r | |
431 | case XK_F14: KeyData.Key.ScanCode = SCAN_F14;\r | |
432 | break;\r | |
433 | case XK_F15: KeyData.Key.ScanCode = SCAN_F15;\r | |
434 | break;\r | |
435 | case XK_F16: KeyData.Key.ScanCode = SCAN_F16;\r | |
436 | break;\r | |
437 | case XK_F17: KeyData.Key.ScanCode = SCAN_F17;\r | |
438 | break;\r | |
439 | case XK_F18: KeyData.Key.ScanCode = SCAN_F18;\r | |
440 | break;\r | |
441 | case XK_F19: KeyData.Key.ScanCode = SCAN_F19;\r | |
442 | break;\r | |
443 | case XK_F20: KeyData.Key.ScanCode = SCAN_F20;\r | |
444 | break;\r | |
445 | case XK_F21: KeyData.Key.ScanCode = SCAN_F21;\r | |
446 | break;\r | |
447 | case XK_F22: KeyData.Key.ScanCode = SCAN_F22;\r | |
448 | break;\r | |
449 | case XK_F23: KeyData.Key.ScanCode = SCAN_F23;\r | |
450 | break;\r | |
451 | case XK_F24: KeyData.Key.ScanCode = SCAN_F24;\r | |
452 | break;\r | |
453 | \r | |
454 | // No mapping in X11\r | |
455 | // case XK_: KeyData.Key.ScanCode = SCAN_MUTE; break;\r | |
456 | // case XK_: KeyData.Key.ScanCode = SCAN_VOLUME_UP; break;\r | |
457 | // case XK_: KeyData.Key.ScanCode = SCAN_VOLUME_DOWN; break;\r | |
458 | // case XK_: KeyData.Key.ScanCode = SCAN_BRIGHTNESS_UP; break;\r | |
459 | // case XK_: KeyData.Key.ScanCode = SCAN_BRIGHTNESS_DOWN; break;\r | |
460 | // case XK_: KeyData.Key.ScanCode = SCAN_SUSPEND; break;\r | |
461 | // case XK_: KeyData.Key.ScanCode = SCAN_HIBERNATE; break;\r | |
462 | // case XK_: KeyData.Key.ScanCode = SCAN_TOGGLE_DISPLAY; break;\r | |
463 | // case XK_: KeyData.Key.ScanCode = SCAN_RECOVERY; break;\r | |
464 | // case XK_: KeyData.Key.ScanCode = SCAN_EJECT; break;\r | |
465 | \r | |
466 | case XK_BackSpace: KeyData.Key.UnicodeChar = 0x0008;\r | |
467 | break;\r | |
468 | \r | |
469 | case XK_KP_Tab:\r | |
470 | case XK_Tab: KeyData.Key.UnicodeChar = 0x0009;\r | |
471 | break;\r | |
472 | \r | |
473 | case XK_Linefeed: KeyData.Key.UnicodeChar = 0x000a;\r | |
474 | break;\r | |
475 | \r | |
476 | case XK_KP_Enter:\r | |
477 | case XK_Return: KeyData.Key.UnicodeChar = 0x000d;\r | |
478 | break;\r | |
479 | \r | |
480 | case XK_KP_Equal: KeyData.Key.UnicodeChar = L'=';\r | |
481 | break;\r | |
482 | case XK_KP_Multiply: KeyData.Key.UnicodeChar = L'*';\r | |
483 | break;\r | |
484 | case XK_KP_Add: KeyData.Key.UnicodeChar = L'+';\r | |
485 | break;\r | |
486 | case XK_KP_Separator: KeyData.Key.UnicodeChar = L'~';\r | |
487 | break;\r | |
488 | case XK_KP_Subtract: KeyData.Key.UnicodeChar = L'-';\r | |
489 | break;\r | |
490 | case XK_KP_Decimal: KeyData.Key.UnicodeChar = L'.';\r | |
491 | break;\r | |
492 | case XK_KP_Divide: KeyData.Key.UnicodeChar = L'/';\r | |
493 | break;\r | |
494 | \r | |
495 | case XK_KP_0: KeyData.Key.UnicodeChar = L'0';\r | |
496 | break;\r | |
497 | case XK_KP_1: KeyData.Key.UnicodeChar = L'1';\r | |
498 | break;\r | |
499 | case XK_KP_2: KeyData.Key.UnicodeChar = L'2';\r | |
500 | break;\r | |
501 | case XK_KP_3: KeyData.Key.UnicodeChar = L'3';\r | |
502 | break;\r | |
503 | case XK_KP_4: KeyData.Key.UnicodeChar = L'4';\r | |
504 | break;\r | |
505 | case XK_KP_5: KeyData.Key.UnicodeChar = L'5';\r | |
506 | break;\r | |
507 | case XK_KP_6: KeyData.Key.UnicodeChar = L'6';\r | |
508 | break;\r | |
509 | case XK_KP_7: KeyData.Key.UnicodeChar = L'7';\r | |
510 | break;\r | |
511 | case XK_KP_8: KeyData.Key.UnicodeChar = L'8';\r | |
512 | break;\r | |
513 | case XK_KP_9: KeyData.Key.UnicodeChar = L'9';\r | |
514 | break;\r | |
515 | \r | |
516 | default:\r | |
517 | ;\r | |
79e4f2a5 RN |
518 | }\r |
519 | \r | |
520 | // The global state is our state\r | |
a550d468 | 521 | KeyData.KeyState.KeyShiftState = Drv->KeyState.KeyShiftState;\r |
79e4f2a5 RN |
522 | KeyData.KeyState.KeyToggleState = Drv->KeyState.KeyToggleState;\r |
523 | \r | |
524 | if (*KeySym < XK_BackSpace) {\r | |
525 | if (((Drv->KeyState.KeyShiftState & (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED)) != 0) ||\r | |
a550d468 MK |
526 | ((Drv->KeyState.KeyToggleState & EFI_CAPS_LOCK_ACTIVE) != 0))\r |
527 | {\r | |
79e4f2a5 RN |
528 | KeyData.Key.UnicodeChar = (CHAR16)KeySym[KEYSYM_UPPER];\r |
529 | \r | |
530 | // Per UEFI spec since we converted the Unicode clear the shift bits we pass up\r | |
531 | KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);\r | |
532 | } else {\r | |
533 | KeyData.Key.UnicodeChar = (CHAR16)KeySym[KEYSYM_LOWER];\r | |
534 | }\r | |
535 | } else {\r | |
536 | // XK_BackSpace is the start of XK_MISCELLANY. These are the XK_? keys we process in this file\r | |
79e4f2a5 RN |
537 | }\r |
538 | \r | |
539 | if (Make) {\r | |
540 | memcpy (&Drv->keys[Drv->key_wr], &KeyData, sizeof (EFI_KEY_DATA));\r | |
541 | Drv->key_wr = (Drv->key_wr + 1) % NBR_KEYS;\r | |
542 | Drv->key_count++;\r | |
543 | if (Drv->MakeRegisterdKeyCallback != NULL) {\r | |
a550d468 | 544 | ReverseGasketUint64Uint64 (Drv->MakeRegisterdKeyCallback, Drv->RegisterdKeyCallbackContext, &KeyData);\r |
79e4f2a5 RN |
545 | }\r |
546 | } else {\r | |
547 | if (Drv->BreakRegisterdKeyCallback != NULL) {\r | |
a550d468 | 548 | ReverseGasketUint64Uint64 (Drv->BreakRegisterdKeyCallback, Drv->RegisterdKeyCallbackContext, &KeyData);\r |
79e4f2a5 RN |
549 | }\r |
550 | }\r | |
551 | }\r | |
552 | \r | |
79e4f2a5 | 553 | void\r |
a550d468 MK |
554 | handleMouseMoved (\r |
555 | IN GRAPHICS_IO_PRIVATE *Drv,\r | |
556 | IN XEvent *ev\r | |
79e4f2a5 RN |
557 | )\r |
558 | {\r | |
559 | if (ev->xmotion.x != Drv->previous_x) {\r | |
a550d468 MK |
560 | Drv->pointer_state.RelativeMovementX += (ev->xmotion.x - Drv->previous_x);\r |
561 | Drv->previous_x = ev->xmotion.x;\r | |
562 | Drv->pointer_state_changed = 1;\r | |
79e4f2a5 RN |
563 | }\r |
564 | \r | |
565 | if (ev->xmotion.y != Drv->previous_y) {\r | |
a550d468 MK |
566 | Drv->pointer_state.RelativeMovementY += (ev->xmotion.y - Drv->previous_y);\r |
567 | Drv->previous_y = ev->xmotion.y;\r | |
568 | Drv->pointer_state_changed = 1;\r | |
79e4f2a5 RN |
569 | }\r |
570 | \r | |
571 | Drv->pointer_state.RelativeMovementZ = 0;\r | |
572 | }\r | |
573 | \r | |
574 | void\r | |
575 | handleMouseDown (\r | |
a550d468 MK |
576 | IN GRAPHICS_IO_PRIVATE *Drv,\r |
577 | IN XEvent *ev,\r | |
578 | IN BOOLEAN Pressed\r | |
79e4f2a5 RN |
579 | )\r |
580 | {\r | |
581 | if (ev->xbutton.button == Button1) {\r | |
a550d468 | 582 | Drv->pointer_state_changed = (Drv->pointer_state.LeftButton != Pressed);\r |
79e4f2a5 RN |
583 | Drv->pointer_state.LeftButton = Pressed;\r |
584 | }\r | |
a550d468 | 585 | \r |
79e4f2a5 | 586 | if ( ev->xbutton.button == Button2 ) {\r |
a550d468 | 587 | Drv->pointer_state_changed = (Drv->pointer_state.RightButton != Pressed);\r |
79e4f2a5 RN |
588 | Drv->pointer_state.RightButton = Pressed;\r |
589 | }\r | |
590 | }\r | |
591 | \r | |
592 | void\r | |
593 | Redraw (\r | |
a550d468 MK |
594 | IN GRAPHICS_IO_PRIVATE *Drv,\r |
595 | IN UINTN X,\r | |
596 | IN UINTN Y,\r | |
597 | IN UINTN Width,\r | |
598 | IN UINTN Height\r | |
79e4f2a5 RN |
599 | )\r |
600 | {\r | |
601 | if (Drv->use_shm) {\r | |
602 | XShmPutImage (\r | |
a550d468 MK |
603 | Drv->display,\r |
604 | Drv->win,\r | |
605 | Drv->gc,\r | |
606 | Drv->image,\r | |
607 | X,\r | |
608 | Y,\r | |
609 | X,\r | |
610 | Y,\r | |
611 | Width,\r | |
612 | Height,\r | |
613 | False\r | |
79e4f2a5 RN |
614 | );\r |
615 | } else {\r | |
616 | XPutImage (\r | |
a550d468 MK |
617 | Drv->display,\r |
618 | Drv->win,\r | |
619 | Drv->gc,\r | |
620 | Drv->image,\r | |
621 | X,\r | |
622 | Y,\r | |
623 | X,\r | |
624 | Y,\r | |
625 | Width,\r | |
626 | Height\r | |
79e4f2a5 RN |
627 | );\r |
628 | }\r | |
a550d468 MK |
629 | \r |
630 | XFlush (Drv->display);\r | |
79e4f2a5 RN |
631 | }\r |
632 | \r | |
633 | void\r | |
a550d468 MK |
634 | HandleEvent (\r |
635 | GRAPHICS_IO_PRIVATE *Drv,\r | |
636 | XEvent *ev\r | |
637 | )\r | |
79e4f2a5 RN |
638 | {\r |
639 | switch (ev->type) {\r | |
a550d468 MK |
640 | case Expose:\r |
641 | Redraw (\r | |
642 | Drv,\r | |
643 | ev->xexpose.x,\r | |
644 | ev->xexpose.y,\r | |
645 | ev->xexpose.width,\r | |
646 | ev->xexpose.height\r | |
647 | );\r | |
648 | break;\r | |
649 | case GraphicsExpose:\r | |
650 | Redraw (\r | |
651 | Drv,\r | |
652 | ev->xgraphicsexpose.x,\r | |
653 | ev->xgraphicsexpose.y,\r | |
654 | ev->xgraphicsexpose.width,\r | |
655 | ev->xgraphicsexpose.height\r | |
656 | );\r | |
657 | break;\r | |
658 | case KeyPress:\r | |
659 | handleKeyEvent (Drv, ev, TRUE);\r | |
660 | break;\r | |
661 | case KeyRelease:\r | |
662 | handleKeyEvent (Drv, ev, FALSE);\r | |
663 | break;\r | |
664 | case MappingNotify:\r | |
665 | XRefreshKeyboardMapping (&ev->xmapping);\r | |
666 | break;\r | |
667 | case MotionNotify:\r | |
668 | handleMouseMoved (Drv, ev);\r | |
669 | break;\r | |
670 | case ButtonPress:\r | |
671 | handleMouseDown (Drv, ev, TRUE);\r | |
672 | break;\r | |
673 | case ButtonRelease:\r | |
674 | handleMouseDown (Drv, ev, FALSE);\r | |
675 | break;\r | |
676 | #if 0\r | |
677 | case DestroyNotify:\r | |
678 | XCloseDisplay (Drv->display);\r | |
679 | exit (1);\r | |
680 | break;\r | |
681 | #endif\r | |
682 | case NoExpose:\r | |
683 | default:\r | |
684 | break;\r | |
79e4f2a5 RN |
685 | }\r |
686 | }\r | |
687 | \r | |
688 | void\r | |
689 | HandleEvents (\r | |
a550d468 | 690 | IN GRAPHICS_IO_PRIVATE *Drv\r |
79e4f2a5 RN |
691 | )\r |
692 | {\r | |
a550d468 | 693 | XEvent ev;\r |
79e4f2a5 RN |
694 | \r |
695 | while (XPending (Drv->display) != 0) {\r | |
696 | XNextEvent (Drv->display, &ev);\r | |
697 | HandleEvent (Drv, &ev);\r | |
698 | }\r | |
699 | }\r | |
700 | \r | |
701 | unsigned long\r | |
702 | X11PixelToColor (\r | |
a550d468 MK |
703 | IN GRAPHICS_IO_PRIVATE *Drv,\r |
704 | IN EFI_UGA_PIXEL pixel\r | |
79e4f2a5 RN |
705 | )\r |
706 | {\r | |
707 | return ((pixel.Red >> Drv->r.csize) << Drv->r.shift)\r | |
a550d468 MK |
708 | | ((pixel.Green >> Drv->g.csize) << Drv->g.shift)\r |
709 | | ((pixel.Blue >> Drv->b.csize) << Drv->b.shift);\r | |
79e4f2a5 RN |
710 | }\r |
711 | \r | |
712 | EFI_UGA_PIXEL\r | |
713 | X11ColorToPixel (\r | |
a550d468 MK |
714 | IN GRAPHICS_IO_PRIVATE *Drv,\r |
715 | IN unsigned long val\r | |
79e4f2a5 RN |
716 | )\r |
717 | {\r | |
a550d468 | 718 | EFI_UGA_PIXEL Pixel;\r |
79e4f2a5 RN |
719 | \r |
720 | memset (&Pixel, 0, sizeof (EFI_UGA_PIXEL));\r | |
721 | \r | |
722 | // Truncation not an issue since X11 and EFI are both using 8 bits per color\r | |
a550d468 | 723 | Pixel.Red = (val >> Drv->r.shift) << Drv->r.csize;\r |
79e4f2a5 | 724 | Pixel.Green = (val >> Drv->g.shift) << Drv->g.csize;\r |
a550d468 | 725 | Pixel.Blue = (val >> Drv->b.shift) << Drv->b.csize;\r |
79e4f2a5 RN |
726 | \r |
727 | return Pixel;\r | |
728 | }\r | |
729 | \r | |
79e4f2a5 RN |
730 | EFI_STATUS\r |
731 | X11CheckKey (\r | |
a550d468 | 732 | IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo\r |
79e4f2a5 RN |
733 | )\r |
734 | {\r | |
735 | GRAPHICS_IO_PRIVATE *Drv;\r | |
736 | \r | |
737 | Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r | |
738 | \r | |
739 | HandleEvents (Drv);\r | |
740 | \r | |
741 | if (Drv->key_count != 0) {\r | |
742 | return EFI_SUCCESS;\r | |
743 | }\r | |
744 | \r | |
745 | return EFI_NOT_READY;\r | |
746 | }\r | |
747 | \r | |
748 | EFI_STATUS\r | |
749 | X11GetKey (\r | |
750 | IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r | |
751 | IN EFI_KEY_DATA *KeyData\r | |
752 | )\r | |
753 | {\r | |
a550d468 MK |
754 | EFI_STATUS EfiStatus;\r |
755 | GRAPHICS_IO_PRIVATE *Drv;\r | |
79e4f2a5 RN |
756 | \r |
757 | Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r | |
758 | \r | |
759 | EfiStatus = X11CheckKey (GraphicsIo);\r | |
760 | if (EFI_ERROR (EfiStatus)) {\r | |
761 | return EfiStatus;\r | |
762 | }\r | |
763 | \r | |
764 | CopyMem (KeyData, &Drv->keys[Drv->key_rd], sizeof (EFI_KEY_DATA));\r | |
765 | Drv->key_rd = (Drv->key_rd + 1) % NBR_KEYS;\r | |
766 | Drv->key_count--;\r | |
767 | \r | |
768 | return EFI_SUCCESS;\r | |
769 | }\r | |
770 | \r | |
79e4f2a5 RN |
771 | EFI_STATUS\r |
772 | X11KeySetState (\r | |
a550d468 MK |
773 | IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r |
774 | IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r | |
79e4f2a5 RN |
775 | )\r |
776 | {\r | |
777 | GRAPHICS_IO_PRIVATE *Drv;\r | |
778 | \r | |
779 | Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r | |
780 | \r | |
781 | if (*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) {\r | |
782 | if ((Drv->KeyState.KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == 0) {\r | |
783 | //\r | |
784 | // We could create an XKeyEvent and send a XK_Caps_Lock to\r | |
785 | // the UGA/GOP Window\r | |
786 | //\r | |
787 | }\r | |
788 | }\r | |
789 | \r | |
790 | Drv->KeyState.KeyToggleState = *KeyToggleState;\r | |
791 | return EFI_SUCCESS;\r | |
792 | }\r | |
793 | \r | |
79e4f2a5 RN |
794 | EFI_STATUS\r |
795 | X11RegisterKeyNotify (\r | |
a550d468 MK |
796 | IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r |
797 | IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeCallBack,\r | |
798 | IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakCallBack,\r | |
799 | IN VOID *Context\r | |
79e4f2a5 RN |
800 | )\r |
801 | {\r | |
802 | GRAPHICS_IO_PRIVATE *Drv;\r | |
803 | \r | |
804 | Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r | |
805 | \r | |
806 | Drv->MakeRegisterdKeyCallback = MakeCallBack;\r | |
807 | Drv->BreakRegisterdKeyCallback = BreakCallBack;\r | |
808 | Drv->RegisterdKeyCallbackContext = Context;\r | |
809 | \r | |
810 | return EFI_SUCCESS;\r | |
811 | }\r | |
812 | \r | |
79e4f2a5 RN |
813 | EFI_STATUS\r |
814 | X11Blt (\r | |
a550d468 MK |
815 | IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r |
816 | IN EFI_UGA_PIXEL *BltBuffer OPTIONAL,\r | |
817 | IN EFI_UGA_BLT_OPERATION BltOperation,\r | |
818 | IN EMU_GRAPHICS_WINDOWS__BLT_ARGS *Args\r | |
79e4f2a5 RN |
819 | )\r |
820 | {\r | |
a550d468 MK |
821 | GRAPHICS_IO_PRIVATE *Private;\r |
822 | UINTN DstY;\r | |
823 | UINTN SrcY;\r | |
824 | UINTN DstX;\r | |
825 | UINTN SrcX;\r | |
826 | UINTN Index;\r | |
827 | EFI_UGA_PIXEL *Blt;\r | |
828 | UINT8 *Dst;\r | |
829 | UINT8 *Src;\r | |
830 | UINTN Nbr;\r | |
831 | unsigned long Color;\r | |
832 | XEvent ev;\r | |
79e4f2a5 RN |
833 | \r |
834 | Private = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r | |
835 | \r | |
79e4f2a5 RN |
836 | //\r |
837 | // Check bounds\r | |
838 | //\r | |
a550d468 MK |
839 | if ( (BltOperation == EfiUgaVideoToBltBuffer)\r |
840 | || (BltOperation == EfiUgaVideoToVideo))\r | |
841 | {\r | |
79e4f2a5 RN |
842 | //\r |
843 | // Source is Video.\r | |
844 | //\r | |
845 | if (Args->SourceY + Args->Height > Private->height) {\r | |
846 | return EFI_INVALID_PARAMETER;\r | |
847 | }\r | |
848 | \r | |
849 | if (Args->SourceX + Args->Width > Private->width) {\r | |
850 | return EFI_INVALID_PARAMETER;\r | |
851 | }\r | |
852 | }\r | |
853 | \r | |
a550d468 MK |
854 | if ( (BltOperation == EfiUgaBltBufferToVideo)\r |
855 | || (BltOperation == EfiUgaVideoToVideo)\r | |
856 | || (BltOperation == EfiUgaVideoFill))\r | |
857 | {\r | |
79e4f2a5 RN |
858 | //\r |
859 | // Destination is Video\r | |
860 | //\r | |
861 | if (Args->DestinationY + Args->Height > Private->height) {\r | |
862 | return EFI_INVALID_PARAMETER;\r | |
863 | }\r | |
864 | \r | |
865 | if (Args->DestinationX + Args->Width > Private->width) {\r | |
866 | return EFI_INVALID_PARAMETER;\r | |
867 | }\r | |
868 | }\r | |
869 | \r | |
870 | switch (BltOperation) {\r | |
a550d468 MK |
871 | case EfiUgaVideoToBltBuffer:\r |
872 | Blt = (EFI_UGA_PIXEL *)((UINT8 *)BltBuffer + (Args->DestinationY * Args->Delta) + Args->DestinationX * sizeof (EFI_UGA_PIXEL));\r | |
873 | Args->Delta -= Args->Width * sizeof (EFI_UGA_PIXEL);\r | |
874 | for (SrcY = Args->SourceY; SrcY < (Args->Height + Args->SourceY); SrcY++) {\r | |
875 | for (SrcX = Args->SourceX; SrcX < (Args->Width + Args->SourceX); SrcX++) {\r | |
876 | *Blt++ = X11ColorToPixel (Private, XGetPixel (Private->image, SrcX, SrcY));\r | |
877 | }\r | |
878 | \r | |
879 | Blt = (EFI_UGA_PIXEL *)((UINT8 *)Blt + Args->Delta);\r | |
79e4f2a5 | 880 | }\r |
a550d468 MK |
881 | \r |
882 | break;\r | |
883 | case EfiUgaBltBufferToVideo:\r | |
884 | Blt = (EFI_UGA_PIXEL *)((UINT8 *)BltBuffer + (Args->SourceY * Args->Delta) + Args->SourceX * sizeof (EFI_UGA_PIXEL));\r | |
885 | Args->Delta -= Args->Width * sizeof (EFI_UGA_PIXEL);\r | |
886 | for (DstY = Args->DestinationY; DstY < (Args->Height + Args->DestinationY); DstY++) {\r | |
887 | for (DstX = Args->DestinationX; DstX < (Args->Width + Args->DestinationX); DstX++) {\r | |
888 | XPutPixel (Private->image, DstX, DstY, X11PixelToColor (Private, *Blt));\r | |
889 | Blt++;\r | |
890 | }\r | |
891 | \r | |
892 | Blt = (EFI_UGA_PIXEL *)((UINT8 *)Blt + Args->Delta);\r | |
79e4f2a5 | 893 | }\r |
a550d468 MK |
894 | \r |
895 | break;\r | |
896 | case EfiUgaVideoToVideo:\r | |
897 | Dst = Private->image_data + (Args->DestinationX << Private->pixel_shift)\r | |
898 | + Args->DestinationY * Private->line_bytes;\r | |
899 | Src = Private->image_data + (Args->SourceX << Private->pixel_shift)\r | |
900 | + Args->SourceY * Private->line_bytes;\r | |
901 | Nbr = Args->Width << Private->pixel_shift;\r | |
902 | if (Args->DestinationY < Args->SourceY) {\r | |
903 | for (Index = 0; Index < Args->Height; Index++) {\r | |
904 | memcpy (Dst, Src, Nbr);\r | |
905 | Dst += Private->line_bytes;\r | |
906 | Src += Private->line_bytes;\r | |
907 | }\r | |
908 | } else {\r | |
909 | Dst += (Args->Height - 1) * Private->line_bytes;\r | |
910 | Src += (Args->Height - 1) * Private->line_bytes;\r | |
911 | for (Index = 0; Index < Args->Height; Index++) {\r | |
912 | //\r | |
913 | // Source and Destination Y may be equal, therefore Dst and Src may\r | |
914 | // overlap.\r | |
915 | //\r | |
916 | memmove (Dst, Src, Nbr);\r | |
917 | Dst -= Private->line_bytes;\r | |
918 | Src -= Private->line_bytes;\r | |
919 | }\r | |
79e4f2a5 | 920 | }\r |
a550d468 MK |
921 | \r |
922 | break;\r | |
923 | case EfiUgaVideoFill:\r | |
924 | Color = X11PixelToColor (Private, *BltBuffer);\r | |
925 | for (DstY = Args->DestinationY; DstY < (Args->Height + Args->DestinationY); DstY++) {\r | |
926 | for (DstX = Args->DestinationX; DstX < (Args->Width + Args->DestinationX); DstX++) {\r | |
927 | XPutPixel (Private->image, DstX, DstY, Color);\r | |
928 | }\r | |
79e4f2a5 | 929 | }\r |
a550d468 MK |
930 | \r |
931 | break;\r | |
932 | default:\r | |
933 | return EFI_INVALID_PARAMETER;\r | |
79e4f2a5 RN |
934 | }\r |
935 | \r | |
936 | //\r | |
937 | // Refresh screen.\r | |
938 | //\r | |
939 | switch (BltOperation) {\r | |
a550d468 MK |
940 | case EfiUgaVideoToVideo:\r |
941 | XCopyArea (\r | |
942 | Private->display,\r | |
943 | Private->win,\r | |
944 | Private->win,\r | |
945 | Private->gc,\r | |
946 | Args->SourceX,\r | |
947 | Args->SourceY,\r | |
948 | Args->Width,\r | |
949 | Args->Height,\r | |
950 | Args->DestinationX,\r | |
951 | Args->DestinationY\r | |
952 | );\r | |
953 | \r | |
954 | while (1) {\r | |
955 | XNextEvent (Private->display, &ev);\r | |
956 | HandleEvent (Private, &ev);\r | |
957 | if ((ev.type == NoExpose) || (ev.type == GraphicsExpose)) {\r | |
958 | break;\r | |
959 | }\r | |
79e4f2a5 | 960 | }\r |
a550d468 MK |
961 | \r |
962 | break;\r | |
963 | case EfiUgaVideoFill:\r | |
964 | Color = X11PixelToColor (Private, *BltBuffer);\r | |
965 | XSetForeground (Private->display, Private->gc, Color);\r | |
966 | XFillRectangle (\r | |
967 | Private->display,\r | |
968 | Private->win,\r | |
969 | Private->gc,\r | |
970 | Args->DestinationX,\r | |
971 | Args->DestinationY,\r | |
972 | Args->Width,\r | |
973 | Args->Height\r | |
974 | );\r | |
975 | XFlush (Private->display);\r | |
976 | break;\r | |
977 | case EfiUgaBltBufferToVideo:\r | |
978 | Redraw (Private, Args->DestinationX, Args->DestinationY, Args->Width, Args->Height);\r | |
979 | break;\r | |
980 | default:\r | |
981 | break;\r | |
79e4f2a5 | 982 | }\r |
a550d468 | 983 | \r |
79e4f2a5 RN |
984 | return EFI_SUCCESS;\r |
985 | }\r | |
986 | \r | |
79e4f2a5 RN |
987 | EFI_STATUS\r |
988 | X11CheckPointer (\r | |
a550d468 | 989 | IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo\r |
79e4f2a5 RN |
990 | )\r |
991 | {\r | |
992 | GRAPHICS_IO_PRIVATE *Drv;\r | |
993 | \r | |
994 | Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r | |
995 | \r | |
996 | HandleEvents (Drv);\r | |
997 | if (Drv->pointer_state_changed != 0) {\r | |
998 | return EFI_SUCCESS;\r | |
999 | }\r | |
1000 | \r | |
1001 | return EFI_NOT_READY;\r | |
1002 | }\r | |
1003 | \r | |
79e4f2a5 RN |
1004 | EFI_STATUS\r |
1005 | X11GetPointerState (\r | |
1006 | IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r | |
1007 | IN EFI_SIMPLE_POINTER_STATE *State\r | |
1008 | )\r | |
1009 | {\r | |
a550d468 MK |
1010 | EFI_STATUS EfiStatus;\r |
1011 | GRAPHICS_IO_PRIVATE *Drv;\r | |
79e4f2a5 RN |
1012 | \r |
1013 | Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r | |
1014 | \r | |
1015 | EfiStatus = X11CheckPointer (GraphicsIo);\r | |
1016 | if (EfiStatus != EFI_SUCCESS) {\r | |
1017 | return EfiStatus;\r | |
1018 | }\r | |
1019 | \r | |
1020 | memcpy (State, &Drv->pointer_state, sizeof (EFI_SIMPLE_POINTER_STATE));\r | |
1021 | \r | |
1022 | Drv->pointer_state.RelativeMovementX = 0;\r | |
1023 | Drv->pointer_state.RelativeMovementY = 0;\r | |
1024 | Drv->pointer_state.RelativeMovementZ = 0;\r | |
a550d468 | 1025 | Drv->pointer_state_changed = 0;\r |
79e4f2a5 RN |
1026 | return EFI_SUCCESS;\r |
1027 | }\r | |
1028 | \r | |
79e4f2a5 RN |
1029 | EFI_STATUS\r |
1030 | X11GraphicsWindowOpen (\r | |
a550d468 | 1031 | IN EMU_IO_THUNK_PROTOCOL *This\r |
79e4f2a5 RN |
1032 | )\r |
1033 | {\r | |
a550d468 MK |
1034 | GRAPHICS_IO_PRIVATE *Drv;\r |
1035 | unsigned int border_width = 0;\r | |
1036 | char *display_name = NULL;\r | |
79e4f2a5 RN |
1037 | \r |
1038 | Drv = (GRAPHICS_IO_PRIVATE *)calloc (1, sizeof (GRAPHICS_IO_PRIVATE));\r | |
1039 | if (Drv == NULL) {\r | |
1040 | return EFI_OUT_OF_RESOURCES;\r | |
1041 | }\r | |
1042 | \r | |
a550d468 MK |
1043 | Drv->GraphicsIo.Size = GasketX11Size;\r |
1044 | Drv->GraphicsIo.CheckKey = GasketX11CheckKey;\r | |
1045 | Drv->GraphicsIo.GetKey = GasketX11GetKey;\r | |
1046 | Drv->GraphicsIo.KeySetState = GasketX11KeySetState;\r | |
1047 | Drv->GraphicsIo.RegisterKeyNotify = GasketX11RegisterKeyNotify;\r | |
1048 | Drv->GraphicsIo.Blt = GasketX11Blt;\r | |
1049 | Drv->GraphicsIo.CheckPointer = GasketX11CheckPointer;\r | |
1050 | Drv->GraphicsIo.GetPointerState = GasketX11GetPointerState;\r | |
1051 | \r | |
1052 | Drv->key_count = 0;\r | |
1053 | Drv->key_rd = 0;\r | |
1054 | Drv->key_wr = 0;\r | |
79e4f2a5 RN |
1055 | Drv->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r |
1056 | Drv->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r | |
1057 | Drv->MakeRegisterdKeyCallback = NULL;\r | |
1058 | Drv->BreakRegisterdKeyCallback = NULL;\r | |
1059 | Drv->RegisterdKeyCallbackContext = NULL;\r | |
1060 | \r | |
79e4f2a5 RN |
1061 | Drv->display = XOpenDisplay (display_name);\r |
1062 | if (Drv->display == NULL) {\r | |
1063 | fprintf (stderr, "uga: cannot connect to X server %s\n", XDisplayName (display_name));\r | |
1064 | free (Drv);\r | |
1065 | return EFI_DEVICE_ERROR;\r | |
1066 | }\r | |
a550d468 | 1067 | \r |
79e4f2a5 RN |
1068 | Drv->screen = DefaultScreen (Drv->display);\r |
1069 | Drv->visual = DefaultVisual (Drv->display, Drv->screen);\r | |
a550d468 MK |
1070 | Drv->win = XCreateSimpleWindow (\r |
1071 | Drv->display,\r | |
1072 | RootWindow (Drv->display, Drv->screen),\r | |
1073 | 0,\r | |
1074 | 0,\r | |
1075 | 4,\r | |
1076 | 4,\r | |
1077 | border_width,\r | |
1078 | WhitePixel (Drv->display, Drv->screen),\r | |
1079 | BlackPixel (Drv->display, Drv->screen)\r | |
1080 | );\r | |
79e4f2a5 RN |
1081 | \r |
1082 | Drv->depth = DefaultDepth (Drv->display, Drv->screen);\r | |
1083 | XDefineCursor (Drv->display, Drv->win, XCreateFontCursor (Drv->display, XC_pirate));\r | |
1084 | \r | |
1085 | Drv->Title = malloc (StrSize (This->ConfigString));\r | |
9e3ab94d | 1086 | UnicodeStrToAsciiStrS (This->ConfigString, Drv->Title, StrSize (This->ConfigString));\r |
79e4f2a5 RN |
1087 | XStoreName (Drv->display, Drv->win, Drv->Title);\r |
1088 | \r | |
a550d468 | 1089 | // XAutoRepeatOff (Drv->display);\r |
79e4f2a5 | 1090 | XSelectInput (\r |
a550d468 MK |
1091 | Drv->display,\r |
1092 | Drv->win,\r | |
79e4f2a5 RN |
1093 | ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask\r |
1094 | );\r | |
1095 | Drv->gc = DefaultGC (Drv->display, Drv->screen);\r | |
1096 | \r | |
1097 | This->Private = (VOID *)Drv;\r | |
1098 | This->Interface = (VOID *)Drv;\r | |
1099 | return EFI_SUCCESS;\r | |
1100 | }\r | |
1101 | \r | |
79e4f2a5 RN |
1102 | EFI_STATUS\r |
1103 | X11GraphicsWindowClose (\r | |
a550d468 | 1104 | IN EMU_IO_THUNK_PROTOCOL *This\r |
79e4f2a5 RN |
1105 | )\r |
1106 | {\r | |
a550d468 | 1107 | GRAPHICS_IO_PRIVATE *Drv;\r |
79e4f2a5 RN |
1108 | \r |
1109 | Drv = (GRAPHICS_IO_PRIVATE *)This->Private;\r | |
1110 | \r | |
1111 | if (Drv == NULL) {\r | |
1112 | return EFI_SUCCESS;\r | |
1113 | }\r | |
1114 | \r | |
1115 | if (Drv->image != NULL) {\r | |
a550d468 | 1116 | XDestroyImage (Drv->image);\r |
79e4f2a5 RN |
1117 | \r |
1118 | if (Drv->use_shm) {\r | |
1119 | shmdt (Drv->image_data);\r | |
1120 | }\r | |
1121 | \r | |
1122 | Drv->image_data = NULL;\r | |
a550d468 | 1123 | Drv->image = NULL;\r |
79e4f2a5 | 1124 | }\r |
a550d468 | 1125 | \r |
79e4f2a5 RN |
1126 | XDestroyWindow (Drv->display, Drv->win);\r |
1127 | XCloseDisplay (Drv->display);\r | |
1128 | \r | |
a550d468 | 1129 | #ifdef __APPLE__\r |
79e4f2a5 RN |
1130 | // Free up the shared memory\r |
1131 | shmctl (Drv->xshm_info.shmid, IPC_RMID, NULL);\r | |
a550d468 | 1132 | #endif\r |
79e4f2a5 RN |
1133 | \r |
1134 | free (Drv);\r | |
1135 | return EFI_SUCCESS;\r | |
1136 | }\r | |
1137 | \r | |
a550d468 | 1138 | EMU_IO_THUNK_PROTOCOL gX11ThunkIo = {\r |
79e4f2a5 RN |
1139 | &gEmuGraphicsWindowProtocolGuid,\r |
1140 | NULL,\r | |
1141 | NULL,\r | |
1142 | 0,\r | |
1143 | GasketX11GraphicsWindowOpen,\r | |
1144 | GasketX11GraphicsWindowClose,\r | |
1145 | NULL\r | |
1146 | };\r |