[PATCH 6/6] Xwayland DDX

Hi Kristian, This direction seems to conflict with our plans to continue running our DDX driver under XWayland. If we can't run our DDX, we don't have a path to support GLX direct rendering under Wayland. I know we don't have anything publicly available for Wayland at the moment, but as I've alluded to publicly a few times, we are actively working on support and this certainly throws a wrench into things. Thanks, -James On 03/25/2014 02:57 PM, Kristian Høgsberg wrote: > Started out as an Xorg module to be used from Xorg drivers to let > Xorg run under a wayland server. The idea was to be able to reuse the > 2D acceleration from the Xorg driver. Now with glamor being credible, > a better plan is to just make Xwayland its own DDX, similar to Xwin > and Xquartz. This is a much better fit, as much of the code in the > original approach had to hack around Xorg doing Xorg things like take > over the VT, probe input devices and read config files. Another big win > is that Xwayland dosn't need to be setuid root. > > Contributions from: > > Christopher James Halse Rogers <christopher.halse.rogers at canonical.com> > Corentin Chary <corentin.chary at gmail.com> > Daniel Stone <daniel at fooishbar.org> > Kristian Høgsberg <krh at bitplanet.net> > Robert Bragg <robert at linux.intel.com> > Scott Moreau <oreaus at gmail.com> > Tiago Vignatti <tiago.vignatti at intel.com> > Giovanni Campagna <gcampagn at redhat.com> > Jonas Ådahl <jadahl at gmail.com> > Ray Strode <rstrode at redhat.com> > Trevor McCort <tjmccort at gmail.com> > Rui Matos <tiagomatos at gmail.com> > Axel Davy <axel.davy at ens.fr> > > Signed-off-by: Kristian Høgsberg <krh at bitplanet.net> > --- > configure.ac | 26 ++ > hw/Makefile.am | 9 +- > hw/xwayland/.gitignore | 1 + > hw/xwayland/Makefile.am | 30 ++ > hw/xwayland/xwayland-cursor.c | 198 ++++++++++++ > hw/xwayland/xwayland-cvt.c | 304 ++++++++++++++++++ > hw/xwayland/xwayland-input.c | 655 +++++++++++++++++++++++++++++++++++++++ > hw/xwayland/xwayland-output.c | 226 ++++++++++++++ > hw/xwayland/xwayland-shm.c | 222 ++++++++++++++ > hw/xwayland/xwayland.c | 695 ++++++++++++++++++++++++++++++++++++++++++ > hw/xwayland/xwayland.h | 160 ++++++++++ > 11 files changed, 2524 insertions(+), 2 deletions(-) > create mode 100644 hw/xwayland/.gitignore > create mode 100644 hw/xwayland/Makefile.am > create mode 100644 hw/xwayland/xwayland-cursor.c > create mode 100644 hw/xwayland/xwayland-cvt.c > create mode 100644 hw/xwayland/xwayland-input.c > create mode 100644 hw/xwayland/xwayland-output.c > create mode 100644 hw/xwayland/xwayland-shm.c > create mode 100644 hw/xwayland/xwayland.c > create mode 100644 hw/xwayland/xwayland.h > > diff --git a/configure.ac b/configure.ac > index a75ba8f..2c38565 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -633,6 +633,7 @@ AC_ARG_ENABLE(dmx, AS_HELP_STRING([--enable-dmx], [Build DMX server (d > AC_ARG_ENABLE(xvfb, AS_HELP_STRING([--enable-xvfb], [Build Xvfb server (default: yes)]), [XVFB=$enableval], [XVFB=yes]) > AC_ARG_ENABLE(xnest, AS_HELP_STRING([--enable-xnest], [Build Xnest server (default: auto)]), [XNEST=$enableval], [XNEST=auto]) > AC_ARG_ENABLE(xquartz, AS_HELP_STRING([--enable-xquartz], [Build Xquartz server for OS-X (default: auto)]), [XQUARTZ=$enableval], [XQUARTZ=auto]) > +AC_ARG_ENABLE(xwayland, AS_HELP_STRING([--enable-xwayland], [Build Xwayland server (default: auto)]), [XWAYLAND=$enableval], [XWAYLAND=auto]) > AC_ARG_ENABLE(standalone-xpbproxy, AS_HELP_STRING([--enable-standalone-xpbproxy], [Build a standalone xpbproxy (in addition to the one integrated into Xquartz as a separate thread) (default: no)]), [STANDALONE_XPBPROXY=$enableval], [STANDALONE_XPBPROXY=no]) > AC_ARG_ENABLE(xwin, AS_HELP_STRING([--enable-xwin], [Build XWin server (default: auto)]), [XWIN=$enableval], [XWIN=auto]) > AC_ARG_ENABLE(glamor, AS_HELP_STRING([--enable-glamor], [Build glamor dix module (default: no)]), [GLAMOR=$enableval], [GLAMOR=no]) > @@ -751,6 +752,7 @@ case $host_os in > XQUARTZ=yes > XVFB=no > XNEST=no > + XWAYLAND=no > > COMPOSITE=no > DGA=no > @@ -2433,6 +2435,29 @@ AM_CONDITIONAL(XEPHYR, [test "x$KDRIVE" = xyes && test "x$XEPHYR" = xyes]) > AM_CONDITIONAL(BUILD_KDRIVEFBDEVLIB, [test "x$KDRIVE" = xyes && test "x$KDRIVEFBDEVLIB" = xyes]) > AM_CONDITIONAL(XFAKESERVER, [test "x$KDRIVE" = xyes && test "x$XFAKE" = xyes]) > > +dnl Xwayland DDX > + > +PKG_CHECK_MODULES(XWAYLANDMODULES, [wayland-client libdrm], [have_xwayland=yes], [have_xwayland=no]) > +AC_MSG_CHECKING([whether to build Xwayland DDX]) > +if test "x$XWAYLAND" = xauto; then > + $XWAYLAND="$have_xwayland" > +fi > +AC_MSG_RESULT([$XWAYLAND]) > +AM_CONDITIONAL(XWAYLAND, [test "x$XWAYLAND" = xyes]) > + > +if test "x$XWAYLAND" = xyes; then > + if test "x$have_xwayland" = xno; then > + AC_MSG_ERROR([Xwayland build explicitly requested, but required modules not found.]) > + fi > + > + XWAYLAND_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB" > + XWAYLAND_SYS_LIBS="$XWAYLANDMODULES_LIBS $GLX_SYS_LIBS" > + AC_SUBST([XWAYLAND_LIBS]) > + AC_SUBST([XWAYLAND_SYS_LIBS]) > + WAYLAND_SCANNER_RULES(['$(top_srcdir)/hw/xwayland']) > +fi > + > + > dnl and the rest of these are generic, so they're in config.h > dnl > dnl though, thanks to the passing of some significant amount of time, the > @@ -2575,6 +2600,7 @@ hw/kdrive/fake/Makefile > hw/kdrive/fbdev/Makefile > hw/kdrive/linux/Makefile > hw/kdrive/src/Makefile > +hw/xwayland/Makefile > test/Makefile > test/xi2/Makefile > xserver.ent > diff --git a/hw/Makefile.am b/hw/Makefile.am > index 6c2cc6b..19895dc 100644 > --- a/hw/Makefile.am > +++ b/hw/Makefile.am > @@ -26,6 +26,10 @@ if XQUARTZ > XQUARTZ_SUBDIRS = xquartz > endif > > +if XWAYLAND > +XWAYLAND_SUBDIRS = xwayland > +endif > + > SUBDIRS = \ > $(XORG_SUBDIRS) \ > $(XWIN_SUBDIRS) \ > @@ -33,9 +37,10 @@ SUBDIRS = \ > $(XNEST_SUBDIRS) \ > $(DMX_SUBDIRS) \ > $(KDRIVE_SUBDIRS) \ > - $(XQUARTZ_SUBDIRS) > + $(XQUARTZ_SUBDIRS) \ > + $(XWAYLAND_SUBDIRS) > > -DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive > +DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland > > relink: > $(AM_V_at)for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink || exit 1 ; done > diff --git a/hw/xwayland/.gitignore b/hw/xwayland/.gitignore > new file mode 100644 > index 0000000..ab0326b > --- /dev/null > +++ b/hw/xwayland/.gitignore > @@ -0,0 +1 @@ > +Xwayland > diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am > new file mode 100644 > index 0000000..18c2d07 > --- /dev/null > +++ b/hw/xwayland/Makefile.am > @@ -0,0 +1,30 @@ > +bin_PROGRAMS = Xwayland > + > +Xwayland_CFLAGS = \ > + -DHAVE_DIX_CONFIG_H \ > + $(XWAYLANDMODULES_CFLAGS) \ > + $(DIX_CFLAGS) > + > +Xwayland_SOURCES = \ > + xwayland.c \ > + xwayland-input.c \ > + xwayland-cursor.c \ > + xwayland-shm.c \ > + xwayland-output.c \ > + xwayland-cvt.c \ > + xwayland.h \ > + $(top_srcdir)/Xext/dpmsstubs.c \ > + $(top_srcdir)/Xi/stubs.c \ > + $(top_srcdir)/mi/miinitext.c > + > +Xwayland_LDADD = $(XWAYLAND_LIBS) libfbcmap.a $(XWAYLAND_SYS_LIBS) $(XSERVER_SYS_LIBS) > +Xwayland_DEPENDENCIES = $(XWAYLAND_LIBS) > +Xwayland_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG) > + > +noinst_LIBRARIES = libfbcmap.a > + > +libfbcmap_a_CFLAGS = $(DIX_CFLAGS) $(PIXMAN_CFLAGS) -DHAVE_DIX_CONFIG_H > +libfbcmap_a_SOURCES = $(top_srcdir)/fb/fbcmap_mi.c > + > +relink: > + $(AM_V_at)rm -f Xwayland$(EXEEXT) && $(MAKE) Xwayland$(EXEEXT) > diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c > new file mode 100644 > index 0000000..14b5b3a > --- /dev/null > +++ b/hw/xwayland/xwayland-cursor.c > @@ -0,0 +1,198 @@ > +/* > + * Copyright © 2014 Intel Corporation > + * Copyright © 2011 Kristian Høgsberg > + * > + * Permission to use, copy, modify, distribute, and sell this software > + * and its documentation for any purpose is hereby granted without > + * fee, provided that the above copyright notice appear in all copies > + * and that both that copyright notice and this permission notice > + * appear in supporting documentation, and that the name of the > + * copyright holders not be used in advertising or publicity > + * pertaining to distribution of the software without specific, > + * written prior permission. The copyright holders make no > + * representations about the suitability of this software for any > + * purpose. It is provided "as is" without express or implied > + * warranty. > + * > + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS > + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND > + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY > + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN > + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING > + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS > + * SOFTWARE. > + */ > + > +#include "xwayland.h" > + > +#include <mipointer.h> > + > +static DevPrivateKeyRec xwl_cursor_private_key; > + > +static void > +expand_source_and_mask(CursorPtr cursor, CARD32 *data) > +{ > + CARD32 *p, d, fg, bg; > + CursorBitsPtr bits = cursor->bits; > + int x, y, stride, i, bit; > + > + p = data; > + fg = ((cursor->foreRed & 0xff00) << 8) | > + (cursor->foreGreen & 0xff00) | (cursor->foreGreen >> 8); > + bg = ((cursor->backRed & 0xff00) << 8) | > + (cursor->backGreen & 0xff00) | (cursor->backGreen >> 8); > + stride = (bits->width / 8 + 3) & ~3; > + for (y = 0; y < bits->height; y++) > + for (x = 0; x < bits->width; x++) { > + i = y * stride + x / 8; > + bit = 1 << (x & 7); > + if (bits->source[i] & bit) > + d = fg; > + else > + d = bg; > + if (bits->mask[i] & bit) > + d |= 0xff000000; > + else > + d = 0x00000000; > + > + *p++ = d; > + } > +} > + > +static Bool > +xwl_realize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor) > +{ > + struct xwl_screen *xwl_screen; > + struct xwl_shm_buffer *buffer; > + int stride; > + > + xwl_screen = xwl_screen_get(screen); > + > + stride = cursor->bits->width * 4; > + buffer = xwl_shm_buffer_create(xwl_screen, > + cursor->bits->width, cursor->bits->height, > + stride, WL_SHM_FORMAT_ARGB8888); > + dixSetPrivate(&cursor->devPrivates, &xwl_cursor_private_key, buffer); > + > + return TRUE; > +} > + > +static Bool > +xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor) > +{ > + struct xwl_shm_buffer *buffer; > + > + buffer = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key); > + xwl_shm_buffer_destroy(buffer); > + > + return TRUE; > +} > + > +void > +xwl_seat_set_cursor(struct xwl_seat *xwl_seat) > +{ > + struct xwl_shm_buffer *buffer; > + CursorPtr cursor; > + int stride; > + > + if (!xwl_seat->wl_pointer) > + return; > + > + if (!xwl_seat->x_cursor) { > + wl_pointer_set_cursor(xwl_seat->wl_pointer, > + xwl_seat->pointer_enter_serial, NULL, 0, 0); > + return; > + } > + > + cursor = xwl_seat->x_cursor; > + buffer = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key); > + stride = cursor->bits->width * 4; > + if (cursor->bits->argb) > + memcpy(buffer->data, cursor->bits->argb, cursor->bits->height * stride); > + else > + expand_source_and_mask(cursor, buffer->data); > + > + wl_pointer_set_cursor(xwl_seat->wl_pointer, > + xwl_seat->pointer_enter_serial, > + xwl_seat->cursor, > + xwl_seat->x_cursor->bits->xhot, > + xwl_seat->x_cursor->bits->yhot); > + wl_surface_attach(xwl_seat->cursor, buffer->buffer, 0, 0); > + wl_surface_damage(xwl_seat->cursor, 0, 0, > + xwl_seat->x_cursor->bits->width, > + xwl_seat->x_cursor->bits->height); > + wl_surface_commit(xwl_seat->cursor); > +} > + > +static void > +xwl_set_cursor(DeviceIntPtr device, > + ScreenPtr screen, CursorPtr cursor, int x, int y) > +{ > + struct xwl_seat *xwl_seat; > + > + xwl_seat = device->public.devicePrivate; > + if (xwl_seat == NULL) > + return; > + > + xwl_seat->x_cursor = cursor; > + xwl_seat_set_cursor(xwl_seat); > +} > + > +static void > +xwl_move_cursor(DeviceIntPtr device, ScreenPtr screen, int x, int y) > +{ > +} > + > +static Bool > +xwl_device_cursor_initialize(DeviceIntPtr device, ScreenPtr screen) > +{ > + return TRUE; > +} > + > +static void > +xwl_device_cursor_cleanup(DeviceIntPtr device, ScreenPtr screen) > +{ > +} > + > +static miPointerSpriteFuncRec xwl_pointer_sprite_funcs = { > + xwl_realize_cursor, > + xwl_unrealize_cursor, > + xwl_set_cursor, > + xwl_move_cursor, > + xwl_device_cursor_initialize, > + xwl_device_cursor_cleanup > +}; > + > +static Bool > +xwl_cursor_off_screen(ScreenPtr *ppScreen, int *x, int *y) > +{ > + return FALSE; > +} > + > +static void > +xwl_cross_screen(ScreenPtr pScreen, Bool entering) > +{ > +} > + > +static void > +xwl_pointer_warp_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) > +{ > +} > + > +static miPointerScreenFuncRec xwl_pointer_screen_funcs = { > + xwl_cursor_off_screen, > + xwl_cross_screen, > + xwl_pointer_warp_cursor > +}; > + > +Bool > +xwl_screen_init_cursor(struct xwl_screen *xwl_screen) > +{ > + if (!dixRegisterPrivateKey(&xwl_cursor_private_key, PRIVATE_CURSOR_BITS, 0)) > + return FALSE; > + > + return miPointerInitialize(xwl_screen->screen, > + &xwl_pointer_sprite_funcs, > + &xwl_pointer_screen_funcs, TRUE); > +} > diff --git a/hw/xwayland/xwayland-cvt.c b/hw/xwayland/xwayland-cvt.c > new file mode 100644 > index 0000000..3566559 > --- /dev/null > +++ b/hw/xwayland/xwayland-cvt.c > @@ -0,0 +1,304 @@ > +/* Copied from hw/xfree86/modes/xf86cvt.c into xwayland DDX and > + * changed to generate an RRMode */ > + > +/* > + * Copyright 2005-2006 Luc Verhaegen. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR > + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, > + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR > + * OTHER DEALINGS IN THE SOFTWARE. > + */ > + > +/* > + * The reason for having this function in a file of its own is > + * so that ../utils/cvt/cvt can link to it, and that xf86CVTMode > + * code is shared directly. > + */ > + > +#ifdef HAVE_DIX_CONFIG_H > +#include <dix-config.h> > +#endif > + > +#include <string.h> > +#include <randrstr.h> > +#include "xwayland.h" > + > +/* > + * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh. > + * > + * These calculations are stolen from the CVT calculation spreadsheet written > + * by Graham Loveridge. He seems to be claiming no copyright and there seems to > + * be no license attached to this. He apparently just wants to see his name > + * mentioned. > + * > + * This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls > + * > + * Comments and structure corresponds to the comments and structure of the xls. > + * This should ease importing of future changes to the standard (not very > + * likely though). > + * > + * About margins; i'm sure that they are to be the bit between HDisplay and > + * HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and > + * VTotal, where the overscan colour is shown. FB seems to call _all_ blanking > + * outside sync "margin" for some reason. Since we prefer seeing proper > + * blanking instead of the overscan colour, and since the Crtc* values will > + * probably get altered after us, we will disable margins altogether. With > + * these calculations, Margins will plainly expand H/VDisplay, and we don't > + * want that. -- libv > + * > + */ > +RRModePtr > +xwayland_cvt(int HDisplay, int VDisplay, float VRefresh, Bool Reduced, > + Bool Interlaced) > +{ > + /* 1) top/bottom margin size (% of height) - default: 1.8 */ > +#define CVT_MARGIN_PERCENTAGE 1.8 > + > + /* 2) character cell horizontal granularity (pixels) - default 8 */ > +#define CVT_H_GRANULARITY 8 > + > + /* 4) Minimum vertical porch (lines) - default 3 */ > +#define CVT_MIN_V_PORCH 3 > + > + /* 4) Minimum number of vertical back porch lines - default 6 */ > +#define CVT_MIN_V_BPORCH 6 > + > + /* Pixel Clock step (kHz) */ > +#define CVT_CLOCK_STEP 250 > + > + Bool Margins = FALSE; > + float VFieldRate, HPeriod; > + int HDisplayRnd, HMargin; > + int VDisplayRnd, VMargin, VSync; > + float Interlace; /* Please rename this */ > + char name[128]; > + xRRModeInfo modeinfo; > + > + memset(&modeinfo, 0, sizeof modeinfo); > + > + /* CVT default is 60.0Hz */ > + if (!VRefresh) > + VRefresh = 60.0; > + > + /* 1. Required field rate */ > + if (Interlaced) > + VFieldRate = VRefresh * 2; > + else > + VFieldRate = VRefresh; > + > + /* 2. Horizontal pixels */ > + HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY); > + > + /* 3. Determine left and right borders */ > + if (Margins) { > + /* right margin is actually exactly the same as left */ > + HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0); > + HMargin -= HMargin % CVT_H_GRANULARITY; > + } > + else > + HMargin = 0; > + > + /* 4. Find total active pixels */ > + modeinfo.width = HDisplayRnd + 2 * HMargin; > + > + /* 5. Find number of lines per field */ > + if (Interlaced) > + VDisplayRnd = VDisplay / 2; > + else > + VDisplayRnd = VDisplay; > + > + /* 6. Find top and bottom margins */ > + /* nope. */ > + if (Margins) > + /* top and bottom margins are equal again. */ > + VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0); > + else > + VMargin = 0; > + > + modeinfo.height = VDisplay + 2 * VMargin; > + > + /* 7. Interlace */ > + if (Interlaced) > + Interlace = 0.5; > + else > + Interlace = 0.0; > + > + /* Determine VSync Width from aspect ratio */ > + if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay)) > + VSync = 4; > + else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay)) > + VSync = 5; > + else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay)) > + VSync = 6; > + else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay)) > + VSync = 7; > + else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay)) > + VSync = 7; > + else /* Custom */ > + VSync = 10; > + > + if (!Reduced) { /* simplified GTF calculation */ > + > + /* 4) Minimum time of vertical sync + back porch interval (µs) > + * default 550.0 */ > +#define CVT_MIN_VSYNC_BP 550.0 > + > + /* 3) Nominal HSync width (% of line period) - default 8 */ > +#define CVT_HSYNC_PERCENTAGE 8 > + > + float HBlankPercentage; > + int VSyncAndBackPorch, VBackPorch; > + int HBlank; > + > + /* 8. Estimated Horizontal period */ > + HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) / > + (VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace); > + > + /* 9. Find number of lines in sync + backporch */ > + if (((int) (CVT_MIN_VSYNC_BP / HPeriod) + 1) < > + (VSync + CVT_MIN_V_PORCH)) > + VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH; > + else > + VSyncAndBackPorch = (int) (CVT_MIN_VSYNC_BP / HPeriod) + 1; > + > + /* 10. Find number of lines in back porch */ > + VBackPorch = VSyncAndBackPorch - VSync; > + (void) VBackPorch; > + > + /* 11. Find total number of lines in vertical field */ > + modeinfo.vTotal = > + VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace + > + CVT_MIN_V_PORCH; > + > + /* 5) Definition of Horizontal blanking time limitation */ > + /* Gradient (%/kHz) - default 600 */ > +#define CVT_M_FACTOR 600 > + > + /* Offset (%) - default 40 */ > +#define CVT_C_FACTOR 40 > + > + /* Blanking time scaling factor - default 128 */ > +#define CVT_K_FACTOR 128 > + > + /* Scaling factor weighting - default 20 */ > +#define CVT_J_FACTOR 20 > + > +#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256 > +#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \ > + CVT_J_FACTOR > + > + /* 12. Find ideal blanking duty cycle from formula */ > + HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod / 1000.0; > + > + /* 13. Blanking time */ > + if (HBlankPercentage < 20) > + HBlankPercentage = 20; > + > + HBlank = modeinfo.width * HBlankPercentage / (100.0 - HBlankPercentage); > + HBlank -= HBlank % (2 * CVT_H_GRANULARITY); > + > + /* 14. Find total number of pixels in a line. */ > + modeinfo.hTotal = modeinfo.width + HBlank; > + > + /* Fill in HSync values */ > + modeinfo.hSyncEnd = modeinfo.width + HBlank / 2; > + > + modeinfo.hSyncStart = modeinfo.hSyncEnd - > + (modeinfo.hTotal * CVT_HSYNC_PERCENTAGE) / 100; > + modeinfo.hSyncStart += CVT_H_GRANULARITY - > + modeinfo.hSyncStart % CVT_H_GRANULARITY; > + > + /* Fill in VSync values */ > + modeinfo.vSyncStart = modeinfo.height + CVT_MIN_V_PORCH; > + modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync; > + > + } > + else { /* Reduced blanking */ > + /* Minimum vertical blanking interval time (µs) - default 460 */ > +#define CVT_RB_MIN_VBLANK 460.0 > + > + /* Fixed number of clocks for horizontal sync */ > +#define CVT_RB_H_SYNC 32.0 > + > + /* Fixed number of clocks for horizontal blanking */ > +#define CVT_RB_H_BLANK 160.0 > + > + /* Fixed number of lines for vertical front porch - default 3 */ > +#define CVT_RB_VFPORCH 3 > + > + int VBILines; > + > + /* 8. Estimate Horizontal period. */ > + HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) / > + (VDisplayRnd + 2 * VMargin); > + > + /* 9. Find number of lines in vertical blanking */ > + VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1; > + > + /* 10. Check if vertical blanking is sufficient */ > + if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH)) > + VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH; > + > + /* 11. Find total number of lines in vertical field */ > + modeinfo.vTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines; > + > + /* 12. Find total number of pixels in a line */ > + modeinfo.hTotal = modeinfo.width + CVT_RB_H_BLANK; > + > + /* Fill in HSync values */ > + modeinfo.hSyncEnd = modeinfo.width + CVT_RB_H_BLANK / 2; > + modeinfo.hSyncStart = modeinfo.hSyncEnd - CVT_RB_H_SYNC; > + > + /* Fill in VSync values */ > + modeinfo.vSyncStart = modeinfo.height + CVT_RB_VFPORCH; > + modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync; > + } > + > + /* 15/13. Find pixel clock frequency (kHz for xf86) */ > + modeinfo.dotClock = modeinfo.hTotal * 1000.0 / HPeriod; > + modeinfo.dotClock -= modeinfo.dotClock % CVT_CLOCK_STEP; > + modeinfo.dotClock *= 1000.0; > +#if 0 > + /* 16/14. Find actual Horizontal Frequency (kHz) */ > + modeinfo.hSync = ((float) modeinfo.dotClock) / ((float) modeinfo.hTotal); > +#endif > + > +#if 0 > + /* 17/15. Find actual Field rate */ > + modeinfo.vRefresh = (1000.0 * ((float) modeinfo.dotClock)) / > + ((float) (modeinfo.hTotal * modeinfo.vTotal)); > +#endif > + > + /* 18/16. Find actual vertical frame frequency */ > + /* ignore - just set the mode flag for interlaced */ > + if (Interlaced) > + modeinfo.vTotal *= 2; > + > + if (Reduced) > + modeinfo.modeFlags |= RR_HSyncPositive | RR_VSyncNegative; > + else > + modeinfo.modeFlags |= RR_HSyncNegative | RR_VSyncPositive; > + > + if (Interlaced) > + modeinfo.modeFlags |= RR_Interlace; > + > + snprintf(name, sizeof name, "%dx%d@%.1fHz", > + modeinfo.width, modeinfo.height, VRefresh); > + modeinfo.nameLength = strlen(name); > + > + return RRModeGet(&modeinfo, name); > +} > diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c > new file mode 100644 > index 0000000..452789f > --- /dev/null > +++ b/hw/xwayland/xwayland-input.c > @@ -0,0 +1,655 @@ > +/* > + * Copyright © 2014 Intel Corporation > + * Copyright © 2008 Kristian Høgsberg > + * > + * Permission to use, copy, modify, distribute, and sell this software > + * and its documentation for any purpose is hereby granted without > + * fee, provided that the above copyright notice appear in all copies > + * and that both that copyright notice and this permission notice > + * appear in supporting documentation, and that the name of the > + * copyright holders not be used in advertising or publicity > + * pertaining to distribution of the software without specific, > + * written prior permission. The copyright holders make no > + * representations about the suitability of this software for any > + * purpose. It is provided "as is" without express or implied > + * warranty. > + * > + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS > + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND > + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY > + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN > + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING > + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS > + * SOFTWARE. > + */ > + > +#include "xwayland.h" > + > +#include <linux/input.h> > + > +#include <sys/mman.h> > +#include <xkbsrv.h> > +#include <xserver-properties.h> > +#include <inpututils.h> > + > +static void > +xwl_pointer_control(DeviceIntPtr device, PtrCtrl *ctrl) > +{ > + /* Nothing to do, dix handles all settings */ > +} > + > +static int > +xwl_pointer_proc(DeviceIntPtr device, int what) > +{ > +#define NBUTTONS 10 > +#define NAXES 2 > + BYTE map[NBUTTONS + 1]; > + int i = 0; > + Atom btn_labels[NBUTTONS] = { 0 }; > + Atom axes_labels[NAXES] = { 0 }; > + > + switch (what) { > + case DEVICE_INIT: > + device->public.on = FALSE; > + > + for (i = 1; i <= NBUTTONS; i++) > + map[i] = i; > + > + btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); > + btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); > + btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); > + btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); > + btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); > + btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); > + btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); > + /* don't know about the rest */ > + > + axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X); > + axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y); > + > + if (!InitValuatorClassDeviceStruct(device, 2, btn_labels, > + GetMotionHistorySize(), Absolute)) > + return BadValue; > + > + /* Valuators */ > + InitValuatorAxisStruct(device, 0, axes_labels[0], > + 0, 0xFFFF, 10000, 0, 10000, Absolute); > + InitValuatorAxisStruct(device, 1, axes_labels[1], > + 0, 0xFFFF, 10000, 0, 10000, Absolute); > + > + if (!InitPtrFeedbackClassDeviceStruct(device, xwl_pointer_control)) > + return BadValue; > + > + if (!InitButtonClassDeviceStruct(device, 3, btn_labels, map)) > + return BadValue; > + > + return Success; > + > + case DEVICE_ON: > + device->public.on = TRUE; > + return Success; > + > + case DEVICE_OFF: > + case DEVICE_CLOSE: > + device->public.on = FALSE; > + return Success; > + } > + > + return BadMatch; > + > +#undef NBUTTONS > +#undef NAXES > +} > + > +static void > +xwl_keyboard_control(DeviceIntPtr device, KeybdCtrl *ctrl) > +{ > +} > + > +static int > +xwl_keyboard_proc(DeviceIntPtr device, int what) > +{ > + struct xwl_seat *xwl_seat = device->public.devicePrivate; > + int len; > + > + switch (what) { > + case DEVICE_INIT: > + device->public.on = FALSE; > + if (xwl_seat->keymap) > + len = strnlen(xwl_seat->keymap, xwl_seat->keymap_size); > + else > + len = 0; > + if (!InitKeyboardDeviceStructFromString(device, xwl_seat->keymap, > + len, > + NULL, xwl_keyboard_control)) > + return BadValue; > + > + return Success; > + case DEVICE_ON: > + device->public.on = TRUE; > + return Success; > + > + case DEVICE_OFF: > + case DEVICE_CLOSE: > + device->public.on = FALSE; > + return Success; > + } > + > + return BadMatch; > +} > + > +static void > +pointer_handle_enter(void *data, struct wl_pointer *pointer, > + uint32_t serial, struct wl_surface *surface, > + wl_fixed_t sx_w, wl_fixed_t sy_w) > +{ > + struct xwl_seat *xwl_seat = data; > + DeviceIntPtr dev = xwl_seat->pointer; > + int i; > + int sx = wl_fixed_to_int(sx_w); > + int sy = wl_fixed_to_int(sy_w); > + ScreenPtr pScreen = xwl_seat->xwl_screen->screen; > + ValuatorMask mask; > + > + xwl_seat->xwl_screen->serial = serial; > + xwl_seat->pointer_enter_serial = serial; > + > + xwl_seat->focus_window = wl_surface_get_user_data(surface); > + > + (*pScreen->SetCursorPosition) (dev, pScreen, sx, sy, TRUE); > + > + /* Ideally, X clients shouldn't see these button releases. When > + * the pointer leaves a window with buttons down, it means that > + * the wayland compositor has grabbed the pointer. The button > + * release event is consumed by whatever grab in the compositor > + * and won't be sent to clients (the X server is a client). > + * However, we need to reset X's idea of which buttons are up and > + * down, and they're all up (by definition) when the pointer > + * enters a window. We should figure out a way to swallow these > + * events, perhaps using an X grab whenever the pointer is not in > + * any X window, but for now just send the events. */ > + valuator_mask_zero(&mask); > + for (i = 0; i < dev->button->numButtons; i++) > + if (BitIsOn(dev->button->down, i)) > + QueuePointerEvents(xwl_seat->pointer, ButtonRelease, i, 0, &mask); > +} > + > +static void > +pointer_handle_leave(void *data, struct wl_pointer *pointer, > + uint32_t serial, struct wl_surface *surface) > +{ > + struct xwl_seat *xwl_seat = data; > + > + xwl_seat->xwl_screen->serial = serial; > + > + xwl_seat->focus_window = NULL; > + > +#if 0 > + /* Park the pointer in our pointer limbo window while it's not in > + * any X window. */ > + if (xwl_seat->xwl_screen->rootless) { > + sprite = dev->spriteInfo->sprite; > + sprite->spriteTrace[0] = xwl_seat->xwl_screen->pointer_limbo_window; > + sprite->spriteTrace[0] = xwl_seat->xwl_screen->screen->root; > + CheckMotion(NULL, GetMaster(dev, MASTER_POINTER)); > + } > +#endif > +} > + > +static void > +pointer_handle_motion(void *data, struct wl_pointer *pointer, > + uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) > +{ > + struct xwl_seat *xwl_seat = data; > + int32_t dx, dy; > + int sx = wl_fixed_to_int(sx_w); > + int sy = wl_fixed_to_int(sy_w); > + ValuatorMask mask; > + > + if (!xwl_seat->focus_window) > + return; > + > + dx = xwl_seat->focus_window->window->drawable.x; > + dy = xwl_seat->focus_window->window->drawable.y; > + > + valuator_mask_zero(&mask); > + valuator_mask_set(&mask, 0, dx + sx); > + valuator_mask_set(&mask, 1, dy + sy); > + > + QueuePointerEvents(xwl_seat->pointer, MotionNotify, 0, > + POINTER_ABSOLUTE | POINTER_SCREEN, &mask); > +} > + > +static void > +pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, > + uint32_t time, uint32_t button, uint32_t state) > +{ > + struct xwl_seat *xwl_seat = data; > + int index; > + ValuatorMask mask; > + > + xwl_seat->xwl_screen->serial = serial; > + > + switch (button) { > + case BTN_MIDDLE: > + index = 2; > + break; > + case BTN_RIGHT: > + index = 3; > + break; > + default: > + index = button - BTN_LEFT + 1; > + break; > + } > + > + valuator_mask_zero(&mask); > + QueuePointerEvents(xwl_seat->pointer, > + state ? ButtonPress : ButtonRelease, index, 0, &mask); > +} > + > +static void > +pointer_handle_axis(void *data, struct wl_pointer *pointer, > + uint32_t time, uint32_t axis, wl_fixed_t value) > +{ > + struct xwl_seat *xwl_seat = data; > + int index, count; > + int i, val; > + const int divisor = 10; > + ValuatorMask mask; > + > + if (time - xwl_seat->scroll_time > 2000) { > + xwl_seat->vertical_scroll = 0; > + xwl_seat->horizontal_scroll = 0; > + } > + xwl_seat->scroll_time = time; > + > + /* FIXME: Need to do proper smooth scrolling here! */ > + switch (axis) { > + case WL_POINTER_AXIS_VERTICAL_SCROLL: > + xwl_seat->vertical_scroll += value / divisor; > + val = wl_fixed_to_int(xwl_seat->vertical_scroll); > + xwl_seat->vertical_scroll -= wl_fixed_from_int(val); > + > + if (val <= -1) > + index = 4; > + else if (val >= 1) > + index = 5; > + else > + return; > + break; > + case WL_POINTER_AXIS_HORIZONTAL_SCROLL: > + xwl_seat->horizontal_scroll += value / divisor; > + val = wl_fixed_to_int(xwl_seat->horizontal_scroll); > + xwl_seat->horizontal_scroll -= wl_fixed_from_int(val); > + > + if (val <= -1) > + index = 6; > + else if (val >= 1) > + index = 7; > + else > + return; > + break; > + default: > + return; > + } > + > + valuator_mask_zero(&mask); > + > + count = abs(val); > + for (i = 0; i < count; i++) { > + QueuePointerEvents(xwl_seat->pointer, ButtonPress, index, 0, &mask); > + QueuePointerEvents(xwl_seat->pointer, ButtonRelease, index, 0, &mask); > + } > +} > + > +static const struct wl_pointer_listener pointer_listener = { > + pointer_handle_enter, > + pointer_handle_leave, > + pointer_handle_motion, > + pointer_handle_button, > + pointer_handle_axis, > +}; > + > +static void > +keyboard_handle_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, > + uint32_t time, uint32_t key, uint32_t state) > +{ > + struct xwl_seat *xwl_seat = data; > + uint32_t *k, *end; > + ValuatorMask mask; > + > + xwl_seat->xwl_screen->serial = serial; > + > + end = (uint32_t *) ((char *) xwl_seat->keys.data + xwl_seat->keys.size); > + for (k = xwl_seat->keys.data; k < end; k++) { > + if (*k == key) > + *k = *--end; > + } > + xwl_seat->keys.size = (char *) end - (char *) xwl_seat->keys.data; > + if (state) { > + k = wl_array_add(&xwl_seat->keys, sizeof *k); > + *k = key; > + } > + > + valuator_mask_zero(&mask); > + QueueKeyboardEvents(xwl_seat->keyboard, > + state ? KeyPress : KeyRelease, key + 8, &mask); > +} > + > +static void > +keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, > + uint32_t format, int fd, uint32_t size) > +{ > + struct xwl_seat *xwl_seat = data; > + DeviceIntPtr master; > + XkbDescPtr xkb; > + XkbChangesRec changes = { 0 }; > + > + if (xwl_seat->keymap) > + munmap(xwl_seat->keymap, xwl_seat->keymap_size); > + > + xwl_seat->keymap_size = size; > + xwl_seat->keymap = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); > + if (xwl_seat->keymap == MAP_FAILED) { > + xwl_seat->keymap_size = 0; > + xwl_seat->keymap = NULL; > + goto out; > + } > + > + xkb = XkbCompileKeymapFromString(xwl_seat->keyboard, xwl_seat->keymap, > + strnlen(xwl_seat->keymap, > + xwl_seat->keymap_size)); > + if (!xkb) > + goto out; > + > + XkbUpdateDescActions(xkb, xkb->min_key_code, XkbNumKeys(xkb), &changes); > + > + if (xwl_seat->keyboard->key) > + /* Keep the current controls */ > + XkbCopyControls(xkb, xwl_seat->keyboard->key->xkbInfo->desc); > + > + XkbDeviceApplyKeymap(xwl_seat->keyboard, xkb); > + > + master = GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD); > + if (master && master->lastSlave == xwl_seat->keyboard) > + XkbDeviceApplyKeymap(master, xkb); > + > + XkbFreeKeyboard(xkb, XkbAllComponentsMask, TRUE); > + > + out: > + close(fd); > +} > + > +static void > +keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, > + uint32_t serial, > + struct wl_surface *surface, struct wl_array *keys) > +{ > + struct xwl_seat *xwl_seat = data; > + ValuatorMask mask; > + uint32_t *k; > + > + xwl_seat->xwl_screen->serial = serial; > + xwl_seat->keyboard_focus = surface; > + > + wl_array_copy(&xwl_seat->keys, keys); > + valuator_mask_zero(&mask); > + wl_array_for_each(k, &xwl_seat->keys) > + QueueKeyboardEvents(xwl_seat->keyboard, KeyPress, *k + 8, &mask); > +} > + > +static void > +keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, > + uint32_t serial, struct wl_surface *surface) > +{ > + struct xwl_seat *xwl_seat = data; > + ValuatorMask mask; > + uint32_t *k; > + > + xwl_seat->xwl_screen->serial = serial; > + > + valuator_mask_zero(&mask); > + wl_array_for_each(k, &xwl_seat->keys) > + QueueKeyboardEvents(xwl_seat->keyboard, KeyRelease, *k + 8, &mask); > + > + xwl_seat->keyboard_focus = NULL; > +} > + > +static void > +keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, > + uint32_t serial, uint32_t mods_depressed, > + uint32_t mods_latched, uint32_t mods_locked, > + uint32_t group) > +{ > + struct xwl_seat *xwl_seat = data; > + DeviceIntPtr dev; > + XkbStateRec old_state, *new_state; > + xkbStateNotify sn; > + CARD16 changed; > + > + /* We don't need any of this while we have keyboard focus since > + the regular key event processing already takes care of setting > + our internal state correctly. */ > + if (xwl_seat->keyboard_focus) > + return; > + > + for (dev = inputInfo.devices; dev; dev = dev->next) { > + if (dev != xwl_seat->keyboard && > + dev != GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD)) > + continue; > + > + old_state = dev->key->xkbInfo->state; > + new_state = &dev->key->xkbInfo->state; > + > + new_state->locked_group = group & XkbAllGroupsMask; > + new_state->locked_mods = mods_locked & XkbAllModifiersMask; > + XkbLatchModifiers(dev, XkbAllModifiersMask, > + mods_latched & XkbAllModifiersMask); > + > + XkbComputeDerivedState(dev->key->xkbInfo); > + > + changed = XkbStateChangedFlags(&old_state, new_state); > + if (!changed) > + continue; > + > + sn.keycode = 0; > + sn.eventType = 0; > + sn.requestMajor = XkbReqCode; > + sn.requestMinor = X_kbLatchLockState; /* close enough */ > + sn.changed = changed; > + XkbSendStateNotify(dev, &sn); > + } > +} > + > +static const struct wl_keyboard_listener keyboard_listener = { > + keyboard_handle_keymap, > + keyboard_handle_enter, > + keyboard_handle_leave, > + keyboard_handle_key, > + keyboard_handle_modifiers, > +}; > + > +static DeviceIntPtr > +add_device(struct xwl_seat *xwl_seat, > + const char *driver, DeviceProc device_proc) > +{ > + DeviceIntPtr dev = NULL; > + static Atom type_atom; > + char name[32]; > + > + dev = AddInputDevice(serverClient, device_proc, TRUE); > + if (dev == NULL) > + return NULL; > + > + if (type_atom == None) > + type_atom = MakeAtom(driver, strlen(driver), TRUE); > + snprintf(name, sizeof name, "%s:%d", driver, xwl_seat->id); > + AssignTypeAndName(dev, type_atom, name); > + dev->public.devicePrivate = xwl_seat; > + dev->type = SLAVE; > + dev->spriteInfo->spriteOwner = FALSE; > + > + return dev; > +} > + > +static void > +seat_handle_capabilities(void *data, struct wl_seat *seat, > + enum wl_seat_capability caps) > +{ > + struct xwl_seat *xwl_seat = data; > + > + if (caps & WL_SEAT_CAPABILITY_POINTER) { > + xwl_seat->wl_pointer = wl_seat_get_pointer(seat); > + wl_pointer_add_listener(xwl_seat->wl_pointer, > + &pointer_listener, xwl_seat); > + xwl_seat_set_cursor(xwl_seat); > + xwl_seat->pointer = > + add_device(xwl_seat, "xwayland-pointer", xwl_pointer_proc); > + } > + > + if (caps & WL_SEAT_CAPABILITY_KEYBOARD) { > + xwl_seat->wl_keyboard = wl_seat_get_keyboard(seat); > + wl_keyboard_add_listener(xwl_seat->wl_keyboard, > + &keyboard_listener, xwl_seat); > + xwl_seat->keyboard = > + add_device(xwl_seat, "xwayland-keyboard", xwl_keyboard_proc); > + } > + > + xwl_seat->xwl_screen->expecting_event--; > + /* FIXME: Touch ... */ > +} > + > +static const struct wl_seat_listener seat_listener = { > + seat_handle_capabilities, > +}; > + > +static void > +create_input_device(struct xwl_screen *xwl_screen, uint32_t id) > +{ > + struct xwl_seat *xwl_seat; > + > + xwl_seat = calloc(sizeof *xwl_seat, 1); > + if (xwl_seat == NULL) { > + ErrorF("create_input ENOMEM"); > + return; > + } > + > + xwl_seat->xwl_screen = xwl_screen; > + xorg_list_add(&xwl_seat->link, &xwl_screen->seat_list); > + > + xwl_seat->seat = > + wl_registry_bind(xwl_screen->registry, id, &wl_seat_interface, 1); > + xwl_seat->id = id; > + > + xwl_seat->cursor = wl_compositor_create_surface(xwl_screen->compositor); > + wl_seat_add_listener(xwl_seat->seat, &seat_listener, xwl_seat); > + wl_array_init(&xwl_seat->keys); > +} > + > +void > +xwl_seat_destroy(struct xwl_seat *xwl_seat) > +{ > + RemoveDevice(xwl_seat->pointer, FALSE); > + RemoveDevice(xwl_seat->keyboard, FALSE); > + wl_seat_destroy(xwl_seat->seat); > + wl_surface_destroy(xwl_seat->cursor); > + wl_array_release(&xwl_seat->keys); > + free(xwl_seat); > +} > + > +static void > +input_handler(void *data, struct wl_registry *registry, uint32_t id, > + const char *interface, uint32_t version) > +{ > + struct xwl_screen *xwl_screen = data; > + > + if (strcmp(interface, "wl_seat") == 0) { > + create_input_device(xwl_screen, id); > + xwl_screen->expecting_event++; > + } > +} > + > +static void > +global_remove(void *data, struct wl_registry *registry, uint32_t name) > +{ > + /* FIXME */ > +} > + > +static const struct wl_registry_listener input_listener = { > + input_handler, > + global_remove, > +}; > + > +Bool > +LegalModifier(unsigned int key, DeviceIntPtr pDev) > +{ > + return TRUE; > +} > + > +void > +ProcessInputEvents(void) > +{ > + mieqProcessInputEvents(); > +} > + > +void > +DDXRingBell(int volume, int pitch, int duration) > +{ > +} > + > +static WindowPtr > +xwl_xy_to_window(DeviceIntPtr master, SpritePtr sprite, int x, int y) > +{ > + struct xwl_seat *xwl_seat = NULL; > + DeviceIntPtr device; > + > + for (device = inputInfo.devices; device; device = device->next) > + if (GetMaster(device, MASTER_ATTACHED) == master) { > + xwl_seat = device->public.devicePrivate; > + break; > + } > + > + if (xwl_seat == NULL) { > + /* XTEST device */ > + sprite->spriteTraceGood = 1; > + return sprite->spriteTrace[0]; > + } > + > + if (xwl_seat->focus_window) { > + sprite->spriteTraceGood = 2; > + sprite->spriteTrace[1] = xwl_seat->focus_window->window; > + } > + else { > + sprite->spriteTraceGood = 1; > + } > + > + return miSpriteTrace(sprite, x, y); > +} > + > +void > +InitInput(int argc, char *argv[]) > +{ > + ScreenPtr pScreen = screenInfo.screens[0]; > + struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); > + > + mieqInit(); > + > + xwl_screen->input_registry = wl_display_get_registry(xwl_screen->display); > + wl_registry_add_listener(xwl_screen->input_registry, &input_listener, > + xwl_screen); > + > + xwl_screen->XYToWindow = pScreen->XYToWindow; > + pScreen->XYToWindow = xwl_xy_to_window; > + > + xwl_screen->expecting_event = 0; > + wl_display_roundtrip(xwl_screen->display); > + while (xwl_screen->expecting_event) > + wl_display_roundtrip(xwl_screen->display); > +} > + > +void > +CloseInput(void) > +{ > + mieqFini(); > +} > diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c > new file mode 100644 > index 0000000..778914c > --- /dev/null > +++ b/hw/xwayland/xwayland-output.c > @@ -0,0 +1,226 @@ > +/* > + * Copyright © 2011-2014 Intel Corporation > + * > + * Permission to use, copy, modify, distribute, and sell this software > + * and its documentation for any purpose is hereby granted without > + * fee, provided that the above copyright notice appear in all copies > + * and that both that copyright notice and this permission notice > + * appear in supporting documentation, and that the name of the > + * copyright holders not be used in advertising or publicity > + * pertaining to distribution of the software without specific, > + * written prior permission. The copyright holders make no > + * representations about the suitability of this software for any > + * purpose. It is provided "as is" without express or implied > + * warranty. > + * > + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS > + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND > + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY > + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN > + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING > + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS > + * SOFTWARE. > + */ > + > +#ifdef HAVE_DIX_CONFIG_H > +#include <dix-config.h> > +#endif > + > +#include "xwayland.h" > +#include <randrstr.h> > + > +static Rotation > +wl_transform_to_xrandr(enum wl_output_transform transform) > +{ > + switch (transform) { > + default: > + case WL_OUTPUT_TRANSFORM_NORMAL: > + return RR_Rotate_0; > + case WL_OUTPUT_TRANSFORM_90: > + return RR_Rotate_90; > + case WL_OUTPUT_TRANSFORM_180: > + return RR_Rotate_180; > + case WL_OUTPUT_TRANSFORM_270: > + return RR_Rotate_270; > + case WL_OUTPUT_TRANSFORM_FLIPPED: > + return RR_Reflect_X | RR_Rotate_0; > + case WL_OUTPUT_TRANSFORM_FLIPPED_90: > + return RR_Reflect_X | RR_Rotate_90; > + case WL_OUTPUT_TRANSFORM_FLIPPED_180: > + return RR_Reflect_X | RR_Rotate_180; > + case WL_OUTPUT_TRANSFORM_FLIPPED_270: > + return RR_Reflect_X | RR_Rotate_270; > + } > +} > + > +static int > +wl_subpixel_to_xrandr(int subpixel) > +{ > + switch (subpixel) { > + default: > + case WL_OUTPUT_SUBPIXEL_UNKNOWN: > + return SubPixelUnknown; > + case WL_OUTPUT_SUBPIXEL_NONE: > + return SubPixelNone; > + case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB: > + return SubPixelHorizontalRGB; > + case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR: > + return SubPixelHorizontalBGR; > + case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB: > + return SubPixelVerticalRGB; > + case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR: > + return SubPixelVerticalBGR; > + } > +} > + > +static void > +output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y, > + int physical_width, int physical_height, int subpixel, > + const char *make, const char *model, int transform) > +{ > + struct xwl_output *xwl_output = data; > + > + RROutputSetPhysicalSize(xwl_output->randr_output, > + physical_width, physical_height); > + RROutputSetSubpixelOrder(xwl_output->randr_output, > + wl_subpixel_to_xrandr(subpixel)); > + xwl_output->x = x; > + xwl_output->y = y; > + > + xwl_output->rotation = wl_transform_to_xrandr(transform); > +} > + > +static void > +output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags, > + int width, int height, int refresh) > +{ > + struct xwl_output *xwl_output = data; > + RRModePtr randr_mode; > + > + if (!(flags & WL_OUTPUT_MODE_CURRENT)) > + return; > + > + xwl_output->width = width; > + xwl_output->height = height; > + > + randr_mode = xwayland_cvt(width, height, refresh / 1000.0, 0, 0); > + > + RROutputSetModes(xwl_output->randr_output, &randr_mode, 1, 1); > + > + RRCrtcNotify(xwl_output->randr_crtc, randr_mode, > + xwl_output->x, xwl_output->y, > + xwl_output->rotation, NULL, 1, &xwl_output->randr_output); > +} > + > +static void > +output_handle_done(void *data, struct wl_output *wl_output) > +{ > + struct xwl_output *xwl_output = data; > + struct xwl_screen *xwl_screen = xwl_output->xwl_screen; > + int width, height; > + > + xorg_list_append(&xwl_output->link, &xwl_screen->output_list); > + > + width = 0; > + height = 0; > + xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) { > + if (width < xwl_output->x + xwl_output->width) > + width = xwl_output->x + xwl_output->width; > + if (height < xwl_output->y + xwl_output->height) > + height = xwl_output->y + xwl_output->height; > + } > + > + xwl_screen->width = width; > + xwl_screen->height = height; > + RRScreenSizeNotify(xwl_screen->screen); > + > + xwl_screen->expecting_event--; > +} > + > +static void > +output_handle_scale(void *data, struct wl_output *wl_output, int32_t factor) > +{ > +} > + > +static const struct wl_output_listener output_listener = { > + output_handle_geometry, > + output_handle_mode, > + output_handle_done, > + output_handle_scale > +}; > + > +struct xwl_output * > +xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id) > +{ > + struct xwl_output *xwl_output; > + static int serial; > + char name[256]; > + > + xwl_output = calloc(sizeof *xwl_output, 1); > + if (xwl_output == NULL) { > + ErrorF("create_output ENOMEM"); > + return NULL; > + } > + > + xwl_output->output = wl_registry_bind(xwl_screen->registry, id, > + &wl_output_interface, 2); > + wl_output_add_listener(xwl_output->output, &output_listener, xwl_output); > + > + if (snprintf(name, sizeof name, "XWAYLAND%d", serial++) < 0) { > + ErrorF("create_output ENOMEM"); > + free(xwl_output); > + return NULL; > + } > + > + xwl_output->xwl_screen = xwl_screen; > + xwl_output->randr_crtc = RRCrtcCreate(xwl_screen->screen, xwl_output); > + xwl_output->randr_output = RROutputCreate(xwl_screen->screen, name, > + strlen(name), xwl_output); > + RRCrtcGammaSetSize(xwl_output->randr_crtc, 256); > + RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1); > + RROutputSetConnection(xwl_output->randr_output, RR_Connected); > + > + return xwl_output; > +} > + > +void > +xwl_output_destroy(struct xwl_output *xwl_output) > +{ > + wl_output_destroy(xwl_output->output); > + RRCrtcDestroy(xwl_output->randr_crtc); > + RROutputDestroy(xwl_output->randr_output); > + free(xwl_output); > +} > + > +static Bool > +xwl_randr_get_info(ScreenPtr pScreen, Rotation * rotations) > +{ > + *rotations = 0; > + > + return TRUE; > +} > + > +static Bool > +xwl_randr_set_config(ScreenPtr pScreen, > + Rotation rotation, int rate, RRScreenSizePtr pSize) > +{ > + return FALSE; > +} > + > +Bool > +xwl_screen_init_output(struct xwl_screen *xwl_screen) > +{ > + rrScrPrivPtr rp; > + > + if (!RRScreenInit(xwl_screen->screen)) > + return FALSE; > + > + RRScreenSetSizeRange(xwl_screen->screen, 320, 200, 8192, 8192); > + > + rp = rrGetScrPriv(xwl_screen->screen); > + rp->rrGetInfo = xwl_randr_get_info; > + rp->rrSetConfig = xwl_randr_set_config; > + > + return TRUE; > +} > diff --git a/hw/xwayland/xwayland-shm.c b/hw/xwayland/xwayland-shm.c > new file mode 100644 > index 0000000..516dcd0 > --- /dev/null > +++ b/hw/xwayland/xwayland-shm.c > @@ -0,0 +1,222 @@ > +/* > + * Copyright © 2014 Intel Corporation > + * Copyright © 2012 Collabora, Ltd. > + * > + * Permission to use, copy, modify, distribute, and sell this software > + * and its documentation for any purpose is hereby granted without > + * fee, provided that the above copyright notice appear in all copies > + * and that both that copyright notice and this permission notice > + * appear in supporting documentation, and that the name of the > + * copyright holders not be used in advertising or publicity > + * pertaining to distribution of the software without specific, > + * written prior permission. The copyright holders make no > + * representations about the suitability of this software for any > + * purpose. It is provided "as is" without express or implied > + * warranty. > + * > + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS > + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND > + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY > + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN > + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING > + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS > + * SOFTWARE. > + */ > + > +#include "xwayland.h" > + > +#include <sys/mman.h> > +#include <sys/types.h> > +#include <unistd.h> > +#include <fcntl.h> > +#include <errno.h> > +#include <string.h> > +#include <stdlib.h> > + > +struct shm_pool { > + struct wl_shm_pool *pool; > + int fd; > + unsigned int size; > + unsigned int used; > + char *data; > +}; > + > +#ifndef HAVE_MKOSTEMP > +static int > +set_cloexec_or_close(int fd) > +{ > + long flags; > + > + if (fd == -1) > + return -1; > + > + flags = fcntl(fd, F_GETFD); > + if (flags == -1) > + goto err; > + > + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) > + goto err; > + > + return fd; > + > + err: > + close(fd); > + return -1; > +} > +#endif > + > +static int > +create_tmpfile_cloexec(char *tmpname) > +{ > + int fd; > + > +#ifdef HAVE_MKOSTEMP > + fd = mkostemp(tmpname, O_CLOEXEC); > + if (fd >= 0) > + unlink(tmpname); > +#else > + fd = mkstemp(tmpname); > + if (fd >= 0) { > + fd = set_cloexec_or_close(fd); > + unlink(tmpname); > + } > +#endif > + > + return fd; > +} > + > +/* > + * Create a new, unique, anonymous file of the given size, and > + * return the file descriptor for it. The file descriptor is set > + * CLOEXEC. The file is immediately suitable for mmap()'ing > + * the given size at offset zero. > + * > + * The file should not have a permanent backing store like a disk, > + * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. > + * > + * The file name is deleted from the file system. > + * > + * The file is suitable for buffer sharing between processes by > + * transmitting the file descriptor over Unix sockets using the > + * SCM_RIGHTS methods. > + * > + * If the C library implements posix_fallocate(), it is used to > + * guarantee that disk space is available for the file at the > + * given size. If disk space is insufficent, errno is set to ENOSPC. > + * If posix_fallocate() is not supported, program may receive > + * SIGBUS on accessing mmap()'ed file contents instead. > + */ > +static int > +os_create_anonymous_file(off_t size) > +{ > + static const char template[] = "/weston-shared-XXXXXX"; > + const char *path; > + char *name; > + int fd; > + int ret; > + > + path = getenv("XDG_RUNTIME_DIR"); > + if (!path) { > + errno = ENOENT; > + return -1; > + } > + > + name = malloc(strlen(path) + sizeof(template)); > + if (!name) > + return -1; > + > + strcpy(name, path); > + strcat(name, template); > + > + fd = create_tmpfile_cloexec(name); > + > + free(name); > + > + if (fd < 0) > + return -1; > + > +#ifdef HAVE_POSIX_FALLOCATE > + ret = posix_fallocate(fd, 0, size); > + if (ret != 0) { > + close(fd); > + errno = ret; > + return -1; > + } > +#else > + ret = ftruncate(fd, size); > + if (ret < 0) { > + close(fd); > + return -1; > + } > +#endif > + > + return fd; > +} > + > +static struct shm_pool * > +shm_pool_create(struct wl_shm *shm, int size) > +{ > + struct shm_pool *pool; > + > + pool = malloc(sizeof *pool); > + if (!pool) > + return NULL; > + > + pool->fd = os_create_anonymous_file(size); > + if (pool->fd < 0) > + goto err_free; > + > + pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, > + pool->fd, 0); > + > + if (pool->data == MAP_FAILED) > + goto err_close; > + > + pool->pool = wl_shm_create_pool(shm, pool->fd, size); > + pool->size = size; > + pool->used = 0; > + > + return pool; > + > + err_close: > + close(pool->fd); > + err_free: > + free(pool); > + return NULL; > +} > + > +static void > +shm_pool_destroy(struct shm_pool *pool) > +{ > + munmap(pool->data, pool->size); > + wl_shm_pool_destroy(pool->pool); > + close(pool->fd); > + free(pool); > +} > + > +struct xwl_shm_buffer * > +xwl_shm_buffer_create(struct xwl_screen *xwl_screen, > + int width, int height, int stride, uint32_t format) > +{ > + struct xwl_shm_buffer *buffer; > + > + buffer = malloc(sizeof *buffer); > + if (buffer == NULL) > + return NULL; > + > + buffer->pool = shm_pool_create(xwl_screen->shm, stride * height); > + buffer->buffer = wl_shm_pool_create_buffer(buffer->pool->pool, 0, > + width, height, stride, format); > + buffer->data = buffer->pool->data; > + > + return buffer; > +} > + > +void > +xwl_shm_buffer_destroy(struct xwl_shm_buffer *buffer) > +{ > + wl_buffer_destroy(buffer->buffer); > + shm_pool_destroy(buffer->pool); > + free(buffer); > +} > diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c > new file mode 100644 > index 0000000..35b6bf3 > --- /dev/null > +++ b/hw/xwayland/xwayland.c > @@ -0,0 +1,695 @@ > +/* > + * Copyright © 2011-2014 Intel Corporation > + * > + * Permission to use, copy, modify, distribute, and sell this software > + * and its documentation for any purpose is hereby granted without > + * fee, provided that the above copyright notice appear in all copies > + * and that both that copyright notice and this permission notice > + * appear in supporting documentation, and that the name of the > + * copyright holders not be used in advertising or publicity > + * pertaining to distribution of the software without specific, > + * written prior permission. The copyright holders make no > + * representations about the suitability of this software for any > + * purpose. It is provided "as is" without express or implied > + * warranty. > + * > + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS > + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND > + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY > + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN > + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING > + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS > + * SOFTWARE. > + */ > + > +#include "xwayland.h" > + > +#include <selection.h> > +#include <micmap.h> > + > +void > +ddxGiveUp(enum ExitCode error) > +{ > +} > + > +void > +AbortDDX(enum ExitCode error) > +{ > + ddxGiveUp(error); > +} > + > +void > +OsVendorInit(void) > +{ > +} > + > +void > +OsVendorFatalError(const char *f, va_list args) > +{ > +} > + > +#if defined(DDXBEFORERESET) > +void > +ddxBeforeReset(void) > +{ > + return; > +} > +#endif > + > +void > +ddxUseMsg(void) > +{ > + ErrorF("-rootless run rootless, requires wm support

