[PATCH 6/6] Xwayland DDX

James Jones jajones at nvidia.com
Fri Mar 28 14:08:30 PDT 2014


Hi Kristian,

This direction seems to conflict with our plans to continue running our 
DDX driver under XWayland.  If we can't run our DDX, we don't have a 
path to support GLX direct rendering under Wayland.  I know we don't 
have anything publicly available for Wayland at the moment, but as I've 
alluded to publicly a few times, we are actively working on support and 
this certainly throws a wrench into things.

Thanks,
-James

On 03/25/2014 02:57 PM, Kristian Høgsberg wrote:
> 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.
>
> 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>
>
> Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
> ---
>   configure.ac                  |  26 ++
>   hw/Makefile.am                |   9 +-
>   hw/xwayland/.gitignore        |   1 +
>   hw/xwayland/Makefile.am       |  30 ++
>   hw/xwayland/xwayland-cursor.c | 198 ++++++++++++
>   hw/xwayland/xwayland-cvt.c    | 304 ++++++++++++++++++
>   hw/xwayland/xwayland-input.c  | 655 +++++++++++++++++++++++++++++++++++++++
>   hw/xwayland/xwayland-output.c | 226 ++++++++++++++
>   hw/xwayland/xwayland-shm.c    | 222 ++++++++++++++
>   hw/xwayland/xwayland.c        | 695 ++++++++++++++++++++++++++++++++++++++++++
>   hw/xwayland/xwayland.h        | 160 ++++++++++
>   11 files changed, 2524 insertions(+), 2 deletions(-)
>   create mode 100644 hw/xwayland/.gitignore
>   create mode 100644 hw/xwayland/Makefile.am
>   create mode 100644 hw/xwayland/xwayland-cursor.c
>   create mode 100644 hw/xwayland/xwayland-cvt.c
>   create mode 100644 hw/xwayland/xwayland-input.c
>   create mode 100644 hw/xwayland/xwayland-output.c
>   create mode 100644 hw/xwayland/xwayland-shm.c
>   create mode 100644 hw/xwayland/xwayland.c
>   create mode 100644 hw/xwayland/xwayland.h
>
> diff --git a/configure.ac b/configure.ac
> index a75ba8f..2c38565 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
> @@ -2433,6 +2435,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], [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
> @@ -2575,6 +2600,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..ab0326b
> --- /dev/null
> +++ b/hw/xwayland/.gitignore
> @@ -0,0 +1 @@
> +Xwayland
> diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am
> new file mode 100644
> index 0000000..18c2d07
> --- /dev/null
> +++ b/hw/xwayland/Makefile.am
> @@ -0,0 +1,30 @@
> +bin_PROGRAMS = Xwayland
> +
> +Xwayland_CFLAGS =                              \
> +       -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) libfbcmap.a $(XWAYLAND_SYS_LIBS) $(XSERVER_SYS_LIBS)
> +Xwayland_DEPENDENCIES = $(XWAYLAND_LIBS)
> +Xwayland_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
> +
> +noinst_LIBRARIES = libfbcmap.a
> +
> +libfbcmap_a_CFLAGS = $(DIX_CFLAGS) $(PIXMAN_CFLAGS) -DHAVE_DIX_CONFIG_H
> +libfbcmap_a_SOURCES = $(top_srcdir)/fb/fbcmap_mi.c
> +
> +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..14b5b3a
> --- /dev/null
> +++ b/hw/xwayland/xwayland-cursor.c
> @@ -0,0 +1,198 @@
> +/*
> + * 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)
> +{
> +    struct xwl_screen *xwl_screen;
> +    struct xwl_shm_buffer *buffer;
> +    int stride;
> +
> +    xwl_screen = xwl_screen_get(screen);
> +
> +    stride = cursor->bits->width * 4;
> +    buffer = xwl_shm_buffer_create(xwl_screen,
> +                                   cursor->bits->width, cursor->bits->height,
> +                                   stride, WL_SHM_FORMAT_ARGB8888);
> +    dixSetPrivate(&cursor->devPrivates, &xwl_cursor_private_key, buffer);
> +
> +    return TRUE;
> +}
> +
> +static Bool
> +xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
> +{
> +    struct xwl_shm_buffer *buffer;
> +
> +    buffer = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key);
> +    xwl_shm_buffer_destroy(buffer);
> +
> +    return TRUE;
> +}
> +
> +void
> +xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
> +{
> +    struct xwl_shm_buffer *buffer;
> +    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;
> +    buffer = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key);
> +    stride = cursor->bits->width * 4;
> +    if (cursor->bits->argb)
> +        memcpy(buffer->data, cursor->bits->argb, cursor->bits->height * stride);
> +    else
> +        expand_source_and_mask(cursor, buffer->data);
> +
> +    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, buffer->buffer, 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..452789f
> --- /dev/null
> +++ b/hw/xwayland/xwayland-input.c
> @@ -0,0 +1,655 @@
> +/*
> + * 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);
> +
> +    /* 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;
> +
> +    xwl_seat->xwl_screen->serial = serial;
> +
> +    xwl_seat->focus_window = NULL;
> +
> +#if 0
> +    /* Park the pointer in our pointer limbo window while it's not in
> +     * any X window. */
> +    if (xwl_seat->xwl_screen->rootless) {
> +        sprite = dev->spriteInfo->sprite;
> +        sprite->spriteTrace[0] = xwl_seat->xwl_screen->pointer_limbo_window;
> +        sprite->spriteTrace[0] = xwl_seat->xwl_screen->screen->root;
> +        CheckMotion(NULL, GetMaster(dev, MASTER_POINTER));
> +    }
> +#endif
> +}
> +
> +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->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);
> +    }
> +
> +    if (caps & WL_SEAT_CAPABILITY_KEYBOARD) {
> +        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);
> +    }
> +
> +    xwl_seat->xwl_screen->expecting_event--;
> +    /* FIXME: Touch ... */
> +}
> +
> +static const struct wl_seat_listener seat_listener = {
> +    seat_handle_capabilities,
> +};
> +
> +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, 1);
> +    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) {
> +        create_input_device(xwl_screen, id);
> +        xwl_screen->expecting_event++;
> +    }
> +}
> +
> +static void
> +global_remove(void *data, struct wl_registry *registry, uint32_t name)
> +{
> +    /* FIXME */
> +}
> +
> +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(DeviceIntPtr master, SpritePtr sprite, int x, int y)
> +{
> +    struct xwl_seat *xwl_seat = NULL;
> +    DeviceIntPtr device;
> +
> +    for (device = inputInfo.devices; device; device = device->next)
> +        if (GetMaster(device, MASTER_ATTACHED) == master) {
> +            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;
> +    }
> +    else {
> +        sprite->spriteTraceGood = 1;
> +    }
> +
> +    return miSpriteTrace(sprite, x, y);
> +}
> +
> +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..516dcd0
> --- /dev/null
> +++ b/hw/xwayland/xwayland-shm.c
> @@ -0,0 +1,222 @@
> +/*
> + * 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 shm_pool {
> +    struct wl_shm_pool *pool;
> +    int fd;
> +    unsigned int size;
> +    unsigned int used;
> +    char *data;
> +};
> +
> +#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 struct shm_pool *
> +shm_pool_create(struct wl_shm *shm, int size)
> +{
> +    struct shm_pool *pool;
> +
> +    pool = malloc(sizeof *pool);
> +    if (!pool)
> +        return NULL;
> +
> +    pool->fd = os_create_anonymous_file(size);
> +    if (pool->fd < 0)
> +        goto err_free;
> +
> +    pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
> +                      pool->fd, 0);
> +
> +    if (pool->data == MAP_FAILED)
> +        goto err_close;
> +
> +    pool->pool = wl_shm_create_pool(shm, pool->fd, size);
> +    pool->size = size;
> +    pool->used = 0;
> +
> +    return pool;
> +
> + err_close:
> +    close(pool->fd);
> + err_free:
> +    free(pool);
> +    return NULL;
> +}
> +
> +static void
> +shm_pool_destroy(struct shm_pool *pool)
> +{
> +    munmap(pool->data, pool->size);
> +    wl_shm_pool_destroy(pool->pool);
> +    close(pool->fd);
> +    free(pool);
> +}
> +
> +struct xwl_shm_buffer *
> +xwl_shm_buffer_create(struct xwl_screen *xwl_screen,
> +                      int width, int height, int stride, uint32_t format)
> +{
> +    struct xwl_shm_buffer *buffer;
> +
> +    buffer = malloc(sizeof *buffer);
> +    if (buffer == NULL)
> +        return NULL;
> +
> +    buffer->pool = shm_pool_create(xwl_screen->shm, stride * height);
> +    buffer->buffer = wl_shm_pool_create_buffer(buffer->pool->pool, 0,
> +                                               width, height, stride, format);
> +    buffer->data = buffer->pool->data;
> +
> +    return buffer;
> +}
> +
> +void
> +xwl_shm_buffer_destroy(struct xwl_shm_buffer *buffer)
> +{
> +    wl_buffer_destroy(buffer->buffer);
> +    shm_pool_destroy(buffer->pool);
> +    free(buffer);
> +}
> diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
> new file mode 100644
> index 0000000..35b6bf3
> --- /dev/null
> +++ b/hw/xwayland/xwayland.c
> @@ -0,0 +1,695 @@
> +/*
> + * 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 <selection.h>
> +#include <micmap.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;
> +    }
> +
> +    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;
> +    xwl_shm_buffer_destroy(xwl_screen->root_buffer);
> +    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
> +};
> +
> +static uint32_t
> +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
> +    }
> +}
> +
> +static PixmapPtr
> +xwl_create_pixmap(ScreenPtr screen,
> +                  int width, int height, int depth, unsigned int hint)
> +{
> +    PixmapPtr pixmap;
> +    struct xwl_screen *xwl_screen;
> +    struct xwl_shm_buffer *buffer;
> +    int stride, bpp;
> +    uint32_t format;
> +
> +    xwl_screen = xwl_screen_get(screen);
> +
> +    if (hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP && width > 0) {
> +        screen->CreatePixmap = xwl_screen->CreatePixmap;
> +        pixmap = (*screen->CreatePixmap) (screen, 0, 0, depth, hint);
> +        xwl_screen->CreatePixmap = screen->CreatePixmap;
> +        screen->CreatePixmap = xwl_create_pixmap;
> +
> +        if (!pixmap)
> +            return NullPixmap;
> +
> +        stride = PixmapBytePad(width, depth);
> +        format = format_for_depth(depth);
> +        bpp = BitsPerPixel(depth);
> +        buffer = xwl_shm_buffer_create(xwl_screen,
> +                                       width, height, stride, format);
> +        if (!(*screen->ModifyPixmapHeader) (pixmap, width, height, depth,
> +                                            bpp, stride, buffer->data))
> +            return NullPixmap;
> +
> +        dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key, buffer);
> +
> +        return pixmap;
> +    }
> +
> +    screen->CreatePixmap = xwl_screen->CreatePixmap;
> +    pixmap = (*screen->CreatePixmap) (screen, width, height, depth, hint);
> +    xwl_screen->CreatePixmap = screen->CreatePixmap;
> +    screen->CreatePixmap = xwl_create_pixmap;
> +
> +    return pixmap;
> +}
> +
> +static Bool
> +xwl_destroy_pixmap(PixmapPtr pixmap)
> +{
> +    ScreenPtr screen = pixmap->drawable.pScreen;
> +    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
> +    struct xwl_shm_buffer *buffer =
> +        dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key);
> +    Bool ret;
> +
> +    if (buffer && pixmap->refcnt == 1)
> +        xwl_shm_buffer_destroy(buffer);
> +
> +    screen->DestroyPixmap = xwl_screen->DestroyPixmap;
> +    ret = (*screen->DestroyPixmap) (pixmap);
> +    xwl_screen->DestroyPixmap = screen->DestroyPixmap;
> +    screen->DestroyPixmap = xwl_destroy_pixmap;
> +
> +    return ret;
> +}
> +
> +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)
> +        RegionNull(&window->clipList);
> +
> +    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 struct wl_buffer *
> +xwl_window_get_buffer(struct xwl_window *xwl_window)
> +{
> +    struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
> +    struct xwl_shm_buffer *buffer;
> +    PixmapPtr pixmap;
> +
> +    if (xwl_window->window->parent == NULL) {
> +        return xwl_screen->root_buffer->buffer;
> +    }
> +    else {
> +        pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window);
> +        buffer = dixGetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key);
> +        if (buffer)
> +            return buffer->buffer;
> +    }
> +
> +    return NULL;
> +}
> +
> +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;
> +
> +    xorg_list_for_each_entry(xwl_window, &xwl_screen->damage_window_list,
> +                             link_damage) {
> +        region = DamageRegion(xwl_window->damage);
> +        count = RegionNumRects(region);
> +        buffer = xwl_window_get_buffer(xwl_window);
> +        if (!buffer)
> +            continue;
> +
> +        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_dispatch(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);
> +
> +    ret = wl_display_dispatch_pending(xwl_screen->display);
> +    if (ret == -1)
> +        FatalError("failed to dispatch Wayland events: %s\n", strerror(errno));
> +
> +    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
> +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;
> +    int i;
> +
> +    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;
> +    for (i = 0; i < xwl_screen->listen_fd_count; i++)
> +        ListenOnOpenFD(xwl_screen->listen_fds[i], TRUE);
> +
> +    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, stride, i;
> +    uint32_t format;
> +    void *data = NULL;
> +
> +    xwl_screen = calloc(sizeof *xwl_screen, 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)
> +        AddCallback(&SelectionCallback, wm_selection_callback, 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);
> +
> +    stride = PixmapBytePad(xwl_screen->width, xwl_screen->depth);
> +    format = format_for_depth(xwl_screen->depth);
> +    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();
> +
> +    if (!xwl_screen->rootless) {
> +        xwl_screen->root_buffer =
> +            xwl_shm_buffer_create(xwl_screen,
> +                                  xwl_screen->width, xwl_screen->height,
> +                                  stride, format);
> +        if (xwl_screen->root_buffer == NULL)
> +            return FALSE;
> +        data = xwl_screen->root_buffer->data;
> +    }
> +
> +    ret = fbScreenInit(pScreen, data,
> +                       xwl_screen->width, xwl_screen->height,
> +                       96, 96, xwl_screen->width,
> +                       BitsPerPixel(xwl_screen->depth));
> +    if (!ret)
> +        return FALSE;
> +
> +    fbPictureInit(pScreen, 0, 0);
> +
> +    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->CreatePixmap = pScreen->CreatePixmap;
> +    pScreen->CreatePixmap = xwl_create_pixmap;
> +
> +    xwl_screen->DestroyPixmap = pScreen->DestroyPixmap;
> +    pScreen->DestroyPixmap = xwl_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;
> +}
> +
> +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);
> +
> +    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..cbfd6ea
> --- /dev/null
> +++ b/hw/xwayland/xwayland.h
> @@ -0,0 +1,160 @@
> +/*
> + * 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;
> +
> +    struct xwl_shm_buffer *root_buffer;
> +
> +    int wm_fd;
> +    int listen_fds[5];
> +    int listen_fd_count;
> +    int rootless;
> +
> +    CreatePixmapProcPtr CreatePixmap;
> +    DestroyPixmapProcPtr DestroyPixmap;
> +    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;
> +};
> +
> +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_shm_buffer {
> +    struct shm_pool *pool;
> +    struct wl_buffer *buffer;
> +    void *data;
> +};
> +
> +struct xwl_shm_buffer *xwl_shm_buffer_create(struct xwl_screen *xwl_screen,
> +                                             int width, int height, int stride,
> +                                             uint32_t format);
> +
> +void xwl_shm_buffer_destroy(struct xwl_shm_buffer *buffer);
> +
> +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);
> +
> +#endif
> --
> 1.9.0
>
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel
>


More information about the xorg-devel mailing list