Merge remote-tracking branch 'krh/xwayland-for-keithp'
This commit is contained in:
commit
b4d0bec22c
|
@ -229,6 +229,28 @@ CompositeRegisterAlternateVisuals(ScreenPtr pScreen, VisualID * vids,
|
|||
return compRegisterAlternateVisuals(cs, vids, nVisuals);
|
||||
}
|
||||
|
||||
Bool
|
||||
CompositeRegisterImplicitRedirectionException(ScreenPtr pScreen,
|
||||
VisualID parentVisual,
|
||||
VisualID winVisual)
|
||||
{
|
||||
CompScreenPtr cs = GetCompScreen(pScreen);
|
||||
CompImplicitRedirectException *p;
|
||||
|
||||
p = realloc(cs->implicitRedirectExceptions,
|
||||
sizeof(p[0]) * (cs->numImplicitRedirectExceptions + 1));
|
||||
if (p == NULL)
|
||||
return FALSE;
|
||||
|
||||
p[cs->numImplicitRedirectExceptions].parentVisual = parentVisual;
|
||||
p[cs->numImplicitRedirectExceptions].winVisual = winVisual;
|
||||
|
||||
cs->implicitRedirectExceptions = p;
|
||||
cs->numImplicitRedirectExceptions++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct _alternateVisual {
|
||||
int depth;
|
||||
CARD32 format;
|
||||
|
@ -349,6 +371,8 @@ compScreenInit(ScreenPtr pScreen)
|
|||
|
||||
cs->numAlternateVisuals = 0;
|
||||
cs->alternateVisuals = NULL;
|
||||
cs->numImplicitRedirectExceptions = 0;
|
||||
cs->implicitRedirectExceptions = NULL;
|
||||
|
||||
if (!compAddAlternateVisuals(pScreen, cs)) {
|
||||
free(cs);
|
||||
|
|
|
@ -119,6 +119,11 @@ typedef struct _CompOverlayClientRec {
|
|||
XID resource;
|
||||
} CompOverlayClientRec;
|
||||
|
||||
typedef struct _CompImplicitRedirectException {
|
||||
XID parentVisual;
|
||||
XID winVisual;
|
||||
} CompImplicitRedirectException;
|
||||
|
||||
typedef struct _CompScreen {
|
||||
PositionWindowProcPtr PositionWindow;
|
||||
CopyWindowProcPtr CopyWindow;
|
||||
|
@ -155,6 +160,8 @@ typedef struct _CompScreen {
|
|||
CloseScreenProcPtr CloseScreen;
|
||||
int numAlternateVisuals;
|
||||
VisualID *alternateVisuals;
|
||||
int numImplicitRedirectExceptions;
|
||||
CompImplicitRedirectException *implicitRedirectExceptions;
|
||||
|
||||
WindowPtr pOverlayWin;
|
||||
Window overlayWid;
|
||||
|
|
|
@ -35,6 +35,10 @@ extern _X_EXPORT Bool CompositeRegisterAlternateVisuals(ScreenPtr pScreen,
|
|||
VisualID * vids,
|
||||
int nVisuals);
|
||||
|
||||
extern _X_EXPORT Bool CompositeRegisterImplicitRedirectionException(ScreenPtr pScreen,
|
||||
VisualID parentVisual,
|
||||
VisualID winVisual);
|
||||
|
||||
extern _X_EXPORT RESTYPE CompositeClientWindowType;
|
||||
|
||||
#endif /* _COMPOSITEEXT_H_ */
|
||||
|
|
|
@ -335,6 +335,21 @@ compIsAlternateVisual(ScreenPtr pScreen, XID visual)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
compIsImplicitRedirectException(ScreenPtr pScreen,
|
||||
XID parentVisual, XID winVisual)
|
||||
{
|
||||
CompScreenPtr cs = GetCompScreen(pScreen);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cs->numImplicitRedirectExceptions; i++)
|
||||
if (cs->implicitRedirectExceptions[i].parentVisual == parentVisual &&
|
||||
cs->implicitRedirectExceptions[i].winVisual == winVisual)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
compImplicitRedirect(WindowPtr pWin, WindowPtr pParent)
|
||||
{
|
||||
|
@ -343,6 +358,9 @@ compImplicitRedirect(WindowPtr pWin, WindowPtr pParent)
|
|||
XID winVisual = wVisual(pWin);
|
||||
XID parentVisual = wVisual(pParent);
|
||||
|
||||
if (compIsImplicitRedirectException(pScreen, parentVisual, winVisual))
|
||||
return FALSE;
|
||||
|
||||
if (winVisual != parentVisual &&
|
||||
(compIsAlternateVisual(pScreen, winVisual) ||
|
||||
compIsAlternateVisual(pScreen, parentVisual)))
|
||||
|
|
26
configure.ac
26
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
|
||||
|
@ -2437,6 +2439,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 epoxy], [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
|
||||
|
@ -2579,6 +2604,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
|
||||
|
|
46
dix/events.c
46
dix/events.c
|
@ -2835,7 +2835,7 @@ DeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent)
|
|||
return deliveries;
|
||||
}
|
||||
|
||||
static Bool
|
||||
Bool
|
||||
PointInBorderSize(WindowPtr pWin, int x, int y)
|
||||
{
|
||||
BoxRec box;
|
||||
|
@ -2876,49 +2876,9 @@ PointInBorderSize(WindowPtr pWin, int x, int y)
|
|||
WindowPtr
|
||||
XYToWindow(SpritePtr pSprite, int x, int y)
|
||||
{
|
||||
WindowPtr pWin;
|
||||
BoxRec box;
|
||||
ScreenPtr pScreen = RootWindow(pSprite)->drawable.pScreen;
|
||||
|
||||
pSprite->spriteTraceGood = 1; /* root window still there */
|
||||
pWin = RootWindow(pSprite)->firstChild;
|
||||
while (pWin) {
|
||||
if ((pWin->mapped) &&
|
||||
(x >= pWin->drawable.x - wBorderWidth(pWin)) &&
|
||||
(x < pWin->drawable.x + (int) pWin->drawable.width +
|
||||
wBorderWidth(pWin)) &&
|
||||
(y >= pWin->drawable.y - wBorderWidth(pWin)) &&
|
||||
(y < pWin->drawable.y + (int) pWin->drawable.height +
|
||||
wBorderWidth(pWin))
|
||||
/* When a window is shaped, a further check
|
||||
* is made to see if the point is inside
|
||||
* borderSize
|
||||
*/
|
||||
&& (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
|
||||
&& (!wInputShape(pWin) ||
|
||||
RegionContainsPoint(wInputShape(pWin),
|
||||
x - pWin->drawable.x,
|
||||
y - pWin->drawable.y, &box))
|
||||
#ifdef ROOTLESS
|
||||
/* In rootless mode windows may be offscreen, even when
|
||||
* they're in X's stack. (E.g. if the native window system
|
||||
* implements some form of virtual desktop system).
|
||||
*/
|
||||
&& !pWin->rootlessUnhittable
|
||||
#endif
|
||||
) {
|
||||
if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) {
|
||||
pSprite->spriteTraceSize += 10;
|
||||
pSprite->spriteTrace = realloc(pSprite->spriteTrace,
|
||||
pSprite->spriteTraceSize *
|
||||
sizeof(WindowPtr));
|
||||
}
|
||||
pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
|
||||
pWin = pWin->firstChild;
|
||||
}
|
||||
else
|
||||
pWin = pWin->nextSib;
|
||||
}
|
||||
return DeepestSpriteWin(pSprite);
|
||||
return (*pScreen->XYToWindow)(pScreen, pSprite, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,7 +32,8 @@
|
|||
|
||||
#define DRI3_SCREEN_INFO_VERSION 0
|
||||
|
||||
typedef int (*dri3_open_proc)(ScreenPtr screen,
|
||||
typedef int (*dri3_open_proc)(ClientPtr client,
|
||||
ScreenPtr screen,
|
||||
RRProviderPtr provider,
|
||||
int *fd);
|
||||
|
||||
|
@ -60,6 +61,9 @@ typedef struct dri3_screen_info {
|
|||
extern _X_EXPORT Bool
|
||||
dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info);
|
||||
|
||||
extern _X_EXPORT int
|
||||
dri3_send_open_reply(ClientPtr client, int fd);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _DRI3_H_ */
|
||||
|
|
|
@ -55,16 +55,35 @@ proc_dri3_query_version(ClientPtr client)
|
|||
return Success;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_dri3_open(ClientPtr client)
|
||||
int
|
||||
dri3_send_open_reply(ClientPtr client, int fd)
|
||||
{
|
||||
REQUEST(xDRI3OpenReq);
|
||||
xDRI3OpenReply rep = {
|
||||
.type = X_Reply,
|
||||
.nfd = 1,
|
||||
.sequenceNumber = client->sequence,
|
||||
.length = 0,
|
||||
};
|
||||
|
||||
if (client->swapped) {
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.length);
|
||||
}
|
||||
|
||||
if (WriteFdToClient(client, fd, TRUE) < 0) {
|
||||
close(fd);
|
||||
return BadAlloc;
|
||||
}
|
||||
|
||||
WriteToClient(client, sizeof (rep), &rep);
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_dri3_open(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI3OpenReq);
|
||||
RRProviderPtr provider;
|
||||
DrawablePtr drawable;
|
||||
ScreenPtr screen;
|
||||
|
@ -92,17 +111,8 @@ proc_dri3_open(ClientPtr client)
|
|||
if (status != Success)
|
||||
return status;
|
||||
|
||||
if (client->swapped) {
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.length);
|
||||
}
|
||||
|
||||
if (WriteFdToClient(client, fd, TRUE) < 0) {
|
||||
close(fd);
|
||||
return BadAlloc;
|
||||
}
|
||||
|
||||
WriteToClient(client, sizeof (rep), &rep);
|
||||
if (client->ignoreCount == 0)
|
||||
return dri3_send_open_reply(client, fd);
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd)
|
|||
if (!info || !info->open)
|
||||
return BadMatch;
|
||||
|
||||
rc = (*info->open) (screen, provider, fd);
|
||||
rc = (*info->open) (client, screen, provider, fd);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
|
||||
|
|
|
@ -182,7 +182,15 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
|
|||
pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3;
|
||||
screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL);
|
||||
|
||||
if (type == GLAMOR_MEMORY_MAP || usage == GLAMOR_CREATE_NO_LARGE ||
|
||||
if (usage == GLAMOR_CREATE_PIXMAP_NO_TEXTURE) {
|
||||
pixmap_priv->type = GLAMOR_TEXTURE_ONLY;
|
||||
pixmap_priv->base.box.x1 = 0;
|
||||
pixmap_priv->base.box.y1 = 0;
|
||||
pixmap_priv->base.box.x2 = w;
|
||||
pixmap_priv->base.box.y2 = h;
|
||||
return pixmap;
|
||||
}
|
||||
else if (type == GLAMOR_MEMORY_MAP || usage == GLAMOR_CREATE_NO_LARGE ||
|
||||
glamor_check_fbo_size(glamor_priv, w, h))
|
||||
{
|
||||
pixmap_priv->type = type;
|
||||
|
|
|
@ -143,12 +143,14 @@ extern _X_EXPORT void glamor_block_handler(ScreenPtr screen);
|
|||
|
||||
extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h,
|
||||
int depth, unsigned int usage);
|
||||
extern _X_EXPORT Bool glamor_destroy_pixmap(PixmapPtr pixmap);
|
||||
|
||||
#define GLAMOR_CREATE_PIXMAP_CPU 0x100
|
||||
#define GLAMOR_CREATE_PIXMAP_FIXUP 0x101
|
||||
#define GLAMOR_CREATE_FBO_NO_FBO 0x103
|
||||
#define GLAMOR_CREATE_PIXMAP_MAP 0x104
|
||||
#define GLAMOR_CREATE_NO_LARGE 0x105
|
||||
#define GLAMOR_CREATE_PIXMAP_NO_TEXTURE 0x106
|
||||
|
||||
/* @glamor_egl_exchange_buffers: Exchange the underlying buffers(KHR image,fbo).
|
||||
*
|
||||
|
@ -310,6 +312,8 @@ extern _X_EXPORT Bool
|
|||
|
||||
#endif
|
||||
|
||||
extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen,
|
||||
struct glamor_context *glamor_ctx);
|
||||
extern _X_EXPORT void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap);
|
||||
|
||||
extern _X_EXPORT int glamor_create_gc(GCPtr gc);
|
||||
|
|
|
@ -608,7 +608,8 @@ glamor_egl_close_screen(ScreenPtr screen)
|
|||
}
|
||||
|
||||
static int
|
||||
glamor_dri3_open(ScreenPtr screen,
|
||||
glamor_dri3_open(ClientPtr client,
|
||||
ScreenPtr screen,
|
||||
RRProviderPtr provider,
|
||||
int *fdp)
|
||||
{
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
* Stubbed out glamor_egl.c functions for servers other than Xorg.
|
||||
*/
|
||||
|
||||
#include "glamor_priv.h"
|
||||
#include "dix-config.h"
|
||||
|
||||
#include "glamor.h"
|
||||
|
||||
void
|
||||
glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
|
||||
|
|
|
@ -599,8 +599,6 @@ extern int glamor_debug_level;
|
|||
/* glamor.c */
|
||||
PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable);
|
||||
|
||||
Bool glamor_destroy_pixmap(PixmapPtr pixmap);
|
||||
|
||||
glamor_pixmap_fbo *glamor_pixmap_detach_fbo(glamor_pixmap_private *
|
||||
pixmap_priv);
|
||||
void glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo);
|
||||
|
@ -1022,9 +1020,6 @@ void glamor_composite_rectangles(CARD8 op,
|
|||
xRenderColor *color,
|
||||
int num_rects, xRectangle *rects);
|
||||
|
||||
extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen,
|
||||
struct glamor_context *glamor_ctx);
|
||||
|
||||
/* glamor_xv */
|
||||
typedef struct {
|
||||
uint32_t transform_index;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
Xwayland
|
||||
drm-client-protocol.h
|
||||
drm-protocol.c
|
|
@ -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)
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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,
|
||||
®istry_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");
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -607,6 +607,7 @@ extern int GetXI2MaskByte(XI2Mask *mask, DeviceIntPtr dev, int event_type);
|
|||
void FixUpEventFromWindow(SpritePtr pSprite,
|
||||
xEvent *xE,
|
||||
WindowPtr pWin, Window child, Bool calcChild);
|
||||
extern Bool PointInBorderSize(WindowPtr pWin, int x, int y);
|
||||
extern WindowPtr XYToWindow(SpritePtr pSprite, int x, int y);
|
||||
extern int EventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win);
|
||||
extern Bool ActivatePassiveGrab(DeviceIntPtr dev, GrabPtr grab,
|
||||
|
|
|
@ -353,6 +353,9 @@ typedef Bool (*StopPixmapTrackingProcPtr)(PixmapPtr, PixmapPtr);
|
|||
|
||||
typedef Bool (*ReplaceScanoutPixmapProcPtr)(DrawablePtr, PixmapPtr, Bool);
|
||||
|
||||
typedef WindowPtr (*XYToWindowProcPtr)(ScreenPtr pScreen,
|
||||
SpritePtr pSprite, int x, int y);
|
||||
|
||||
typedef struct _Screen {
|
||||
int myNum; /* index of this instance in Screens[] */
|
||||
ATOM id;
|
||||
|
@ -513,6 +516,7 @@ typedef struct _Screen {
|
|||
struct xorg_list offload_head;
|
||||
|
||||
ReplaceScanoutPixmapProcPtr ReplaceScanoutPixmap;
|
||||
XYToWindowProcPtr XYToWindow;
|
||||
} ScreenRec;
|
||||
|
||||
static inline RegionPtr
|
||||
|
|
4
mi/mi.h
4
mi/mi.h
|
@ -507,6 +507,10 @@ extern _X_EXPORT void miMarkUnrealizedWindow(WindowPtr /*pChild */ ,
|
|||
extern _X_EXPORT void miSegregateChildren(WindowPtr pWin, RegionPtr pReg,
|
||||
int depth);
|
||||
|
||||
extern _X_EXPORT WindowPtr miSpriteTrace(SpritePtr pSprite, int x, int y);
|
||||
|
||||
extern _X_EXPORT WindowPtr miXYToWindow(ScreenPtr pScreen, SpritePtr pSprite, int x, int y);
|
||||
|
||||
/* mizerarc.c */
|
||||
|
||||
extern _X_EXPORT void miZeroPolyArc(DrawablePtr /*pDraw */ ,
|
||||
|
|
|
@ -272,6 +272,7 @@ miScreenInit(ScreenPtr pScreen, void *pbits, /* pointer to screen bits */
|
|||
pScreen->ChangeBorderWidth = miChangeBorderWidth;
|
||||
pScreen->SetShape = miSetShape;
|
||||
pScreen->MarkUnrealizedWindow = miMarkUnrealizedWindow;
|
||||
pScreen->XYToWindow = miXYToWindow;
|
||||
|
||||
miSetZeroLineBias(pScreen, DEFAULTZEROLINEBIAS);
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ SOFTWARE.
|
|||
#include "scrnintstr.h"
|
||||
#include "pixmapstr.h"
|
||||
#include "mivalidate.h"
|
||||
#include "inputstr.h"
|
||||
|
||||
void
|
||||
miClearToBackground(WindowPtr pWin,
|
||||
|
@ -758,3 +759,68 @@ miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth)
|
|||
miSegregateChildren(pChild, pReg, depth);
|
||||
}
|
||||
}
|
||||
|
||||
WindowPtr
|
||||
miSpriteTrace(SpritePtr pSprite, int x, int y)
|
||||
{
|
||||
WindowPtr pWin;
|
||||
BoxRec box;
|
||||
|
||||
pWin = DeepestSpriteWin(pSprite);
|
||||
while (pWin) {
|
||||
if ((pWin->mapped) &&
|
||||
(x >= pWin->drawable.x - wBorderWidth(pWin)) &&
|
||||
(x < pWin->drawable.x + (int) pWin->drawable.width +
|
||||
wBorderWidth(pWin)) &&
|
||||
(y >= pWin->drawable.y - wBorderWidth(pWin)) &&
|
||||
(y < pWin->drawable.y + (int) pWin->drawable.height +
|
||||
wBorderWidth(pWin))
|
||||
/* When a window is shaped, a further check
|
||||
* is made to see if the point is inside
|
||||
* borderSize
|
||||
*/
|
||||
&& (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
|
||||
&& (!wInputShape(pWin) ||
|
||||
RegionContainsPoint(wInputShape(pWin),
|
||||
x - pWin->drawable.x,
|
||||
y - pWin->drawable.y, &box))
|
||||
#ifdef ROOTLESS
|
||||
/* In rootless mode windows may be offscreen, even when
|
||||
* they're in X's stack. (E.g. if the native window system
|
||||
* implements some form of virtual desktop system).
|
||||
*/
|
||||
&& !pWin->rootlessUnhittable
|
||||
#endif
|
||||
) {
|
||||
if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) {
|
||||
pSprite->spriteTraceSize += 10;
|
||||
pSprite->spriteTrace = realloc(pSprite->spriteTrace,
|
||||
pSprite->spriteTraceSize *
|
||||
sizeof(WindowPtr));
|
||||
}
|
||||
pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
|
||||
pWin = pWin->firstChild;
|
||||
}
|
||||
else
|
||||
pWin = pWin->nextSib;
|
||||
}
|
||||
return DeepestSpriteWin(pSprite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Traversed from the root window to the window at the position x/y. While
|
||||
* traversing, it sets up the traversal history in the spriteTrace array.
|
||||
* After completing, the spriteTrace history is set in the following way:
|
||||
* spriteTrace[0] ... root window
|
||||
* spriteTrace[1] ... top level window that encloses x/y
|
||||
* ...
|
||||
* spriteTrace[spriteTraceGood - 1] ... window at x/y
|
||||
*
|
||||
* @returns the window at the given coordinates.
|
||||
*/
|
||||
WindowPtr
|
||||
miXYToWindow(ScreenPtr pScreen, SpritePtr pSprite, int x, int y)
|
||||
{
|
||||
pSprite->spriteTraceGood = 1; /* root window still there */
|
||||
return miSpriteTrace(pSprite, x, y);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue