3 Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
4 Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
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
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.
22 #include <X11/Xutil.h>
24 #include <X11/extensions/XShm.h>
25 #include <X11/keysym.h>
26 #include <X11/cursorfont.h>
28 #define KEYSYM_LOWER 0
29 #define KEYSYM_UPPER 1
32 struct uga_drv_shift_mask
{
40 EMU_GRAPHICS_WINDOW_PROTOCOL GraphicsIo
;
43 int screen
; // values for window_size in main
51 unsigned int line_bytes
;
52 unsigned int pixel_shift
;
53 unsigned char *image_data
;
55 struct uga_drv_shift_mask r
, g
, b
;
58 XShmSegmentInfo xshm_info
;
64 unsigned int key_count
;
65 EFI_KEY_DATA keys
[NBR_KEYS
];
67 EFI_KEY_STATE KeyState
;
69 EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeRegisterdKeyCallback
;
70 EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakRegisterdKeyCallback
;
71 VOID
*RegisterdKeyCallbackContext
;
75 EFI_SIMPLE_POINTER_STATE pointer_state
;
76 int pointer_state_changed
;
77 } GRAPHICS_IO_PRIVATE
;
81 IN GRAPHICS_IO_PRIVATE
*Drv
86 IN
struct uga_drv_shift_mask
*sm
,
92 while ((mask
& 1) == 0) {
100 sm
->csize
= 8 - sm
->size
;
105 IN GRAPHICS_IO_PRIVATE
*Drv
108 Drv
->image
= XShmCreateImage (
109 Drv
->display
, Drv
->visual
,
110 Drv
->depth
, ZPixmap
, NULL
, &Drv
->xshm_info
,
111 Drv
->width
, Drv
->height
113 if (Drv
->image
== NULL
) {
117 switch (Drv
->image
->bitmap_unit
) {
119 Drv
->pixel_shift
= 2;
122 Drv
->pixel_shift
= 1;
125 Drv
->pixel_shift
= 0;
129 Drv
->xshm_info
.shmid
= shmget (
130 IPC_PRIVATE
, Drv
->image
->bytes_per_line
* Drv
->image
->height
,
133 if (Drv
->xshm_info
.shmid
< 0) {
134 XDestroyImage(Drv
->image
);
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
);
147 // This closes shared memory in real time on OS X. Only closes after folks quit using
150 shmctl (Drv
->xshm_info
.shmid
, IPC_RMID
, NULL
);
153 Drv
->xshm_info
.shmaddr
= (char*)Drv
->image_data
;
154 Drv
->image
->data
= (char*)Drv
->image_data
;
156 if (!XShmAttach (Drv
->display
, &Drv
->xshm_info
)) {
157 shmdt (Drv
->image_data
);
158 XDestroyImage(Drv
->image
);
167 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
172 GRAPHICS_IO_PRIVATE
*Drv
;
173 XSizeHints size_hints
;
175 // Destroy current buffer if created.
176 Drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
177 if (Drv
->image
!= NULL
) {
178 // Before destroy buffer, need to make sure the buffer available for access.
179 XDestroyImage (Drv
->image
);
182 shmdt (Drv
->image_data
);
185 Drv
->image_data
= NULL
;
190 Drv
->height
= Height
;
191 XResizeWindow (Drv
->display
, Drv
->win
, Width
, Height
);
194 if (XShmQueryExtension(Drv
->display
) && TryCreateShmImage(Drv
)) {
198 if (Drv
->depth
> 16) {
199 Drv
->pixel_shift
= 2;
200 } else if (Drv
->depth
> 8) {
201 Drv
->pixel_shift
= 1;
203 Drv
->pixel_shift
= 0;
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
215 Drv
->line_bytes
= Drv
->image
->bytes_per_line
;
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
);
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
;
225 XSetWMNormalHints (Drv
->display
, Drv
->win
, &size_hints
);
227 XMapWindow (Drv
->display
, Drv
->win
);
234 IN GRAPHICS_IO_PRIVATE
*Drv
,
240 EFI_KEY_DATA KeyData
;
244 if (Drv
->key_count
== NBR_KEYS
) {
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, ...
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
255 // could be mapped to a crazy Unicode character so the old scheme of returning a string.
257 KeySym
= XGetKeyboardMapping (Drv
->display
, ev
->xkey
.keycode
, 1, &KeySymArraySize
);
259 KeyData
.Key
.ScanCode
= 0;
260 KeyData
.Key
.UnicodeChar
= 0;
261 KeyData
.KeyState
.KeyShiftState
= 0;
264 // Skipping EFI_SCROLL_LOCK_ACTIVE & EFI_NUM_LOCK_ACTIVE since they are not on Macs
266 if ((ev
->xkey
.state
& LockMask
) == 0) {
267 Drv
->KeyState
.KeyToggleState
&= ~EFI_CAPS_LOCK_ACTIVE
;
270 Drv
->KeyState
.KeyToggleState
|= EFI_CAPS_LOCK_ACTIVE
;
274 // Skipping EFI_MENU_KEY_PRESSED and EFI_SYS_REQ_PRESSED
279 Drv
->KeyState
.KeyShiftState
|= EFI_RIGHT_CONTROL_PRESSED
;
281 Drv
->KeyState
.KeyShiftState
&= ~EFI_RIGHT_CONTROL_PRESSED
;
286 Drv
->KeyState
.KeyShiftState
|= EFI_LEFT_CONTROL_PRESSED
;
288 Drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_CONTROL_PRESSED
;
294 Drv
->KeyState
.KeyShiftState
|= EFI_RIGHT_SHIFT_PRESSED
;
296 Drv
->KeyState
.KeyShiftState
&= ~EFI_RIGHT_SHIFT_PRESSED
;
301 Drv
->KeyState
.KeyShiftState
|= EFI_LEFT_SHIFT_PRESSED
;
303 Drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_SHIFT_PRESSED
;
309 Drv
->KeyState
.KeyShiftState
|= EFI_LEFT_ALT_PRESSED
;
311 Drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_ALT_PRESSED
;
317 Drv
->KeyState
.KeyShiftState
|= EFI_RIGHT_LOGO_PRESSED
;
319 Drv
->KeyState
.KeyShiftState
&= ~EFI_RIGHT_LOGO_PRESSED
;
324 Drv
->KeyState
.KeyShiftState
|= EFI_LEFT_LOGO_PRESSED
;
326 Drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_LOGO_PRESSED
;
331 case XK_Home
: KeyData
.Key
.ScanCode
= SCAN_HOME
; break;
334 case XK_End
: KeyData
.Key
.ScanCode
= SCAN_END
; break;
337 case XK_Left
: KeyData
.Key
.ScanCode
= SCAN_LEFT
; break;
340 case XK_Right
: KeyData
.Key
.ScanCode
= SCAN_RIGHT
; break;
343 case XK_Up
: KeyData
.Key
.ScanCode
= SCAN_UP
; break;
346 case XK_Down
: KeyData
.Key
.ScanCode
= SCAN_DOWN
; break;
349 case XK_Delete
: KeyData
.Key
.ScanCode
= SCAN_DELETE
; break;
352 case XK_Insert
: KeyData
.Key
.ScanCode
= SCAN_INSERT
; break;
355 case XK_Page_Up
: KeyData
.Key
.ScanCode
= SCAN_PAGE_UP
; break;
357 case XK_KP_Page_Down
:
358 case XK_Page_Down
: KeyData
.Key
.ScanCode
= SCAN_PAGE_DOWN
; break;
360 case XK_Escape
: KeyData
.Key
.ScanCode
= SCAN_ESC
; break;
362 case XK_Pause
: KeyData
.Key
.ScanCode
= SCAN_PAUSE
; break;
365 case XK_F1
: KeyData
.Key
.ScanCode
= SCAN_F1
; break;
368 case XK_F2
: KeyData
.Key
.ScanCode
= SCAN_F2
; break;
371 case XK_F3
: KeyData
.Key
.ScanCode
= SCAN_F3
; break;
374 case XK_F4
: KeyData
.Key
.ScanCode
= SCAN_F4
; break;
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;
380 // Don't map into X11 by default on a Mac
381 // System Preferences->Keyboard->Keyboard Shortcuts can be configured
382 // to not use higher function keys as shortcuts and the will show up
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;
388 case XK_F11
: KeyData
.Key
.ScanCode
= SCAN_F11
; break;
389 case XK_F12
: KeyData
.Key
.ScanCode
= SCAN_F12
; break;
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;
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;
416 case XK_BackSpace
: KeyData
.Key
.UnicodeChar
= 0x0008; break;
419 case XK_Tab
: KeyData
.Key
.UnicodeChar
= 0x0009; break;
421 case XK_Linefeed
: KeyData
.Key
.UnicodeChar
= 0x000a; break;
424 case XK_Return
: KeyData
.Key
.UnicodeChar
= 0x000d; break;
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;
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;
449 // The global state is our state
450 KeyData
.KeyState
.KeyShiftState
= Drv
->KeyState
.KeyShiftState
;
451 KeyData
.KeyState
.KeyToggleState
= Drv
->KeyState
.KeyToggleState
;
453 if (*KeySym
< XK_BackSpace
) {
454 if (((Drv
->KeyState
.KeyShiftState
& (EFI_LEFT_SHIFT_PRESSED
| EFI_RIGHT_SHIFT_PRESSED
)) != 0) ||
455 ((Drv
->KeyState
.KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) != 0) ) {
457 KeyData
.Key
.UnicodeChar
= (CHAR16
)KeySym
[KEYSYM_UPPER
];
459 // Per UEFI spec since we converted the Unicode clear the shift bits we pass up
460 KeyData
.KeyState
.KeyShiftState
&= ~(EFI_LEFT_SHIFT_PRESSED
| EFI_RIGHT_SHIFT_PRESSED
);
462 KeyData
.Key
.UnicodeChar
= (CHAR16
)KeySym
[KEYSYM_LOWER
];
465 // XK_BackSpace is the start of XK_MISCELLANY. These are the XK_? keys we process in this file
470 memcpy (&Drv
->keys
[Drv
->key_wr
], &KeyData
, sizeof (EFI_KEY_DATA
));
471 Drv
->key_wr
= (Drv
->key_wr
+ 1) % NBR_KEYS
;
473 if (Drv
->MakeRegisterdKeyCallback
!= NULL
) {
474 ReverseGasketUint64Uint64 (Drv
->MakeRegisterdKeyCallback
,Drv
->RegisterdKeyCallbackContext
, &KeyData
);
477 if (Drv
->BreakRegisterdKeyCallback
!= NULL
) {
478 ReverseGasketUint64Uint64 (Drv
->BreakRegisterdKeyCallback
,Drv
->RegisterdKeyCallbackContext
, &KeyData
);
486 IN GRAPHICS_IO_PRIVATE
*Drv
,
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;
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;
502 Drv
->pointer_state
.RelativeMovementZ
= 0;
507 IN GRAPHICS_IO_PRIVATE
*Drv
,
512 if (ev
->xbutton
.button
== Button1
) {
513 Drv
->pointer_state_changed
= (Drv
->pointer_state
.LeftButton
!= Pressed
);
514 Drv
->pointer_state
.LeftButton
= Pressed
;
516 if ( ev
->xbutton
.button
== Button2
) {
517 Drv
->pointer_state_changed
= (Drv
->pointer_state
.RightButton
!= Pressed
);
518 Drv
->pointer_state
.RightButton
= Pressed
;
524 IN GRAPHICS_IO_PRIVATE
*Drv
,
533 Drv
->display
, Drv
->win
, Drv
->gc
, Drv
->image
, X
, Y
, X
, Y
, Width
, Height
, False
537 Drv
->display
, Drv
->win
, Drv
->gc
, Drv
->image
, X
, Y
, X
, Y
, Width
, Height
540 XFlush(Drv
->display
);
544 HandleEvent(GRAPHICS_IO_PRIVATE
*Drv
, XEvent
*ev
)
548 Redraw (Drv
, ev
->xexpose
.x
, ev
->xexpose
.y
,
549 ev
->xexpose
.width
, ev
->xexpose
.height
);
552 Redraw (Drv
, ev
->xgraphicsexpose
.x
, ev
->xgraphicsexpose
.y
,
553 ev
->xgraphicsexpose
.width
, ev
->xgraphicsexpose
.height
);
556 handleKeyEvent (Drv
, ev
, TRUE
);
559 handleKeyEvent (Drv
, ev
, FALSE
);
562 XRefreshKeyboardMapping (&ev
->xmapping
);
565 handleMouseMoved (Drv
, ev
);
568 handleMouseDown (Drv
, ev
, TRUE
);
571 handleMouseDown (Drv
, ev
, FALSE
);
575 XCloseDisplay (Drv
->display
);
587 IN GRAPHICS_IO_PRIVATE
*Drv
592 while (XPending (Drv
->display
) != 0) {
593 XNextEvent (Drv
->display
, &ev
);
594 HandleEvent (Drv
, &ev
);
600 IN GRAPHICS_IO_PRIVATE
*Drv
,
601 IN EFI_UGA_PIXEL pixel
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
);
611 IN GRAPHICS_IO_PRIVATE
*Drv
,
617 memset (&Pixel
, 0, sizeof (EFI_UGA_PIXEL
));
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
;
630 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
633 GRAPHICS_IO_PRIVATE
*Drv
;
635 Drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
639 if (Drv
->key_count
!= 0) {
643 return EFI_NOT_READY
;
648 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
649 IN EFI_KEY_DATA
*KeyData
652 EFI_STATUS EfiStatus
;
653 GRAPHICS_IO_PRIVATE
*Drv
;
655 Drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
657 EfiStatus
= X11CheckKey (GraphicsIo
);
658 if (EFI_ERROR (EfiStatus
)) {
662 CopyMem (KeyData
, &Drv
->keys
[Drv
->key_rd
], sizeof (EFI_KEY_DATA
));
663 Drv
->key_rd
= (Drv
->key_rd
+ 1) % NBR_KEYS
;
672 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
673 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
676 GRAPHICS_IO_PRIVATE
*Drv
;
678 Drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
680 if (*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) {
681 if ((Drv
->KeyState
.KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == 0) {
683 // We could create an XKeyEvent and send a XK_Caps_Lock to
684 // the UGA/GOP Window
689 Drv
->KeyState
.KeyToggleState
= *KeyToggleState
;
695 X11RegisterKeyNotify (
696 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
697 IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeCallBack
,
698 IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakCallBack
,
702 GRAPHICS_IO_PRIVATE
*Drv
;
704 Drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
706 Drv
->MakeRegisterdKeyCallback
= MakeCallBack
;
707 Drv
->BreakRegisterdKeyCallback
= BreakCallBack
;
708 Drv
->RegisterdKeyCallbackContext
= Context
;
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
722 GRAPHICS_IO_PRIVATE
*Private
;
735 Private
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
741 if (BltOperation
== EfiUgaVideoToBltBuffer
742 || BltOperation
== EfiUgaVideoToVideo
) {
746 if (Args
->SourceY
+ Args
->Height
> Private
->height
) {
747 return EFI_INVALID_PARAMETER
;
750 if (Args
->SourceX
+ Args
->Width
> Private
->width
) {
751 return EFI_INVALID_PARAMETER
;
755 if (BltOperation
== EfiUgaBltBufferToVideo
756 || BltOperation
== EfiUgaVideoToVideo
757 || BltOperation
== EfiUgaVideoFill
) {
759 // Destination is Video
761 if (Args
->DestinationY
+ Args
->Height
> Private
->height
) {
762 return EFI_INVALID_PARAMETER
;
765 if (Args
->DestinationX
+ Args
->Width
> Private
->width
) {
766 return EFI_INVALID_PARAMETER
;
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
++) {
776 *Blt
++ = X11ColorToPixel (Private
, XGetPixel (Private
->image
, SrcX
, SrcY
));
778 Blt
= (EFI_UGA_PIXEL
*) ((UINT8
*) Blt
+ Args
->Delta
);
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
));
789 Blt
= (EFI_UGA_PIXEL
*) ((UINT8
*) Blt
+ Args
->Delta
);
792 case EfiUgaVideoToVideo
:
793 Dst
= Private
->image_data
+ (Args
->DestinationX
<< Private
->pixel_shift
)
794 + Args
->DestinationY
* Private
->line_bytes
;
795 Src
= Private
->image_data
+ (Args
->SourceX
<< Private
->pixel_shift
)
796 + Args
->SourceY
* Private
->line_bytes
;
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
;
805 Dst
+= (Args
->Height
- 1) * Private
->line_bytes
;
806 Src
+= (Args
->Height
- 1) * Private
->line_bytes
;
807 for (Index
= 0; Index
< Args
->Height
; Index
++) {
809 // Source and Destination Y may be equal, therefore Dst and Src may
812 memmove (Dst
, Src
, Nbr
);
813 Dst
-= Private
->line_bytes
;
814 Src
-= Private
->line_bytes
;
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
);
827 return EFI_INVALID_PARAMETER
;
833 switch (BltOperation
) {
834 case EfiUgaVideoToVideo
:
836 Private
->display
, Private
->win
, Private
->win
, Private
->gc
,
837 Args
->SourceX
, Args
->SourceY
, Args
->Width
, Args
->Height
,
838 Args
->DestinationX
, Args
->DestinationY
842 XNextEvent (Private
->display
, &ev
);
843 HandleEvent (Private
, &ev
);
844 if (ev
.type
== NoExpose
|| ev
.type
== GraphicsExpose
) {
849 case EfiUgaVideoFill
:
850 Color
= X11PixelToColor (Private
, *BltBuffer
);
851 XSetForeground (Private
->display
, Private
->gc
, Color
);
853 Private
->display
, Private
->win
, Private
->gc
,
854 Args
->DestinationX
, Args
->DestinationY
, Args
->Width
, Args
->Height
856 XFlush (Private
->display
);
858 case EfiUgaBltBufferToVideo
:
859 Redraw (Private
, Args
->DestinationX
, Args
->DestinationY
, Args
->Width
, Args
->Height
);
870 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
873 GRAPHICS_IO_PRIVATE
*Drv
;
875 Drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
878 if (Drv
->pointer_state_changed
!= 0) {
882 return EFI_NOT_READY
;
888 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
889 IN EFI_SIMPLE_POINTER_STATE
*State
892 EFI_STATUS EfiStatus
;
893 GRAPHICS_IO_PRIVATE
*Drv
;
895 Drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
897 EfiStatus
= X11CheckPointer (GraphicsIo
);
898 if (EfiStatus
!= EFI_SUCCESS
) {
902 memcpy (State
, &Drv
->pointer_state
, sizeof (EFI_SIMPLE_POINTER_STATE
));
904 Drv
->pointer_state
.RelativeMovementX
= 0;
905 Drv
->pointer_state
.RelativeMovementY
= 0;
906 Drv
->pointer_state
.RelativeMovementZ
= 0;
907 Drv
->pointer_state_changed
= 0;
914 X11GraphicsWindowOpen (
915 IN EMU_IO_THUNK_PROTOCOL
*This
918 GRAPHICS_IO_PRIVATE
*Drv
;
919 unsigned int border_width
= 0;
920 char *display_name
= NULL
;
922 Drv
= (GRAPHICS_IO_PRIVATE
*)calloc (1, sizeof (GRAPHICS_IO_PRIVATE
));
924 return EFI_OUT_OF_RESOURCES
;
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
;
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
;
947 Drv
->display
= XOpenDisplay (display_name
);
948 if (Drv
->display
== NULL
) {
949 fprintf (stderr
, "uga: cannot connect to X server %s\n", XDisplayName (display_name
));
951 return EFI_DEVICE_ERROR
;
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
),
957 0, 0, 4, 4, border_width
,
958 WhitePixel (Drv
->display
, Drv
->screen
),
959 BlackPixel (Drv
->display
, Drv
->screen
)
962 Drv
->depth
= DefaultDepth (Drv
->display
, Drv
->screen
);
963 XDefineCursor (Drv
->display
, Drv
->win
, XCreateFontCursor (Drv
->display
, XC_pirate
));
965 Drv
->Title
= malloc (StrSize (This
->ConfigString
));
966 UnicodeStrToAsciiStr (This
->ConfigString
, Drv
->Title
);
967 XStoreName (Drv
->display
, Drv
->win
, Drv
->Title
);
969 // XAutoRepeatOff (Drv->display);
971 Drv
->display
, Drv
->win
,
972 ExposureMask
| KeyPressMask
| KeyReleaseMask
| PointerMotionMask
| ButtonPressMask
| ButtonReleaseMask
974 Drv
->gc
= DefaultGC (Drv
->display
, Drv
->screen
);
976 This
->Private
= (VOID
*)Drv
;
977 This
->Interface
= (VOID
*)Drv
;
983 X11GraphicsWindowClose (
984 IN EMU_IO_THUNK_PROTOCOL
*This
987 GRAPHICS_IO_PRIVATE
*Drv
;
989 Drv
= (GRAPHICS_IO_PRIVATE
*)This
->Private
;
995 if (Drv
->image
!= NULL
) {
996 XDestroyImage(Drv
->image
);
999 shmdt (Drv
->image_data
);
1002 Drv
->image_data
= NULL
;
1005 XDestroyWindow (Drv
->display
, Drv
->win
);
1006 XCloseDisplay (Drv
->display
);
1009 // Free up the shared memory
1010 shmctl (Drv
->xshm_info
.shmid
, IPC_RMID
, NULL
);
1018 EMU_IO_THUNK_PROTOCOL gX11ThunkIo
= {
1019 &gEmuGraphicsWindowProtocolGuid
,
1023 GasketX11GraphicsWindowOpen
,
1024 GasketX11GraphicsWindowClose
,