[PATCH 6/6] Add hosted XWayland module
Daniel Stone
daniel at fooishbar.org
Tue Nov 6 22:58:23 PST 2012
XWayland is a (usually rootless) module which backs on to a running
Wayland compositor, backed by either a hardware driver such as Intel, or
a software-only driver such as xf86-video-wlshm.
Signed-off-by: Kristian Høgsberg <krh at redhat.com>
Co-authored-by: Christopher James Halse Rogers <christopher.halse.rogers at canonical.com>
Co-authored-by: Corentin Chary <corentin.chary at gmail.com>
Co-authored-by: Daniel Stone <daniel at fooishbar.org>
Co-authored-by: Robert Bragg <robert at linux.intel.com>
Co-authored-by: Scott Moreau <oreaus at gmail.com>
Co-authored-by: Tiago Vignatti <tiago.vignatti at intel.com>
---
configure.ac | 16 +-
hw/xfree86/Makefile.am | 9 +-
hw/xfree86/common/xf86AutoConfig.c | 5 +
hw/xfree86/common/xf86Bus.c | 2 +
hw/xfree86/common/xf86Config.c | 33 +-
hw/xfree86/common/xf86Globals.c | 2 +
hw/xfree86/common/xf86Init.c | 33 +-
hw/xfree86/common/xf86Priv.h | 2 +
hw/xfree86/common/xf86Xinput.h | 9 +-
hw/xfree86/xwayland/Makefile.am | 46 +++
hw/xfree86/xwayland/drm.xml | 139 ++++++++
hw/xfree86/xwayland/xserver.xml | 20 ++
hw/xfree86/xwayland/xwayland-cursor.c | 241 ++++++++++++++
hw/xfree86/xwayland/xwayland-drm.c | 193 +++++++++++
hw/xfree86/xwayland/xwayland-input.c | 549 ++++++++++++++++++++++++++++++++
hw/xfree86/xwayland/xwayland-output.c | 311 ++++++++++++++++++
hw/xfree86/xwayland/xwayland-private.h | 128 ++++++++
hw/xfree86/xwayland/xwayland-window.c | 353 ++++++++++++++++++++
hw/xfree86/xwayland/xwayland.c | 423 ++++++++++++++++++++++++
hw/xfree86/xwayland/xwayland.h | 83 +++++
include/dix.h | 2 +-
include/os.h | 5 +-
include/xorg-config.h.in | 3 +
include/xorg-server.h.in | 3 +
os/connection.c | 23 +-
25 files changed, 2613 insertions(+), 20 deletions(-)
create mode 100644 hw/xfree86/xwayland/Makefile.am
create mode 100644 hw/xfree86/xwayland/drm.xml
create mode 100644 hw/xfree86/xwayland/xserver.xml
create mode 100644 hw/xfree86/xwayland/xwayland-cursor.c
create mode 100644 hw/xfree86/xwayland/xwayland-drm.c
create mode 100644 hw/xfree86/xwayland/xwayland-input.c
create mode 100644 hw/xfree86/xwayland/xwayland-output.c
create mode 100644 hw/xfree86/xwayland/xwayland-private.h
create mode 100644 hw/xfree86/xwayland/xwayland-window.c
create mode 100644 hw/xfree86/xwayland/xwayland.c
create mode 100644 hw/xfree86/xwayland/xwayland.h
diff --git a/configure.ac b/configure.ac
index 38ac240..69cb1dd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -628,6 +628,7 @@ AC_ARG_ENABLE(windowswm, AS_HELP_STRING([--enable-windowswm], [Build XWin w
AC_ARG_ENABLE(libdrm, AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes])
AC_ARG_ENABLE(clientids, AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes])
AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=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])
@@ -1008,6 +1009,17 @@ if test "x$COMPOSITE" = xyes; then
COMPOSITE_INC='-I$(top_srcdir)/composite'
fi
+WAYLAND_MODULES="[wayland-client >= 1.0]"
+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])
+
if test "x$MITSHM" = xauto; then
MITSHM="$ac_cv_sysv_ipc"
fi
@@ -1104,12 +1116,13 @@ case "$DRI2,$HAVE_DRI2PROTO" in
esac
AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes)
-if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$CONFIG_UDEV_KMS" = xyes; then
+if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$CONFIG_UDEV_KMS" = xyes || test "x$WAYLAND" = xyes; then
if test "x$DRM" = xyes; then
AC_DEFINE(WITH_LIBDRM, 1, [Building with libdrm support])
PKG_CHECK_MODULES([LIBDRM], $LIBDRM)
fi
fi
+AM_CONDITIONAL(DRM, test "x$DRM" = xyes)
if test "x$DRI2" = xyes; then
save_CFLAGS=$CFLAGS
@@ -2253,6 +2266,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 c3899b5..d0ca06f 100644
--- a/hw/xfree86/Makefile.am
+++ b/hw/xfree86/Makefile.am
@@ -9,6 +9,10 @@ DRI2_SUBDIR = dri2
DRI2_LIB = dri2/libdri2.la
endif
+if WAYLAND
+WAYLAND_SUBDIR = xwayland
+endif
+
if XF86UTILS
XF86UTILS_SUBDIR = utils
endif
@@ -28,11 +32,12 @@ endif
SUBDIRS = common ddc x86emu $(INT10_SUBDIR) os-support parser \
ramdac $(VGAHW_SUBDIR) loader modes $(DRI_SUBDIR) \
$(DRI2_SUBDIR) . $(VBE_SUBDIR) i2c dixmods \
- fbdevhw shadowfb exa $(XF86UTILS_SUBDIR) doc man
+ fbdevhw shadowfb exa $(XF86UTILS_SUBDIR) $(WAYLAND_SUBDIR) \
+ doc man
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 95d58fe..825c676 100644
--- a/hw/xfree86/common/xf86AutoConfig.c
+++ b/hw/xfree86/common/xf86AutoConfig.c
@@ -280,6 +280,11 @@ listPossibleVideoDrivers(char *matches[], int nmatches)
matches[i++] = xnfstrdup("modesetting");
#endif
+#ifdef XORG_WAYLAND
+ if (xorgWayland)
+ matches[i++] = xnfstrdup("wlshm");
+#endif
+
#if !defined(sun)
/* Fallback to platform default frame buffer driver */
if (i < (nmatches - 1)) {
diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index e101537..0e845ad 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -123,6 +123,8 @@ xf86BusConfig(void)
* instance of the hardware found.
*/
for (i = 0; i < xf86NumDrivers; i++) {
+ if (!xf86DriverList[i])
+ continue;
xf86CallDriverProbe(xf86DriverList[i], FALSE);
}
diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index 486752b..19a1c53 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -117,7 +117,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 */
@@ -259,6 +260,19 @@ xf86ModulelistFromConfig(pointer **optlist)
return NULL;
}
+ /*
+ * Set the xwayland module to autoload if requested.
+ */
+#ifdef XORG_WAYLAND
+ if (xorgWayland) {
+ for (i=0 ; ModuleDefaults[i].name != NULL ; i++) {
+ if (strcmp(ModuleDefaults[i].name, "xwayland") == 0) {
+ ModuleDefaults[i].toLoad = TRUE;
+ }
+ }
+ }
+#endif
+
if (xf86configptr->conf_modules) {
/* Walk the disable list and let people know what we've parsed to
* not be loaded
@@ -782,6 +796,14 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts)
set.variant = NULL;
set.options = NULL;
+ /* FIXME: Do that at the right place (before xf86Msg). */
+#ifdef XORG_WAYLAND
+ if (xorgWayland) {
+ xf86Info.autoAddDevices = FALSE;
+ xf86Info.autoEnableDevices = FALSE;
+ }
+#endif
+
/*
* Merge the ServerLayout and ServerFlags options. The former have
* precedence over the latter.
@@ -952,9 +974,12 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts)
}
#endif
- /* if we're not hotplugging, force some input devices to exist */
- xf86Info.forceInputDevices = !(xf86Info.autoAddDevices &&
- xf86Info.autoEnableDevices);
+#ifdef XORG_WAYLAND
+ if (xorgWayland) /* Don't force input devices */
+ xf86Info.forceInputDevices = FALSE;
+ else /* if we're not hotplugging, force some input devices to exist */
+#endif
+ 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 7df7a80..b41d2cc 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 1695dbf..5449b4f 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -541,11 +541,19 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
GET_REQUIRED_HW_INTERFACES,
&flags);
+#ifdef XORG_WAYLAND
+ if (xorgWayland &&
+ (NEED_IO_ENABLED(flags) || !(flags & HW_SKIP_CONSOLE))) {
+
+ ErrorF("flags %lu, deleting\n", flags);
+
+ xf86DeleteDriver(i);
+ continue;
+ }
+#endif
+
if (NEED_IO_ENABLED(flags))
want_hw_access = TRUE;
-
- if (!(flags & HW_SKIP_CONSOLE))
- xorgHWOpenConsole = TRUE;
}
if (xorgHWOpenConsole)
@@ -957,6 +965,11 @@ InitInput(int argc, char **argv)
mieqInit();
+#ifdef XORG_WAYLAND
+ if (xorgWayland)
+ return;
+#endif
+
/* Initialize all configured input devices */
for (pInfo = xf86ConfigLayout.inputs; pInfo && *pInfo; pInfo++) {
(*pInfo)->options =
@@ -1455,6 +1468,20 @@ ddxProcessArgument(int argc, char **argv, int i)
return 1;
}
+#ifdef XORG_WAYLAND
+ if (!strcmp(argv[i], "-wayland"))
+ {
+ xorgWayland = TRUE;
+ return 1;
+ }
+#endif
+
+ 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 58cfe0a..6d60c7e 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/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index 35c38a5..b0f94c1 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -172,14 +172,11 @@ extern _X_EXPORT void xf86AddEnabledDevice(InputInfoPtr pInfo);
extern _X_EXPORT void xf86RemoveEnabledDevice(InputInfoPtr pInfo);
extern _X_EXPORT void xf86DisableDevice(DeviceIntPtr dev, Bool panic);
extern _X_EXPORT void xf86EnableDevice(DeviceIntPtr dev);
-
-/* not exported */
-int xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL is_auto);
-InputInfoPtr xf86AllocateInput(void);
+extern _X_EXPORT int xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL is_auto);
+extern _X_EXPORT InputInfoPtr xf86AllocateInput(void);
/* xf86Helper.c */
-extern _X_EXPORT void xf86AddInputDriver(InputDriverPtr driver, pointer module,
- int flags);
+extern _X_EXPORT void xf86AddInputDriver(InputDriverPtr driver, pointer module, int flags);
extern _X_EXPORT void xf86DeleteInputDriver(int drvIndex);
extern _X_EXPORT InputDriverPtr xf86LookupInputDriver(const char *name);
extern _X_EXPORT InputInfoPtr xf86LookupInput(const char *name);
diff --git a/hw/xfree86/xwayland/Makefile.am b/hw/xfree86/xwayland/Makefile.am
new file mode 100644
index 0000000..a192b0c
--- /dev/null
+++ b/hw/xfree86/xwayland/Makefile.am
@@ -0,0 +1,46 @@
+INCLUDES = \
+ $(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)
+
+ at wayland_scanner_rules@
diff --git a/hw/xfree86/xwayland/drm.xml b/hw/xfree86/xwayland/drm.xml
new file mode 100644
index 0000000..89fd8f0
--- /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 0000000..2900fef
--- /dev/null
+++ b/hw/xfree86/xwayland/xserver.xml
@@ -0,0 +1,20 @@
+<protocol name="xserver">
+
+ <interface name="xserver" version="2">
+ <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>
+
+ <request name="init_complete"/>
+ </interface>
+
+</protocol>
diff --git a/hw/xfree86/xwayland/xwayland-cursor.c b/hw/xfree86/xwayland/xwayland-cursor.c
new file mode 100644
index 0000000..eb1106c
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland-cursor.c
@@ -0,0 +1,241 @@
+/*
+ * 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 <xorg-server.h>
+#include <cursorstr.h>
+#include <xf86Crtc.h>
+#include <mipointrst.h>
+
+#include "xwayland.h"
+#include "xwayland-private.h"
+#include "xserver-client-protocol.h"
+
+static DevPrivateKeyRec xwl_cursor_private_key;
+
+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_cursor_private_key, buffer);
+
+ return TRUE;
+}
+
+static Bool
+xwl_unrealize_cursor(DeviceIntPtr device,
+ ScreenPtr screen, CursorPtr cursor)
+{
+ struct wl_buffer *buffer;
+
+ buffer = dixGetPrivate(&cursor->devPrivates, &xwl_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->x_cursor || !xwl_seat->wl_pointer)
+ return;
+
+ buffer = dixGetPrivate(&xwl_seat->x_cursor->devPrivates,
+ &xwl_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_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 0000000..a7bd4a6
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland-drm.c
@@ -0,0 +1,193 @@
+/*
+ * 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"
+
+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;
+
+ xwl_screen->authenticated = 1;
+}
+
+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, version);
+ wl_drm_add_listener(xwl_screen->drm, &xwl_drm_listener, xwl_screen);
+ }
+}
+
+static const struct wl_registry_listener drm_listener = {
+ drm_handler,
+};
+
+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(struct xwl_screen *xwl_screen,
+ uint32_t magic)
+{
+ int ret;
+
+ xwl_screen->authenticated = 0;
+
+ if (xwl_screen->drm)
+ wl_drm_authenticate (xwl_screen->drm, magic);
+
+ ret = wl_display_flush(xwl_screen->display);
+ if (ret == -1)
+ return BadAlloc;
+ ret = wl_display_dispatch(xwl_screen->display);
+ if (ret == -1)
+ return BadAlloc;
+
+ if (!xwl_screen->authenticated)
+ wl_display_roundtrip(xwl_screen->display);
+
+ 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;
+ int i;
+
+ visual = wVisual(window);
+ for (i = 0; i < screen->numVisuals; i++)
+ if (screen->visuals[i].vid == visual)
+ break;
+
+ xwl_window->buffer =
+ wl_drm_create_buffer(xwl_window->xwl_screen->drm,
+ name,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ pixmap->devKind,
+ WL_DRM_FORMAT_ARGB8888);
+
+ 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 0000000..882edd9
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland-input.c
@@ -0,0 +1,549 @@
+/*
+ * Copyright © 2008 Kristian Høgsberg
+ * Copyright © 2012 Raspberry Pi Foundation
+ *
+ * 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 <inputstr.h>
+#include <exevents.h>
+#include <xkbsrv.h>
+#include <xf86Xinput.h>
+#include <xf86Crtc.h>
+#include <xf86str.h>
+#include <windowstr.h>
+#include <xf86Priv.h>
+#include <mipointrst.h>
+
+#include "xwayland.h"
+#include "xwayland-private.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)
+{
+ XkbRMLVOSet rmlvo;
+
+ switch (what) {
+ case DEVICE_INIT:
+ device->public.on = FALSE;
+
+ /* FIXME: Get the keymap from wl_keyboard::keymap events, which
+ * requires more X server API to set a keymap from a string
+ * rather than RMLVO. */
+ rmlvo.rules = "evdev";
+ rmlvo.model = "evdev";
+ rmlvo.layout = "us";
+ rmlvo.variant = NULL;
+ rmlvo.options = NULL;
+
+ if (!InitKeyboardDeviceStruct(device, &rmlvo, 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
+xwl_keyboard_uninit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+{
+}
+
+static int
+xwl_keyboard_init(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+{
+ pInfo->type_name = "xwayland-keyboard";
+ pInfo->device_control = xwl_keyboard_proc;
+ pInfo->read_input = NULL;
+ pInfo->control_proc = NULL;
+ pInfo->switch_mode = NULL;
+ pInfo->fd = -1;
+
+ return Success;
+}
+
+_X_EXPORT InputDriverRec xwl_keyboard_driver = {
+ 1,
+ "xwayland-keyboard",
+ NULL,
+ xwl_keyboard_init,
+ xwl_keyboard_uninit,
+ NULL,
+};
+
+static void
+xwl_pointer_uninit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+{
+}
+
+static int
+xwl_pointer_init(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+{
+ pInfo->type_name = "xwayland-pointer";
+ pInfo->device_control = xwl_pointer_proc;
+ pInfo->read_input = NULL;
+ pInfo->control_proc = NULL;
+ pInfo->switch_mode = NULL;
+ pInfo->fd = -1;
+
+ return Success;
+}
+
+_X_EXPORT InputDriverRec xwl_pointer_driver = {
+ 1,
+ "xwayland-pointer",
+ NULL,
+ xwl_pointer_init,
+ xwl_pointer_uninit,
+ NULL,
+};
+
+void
+xwl_input_teardown(pointer p)
+{
+}
+
+pointer
+xwl_input_setup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ xf86AddInputDriver(&xwl_keyboard_driver, module, 0);
+ xf86AddInputDriver(&xwl_pointer_driver, module, 0);
+
+ return module;
+}
+
+static DeviceIntPtr
+device_added(struct xwl_seat *xwl_seat, const char *driver)
+{
+ DeviceIntPtr dev = NULL;
+ InputInfoPtr pInfo;
+ int rc;
+
+ pInfo = xf86AllocateInput();
+ if (!pInfo)
+ return NULL;
+
+ pInfo->driver = xstrdup(driver);
+
+ if (asprintf(&pInfo->name, "%s:%d", pInfo->driver, xwl_seat->id) == -1) {
+ free(pInfo);
+ return NULL;
+ }
+
+ pInfo->private = xwl_seat;
+
+ rc = xf86NewInputDevice(pInfo, &dev, 1);
+ if (rc != Success) {
+ free(pInfo);
+ return NULL;
+ }
+
+ LogMessage(X_INFO, "config/xwayland: Adding input device %s\n",
+ pInfo->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;
+
+ 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. */
+ for (i = 0; i < dev->button->numButtons; i++)
+ if (BitIsOn(dev->button->down, i))
+ xf86PostButtonEvent(dev, TRUE, i, 0, 0, 0);
+
+ (*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;
+ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
+ int32_t dx, dy, lx, ly;
+ int sx = wl_fixed_to_int(sx_w);
+ int sy = wl_fixed_to_int(sy_w);
+
+ if (!xwl_seat->focus_window)
+ return ;
+
+ dx = xwl_seat->focus_window->window->drawable.x;
+ dy = xwl_seat->focus_window->window->drawable.y;
+
+ lx = xf86ScaleAxis(sx + dx, 0xFFFF, 0, xwl_screen->scrninfo->virtualX, 0);
+ ly = xf86ScaleAxis(sy + dy, 0xFFFF, 0, xwl_screen->scrninfo->virtualY, 0);
+
+ xf86PostMotionEvent(xwl_seat->pointer, TRUE, 0, 2, lx, ly);
+}
+
+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;
+
+ 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;
+ }
+
+ xf86PostButtonEvent(xwl_seat->pointer, TRUE, index, state, 0, 0);
+}
+
+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;
+ int val = wl_fixed_to_int(value);
+
+ /* FIXME: Need to do proper smooth scrolling here! */
+ if (val == 1)
+ index = 4;
+ else if (val == -1)
+ index = 5;
+ else
+ return;
+
+ xf86PostButtonEvent(xwl_seat->pointer, TRUE, index, 1, 0, 0);
+ xf86PostButtonEvent(xwl_seat->pointer, TRUE, index, 0, 0, 0);
+}
+
+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;
+
+ xwl_seat->xwl_screen->serial = serial;
+
+ end = 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 = (void *) end - xwl_seat->keys.data;
+ if (state) {
+ k = wl_array_add(&xwl_seat->keys, sizeof *k);
+ *k = key;
+ }
+
+ xf86PostKeyboardEvent(xwl_seat->keyboard, key + 8, state);
+}
+
+static void
+keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
+ uint32_t format, int fd, uint32_t size)
+{
+ /* FIXME: Handle keymap */
+
+ 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;
+ uint32_t *k;
+
+ xwl_seat->xwl_screen->serial = serial;
+
+ wl_array_copy(&xwl_seat->keys, keys);
+ wl_array_for_each(k, &xwl_seat->keys)
+ xf86PostKeyboardEvent(xwl_seat->keyboard, *k + 8, 1);
+}
+
+static void
+keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
+ uint32_t serial, struct wl_surface *surface)
+{
+ struct xwl_seat *xwl_seat = data;
+ uint32_t *k;
+
+ xwl_seat->xwl_screen->serial = serial;
+
+ wl_array_for_each(k, &xwl_seat->keys)
+ xf86PostKeyboardEvent(xwl_seat->keyboard, *k + 8, 0);
+}
+
+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)
+{
+ /* FIXME: Need more server XKB API here. */
+}
+
+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
+seat_handle_capabilities(void *data, struct wl_seat *seat,
+ enum wl_seat_capability caps)
+{
+ struct xwl_seat *xwl_seat = data;
+
+ if (caps & WL_SEAT_CAPABILITY_POINTER) {
+ xwl_seat->pointer = device_added(xwl_seat, "xwayland-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->keyboard = device_added(xwl_seat, "xwayland-keyboard");
+ xwl_seat->wl_keyboard = wl_seat_get_keyboard(seat);
+ wl_keyboard_add_listener(xwl_seat->wl_keyboard,
+ &keyboard_listener, xwl_seat);
+ }
+ /* 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,
+ uint32_t version)
+{
+ 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,
+ version);
+ 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, version);
+ }
+}
+
+static const struct wl_registry_listener input_listener = {
+ input_handler,
+};
+
+void
+xwl_input_init(struct xwl_screen *xwl_screen)
+{
+ int ret;
+
+ 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 0000000..58f699f
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland-output.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ * Copyright © 2012 Raspberry Pi Foundation
+ *
+ * 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 <xorg-server.h>
+#include <cursorstr.h>
+#include <xf86Crtc.h>
+#include <mipointrst.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 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 = NULL, /* XXX */
+};
+
+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;
+
+ xwl_output = calloc(sizeof *xwl_output, 1);
+ if (xwl_output == NULL) {
+ ErrorF("create_output ENOMEM");
+ return NULL;
+ }
+
+ xwl_output->xwl_screen = xwl_screen;
+
+ xf86output = xf86OutputCreate(xwl_screen->scrninfo,
+ &output_funcs, "XWAYLAND-1");
+ xf86output->driver_private = xwl_output;
+ xf86output->possible_crtcs = 1;
+ xf86output->possible_clones = 1;
+
+ xf86crtc = xf86CrtcCreate(xwl_screen->scrninfo, &crtc_funcs);
+ xf86crtc->driver_private = xwl_output;
+
+ xwl_output->xf86output = xf86output;
+ xwl_output->xf86crtc = xf86crtc;
+
+ 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 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_screen->xwl_output = xwl_output;
+}
+
+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;
+
+ if (flags & WL_OUTPUT_MODE_CURRENT) {
+ xwl_output->width = width;
+ xwl_output->height = height;
+ }
+}
+
+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;
+ int ret;
+
+ if (strcmp(interface, "wl_output") == 0) {
+ xwl_output = xwl_output_create(xwl_screen);
+ xwl_output->output = wl_registry_bind(registry, id,
+ &wl_output_interface, version);
+ wl_output_add_listener(xwl_output->output,
+ &output_listener, xwl_output);
+ }
+}
+
+static const struct wl_registry_listener global_listener = {
+ global_handler,
+};
+
+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->xwl_output) {
+ ret = wl_display_roundtrip(xwl_screen->display);
+ if (ret == -1)
+ FatalError("failed to dispatch Wayland events: %s\n", strerror(errno));
+ }
+
+ xf86InitialConfiguration(scrninfo, TRUE);
+}
diff --git a/hw/xfree86/xwayland/xwayland-private.h b/hw/xfree86/xwayland/xwayland-private.h
new file mode 100644
index 0000000..0ab2023
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland-private.h
@@ -0,0 +1,128 @@
+/*
+ * 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_
+
+struct xwl_window {
+ struct xwl_screen *xwl_screen;
+ struct wl_surface *surface;
+ struct wl_buffer *buffer;
+ WindowPtr window;
+ DamagePtr damage;
+ PixmapPtr pixmap;
+ int attach_x;
+ int attach_y;
+ int last_x;
+ int last_y;
+ struct xorg_list link;
+ struct xorg_list link_damage;
+ int window_id_set;
+};
+
+struct xwl_output;
+
+struct xwl_screen {
+ struct xwl_driver *driver;
+ ScreenPtr screen;
+ ScrnInfoPtr scrninfo;
+ int drm_fd;
+ int wayland_fd;
+ struct xwl_output *xwl_output;
+ 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;
+ int supports_init_complete;
+ uint32_t mask;
+ uint32_t flags;
+ char *device_name;
+ uint32_t authenticated;
+ struct xorg_list seat_list;
+ struct xorg_list damage_window_list;
+ struct xorg_list window_list;
+ uint32_t serial;
+
+ CreateWindowProcPtr CreateWindow;
+ RealizeWindowProcPtr RealizeWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ SetWindowPixmapProcPtr SetWindowPixmap;
+ ConfigNotifyProcPtr ConfigNotify;
+ miPointerSpriteFuncPtr sprite_funcs;
+};
+
+struct xwl_output {
+ struct wl_output *output;
+ struct xwl_screen *xwl_screen;
+ int32_t x, y, width, height;
+ xf86Monitor xf86monitor;
+ xf86OutputPtr xf86output;
+ xf86CrtcPtr xf86crtc;
+};
+
+
+#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;
+};
+
+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_teardown(pointer p);
+pointer xwl_input_setup(pointer module, pointer opts, int *errmaj, int *errmin);
+void xwl_input_init(struct xwl_screen *screen);
+
+Bool xwl_drm_initialised(struct xwl_screen *screen);
+
+Bool xwl_window_has_alpha(struct xwl_window *xwl_window);
+
+void xwl_seat_set_cursor(struct xwl_seat *xwl_seat);
+
+#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 0000000..425d45a
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland-window.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ * Copyright © 2012 Raspberry Pi Foundation
+ *
+ * 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 <X11/extensions/compositeproto.h>
+
+#include <xorg-server.h>
+#include <xf86Crtc.h>
+#include <selection.h>
+#include <compositeext.h>
+#include <exevents.h>
+
+#include "xwayland.h"
+#include "xwayland-private.h"
+#include "xserver-client-protocol.h"
+
+static DevPrivateKeyRec xwl_window_private_key;
+
+Bool
+xwl_window_has_alpha(struct xwl_window *xwl_window)
+{
+ WindowPtr window = xwl_window->window;
+ ScreenPtr pScreen = window->drawable.pScreen;
+ VisualPtr visual;
+ VisualID vid = wVisual(window);
+ int rgb_bits = 0;
+ int i;
+
+ for (i = 0; i < pScreen->numVisuals; i++) {
+ visual = &pScreen->visuals[i];
+ if (visual->vid != vid)
+ continue;
+
+ rgb_bits += CountBits((uint8_t *) &visual->redMask, 32);
+ rgb_bits += CountBits((uint8_t *) &visual->greenMask, 32);
+ rgb_bits += CountBits((uint8_t *) &visual->blueMask, 32);
+
+ return (visual->nplanes > rgb_bits);
+ }
+
+ BUG_WARN(i == pScreen->numVisuals);
+ return FALSE;
+}
+
+static void
+xwl_window_attach(struct xwl_window *xwl_window, PixmapPtr pixmap)
+{
+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+ struct wl_buffer *old_buffer = xwl_window->buffer;
+ struct xwl_window *tmp_window;
+
+ if (xwl_window->pixmap == pixmap)
+ return;
+
+ xwl_screen->driver->create_window_buffer(xwl_window, pixmap);
+ if (!xwl_window->buffer) {
+ ErrorF("failed to create buffer\n");
+ return;
+ }
+
+ xwl_window->pixmap = pixmap;
+
+ wl_surface_attach(xwl_window->surface, xwl_window->buffer,
+ xwl_window->attach_x,
+ xwl_window->attach_y);
+ wl_surface_damage(xwl_window->surface, 0, 0,
+ pixmap->drawable.width, pixmap->drawable.height);
+
+ if (old_buffer)
+ wl_buffer_destroy(old_buffer);
+
+ xorg_list_for_each_entry(tmp_window, &xwl_screen->damage_window_list,
+ link_damage) {
+ if (tmp_window == xwl_window)
+ return;
+ }
+ xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
+}
+
+static void
+damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
+{
+ struct xwl_window *xwl_window = data;
+ struct xwl_window *tmp_window;
+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+
+ xorg_list_for_each_entry(tmp_window, &xwl_screen->damage_window_list,
+ link_damage) {
+ if (tmp_window == xwl_window)
+ return;
+ }
+ xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
+}
+
+static void
+damage_destroy(DamagePtr pDamage, void *data)
+{
+}
+
+static Bool
+xwl_create_window(WindowPtr window)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ struct xwl_screen *xwl_screen;
+ Bool ret;
+
+ xwl_screen = xwl_screen_get(screen);
+
+ screen->CreateWindow = xwl_screen->CreateWindow;
+ ret = (*screen->CreateWindow)(window);
+ xwl_screen->CreateWindow = screen->CreateWindow;
+ screen->CreateWindow = xwl_create_window;
+
+ if ((xwl_screen->flags & XWL_FLAGS_ROOTLESS) && !window->parent)
+ CompositeRedirectSubwindows(window, CompositeRedirectManual);
+
+ return ret;
+}
+
+static void
+wrap_window(WindowPtr window)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ struct xwl_screen *xwl_screen;
+ struct xwl_window *xwl_window;
+ Selection *selection;
+ char buffer[32];
+ int len;
+ Atom name;
+
+ xwl_screen = xwl_screen_get(screen);
+
+ xwl_window = calloc(sizeof *xwl_window, 1);
+ xwl_window->xwl_screen = xwl_screen;
+ xwl_window->window = window;
+ dixSetPrivate(&window->devPrivates,
+ &xwl_window_private_key, xwl_window);
+
+ len = snprintf(buffer, sizeof buffer, "_NET_WM_CM_S%d", screen->myNum);
+ name = MakeAtom(buffer, len, TRUE);
+ AddSelection(&selection, name, serverClient);
+
+ selection->lastTimeChanged = currentTime;
+ selection->window = window->drawable.id;
+ selection->pWin = window;
+ selection->client = serverClient;
+
+ xwl_window->surface =
+ wl_compositor_create_surface(xwl_screen->compositor);
+ if (xwl_window->surface == NULL) {
+ ErrorF("wl_display_create_surface failed\n");
+ return;
+ }
+ wl_surface_set_user_data(xwl_window->surface, xwl_window);
+ xserver_set_window_id(xwl_screen->xorg_server,
+ xwl_window->surface, window->drawable.id);
+
+ 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);
+}
+
+static Bool
+xwl_realize_window(WindowPtr window)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ struct xwl_screen *xwl_screen;
+ struct xwl_window *xwl_window;
+ Bool ret;
+ Bool do_wrap = FALSE;
+
+ xwl_screen = xwl_screen_get(screen);
+
+ /* If we're rootless, then we only want top-level windows; if not, then
+ * we've already set up on the top-level window. */
+ if (xwl_screen->flags & XWL_FLAGS_ROOTLESS) {
+ if (window->parent && !window->parent->parent)
+ do_wrap = TRUE;
+ if (window->overrideRedirect)
+ do_wrap = TRUE;
+ }
+ else {
+ if (window->parent)
+ do_wrap = TRUE;
+ }
+
+ if (do_wrap)
+ wrap_window(window);
+
+ screen->RealizeWindow = xwl_screen->RealizeWindow;
+ ret = (*screen->RealizeWindow)(window);
+ xwl_screen->RealizeWindow = xwl_screen->RealizeWindow;
+ screen->RealizeWindow = xwl_realize_window;
+
+ xwl_window =
+ dixLookupPrivate(&window->devPrivates, &xwl_window_private_key);
+ if (xwl_window)
+ xwl_window_attach(xwl_window, (*screen->GetWindowPixmap)(window));
+
+ 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);
+ }
+ }
+
+ xwl_window =
+ dixLookupPrivate(&window->devPrivates, &xwl_window_private_key);
+ if (xwl_window) {
+ if (xwl_window->surface);
+ wl_surface_destroy(xwl_window->surface);
+ if (xwl_window->buffer)
+ wl_buffer_destroy(xwl_window->buffer);
+ xorg_list_del(&xwl_window->link);
+ xorg_list_del(&xwl_window->link_damage);
+ DamageUnregister(&xwl_window->window->drawable, xwl_window->damage);
+ DamageDestroy(xwl_window->damage);
+ free(xwl_window);
+ dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL);
+ }
+
+ screen->UnrealizeWindow = xwl_screen->UnrealizeWindow;
+ ret = (*screen->UnrealizeWindow)(window);
+ xwl_screen->UnrealizeWindow = screen->UnrealizeWindow;
+ screen->UnrealizeWindow = xwl_unrealize_window;
+
+ 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 int
+xwl_configure_window(WindowPtr window, int x, int y, int width, int height,
+ int border_width, WindowPtr sibling)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+ struct xwl_window *xwl_window;
+ int ret = Success;
+
+ screen->ConfigNotify = xwl_screen->ConfigNotify;
+ if (screen->ConfigNotify)
+ ret = (*screen->ConfigNotify)(window, x, y, width, height,
+ border_width, sibling);
+ xwl_screen->ConfigNotify = screen->ConfigNotify;
+ screen->ConfigNotify = xwl_configure_window;
+
+ xwl_window =
+ dixLookupPrivate(&window->devPrivates, &xwl_window_private_key);
+ if (!xwl_window)
+ return ret;
+
+ xwl_window->attach_x += x - xwl_window->last_x;
+ xwl_window->last_x = x;
+ xwl_window->attach_y += y - xwl_window->last_y;
+ xwl_window->last_y = y;
+
+ return ret;
+}
+
+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->CreateWindow = screen->CreateWindow;
+ screen->CreateWindow = xwl_create_window;
+
+ 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->ConfigNotify = screen->ConfigNotify;
+ screen->ConfigNotify = xwl_configure_window;
+
+ return Success;
+}
diff --git a/hw/xfree86/xwayland/xwayland.c b/hw/xfree86/xwayland/xwayland.c
new file mode 100644
index 0000000..873c353
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland.c
@@ -0,0 +1,423 @@
+/*
+ * Copyright © 2008-2011 Kristian Høgsberg
+ * Copyright © 2012 Raspberry Pi Foundation
+ *
+ * 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 <xorg-server.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 Atom xdnd_atom;
+
+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);
+}
+
+static const struct xserver_listener xserver_listener = {
+ xserver_client,
+ xserver_listen_socket
+};
+
+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, version);
+ } else if (strcmp(interface, "wl_shm") == 0) {
+ xwl_screen->shm =
+ wl_registry_bind(registry, id, &wl_shm_interface, version);
+ } else if (strcmp(interface, "xserver") == 0) {
+ xwl_screen->xorg_server =
+ wl_registry_bind(registry, id, &xserver_interface, version);
+ xwl_screen->supports_init_complete = (version >= 2);
+ xserver_add_listener(xwl_screen->xorg_server, &xserver_listener,
+ xwl_screen);
+ }
+}
+
+static const struct wl_registry_listener registry_listener = {
+ registry_global,
+};
+
+static void
+wakeup_handler(pointer data, int err, pointer read_mask)
+{
+ struct xwl_screen *xwl_screen = data;
+ int ret;
+
+ if (err < 0)
+ return;
+
+ /* First dispatch any pending events we might've picked up along the
+ * way, then do a blocking read if there's been any activity on our fd. */
+ ret = wl_display_dispatch_pending(xwl_screen->display);
+ if (ret == -1)
+ FatalError("failed to dispatch Wayland events: %s\n", strerror(errno));
+
+ 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(pointer data, struct timeval **tv, pointer read_mask)
+{
+ struct xwl_screen *xwl_screen = data;
+ int ret;
+
+ 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)
+{
+ int ret;
+
+ 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);
+
+ ret = wl_display_roundtrip(xwl_screen->display);
+ if (ret == -1) {
+ xf86DrvMsg(screen->myNum, X_ERROR,
+ "failed to flush Wayland events: %s\n", strerror(errno));
+ return BadAlloc;
+ }
+
+ if (!xwl_screen->xorg_server) {
+ xf86DrvMsg(screen->myNum, X_ERROR,
+ "host server does not support xserver extension\n");
+ return BadAlloc;
+ }
+
+ if (xwl_screen->supports_init_complete)
+ xserver_init_complete(xwl_screen->xorg_server);
+
+ xwl_input_init(xwl_screen);
+
+ return Success;
+}
+
+struct xwl_screen *
+xwl_screen_get(ScreenPtr screen)
+{
+ return dixLookupPrivate(&screen->devPrivates, &xwl_screen_private_key);
+}
+
+static void
+xwayland_selection_callback(CallbackListPtr *callbacks,
+ pointer data, pointer args)
+{
+ SelectionInfoRec *info = (SelectionInfoRec *) args;
+ Selection *selection = info->selection;
+
+ switch (info->kind) {
+ case SelectionSetOwner:
+ if (selection->selection == xdnd_atom) {
+ if (selection->window != None)
+ ErrorF("client %p starts dnd\n", info->client);
+ else
+ ErrorF("client %p stops dnd\n", info->client);
+ }
+ break;
+ case SelectionWindowDestroy:
+ ErrorF("selection window destroy\n");
+ break;
+ case SelectionClientClose:
+ ErrorF("selection client close\n");
+ break;
+ }
+}
+
+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;
+
+ xdnd_atom = MakeAtom("XdndSelection", 13, 1);
+ if (!AddCallback(&SelectionCallback,
+ xwayland_selection_callback, xwl_screen)) {
+ return FALSE;
+ }
+
+ xorg_list_init(&xwl_screen->seat_list);
+ xorg_list_init(&xwl_screen->damage_window_list);
+ xorg_list_init(&xwl_screen->window_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, ®istry_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;
+}
+
+static void
+buffer_handle_release(void *data, struct wl_buffer *buffer)
+{
+ PixmapPtr pixmap = data;
+ ScreenPtr screen = pixmap->drawable.pScreen;
+
+ screen->DestroyPixmap(pixmap);
+}
+
+static const struct wl_buffer_listener buffer_listener = {
+ buffer_handle_release
+};
+
+int
+xwl_create_window_buffer_shm(struct xwl_window *xwl_window,
+ PixmapPtr pixmap, int fd)
+{
+ struct wl_shm_pool *pool;
+ int size, stride;
+
+ stride = pixmap->drawable.width * 4;
+
+ size = pixmap->drawable.width * pixmap->drawable.height * 4;
+ pool = wl_shm_create_pool(xwl_window->xwl_screen->shm, fd, size);
+ /* It's not really ARGB; we rely on the compositor to set the content
+ * (rather than frame) region as opaque for us. */
+ xwl_window->buffer =
+ wl_shm_pool_create_buffer(pool, 0,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ stride, WL_SHM_FORMAT_ARGB8888);
+ wl_buffer_add_listener(xwl_window->buffer, &buffer_listener, pixmap);
+ 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);
+
+ wl_display_roundtrip(xwl_screen->display);
+}
+
+void xwl_screen_destroy(struct xwl_screen *xwl_screen)
+{
+ if (xwl_screen->xwl_output) {
+ xf86OutputDestroy(xwl_screen->xwl_output->xf86output);
+ xf86CrtcDestroy(xwl_screen->xwl_output->xf86crtc);
+ }
+
+ free(xwl_screen->xwl_output);
+ 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);
+ }
+ DamageEmpty(xwl_window->damage);
+
+ if (count == 0)
+ wl_surface_damage(xwl_window->surface, 0, 0,
+ xwl_window->window->drawable.width,
+ xwl_window->window->drawable.height);
+
+ xwl_window->pixmap->refcnt++;
+ xwl_window->attach_x = 0;
+ xwl_window->attach_y = 0;
+ wl_surface_commit(xwl_window->surface);
+ }
+
+ wl_display_flush(xwl_screen->display);
+
+ xorg_list_init(&xwl_screen->damage_window_list);
+}
+
+static pointer
+xwl_setup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ return xwl_input_setup(module, opts, errmaj, errmin);
+}
+
+static void
+xwl_teardown(pointer p)
+{
+ xwl_input_teardown(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 0000000..e536c42
--- /dev/null
+++ b/hw/xfree86/xwayland/xwayland.h
@@ -0,0 +1,83 @@
+/*
+ * 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_
+
+#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(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/dix.h b/include/dix.h
index 171e56e..27554ba 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -439,7 +439,7 @@ DoFocusEvents(DeviceIntPtr /* dev */ ,
WindowPtr /* toWin */ ,
int /* mode */ );
-extern int
+extern _X_EXPORT int
SetInputFocus(ClientPtr /* client */ ,
DeviceIntPtr /* dev */ ,
Window /* focusID */ ,
diff --git a/include/os.h b/include/os.h
index c7108a5..32e5b96 100644
--- a/include/os.h
+++ b/include/os.h
@@ -160,8 +160,9 @@ extern _X_EXPORT void MakeClientGrabImpervious(ClientPtr /*client */ );
extern _X_EXPORT void MakeClientGrabPervious(ClientPtr /*client */ );
-#ifdef XQUARTZ
-extern void ListenOnOpenFD(int /* fd */ , int /* noxauth */ );
+#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);
diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in
index a71b25d..709b212 100644
--- a/include/xorg-config.h.in
+++ b/include/xorg-config.h.in
@@ -139,4 +139,7 @@
/* Have X server platform bus support */
#undef XSERVER_PLATFORM_BUS
+/* Support nesting under a Wayland compositor */
+#undef XORG_WAYLAND
+
#endif /* _XORG_CONFIG_H_ */
diff --git a/include/xorg-server.h.in b/include/xorg-server.h.in
index 81935be..2f9d27b 100644
--- a/include/xorg-server.h.in
+++ b/include/xorg-server.h.in
@@ -212,4 +212,7 @@
#define _XSERVER64 1
#endif
+/* Building Xorg server. */
+#undef XORG_WAYLAND
+
#endif /* _XORG_SERVER_H_ */
diff --git a/os/connection.c b/os/connection.c
index 91e3b13..701fd1c 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -64,6 +64,7 @@ SOFTWARE.
#include <dix-config.h>
#endif
+#include <xorg-server.h>
#ifdef WIN32
#include <X11/Xwinsock.h>
#endif
@@ -1258,7 +1259,7 @@ MakeClientGrabPervious(ClientPtr client)
}
}
-#ifdef XQUARTZ
+#if defined(XQUARTZ) || defined(XORG_WAYLAND)
/* Add a fd (from launchd) to our listeners */
void
ListenOnOpenFD(int fd, int noxauth)
@@ -1314,4 +1315,24 @@ ListenOnOpenFD(int fd, int noxauth)
#endif
}
+/* based on TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status) */
+void
+AddClientOnOpenFD(int fd)
+{
+ XtransConnInfo ciptr;
+ CARD32 connect_time;
+
+ ciptr = _XSERVTransReopenCOTSServer(5, fd, "@anonymous");
+
+ _XSERVTransSetOption(ciptr, TRANS_NONBLOCKING, 1);
+ ciptr->flags |= TRANS_NOXAUTH;
+
+ connect_time = GetTimeInMillis();
+
+ if (!AllocNewConnection(ciptr, fd, connect_time)) {
+ fprintf(stderr, "failed to create client for wayland server\n");
+ return;
+ }
+}
+
#endif
--
1.7.10.4
More information about the xorg-devel
mailing list