xserver: Branch 'master' - 8 commits

Keith Packard keithp at kemper.freedesktop.org
Thu Apr 3 15:36:34 PDT 2014


 composite/compinit.c          |   24 +
 composite/compint.h           |    7 
 composite/compositeext.h      |    4 
 composite/compwindow.c        |   18 +
 configure.ac                  |   26 +
 dix/events.c                  |   46 --
 dri3/dri3.h                   |    6 
 dri3/dri3_request.c           |   38 +-
 dri3/dri3_screen.c            |    2 
 glamor/glamor.c               |   10 
 glamor/glamor.h               |    4 
 glamor/glamor_egl.c           |    3 
 glamor/glamor_egl_stubs.c     |    4 
 glamor/glamor_priv.h          |    5 
 hw/Makefile.am                |    9 
 hw/xwayland/.gitignore        |    3 
 hw/xwayland/Makefile.am       |   30 +
 hw/xwayland/xwayland-cursor.c |  193 ++++++++++++
 hw/xwayland/xwayland-cvt.c    |  304 +++++++++++++++++++
 hw/xwayland/xwayland-input.c  |  666 ++++++++++++++++++++++++++++++++++++++++++
 hw/xwayland/xwayland-output.c |  226 ++++++++++++++
 hw/xwayland/xwayland-shm.c    |  292 ++++++++++++++++++
 hw/xwayland/xwayland.c        |  652 +++++++++++++++++++++++++++++++++++++++++
 hw/xwayland/xwayland.h        |  164 ++++++++++
 include/input.h               |    1 
 include/scrnintstr.h          |    4 
 mi/mi.h                       |    4 
 mi/miscrinit.c                |    1 
 mi/miwindow.c                 |   66 ++++
 29 files changed, 2743 insertions(+), 69 deletions(-)

New commits:
commit b4d0bec22c15930abf13a7fb9d684208ccd56b1d
Merge: 3c34dd3 6e539d8
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Apr 3 15:35:01 2014 -0700

    Merge remote-tracking branch 'krh/xwayland-for-keithp'

commit 6e539d8817f738289dc2dea13d0720116287ab9d
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Tue Mar 11 16:11:39 2014 -0700

    Xwayland DDX
    
    Started out as an Xorg module to be used from Xorg drivers to let
    Xorg run under a wayland server.  The idea was to be able to reuse the
    2D acceleration from the Xorg driver.  Now with glamor being credible,
    a better plan is to just make Xwayland its own DDX, similar to Xwin
    and Xquartz.  This is a much better fit, as much of the code in the
    original approach had to hack around Xorg doing Xorg things like take
    over the VT, probe input devices and read config files.  Another big win
    is that Xwayland dosn't need to be setuid root.
    
    The Xwayland support for DRI3, Glamor and render nodes was done by
    Axel Davy <axel.davy at ens.fr>, who also did a lot of work on the rebase
    to the Xwayland DDX.
    
    Contributions from:
    
      Christopher James Halse Rogers <christopher.halse.rogers at canonical.com>
      Corentin Chary <corentin.chary at gmail.com>
      Daniel Stone <daniel at fooishbar.org>
      Kristian Høgsberg <krh at bitplanet.net>
      Robert Bragg <robert at linux.intel.com>
      Scott Moreau <oreaus at gmail.com>
      Tiago Vignatti <tiago.vignatti at intel.com>
      Giovanni Campagna <gcampagn at redhat.com>
      Jonas Ã…dahl <jadahl at gmail.com>
      Ray Strode <rstrode at redhat.com>
      Trevor McCort <tjmccort at gmail.com>
      Rui Matos <tiagomatos at gmail.com>
      Axel Davy <axel.davy at ens.fr>
      Jasper St. Pierre <jstpierre at mecheye.net>
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Axel Davy <axel.davy at ens.fr>

