]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EmulatorPkg/Unix/Host/X11GraphicsWindow.c
EmulatorPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / EmulatorPkg / Unix / Host / X11GraphicsWindow.c
index adb9b2b83037574b9f84b7c88f223267976f44c7..9d03c1301148139449289f68f1d290488865a73b 100644 (file)
-/*++ @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