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