diff --git a/configure.ac b/configure.ac
index f589d6d..6e01b54 100644
--- a/configure.ac
+++ b/configure.ac
@@ -633,6 +633,7 @@ AC_ARG_ENABLE(dmx,    	      AS_HELP_STRING([--enable-dmx], [Build DMX server (d
 AC_ARG_ENABLE(xvfb,    	      AS_HELP_STRING([--enable-xvfb], [Build Xvfb server (default: yes)]), [XVFB=$enableval], [XVFB=yes])
 AC_ARG_ENABLE(xnest,   	      AS_HELP_STRING([--enable-xnest], [Build Xnest server (default: auto)]), [XNEST=$enableval], [XNEST=auto])
 AC_ARG_ENABLE(xquartz,        AS_HELP_STRING([--enable-xquartz], [Build Xquartz server for OS-X (default: auto)]), [XQUARTZ=$enableval], [XQUARTZ=auto])
+AC_ARG_ENABLE(xwayland,       AS_HELP_STRING([--enable-xwayland], [Build Xwayland server (default: auto)]), [XWAYLAND=$enableval], [XWAYLAND=auto])
 AC_ARG_ENABLE(standalone-xpbproxy, AS_HELP_STRING([--enable-standalone-xpbproxy], [Build a standalone xpbproxy (in addition to the one integrated into Xquartz as a separate thread) (default: no)]), [STANDALONE_XPBPROXY=$enableval], [STANDALONE_XPBPROXY=no])
 AC_ARG_ENABLE(xwin,    	      AS_HELP_STRING([--enable-xwin], [Build XWin server (default: auto)]), [XWIN=$enableval], [XWIN=auto])
 AC_ARG_ENABLE(glamor,         AS_HELP_STRING([--enable-glamor], [Build glamor dix module (default: no)]), [GLAMOR=$enableval], [GLAMOR=no])
@@ -751,6 +752,7 @@ case $host_os in
 			XQUARTZ=yes
 			XVFB=no
 			XNEST=no
+			XWAYLAND=no
 
 			COMPOSITE=no
 			DGA=no
@@ -2432,6 +2434,29 @@ AM_CONDITIONAL(XEPHYR, [test "x$KDRIVE" = xyes && test "x$XEPHYR" = xyes])
 AM_CONDITIONAL(BUILD_KDRIVEFBDEVLIB, [test "x$KDRIVE" = xyes && test "x$KDRIVEFBDEVLIB" = xyes])
 AM_CONDITIONAL(XFAKESERVER, [test "x$KDRIVE" = xyes && test "x$XFAKE" = xyes])
 
+dnl Xwayland DDX
+
+PKG_CHECK_MODULES(XWAYLANDMODULES, [wayland-client libdrm epoxy], [have_xwayland=yes], [have_xwayland=no])
+AC_MSG_CHECKING([whether to build Xwayland DDX])
+if test "x$XWAYLAND" = xauto; then
+   XWAYLAND="$have_xwayland"
+fi
+AC_MSG_RESULT([$XWAYLAND])
+AM_CONDITIONAL(XWAYLAND, [test "x$XWAYLAND" = xyes])
+
+if test "x$XWAYLAND" = xyes; then
+	if test "x$have_xwayland" = xno; then
+		AC_MSG_ERROR([Xwayland build explicitly requested, but required modules not found.])
+	fi
+
+	XWAYLAND_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
+	XWAYLAND_SYS_LIBS="$XWAYLANDMODULES_LIBS $GLX_SYS_LIBS"
+	AC_SUBST([XWAYLAND_LIBS])
+	AC_SUBST([XWAYLAND_SYS_LIBS])
+	WAYLAND_SCANNER_RULES(['$(top_srcdir)/hw/xwayland'])
+fi
+
+
 dnl and the rest of these are generic, so they're in config.h
 dnl 
 dnl though, thanks to the passing of some significant amount of time, the
@@ -2574,6 +2599,7 @@ hw/kdrive/fake/Makefile
 hw/kdrive/fbdev/Makefile
 hw/kdrive/linux/Makefile
 hw/kdrive/src/Makefile
+hw/xwayland/Makefile
 test/Makefile
 test/xi2/Makefile
 xserver.ent
diff --git a/hw/Makefile.am b/hw/Makefile.am
index 6c2cc6b..19895dc 100644
--- a/hw/Makefile.am
+++ b/hw/Makefile.am
@@ -26,6 +26,10 @@ if XQUARTZ
 XQUARTZ_SUBDIRS = xquartz
 endif
 
+if XWAYLAND
+XWAYLAND_SUBDIRS = xwayland
+endif
+
 SUBDIRS =			\
 	$(XORG_SUBDIRS)		\
 	$(XWIN_SUBDIRS)		\
@@ -33,9 +37,10 @@ SUBDIRS =			\
 	$(XNEST_SUBDIRS)	\
 	$(DMX_SUBDIRS)		\
 	$(KDRIVE_SUBDIRS)	\
-	$(XQUARTZ_SUBDIRS)
+	$(XQUARTZ_SUBDIRS)	\
+	$(XWAYLAND_SUBDIRS)
 
-DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive
+DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland
 
 relink:
 	$(AM_V_at)for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink || exit 1 ; done
diff --git a/hw/xwayland/.gitignore b/hw/xwayland/.gitignore
new file mode 100644
index 0000000..c54ba2d
--- /dev/null
+++ b/hw/xwayland/.gitignore
@@ -0,0 +1,3 @@
+Xwayland
+drm-client-protocol.h
+drm-protocol.c
diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am
new file mode 100644
index 0000000..36e6127
--- /dev/null
+++ b/hw/xwayland/Makefile.am
@@ -0,0 +1,30 @@
+bin_PROGRAMS = Xwayland
+
+Xwayland_CFLAGS =				\
+	-I$(top_srcdir)/dri3			\
+	-DHAVE_DIX_CONFIG_H			\
+	$(XWAYLANDMODULES_CFLAGS)		\
+	$(DIX_CFLAGS)
+
+Xwayland_SOURCES =				\
+	xwayland.c				\
+	xwayland-input.c			\
+	xwayland-cursor.c			\
+	xwayland-shm.c				\
+	xwayland-output.c			\
+	xwayland-cvt.c				\
+	xwayland.h				\
+	$(top_srcdir)/Xext/dpmsstubs.c		\
+	$(top_srcdir)/Xi/stubs.c		\
+	$(top_srcdir)/mi/miinitext.c
+
+Xwayland_LDADD =				\
+	$(XWAYLAND_LIBS)			\
+	$(XWAYLAND_SYS_LIBS)			\
+	$(XSERVER_SYS_LIBS)
+Xwayland_DEPENDENCIES = $(XWAYLAND_LIBS)
+Xwayland_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
+
+
+relink:
+	$(AM_V_at)rm -f Xwayland$(EXEEXT) && $(MAKE) Xwayland$(EXEEXT)
diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c
new file mode 100644
index 0000000..5a9d1fe
--- /dev/null
+++ b/hw/xwayland/xwayland-cursor.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ * Copyright © 2011 Kristian Høgsberg
+ *
+ * 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 the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 "xwayland.h"
+
+#include <mipointer.h>
+
+static DevPrivateKeyRec xwl_cursor_private_key;
+
+static void
+expand_source_and_mask(CursorPtr cursor, CARD32 *data)
+{
+    CARD32 *p, d, fg, bg;
+    CursorBitsPtr bits = cursor->bits;
+    int x, y, stride, i, bit;
+
+    p = data;
+    fg = ((cursor->foreRed & 0xff00) << 8) |
+        (cursor->foreGreen & 0xff00) | (cursor->foreGreen >> 8);
+    bg = ((cursor->backRed & 0xff00) << 8) |
+        (cursor->backGreen & 0xff00) | (cursor->backGreen >> 8);
+    stride = (bits->width / 8 + 3) & ~3;
+    for (y = 0; y < bits->height; y++)
+        for (x = 0; x < bits->width; x++) {
+            i = y * stride + x / 8;
+            bit = 1 << (x & 7);
+            if (bits->source[i] & bit)
+                d = fg;
+            else
+                d = bg;
+            if (bits->mask[i] & bit)
+                d |= 0xff000000;
+            else
+                d = 0x00000000;
+
+            *p++ = d;
+        }
+}
+
+static Bool
+xwl_realize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
+{
+    PixmapPtr pixmap;
+
+    pixmap = xwl_shm_create_pixmap(screen, cursor->bits->width,
+                                   cursor->bits->height, 32, 0);
+    dixSetPrivate(&cursor->devPrivates, &xwl_cursor_private_key, pixmap);
+
+    return TRUE;
+}
+
+static Bool
+xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
+{
+    PixmapPtr pixmap;
+
+    pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key);
+
+    return xwl_shm_destroy_pixmap(pixmap);
+}
+
+void
+xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
+{
+    PixmapPtr pixmap;
+    CursorPtr cursor;
+    int stride;
+
+    if (!xwl_seat->wl_pointer)
+        return;
+
+    if (!xwl_seat->x_cursor) {
+        wl_pointer_set_cursor(xwl_seat->wl_pointer,
+                              xwl_seat->pointer_enter_serial, NULL, 0, 0);
+        return;
+    }
+
+    cursor = xwl_seat->x_cursor;
+    pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key);
+    stride = cursor->bits->width * 4;
+    if (cursor->bits->argb)
+        memcpy(pixmap->devPrivate.ptr,
+               cursor->bits->argb, cursor->bits->height * stride);
+    else
+        expand_source_and_mask(cursor, pixmap->devPrivate.ptr);
+
+    wl_pointer_set_cursor(xwl_seat->wl_pointer,
+                          xwl_seat->pointer_enter_serial,
+                          xwl_seat->cursor,
+                          xwl_seat->x_cursor->bits->xhot,
+                          xwl_seat->x_cursor->bits->yhot);
+    wl_surface_attach(xwl_seat->cursor,
+                      xwl_shm_pixmap_get_wl_buffer(pixmap), 0, 0);
+    wl_surface_damage(xwl_seat->cursor, 0, 0,
+                      xwl_seat->x_cursor->bits->width,
+                      xwl_seat->x_cursor->bits->height);
+    wl_surface_commit(xwl_seat->cursor);
+}
+
+static void
+xwl_set_cursor(DeviceIntPtr device,
+               ScreenPtr screen, CursorPtr cursor, int x, int y)
+{
+    struct xwl_seat *xwl_seat;
+
+    xwl_seat = device->public.devicePrivate;
+    if (xwl_seat == NULL)
+        return;
+
+    xwl_seat->x_cursor = cursor;
+    xwl_seat_set_cursor(xwl_seat);
+}
+
+static void
+xwl_move_cursor(DeviceIntPtr device, ScreenPtr screen, int x, int y)
+{
+}
+
+static Bool
+xwl_device_cursor_initialize(DeviceIntPtr device, ScreenPtr screen)
+{
+    return TRUE;
+}
+
+static void
+xwl_device_cursor_cleanup(DeviceIntPtr device, ScreenPtr screen)
+{
+}
+
+static miPointerSpriteFuncRec xwl_pointer_sprite_funcs = {
+    xwl_realize_cursor,
+    xwl_unrealize_cursor,
+    xwl_set_cursor,
+    xwl_move_cursor,
+    xwl_device_cursor_initialize,
+    xwl_device_cursor_cleanup
+};
+
+static Bool
+xwl_cursor_off_screen(ScreenPtr *ppScreen, int *x, int *y)
+{
+    return FALSE;
+}
+
+static void
+xwl_cross_screen(ScreenPtr pScreen, Bool entering)
+{
+}
+
+static void
+xwl_pointer_warp_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
+{
+}
+
+static miPointerScreenFuncRec xwl_pointer_screen_funcs = {
+    xwl_cursor_off_screen,
+    xwl_cross_screen,
+    xwl_pointer_warp_cursor
+};
+
+Bool
+xwl_screen_init_cursor(struct xwl_screen *xwl_screen)
+{
+    if (!dixRegisterPrivateKey(&xwl_cursor_private_key, PRIVATE_CURSOR_BITS, 0))
+        return FALSE;
+
+    return miPointerInitialize(xwl_screen->screen,
+                               &xwl_pointer_sprite_funcs,
+                               &xwl_pointer_screen_funcs, TRUE);
+}
diff --git a/hw/xwayland/xwayland-cvt.c b/hw/xwayland/xwayland-cvt.c
new file mode 100644
index 0000000..3566559
--- /dev/null
+++ b/hw/xwayland/xwayland-cvt.c
@@ -0,0 +1,304 @@
+/* Copied from hw/xfree86/modes/xf86cvt.c into xwayland DDX and
+ * changed to generate an RRMode */
+
+/*
+ * Copyright 2005-2006 Luc Verhaegen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The reason for having this function in a file of its own is
+ * so that ../utils/cvt/cvt can link to it, and that xf86CVTMode
+ * code is shared directly.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+#include <randrstr.h>
+#include "xwayland.h"
+
+/*
+ * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
+ *
+ * These calculations are stolen from the CVT calculation spreadsheet written
+ * by Graham Loveridge. He seems to be claiming no copyright and there seems to
+ * be no license attached to this. He apparently just wants to see his name
+ * mentioned.
+ *
+ * This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls
+ *
+ * Comments and structure corresponds to the comments and structure of the xls.
+ * This should ease importing of future changes to the standard (not very
+ * likely though).
+ *
+ * About margins; i'm sure that they are to be the bit between HDisplay and
+ * HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and
+ * VTotal, where the overscan colour is shown. FB seems to call _all_ blanking
+ * outside sync "margin" for some reason. Since we prefer seeing proper
+ * blanking instead of the overscan colour, and since the Crtc* values will
+ * probably get altered after us, we will disable margins altogether. With
+ * these calculations, Margins will plainly expand H/VDisplay, and we don't
+ * want that. -- libv
+ *
+ */
+RRModePtr
+xwayland_cvt(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
+             Bool Interlaced)
+{
+    /* 1) top/bottom margin size (% of height) - default: 1.8 */
+#define CVT_MARGIN_PERCENTAGE 1.8
+
+    /* 2) character cell horizontal granularity (pixels) - default 8 */
+#define CVT_H_GRANULARITY 8
+
+    /* 4) Minimum vertical porch (lines) - default 3 */
+#define CVT_MIN_V_PORCH 3
+
+    /* 4) Minimum number of vertical back porch lines - default 6 */
+#define CVT_MIN_V_BPORCH 6
+
+    /* Pixel Clock step (kHz) */
+#define CVT_CLOCK_STEP 250
+
+    Bool Margins = FALSE;
+    float VFieldRate, HPeriod;
+    int HDisplayRnd, HMargin;
+    int VDisplayRnd, VMargin, VSync;
+    float Interlace;            /* Please rename this */
+    char name[128];
+    xRRModeInfo modeinfo;
+
+    memset(&modeinfo, 0, sizeof modeinfo);
+
+    /* CVT default is 60.0Hz */
+    if (!VRefresh)
+        VRefresh = 60.0;
+
+    /* 1. Required field rate */
+    if (Interlaced)
+        VFieldRate = VRefresh * 2;
+    else
+        VFieldRate = VRefresh;
+
+    /* 2. Horizontal pixels */
+    HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY);
+
+    /* 3. Determine left and right borders */
+    if (Margins) {
+        /* right margin is actually exactly the same as left */
+        HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
+        HMargin -= HMargin % CVT_H_GRANULARITY;
+    }
+    else
+        HMargin = 0;
+
+    /* 4. Find total active pixels */
+    modeinfo.width = HDisplayRnd + 2 * HMargin;
+
+    /* 5. Find number of lines per field */
+    if (Interlaced)
+        VDisplayRnd = VDisplay / 2;
+    else
+        VDisplayRnd = VDisplay;
+
+    /* 6. Find top and bottom margins */
+    /* nope. */
+    if (Margins)
+        /* top and bottom margins are equal again. */
+        VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
+    else
+        VMargin = 0;
+
+    modeinfo.height = VDisplay + 2 * VMargin;
+
+    /* 7. Interlace */
+    if (Interlaced)
+        Interlace = 0.5;
+    else
+        Interlace = 0.0;
+
+    /* Determine VSync Width from aspect ratio */
+    if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay))
+        VSync = 4;
+    else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay))
+        VSync = 5;
+    else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay))
+        VSync = 6;
+    else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay))
+        VSync = 7;
+    else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay))
+        VSync = 7;
+    else                        /* Custom */
+        VSync = 10;
+
+    if (!Reduced) {             /* simplified GTF calculation */
+
+        /* 4) Minimum time of vertical sync + back porch interval (µs)
+         * default 550.0 */
+#define CVT_MIN_VSYNC_BP 550.0
+
+        /* 3) Nominal HSync width (% of line period) - default 8 */
+#define CVT_HSYNC_PERCENTAGE 8
+
+        float HBlankPercentage;
+        int VSyncAndBackPorch, VBackPorch;
+        int HBlank;
+
+        /* 8. Estimated Horizontal period */
+        HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) /
+            (VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace);
+
+        /* 9. Find number of lines in sync + backporch */
+        if (((int) (CVT_MIN_VSYNC_BP / HPeriod) + 1) <
+            (VSync + CVT_MIN_V_PORCH))
+            VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH;
+        else
+            VSyncAndBackPorch = (int) (CVT_MIN_VSYNC_BP / HPeriod) + 1;
+
+        /* 10. Find number of lines in back porch */
+        VBackPorch = VSyncAndBackPorch - VSync;
+        (void) VBackPorch;
+
+        /* 11. Find total number of lines in vertical field */
+        modeinfo.vTotal =
+            VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace +
+            CVT_MIN_V_PORCH;
+
+        /* 5) Definition of Horizontal blanking time limitation */
+        /* Gradient (%/kHz) - default 600 */
+#define CVT_M_FACTOR 600
+
+        /* Offset (%) - default 40 */
+#define CVT_C_FACTOR 40
+
+        /* Blanking time scaling factor - default 128 */
+#define CVT_K_FACTOR 128
+
+        /* Scaling factor weighting - default 20 */
+#define CVT_J_FACTOR 20
+
+#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256
+#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
+        CVT_J_FACTOR
+
+        /* 12. Find ideal blanking duty cycle from formula */
+        HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod / 1000.0;
+
+        /* 13. Blanking time */
+        if (HBlankPercentage < 20)
+            HBlankPercentage = 20;
+
+        HBlank = modeinfo.width * HBlankPercentage / (100.0 - HBlankPercentage);
+        HBlank -= HBlank % (2 * CVT_H_GRANULARITY);
+
+        /* 14. Find total number of pixels in a line. */
+        modeinfo.hTotal = modeinfo.width + HBlank;
+
+        /* Fill in HSync values */
+        modeinfo.hSyncEnd = modeinfo.width + HBlank / 2;
+
+        modeinfo.hSyncStart = modeinfo.hSyncEnd -
+            (modeinfo.hTotal * CVT_HSYNC_PERCENTAGE) / 100;
+        modeinfo.hSyncStart += CVT_H_GRANULARITY -
+            modeinfo.hSyncStart % CVT_H_GRANULARITY;
+
+        /* Fill in VSync values */
+        modeinfo.vSyncStart = modeinfo.height + CVT_MIN_V_PORCH;
+        modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync;
+
+    }
+    else {                      /* Reduced blanking */
+        /* Minimum vertical blanking interval time (µs) - default 460 */
+#define CVT_RB_MIN_VBLANK 460.0
+
+        /* Fixed number of clocks for horizontal sync */
+#define CVT_RB_H_SYNC 32.0
+
+        /* Fixed number of clocks for horizontal blanking */
+#define CVT_RB_H_BLANK 160.0
+
+        /* Fixed number of lines for vertical front porch - default 3 */
+#define CVT_RB_VFPORCH 3
+
+        int VBILines;
+
+        /* 8. Estimate Horizontal period. */
+        HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) /
+            (VDisplayRnd + 2 * VMargin);
+
+        /* 9. Find number of lines in vertical blanking */
+        VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1;
+
+        /* 10. Check if vertical blanking is sufficient */
+        if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH))
+            VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH;
+
+        /* 11. Find total number of lines in vertical field */
+        modeinfo.vTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines;
+
+        /* 12. Find total number of pixels in a line */
+        modeinfo.hTotal = modeinfo.width + CVT_RB_H_BLANK;
+
+        /* Fill in HSync values */
+        modeinfo.hSyncEnd = modeinfo.width + CVT_RB_H_BLANK / 2;
+        modeinfo.hSyncStart = modeinfo.hSyncEnd - CVT_RB_H_SYNC;
+
+        /* Fill in VSync values */
+        modeinfo.vSyncStart = modeinfo.height + CVT_RB_VFPORCH;
+        modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync;
+    }
+
+    /* 15/13. Find pixel clock frequency (kHz for xf86) */
+    modeinfo.dotClock = modeinfo.hTotal * 1000.0 / HPeriod;
+    modeinfo.dotClock -= modeinfo.dotClock % CVT_CLOCK_STEP;
+    modeinfo.dotClock *= 1000.0;
+#if 0
+    /* 16/14. Find actual Horizontal Frequency (kHz) */
+    modeinfo.hSync = ((float) modeinfo.dotClock) / ((float) modeinfo.hTotal);
+#endif
+
+#if 0
+    /* 17/15. Find actual Field rate */
+    modeinfo.vRefresh = (1000.0 * ((float) modeinfo.dotClock)) /
+        ((float) (modeinfo.hTotal * modeinfo.vTotal));
+#endif
+
+    /* 18/16. Find actual vertical frame frequency */
+    /* ignore - just set the mode flag for interlaced */
+    if (Interlaced)
+        modeinfo.vTotal *= 2;
+
+    if (Reduced)
+        modeinfo.modeFlags |= RR_HSyncPositive | RR_VSyncNegative;
+    else
+        modeinfo.modeFlags |= RR_HSyncNegative | RR_VSyncPositive;
+
+    if (Interlaced)
+        modeinfo.modeFlags |= RR_Interlace;
+
+    snprintf(name, sizeof name, "%dx%d@%.1fHz",
+             modeinfo.width, modeinfo.height, VRefresh);
+    modeinfo.nameLength = strlen(name);
+
+    return RRModeGet(&modeinfo, name);
+}
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
new file mode 100644
index 0000000..990cb82
--- /dev/null
+++ b/hw/xwayland/xwayland-input.c
@@ -0,0 +1,666 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ * Copyright © 2008 Kristian Høgsberg
+ *
+ * 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 the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 "xwayland.h"
+
+#include <linux/input.h>
+
+#include <sys/mman.h>
+#include <xkbsrv.h>
+#include <xserver-properties.h>
+#include <inpututils.h>
+
+static void
+xwl_pointer_control(DeviceIntPtr device, PtrCtrl *ctrl)
+{
+    /* Nothing to do, dix handles all settings */
+}
+
+static int
+xwl_pointer_proc(DeviceIntPtr device, int what)
+{
+#define NBUTTONS 10
+#define NAXES 2
+    BYTE map[NBUTTONS + 1];
+    int i = 0;
+    Atom btn_labels[NBUTTONS] = { 0 };
+    Atom axes_labels[NAXES] = { 0 };
+
+    switch (what) {
+    case DEVICE_INIT:
+        device->public.on = FALSE;
+
+        for (i = 1; i <= NBUTTONS; i++)
+            map[i] = i;
+
+        btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
+        btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
+        btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
+        btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
+        btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
+        btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
+        btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
+        /* don't know about the rest */
+
+        axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
+        axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
+
+        if (!InitValuatorClassDeviceStruct(device, 2, btn_labels,
+                                           GetMotionHistorySize(), Absolute))
+            return BadValue;
+
+        /* Valuators */
+        InitValuatorAxisStruct(device, 0, axes_labels[0],
+                               0, 0xFFFF, 10000, 0, 10000, Absolute);
+        InitValuatorAxisStruct(device, 1, axes_labels[1],
+                               0, 0xFFFF, 10000, 0, 10000, Absolute);
+
+        if (!InitPtrFeedbackClassDeviceStruct(device, xwl_pointer_control))
+            return BadValue;
+
+        if (!InitButtonClassDeviceStruct(device, 3, btn_labels, map))
+            return BadValue;
+
+        return Success;
+
+    case DEVICE_ON:
+        device->public.on = TRUE;
+        return Success;
+
+    case DEVICE_OFF:
+    case DEVICE_CLOSE:
+        device->public.on = FALSE;
+        return Success;
+    }
+
+    return BadMatch;
+
+#undef NBUTTONS
+#undef NAXES
+}
+
+static void
+xwl_keyboard_control(DeviceIntPtr device, KeybdCtrl *ctrl)
+{
+}
+
+static int
+xwl_keyboard_proc(DeviceIntPtr device, int what)
+{
+    struct xwl_seat *xwl_seat = device->public.devicePrivate;
+    int len;
+
+    switch (what) {
+    case DEVICE_INIT:
+        device->public.on = FALSE;
+        if (xwl_seat->keymap)
+            len = strnlen(xwl_seat->keymap, xwl_seat->keymap_size);
+        else
+            len = 0;
+        if (!InitKeyboardDeviceStructFromString(device, xwl_seat->keymap,
+                                                len,
+                                                NULL, xwl_keyboard_control))
+            return BadValue;
+
+        return Success;
+    case DEVICE_ON:
+        device->public.on = TRUE;
+        return Success;
+
+    case DEVICE_OFF:
+    case DEVICE_CLOSE:
+        device->public.on = FALSE;
+        return Success;
+    }
+
+    return BadMatch;
+}
+
+static void
+pointer_handle_enter(void *data, struct wl_pointer *pointer,
+                     uint32_t serial, struct wl_surface *surface,
+                     wl_fixed_t sx_w, wl_fixed_t sy_w)
+{
+    struct xwl_seat *xwl_seat = data;
+    DeviceIntPtr dev = xwl_seat->pointer;
+    int i;
+    int sx = wl_fixed_to_int(sx_w);
+    int sy = wl_fixed_to_int(sy_w);
+    ScreenPtr pScreen = xwl_seat->xwl_screen->screen;
+    ValuatorMask mask;
+
+    xwl_seat->xwl_screen->serial = serial;
+    xwl_seat->pointer_enter_serial = serial;
+
+    xwl_seat->focus_window = wl_surface_get_user_data(surface);
+
+    (*pScreen->SetCursorPosition) (dev, pScreen, sx, sy, TRUE);
+    CheckMotion(NULL, GetMaster(dev, MASTER_POINTER));
+
+    /* Ideally, X clients shouldn't see these button releases.  When
+     * the pointer leaves a window with buttons down, it means that
+     * the wayland compositor has grabbed the pointer.  The button
+     * release event is consumed by whatever grab in the compositor
+     * and won't be sent to clients (the X server is a client).
+     * However, we need to reset X's idea of which buttons are up and
+     * down, and they're all up (by definition) when the pointer
+     * enters a window.  We should figure out a way to swallow these
+     * events, perhaps using an X grab whenever the pointer is not in
+     * any X window, but for now just send the events. */
+    valuator_mask_zero(&mask);
+    for (i = 0; i < dev->button->numButtons; i++)
+        if (BitIsOn(dev->button->down, i))
+            QueuePointerEvents(xwl_seat->pointer, ButtonRelease, i, 0, &mask);
+}
+
+static void
+pointer_handle_leave(void *data, struct wl_pointer *pointer,
+                     uint32_t serial, struct wl_surface *surface)
+{
+    struct xwl_seat *xwl_seat = data;
+    DeviceIntPtr dev = xwl_seat->pointer;
+
+    xwl_seat->xwl_screen->serial = serial;
+
+    xwl_seat->focus_window = NULL;
+    CheckMotion(NULL, GetMaster(dev, MASTER_POINTER));
+}
+
+static void
+pointer_handle_motion(void *data, struct wl_pointer *pointer,
+                      uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
+{
+    struct xwl_seat *xwl_seat = data;
+    int32_t dx, dy;
+    int sx = wl_fixed_to_int(sx_w);
+    int sy = wl_fixed_to_int(sy_w);
+    ValuatorMask mask;
+
+    if (!xwl_seat->focus_window)
+        return;
+
+    dx = xwl_seat->focus_window->window->drawable.x;
+    dy = xwl_seat->focus_window->window->drawable.y;
+
+    valuator_mask_zero(&mask);
+    valuator_mask_set(&mask, 0, dx + sx);
+    valuator_mask_set(&mask, 1, dy + sy);
+
+    QueuePointerEvents(xwl_seat->pointer, MotionNotify, 0,
+                       POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
+}
+
+static void
+pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
+                      uint32_t time, uint32_t button, uint32_t state)
+{
+    struct xwl_seat *xwl_seat = data;
+    int index;
+    ValuatorMask mask;
+
+    xwl_seat->xwl_screen->serial = serial;
+
+    switch (button) {
+    case BTN_MIDDLE:
+        index = 2;
+        break;
+    case BTN_RIGHT:
+        index = 3;
+        break;
+    default:
+        index = button - BTN_LEFT + 1;
+        break;
+    }
+
+    valuator_mask_zero(&mask);
+    QueuePointerEvents(xwl_seat->pointer,
+                       state ? ButtonPress : ButtonRelease, index, 0, &mask);
+}
+
+static void
+pointer_handle_axis(void *data, struct wl_pointer *pointer,
+                    uint32_t time, uint32_t axis, wl_fixed_t value)
+{
+    struct xwl_seat *xwl_seat = data;
+    int index, count;
+    int i, val;
+    const int divisor = 10;
+    ValuatorMask mask;
+
+    if (time - xwl_seat->scroll_time > 2000) {
+        xwl_seat->vertical_scroll = 0;
+        xwl_seat->horizontal_scroll = 0;
+    }
+    xwl_seat->scroll_time = time;
+
+    /* FIXME: Need to do proper smooth scrolling here! */
+    switch (axis) {
+    case WL_POINTER_AXIS_VERTICAL_SCROLL:
+        xwl_seat->vertical_scroll += value / divisor;
+        val = wl_fixed_to_int(xwl_seat->vertical_scroll);
+        xwl_seat->vertical_scroll -= wl_fixed_from_int(val);
+
+        if (val <= -1)
+            index = 4;
+        else if (val >= 1)
+            index = 5;
+        else
+            return;
+        break;
+    case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
+        xwl_seat->horizontal_scroll += value / divisor;
+        val = wl_fixed_to_int(xwl_seat->horizontal_scroll);
+        xwl_seat->horizontal_scroll -= wl_fixed_from_int(val);
+
+        if (val <= -1)
+            index = 6;
+        else if (val >= 1)
+            index = 7;
+        else
+            return;
+        break;
+    default:
+        return;
+    }
+
+    valuator_mask_zero(&mask);
+
+    count = abs(val);
+    for (i = 0; i < count; i++) {
+        QueuePointerEvents(xwl_seat->pointer, ButtonPress, index, 0, &mask);
+        QueuePointerEvents(xwl_seat->pointer, ButtonRelease, index, 0, &mask);
+    }
+}
+
+static const struct wl_pointer_listener pointer_listener = {
+    pointer_handle_enter,
+    pointer_handle_leave,
+    pointer_handle_motion,
+    pointer_handle_button,
+    pointer_handle_axis,
+};
+
+static void
+keyboard_handle_key(void *data, struct wl_keyboard *keyboard, uint32_t serial,
+                    uint32_t time, uint32_t key, uint32_t state)
+{
+    struct xwl_seat *xwl_seat = data;
+    uint32_t *k, *end;
+    ValuatorMask mask;
+
+    xwl_seat->xwl_screen->serial = serial;
+
+    end = (uint32_t *) ((char *) xwl_seat->keys.data + xwl_seat->keys.size);
+    for (k = xwl_seat->keys.data; k < end; k++) {
+        if (*k == key)
+            *k = *--end;
+    }
+    xwl_seat->keys.size = (char *) end - (char *) xwl_seat->keys.data;
+    if (state) {
+        k = wl_array_add(&xwl_seat->keys, sizeof *k);
+        *k = key;
+    }
+
+    valuator_mask_zero(&mask);
+    QueueKeyboardEvents(xwl_seat->keyboard,
+                        state ? KeyPress : KeyRelease, key + 8, &mask);
+}
+
+static void
+keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
+                       uint32_t format, int fd, uint32_t size)
+{
+    struct xwl_seat *xwl_seat = data;
+    DeviceIntPtr master;
+    XkbDescPtr xkb;
+    XkbChangesRec changes = { 0 };
+
+    if (xwl_seat->keymap)
+        munmap(xwl_seat->keymap, xwl_seat->keymap_size);
+
+    xwl_seat->keymap_size = size;
+    xwl_seat->keymap = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+    if (xwl_seat->keymap == MAP_FAILED) {
+        xwl_seat->keymap_size = 0;
+        xwl_seat->keymap = NULL;
+        goto out;
+    }
+
+    xkb = XkbCompileKeymapFromString(xwl_seat->keyboard, xwl_seat->keymap,
+                                     strnlen(xwl_seat->keymap,
+                                             xwl_seat->keymap_size));
+    if (!xkb)
+        goto out;
+
+    XkbUpdateDescActions(xkb, xkb->min_key_code, XkbNumKeys(xkb), &changes);
+
+    if (xwl_seat->keyboard->key)
+        /* Keep the current controls */
+        XkbCopyControls(xkb, xwl_seat->keyboard->key->xkbInfo->desc);
+
+    XkbDeviceApplyKeymap(xwl_seat->keyboard, xkb);
+
+    master = GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD);
+    if (master && master->lastSlave == xwl_seat->keyboard)
+        XkbDeviceApplyKeymap(master, xkb);
+
+    XkbFreeKeyboard(xkb, XkbAllComponentsMask, TRUE);
+
+ out:
+    close(fd);
+}
+
+static void
+keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
+                      uint32_t serial,
+                      struct wl_surface *surface, struct wl_array *keys)
+{
+    struct xwl_seat *xwl_seat = data;
+    ValuatorMask mask;
+    uint32_t *k;
+
+    xwl_seat->xwl_screen->serial = serial;
+    xwl_seat->keyboard_focus = surface;
+
+    wl_array_copy(&xwl_seat->keys, keys);
+    valuator_mask_zero(&mask);
+    wl_array_for_each(k, &xwl_seat->keys)
+        QueueKeyboardEvents(xwl_seat->keyboard, KeyPress, *k + 8, &mask);
+}
+
+static void
+keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
+                      uint32_t serial, struct wl_surface *surface)
+{
+    struct xwl_seat *xwl_seat = data;
+    ValuatorMask mask;
+    uint32_t *k;
+
+    xwl_seat->xwl_screen->serial = serial;
+
+    valuator_mask_zero(&mask);
+    wl_array_for_each(k, &xwl_seat->keys)
+        QueueKeyboardEvents(xwl_seat->keyboard, KeyRelease, *k + 8, &mask);
+
+    xwl_seat->keyboard_focus = NULL;
+}
+
+static void
+keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
+                          uint32_t serial, uint32_t mods_depressed,
+                          uint32_t mods_latched, uint32_t mods_locked,
+                          uint32_t group)
+{
+    struct xwl_seat *xwl_seat = data;
+    DeviceIntPtr dev;
+    XkbStateRec old_state, *new_state;
+    xkbStateNotify sn;
+    CARD16 changed;
+
+    /* We don't need any of this while we have keyboard focus since
+       the regular key event processing already takes care of setting
+       our internal state correctly. */
+    if (xwl_seat->keyboard_focus)
+        return;
+
+    for (dev = inputInfo.devices; dev; dev = dev->next) {
+        if (dev != xwl_seat->keyboard &&
+            dev != GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD))
+            continue;
+
+        old_state = dev->key->xkbInfo->state;
+        new_state = &dev->key->xkbInfo->state;
+
+        new_state->locked_group = group & XkbAllGroupsMask;
+        new_state->locked_mods = mods_locked & XkbAllModifiersMask;
+        XkbLatchModifiers(dev, XkbAllModifiersMask,
+                          mods_latched & XkbAllModifiersMask);
+
+        XkbComputeDerivedState(dev->key->xkbInfo);
+
+        changed = XkbStateChangedFlags(&old_state, new_state);
+        if (!changed)
+            continue;
+
+        sn.keycode = 0;
+        sn.eventType = 0;
+        sn.requestMajor = XkbReqCode;
+        sn.requestMinor = X_kbLatchLockState;   /* close enough */
+        sn.changed = changed;
+        XkbSendStateNotify(dev, &sn);
+    }
+}
+
+static const struct wl_keyboard_listener keyboard_listener = {
+    keyboard_handle_keymap,
+    keyboard_handle_enter,
+    keyboard_handle_leave,
+    keyboard_handle_key,
+    keyboard_handle_modifiers,
+};
+
+static DeviceIntPtr
+add_device(struct xwl_seat *xwl_seat,
+           const char *driver, DeviceProc device_proc)
+{
+    DeviceIntPtr dev = NULL;
+    static Atom type_atom;
+    char name[32];
+
+    dev = AddInputDevice(serverClient, device_proc, TRUE);
+    if (dev == NULL)
+        return NULL;
+
+    if (type_atom == None)
+        type_atom = MakeAtom(driver, strlen(driver), TRUE);
+    snprintf(name, sizeof name, "%s:%d", driver, xwl_seat->id);
+    AssignTypeAndName(dev, type_atom, name);
+    dev->public.devicePrivate = xwl_seat;
+    dev->type = SLAVE;
+    dev->spriteInfo->spriteOwner = FALSE;
+
+    return dev;
+}
+
+static void
+seat_handle_capabilities(void *data, struct wl_seat *seat,
+                         enum wl_seat_capability caps)
+{
+    struct xwl_seat *xwl_seat = data;
+
+    if (caps & WL_SEAT_CAPABILITY_POINTER && xwl_seat->pointer == NULL) {
+        xwl_seat->wl_pointer = wl_seat_get_pointer(seat);
+        wl_pointer_add_listener(xwl_seat->wl_pointer,
+                                &pointer_listener, xwl_seat);
+        xwl_seat_set_cursor(xwl_seat);
+        xwl_seat->pointer =
+            add_device(xwl_seat, "xwayland-pointer", xwl_pointer_proc);
+    }
+    else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && xwl_seat->pointer) {
+        wl_pointer_release(xwl_seat->wl_pointer);
+        RemoveDevice(xwl_seat->pointer, FALSE);
+        xwl_seat->pointer = NULL;
+    }
+
+    if (caps & WL_SEAT_CAPABILITY_KEYBOARD && xwl_seat->keyboard == NULL) {
+        xwl_seat->wl_keyboard = wl_seat_get_keyboard(seat);
+        wl_keyboard_add_listener(xwl_seat->wl_keyboard,
+                                 &keyboard_listener, xwl_seat);
+        xwl_seat->keyboard =
+            add_device(xwl_seat, "xwayland-keyboard", xwl_keyboard_proc);
+    }
+    else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && xwl_seat->keyboard) {
+        wl_keyboard_release(xwl_seat->wl_keyboard);
+        RemoveDevice(xwl_seat->keyboard, FALSE);
+        xwl_seat->keyboard = NULL;
+    }
+
+    xwl_seat->xwl_screen->expecting_event--;
+    /* FIXME: Touch ... */
+}
+
+static void
+seat_handle_name(void *data, struct wl_seat *seat,
+		 const char *name)
+{
+
+}
+
+static const struct wl_seat_listener seat_listener = {
+    seat_handle_capabilities,
+    seat_handle_name
+};
+
+static void
+create_input_device(struct xwl_screen *xwl_screen, uint32_t id)
+{
+    struct xwl_seat *xwl_seat;
+
+    xwl_seat = calloc(sizeof *xwl_seat, 1);
+    if (xwl_seat == NULL) {
+        ErrorF("create_input ENOMEM");
+        return;
+    }
+
+    xwl_seat->xwl_screen = xwl_screen;
+    xorg_list_add(&xwl_seat->link, &xwl_screen->seat_list);
+
+    xwl_seat->seat =
+        wl_registry_bind(xwl_screen->registry, id, &wl_seat_interface, 3);
+    xwl_seat->id = id;
+
+    xwl_seat->cursor = wl_compositor_create_surface(xwl_screen->compositor);
+    wl_seat_add_listener(xwl_seat->seat, &seat_listener, xwl_seat);
+    wl_array_init(&xwl_seat->keys);
+}
+
+void
+xwl_seat_destroy(struct xwl_seat *xwl_seat)
+{
+    RemoveDevice(xwl_seat->pointer, FALSE);
+    RemoveDevice(xwl_seat->keyboard, FALSE);
+    wl_seat_destroy(xwl_seat->seat);
+    wl_surface_destroy(xwl_seat->cursor);
+    wl_array_release(&xwl_seat->keys);
+    free(xwl_seat);
+}
+
+static void
+input_handler(void *data, struct wl_registry *registry, uint32_t id,
+              const char *interface, uint32_t version)
+{
+    struct xwl_screen *xwl_screen = data;
+
+    if (strcmp(interface, "wl_seat") == 0 && version >= 3) {
+        create_input_device(xwl_screen, id);
+        xwl_screen->expecting_event++;
+    }
+}
+
+static void
+global_remove(void *data, struct wl_registry *registry, uint32_t name)
+{
+}
+
+static const struct wl_registry_listener input_listener = {
+    input_handler,
+    global_remove,
+};
+
+Bool
+LegalModifier(unsigned int key, DeviceIntPtr pDev)
+{
+    return TRUE;
+}
+
+void
+ProcessInputEvents(void)
+{
+    mieqProcessInputEvents();
+}
+
+void
+DDXRingBell(int volume, int pitch, int duration)
+{
+}
+
+static WindowPtr
+xwl_xy_to_window(ScreenPtr screen, SpritePtr sprite, int x, int y)
+{
+    struct xwl_seat *xwl_seat = NULL;
+    DeviceIntPtr device;
+
+    for (device = inputInfo.devices; device; device = device->next) {
+        if (device->deviceProc == xwl_pointer_proc &&
+            device->spriteInfo->sprite == sprite) {
+            xwl_seat = device->public.devicePrivate;
+            break;
+        }
+    }
+
+    if (xwl_seat == NULL) {
+        /* XTEST device */
+        sprite->spriteTraceGood = 1;
+        return sprite->spriteTrace[0];
+    }
+
+    if (xwl_seat->focus_window) {
+        sprite->spriteTraceGood = 2;
+        sprite->spriteTrace[1] = xwl_seat->focus_window->window;
+        return miSpriteTrace(sprite, x, y);
+    }
+    else {
+        sprite->spriteTraceGood = 1;
+        return sprite->spriteTrace[0];
+    }
+}
+
+void
+InitInput(int argc, char *argv[])
+{
+    ScreenPtr pScreen = screenInfo.screens[0];
+    struct xwl_screen *xwl_screen = xwl_screen_get(pScreen);
+
+    mieqInit();
+
+    xwl_screen->input_registry = wl_display_get_registry(xwl_screen->display);
+    wl_registry_add_listener(xwl_screen->input_registry, &input_listener,
+                             xwl_screen);
+
+    xwl_screen->XYToWindow = pScreen->XYToWindow;
+    pScreen->XYToWindow = xwl_xy_to_window;
+
+    xwl_screen->expecting_event = 0;
+    wl_display_roundtrip(xwl_screen->display);
+    while (xwl_screen->expecting_event)
+        wl_display_roundtrip(xwl_screen->display);
+}
+
+void
+CloseInput(void)
+{
+    mieqFini();
+}
diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
new file mode 100644
index 0000000..778914c
--- /dev/null
+++ b/hw/xwayland/xwayland-output.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright © 2011-2014 Intel Corporation
+ *
+ * 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 the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "xwayland.h"
+#include <randrstr.h>
+
+static Rotation
+wl_transform_to_xrandr(enum wl_output_transform transform)
+{
+    switch (transform) {
+    default:
+    case WL_OUTPUT_TRANSFORM_NORMAL:
+        return RR_Rotate_0;
+    case WL_OUTPUT_TRANSFORM_90:
+        return RR_Rotate_90;
+    case WL_OUTPUT_TRANSFORM_180:
+        return RR_Rotate_180;
+    case WL_OUTPUT_TRANSFORM_270:
+        return RR_Rotate_270;
+    case WL_OUTPUT_TRANSFORM_FLIPPED:
+        return RR_Reflect_X | RR_Rotate_0;
+    case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+        return RR_Reflect_X | RR_Rotate_90;
+    case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+        return RR_Reflect_X | RR_Rotate_180;
+    case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+        return RR_Reflect_X | RR_Rotate_270;
+    }
+}
+
+static int
+wl_subpixel_to_xrandr(int subpixel)
+{
+    switch (subpixel) {
+    default:
+    case WL_OUTPUT_SUBPIXEL_UNKNOWN:
+        return SubPixelUnknown;
+    case WL_OUTPUT_SUBPIXEL_NONE:
+        return SubPixelNone;
+    case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
+        return SubPixelHorizontalRGB;
+    case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
+        return SubPixelHorizontalBGR;
+    case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
+        return SubPixelVerticalRGB;
+    case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
+        return SubPixelVerticalBGR;
+    }
+}
+
+static void
+output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
+                       int physical_width, int physical_height, int subpixel,
+                       const char *make, const char *model, int transform)
+{
+    struct xwl_output *xwl_output = data;
+
+    RROutputSetPhysicalSize(xwl_output->randr_output,
+                            physical_width, physical_height);
+    RROutputSetSubpixelOrder(xwl_output->randr_output,
+                             wl_subpixel_to_xrandr(subpixel));
+    xwl_output->x = x;
+    xwl_output->y = y;
+
+    xwl_output->rotation = wl_transform_to_xrandr(transform);
+}
+
+static void
+output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
+                   int width, int height, int refresh)
+{
+    struct xwl_output *xwl_output = data;
+    RRModePtr randr_mode;
+
+    if (!(flags & WL_OUTPUT_MODE_CURRENT))
+        return;
+
+    xwl_output->width = width;
+    xwl_output->height = height;
+
+    randr_mode = xwayland_cvt(width, height, refresh / 1000.0, 0, 0);
+
+    RROutputSetModes(xwl_output->randr_output, &randr_mode, 1, 1);
+
+    RRCrtcNotify(xwl_output->randr_crtc, randr_mode,
+                 xwl_output->x, xwl_output->y,
+                 xwl_output->rotation, NULL, 1, &xwl_output->randr_output);
+}
+
+static void
+output_handle_done(void *data, struct wl_output *wl_output)
+{
+    struct xwl_output *xwl_output = data;
+    struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
+    int width, height;
+
+    xorg_list_append(&xwl_output->link, &xwl_screen->output_list);
+
+    width = 0;
+    height = 0;
+    xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) {
+        if (width < xwl_output->x + xwl_output->width)
+            width = xwl_output->x + xwl_output->width;
+        if (height < xwl_output->y + xwl_output->height)
+            height = xwl_output->y + xwl_output->height;
+    }
+
+    xwl_screen->width = width;
+    xwl_screen->height = height;
+    RRScreenSizeNotify(xwl_screen->screen);
+
+    xwl_screen->expecting_event--;
+}
+
+static void
+output_handle_scale(void *data, struct wl_output *wl_output, int32_t factor)
+{
+}
+
+static const struct wl_output_listener output_listener = {
+    output_handle_geometry,
+    output_handle_mode,
+    output_handle_done,
+    output_handle_scale
+};
+
+struct xwl_output *
+xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
+{
+    struct xwl_output *xwl_output;
+    static int serial;
+    char name[256];
+
+    xwl_output = calloc(sizeof *xwl_output, 1);
+    if (xwl_output == NULL) {
+        ErrorF("create_output ENOMEM");
+        return NULL;
+    }
+
+    xwl_output->output = wl_registry_bind(xwl_screen->registry, id,
+                                          &wl_output_interface, 2);
+    wl_output_add_listener(xwl_output->output, &output_listener, xwl_output);
+
+    if (snprintf(name, sizeof name, "XWAYLAND%d", serial++) < 0) {
+        ErrorF("create_output ENOMEM");
+        free(xwl_output);
+        return NULL;
+    }
+
+    xwl_output->xwl_screen = xwl_screen;
+    xwl_output->randr_crtc = RRCrtcCreate(xwl_screen->screen, xwl_output);
+    xwl_output->randr_output = RROutputCreate(xwl_screen->screen, name,
+                                              strlen(name), xwl_output);
+    RRCrtcGammaSetSize(xwl_output->randr_crtc, 256);
+    RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1);
+    RROutputSetConnection(xwl_output->randr_output, RR_Connected);
+
+    return xwl_output;
+}
+
+void
+xwl_output_destroy(struct xwl_output *xwl_output)
+{
+    wl_output_destroy(xwl_output->output);
+    RRCrtcDestroy(xwl_output->randr_crtc);
+    RROutputDestroy(xwl_output->randr_output);
+    free(xwl_output);
+}
+
+static Bool
+xwl_randr_get_info(ScreenPtr pScreen, Rotation * rotations)
+{
+    *rotations = 0;
+
+    return TRUE;
+}
+
+static Bool
+xwl_randr_set_config(ScreenPtr pScreen,
+                     Rotation rotation, int rate, RRScreenSizePtr pSize)
+{
+    return FALSE;
+}
+
+Bool
+xwl_screen_init_output(struct xwl_screen *xwl_screen)
+{
+    rrScrPrivPtr rp;
+
+    if (!RRScreenInit(xwl_screen->screen))
+        return FALSE;
+
+    RRScreenSetSizeRange(xwl_screen->screen, 320, 200, 8192, 8192);
+
+    rp = rrGetScrPriv(xwl_screen->screen);
+    rp->rrGetInfo = xwl_randr_get_info;
+    rp->rrSetConfig = xwl_randr_set_config;
+
+    return TRUE;
+}
diff --git a/hw/xwayland/xwayland-shm.c b/hw/xwayland/xwayland-shm.c
new file mode 100644
index 0000000..2d0ce3e
--- /dev/null
+++ b/hw/xwayland/xwayland-shm.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ * Copyright © 2012 Collabora, Ltd.
+ *
+ * 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 the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 "xwayland.h"
+
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+struct xwl_pixmap {
+    struct wl_buffer *buffer;
+    int fd;
+    void *data;
+    size_t size;
+};
+
+#ifndef HAVE_MKOSTEMP
+static int
+set_cloexec_or_close(int fd)
+{
+    long flags;
+
+    if (fd == -1)
+        return -1;
+
+    flags = fcntl(fd, F_GETFD);
+    if (flags == -1)
+        goto err;
+
+    if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
+        goto err;
+
+    return fd;
+
+ err:
+    close(fd);
+    return -1;
+}
+#endif
+
+static int
+create_tmpfile_cloexec(char *tmpname)
+{
+    int fd;
+
+#ifdef HAVE_MKOSTEMP
+    fd = mkostemp(tmpname, O_CLOEXEC);
+    if (fd >= 0)
+        unlink(tmpname);
+#else
+    fd = mkstemp(tmpname);
+    if (fd >= 0) {
+        fd = set_cloexec_or_close(fd);
+        unlink(tmpname);
+    }
+#endif
+
+    return fd;
+}
+
+/*
+ * Create a new, unique, anonymous file of the given size, and
+ * return the file descriptor for it. The file descriptor is set
+ * CLOEXEC. The file is immediately suitable for mmap()'ing
+ * the given size at offset zero.
+ *
+ * The file should not have a permanent backing store like a disk,
+ * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
+ *
+ * The file name is deleted from the file system.
+ *
+ * The file is suitable for buffer sharing between processes by
+ * transmitting the file descriptor over Unix sockets using the
+ * SCM_RIGHTS methods.
+ *
+ * If the C library implements posix_fallocate(), it is used to
+ * guarantee that disk space is available for the file at the
+ * given size. If disk space is insufficent, errno is set to ENOSPC.
+ * If posix_fallocate() is not supported, program may receive
+ * SIGBUS on accessing mmap()'ed file contents instead.
+ */
+static int
+os_create_anonymous_file(off_t size)
+{
+    static const char template[] = "/weston-shared-XXXXXX";
+    const char *path;
+    char *name;
+    int fd;
+    int ret;
+
+    path = getenv("XDG_RUNTIME_DIR");
+    if (!path) {
+        errno = ENOENT;
+        return -1;
+    }
+
+    name = malloc(strlen(path) + sizeof(template));
+    if (!name)
+        return -1;
+
+    strcpy(name, path);
+    strcat(name, template);
+
+    fd = create_tmpfile_cloexec(name);
+
+    free(name);
+
+    if (fd < 0)
+        return -1;
+
+#ifdef HAVE_POSIX_FALLOCATE
+    ret = posix_fallocate(fd, 0, size);
+    if (ret != 0) {
+        close(fd);
+        errno = ret;
+        return -1;
+    }
+#else
+    ret = ftruncate(fd, size);
+    if (ret < 0) {
+        close(fd);
+        return -1;
+    }
+#endif
+
+    return fd;
+}
+
+static uint32_t
+shm_format_for_depth(int depth)
+{
+    switch (depth) {
+    case 32:
+        return WL_SHM_FORMAT_ARGB8888;
+    case 24:
+    default:
+        return WL_SHM_FORMAT_XRGB8888;
+#ifdef WL_SHM_FORMAT_RGB565
+    case 16:
+        /* XXX: Check run-time protocol version too */
+        return WL_SHM_FORMAT_RGB565;
+#endif
+    }
+}
+
+PixmapPtr
+xwl_shm_create_pixmap(ScreenPtr screen,
+                      int width, int height, int depth, unsigned int hint)
+{
+    PixmapPtr pixmap;
+    struct xwl_pixmap *xwl_pixmap;
+    size_t size, stride;
+
+    if (hint == CREATE_PIXMAP_USAGE_GLYPH_PICTURE ||
+        (width == 0 && height == 0) || depth < 15)
+        return fbCreatePixmap(screen, width, height, depth, hint);
+
+    pixmap = fbCreatePixmap(screen, 0, 0, depth, hint);
+    if (!pixmap)
+        return NULL;
+
+    xwl_pixmap = malloc(sizeof *xwl_pixmap);
+    if (xwl_pixmap == NULL)
+        goto err_destroy_pixmap;
+
+    stride = PixmapBytePad(width, depth);
+    size = stride * height;
+    xwl_pixmap->buffer = NULL;
+    xwl_pixmap->size = size;
+    xwl_pixmap->fd = os_create_anonymous_file(size);
+    if (xwl_pixmap->fd < 0)
+        goto err_free_xwl_pixmap;
+
+    xwl_pixmap->data = mmap(NULL, size, PROT_READ | PROT_WRITE,
+                                  MAP_SHARED, xwl_pixmap->fd, 0);
+    if (xwl_pixmap->data == MAP_FAILED)
+        goto err_close_fd;
+
+    if (!(*screen->ModifyPixmapHeader) (pixmap, width, height, depth,
+                                        BitsPerPixel(depth),
+                                        stride, xwl_pixmap->data))
+        goto err_munmap;
+
+    xwl_pixmap_set_private(pixmap, xwl_pixmap);
+
+    return pixmap;
+
+ err_munmap:
+    munmap(xwl_pixmap->data, size);
+ err_close_fd:
+    close(xwl_pixmap->fd);
+ err_free_xwl_pixmap:
+    free(xwl_pixmap);
+ err_destroy_pixmap:
+    fbDestroyPixmap(pixmap);
+
+    return NULL;
+}
+
+Bool
+xwl_shm_destroy_pixmap(PixmapPtr pixmap)
+{
+    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+
+    if (xwl_pixmap && pixmap->refcnt == 1) {
+        if (xwl_pixmap->buffer)
+            wl_buffer_destroy(xwl_pixmap->buffer);
+        munmap(xwl_pixmap->data, xwl_pixmap->size);
+        close(xwl_pixmap->fd);
+        free(xwl_pixmap);
+    }
+
+    return fbDestroyPixmap(pixmap);
+}
+
+struct wl_buffer *
+xwl_shm_pixmap_get_wl_buffer(PixmapPtr pixmap)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
+    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+    struct wl_shm_pool *pool;
+    uint32_t format;
+
+    if (xwl_pixmap->buffer)
+        return xwl_pixmap->buffer;
+
+    pool = wl_shm_create_pool(xwl_screen->shm,
+                              xwl_pixmap->fd, xwl_pixmap->size);
+
+    format = shm_format_for_depth(pixmap->drawable.depth);
+    xwl_pixmap->buffer = wl_shm_pool_create_buffer(pool, 0,
+                                                   pixmap->drawable.width,
+                                                   pixmap->drawable.height,
+                                                   pixmap->devKind, format);
+
+    wl_shm_pool_destroy(pool);
+
+    return xwl_pixmap->buffer;
+}
+
+Bool
+xwl_shm_create_screen_resources(ScreenPtr screen)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    int ret;
+
+    screen->CreateScreenResources = xwl_screen->CreateScreenResources;
+    ret = (*screen->CreateScreenResources) (screen);
+    xwl_screen->CreateScreenResources = screen->CreateScreenResources;
+    screen->CreateScreenResources = xwl_shm_create_screen_resources;
+
+    if (!ret)
+        return ret;
+
+    if (xwl_screen->rootless)
+        screen->devPrivate =
+            fbCreatePixmap(screen, 0, 0, screen->rootDepth, 0);
+    else
+        screen->devPrivate =
+            xwl_shm_create_pixmap(screen, screen->width, screen->height,
+                                  screen->rootDepth,
+                                  CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
+
+    return screen->devPrivate != NULL;
+}
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
new file mode 100644
index 0000000..c2c6481
--- /dev/null
+++ b/hw/xwayland/xwayland.c
@@ -0,0 +1,652 @@
+/*
+ * Copyright © 2011-2014 Intel Corporation
+ *
+ * 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 the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 "xwayland.h"
+
+#include <stdio.h>
+
+#include <selection.h>
+#include <micmap.h>
+#include <misyncshm.h>
+#include <compositeext.h>
+#include <glx_extinit.h>
+
+void
+ddxGiveUp(enum ExitCode error)
+{
+}
+
+void
+AbortDDX(enum ExitCode error)
+{
+    ddxGiveUp(error);
+}
+
+void
+OsVendorInit(void)
+{
+}
+
+void
+OsVendorFatalError(const char *f, va_list args)
+{
+}
+
+#if defined(DDXBEFORERESET)
+void
+ddxBeforeReset(void)
+{
+    return;
+}
+#endif
+
+void
+ddxUseMsg(void)
+{
+    ErrorF("-rootless              run rootless, requires wm support\n");
+    ErrorF("-wm fd                 create X client for wm on given fd\n");
+    ErrorF("-listen fd             add give fd as a listen socket\n");
+}
+
+int
+ddxProcessArgument(int argc, char *argv[], int i)
+{
+    if (strcmp(argv[i], "-rootless") == 0) {
+        return 1;
+    }
+    else if (strcmp(argv[i], "-listen") == 0) {
+        NoListenAll = TRUE;
+        return 2;
+    }
+    else if (strcmp(argv[i], "-wm") == 0) {
+        return 2;
+    }
+    else if (strcmp(argv[i], "-shm") == 0) {
+        return 1;
+    }
+
+    return 0;
+}
+
+static DevPrivateKeyRec xwl_window_private_key;
+static DevPrivateKeyRec xwl_screen_private_key;
+static DevPrivateKeyRec xwl_pixmap_private_key;
+
+struct xwl_screen *
+xwl_screen_get(ScreenPtr screen)
+{
+    return dixLookupPrivate(&screen->devPrivates, &xwl_screen_private_key);
+}
+
+static Bool
+xwl_close_screen(ScreenPtr screen)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    struct xwl_output *xwl_output, *next_xwl_output;
+    struct xwl_seat *xwl_seat, *next_xwl_seat;
+
+    xorg_list_for_each_entry_safe(xwl_output, next_xwl_output,
+                                  &xwl_screen->output_list, link)
+        xwl_output_destroy(xwl_output);
+
+    xorg_list_for_each_entry_safe(xwl_seat, next_xwl_seat,
+                                  &xwl_screen->seat_list, link)
+        xwl_seat_destroy(xwl_seat);
+
+    wl_display_disconnect(xwl_screen->display);
+
+    screen->CloseScreen = xwl_screen->CloseScreen;
+    free(xwl_screen);
+
+    return screen->CloseScreen(screen);
+}
+
+static void
+damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
+{
+    struct xwl_window *xwl_window = data;
+    struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+
+    xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
+}
+
+static void
+damage_destroy(DamagePtr pDamage, void *data)
+{
+}
+
+static void
+shell_surface_ping(void *data,
+                   struct wl_shell_surface *shell_surface, uint32_t serial)
+{
+    wl_shell_surface_pong(shell_surface, serial);
+}
+
+static void
+shell_surface_configure(void *data,
+                        struct wl_shell_surface *wl_shell_surface,
+                        uint32_t edges, int32_t width, int32_t height)
+{
+}
+
+static void
+shell_surface_popup_done(void *data, struct wl_shell_surface *wl_shell_surface)
+{
+}
+
+static const struct wl_shell_surface_listener shell_surface_listener = {
+    shell_surface_ping,
+    shell_surface_configure,
+    shell_surface_popup_done
+};
+
+void
+xwl_pixmap_set_private(PixmapPtr pixmap, struct xwl_pixmap *xwl_pixmap)
+{
+    dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key, xwl_pixmap);
+}
+
+struct xwl_pixmap *
+xwl_pixmap_get(PixmapPtr pixmap)
+{
+    return dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key);
+}
+
+static void
+send_surface_id_event(struct xwl_window *xwl_window)
+{
+    static const char atom_name[] = "WL_SURFACE_ID";
+    static Atom type_atom;
+    DeviceIntPtr dev;
+    xEvent e;
+
+    if (type_atom == None)
+        type_atom = MakeAtom(atom_name, strlen(atom_name), TRUE);
+
+    e.u.u.type = ClientMessage;
+    e.u.u.detail = 32;
+    e.u.clientMessage.window = xwl_window->window->drawable.id;
+    e.u.clientMessage.u.l.type = type_atom;
+    e.u.clientMessage.u.l.longs0 =
+        wl_proxy_get_id((struct wl_proxy *) xwl_window->surface);
+    e.u.clientMessage.u.l.longs1 = 0;
+    e.u.clientMessage.u.l.longs2 = 0;
+    e.u.clientMessage.u.l.longs3 = 0;
+    e.u.clientMessage.u.l.longs4 = 0;
+
+    dev = PickPointer(serverClient);
+    DeliverEventsToWindow(dev, xwl_window->xwl_screen->screen->root,
+                          &e, 1, SubstructureRedirectMask, NullGrab);
+}
+
+static Bool
+xwl_realize_window(WindowPtr window)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    struct xwl_screen *xwl_screen;
+    struct xwl_window *xwl_window;
+    struct wl_region *region;
+    Bool ret;
+
+    xwl_screen = xwl_screen_get(screen);
+
+    screen->RealizeWindow = xwl_screen->RealizeWindow;
+    ret = (*screen->RealizeWindow) (window);
+    xwl_screen->RealizeWindow = screen->RealizeWindow;
+    screen->RealizeWindow = xwl_realize_window;
+
+    if (xwl_screen->rootless && !window->parent) {
+        ErrorF("Clearing root clip\n");
+        RegionNull(&window->clipList);
+        RegionNull(&window->borderClip);
+        RegionNull(&window->winSize);
+    }
+
+    if (xwl_screen->rootless) {
+        if (window->redirectDraw != RedirectDrawManual)
+            return ret;
+    }
+    else {
+        if (window->parent)
+            return ret;
+    }
+
+    xwl_window = calloc(sizeof *xwl_window, 1);
+    xwl_window->xwl_screen = xwl_screen;
+    xwl_window->window = window;
+    xwl_window->surface = wl_compositor_create_surface(xwl_screen->compositor);
+    if (xwl_window->surface == NULL) {
+        ErrorF("wl_display_create_surface failed\n");
+        return FALSE;
+    }
+
+    if (!xwl_screen->rootless) {
+        xwl_window->shell_surface =
+            wl_shell_get_shell_surface(xwl_screen->shell, xwl_window->surface);
+        wl_shell_surface_add_listener(xwl_window->shell_surface,
+                                      &shell_surface_listener, xwl_window);
+
+        wl_shell_surface_set_toplevel(xwl_window->shell_surface);
+
+        region = wl_compositor_create_region(xwl_screen->compositor);
+        wl_region_add(region, 0, 0,
+                      window->drawable.width, window->drawable.height);
+        wl_surface_set_opaque_region(xwl_window->surface, region);
+        wl_region_destroy(region);
+    }
+
+    wl_display_flush(xwl_screen->display);
+
+    send_surface_id_event(xwl_window);
+
+    wl_surface_set_user_data(xwl_window->surface, xwl_window);
+
+    dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window);
+
+    xwl_window->damage =
+        DamageCreate(damage_report, damage_destroy, DamageReportNonEmpty,
+                     FALSE, screen, xwl_window);
+    DamageRegister(&window->drawable, xwl_window->damage);
+    DamageSetReportAfterOp(xwl_window->damage, TRUE);
+
+    xorg_list_init(&xwl_window->link_damage);
+
+    return ret;
+}
+
+static Bool
+xwl_unrealize_window(WindowPtr window)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    struct xwl_screen *xwl_screen;
+    struct xwl_window *xwl_window;
+    struct xwl_seat *xwl_seat;
+    Bool ret;
+
+    xwl_screen = xwl_screen_get(screen);
+
+    xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
+        if (!xwl_seat->focus_window)
+            continue;
+        if (xwl_seat->focus_window->window == window)
+            xwl_seat->focus_window = NULL;
+    }
+
+    screen->UnrealizeWindow = xwl_screen->UnrealizeWindow;
+    ret = (*screen->UnrealizeWindow) (window);
+    xwl_screen->UnrealizeWindow = screen->UnrealizeWindow;
+    screen->UnrealizeWindow = xwl_unrealize_window;
+
+    xwl_window =
+        dixLookupPrivate(&window->devPrivates, &xwl_window_private_key);
+    if (!xwl_window)
+        return ret;
+
+    wl_surface_destroy(xwl_window->surface);
+    if (RegionNotEmpty(DamageRegion(xwl_window->damage)))
+        xorg_list_del(&xwl_window->link_damage);
+    DamageUnregister(xwl_window->damage);
+    DamageDestroy(xwl_window->damage);
+    free(xwl_window);
+    dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL);
+
+    return ret;
+}
+
+static Bool
+xwl_save_screen(ScreenPtr pScreen, int on)
+{
+    return TRUE;
+}
+
+static void
+xwl_screen_post_damage(struct xwl_screen *xwl_screen)
+{
+    struct xwl_window *xwl_window;
+    RegionPtr region;
+    BoxPtr box;
+    int count, i;
+    struct wl_buffer *buffer;
+    PixmapPtr pixmap;
+
+    xorg_list_for_each_entry(xwl_window, &xwl_screen->damage_window_list,
+                             link_damage) {
+        region = DamageRegion(xwl_window->damage);
+        count = RegionNumRects(region);
+
+        pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window);
+
+        buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
+        wl_surface_attach(xwl_window->surface, buffer, 0, 0);
+        for (i = 0; i < count; i++) {
+            box = &RegionRects(region)[i];
+            wl_surface_damage(xwl_window->surface,
+                              box->x1, box->y1,
+                              box->x2 - box->x1, box->y2 - box->y1);
+        }
+        wl_surface_commit(xwl_window->surface);
+        DamageEmpty(xwl_window->damage);
+    }
+
+    xorg_list_init(&xwl_screen->damage_window_list);
+}
+
+static void
+registry_global(void *data, struct wl_registry *registry, uint32_t id,
+                const char *interface, uint32_t version)
+{
+    struct xwl_screen *xwl_screen = data;
+
+    if (strcmp(interface, "wl_compositor") == 0) {
+        xwl_screen->compositor =
+            wl_registry_bind(registry, id, &wl_compositor_interface, 1);
+    }
+    else if (strcmp(interface, "wl_shm") == 0) {
+        xwl_screen->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
+    }
+    else if (strcmp(interface, "wl_shell") == 0) {
+        xwl_screen->shell =
+            wl_registry_bind(registry, id, &wl_shell_interface, 1);
+    }
+    else if (strcmp(interface, "wl_output") == 0 && version >= 2) {
+        xwl_output_create(xwl_screen, id);
+        xwl_screen->expecting_event++;
+    }
+}
+
+static void
+global_remove(void *data, struct wl_registry *registry, uint32_t name)
+{
+    /* Nothing to do here, wl_compositor and wl_shm should not be removed */
+}
+
+static const struct wl_registry_listener registry_listener = {
+    registry_global,
+    global_remove
+};
+
+static void
+wakeup_handler(void *data, int err, void *read_mask)
+{
+    struct xwl_screen *xwl_screen = data;
+    int ret;
+
+    if (err < 0)
+        return;
+
+    if (!FD_ISSET(xwl_screen->wayland_fd, (fd_set *) read_mask))
+        return;
+
+    ret = wl_display_read_events(xwl_screen->display);
+    if (ret == -1)
+        FatalError("failed to dispatch Wayland events: %s\n", strerror(errno));
+
+    xwl_screen->prepare_read = 0;
+
+    ret = wl_display_dispatch_pending(xwl_screen->display);
+    if (ret == -1)
+        FatalError("failed to dispatch Wayland events: %s\n", strerror(errno));
+}
+
+static void
+block_handler(void *data, struct timeval **tv, void *read_mask)
+{
+    struct xwl_screen *xwl_screen = data;
+    int ret;
+
+    xwl_screen_post_damage(xwl_screen);
+
+    while (xwl_screen->prepare_read == 0 &&
+           wl_display_prepare_read(xwl_screen->display) == -1) {
+        ret = wl_display_dispatch_pending(xwl_screen->display);
+        if (ret == -1)
+            FatalError("failed to dispatch Wayland events: %s\n",
+                       strerror(errno));
+    }
+
+    xwl_screen->prepare_read = 1;
+
+    ret = wl_display_flush(xwl_screen->display);
+    if (ret == -1)
+        FatalError("failed to write to XWayland fd: %s\n", strerror(errno));
+}
+
+static CARD32
+add_client_fd(OsTimerPtr timer, CARD32 time, void *arg)
+{
+    struct xwl_screen *xwl_screen = arg;
+
+    if (!AddClientOnOpenFD(xwl_screen->wm_fd))
+        FatalError("Failed to add wm client\n");
+
+    TimerFree(timer);
+
+    return 0;
+}
+
+static void
+listen_on_fds(struct xwl_screen *xwl_screen)
+{
+    int i;
+
+    for (i = 0; i < xwl_screen->listen_fd_count; i++)
+        ListenOnOpenFD(xwl_screen->listen_fds[i], TRUE);
+}
+
+static void
+wm_selection_callback(CallbackListPtr *p, void *data, void *arg)
+{
+    SelectionInfoRec *info = arg;
+    struct xwl_screen *xwl_screen = data;
+    static const char atom_name[] = "WM_S0";
+    static Atom atom_wm_s0;
+
+    if (atom_wm_s0 == None)
+        atom_wm_s0 = MakeAtom(atom_name, strlen(atom_name), TRUE);
+    if (info->selection->selection != atom_wm_s0 ||
+        info->kind != SelectionSetOwner)
+        return;
+
+    listen_on_fds(xwl_screen);
+
+    DeleteCallback(&SelectionCallback, wm_selection_callback, xwl_screen);
+}
+
+static Bool
+xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
+{
+    struct xwl_screen *xwl_screen;
+    Pixel red_mask, blue_mask, green_mask;
+    int ret, bpc, green_bpc, i;
+
+    xwl_screen = calloc(sizeof *xwl_screen, 1);
+    xwl_screen->wm_fd = -1;
+    if (xwl_screen == NULL)
+        return FALSE;
+
+    if (!dixRegisterPrivateKey(&xwl_screen_private_key, PRIVATE_SCREEN, 0))
+        return FALSE;
+    if (!dixRegisterPrivateKey(&xwl_window_private_key, PRIVATE_WINDOW, 0))
+        return FALSE;
+    if (!dixRegisterPrivateKey(&xwl_pixmap_private_key, PRIVATE_PIXMAP, 0))
+        return FALSE;
+
+    dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen);
+    xwl_screen->screen = pScreen;
+
+    for (i = 1; i < argc; i++) {
+        if (strcmp(argv[i], "-rootless") == 0) {
+            xwl_screen->rootless = 1;
+        }
+        else if (strcmp(argv[i], "-wm") == 0) {
+            xwl_screen->wm_fd = atoi(argv[i + 1]);
+            i++;
+            TimerSet(NULL, 0, 1, add_client_fd, xwl_screen);
+        }
+        else if (strcmp(argv[i], "-listen") == 0) {
+            if (xwl_screen->listen_fd_count ==
+                ARRAY_SIZE(xwl_screen->listen_fds))
+                FatalError("Too many -listen arguments given, max is %ld\n",
+                           ARRAY_SIZE(xwl_screen->listen_fds));
+
+            xwl_screen->listen_fds[xwl_screen->listen_fd_count++] =
+                atoi(argv[i + 1]);
+            i++;
+        }
+    }
+
+    if (xwl_screen->listen_fd_count > 0) {
+        if (xwl_screen->wm_fd >= 0)
+            AddCallback(&SelectionCallback, wm_selection_callback, xwl_screen);
+        else
+            listen_on_fds(xwl_screen);
+    }
+
+    xorg_list_init(&xwl_screen->output_list);
+    xorg_list_init(&xwl_screen->seat_list);
+    xorg_list_init(&xwl_screen->damage_window_list);
+    xwl_screen->depth = 24;
+
+    xwl_screen->display = wl_display_connect(NULL);
+    if (xwl_screen->display == NULL) {
+        ErrorF("could not connect to wayland server\n");
+        return FALSE;
+    }
+
+    if (!xwl_screen_init_output(xwl_screen))
+        return FALSE;
+
+    xwl_screen->expecting_event = 0;
+    xwl_screen->registry = wl_display_get_registry(xwl_screen->display);
+    wl_registry_add_listener(xwl_screen->registry,
+                             &registry_listener, xwl_screen);
+    ret = wl_display_roundtrip(xwl_screen->display);
+    if (ret == -1) {
+        ErrorF("could not connect to wayland server\n");
+        return FALSE;
+    }
+
+    while (xwl_screen->expecting_event > 0)
+        wl_display_roundtrip(xwl_screen->display);
+
+    bpc = xwl_screen->depth / 3;
+    green_bpc = xwl_screen->depth - 2 * bpc;
+    blue_mask = (1 << bpc) - 1;
+    green_mask = ((1 << green_bpc) - 1) << bpc;
+    red_mask = blue_mask << (green_bpc + bpc);
+
+    miSetVisualTypesAndMasks(xwl_screen->depth,
+                             ((1 << TrueColor) | (1 << DirectColor)),
+                             green_bpc, TrueColor,
+                             red_mask, green_mask, blue_mask);
+
+    miSetPixmapDepths();
+
+    ret = fbScreenInit(pScreen, NULL,
+                       xwl_screen->width, xwl_screen->height,
+                       96, 96, 0,
+                       BitsPerPixel(xwl_screen->depth));
+    if (!ret)
+        return FALSE;
+
+    fbPictureInit(pScreen, 0, 0);
+
+    if (!miSyncShmScreenInit(pScreen))
+        return FALSE;
+
+    xwl_screen->wayland_fd = wl_display_get_fd(xwl_screen->display);
+    AddGeneralSocket(xwl_screen->wayland_fd);
+    RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, xwl_screen);
+
+    pScreen->SaveScreen = xwl_save_screen;
+
+    pScreen->blackPixel = 0;
+    pScreen->whitePixel = 1;
+
+    ret = fbCreateDefColormap(pScreen);
+
+    if (!xwl_screen_init_cursor(xwl_screen))
+        return FALSE;
+
+    xwl_screen->CreateScreenResources = pScreen->CreateScreenResources;
+    pScreen->CreateScreenResources = xwl_shm_create_screen_resources;
+    pScreen->CreatePixmap = xwl_shm_create_pixmap;
+    pScreen->DestroyPixmap = xwl_shm_destroy_pixmap;
+
+    xwl_screen->RealizeWindow = pScreen->RealizeWindow;
+    pScreen->RealizeWindow = xwl_realize_window;
+
+    xwl_screen->UnrealizeWindow = pScreen->UnrealizeWindow;
+    pScreen->UnrealizeWindow = xwl_unrealize_window;
+
+    xwl_screen->CloseScreen = pScreen->CloseScreen;
+    pScreen->CloseScreen = xwl_close_screen;
+
+    return ret;
+}
+
+static void _X_ATTRIBUTE_PRINTF(1, 0)
+xwl_log_handler(const char *format, va_list args)
+{
+    char msg[256];
+
+    vsnprintf(msg, sizeof msg, format, args);
+    FatalError("%s", msg);
+}
+
+static const ExtensionModule glx_extension[] = {
+    { GlxExtensionInit, "GLX", &noGlxExtension },
+};
+
+void
+InitOutput(ScreenInfo * screen_info, int argc, char **argv)
+{
+    int depths[] = { 1, 4, 8, 15, 16, 24, 32 };
+    int bpp[] =    { 1, 8, 8, 16, 16, 32, 32 };
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(depths); i++) {
+        screen_info->formats[i].depth = depths[i];
+        screen_info->formats[i].bitsPerPixel = bpp[i];
+        screen_info->formats[i].scanlinePad = BITMAP_SCANLINE_PAD;
+    }
+
+    screen_info->imageByteOrder = IMAGE_BYTE_ORDER;
+    screen_info->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+    screen_info->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+    screen_info->bitmapBitOrder = BITMAP_BIT_ORDER;
+    screen_info->numPixmapFormats = ARRAY_SIZE(depths);
+
+    LoadExtensionList(glx_extension, ARRAY_SIZE(glx_extension), FALSE);
+
+    /* Cast away warning from missing printf annotation for
+     * wl_log_func_t.  Wayland 1.5 will have the annotation, so we can
+     * remove the cast and require that when it's released. */
+    wl_log_set_handler_client((void *) xwl_log_handler);
+
+    if (AddScreen(xwl_screen_init, argc, argv) == -1) {
+        FatalError("Couldn't add screen\n");
+    }
+}
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
new file mode 100644
index 0000000..8157e71
--- /dev/null
+++ b/hw/xwayland/xwayland.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * 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 the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 XWAYLAND_H
+#define XWAYLAND_H
+
+#include <dix-config.h>
+#include <xorg-server.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <wayland-client.h>
+
+#include <X11/X.h>
+
+#include <fb.h>
+#include <input.h>
+#include <dix.h>
+#include <randrstr.h>
+#include <exevents.h>
+
+struct xwl_screen {
+    int width;
+    int height;
+    int depth;
+    ScreenPtr screen;
+    WindowPtr pointer_limbo_window;
+    int expecting_event;
+
+    int wm_fd;
+    int listen_fds[5];
+    int listen_fd_count;
+    int rootless;
+
+    CreateScreenResourcesProcPtr CreateScreenResources;
+    CloseScreenProcPtr CloseScreen;
+    CreateWindowProcPtr CreateWindow;
+    DestroyWindowProcPtr DestroyWindow;
+    RealizeWindowProcPtr RealizeWindow;
+    UnrealizeWindowProcPtr UnrealizeWindow;
+    XYToWindowProcPtr XYToWindow;
+
+    struct xorg_list output_list;
+    struct xorg_list seat_list;
+    struct xorg_list damage_window_list;
+
+    int wayland_fd;
+    struct wl_display *display;
+    struct wl_registry *registry;
+    struct wl_registry *input_registry;
+    struct wl_compositor *compositor;
+    struct wl_shm *shm;
+    struct wl_shell *shell;
+
+    uint32_t serial;
+
+#define XWL_FORMAT_ARGB8888 (1 << 0)
+#define XWL_FORMAT_XRGB8888 (1 << 1)
+#define XWL_FORMAT_RGB565   (1 << 2)
+
+    int prepare_read;
+};
+
+struct xwl_window {
+    struct xwl_screen *xwl_screen;
+    struct wl_surface *surface;
+    struct wl_shell_surface *shell_surface;
+    WindowPtr window;
+    DamagePtr damage;
+    struct xorg_list link_damage;
+};
+
+#define MODIFIER_META 0x01
+
+struct xwl_seat {
+    DeviceIntPtr pointer;
+    DeviceIntPtr keyboard;
+    struct xwl_screen *xwl_screen;
+    struct wl_seat *seat;
+    struct wl_pointer *wl_pointer;
+    struct wl_keyboard *wl_keyboard;
+    struct wl_array keys;
+    struct wl_surface *cursor;
+    struct xwl_window *focus_window;
+    uint32_t id;
+    uint32_t pointer_enter_serial;
+    struct xorg_list link;
+    CursorPtr x_cursor;
+
+    wl_fixed_t horizontal_scroll;
+    wl_fixed_t vertical_scroll;
+    uint32_t scroll_time;
+
+    size_t keymap_size;
+    char *keymap;
+    struct wl_surface *keyboard_focus;
+};
+
+struct xwl_output {
+    struct xorg_list link;
+    struct wl_output *output;
+    struct xwl_screen *xwl_screen;
+    RROutputPtr randr_output;
+    RRCrtcPtr randr_crtc;
+    int32_t x, y, width, height;
+    Rotation rotation;
+};
+
+struct xwl_pixmap;
+
+Bool xwl_screen_init_cursor(struct xwl_screen *xwl_screen);
+
+struct xwl_screen *xwl_screen_get(ScreenPtr screen);
+
+void xwl_seat_set_cursor(struct xwl_seat *xwl_seat);
+
+void xwl_seat_destroy(struct xwl_seat *xwl_seat);
+
+Bool xwl_screen_init_output(struct xwl_screen *xwl_screen);
+
+struct xwl_output *xwl_output_create(struct xwl_screen *xwl_screen,
+                                     uint32_t id);
+
+void xwl_output_destroy(struct xwl_output *xwl_output);
+
+RRModePtr xwayland_cvt(int HDisplay, int VDisplay,
+                       float VRefresh, Bool Reduced, Bool Interlaced);
+
+void xwl_pixmap_set_private(PixmapPtr pixmap, struct xwl_pixmap *xwl_pixmap);
+struct xwl_pixmap *xwl_pixmap_get(PixmapPtr pixmap);
+
+
+Bool xwl_shm_create_screen_resources(ScreenPtr screen);
+PixmapPtr xwl_shm_create_pixmap(ScreenPtr screen, int width, int height,
+                                int depth, unsigned int hint);
+Bool xwl_shm_destroy_pixmap(PixmapPtr pixmap);
+struct wl_buffer *xwl_shm_pixmap_get_wl_buffer(PixmapPtr pixmap);
+
+
+#endif
commit e738276e96590b2230dd9d9f5a3f9485f592e1e6
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Mon Mar 31 18:04:07 2014 -0700

    glamor: Expose glamor_destroy_pixmap()
    
    When we create a glamor pixmap by calling glamor_create_pixmap()
    directly, we need to call glamor_destroy_pixmap() to destroy it.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor.h b/glamor/glamor.h
