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
33 struct uga_drv_shift_mask
{
41 EMU_GRAPHICS_WINDOW_PROTOCOL GraphicsIo
;
44 int screen
; /* values for window_size in main */
52 unsigned int line_bytes
;
53 unsigned int pixel_shift
;
54 unsigned char *image_data
;
56 struct uga_drv_shift_mask r
, g
, b
;
59 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
;
80 HandleEvents(GRAPHICS_IO_PRIVATE
*drv
);
83 fill_shift_mask (struct uga_drv_shift_mask
*sm
, unsigned long mask
)
87 while ((mask
& 1) == 0)
97 sm
->csize
= 8 - sm
->size
;
102 IN GRAPHICS_IO_PRIVATE
*drv
105 drv
->image
= XShmCreateImage (drv
->display
, drv
->visual
,
106 drv
->depth
, ZPixmap
, NULL
, &drv
->xshm_info
,
107 drv
->width
, drv
->height
);
108 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
,
126 if (drv
->xshm_info
.shmid
< 0) {
127 XDestroyImage(drv
->image
);
131 drv
->image_data
= shmat (drv
->xshm_info
.shmid
, NULL
, 0);
132 if(!drv
->image_data
) {
133 shmctl (drv
->xshm_info
.shmid
, IPC_RMID
, NULL
);
134 XDestroyImage(drv
->image
);
140 // This closes shared memory in real time on OS X. Only closes after folks quit using
143 /* Can this fail ? */
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
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
167 XSizeHints size_hints
;
169 /* Destroy current buffer if created. */
170 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
);
178 drv
->image_data
= NULL
;
183 drv
->height
= Height
;
184 XResizeWindow (drv
->display
, drv
->win
, Width
, Height
);
186 /* Allocate image. */
187 if (XShmQueryExtension(drv
->display
) && TryCreateShmImage(drv
)) {
192 drv
->pixel_shift
= 2;
193 else if (drv
->depth
> 8)
194 drv
->pixel_shift
= 1;
196 drv
->pixel_shift
= 0;
198 drv
->image_data
= malloc((drv
->width
* drv
->height
) << drv
->pixel_shift
);
199 drv
->image
= XCreateImage (drv
->display
, drv
->visual
, drv
->depth
,
200 ZPixmap
, 0, (char *)drv
->image_data
,
201 drv
->width
, drv
->height
,
202 8 << drv
->pixel_shift
, 0);
204 drv
->line_bytes
= drv
->image
->bytes_per_line
;
205 fill_shift_mask (&drv
->r
, drv
->image
->red_mask
);
206 fill_shift_mask (&drv
->g
, drv
->image
->green_mask
);
207 fill_shift_mask (&drv
->b
, drv
->image
->blue_mask
);
210 size_hints
.flags
= PSize
| PMinSize
| PMaxSize
;
211 size_hints
.min_width
= size_hints
.max_width
= size_hints
.base_width
= Width
;
212 size_hints
.min_height
= size_hints
.max_height
= size_hints
.base_height
= Height
;
213 XSetWMNormalHints (drv
->display
, drv
->win
, &size_hints
);
215 XMapWindow (drv
->display
, drv
->win
);
221 handleKeyEvent(GRAPHICS_IO_PRIVATE
*drv
, XEvent
*ev
, BOOLEAN Make
)
224 EFI_KEY_DATA KeyData
;
228 if (drv
->key_count
== NBR_KEYS
) {
233 // keycode is a physical key on the keyboard
234 // KeySym is a mapping of a physical key
235 // KeyboardMapping is the array of KeySym for a given keycode. key, shifted key, option key, command key, ...
237 // Returns an array of KeySymArraySize of KeySym for the keycode. [0] is lower case, [1] is upper case,
238 // [2] and [3] are based on option and command modifiers. The problem we have is command V
239 // could be mapped to a crazy Unicode character so the old scheme of returning a string.
241 KeySym
= XGetKeyboardMapping (drv
->display
, ev
->xkey
.keycode
, 1, &KeySymArraySize
);
243 KeyData
.Key
.ScanCode
= 0;
244 KeyData
.Key
.UnicodeChar
= 0;
245 KeyData
.KeyState
.KeyShiftState
= 0;
248 // Skipping EFI_SCROLL_LOCK_ACTIVE & EFI_NUM_LOCK_ACTIVE since they are not on Macs
250 if ((ev
->xkey
.state
& LockMask
) == 0) {
251 drv
->KeyState
.KeyToggleState
&= ~EFI_CAPS_LOCK_ACTIVE
;
254 drv
->KeyState
.KeyToggleState
|= EFI_CAPS_LOCK_ACTIVE
;
258 // Skipping EFI_MENU_KEY_PRESSED and EFI_SYS_REQ_PRESSED
263 drv
->KeyState
.KeyShiftState
|= EFI_RIGHT_CONTROL_PRESSED
;
265 drv
->KeyState
.KeyShiftState
&= ~EFI_RIGHT_CONTROL_PRESSED
;
270 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_CONTROL_PRESSED
;
272 drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_CONTROL_PRESSED
;
278 drv
->KeyState
.KeyShiftState
|= EFI_RIGHT_SHIFT_PRESSED
;
280 drv
->KeyState
.KeyShiftState
&= ~EFI_RIGHT_SHIFT_PRESSED
;
285 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_SHIFT_PRESSED
;
287 drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_SHIFT_PRESSED
;
293 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_ALT_PRESSED
;
295 drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_ALT_PRESSED
;
301 drv
->KeyState
.KeyShiftState
|= EFI_RIGHT_LOGO_PRESSED
;
303 drv
->KeyState
.KeyShiftState
&= ~EFI_RIGHT_LOGO_PRESSED
;
308 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_LOGO_PRESSED
;
310 drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_LOGO_PRESSED
;
315 case XK_Home
: KeyData
.Key
.ScanCode
= SCAN_HOME
; break;
318 case XK_End
: KeyData
.Key
.ScanCode
= SCAN_END
; break;
321 case XK_Left
: KeyData
.Key
.ScanCode
= SCAN_LEFT
; break;
324 case XK_Right
: KeyData
.Key
.ScanCode
= SCAN_RIGHT
; break;
327 case XK_Up
: KeyData
.Key
.ScanCode
= SCAN_UP
; break;
330 case XK_Down
: KeyData
.Key
.ScanCode
= SCAN_DOWN
; break;
333 case XK_Delete
: KeyData
.Key
.ScanCode
= SCAN_DELETE
; break;
336 case XK_Insert
: KeyData
.Key
.ScanCode
= SCAN_INSERT
; break;
339 case XK_Page_Up
: KeyData
.Key
.ScanCode
= SCAN_PAGE_UP
; break;
341 case XK_KP_Page_Down
:
342 case XK_Page_Down
: KeyData
.Key
.ScanCode
= SCAN_PAGE_DOWN
; break;
344 case XK_Escape
: KeyData
.Key
.ScanCode
= SCAN_ESC
; break;
346 case XK_Pause
: KeyData
.Key
.ScanCode
= SCAN_PAUSE
; break;
349 case XK_F1
: KeyData
.Key
.ScanCode
= SCAN_F1
; break;
352 case XK_F2
: KeyData
.Key
.ScanCode
= SCAN_F2
; break;
355 case XK_F3
: KeyData
.Key
.ScanCode
= SCAN_F3
; break;
358 case XK_F4
: KeyData
.Key
.ScanCode
= SCAN_F4
; break;
360 case XK_F5
: KeyData
.Key
.ScanCode
= SCAN_F5
; break;
361 case XK_F6
: KeyData
.Key
.ScanCode
= SCAN_F6
; break;
362 case XK_F7
: KeyData
.Key
.ScanCode
= SCAN_F7
; break;
364 // Don't map into X11 by default on a Mac
365 // System Preferences->Keyboard->Keyboard Shortcuts can be configured
366 // to not use higher function keys as shortcuts and the will show up
368 case XK_F8
: KeyData
.Key
.ScanCode
= SCAN_F8
; break;
369 case XK_F9
: KeyData
.Key
.ScanCode
= SCAN_F9
; break;
370 case XK_F10
: KeyData
.Key
.ScanCode
= SCAN_F10
; break;
372 case XK_F11
: KeyData
.Key
.ScanCode
= SCAN_F11
; break;
373 case XK_F12
: KeyData
.Key
.ScanCode
= SCAN_F12
; break;
375 case XK_F13
: KeyData
.Key
.ScanCode
= SCAN_F13
; break;
376 case XK_F14
: KeyData
.Key
.ScanCode
= SCAN_F14
; break;
377 case XK_F15
: KeyData
.Key
.ScanCode
= SCAN_F15
; break;
378 case XK_F16
: KeyData
.Key
.ScanCode
= SCAN_F16
; break;
379 case XK_F17
: KeyData
.Key
.ScanCode
= SCAN_F17
; break;
380 case XK_F18
: KeyData
.Key
.ScanCode
= SCAN_F18
; break;
381 case XK_F19
: KeyData
.Key
.ScanCode
= SCAN_F19
; break;
382 case XK_F20
: KeyData
.Key
.ScanCode
= SCAN_F20
; break;
383 case XK_F21
: KeyData
.Key
.ScanCode
= SCAN_F21
; break;
384 case XK_F22
: KeyData
.Key
.ScanCode
= SCAN_F22
; break;
385 case XK_F23
: KeyData
.Key
.ScanCode
= SCAN_F23
; break;
386 case XK_F24
: KeyData
.Key
.ScanCode
= SCAN_F24
; break;
389 //case XK_: KeyData.Key.ScanCode = SCAN_MUTE; break;
390 //case XK_: KeyData.Key.ScanCode = SCAN_VOLUME_UP; break;
391 //case XK_: KeyData.Key.ScanCode = SCAN_VOLUME_DOWN; break;
392 //case XK_: KeyData.Key.ScanCode = SCAN_BRIGHTNESS_UP; break;
393 //case XK_: KeyData.Key.ScanCode = SCAN_BRIGHTNESS_DOWN; break;
394 //case XK_: KeyData.Key.ScanCode = SCAN_SUSPEND; break;
395 //case XK_: KeyData.Key.ScanCode = SCAN_HIBERNATE; break;
396 //case XK_: KeyData.Key.ScanCode = SCAN_TOGGLE_DISPLAY; break;
397 //case XK_: KeyData.Key.ScanCode = SCAN_RECOVERY; break;
398 //case XK_: KeyData.Key.ScanCode = SCAN_EJECT; break;
400 case XK_BackSpace
: KeyData
.Key
.UnicodeChar
= 0x0008; break;
403 case XK_Tab
: KeyData
.Key
.UnicodeChar
= 0x0009; break;
405 case XK_Linefeed
: KeyData
.Key
.UnicodeChar
= 0x000a; break;
408 case XK_Return
: KeyData
.Key
.UnicodeChar
= 0x000d; break;
410 case XK_KP_Equal
: KeyData
.Key
.UnicodeChar
= L
'='; break;
411 case XK_KP_Multiply
: KeyData
.Key
.UnicodeChar
= L
'*'; break;
412 case XK_KP_Add
: KeyData
.Key
.UnicodeChar
= L
'+'; break;
413 case XK_KP_Separator
: KeyData
.Key
.UnicodeChar
= L
'~'; break;
414 case XK_KP_Subtract
: KeyData
.Key
.UnicodeChar
= L
'-'; break;
415 case XK_KP_Decimal
: KeyData
.Key
.UnicodeChar
= L
'.'; break;
416 case XK_KP_Divide
: KeyData
.Key
.UnicodeChar
= L
'/'; break;
418 case XK_KP_0
: KeyData
.Key
.UnicodeChar
= L
'0'; break;
419 case XK_KP_1
: KeyData
.Key
.UnicodeChar
= L
'1'; break;
420 case XK_KP_2
: KeyData
.Key
.UnicodeChar
= L
'2'; break;
421 case XK_KP_3
: KeyData
.Key
.UnicodeChar
= L
'3'; break;
422 case XK_KP_4
: KeyData
.Key
.UnicodeChar
= L
'4'; break;
423 case XK_KP_5
: KeyData
.Key
.UnicodeChar
= L
'5'; break;
424 case XK_KP_6
: KeyData
.Key
.UnicodeChar
= L
'6'; break;
425 case XK_KP_7
: KeyData
.Key
.UnicodeChar
= L
'7'; break;
426 case XK_KP_8
: KeyData
.Key
.UnicodeChar
= L
'8'; break;
427 case XK_KP_9
: KeyData
.Key
.UnicodeChar
= L
'9'; break;
433 // The global state is our state
434 KeyData
.KeyState
.KeyShiftState
= drv
->KeyState
.KeyShiftState
;
435 KeyData
.KeyState
.KeyToggleState
= drv
->KeyState
.KeyToggleState
;
437 if (*KeySym
< XK_BackSpace
) {
438 if (((drv
->KeyState
.KeyShiftState
& (EFI_LEFT_SHIFT_PRESSED
| EFI_RIGHT_SHIFT_PRESSED
)) != 0) ||
439 ((drv
->KeyState
.KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) != 0) ) {
441 KeyData
.Key
.UnicodeChar
= (CHAR16
)KeySym
[KEYSYM_UPPER
];
443 // Per UEFI spec since we converted the Unicode clear the shift bits we pass up
444 KeyData
.KeyState
.KeyShiftState
&= ~(EFI_LEFT_SHIFT_PRESSED
| EFI_RIGHT_SHIFT_PRESSED
);
446 KeyData
.Key
.UnicodeChar
= (CHAR16
)KeySym
[KEYSYM_LOWER
];
449 // XK_BackSpace is the start of XK_MISCELLANY. These are the XK_? keys we process in this file
454 memcpy (&drv
->keys
[drv
->key_wr
], &KeyData
, sizeof (EFI_KEY_DATA
));
455 drv
->key_wr
= (drv
->key_wr
+ 1) % NBR_KEYS
;
457 if (drv
->MakeRegisterdKeyCallback
!= NULL
) {
458 ReverseGasketUint64Uint64 (drv
->MakeRegisterdKeyCallback
,drv
->RegisterdKeyCallbackContext
, &KeyData
);
461 if (drv
->BreakRegisterdKeyCallback
!= NULL
) {
462 ReverseGasketUint64Uint64 (drv
->BreakRegisterdKeyCallback
,drv
->RegisterdKeyCallbackContext
, &KeyData
);
469 handleMouseMoved(GRAPHICS_IO_PRIVATE
*drv
, XEvent
*ev
)
471 if ( ev
->xmotion
.x
!= drv
->previous_x
)
473 drv
->pointer_state
.RelativeMovementX
+= ( ev
->xmotion
.x
- drv
->previous_x
);
474 drv
->previous_x
= ev
->xmotion
.x
;
475 drv
->pointer_state_changed
= 1;
478 if ( ev
->xmotion
.y
!= drv
->previous_y
)
480 drv
->pointer_state
.RelativeMovementY
+= ( ev
->xmotion
.y
- drv
->previous_y
);
481 drv
->previous_y
= ev
->xmotion
.y
;
482 drv
->pointer_state_changed
= 1;
485 drv
->pointer_state
.RelativeMovementZ
= 0;
489 handleMouseDown(GRAPHICS_IO_PRIVATE
*drv
, XEvent
*ev
, BOOLEAN Pressed
)
491 if ( ev
->xbutton
.button
== Button1
)
493 drv
->pointer_state_changed
= ( drv
->pointer_state
.LeftButton
!= Pressed
);
494 drv
->pointer_state
.LeftButton
= Pressed
;
496 if ( ev
->xbutton
.button
== Button2
)
498 drv
->pointer_state_changed
= ( drv
->pointer_state
.RightButton
!= Pressed
);
499 drv
->pointer_state
.RightButton
= Pressed
;
504 Redraw(GRAPHICS_IO_PRIVATE
*drv
, UINTN X
, UINTN Y
, UINTN Width
, UINTN Height
)
507 XShmPutImage (drv
->display
, drv
->win
, drv
->gc
, drv
->image
,
508 X
, Y
, X
, Y
, Width
, Height
, False
);
510 XPutImage (drv
->display
, drv
->win
, drv
->gc
, drv
->image
,
511 X
, Y
, X
, Y
, Width
, Height
);
512 XFlush(drv
->display
);
516 HandleEvent(GRAPHICS_IO_PRIVATE
*drv
, XEvent
*ev
)
521 Redraw(drv
, ev
->xexpose
.x
, ev
->xexpose
.y
,
522 ev
->xexpose
.width
, ev
->xexpose
.height
);
525 Redraw(drv
, ev
->xgraphicsexpose
.x
, ev
->xgraphicsexpose
.y
,
526 ev
->xgraphicsexpose
.width
, ev
->xgraphicsexpose
.height
);
529 handleKeyEvent(drv
, ev
, TRUE
);
532 handleKeyEvent(drv
, ev
, FALSE
);
535 XRefreshKeyboardMapping(&ev
->xmapping
);
538 handleMouseMoved(drv
, ev
);
541 handleMouseDown(drv
, ev
, TRUE
);
544 handleMouseDown(drv
, ev
, FALSE
);
548 XCloseDisplay (drv
->display
);
559 HandleEvents(GRAPHICS_IO_PRIVATE
*drv
)
561 while (XPending(drv
->display
) != 0)
565 XNextEvent (drv
->display
, &ev
);
566 HandleEvent(drv
, &ev
);
571 X11PixelToColor (GRAPHICS_IO_PRIVATE
*drv
, EFI_UGA_PIXEL pixel
)
573 return ((pixel
.Red
>> drv
->r
.csize
) << drv
->r
.shift
)
574 | ((pixel
.Green
>> drv
->g
.csize
) << drv
->g
.shift
)
575 | ((pixel
.Blue
>> drv
->b
.csize
) << drv
->b
.shift
);
579 X11ColorToPixel (GRAPHICS_IO_PRIVATE
*drv
, unsigned long val
)
583 memset (&res
, 0, sizeof (EFI_UGA_PIXEL
));
584 /* FIXME: should round instead of truncate. */
585 res
.Red
= (val
>> drv
->r
.shift
) << drv
->r
.csize
;
586 res
.Green
= (val
>> drv
->g
.shift
) << drv
->g
.csize
;
587 res
.Blue
= (val
>> drv
->b
.shift
) << drv
->b
.csize
;
593 CheckKeyInternal( GRAPHICS_IO_PRIVATE
*drv
, BOOLEAN delay
)
596 if (drv
->key_count
!= 0)
599 /* EFI is polling. Be CPU-friendly. */
601 return EFI_NOT_READY
;
605 X11CheckKey(EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
)
607 GRAPHICS_IO_PRIVATE
*drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
608 return CheckKeyInternal(drv
, TRUE
);
614 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
615 IN EFI_KEY_DATA
*KeyData
618 GRAPHICS_IO_PRIVATE
*drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
621 status
= CheckKeyInternal(drv
, FALSE
);
622 if (status
!= EFI_SUCCESS
)
625 CopyMem (KeyData
, &drv
->keys
[drv
->key_rd
], sizeof (EFI_KEY_DATA
));
626 drv
->key_rd
= (drv
->key_rd
+ 1) % NBR_KEYS
;
635 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
636 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
639 GRAPHICS_IO_PRIVATE
*drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
642 if (*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) {
643 if ((drv
->KeyState
.KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == 0) {
645 // We could create an XKeyEvent and send a XK_Caps_Lock to
646 // the UGA/GOP Window
651 drv
->KeyState
.KeyToggleState
= *KeyToggleState
;
658 X11RegisterKeyNotify (
659 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
660 IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeCallBack
,
661 IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakCallBack
,
665 GRAPHICS_IO_PRIVATE
*drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
667 drv
->MakeRegisterdKeyCallback
= MakeCallBack
;
668 drv
->BreakRegisterdKeyCallback
= BreakCallBack
;
669 drv
->RegisterdKeyCallbackContext
= Context
;
677 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
678 IN EFI_UGA_PIXEL
*BltBuffer OPTIONAL
,
679 IN EFI_UGA_BLT_OPERATION BltOperation
,
680 IN EMU_GRAPHICS_WINDOWS__BLT_ARGS
*Args
683 GRAPHICS_IO_PRIVATE
*Private
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
698 if (BltOperation
== EfiUgaVideoToBltBuffer
699 || BltOperation
== EfiUgaVideoToVideo
) {
703 if (Args
->SourceY
+ Args
->Height
> Private
->height
) {
704 return EFI_INVALID_PARAMETER
;
707 if (Args
->SourceX
+ Args
->Width
> Private
->width
) {
708 return EFI_INVALID_PARAMETER
;
712 if (BltOperation
== EfiUgaBltBufferToVideo
713 || BltOperation
== EfiUgaVideoToVideo
714 || BltOperation
== EfiUgaVideoFill
) {
716 // Destination is Video
718 if (Args
->DestinationY
+ Args
->Height
> Private
->height
) {
719 return EFI_INVALID_PARAMETER
;
722 if (Args
->DestinationX
+ Args
->Width
> Private
->width
) {
723 return EFI_INVALID_PARAMETER
;
727 switch (BltOperation
) {
728 case EfiUgaVideoToBltBuffer
:
729 Blt
= (EFI_UGA_PIXEL
*)((UINT8
*)BltBuffer
+ (Args
->DestinationY
* Args
->Delta
) + Args
->DestinationX
* sizeof (EFI_UGA_PIXEL
));
730 Args
->Delta
-= Args
->Width
* sizeof (EFI_UGA_PIXEL
);
731 for (SrcY
= Args
->SourceY
; SrcY
< (Args
->Height
+ Args
->SourceY
); SrcY
++) {
732 for (SrcX
= Args
->SourceX
; SrcX
< (Args
->Width
+ Args
->SourceX
); SrcX
++) {
733 *Blt
++ = X11ColorToPixel(Private
,
734 XGetPixel(Private
->image
, SrcX
, SrcY
));
736 Blt
= (EFI_UGA_PIXEL
*) ((UINT8
*) Blt
+ Args
->Delta
);
739 case EfiUgaBltBufferToVideo
:
740 Blt
= (EFI_UGA_PIXEL
*)((UINT8
*)BltBuffer
+ (Args
->SourceY
* Args
->Delta
) + Args
->SourceX
* sizeof (EFI_UGA_PIXEL
));
741 Args
->Delta
-= Args
->Width
* sizeof (EFI_UGA_PIXEL
);
742 for (DstY
= Args
->DestinationY
; DstY
< (Args
->Height
+ Args
->DestinationY
); DstY
++) {
743 for (DstX
= Args
->DestinationX
; DstX
< (Args
->Width
+ Args
->DestinationX
); DstX
++) {
744 XPutPixel(Private
->image
, DstX
, DstY
, X11PixelToColor(Private
, *Blt
));
747 Blt
= (EFI_UGA_PIXEL
*) ((UINT8
*) Blt
+ Args
->Delta
);
750 case EfiUgaVideoToVideo
:
751 Dst
= Private
->image_data
+ (Args
->DestinationX
<< Private
->pixel_shift
)
752 + Args
->DestinationY
* Private
->line_bytes
;
753 Src
= Private
->image_data
+ (Args
->SourceX
<< Private
->pixel_shift
)
754 + Args
->SourceY
* Private
->line_bytes
;
755 Nbr
= Args
->Width
<< Private
->pixel_shift
;
756 if (Args
->DestinationY
< Args
->SourceY
) {
757 for (Index
= 0; Index
< Args
->Height
; Index
++) {
758 memcpy (Dst
, Src
, Nbr
);
759 Dst
+= Private
->line_bytes
;
760 Src
+= Private
->line_bytes
;
764 Dst
+= (Args
->Height
- 1) * Private
->line_bytes
;
765 Src
+= (Args
->Height
- 1) * Private
->line_bytes
;
766 for (Index
= 0; Index
< Args
->Height
; Index
++) {
768 // Source and Destination Y may be equal, therefore Dst and Src may
771 memmove (Dst
, Src
, Nbr
);
772 Dst
-= Private
->line_bytes
;
773 Src
-= Private
->line_bytes
;
777 case EfiUgaVideoFill
:
778 Color
= X11PixelToColor(Private
, *BltBuffer
);
779 for (DstY
= Args
->DestinationY
; DstY
< (Args
->Height
+ Args
->DestinationY
); DstY
++) {
780 for (DstX
= Args
->DestinationX
; DstX
< (Args
->Width
+ Args
->DestinationX
); DstX
++) {
781 XPutPixel(Private
->image
, DstX
, DstY
, Color
);
786 return EFI_INVALID_PARAMETER
;
792 switch (BltOperation
) {
793 case EfiUgaVideoToVideo
:
794 XCopyArea(Private
->display
, Private
->win
, Private
->win
, Private
->gc
,
795 Args
->SourceX
, Args
->SourceY
, Args
->Width
, Args
->Height
, Args
->DestinationX
, Args
->DestinationY
);
799 XNextEvent (Private
->display
, &ev
);
800 HandleEvent(Private
, &ev
);
801 if (ev
.type
== NoExpose
|| ev
.type
== GraphicsExpose
)
805 case EfiUgaVideoFill
:
806 Color
= X11PixelToColor(Private
, *BltBuffer
);
807 XSetForeground(Private
->display
, Private
->gc
, Color
);
808 XFillRectangle(Private
->display
, Private
->win
, Private
->gc
,
809 Args
->DestinationX
, Args
->DestinationY
, Args
->Width
, Args
->Height
);
810 XFlush(Private
->display
);
812 case EfiUgaBltBufferToVideo
:
813 Redraw(Private
, Args
->DestinationX
, Args
->DestinationY
, Args
->Width
, Args
->Height
);
822 CheckPointerInternal( GRAPHICS_IO_PRIVATE
*drv
, BOOLEAN delay
)
825 if (drv
->pointer_state_changed
!= 0)
828 /* EFI is polling. Be CPU-friendly. */
830 return EFI_NOT_READY
;
834 X11CheckPointer(EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
)
836 GRAPHICS_IO_PRIVATE
*drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
837 return( CheckPointerInternal( drv
, TRUE
) );
841 X11GetPointerState (EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
, EFI_SIMPLE_POINTER_STATE
*state
)
843 GRAPHICS_IO_PRIVATE
*drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
846 status
= CheckPointerInternal( drv
, FALSE
);
847 if (status
!= EFI_SUCCESS
)
850 memcpy( state
, &drv
->pointer_state
, sizeof( EFI_SIMPLE_POINTER_STATE
) );
852 drv
->pointer_state
.RelativeMovementX
= 0;
853 drv
->pointer_state
.RelativeMovementY
= 0;
854 drv
->pointer_state
.RelativeMovementZ
= 0;
855 drv
->pointer_state_changed
= 0;
862 X11GraphicsWindowOpen (
863 IN EMU_IO_THUNK_PROTOCOL
*This
866 GRAPHICS_IO_PRIVATE
*drv
;
867 unsigned int border_width
= 0;
868 char *display_name
= NULL
;
871 drv
= (GRAPHICS_IO_PRIVATE
*)calloc (1, sizeof (GRAPHICS_IO_PRIVATE
));
873 return EFI_OUT_OF_RESOURCES
;
875 drv
->GraphicsIo
.Size
= GasketX11Size
;
876 drv
->GraphicsIo
.CheckKey
= GasketX11CheckKey
;
877 drv
->GraphicsIo
.GetKey
= GasketX11GetKey
;
878 drv
->GraphicsIo
.KeySetState
= GasketX11KeySetState
;
879 drv
->GraphicsIo
.RegisterKeyNotify
= GasketX11RegisterKeyNotify
;
880 drv
->GraphicsIo
.Blt
= GasketX11Blt
;
881 drv
->GraphicsIo
.CheckPointer
= GasketX11CheckPointer
;
882 drv
->GraphicsIo
.GetPointerState
= GasketX11GetPointerState
;
888 drv
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
889 drv
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
890 drv
->MakeRegisterdKeyCallback
= NULL
;
891 drv
->BreakRegisterdKeyCallback
= NULL
;
892 drv
->RegisterdKeyCallbackContext
= NULL
;
895 drv
->display
= XOpenDisplay (display_name
);
896 if (drv
->display
== NULL
) {
897 fprintf (stderr
, "uga: cannot connect to X server %s\n", XDisplayName (display_name
));
899 return EFI_DEVICE_ERROR
;
901 drv
->screen
= DefaultScreen (drv
->display
);
902 drv
->visual
= DefaultVisual (drv
->display
, drv
->screen
);
903 drv
->win
= XCreateSimpleWindow
904 (drv
->display
, RootWindow (drv
->display
, drv
->screen
),
905 0, 0, 4, 4, border_width
,
906 WhitePixel (drv
->display
, drv
->screen
),
907 BlackPixel (drv
->display
, drv
->screen
));
909 drv
->depth
= DefaultDepth (drv
->display
, drv
->screen
);
910 XDefineCursor (drv
->display
, drv
->win
, XCreateFontCursor (drv
->display
, XC_pirate
));
912 /* Compute title len and convert to Ascii. */
913 for (title_len
= 0; This
->ConfigString
[title_len
] != 0; title_len
++)
916 char title
[title_len
+ 1];
918 for (i
= 0; i
< title_len
; i
++)
919 title
[i
] = This
->ConfigString
[i
];
922 XStoreName (drv
->display
, drv
->win
, title
);
925 // XAutoRepeatOff (drv->display);
926 XSelectInput (drv
->display
, drv
->win
,
927 ExposureMask
| KeyPressMask
| KeyReleaseMask
| PointerMotionMask
| ButtonPressMask
| ButtonReleaseMask
);
928 drv
->gc
= DefaultGC (drv
->display
, drv
->screen
);
930 This
->Private
= (VOID
*)drv
;
931 This
->Interface
= (VOID
*)drv
;
937 X11GraphicsWindowClose (
938 IN EMU_IO_THUNK_PROTOCOL
*This
941 GRAPHICS_IO_PRIVATE
*drv
= (GRAPHICS_IO_PRIVATE
*)This
->Private
;
945 if (drv
->image
!= NULL
)
947 XDestroyImage(drv
->image
);
950 shmdt (drv
->image_data
);
952 drv
->image_data
= NULL
;
955 XDestroyWindow(drv
->display
, drv
->win
);
956 XCloseDisplay(drv
->display
);
959 // Free up the shared memory
960 shmctl (drv
->xshm_info
.shmid
, IPC_RMID
, NULL
);
968 EMU_IO_THUNK_PROTOCOL gX11ThunkIo
= {
969 &gEmuGraphicsWindowProtocolGuid
,
973 GasketX11GraphicsWindowOpen
,
974 GasketX11GraphicsWindowClose
,