"); > + ErrorF("-wm fd create X client for wm on given fd

"); > + ErrorF("-listen fd add give fd as a listen socket

"); > +} > + > +int > +ddxProcessArgument(int argc, char *argv[], int i) > +{ > + if (strcmp(argv[i], "-rootless") == 0) { > + return 1; > + } > + else if (strcmp(argv[i], "-listen") == 0) { > + NoListenAll = TRUE; > + return 2; > + } > + else if (strcmp(argv[i], "-wm") == 0) { > + return 2; > + } > + > + return 0; > +} > + > +static DevPrivateKeyRec xwl_window_private_key; > +static DevPrivateKeyRec xwl_screen_private_key; > +static DevPrivateKeyRec xwl_pixmap_private_key; > + > +struct xwl_screen * > +xwl_screen_get(ScreenPtr screen) > +{ > + return dixLookupPrivate(&screen->devPrivates, &xwl_screen_private_key); > +} > + > +static Bool > +xwl_close_screen(ScreenPtr screen) > +{ > + struct xwl_screen *xwl_screen = xwl_screen_get(screen); > + struct xwl_output *xwl_output, *next_xwl_output; > + struct xwl_seat *xwl_seat, *next_xwl_seat; > + > + xorg_list_for_each_entry_safe(xwl_output, next_xwl_output, > + &xwl_screen->output_list, link) > + xwl_output_destroy(xwl_output); > + > + xorg_list_for_each_entry_safe(xwl_seat, next_xwl_seat, > + &xwl_screen->seat_list, link) > + xwl_seat_destroy(xwl_seat); > + > + wl_display_disconnect(xwl_screen->display); > + > + screen->CloseScreen = xwl_screen->CloseScreen; > + xwl_shm_buffer_destroy(xwl_screen->root_buffer); > + free(xwl_screen); > + > + return screen->CloseScreen(screen); > +} > + > +static void > +damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data) > +{ > + struct xwl_window *xwl_window = data; > + struct xwl_screen *xwl_screen = xwl_window->xwl_screen; > + > + xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list); > +} > + > +static void > +damage_destroy(DamagePtr pDamage, void *data) > +{ > +} > + > +static void > +shell_surface_ping(void *data, > + struct wl_shell_surface *shell_surface, uint32_t serial) > +{ > + wl_shell_surface_pong(shell_surface, serial); > +} > + > +static void > +shell_surface_configure(void *data, > + struct wl_shell_surface *wl_shell_surface, > + uint32_t edges, int32_t width, int32_t height) > +{ > +} > + > +static void > +shell_surface_popup_done(void *data, struct wl_shell_surface *wl_shell_surface) > +{ > +} > + > +static const struct wl_shell_surface_listener shell_surface_listener = { > + shell_surface_ping, > + shell_surface_configure, > + shell_surface_popup_done > +}; > + > +static uint32_t > +format_for_depth(int depth) > +{ > + switch (depth) { > + case 32: > + return WL_SHM_FORMAT_ARGB8888; > + case 24: > + default: > + return WL_SHM_FORMAT_XRGB8888; > +#ifdef WL_SHM_FORMAT_RGB565 > + case 16: > + /* XXX: Check run-time protocol version too */ > + return WL_SHM_FORMAT_RGB565; > +#endif > + } > +} > + > +static PixmapPtr > +xwl_create_pixmap(ScreenPtr screen, > + int width, int height, int depth, unsigned int hint) > +{ > + PixmapPtr pixmap; > + struct xwl_screen *xwl_screen; > + struct xwl_shm_buffer *buffer; > + int stride, bpp; > + uint32_t format; > + > + xwl_screen = xwl_screen_get(screen); > + > + if (hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP && width > 0) { > + screen->CreatePixmap = xwl_screen->CreatePixmap; > + pixmap = (*screen->CreatePixmap) (screen, 0, 0, depth, hint); > + xwl_screen->CreatePixmap = screen->CreatePixmap; > + screen->CreatePixmap = xwl_create_pixmap; > + > + if (!pixmap) > + return NullPixmap; > + > + stride = PixmapBytePad(width, depth); > + format = format_for_depth(depth); > + bpp = BitsPerPixel(depth); > + buffer = xwl_shm_buffer_create(xwl_screen, > + width, height, stride, format); > + if (!(*screen->ModifyPixmapHeader) (pixmap, width, height, depth, > + bpp, stride, buffer->data)) > + return NullPixmap; > + > + dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key, buffer); > + > + return pixmap; > + } > + > + screen->CreatePixmap = xwl_screen->CreatePixmap; > + pixmap = (*screen->CreatePixmap) (screen, width, height, depth, hint); > + xwl_screen->CreatePixmap = screen->CreatePixmap; > + screen->CreatePixmap = xwl_create_pixmap; > + > + return pixmap; > +} > + > +static Bool > +xwl_destroy_pixmap(PixmapPtr pixmap) > +{ > + ScreenPtr screen = pixmap->drawable.pScreen; > + struct xwl_screen *xwl_screen = xwl_screen_get(screen); > + struct xwl_shm_buffer *buffer = > + dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key); > + Bool ret; > + > + if (buffer && pixmap->refcnt == 1) > + xwl_shm_buffer_destroy(buffer); > + > + screen->DestroyPixmap = xwl_screen->DestroyPixmap; > + ret = (*screen->DestroyPixmap) (pixmap); > + xwl_screen->DestroyPixmap = screen->DestroyPixmap; > + screen->DestroyPixmap = xwl_destroy_pixmap; > + > + return ret; > +} > + > +static void > +send_surface_id_event(struct xwl_window *xwl_window) > +{ > + static const char atom_name[] = "WL_SURFACE_ID"; > + static Atom type_atom; > + DeviceIntPtr dev; > + xEvent e; > + > + if (type_atom == None) > + type_atom = MakeAtom(atom_name, strlen(atom_name), TRUE); > + > + e.u.u.type = ClientMessage; > + e.u.u.detail = 32; > + e.u.clientMessage.window = xwl_window->window->drawable.id; > + e.u.clientMessage.u.l.type = type_atom; > + e.u.clientMessage.u.l.longs0 = > + wl_proxy_get_id((struct wl_proxy *) xwl_window->surface); > + e.u.clientMessage.u.l.longs1 = 0; > + e.u.clientMessage.u.l.longs2 = 0; > + e.u.clientMessage.u.l.longs3 = 0; > + e.u.clientMessage.u.l.longs4 = 0; > + > + dev = PickPointer(serverClient); > + DeliverEventsToWindow(dev, xwl_window->xwl_screen->screen->root, > + &e, 1, SubstructureRedirectMask, NullGrab); > +} > + > +static Bool > +xwl_realize_window(WindowPtr window) > +{ > + ScreenPtr screen = window->drawable.pScreen; > + struct xwl_screen *xwl_screen; > + struct xwl_window *xwl_window; > + struct wl_region *region; > + Bool ret; > + > + xwl_screen = xwl_screen_get(screen); > + > + screen->RealizeWindow = xwl_screen->RealizeWindow; > + ret = (*screen->RealizeWindow) (window); > + xwl_screen->RealizeWindow = screen->RealizeWindow; > + screen->RealizeWindow = xwl_realize_window; > + > + if (xwl_screen->rootless && !window->parent) > + RegionNull(&window->clipList); > + > + if (xwl_screen->rootless) { > + if (window->redirectDraw != RedirectDrawManual) > + return ret; > + } > + else { > + if (window->parent) > + return ret; > + } > + > + xwl_window = calloc(sizeof *xwl_window, 1); > + xwl_window->xwl_screen = xwl_screen; > + xwl_window->window = window; > + xwl_window->surface = wl_compositor_create_surface(xwl_screen->compositor); > + if (xwl_window->surface == NULL) { > + ErrorF("wl_display_create_surface failed

