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