]> git.proxmox.com Git - mirror_edk2.git/blame - EmulatorPkg/Unix/Host/X11GraphicsWindow.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / EmulatorPkg / Unix / Host / X11GraphicsWindow.c
CommitLineData
79e4f2a5
RN
1/*++ @file\r
2\r
9e3ab94d 3Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>\r
79e4f2a5
RN
4Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>\r
5\r
e3ba31da 6SPDX-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 25struct 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 32typedef 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
72void\r
a550d468
MK
73HandleEvents (\r
74 IN GRAPHICS_IO_PRIVATE *Drv\r
79e4f2a5
RN
75 );\r
76\r
77void\r
78fill_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
98int\r
99TryCreateShmImage (\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
166EFI_STATUS\r
167X11Size (\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
239void\r
240handleKeyEvent (\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 553void\r
a550d468
MK
554handleMouseMoved (\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
574void\r
575handleMouseDown (\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
592void\r
593Redraw (\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
633void\r
a550d468
MK
634HandleEvent (\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
688void\r
689HandleEvents (\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
701unsigned long\r
702X11PixelToColor (\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
712EFI_UGA_PIXEL\r
713X11ColorToPixel (\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
730EFI_STATUS\r
731X11CheckKey (\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
748EFI_STATUS\r
749X11GetKey (\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
771EFI_STATUS\r
772X11KeySetState (\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
794EFI_STATUS\r
795X11RegisterKeyNotify (\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
813EFI_STATUS\r
814X11Blt (\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
987EFI_STATUS\r
988X11CheckPointer (\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
1004EFI_STATUS\r
1005X11GetPointerState (\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
1029EFI_STATUS\r
1030X11GraphicsWindowOpen (\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
1102EFI_STATUS\r
1103X11GraphicsWindowClose (\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 1138EMU_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