index 913bdce..27c9cb3 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -143,6 +143,7 @@ extern _X_EXPORT void glamor_block_handler(ScreenPtr screen);
 
 extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h,
                                                 int depth, unsigned int usage);
+extern _X_EXPORT Bool glamor_destroy_pixmap(PixmapPtr pixmap);
 
 #define GLAMOR_CREATE_PIXMAP_CPU        0x100
 #define GLAMOR_CREATE_PIXMAP_FIXUP      0x101
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 6aa2f74..e8925a6 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -584,8 +584,6 @@ extern int glamor_debug_level;
 /* glamor.c */
 PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable);
 
-Bool glamor_destroy_pixmap(PixmapPtr pixmap);
-
 glamor_pixmap_fbo *glamor_pixmap_detach_fbo(glamor_pixmap_private *
                                             pixmap_priv);
 void glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo);
commit d14803437582668f5ffea14071ea962b6b8e450d
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Mon Mar 31 18:00:54 2014 -0700

    glamor: Add new GLAMOR_CREATE_PIXMAP_NO_TEXTURE pixmap create flag
    
    This flag lets a DDX allocate a glamor pixmap without allocating the
    texture that backs it.  The DDX can then allocate the texture itself
    and then set it later.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 3094432..8d24531 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -182,7 +182,15 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
     pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3;
     screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL);
 