"); > + return FALSE; > + } > + > + if (!xwl_screen->rootless) { > + xwl_window->shell_surface = > + wl_shell_get_shell_surface(xwl_screen->shell, xwl_window->surface); > + wl_shell_surface_add_listener(xwl_window->shell_surface, > + &shell_surface_listener, xwl_window); > + > + wl_shell_surface_set_toplevel(xwl_window->shell_surface); > + > + region = wl_compositor_create_region(xwl_screen->compositor); > + wl_region_add(region, 0, 0, > + window->drawable.width, window->drawable.height); > + wl_surface_set_opaque_region(xwl_window->surface, region); > + wl_region_destroy(region); > + } > + > + wl_display_flush(xwl_screen->display); > + > + send_surface_id_event(xwl_window); > + > + wl_surface_set_user_data(xwl_window->surface, xwl_window); > + > + dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window); > + > + xwl_window->damage = > + DamageCreate(damage_report, damage_destroy, DamageReportNonEmpty, > + FALSE, screen, xwl_window); > + DamageRegister(&window->drawable, xwl_window->damage); > + DamageSetReportAfterOp(xwl_window->damage, TRUE); > + > + xorg_list_init(&xwl_window->link_damage); > + > + return ret; > +} > + > +static Bool > +xwl_unrealize_window(WindowPtr window) > +{ > + ScreenPtr screen = window->drawable.pScreen; > + struct xwl_screen *xwl_screen; > + struct xwl_window *xwl_window; > + struct xwl_seat *xwl_seat; > + Bool ret; > + > + xwl_screen = xwl_screen_get(screen); > + > + xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) { > + if (!xwl_seat->focus_window) > + continue; > + if (xwl_seat->focus_window->window == window) > + xwl_seat->focus_window = NULL; > + } > + > + screen->UnrealizeWindow = xwl_screen->UnrealizeWindow; > + ret = (*screen->UnrealizeWindow) (window); > + xwl_screen->UnrealizeWindow = screen->UnrealizeWindow; > + screen->UnrealizeWindow = xwl_unrealize_window; > + > + xwl_window = > + dixLookupPrivate(&window->devPrivates, &xwl_window_private_key); > + if (!xwl_window) > + return ret; > + > + wl_surface_destroy(xwl_window->surface); > + if (RegionNotEmpty(DamageRegion(xwl_window->damage))) > + xorg_list_del(&xwl_window->link_damage); > + DamageUnregister(xwl_window->damage); > + DamageDestroy(xwl_window->damage); > + free(xwl_window); > + dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL); > + > + return ret; > +} > + > +static Bool > +xwl_save_screen(ScreenPtr pScreen, int on) > +{ > + return TRUE; > +} > + > +static struct wl_buffer * > +xwl_window_get_buffer(struct xwl_window *xwl_window) > +{ > + struct xwl_screen *xwl_screen = xwl_window->xwl_screen; > + struct xwl_shm_buffer *buffer; > + PixmapPtr pixmap; > + > + if (xwl_window->window->parent == NULL) { > + return xwl_screen->root_buffer->buffer; > + } > + else { > + pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window); > + buffer = dixGetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key); > + if (buffer) > + return buffer->buffer; > + } > + > + return NULL; > +} > + > +static void > +xwl_screen_post_damage(struct xwl_screen *xwl_screen) > +{ > + struct xwl_window *xwl_window; > + RegionPtr region; > + BoxPtr box; > + int count, i; > + struct wl_buffer *buffer; > + > + xorg_list_for_each_entry(xwl_window, &xwl_screen->damage_window_list, > + link_damage) { > + region = DamageRegion(xwl_window->damage); > + count = RegionNumRects(region); > + buffer = xwl_window_get_buffer(xwl_window); > + if (!buffer) > + continue; > + > + wl_surface_attach(xwl_window->surface, buffer, 0, 0); > + for (i = 0; i < count; i++) { > + box = &RegionRects(region)[i]; > + wl_surface_damage(xwl_window->surface, > + box->x1, box->y1, > + box->x2 - box->x1, box->y2 - box->y1); > + } > + wl_surface_commit(xwl_window->surface); > + DamageEmpty(xwl_window->damage); > + } > + > + xorg_list_init(&xwl_screen->damage_window_list); > +} > + > +static void > +registry_global(void *data, struct wl_registry *registry, uint32_t id, > + const char *interface, uint32_t version) > +{ > + struct xwl_screen *xwl_screen = data; > + > + if (strcmp(interface, "wl_compositor") == 0) { > + xwl_screen->compositor = > + wl_registry_bind(registry, id, &wl_compositor_interface, 1); > + } > + else if (strcmp(interface, "wl_shm") == 0) { > + xwl_screen->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); > + } > + else if (strcmp(interface, "wl_shell") == 0) { > + xwl_screen->shell = > + wl_registry_bind(registry, id, &wl_shell_interface, 1); > + } > + else if (strcmp(interface, "wl_output") == 0 && version >= 2) { > + xwl_output_create(xwl_screen, id); > + xwl_screen->expecting_event++; > + } > +} > + > +static void > +global_remove(void *data, struct wl_registry *registry, uint32_t name) > +{ > + /* Nothing to do here, wl_compositor and wl_shm should not be removed */ > +} > + > +static const struct wl_registry_listener registry_listener = { > + registry_global, > + global_remove > +}; > + > +static void > +wakeup_handler(void *data, int err, void *read_mask) > +{ > + struct xwl_screen *xwl_screen = data; > + int ret; > + > + if (err < 0) > + return; > + > + if (!FD_ISSET(xwl_screen->wayland_fd, (fd_set *) read_mask)) > + return; > + > + ret = wl_display_dispatch(xwl_screen->display); > + if (ret == -1) > + FatalError("failed to dispatch Wayland events: %s

