-/*++ @file
-
-Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
-Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
-
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "Host.h"
-
-#include <sys/ipc.h>
-#include <sys/shm.h>
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xos.h>
-#include <X11/extensions/XShm.h>
-#include <X11/keysym.h>
-#include <X11/cursorfont.h>
-
-#define KEYSYM_LOWER 0
-#define KEYSYM_UPPER 1
-
-
-struct uga_drv_shift_mask {
- unsigned char shift;
- unsigned char size;
- unsigned char csize;
-};
-
-#define NBR_KEYS 32
-typedef struct {
- EMU_GRAPHICS_WINDOW_PROTOCOL GraphicsIo;
-
- Display *display;
- int screen; // values for window_size in main
- Window win;
- GC gc;
- Visual *visual;
-
- int depth;
- unsigned int width;
- unsigned int height;
- unsigned int line_bytes;
- unsigned int pixel_shift;
- unsigned char *image_data;
-
- struct uga_drv_shift_mask r, g, b;
-
- int use_shm;
- XShmSegmentInfo xshm_info;
- XImage *image;
- char *Title;
-
- unsigned int key_rd;
- unsigned int key_wr;
- unsigned int key_count;
- EFI_KEY_DATA keys[NBR_KEYS];
-
- EFI_KEY_STATE KeyState;
-
- EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeRegisterdKeyCallback;
- EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakRegisterdKeyCallback;
- VOID *RegisterdKeyCallbackContext;
-
- int previous_x;
- int previous_y;
- EFI_SIMPLE_POINTER_STATE pointer_state;
- int pointer_state_changed;
-} GRAPHICS_IO_PRIVATE;
-
-void
-HandleEvents(
- IN GRAPHICS_IO_PRIVATE *Drv
- );
-
-void
-fill_shift_mask (
- IN struct uga_drv_shift_mask *sm,
- IN unsigned long mask
- )
-{
- sm->shift = 0;
- sm->size = 0;
- while ((mask & 1) == 0) {
- mask >>= 1;
- sm->shift++;
- }
- while (mask & 1) {
- sm->size++;
- mask >>= 1;
- }
- sm->csize = 8 - sm->size;
-}
-
-int
-TryCreateShmImage (
- IN GRAPHICS_IO_PRIVATE *Drv
- )
-{
- Drv->image = XShmCreateImage (
- Drv->display, Drv->visual,
- Drv->depth, ZPixmap, NULL, &Drv->xshm_info,
- Drv->width, Drv->height
- );
- if (Drv->image == NULL) {
- return 0;
- }
-
- switch (Drv->image->bitmap_unit) {
- case 32:
- Drv->pixel_shift = 2;
- break;
- case 16:
- Drv->pixel_shift = 1;
- break;
- case 8:
- Drv->pixel_shift = 0;
- break;
- }
-
- Drv->xshm_info.shmid = shmget (
- IPC_PRIVATE, Drv->image->bytes_per_line * Drv->image->height,
- IPC_CREAT | 0777
- );
- if (Drv->xshm_info.shmid < 0) {
- XDestroyImage(Drv->image);
- return 0;
- }
-
- Drv->image_data = shmat (Drv->xshm_info.shmid, NULL, 0);
- if(!Drv->image_data) {
- shmctl (Drv->xshm_info.shmid, IPC_RMID, NULL);
- XDestroyImage(Drv->image);
- return 0;
- }
-
-#ifndef __APPLE__
- //
- // This closes shared memory in real time on OS X. Only closes after folks quit using
- // it on Linux.
- //
- shmctl (Drv->xshm_info.shmid, IPC_RMID, NULL);
-#endif
-
- Drv->xshm_info.shmaddr = (char*)Drv->image_data;
- Drv->image->data = (char*)Drv->image_data;
-
- if (!XShmAttach (Drv->display, &Drv->xshm_info)) {
- shmdt (Drv->image_data);
- XDestroyImage(Drv->image);
- return 0;
- }
- return 1;
-}
-
-
-EFI_STATUS
-X11Size (
- IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
- IN UINT32 Width,
- IN UINT32 Height
- )
-{
- GRAPHICS_IO_PRIVATE *Drv;
- XSizeHints size_hints;
-
- // Destroy current buffer if created.
- Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;
- if (Drv->image != NULL) {
- // Before destroy buffer, need to make sure the buffer available for access.
- XDestroyImage (Drv->image);
-
- if (Drv->use_shm) {
- shmdt (Drv->image_data);
- }
-
- Drv->image_data = NULL;
- Drv->image = NULL;
- }
-
- Drv->width = Width;
- Drv->height = Height;
- XResizeWindow (Drv->display, Drv->win, Width, Height);
-
- // Allocate image.
- if (XShmQueryExtension(Drv->display) && TryCreateShmImage(Drv)) {
- Drv->use_shm = 1;
- } else {
- Drv->use_shm = 0;
- if (Drv->depth > 16) {
- Drv->pixel_shift = 2;
- } else if (Drv->depth > 8) {
- Drv->pixel_shift = 1;
- } else {
- Drv->pixel_shift = 0;
- }
-
- Drv->image_data = malloc ((Drv->width * Drv->height) << Drv->pixel_shift);
- Drv->image = XCreateImage (
- Drv->display, Drv->visual, Drv->depth,
- ZPixmap, 0, (char *)Drv->image_data,
- Drv->width, Drv->height,
- 8 << Drv->pixel_shift, 0
- );
- }
-
- Drv->line_bytes = Drv->image->bytes_per_line;
-
- fill_shift_mask (&Drv->r, Drv->image->red_mask);
- fill_shift_mask (&Drv->g, Drv->image->green_mask);
- fill_shift_mask (&Drv->b, Drv->image->blue_mask);
-
- // Set WM hints.
- size_hints.flags = PSize | PMinSize | PMaxSize;
- size_hints.min_width = size_hints.max_width = size_hints.base_width = Width;
- size_hints.min_height = size_hints.max_height = size_hints.base_height = Height;
- XSetWMNormalHints (Drv->display, Drv->win, &size_hints);
-
- XMapWindow (Drv->display, Drv->win);
- HandleEvents (Drv);
- return EFI_SUCCESS;
-}
-
-void
-handleKeyEvent (
- IN GRAPHICS_IO_PRIVATE *Drv,
- IN XEvent *ev,
- IN BOOLEAN Make
- )
-{
- KeySym *KeySym;
- EFI_KEY_DATA KeyData;
- int KeySymArraySize;
-
- if (Make) {
- if (Drv->key_count == NBR_KEYS) {
- return;
- }
- }
-
- // keycode is a physical key on the keyboard
- // KeySym is a mapping of a physical key
- // KeyboardMapping is the array of KeySym for a given keycode. key, shifted key, option key, command key, ...
- //
- // Returns an array of KeySymArraySize of KeySym for the keycode. [0] is lower case, [1] is upper case,
- // [2] and [3] are based on option and command modifiers. The problem we have is command V
- // could be mapped to a crazy Unicode character so the old scheme of returning a string.
- //
- KeySym = XGetKeyboardMapping (Drv->display, ev->xkey.keycode, 1, &KeySymArraySize);
-
- KeyData.Key.ScanCode = 0;
- KeyData.Key.UnicodeChar = 0;
- KeyData.KeyState.KeyShiftState = 0;
-
- //
- // Skipping EFI_SCROLL_LOCK_ACTIVE & EFI_NUM_LOCK_ACTIVE since they are not on Macs
- //
- if ((ev->xkey.state & LockMask) == 0) {
- Drv->KeyState.KeyToggleState &= ~EFI_CAPS_LOCK_ACTIVE;
- } else {
- if (Make) {
- Drv->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
- }
- }
-
- // Skipping EFI_MENU_KEY_PRESSED and EFI_SYS_REQ_PRESSED
-
- switch (*KeySym) {
- case XK_Control_R:
- if (Make) {
- Drv->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;
- } else {
- Drv->KeyState.KeyShiftState &= ~EFI_RIGHT_CONTROL_PRESSED;
- }
- break;
- case XK_Control_L:
- if (Make) {
- Drv->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;
- } else {
- Drv->KeyState.KeyShiftState &= ~EFI_LEFT_CONTROL_PRESSED;
- }
- break;
-
- case XK_Shift_R:
- if (Make) {
- Drv->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
- } else {
- Drv->KeyState.KeyShiftState &= ~EFI_RIGHT_SHIFT_PRESSED;
- }
- break;
- case XK_Shift_L:
- if (Make) {
- Drv->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
- } else {
- Drv->KeyState.KeyShiftState &= ~EFI_LEFT_SHIFT_PRESSED;
- }
- break;
-
- case XK_Mode_switch:
- if (Make) {
- Drv->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;
- } else {
- Drv->KeyState.KeyShiftState &= ~EFI_LEFT_ALT_PRESSED;
- }
- break;
-
- case XK_Meta_R:
- if (Make) {
- Drv->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;
- } else {
- Drv->KeyState.KeyShiftState &= ~EFI_RIGHT_LOGO_PRESSED;
- }
- break;
- case XK_Meta_L:
- if (Make) {
- Drv->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
- } else {
- Drv->KeyState.KeyShiftState &= ~EFI_LEFT_LOGO_PRESSED;
- }
- break;
-
- case XK_KP_Home:
- case XK_Home: KeyData.Key.ScanCode = SCAN_HOME; break;
-
- case XK_KP_End:
- case XK_End: KeyData.Key.ScanCode = SCAN_END; break;
-
- case XK_KP_Left:
- case XK_Left: KeyData.Key.ScanCode = SCAN_LEFT; break;
-
- case XK_KP_Right:
- case XK_Right: KeyData.Key.ScanCode = SCAN_RIGHT; break;
-
- case XK_KP_Up:
- case XK_Up: KeyData.Key.ScanCode = SCAN_UP; break;
-
- case XK_KP_Down:
- case XK_Down: KeyData.Key.ScanCode = SCAN_DOWN; break;
-
- case XK_KP_Delete:
- case XK_Delete: KeyData.Key.ScanCode = SCAN_DELETE; break;
-
- case XK_KP_Insert:
- case XK_Insert: KeyData.Key.ScanCode = SCAN_INSERT; break;
-
- case XK_KP_Page_Up:
- case XK_Page_Up: KeyData.Key.ScanCode = SCAN_PAGE_UP; break;
-
- case XK_KP_Page_Down:
- case XK_Page_Down: KeyData.Key.ScanCode = SCAN_PAGE_DOWN; break;
-
- case XK_Escape: KeyData.Key.ScanCode = SCAN_ESC; break;
-
- case XK_Pause: KeyData.Key.ScanCode = SCAN_PAUSE; break;
-
- case XK_KP_F1:
- case XK_F1: KeyData.Key.ScanCode = SCAN_F1; break;
-
- case XK_KP_F2:
- case XK_F2: KeyData.Key.ScanCode = SCAN_F2; break;
-
- case XK_KP_F3:
- case XK_F3: KeyData.Key.ScanCode = SCAN_F3; break;
-
- case XK_KP_F4:
- case XK_F4: KeyData.Key.ScanCode = SCAN_F4; break;
-
- case XK_F5: KeyData.Key.ScanCode = SCAN_F5; break;
- case XK_F6: KeyData.Key.ScanCode = SCAN_F6; break;
- case XK_F7: KeyData.Key.ScanCode = SCAN_F7; break;
-
- // Don't map into X11 by default on a Mac
- // System Preferences->Keyboard->Keyboard Shortcuts can be configured
- // to not use higher function keys as shortcuts and the will show up
- // in X11.
- case XK_F8: KeyData.Key.ScanCode = SCAN_F8; break;
- case XK_F9: KeyData.Key.ScanCode = SCAN_F9; break;
- case XK_F10: KeyData.Key.ScanCode = SCAN_F10; break;
-
- case XK_F11: KeyData.Key.ScanCode = SCAN_F11; break;
- case XK_F12: KeyData.Key.ScanCode = SCAN_F12; break;
-
- case XK_F13: KeyData.Key.ScanCode = SCAN_F13; break;
- case XK_F14: KeyData.Key.ScanCode = SCAN_F14; break;
- case XK_F15: KeyData.Key.ScanCode = SCAN_F15; break;
- case XK_F16: KeyData.Key.ScanCode = SCAN_F16; break;
- case XK_F17: KeyData.Key.ScanCode = SCAN_F17; break;
- case XK_F18: KeyData.Key.ScanCode = SCAN_F18; break;
- case XK_F19: KeyData.Key.ScanCode = SCAN_F19; break;
- case XK_F20: KeyData.Key.ScanCode = SCAN_F20; break;
- case XK_F21: KeyData.Key.ScanCode = SCAN_F21; break;
- case XK_F22: KeyData.Key.ScanCode = SCAN_F22; break;
- case XK_F23: KeyData.Key.ScanCode = SCAN_F23; break;
- case XK_F24: KeyData.Key.ScanCode = SCAN_F24; break;
-
- // No mapping in X11
- //case XK_: KeyData.Key.ScanCode = SCAN_MUTE; break;
- //case XK_: KeyData.Key.ScanCode = SCAN_VOLUME_UP; break;
- //case XK_: KeyData.Key.ScanCode = SCAN_VOLUME_DOWN; break;
- //case XK_: KeyData.Key.ScanCode = SCAN_BRIGHTNESS_UP; break;
- //case XK_: KeyData.Key.ScanCode = SCAN_BRIGHTNESS_DOWN; break;
- //case XK_: KeyData.Key.ScanCode = SCAN_SUSPEND; break;
- //case XK_: KeyData.Key.ScanCode = SCAN_HIBERNATE; break;
- //case XK_: KeyData.Key.ScanCode = SCAN_TOGGLE_DISPLAY; break;
- //case XK_: KeyData.Key.ScanCode = SCAN_RECOVERY; break;
- //case XK_: KeyData.Key.ScanCode = SCAN_EJECT; break;
-
- case XK_BackSpace: KeyData.Key.UnicodeChar = 0x0008; break;
-
- case XK_KP_Tab:
- case XK_Tab: KeyData.Key.UnicodeChar = 0x0009; break;
-
- case XK_Linefeed: KeyData.Key.UnicodeChar = 0x000a; break;
-
- case XK_KP_Enter:
- case XK_Return: KeyData.Key.UnicodeChar = 0x000d; break;
-
- case XK_KP_Equal : KeyData.Key.UnicodeChar = L'='; break;
- case XK_KP_Multiply : KeyData.Key.UnicodeChar = L'*'; break;
- case XK_KP_Add : KeyData.Key.UnicodeChar = L'+'; break;
- case XK_KP_Separator : KeyData.Key.UnicodeChar = L'~'; break;
- case XK_KP_Subtract : KeyData.Key.UnicodeChar = L'-'; break;
- case XK_KP_Decimal : KeyData.Key.UnicodeChar = L'.'; break;
- case XK_KP_Divide : KeyData.Key.UnicodeChar = L'/'; break;
-
- case XK_KP_0 : KeyData.Key.UnicodeChar = L'0'; break;
- case XK_KP_1 : KeyData.Key.UnicodeChar = L'1'; break;
- case XK_KP_2 : KeyData.Key.UnicodeChar = L'2'; break;
- case XK_KP_3 : KeyData.Key.UnicodeChar = L'3'; break;
- case XK_KP_4 : KeyData.Key.UnicodeChar = L'4'; break;
- case XK_KP_5 : KeyData.Key.UnicodeChar = L'5'; break;
- case XK_KP_6 : KeyData.Key.UnicodeChar = L'6'; break;
- case XK_KP_7 : KeyData.Key.UnicodeChar = L'7'; break;
- case XK_KP_8 : KeyData.Key.UnicodeChar = L'8'; break;
- case XK_KP_9 : KeyData.Key.UnicodeChar = L'9'; break;
-
- default:
- ;
- }
-
- // The global state is our state
- KeyData.KeyState.KeyShiftState = Drv->KeyState.KeyShiftState;
- KeyData.KeyState.KeyToggleState = Drv->KeyState.KeyToggleState;
-
- if (*KeySym < XK_BackSpace) {
- if (((Drv->KeyState.KeyShiftState & (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED)) != 0) ||
- ((Drv->KeyState.KeyToggleState & EFI_CAPS_LOCK_ACTIVE) != 0) ) {
-
- KeyData.Key.UnicodeChar = (CHAR16)KeySym[KEYSYM_UPPER];
-
- // Per UEFI spec since we converted the Unicode clear the shift bits we pass up
- KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);
- } else {
- KeyData.Key.UnicodeChar = (CHAR16)KeySym[KEYSYM_LOWER];
- }
- } else {
- // XK_BackSpace is the start of XK_MISCELLANY. These are the XK_? keys we process in this file
- ;
- }
-
- if (Make) {
- memcpy (&Drv->keys[Drv->key_wr], &KeyData, sizeof (EFI_KEY_DATA));
- Drv->key_wr = (Drv->key_wr + 1) % NBR_KEYS;
- Drv->key_count++;
- if (Drv->MakeRegisterdKeyCallback != NULL) {
- ReverseGasketUint64Uint64 (Drv->MakeRegisterdKeyCallback ,Drv->RegisterdKeyCallbackContext, &KeyData);
- }
- } else {
- if (Drv->BreakRegisterdKeyCallback != NULL) {
- ReverseGasketUint64Uint64 (Drv->BreakRegisterdKeyCallback ,Drv->RegisterdKeyCallbackContext, &KeyData);
- }
- }
-}
-
-
-void
-handleMouseMoved(
- IN GRAPHICS_IO_PRIVATE *Drv,
- IN XEvent *ev
- )
-{
- if (ev->xmotion.x != Drv->previous_x) {
- Drv->pointer_state.RelativeMovementX += ( ev->xmotion.x - Drv->previous_x );
- Drv->previous_x = ev->xmotion.x;
- Drv->pointer_state_changed = 1;
- }
-
- if (ev->xmotion.y != Drv->previous_y) {
- Drv->pointer_state.RelativeMovementY += ( ev->xmotion.y - Drv->previous_y );
- Drv->previous_y = ev->xmotion.y;
- Drv->pointer_state_changed = 1;
- }
-
- Drv->pointer_state.RelativeMovementZ = 0;
-}
-
-void
-handleMouseDown (
- IN GRAPHICS_IO_PRIVATE *Drv,
- IN XEvent *ev,
- IN BOOLEAN Pressed
- )
-{
- if (ev->xbutton.button == Button1) {
- Drv->pointer_state_changed = (Drv->pointer_state.LeftButton != Pressed);
- Drv->pointer_state.LeftButton = Pressed;
- }
- if ( ev->xbutton.button == Button2 ) {
- Drv->pointer_state_changed = (Drv->pointer_state.RightButton != Pressed);
- Drv->pointer_state.RightButton = Pressed;
- }
-}
-
-void
-Redraw (
- IN GRAPHICS_IO_PRIVATE *Drv,
- IN UINTN X,
- IN UINTN Y,
- IN UINTN Width,
- IN UINTN Height
- )
-{
- if (Drv->use_shm) {
- XShmPutImage (
- Drv->display, Drv->win, Drv->gc, Drv->image, X, Y, X, Y, Width, Height, False
- );
- } else {
- XPutImage (
- Drv->display, Drv->win, Drv->gc, Drv->image, X, Y, X, Y, Width, Height
- );
- }
- XFlush(Drv->display);
-}
-
-void
-HandleEvent(GRAPHICS_IO_PRIVATE *Drv, XEvent *ev)
-{
- switch (ev->type) {
- case Expose:
- Redraw (Drv, ev->xexpose.x, ev->xexpose.y,
- ev->xexpose.width, ev->xexpose.height);
- break;
- case GraphicsExpose:
- Redraw (Drv, ev->xgraphicsexpose.x, ev->xgraphicsexpose.y,
- ev->xgraphicsexpose.width, ev->xgraphicsexpose.height);
- break;
- case KeyPress:
- handleKeyEvent (Drv, ev, TRUE);
- break;
- case KeyRelease:
- handleKeyEvent (Drv, ev, FALSE);
- break;
- case MappingNotify:
- XRefreshKeyboardMapping (&ev->xmapping);
- break;
- case MotionNotify:
- handleMouseMoved (Drv, ev);
- break;
- case ButtonPress:
- handleMouseDown (Drv, ev, TRUE);
- break;
- case ButtonRelease:
- handleMouseDown (Drv, ev, FALSE);
- break;
-#if 0
- case DestroyNotify:
- XCloseDisplay (Drv->display);
- exit (1);
- break;
-#endif
- case NoExpose:
- default:
- break;
- }
-}
-
-void
-HandleEvents (
- IN GRAPHICS_IO_PRIVATE *Drv
- )
-{
- XEvent ev;
-
- while (XPending (Drv->display) != 0) {
- XNextEvent (Drv->display, &ev);
- HandleEvent (Drv, &ev);
- }
-}
-
-unsigned long
-X11PixelToColor (
- IN GRAPHICS_IO_PRIVATE *Drv,
- IN EFI_UGA_PIXEL pixel
- )
-{
- return ((pixel.Red >> Drv->r.csize) << Drv->r.shift)
- | ((pixel.Green >> Drv->g.csize) << Drv->g.shift)
- | ((pixel.Blue >> Drv->b.csize) << Drv->b.shift);
-}
-
-EFI_UGA_PIXEL
-X11ColorToPixel (
- IN GRAPHICS_IO_PRIVATE *Drv,
- IN unsigned long val
- )
-{
- EFI_UGA_PIXEL Pixel;
-
- memset (&Pixel, 0, sizeof (EFI_UGA_PIXEL));
-
- // Truncation not an issue since X11 and EFI are both using 8 bits per color
- Pixel.Red = (val >> Drv->r.shift) << Drv->r.csize;
- Pixel.Green = (val >> Drv->g.shift) << Drv->g.csize;
- Pixel.Blue = (val >> Drv->b.shift) << Drv->b.csize;
-
- return Pixel;
-}
-
-
-EFI_STATUS
-X11CheckKey (
- IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo
- )
-{
- GRAPHICS_IO_PRIVATE *Drv;
-
- Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;
-
- HandleEvents (Drv);
-
- if (Drv->key_count != 0) {
- return EFI_SUCCESS;
- }
-
- return EFI_NOT_READY;
-}
-
-EFI_STATUS
-X11GetKey (
- IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
- IN EFI_KEY_DATA *KeyData
- )
-{
- EFI_STATUS EfiStatus;
- GRAPHICS_IO_PRIVATE *Drv;
-
- Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;
-
- EfiStatus = X11CheckKey (GraphicsIo);
- if (EFI_ERROR (EfiStatus)) {
- return EfiStatus;
- }
-
- CopyMem (KeyData, &Drv->keys[Drv->key_rd], sizeof (EFI_KEY_DATA));
- Drv->key_rd = (Drv->key_rd + 1) % NBR_KEYS;
- Drv->key_count--;
-
- return EFI_SUCCESS;
-}
-
-
-EFI_STATUS
-X11KeySetState (
- IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
- IN EFI_KEY_TOGGLE_STATE *KeyToggleState
- )
-{
- GRAPHICS_IO_PRIVATE *Drv;
-
- Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;
-
- if (*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) {
- if ((Drv->KeyState.KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == 0) {
- //
- // We could create an XKeyEvent and send a XK_Caps_Lock to
- // the UGA/GOP Window
- //
- }
- }
-
- Drv->KeyState.KeyToggleState = *KeyToggleState;
- return EFI_SUCCESS;
-}
-
-
-EFI_STATUS
-X11RegisterKeyNotify (
- IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
- IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeCallBack,
- IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakCallBack,
- IN VOID *Context
- )
-{
- GRAPHICS_IO_PRIVATE *Drv;
-
- Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;
-
- Drv->MakeRegisterdKeyCallback = MakeCallBack;
- Drv->BreakRegisterdKeyCallback = BreakCallBack;
- Drv->RegisterdKeyCallbackContext = Context;
-
- return EFI_SUCCESS;
-}
-
-
-EFI_STATUS
-X11Blt (
- IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
- IN EFI_UGA_PIXEL *BltBuffer OPTIONAL,
- IN EFI_UGA_BLT_OPERATION BltOperation,
- IN EMU_GRAPHICS_WINDOWS__BLT_ARGS *Args
- )
-{
- GRAPHICS_IO_PRIVATE *Private;
- UINTN DstY;
- UINTN SrcY;
- UINTN DstX;
- UINTN SrcX;
- UINTN Index;
- EFI_UGA_PIXEL *Blt;
- UINT8 *Dst;
- UINT8 *Src;
- UINTN Nbr;
- unsigned long Color;
- XEvent ev;
-
- Private = (GRAPHICS_IO_PRIVATE *)GraphicsIo;
-
-
- //
- // Check bounds
- //
- if (BltOperation == EfiUgaVideoToBltBuffer
- || BltOperation == EfiUgaVideoToVideo) {
- //
- // Source is Video.
- //
- if (Args->SourceY + Args->Height > Private->height) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Args->SourceX + Args->Width > Private->width) {
- return EFI_INVALID_PARAMETER;
- }
- }
-
- if (BltOperation == EfiUgaBltBufferToVideo
- || BltOperation == EfiUgaVideoToVideo
- || BltOperation == EfiUgaVideoFill) {
- //
- // Destination is Video
- //
- if (Args->DestinationY + Args->Height > Private->height) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Args->DestinationX + Args->Width > Private->width) {
- return EFI_INVALID_PARAMETER;
- }
- }
-
- switch (BltOperation) {
- case EfiUgaVideoToBltBuffer:
- Blt = (EFI_UGA_PIXEL *)((UINT8 *)BltBuffer + (Args->DestinationY * Args->Delta) + Args->DestinationX * sizeof (EFI_UGA_PIXEL));
- Args->Delta -= Args->Width * sizeof (EFI_UGA_PIXEL);
- for (SrcY = Args->SourceY; SrcY < (Args->Height + Args->SourceY); SrcY++) {
- for (SrcX = Args->SourceX; SrcX < (Args->Width + Args->SourceX); SrcX++) {
- *Blt++ = X11ColorToPixel (Private, XGetPixel (Private->image, SrcX, SrcY));
- }
- Blt = (EFI_UGA_PIXEL *) ((UINT8 *) Blt + Args->Delta);
- }
- break;
- case EfiUgaBltBufferToVideo:
- Blt = (EFI_UGA_PIXEL *)((UINT8 *)BltBuffer + (Args->SourceY * Args->Delta) + Args->SourceX * sizeof (EFI_UGA_PIXEL));
- Args->Delta -= Args->Width * sizeof (EFI_UGA_PIXEL);
- for (DstY = Args->DestinationY; DstY < (Args->Height + Args->DestinationY); DstY++) {
- for (DstX = Args->DestinationX; DstX < (Args->Width + Args->DestinationX); DstX++) {
- XPutPixel(Private->image, DstX, DstY, X11PixelToColor(Private, *Blt));
- Blt++;
- }
- Blt = (EFI_UGA_PIXEL *) ((UINT8 *) Blt + Args->Delta);
- }
- break;
- case EfiUgaVideoToVideo:
- Dst = Private->image_data + (Args->DestinationX << Private->pixel_shift)
- + Args->DestinationY * Private->line_bytes;
- Src = Private->image_data + (Args->SourceX << Private->pixel_shift)
- + Args->SourceY * Private->line_bytes;
- Nbr = Args->Width << Private->pixel_shift;
- if (Args->DestinationY < Args->SourceY) {
- for (Index = 0; Index < Args->Height; Index++) {
- memcpy (Dst, Src, Nbr);
- Dst += Private->line_bytes;
- Src += Private->line_bytes;
- }
- } else {
- Dst += (Args->Height - 1) * Private->line_bytes;
- Src += (Args->Height - 1) * Private->line_bytes;
- for (Index = 0; Index < Args->Height; Index++) {
- //
- // Source and Destination Y may be equal, therefore Dst and Src may
- // overlap.
- //
- memmove (Dst, Src, Nbr);
- Dst -= Private->line_bytes;
- Src -= Private->line_bytes;
- }
- }
- break;
- case EfiUgaVideoFill:
- Color = X11PixelToColor(Private, *BltBuffer);
- for (DstY = Args->DestinationY; DstY < (Args->Height + Args->DestinationY); DstY++) {
- for (DstX = Args->DestinationX; DstX < (Args->Width + Args->DestinationX); DstX++) {
- XPutPixel(Private->image, DstX, DstY, Color);
- }
- }
- break;
- default:
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Refresh screen.
- //
- switch (BltOperation) {
- case EfiUgaVideoToVideo:
- XCopyArea(
- Private->display, Private->win, Private->win, Private->gc,
- Args->SourceX, Args->SourceY, Args->Width, Args->Height,
- Args->DestinationX, Args->DestinationY
- );
-
- while (1) {
- XNextEvent (Private->display, &ev);
- HandleEvent (Private, &ev);
- if (ev.type == NoExpose || ev.type == GraphicsExpose) {
- break;
- }
- }
- break;
- case EfiUgaVideoFill:
- Color = X11PixelToColor (Private, *BltBuffer);
- XSetForeground (Private->display, Private->gc, Color);
- XFillRectangle (
- Private->display, Private->win, Private->gc,
- Args->DestinationX, Args->DestinationY, Args->Width, Args->Height
- );
- XFlush (Private->display);
- break;
- case EfiUgaBltBufferToVideo:
- Redraw (Private, Args->DestinationX, Args->DestinationY, Args->Width, Args->Height);
- break;
- default:
- break;
- }
- return EFI_SUCCESS;
-}
-
-
-EFI_STATUS
-X11CheckPointer (
- IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo
- )
-{
- GRAPHICS_IO_PRIVATE *Drv;
-
- Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;
-
- HandleEvents (Drv);
- if (Drv->pointer_state_changed != 0) {
- return EFI_SUCCESS;
- }
-
- return EFI_NOT_READY;
-}
-
-
-EFI_STATUS
-X11GetPointerState (
- IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
- IN EFI_SIMPLE_POINTER_STATE *State
- )
-{
- EFI_STATUS EfiStatus;
- GRAPHICS_IO_PRIVATE *Drv;
-
- Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;
-
- EfiStatus = X11CheckPointer (GraphicsIo);
- if (EfiStatus != EFI_SUCCESS) {
- return EfiStatus;
- }
-
- memcpy (State, &Drv->pointer_state, sizeof (EFI_SIMPLE_POINTER_STATE));
-
- Drv->pointer_state.RelativeMovementX = 0;
- Drv->pointer_state.RelativeMovementY = 0;
- Drv->pointer_state.RelativeMovementZ = 0;
- Drv->pointer_state_changed = 0;
- return EFI_SUCCESS;
-}
-
-
-
-EFI_STATUS
-X11GraphicsWindowOpen (
- IN EMU_IO_THUNK_PROTOCOL *This
- )
-{
- GRAPHICS_IO_PRIVATE *Drv;
- unsigned int border_width = 0;
- char *display_name = NULL;
-
- Drv = (GRAPHICS_IO_PRIVATE *)calloc (1, sizeof (GRAPHICS_IO_PRIVATE));
- if (Drv == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Drv->GraphicsIo.Size = GasketX11Size;
- Drv->GraphicsIo.CheckKey = GasketX11CheckKey;
- Drv->GraphicsIo.GetKey = GasketX11GetKey;
- Drv->GraphicsIo.KeySetState = GasketX11KeySetState;
- Drv->GraphicsIo.RegisterKeyNotify = GasketX11RegisterKeyNotify;
- Drv->GraphicsIo.Blt = GasketX11Blt;
- Drv->GraphicsIo.CheckPointer = GasketX11CheckPointer;
- Drv->GraphicsIo.GetPointerState = GasketX11GetPointerState;
-
-
- Drv->key_count = 0;
- Drv->key_rd = 0;
- Drv->key_wr = 0;
- Drv->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
- Drv->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
- Drv->MakeRegisterdKeyCallback = NULL;
- Drv->BreakRegisterdKeyCallback = NULL;
- Drv->RegisterdKeyCallbackContext = NULL;
-
-
- Drv->display = XOpenDisplay (display_name);
- if (Drv->display == NULL) {
- fprintf (stderr, "uga: cannot connect to X server %s\n", XDisplayName (display_name));
- free (Drv);
- return EFI_DEVICE_ERROR;
- }
- Drv->screen = DefaultScreen (Drv->display);
- Drv->visual = DefaultVisual (Drv->display, Drv->screen);
- Drv->win = XCreateSimpleWindow (
- Drv->display, RootWindow (Drv->display, Drv->screen),
- 0, 0, 4, 4, border_width,
- WhitePixel (Drv->display, Drv->screen),
- BlackPixel (Drv->display, Drv->screen)
- );
-
- Drv->depth = DefaultDepth (Drv->display, Drv->screen);
- XDefineCursor (Drv->display, Drv->win, XCreateFontCursor (Drv->display, XC_pirate));
-
- Drv->Title = malloc (StrSize (This->ConfigString));
- UnicodeStrToAsciiStr (This->ConfigString, Drv->Title);
- XStoreName (Drv->display, Drv->win, Drv->Title);
-
-// XAutoRepeatOff (Drv->display);
- XSelectInput (
- Drv->display, Drv->win,
- ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask
- );
- Drv->gc = DefaultGC (Drv->display, Drv->screen);
-
- This->Private = (VOID *)Drv;
- This->Interface = (VOID *)Drv;
- return EFI_SUCCESS;
-}
-
-
-EFI_STATUS
-X11GraphicsWindowClose (
- IN EMU_IO_THUNK_PROTOCOL *This
- )
-{
- GRAPHICS_IO_PRIVATE *Drv;
-
- Drv = (GRAPHICS_IO_PRIVATE *)This->Private;
-
- if (Drv == NULL) {
- return EFI_SUCCESS;
- }
-
- if (Drv->image != NULL) {
- XDestroyImage(Drv->image);
-
- if (Drv->use_shm) {
- shmdt (Drv->image_data);
- }
-
- Drv->image_data = NULL;
- Drv->image = NULL;
- }
- XDestroyWindow (Drv->display, Drv->win);
- XCloseDisplay (Drv->display);
-
-#ifdef __APPLE__
- // Free up the shared memory
- shmctl (Drv->xshm_info.shmid, IPC_RMID, NULL);
-#endif
-
- free (Drv);
- return EFI_SUCCESS;
-}
-
-
-EMU_IO_THUNK_PROTOCOL gX11ThunkIo = {
- &gEmuGraphicsWindowProtocolGuid,
- NULL,
- NULL,
- 0,
- GasketX11GraphicsWindowOpen,
- GasketX11GraphicsWindowClose,
- NULL
-};
-
-
+/*++ @file\r
+\r
+Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>\r
+\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "Host.h"\r
+\r
+#include <sys/ipc.h>\r
+#include <sys/shm.h>\r
+\r
+#include <X11/Xlib.h>\r
+#include <X11/Xutil.h>\r
+#include <X11/Xos.h>\r
+#include <X11/extensions/XShm.h>\r
+#include <X11/keysym.h>\r
+#include <X11/cursorfont.h>\r
+\r
+#define KEYSYM_LOWER 0\r
+#define KEYSYM_UPPER 1\r
+\r
+\r
+struct uga_drv_shift_mask {\r
+ unsigned char shift;\r
+ unsigned char size;\r
+ unsigned char csize;\r
+};\r
+\r
+#define NBR_KEYS 32\r
+typedef struct {\r
+ EMU_GRAPHICS_WINDOW_PROTOCOL GraphicsIo;\r
+\r
+ Display *display;\r
+ int screen; // values for window_size in main\r
+ Window win;\r
+ GC gc;\r
+ Visual *visual;\r
+\r
+ int depth;\r
+ unsigned int width;\r
+ unsigned int height;\r
+ unsigned int line_bytes;\r
+ unsigned int pixel_shift;\r
+ unsigned char *image_data;\r
+\r
+ struct uga_drv_shift_mask r, g, b;\r
+\r
+ int use_shm;\r
+ XShmSegmentInfo xshm_info;\r
+ XImage *image;\r
+ char *Title;\r
+\r
+ unsigned int key_rd;\r
+ unsigned int key_wr;\r
+ unsigned int key_count;\r
+ EFI_KEY_DATA keys[NBR_KEYS];\r
+\r
+ EFI_KEY_STATE KeyState;\r
+\r
+ EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeRegisterdKeyCallback;\r
+ EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakRegisterdKeyCallback;\r
+ VOID *RegisterdKeyCallbackContext;\r
+\r
+ int previous_x;\r
+ int previous_y;\r
+ EFI_SIMPLE_POINTER_STATE pointer_state;\r
+ int pointer_state_changed;\r
+} GRAPHICS_IO_PRIVATE;\r
+\r
+void\r
+HandleEvents(\r
+ IN GRAPHICS_IO_PRIVATE *Drv\r
+ );\r
+\r
+void\r
+fill_shift_mask (\r
+ IN struct uga_drv_shift_mask *sm,\r
+ IN unsigned long mask\r
+ )\r
+{\r
+ sm->shift = 0;\r
+ sm->size = 0;\r
+ while ((mask & 1) == 0) {\r
+ mask >>= 1;\r
+ sm->shift++;\r
+ }\r
+ while (mask & 1) {\r
+ sm->size++;\r
+ mask >>= 1;\r
+ }\r
+ sm->csize = 8 - sm->size;\r
+}\r
+\r
+int\r
+TryCreateShmImage (\r
+ IN GRAPHICS_IO_PRIVATE *Drv\r
+ )\r
+{\r
+ Drv->image = XShmCreateImage (\r
+ Drv->display, Drv->visual,\r
+ Drv->depth, ZPixmap, NULL, &Drv->xshm_info,\r
+ Drv->width, Drv->height\r
+ );\r
+ if (Drv->image == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ switch (Drv->image->bitmap_unit) {\r
+ case 32:\r
+ Drv->pixel_shift = 2;\r
+ break;\r
+ case 16:\r
+ Drv->pixel_shift = 1;\r
+ break;\r
+ case 8:\r
+ Drv->pixel_shift = 0;\r
+ break;\r
+ }\r
+\r
+ Drv->xshm_info.shmid = shmget (\r
+ IPC_PRIVATE, Drv->image->bytes_per_line * Drv->image->height,\r
+ IPC_CREAT | 0777\r
+ );\r
+ if (Drv->xshm_info.shmid < 0) {\r
+ XDestroyImage(Drv->image);\r
+ return 0;\r
+ }\r
+\r
+ Drv->image_data = shmat (Drv->xshm_info.shmid, NULL, 0);\r
+ if(!Drv->image_data) {\r
+ shmctl (Drv->xshm_info.shmid, IPC_RMID, NULL);\r
+ XDestroyImage(Drv->image);\r
+ return 0;\r
+ }\r
+\r
+#ifndef __APPLE__\r
+ //\r
+ // This closes shared memory in real time on OS X. Only closes after folks quit using\r
+ // it on Linux.\r
+ //\r
+ shmctl (Drv->xshm_info.shmid, IPC_RMID, NULL);\r
+#endif\r
+\r
+ Drv->xshm_info.shmaddr = (char*)Drv->image_data;\r
+ Drv->image->data = (char*)Drv->image_data;\r
+\r
+ if (!XShmAttach (Drv->display, &Drv->xshm_info)) {\r
+ shmdt (Drv->image_data);\r
+ XDestroyImage(Drv->image);\r
+ return 0;\r
+ }\r
+ return 1;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+X11Size (\r
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r
+ IN UINT32 Width,\r
+ IN UINT32 Height\r
+ )\r
+{\r
+ GRAPHICS_IO_PRIVATE *Drv;\r
+ XSizeHints size_hints;\r
+\r
+ // Destroy current buffer if created.\r
+ Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r
+ if (Drv->image != NULL) {\r
+ // Before destroy buffer, need to make sure the buffer available for access.\r
+ XDestroyImage (Drv->image);\r
+\r
+ if (Drv->use_shm) {\r
+ shmdt (Drv->image_data);\r
+ }\r
+\r
+ Drv->image_data = NULL;\r
+ Drv->image = NULL;\r
+ }\r
+\r
+ Drv->width = Width;\r
+ Drv->height = Height;\r
+ XResizeWindow (Drv->display, Drv->win, Width, Height);\r
+\r
+ // Allocate image.\r
+ if (XShmQueryExtension(Drv->display) && TryCreateShmImage(Drv)) {\r
+ Drv->use_shm = 1;\r
+ } else {\r
+ Drv->use_shm = 0;\r
+ if (Drv->depth > 16) {\r
+ Drv->pixel_shift = 2;\r
+ } else if (Drv->depth > 8) {\r
+ Drv->pixel_shift = 1;\r
+ } else {\r
+ Drv->pixel_shift = 0;\r
+ }\r
+\r
+ Drv->image_data = malloc ((Drv->width * Drv->height) << Drv->pixel_shift);\r
+ Drv->image = XCreateImage (\r
+ Drv->display, Drv->visual, Drv->depth,\r
+ ZPixmap, 0, (char *)Drv->image_data,\r
+ Drv->width, Drv->height,\r
+ 8 << Drv->pixel_shift, 0\r
+ );\r
+ }\r
+\r
+ Drv->line_bytes = Drv->image->bytes_per_line;\r
+\r
+ fill_shift_mask (&Drv->r, Drv->image->red_mask);\r
+ fill_shift_mask (&Drv->g, Drv->image->green_mask);\r
+ fill_shift_mask (&Drv->b, Drv->image->blue_mask);\r
+\r
+ // Set WM hints.\r
+ size_hints.flags = PSize | PMinSize | PMaxSize;\r
+ size_hints.min_width = size_hints.max_width = size_hints.base_width = Width;\r
+ size_hints.min_height = size_hints.max_height = size_hints.base_height = Height;\r
+ XSetWMNormalHints (Drv->display, Drv->win, &size_hints);\r
+\r
+ XMapWindow (Drv->display, Drv->win);\r
+ HandleEvents (Drv);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+void\r
+handleKeyEvent (\r
+ IN GRAPHICS_IO_PRIVATE *Drv,\r
+ IN XEvent *ev,\r
+ IN BOOLEAN Make\r
+ )\r
+{\r
+ KeySym *KeySym;\r
+ EFI_KEY_DATA KeyData;\r
+ int KeySymArraySize;\r
+\r
+ if (Make) {\r
+ if (Drv->key_count == NBR_KEYS) {\r
+ return;\r
+ }\r
+ }\r
+\r
+ // keycode is a physical key on the keyboard\r
+ // KeySym is a mapping of a physical key\r
+ // KeyboardMapping is the array of KeySym for a given keycode. key, shifted key, option key, command key, ...\r
+ //\r
+ // Returns an array of KeySymArraySize of KeySym for the keycode. [0] is lower case, [1] is upper case,\r
+ // [2] and [3] are based on option and command modifiers. The problem we have is command V\r
+ // could be mapped to a crazy Unicode character so the old scheme of returning a string.\r
+ //\r
+ KeySym = XGetKeyboardMapping (Drv->display, ev->xkey.keycode, 1, &KeySymArraySize);\r
+\r
+ KeyData.Key.ScanCode = 0;\r
+ KeyData.Key.UnicodeChar = 0;\r
+ KeyData.KeyState.KeyShiftState = 0;\r
+\r
+ //\r
+ // Skipping EFI_SCROLL_LOCK_ACTIVE & EFI_NUM_LOCK_ACTIVE since they are not on Macs\r
+ //\r
+ if ((ev->xkey.state & LockMask) == 0) {\r
+ Drv->KeyState.KeyToggleState &= ~EFI_CAPS_LOCK_ACTIVE;\r
+ } else {\r
+ if (Make) {\r
+ Drv->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r
+ }\r
+ }\r
+\r
+ // Skipping EFI_MENU_KEY_PRESSED and EFI_SYS_REQ_PRESSED\r
+\r
+ switch (*KeySym) {\r
+ case XK_Control_R:\r
+ if (Make) {\r
+ Drv->KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;\r
+ } else {\r
+ Drv->KeyState.KeyShiftState &= ~EFI_RIGHT_CONTROL_PRESSED;\r
+ }\r
+ break;\r
+ case XK_Control_L:\r
+ if (Make) {\r
+ Drv->KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;\r
+ } else {\r
+ Drv->KeyState.KeyShiftState &= ~EFI_LEFT_CONTROL_PRESSED;\r
+ }\r
+ break;\r
+\r
+ case XK_Shift_R:\r
+ if (Make) {\r
+ Drv->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;\r
+ } else {\r
+ Drv->KeyState.KeyShiftState &= ~EFI_RIGHT_SHIFT_PRESSED;\r
+ }\r
+ break;\r
+ case XK_Shift_L:\r
+ if (Make) {\r
+ Drv->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;\r
+ } else {\r
+ Drv->KeyState.KeyShiftState &= ~EFI_LEFT_SHIFT_PRESSED;\r
+ }\r
+ break;\r
+\r
+ case XK_Mode_switch:\r
+ if (Make) {\r
+ Drv->KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED;\r
+ } else {\r
+ Drv->KeyState.KeyShiftState &= ~EFI_LEFT_ALT_PRESSED;\r
+ }\r
+ break;\r
+\r
+ case XK_Meta_R:\r
+ if (Make) {\r
+ Drv->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;\r
+ } else {\r
+ Drv->KeyState.KeyShiftState &= ~EFI_RIGHT_LOGO_PRESSED;\r
+ }\r
+ break;\r
+ case XK_Meta_L:\r
+ if (Make) {\r
+ Drv->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;\r
+ } else {\r
+ Drv->KeyState.KeyShiftState &= ~EFI_LEFT_LOGO_PRESSED;\r
+ }\r
+ break;\r
+\r
+ case XK_KP_Home:\r
+ case XK_Home: KeyData.Key.ScanCode = SCAN_HOME; break;\r
+\r
+ case XK_KP_End:\r
+ case XK_End: KeyData.Key.ScanCode = SCAN_END; break;\r
+\r
+ case XK_KP_Left:\r
+ case XK_Left: KeyData.Key.ScanCode = SCAN_LEFT; break;\r
+\r
+ case XK_KP_Right:\r
+ case XK_Right: KeyData.Key.ScanCode = SCAN_RIGHT; break;\r
+\r
+ case XK_KP_Up:\r
+ case XK_Up: KeyData.Key.ScanCode = SCAN_UP; break;\r
+\r
+ case XK_KP_Down:\r
+ case XK_Down: KeyData.Key.ScanCode = SCAN_DOWN; break;\r
+\r
+ case XK_KP_Delete:\r
+ case XK_Delete: KeyData.Key.ScanCode = SCAN_DELETE; break;\r
+\r
+ case XK_KP_Insert:\r
+ case XK_Insert: KeyData.Key.ScanCode = SCAN_INSERT; break;\r
+\r
+ case XK_KP_Page_Up:\r
+ case XK_Page_Up: KeyData.Key.ScanCode = SCAN_PAGE_UP; break;\r
+\r
+ case XK_KP_Page_Down:\r
+ case XK_Page_Down: KeyData.Key.ScanCode = SCAN_PAGE_DOWN; break;\r
+\r
+ case XK_Escape: KeyData.Key.ScanCode = SCAN_ESC; break;\r
+\r
+ case XK_Pause: KeyData.Key.ScanCode = SCAN_PAUSE; break;\r
+\r
+ case XK_KP_F1:\r
+ case XK_F1: KeyData.Key.ScanCode = SCAN_F1; break;\r
+\r
+ case XK_KP_F2:\r
+ case XK_F2: KeyData.Key.ScanCode = SCAN_F2; break;\r
+\r
+ case XK_KP_F3:\r
+ case XK_F3: KeyData.Key.ScanCode = SCAN_F3; break;\r
+\r
+ case XK_KP_F4:\r
+ case XK_F4: KeyData.Key.ScanCode = SCAN_F4; break;\r
+\r
+ case XK_F5: KeyData.Key.ScanCode = SCAN_F5; break;\r
+ case XK_F6: KeyData.Key.ScanCode = SCAN_F6; break;\r
+ case XK_F7: KeyData.Key.ScanCode = SCAN_F7; break;\r
+\r
+ // Don't map into X11 by default on a Mac\r
+ // System Preferences->Keyboard->Keyboard Shortcuts can be configured\r
+ // to not use higher function keys as shortcuts and the will show up\r
+ // in X11.\r
+ case XK_F8: KeyData.Key.ScanCode = SCAN_F8; break;\r
+ case XK_F9: KeyData.Key.ScanCode = SCAN_F9; break;\r
+ case XK_F10: KeyData.Key.ScanCode = SCAN_F10; break;\r
+\r
+ case XK_F11: KeyData.Key.ScanCode = SCAN_F11; break;\r
+ case XK_F12: KeyData.Key.ScanCode = SCAN_F12; break;\r
+\r
+ case XK_F13: KeyData.Key.ScanCode = SCAN_F13; break;\r
+ case XK_F14: KeyData.Key.ScanCode = SCAN_F14; break;\r
+ case XK_F15: KeyData.Key.ScanCode = SCAN_F15; break;\r
+ case XK_F16: KeyData.Key.ScanCode = SCAN_F16; break;\r
+ case XK_F17: KeyData.Key.ScanCode = SCAN_F17; break;\r
+ case XK_F18: KeyData.Key.ScanCode = SCAN_F18; break;\r
+ case XK_F19: KeyData.Key.ScanCode = SCAN_F19; break;\r
+ case XK_F20: KeyData.Key.ScanCode = SCAN_F20; break;\r
+ case XK_F21: KeyData.Key.ScanCode = SCAN_F21; break;\r
+ case XK_F22: KeyData.Key.ScanCode = SCAN_F22; break;\r
+ case XK_F23: KeyData.Key.ScanCode = SCAN_F23; break;\r
+ case XK_F24: KeyData.Key.ScanCode = SCAN_F24; break;\r
+\r
+ // No mapping in X11\r
+ //case XK_: KeyData.Key.ScanCode = SCAN_MUTE; break;\r
+ //case XK_: KeyData.Key.ScanCode = SCAN_VOLUME_UP; break;\r
+ //case XK_: KeyData.Key.ScanCode = SCAN_VOLUME_DOWN; break;\r
+ //case XK_: KeyData.Key.ScanCode = SCAN_BRIGHTNESS_UP; break;\r
+ //case XK_: KeyData.Key.ScanCode = SCAN_BRIGHTNESS_DOWN; break;\r
+ //case XK_: KeyData.Key.ScanCode = SCAN_SUSPEND; break;\r
+ //case XK_: KeyData.Key.ScanCode = SCAN_HIBERNATE; break;\r
+ //case XK_: KeyData.Key.ScanCode = SCAN_TOGGLE_DISPLAY; break;\r
+ //case XK_: KeyData.Key.ScanCode = SCAN_RECOVERY; break;\r
+ //case XK_: KeyData.Key.ScanCode = SCAN_EJECT; break;\r
+\r
+ case XK_BackSpace: KeyData.Key.UnicodeChar = 0x0008; break;\r
+\r
+ case XK_KP_Tab:\r
+ case XK_Tab: KeyData.Key.UnicodeChar = 0x0009; break;\r
+\r
+ case XK_Linefeed: KeyData.Key.UnicodeChar = 0x000a; break;\r
+\r
+ case XK_KP_Enter:\r
+ case XK_Return: KeyData.Key.UnicodeChar = 0x000d; break;\r
+\r
+ case XK_KP_Equal : KeyData.Key.UnicodeChar = L'='; break;\r
+ case XK_KP_Multiply : KeyData.Key.UnicodeChar = L'*'; break;\r
+ case XK_KP_Add : KeyData.Key.UnicodeChar = L'+'; break;\r
+ case XK_KP_Separator : KeyData.Key.UnicodeChar = L'~'; break;\r
+ case XK_KP_Subtract : KeyData.Key.UnicodeChar = L'-'; break;\r
+ case XK_KP_Decimal : KeyData.Key.UnicodeChar = L'.'; break;\r
+ case XK_KP_Divide : KeyData.Key.UnicodeChar = L'/'; break;\r
+\r
+ case XK_KP_0 : KeyData.Key.UnicodeChar = L'0'; break;\r
+ case XK_KP_1 : KeyData.Key.UnicodeChar = L'1'; break;\r
+ case XK_KP_2 : KeyData.Key.UnicodeChar = L'2'; break;\r
+ case XK_KP_3 : KeyData.Key.UnicodeChar = L'3'; break;\r
+ case XK_KP_4 : KeyData.Key.UnicodeChar = L'4'; break;\r
+ case XK_KP_5 : KeyData.Key.UnicodeChar = L'5'; break;\r
+ case XK_KP_6 : KeyData.Key.UnicodeChar = L'6'; break;\r
+ case XK_KP_7 : KeyData.Key.UnicodeChar = L'7'; break;\r
+ case XK_KP_8 : KeyData.Key.UnicodeChar = L'8'; break;\r
+ case XK_KP_9 : KeyData.Key.UnicodeChar = L'9'; break;\r
+\r
+ default:\r
+ ;\r
+ }\r
+\r
+ // The global state is our state\r
+ KeyData.KeyState.KeyShiftState = Drv->KeyState.KeyShiftState;\r
+ KeyData.KeyState.KeyToggleState = Drv->KeyState.KeyToggleState;\r
+\r
+ if (*KeySym < XK_BackSpace) {\r
+ if (((Drv->KeyState.KeyShiftState & (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED)) != 0) ||\r
+ ((Drv->KeyState.KeyToggleState & EFI_CAPS_LOCK_ACTIVE) != 0) ) {\r
+\r
+ KeyData.Key.UnicodeChar = (CHAR16)KeySym[KEYSYM_UPPER];\r
+\r
+ // Per UEFI spec since we converted the Unicode clear the shift bits we pass up\r
+ KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);\r
+ } else {\r
+ KeyData.Key.UnicodeChar = (CHAR16)KeySym[KEYSYM_LOWER];\r
+ }\r
+ } else {\r
+ // XK_BackSpace is the start of XK_MISCELLANY. These are the XK_? keys we process in this file\r
+ ;\r
+ }\r
+\r
+ if (Make) {\r
+ memcpy (&Drv->keys[Drv->key_wr], &KeyData, sizeof (EFI_KEY_DATA));\r
+ Drv->key_wr = (Drv->key_wr + 1) % NBR_KEYS;\r
+ Drv->key_count++;\r
+ if (Drv->MakeRegisterdKeyCallback != NULL) {\r
+ ReverseGasketUint64Uint64 (Drv->MakeRegisterdKeyCallback ,Drv->RegisterdKeyCallbackContext, &KeyData);\r
+ }\r
+ } else {\r
+ if (Drv->BreakRegisterdKeyCallback != NULL) {\r
+ ReverseGasketUint64Uint64 (Drv->BreakRegisterdKeyCallback ,Drv->RegisterdKeyCallbackContext, &KeyData);\r
+ }\r
+ }\r
+}\r
+\r
+\r
+void\r
+handleMouseMoved(\r
+ IN GRAPHICS_IO_PRIVATE *Drv,\r
+ IN XEvent *ev\r
+ )\r
+{\r
+ if (ev->xmotion.x != Drv->previous_x) {\r
+ Drv->pointer_state.RelativeMovementX += ( ev->xmotion.x - Drv->previous_x );\r
+ Drv->previous_x = ev->xmotion.x;\r
+ Drv->pointer_state_changed = 1;\r
+ }\r
+\r
+ if (ev->xmotion.y != Drv->previous_y) {\r
+ Drv->pointer_state.RelativeMovementY += ( ev->xmotion.y - Drv->previous_y );\r
+ Drv->previous_y = ev->xmotion.y;\r
+ Drv->pointer_state_changed = 1;\r
+ }\r
+\r
+ Drv->pointer_state.RelativeMovementZ = 0;\r
+}\r
+\r
+void\r
+handleMouseDown (\r
+ IN GRAPHICS_IO_PRIVATE *Drv,\r
+ IN XEvent *ev,\r
+ IN BOOLEAN Pressed\r
+ )\r
+{\r
+ if (ev->xbutton.button == Button1) {\r
+ Drv->pointer_state_changed = (Drv->pointer_state.LeftButton != Pressed);\r
+ Drv->pointer_state.LeftButton = Pressed;\r
+ }\r
+ if ( ev->xbutton.button == Button2 ) {\r
+ Drv->pointer_state_changed = (Drv->pointer_state.RightButton != Pressed);\r
+ Drv->pointer_state.RightButton = Pressed;\r
+ }\r
+}\r
+\r
+void\r
+Redraw (\r
+ IN GRAPHICS_IO_PRIVATE *Drv,\r
+ IN UINTN X,\r
+ IN UINTN Y,\r
+ IN UINTN Width,\r
+ IN UINTN Height\r
+ )\r
+{\r
+ if (Drv->use_shm) {\r
+ XShmPutImage (\r
+ Drv->display, Drv->win, Drv->gc, Drv->image, X, Y, X, Y, Width, Height, False\r
+ );\r
+ } else {\r
+ XPutImage (\r
+ Drv->display, Drv->win, Drv->gc, Drv->image, X, Y, X, Y, Width, Height\r
+ );\r
+ }\r
+ XFlush(Drv->display);\r
+}\r
+\r
+void\r
+HandleEvent(GRAPHICS_IO_PRIVATE *Drv, XEvent *ev)\r
+{\r
+ switch (ev->type) {\r
+ case Expose:\r
+ Redraw (Drv, ev->xexpose.x, ev->xexpose.y,\r
+ ev->xexpose.width, ev->xexpose.height);\r
+ break;\r
+ case GraphicsExpose:\r
+ Redraw (Drv, ev->xgraphicsexpose.x, ev->xgraphicsexpose.y,\r
+ ev->xgraphicsexpose.width, ev->xgraphicsexpose.height);\r
+ break;\r
+ case KeyPress:\r
+ handleKeyEvent (Drv, ev, TRUE);\r
+ break;\r
+ case KeyRelease:\r
+ handleKeyEvent (Drv, ev, FALSE);\r
+ break;\r
+ case MappingNotify:\r
+ XRefreshKeyboardMapping (&ev->xmapping);\r
+ break;\r
+ case MotionNotify:\r
+ handleMouseMoved (Drv, ev);\r
+ break;\r
+ case ButtonPress:\r
+ handleMouseDown (Drv, ev, TRUE);\r
+ break;\r
+ case ButtonRelease:\r
+ handleMouseDown (Drv, ev, FALSE);\r
+ break;\r
+#if 0\r
+ case DestroyNotify:\r
+ XCloseDisplay (Drv->display);\r
+ exit (1);\r
+ break;\r
+#endif\r
+ case NoExpose:\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+void\r
+HandleEvents (\r
+ IN GRAPHICS_IO_PRIVATE *Drv\r
+ )\r
+{\r
+ XEvent ev;\r
+\r
+ while (XPending (Drv->display) != 0) {\r
+ XNextEvent (Drv->display, &ev);\r
+ HandleEvent (Drv, &ev);\r
+ }\r
+}\r
+\r
+unsigned long\r
+X11PixelToColor (\r
+ IN GRAPHICS_IO_PRIVATE *Drv,\r
+ IN EFI_UGA_PIXEL pixel\r
+ )\r
+{\r
+ return ((pixel.Red >> Drv->r.csize) << Drv->r.shift)\r
+ | ((pixel.Green >> Drv->g.csize) << Drv->g.shift)\r
+ | ((pixel.Blue >> Drv->b.csize) << Drv->b.shift);\r
+}\r
+\r
+EFI_UGA_PIXEL\r
+X11ColorToPixel (\r
+ IN GRAPHICS_IO_PRIVATE *Drv,\r
+ IN unsigned long val\r
+ )\r
+{\r
+ EFI_UGA_PIXEL Pixel;\r
+\r
+ memset (&Pixel, 0, sizeof (EFI_UGA_PIXEL));\r
+\r
+ // Truncation not an issue since X11 and EFI are both using 8 bits per color\r
+ Pixel.Red = (val >> Drv->r.shift) << Drv->r.csize;\r
+ Pixel.Green = (val >> Drv->g.shift) << Drv->g.csize;\r
+ Pixel.Blue = (val >> Drv->b.shift) << Drv->b.csize;\r
+\r
+ return Pixel;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+X11CheckKey (\r
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo\r
+ )\r
+{\r
+ GRAPHICS_IO_PRIVATE *Drv;\r
+\r
+ Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r
+\r
+ HandleEvents (Drv);\r
+\r
+ if (Drv->key_count != 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_NOT_READY;\r
+}\r
+\r
+EFI_STATUS\r
+X11GetKey (\r
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r
+ IN EFI_KEY_DATA *KeyData\r
+ )\r
+{\r
+ EFI_STATUS EfiStatus;\r
+ GRAPHICS_IO_PRIVATE *Drv;\r
+\r
+ Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r
+\r
+ EfiStatus = X11CheckKey (GraphicsIo);\r
+ if (EFI_ERROR (EfiStatus)) {\r
+ return EfiStatus;\r
+ }\r
+\r
+ CopyMem (KeyData, &Drv->keys[Drv->key_rd], sizeof (EFI_KEY_DATA));\r
+ Drv->key_rd = (Drv->key_rd + 1) % NBR_KEYS;\r
+ Drv->key_count--;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+X11KeySetState (\r
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
+ )\r
+{\r
+ GRAPHICS_IO_PRIVATE *Drv;\r
+\r
+ Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r
+\r
+ if (*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) {\r
+ if ((Drv->KeyState.KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == 0) {\r
+ //\r
+ // We could create an XKeyEvent and send a XK_Caps_Lock to\r
+ // the UGA/GOP Window\r
+ //\r
+ }\r
+ }\r
+\r
+ Drv->KeyState.KeyToggleState = *KeyToggleState;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+X11RegisterKeyNotify (\r
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r
+ IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeCallBack,\r
+ IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakCallBack,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ GRAPHICS_IO_PRIVATE *Drv;\r
+\r
+ Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r
+\r
+ Drv->MakeRegisterdKeyCallback = MakeCallBack;\r
+ Drv->BreakRegisterdKeyCallback = BreakCallBack;\r
+ Drv->RegisterdKeyCallbackContext = Context;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+X11Blt (\r
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r
+ IN EFI_UGA_PIXEL *BltBuffer OPTIONAL,\r
+ IN EFI_UGA_BLT_OPERATION BltOperation,\r
+ IN EMU_GRAPHICS_WINDOWS__BLT_ARGS *Args\r
+ )\r
+{\r
+ GRAPHICS_IO_PRIVATE *Private;\r
+ UINTN DstY;\r
+ UINTN SrcY;\r
+ UINTN DstX;\r
+ UINTN SrcX;\r
+ UINTN Index;\r
+ EFI_UGA_PIXEL *Blt;\r
+ UINT8 *Dst;\r
+ UINT8 *Src;\r
+ UINTN Nbr;\r
+ unsigned long Color;\r
+ XEvent ev;\r
+\r
+ Private = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r
+\r
+\r
+ //\r
+ // Check bounds\r
+ //\r
+ if (BltOperation == EfiUgaVideoToBltBuffer\r
+ || BltOperation == EfiUgaVideoToVideo) {\r
+ //\r
+ // Source is Video.\r
+ //\r
+ if (Args->SourceY + Args->Height > Private->height) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Args->SourceX + Args->Width > Private->width) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ if (BltOperation == EfiUgaBltBufferToVideo\r
+ || BltOperation == EfiUgaVideoToVideo\r
+ || BltOperation == EfiUgaVideoFill) {\r
+ //\r
+ // Destination is Video\r
+ //\r
+ if (Args->DestinationY + Args->Height > Private->height) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Args->DestinationX + Args->Width > Private->width) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ switch (BltOperation) {\r
+ case EfiUgaVideoToBltBuffer:\r
+ Blt = (EFI_UGA_PIXEL *)((UINT8 *)BltBuffer + (Args->DestinationY * Args->Delta) + Args->DestinationX * sizeof (EFI_UGA_PIXEL));\r
+ Args->Delta -= Args->Width * sizeof (EFI_UGA_PIXEL);\r
+ for (SrcY = Args->SourceY; SrcY < (Args->Height + Args->SourceY); SrcY++) {\r
+ for (SrcX = Args->SourceX; SrcX < (Args->Width + Args->SourceX); SrcX++) {\r
+ *Blt++ = X11ColorToPixel (Private, XGetPixel (Private->image, SrcX, SrcY));\r
+ }\r
+ Blt = (EFI_UGA_PIXEL *) ((UINT8 *) Blt + Args->Delta);\r
+ }\r
+ break;\r
+ case EfiUgaBltBufferToVideo:\r
+ Blt = (EFI_UGA_PIXEL *)((UINT8 *)BltBuffer + (Args->SourceY * Args->Delta) + Args->SourceX * sizeof (EFI_UGA_PIXEL));\r
+ Args->Delta -= Args->Width * sizeof (EFI_UGA_PIXEL);\r
+ for (DstY = Args->DestinationY; DstY < (Args->Height + Args->DestinationY); DstY++) {\r
+ for (DstX = Args->DestinationX; DstX < (Args->Width + Args->DestinationX); DstX++) {\r
+ XPutPixel(Private->image, DstX, DstY, X11PixelToColor(Private, *Blt));\r
+ Blt++;\r
+ }\r
+ Blt = (EFI_UGA_PIXEL *) ((UINT8 *) Blt + Args->Delta);\r
+ }\r
+ break;\r
+ case EfiUgaVideoToVideo:\r
+ Dst = Private->image_data + (Args->DestinationX << Private->pixel_shift)\r
+ + Args->DestinationY * Private->line_bytes;\r
+ Src = Private->image_data + (Args->SourceX << Private->pixel_shift)\r
+ + Args->SourceY * Private->line_bytes;\r
+ Nbr = Args->Width << Private->pixel_shift;\r
+ if (Args->DestinationY < Args->SourceY) {\r
+ for (Index = 0; Index < Args->Height; Index++) {\r
+ memcpy (Dst, Src, Nbr);\r
+ Dst += Private->line_bytes;\r
+ Src += Private->line_bytes;\r
+ }\r
+ } else {\r
+ Dst += (Args->Height - 1) * Private->line_bytes;\r
+ Src += (Args->Height - 1) * Private->line_bytes;\r
+ for (Index = 0; Index < Args->Height; Index++) {\r
+ //\r
+ // Source and Destination Y may be equal, therefore Dst and Src may\r
+ // overlap.\r
+ //\r
+ memmove (Dst, Src, Nbr);\r
+ Dst -= Private->line_bytes;\r
+ Src -= Private->line_bytes;\r
+ }\r
+ }\r
+ break;\r
+ case EfiUgaVideoFill:\r
+ Color = X11PixelToColor(Private, *BltBuffer);\r
+ for (DstY = Args->DestinationY; DstY < (Args->Height + Args->DestinationY); DstY++) {\r
+ for (DstX = Args->DestinationX; DstX < (Args->Width + Args->DestinationX); DstX++) {\r
+ XPutPixel(Private->image, DstX, DstY, Color);\r
+ }\r
+ }\r
+ break;\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Refresh screen.\r
+ //\r
+ switch (BltOperation) {\r
+ case EfiUgaVideoToVideo:\r
+ XCopyArea(\r
+ Private->display, Private->win, Private->win, Private->gc,\r
+ Args->SourceX, Args->SourceY, Args->Width, Args->Height,\r
+ Args->DestinationX, Args->DestinationY\r
+ );\r
+\r
+ while (1) {\r
+ XNextEvent (Private->display, &ev);\r
+ HandleEvent (Private, &ev);\r
+ if (ev.type == NoExpose || ev.type == GraphicsExpose) {\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ case EfiUgaVideoFill:\r
+ Color = X11PixelToColor (Private, *BltBuffer);\r
+ XSetForeground (Private->display, Private->gc, Color);\r
+ XFillRectangle (\r
+ Private->display, Private->win, Private->gc,\r
+ Args->DestinationX, Args->DestinationY, Args->Width, Args->Height\r
+ );\r
+ XFlush (Private->display);\r
+ break;\r
+ case EfiUgaBltBufferToVideo:\r
+ Redraw (Private, Args->DestinationX, Args->DestinationY, Args->Width, Args->Height);\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+X11CheckPointer (\r
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo\r
+ )\r
+{\r
+ GRAPHICS_IO_PRIVATE *Drv;\r
+\r
+ Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r
+\r
+ HandleEvents (Drv);\r
+ if (Drv->pointer_state_changed != 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_NOT_READY;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+X11GetPointerState (\r
+ IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,\r
+ IN EFI_SIMPLE_POINTER_STATE *State\r
+ )\r
+{\r
+ EFI_STATUS EfiStatus;\r
+ GRAPHICS_IO_PRIVATE *Drv;\r
+\r
+ Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;\r
+\r
+ EfiStatus = X11CheckPointer (GraphicsIo);\r
+ if (EfiStatus != EFI_SUCCESS) {\r
+ return EfiStatus;\r
+ }\r
+\r
+ memcpy (State, &Drv->pointer_state, sizeof (EFI_SIMPLE_POINTER_STATE));\r
+\r
+ Drv->pointer_state.RelativeMovementX = 0;\r
+ Drv->pointer_state.RelativeMovementY = 0;\r
+ Drv->pointer_state.RelativeMovementZ = 0;\r
+ Drv->pointer_state_changed = 0;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+EFI_STATUS\r
+X11GraphicsWindowOpen (\r
+ IN EMU_IO_THUNK_PROTOCOL *This\r
+ )\r
+{\r
+ GRAPHICS_IO_PRIVATE *Drv;\r
+ unsigned int border_width = 0;\r
+ char *display_name = NULL;\r
+\r
+ Drv = (GRAPHICS_IO_PRIVATE *)calloc (1, sizeof (GRAPHICS_IO_PRIVATE));\r
+ if (Drv == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Drv->GraphicsIo.Size = GasketX11Size;\r
+ Drv->GraphicsIo.CheckKey = GasketX11CheckKey;\r
+ Drv->GraphicsIo.GetKey = GasketX11GetKey;\r
+ Drv->GraphicsIo.KeySetState = GasketX11KeySetState;\r
+ Drv->GraphicsIo.RegisterKeyNotify = GasketX11RegisterKeyNotify;\r
+ Drv->GraphicsIo.Blt = GasketX11Blt;\r
+ Drv->GraphicsIo.CheckPointer = GasketX11CheckPointer;\r
+ Drv->GraphicsIo.GetPointerState = GasketX11GetPointerState;\r
+\r
+\r
+ Drv->key_count = 0;\r
+ Drv->key_rd = 0;\r
+ Drv->key_wr = 0;\r
+ Drv->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
+ Drv->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
+ Drv->MakeRegisterdKeyCallback = NULL;\r
+ Drv->BreakRegisterdKeyCallback = NULL;\r
+ Drv->RegisterdKeyCallbackContext = NULL;\r
+\r
+\r
+ Drv->display = XOpenDisplay (display_name);\r
+ if (Drv->display == NULL) {\r
+ fprintf (stderr, "uga: cannot connect to X server %s\n", XDisplayName (display_name));\r
+ free (Drv);\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ Drv->screen = DefaultScreen (Drv->display);\r
+ Drv->visual = DefaultVisual (Drv->display, Drv->screen);\r
+ Drv->win = XCreateSimpleWindow (\r
+ Drv->display, RootWindow (Drv->display, Drv->screen),\r
+ 0, 0, 4, 4, border_width,\r
+ WhitePixel (Drv->display, Drv->screen),\r
+ BlackPixel (Drv->display, Drv->screen)\r
+ );\r
+\r
+ Drv->depth = DefaultDepth (Drv->display, Drv->screen);\r
+ XDefineCursor (Drv->display, Drv->win, XCreateFontCursor (Drv->display, XC_pirate));\r
+\r
+ Drv->Title = malloc (StrSize (This->ConfigString));\r
+ UnicodeStrToAsciiStr (This->ConfigString, Drv->Title);\r
+ XStoreName (Drv->display, Drv->win, Drv->Title);\r
+\r
+// XAutoRepeatOff (Drv->display);\r
+ XSelectInput (\r
+ Drv->display, Drv->win,\r
+ ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask\r
+ );\r
+ Drv->gc = DefaultGC (Drv->display, Drv->screen);\r
+\r
+ This->Private = (VOID *)Drv;\r
+ This->Interface = (VOID *)Drv;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+X11GraphicsWindowClose (\r
+ IN EMU_IO_THUNK_PROTOCOL *This\r
+ )\r
+{\r
+ GRAPHICS_IO_PRIVATE *Drv;\r
+\r
+ Drv = (GRAPHICS_IO_PRIVATE *)This->Private;\r
+\r
+ if (Drv == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (Drv->image != NULL) {\r
+ XDestroyImage(Drv->image);\r
+\r
+ if (Drv->use_shm) {\r
+ shmdt (Drv->image_data);\r
+ }\r
+\r
+ Drv->image_data = NULL;\r
+ Drv->image = NULL;\r
+ }\r
+ XDestroyWindow (Drv->display, Drv->win);\r
+ XCloseDisplay (Drv->display);\r
+\r
+#ifdef __APPLE__\r
+ // Free up the shared memory\r
+ shmctl (Drv->xshm_info.shmid, IPC_RMID, NULL);\r
+#endif\r
+\r
+ free (Drv);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EMU_IO_THUNK_PROTOCOL gX11ThunkIo = {\r
+ &gEmuGraphicsWindowProtocolGuid,\r
+ NULL,\r
+ NULL,\r
+ 0,\r
+ GasketX11GraphicsWindowOpen,\r
+ GasketX11GraphicsWindowClose,\r
+ NULL\r
+};\r
+\r
+\r