-    if (type == GLAMOR_MEMORY_MAP || usage == GLAMOR_CREATE_NO_LARGE ||
+    if (usage == GLAMOR_CREATE_PIXMAP_NO_TEXTURE) {
+        pixmap_priv->type = GLAMOR_TEXTURE_ONLY;
+        pixmap_priv->base.box.x1 = 0;
+        pixmap_priv->base.box.y1 = 0;
+        pixmap_priv->base.box.x2 = w;
+        pixmap_priv->base.box.y2 = h;
+        return pixmap;
+    }
+    else if (type == GLAMOR_MEMORY_MAP || usage == GLAMOR_CREATE_NO_LARGE ||
         glamor_check_fbo_size(glamor_priv, w, h))
     {
         pixmap_priv->type = type;
diff --git a/glamor/glamor.h b/glamor/glamor.h
index 84b6736..913bdce 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -149,6 +149,7 @@ extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h,
 #define GLAMOR_CREATE_FBO_NO_FBO        0x103
 #define GLAMOR_CREATE_PIXMAP_MAP        0x104
 #define GLAMOR_CREATE_NO_LARGE          0x105
+#define GLAMOR_CREATE_PIXMAP_NO_TEXTURE 0x106
 
 /* @glamor_egl_exchange_buffers: Exchange the underlying buffers(KHR image,fbo).
  *
commit fe204185bc801bb17785dc8d1cde09d48b5e257f
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Mon Mar 31 17:59:18 2014 -0700

    glamor: Move glamor_egl_screen_init() prototype to glamor.h
    
    A DDX that implements the glamor EGL functions need to pull in this
    prototype but shouldn't need to pull in glamor_priv.h
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor.h b/glamor/glamor.h
index 11ec493..84b6736 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -310,6 +310,8 @@ extern _X_EXPORT Bool
 
 #endif
 
+extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen,
+                                             struct glamor_context *glamor_ctx);
 extern _X_EXPORT void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap);
 
 extern _X_EXPORT int glamor_create_gc(GCPtr gc);
diff --git a/glamor/glamor_egl_stubs.c b/glamor/glamor_egl_stubs.c
index 4fd9e80..028d1cc 100644
--- a/glamor/glamor_egl_stubs.c
+++ b/glamor/glamor_egl_stubs.c
@@ -26,7 +26,9 @@
  * Stubbed out glamor_egl.c functions for servers other than Xorg.
  */
 
-#include "glamor_priv.h"
+#include "dix-config.h"
+
+#include "glamor.h"
 
 void
 glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 4c305ab..6aa2f74 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -992,9 +992,6 @@ void glamor_composite_rectangles(CARD8 op,
                                  xRenderColor *color,
                                  int num_rects, xRectangle *rects);
 
-extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen,
-                                             struct glamor_context *glamor_ctx);
-
 /* glamor_xv */
 typedef struct {
     uint32_t transform_index;
commit 9ba2084321b1ac8d271feefee4f5b968d34226d6
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Thu Mar 27 23:47:59 2014 -0700

    dri3: Allow asynchronous implementation for dri3_open
    
    By passing the client pointer to the dri3_open implementation, we allow
    the clients to implement the open callback asynchronously.  If the
    client ignore count is positive after returning from dri3_open, we
    assume that authentication is in progress and doesn't send the reply.
    The code to send the reply is moved into a helper function, which the
    implementation can call upon receiving its authenticaion reply.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/dri3/dri3.h b/dri3/dri3.h
index 7c0c330..1c04cbd 100644
--- a/dri3/dri3.h
+++ b/dri3/dri3.h
@@ -32,7 +32,8 @@
 
 #define DRI3_SCREEN_INFO_VERSION        0
 
-typedef int (*dri3_open_proc)(ScreenPtr screen,
+typedef int (*dri3_open_proc)(ClientPtr client,
+                              ScreenPtr screen,
                               RRProviderPtr provider,
                               int *fd);
 
@@ -60,6 +61,9 @@ typedef struct dri3_screen_info {
 extern _X_EXPORT Bool
 dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info);
 
+extern _X_EXPORT int
+dri3_send_open_reply(ClientPtr client, int fd);
+
 #endif
 
 #endif /* _DRI3_H_ */
diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c
index 31dce83..fe45620 100644
--- a/dri3/dri3_request.c
+++ b/dri3/dri3_request.c
@@ -55,16 +55,35 @@ proc_dri3_query_version(ClientPtr client)
     return Success;
 }
 
-static int
-proc_dri3_open(ClientPtr client)
+int
+dri3_send_open_reply(ClientPtr client, int fd)
 {
-    REQUEST(xDRI3OpenReq);
     xDRI3OpenReply rep = {
         .type = X_Reply,
         .nfd = 1,
         .sequenceNumber = client->sequence,
         .length = 0,
     };
+
+    if (client->swapped) {
+        swaps(&rep.sequenceNumber);
+        swapl(&rep.length);
+    }
+
+    if (WriteFdToClient(client, fd, TRUE) < 0) {
+        close(fd);
+        return BadAlloc;
+    }
+
+    WriteToClient(client, sizeof (rep), &rep);
+
+    return Success;
+}
+
+static int
+proc_dri3_open(ClientPtr client)
+{
+    REQUEST(xDRI3OpenReq);
     RRProviderPtr provider;
     DrawablePtr drawable;
     ScreenPtr screen;
@@ -92,17 +111,8 @@ proc_dri3_open(ClientPtr client)
     if (status != Success)
         return status;
 
-    if (client->swapped) {
-        swaps(&rep.sequenceNumber);
-        swapl(&rep.length);
-    }
-
-    if (WriteFdToClient(client, fd, TRUE) < 0) {
-        close(fd);
-        return BadAlloc;
-    }
-
-    WriteToClient(client, sizeof (rep), &rep);
+    if (client->ignoreCount == 0)
+        return dri3_send_open_reply(client, fd);
 
     return Success;
 }
diff --git a/dri3/dri3_screen.c b/dri3/dri3_screen.c
index c880296..bbf1d05 100644
--- a/dri3/dri3_screen.c
+++ b/dri3/dri3_screen.c
@@ -40,7 +40,7 @@ dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd)
     if (!info || !info->open)
         return BadMatch;
 
-    rc = (*info->open) (screen, provider, fd);
+    rc = (*info->open) (client, screen, provider, fd);
     if (rc != Success)
         return rc;
 
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 8123421..e2b6a92 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -608,7 +608,8 @@ glamor_egl_close_screen(ScreenPtr screen)
 }
 
 static int
