summaryrefslogtreecommitdiff
path: root/hw/kdrive
diff options
context:
space:
mode:
authorMatthew Allum <breakfast@10.am>2004-08-31 16:33:05 +0000
committerMatthew Allum <breakfast@10.am>2004-08-31 16:33:05 +0000
commit2d065c4c33b9ec17c4c791070cf8189cb57bbb9c (patch)
tree3c8b69c3ef10a2910cccd539b68299a9ea0a7525 /hw/kdrive
parent6ec9ecd591fba9e9b69b8ebbd2fa08c0a2beac08 (diff)
Added ephyr server sources
Diffstat (limited to 'hw/kdrive')
-rw-r--r--hw/kdrive/Makefile.am6
-rw-r--r--hw/kdrive/ephyr/Makefile.am35
-rw-r--r--hw/kdrive/ephyr/README71
-rw-r--r--hw/kdrive/ephyr/ephyr.c677
-rw-r--r--hw/kdrive/ephyr/ephyr.h156
-rw-r--r--hw/kdrive/ephyr/ephyrinit.c183
-rw-r--r--hw/kdrive/ephyr/hostx.c566
-rw-r--r--hw/kdrive/ephyr/hostx.h137
-rw-r--r--hw/kdrive/ephyr/os.c67
9 files changed, 1898 insertions, 0 deletions
diff --git a/hw/kdrive/Makefile.am b/hw/kdrive/Makefile.am
index 7c5c406e0..27cd1ed63 100644
--- a/hw/kdrive/Makefile.am
+++ b/hw/kdrive/Makefile.am
@@ -10,12 +10,18 @@ if XSDLSERVER
XSDL_SUBDIRS=sdl
endif
+if XEPHYR
+XEPHYR_SUBDIRS = ephyr
+endif
+
SUBDIRS = \
src \
linux \
$(XSDL_SUBDIRS) \
$(FBDEV_SUBDIRS) \
$(VESA_SUBDIRS) \
+ $(XEPHYR_SUBDIRS) \
ati \
fake \
+ ephyr \
i810
diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am
new file mode 100644
index 000000000..1a38e5934
--- /dev/null
+++ b/hw/kdrive/ephyr/Makefile.am
@@ -0,0 +1,35 @@
+INCLUDES = \
+ @KDRIVE_INCS@ \
+ @XSERVER_CFLAGS@
+
+noinst_LIBRARIES = libxephyr.a libxephyr-hostx.a
+
+bin_PROGRAMS = Xephyr
+
+libxephyr_a_SOURCES = \
+ ephyr.c \
+ os.c \
+ hostx.h \
+ ephyr.h
+
+libxephyr_hostx_a_SOURCES = \
+ hostx.c \
+ hostx.h
+
+libxephyr_hostx_a_INCLUDES = @XEPHYR_INCS@
+
+Xephyr_SOURCES = \
+ ephyrinit.c
+
+Xephyr_LDADD = \
+ libxephyr.a \
+ libxephyr-hostx.a \
+ @KDRIVE_LIBS@ \
+ @XSERVER_LIBS@ \
+ @XEPHYR_LIBS@
+
+Xephyr_DEPENDENCIES = \
+ libxephyr.a \
+ libxephyr-hostx.a \
+ @KDRIVE_LIBS@
+
diff --git a/hw/kdrive/ephyr/README b/hw/kdrive/ephyr/README
new file mode 100644
index 000000000..309b73d6f
--- /dev/null
+++ b/hw/kdrive/ephyr/README
@@ -0,0 +1,71 @@
+Xephyr README
+=============
+
+
+What Is It ?
+============
+
+Xephyr is a a kdrive server that outputs to a window on a pre-existing
+'host' X display. Think Xnest but with support for modern extensions
+like composite, damage and randr.
+
+Unlike Xnest which is an X proxy, i.e. limited to the
+capabilities of the host X server, Xephyr is a real X server which
+uses the host X server window as "framebuffer" via fast SHM XImages.
+
+It also has support for 'visually' debugging what the server is
+painting.
+
+
+How To Use
+==========
+
+You probably want to run like;
+
+Xephyr :1 -ac -screen 800x600 &
+
+Then set DISPLAY=:1 and run whatever X apps you like.
+
+Use 'xrandr' to change to orientation/size.
+
+There is a '-parent' switch which works just like Xnests ( for use
+with things like matchbox-nest - http://matchbox.handhelds.org ).
+
+There is also a '-host-cursor' switch to set 'cursor acceleration' -
+The host's cursor is reused. This is only really there to aid
+debugging by avoiding server paints for the cursor. Performance
+improvement is negiable.
+
+Send a SIGUSR1 to the server ( eg kill -USR1 `pidof Xephyr` ) to
+toggle the debugging mode. In this mode red rectangles are painted to
+screen areas getting painted before painting the actual content. The
+delay between this can be altered by setting a XEPHYR_PAUSE env var to
+a value in nano seconds.
+
+
+Caveats
+=======
+
+ - Depth is limited to being the same as the host.
+
+ - Rotated displays are currently updated via full blits. This
+ is slower than a normal oprientated display. Debug mode will
+ therefor not be of much use rotated.
+
+ - The '-host-cursor' cursor is static in its appearence.
+
+ - The build gets a warning about 'nanosleep'. I think the various '-D'
+ build flags are causing this. I havn't figured as yet how to work
+ round it. It doesn't appear to break anything however.
+
+ - Keyboard handling is basic but works.
+
+ - Mouse button 5 probably wont work.
+
+
+
+
+
+Matthew Allum <mallum@o-hand.com> 2004
+
+
diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
new file mode 100644
index 000000000..ffee350c3
--- /dev/null
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -0,0 +1,677 @@
+/*
+ * Xephyr - A kdrive X server thats runs in a host X window.
+ * Authored by Matthew Allum <mallum@o-hand.com>
+ *
+ * Copyright © 2004 Nokia
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Nokia not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Nokia makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* TODO:
+ *
+ * POSSIBLES
+ * - much improve keyboard handling *kind of done*
+ * - '-fullscreen' switch ?
+ * - full keyboard grab option somehow ? - use for testing WM key shortcuts
+ * with out host WM getting them instead.
+ * - Make cursor 'accel' better.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "ephyr.h"
+
+extern int KdTsPhyScreen;
+
+static int mouseState = 0;
+
+Bool
+ephyrInitialize (KdCardInfo *card, EphyrPriv *priv)
+{
+ OsSignal(SIGUSR1, hostx_handle_signal);
+
+ priv->base = 0;
+ priv->bytes_per_line = 0;
+ return TRUE;
+}
+
+Bool
+ephyrCardInit (KdCardInfo *card)
+{
+ EphyrPriv *priv;
+
+ priv = (EphyrPriv *) xalloc (sizeof (EphyrPriv));
+ if (!priv)
+ return FALSE;
+
+ if (!ephyrInitialize (card, priv))
+ {
+ xfree (priv);
+ return FALSE;
+ }
+ card->driver = priv;
+
+ return TRUE;
+}
+
+Bool
+ephyrScreenInitialize (KdScreenInfo *screen, EphyrScrPriv *scrpriv)
+{
+ int width = 640, height = 480;
+
+ if (hostx_want_screen_size(&width, &height)
+ || !screen->width || !screen->height)
+ {
+ screen->width = width;
+ screen->height = height;
+ }
+
+ screen->width_mm = screen->width * hostx_mm_per_pixel_horizontal();
+ screen->height_mm = screen->height * hostx_mm_per_pixel_vertical();
+
+ screen->fb[0].depth = hostx_get_depth();
+ screen->rate = 72;
+
+ if (screen->fb[0].depth <= 8)
+ {
+ screen->fb[0].visuals = ((1 << StaticGray) |
+ (1 << GrayScale) |
+ (1 << StaticColor) |
+ (1 << PseudoColor) |
+ (1 << TrueColor) |
+ (1 << DirectColor));
+ }
+ else
+ {
+ screen->fb[0].visuals = (1 << TrueColor);
+
+ if (screen->fb[0].depth <= 15)
+ {
+ screen->fb[0].depth = 15;
+ screen->fb[0].bitsPerPixel = 16;
+
+ hostx_get_visual_masks (&screen->fb[0].redMask,
+ &screen->fb[0].greenMask,
+ &screen->fb[0].blueMask);
+
+ }
+ else if (screen->fb[0].depth <= 16)
+ {
+ screen->fb[0].depth = 16;
+ screen->fb[0].bitsPerPixel = 16;
+
+ hostx_get_visual_masks (&screen->fb[0].redMask,
+ &screen->fb[0].greenMask,
+ &screen->fb[0].blueMask);
+ }
+ else
+ {
+ screen->fb[0].depth = 24;
+ screen->fb[0].bitsPerPixel = 32;
+
+ hostx_get_visual_masks (&screen->fb[0].redMask,
+ &screen->fb[0].greenMask,
+ &screen->fb[0].blueMask);
+ }
+ }
+
+ scrpriv->randr = screen->randr;
+
+ return ephyrMapFramebuffer (screen);
+}
+
+Bool
+ephyrScreenInit (KdScreenInfo *screen)
+{
+ EphyrScrPriv *scrpriv;
+
+ scrpriv = xalloc (sizeof (EphyrScrPriv));
+ if (!scrpriv)
+ return FALSE;
+ memset (scrpriv, 0, sizeof (EphyrScrPriv));
+ screen->driver = scrpriv;
+ if (!ephyrScreenInitialize (screen, scrpriv))
+ {
+ screen->driver = 0;
+ xfree (scrpriv);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void*
+ephyrWindowLinear (ScreenPtr pScreen,
+ CARD32 row,
+ CARD32 offset,
+ int mode,
+ CARD32 *size,
+ void *closure)
+{
+ KdScreenPriv(pScreen);
+ EphyrPriv *priv = pScreenPriv->card->driver;
+
+ if (!pScreenPriv->enabled)
+ {
+ return 0;
+ }
+
+ *size = priv->bytes_per_line;
+ return priv->base + row * priv->bytes_per_line + offset;
+}
+
+Bool
+ephyrMapFramebuffer (KdScreenInfo *screen)
+{
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrPriv *priv = screen->card->driver;
+ KdMouseMatrix m;
+
+ EPHYR_DBG(" screen->width: %d, screen->height: %d",
+ screen->width, screen->height);
+
+ /* Always use shadow so we get damage notifications */
+ scrpriv->shadow = TRUE;
+
+ KdComputeMouseMatrix (&m, scrpriv->randr, screen->width, screen->height);
+
+ KdSetMouseMatrix (&m);
+
+ priv->bytes_per_line = ((screen->width * screen->fb[0].bitsPerPixel + 31) >> 5) << 2;
+
+ /* point the framebuffer to the data in an XImage */
+ priv->base = hostx_screen_init (screen->width, screen->height);
+
+ screen->memory_base = (CARD8 *) (priv->base);
+ screen->memory_size = 0;
+ screen->off_screen_base = 0;
+
+ KdShadowFbAlloc (screen, 0,
+ scrpriv->randr & (RR_Rotate_90|RR_Rotate_270));
+ return TRUE;
+}
+
+void
+ephyrSetScreenSizes (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+
+ if (scrpriv->randr & (RR_Rotate_0|RR_Rotate_180))
+ {
+ pScreen->width = screen->width;
+ pScreen->height = screen->height;
+ pScreen->mmWidth = screen->width_mm;
+ pScreen->mmHeight = screen->height_mm;
+ }
+ else
+ {
+ pScreen->width = screen->height;
+ pScreen->height = screen->width;
+ pScreen->mmWidth = screen->height_mm;
+ pScreen->mmHeight = screen->width_mm;
+ }
+}
+
+Bool
+ephyrUnmapFramebuffer (KdScreenInfo *screen)
+{
+ KdShadowFbFree (screen, 0);
+
+ /* Note, priv->base will get freed when XImage recreated */
+
+ return TRUE;
+}
+
+void
+ephyrShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ int nbox;
+ BoxPtr pbox;
+
+ RegionPtr damage;
+
+ if (!(scrpriv->randr & RR_Rotate_0) || (scrpriv->randr & RR_Reflect_All))
+ {
+ /* Rotated.
+ * TODO: Fix this to use damage as well so much faster.
+ * Sledgehammer approach atm.
+ *
+ * Catch reflects here too - though thats wrong ...
+ */
+ EPHYR_DBG("slow paint");
+ shadowUpdateRotatePacked(pScreen, pBuf);
+ hostx_paint_rect(0,0,0,0, screen->width, screen->height);
+ return;
+ }
+ else shadowUpdatePacked(pScreen, pBuf);
+
+ /* Figure out what rects have changed and update em. */
+
+ if (!pBuf || !pBuf->pDamage)
+ return;
+
+ damage = DamageRegion (pBuf->pDamage);
+
+ if (!REGION_NOTEMPTY (pScreen, damage))
+ return;
+
+ nbox = REGION_NUM_RECTS (damage);
+ pbox = REGION_RECTS (damage);
+
+ while (nbox--)
+ {
+ hostx_paint_rect(pbox->x1, pbox->y1,
+ pbox->x1, pbox->y1,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ pbox++;
+ }
+}
+
+Bool
+ephyrSetShadow (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ ShadowUpdateProc update;
+ ShadowWindowProc window;
+
+ window = ephyrWindowLinear;
+ update = ephyrShadowUpdate;
+
+ return KdShadowSet (pScreen, scrpriv->randr, update, window);
+}
+
+#ifdef RANDR
+Bool
+ephyrRandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ RRScreenSizePtr pSize;
+ Rotation randr;
+ int n = 0;
+
+ EPHYR_DBG("mark");
+
+ struct { int width, height; } sizes[] =
+ {
+ { 1600, 1200 },
+ { 1400, 1050 },
+ { 1280, 960 },
+ { 1280, 1024 },
+ { 1152, 768 },
+ { 1024, 768 },
+ { 832, 624 },
+ { 800, 600 },
+ { 720, 400 },
+ { 480, 640 },
+ { 640, 480 },
+ { 640, 400 },
+ { 320, 240 },
+ { 240, 320 },
+ { 160, 160 },
+ { 0, 0 }
+ };
+
+ *rotations = RR_Rotate_All|RR_Reflect_All;
+
+ if (!hostx_want_preexisting_window()) /* only if no -parent switch */
+ {
+ while (sizes[n].width != 0 && sizes[n].height != 0)
+ {
+ RRRegisterSize (pScreen,
+ sizes[n].width,
+ sizes[n].height,
+ sizes[n].width * hostx_mm_per_pixel_horizontal(),
+ sizes[n].height * hostx_mm_per_pixel_vertical());
+ n++;
+ }
+ }
+
+ pSize = RRRegisterSize (pScreen,
+ screen->width,
+ screen->height,
+ screen->width_mm,
+ screen->height_mm);
+
+ randr = KdSubRotation (scrpriv->randr, screen->randr);
+
+ RRSetCurrentConfig (pScreen, randr, 0, pSize);
+
+ return TRUE;
+}
+
+Bool
+ephyrRandRSetConfig (ScreenPtr pScreen,
+ Rotation randr,
+ int rate,
+ RRScreenSizePtr pSize)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ Bool wasEnabled = pScreenPriv->enabled;
+ EphyrScrPriv oldscr;
+ int oldwidth;
+ int oldheight;
+ int oldmmwidth;
+ int oldmmheight;
+ int newwidth, newheight;
+
+ if (screen->randr & (RR_Rotate_0|RR_Rotate_180))
+ {
+ newwidth = pSize->width;
+ newheight = pSize->height;
+ }
+ else
+ {
+ newwidth = pSize->height;
+ newheight = pSize->width;
+ }
+
+ if (wasEnabled)
+ KdDisableScreen (pScreen);
+
+ oldscr = *scrpriv;
+
+ oldwidth = screen->width;
+ oldheight = screen->height;
+ oldmmwidth = pScreen->mmWidth;
+ oldmmheight = pScreen->mmHeight;
+
+ /*
+ * Set new configuration
+ */
+
+ scrpriv->randr = KdAddRotation (screen->randr, randr);
+
+ KdOffscreenSwapOut (screen->pScreen);
+
+ ephyrUnmapFramebuffer (screen);
+
+ screen->width = newwidth;
+ screen->height = newheight;
+
+ if (!ephyrMapFramebuffer (screen))
+ goto bail4;
+
+ KdShadowUnset (screen->pScreen);
+
+ if (!ephyrSetShadow (screen->pScreen))
+ goto bail4;
+
+ ephyrSetScreenSizes (screen->pScreen);
+
+ /*
+ * Set frame buffer mapping
+ */
+ (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen),
+ pScreen->width,
+ pScreen->height,
+ screen->fb[0].depth,
+ screen->fb[0].bitsPerPixel,
+ screen->fb[0].byteStride,
+ screen->fb[0].frameBuffer);
+
+ /* set the subpixel order */
+
+ KdSetSubpixelOrder (pScreen, scrpriv->randr);
+
+
+ if (wasEnabled)
+ KdEnableScreen (pScreen);
+
+ return TRUE;
+
+bail4:
+ EPHYR_DBG("bailed");
+
+ ephyrUnmapFramebuffer (screen);
+ *scrpriv = oldscr;
+ (void) ephyrMapFramebuffer (screen);
+
+ pScreen->width = oldwidth;
+ pScreen->height = oldheight;
+ pScreen->mmWidth = oldmmwidth;
+ pScreen->mmHeight = oldmmheight;
+
+ if (wasEnabled)
+ KdEnableScreen (pScreen);
+ return FALSE;
+}
+
+Bool
+ephyrRandRInit (ScreenPtr pScreen)
+{
+ rrScrPrivPtr pScrPriv;
+
+ if (!RRScreenInit (pScreen))
+ {
+ return FALSE;
+ }
+
+ pScrPriv = rrGetScrPriv(pScreen);
+ pScrPriv->rrGetInfo = ephyrRandRGetInfo;
+ pScrPriv->rrSetConfig = ephyrRandRSetConfig;
+ return TRUE;
+}
+#endif
+
+Bool
+ephyrCreateColormap (ColormapPtr pmap)
+{
+ return fbInitializeColormap (pmap);
+}
+
+Bool
+ephyrInitScreen (ScreenPtr pScreen)
+{
+#ifdef TOUCHSCREEN
+ KdTsPhyScreen = pScreen->myNum;
+#endif
+
+ pScreen->CreateColormap = ephyrCreateColormap;
+ return TRUE;
+}
+
+Bool
+ephyrFinishInitScreen (ScreenPtr pScreen)
+{
+ if (!shadowSetup (pScreen))
+ return FALSE;
+
+#ifdef RANDR
+ if (!ephyrRandRInit (pScreen))
+ return FALSE;
+#endif
+
+ return TRUE;
+}
+
+Bool
+ephyrCreateResources (ScreenPtr pScreen)
+{
+ return ephyrSetShadow (pScreen);
+}
+
+void
+ephyrPreserve (KdCardInfo *card)
+{
+}
+
+Bool
+ephyrEnable (ScreenPtr pScreen)
+{
+ return TRUE;
+}
+
+Bool
+ephyrDPMS (ScreenPtr pScreen, int mode)
+{
+ return TRUE;
+}
+
+void
+ephyrDisable (ScreenPtr pScreen)
+{
+}
+
+void
+ephyrRestore (KdCardInfo *card)
+{
+}
+
+void
+ephyrScreenFini (KdScreenInfo *screen)
+{
+}
+
+void
+ephyrPoll(void)
+{
+ EphyrHostXEvent ev;
+
+ while (hostx_get_event(&ev))
+ {
+ switch (ev.type)
+ {
+ case EPHYR_EV_MOUSE_MOTION:
+ KdEnqueueMouseEvent(kdMouseInfo, mouseState,
+ ev.data.mouse_motion.x,
+ ev.data.mouse_motion.y);
+ break;
+
+ case EPHYR_EV_MOUSE_PRESS:
+
+ mouseState |= ev.data.mouse_down.button_num;
+ KdEnqueueMouseEvent(kdMouseInfo, mouseState|KD_MOUSE_DELTA, 0, 0);
+ break;
+
+ case EPHYR_EV_MOUSE_RELEASE:
+
+ mouseState &= ~ev.data.mouse_up.button_num;
+ KdEnqueueMouseEvent(kdMouseInfo, mouseState|KD_MOUSE_DELTA, 0, 0);
+ break;
+
+ case EPHYR_EV_KEY_PRESS:
+
+ KdEnqueueKeyboardEvent (ev.data.key_down.scancode, FALSE);
+ break;
+
+ case EPHYR_EV_KEY_RELEASE:
+
+ KdEnqueueKeyboardEvent (ev.data.key_up.scancode, TRUE);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void
+ephyrCardFini (KdCardInfo *card)
+{
+ EphyrPriv *priv = card->driver;
+ xfree (priv);
+}
+
+void
+ephyrGetColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
+{
+ while (n--)
+ {
+ pdefs->red = 0;
+ pdefs->green = 0;
+ pdefs->blue = 0;
+ pdefs++;
+ }
+}
+
+void
+ephyrPutColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
+{
+}
+
+/* Mouse calls */
+
+static Bool
+MouseInit (void)
+{
+ return TRUE;
+}
+
+static void
+MouseFini (void)
+{
+ ;
+}
+
+KdMouseFuncs EphyrMouseFuncs = {
+ MouseInit,
+ MouseFini,
+};
+
+/* Keyboard */
+
+static void
+EphyrKeyboardLoad (void)
+{
+ EPHYR_DBG("mark");
+
+ hostx_load_keymap();
+}
+
+static int
+EphyrKeyboardInit (void)
+{
+ return 0;
+}
+
+static void
+EphyrKeyboardFini (void)
+{
+}
+
+static void
+EphyrKeyboardLeds (int leds)
+{
+}
+
+static void
+EphyrKeyboardBell (int volume, int frequency, int duration)
+{
+}
+
+KdKeyboardFuncs EphyrKeyboardFuncs = {
+ EphyrKeyboardLoad,
+ EphyrKeyboardInit,
+ EphyrKeyboardLeds,
+ EphyrKeyboardBell,
+ EphyrKeyboardFini,
+ 0,
+};
diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h
new file mode 100644
index 000000000..d7c9ecdb4
--- /dev/null
+++ b/hw/kdrive/ephyr/ephyr.h
@@ -0,0 +1,156 @@
+/*
+ * Xephyr - A kdrive X server thats runs in a host X window.
+ * Authored by Matthew Allum <mallum@o-hand.com>
+ *
+ * Copyright © 2004 Nokia
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Nokia not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Nokia makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _EPHYR_H_
+#define _EPHYR_H_
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "os.h" /* for OsSignal() */
+#include "kdrive.h"
+#include "kkeymap.h"
+#include "hostx.h"
+
+#ifdef RANDR
+#include "randrstr.h"
+#endif
+
+typedef struct _ephyrPriv {
+ CARD8 *base;
+ int bytes_per_line;
+} EphyrPriv;
+
+typedef struct _ephyrScrPriv {
+ Rotation randr;
+ Bool shadow;
+ PixmapPtr pShadow;
+} EphyrScrPriv;
+
+extern KdCardFuncs ephyrFuncs;
+
+Bool
+ephyrInitialize (KdCardInfo *card, EphyrPriv *priv);
+
+Bool
+ephyrCardInit (KdCardInfo *card);
+
+Bool
+ephyrScreenInit (KdScreenInfo *screen);
+
+Bool
+ephyrScreenInitialize (KdScreenInfo *screen, EphyrScrPriv *scrpriv);
+
+Bool
+ephyrInitScreen (ScreenPtr pScreen);
+
+Bool
+ephyrFinishInitScreen (ScreenPtr pScreen);
+
+Bool
+ephyrCreateResources (ScreenPtr pScreen);
+
+void
+ephyrPreserve (KdCardInfo *card);
+
+Bool
+ephyrEnable (ScreenPtr pScreen);
+
+Bool
+ephyrDPMS (ScreenPtr pScreen, int mode);
+
+void
+ephyrDisable (ScreenPtr pScreen);
+
+void
+ephyrRestore (KdCardInfo *card);
+
+void
+ephyrScreenFini (KdScreenInfo *screen);
+
+void
+ephyrCardFini (KdCardInfo *card);
+
+void
+ephyrGetColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs);
+
+void
+ephyrPutColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs);
+
+Bool
+ephyrMapFramebuffer (KdScreenInfo *screen);
+
+void *
+ephyrWindowLinear (ScreenPtr pScreen,
+ CARD32 row,
+ CARD32 offset,
+ int mode,
+ CARD32 *size,
+ void *closure);
+
+void
+ephyrSetScreenSizes (ScreenPtr pScreen);
+
+Bool
+ephyrUnmapFramebuffer (KdScreenInfo *screen);
+
+Bool
+ephyrSetShadow (ScreenPtr pScreen);
+
+Bool
+ephyrCreateColormap (ColormapPtr pmap);
+
+void
+ephyrPoll(void);
+
+#ifdef RANDR
+Bool
+ephyrRandRGetInfo (ScreenPtr pScreen, Rotation *rotations);
+
+Bool
+ephyrRandRSetConfig (ScreenPtr pScreen,
+ Rotation randr,
+ int rate,
+ RRScreenSizePtr pSize);
+Bool
+ephyrRandRInit (ScreenPtr pScreen);
+
+void
+ephyrShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf);
+
+#endif
+
+extern KdMouseFuncs EphyrMouseFuncs;
+
+extern KdKeyboardFuncs EphyrKeyboardFuncs;
+
+extern KdOsFuncs EphyrOsFuncs;
+
+extern Bool ephyrCursorInit(ScreenPtr pScreen);
+
+extern void ephyrCursorEnable(ScreenPtr pScreen);
+
+
+#endif
diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c
new file mode 100644
index 000000000..76df5885e
--- /dev/null
+++ b/hw/kdrive/ephyr/ephyrinit.c
@@ -0,0 +1,183 @@
+/*
+ * Xephyr - A kdrive X server thats runs in a host X window.
+ * Authored by Matthew Allum <mallum@o-hand.com>
+ *
+ * Copyright © 2004 Nokia
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Nokia not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Nokia makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "ephyr.h"
+
+extern Window EphyrPreExistingHostWin;
+
+void
+InitCard (char *name)
+{
+ KdCardAttr attr;
+
+ EPHYR_DBG("mark");
+
+ if (hostx_want_host_cursor())
+ {
+ ephyrFuncs.initCursor = &ephyrCursorInit;
+ ephyrFuncs.enableCursor = &ephyrCursorEnable;
+ }
+
+ KdCardInfoAdd (&ephyrFuncs, &attr, 0);
+}
+
+void
+InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv)
+{
+ KdInitOutput (pScreenInfo, argc, argv);
+}
+
+void
+InitInput (int argc, char **argv)
+{
+ KdInitInput (&EphyrMouseFuncs, &EphyrKeyboardFuncs);
+}
+
+void
+ddxUseMsg (void)
+{
+ KdUseMsg();
+
+ ErrorF("\nXephyr Option Usage:\n");
+ ErrorF("-parent XID Use existing window as Xephyr root win\n");
+ ErrorF("-host-cursor Re-use exisiting X host server cursor\n");
+ ErrorF("\n");
+
+ exit(1);
+}
+
+int
+ddxProcessArgument (int argc, char **argv, int i)
+{
+ EPHYR_DBG("mark");
+
+ if (!strcmp (argv[i], "-parent"))
+ {
+ if(i+1 < argc)
+ {
+ hostx_use_preexisting_window(strtol(argv[i+1], NULL, 0));
+ return 2;
+ }
+
+ UseMsg();
+ exit(1);
+ }
+ else if (!strcmp (argv[i], "-host-cursor"))
+ {
+ hostx_use_host_cursor();
+ return 1;
+ }
+
+ return KdProcessArgument (argc, argv, i);
+}
+
+void
+OsVendorInit (void)
+{
+ EPHYR_DBG("mark");
+ KdOsInit (&EphyrOsFuncs);
+}
+
+/* 'Fake' cursor stuff, could be improved */
+
+static Bool
+ephyrRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+{
+ return TRUE;
+}
+
+static Bool
+ephyrUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+{
+ return TRUE;
+}
+
+static void
+ephyrSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+{
+ ;
+}
+
+static void
+ephyrMoveCursor(ScreenPtr pScreen, int x, int y)
+{
+ ;
+}
+
+miPointerSpriteFuncRec EphyrPointerSpriteFuncs = {
+ ephyrRealizeCursor,
+ ephyrUnrealizeCursor,
+ ephyrSetCursor,
+ ephyrMoveCursor,
+};
+
+
+Bool
+ephyrCursorInit(ScreenPtr pScreen)
+{
+ miPointerInitialize(pScreen, &EphyrPointerSpriteFuncs,
+ &kdPointerScreenFuncs, FALSE);
+
+ return TRUE;
+}
+
+void
+ephyrCursorEnable(ScreenPtr pScreen)
+{
+ ;
+}
+
+KdCardFuncs ephyrFuncs = {
+ ephyrCardInit, /* cardinit */
+ ephyrScreenInit, /* scrinit */
+ ephyrInitScreen, /* initScreen */
+ ephyrFinishInitScreen, /* finishInitScreen */
+ ephyrCreateResources, /* createRes */
+ ephyrPreserve, /* preserve */
+ ephyrEnable, /* enable */
+ ephyrDPMS, /* dpms */
+ ephyrDisable, /* disable */
+ ephyrRestore, /* restore */
+ ephyrScreenFini, /* scrfini */
+ ephyrCardFini, /* cardfini */
+
+ 0, /* initCursor */
+ 0, /* enableCursor */
+ 0, /* disableCursor */
+ 0, /* finiCursor */
+ 0, /* recolorCursor */
+
+ 0, /* initAccel */
+ 0, /* enableAccel */
+ 0, /* syncAccel */
+ 0, /* disableAccel */
+ 0, /* finiAccel */
+
+ ephyrGetColors, /* getColors */
+ ephyrPutColors, /* putColors */
+};
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
new file mode 100644
index 000000000..a4aea3f3f
--- /dev/null
+++ b/hw/kdrive/ephyr/hostx.c
@@ -0,0 +1,566 @@
+/*
+ * Xephyr - A kdrive X server thats runs in a host X window.
+ * Authored by Matthew Allum <mallum@o-hand.com>
+ *
+ * Copyright © 2004 Nokia
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Nokia not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Nokia makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hostx.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h> /* for memset */
+#include <time.h>
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/time.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/XShm.h>
+
+/*
+ * All xlib calls go here, which gets built as its own .a .
+ * Mixing kdrive and xlib headers causes all sorts of types
+ * to get clobbered.
+ */
+
+struct EphyrHostXVars
+{
+ Display *dpy;
+ int screen;
+ Visual *visual;
+ Window win, winroot;
+ Window win_pre_existing; /* Set via -parent option like xnest */
+ GC gc;
+ int depth;
+ XImage *ximg;
+ int win_width, win_height;
+ double mm_per_pixel_vertical, mm_per_pixel_horizontal;
+
+ Bool use_host_cursor;
+ Bool have_shm;
+ long damage_debug_nsec;
+
+ XShmSegmentInfo shminfo;
+};
+
+static EphyrHostXVars HostX = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; /* defaults */
+
+static int HostXWantDamageDebug = 0;
+
+extern KeySym EphyrKeymap[];
+
+extern KeySym kdKeymap[];
+extern int kdMinScanCode;
+extern int kdMaxScanCode;
+extern int kdMinKeyCode;
+extern int kdMaxKeyCode;
+extern int kdKeymapWidth;
+
+/* X Error traps */
+
+static int trapped_error_code = 0;
+static int (*old_error_handler) (Display *d, XErrorEvent *e);
+
+static int
+error_handler(Display *display,
+ XErrorEvent *error)
+{
+ trapped_error_code = error->error_code;
+ return 0;
+}
+
+static void
+hostx_errors_trap(void)
+{
+ trapped_error_code = 0;
+ old_error_handler = XSetErrorHandler(error_handler);
+}
+
+static int
+hostx_errors_untrap(void)
+{
+ XSetErrorHandler(old_error_handler);
+ return trapped_error_code;
+}
+
+int
+hostx_want_screen_size(int *width, int *height)
+{
+ if (HostX.win_pre_existing != None)
+ {
+ *width = HostX.win_width;
+ *height = HostX.win_height;
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+hostx_want_host_cursor(void)
+{
+ return HostX.use_host_cursor;
+}
+
+void
+hostx_use_host_cursor(void)
+{
+ HostX.use_host_cursor = True;
+}
+
+int
+hostx_want_preexisting_window(void)
+{
+ if (HostX.win_pre_existing)
+ return 1;
+ else
+ return 0;
+}
+
+void
+hostx_use_preexisting_window(unsigned long win_id)
+{
+ HostX.win_pre_existing = win_id;
+}
+
+static void
+hostx_toggle_damage_debug(void)
+{
+ HostXWantDamageDebug ^= 1;
+}
+
+void
+hostx_handle_signal(int signum)
+{
+ hostx_toggle_damage_debug();
+ EPHYR_DBG("Signal caught. Damage Debug:%i\n", HostXWantDamageDebug);
+}
+
+int
+hostx_init(void)
+{
+ XSetWindowAttributes attr;
+ Cursor empty_cursor;
+ Pixmap cursor_pxm;
+ XColor col;
+
+ attr.event_mask =
+ ButtonPressMask
+ |ButtonReleaseMask
+ |PointerMotionMask
+ |KeyPressMask
+ |KeyReleaseMask
+ |ExposureMask;
+
+ EPHYR_DBG("mark");
+
+ if ((HostX.dpy = XOpenDisplay(getenv("DISPLAY"))) == NULL)
+ {
+ fprintf(stderr, "\nXephyr cannot open host display. Is DISPLAY set?\n");
+ exit(1);
+ }
+
+ HostX.screen = DefaultScreen(HostX.dpy);
+ HostX.winroot = RootWindow(HostX.dpy, HostX.screen);
+ HostX.gc = XCreateGC(HostX.dpy, HostX.winroot, 0, NULL);
+ HostX.depth = DefaultDepth(HostX.dpy, HostX.screen);
+ HostX.visual = DefaultVisual(HostX.dpy, HostX.screen);
+
+ HostX.mm_per_pixel_vertical = (double)DisplayHeightMM(HostX.dpy, HostX.screen)
+ / DisplayHeight(HostX.dpy, HostX.screen);
+
+ HostX.mm_per_pixel_horizontal = (double)DisplayWidthMM(HostX.dpy, HostX.screen)
+ / DisplayWidth(HostX.dpy, HostX.screen);
+
+ if (HostX.win_pre_existing != None)
+ {
+ Status result;
+ XWindowAttributes attr;
+
+ /* Get screen size from existing window */
+
+ HostX.win = HostX.win_pre_existing;
+
+ hostx_errors_trap();
+
+ result = XGetWindowAttributes(HostX.dpy, HostX.win, &attr);
+
+ if (hostx_errors_untrap() || !result)
+ {
+ fprintf(stderr, "\nXephyr -parent window' does not exist!\n");
+ exit(1);
+ }
+
+ HostX.win_width = attr.width;
+ HostX.win_height = attr.height;
+ }
+ else
+ {
+ HostX.win = XCreateWindow(HostX.dpy,
+ HostX.winroot,
+ 0,0,100,100, /* will resize */
+ 0,
+ CopyFromParent,
+ CopyFromParent,
+ CopyFromParent,
+ CWEventMask,
+ &attr);
+
+ XStoreName(HostX.dpy, HostX.win, "Xephyr");
+ }
+
+ HostX.gc = XCreateGC(HostX.dpy, HostX.winroot, 0, NULL);
+
+ XParseColor(HostX.dpy, DefaultColormap(HostX.dpy,HostX.screen), "red", &col);
+ XAllocColor(HostX.dpy, DefaultColormap(HostX.dpy, HostX.screen), &col);
+ XSetForeground(HostX.dpy, HostX.gc, col.pixel);
+
+ if (!hostx_want_host_cursor())
+ {
+ /* Ditch the cursor, we provide our 'own' */
+ cursor_pxm = XCreatePixmap (HostX.dpy, HostX.winroot, 1, 1, 1);
+ memset (&col, 0, sizeof (col));
+ empty_cursor = XCreatePixmapCursor (HostX.dpy,
+ cursor_pxm, cursor_pxm,
+ &col, &col, 1, 1);
+ XDefineCursor (HostX.dpy, HostX.win, empty_cursor);
+ XFreePixmap (HostX.dpy, cursor_pxm);
+ }
+
+ HostX.ximg = NULL;
+
+ /* Try to get share memory ximages for a little bit more speed */
+
+ if (!XShmQueryExtension(HostX.dpy) || getenv("XEPHYR_NO_SHM"))
+ {
+ fprintf(stderr, "\nXephyr unable to use SHM XImages\n");
+ HostX.have_shm = False;
+ }
+ else
+ {
+ /* Really really check we have shm - better way ?*/
+ XShmSegmentInfo shminfo;
+
+ HostX.have_shm = True;
+
+ shminfo.shmid=shmget(IPC_PRIVATE, 1, IPC_CREAT|0777);
+ shminfo.shmaddr=shmat(shminfo.shmid,0,0);
+ shminfo.readOnly=True;
+
+ hostx_errors_trap();
+
+ XShmAttach(HostX.dpy, &shminfo);
+ XSync(HostX.dpy, False);
+
+ if (hostx_errors_untrap())
+ {
+ fprintf(stderr, "\nXephyr unable to use SHM XImages\n");
+ HostX.have_shm = False;
+ }
+
+ shmdt(shminfo.shmaddr);
+ shmctl(shminfo.shmid, IPC_RMID, 0);
+ }
+
+ XFlush(HostX.dpy);
+
+ /* Setup the pause time between paints when debugging updates */
+
+ HostX.damage_debug_nsec = 10^8;
+
+ if (getenv("XEPHYR_PAUSE"))
+ HostX.damage_debug_nsec = strtol(getenv("XEPHYR_PAUSE"), NULL, 0);
+
+ return 1;
+}
+
+int
+hostx_get_depth (void)
+{
+ return HostX.depth;
+}
+
+int
+hostx_get_bpp(void)
+{
+ return HostX.visual->bits_per_rgb;
+}
+
+void
+hostx_get_visual_masks (unsigned long *rmsk,
+ unsigned long *gmsk,
+ unsigned long *bmsk)
+{
+ *rmsk = HostX.visual->red_mask;
+ *gmsk = HostX.visual->green_mask;
+ *bmsk = HostX.visual->blue_mask;
+}
+
+double
+hostx_mm_per_pixel_vertical(void)
+{
+ return HostX.mm_per_pixel_vertical;
+}
+
+double
+hostx_mm_per_pixel_horizontal(void)
+{
+ return HostX.mm_per_pixel_horizontal;
+}
+
+
+void*
+hostx_screen_init (int width, int height)
+{
+ int bitmap_pad;
+ Bool shm_success = False;
+ XSizeHints *size_hints;
+
+ EPHYR_DBG("mark");
+
+ if (HostX.ximg != NULL)
+ {
+ /* Free up the image data if previously used
+ * i.ie called by server reset
+ */
+
+ if (HostX.have_shm)
+ {
+ XShmDetach(HostX.dpy, &HostX.shminfo);
+ XDestroyImage (HostX.ximg);
+ shmdt(HostX.shminfo.shmaddr);
+ shmctl(HostX.shminfo.shmid, IPC_RMID, 0);
+ }
+ else
+ {
+ if (HostX.ximg->data)
+ {
+ free(HostX.ximg->data);
+ HostX.ximg->data = NULL;
+ }
+
+ XDestroyImage(HostX.ximg);
+ }
+ }
+
+ if (HostX.have_shm)
+ {
+ HostX.ximg = XShmCreateImage(HostX.dpy, HostX.visual, HostX.depth,
+ ZPixmap, NULL, &HostX.shminfo,
+ width, height );
+
+ HostX.shminfo.shmid = shmget(IPC_PRIVATE,
+ HostX.ximg->bytes_per_line * height,
+ IPC_CREAT|0777);
+ HostX.shminfo.shmaddr = HostX.ximg->data = shmat(HostX.shminfo.shmid,
+ 0, 0);
+
+ if (HostX.ximg->data == (char *)-1)
+ {
+ EPHYR_DBG("Can't attach SHM Segment, falling back to plain XImages");
+ HostX.have_shm = False;
+ XDestroyImage(HostX.ximg);
+ shmctl(HostX.shminfo.shmid, IPC_RMID, 0);
+ }
+ else
+ {
+ EPHYR_DBG("SHM segment attached");
+ HostX.shminfo.readOnly = False;
+ XShmAttach(HostX.dpy, &HostX.shminfo);
+ shm_success = True;
+ }
+ }
+
+ if (!shm_success)
+ {
+ bitmap_pad = ( HostX.depth > 16 )? 32 : (( HostX.depth > 8 )? 16 : 8 );
+
+ HostX.ximg = XCreateImage( HostX.dpy,
+ HostX.visual,
+ HostX.depth,
+ ZPixmap, 0, 0,
+ width,
+ height,
+ bitmap_pad,
+ 0);
+
+ HostX.ximg->data = malloc( HostX.ximg->bytes_per_line * height );
+ }
+
+
+ XResizeWindow(HostX.dpy, HostX.win, width, height);
+
+ /* Ask the WM to keep our size static */
+ size_hints = XAllocSizeHints();
+ size_hints->max_width = size_hints->min_width = width;
+ size_hints->max_height = size_hints->min_height = height;
+ size_hints->flags = PMinSize|PMaxSize;
+ XSetWMNormalHints(HostX.dpy, HostX.win, size_hints);
+ XFree(size_hints);
+
+ XMapWindow(HostX.dpy, HostX.win);
+
+ XSync(HostX.dpy, False);
+
+ HostX.win_width = width;
+ HostX.win_height = height;
+
+ return HostX.ximg->data;
+}
+
+void
+hostx_paint_rect(int sx, int sy,
+ int dx, int dy,
+ int width, int height)
+{
+ /*
+ * Copy the image data updated by the shadow layer
+ * on to the window
+ */
+
+ if (HostXWantDamageDebug)
+ {
+ hostx_paint_debug_rect(dx, dy, width, height);
+ }
+
+ if (HostX.have_shm)
+ {
+ XShmPutImage(HostX.dpy, HostX.win, HostX.gc, HostX.ximg,
+ sx, sy, dx, dy, width, height, False);
+ }
+ else
+ {
+ XPutImage(HostX.dpy, HostX.win, HostX.gc, HostX.ximg,
+ sx, sy, dx, dy, width, height);
+ }
+
+ XSync(HostX.dpy, False);
+}
+
+void
+hostx_paint_debug_rect(int x, int y,
+ int width, int height)
+{
+ struct timespec tspec;
+
+ tspec.tv_sec = 0;
+ tspec.tv_nsec = HostX.damage_debug_nsec;
+
+ XFillRectangle(HostX.dpy, HostX.win, HostX.gc, x, y, width,height);
+ XSync(HostX.dpy, False);
+
+ nanosleep(&tspec, NULL);
+}
+
+void
+hostx_load_keymap(void)
+{
+ KeySym *keymap;
+ int mapWidth, min_keycode, max_keycode;
+
+ XDisplayKeycodes(HostX.dpy, &min_keycode, &max_keycode);
+
+ EPHYR_DBG("min: %d, max: %d", min_keycode, max_keycode);
+
+ keymap = XGetKeyboardMapping(HostX.dpy,
+ min_keycode,
+ max_keycode - min_keycode + 1,
+ &mapWidth);
+
+ memcpy (kdKeymap, keymap,
+ (max_keycode - min_keycode + 1)*mapWidth*sizeof(KeySym));
+
+ EPHYR_DBG("keymap width: %d", mapWidth);
+
+ /* all kdrive vars - see kkeymap.c */
+
+ kdMinScanCode = min_keycode;
+ kdMaxScanCode = max_keycode;
+ kdMinKeyCode = min_keycode;
+ kdMaxKeyCode = max_keycode;
+ kdKeymapWidth = mapWidth;
+
+ XFree(keymap);
+}
+
+int
+hostx_get_event(EphyrHostXEvent *ev)
+{
+ XEvent xev;
+
+ if (XPending(HostX.dpy))
+ {
+ XNextEvent(HostX.dpy, &xev);
+
+ switch (xev.type)
+ {
+ case Expose:
+ /* Not so great event compression, but works ok */
+ while (XCheckTypedWindowEvent(HostX.dpy, xev.xexpose.window,
+ Expose, &xev));
+ hostx_paint_rect(0, 0, 0, 0, HostX.win_width, HostX.win_height);
+ return 0;
+
+ case MotionNotify:
+ ev->type = EPHYR_EV_MOUSE_MOTION;
+ ev->data.mouse_motion.x = xev.xmotion.x;
+ ev->data.mouse_motion.y = xev.xmotion.y;
+ return 1;
+
+ case ButtonPress:
+ ev->type = EPHYR_EV_MOUSE_PRESS;
+ /*
+ * This is a bit hacky. will break for button 5 ( defined as 0x10 )
+ * Check KD_BUTTON defines in kdrive.h
+ */
+ ev->data.mouse_down.button_num = 1<<(xev.xbutton.button-1);
+ return 1;
+
+ case ButtonRelease:
+ ev->type = EPHYR_EV_MOUSE_RELEASE;
+ ev->data.mouse_up.button_num = 1<<(xev.xbutton.button-1);
+ return 1;
+
+ case KeyPress:
+ {
+ ev->type = EPHYR_EV_KEY_PRESS;
+ ev->data.key_down.scancode = xev.xkey.keycode;
+ return 1;
+ }
+ case KeyRelease:
+ ev->type = EPHYR_EV_KEY_RELEASE;
+ ev->data.key_up.scancode = xev.xkey.keycode;
+
+ return 1;
+
+ default:
+ break;
+
+ }
+ }
+ return 0;
+}
+
diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h
new file mode 100644
index 000000000..69607e73d
--- /dev/null
+++ b/hw/kdrive/ephyr/hostx.h
@@ -0,0 +1,137 @@
+/*
+ * Xephyr - A kdrive X server thats runs in a host X window.
+ * Authored by Matthew Allum <mallum@o-hand.com>
+ *
+ * Copyright © 2004 Nokia
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Nokia not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Nokia makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _XLIBS_STUFF_H_
+#define _XLIBS_STUFF_H_
+
+#define EPHYR_WANT_DEBUG 0
+
+#if (EPHYR_WANT_DEBUG)
+#define EPHYR_DBG(x, a...) \
+ fprintf(stderr, __FILE__ ":%d,%s() " x "\n", __LINE__, __func__, ##a)
+#else
+#define EPHYR_DBG(x, a...) do {} while (0)
+#endif
+
+typedef struct EphyrHostXVars EphyrHostXVars;
+typedef struct EphyrHostXEvent EphyrHostXEvent;
+
+typedef enum EphyrHostXEventType
+{
+ EPHYR_EV_MOUSE_MOTION,
+ EPHYR_EV_MOUSE_PRESS,
+ EPHYR_EV_MOUSE_RELEASE,
+ EPHYR_EV_KEY_PRESS,
+ EPHYR_EV_KEY_RELEASE
+}
+EphyrHostXEventType;
+
+struct EphyrHostXEvent
+{
+ EphyrHostXEventType type;
+
+ union
+ {
+ struct mouse_motion {
+ int x;
+ int y;
+ } mouse_motion;
+
+ struct mouse_down {
+ int button_num;
+ } mouse_down;
+
+ struct mouse_up {
+ int button_num;
+ } mouse_up;
+
+ struct key_up {
+ int scancode;
+ } key_up;
+
+ struct key_down {
+ int scancode;
+ } key_down;
+
+ } data;
+
+};
+
+int
+hostx_want_screen_size(int *width, int *height);
+
+int
+hostx_want_host_cursor(void);
+
+void
+hostx_use_host_cursor(void);
+
+int
+hostx_want_preexisting_window(void);
+
+void
+hostx_use_preexisting_window(unsigned long win_id);
+
+void
+hostx_handle_signal(int signum);
+
+int
+hostx_init(void);
+
+int
+hostx_get_depth (void);
+
+int
+hostx_get_bpp(void);
+
+void
+hostx_get_visual_masks (unsigned long *rmsk,
+ unsigned long *gmsk,
+ unsigned long *bmsk);
+
+double
+hostx_mm_per_pixel_vertical(void);
+
+double
+hostx_mm_per_pixel_horizontal(void);
+
+void*
+hostx_screen_init (int width, int height);
+
+void
+hostx_paint_rect(int sx, int sy,
+ int dx, int dy,
+ int width, int height);
+void
+hostx_paint_debug_rect(int x, int y,
+ int width, int height);
+
+void
+hostx_load_keymap(void);
+
+int
+hostx_get_event(EphyrHostXEvent *ev);
+
+#endif
diff --git a/hw/kdrive/ephyr/os.c b/hw/kdrive/ephyr/os.c
new file mode 100644
index 000000000..2ee556155
--- /dev/null
+++ b/hw/kdrive/ephyr/os.c
@@ -0,0 +1,67 @@
+/*
+ * Xephyr - A kdrive X server thats runs in a host X window.
+ * Authored by Matthew Allum <mallum@o-hand.com>
+ *
+ * Copyright © 2004 Nokia
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Nokia not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Nokia makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "ephyr.h"
+
+static int
+EphyrInit (void)
+{
+ return hostx_init();
+}
+
+static void
+EphyrEnable (void)
+{
+ EPHYR_DBG("mark");
+}
+
+static Bool
+EphyrSpecialKey (KeySym sym)
+{
+ return FALSE;
+}
+
+static void
+EphyrDisable (void)
+{
+}
+
+static void
+EphyrFini (void)
+{
+}
+
+KdOsFuncs EphyrOsFuncs = {
+ EphyrInit,
+ EphyrEnable,
+ EphyrSpecialKey,
+ EphyrDisable,
+ EphyrFini,
+ ephyrPoll
+};
+