", strerror(errno)); > +} > + > +static void > +block_handler(void *data, struct timeval **tv, void *read_mask) > +{ > + struct xwl_screen *xwl_screen = data; > + int ret; > + > + xwl_screen_post_damage(xwl_screen); > + > + ret = wl_display_dispatch_pending(xwl_screen->display); > + if (ret == -1) > + FatalError("failed to dispatch Wayland events: %s

", strerror(errno)); > + > + ret = wl_display_flush(xwl_screen->display); > + if (ret == -1) > + FatalError("failed to write to XWayland fd: %s

", 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

"); > + > + TimerFree(timer); > + > + return 0; > +} > + > +static void > +wm_selection_callback(CallbackListPtr *p, void *data, void *arg) > +{ > + SelectionInfoRec *info = arg; > + struct xwl_screen *xwl_screen = data; > + static const char atom_name[] = "WM_S0"; > + static Atom atom_wm_s0; > + int i; > + > + if (atom_wm_s0 == None) > + atom_wm_s0 = MakeAtom(atom_name, strlen(atom_name), TRUE); > + if (info->selection->selection != atom_wm_s0 || > + info->kind != SelectionSetOwner) > + return; > + for (i = 0; i < xwl_screen->listen_fd_count; i++) > + ListenOnOpenFD(xwl_screen->listen_fds[i], TRUE); > + > + DeleteCallback(&SelectionCallback, wm_selection_callback, xwl_screen); > +} > + > +static Bool > +xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) > +{ > + struct xwl_screen *xwl_screen; > + Pixel red_mask, blue_mask, green_mask; > + int ret, bpc, green_bpc, stride, i; > + uint32_t format; > + void *data = NULL; > + > + xwl_screen = calloc(sizeof *xwl_screen, 1); > + if (xwl_screen == NULL) > + return FALSE; > + > + if (!dixRegisterPrivateKey(&xwl_screen_private_key, PRIVATE_SCREEN, 0)) > + return FALSE; > + if (!dixRegisterPrivateKey(&xwl_window_private_key, PRIVATE_WINDOW, 0)) > + return FALSE; > + if (!dixRegisterPrivateKey(&xwl_pixmap_private_key, PRIVATE_PIXMAP, 0)) > + return FALSE; > + > + dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen); > + xwl_screen->screen = pScreen; > + > + for (i = 1; i < argc; i++) { > + if (strcmp(argv[i], "-rootless") == 0) { > + xwl_screen->rootless = 1; > + } > + else if (strcmp(argv[i], "-wm") == 0) { > + xwl_screen->wm_fd = atoi(argv[i + 1]); > + i++; > + TimerSet(NULL, 0, 1, add_client_fd, xwl_screen); > + } > + else if (strcmp(argv[i], "-listen") == 0) { > + if (xwl_screen->listen_fd_count == > + ARRAY_SIZE(xwl_screen->listen_fds)) > + FatalError("Too many -listen arguments given, max is %ld

