summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2009-09-18 22:08:16 -0400
committerKristian Høgsberg <krh@bitplanet.net>2014-03-07 16:56:59 -0800
commit0c14bdb995f5aa9559ca7bf6a03e6ba52854cff1 (patch)
treebbfd693cb84f6d59f2a233a80b924ea14887c792
parent945ca467d64d4785b5fb2d2cd01dd645d8716f3c (diff)
Add xwayland modulexwayland
Squashed and rebased from the xwayland-1.12 branch. Contributions from Christopher James Halse Rogers <christopher.halse.rogers@canonical.com> Corentin Chary <corentin.chary@gmail.com> Daniel Stone <daniel@fooishbar.org> Kristian Høgsberg <krh@bitplanet.net> Robert Bragg <robert@linux.intel.com> Scott Moreau <oreaus@gmail.com> Tiago Vignatti <tiago.vignatti@intel.com> Giovanni Campagna <gcampagn@redhat.com> Jonas Ådahl <jadahl@gmail.com> Ray Strode <rstrode@redhat.com> Trevor McCort <tjmccort@gmail.com> Rui Matos <tiagomatos@gmail.com>
-rw-r--r--configure.ac15
-rw-r--r--hw/xfree86/Makefile.am9
-rw-r--r--hw/xfree86/common/xf86AutoConfig.c12
-rw-r--r--hw/xfree86/common/xf86Config.c44
-rw-r--r--hw/xfree86/common/xf86Globals.c2
-rw-r--r--hw/xfree86/common/xf86Init.c32
-rw-r--r--hw/xfree86/common/xf86Priv.h2
-rw-r--r--hw/xfree86/common/xf86str.h1
-rw-r--r--hw/xfree86/dri2/dri2.c7
-rw-r--r--hw/xfree86/dri2/dri2.h2
-rw-r--r--hw/xfree86/xwayland/.gitignore4
-rw-r--r--hw/xfree86/xwayland/Makefile.am46
-rw-r--r--hw/xfree86/xwayland/drm.xml139
-rw-r--r--hw/xfree86/xwayland/xserver.xml18
-rw-r--r--hw/xfree86/xwayland/xwayland-cursor.c250
-rw-r--r--hw/xfree86/xwayland/xwayland-drm.c250
-rw-r--r--hw/xfree86/xwayland/xwayland-input.c647
-rw-r--r--hw/xfree86/xwayland/xwayland-output.c438
-rw-r--r--hw/xfree86/xwayland/xwayland-private.h142
-rw-r--r--hw/xfree86/xwayland/xwayland-window.c261
-rw-r--r--hw/xfree86/xwayland/xwayland.c393
-rw-r--r--hw/xfree86/xwayland/xwayland.h86
-rw-r--r--include/input.h2
-rw-r--r--include/os.h3
-rw-r--r--include/xorg-config.h.in3
-rw-r--r--include/xorg-server.h.in3
-rw-r--r--os/connection.c4
27 files changed, 2793 insertions, 22 deletions
diff --git a/configure.ac b/configure.ac
index 74819bf62..6d412f74a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -626,6 +626,7 @@ AC_ARG_ENABLE(clientids, AS_HELP_STRING([--disable-clientids], [Build Xorg
AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=yes])
AC_ARG_ENABLE(linux_acpi, AS_HELP_STRING([--disable-linux-acpi], [Disable building ACPI support on Linux (if available).]), [enable_linux_acpi=$enableval], [enable_linux_acpi=yes])
AC_ARG_ENABLE(linux_apm, AS_HELP_STRING([--disable-linux-apm], [Disable building APM support on Linux (if available).]), [enable_linux_apm=$enableval], [enable_linux_apm=yes])
+AC_ARG_ENABLE(wayland, AS_HELP_STRING([--disable-wayland], [Build Wayland extension (default: auto)]), [WAYLAND=$enableval], [WAYLAND=auto])
dnl DDXes.
AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto])
@@ -1019,6 +1020,18 @@ fi
if test "x$MITSHM" = xauto; then
MITSHM="$ac_cv_sysv_ipc"
fi
+
+WAYLAND_MODULES="wayland-client libdrm"
+if test "x$WAYLAND" = xauto; then
+ PKG_CHECK_MODULES(XWAYLAND, $WAYLAND_MODULES, [WAYLAND=yes], [WAYLAND=no])
+fi
+if test "x$WAYLAND" = xyes; then
+ PKG_CHECK_MODULES(XWAYLAND, $WAYLAND_MODULES)
+ AC_DEFINE(XORG_WAYLAND, 1, [Support wayland mode])
+ WAYLAND_SCANNER_RULES(['$(top_srcdir)/hw/xfree86/xwayland'])
+fi
+AM_CONDITIONAL(WAYLAND, [test "x$WAYLAND" = xyes])
+
AM_CONDITIONAL(MITSHM, [test "x$MITSHM" = xyes])
if test "x$MITSHM" = xyes; then
AC_DEFINE(MITSHM, 1, [Support MIT-SHM extension])
@@ -1248,6 +1261,7 @@ if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$DRI3" = xyes || test "
PKG_CHECK_MODULES([LIBDRM], $LIBDRM)
fi
fi
+AM_CONDITIONAL(DRM, test "x$DRM" = xyes)
if test "x$DRI2" = xyes; then
save_CFLAGS=$CFLAGS
@@ -2485,6 +2499,7 @@ hw/xfree86/dixmods/Makefile
hw/xfree86/doc/Makefile
hw/xfree86/dri/Makefile
hw/xfree86/dri2/Makefile
+hw/xfree86/xwayland/Makefile
hw/xfree86/exa/Makefile
hw/xfree86/exa/man/Makefile
hw/xfree86/fbdevhw/Makefile
diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am
index 73e1b4c1f..9c82ffd70 100644
--- a/hw/xfree86/Makefile.am
+++ b/hw/xfree86/Makefile.am
@@ -14,10 +14,15 @@ DRI3_BUILDDIR = $(top_builddir)/dri3
DRI3_LIB = $(DRI3_BUILDDIR)/libdri3.la
endif
+
if GLAMOR_EGL
GLAMOR_EGL_SUBDIR = glamor_egl
endif
+if WAYLAND
+WAYLAND_SUBDIR = xwayland
+endif
+
if XF86UTILS
XF86UTILS_SUBDIR = utils
endif
@@ -36,13 +41,13 @@ endif
SUBDIRS = common ddc x86emu $(INT10_SUBDIR) os-support parser \
ramdac $(VGAHW_SUBDIR) loader modes $(DRI_SUBDIR) \
- $(DRI2_SUBDIR) . $(VBE_SUBDIR) i2c dixmods \
+ $(DRI2_SUBDIR) $(WAYLAND_SUBDIR) . $(VBE_SUBDIR) i2c dixmods \
fbdevhw shadowfb exa $(XF86UTILS_SUBDIR) doc man \
$(GLAMOR_EGL_SUBDIR)
DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw os-support \
parser ramdac shadowfb vbe vgahw \
- loader dixmods dri dri2 exa modes \
+ loader dixmods dri dri2 exa modes xwayland \
utils doc man
bin_PROGRAMS = Xorg
diff --git a/hw/xfree86/common/xf86AutoConfig.c b/hw/xfree86/common/xf86AutoConfig.c
index 4eb86de22..47ef68462 100644
--- a/hw/xfree86/common/xf86AutoConfig.c
+++ b/hw/xfree86/common/xf86AutoConfig.c
@@ -274,11 +274,17 @@ listPossibleVideoDrivers(char *matches[], int nmatches)
#if !defined(sun)
/* Fallback to platform default frame buffer driver */
- if (i < (nmatches - 1)) {
+ if (i < (nmatches - 2)) {
+#ifdef XORG_WAYLAND
+ if (xorgWayland) {
+ matches[i++] = xnfstrdup("wlglamor");
+ matches[i++] = xnfstrdup("wayland");
+ } else
+#endif
#if !defined(__linux__) && defined(__sparc__)
- matches[i++] = xnfstrdup("wsfb");
+ matches[i++] = xnfstrdup("wsfb");
#else
- matches[i++] = xnfstrdup("fbdev");
+ matches[i++] = xnfstrdup("fbdev");
#endif
}
#endif /* !sun */
diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index 542d5abf6..7eb8b1b37 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -118,7 +118,8 @@ static ModuleDefault ModuleDefaults[] = {
{.name = "fb",.toLoad = TRUE,.load_opt = NULL},
{.name = "shadow",.toLoad = TRUE,.load_opt = NULL},
#endif
- {.name = NULL,.toLoad = FALSE,.load_opt = NULL}
+ {.name = "xwayland",.toLoad = FALSE,.load_opt=NULL},
+ {.name = NULL,.toLoad = FALSE,.load_opt=NULL}
};
/* Forward declarations */
@@ -260,6 +261,17 @@ xf86ModulelistFromConfig(void ***optlist)
return NULL;
}
+ /*
+ * Set the xwayland module to autoload if requested.
+ */
+ if (xorgWayland) {
+ for (i=0 ; ModuleDefaults[i].name != NULL ; i++) {
+ if (strcmp(ModuleDefaults[i].name, "xwayland") == 0) {
+ ModuleDefaults[i].toLoad = TRUE;
+ }
+ }
+ }
+
if (xf86configptr->conf_modules) {
/* Walk the disable list and let people know what we've parsed to
* not be loaded
@@ -507,9 +519,13 @@ xf86InputDriverlistFromConfig(void)
static void
fixup_video_driver_list(const char **drivers)
{
- static const char *fallback[4] = { "fbdev", "vesa", "wsfb", NULL };
+ static const char *fallback_hw[4] = { "fbdev", "vesa", "wsfb", NULL };
const char **end, **drv;
const char *x;
+#ifdef XORG_WAYLAND
+ static const char *fallback_wl[2] = { "wayland", NULL };
+#endif
+ static const char **fallbacks;
int i;
/* walk to the end of the list */
@@ -520,9 +536,15 @@ fixup_video_driver_list(const char **drivers)
* for each of the fallback drivers, if we find it in the list,
* swap it with the last available non-fallback driver.
*/
- for (i = 0; fallback[i]; i++) {
+#ifdef XORG_WAYLAND
+ if (xorgWayland)
+ fallbacks = fallback_wl;
+ else
+#endif
+ fallbacks = fallback_hw;
+ for (i = 0; fallbacks[i]; i++) {
for (drv = drivers; drv != end; drv++) {
- if (strstr(*drv, fallback[i])) {
+ if (strstr(*drv, fallbacks[i])) {
x = *drv;
*drv = *end;
*end = x;
@@ -859,6 +881,13 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts)
}
xf86Msg(from, "%sutomatically adding GPU devices\n",
xf86Info.autoAddGPU ? "A" : "Not a");
+
+ /* FIXME: Do that at the right place (before xf86Msg). */
+ if (xorgWayland) {
+ xf86Info.autoAddDevices = FALSE;
+ xf86Info.autoEnableDevices = FALSE;
+ }
+
/*
* Set things up based on the config file information. Some of these
* settings may be overridden later when the command line options are
@@ -949,9 +978,10 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts)
}
#endif
- /* if we're not hotplugging, force some input devices to exist */
- xf86Info.forceInputDevices = !(xf86Info.autoAddDevices &&
- xf86Info.autoEnableDevices);
+ if (xorgWayland) /* Don't force input devices */
+ xf86Info.forceInputDevices = FALSE;
+ else /* if we're not hotplugging, force some input devices to exist */
+ xf86Info.forceInputDevices = !(xf86Info.autoAddDevices && xf86Info.autoEnableDevices);
/* when forcing input devices, we use kbd. otherwise evdev, so use the
* evdev rules set. */
diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c
index 7df7a80c4..b41d2cc86 100644
--- a/hw/xfree86/common/xf86Globals.c
+++ b/hw/xfree86/common/xf86Globals.c
@@ -204,3 +204,5 @@ Bool xf86VidModeAllowNonLocal = FALSE;
#endif
RootWinPropPtr *xf86RegisteredPropertiesTable = NULL;
Bool xorgHWAccess = FALSE;
+Bool xorgWayland = FALSE;
+Bool xorgRootless = FALSE;
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index ff4d38f28..919d35f0a 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -550,6 +550,25 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
/* Non-seat0 X servers should not open console */
if (!(flags & HW_SKIP_CONSOLE) && !ServerIsNotSeat0())
xorgHWOpenConsole = TRUE;
+
+ if (xorgWayland) {
+ if (flags != HW_WAYLAND) {
+ xf86DeleteDriver(i);
+ continue;
+ }
+
+ want_hw_access = FALSE;
+ xorgHWOpenConsole = FALSE;
+ }
+ }
+
+ for (i = 0; i < xf86NumDrivers; i++) {
+ if (xf86DriverList[i] == NULL) {
+ for (j = i; j < xf86NumDrivers; j++) {
+ xf86DriverList[j] = xf86DriverList[j + 1];
+ }
+ xf86NumDrivers--;
+ }
}
if (xorgHWOpenConsole)
@@ -963,6 +982,9 @@ InitInput(int argc, char **argv)
mieqInit();
+ if (xorgWayland)
+ return;
+
/* Initialize all configured input devices */
for (pInfo = xf86ConfigLayout.inputs; pInfo && *pInfo; pInfo++) {
(*pInfo)->options =
@@ -1463,6 +1485,16 @@ ddxProcessArgument(int argc, char **argv, int i)
return 1;
}
+ if (!strcmp(argv[i], "-wayland")) {
+ xorgWayland = TRUE;
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-rootless")) {
+ xorgRootless = TRUE;
+ return 1;
+ }
+
/* OS-specific processing */
return xf86ProcessArgument(argc, argv, i);
}
diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
index 6e374eb7e..f84376575 100644
--- a/hw/xfree86/common/xf86Priv.h
+++ b/hw/xfree86/common/xf86Priv.h
@@ -91,6 +91,8 @@ extern _X_EXPORT int xf86NumScreens;
extern _X_EXPORT const char *xf86VisualNames[];
extern _X_EXPORT int xf86Verbose; /* verbosity level */
extern _X_EXPORT int xf86LogVerbose; /* log file verbosity level */
+extern _X_EXPORT Bool xorgWayland;
+extern _X_EXPORT Bool xorgRootless;
extern _X_EXPORT RootWinPropPtr *xf86RegisteredPropertiesTable;
diff --git a/hw/xfree86/common/xf86str.h b/hw/xfree86/common/xf86str.h
index b164b7f21..676f9d89b 100644
--- a/hw/xfree86/common/xf86str.h
+++ b/hw/xfree86/common/xf86str.h
@@ -288,6 +288,7 @@ typedef struct {
#define HW_MMIO 2
#define HW_SKIP_CONSOLE 4
#define NEED_IO_ENABLED(x) (x & HW_IO)
+#define HW_WAYLAND 8
typedef CARD32 xorgHWFlags;
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index c70f72ee8..3d4013809 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -1332,13 +1332,16 @@ DRI2Connect(ClientPtr client, ScreenPtr pScreen,
}
static int
-DRI2AuthMagic (ScreenPtr pScreen, uint32_t magic)
+DRI2AuthMagic (ClientPtr client, ScreenPtr pScreen, uint32_t magic)
{
DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
if (ds == NULL)
return -EINVAL;
- return (*ds->LegacyAuthMagic) (ds->fd, magic);
+ if (ds->LegacyAuthMagic2)
+ return (*ds->LegacyAuthMagic2) (pScreen, magic);
+ else
+ return (*ds->LegacyAuthMagic) (ds->fd, magic);
}
Bool
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index 38b4f588d..ed67d0148 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -207,7 +207,7 @@ typedef int (*DRI2GetParamProcPtr) (ClientPtr client,
/**
* Version of the DRI2InfoRec structure defined in this header
*/
-#define DRI2INFOREC_VERSION 9
+#define DRI2INFOREC_VERSION 10
typedef struct {
unsigned int version; /**< Version of this struct */
diff --git a/hw/xfree86/xwayland/.gitignore b/hw/xfree86/xwayland/.gitignore
new file mode 100644
index 000000000..abedfee1b
--- /dev/null
+++ b/hw/xfree86/xwayland/.gitignore
@@ -0,0 +1,4 @@
+drm-client-protocol.h
+drm-protocol.c
+xserver-client-protocol.h
+xserver-protocol.c
diff --git a/hw/xfree86/xwayland/Makefile.am b/hw/xfree86/xwayland/Makefile.am
new file mode 100644
index 000000000..22ab154af
--- /dev/null
+++ b/hw/xfree86/xwayland/Makefile.am
@@ -0,0 +1,46 @@
+AM_CPPFLAGS = \
+ $(XORG_INCS) \
+ -I$(srcdir)/../ddc \
+ -I$(srcdir)/../ramdac \
+ -I$(srcdir)/../i2c \
+ -I$(srcdir)/../parser \
+ -I$(srcdir)/../modes
+
+libxwayland_la_LTLIBRARIES = libxwayland.la
+AM_CFLAGS = \
+ -DHAVE_XORG_CONFIG_H \
+ @DIX_CFLAGS@ @XORG_CFLAGS@ @XWAYLAND_CFLAGS@ \
+ -I$(top_srcdir)/hw/xfree86/common \
+ -I$(top_srcdir)/hw/xfree86/os-support/bus
+
+libxwayland_la_LDFLAGS = -module -avoid-version @XWAYLAND_LIBS@
+libxwayland_ladir = $(moduledir)/extensions
+libxwayland_la_SOURCES = \
+ xwayland.c \
+ xwayland-input.c \
+ xwayland-output.c \
+ xwayland-cursor.c \
+ xwayland-window.c \
+ xwayland-private.h \
+ drm-client-protocol.h \
+ drm-protocol.c \
+ xserver-client-protocol.h \
+ xserver-protocol.c
+
+if DRM
+AM_CFLAGS += @LIBDRM_CFLAGS@
+libxwayland_la_LDFLAGS += @LIBDRM_LIBS@
+libxwayland_la_SOURCES += xwayland-drm.c
+endif
+
+sdk_HEADERS = xwayland.h
+
+BUILT_SOURCES = \
+ drm-client-protocol.h \
+ drm-protocol.c \
+ xserver-client-protocol.h \
+ xserver-protocol.c
+
+CLEANFILES = $(BUILT_SOURCES)
+
+@wayland_scanner_rules@
diff --git a/hw/xfree86/xwayland/drm.xml b/hw/xfree86/xwayland/drm.xml
new file mode 100644
index 000000000..89fd8f088
--- /dev/null
+++ b/hw/xfree86/xwayland/drm.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="drm">
+
+ <copyright>
+ Copyright © 2008-2011 Kristian Høgsberg
+ Copyright © 2010-2011 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\n 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.
+ </copyright>
+
+ <!-- drm support. This object is created by the server and published
+ using the display's global event. -->
+ <interface name="wl_drm" version="1">
+ <enum name="error">
+ <entry name="authenticate_fail" value="0"/>
+ <entry name="invalid_format" value="1"/>
+ <entry name="invalid_name" value="2"/>
+ </enum>
+
+ <enum name="format">
+ <!-- The drm format codes match the #defines in drm_fourcc.h.
+ The formats actually supported by the compositor will be
+ reported by the format event. -->
+ <entry name="c8" value="0x20203843"/>
+ <entry name="rgb332" value="0x38424752"/>
+ <entry name="bgr233" value="0x38524742"/>
+ <entry name="xrgb4444" value="0x32315258"/>
+ <entry name="xbgr4444" value="0x32314258"/>
+ <entry name="rgbx4444" value="0x32315852"/>
+ <entry name="bgrx4444" value="0x32315842"/>
+ <entry name="argb4444" value="0x32315241"/>
+ <entry name="abgr4444" value="0x32314241"/>
+ <entry name="rgba4444" value="0x32314152"/>
+ <entry name="bgra4444" value="0x32314142"/>
+ <entry name="xrgb1555" value="0x35315258"/>
+ <entry name="xbgr1555" value="0x35314258"/>
+ <entry name="rgbx5551" value="0x35315852"/>
+ <entry name="bgrx5551" value="0x35315842"/>
+ <entry name="argb1555" value="0x35315241"/>
+ <entry name="abgr1555" value="0x35314241"/>
+ <entry name="rgba5551" value="0x35314152"/>
+ <entry name="bgra5551" value="0x35314142"/>
+ <entry name="rgb565" value="0x36314752"/>
+ <entry name="bgr565" value="0x36314742"/>
+ <entry name="rgb888" value="0x34324752"/>
+ <entry name="bgr888" value="0x34324742"/>
+ <entry name="xrgb8888" value="0x34325258"/>
+ <entry name="xbgr8888" value="0x34324258"/>
+ <entry name="rgbx8888" value="0x34325852"/>
+ <entry name="bgrx8888" value="0x34325842"/>
+ <entry name="argb8888" value="0x34325241"/>
+ <entry name="abgr8888" value="0x34324241"/>
+ <entry name="rgba8888" value="0x34324152"/>
+ <entry name="bgra8888" value="0x34324142"/>
+ <entry name="xrgb2101010" value="0x30335258"/>
+ <entry name="xbgr2101010" value="0x30334258"/>
+ <entry name="rgbx1010102" value="0x30335852"/>
+ <entry name="bgrx1010102" value="0x30335842"/>
+ <entry name="argb2101010" value="0x30335241"/>
+ <entry name="abgr2101010" value="0x30334241"/>
+ <entry name="rgba1010102" value="0x30334152"/>
+ <entry name="bgra1010102" value="0x30334142"/>
+ <entry name="yuyv" value="0x56595559"/>
+ <entry name="yvyu" value="0x55595659"/>
+ <entry name="uyvy" value="0x59565955"/>
+ <entry name="vyuy" value="0x59555956"/>
+ <entry name="ayuv" value="0x56555941"/>
+ <entry name="nv12" value="0x3231564e"/>
+ <entry name="nv21" value="0x3132564e"/>
+ <entry name="nv16" value="0x3631564e"/>
+ <entry name="nv61" value="0x3136564e"/>
+ <entry name="yuv410" value="0x39565559"/>
+ <entry name="yvu410" value="0x39555659"/>
+ <entry name="yuv411" value="0x31315559"/>
+ <entry name="yvu411" value="0x31315659"/>
+ <entry name="yuv420" value="0x32315559"/>
+ <entry name="yvu420" value="0x32315659"/>
+ <entry name="yuv422" value="0x36315559"/>
+ <entry name="yvu422" value="0x36315659"/>
+ <entry name="yuv444" value="0x34325559"/>
+ <entry name="yvu444" value="0x34325659"/>
+ </enum>
+
+ <!-- Call this request with the magic received from drmGetMagic().
+ It will be passed on to the drmAuthMagic() or
+ DRIAuthConnection() call. This authentication must be
+ completed before create_buffer could be used. -->
+ <request name="authenticate">
+ <arg name="id" type="uint"/>
+ </request>
+
+ <!-- Create a wayland buffer for the named DRM buffer. The DRM
+ surface must have a name using the flink ioctl -->
+ <request name="create_buffer">
+ <arg name="id" type="new_id" interface="wl_buffer"/>
+ <arg name="name" type="uint"/>
+ <arg name="width" type="int"/>
+ <arg name="height" type="int"/>
+ <arg name="stride" type="uint"/>
+ <arg name="format" type="uint"/>
+ </request>
+
+ <!-- Notification of the path of the drm device which is used by
+ the server. The client should use this device for creating
+ local buffers. Only buffers created from this device should
+ be be passed to the server using this drm object's
+ create_buffer request. -->
+ <event name="device">
+ <arg name="name" type="string"/>
+ </event>
+
+ <event name="format">
+ <arg name="format" type="uint"/>
+ </event>
+
+ <!-- Raised if the authenticate request succeeded -->
+ <event name="authenticated"/>
+ </interface>
+
+</protocol>
diff --git a/hw/xfree86/xwayland/xserver.xml b/hw/xfree86/xwayland/xserver.xml
new file mode 100644
index 000000000..9e25f5c0d
--- /dev/null
+++ b/hw/xfree86/xwayland/xserver.xml
@@ -0,0 +1,18 @@
+<protocol name="xserver">
+
+ <interface name="xserver" version="1">
+ <request name="set_window_id">
+ <arg name="surface" type="object" interface="wl_surface"/>
+ <arg name="id" type="uint"/>
+ </request>
+
+ <event name="client">
+ <arg name="fd" type="fd"/>
+ </event>
+
+ <event name="listen_socket">
+ <arg name="fd" type="fd"/>
+ </event>
+ </interface>
+
+</protocol>
diff --git a/hw/xfree86/xwayland/xwayland-cursor.c b/hw/xfree86/xwayland/xwayland-cursor.c
new file mode 100644
index 000000000..2b3cb5e63
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland-cursor.c
@@ -0,0 +1,250 @@
+/*
+ * 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include "xorg-config.h"
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <wayland-client.h>
+
+#include <cursorstr.h>
+#include <xf86Crtc.h>
+#include <mipointrst.h>
+
+#include "xwayland.h"
+#include "xwayland-private.h"
+#include "xserver-client-protocol.h"
+
+static void
+expand_source_and_mask(CursorPtr cursor, void *data)
+{
+ CARD32 *argb, *p, d, fg, bg;
+ CursorBitsPtr bits = cursor->bits;
+ int size;
+ int x, y, stride, i, bit;
+
+ size = bits->width * bits->height * 4;
+ argb = malloc(size);
+ if (argb == NULL)
+ return;
+
+ p = argb;
+ 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;
+ }
+
+ memcpy(data, argb, size);
+ free(argb);
+}
+
+static Bool
+xwl_realize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
+{
+ struct xwl_screen *xwl_screen;
+ int size;
+ char filename[] = "/tmp/wayland-shm-XXXXXX";
+ int fd;
+ struct wl_shm_pool *pool;
+ struct wl_buffer *buffer;
+ void *data;
+
+ xwl_screen = xwl_screen_get(screen);
+ size = cursor->bits->width * cursor->bits->height * 4;
+
+ fd = mkstemp(filename);
+ if (fd < 0) {
+ ErrorF("open %s failed: %s", filename, strerror(errno));
+ return FALSE;
+ }
+ if (ftruncate(fd, size) < 0) {
+ ErrorF("ftruncate failed: %s", strerror(errno));
+ close(fd);
+ return FALSE;
+ }
+
+ data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ unlink(filename);
+
+ if (data == MAP_FAILED) {
+ ErrorF("mmap failed: %s", strerror(errno));
+ close(fd);
+ return FALSE;
+ }
+
+ if (cursor->bits->argb)
+ memcpy(data, cursor->bits->argb, size);
+ else
+ expand_source_and_mask(cursor, data);
+ munmap(data, size);
+
+ pool = wl_shm_create_pool(xwl_screen->shm, fd, size);
+ close(fd);
+ buffer = wl_shm_pool_create_buffer(pool, 0,
+ cursor->bits->width, cursor->bits->height,
+ cursor->bits->width * 4,
+ WL_SHM_FORMAT_ARGB8888);
+ wl_shm_pool_destroy(pool);
+
+ dixSetPrivate(&cursor->devPrivates,
+ &xwl_screen->cursor_private_key, buffer);
+
+ return TRUE;
+}
+
+static Bool
+xwl_unrealize_cursor(DeviceIntPtr device,
+ ScreenPtr screen, CursorPtr cursor)
+{
+ struct wl_buffer *buffer;
+ struct xwl_screen *xwl_screen;
+
+ xwl_screen = xwl_screen_get(screen);
+ buffer = dixGetPrivate(&cursor->devPrivates,
+ &xwl_screen->cursor_private_key);
+ wl_buffer_destroy(buffer);
+
+ return TRUE;
+}
+
+void
+xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
+{
+ struct wl_buffer *buffer;
+
+ 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;
+ }
+
+ buffer = dixGetPrivate(&xwl_seat->x_cursor->devPrivates,
+ &xwl_seat->xwl_screen->cursor_private_key);
+
+ 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, 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_screen *xwl_screen;
+ struct xwl_seat *xwl_seat;
+
+ xwl_screen = xwl_screen_get(screen);
+
+ if (!xwl_screen || xorg_list_is_empty(&xwl_screen->seat_list))
+ return;
+
+ xwl_seat = xorg_list_first_entry(&xwl_screen->seat_list,
+ struct xwl_seat, link);
+
+ 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)
+{
+ struct xwl_screen *xwl_screen;
+
+ xwl_screen = xwl_screen_get(screen);
+
+ return xwl_screen->sprite_funcs->DeviceCursorInitialize(device,
+ screen);
+}
+
+static void
+xwl_device_cursor_cleanup(DeviceIntPtr device, ScreenPtr screen)
+{
+ struct xwl_screen *xwl_screen;
+
+ xwl_screen = xwl_screen_get(screen);
+
+ xwl_screen->sprite_funcs->DeviceCursorCleanup(device, 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
+};
+
+int
+xwl_screen_init_cursor(struct xwl_screen *xwl_screen, ScreenPtr screen)
+{
+ miPointerScreenPtr pointer_priv;
+
+ if (!dixRegisterPrivateKey(&xwl_screen->cursor_private_key,
+ PRIVATE_CURSOR, 0))
+ return BadAlloc;
+
+ pointer_priv = dixLookupPrivate(&screen->devPrivates, miPointerScreenKey);
+ xwl_screen->sprite_funcs = pointer_priv->spriteFuncs;
+ pointer_priv->spriteFuncs = &xwl_pointer_sprite_funcs;
+
+ return Success;
+}
diff --git a/hw/xfree86/xwayland/xwayland-drm.c b/hw/xfree86/xwayland/xwayland-drm.c
new file mode 100644
index 000000000..52508575f
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland-drm.c
@@ -0,0 +1,250 @@
+/*
+ * 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include "xorg-config.h"
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <xf86drm.h>
+#include <wayland-util.h>
+#include <wayland-client.h>
+#include <drm-client-protocol.h>
+
+#include <xf86Xinput.h>
+#include <xf86Crtc.h>
+#include <xf86str.h>
+#include <windowstr.h>
+#include <input.h>
+#include <inputstr.h>
+#include <exevents.h>
+
+#include "xwayland.h"
+#include "xwayland-private.h"
+#include "../dri2/dri2.h"
+
+struct xwl_auth_req {
+ struct xorg_list link;
+
+ ClientPtr client;
+ struct xwl_screen *xwl_screen;
+ uint32_t magic;
+};
+
+static void
+drm_handle_device (void *data, struct wl_drm *drm, const char *device)
+{
+ struct xwl_screen *xwl_screen = data;
+
+ xwl_screen->device_name = strdup (device);
+}
+
+static void
+drm_handle_format(void *data, struct wl_drm *wl_drm, uint32_t format)
+{
+}
+
+static void
+drm_handle_authenticated (void *data, struct wl_drm *drm)
+{
+ struct xwl_screen *xwl_screen = data;
+ struct xwl_auth_req *req;
+
+ xwl_screen->authenticated = 1;
+
+ /* it does one authentication transaction at a time, so if there's an
+ * element in the list, we call DRI2SendAuthReply for that client, remove
+ * the head and free the struct. If there are still elements in the list,
+ * it means that we have one or more clients waiting to be authenticated
+ * and we send out a wl_drm authenticate request for the first client in
+ * the list */
+ if (xorg_list_is_empty(&xwl_screen->authenticate_client_list))
+ return;
+
+ req = xorg_list_first_entry(&xwl_screen->authenticate_client_list,
+ struct xwl_auth_req, link);
+ DRI2SendAuthReply(req->client, TRUE);
+ AttendClient(req->client);
+ xorg_list_del(&req->link);
+ free(req);
+
+ xorg_list_for_each_entry(req, &xwl_screen->authenticate_client_list,
+ link) {
+ wl_drm_authenticate (xwl_screen->drm, req->magic);
+ return;
+ }
+}
+
+static const struct wl_drm_listener xwl_drm_listener =
+{
+ drm_handle_device,
+ drm_handle_format,
+ drm_handle_authenticated
+};
+
+static void
+drm_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_drm") == 0) {
+ xwl_screen->drm = wl_registry_bind(xwl_screen->registry, id,
+ &wl_drm_interface, 1);
+ wl_drm_add_listener(xwl_screen->drm, &xwl_drm_listener, xwl_screen);
+ }
+}
+
+static void
+global_remove(void *data, struct wl_registry *registry, uint32_t name)
+{
+ /* Nothing to do here, wl_drm should not be removed */
+}
+
+static const struct wl_registry_listener drm_listener = {
+ drm_handler,
+ global_remove
+};
+
+int
+xwl_drm_pre_init(struct xwl_screen *xwl_screen)
+{
+ uint32_t magic;
+
+ xwl_screen->drm_registry = wl_display_get_registry(xwl_screen->display);
+ wl_registry_add_listener(xwl_screen->drm_registry, &drm_listener,
+ xwl_screen);
+
+ /* Ensure drm_handler has seen all the interfaces */
+ wl_display_roundtrip(xwl_screen->display);
+ /* Ensure the xwl_drm_listener has seen the drm device, if any */
+ wl_display_roundtrip(xwl_screen->display);
+
+ ErrorF("wayland_drm_screen_init, device name %s\n",
+ xwl_screen->device_name);
+
+ xwl_screen->drm_fd = open(xwl_screen->device_name, O_RDWR);
+ if (xwl_screen->drm_fd < 0) {
+ ErrorF("failed to open the drm fd\n");
+ return BadAccess;
+ }
+
+ if (drmGetMagic(xwl_screen->drm_fd, &magic)) {
+ ErrorF("failed to get drm magic");
+ return BadAccess;
+ }
+
+ wl_drm_authenticate(xwl_screen->drm, magic);
+
+ wl_display_roundtrip(xwl_screen->display);
+
+ ErrorF("opened drm fd: %d\n", xwl_screen->drm_fd);
+
+ if (!xwl_screen->authenticated) {
+ ErrorF("Failed to auth drm fd\n");
+ return BadAccess;
+ }
+
+ return Success;
+}
+
+Bool xwl_drm_initialised(struct xwl_screen *xwl_screen)
+{
+ return xwl_screen->authenticated;
+}
+
+int xwl_screen_get_drm_fd(struct xwl_screen *xwl_screen)
+{
+ return xwl_screen->drm_fd;
+}
+
+int xwl_drm_authenticate(ClientPtr client, struct xwl_screen *xwl_screen,
+ uint32_t magic)
+{
+ struct xwl_auth_req *req;
+
+ if (!xwl_screen->drm)
+ return BadAccess;
+
+ req = malloc (sizeof *req);
+ if (req == NULL)
+ return BadAlloc;
+
+ req->client = client;
+ req->xwl_screen = xwl_screen;
+ req->magic = magic;
+
+ if (xorg_list_is_empty(&xwl_screen->authenticate_client_list))
+ wl_drm_authenticate (xwl_screen->drm, magic);
+
+ xorg_list_append(&req->link, &xwl_screen->authenticate_client_list);
+
+ IgnoreClient(req->client);
+ xwl_screen->authenticated = 0;
+
+ return Success;
+}
+
+
+int
+xwl_create_window_buffer_drm(struct xwl_window *xwl_window,
+ PixmapPtr pixmap, uint32_t name)
+{
+ VisualID visual;
+ WindowPtr window = xwl_window->window;
+ ScreenPtr screen = window->drawable.pScreen;
+ uint32_t format;
+ int i;
+
+ visual = wVisual(window);
+ for (i = 0; i < screen->numVisuals; i++)
+ if (screen->visuals[i].vid == visual)
+ break;
+
+ switch (screen->visuals[i].nplanes) {
+ case 32:
+ format = WL_DRM_FORMAT_ARGB8888;
+ break;
+ case 24:
+ default:
+ format = WL_DRM_FORMAT_XRGB8888;
+ break;
+ case 16:
+ format = WL_DRM_FORMAT_RGB565;
+ break;
+ }
+
+ xwl_window->buffer =
+ wl_drm_create_buffer(xwl_window->xwl_screen->drm,
+ name,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ pixmap->devKind,
+ format);
+
+ return xwl_window->buffer ? Success : BadDrawable;
+}
diff --git a/hw/xfree86/xwayland/xwayland-input.c b/hw/xfree86/xwayland/xwayland-input.c
new file mode 100644
index 000000000..9adc6159b
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland-input.c
@@ -0,0 +1,647 @@
+/*
+ * 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include "xorg-config.h"
+#endif
+
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <linux/input.h>
+#include <wayland-util.h>
+#include <wayland-client.h>
+#include <X11/extensions/compositeproto.h>
+#include <xserver-properties.h>
+
+#include <compositeext.h>
+#include <selection.h>
+#include <extinit.h>
+#include <exevents.h>
+#include <input.h>
+#include <inpututils.h>
+#include <inputstr.h>
+#include <exevents.h>
+#include <xkbsrv.h>
+#include <windowstr.h>
+#include <mipointrst.h>
+#include <sys/mman.h>
+
+#include "xwayland.h"
+#include "xwayland-private.h"
+#include "xserver-client-protocol.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)
+{
+ /* FIXME: Set keyboard leds based on CAPSFLAG etc being set in
+ * ctrl->leds - needs private protocol. */
+}
+
+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 DeviceIntPtr
+device_added(struct xwl_seat *xwl_seat, const char *driver)
+{
+ DeviceIntPtr dev = NULL;
+ Atom type_atom;
+ char *name;
+ int rc;
+ Bool (*device_control) (DeviceIntPtr device, int what);
+
+ if (strcmp(driver, "xwayland-keyboard") == 0) {
+ name = xwl_seat->keyboard_name;
+ device_control = xwl_keyboard_proc;
+ } else {
+ name = xwl_seat->pointer_name;
+ device_control = xwl_pointer_proc;
+ }
+
+ snprintf(name, sizeof xwl_seat->keyboard_name,
+ "%s:%d", driver, xwl_seat->id);
+
+ dev = AddInputDevice(serverClient, device_control, TRUE);
+ if (dev == NULL)
+ return NULL;
+
+ type_atom = MakeAtom(driver, strlen(driver), TRUE);
+ AssignTypeAndName(dev, type_atom, name);
+ dev->public.devicePrivate = xwl_seat;
+ dev->type = SLAVE;
+ dev->spriteInfo->spriteOwner = FALSE;
+
+ rc = ActivateDevice(dev, TRUE);
+ if (rc != Success) {
+ RemoveDevice(dev, TRUE);
+ xf86Msg(X_ERROR, "xwayland: Couldn't init device \"%s\"\n", name);
+ return NULL;
+ }
+
+ EnableDevice(dev, TRUE);
+ if (!dev->enabled) {
+ RemoveDevice(dev, TRUE);
+ xf86Msg(X_ERROR, "xwayland: Couldn't enable device \"%s\"\n", name);
+ return NULL;
+ }
+
+ LogMessage(X_INFO, "xwayland: Adding input device %s\n", name);
+
+ return dev;
+}
+
+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);
+
+ SetDeviceRedirectWindow(xwl_seat->pointer, xwl_seat->focus_window->window);
+
+ /* 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);
+
+ (*pScreen->DisplayCursor)(dev, pScreen, dev->spriteInfo->sprite->current);
+}
+
+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;
+ ScreenPtr pScreen = xwl_seat->xwl_screen->screen;
+
+ xwl_seat->xwl_screen->serial = serial;
+
+ xwl_seat->focus_window = NULL;
+ SetDeviceRedirectWindow(xwl_seat->pointer, PointerRootWin);
+ (*pScreen->DisplayCursor)(dev, pScreen, NullCursor);
+}
+
+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;
+ }
+
+ if (!xwl_seat->keyboard)
+ 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);
+ /* 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 void
+add_devices(void *data, struct wl_callback *callback, uint32_t time)
+{
+ struct xwl_seat *xwl_seat = data;
+
+ wl_callback_destroy(callback);
+
+ if (xwl_seat->wl_pointer)
+ xwl_seat->pointer = device_added(xwl_seat, "xwayland-pointer");
+ if (xwl_seat->wl_keyboard)
+ xwl_seat->keyboard = device_added(xwl_seat, "xwayland-keyboard");
+}
+
+static const struct wl_callback_listener add_devices_listener = {
+ add_devices
+};
+
+static void
+seat_handle_capabilities(void *data, struct wl_seat *seat,
+ enum wl_seat_capability caps)
+{
+ struct xwl_seat *xwl_seat = data;
+ struct wl_callback *callback;
+
+ 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);
+ }
+
+ 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);
+
+ }
+ /* FIXME: Touch ... */
+
+ /* Add devices after we've received keymaps. */
+ if (caps) {
+ callback = wl_display_sync(xwl_seat->xwl_screen->display);
+ wl_callback_add_listener(callback,
+ &add_devices_listener, xwl_seat);
+ }
+}
+
+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);
+}
+
+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);
+ } else if (strcmp(interface, "xserver") == 0) {
+ xwl_screen->xorg_server =
+ wl_registry_bind(registry, id, &xserver_interface, 1);
+ xserver_add_listener(xwl_screen->xorg_server, &xwl_server_listener,
+ xwl_screen);
+ }
+}
+
+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,
+};
+
+void
+xwl_input_init(struct xwl_screen *xwl_screen)
+{
+ xwl_screen->input_registry = wl_display_get_registry(xwl_screen->display);
+ wl_registry_add_listener(xwl_screen->input_registry, &input_listener,
+ xwl_screen);
+}
diff --git a/hw/xfree86/xwayland/xwayland-output.c b/hw/xfree86/xwayland/xwayland-output.c
new file mode 100644
index 000000000..a45e21311
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland-output.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright © 2011 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_XORG_CONFIG_H
+#include "xorg-config.h"
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <wayland-client.h>
+
+#include <cursorstr.h>
+#include <xf86Crtc.h>
+#include <mipointrst.h>
+#include <randrstr.h>
+
+#include "xwayland.h"
+#include "xwayland-private.h"
+#include "xserver-client-protocol.h"
+
+static void
+crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode)
+{
+}
+
+static Bool
+crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
+ Rotation rotation, int x, int y)
+{
+ return TRUE;
+}
+
+static void
+crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
+{
+}
+
+static void
+crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
+{
+}
+
+static void
+crtc_show_cursor (xf86CrtcPtr crtc)
+{
+}
+
+static void
+crtc_hide_cursor (xf86CrtcPtr crtc)
+{
+}
+
+static void
+crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
+{
+}
+
+static PixmapPtr
+crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
+{
+ return NULL;
+}
+
+static void *
+crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
+{
+ return NULL;
+}
+
+static void
+crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
+{
+}
+
+static void
+crtc_destroy(xf86CrtcPtr crtc)
+{
+ /* Nothing to do here, we only destroy CRTCs when instructed to do
+ so by wl_output changes
+ */
+}
+
+static const xf86CrtcFuncsRec crtc_funcs = {
+ .dpms = crtc_dpms,
+ .set_mode_major = crtc_set_mode_major,
+ .set_cursor_colors = crtc_set_cursor_colors,
+ .set_cursor_position = crtc_set_cursor_position,
+ .show_cursor = crtc_show_cursor,
+ .hide_cursor = crtc_hide_cursor,
+ .load_cursor_argb = crtc_load_cursor_argb,
+ .shadow_create = crtc_shadow_create,
+ .shadow_allocate = crtc_shadow_allocate,
+ .shadow_destroy = crtc_shadow_destroy,
+ .destroy = crtc_destroy,
+};
+
+static void
+output_dpms(xf86OutputPtr output, int mode)
+{
+ return;
+}
+
+static xf86OutputStatus
+output_detect(xf86OutputPtr output)
+{
+ return XF86OutputStatusConnected;
+}
+
+static Bool
+output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
+{
+ return MODE_OK;
+}
+
+static DisplayModePtr
+output_get_modes(xf86OutputPtr xf86output)
+{
+ struct xwl_output *output = xf86output->driver_private;
+ struct monitor_ranges *ranges;
+ DisplayModePtr modes;
+
+ modes = xf86CVTMode(output->width, output->height, 60, TRUE, FALSE);
+ output->xf86monitor.det_mon[0].type = DS_RANGES;
+ ranges = &output->xf86monitor.det_mon[0].section.ranges;
+ ranges->min_h = modes->HSync - 10;
+ ranges->max_h = modes->HSync + 10;
+ ranges->min_v = modes->VRefresh - 10;
+ ranges->max_v = modes->VRefresh + 10;
+ ranges->max_clock = modes->Clock + 100;
+ output->xf86monitor.det_mon[1].type = DT;
+ output->xf86monitor.det_mon[2].type = DT;
+ output->xf86monitor.det_mon[3].type = DT;
+ output->xf86monitor.no_sections = 0;
+
+ xf86output->MonInfo = &output->xf86monitor;
+
+ return modes;
+}
+
+static void
+output_destroy(xf86OutputPtr xf86output)
+{
+ struct xwl_output *output = xf86output->driver_private;
+
+ free(output);
+}
+
+static const xf86OutputFuncsRec output_funcs = {
+ .dpms = output_dpms,
+ .detect = output_detect,
+ .mode_valid = output_mode_valid,
+ .get_modes = output_get_modes,
+ .destroy = output_destroy
+};
+
+struct xwl_output *
+xwl_output_create(struct xwl_screen *xwl_screen)
+{
+ struct xwl_output *xwl_output;
+ xf86OutputPtr xf86output;
+ xf86CrtcPtr xf86crtc;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(xwl_screen->scrninfo);
+ int crtcId, outputId;
+ static int nameId;
+ char *name;
+
+ xwl_output = calloc(sizeof *xwl_output, 1);
+ if (xwl_output == NULL) {
+ ErrorF("create_output ENOMEM");
+ return NULL;
+ }
+
+ nameId++;
+ if (asprintf(&name, "XWAYLAND-%d", nameId) < 0) {
+ ErrorF("create_output ENOMEM");
+ free(xwl_output);
+ return NULL;
+ }
+
+ xwl_output->xwl_screen = xwl_screen;
+
+ xf86crtc = xf86CrtcCreate(xwl_screen->scrninfo, &crtc_funcs);
+ xf86crtc->enabled = TRUE;
+ xf86crtc->driver_private = xwl_output;
+
+ for (crtcId = 0; crtcId < xf86_config->num_crtc; crtcId++) {
+ if (xf86_config->crtc[crtcId] == xf86crtc)
+ break;
+ }
+
+ xf86output = xf86OutputCreate(xwl_screen->scrninfo,
+ &output_funcs, name);
+ xf86output->driver_private = xwl_output;
+ xf86output->possible_crtcs = 1 << crtcId;
+
+ for (outputId = 0; outputId < xf86_config->num_output; outputId++) {
+ if (xf86_config->output[outputId] == xf86output)
+ break;
+ }
+
+ xf86output->possible_clones = 1 << outputId;
+
+ xwl_output->xf86output = xf86output;
+ xwl_output->xf86crtc = xf86crtc;
+ xwl_output->xf86output->crtc = xf86crtc;
+
+ free(name);
+
+ return xwl_output;
+}
+
+static Bool
+resize(ScrnInfoPtr scrn, int width, int height)
+{
+ if (scrn->virtualX == width && scrn->virtualY == height)
+ return TRUE;
+ /* We don't handle resize at all, we must match the compositor size */
+ return FALSE;
+}
+
+static const xf86CrtcConfigFuncsRec config_funcs = {
+ resize
+};
+
+static Rotation
+wl_transform_to_xrandr (enum wl_output_transform transform)
+{
+ switch (transform)
+ {
+ 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;
+ }
+
+ return RR_Rotate_0;
+}
+
+static void
+display_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;
+ struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
+
+ xwl_output->xf86output->mm_width = physical_width;
+ xwl_output->xf86output->mm_height = physical_height;
+
+ switch (subpixel) {
+ case WL_OUTPUT_SUBPIXEL_UNKNOWN:
+ xwl_output->xf86output->subpixel_order = SubPixelUnknown;
+ break;
+ case WL_OUTPUT_SUBPIXEL_NONE:
+ xwl_output->xf86output->subpixel_order = SubPixelNone;
+ break;
+ case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
+ xwl_output->xf86output->subpixel_order = SubPixelHorizontalRGB;
+ break;
+ case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
+ xwl_output->xf86output->subpixel_order = SubPixelHorizontalBGR;
+ break;
+ case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
+ xwl_output->xf86output->subpixel_order = SubPixelVerticalRGB;
+ break;
+ case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
+ xwl_output->xf86output->subpixel_order = SubPixelVerticalBGR;
+ break;
+ }
+
+ xwl_output->x = x;
+ xwl_output->y = y;
+ xwl_output->rotation = wl_transform_to_xrandr (transform);
+
+ xorg_list_append (&xwl_output->link, &xwl_screen->output_list);
+}
+
+static void
+display_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
+ int width, int height, int refresh)
+{
+ struct xwl_output *xwl_output = data;
+ struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
+ ScreenPtr pScreen = xwl_screen->screen;
+ ScrnInfoPtr scrn = xwl_screen->scrninfo;
+ CARD16 width_mm, height_mm;
+ DisplayModePtr mode;
+ rrScrPrivPtr rp;
+
+ if (!(flags & WL_OUTPUT_MODE_CURRENT))
+ return;
+
+ xwl_output->width = width;
+ xwl_output->height = height;
+
+ if (xwl_output->x + xwl_output->width > scrn->virtualX ||
+ xwl_output->y + xwl_output->height > scrn->virtualY) {
+ /* Fake a RandR request to resize the screen. It will bounce
+ back to our crtc_resize, which does nothing.
+ */
+ /* Preupdate virtualX / virtualY, so that crtc_resize returns TRUE */
+ scrn->virtualX = xwl_output->x + xwl_output->width;
+ scrn->virtualY = xwl_output->y + xwl_output->height;
+
+ /* Ignore the compositor provided values for mm_width/mm_height,
+ as it doesn't make sense to sum the values of different outputs.
+ Just make the DPI 96 */
+ width_mm = (scrn->virtualX / 96.0) * 25.4 + 0.5;
+ height_mm = (scrn->virtualY / 96.0) * 25.4 + 0.5;
+
+ /* But! When the server starts, the RandR stuff is not initialized,
+ so we can't call rrGetScrPriv. We updated virtualX/Y anyway, let's
+ hope it's enough.
+ */
+ if (xwl_screen->outputs_initialized) {
+ rp = rrGetScrPriv(pScreen);
+ if (rp->rrScreenSetSize)
+ rp->rrScreenSetSize(pScreen, scrn->virtualX, scrn->virtualY, width_mm, height_mm);
+ }
+ }
+
+ xwl_output->xf86crtc->enabled = TRUE;
+ mode = xf86CVTMode(width, height, (float) refresh / 1000, TRUE, FALSE);
+ xf86CrtcSetModeTransform(xwl_output->xf86crtc, mode, xwl_output->rotation,
+ NULL, xwl_output->x, xwl_output->y);
+}
+
+static const struct wl_output_listener output_listener = {
+ display_handle_geometry,
+ display_handle_mode
+};
+
+static void
+global_handler(void *data, struct wl_registry *registry, uint32_t id,
+ const char *interface, uint32_t version)
+{
+ struct xwl_screen *xwl_screen = data;
+ struct xwl_output *xwl_output;
+
+ if (strcmp (interface, "wl_output") == 0) {
+ xwl_output = xwl_output_create(xwl_screen);
+ xwl_output->output = wl_registry_bind(registry, id,
+ &wl_output_interface, 1);
+ xwl_output->name = id;
+ wl_output_add_listener(xwl_output->output,
+ &output_listener, xwl_output);
+ }
+}
+
+void
+xwl_output_remove(struct xwl_output *xwl_output)
+{
+ xorg_list_del (&xwl_output->link);
+ xf86OutputDestroy (xwl_output->xf86output);
+ xf86CrtcDestroy (xwl_output->xf86crtc);
+
+ wl_output_destroy (xwl_output->output);
+}
+
+static void
+global_remove(void *data, struct wl_registry *registry, uint32_t name)
+{
+ struct xwl_screen *xwl_screen = data;
+ struct xwl_output *xwl_output, *tmp;
+
+ xorg_list_for_each_entry_safe (xwl_output, tmp, &xwl_screen->output_list, link) {
+ if (xwl_output->name == name) {
+ xwl_output_remove(xwl_output);
+ break;
+ }
+ }
+}
+
+static const struct wl_registry_listener global_listener = {
+ global_handler,
+ global_remove
+};
+
+void
+xwayland_screen_preinit_output(struct xwl_screen *xwl_screen, ScrnInfoPtr scrninfo)
+{
+ int ret;
+
+ xf86CrtcConfigInit(scrninfo, &config_funcs);
+
+ xf86CrtcSetSizeRange(scrninfo, 320, 200, 8192, 8192);
+
+ xwl_screen->output_registry = wl_display_get_registry(xwl_screen->display);
+ wl_registry_add_listener(xwl_screen->output_registry, &global_listener,
+ xwl_screen);
+
+ while (xwl_screen->output_list.next == &xwl_screen->output_list) {
+ ret = wl_display_roundtrip(xwl_screen->display);
+ if (ret == -1)
+ FatalError("failed to dispatch Wayland events: %s\n", strerror(errno));
+ }
+
+ xf86ProbeOutputModes(scrninfo, 0, 0);
+
+ xwl_screen->outputs_initialized = TRUE;
+
+ xf86SetScrnInfoModes(scrninfo);
+}
diff --git a/hw/xfree86/xwayland/xwayland-private.h b/hw/xfree86/xwayland/xwayland-private.h
new file mode 100644
index 000000000..27d68d150
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland-private.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright © 2010 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.
+ */
+
+#ifndef _XWAYLAND_PRIVATE_H_
+#define _XWAYLAND_PRIVATE_H_
+
+#include <xf86Crtc.h>
+
+struct xwl_window {
+ struct xwl_screen *xwl_screen;
+ struct wl_surface *surface;
+ struct wl_buffer *buffer;
+ WindowPtr window;
+ DamagePtr damage;
+ struct xorg_list link;
+ struct xorg_list link_damage;
+};
+
+struct xwl_output;
+
+struct xwl_screen {
+ struct xwl_driver *driver;
+ ScreenPtr screen;
+ ScrnInfoPtr scrninfo;
+ int drm_fd;
+ int wayland_fd;
+ struct wl_display *display;
+ struct wl_registry *registry;
+ struct wl_registry *drm_registry;
+ struct wl_registry *input_registry;
+ struct wl_registry *output_registry;
+ struct wl_compositor *compositor;
+ struct wl_drm *drm;
+ struct wl_shm *shm;
+ struct xserver *xorg_server;
+ uint32_t mask;
+ uint32_t flags;
+ char *device_name;
+ uint32_t authenticated;
+ struct xorg_list output_list;
+ struct xorg_list seat_list;
+ struct xorg_list damage_window_list;
+ struct xorg_list window_list;
+ struct xorg_list authenticate_client_list;
+ uint32_t serial;
+ Bool outputs_initialized;
+
+ DevPrivateKeyRec cursor_private_key;
+
+ CreateWindowProcPtr CreateWindow;
+ DestroyWindowProcPtr DestroyWindow;
+ RealizeWindowProcPtr RealizeWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ SetWindowPixmapProcPtr SetWindowPixmap;
+ MoveWindowProcPtr MoveWindow;
+ miPointerSpriteFuncPtr sprite_funcs;
+};
+
+struct xwl_output {
+ struct xorg_list link;
+ struct wl_output *output;
+ struct xwl_screen *xwl_screen;
+ int32_t x, y, width, height;
+ xf86Monitor xf86monitor;
+ xf86OutputPtr xf86output;
+ xf86CrtcPtr xf86crtc;
+ int32_t name;
+ Rotation rotation;
+};
+
+
+#define MODIFIER_META 0x01
+
+struct xwl_seat {
+ DeviceIntPtr pointer;
+ char pointer_name[32];
+ DeviceIntPtr keyboard;
+ char keyboard_name[32];
+ 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_screen *xwl_screen_get(ScreenPtr screen);
+
+void xwayland_screen_preinit_output(struct xwl_screen *xwl_screen, ScrnInfoPtr scrninfo);
+
+int xwl_screen_init_cursor(struct xwl_screen *xwl_screen, ScreenPtr screen);
+int xwl_screen_init_window(struct xwl_screen *xwl_screen, ScreenPtr screen);
+
+struct xwl_output *xwl_output_create(struct xwl_screen *xwl_screen);
+
+void xwl_input_init(struct xwl_screen *screen);
+
+Bool xwl_drm_initialised(struct xwl_screen *screen);
+
+void xwl_seat_set_cursor(struct xwl_seat *xwl_seat);
+
+void xwl_output_remove(struct xwl_output *output);
+
+extern const struct xserver_listener xwl_server_listener;
+
+#endif /* _XWAYLAND_PRIVATE_H_ */
diff --git a/hw/xfree86/xwayland/xwayland-window.c b/hw/xfree86/xwayland/xwayland-window.c
new file mode 100644
index 000000000..a2a820624
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland-window.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright © 2011 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_XORG_CONFIG_H
+#include "xorg-config.h"
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <wayland-client.h>
+
+#include <xf86Crtc.h>
+#include <selection.h>
+#include <exevents.h>
+
+#include "xwayland.h"
+#include "xwayland-private.h"
+#include "xserver-client-protocol.h"
+
+static DevPrivateKeyRec xwl_window_private_key;
+
+static void
+free_pixmap(void *data, struct wl_callback *callback, uint32_t time)
+{
+ PixmapPtr pixmap = data;
+ ScreenPtr screen = pixmap->drawable.pScreen;
+
+ (*screen->DestroyPixmap)(pixmap);
+ wl_callback_destroy(callback);
+}
+
+static const struct wl_callback_listener free_pixmap_listener = {
+ free_pixmap,
+};
+
+static void
+xwl_window_attach(struct xwl_window *xwl_window, PixmapPtr pixmap)
+{
+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+ struct wl_callback *callback;
+
+ /* We can safely destroy the buffer because we only use one buffer
+ * per surface in xwayland model */
+ if (xwl_window->buffer)
+ wl_buffer_destroy(xwl_window->buffer);
+
+ xwl_screen->driver->create_window_buffer(xwl_window, pixmap);
+
+ if (!xwl_window->buffer) {
+ ErrorF("failed to create buffer\n");
+ return;
+ }
+
+ wl_surface_attach(xwl_window->surface, xwl_window->buffer, 0, 0);
+ wl_surface_damage(xwl_window->surface, 0, 0,
+ pixmap->drawable.width,
+ pixmap->drawable.height);
+
+ callback = wl_display_sync(xwl_screen->display);
+ wl_callback_add_listener(callback, &free_pixmap_listener, pixmap);
+ pixmap->refcnt++;
+}
+
+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 Bool
+xwl_realize_window(WindowPtr window)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ struct xwl_screen *xwl_screen;
+ struct xwl_window *xwl_window;
+ 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->flags & XWL_FLAGS_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->xorg_server)
+ xserver_set_window_id(xwl_screen->xorg_server,
+ xwl_window->surface, window->drawable.id);
+
+ wl_surface_set_user_data(xwl_window->surface, xwl_window);
+ xwl_window_attach(xwl_window, (*screen->GetWindowPixmap)(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_add(&xwl_window->link, &xwl_screen->window_list);
+ 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;
+ SetDeviceRedirectWindow(xwl_seat->pointer, PointerRootWin);
+ }
+ }
+
+ 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;
+
+ if (xwl_window->buffer)
+ wl_buffer_destroy(xwl_window->buffer);
+ wl_surface_destroy(xwl_window->surface);
+ xorg_list_del(&xwl_window->link);
+ 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 void
+xwl_set_window_pixmap(WindowPtr window, PixmapPtr pixmap)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ struct xwl_screen *xwl_screen;
+ struct xwl_window *xwl_window;
+
+ xwl_screen = xwl_screen_get(screen);
+
+ screen->SetWindowPixmap = xwl_screen->SetWindowPixmap;
+ (*screen->SetWindowPixmap)(window, pixmap);
+ xwl_screen->SetWindowPixmap = screen->SetWindowPixmap;
+ screen->SetWindowPixmap = xwl_set_window_pixmap;
+
+ xwl_window =
+ dixLookupPrivate(&window->devPrivates, &xwl_window_private_key);
+ if (xwl_window)
+ xwl_window_attach(xwl_window, pixmap);
+}
+
+static void
+xwl_move_window(WindowPtr window, int x, int y,
+ WindowPtr sibling, VTKind kind)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ struct xwl_screen *xwl_screen;
+ struct xwl_window *xwl_window;
+
+ xwl_screen = xwl_screen_get(screen);
+
+ screen->MoveWindow = xwl_screen->MoveWindow;
+ (*screen->MoveWindow)(window, x, y, sibling, kind);
+ xwl_screen->MoveWindow = screen->MoveWindow;
+ screen->MoveWindow = xwl_move_window;
+
+ xwl_window =
+ dixLookupPrivate(&window->devPrivates, &xwl_window_private_key);
+ if (xwl_window == NULL)
+ return;
+}
+
+int
+xwl_screen_init_window(struct xwl_screen *xwl_screen, ScreenPtr screen)
+{
+ if (!dixRegisterPrivateKey(&xwl_window_private_key, PRIVATE_WINDOW, 0))
+ return BadAlloc;
+
+ xwl_screen->RealizeWindow = screen->RealizeWindow;
+ screen->RealizeWindow = xwl_realize_window;
+
+ xwl_screen->UnrealizeWindow = screen->UnrealizeWindow;
+ screen->UnrealizeWindow = xwl_unrealize_window;
+
+ xwl_screen->SetWindowPixmap = screen->SetWindowPixmap;
+ screen->SetWindowPixmap = xwl_set_window_pixmap;
+
+ xwl_screen->MoveWindow = screen->MoveWindow;
+ screen->MoveWindow = xwl_move_window;
+
+ return Success;
+}
diff --git a/hw/xfree86/xwayland/xwayland.c b/hw/xfree86/xwayland/xwayland.c
new file mode 100644
index 000000000..122346ced
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright © 2008-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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include "xorg-config.h"
+#endif
+
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <wayland-util.h>
+#include <wayland-client.h>
+
+#include <extinit.h>
+
+#include <xf86Xinput.h>
+#include <xf86Crtc.h>
+#include <xf86Priv.h>
+#include <os.h>
+#include <selection.h>
+
+#include "xwayland.h"
+#include "xwayland-private.h"
+#include "xserver-client-protocol.h"
+
+/*
+ * TODO:
+ * - lose X kb focus when wayland surface loses it
+ * - active grabs, grab owner crack
+ */
+
+static DevPrivateKeyRec xwl_screen_private_key;
+
+static void
+xserver_client(void *data, struct xserver *xserver, int fd)
+{
+ AddClientOnOpenFD(fd);
+}
+
+static void
+xserver_listen_socket(void *data, struct xserver *xserver, int fd)
+{
+ ListenOnOpenFD(fd, TRUE);
+}
+
+const struct xserver_listener xwl_server_listener = {
+ xserver_client,
+ xserver_listen_socket
+};
+
+static void
+xwl_input_delayed_init(void *data, struct wl_callback *callback, uint32_t time)
+{
+ struct xwl_screen *xwl_screen = data;
+
+ ErrorF("xwl_input_delayed_init\n");
+
+ wl_callback_destroy(callback);
+ xwl_input_init(xwl_screen);
+}
+
+static const struct wl_callback_listener delayed_init_listner = {
+ xwl_input_delayed_init
+};
+
+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);
+ }
+}
+
+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;
+
+ 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));
+}
+
+int
+xwl_screen_init(struct xwl_screen *xwl_screen, ScreenPtr screen)
+{
+ struct wl_callback *callback;
+
+ xwl_screen->screen = screen;
+
+ if (!dixRegisterPrivateKey(&xwl_screen_private_key, PRIVATE_SCREEN, 0))
+ return BadAlloc;
+
+ dixSetPrivate(&screen->devPrivates,
+ &xwl_screen_private_key, xwl_screen);
+
+ xwl_screen_init_window(xwl_screen, screen);
+
+ xwl_screen_init_cursor(xwl_screen, screen);
+
+ AddGeneralSocket(xwl_screen->wayland_fd);
+ RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, xwl_screen);
+
+ callback = wl_display_sync(xwl_screen->display);
+ wl_callback_add_listener(callback, &delayed_init_listner, xwl_screen);
+
+ return Success;
+}
+
+struct xwl_screen *
+xwl_screen_get(ScreenPtr screen)
+{
+ return dixLookupPrivate(&screen->devPrivates, &xwl_screen_private_key);
+}
+
+struct xwl_screen *
+xwl_screen_create(void)
+{
+ struct xwl_screen *xwl_screen;
+
+ xwl_screen = calloc(sizeof *xwl_screen, 1);
+ if (xwl_screen == NULL) {
+ ErrorF("calloc failed\n");
+ return NULL;
+ }
+
+ xwl_screen->display = wl_display_connect(NULL);
+ if (xwl_screen->display == NULL) {
+ ErrorF("wl_display_create failed\n");
+ return NULL;
+ }
+
+ return xwl_screen;
+}
+
+Bool
+xwl_screen_pre_init(ScrnInfoPtr scrninfo, struct xwl_screen *xwl_screen,
+ uint32_t flags, struct xwl_driver *driver)
+{
+ int ret;
+
+ noScreenSaverExtension = TRUE;
+
+ xorg_list_init(&xwl_screen->output_list);
+ xorg_list_init(&xwl_screen->seat_list);
+ xorg_list_init(&xwl_screen->damage_window_list);
+ xorg_list_init(&xwl_screen->window_list);
+ xorg_list_init(&xwl_screen->authenticate_client_list);
+ xwl_screen->scrninfo = scrninfo;
+ xwl_screen->driver = driver;
+ xwl_screen->flags = flags;
+ xwl_screen->wayland_fd = wl_display_get_fd(xwl_screen->display);
+
+ if (xorgRootless)
+ xwl_screen->flags |= XWL_FLAGS_ROOTLESS;
+
+ /* Set up listener so we'll catch all events. */
+ 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) {
+ xf86DrvMsg(scrninfo->scrnIndex, X_ERROR,
+ "failed to dispatch Wayland events: %s\n", strerror(errno));
+ return FALSE;
+ }
+
+#ifdef WITH_LIBDRM
+ if (xwl_screen->driver->use_drm && !xwl_drm_initialised(xwl_screen))
+ if (xwl_drm_pre_init(xwl_screen) != Success)
+ return FALSE;
+#endif
+
+ xwayland_screen_preinit_output(xwl_screen, scrninfo);
+
+ return TRUE;
+}
+
+int
+xwl_create_window_buffer_shm(struct xwl_window *xwl_window,
+ PixmapPtr pixmap, int fd)
+{
+ struct wl_shm_pool *pool;
+ WindowPtr window = xwl_window->window;
+ ScreenPtr screen = window->drawable.pScreen;
+ VisualID visual = wVisual(window);
+ uint32_t format;
+ int size, stride, bpp, i;
+
+ for (i = 0; i < screen->numVisuals; i++)
+ if (screen->visuals[i].vid == visual)
+ break;
+
+ switch (screen->visuals[i].nplanes) {
+ case 32:
+ format = WL_SHM_FORMAT_ARGB8888;
+ bpp = 4;
+ break;
+ case 24:
+ default:
+ format = WL_SHM_FORMAT_XRGB8888;
+ bpp = 4;
+ break;
+#ifdef WL_SHM_FORMAT_RGB565
+ case 16:
+ /* XXX: Check run-time protocol version too */
+ format = WL_SHM_FORMAT_RGB565;
+ bpp = 2;
+ break;
+#endif
+ }
+
+ stride = pixmap->drawable.width * bpp;
+ size = stride * pixmap->drawable.height;
+
+ pool = wl_shm_create_pool(xwl_window->xwl_screen->shm, fd, size);
+ xwl_window->buffer = wl_shm_pool_create_buffer(pool, 0,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ stride, format);
+ wl_shm_pool_destroy(pool);
+
+ return xwl_window->buffer ? Success : BadDrawable;
+}
+
+void xwl_screen_close(struct xwl_screen *xwl_screen)
+{
+ struct xwl_seat *xwl_seat, *itmp;
+ struct xwl_window *xwl_window, *wtmp;
+
+ if (xwl_screen->registry)
+ wl_registry_destroy(xwl_screen->registry);
+ xwl_screen->registry = NULL;
+
+ xorg_list_for_each_entry_safe(xwl_seat, itmp,
+ &xwl_screen->seat_list, link) {
+ wl_seat_destroy(xwl_seat->seat);
+ free(xwl_seat);
+ }
+ xorg_list_for_each_entry_safe(xwl_window, wtmp,
+ &xwl_screen->window_list, link) {
+ wl_buffer_destroy(xwl_window->buffer);
+ wl_surface_destroy(xwl_window->surface);
+ free(xwl_window);
+ }
+
+ xorg_list_init(&xwl_screen->seat_list);
+ xorg_list_init(&xwl_screen->damage_window_list);
+ xorg_list_init(&xwl_screen->window_list);
+ xorg_list_init(&xwl_screen->authenticate_client_list);
+
+ wl_display_roundtrip(xwl_screen->display);
+}
+
+void xwl_screen_destroy(struct xwl_screen *xwl_screen)
+{
+ struct xwl_output *xwl_output, *tmp;
+
+ xorg_list_for_each_entry_safe (xwl_output, tmp, &xwl_screen->output_list, link) {
+ xwl_output_remove(xwl_output);
+ break;
+ }
+
+ free(xwl_screen);
+}
+
+/* DDX driver must call this after submitting the rendering */
+void xwl_screen_post_damage(struct xwl_screen *xwl_screen)
+{
+ struct xwl_window *xwl_window;
+ RegionPtr region;
+ BoxPtr box;
+ int count, i;
+
+ xorg_list_for_each_entry(xwl_window, &xwl_screen->damage_window_list,
+ link_damage) {
+ region = DamageRegion(xwl_window->damage);
+ count = RegionNumRects(region);
+ 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_attach(xwl_window->surface,
+ xwl_window->buffer,
+ 0, 0);
+ wl_surface_commit(xwl_window->surface);
+ DamageEmpty(xwl_window->damage);
+ }
+
+ xorg_list_init(&xwl_screen->damage_window_list);
+}
+
+static void *
+xwl_setup(void *module, void *opts, int *errmaj, int *errmin)
+{
+ return module;
+}
+
+static void
+xwl_teardown(void *p)
+{
+}
+
+static XF86ModuleVersionInfo xwl_version_info = {
+ "xwayland",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ 1, 0, 0,
+ ABI_CLASS_EXTENSION,
+ ABI_EXTENSION_VERSION,
+ MOD_CLASS_NONE,
+ { 0, 0, 0, 0 }
+};
+
+_X_EXPORT const XF86ModuleData xwaylandModuleData = {
+ &xwl_version_info,
+ &xwl_setup,
+ &xwl_teardown
+};
+
+int
+xwl_version(void)
+{
+ return xwl_version_info.minorversion;
+}
diff --git a/hw/xfree86/xwayland/xwayland.h b/hw/xfree86/xwayland/xwayland.h
new file mode 100644
index 000000000..7f81e2cfc
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland.h
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#ifndef _XWAYLAND_H_
+#define _XWAYLAND_H_
+
+#include <xf86str.h>
+
+
+#define XWL_VERSION 2
+
+struct xwl_window;
+struct xwl_screen;
+
+struct xwl_driver {
+ int version;
+ int use_drm;
+ int (*create_window_buffer)(struct xwl_window *xwl_window,
+ PixmapPtr pixmap);
+};
+
+#define XWL_FLAGS_ROOTLESS 0x01
+
+extern _X_EXPORT int
+xwl_version(void);
+
+extern _X_EXPORT struct xwl_screen *
+xwl_screen_create(void);
+
+extern _X_EXPORT Bool
+xwl_screen_pre_init(ScrnInfoPtr scrninfo, struct xwl_screen *xwl_screen,
+ uint32_t flags, struct xwl_driver *driver);
+
+extern _X_EXPORT int
+xwl_screen_init(struct xwl_screen *xwl_screen, ScreenPtr screen);
+
+extern _X_EXPORT int
+xwl_drm_pre_init(struct xwl_screen *xwl_screen);
+
+extern _X_EXPORT int
+xwl_screen_get_drm_fd(struct xwl_screen *xwl_screen);
+
+extern _X_EXPORT void
+xwl_screen_close(struct xwl_screen *xwl_screen);
+
+extern _X_EXPORT void
+xwl_screen_destroy(struct xwl_screen *xwl_screen);
+
+extern _X_EXPORT void
+xwl_screen_post_damage(struct xwl_screen *xwl_screen);
+
+extern _X_EXPORT int
+xwl_drm_authenticate(ClientPtr client, struct xwl_screen *xwl_screen,
+ uint32_t magic);
+
+extern _X_EXPORT int
+xwl_create_window_buffer_drm(struct xwl_window *xwl_window,
+ PixmapPtr pixmap, uint32_t name);
+
+extern _X_EXPORT int
+xwl_create_window_buffer_shm(struct xwl_window *xwl_window,
+ PixmapPtr pixmap, int fd);
+
+#endif /* _XWAYLAND_H_ */
diff --git a/include/input.h b/include/input.h
index 36463f2d1..afbb37026 100644
--- a/include/input.h
+++ b/include/input.h
@@ -508,7 +508,7 @@ extern int AttachDevice(ClientPtr client,
DeviceIntPtr slave, DeviceIntPtr master);
extern _X_EXPORT DeviceIntPtr GetPairedDevice(DeviceIntPtr kbd);
-extern DeviceIntPtr GetMaster(DeviceIntPtr dev, int type);
+extern _X_EXPORT DeviceIntPtr GetMaster(DeviceIntPtr dev, int type);
extern _X_EXPORT int AllocDevicePair(ClientPtr client,
const char *name,
diff --git a/include/os.h b/include/os.h
index 3b4e8f341..5be3bcc49 100644
--- a/include/os.h
+++ b/include/os.h
@@ -166,10 +166,9 @@ extern _X_EXPORT void MakeClientGrabImpervious(ClientPtr /*client */ );
extern _X_EXPORT void MakeClientGrabPervious(ClientPtr /*client */ );
-#if defined(XQUARTZ) || defined(XORG_WAYLAND)
extern _X_EXPORT void ListenOnOpenFD(int /* fd */ , int /* noxauth */ );
+
extern _X_EXPORT void AddClientOnOpenFD(int /* fd */ );
-#endif
extern _X_EXPORT CARD32 GetTimeInMillis(void);
extern _X_EXPORT CARD64 GetTimeInMicros(void);
diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in
index 487d7addb..b5b0ed499 100644
--- a/include/xorg-config.h.in
+++ b/include/xorg-config.h.in
@@ -145,4 +145,7 @@
/* Support APM/ACPI power management in the server */
#undef XF86PM
+/* Building Xorg server. */
+#undef XORG_WAYLAND
+
#endif /* _XORG_CONFIG_H_ */
diff --git a/include/xorg-server.h.in b/include/xorg-server.h.in
index 8bf9d38f2..b4180f4a6 100644
--- a/include/xorg-server.h.in
+++ b/include/xorg-server.h.in
@@ -227,4 +227,7 @@
/* Ask fontsproto to make font path element names const */
#define FONT_PATH_ELEMENT_NAME_CONST 1
+/* Building Xorg server. */
+#undef XORG_WAYLAND
+
#endif /* _XORG_SERVER_H_ */
diff --git a/os/connection.c b/os/connection.c
index b0e999e33..848e72316 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -64,7 +64,6 @@ SOFTWARE.
#include <dix-config.h>
#endif
-#include <xorg-server.h>
#ifdef WIN32
#include <X11/Xwinsock.h>
#endif
@@ -1259,7 +1258,6 @@ MakeClientGrabPervious(ClientPtr client)
}
}
-#if defined(XQUARTZ) || defined(XORG_WAYLAND)
/* Add a fd (from launchd) to our listeners */
void
ListenOnOpenFD(int fd, int noxauth)
@@ -1334,5 +1332,3 @@ AddClientOnOpenFD(int fd)
return;
}
}
-
-#endif