3 Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>
4 Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 #include <Common/UnixInclude.h>
20 #include <Protocol/SimplePointer.h>
21 #include <Protocol/SimpleTextIn.h>
22 #include <Protocol/SimpleTextInEx.h>
23 #include <Protocol/UgaDraw.h>
25 #include <X11/Xutil.h>
27 #include <X11/extensions/XShm.h>
28 #include <X11/keysym.h>
29 #include <X11/cursorfont.h>
31 #include <Protocol/UnixThunk.h>
32 #include <Protocol/UnixUgaIo.h>
34 #include <Ppi/StatusCode.h>
36 #include <Library/PeCoffLib.h>
37 #include <Library/BaseLib.h>
38 #include <Library/BaseMemoryLib.h>
39 #include <Library/PrintLib.h>
40 #include <Library/PcdLib.h>
41 #include <Library/DebugLib.h>
47 extern void msSleep (unsigned long Milliseconds
);
51 struct uga_drv_shift_mask
{
59 EFI_UNIX_UGA_IO_PROTOCOL UgaIo
;
62 int screen
; /* values for window_size in main */
70 unsigned int line_bytes
;
71 unsigned int pixel_shift
;
72 unsigned char *image_data
;
74 struct uga_drv_shift_mask r
, g
, b
;
77 XShmSegmentInfo xshm_info
;
82 unsigned int key_count
;
83 EFI_KEY_DATA keys
[NBR_KEYS
];
85 EFI_KEY_STATE KeyState
;
87 UGA_REGISTER_KEY_NOTIFY_CALLBACK RegisterdKeyCallback
;
88 VOID
*RegisterdKeyCallbackContext
;
92 EFI_SIMPLE_POINTER_STATE pointer_state
;
93 int pointer_state_changed
;
97 HandleEvents(UGA_IO_PRIVATE
*drv
);
100 fill_shift_mask (struct uga_drv_shift_mask
*sm
, unsigned long mask
)
104 while ((mask
& 1) == 0)
114 sm
->csize
= 8 - sm
->size
;
118 TryCreateShmImage(UGA_IO_PRIVATE
*drv
)
120 drv
->image
= XShmCreateImage (drv
->display
, drv
->visual
,
121 drv
->depth
, ZPixmap
, NULL
, &drv
->xshm_info
,
122 drv
->width
, drv
->height
);
123 if (drv
->image
== NULL
)
126 switch (drv
->image
->bitmap_unit
) {
128 drv
->pixel_shift
= 2;
131 drv
->pixel_shift
= 1;
134 drv
->pixel_shift
= 0;
138 drv
->xshm_info
.shmid
= shmget
139 (IPC_PRIVATE
, drv
->image
->bytes_per_line
* drv
->image
->height
,
141 if (drv
->xshm_info
.shmid
< 0) {
142 XDestroyImage(drv
->image
);
146 drv
->image_data
= shmat (drv
->xshm_info
.shmid
, NULL
, 0);
147 if(!drv
->image_data
) {
148 shmctl (drv
->xshm_info
.shmid
, IPC_RMID
, NULL
);
149 XDestroyImage(drv
->image
);
155 // This closes shared memory in real time on OS X. Only closes after folks quit using
158 /* Can this fail ? */
159 shmctl (drv
->xshm_info
.shmid
, IPC_RMID
, NULL
);
162 drv
->xshm_info
.shmaddr
= (char*)drv
->image_data
;
163 drv
->image
->data
= (char*)drv
->image_data
;
165 if (!XShmAttach (drv
->display
, &drv
->xshm_info
)) {
166 shmdt (drv
->image_data
);
167 XDestroyImage(drv
->image
);
174 UgaClose (EFI_UNIX_UGA_IO_PROTOCOL
*UgaIo
)
176 UGA_IO_PRIVATE
*drv
= (UGA_IO_PRIVATE
*)UgaIo
;
180 if (drv
->image
!= NULL
)
182 XDestroyImage(drv
->image
);
185 shmdt (drv
->image_data
);
187 drv
->image_data
= NULL
;
190 XDestroyWindow(drv
->display
, drv
->win
);
191 XCloseDisplay(drv
->display
);
194 // Free up the shared memory
195 shmctl (drv
->xshm_info
.shmid
, IPC_RMID
, NULL
);
203 UgaSize(EFI_UNIX_UGA_IO_PROTOCOL
*UgaIo
, UINT32 Width
, UINT32 Height
)
205 UGA_IO_PRIVATE
*drv
= (UGA_IO_PRIVATE
*)UgaIo
;
206 XSizeHints size_hints
;
208 /* Destroy current buffer if created. */
209 if (drv
->image
!= NULL
)
211 /* Before destroy buffer, need to make sure the buffer available for access. */
212 XDestroyImage(drv
->image
);
215 shmdt (drv
->image_data
);
217 drv
->image_data
= NULL
;
222 drv
->height
= Height
;
223 XResizeWindow (drv
->display
, drv
->win
, Width
, Height
);
225 /* Allocate image. */
226 if (XShmQueryExtension(drv
->display
) && TryCreateShmImage(drv
)) {
231 drv
->pixel_shift
= 2;
232 else if (drv
->depth
> 8)
233 drv
->pixel_shift
= 1;
235 drv
->pixel_shift
= 0;
237 drv
->image_data
= malloc((drv
->width
* drv
->height
) << drv
->pixel_shift
);
238 drv
->image
= XCreateImage (drv
->display
, drv
->visual
, drv
->depth
,
239 ZPixmap
, 0, (char *)drv
->image_data
,
240 drv
->width
, drv
->height
,
241 8 << drv
->pixel_shift
, 0);
243 drv
->line_bytes
= drv
->image
->bytes_per_line
;
244 fill_shift_mask (&drv
->r
, drv
->image
->red_mask
);
245 fill_shift_mask (&drv
->g
, drv
->image
->green_mask
);
246 fill_shift_mask (&drv
->b
, drv
->image
->blue_mask
);
249 size_hints
.flags
= PSize
| PMinSize
| PMaxSize
;
250 size_hints
.min_width
= size_hints
.max_width
= size_hints
.base_width
= Width
;
251 size_hints
.min_height
= size_hints
.max_height
= size_hints
.base_height
= Height
;
252 XSetWMNormalHints (drv
->display
, drv
->win
, &size_hints
);
254 XMapWindow (drv
->display
, drv
->win
);
260 handleKeyEvent(UGA_IO_PRIVATE
*drv
, XEvent
*ev
)
264 EFI_KEY_DATA KeyData
;
267 if (drv
->key_count
== NBR_KEYS
)
270 res
= XLookupString(&ev
->xkey
, str
, sizeof(str
), &keysym
, NULL
);
271 KeyData
.Key
.ScanCode
= 0;
272 KeyData
.Key
.UnicodeChar
= 0;
273 KeyData
.KeyState
.KeyShiftState
= 0;
276 // KeyRelease is not supported (on Mac) so we can not easily implement Ex functions.
277 // If a modifier key is hit by its self we get a keysym. If a modfifier and key is hit
278 // we get the state bit set and keysym is the modified key.
280 // We use lack of state bits being set to clear ToggleState and KeyShiftState. We can
281 // also use the stat bits to set ToggleState and KeyShiftState.
282 // Skipping EFI_SCROLL_LOCK_ACTIVE & EFI_NUM_LOCK_ACTIVE since they are not on Macs
284 if ((ev
->xkey
.state
& LockMask
) == 0) {
285 drv
->KeyState
.KeyToggleState
&= ~EFI_CAPS_LOCK_ACTIVE
;
287 drv
->KeyState
.KeyToggleState
|= EFI_CAPS_LOCK_ACTIVE
;
290 if ((ev
->xkey
.state
& ControlMask
) == 0) {
291 drv
->KeyState
.KeyShiftState
&= ~(EFI_RIGHT_CONTROL_PRESSED
| EFI_LEFT_CONTROL_PRESSED
);
292 } else if ((drv
->KeyState
.KeyShiftState
& EFI_RIGHT_CONTROL_PRESSED
) == 0) {
293 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_CONTROL_PRESSED
;
296 if ((ev
->xkey
.state
& ShiftMask
) == 0) {
297 drv
->KeyState
.KeyShiftState
&= ~(EFI_RIGHT_SHIFT_PRESSED
| EFI_LEFT_SHIFT_PRESSED
);
298 } else if ((drv
->KeyState
.KeyShiftState
& EFI_RIGHT_SHIFT_PRESSED
) == 0) {
299 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_SHIFT_PRESSED
;
302 if ((ev
->xkey
.state
& Mod2Mask
) == 0) {
303 drv
->KeyState
.KeyShiftState
&= ~(EFI_RIGHT_LOGO_PRESSED
| EFI_LEFT_LOGO_PRESSED
);
304 } else if ((drv
->KeyState
.KeyShiftState
& EFI_RIGHT_LOGO_PRESSED
) == 0) {
305 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_LOGO_PRESSED
;
308 if ((ev
->xkey
.state
& 0x2000) == 0) {
309 drv
->KeyState
.KeyShiftState
&= ~(EFI_LEFT_ALT_PRESSED
);
311 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_ALT_PRESSED
;
317 drv
->KeyState
.KeyShiftState
|= EFI_RIGHT_CONTROL_PRESSED
;
320 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_CONTROL_PRESSED
;
324 drv
->KeyState
.KeyShiftState
|= EFI_RIGHT_SHIFT_PRESSED
;
327 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_SHIFT_PRESSED
;
331 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_ALT_PRESSED
;
335 drv
->KeyState
.KeyShiftState
|= EFI_RIGHT_LOGO_PRESSED
;
338 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_LOGO_PRESSED
;
341 case XK_Home
: KeyData
.Key
.ScanCode
= SCAN_HOME
; break;
342 case XK_End
: KeyData
.Key
.ScanCode
= SCAN_END
; break;
343 case XK_Left
: KeyData
.Key
.ScanCode
= SCAN_LEFT
; break;
344 case XK_Right
: KeyData
.Key
.ScanCode
= SCAN_RIGHT
; break;
345 case XK_Up
: KeyData
.Key
.ScanCode
= SCAN_UP
; break;
346 case XK_Down
: KeyData
.Key
.ScanCode
= SCAN_DOWN
; break;
347 case XK_Delete
: KeyData
.Key
.ScanCode
= SCAN_DELETE
; break;
348 case XK_Insert
: KeyData
.Key
.ScanCode
= SCAN_INSERT
; break;
349 case XK_Page_Up
: KeyData
.Key
.ScanCode
= SCAN_PAGE_UP
; break;
350 case XK_Page_Down
: KeyData
.Key
.ScanCode
= SCAN_PAGE_DOWN
; break;
351 case XK_Escape
: KeyData
.Key
.ScanCode
= SCAN_ESC
; break;
353 case XK_F1
: KeyData
.Key
.ScanCode
= SCAN_F1
; break;
354 case XK_F2
: KeyData
.Key
.ScanCode
= SCAN_F2
; break;
355 case XK_F3
: KeyData
.Key
.ScanCode
= SCAN_F3
; break;
356 case XK_F4
: KeyData
.Key
.ScanCode
= SCAN_F4
; break;
357 case XK_F5
: KeyData
.Key
.ScanCode
= SCAN_F5
; break;
358 case XK_F6
: KeyData
.Key
.ScanCode
= SCAN_F6
; break;
359 case XK_F7
: KeyData
.Key
.ScanCode
= SCAN_F7
; break;
360 case XK_F8
: KeyData
.Key
.ScanCode
= SCAN_F8
; break;
361 case XK_F9
: KeyData
.Key
.ScanCode
= SCAN_F9
; break;
365 KeyData
.Key
.UnicodeChar
= str
[0];
371 // The global state is our state
372 KeyData
.KeyState
.KeyShiftState
= drv
->KeyState
.KeyShiftState
;
373 KeyData
.KeyState
.KeyToggleState
= drv
->KeyState
.KeyToggleState
;
375 CopyMem (&drv
->keys
[drv
->key_wr
], &KeyData
, sizeof (EFI_KEY_DATA
));
376 drv
->key_wr
= (drv
->key_wr
+ 1) % NBR_KEYS
;
380 #if defined(__APPLE__) || defined(MDE_CPU_X64)
381 ReverseGasketUint64Uint64 (drv
->RegisterdKeyCallback
,drv
->RegisterdKeyCallbackContext
, &KeyData
);
383 drv
->RegisterdKeyCallback (drv
->RegisterdKeyCallbackContext
, &KeyData
);
391 handleMouseMoved(UGA_IO_PRIVATE
*drv
, XEvent
*ev
)
393 if ( ev
->xmotion
.x
!= drv
->previous_x
)
395 drv
->pointer_state
.RelativeMovementX
+= ( ev
->xmotion
.x
- drv
->previous_x
);
396 drv
->previous_x
= ev
->xmotion
.x
;
397 drv
->pointer_state_changed
= 1;
400 if ( ev
->xmotion
.y
!= drv
->previous_y
)
402 drv
->pointer_state
.RelativeMovementY
+= ( ev
->xmotion
.y
- drv
->previous_y
);
403 drv
->previous_y
= ev
->xmotion
.y
;
404 drv
->pointer_state_changed
= 1;
407 drv
->pointer_state
.RelativeMovementZ
= 0;
411 handleMouseDown(UGA_IO_PRIVATE
*drv
, XEvent
*ev
, BOOLEAN Pressed
)
413 if ( ev
->xbutton
.button
== Button1
)
415 drv
->pointer_state_changed
= ( drv
->pointer_state
.LeftButton
!= Pressed
);
416 drv
->pointer_state
.LeftButton
= Pressed
;
418 if ( ev
->xbutton
.button
== Button2
)
420 drv
->pointer_state_changed
= ( drv
->pointer_state
.RightButton
!= Pressed
);
421 drv
->pointer_state
.RightButton
= Pressed
;
426 Redraw(UGA_IO_PRIVATE
*drv
, UINTN X
, UINTN Y
, UINTN Width
, UINTN Height
)
429 XShmPutImage (drv
->display
, drv
->win
, drv
->gc
, drv
->image
,
430 X
, Y
, X
, Y
, Width
, Height
, False
);
432 XPutImage (drv
->display
, drv
->win
, drv
->gc
, drv
->image
,
433 X
, Y
, X
, Y
, Width
, Height
);
434 XFlush(drv
->display
);
438 HandleEvent(UGA_IO_PRIVATE
*drv
, XEvent
*ev
)
443 Redraw(drv
, ev
->xexpose
.x
, ev
->xexpose
.y
,
444 ev
->xexpose
.width
, ev
->xexpose
.height
);
447 Redraw(drv
, ev
->xgraphicsexpose
.x
, ev
->xgraphicsexpose
.y
,
448 ev
->xgraphicsexpose
.width
, ev
->xgraphicsexpose
.height
);
451 handleKeyEvent(drv
, ev
);
456 XRefreshKeyboardMapping(&ev
->xmapping
);
459 handleMouseMoved(drv
, ev
);
462 handleMouseDown(drv
, ev
, TRUE
);
465 handleMouseDown(drv
, ev
, FALSE
);
469 XCloseDisplay (drv
->display
);
480 HandleEvents(UGA_IO_PRIVATE
*drv
)
482 while (XPending(drv
->display
) != 0)
486 XNextEvent (drv
->display
, &ev
);
487 HandleEvent(drv
, &ev
);
492 UgaPixelToColor (UGA_IO_PRIVATE
*drv
, EFI_UGA_PIXEL pixel
)
494 return ((pixel
.Red
>> drv
->r
.csize
) << drv
->r
.shift
)
495 | ((pixel
.Green
>> drv
->g
.csize
) << drv
->g
.shift
)
496 | ((pixel
.Blue
>> drv
->b
.csize
) << drv
->b
.shift
);
500 UgaColorToPixel (UGA_IO_PRIVATE
*drv
, unsigned long val
)
504 memset (&res
, 0, sizeof (EFI_UGA_PIXEL
));
505 /* FIXME: should round instead of truncate. */
506 res
.Red
= (val
>> drv
->r
.shift
) << drv
->r
.csize
;
507 res
.Green
= (val
>> drv
->g
.shift
) << drv
->g
.csize
;
508 res
.Blue
= (val
>> drv
->b
.shift
) << drv
->b
.csize
;
514 CheckKeyInternal( UGA_IO_PRIVATE
*drv
, BOOLEAN delay
)
517 if (drv
->key_count
!= 0)
520 /* EFI is polling. Be CPU-friendly. */
522 return EFI_NOT_READY
;
526 UgaCheckKey(EFI_UNIX_UGA_IO_PROTOCOL
*UgaIo
)
528 UGA_IO_PRIVATE
*drv
= (UGA_IO_PRIVATE
*)UgaIo
;
529 return( CheckKeyInternal( drv
, TRUE
) );
535 IN EFI_UNIX_UGA_IO_PROTOCOL
*UgaIo
,
536 IN EFI_KEY_DATA
*KeyData
539 UGA_IO_PRIVATE
*drv
= (UGA_IO_PRIVATE
*)UgaIo
;
542 status
= CheckKeyInternal(drv
, FALSE
);
543 if (status
!= EFI_SUCCESS
)
546 CopyMem (KeyData
, &drv
->keys
[drv
->key_rd
], sizeof (EFI_KEY_DATA
));
547 drv
->key_rd
= (drv
->key_rd
+ 1) % NBR_KEYS
;
556 IN EFI_UNIX_UGA_IO_PROTOCOL
*UgaIo
,
557 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
560 UGA_IO_PRIVATE
*drv
= (UGA_IO_PRIVATE
*)UgaIo
;
563 if (*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) {
564 if ((drv
->KeyState
.KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == 0) {
566 // We could create an XKeyEvent and send a XK_Caps_Lock to
567 // the UGA/GOP Window
572 drv
->KeyState
.KeyToggleState
= *KeyToggleState
;
579 UgaRegisterKeyNotify (
580 IN EFI_UNIX_UGA_IO_PROTOCOL
*UgaIo
,
581 IN UGA_REGISTER_KEY_NOTIFY_CALLBACK CallBack
,
585 UGA_IO_PRIVATE
*drv
= (UGA_IO_PRIVATE
*)UgaIo
;
587 drv
->RegisterdKeyCallback
= CallBack
;
588 drv
->RegisterdKeyCallbackContext
= Context
;
596 IN EFI_UNIX_UGA_IO_PROTOCOL
*UgaIo
,
597 IN EFI_UGA_PIXEL
*BltBuffer OPTIONAL
,
598 IN EFI_UGA_BLT_OPERATION BltOperation
,
599 IN UGA_BLT_ARGS
*Args
602 UGA_IO_PRIVATE
*Private
= (UGA_IO_PRIVATE
*)UgaIo
;
617 if (BltOperation
== EfiUgaVideoToBltBuffer
618 || BltOperation
== EfiUgaVideoToVideo
) {
622 if (Args
->SourceY
+ Args
->Height
> Private
->height
) {
623 return EFI_INVALID_PARAMETER
;
626 if (Args
->SourceX
+ Args
->Width
> Private
->width
) {
627 return EFI_INVALID_PARAMETER
;
631 if (BltOperation
== EfiUgaBltBufferToVideo
632 || BltOperation
== EfiUgaVideoToVideo
633 || BltOperation
== EfiUgaVideoFill
) {
635 // Destination is Video
637 if (Args
->DestinationY
+ Args
->Height
> Private
->height
) {
638 return EFI_INVALID_PARAMETER
;
641 if (Args
->DestinationX
+ Args
->Width
> Private
->width
) {
642 return EFI_INVALID_PARAMETER
;
646 switch (BltOperation
) {
647 case EfiUgaVideoToBltBuffer
:
648 Blt
= (EFI_UGA_PIXEL
*)((UINT8
*)BltBuffer
+ (Args
->DestinationY
* Args
->Delta
) + Args
->DestinationX
* sizeof (EFI_UGA_PIXEL
));
649 Args
->Delta
-= Args
->Width
* sizeof (EFI_UGA_PIXEL
);
650 for (SrcY
= Args
->SourceY
; SrcY
< (Args
->Height
+ Args
->SourceY
); SrcY
++) {
651 for (SrcX
= Args
->SourceX
; SrcX
< (Args
->Width
+ Args
->SourceX
); SrcX
++) {
652 *Blt
++ = UgaColorToPixel(Private
,
653 XGetPixel(Private
->image
, SrcX
, SrcY
));
655 Blt
= (EFI_UGA_PIXEL
*) ((UINT8
*) Blt
+ Args
->Delta
);
658 case EfiUgaBltBufferToVideo
:
659 Blt
= (EFI_UGA_PIXEL
*)((UINT8
*)BltBuffer
+ (Args
->SourceY
* Args
->Delta
) + Args
->SourceX
* sizeof (EFI_UGA_PIXEL
));
660 Args
->Delta
-= Args
->Width
* sizeof (EFI_UGA_PIXEL
);
661 for (DstY
= Args
->DestinationY
; DstY
< (Args
->Height
+ Args
->DestinationY
); DstY
++) {
662 for (DstX
= Args
->DestinationX
; DstX
< (Args
->Width
+ Args
->DestinationX
); DstX
++) {
663 XPutPixel(Private
->image
, DstX
, DstY
, UgaPixelToColor(Private
, *Blt
));
666 Blt
= (EFI_UGA_PIXEL
*) ((UINT8
*) Blt
+ Args
->Delta
);
669 case EfiUgaVideoToVideo
:
670 Dst
= Private
->image_data
+ (Args
->DestinationX
<< Private
->pixel_shift
)
671 + Args
->DestinationY
* Private
->line_bytes
;
672 Src
= Private
->image_data
+ (Args
->SourceX
<< Private
->pixel_shift
)
673 + Args
->SourceY
* Private
->line_bytes
;
674 Nbr
= Args
->Width
<< Private
->pixel_shift
;
675 if (Args
->DestinationY
< Args
->SourceY
) {
676 for (Index
= 0; Index
< Args
->Height
; Index
++) {
677 memcpy (Dst
, Src
, Nbr
);
678 Dst
+= Private
->line_bytes
;
679 Src
+= Private
->line_bytes
;
683 Dst
+= (Args
->Height
- 1) * Private
->line_bytes
;
684 Src
+= (Args
->Height
- 1) * Private
->line_bytes
;
685 for (Index
= 0; Index
< Args
->Height
; Index
++) {
687 // Source and Destination Y may be equal, therefore Dst and Src may
690 memmove (Dst
, Src
, Nbr
);
691 Dst
-= Private
->line_bytes
;
692 Src
-= Private
->line_bytes
;
696 case EfiUgaVideoFill
:
697 Color
= UgaPixelToColor(Private
, *BltBuffer
);
698 for (DstY
= Args
->DestinationY
; DstY
< (Args
->Height
+ Args
->DestinationY
); DstY
++) {
699 for (DstX
= Args
->DestinationX
; DstX
< (Args
->Width
+ Args
->DestinationX
); DstX
++) {
700 XPutPixel(Private
->image
, DstX
, DstY
, Color
);
705 return EFI_INVALID_PARAMETER
;
711 switch (BltOperation
) {
712 case EfiUgaVideoToVideo
:
713 XCopyArea(Private
->display
, Private
->win
, Private
->win
, Private
->gc
,
714 Args
->SourceX
, Args
->SourceY
, Args
->Width
, Args
->Height
, Args
->DestinationX
, Args
->DestinationY
);
718 XNextEvent (Private
->display
, &ev
);
719 HandleEvent(Private
, &ev
);
720 if (ev
.type
== NoExpose
|| ev
.type
== GraphicsExpose
)
724 case EfiUgaVideoFill
:
725 Color
= UgaPixelToColor(Private
, *BltBuffer
);
726 XSetForeground(Private
->display
, Private
->gc
, Color
);
727 XFillRectangle(Private
->display
, Private
->win
, Private
->gc
,
728 Args
->DestinationX
, Args
->DestinationY
, Args
->Width
, Args
->Height
);
729 XFlush(Private
->display
);
731 case EfiUgaBltBufferToVideo
:
732 Redraw(Private
, Args
->DestinationX
, Args
->DestinationY
, Args
->Width
, Args
->Height
);
741 CheckPointerInternal( UGA_IO_PRIVATE
*drv
, BOOLEAN delay
)
744 if (drv
->pointer_state_changed
!= 0)
747 /* EFI is polling. Be CPU-friendly. */
749 return EFI_NOT_READY
;
753 UgaCheckPointer(EFI_UNIX_UGA_IO_PROTOCOL
*UgaIo
)
755 UGA_IO_PRIVATE
*drv
= (UGA_IO_PRIVATE
*)UgaIo
;
756 return( CheckPointerInternal( drv
, TRUE
) );
760 UgaGetPointerState (EFI_UNIX_UGA_IO_PROTOCOL
*UgaIo
, EFI_SIMPLE_POINTER_STATE
*state
)
762 UGA_IO_PRIVATE
*drv
= (UGA_IO_PRIVATE
*)UgaIo
;
765 status
= CheckPointerInternal( drv
, FALSE
);
766 if (status
!= EFI_SUCCESS
)
769 memcpy( state
, &drv
->pointer_state
, sizeof( EFI_SIMPLE_POINTER_STATE
) );
771 drv
->pointer_state
.RelativeMovementX
= 0;
772 drv
->pointer_state
.RelativeMovementY
= 0;
773 drv
->pointer_state
.RelativeMovementZ
= 0;
774 drv
->pointer_state_changed
= 0;
779 UgaCreate (EFI_UNIX_UGA_IO_PROTOCOL
**Uga
, CONST CHAR16
*Title
)
782 unsigned int border_width
= 0;
783 char *display_name
= NULL
;
786 drv
= (UGA_IO_PRIVATE
*)calloc (1, sizeof (UGA_IO_PRIVATE
));
788 return EFI_OUT_OF_RESOURCES
;
790 #if defined(__APPLE__) || defined(MDE_CPU_X64)
794 drv
->UgaIo
.UgaClose
= GasketUgaClose
;
795 drv
->UgaIo
.UgaSize
= GasketUgaSize
;
796 drv
->UgaIo
.UgaCheckKey
= GasketUgaCheckKey
;
797 drv
->UgaIo
.UgaGetKey
= GasketUgaGetKey
;
798 drv
->UgaIo
.UgaKeySetState
= GasketUgaKeySetState
;
799 drv
->UgaIo
.UgaRegisterKeyNotify
= GasketUgaRegisterKeyNotify
;
800 drv
->UgaIo
.UgaBlt
= GasketUgaBlt
;
801 drv
->UgaIo
.UgaCheckPointer
= GasketUgaCheckPointer
;
802 drv
->UgaIo
.UgaGetPointerState
= GasketUgaGetPointerState
;
804 drv
->UgaIo
.UgaClose
= UgaClose
;
805 drv
->UgaIo
.UgaSize
= UgaSize
;
806 drv
->UgaIo
.UgaCheckKey
= UgaCheckKey
;
807 drv
->UgaIo
.UgaGetKey
= UgaGetKey
;
808 drv
->UgaIo
.UgaKeySetState
= UgaKeySetState
;
809 drv
->UgaIo
.UgaRegisterKeyNotify
= UgaRegisterKeyNotify
;
810 drv
->UgaIo
.UgaBlt
= UgaBlt
;
811 drv
->UgaIo
.UgaCheckPointer
= UgaCheckPointer
;
812 drv
->UgaIo
.UgaGetPointerState
= UgaGetPointerState
;
820 drv
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
821 drv
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
822 drv
->RegisterdKeyCallback
= NULL
;
823 drv
->RegisterdKeyCallbackContext
= NULL
;
826 drv
->display
= XOpenDisplay (display_name
);
827 if (drv
->display
== NULL
)
829 fprintf (stderr
, "uga: cannot connect to X server %s\n",
830 XDisplayName (display_name
));
832 return EFI_DEVICE_ERROR
;
834 drv
->screen
= DefaultScreen (drv
->display
);
835 drv
->visual
= DefaultVisual (drv
->display
, drv
->screen
);
836 drv
->win
= XCreateSimpleWindow
837 (drv
->display
, RootWindow (drv
->display
, drv
->screen
),
838 0, 0, 4, 4, border_width
,
839 WhitePixel (drv
->display
, drv
->screen
),
840 BlackPixel (drv
->display
, drv
->screen
));
842 drv
->depth
= DefaultDepth (drv
->display
, drv
->screen
);
843 XDefineCursor (drv
->display
, drv
->win
, XCreateFontCursor (drv
->display
, XC_pirate
));
845 /* Compute title len and convert to Ascii. */
846 for (title_len
= 0; Title
[title_len
] != 0; title_len
++)
849 char title
[title_len
+ 1];
851 for (i
= 0; i
< title_len
; i
++)
855 XStoreName (drv
->display
, drv
->win
, title
);
858 XSelectInput (drv
->display
, drv
->win
,
859 ExposureMask
| KeyPressMask
| PointerMotionMask
| ButtonPressMask
| ButtonReleaseMask
);
860 drv
->gc
= DefaultGC (drv
->display
, drv
->screen
);
862 *Uga
= (EFI_UNIX_UGA_IO_PROTOCOL
*)drv
;