", > + ARRAY_SIZE(xwl_screen->listen_fds)); > + > + xwl_screen->listen_fds[xwl_screen->listen_fd_count++] = > + atoi(argv[i + 1]); > + i++; > + } > + } > + > + if (xwl_screen->listen_fd_count > 0) > + AddCallback(&SelectionCallback, wm_selection_callback, xwl_screen); > + > + xorg_list_init(&xwl_screen->output_list); > + xorg_list_init(&xwl_screen->seat_list); > + xorg_list_init(&xwl_screen->damage_window_list); > + xwl_screen->depth = 24; > + > + xwl_screen->display = wl_display_connect(NULL); > + if (xwl_screen->display == NULL) { > + ErrorF("could not connect to wayland server

"); > + 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, > + ®istry_listener, xwl_screen); > + ret = wl_display_roundtrip(xwl_screen->display); > + if (ret == -1) { > + ErrorF("could not connect to wayland server

"); > + return FALSE; > + } > + > + while (xwl_screen->expecting_event > 0) > + wl_display_roundtrip(xwl_screen->display); > + > + stride = PixmapBytePad(xwl_screen->width, xwl_screen->depth); > + format = format_for_depth(xwl_screen->depth); > + bpc = xwl_screen->depth / 3; > + green_bpc = xwl_screen->depth - 2 * bpc; > + blue_mask = (1 << bpc) - 1; > + green_mask = ((1 << green_bpc) - 1) << bpc; > + red_mask = blue_mask << (green_bpc + bpc); > + > + miSetVisualTypesAndMasks(xwl_screen->depth, > + ((1 << TrueColor) | (1 << DirectColor)), > + green_bpc, TrueColor, > + red_mask, green_mask, blue_mask); > + > + miSetPixmapDepths(); > + > + if (!xwl_screen->rootless) { > + xwl_screen->root_buffer = > + xwl_shm_buffer_create(xwl_screen, > + xwl_screen->width, xwl_screen->height, > + stride, format); > + if (xwl_screen->root_buffer == NULL) > + return FALSE; > + data = xwl_screen->root_buffer->data; > + } > + > + ret = fbScreenInit(pScreen, data, > + xwl_screen->width, xwl_screen->height, > + 96, 96, xwl_screen->width, > + BitsPerPixel(xwl_screen->depth)); > + if (!ret) > + return FALSE; > + > + fbPictureInit(pScreen, 0, 0); > + > + xwl_screen->wayland_fd = wl_display_get_fd(xwl_screen->display); > + AddGeneralSocket(xwl_screen->wayland_fd); > + RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, xwl_screen); > + > + pScreen->SaveScreen = xwl_save_screen; > + > + pScreen->blackPixel = 0; > + pScreen->whitePixel = 1; > + > + ret = fbCreateDefColormap(pScreen); > + > + if (!xwl_screen_init_cursor(xwl_screen)) > + return FALSE; > + > + xwl_screen->CreatePixmap = pScreen->CreatePixmap; > + pScreen->CreatePixmap = xwl_create_pixmap; > + > + xwl_screen->DestroyPixmap = pScreen->DestroyPixmap; > + pScreen->DestroyPixmap = xwl_destroy_pixmap; > + > + xwl_screen->RealizeWindow = pScreen->RealizeWindow; > + pScreen->RealizeWindow = xwl_realize_window; > + > + xwl_screen->UnrealizeWindow = pScreen->UnrealizeWindow; > + pScreen->UnrealizeWindow = xwl_unrealize_window; > + > + xwl_screen->CloseScreen = pScreen->CloseScreen; > + pScreen->CloseScreen = xwl_close_screen; > + > + return ret; > +} > + > +void > +InitOutput(ScreenInfo * screen_info, int argc, char **argv) > +{ > + int depths[] = { 1, 4, 8, 15, 16, 24, 32 }; > + int bpp[] = { 1, 8, 8, 16, 16, 32, 32 }; > + int i; > + > + for (i = 0; i < ARRAY_SIZE(depths); i++) { > + screen_info->formats[i].depth = depths[i]; > + screen_info->formats[i].bitsPerPixel = bpp[i]; > + screen_info->formats[i].scanlinePad = BITMAP_SCANLINE_PAD; > + } > + > + screen_info->imageByteOrder = IMAGE_BYTE_ORDER; > + screen_info->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; > + screen_info->bitmapScanlinePad = BITMAP_SCANLINE_PAD; > + screen_info->bitmapBitOrder = BITMAP_BIT_ORDER; > + screen_info->numPixmapFormats = ARRAY_SIZE(depths); > + > + if (AddScreen(xwl_screen_init, argc, argv) == -1) { > + FatalError("Couldn't add screen