-glamor_dri3_open(ScreenPtr screen,
+glamor_dri3_open(ClientPtr client,
+                 ScreenPtr screen,
                  RRProviderPtr provider,
                  int *fdp)
 {
commit 4ba7b594464887ae68623e150348d90812eec36c
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Thu Mar 27 22:15:28 2014 -0700

    composite: Add exception mechanism for implicit redirection policy
    
    Normally composite will decide to add implicit redirection when a
    window with an alternate visual is a parent of a window with a regular
    visual or vice versa.  This uses extra pixmap memory and incurs an extra
    copy.  This exception mechanism provides a way for a DDX to override this
    if the DDX knows that its acceleration architecture will render correctly.
    
    The relevant case is that of an RGB window reparented into a ARGB parent
    frame window.  If the DDX knows that the acceleration architecture in use
    will pad the alpha channel to opaque when rendering to the RGB window,
    the implicit redirection can be avoided.
    
    This patch adds a new composite function:
    
      CompositeRegisterImplicitRedirectionException()
    
    which lets a DDX register a pair of parent and child window visuals, that
    will not be implicitly redirected even if the normal policy would have
    made that choice.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/composite/compinit.c b/composite/compinit.c
index 1db9e0b..48e938f 100644
--- a/composite/compinit.c
+++ b/composite/compinit.c
@@ -229,6 +229,28 @@ CompositeRegisterAlternateVisuals(ScreenPtr pScreen, VisualID * vids,
     return compRegisterAlternateVisuals(cs, vids, nVisuals);
 }
 
+Bool
+CompositeRegisterImplicitRedirectionException(ScreenPtr pScreen,
+                                              VisualID parentVisual,
+                                              VisualID winVisual)
+{
+    CompScreenPtr cs = GetCompScreen(pScreen);
+    CompImplicitRedirectException *p;
+
+    p = realloc(cs->implicitRedirectExceptions,
+                sizeof(p[0]) * (cs->numImplicitRedirectExceptions + 1));
+    if (p == NULL)
+        return FALSE;
+
+    p[cs->numImplicitRedirectExceptions].parentVisual = parentVisual;
+    p[cs->numImplicitRedirectExceptions].winVisual = winVisual;
+
+    cs->implicitRedirectExceptions = p;
+    cs->numImplicitRedirectExceptions++;
+
+    return TRUE;
+}
+
 typedef struct _alternateVisual {
     int depth;
     CARD32 format;
@@ -349,6 +371,8 @@ compScreenInit(ScreenPtr pScreen)
 
     cs->numAlternateVisuals = 0;
     cs->alternateVisuals = NULL;
+    cs->numImplicitRedirectExceptions = 0;
+    cs->implicitRedirectExceptions = NULL;
 
     if (!compAddAlternateVisuals(pScreen, cs)) {
         free(cs);
diff --git a/composite/compint.h b/composite/compint.h
index 12dc8b3..56b76c5 100644
--- a/composite/compint.h
+++ b/composite/compint.h
@@ -119,6 +119,11 @@ typedef struct _CompOverlayClientRec {
     XID resource;
 } CompOverlayClientRec;
 
+typedef struct _CompImplicitRedirectException {
+    XID parentVisual;
+    XID winVisual;
+} CompImplicitRedirectException;
+
 typedef struct _CompScreen {
     PositionWindowProcPtr PositionWindow;
     CopyWindowProcPtr CopyWindow;
@@ -155,6 +160,8 @@ typedef struct _CompScreen {
     CloseScreenProcPtr CloseScreen;
     int numAlternateVisuals;
     VisualID *alternateVisuals;
+    int numImplicitRedirectExceptions;
+    CompImplicitRedirectException *implicitRedirectExceptions;
 
     WindowPtr pOverlayWin;
     Window overlayWid;
diff --git a/composite/compositeext.h b/composite/compositeext.h
index 0b148f0..b96cb1d 100644
--- a/composite/compositeext.h
+++ b/composite/compositeext.h
@@ -35,6 +35,10 @@ extern _X_EXPORT Bool CompositeRegisterAlternateVisuals(ScreenPtr pScreen,
                                                         VisualID * vids,
                                                         int nVisuals);
 
+extern _X_EXPORT Bool CompositeRegisterImplicitRedirectionException(ScreenPtr pScreen,
+                                                                    VisualID parentVisual,
+                                                                    VisualID winVisual);
+
 extern _X_EXPORT RESTYPE CompositeClientWindowType;
 
 #endif                          /* _COMPOSITEEXT_H_ */
diff --git a/composite/compwindow.c b/composite/compwindow.c
index 6c24349..8824294 100644
--- a/composite/compwindow.c
+++ b/composite/compwindow.c
@@ -336,6 +336,21 @@ compIsAlternateVisual(ScreenPtr pScreen, XID visual)
 }
 
 static Bool
+compIsImplicitRedirectException(ScreenPtr pScreen,
+                                XID parentVisual, XID winVisual)
+{
+    CompScreenPtr cs = GetCompScreen(pScreen);
+    int i;
+
+    for (i = 0; i < cs->numImplicitRedirectExceptions; i++)
+        if (cs->implicitRedirectExceptions[i].parentVisual == parentVisual &&
+            cs->implicitRedirectExceptions[i].winVisual == winVisual)
+            return TRUE;
+
+    return FALSE;
+}
+
+static Bool
 compImplicitRedirect(WindowPtr pWin, WindowPtr pParent)
 {
     if (pParent) {
@@ -343,6 +358,9 @@ compImplicitRedirect(WindowPtr pWin, WindowPtr pParent)
         XID winVisual = wVisual(pWin);
         XID parentVisual = wVisual(pParent);
 
+        if (compIsImplicitRedirectException(pScreen, parentVisual, winVisual))
+            return FALSE;
+
         if (winVisual != parentVisual &&
             (compIsAlternateVisual(pScreen, winVisual) ||
              compIsAlternateVisual(pScreen, parentVisual)))
commit 73698d41e41ce76bef2d9a90b46ac0c24ae148dd
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Mar 31 23:55:25 2014 -0700

    Make XYToWindow a screen function
    
    This allows DDXen to override the window picking to account for
    native windows not seen by the X server.  The bulk of the picking logic
    is exposed as a new helper function, miSpriteTrace().  This function
    completes the sprite trace filled out by the caller, and can be set up
    to start the search from a given toplevel window.
    
    v2: Leave existing XYToWindow API in place for API compatibility
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>

diff --git a/dix/events.c b/dix/events.c
index f05dada..125a0ee 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2835,7 +2835,7 @@ DeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent)
     return deliveries;
 }
 
-static Bool
+Bool
 PointInBorderSize(WindowPtr pWin, int x, int y)
 {
     BoxRec box;
@@ -2876,49 +2876,9 @@ PointInBorderSize(WindowPtr pWin, int x, int y)
 WindowPtr
 XYToWindow(SpritePtr pSprite, int x, int y)
 {
-    WindowPtr pWin;
-    BoxRec box;
+    ScreenPtr pScreen = RootWindow(pSprite)->drawable.pScreen;
 
-    pSprite->spriteTraceGood = 1;       /* root window still there */
-    pWin = RootWindow(pSprite)->firstChild;
-    while (pWin) {
-        if ((pWin->mapped) &&
-            (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
-            (x < pWin->drawable.x + (int) pWin->drawable.width +
-             wBorderWidth(pWin)) &&
-            (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
-            (y < pWin->drawable.y + (int) pWin->drawable.height +
-             wBorderWidth(pWin))
-            /* When a window is shaped, a further check
-             * is made to see if the point is inside
-             * borderSize
-             */
-            && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
-            && (!wInputShape(pWin) ||
-                RegionContainsPoint(wInputShape(pWin),
-                                    x - pWin->drawable.x,
-                                    y - pWin->drawable.y, &box))
-#ifdef ROOTLESS
-            /* In rootless mode windows may be offscreen, even when
-             * they're in X's stack. (E.g. if the native window system
-             * implements some form of virtual desktop system).
-             */
-            && !pWin->rootlessUnhittable
-#endif
-            ) {
-            if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) {
-                pSprite->spriteTraceSize += 10;
-                pSprite->spriteTrace = realloc(pSprite->spriteTrace,
-                                               pSprite->spriteTraceSize *
-                                               sizeof(WindowPtr));
-            }
-            pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
-            pWin = pWin->firstChild;
-        }
-        else
-            pWin = pWin->nextSib;
-    }
-    return DeepestSpriteWin(pSprite);
+    return (*pScreen->XYToWindow)(pScreen, pSprite, x, y);
 }
 
 /**
diff --git a/include/input.h b/include/input.h
index 36463f2..cbf949b 100644
--- a/include/input.h
+++ b/include/input.h
@@ -607,6 +607,7 @@ extern int GetXI2MaskByte(XI2Mask *mask, DeviceIntPtr dev, int event_type);
 void FixUpEventFromWindow(SpritePtr pSprite,
                           xEvent *xE,
                           WindowPtr pWin, Window child, Bool calcChild);
+extern Bool PointInBorderSize(WindowPtr pWin, int x, int y);
 extern WindowPtr XYToWindow(SpritePtr pSprite, int x, int y);
 extern int EventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win);
 extern Bool ActivatePassiveGrab(DeviceIntPtr dev, GrabPtr grab,
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 86da789..5197c79 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -353,6 +353,9 @@ typedef Bool (*StopPixmapTrackingProcPtr)(PixmapPtr, PixmapPtr);
 
 typedef Bool (*ReplaceScanoutPixmapProcPtr)(DrawablePtr, PixmapPtr, Bool);
 
+typedef WindowPtr (*XYToWindowProcPtr)(ScreenPtr pScreen,
+                                       SpritePtr pSprite, int x, int y);
+
 typedef struct _Screen {
     int myNum;                  /* index of this instance in Screens[] */
     ATOM id;
@@ -513,6 +516,7 @@ typedef struct _Screen {
     struct xorg_list offload_head;
 
     ReplaceScanoutPixmapProcPtr ReplaceScanoutPixmap;
+    XYToWindowProcPtr XYToWindow;
 } ScreenRec;
 
 static inline RegionPtr
diff --git a/mi/mi.h b/mi/mi.h
index 950ee38..1209a16 100644
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -507,6 +507,10 @@ extern _X_EXPORT void miMarkUnrealizedWindow(WindowPtr /*pChild */ ,
 extern _X_EXPORT void miSegregateChildren(WindowPtr pWin, RegionPtr pReg,
                                           int depth);
 
+extern _X_EXPORT WindowPtr miSpriteTrace(SpritePtr pSprite, int x, int y);
+
+extern _X_EXPORT WindowPtr miXYToWindow(ScreenPtr pScreen, SpritePtr pSprite, int x, int y);
+
 /* mizerarc.c */
 
 extern _X_EXPORT void miZeroPolyArc(DrawablePtr /*pDraw */ ,
diff --git a/mi/miscrinit.c b/mi/miscrinit.c
index 6aed52f..00c15f7 100644
--- a/mi/miscrinit.c
+++ b/mi/miscrinit.c
@@ -272,6 +272,7 @@ miScreenInit(ScreenPtr pScreen, void *pbits,  /* pointer to screen bits */
     pScreen->ChangeBorderWidth = miChangeBorderWidth;
     pScreen->SetShape = miSetShape;
     pScreen->MarkUnrealizedWindow = miMarkUnrealizedWindow;
+    pScreen->XYToWindow = miXYToWindow;
 
     miSetZeroLineBias(pScreen, DEFAULTZEROLINEBIAS);
 
diff --git a/mi/miwindow.c b/mi/miwindow.c
index 697ffbc..951b8c5 100644
--- a/mi/miwindow.c
+++ b/mi/miwindow.c
@@ -57,6 +57,7 @@ SOFTWARE.
 #include "scrnintstr.h"
 #include "pixmapstr.h"
 #include "mivalidate.h"
+#include "inputstr.h"
 
 void
 miClearToBackground(WindowPtr pWin,
@@ -758,3 +759,68 @@ miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth)
             miSegregateChildren(pChild, pReg, depth);
     }
 }
+
+WindowPtr
+miSpriteTrace(SpritePtr pSprite, int x, int y)
+{
+    WindowPtr pWin;
+    BoxRec box;
+
+    pWin = DeepestSpriteWin(pSprite);
+    while (pWin) {
+        if ((pWin->mapped) &&
+            (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
+            (x < pWin->drawable.x + (int) pWin->drawable.width +
+             wBorderWidth(pWin)) &&
+            (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
+            (y < pWin->drawable.y + (int) pWin->drawable.height +
+             wBorderWidth(pWin))
+            /* When a window is shaped, a further check
+             * is made to see if the point is inside
+             * borderSize
+             */
+            && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
+            && (!wInputShape(pWin) ||
+                RegionContainsPoint(wInputShape(pWin),
+                                    x - pWin->drawable.x,
+                                    y - pWin->drawable.y, &box))
+#ifdef ROOTLESS
+            /* In rootless mode windows may be offscreen, even when
+             * they're in X's stack. (E.g. if the native window system
+             * implements some form of virtual desktop system).
+             */
+            && !pWin->rootlessUnhittable
+#endif
+            ) {
+            if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) {
+                pSprite->spriteTraceSize += 10;
+                pSprite->spriteTrace = realloc(pSprite->spriteTrace,
+                                               pSprite->spriteTraceSize *
+                                               sizeof(WindowPtr));
+            }
+            pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
+            pWin = pWin->firstChild;
+        }
+        else
+            pWin = pWin->nextSib;
+    }
+    return DeepestSpriteWin(pSprite);
+}
+
+/**
+ * Traversed from the root window to the window at the position x/y. While
+ * traversing, it sets up the traversal history in the spriteTrace array.
+ * After completing, the spriteTrace history is set in the following way:
+ *   spriteTrace[0] ... root window
+ *   spriteTrace[1] ... top level window that encloses x/y
+ *       ...
+ *   spriteTrace[spriteTraceGood - 1] ... window at x/y
+ *
+ * @returns the window at the given coordinates.
+ */
+WindowPtr
+miXYToWindow(ScreenPtr pScreen, SpritePtr pSprite, int x, int y)
+{
+    pSprite->spriteTraceGood = 1;       /* root window still there */
+    return miSpriteTrace(pSprite, x, y);
+}


More information about the xorg-commit mailing list