3 Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
4 Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
16 #include <X11/Xutil.h>
18 #include <X11/extensions/XShm.h>
19 #include <X11/keysym.h>
20 #include <X11/cursorfont.h>
22 #define KEYSYM_LOWER 0
23 #define KEYSYM_UPPER 1
26 struct uga_drv_shift_mask
{
34 EMU_GRAPHICS_WINDOW_PROTOCOL GraphicsIo
;
37 int screen
; // values for window_size in main
45 unsigned int line_bytes
;
46 unsigned int pixel_shift
;
47 unsigned char *image_data
;
49 struct uga_drv_shift_mask r
, g
, b
;
52 XShmSegmentInfo xshm_info
;
58 unsigned int key_count
;
59 EFI_KEY_DATA keys
[NBR_KEYS
];
61 EFI_KEY_STATE KeyState
;
63 EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeRegisterdKeyCallback
;
64 EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakRegisterdKeyCallback
;
65 VOID
*RegisterdKeyCallbackContext
;
69 EFI_SIMPLE_POINTER_STATE pointer_state
;
70 int pointer_state_changed
;
71 } GRAPHICS_IO_PRIVATE
;
75 IN GRAPHICS_IO_PRIVATE
*Drv
80 IN
struct uga_drv_shift_mask
*sm
,
86 while ((mask
& 1) == 0) {
94 sm
->csize
= 8 - sm
->size
;
99 IN GRAPHICS_IO_PRIVATE
*Drv
102 Drv
->image
= XShmCreateImage (
103 Drv
->display
, Drv
->visual
,
104 Drv
->depth
, ZPixmap
, NULL
, &Drv
->xshm_info
,
105 Drv
->width
, Drv
->height
107 if (Drv
->image
== NULL
) {
111 switch (Drv
->image
->bitmap_unit
) {
113 Drv
->pixel_shift
= 2;
116 Drv
->pixel_shift
= 1;
119 Drv
->pixel_shift
= 0;
123 Drv
->xshm_info
.shmid
= shmget (
124 IPC_PRIVATE
, Drv
->image
->bytes_per_line
* Drv
->image
->height
,
127 if (Drv
->xshm_info
.shmid
< 0) {
128 XDestroyImage(Drv
->image
);
132 Drv
->image_data
= shmat (Drv
->xshm_info
.shmid
, NULL
, 0);
133 if(!Drv
->image_data
) {
134 shmctl (Drv
->xshm_info
.shmid
, IPC_RMID
, NULL
);
135 XDestroyImage(Drv
->image
);
141 // This closes shared memory in real time on OS X. Only closes after folks quit using
144 shmctl (Drv
->xshm_info
.shmid
, IPC_RMID
, NULL
);
147 Drv
->xshm_info
.shmaddr
= (char*)Drv
->image_data
;
148 Drv
->image
->data
= (char*)Drv
->image_data
;
150 if (!XShmAttach (Drv
->display
, &Drv
->xshm_info
)) {
151 shmdt (Drv
->image_data
);
152 XDestroyImage(Drv
->image
);
161 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
166 GRAPHICS_IO_PRIVATE
*Drv
;
167 XSizeHints size_hints
;
169 // Destroy current buffer if created.
170 Drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
171 if (Drv
->image
!= NULL
) {
172 // Before destroy buffer, need to make sure the buffer available for access.
173 XDestroyImage (Drv
->image
);
176 shmdt (Drv
->image_data
);
179 Drv
->image_data
= NULL
;
184 Drv
->height
= Height
;
185 XResizeWindow (Drv
->display
, Drv
->win
, Width
, Height
);
188 if (XShmQueryExtension(Drv
->display
) && TryCreateShmImage(Drv
)) {
192 if (Drv
->depth
> 16) {
193 Drv
->pixel_shift
= 2;
194 } else if (Drv
->depth
> 8) {
195 Drv
->pixel_shift
= 1;
197 Drv
->pixel_shift
= 0;
200 Drv
->image_data
= malloc ((Drv
->width
* Drv
->height
) << Drv
->pixel_shift
);
201 Drv
->image
= XCreateImage (
202 Drv
->display
, Drv
->visual
, Drv
->depth
,
203 ZPixmap
, 0, (char *)Drv
->image_data
,
204 Drv
->width
, Drv
->height
,
205 8 << Drv
->pixel_shift
, 0
209 Drv
->line_bytes
= Drv
->image
->bytes_per_line
;
211 fill_shift_mask (&Drv
->r
, Drv
->image
->red_mask
);
212 fill_shift_mask (&Drv
->g
, Drv
->image
->green_mask
);
213 fill_shift_mask (&Drv
->b
, Drv
->image
->blue_mask
);
216 size_hints
.flags
= PSize
| PMinSize
| PMaxSize
;
217 size_hints
.min_width
= size_hints
.max_width
= size_hints
.base_width
= Width
;
218 size_hints
.min_height
= size_hints
.max_height
= size_hints
.base_height
= Height
;
219 XSetWMNormalHints (Drv
->display
, Drv
->win
, &size_hints
);
221 XMapWindow (Drv
->display
, Drv
->win
);
228 IN GRAPHICS_IO_PRIVATE
*Drv
,
234 EFI_KEY_DATA KeyData
;
238 if (Drv
->key_count
== NBR_KEYS
) {
243 // keycode is a physical key on the keyboard
244 // KeySym is a mapping of a physical key
245 // KeyboardMapping is the array of KeySym for a given keycode. key, shifted key, option key, command key, ...
247 // Returns an array of KeySymArraySize of KeySym for the keycode. [0] is lower case, [1] is upper case,
248 // [2] and [3] are based on option and command modifiers. The problem we have is command V
249 // could be mapped to a crazy Unicode character so the old scheme of returning a string.
251 KeySym
= XGetKeyboardMapping (Drv
->display
, ev
->xkey
.keycode
, 1, &KeySymArraySize
);
253 KeyData
.Key
.ScanCode
= 0;
254 KeyData
.Key
.UnicodeChar
= 0;
255 KeyData
.KeyState
.KeyShiftState
= 0;
258 // Skipping EFI_SCROLL_LOCK_ACTIVE & EFI_NUM_LOCK_ACTIVE since they are not on Macs
260 if ((ev
->xkey
.state
& LockMask
) == 0) {
261 Drv
->KeyState
.KeyToggleState
&= ~EFI_CAPS_LOCK_ACTIVE
;
264 Drv
->KeyState
.KeyToggleState
|= EFI_CAPS_LOCK_ACTIVE
;
268 // Skipping EFI_MENU_KEY_PRESSED and EFI_SYS_REQ_PRESSED
273 Drv
->KeyState
.KeyShiftState
|= EFI_RIGHT_CONTROL_PRESSED
;
275 Drv
->KeyState
.KeyShiftState
&= ~EFI_RIGHT_CONTROL_PRESSED
;
280 Drv
->KeyState
.KeyShiftState
|= EFI_LEFT_CONTROL_PRESSED
;
282 Drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_CONTROL_PRESSED
;
288 Drv
->KeyState
.KeyShiftState
|= EFI_RIGHT_SHIFT_PRESSED
;
290 Drv
->KeyState
.KeyShiftState
&= ~EFI_RIGHT_SHIFT_PRESSED
;
295 Drv
->KeyState
.KeyShiftState
|= EFI_LEFT_SHIFT_PRESSED
;
297 Drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_SHIFT_PRESSED
;
303 Drv
->KeyState
.KeyShiftState
|= EFI_LEFT_ALT_PRESSED
;
305 Drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_ALT_PRESSED
;
311 Drv
->KeyState
.KeyShiftState
|= EFI_RIGHT_LOGO_PRESSED
;
313 Drv
->KeyState
.KeyShiftState
&= ~EFI_RIGHT_LOGO_PRESSED
;
318 Drv
->KeyState
.KeyShiftState
|= EFI_LEFT_LOGO_PRESSED
;
320 Drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_LOGO_PRESSED
;
325 case XK_Home
: KeyData
.Key
.ScanCode
= SCAN_HOME
; break;
328 case XK_End
: KeyData
.Key
.ScanCode
= SCAN_END
; break;
331 case XK_Left
: KeyData
.Key
.ScanCode
= SCAN_LEFT
; break;
334 case XK_Right
: KeyData
.Key
.ScanCode
= SCAN_RIGHT
; break;
337 case XK_Up
: KeyData
.Key
.ScanCode
= SCAN_UP
; break;
340 case XK_Down
: KeyData
.Key
.ScanCode
= SCAN_DOWN
; break;
343 case XK_Delete
: KeyData
.Key
.ScanCode
= SCAN_DELETE
; break;
346 case XK_Insert
: KeyData
.Key
.ScanCode
= SCAN_INSERT
; break;
349 case XK_Page_Up
: KeyData
.Key
.ScanCode
= SCAN_PAGE_UP
; break;
351 case XK_KP_Page_Down
:
352 case XK_Page_Down
: KeyData
.Key
.ScanCode
= SCAN_PAGE_DOWN
; break;
354 case XK_Escape
: KeyData
.Key
.ScanCode
= SCAN_ESC
; break;
356 case XK_Pause
: KeyData
.Key
.ScanCode
= SCAN_PAUSE
; break;
359 case XK_F1
: KeyData
.Key
.ScanCode
= SCAN_F1
; break;
362 case XK_F2
: KeyData
.Key
.ScanCode
= SCAN_F2
; break;
365 case XK_F3
: KeyData
.Key
.ScanCode
= SCAN_F3
; break;
368 case XK_F4
: KeyData
.Key
.ScanCode
= SCAN_F4
; break;
370 case XK_F5
: KeyData
.Key
.ScanCode
= SCAN_F5
; break;
371 case XK_F6
: KeyData
.Key
.ScanCode
= SCAN_F6
; break;
372 case XK_F7
: KeyData
.Key
.ScanCode
= SCAN_F7
; break;
374 // Don't map into X11 by default on a Mac
375 // System Preferences->Keyboard->Keyboard Shortcuts can be configured
376 // to not use higher function keys as shortcuts and the will show up
378 case XK_F8
: KeyData
.Key
.ScanCode
= SCAN_F8
; break;
379 case XK_F9
: KeyData
.Key
.ScanCode
= SCAN_F9
; break;
380 case XK_F10
: KeyData
.Key
.ScanCode
= SCAN_F10
; break;
382 case XK_F11
: KeyData
.Key
.ScanCode
= SCAN_F11
; break;
383 case XK_F12
: KeyData
.Key
.ScanCode
= SCAN_F12
; break;
385 case XK_F13
: KeyData
.Key
.ScanCode
= SCAN_F13
; break;
386 case XK_F14
: KeyData
.Key
.ScanCode
= SCAN_F14
; break;
387 case XK_F15
: KeyData
.Key
.ScanCode
= SCAN_F15
; break;
388 case XK_F16
: KeyData
.Key
.ScanCode
= SCAN_F16
; break;
389 case XK_F17
: KeyData
.Key
.ScanCode
= SCAN_F17
; break;
390 case XK_F18
: KeyData
.Key
.ScanCode
= SCAN_F18
; break;
391 case XK_F19
: KeyData
.Key
.ScanCode
= SCAN_F19
; break;
392 case XK_F20
: KeyData
.Key
.ScanCode
= SCAN_F20
; break;
393 case XK_F21
: KeyData
.Key
.ScanCode
= SCAN_F21
; break;
394 case XK_F22
: KeyData
.Key
.ScanCode
= SCAN_F22
; break;
395 case XK_F23
: KeyData
.Key
.ScanCode
= SCAN_F23
; break;
396 case XK_F24
: KeyData
.Key
.ScanCode
= SCAN_F24
; break;
399 //case XK_: KeyData.Key.ScanCode = SCAN_MUTE; break;
400 //case XK_: KeyData.Key.ScanCode = SCAN_VOLUME_UP; break;
401 //case XK_: KeyData.Key.ScanCode = SCAN_VOLUME_DOWN; break;
402 //case XK_: KeyData.Key.ScanCode = SCAN_BRIGHTNESS_UP; break;
403 //case XK_: KeyData.Key.ScanCode = SCAN_BRIGHTNESS_DOWN; break;
404 //case XK_: KeyData.Key.ScanCode = SCAN_SUSPEND; break;
405 //case XK_: KeyData.Key.ScanCode = SCAN_HIBERNATE; break;
406 //case XK_: KeyData.Key.ScanCode = SCAN_TOGGLE_DISPLAY; break;
407 //case XK_: KeyData.Key.ScanCode = SCAN_RECOVERY; break;
408 //case XK_: KeyData.Key.ScanCode = SCAN_EJECT; break;
410 case XK_BackSpace
: KeyData
.Key
.UnicodeChar
= 0x0008; break;
413 case XK_Tab
: KeyData
.Key
.UnicodeChar
= 0x0009; break;
415 case XK_Linefeed
: KeyData
.Key
.UnicodeChar
= 0x000a; break;
418 case XK_Return
: KeyData
.Key
.UnicodeChar
= 0x000d; break;
420 case XK_KP_Equal
: KeyData
.Key
.UnicodeChar
= L
'='; break;
421 case XK_KP_Multiply
: KeyData
.Key
.UnicodeChar
= L
'*'; break;
422 case XK_KP_Add
: KeyData
.Key
.UnicodeChar
= L
'+'; break;
423 case XK_KP_Separator
: KeyData
.Key
.UnicodeChar
= L
'~'; break;
424 case XK_KP_Subtract
: KeyData
.Key
.UnicodeChar
= L
'-'; break;
425 case XK_KP_Decimal
: KeyData
.Key
.UnicodeChar
= L
'.'; break;
426 case XK_KP_Divide
: KeyData
.Key
.UnicodeChar
= L
'/'; break;
428 case XK_KP_0
: KeyData
.Key
.UnicodeChar
= L
'0'; break;
429 case XK_KP_1
: KeyData
.Key
.UnicodeChar
= L
'1'; break;
430 case XK_KP_2
: KeyData
.Key
.UnicodeChar
= L
'2'; break;
431 case XK_KP_3
: KeyData
.Key
.UnicodeChar
= L
'3'; break;
432 case XK_KP_4
: KeyData
.Key
.UnicodeChar
= L
'4'; break;
433 case XK_KP_5
: KeyData
.Key
.UnicodeChar
= L
'5'; break;
434 case XK_KP_6
: KeyData
.Key
.UnicodeChar
= L
'6'; break;
435 case XK_KP_7
: KeyData
.Key
.UnicodeChar
= L
'7'; break;
436 case XK_KP_8
: KeyData
.Key
.UnicodeChar
= L
'8'; break;
437 case XK_KP_9
: KeyData
.Key
.UnicodeChar
= L
'9'; break;
443 // The global state is our state
444 KeyData
.KeyState
.KeyShiftState
= Drv
->KeyState
.KeyShiftState
;
445 KeyData
.KeyState
.KeyToggleState
= Drv
->KeyState
.KeyToggleState
;
447 if (*KeySym
< XK_BackSpace
) {
448 if (((Drv
->KeyState
.KeyShiftState
& (EFI_LEFT_SHIFT_PRESSED
| EFI_RIGHT_SHIFT_PRESSED
)) != 0) ||
449 ((Drv
->KeyState
.KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) != 0) ) {
451 KeyData
.Key
.UnicodeChar
= (CHAR16
)KeySym
[KEYSYM_UPPER
];
453 // Per UEFI spec since we converted the Unicode clear the shift bits we pass up
454 KeyData
.KeyState
.KeyShiftState
&= ~(EFI_LEFT_SHIFT_PRESSED
| EFI_RIGHT_SHIFT_PRESSED
);
456 KeyData
.Key
.UnicodeChar
= (CHAR16
)KeySym
[KEYSYM_LOWER
];
459 // XK_BackSpace is the start of XK_MISCELLANY. These are the XK_? keys we process in this file
464 memcpy (&Drv
->keys
[Drv
->key_wr
], &KeyData
, sizeof (EFI_KEY_DATA
));
465 Drv
->key_wr
= (Drv
->key_wr
+ 1) % NBR_KEYS
;
467 if (Drv
->MakeRegisterdKeyCallback
!= NULL
) {
468 ReverseGasketUint64Uint64 (Drv
->MakeRegisterdKeyCallback
,Drv
->RegisterdKeyCallbackContext
, &KeyData
);
471 if (Drv
->BreakRegisterdKeyCallback
!= NULL
) {
472 ReverseGasketUint64Uint64 (Drv
->BreakRegisterdKeyCallback
,Drv
->RegisterdKeyCallbackContext
, &KeyData
);
480 IN GRAPHICS_IO_PRIVATE
*Drv
,
484 if (ev
->xmotion
.x
!= Drv
->previous_x
) {
485 Drv
->pointer_state
.RelativeMovementX
+= ( ev
->xmotion
.x
- Drv
->previous_x
);
486 Drv
->previous_x
= ev
->xmotion
.x
;
487 Drv
->pointer_state_changed
= 1;
490 if (ev
->xmotion
.y
!= Drv
->previous_y
) {
491 Drv
->pointer_state
.RelativeMovementY
+= ( ev
->xmotion
.y
- Drv
->previous_y
);
492 Drv
->previous_y
= ev
->xmotion
.y
;
493 Drv
->pointer_state_changed
= 1;
496 Drv
->pointer_state
.RelativeMovementZ
= 0;
501 IN GRAPHICS_IO_PRIVATE
*Drv
,
506 if (ev
->xbutton
.button
== Button1
) {
507 Drv
->pointer_state_changed
= (Drv
->pointer_state
.LeftButton
!= Pressed
);
508 Drv
->pointer_state
.LeftButton
= Pressed
;
510 if ( ev
->xbutton
.button
== Button2
) {
511 Drv
->pointer_state_changed
= (Drv
->pointer_state
.RightButton
!= Pressed
);
512 Drv
->pointer_state
.RightButton
= Pressed
;
518 IN GRAPHICS_IO_PRIVATE
*Drv
,
527 Drv
->display
, Drv
->win
, Drv
->gc
, Drv
->image
, X
, Y
, X
, Y
, Width
, Height
, False
531 Drv
->display
, Drv
->win
, Drv
->gc
, Drv
->image
, X
, Y
, X
, Y
, Width
, Height
534 XFlush(Drv
->display
);
538 HandleEvent(GRAPHICS_IO_PRIVATE
*Drv
, XEvent
*ev
)
542 Redraw (Drv
, ev
->xexpose
.x
, ev
->xexpose
.y
,
543 ev
->xexpose
.width
, ev
->xexpose
.height
);
546 Redraw (Drv
, ev
->xgraphicsexpose
.x
, ev
->xgraphicsexpose
.y
,
547 ev
->xgraphicsexpose
.width
, ev
->xgraphicsexpose
.height
);
550 handleKeyEvent (Drv
, ev
, TRUE
);
553 handleKeyEvent (Drv
, ev
, FALSE
);
556 XRefreshKeyboardMapping (&ev
->xmapping
);
559 handleMouseMoved (Drv
, ev
);
562 handleMouseDown (Drv
, ev
, TRUE
);
565 handleMouseDown (Drv
, ev
, FALSE
);
569 XCloseDisplay (Drv
->display
);
581 IN GRAPHICS_IO_PRIVATE
*Drv
586 while (XPending (Drv
->display
) != 0) {
587 XNextEvent (Drv
->display
, &ev
);
588 HandleEvent (Drv
, &ev
);
594 IN GRAPHICS_IO_PRIVATE
*Drv
,
595 IN EFI_UGA_PIXEL pixel
598 return ((pixel
.Red
>> Drv
->r
.csize
) << Drv
->r
.shift
)
599 | ((pixel
.Green
>> Drv
->g
.csize
) << Drv
->g
.shift
)
600 | ((pixel
.Blue
>> Drv
->b
.csize
) << Drv
->b
.shift
);
605 IN GRAPHICS_IO_PRIVATE
*Drv
,
611 memset (&Pixel
, 0, sizeof (EFI_UGA_PIXEL
));
613 // Truncation not an issue since X11 and EFI are both using 8 bits per color
614 Pixel
.Red
= (val
>> Drv
->r
.shift
) << Drv
->r
.csize
;
615 Pixel
.Green
= (val
>> Drv
->g
.shift
) << Drv
->g
.csize
;
616 Pixel
.Blue
= (val
>> Drv
->b
.shift
) << Drv
->b
.csize
;
624 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
627 GRAPHICS_IO_PRIVATE
*Drv
;
629 Drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
633 if (Drv
->key_count
!= 0) {
637 return EFI_NOT_READY
;
642 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
643 IN EFI_KEY_DATA
*KeyData
646 EFI_STATUS EfiStatus
;
647 GRAPHICS_IO_PRIVATE
*Drv
;
649 Drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
651 EfiStatus
= X11CheckKey (GraphicsIo
);
652 if (EFI_ERROR (EfiStatus
)) {
656 CopyMem (KeyData
, &Drv
->keys
[Drv
->key_rd
], sizeof (EFI_KEY_DATA
));
657 Drv
->key_rd
= (Drv
->key_rd
+ 1) % NBR_KEYS
;
666 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
667 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
670 GRAPHICS_IO_PRIVATE
*Drv
;
672 Drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
674 if (*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) {
675 if ((Drv
->KeyState
.KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == 0) {
677 // We could create an XKeyEvent and send a XK_Caps_Lock to
678 // the UGA/GOP Window
683 Drv
->KeyState
.KeyToggleState
= *KeyToggleState
;
689 X11RegisterKeyNotify (
690 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
691 IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeCallBack
,
692 IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakCallBack
,
696 GRAPHICS_IO_PRIVATE
*Drv
;
698 Drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
700 Drv
->MakeRegisterdKeyCallback
= MakeCallBack
;
701 Drv
->BreakRegisterdKeyCallback
= BreakCallBack
;
702 Drv
->RegisterdKeyCallbackContext
= Context
;
710 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
711 IN EFI_UGA_PIXEL
*BltBuffer OPTIONAL
,
712 IN EFI_UGA_BLT_OPERATION BltOperation
,
713 IN EMU_GRAPHICS_WINDOWS__BLT_ARGS
*Args
716 GRAPHICS_IO_PRIVATE
*Private
;
729 Private
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
735 if (BltOperation
== EfiUgaVideoToBltBuffer
736 || BltOperation
== EfiUgaVideoToVideo
) {
740 if (Args
->SourceY
+ Args
->Height
> Private
->height
) {
741 return EFI_INVALID_PARAMETER
;
744 if (Args
->SourceX
+ Args
->Width
> Private
->width
) {
745 return EFI_INVALID_PARAMETER
;
749 if (BltOperation
== EfiUgaBltBufferToVideo
750 || BltOperation
== EfiUgaVideoToVideo
751 || BltOperation
== EfiUgaVideoFill
) {
753 // Destination is Video
755 if (Args
->DestinationY
+ Args
->Height
> Private
->height
) {
756 return EFI_INVALID_PARAMETER
;
759 if (Args
->DestinationX
+ Args
->Width
> Private
->width
) {
760 return EFI_INVALID_PARAMETER
;
764 switch (BltOperation
) {
765 case EfiUgaVideoToBltBuffer
:
766 Blt
= (EFI_UGA_PIXEL
*)((UINT8
*)BltBuffer
+ (Args
->DestinationY
* Args
->Delta
) + Args
->DestinationX
* sizeof (EFI_UGA_PIXEL
));
767 Args
->Delta
-= Args
->Width
* sizeof (EFI_UGA_PIXEL
);
768 for (SrcY
= Args
->SourceY
; SrcY
< (Args
->Height
+ Args
->SourceY
); SrcY
++) {
769 for (SrcX
= Args
->SourceX
; SrcX
< (Args
->Width
+ Args
->SourceX
); SrcX
++) {
770 *Blt
++ = X11ColorToPixel (Private
, XGetPixel (Private
->image
, SrcX
, SrcY
));
772 Blt
= (EFI_UGA_PIXEL
*) ((UINT8
*) Blt
+ Args
->Delta
);
775 case EfiUgaBltBufferToVideo
:
776 Blt
= (EFI_UGA_PIXEL
*)((UINT8
*)BltBuffer
+ (Args
->SourceY
* Args
->Delta
) + Args
->SourceX
* sizeof (EFI_UGA_PIXEL
));
777 Args
->Delta
-= Args
->Width
* sizeof (EFI_UGA_PIXEL
);
778 for (DstY
= Args
->DestinationY
; DstY
< (Args
->Height
+ Args
->DestinationY
); DstY
++) {
779 for (DstX
= Args
->DestinationX
; DstX
< (Args
->Width
+ Args
->DestinationX
); DstX
++) {
780 XPutPixel(Private
->image
, DstX
, DstY
, X11PixelToColor(Private
, *Blt
));
783 Blt
= (EFI_UGA_PIXEL
*) ((UINT8
*) Blt
+ Args
->Delta
);
786 case EfiUgaVideoToVideo
:
787 Dst
= Private
->image_data
+ (Args
->DestinationX
<< Private
->pixel_shift
)
788 + Args
->DestinationY
* Private
->line_bytes
;
789 Src
= Private
->image_data
+ (Args
->SourceX
<< Private
->pixel_shift
)
790 + Args
->SourceY
* Private
->line_bytes
;
791 Nbr
= Args
->Width
<< Private
->pixel_shift
;
792 if (Args
->DestinationY
< Args
->SourceY
) {
793 for (Index
= 0; Index
< Args
->Height
; Index
++) {
794 memcpy (Dst
, Src
, Nbr
);
795 Dst
+= Private
->line_bytes
;
796 Src
+= Private
->line_bytes
;
799 Dst
+= (Args
->Height
- 1) * Private
->line_bytes
;
800 Src
+= (Args
->Height
- 1) * Private
->line_bytes
;
801 for (Index
= 0; Index
< Args
->Height
; Index
++) {
803 // Source and Destination Y may be equal, therefore Dst and Src may
806 memmove (Dst
, Src
, Nbr
);
807 Dst
-= Private
->line_bytes
;
808 Src
-= Private
->line_bytes
;
812 case EfiUgaVideoFill
:
813 Color
= X11PixelToColor(Private
, *BltBuffer
);
814 for (DstY
= Args
->DestinationY
; DstY
< (Args
->Height
+ Args
->DestinationY
); DstY
++) {
815 for (DstX
= Args
->DestinationX
; DstX
< (Args
->Width
+ Args
->DestinationX
); DstX
++) {
816 XPutPixel(Private
->image
, DstX
, DstY
, Color
);
821 return EFI_INVALID_PARAMETER
;
827 switch (BltOperation
) {
828 case EfiUgaVideoToVideo
:
830 Private
->display
, Private
->win
, Private
->win
, Private
->gc
,
831 Args
->SourceX
, Args
->SourceY
, Args
->Width
, Args
->Height
,
832 Args
->DestinationX
, Args
->DestinationY
836 XNextEvent (Private
->display
, &ev
);
837 HandleEvent (Private
, &ev
);
838 if (ev
.type
== NoExpose
|| ev
.type
== GraphicsExpose
) {
843 case EfiUgaVideoFill
:
844 Color
= X11PixelToColor (Private
, *BltBuffer
);
845 XSetForeground (Private
->display
, Private
->gc
, Color
);
847 Private
->display
, Private
->win
, Private
->gc
,
848 Args
->DestinationX
, Args
->DestinationY
, Args
->Width
, Args
->Height
850 XFlush (Private
->display
);
852 case EfiUgaBltBufferToVideo
:
853 Redraw (Private
, Args
->DestinationX
, Args
->DestinationY
, Args
->Width
, Args
->Height
);
864 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
867 GRAPHICS_IO_PRIVATE
*Drv
;
869 Drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
872 if (Drv
->pointer_state_changed
!= 0) {
876 return EFI_NOT_READY
;
882 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
883 IN EFI_SIMPLE_POINTER_STATE
*State
886 EFI_STATUS EfiStatus
;
887 GRAPHICS_IO_PRIVATE
*Drv
;
889 Drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
891 EfiStatus
= X11CheckPointer (GraphicsIo
);
892 if (EfiStatus
!= EFI_SUCCESS
) {
896 memcpy (State
, &Drv
->pointer_state
, sizeof (EFI_SIMPLE_POINTER_STATE
));
898 Drv
->pointer_state
.RelativeMovementX
= 0;
899 Drv
->pointer_state
.RelativeMovementY
= 0;
900 Drv
->pointer_state
.RelativeMovementZ
= 0;
901 Drv
->pointer_state_changed
= 0;
908 X11GraphicsWindowOpen (
909 IN EMU_IO_THUNK_PROTOCOL
*This
912 GRAPHICS_IO_PRIVATE
*Drv
;
913 unsigned int border_width
= 0;
914 char *display_name
= NULL
;
916 Drv
= (GRAPHICS_IO_PRIVATE
*)calloc (1, sizeof (GRAPHICS_IO_PRIVATE
));
918 return EFI_OUT_OF_RESOURCES
;
921 Drv
->GraphicsIo
.Size
= GasketX11Size
;
922 Drv
->GraphicsIo
.CheckKey
= GasketX11CheckKey
;
923 Drv
->GraphicsIo
.GetKey
= GasketX11GetKey
;
924 Drv
->GraphicsIo
.KeySetState
= GasketX11KeySetState
;
925 Drv
->GraphicsIo
.RegisterKeyNotify
= GasketX11RegisterKeyNotify
;
926 Drv
->GraphicsIo
.Blt
= GasketX11Blt
;
927 Drv
->GraphicsIo
.CheckPointer
= GasketX11CheckPointer
;
928 Drv
->GraphicsIo
.GetPointerState
= GasketX11GetPointerState
;
934 Drv
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
935 Drv
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
936 Drv
->MakeRegisterdKeyCallback
= NULL
;
937 Drv
->BreakRegisterdKeyCallback
= NULL
;
938 Drv
->RegisterdKeyCallbackContext
= NULL
;
941 Drv
->display
= XOpenDisplay (display_name
);
942 if (Drv
->display
== NULL
) {
943 fprintf (stderr
, "uga: cannot connect to X server %s\n", XDisplayName (display_name
));
945 return EFI_DEVICE_ERROR
;
947 Drv
->screen
= DefaultScreen (Drv
->display
);
948 Drv
->visual
= DefaultVisual (Drv
->display
, Drv
->screen
);
949 Drv
->win
= XCreateSimpleWindow (
950 Drv
->display
, RootWindow (Drv
->display
, Drv
->screen
),
951 0, 0, 4, 4, border_width
,
952 WhitePixel (Drv
->display
, Drv
->screen
),
953 BlackPixel (Drv
->display
, Drv
->screen
)
956 Drv
->depth
= DefaultDepth (Drv
->display
, Drv
->screen
);
957 XDefineCursor (Drv
->display
, Drv
->win
, XCreateFontCursor (Drv
->display
, XC_pirate
));
959 Drv
->Title
= malloc (StrSize (This
->ConfigString
));
960 UnicodeStrToAsciiStr (This
->ConfigString
, Drv
->Title
);
961 XStoreName (Drv
->display
, Drv
->win
, Drv
->Title
);
963 // XAutoRepeatOff (Drv->display);
965 Drv
->display
, Drv
->win
,
966 ExposureMask
| KeyPressMask
| KeyReleaseMask
| PointerMotionMask
| ButtonPressMask
| ButtonReleaseMask
968 Drv
->gc
= DefaultGC (Drv
->display
, Drv
->screen
);
970 This
->Private
= (VOID
*)Drv
;
971 This
->Interface
= (VOID
*)Drv
;
977 X11GraphicsWindowClose (
978 IN EMU_IO_THUNK_PROTOCOL
*This
981 GRAPHICS_IO_PRIVATE
*Drv
;
983 Drv
= (GRAPHICS_IO_PRIVATE
*)This
->Private
;
989 if (Drv
->image
!= NULL
) {
990 XDestroyImage(Drv
->image
);
993 shmdt (Drv
->image_data
);
996 Drv
->image_data
= NULL
;
999 XDestroyWindow (Drv
->display
, Drv
->win
);
1000 XCloseDisplay (Drv
->display
);
1003 // Free up the shared memory
1004 shmctl (Drv
->xshm_info
.shmid
, IPC_RMID
, NULL
);
1012 EMU_IO_THUNK_PROTOCOL gX11ThunkIo
= {
1013 &gEmuGraphicsWindowProtocolGuid
,
1017 GasketX11GraphicsWindowOpen
,
1018 GasketX11GraphicsWindowClose
,