"); > + } > +} > diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h > new file mode 100644 > index 0000000..cbfd6ea > --- /dev/null > +++ b/hw/xwayland/xwayland.h > @@ -0,0 +1,160 @@ > +/* > + * Copyright © 2014 Intel Corporation > + * > + * Permission to use, copy, modify, distribute, and sell this software > + * and its documentation for any purpose is hereby granted without > + * fee, provided that the above copyright notice appear in all copies > + * and that both that copyright notice and this permission notice > + * appear in supporting documentation, and that the name of the > + * copyright holders not be used in advertising or publicity > + * pertaining to distribution of the software without specific, > + * written prior permission. The copyright holders make no > + * representations about the suitability of this software for any > + * purpose. It is provided "as is" without express or implied > + * warranty. > + * > + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS > + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND > + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY > + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN > + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING > + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS > + * SOFTWARE. > + */ > + > +#ifndef XWAYLAND_H > +#define XWAYLAND_H > + > +#include <dix-config.h> > +#include <xorg-server.h> > + > +#include <stdio.h> > +#include <unistd.h> > +#include <errno.h> > + > +#include <wayland-client.h> > + > +#include <X11/X.h> > + > +#include <fb.h> > +#include <input.h> > +#include <dix.h> > +#include <randrstr.h> > +#include <exevents.h> > + > +struct xwl_screen { > + int width; > + int height; > + int depth; > + ScreenPtr screen; > + WindowPtr pointer_limbo_window; > + int expecting_event; > + > + struct xwl_shm_buffer *root_buffer; > + > + int wm_fd; > + int listen_fds[5]; > + int listen_fd_count; > + int rootless; > + > + CreatePixmapProcPtr CreatePixmap; > + DestroyPixmapProcPtr DestroyPixmap; > + CloseScreenProcPtr CloseScreen; > + CreateWindowProcPtr CreateWindow; > + DestroyWindowProcPtr DestroyWindow; > + RealizeWindowProcPtr RealizeWindow; > + UnrealizeWindowProcPtr UnrealizeWindow; > + XYToWindowProcPtr XYToWindow; > + > + struct xorg_list output_list; > + struct xorg_list seat_list; > + struct xorg_list damage_window_list; > + > + int wayland_fd; > + struct wl_display *display; > + struct wl_registry *registry; > + struct wl_registry *input_registry; > + struct wl_compositor *compositor; > + struct wl_shm *shm; > + struct wl_shell *shell; > + > + uint32_t serial; > +}; > + > +struct xwl_window { > + struct xwl_screen *xwl_screen; > + struct wl_surface *surface; > + struct wl_shell_surface *shell_surface; > + WindowPtr window; > + DamagePtr damage; > + struct xorg_list link_damage; > +}; > + > +#define MODIFIER_META 0x01 > + > +struct xwl_seat { > + DeviceIntPtr pointer; > + DeviceIntPtr keyboard; > + struct xwl_screen *xwl_screen; > + struct wl_seat *seat; > + struct wl_pointer *wl_pointer; > + struct wl_keyboard *wl_keyboard; > + struct wl_array keys; > + struct wl_surface *cursor; > + struct xwl_window *focus_window; > + uint32_t id; > + uint32_t pointer_enter_serial; > + struct xorg_list link; > + CursorPtr x_cursor; > + > + wl_fixed_t horizontal_scroll; > + wl_fixed_t vertical_scroll; > + uint32_t scroll_time; > + > + size_t keymap_size; > + char *keymap; > + struct wl_surface *keyboard_focus; > +}; > + > +struct xwl_output { > + struct xorg_list link; > + struct wl_output *output; > + struct xwl_screen *xwl_screen; > + RROutputPtr randr_output; > + RRCrtcPtr randr_crtc; > + int32_t x, y, width, height; > + Rotation rotation; > +}; > + > +struct xwl_shm_buffer { > + struct shm_pool *pool; > + struct wl_buffer *buffer; > + void *data; > +}; > + > +struct xwl_shm_buffer *xwl_shm_buffer_create(struct xwl_screen *xwl_screen, > + int width, int height, int stride, > + uint32_t format); > + > +void xwl_shm_buffer_destroy(struct xwl_shm_buffer *buffer); > + > +Bool xwl_screen_init_cursor(struct xwl_screen *xwl_screen); > + > +struct xwl_screen *xwl_screen_get(ScreenPtr screen); > + > +void xwl_seat_set_cursor(struct xwl_seat *xwl_seat); > + > +void xwl_seat_destroy(struct xwl_seat *xwl_seat); > + > +Bool xwl_screen_init_output(struct xwl_screen *xwl_screen); > + > +struct xwl_output *xwl_output_create(struct xwl_screen *xwl_screen, > + uint32_t id); > + > +void xwl_output_destroy(struct xwl_output *xwl_output); > + > +RRModePtr xwayland_cvt(int HDisplay, int VDisplay, > + float VRefresh, Bool Reduced, Bool Interlaced); > + > +#endif > -- > 1.9.0 > > _______________________________________________ > xorg-devel at lists.x.org: X.Org development > Archives: http://lists.x.org/archives/xorg-devel > Info: http://lists.x.org/mailman/listinfo/xorg-devel >