Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

383 Commits   1 Branch   1 Tag
Index: Makefile
===================================================================
--- Makefile	(nonexistent)
+++ Makefile	(revision 5)
@@ -0,0 +1,13 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+SOURCE_REQUIRES += ALL_DIRS
+
+
+include ../../../build-system/core.mk
+
+
+download_clean:
+	@true
+
+.PHONY: download_clean
Index: xorg-server/Makefile
===================================================================
--- xorg-server/Makefile	(nonexistent)
+++ xorg-server/Makefile	(revision 5)
@@ -0,0 +1,66 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/xserver/xorg-server
+
+versions    = 21.1.7
+pkgname     = xorg-server
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+patches     = $(CURDIR)/patches/xorg-server-21.1.7-black.patch
+patches    += $(CURDIR)/patches/xorg-server-21.1.7-dont-check-SeatId.patch
+patches    += $(CURDIR)/patches/xorg-server-21.1.7-mouse-kbd-layout.patch
+patches    += $(CURDIR)/patches/xorg-server-21.1.7-modesetting-on-GeForce.patch
+patches    += $(CURDIR)/patches/xorg-server-21.1.7-intel-ddx-only-on-pre-gen4.patch
+patches    += $(CURDIR)/patches/xorg-server-21.1.7-nouveau-segfault.patch
+
+.NOTPARALLEL: $(patches)
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s) $(patches)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+$(patches): $(sha1s)
+	@echo -e "\n======= Create Patches =======\n" ; \
+	 ( cd create-21.1.7-black-patch                       ; ./create.patch.sh ) ; \
+	 ( cd create-21.1.7-dont-check-SeatId-patch           ; ./create.patch.sh ) ; \
+	 ( cd create-21.1.7-mouse-kbd-layout-patch            ; ./create.patch.sh ) ; \
+	 ( cd create-21.1.7-modesetting-on-GeForce-patch      ; ./create.patch.sh ) ; \
+	 ( cd create-21.1.7-intel-ddx-only-on-pre-gen4-patch  ; ./create.patch.sh ) ; \
+	 ( cd create-21.1.7-nouveau-segfault-patch            ; ./create.patch.sh ) ; \
+	 echo -e "\n"
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s) $(patches)
Index: xorg-server/create-21.1.7-black-patch/create.patch.sh
===================================================================
--- xorg-server/create-21.1.7-black-patch/create.patch.sh	(nonexistent)
+++ xorg-server/create-21.1.7-black-patch/create.patch.sh	(revision 5)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=21.1.7
+
+tar --files-from=file.list -xJvf ../xorg-server-$VERSION.tar.xz
+mv xorg-server-$VERSION xorg-server-$VERSION-orig
+
+cp -rf ./xorg-server-$VERSION-new ./xorg-server-$VERSION
+
+diff --unified -Nr  xorg-server-$VERSION-orig  xorg-server-$VERSION > xorg-server-$VERSION-black.patch
+
+mv xorg-server-$VERSION-black.patch ../patches
+
+rm -rf ./xorg-server-$VERSION
+rm -rf ./xorg-server-$VERSION-orig

Property changes on: xorg-server/create-21.1.7-black-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xorg-server/create-21.1.7-black-patch/file.list
===================================================================
--- xorg-server/create-21.1.7-black-patch/file.list	(nonexistent)
+++ xorg-server/create-21.1.7-black-patch/file.list	(revision 5)
@@ -0,0 +1 @@
+xorg-server-21.1.7/dix/window.c
Index: xorg-server/create-21.1.7-black-patch/xorg-server-21.1.7-new/dix/window.c
===================================================================
--- xorg-server/create-21.1.7-black-patch/xorg-server-21.1.7-new/dix/window.c	(nonexistent)
+++ xorg-server/create-21.1.7-black-patch/xorg-server-21.1.7-new/dix/window.c	(revision 5)
@@ -0,0 +1,3733 @@
+/*
+
+Copyright (c) 2006, Red Hat, Inc.
+
+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 (including the next
+paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+
+Copyright 1987, 1998  The Open Group
+
+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.
+
+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 OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
+
+			All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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.
+
+*/
+
+/* The panoramix components contained the following notice */
+/*****************************************************************
+
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+
+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.
+
+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
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+
+******************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "misc.h"
+#include "scrnintstr.h"
+#include "os.h"
+#include "regionstr.h"
+#include "validate.h"
+#include "windowstr.h"
+#include "propertyst.h"
+#include "input.h"
+#include "inputstr.h"
+#include "resource.h"
+#include "colormapst.h"
+#include "cursorstr.h"
+#include "dixstruct.h"
+#include "gcstruct.h"
+#include "servermd.h"
+#include "mivalidate.h"
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+#include "dixevents.h"
+#include "globals.h"
+#include "mi.h"                 /* miPaintWindow */
+#ifdef COMPOSITE
+#include "compint.h"
+#endif
+#include "selection.h"
+#include "inpututils.h"
+
+#include "privates.h"
+#include "xace.h"
+#include "exevents.h"
+
+#include <X11/Xatom.h>          /* must come after server includes */
+
+/******
+ * Window stuff for server
+ *
+ *    CreateRootWindow, CreateWindow, ChangeWindowAttributes,
+ *    GetWindowAttributes, DeleteWindow, DestroySubWindows,
+ *    HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows,
+ *    UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow,
+ *    ChangeWindowDeviceCursor
+ ******/
+
+Bool bgNoneRoot = FALSE;
+
+static unsigned char _back_lsb[4] = { 0x00, 0x00, 0x00, 0x00 };
+static unsigned char _back_msb[4] = { 0x00, 0x00, 0x00, 0x00 };
+
+static Bool WindowParentHasDeviceCursor(WindowPtr pWin,
+                                        DeviceIntPtr pDev, CursorPtr pCurs);
+static Bool
+
+WindowSeekDeviceCursor(WindowPtr pWin,
+                       DeviceIntPtr pDev,
+                       DevCursNodePtr * pNode, DevCursNodePtr * pPrev);
+
+int screenIsSaved = SCREEN_SAVER_OFF;
+
+static Bool TileScreenSaver(ScreenPtr pScreen, int kind);
+
+#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \
+			      CWDontPropagate | CWOverrideRedirect | CWCursor )
+
+#define BOXES_OVERLAP(b1, b2) \
+      (!( ((b1)->x2 <= (b2)->x1)  || \
+	( ((b1)->x1 >= (b2)->x2)) || \
+	( ((b1)->y2 <= (b2)->y1)) || \
+	( ((b1)->y1 >= (b2)->y2)) ) )
+
+#define RedirectSend(pWin) \
+    ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureRedirectMask)
+
+#define SubSend(pWin) \
+    ((pWin->eventMask|wOtherEventMasks(pWin)) & SubstructureNotifyMask)
+
+#define StrSend(pWin) \
+    ((pWin->eventMask|wOtherEventMasks(pWin)) & StructureNotifyMask)
+
+#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent))
+
+#ifdef COMPOSITE
+static const char *overlay_win_name = "<composite overlay>";
+#endif
+
+static const char *
+get_window_name(WindowPtr pWin)
+{
+#define WINDOW_NAME_BUF_LEN 512
+    PropertyPtr prop;
+    static char buf[WINDOW_NAME_BUF_LEN];
+    int len;
+
+#ifdef COMPOSITE
+    CompScreenPtr comp_screen = GetCompScreen(pWin->drawable.pScreen);
+
+    if (comp_screen && pWin == comp_screen->pOverlayWin)
+        return overlay_win_name;
+#endif
+
+    for (prop = wUserProps(pWin); prop; prop = prop->next) {
+        if (prop->propertyName == XA_WM_NAME && prop->type == XA_STRING &&
+            prop->data) {
+            len = min(prop->size, WINDOW_NAME_BUF_LEN - 1);
+            memcpy(buf, prop->data, len);
+            buf[len] = '\0';
+            return buf;
+        }
+    }
+
+    return NULL;
+#undef WINDOW_NAME_BUF_LEN
+}
+
+static void
+log_window_info(WindowPtr pWin, int depth)
+{
+    int i;
+    const char *win_name, *visibility;
+    BoxPtr rects;
+
+    for (i = 0; i < (depth << 2); i++)
+        ErrorF(" ");
+
+    win_name = get_window_name(pWin);
+    ErrorF("win 0x%.8x (%s), [%d, %d] to [%d, %d]",
+           (unsigned) pWin->drawable.id,
+           win_name ? win_name : "no name",
+           pWin->drawable.x, pWin->drawable.y,
+           pWin->drawable.x + pWin->drawable.width,
+           pWin->drawable.y + pWin->drawable.height);
+
+    if (pWin->overrideRedirect)
+        ErrorF(" (override redirect)");
+#ifdef COMPOSITE
+    if (pWin->redirectDraw)
+        ErrorF(" (%s compositing: pixmap %x)",
+               (pWin->redirectDraw == RedirectDrawAutomatic) ?
+               "automatic" : "manual",
+               (unsigned) pWin->drawable.pScreen->GetWindowPixmap(pWin)->drawable.id);
+#endif
+
+    switch (pWin->visibility) {
+    case VisibilityUnobscured:
+        visibility = "unobscured";
+        break;
+    case VisibilityPartiallyObscured:
+        visibility = "partially obscured";
+        break;
+    case VisibilityFullyObscured:
+        visibility = "fully obscured";
+        break;
+    case VisibilityNotViewable:
+        visibility = "unviewable";
+        break;
+    }
+    ErrorF(", %s", visibility);
+
+    if (RegionNotEmpty(&pWin->clipList)) {
+        ErrorF(", clip list:");
+        rects = RegionRects(&pWin->clipList);
+        for (i = 0; i < RegionNumRects(&pWin->clipList); i++)
+            ErrorF(" [(%d, %d) to (%d, %d)]",
+                   rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
+        ErrorF("; extents [(%d, %d) to (%d, %d)]",
+               pWin->clipList.extents.x1, pWin->clipList.extents.y1,
+               pWin->clipList.extents.x2, pWin->clipList.extents.y2);
+    }
+
+    ErrorF("\n");
+}
+
+static const char*
+grab_grabtype_to_text(GrabPtr pGrab)
+{
+    switch (pGrab->grabtype) {
+        case XI2:
+            return "xi2";
+        case CORE:
+            return "core";
+        default:
+            return "xi1";
+    }
+}
+
+static const char*
+grab_type_to_text(GrabPtr pGrab)
+{
+    switch (pGrab->type) {
+        case ButtonPress:
+            return "ButtonPress";
+        case KeyPress:
+            return "KeyPress";
+        case XI_Enter:
+            return "XI_Enter";
+        case XI_FocusIn:
+            return "XI_FocusIn";
+        default:
+            return "unknown?!";
+    }
+}
+
+static void
+log_grab_info(void *value, XID id, void *cdata)
+{
+    int i, j;
+    GrabPtr pGrab = (GrabPtr)value;
+
+    ErrorF("  grab 0x%lx (%s), type '%s' on window 0x%lx\n",
+           (unsigned long) pGrab->resource,
+           grab_grabtype_to_text(pGrab),
+           grab_type_to_text(pGrab),
+           (unsigned long) pGrab->window->drawable.id);
+    ErrorF("    detail %d (mask %lu), modifiersDetail %d (mask %lu)\n",
+           pGrab->detail.exact,
+           pGrab->detail.pMask ? (unsigned long) *(pGrab->detail.pMask) : 0,
+           pGrab->modifiersDetail.exact,
+           pGrab->modifiersDetail.pMask ?
+           (unsigned long) *(pGrab->modifiersDetail.pMask) :
+           (unsigned long) 0);
+    ErrorF("    device '%s' (%d), modifierDevice '%s' (%d)\n",
+           pGrab->device->name, pGrab->device->id,
+           pGrab->modifierDevice->name, pGrab->modifierDevice->id);
+    if (pGrab->grabtype == CORE) {
+        ErrorF("    core event mask 0x%lx\n",
+               (unsigned long) pGrab->eventMask);
+    }
+    else if (pGrab->grabtype == XI) {
+        ErrorF("    xi1 event mask 0x%lx\n",
+               (unsigned long) pGrab->eventMask);
+    }
+    else if (pGrab->grabtype == XI2) {
+        for (i = 0; i < xi2mask_num_masks(pGrab->xi2mask); i++) {
+            const unsigned char *mask;
+            int print;
+
+            print = 0;
+            for (j = 0; j < XI2MASKSIZE; j++) {
+                mask = xi2mask_get_one_mask(pGrab->xi2mask, i);
+                if (mask[j]) {
+                    print = 1;
+                    break;
+                }
+            }
+            if (!print)
+                continue;
+            ErrorF("      xi2 event mask 0x");
+            for (j = 0; j < xi2mask_mask_size(pGrab->xi2mask); j++)
+                ErrorF("%x ", mask[j]);
+            ErrorF("\n");
+        }
+    }
+    ErrorF("    owner-events %s, kb %d ptr %d, confine 0x%lx, cursor 0x%lx\n",
+           pGrab->ownerEvents ? "true" : "false",
+           pGrab->keyboardMode, pGrab->pointerMode,
+           pGrab->confineTo ? (unsigned long) pGrab->confineTo->drawable.id : 0,
+           pGrab->cursor ? (unsigned long) pGrab->cursor->id : 0);
+}
+
+void
+PrintPassiveGrabs(void)
+{
+    int i;
+    LocalClientCredRec *lcc;
+    pid_t clientpid;
+    const char *cmdname;
+    const char *cmdargs;
+
+    ErrorF("Printing all currently registered grabs\n");
+
+    for (i = 1; i < currentMaxClients; i++) {
+        if (!clients[i] || clients[i]->clientState != ClientStateRunning)
+            continue;
+
+        clientpid = GetClientPid(clients[i]);
+        cmdname = GetClientCmdName(clients[i]);
+        cmdargs = GetClientCmdArgs(clients[i]);
+        if ((clientpid > 0) && (cmdname != NULL)) {
+            ErrorF("  Printing all registered grabs of client pid %ld %s %s\n",
+                   (long) clientpid, cmdname, cmdargs ? cmdargs : "");
+        } else {
+            if (GetLocalClientCreds(clients[i], &lcc) == -1) {
+                ErrorF("  GetLocalClientCreds() failed\n");
+                continue;
+            }
+            ErrorF("  Printing all registered grabs of client pid %ld uid %ld gid %ld\n",
+                   (lcc->fieldsSet & LCC_PID_SET) ? (long) lcc->pid : 0,
+                   (lcc->fieldsSet & LCC_UID_SET) ? (long) lcc->euid : 0,
+                   (lcc->fieldsSet & LCC_GID_SET) ? (long) lcc->egid : 0);
+            FreeLocalClientCreds(lcc);
+        }
+
+        FindClientResourcesByType(clients[i], RT_PASSIVEGRAB, log_grab_info, NULL);
+    }
+    ErrorF("End list of registered passive grabs\n");
+}
+
+void
+PrintWindowTree(void)
+{
+    int scrnum, depth;
+    ScreenPtr pScreen;
+    WindowPtr pWin;
+
+    for (scrnum = 0; scrnum < screenInfo.numScreens; scrnum++) {
+        pScreen = screenInfo.screens[scrnum];
+        ErrorF("[dix] Dumping windows for screen %d (pixmap %x):\n", scrnum,
+               (unsigned) pScreen->GetScreenPixmap(pScreen)->drawable.id);
+        pWin = pScreen->root;
+        depth = 1;
+        while (pWin) {
+            log_window_info(pWin, depth);
+            if (pWin->firstChild) {
+                pWin = pWin->firstChild;
+                depth++;
+                continue;
+            }
+            while (pWin && !pWin->nextSib) {
+                pWin = pWin->parent;
+                depth--;
+            }
+            if (!pWin)
+                break;
+            pWin = pWin->nextSib;
+        }
+    }
+}
+
+int
+TraverseTree(WindowPtr pWin, VisitWindowProcPtr func, void *data)
+{
+    int result;
+    WindowPtr pChild;
+
+    if (!(pChild = pWin))
+        return WT_NOMATCH;
+    while (1) {
+        result = (*func) (pChild, data);
+        if (result == WT_STOPWALKING)
+            return WT_STOPWALKING;
+        if ((result == WT_WALKCHILDREN) && pChild->firstChild) {
+            pChild = pChild->firstChild;
+            continue;
+        }
+        while (!pChild->nextSib && (pChild != pWin))
+            pChild = pChild->parent;
+        if (pChild == pWin)
+            break;
+        pChild = pChild->nextSib;
+    }
+    return WT_NOMATCH;
+}
+
+/*****
+ * WalkTree
+ *   Walk the window tree, for SCREEN, performing FUNC(pWin, data) on
+ *   each window.  If FUNC returns WT_WALKCHILDREN, traverse the children,
+ *   if it returns WT_DONTWALKCHILDREN, don't.  If it returns WT_STOPWALKING,
+ *   exit WalkTree.  Does depth-first traverse.
+ *****/
+
+int
+WalkTree(ScreenPtr pScreen, VisitWindowProcPtr func, void *data)
+{
+    return (TraverseTree(pScreen->root, func, data));
+}
+
+/* hack to force no backing store */
+Bool disableBackingStore = FALSE;
+Bool enableBackingStore = FALSE;
+
+static void
+SetWindowToDefaults(WindowPtr pWin)
+{
+    pWin->prevSib = NullWindow;
+    pWin->firstChild = NullWindow;
+    pWin->lastChild = NullWindow;
+
+    pWin->valdata = NULL;
+    pWin->optional = NULL;
+    pWin->cursorIsNone = TRUE;
+
+    pWin->backingStore = NotUseful;
+
+    pWin->mapped = FALSE;       /* off */
+    pWin->realized = FALSE;     /* off */
+    pWin->viewable = FALSE;
+    pWin->visibility = VisibilityNotViewable;
+    pWin->overrideRedirect = FALSE;
+    pWin->saveUnder = FALSE;
+
+    pWin->bitGravity = ForgetGravity;
+    pWin->winGravity = NorthWestGravity;
+
+    pWin->eventMask = 0;
+    pWin->deliverableEvents = 0;
+    pWin->dontPropagate = 0;
+    pWin->redirectDraw = RedirectDrawNone;
+    pWin->forcedBG = FALSE;
+    pWin->unhittable = FALSE;
+
+#ifdef COMPOSITE
+    pWin->damagedDescendants = FALSE;
+#endif
+}
+
+static void
+MakeRootTile(WindowPtr pWin)
+{
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+    GCPtr pGC;
+    unsigned char back[128];
+    int len = BitmapBytePad(sizeof(long));
+    unsigned char *from, *to;
+    int i, j;
+
+    pWin->background.pixmap = (*pScreen->CreatePixmap) (pScreen, 4, 4,
+                                                        pScreen->rootDepth, 0);
+
+    pWin->backgroundState = BackgroundPixmap;
+    pGC = GetScratchGC(pScreen->rootDepth, pScreen);
+    if (!pWin->background.pixmap || !pGC)
+        FatalError("could not create root tile");
+
+    {
+        ChangeGCVal attributes[2];
+
+        attributes[0].val = pScreen->whitePixel;
+        attributes[1].val = pScreen->blackPixel;
+
+        (void) ChangeGC(NullClient, pGC, GCForeground | GCBackground,
+                        attributes);
+    }
+
+    ValidateGC((DrawablePtr) pWin->background.pixmap, pGC);
+
+    from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb;
+    to = back;
+
+    for (i = 4; i > 0; i--, from++)
+        for (j = len; j > 0; j--)
+            *to++ = *from;
+
+    (*pGC->ops->PutImage) ((DrawablePtr) pWin->background.pixmap, pGC, 1,
+                           0, 0, len, 4, 0, XYBitmap, (char *) back);
+
+    FreeScratchGC(pGC);
+
+}
+
+/*****
+ * CreateRootWindow
+ *    Makes a window at initialization time for specified screen
+ *****/
+
+Bool
+CreateRootWindow(ScreenPtr pScreen)
+{
+    WindowPtr pWin;
+    BoxRec box;
+    PixmapFormatRec *format;
+
+    pWin = dixAllocateScreenObjectWithPrivates(pScreen, WindowRec, PRIVATE_WINDOW);
+    if (!pWin)
+        return FALSE;
+
+    pScreen->screensaver.pWindow = NULL;
+    pScreen->screensaver.wid = FakeClientID(0);
+    pScreen->screensaver.ExternalScreenSaver = NULL;
+    screenIsSaved = SCREEN_SAVER_OFF;
+
+    pScreen->root = pWin;
+
+    pWin->drawable.pScreen = pScreen;
+    pWin->drawable.type = DRAWABLE_WINDOW;
+
+    pWin->drawable.depth = pScreen->rootDepth;
+    for (format = screenInfo.formats;
+         format->depth != pScreen->rootDepth; format++);
+    pWin->drawable.bitsPerPixel = format->bitsPerPixel;
+
+    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+
+    pWin->parent = NullWindow;
+    SetWindowToDefaults(pWin);
+
+    pWin->optional = malloc(sizeof(WindowOptRec));
+    if (!pWin->optional)
+        return FALSE;
+
+    pWin->optional->dontPropagateMask = 0;
+    pWin->optional->otherEventMasks = 0;
+    pWin->optional->otherClients = NULL;
+    pWin->optional->passiveGrabs = NULL;
+    pWin->optional->userProps = NULL;
+    pWin->optional->backingBitPlanes = ~0L;
+    pWin->optional->backingPixel = 0;
+    pWin->optional->boundingShape = NULL;
+    pWin->optional->clipShape = NULL;
+    pWin->optional->inputShape = NULL;
+    pWin->optional->inputMasks = NULL;
+    pWin->optional->deviceCursors = NULL;
+    pWin->optional->colormap = pScreen->defColormap;
+    pWin->optional->visual = pScreen->rootVisual;
+
+    pWin->nextSib = NullWindow;
+
+    pWin->drawable.id = FakeClientID(0);
+
+    pWin->origin.x = pWin->origin.y = 0;
+    pWin->drawable.height = pScreen->height;
+    pWin->drawable.width = pScreen->width;
+    pWin->drawable.x = pWin->drawable.y = 0;
+
+    box.x1 = 0;
+    box.y1 = 0;
+    box.x2 = pScreen->width;
+    box.y2 = pScreen->height;
+    RegionInit(&pWin->clipList, &box, 1);
+    RegionInit(&pWin->winSize, &box, 1);
+    RegionInit(&pWin->borderSize, &box, 1);
+    RegionInit(&pWin->borderClip, &box, 1);
+
+    pWin->drawable.class = InputOutput;
+    pWin->optional->visual = pScreen->rootVisual;
+
+    pWin->backgroundState = BackgroundPixel;
+    pWin->background.pixel = pScreen->whitePixel;
+
+    pWin->borderIsPixel = TRUE;
+    pWin->border.pixel = pScreen->blackPixel;
+    pWin->borderWidth = 0;
+
+    /*  security creation/labeling check
+     */
+    if (XaceHook(XACE_RESOURCE_ACCESS, serverClient, pWin->drawable.id,
+                 RT_WINDOW, pWin, RT_NONE, NULL, DixCreateAccess))
+        return FALSE;
+
+    if (!AddResource(pWin->drawable.id, RT_WINDOW, (void *) pWin))
+        return FALSE;
+
+    if (disableBackingStore)
+        pScreen->backingStoreSupport = NotUseful;
+    if (enableBackingStore)
+        pScreen->backingStoreSupport = WhenMapped;
+#ifdef COMPOSITE
+    if (noCompositeExtension)
+        pScreen->backingStoreSupport = NotUseful;
+#endif
+
+    pScreen->saveUnderSupport = NotUseful;
+
+    return TRUE;
+}
+
+void
+InitRootWindow(WindowPtr pWin)
+{
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+    int backFlag = CWBorderPixel | CWCursor | CWBackingStore;
+
+    if (!(*pScreen->CreateWindow) (pWin))
+        return;                 /* XXX */
+    (*pScreen->PositionWindow) (pWin, 0, 0);
+
+    pWin->cursorIsNone = FALSE;
+    pWin->optional->cursor = RefCursor(rootCursor);
+
+    if (party_like_its_1989) {
+        MakeRootTile(pWin);
+        backFlag |= CWBackPixmap;
+    }
+    else if (pScreen->canDoBGNoneRoot && bgNoneRoot) {
+        pWin->backgroundState = XaceBackgroundNoneState(pWin);
+        pWin->background.pixel = pScreen->whitePixel;
+        backFlag |= CWBackPixmap;
+    }
+    else {
+        pWin->backgroundState = BackgroundPixel;
+        if (whiteRoot)
+            pWin->background.pixel = pScreen->whitePixel;
+        else
+            pWin->background.pixel = pScreen->blackPixel;
+        backFlag |= CWBackPixel;
+    }
+
+    pWin->backingStore = NotUseful;
+    /* We SHOULD check for an error value here XXX */
+    (*pScreen->ChangeWindowAttributes) (pWin, backFlag);
+
+    MapWindow(pWin, serverClient);
+}
+
+/* Set the region to the intersection of the rectangle and the
+ * window's winSize.  The window is typically the parent of the
+ * window from which the region came.
+ */
+
+static void
+ClippedRegionFromBox(WindowPtr pWin, RegionPtr Rgn, int x, int y, int w, int h)
+{
+    BoxRec box = *RegionExtents(&pWin->winSize);
+
+    /* we do these calculations to avoid overflows */
+    if (x > box.x1)
+        box.x1 = x;
+    if (y > box.y1)
+        box.y1 = y;
+    x += w;
+    if (x < box.x2)
+        box.x2 = x;
+    y += h;
+    if (y < box.y2)
+        box.y2 = y;
+    if (box.x1 > box.x2)
+        box.x2 = box.x1;
+    if (box.y1 > box.y2)
+        box.y2 = box.y1;
+    RegionReset(Rgn, &box);
+    RegionIntersect(Rgn, Rgn, &pWin->winSize);
+}
+
+static RealChildHeadProc realChildHeadProc = NULL;
+
+void
+RegisterRealChildHeadProc(RealChildHeadProc proc)
+{
+    realChildHeadProc = proc;
+}
+
+WindowPtr
+RealChildHead(WindowPtr pWin)
+{
+    if (realChildHeadProc) {
+        return realChildHeadProc(pWin);
+    }
+
+    if (!pWin->parent &&
+        (screenIsSaved == SCREEN_SAVER_ON) &&
+        (HasSaverWindow(pWin->drawable.pScreen)))
+        return pWin->firstChild;
+    else
+        return NullWindow;
+}
+
+/*****
+ * CreateWindow
+ *    Makes a window in response to client request
+ *****/
+
+WindowPtr
+CreateWindow(Window wid, WindowPtr pParent, int x, int y, unsigned w,
+             unsigned h, unsigned bw, unsigned class, Mask vmask, XID *vlist,
+             int depth, ClientPtr client, VisualID visual, int *error)
+{
+    WindowPtr pWin;
+    WindowPtr pHead;
+    ScreenPtr pScreen;
+    int idepth, ivisual;
+    Bool fOK;
+    DepthPtr pDepth;
+    PixmapFormatRec *format;
+    WindowOptPtr ancwopt;
+
+    if (class == CopyFromParent)
+        class = pParent->drawable.class;
+
+    if ((class != InputOutput) && (class != InputOnly)) {
+        *error = BadValue;
+        client->errorValue = class;
+        return NullWindow;
+    }
+
+    if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) {
+        *error = BadMatch;
+        return NullWindow;
+    }
+
+    if ((class == InputOnly) && ((bw != 0) || (depth != 0))) {
+        *error = BadMatch;
+        return NullWindow;
+    }
+
+    pScreen = pParent->drawable.pScreen;
+    if ((class == InputOutput) && (depth == 0))
+        depth = pParent->drawable.depth;
+    ancwopt = pParent->optional;
+    if (!ancwopt)
+        ancwopt = FindWindowWithOptional(pParent)->optional;
+    if (visual == CopyFromParent) {
+        visual = ancwopt->visual;
+    }
+
+    /* Find out if the depth and visual are acceptable for this Screen */
+    if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) {
+        fOK = FALSE;
+        for (idepth = 0; idepth < pScreen->numDepths; idepth++) {
+            pDepth = (DepthPtr) &pScreen->allowedDepths[idepth];
+            if ((depth == pDepth->depth) || (depth == 0)) {
+                for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) {
+                    if (visual == pDepth->vids[ivisual]) {
+                        fOK = TRUE;
+                        break;
+                    }
+                }
+            }
+        }
+        if (fOK == FALSE) {
+            *error = BadMatch;
+            return NullWindow;
+        }
+    }
+
+    if (((vmask & (CWBorderPixmap | CWBorderPixel)) == 0) &&
+        (class != InputOnly) && (depth != pParent->drawable.depth)) {
+        *error = BadMatch;
+        return NullWindow;
+    }
+
+    if (((vmask & CWColormap) == 0) &&
+        (class != InputOnly) &&
+        ((visual != ancwopt->visual) || (ancwopt->colormap == None))) {
+        *error = BadMatch;
+        return NullWindow;
+    }
+
+    pWin = dixAllocateScreenObjectWithPrivates(pScreen, WindowRec, PRIVATE_WINDOW);
+    if (!pWin) {
+        *error = BadAlloc;
+        return NullWindow;
+    }
+    pWin->drawable = pParent->drawable;
+    pWin->drawable.depth = depth;
+    if (depth == pParent->drawable.depth)
+        pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel;
+    else {
+        for (format = screenInfo.formats; format->depth != depth; format++);
+        pWin->drawable.bitsPerPixel = format->bitsPerPixel;
+    }
+    if (class == InputOnly)
+        pWin->drawable.type = (short) UNDRAWABLE_WINDOW;
+    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+
+    pWin->drawable.id = wid;
+    pWin->drawable.class = class;
+
+    pWin->parent = pParent;
+    SetWindowToDefaults(pWin);
+
+    if (visual != ancwopt->visual) {
+        if (!MakeWindowOptional(pWin)) {
+            dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
+            *error = BadAlloc;
+            return NullWindow;
+        }
+        pWin->optional->visual = visual;
+        pWin->optional->colormap = None;
+    }
+
+    pWin->borderWidth = bw;
+
+    /*  security creation/labeling check
+     */
+    *error = XaceHook(XACE_RESOURCE_ACCESS, client, wid, RT_WINDOW, pWin,
+                      RT_WINDOW, pWin->parent,
+                      DixCreateAccess | DixSetAttrAccess);
+    if (*error != Success) {
+        dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
+        return NullWindow;
+    }
+
+    pWin->backgroundState = XaceBackgroundNoneState(pWin);
+    pWin->background.pixel = pScreen->whitePixel;
+
+    pWin->borderIsPixel = pParent->borderIsPixel;
+    pWin->border = pParent->border;
+    if (pWin->borderIsPixel == FALSE)
+        pWin->border.pixmap->refcnt++;
+
+    pWin->origin.x = x + (int) bw;
+    pWin->origin.y = y + (int) bw;
+    pWin->drawable.width = w;
+    pWin->drawable.height = h;
+    pWin->drawable.x = pParent->drawable.x + x + (int) bw;
+    pWin->drawable.y = pParent->drawable.y + y + (int) bw;
+
+    /* set up clip list correctly for unobscured WindowPtr */
+    RegionNull(&pWin->clipList);
+    RegionNull(&pWin->borderClip);
+    RegionNull(&pWin->winSize);
+    RegionNull(&pWin->borderSize);
+
+    pHead = RealChildHead(pParent);
+    if (pHead) {
+        pWin->nextSib = pHead->nextSib;
+        if (pHead->nextSib)
+            pHead->nextSib->prevSib = pWin;
+        else
+            pParent->lastChild = pWin;
+        pHead->nextSib = pWin;
+        pWin->prevSib = pHead;
+    }
+    else {
+        pWin->nextSib = pParent->firstChild;
+        if (pParent->firstChild)
+            pParent->firstChild->prevSib = pWin;
+        else
+            pParent->lastChild = pWin;
+        pParent->firstChild = pWin;
+    }
+
+    SetWinSize(pWin);
+    SetBorderSize(pWin);
+
+    /* We SHOULD check for an error value here XXX */
+    if (!(*pScreen->CreateWindow) (pWin)) {
+        *error = BadAlloc;
+        DeleteWindow(pWin, None);
+        return NullWindow;
+    }
+    /* We SHOULD check for an error value here XXX */
+    (*pScreen->PositionWindow) (pWin, pWin->drawable.x, pWin->drawable.y);
+
+    if (!(vmask & CWEventMask))
+        RecalculateDeliverableEvents(pWin);
+
+    if (vmask)
+        *error = ChangeWindowAttributes(pWin, vmask, vlist, wClient(pWin));
+    else
+        *error = Success;
+
+    if (*error != Success) {
+        DeleteWindow(pWin, None);
+        return NullWindow;
+    }
+
+    if (SubSend(pParent)) {
+        xEvent event = {
+            .u.createNotify.window = wid,
+            .u.createNotify.parent = pParent->drawable.id,
+            .u.createNotify.x = x,
+            .u.createNotify.y = y,
+            .u.createNotify.width = w,
+            .u.createNotify.height = h,
+            .u.createNotify.borderWidth = bw,
+            .u.createNotify.override = pWin->overrideRedirect
+        };
+        event.u.u.type = CreateNotify;
+        DeliverEvents(pParent, &event, 1, NullWindow);
+    }
+    return pWin;
+}
+
+static void
+DisposeWindowOptional(WindowPtr pWin)
+{
+    if (!pWin->optional)
+        return;
+    /*
+     * everything is peachy.  Delete the optional record
+     * and clean up
+     */
+    if (pWin->optional->cursor) {
+        FreeCursor(pWin->optional->cursor, (Cursor) 0);
+        pWin->cursorIsNone = FALSE;
+    }
+    else
+        pWin->cursorIsNone = TRUE;
+
+    if (pWin->optional->deviceCursors) {
+        DevCursorList pList;
+        DevCursorList pPrev;
+
+        pList = pWin->optional->deviceCursors;
+        while (pList) {
+            if (pList->cursor)
+                FreeCursor(pList->cursor, (XID) 0);
+            pPrev = pList;
+            pList = pList->next;
+            free(pPrev);
+        }
+        pWin->optional->deviceCursors = NULL;
+    }
+
+    free(pWin->optional);
+    pWin->optional = NULL;
+}
+
+static void
+FreeWindowResources(WindowPtr pWin)
+{
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+
+    DeleteWindowFromAnySaveSet(pWin);
+    DeleteWindowFromAnySelections(pWin);
+    DeleteWindowFromAnyEvents(pWin, TRUE);
+    RegionUninit(&pWin->clipList);
+    RegionUninit(&pWin->winSize);
+    RegionUninit(&pWin->borderClip);
+    RegionUninit(&pWin->borderSize);
+    if (wBoundingShape(pWin))
+        RegionDestroy(wBoundingShape(pWin));
+    if (wClipShape(pWin))
+        RegionDestroy(wClipShape(pWin));
+    if (wInputShape(pWin))
+        RegionDestroy(wInputShape(pWin));
+    if (pWin->borderIsPixel == FALSE)
+        (*pScreen->DestroyPixmap) (pWin->border.pixmap);
+    if (pWin->backgroundState == BackgroundPixmap)
+        (*pScreen->DestroyPixmap) (pWin->background.pixmap);
+
+    DeleteAllWindowProperties(pWin);
+    /* We SHOULD check for an error value here XXX */
+    (*pScreen->DestroyWindow) (pWin);
+    DisposeWindowOptional(pWin);
+}
+
+static void
+CrushTree(WindowPtr pWin)
+{
+    WindowPtr pChild, pSib, pParent;
+    UnrealizeWindowProcPtr UnrealizeWindow;
+
+    if (!(pChild = pWin->firstChild))
+        return;
+    UnrealizeWindow = pWin->drawable.pScreen->UnrealizeWindow;
+    while (1) {
+        if (pChild->firstChild) {
+            pChild = pChild->firstChild;
+            continue;
+        }
+        while (1) {
+            pParent = pChild->parent;
+            if (SubStrSend(pChild, pParent)) {
+                xEvent event = { .u.u.type = DestroyNotify };
+                event.u.destroyNotify.window = pChild->drawable.id;
+                DeliverEvents(pChild, &event, 1, NullWindow);
+            }
+            FreeResource(pChild->drawable.id, RT_WINDOW);
+            pSib = pChild->nextSib;
+            pChild->viewable = FALSE;
+            if (pChild->realized) {
+                pChild->realized = FALSE;
+                (*UnrealizeWindow) (pChild);
+            }
+            FreeWindowResources(pChild);
+            dixFreeObjectWithPrivates(pChild, PRIVATE_WINDOW);
+            if ((pChild = pSib))
+                break;
+            pChild = pParent;
+            pChild->firstChild = NullWindow;
+            pChild->lastChild = NullWindow;
+            if (pChild == pWin)
+                return;
+        }
+    }
+}
+
+/*****
+ *  DeleteWindow
+ *	 Deletes child of window then window itself
+ *	 If wid is None, don't send any events
+ *****/
+
+int
+DeleteWindow(void *value, XID wid)
+{
+    WindowPtr pParent;
+    WindowPtr pWin = (WindowPtr) value;
+
+    UnmapWindow(pWin, FALSE);
+
+    CrushTree(pWin);
+
+    pParent = pWin->parent;
+    if (wid && pParent && SubStrSend(pWin, pParent)) {
+        xEvent event = { .u.u.type = DestroyNotify };
+        event.u.destroyNotify.window = pWin->drawable.id;
+        DeliverEvents(pWin, &event, 1, NullWindow);
+    }
+
+    FreeWindowResources(pWin);
+    if (pParent) {
+        if (pParent->firstChild == pWin)
+            pParent->firstChild = pWin->nextSib;
+        if (pParent->lastChild == pWin)
+            pParent->lastChild = pWin->prevSib;
+        if (pWin->nextSib)
+            pWin->nextSib->prevSib = pWin->prevSib;
+        if (pWin->prevSib)
+            pWin->prevSib->nextSib = pWin->nextSib;
+    }
+    else
+        pWin->drawable.pScreen->root = NULL;
+    dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
+    return Success;
+}
+
+int
+DestroySubwindows(WindowPtr pWin, ClientPtr client)
+{
+    /* XXX
+     * The protocol is quite clear that each window should be
+     * destroyed in turn, however, unmapping all of the first
+     * eliminates most of the calls to ValidateTree.  So,
+     * this implementation is incorrect in that all of the
+     * UnmapNotifies occur before all of the DestroyNotifies.
+     * If you care, simply delete the call to UnmapSubwindows.
+     */
+    UnmapSubwindows(pWin);
+    while (pWin->lastChild) {
+        int rc = XaceHook(XACE_RESOURCE_ACCESS, client,
+                          pWin->lastChild->drawable.id, RT_WINDOW,
+                          pWin->lastChild, RT_NONE, NULL, DixDestroyAccess);
+
+        if (rc != Success)
+            return rc;
+        FreeResource(pWin->lastChild->drawable.id, RT_NONE);
+    }
+    return Success;
+}
+
+static void
+SetRootWindowBackground(WindowPtr pWin, ScreenPtr pScreen, Mask *index2)
+{
+    /* following the protocol: "Changing the background of a root window to
+     * None or ParentRelative restores the default background pixmap" */
+    if (bgNoneRoot) {
+        pWin->backgroundState = XaceBackgroundNoneState(pWin);
+        pWin->background.pixel = pScreen->whitePixel;
+    }
+    else if (party_like_its_1989)
+        MakeRootTile(pWin);
+    else {
+        pWin->backgroundState = BackgroundPixel;
+        if (whiteRoot)
+            pWin->background.pixel = pScreen->whitePixel;
+        else
+            pWin->background.pixel = pScreen->blackPixel;
+        *index2 = CWBackPixel;
+    }
+}
+
+/*****
+ *  ChangeWindowAttributes
+ *
+ *  The value-mask specifies which attributes are to be changed; the
+ *  value-list contains one value for each one bit in the mask, from least
+ *  to most significant bit in the mask.
+ *****/
+
+int
+ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client)
+{
+    XID *pVlist;
+    PixmapPtr pPixmap;
+    Pixmap pixID;
+    CursorPtr pCursor, pOldCursor;
+    Cursor cursorID;
+    WindowPtr pChild;
+    Colormap cmap;
+    ColormapPtr pCmap;
+    xEvent xE;
+    int error, rc;
+    ScreenPtr pScreen;
+    Mask index2, tmask, vmaskCopy = 0;
+    unsigned int val;
+    Bool checkOptional = FALSE, borderRelative = FALSE;
+
+    if ((pWin->drawable.class == InputOnly) &&
+        (vmask & (~INPUTONLY_LEGAL_MASK)))
+        return BadMatch;
+
+    error = Success;
+    pScreen = pWin->drawable.pScreen;
+    pVlist = vlist;
+    tmask = vmask;
+    while (tmask) {
+        index2 = (Mask) lowbit(tmask);
+        tmask &= ~index2;
+        switch (index2) {
+        case CWBackPixmap:
+            pixID = (Pixmap) * pVlist;
+            pVlist++;
+            if (pWin->backgroundState == ParentRelative)
+                borderRelative = TRUE;
+            if (pixID == None) {
+                if (pWin->backgroundState == BackgroundPixmap)
+                    (*pScreen->DestroyPixmap) (pWin->background.pixmap);
+                if (!pWin->parent)
+                    SetRootWindowBackground(pWin, pScreen, &index2);
+                else {
+                    pWin->backgroundState = XaceBackgroundNoneState(pWin);
+                    pWin->background.pixel = pScreen->whitePixel;
+                }
+            }
+            else if (pixID == ParentRelative) {
+                if (pWin->parent &&
+                    pWin->drawable.depth != pWin->parent->drawable.depth) {
+                    error = BadMatch;
+                    goto PatchUp;
+                }
+                if (pWin->backgroundState == BackgroundPixmap)
+                    (*pScreen->DestroyPixmap) (pWin->background.pixmap);
+                if (!pWin->parent)
+                    SetRootWindowBackground(pWin, pScreen, &index2);
+                else
+                    pWin->backgroundState = ParentRelative;
+                borderRelative = TRUE;
+                /* Note that the parent's backgroundTile's refcnt is NOT
+                 * incremented. */
+            }
+            else {
+                rc = dixLookupResourceByType((void **) &pPixmap, pixID,
+                                             RT_PIXMAP, client, DixReadAccess);
+                if (rc == Success) {
+                    if ((pPixmap->drawable.depth != pWin->drawable.depth) ||
+                        (pPixmap->drawable.pScreen != pScreen)) {
+                        error = BadMatch;
+                        goto PatchUp;
+                    }
+                    if (pWin->backgroundState == BackgroundPixmap)
+                        (*pScreen->DestroyPixmap) (pWin->background.pixmap);
+                    pWin->backgroundState = BackgroundPixmap;
+                    pWin->background.pixmap = pPixmap;
+                    pPixmap->refcnt++;
+                }
+                else {
+                    error = rc;
+                    client->errorValue = pixID;
+                    goto PatchUp;
+                }
+            }
+            break;
+        case CWBackPixel:
+            if (pWin->backgroundState == ParentRelative)
+                borderRelative = TRUE;
+            if (pWin->backgroundState == BackgroundPixmap)
+                (*pScreen->DestroyPixmap) (pWin->background.pixmap);
+            pWin->backgroundState = BackgroundPixel;
+            pWin->background.pixel = (CARD32) *pVlist;
+            /* background pixel overrides background pixmap,
+               so don't let the ddx layer see both bits */
+            vmaskCopy &= ~CWBackPixmap;
+            pVlist++;
+            break;
+        case CWBorderPixmap:
+            pixID = (Pixmap) * pVlist;
+            pVlist++;
+            if (pixID == CopyFromParent) {
+                if (!pWin->parent ||
+                    (pWin->drawable.depth != pWin->parent->drawable.depth)) {
+                    error = BadMatch;
+                    goto PatchUp;
+                }
+                if (pWin->parent->borderIsPixel == TRUE) {
+                    if (pWin->borderIsPixel == FALSE)
+                        (*pScreen->DestroyPixmap) (pWin->border.pixmap);
+                    pWin->border = pWin->parent->border;
+                    pWin->borderIsPixel = TRUE;
+                    index2 = CWBorderPixel;
+                    break;
+                }
+                else {
+                    pixID = pWin->parent->border.pixmap->drawable.id;
+                }
+            }
+            rc = dixLookupResourceByType((void **) &pPixmap, pixID, RT_PIXMAP,
+                                         client, DixReadAccess);
+            if (rc == Success) {
+                if ((pPixmap->drawable.depth != pWin->drawable.depth) ||
+                    (pPixmap->drawable.pScreen != pScreen)) {
+                    error = BadMatch;
+                    goto PatchUp;
+                }
+                if (pWin->borderIsPixel == FALSE)
+                    (*pScreen->DestroyPixmap) (pWin->border.pixmap);
+                pWin->borderIsPixel = FALSE;
+                pWin->border.pixmap = pPixmap;
+                pPixmap->refcnt++;
+            }
+            else {
+                error = rc;
+                client->errorValue = pixID;
+                goto PatchUp;
+            }
+            break;
+        case CWBorderPixel:
+            if (pWin->borderIsPixel == FALSE)
+                (*pScreen->DestroyPixmap) (pWin->border.pixmap);
+            pWin->borderIsPixel = TRUE;
+            pWin->border.pixel = (CARD32) *pVlist;
+            /* border pixel overrides border pixmap,
+               so don't let the ddx layer see both bits */
+            vmaskCopy &= ~CWBorderPixmap;
+            pVlist++;
+            break;
+        case CWBitGravity:
+            val = (CARD8) *pVlist;
+            pVlist++;
+            if (val > StaticGravity) {
+                error = BadValue;
+                client->errorValue = val;
+                goto PatchUp;
+            }
+            pWin->bitGravity = val;
+            break;
+        case CWWinGravity:
+            val = (CARD8) *pVlist;
+            pVlist++;
+            if (val > StaticGravity) {
+                error = BadValue;
+                client->errorValue = val;
+                goto PatchUp;
+            }
+            pWin->winGravity = val;
+            break;
+        case CWBackingStore:
+            val = (CARD8) *pVlist;
+            pVlist++;
+            if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) {
+                error = BadValue;
+                client->errorValue = val;
+                goto PatchUp;
+            }
+            /* if we're not actually changing the window's state, hide
+             * CWBackingStore from vmaskCopy so it doesn't get passed to
+             * ->ChangeWindowAttributes below
+             */
+            if (pWin->backingStore == val)
+                continue;
+            pWin->backingStore = val;
+            break;
+        case CWBackingPlanes:
+            if (pWin->optional || ((CARD32) *pVlist != (CARD32) ~0L)) {
+                if (!pWin->optional && !MakeWindowOptional(pWin)) {
+                    error = BadAlloc;
+                    goto PatchUp;
+                }
+                pWin->optional->backingBitPlanes = (CARD32) *pVlist;
+                if ((CARD32) *pVlist == (CARD32) ~0L)
+                    checkOptional = TRUE;
+            }
+            pVlist++;
+            break;
+        case CWBackingPixel:
+            if (pWin->optional || (CARD32) *pVlist) {
+                if (!pWin->optional && !MakeWindowOptional(pWin)) {
+                    error = BadAlloc;
+                    goto PatchUp;
+                }
+                pWin->optional->backingPixel = (CARD32) *pVlist;
+                if (!*pVlist)
+                    checkOptional = TRUE;
+            }
+            pVlist++;
+            break;
+        case CWSaveUnder:
+            val = (BOOL) * pVlist;
+            pVlist++;
+            if ((val != xTrue) && (val != xFalse)) {
+                error = BadValue;
+                client->errorValue = val;
+                goto PatchUp;
+            }
+            pWin->saveUnder = val;
+            break;
+        case CWEventMask:
+            rc = EventSelectForWindow(pWin, client, (Mask) *pVlist);
+            if (rc) {
+                error = rc;
+                goto PatchUp;
+            }
+            pVlist++;
+            break;
+        case CWDontPropagate:
+            rc = EventSuppressForWindow(pWin, client, (Mask) *pVlist,
+                                        &checkOptional);
+            if (rc) {
+                error = rc;
+                goto PatchUp;
+            }
+            pVlist++;
+            break;
+        case CWOverrideRedirect:
+            val = (BOOL) * pVlist;
+            pVlist++;
+            if ((val != xTrue) && (val != xFalse)) {
+                error = BadValue;
+                client->errorValue = val;
+                goto PatchUp;
+            }
+            if (val == xTrue) {
+                rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
+                              RT_WINDOW, pWin, RT_NONE, NULL, DixGrabAccess);
+                if (rc != Success) {
+                    error = rc;
+                    client->errorValue = pWin->drawable.id;
+                    goto PatchUp;
+                }
+            }
+            pWin->overrideRedirect = val;
+            break;
+        case CWColormap:
+            cmap = (Colormap) * pVlist;
+            pVlist++;
+            if (cmap == CopyFromParent) {
+                if (pWin->parent &&
+                    (!pWin->optional ||
+                     pWin->optional->visual == wVisual(pWin->parent))) {
+                    cmap = wColormap(pWin->parent);
+                }
+                else
+                    cmap = None;
+            }
+            if (cmap == None) {
+                error = BadMatch;
+                goto PatchUp;
+            }
+            rc = dixLookupResourceByType((void **) &pCmap, cmap, RT_COLORMAP,
+                                         client, DixUseAccess);
+            if (rc != Success) {
+                error = rc;
+                client->errorValue = cmap;
+                goto PatchUp;
+            }
+            if (pCmap->pVisual->vid != wVisual(pWin) ||
+                pCmap->pScreen != pScreen) {
+                error = BadMatch;
+                goto PatchUp;
+            }
+            if (cmap != wColormap(pWin)) {
+                if (!pWin->optional) {
+                    if (!MakeWindowOptional(pWin)) {
+                        error = BadAlloc;
+                        goto PatchUp;
+                    }
+                }
+                else if (pWin->parent && cmap == wColormap(pWin->parent))
+                    checkOptional = TRUE;
+
+                /*
+                 * propagate the original colormap to any children
+                 * inheriting it
+                 */
+
+                for (pChild = pWin->firstChild; pChild;
+                     pChild = pChild->nextSib) {
+                    if (!pChild->optional && !MakeWindowOptional(pChild)) {
+                        error = BadAlloc;
+                        goto PatchUp;
+                    }
+                }
+
+                pWin->optional->colormap = cmap;
+
+                /*
+                 * check on any children now matching the new colormap
+                 */
+
+                for (pChild = pWin->firstChild; pChild;
+                     pChild = pChild->nextSib) {
+                    if (pChild->optional->colormap == cmap)
+                        CheckWindowOptionalNeed(pChild);
+                }
+
+                xE = (xEvent) {
+                    .u.colormap.window = pWin->drawable.id,
+                    .u.colormap.colormap = cmap,
+                    .u.colormap.new = xTrue,
+                    .u.colormap.state = IsMapInstalled(cmap, pWin)
+                };
+                xE.u.u.type = ColormapNotify;
+                DeliverEvents(pWin, &xE, 1, NullWindow);
+            }
+            break;
+        case CWCursor:
+            cursorID = (Cursor) * pVlist;
+            pVlist++;
+            /*
+             * install the new
+             */
+            if (cursorID == None) {
+                if (pWin == pWin->drawable.pScreen->root)
+                    pCursor = rootCursor;
+                else
+                    pCursor = (CursorPtr) None;
+            }
+            else {
+                rc = dixLookupResourceByType((void **) &pCursor, cursorID,
+                                             RT_CURSOR, client, DixUseAccess);
+                if (rc != Success) {
+                    error = rc;
+                    client->errorValue = cursorID;
+                    goto PatchUp;
+                }
+            }
+
+            if (pCursor != wCursor(pWin)) {
+                /*
+                 * patch up child windows so they don't lose cursors.
+                 */
+
+                for (pChild = pWin->firstChild; pChild;
+                     pChild = pChild->nextSib) {
+                    if (!pChild->optional && !pChild->cursorIsNone &&
+                        !MakeWindowOptional(pChild)) {
+                        error = BadAlloc;
+                        goto PatchUp;
+                    }
+                }
+
+                pOldCursor = 0;
+                if (pCursor == (CursorPtr) None) {
+                    pWin->cursorIsNone = TRUE;
+                    if (pWin->optional) {
+                        pOldCursor = pWin->optional->cursor;
+                        pWin->optional->cursor = (CursorPtr) None;
+                        checkOptional = TRUE;
+                    }
+                }
+                else {
+                    if (!pWin->optional) {
+                        if (!MakeWindowOptional(pWin)) {
+                            error = BadAlloc;
+                            goto PatchUp;
+                        }
+                    }
+                    else if (pWin->parent && pCursor == wCursor(pWin->parent))
+                        checkOptional = TRUE;
+                    pOldCursor = pWin->optional->cursor;
+                    pWin->optional->cursor = RefCursor(pCursor);
+                    pWin->cursorIsNone = FALSE;
+                    /*
+                     * check on any children now matching the new cursor
+                     */
+
+                    for (pChild = pWin->firstChild; pChild;
+                         pChild = pChild->nextSib) {
+                        if (pChild->optional &&
+                            (pChild->optional->cursor == pCursor))
+                            CheckWindowOptionalNeed(pChild);
+                    }
+                }
+
+                CursorVisible = TRUE;
+
+                if (pWin->realized)
+                    WindowHasNewCursor(pWin);
+
+                /* Can't free cursor until here - old cursor
+                 * is needed in WindowHasNewCursor
+                 */
+                if (pOldCursor)
+                    FreeCursor(pOldCursor, (Cursor) 0);
+            }
+            break;
+        default:
+            error = BadValue;
+            client->errorValue = vmask;
+            goto PatchUp;
+        }
+        vmaskCopy |= index2;
+    }
+ PatchUp:
+    if (checkOptional)
+        CheckWindowOptionalNeed(pWin);
+
+    /* We SHOULD check for an error value here XXX */
+    (*pScreen->ChangeWindowAttributes) (pWin, vmaskCopy);
+
+    /*
+       If the border contents have changed, redraw the border.
+       Note that this has to be done AFTER pScreen->ChangeWindowAttributes
+       for the tile to be rotated, and the correct function selected.
+     */
+    if (((vmaskCopy & (CWBorderPixel | CWBorderPixmap)) || borderRelative)
+        && pWin->viewable && HasBorder(pWin)) {
+        RegionRec exposed;
+
+        RegionNull(&exposed);
+        RegionSubtract(&exposed, &pWin->borderClip, &pWin->winSize);
+        pWin->drawable.pScreen->PaintWindow(pWin, &exposed, PW_BORDER);
+        RegionUninit(&exposed);
+    }
+    return error;
+}
+
+/*****
+ * GetWindowAttributes
+ *    Notice that this is different than ChangeWindowAttributes
+ *****/
+
+void
+GetWindowAttributes(WindowPtr pWin, ClientPtr client,
+                    xGetWindowAttributesReply * wa)
+{
+    wa->type = X_Reply;
+    wa->bitGravity = pWin->bitGravity;
+    wa->winGravity = pWin->winGravity;
+    wa->backingStore = pWin->backingStore;
+    wa->length = bytes_to_int32(sizeof(xGetWindowAttributesReply) -
+                                sizeof(xGenericReply));
+    wa->sequenceNumber = client->sequence;
+    wa->backingBitPlanes = wBackingBitPlanes(pWin);
+    wa->backingPixel = wBackingPixel(pWin);
+    wa->saveUnder = (BOOL) pWin->saveUnder;
+    wa->override = pWin->overrideRedirect;
+    if (!pWin->mapped)
+        wa->mapState = IsUnmapped;
+    else if (pWin->realized)
+        wa->mapState = IsViewable;
+    else
+        wa->mapState = IsUnviewable;
+
+    wa->colormap = wColormap(pWin);
+    wa->mapInstalled = (wa->colormap == None) ? xFalse
+        : IsMapInstalled(wa->colormap, pWin);
+
+    wa->yourEventMask = EventMaskForClient(pWin, client);
+    wa->allEventMasks = pWin->eventMask | wOtherEventMasks(pWin);
+    wa->doNotPropagateMask = wDontPropagateMask(pWin);
+    wa->class = pWin->drawable.class;
+    wa->visualID = wVisual(pWin);
+}
+
+WindowPtr
+MoveWindowInStack(WindowPtr pWin, WindowPtr pNextSib)
+{
+    WindowPtr pParent = pWin->parent;
+    WindowPtr pFirstChange = pWin;      /* highest window where list changes */
+
+    if (pWin->nextSib != pNextSib) {
+        WindowPtr pOldNextSib = pWin->nextSib;
+
+        if (!pNextSib) {        /* move to bottom */
+            if (pParent->firstChild == pWin)
+                pParent->firstChild = pWin->nextSib;
+            /* if (pWin->nextSib) *//* is always True: pNextSib == NULL
+             * and pWin->nextSib != pNextSib
+             * therefore pWin->nextSib != NULL */
+            pFirstChange = pWin->nextSib;
+            pWin->nextSib->prevSib = pWin->prevSib;
+            if (pWin->prevSib)
+                pWin->prevSib->nextSib = pWin->nextSib;
+            pParent->lastChild->nextSib = pWin;
+            pWin->prevSib = pParent->lastChild;
+            pWin->nextSib = NullWindow;
+            pParent->lastChild = pWin;
+        }
+        else if (pParent->firstChild == pNextSib) {     /* move to top */
+            pFirstChange = pWin;
+            if (pParent->lastChild == pWin)
+                pParent->lastChild = pWin->prevSib;
+            if (pWin->nextSib)
+                pWin->nextSib->prevSib = pWin->prevSib;
+            if (pWin->prevSib)
+                pWin->prevSib->nextSib = pWin->nextSib;
+            pWin->nextSib = pParent->firstChild;
+            pWin->prevSib = NULL;
+            pNextSib->prevSib = pWin;
+            pParent->firstChild = pWin;
+        }
+        else {                  /* move in middle of list */
+
+            WindowPtr pOldNext = pWin->nextSib;
+
+            pFirstChange = NullWindow;
+            if (pParent->firstChild == pWin)
+                pFirstChange = pParent->firstChild = pWin->nextSib;
+            if (pParent->lastChild == pWin) {
+                pFirstChange = pWin;
+                pParent->lastChild = pWin->prevSib;
+            }
+            if (pWin->nextSib)
+                pWin->nextSib->prevSib = pWin->prevSib;
+            if (pWin->prevSib)
+                pWin->prevSib->nextSib = pWin->nextSib;
+            pWin->nextSib = pNextSib;
+            pWin->prevSib = pNextSib->prevSib;
+            if (pNextSib->prevSib)
+                pNextSib->prevSib->nextSib = pWin;
+            pNextSib->prevSib = pWin;
+            if (!pFirstChange) {        /* do we know it yet? */
+                pFirstChange = pParent->firstChild;     /* no, search from top */
+                while ((pFirstChange != pWin) && (pFirstChange != pOldNext))
+                    pFirstChange = pFirstChange->nextSib;
+            }
+        }
+        if (pWin->drawable.pScreen->RestackWindow)
+            (*pWin->drawable.pScreen->RestackWindow) (pWin, pOldNextSib);
+    }
+
+#ifdef ROOTLESS
+    /*
+     * In rootless mode we can't optimize away window restacks.
+     * There may be non-X windows around, so even if the window
+     * is in the correct position from X's point of view,
+     * the underlying window system may want to reorder it.
+     */
+    else if (pWin->drawable.pScreen->RestackWindow)
+        (*pWin->drawable.pScreen->RestackWindow) (pWin, pWin->nextSib);
+#endif
+
+    return pFirstChange;
+}
+
+void
+SetWinSize(WindowPtr pWin)
+{
+#ifdef COMPOSITE
+    if (pWin->redirectDraw != RedirectDrawNone) {
+        BoxRec box;
+
+        /*
+         * Redirected clients get clip list equal to their
+         * own geometry, not clipped to their parent
+         */
+        box.x1 = pWin->drawable.x;
+        box.y1 = pWin->drawable.y;
+        box.x2 = pWin->drawable.x + pWin->drawable.width;
+        box.y2 = pWin->drawable.y + pWin->drawable.height;
+        RegionReset(&pWin->winSize, &box);
+    }
+    else
+#endif
+        ClippedRegionFromBox(pWin->parent, &pWin->winSize,
+                             pWin->drawable.x, pWin->drawable.y,
+                             (int) pWin->drawable.width,
+                             (int) pWin->drawable.height);
+    if (wBoundingShape(pWin) || wClipShape(pWin)) {
+        RegionTranslate(&pWin->winSize, -pWin->drawable.x, -pWin->drawable.y);
+        if (wBoundingShape(pWin))
+            RegionIntersect(&pWin->winSize, &pWin->winSize,
+                            wBoundingShape(pWin));
+        if (wClipShape(pWin))
+            RegionIntersect(&pWin->winSize, &pWin->winSize, wClipShape(pWin));
+        RegionTranslate(&pWin->winSize, pWin->drawable.x, pWin->drawable.y);
+    }
+}
+
+void
+SetBorderSize(WindowPtr pWin)
+{
+    int bw;
+
+    if (HasBorder(pWin)) {
+        bw = wBorderWidth(pWin);
+#ifdef COMPOSITE
+        if (pWin->redirectDraw != RedirectDrawNone) {
+            BoxRec box;
+
+            /*
+             * Redirected clients get clip list equal to their
+             * own geometry, not clipped to their parent
+             */
+            box.x1 = pWin->drawable.x - bw;
+            box.y1 = pWin->drawable.y - bw;
+            box.x2 = pWin->drawable.x + pWin->drawable.width + bw;
+            box.y2 = pWin->drawable.y + pWin->drawable.height + bw;
+            RegionReset(&pWin->borderSize, &box);
+        }
+        else
+#endif
+            ClippedRegionFromBox(pWin->parent, &pWin->borderSize,
+                                 pWin->drawable.x - bw, pWin->drawable.y - bw,
+                                 (int) (pWin->drawable.width + (bw << 1)),
+                                 (int) (pWin->drawable.height + (bw << 1)));
+        if (wBoundingShape(pWin)) {
+            RegionTranslate(&pWin->borderSize, -pWin->drawable.x,
+                            -pWin->drawable.y);
+            RegionIntersect(&pWin->borderSize, &pWin->borderSize,
+                            wBoundingShape(pWin));
+            RegionTranslate(&pWin->borderSize, pWin->drawable.x,
+                            pWin->drawable.y);
+            RegionUnion(&pWin->borderSize, &pWin->borderSize, &pWin->winSize);
+        }
+    }
+    else {
+        RegionCopy(&pWin->borderSize, &pWin->winSize);
+    }
+}
+
+/**
+ *
+ *  \param x,y          new window position
+ *  \param oldx,oldy    old window position
+ *  \param destx,desty  position relative to gravity
+ */
+
+void
+GravityTranslate(int x, int y, int oldx, int oldy,
+                 int dw, int dh, unsigned gravity, int *destx, int *desty)
+{
+    switch (gravity) {
+    case NorthGravity:
+        *destx = x + dw / 2;
+        *desty = y;
+        break;
+    case NorthEastGravity:
+        *destx = x + dw;
+        *desty = y;
+        break;
+    case WestGravity:
+        *destx = x;
+        *desty = y + dh / 2;
+        break;
+    case CenterGravity:
+        *destx = x + dw / 2;
+        *desty = y + dh / 2;
+        break;
+    case EastGravity:
+        *destx = x + dw;
+        *desty = y + dh / 2;
+        break;
+    case SouthWestGravity:
+        *destx = x;
+        *desty = y + dh;
+        break;
+    case SouthGravity:
+        *destx = x + dw / 2;
+        *desty = y + dh;
+        break;
+    case SouthEastGravity:
+        *destx = x + dw;
+        *desty = y + dh;
+        break;
+    case StaticGravity:
+        *destx = oldx;
+        *desty = oldy;
+        break;
+    default:
+        *destx = x;
+        *desty = y;
+        break;
+    }
+}
+
+/* XXX need to retile border on each window with ParentRelative origin */
+void
+ResizeChildrenWinSize(WindowPtr pWin, int dx, int dy, int dw, int dh)
+{
+    ScreenPtr pScreen;
+    WindowPtr pSib, pChild;
+    Bool resized = (dw || dh);
+
+    pScreen = pWin->drawable.pScreen;
+
+    for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib) {
+        if (resized && (pSib->winGravity > NorthWestGravity)) {
+            int cwsx, cwsy;
+
+            cwsx = pSib->origin.x;
+            cwsy = pSib->origin.y;
+            GravityTranslate(cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh,
+                             pSib->winGravity, &cwsx, &cwsy);
+            if (cwsx != pSib->origin.x || cwsy != pSib->origin.y) {
+                xEvent event = {
+                    .u.gravity.window = pSib->drawable.id,
+                    .u.gravity.x = cwsx - wBorderWidth(pSib),
+                    .u.gravity.y = cwsy - wBorderWidth(pSib)
+                };
+                event.u.u.type = GravityNotify;
+                DeliverEvents(pSib, &event, 1, NullWindow);
+                pSib->origin.x = cwsx;
+                pSib->origin.y = cwsy;
+            }
+        }
+        pSib->drawable.x = pWin->drawable.x + pSib->origin.x;
+        pSib->drawable.y = pWin->drawable.y + pSib->origin.y;
+        SetWinSize(pSib);
+        SetBorderSize(pSib);
+        (*pScreen->PositionWindow) (pSib, pSib->drawable.x, pSib->drawable.y);
+
+        if ((pChild = pSib->firstChild)) {
+            while (1) {
+                pChild->drawable.x = pChild->parent->drawable.x +
+                    pChild->origin.x;
+                pChild->drawable.y = pChild->parent->drawable.y +
+                    pChild->origin.y;
+                SetWinSize(pChild);
+                SetBorderSize(pChild);
+                (*pScreen->PositionWindow) (pChild,
+                                            pChild->drawable.x,
+                                            pChild->drawable.y);
+                if (pChild->firstChild) {
+                    pChild = pChild->firstChild;
+                    continue;
+                }
+                while (!pChild->nextSib && (pChild != pSib))
+                    pChild = pChild->parent;
+                if (pChild == pSib)
+                    break;
+                pChild = pChild->nextSib;
+            }
+        }
+    }
+}
+
+#define GET_INT16(m, f) \
+	if (m & mask) \
+	  { \
+	     f = (INT16) *pVlist;\
+	    pVlist++; \
+	 }
+#define GET_CARD16(m, f) \
+	if (m & mask) \
+	 { \
+	    f = (CARD16) *pVlist;\
+	    pVlist++;\
+	 }
+
+#define GET_CARD8(m, f) \
+	if (m & mask) \
+	 { \
+	    f = (CARD8) *pVlist;\
+	    pVlist++;\
+	 }
+
+#define ChangeMask ((Mask)(CWX | CWY | CWWidth | CWHeight))
+
+/*
+ * IsSiblingAboveMe
+ *     returns Above if pSib above pMe in stack or Below otherwise
+ */
+
+static int
+IsSiblingAboveMe(WindowPtr pMe, WindowPtr pSib)
+{
+    WindowPtr pWin;
+
+    pWin = pMe->parent->firstChild;
+    while (pWin) {
+        if (pWin == pSib)
+            return Above;
+        else if (pWin == pMe)
+            return Below;
+        pWin = pWin->nextSib;
+    }
+    return Below;
+}
+
+static BoxPtr
+WindowExtents(WindowPtr pWin, BoxPtr pBox)
+{
+    pBox->x1 = pWin->drawable.x - wBorderWidth(pWin);
+    pBox->y1 = pWin->drawable.y - wBorderWidth(pWin);
+    pBox->x2 = pWin->drawable.x + (int) pWin->drawable.width
+        + wBorderWidth(pWin);
+    pBox->y2 = pWin->drawable.y + (int) pWin->drawable.height
+        + wBorderWidth(pWin);
+    return pBox;
+}
+
+#define IS_SHAPED(pWin)	(wBoundingShape (pWin) != NULL)
+
+static RegionPtr
+MakeBoundingRegion(WindowPtr pWin, BoxPtr pBox)
+{
+    RegionPtr pRgn = RegionCreate(pBox, 1);
+
+    if (wBoundingShape(pWin)) {
+        RegionTranslate(pRgn, -pWin->origin.x, -pWin->origin.y);
+        RegionIntersect(pRgn, pRgn, wBoundingShape(pWin));
+        RegionTranslate(pRgn, pWin->origin.x, pWin->origin.y);
+    }
+    return pRgn;
+}
+
+static Bool
+ShapeOverlap(WindowPtr pWin, BoxPtr pWinBox, WindowPtr pSib, BoxPtr pSibBox)
+{
+    RegionPtr pWinRgn, pSibRgn;
+    Bool ret;
+
+    if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib))
+        return TRUE;
+    pWinRgn = MakeBoundingRegion(pWin, pWinBox);
+    pSibRgn = MakeBoundingRegion(pSib, pSibBox);
+    RegionIntersect(pWinRgn, pWinRgn, pSibRgn);
+    ret = RegionNotEmpty(pWinRgn);
+    RegionDestroy(pWinRgn);
+    RegionDestroy(pSibRgn);
+    return ret;
+}
+
+static Bool
+AnyWindowOverlapsMe(WindowPtr pWin, WindowPtr pHead, BoxPtr box)
+{
+    WindowPtr pSib;
+    BoxRec sboxrec;
+    BoxPtr sbox;
+
+    for (pSib = pWin->prevSib; pSib != pHead; pSib = pSib->prevSib) {
+        if (pSib->mapped) {
+            sbox = WindowExtents(pSib, &sboxrec);
+            if (BOXES_OVERLAP(sbox, box)
+                && ShapeOverlap(pWin, box, pSib, sbox))
+                return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+static Bool
+IOverlapAnyWindow(WindowPtr pWin, BoxPtr box)
+{
+    WindowPtr pSib;
+    BoxRec sboxrec;
+    BoxPtr sbox;
+
+    for (pSib = pWin->nextSib; pSib; pSib = pSib->nextSib) {
+        if (pSib->mapped) {
+            sbox = WindowExtents(pSib, &sboxrec);
+            if (BOXES_OVERLAP(sbox, box)
+                && ShapeOverlap(pWin, box, pSib, sbox))
+                return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/*
+ *   WhereDoIGoInTheStack()
+ *	  Given pWin and pSib and the relationshipe smode, return
+ *	  the window that pWin should go ABOVE.
+ *	  If a pSib is specified:
+ *	      Above:  pWin is placed just above pSib
+ *	      Below:  pWin is placed just below pSib
+ *	      TopIf:  if pSib occludes pWin, then pWin is placed
+ *		      at the top of the stack
+ *	      BottomIf:	 if pWin occludes pSib, then pWin is
+ *			 placed at the bottom of the stack
+ *	      Opposite: if pSib occludes pWin, then pWin is placed at the
+ *			top of the stack, else if pWin occludes pSib, then
+ *			pWin is placed at the bottom of the stack
+ *
+ *	  If pSib is NULL:
+ *	      Above:  pWin is placed at the top of the stack
+ *	      Below:  pWin is placed at the bottom of the stack
+ *	      TopIf:  if any sibling occludes pWin, then pWin is placed at
+ *		      the top of the stack
+ *	      BottomIf: if pWin occludes any sibline, then pWin is placed at
+ *			the bottom of the stack
+ *	      Opposite: if any sibling occludes pWin, then pWin is placed at
+ *			the top of the stack, else if pWin occludes any
+ *			sibling, then pWin is placed at the bottom of the stack
+ *
+ */
+
+static WindowPtr
+WhereDoIGoInTheStack(WindowPtr pWin,
+                     WindowPtr pSib,
+                     short x,
+                     short y, unsigned short w, unsigned short h, int smode)
+{
+    BoxRec box;
+    WindowPtr pHead, pFirst;
+
+    if ((pWin == pWin->parent->firstChild) && (pWin == pWin->parent->lastChild))
+        return NULL;
+    pHead = RealChildHead(pWin->parent);
+    pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild;
+    box.x1 = x;
+    box.y1 = y;
+    box.x2 = x + (int) w;
+    box.y2 = y + (int) h;
+    switch (smode) {
+    case Above:
+        if (pSib)
+            return pSib;
+        else if (pWin == pFirst)
+            return pWin->nextSib;
+        else
+            return pFirst;
+    case Below:
+        if (pSib)
+            if (pSib->nextSib != pWin)
+                return pSib->nextSib;
+            else
+                return pWin->nextSib;
+        else
+            return NullWindow;
+    case TopIf:
+        if ((!pWin->mapped || (pSib && !pSib->mapped)))
+            return pWin->nextSib;
+        else if (pSib) {
+            if ((IsSiblingAboveMe(pWin, pSib) == Above) &&
+                (RegionContainsRect(&pSib->borderSize, &box) != rgnOUT))
+                return pFirst;
+            else
+                return pWin->nextSib;
+        }
+        else if (AnyWindowOverlapsMe(pWin, pHead, &box))
+            return pFirst;
+        else
+            return pWin->nextSib;
+    case BottomIf:
+        if ((!pWin->mapped || (pSib && !pSib->mapped)))
+            return pWin->nextSib;
+        else if (pSib) {
+            if ((IsSiblingAboveMe(pWin, pSib) == Below) &&
+                (RegionContainsRect(&pSib->borderSize, &box) != rgnOUT))
+                return NullWindow;
+            else
+                return pWin->nextSib;
+        }
+        else if (IOverlapAnyWindow(pWin, &box))
+            return NullWindow;
+        else
+            return pWin->nextSib;
+    case Opposite:
+        if ((!pWin->mapped || (pSib && !pSib->mapped)))
+            return pWin->nextSib;
+        else if (pSib) {
+            if (RegionContainsRect(&pSib->borderSize, &box) != rgnOUT) {
+                if (IsSiblingAboveMe(pWin, pSib) == Above)
+                    return pFirst;
+                else
+                    return NullWindow;
+            }
+            else
+                return pWin->nextSib;
+        }
+        else if (AnyWindowOverlapsMe(pWin, pHead, &box)) {
+            /* If I'm occluded, I can't possibly be the first child
+             * if (pWin == pWin->parent->firstChild)
+             *    return pWin->nextSib;
+             */
+            return pFirst;
+        }
+        else if (IOverlapAnyWindow(pWin, &box))
+            return NullWindow;
+        else
+            return pWin->nextSib;
+    default:
+    {
+        /* should never happen; make something up. */
+        return pWin->nextSib;
+    }
+    }
+}
+
+static void
+ReflectStackChange(WindowPtr pWin, WindowPtr pSib, VTKind kind)
+{
+/* Note that pSib might be NULL */
+
+    Bool WasViewable = (Bool) pWin->viewable;
+    Bool anyMarked;
+    WindowPtr pFirstChange;
+    WindowPtr pLayerWin;
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+
+    /* if this is a root window, can't be restacked */
+    if (!pWin->parent)
+        return;
+
+    pFirstChange = MoveWindowInStack(pWin, pSib);
+
+    if (WasViewable) {
+        anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pFirstChange,
+                                                       &pLayerWin);
+        if (pLayerWin != pWin)
+            pFirstChange = pLayerWin;
+        if (anyMarked) {
+            (*pScreen->ValidateTree) (pLayerWin->parent, pFirstChange, kind);
+            (*pScreen->HandleExposures) (pLayerWin->parent);
+            if (pWin->drawable.pScreen->PostValidateTree)
+                (*pScreen->PostValidateTree) (pLayerWin->parent, pFirstChange,
+                                              kind);
+        }
+    }
+    if (pWin->realized)
+        WindowsRestructured();
+}
+
+/*****
+ * ConfigureWindow
+ *****/
+
+int
+ConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client)
+{
+#define RESTACK_WIN    0
+#define MOVE_WIN       1
+#define RESIZE_WIN     2
+#define REBORDER_WIN   3
+    WindowPtr pSib = NullWindow;
+    WindowPtr pParent = pWin->parent;
+    Window sibwid = 0;
+    Mask index2, tmask;
+    XID *pVlist;
+    short x, y, beforeX, beforeY;
+    unsigned short w = pWin->drawable.width,
+        h = pWin->drawable.height, bw = pWin->borderWidth;
+    int rc, action, smode = Above;
+
+    if ((pWin->drawable.class == InputOnly) && (mask & CWBorderWidth))
+        return BadMatch;
+
+    if ((mask & CWSibling) && !(mask & CWStackMode))
+        return BadMatch;
+
+    pVlist = vlist;
+
+    if (pParent) {
+        x = pWin->drawable.x - pParent->drawable.x - (int) bw;
+        y = pWin->drawable.y - pParent->drawable.y - (int) bw;
+    }
+    else {
+        x = pWin->drawable.x;
+        y = pWin->drawable.y;
+    }
+    beforeX = x;
+    beforeY = y;
+    action = RESTACK_WIN;
+    if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth)))) {
+        GET_INT16(CWX, x);
+        GET_INT16(CWY, y);
+        action = MOVE_WIN;
+    }
+    /* or should be resized */
+    else if (mask & (CWX | CWY | CWWidth | CWHeight)) {
+        GET_INT16(CWX, x);
+        GET_INT16(CWY, y);
+        GET_CARD16(CWWidth, w);
+        GET_CARD16(CWHeight, h);
+        if (!w || !h) {
+            client->errorValue = 0;
+            return BadValue;
+        }
+        action = RESIZE_WIN;
+    }
+    tmask = mask & ~ChangeMask;
+    while (tmask) {
+        index2 = (Mask) lowbit(tmask);
+        tmask &= ~index2;
+        switch (index2) {
+        case CWBorderWidth:
+            GET_CARD16(CWBorderWidth, bw);
+            break;
+        case CWSibling:
+            sibwid = (Window) *pVlist;
+            pVlist++;
+            rc = dixLookupWindow(&pSib, sibwid, client, DixGetAttrAccess);
+            if (rc != Success) {
+                client->errorValue = sibwid;
+                return rc;
+            }
+            if (pSib->parent != pParent)
+                return BadMatch;
+            if (pSib == pWin)
+                return BadMatch;
+            break;
+        case CWStackMode:
+            GET_CARD8(CWStackMode, smode);
+            if ((smode != TopIf) && (smode != BottomIf) &&
+                (smode != Opposite) && (smode != Above) && (smode != Below)) {
+                client->errorValue = smode;
+                return BadValue;
+            }
+            break;
+        default:
+            client->errorValue = mask;
+            return BadValue;
+        }
+    }
+    /* root really can't be reconfigured, so just return */
+    if (!pParent)
+        return Success;
+
+    /* Figure out if the window should be moved.  Doesn't
+       make the changes to the window if event sent. */
+
+    if (mask & CWStackMode)
+        pSib = WhereDoIGoInTheStack(pWin, pSib, pParent->drawable.x + x,
+                                    pParent->drawable.y + y,
+                                    w + (bw << 1), h + (bw << 1), smode);
+    else
+        pSib = pWin->nextSib;
+
+    if ((!pWin->overrideRedirect) && (RedirectSend(pParent))) {
+        xEvent event = {
+            .u.configureRequest.window = pWin->drawable.id,
+            .u.configureRequest.sibling = (mask & CWSibling) ? sibwid : None,
+            .u.configureRequest.x = x,
+            .u.configureRequest.y = y,
+            .u.configureRequest.width = w,
+            .u.configureRequest.height = h,
+            .u.configureRequest.borderWidth = bw,
+            .u.configureRequest.valueMask = mask,
+            .u.configureRequest.parent = pParent->drawable.id
+        };
+        event.u.u.type = ConfigureRequest;
+        event.u.u.detail = (mask & CWStackMode) ? smode : Above;
+#ifdef PANORAMIX
+        if (!noPanoramiXExtension && (!pParent || !pParent->parent)) {
+            event.u.configureRequest.x += screenInfo.screens[0]->x;
+            event.u.configureRequest.y += screenInfo.screens[0]->y;
+        }
+#endif
+        if (MaybeDeliverEventsToClient(pParent, &event, 1,
+                                       SubstructureRedirectMask, client) == 1)
+            return Success;
+    }
+    if (action == RESIZE_WIN) {
+        Bool size_change = (w != pWin->drawable.width)
+            || (h != pWin->drawable.height);
+
+        if (size_change &&
+            ((pWin->eventMask | wOtherEventMasks(pWin)) & ResizeRedirectMask)) {
+            xEvent eventT = {
+                .u.resizeRequest.window = pWin->drawable.id,
+                .u.resizeRequest.width = w,
+                .u.resizeRequest.height = h
+            };
+            eventT.u.u.type = ResizeRequest;
+            if (MaybeDeliverEventsToClient(pWin, &eventT, 1,
+                                           ResizeRedirectMask, client) == 1) {
+                /* if event is delivered, leave the actual size alone. */
+                w = pWin->drawable.width;
+                h = pWin->drawable.height;
+                size_change = FALSE;
+            }
+        }
+        if (!size_change) {
+            if (mask & (CWX | CWY))
+                action = MOVE_WIN;
+            else if (mask & (CWStackMode | CWBorderWidth))
+                action = RESTACK_WIN;
+            else                /* really nothing to do */
+                return (Success);
+        }
+    }
+
+    if (action == RESIZE_WIN)
+        /* we've already checked whether there's really a size change */
+        goto ActuallyDoSomething;
+    if ((mask & CWX) && (x != beforeX))
+        goto ActuallyDoSomething;
+    if ((mask & CWY) && (y != beforeY))
+        goto ActuallyDoSomething;
+    if ((mask & CWBorderWidth) && (bw != wBorderWidth(pWin)))
+        goto ActuallyDoSomething;
+    if (mask & CWStackMode) {
+#ifndef ROOTLESS
+        /* See above for why we always reorder in rootless mode. */
+        if (pWin->nextSib != pSib)
+#endif
+            goto ActuallyDoSomething;
+    }
+    return Success;
+
+ ActuallyDoSomething:
+    if (pWin->drawable.pScreen->ConfigNotify) {
+        int ret;
+
+        ret =
+            (*pWin->drawable.pScreen->ConfigNotify) (pWin, x, y, w, h, bw,
+                                                     pSib);
+        if (ret) {
+            client->errorValue = 0;
+            return ret;
+        }
+    }
+
+    if (SubStrSend(pWin, pParent)) {
+        xEvent event = {
+            .u.configureNotify.window = pWin->drawable.id,
+            .u.configureNotify.aboveSibling = pSib ? pSib->drawable.id : None,
+            .u.configureNotify.x = x,
+            .u.configureNotify.y = y,
+            .u.configureNotify.width = w,
+            .u.configureNotify.height = h,
+            .u.configureNotify.borderWidth = bw,
+            .u.configureNotify.override = pWin->overrideRedirect
+        };
+        event.u.u.type = ConfigureNotify;
+#ifdef PANORAMIX
+        if (!noPanoramiXExtension && (!pParent || !pParent->parent)) {
+            event.u.configureNotify.x += screenInfo.screens[0]->x;
+            event.u.configureNotify.y += screenInfo.screens[0]->y;
+        }
+#endif
+        DeliverEvents(pWin, &event, 1, NullWindow);
+    }
+    if (mask & CWBorderWidth) {
+        if (action == RESTACK_WIN) {
+            action = MOVE_WIN;
+            pWin->borderWidth = bw;
+        }
+        else if ((action == MOVE_WIN) &&
+                 (beforeX + wBorderWidth(pWin) == x + (int) bw) &&
+                 (beforeY + wBorderWidth(pWin) == y + (int) bw)) {
+            action = REBORDER_WIN;
+            (*pWin->drawable.pScreen->ChangeBorderWidth) (pWin, bw);
+        }
+        else
+            pWin->borderWidth = bw;
+    }
+    if (action == MOVE_WIN)
+        (*pWin->drawable.pScreen->MoveWindow) (pWin, x, y, pSib,
+                                               (mask & CWBorderWidth) ? VTOther
+                                               : VTMove);
+    else if (action == RESIZE_WIN)
+        (*pWin->drawable.pScreen->ResizeWindow) (pWin, x, y, w, h, pSib);
+    else if (mask & CWStackMode)
+        ReflectStackChange(pWin, pSib, VTOther);
+
+    if (action != RESTACK_WIN)
+        CheckCursorConfinement(pWin);
+    return Success;
+#undef RESTACK_WIN
+#undef MOVE_WIN
+#undef RESIZE_WIN
+#undef REBORDER_WIN
+}
+
+/******
+ *
+ * CirculateWindow
+ *    For RaiseLowest, raises the lowest mapped child (if any) that is
+ *    obscured by another child to the top of the stack.  For LowerHighest,
+ *    lowers the highest mapped child (if any) that is obscuring another
+ *    child to the bottom of the stack.	 Exposure processing is performed
+ *
+ ******/
+
+int
+CirculateWindow(WindowPtr pParent, int direction, ClientPtr client)
+{
+    WindowPtr pWin, pHead, pFirst;
+    xEvent event;
+    BoxRec box;
+
+    pHead = RealChildHead(pParent);
+    pFirst = pHead ? pHead->nextSib : pParent->firstChild;
+    if (direction == RaiseLowest) {
+        for (pWin = pParent->lastChild;
+             (pWin != pHead) &&
+             !(pWin->mapped &&
+               AnyWindowOverlapsMe(pWin, pHead, WindowExtents(pWin, &box)));
+             pWin = pWin->prevSib);
+        if (pWin == pHead)
+            return Success;
+    }
+    else {
+        for (pWin = pFirst;
+             pWin &&
+             !(pWin->mapped &&
+               IOverlapAnyWindow(pWin, WindowExtents(pWin, &box)));
+             pWin = pWin->nextSib);
+        if (!pWin)
+            return Success;
+    }
+
+    event = (xEvent) {
+        .u.circulate.window = pWin->drawable.id,
+        .u.circulate.parent = pParent->drawable.id,
+        .u.circulate.event = pParent->drawable.id,
+        .u.circulate.place = (direction == RaiseLowest) ?
+                              PlaceOnTop : PlaceOnBottom,
+    };
+
+    if (RedirectSend(pParent)) {
+        event.u.u.type = CirculateRequest;
+        if (MaybeDeliverEventsToClient(pParent, &event, 1,
+                                       SubstructureRedirectMask, client) == 1)
+            return Success;
+    }
+
+    event.u.u.type = CirculateNotify;
+    DeliverEvents(pWin, &event, 1, NullWindow);
+    ReflectStackChange(pWin,
+                       (direction == RaiseLowest) ? pFirst : NullWindow,
+                       VTStack);
+
+    return Success;
+}
+
+static int
+CompareWIDs(WindowPtr pWin, void *value)
+{                               /* must conform to VisitWindowProcPtr */
+    Window *wid = (Window *) value;
+
+    if (pWin->drawable.id == *wid)
+        return WT_STOPWALKING;
+    else
+        return WT_WALKCHILDREN;
+}
+
+/*****
+ *  ReparentWindow
+ *****/
+
+int
+ReparentWindow(WindowPtr pWin, WindowPtr pParent,
+               int x, int y, ClientPtr client)
+{
+    WindowPtr pPrev, pPriorParent;
+    Bool WasMapped = (Bool) (pWin->mapped);
+    xEvent event;
+    int bw = wBorderWidth(pWin);
+    ScreenPtr pScreen;
+
+    pScreen = pWin->drawable.pScreen;
+    if (TraverseTree(pWin, CompareWIDs, (void *) &pParent->drawable.id) ==
+        WT_STOPWALKING)
+        return BadMatch;
+    if (!MakeWindowOptional(pWin))
+        return BadAlloc;
+
+    if (WasMapped)
+        UnmapWindow(pWin, FALSE);
+
+    event = (xEvent) {
+        .u.reparent.window = pWin->drawable.id,
+        .u.reparent.parent = pParent->drawable.id,
+        .u.reparent.x = x,
+        .u.reparent.y = y,
+        .u.reparent.override = pWin->overrideRedirect
+    };
+    event.u.u.type = ReparentNotify;
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension && !pParent->parent) {
+        event.u.reparent.x += screenInfo.screens[0]->x;
+        event.u.reparent.y += screenInfo.screens[0]->y;
+    }
+#endif
+    DeliverEvents(pWin, &event, 1, pParent);
+
+    /* take out of sibling chain */
+
+    pPriorParent = pPrev = pWin->parent;
+    if (pPrev->firstChild == pWin)
+        pPrev->firstChild = pWin->nextSib;
+    if (pPrev->lastChild == pWin)
+        pPrev->lastChild = pWin->prevSib;
+
+    if (pWin->nextSib)
+        pWin->nextSib->prevSib = pWin->prevSib;
+    if (pWin->prevSib)
+        pWin->prevSib->nextSib = pWin->nextSib;
+
+    /* insert at beginning of pParent */
+    pWin->parent = pParent;
+    pPrev = RealChildHead(pParent);
+    if (pPrev) {
+        pWin->nextSib = pPrev->nextSib;
+        if (pPrev->nextSib)
+            pPrev->nextSib->prevSib = pWin;
+        else
+            pParent->lastChild = pWin;
+        pPrev->nextSib = pWin;
+        pWin->prevSib = pPrev;
+    }
+    else {
+        pWin->nextSib = pParent->firstChild;
+        pWin->prevSib = NullWindow;
+        if (pParent->firstChild)
+            pParent->firstChild->prevSib = pWin;
+        else
+            pParent->lastChild = pWin;
+        pParent->firstChild = pWin;
+    }
+
+    pWin->origin.x = x + bw;
+    pWin->origin.y = y + bw;
+    pWin->drawable.x = x + bw + pParent->drawable.x;
+    pWin->drawable.y = y + bw + pParent->drawable.y;
+
+    /* clip to parent */
+    SetWinSize(pWin);
+    SetBorderSize(pWin);
+
+    if (pScreen->ReparentWindow)
+        (*pScreen->ReparentWindow) (pWin, pPriorParent);
+    (*pScreen->PositionWindow) (pWin, pWin->drawable.x, pWin->drawable.y);
+    ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
+
+    CheckWindowOptionalNeed(pWin);
+
+    if (WasMapped)
+        MapWindow(pWin, client);
+    RecalculateDeliverableEvents(pWin);
+    return Success;
+}
+
+static void
+RealizeTree(WindowPtr pWin)
+{
+    WindowPtr pChild;
+    RealizeWindowProcPtr Realize;
+
+    Realize = pWin->drawable.pScreen->RealizeWindow;
+    pChild = pWin;
+    while (1) {
+        if (pChild->mapped) {
+            pChild->realized = TRUE;
+            pChild->viewable = (pChild->drawable.class == InputOutput);
+            (*Realize) (pChild);
+            if (pChild->firstChild) {
+                pChild = pChild->firstChild;
+                continue;
+            }
+        }
+        while (!pChild->nextSib && (pChild != pWin))
+            pChild = pChild->parent;
+        if (pChild == pWin)
+            return;
+        pChild = pChild->nextSib;
+    }
+}
+
+static Bool
+MaybeDeliverMapRequest(WindowPtr pWin, WindowPtr pParent, ClientPtr client)
+{
+    xEvent event = {
+        .u.mapRequest.window = pWin->drawable.id,
+        .u.mapRequest.parent = pParent->drawable.id
+    };
+    event.u.u.type = MapRequest;
+
+    return MaybeDeliverEventsToClient(pParent, &event, 1,
+                                      SubstructureRedirectMask,
+                                      client) == 1;
+}
+
+static void
+DeliverMapNotify(WindowPtr pWin)
+{
+    xEvent event = {
+        .u.mapNotify.window = pWin->drawable.id,
+        .u.mapNotify.override = pWin->overrideRedirect,
+    };
+    event.u.u.type = MapNotify;
+    DeliverEvents(pWin, &event, 1, NullWindow);
+}
+
+/*****
+ * MapWindow
+ *    If some other client has selected SubStructureReDirect on the parent
+ *    and override-redirect is xFalse, then a MapRequest event is generated,
+ *    but the window remains unmapped.	Otherwise, the window is mapped and a
+ *    MapNotify event is generated.
+ *****/
+
+int
+MapWindow(WindowPtr pWin, ClientPtr client)
+{
+    ScreenPtr pScreen;
+
+    WindowPtr pParent;
+    WindowPtr pLayerWin;
+
+    if (pWin->mapped)
+        return Success;
+
+    /* general check for permission to map window */
+    if (XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id, RT_WINDOW,
+                 pWin, RT_NONE, NULL, DixShowAccess) != Success)
+        return Success;
+
+    pScreen = pWin->drawable.pScreen;
+    if ((pParent = pWin->parent)) {
+        Bool anyMarked;
+
+        if ((!pWin->overrideRedirect) && (RedirectSend(pParent)))
+            if (MaybeDeliverMapRequest(pWin, pParent, client))
+                return Success;
+
+        pWin->mapped = TRUE;
+        if (SubStrSend(pWin, pParent))
+            DeliverMapNotify(pWin);
+
+        if (!pParent->realized)
+            return Success;
+        RealizeTree(pWin);
+        if (pWin->viewable) {
+            anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin,
+                                                           &pLayerWin);
+            if (anyMarked) {
+                (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTMap);
+                (*pScreen->HandleExposures) (pLayerWin->parent);
+                if (pScreen->PostValidateTree)
+                    (*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin,
+                                                  VTMap);
+            }
+        }
+        WindowsRestructured();
+    }
+    else {
+        RegionRec temp;
+
+        pWin->mapped = TRUE;
+        pWin->realized = TRUE;  /* for roots */
+        pWin->viewable = pWin->drawable.class == InputOutput;
+        /* We SHOULD check for an error value here XXX */
+        (*pScreen->RealizeWindow) (pWin);
+        if (pScreen->ClipNotify)
+            (*pScreen->ClipNotify) (pWin, 0, 0);
+        if (pScreen->PostValidateTree)
+            (*pScreen->PostValidateTree) (NullWindow, pWin, VTMap);
+        RegionNull(&temp);
+        RegionCopy(&temp, &pWin->clipList);
+        (*pScreen->WindowExposures) (pWin, &temp);
+        RegionUninit(&temp);
+    }
+
+    return Success;
+}
+
+/*****
+ * MapSubwindows
+ *    Performs a MapWindow all unmapped children of the window, in top
+ *    to bottom stacking order.
+ *****/
+
+void
+MapSubwindows(WindowPtr pParent, ClientPtr client)
+{
+    WindowPtr pWin;
+    WindowPtr pFirstMapped = NullWindow;
+    ScreenPtr pScreen;
+    Mask parentRedirect;
+    Mask parentNotify;
+    Bool anyMarked;
+    WindowPtr pLayerWin;
+
+    pScreen = pParent->drawable.pScreen;
+    parentRedirect = RedirectSend(pParent);
+    parentNotify = SubSend(pParent);
+    anyMarked = FALSE;
+    for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) {
+        if (!pWin->mapped) {
+            if (parentRedirect && !pWin->overrideRedirect)
+                if (MaybeDeliverMapRequest(pWin, pParent, client))
+                    continue;
+
+            pWin->mapped = TRUE;
+            if (parentNotify || StrSend(pWin))
+                DeliverMapNotify(pWin);
+
+            if (!pFirstMapped)
+                pFirstMapped = pWin;
+            if (pParent->realized) {
+                RealizeTree(pWin);
+                if (pWin->viewable) {
+                    anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin,
+                                                                    NULL);
+                }
+            }
+        }
+    }
+
+    if (pFirstMapped) {
+        pLayerWin = (*pScreen->GetLayerWindow) (pParent);
+        if (pLayerWin->parent != pParent) {
+            anyMarked |= (*pScreen->MarkOverlappedWindows) (pLayerWin,
+                                                            pLayerWin, NULL);
+            pFirstMapped = pLayerWin;
+        }
+        if (anyMarked) {
+            (*pScreen->ValidateTree) (pLayerWin->parent, pFirstMapped, VTMap);
+            (*pScreen->HandleExposures) (pLayerWin->parent);
+            if (pScreen->PostValidateTree)
+                (*pScreen->PostValidateTree) (pLayerWin->parent, pFirstMapped,
+                                              VTMap);
+        }
+        WindowsRestructured();
+    }
+}
+
+static void
+UnrealizeTree(WindowPtr pWin, Bool fromConfigure)
+{
+    WindowPtr pChild;
+    UnrealizeWindowProcPtr Unrealize;
+    MarkUnrealizedWindowProcPtr MarkUnrealizedWindow;
+
+    Unrealize = pWin->drawable.pScreen->UnrealizeWindow;
+    MarkUnrealizedWindow = pWin->drawable.pScreen->MarkUnrealizedWindow;
+    pChild = pWin;
+    while (1) {
+        if (pChild->realized) {
+            pChild->realized = FALSE;
+            pChild->visibility = VisibilityNotViewable;
+#ifdef PANORAMIX
+            if (!noPanoramiXExtension && !pChild->drawable.pScreen->myNum) {
+                PanoramiXRes *win;
+                int rc = dixLookupResourceByType((void **) &win,
+                                                 pChild->drawable.id,
+                                                 XRT_WINDOW,
+                                                 serverClient, DixWriteAccess);
+
+                if (rc == Success)
+                    win->u.win.visibility = VisibilityNotViewable;
+            }
+#endif
+            (*Unrealize) (pChild);
+            DeleteWindowFromAnyEvents(pChild, FALSE);
+            if (pChild->viewable) {
+                pChild->viewable = FALSE;
+                (*MarkUnrealizedWindow) (pChild, pWin, fromConfigure);
+                pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+            }
+            if (pChild->firstChild) {
+                pChild = pChild->firstChild;
+                continue;
+            }
+        }
+        while (!pChild->nextSib && (pChild != pWin))
+            pChild = pChild->parent;
+        if (pChild == pWin)
+            return;
+        pChild = pChild->nextSib;
+    }
+}
+
+static void
+DeliverUnmapNotify(WindowPtr pWin, Bool fromConfigure)
+{
+    xEvent event = {
+        .u.unmapNotify.window = pWin->drawable.id,
+        .u.unmapNotify.fromConfigure = fromConfigure
+    };
+    event.u.u.type = UnmapNotify;
+    DeliverEvents(pWin, &event, 1, NullWindow);
+}
+
+/*****
+ * UnmapWindow
+ *    If the window is already unmapped, this request has no effect.
+ *    Otherwise, the window is unmapped and an UnMapNotify event is
+ *    generated.  Cannot unmap a root window.
+ *****/
+
+int
+UnmapWindow(WindowPtr pWin, Bool fromConfigure)
+{
+    WindowPtr pParent;
+    Bool wasRealized = (Bool) pWin->realized;
+    Bool wasViewable = (Bool) pWin->viewable;
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+    WindowPtr pLayerWin = pWin;
+
+    if ((!pWin->mapped) || (!(pParent = pWin->parent)))
+        return Success;
+    if (SubStrSend(pWin, pParent))
+        DeliverUnmapNotify(pWin, fromConfigure);
+    if (wasViewable && !fromConfigure) {
+        pWin->valdata = UnmapValData;
+        (*pScreen->MarkOverlappedWindows) (pWin, pWin->nextSib, &pLayerWin);
+        (*pScreen->MarkWindow) (pLayerWin->parent);
+    }
+    pWin->mapped = FALSE;
+    if (wasRealized)
+        UnrealizeTree(pWin, fromConfigure);
+    if (wasViewable && !fromConfigure) {
+        (*pScreen->ValidateTree) (pLayerWin->parent, pWin, VTUnmap);
+        (*pScreen->HandleExposures) (pLayerWin->parent);
+        if (pScreen->PostValidateTree)
+            (*pScreen->PostValidateTree) (pLayerWin->parent, pWin, VTUnmap);
+    }
+    if (wasRealized && !fromConfigure) {
+        WindowsRestructured();
+        WindowGone(pWin);
+    }
+    return Success;
+}
+
+/*****
+ * UnmapSubwindows
+ *    Performs an UnmapWindow request with the specified mode on all mapped
+ *    children of the window, in bottom to top stacking order.
+ *****/
+
+void
+UnmapSubwindows(WindowPtr pWin)
+{
+    WindowPtr pChild, pHead;
+    Bool wasRealized = (Bool) pWin->realized;
+    Bool wasViewable = (Bool) pWin->viewable;
+    Bool anyMarked = FALSE;
+    Mask parentNotify;
+    WindowPtr pLayerWin = NULL;
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+
+    if (!pWin->firstChild)
+        return;
+    parentNotify = SubSend(pWin);
+    pHead = RealChildHead(pWin);
+
+    if (wasViewable)
+        pLayerWin = (*pScreen->GetLayerWindow) (pWin);
+
+    for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) {
+        if (pChild->mapped) {
+            if (parentNotify || StrSend(pChild))
+                DeliverUnmapNotify(pChild, xFalse);
+            if (pChild->viewable) {
+                pChild->valdata = UnmapValData;
+                anyMarked = TRUE;
+            }
+            pChild->mapped = FALSE;
+            if (pChild->realized)
+                UnrealizeTree(pChild, FALSE);
+        }
+    }
+    if (wasViewable && anyMarked) {
+        if (pLayerWin->parent == pWin)
+            (*pScreen->MarkWindow) (pWin);
+        else {
+            WindowPtr ptmp;
+
+            (*pScreen->MarkOverlappedWindows) (pWin, pLayerWin, NULL);
+            (*pScreen->MarkWindow) (pLayerWin->parent);
+
+            /* Windows between pWin and pLayerWin may not have been marked */
+            ptmp = pWin;
+
+            while (ptmp != pLayerWin->parent) {
+                (*pScreen->MarkWindow) (ptmp);
+                ptmp = ptmp->parent;
+            }
+            pHead = pWin->firstChild;
+        }
+        (*pScreen->ValidateTree) (pLayerWin->parent, pHead, VTUnmap);
+        (*pScreen->HandleExposures) (pLayerWin->parent);
+        if (pScreen->PostValidateTree)
+            (*pScreen->PostValidateTree) (pLayerWin->parent, pHead, VTUnmap);
+    }
+    if (wasRealized) {
+        WindowsRestructured();
+        WindowGone(pWin);
+    }
+}
+
+void
+HandleSaveSet(ClientPtr client)
+{
+    WindowPtr pParent, pWin;
+    int j;
+
+    for (j = 0; j < client->numSaved; j++) {
+        pWin = SaveSetWindow(client->saveSet[j]);
+        if (SaveSetToRoot(client->saveSet[j]))
+            pParent = pWin->drawable.pScreen->root;
+        else
+        {
+            pParent = pWin->parent;
+            while (pParent && (wClient(pParent) == client))
+                pParent = pParent->parent;
+        }
+        if (pParent) {
+            if (pParent != pWin->parent) {
+                /* unmap first so that ReparentWindow doesn't remap */
+                if (!SaveSetShouldMap(client->saveSet[j]))
+                    UnmapWindow(pWin, FALSE);
+                ReparentWindow(pWin, pParent,
+                               pWin->drawable.x - wBorderWidth(pWin) -
+                               pParent->drawable.x,
+                               pWin->drawable.y - wBorderWidth(pWin) -
+                               pParent->drawable.y, client);
+                if (!pWin->realized && pWin->mapped)
+                    pWin->mapped = FALSE;
+            }
+            if (SaveSetShouldMap(client->saveSet[j]))
+                MapWindow(pWin, client);
+        }
+    }
+    free(client->saveSet);
+    client->numSaved = 0;
+    client->saveSet = NULL;
+}
+
+/**
+ *
+ * \param x,y  in root
+ */
+Bool
+PointInWindowIsVisible(WindowPtr pWin, int x, int y)
+{
+    BoxRec box;
+
+    if (!pWin->realized)
+        return FALSE;
+    if (RegionContainsPoint(&pWin->borderClip, x, y, &box)
+        && (!wInputShape(pWin) ||
+            RegionContainsPoint(wInputShape(pWin),
+                                x - pWin->drawable.x,
+                                y - pWin->drawable.y, &box)))
+        return TRUE;
+    return FALSE;
+}
+
+RegionPtr
+NotClippedByChildren(WindowPtr pWin)
+{
+    RegionPtr pReg = RegionCreate(NullBox, 1);
+
+    if (pWin->parent ||
+        screenIsSaved != SCREEN_SAVER_ON ||
+        !HasSaverWindow(pWin->drawable.pScreen)) {
+        RegionIntersect(pReg, &pWin->borderClip, &pWin->winSize);
+    }
+    return pReg;
+}
+
+void
+SendVisibilityNotify(WindowPtr pWin)
+{
+    xEvent event;
+    unsigned int visibility = pWin->visibility;
+
+#ifdef PANORAMIX
+    /* This is not quite correct yet, but it's close */
+    if (!noPanoramiXExtension) {
+        PanoramiXRes *win;
+        WindowPtr pWin2;
+        int rc, i, Scrnum;
+
+        Scrnum = pWin->drawable.pScreen->myNum;
+
+        win = PanoramiXFindIDByScrnum(XRT_WINDOW, pWin->drawable.id, Scrnum);
+
+        if (!win || (win->u.win.visibility == visibility))
+            return;
+
+        switch (visibility) {
+        case VisibilityUnobscured:
+        FOR_NSCREENS(i) {
+            if (i == Scrnum)
+                continue;
+
+            rc = dixLookupWindow(&pWin2, win->info[i].id, serverClient,
+                                 DixWriteAccess);
+
+            if (rc == Success) {
+                if (pWin2->visibility == VisibilityPartiallyObscured)
+                    return;
+
+                if (!i)
+                    pWin = pWin2;
+            }
+        }
+            break;
+        case VisibilityPartiallyObscured:
+            if (Scrnum) {
+                rc = dixLookupWindow(&pWin2, win->info[0].id, serverClient,
+                                     DixWriteAccess);
+                if (rc == Success)
+                    pWin = pWin2;
+            }
+            break;
+        case VisibilityFullyObscured:
+        FOR_NSCREENS(i) {
+            if (i == Scrnum)
+                continue;
+
+            rc = dixLookupWindow(&pWin2, win->info[i].id, serverClient,
+                                 DixWriteAccess);
+
+            if (rc == Success) {
+                if (pWin2->visibility != VisibilityFullyObscured)
+                    return;
+
+                if (!i)
+                    pWin = pWin2;
+            }
+        }
+            break;
+        }
+
+        win->u.win.visibility = visibility;
+    }
+#endif
+
+    event = (xEvent) {
+        .u.visibility.window = pWin->drawable.id,
+        .u.visibility.state = visibility
+    };
+    event.u.u.type = VisibilityNotify;
+    DeliverEvents(pWin, &event, 1, NullWindow);
+}
+
+#define RANDOM_WIDTH 32
+int
+dixSaveScreens(ClientPtr client, int on, int mode)
+{
+    int rc, i, what, type;
+    XID vlist[2];
+
+    if (on == SCREEN_SAVER_FORCER) {
+        if (mode == ScreenSaverReset)
+            what = SCREEN_SAVER_OFF;
+        else
+            what = SCREEN_SAVER_ON;
+        type = what;
+    }
+    else {
+        what = on;
+        type = what;
+        if (what == screenIsSaved)
+            type = SCREEN_SAVER_CYCLE;
+    }
+
+    for (i = 0; i < screenInfo.numScreens; i++) {
+        rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
+                      DixShowAccess | DixHideAccess);
+        if (rc != Success)
+            return rc;
+    }
+    for (i = 0; i < screenInfo.numScreens; i++) {
+        ScreenPtr pScreen = screenInfo.screens[i];
+
+        if (on == SCREEN_SAVER_FORCER)
+            (*pScreen->SaveScreen) (pScreen, on);
+        if (pScreen->screensaver.ExternalScreenSaver) {
+            if ((*pScreen->screensaver.ExternalScreenSaver)
+                (pScreen, type, on == SCREEN_SAVER_FORCER))
+                continue;
+        }
+        if (type == screenIsSaved)
+            continue;
+        switch (type) {
+        case SCREEN_SAVER_OFF:
+            if (pScreen->screensaver.blanked == SCREEN_IS_BLANKED) {
+                (*pScreen->SaveScreen) (pScreen, what);
+            }
+            else if (HasSaverWindow(pScreen)) {
+                pScreen->screensaver.pWindow = NullWindow;
+                FreeResource(pScreen->screensaver.wid, RT_NONE);
+            }
+            break;
+        case SCREEN_SAVER_CYCLE:
+            if (pScreen->screensaver.blanked == SCREEN_IS_TILED) {
+                WindowPtr pWin = pScreen->screensaver.pWindow;
+
+                /* make it look like screen saver is off, so that
+                 * NotClippedByChildren will compute a clip list
+                 * for the root window, so PaintWindow works
+                 */
+                screenIsSaved = SCREEN_SAVER_OFF;
+
+                vlist[0] = -(rand() % RANDOM_WIDTH);
+                vlist[1] = -(rand() % RANDOM_WIDTH);
+                ConfigureWindow(pWin, CWX | CWY, vlist, client);
+
+                screenIsSaved = SCREEN_SAVER_ON;
+            }
+            /*
+             * Call the DDX saver in case it wants to do something
+             * at cycle time
+             */
+            else if (pScreen->screensaver.blanked == SCREEN_IS_BLANKED) {
+                (*pScreen->SaveScreen) (pScreen, type);
+            }
+            break;
+        case SCREEN_SAVER_ON:
+            if (ScreenSaverBlanking != DontPreferBlanking) {
+                if ((*pScreen->SaveScreen) (pScreen, what)) {
+                    pScreen->screensaver.blanked = SCREEN_IS_BLANKED;
+                    continue;
+                }
+                if ((ScreenSaverAllowExposures != DontAllowExposures) &&
+                    TileScreenSaver(pScreen, SCREEN_IS_BLACK)) {
+                    pScreen->screensaver.blanked = SCREEN_IS_BLACK;
+                    continue;
+                }
+            }
+            if ((ScreenSaverAllowExposures != DontAllowExposures) &&
+                TileScreenSaver(pScreen, SCREEN_IS_TILED)) {
+                pScreen->screensaver.blanked = SCREEN_IS_TILED;
+            }
+            else
+                pScreen->screensaver.blanked = SCREEN_ISNT_SAVED;
+            break;
+        }
+    }
+    screenIsSaved = what;
+    if (mode == ScreenSaverReset) {
+        if (on == SCREEN_SAVER_FORCER) {
+            DeviceIntPtr dev;
+            UpdateCurrentTimeIf();
+            nt_list_for_each_entry(dev, inputInfo.devices, next)
+                NoticeTime(dev, currentTime);
+        }
+        SetScreenSaverTimer();
+    }
+    return Success;
+}
+
+int
+SaveScreens(int on, int mode)
+{
+    return dixSaveScreens(serverClient, on, mode);
+}
+
+static Bool
+TileScreenSaver(ScreenPtr pScreen, int kind)
+{
+    int j;
+    int result;
+    XID attributes[3];
+    Mask mask;
+    WindowPtr pWin;
+    CursorMetricRec cm;
+    unsigned char *srcbits, *mskbits;
+    CursorPtr cursor;
+    XID cursorID = 0;
+    int attri;
+
+    mask = 0;
+    attri = 0;
+    switch (kind) {
+    case SCREEN_IS_TILED:
+        switch (pScreen->root->backgroundState) {
+        case BackgroundPixel:
+            attributes[attri++] = pScreen->root->background.pixel;
+            mask |= CWBackPixel;
+            break;
+        case BackgroundPixmap:
+            attributes[attri++] = None;
+            mask |= CWBackPixmap;
+            break;
+        default:
+            break;
+        }
+        break;
+    case SCREEN_IS_BLACK:
+        attributes[attri++] = pScreen->root->drawable.pScreen->blackPixel;
+        mask |= CWBackPixel;
+        break;
+    }
+    mask |= CWOverrideRedirect;
+    attributes[attri++] = xTrue;
+
+    /*
+     * create a blank cursor
+     */
+
+    cm.width = 16;
+    cm.height = 16;
+    cm.xhot = 8;
+    cm.yhot = 8;
+    srcbits = malloc(BitmapBytePad(32) * 16);
+    mskbits = malloc(BitmapBytePad(32) * 16);
+    if (!srcbits || !mskbits) {
+        free(srcbits);
+        free(mskbits);
+        cursor = 0;
+    }
+    else {
+        for (j = 0; j < BitmapBytePad(32) * 16; j++)
+            srcbits[j] = mskbits[j] = 0x0;
+        result = AllocARGBCursor(srcbits, mskbits, NULL, &cm, 0, 0, 0, 0, 0, 0,
+                                 &cursor, serverClient, (XID) 0);
+        if (cursor) {
+            cursorID = FakeClientID(0);
+            if (AddResource(cursorID, RT_CURSOR, (void *) cursor)) {
+                attributes[attri] = cursorID;
+                mask |= CWCursor;
+            }
+            else
+                cursor = 0;
+        }
+        else {
+            free(srcbits);
+            free(mskbits);
+        }
+    }
+
+    pWin = pScreen->screensaver.pWindow =
+        CreateWindow(pScreen->screensaver.wid,
+                     pScreen->root,
+                     -RANDOM_WIDTH, -RANDOM_WIDTH,
+                     (unsigned short) pScreen->width + RANDOM_WIDTH,
+                     (unsigned short) pScreen->height + RANDOM_WIDTH,
+                     0, InputOutput, mask, attributes, 0, serverClient,
+                     wVisual(pScreen->root), &result);
+
+    if (cursor)
+        FreeResource(cursorID, RT_NONE);
+
+    if (!pWin)
+        return FALSE;
+
+    if (!AddResource(pWin->drawable.id, RT_WINDOW,
+                     (void *) pScreen->screensaver.pWindow))
+        return FALSE;
+
+    if (mask & CWBackPixmap) {
+        MakeRootTile(pWin);
+        (*pWin->drawable.pScreen->ChangeWindowAttributes) (pWin, CWBackPixmap);
+    }
+    MapWindow(pWin, serverClient);
+    return TRUE;
+}
+
+/*
+ * FindWindowWithOptional
+ *
+ * search ancestors of the given window for an entry containing
+ * a WindowOpt structure.  Assumptions:	 some parent will
+ * contain the structure.
+ */
+
+WindowPtr
+FindWindowWithOptional(WindowPtr w)
+{
+    do
+        w = w->parent;
+    while (!w->optional);
+    return w;
+}
+
+/*
+ * CheckWindowOptionalNeed
+ *
+ * check each optional entry in the given window to see if
+ * the value is satisfied by the default rules.	 If so,
+ * release the optional record
+ */
+
+void
+CheckWindowOptionalNeed(WindowPtr w)
+{
+    WindowOptPtr optional;
+    WindowOptPtr parentOptional;
+
+    if (!w->parent || !w->optional)
+        return;
+    optional = w->optional;
+    if (optional->dontPropagateMask != DontPropagateMasks[w->dontPropagate])
+        return;
+    if (optional->otherEventMasks != 0)
+        return;
+    if (optional->otherClients != NULL)
+        return;
+    if (optional->passiveGrabs != NULL)
+        return;
+    if (optional->userProps != NULL)
+        return;
+    if (optional->backingBitPlanes != (CARD32)~0L)
+        return;
+    if (optional->backingPixel != 0)
+        return;
+    if (optional->boundingShape != NULL)
+        return;
+    if (optional->clipShape != NULL)
+        return;
+    if (optional->inputShape != NULL)
+        return;
+    if (optional->inputMasks != NULL)
+        return;
+    if (optional->deviceCursors != NULL) {
+        DevCursNodePtr pNode = optional->deviceCursors;
+
+        while (pNode) {
+            if (pNode->cursor != None)
+                return;
+            pNode = pNode->next;
+        }
+    }
+
+    parentOptional = FindWindowWithOptional(w)->optional;
+    if (optional->visual != parentOptional->visual)
+        return;
+    if (optional->cursor != None &&
+        (optional->cursor != parentOptional->cursor || w->parent->cursorIsNone))
+        return;
+    if (optional->colormap != parentOptional->colormap)
+        return;
+    DisposeWindowOptional(w);
+}
+
+/*
+ * MakeWindowOptional
+ *
+ * create an optional record and initialize it with the default
+ * values.
+ */
+
+Bool
+MakeWindowOptional(WindowPtr pWin)
+{
+    WindowOptPtr optional;
+    WindowOptPtr parentOptional;
+
+    if (pWin->optional)
+        return TRUE;
+    optional = malloc(sizeof(WindowOptRec));
+    if (!optional)
+        return FALSE;
+    optional->dontPropagateMask = DontPropagateMasks[pWin->dontPropagate];
+    optional->otherEventMasks = 0;
+    optional->otherClients = NULL;
+    optional->passiveGrabs = NULL;
+    optional->userProps = NULL;
+    optional->backingBitPlanes = ~0L;
+    optional->backingPixel = 0;
+    optional->boundingShape = NULL;
+    optional->clipShape = NULL;
+    optional->inputShape = NULL;
+    optional->inputMasks = NULL;
+    optional->deviceCursors = NULL;
+
+    parentOptional = FindWindowWithOptional(pWin)->optional;
+    optional->visual = parentOptional->visual;
+    if (!pWin->cursorIsNone) {
+        optional->cursor = RefCursor(parentOptional->cursor);
+    }
+    else {
+        optional->cursor = None;
+    }
+    optional->colormap = parentOptional->colormap;
+    pWin->optional = optional;
+    return TRUE;
+}
+
+/*
+ * Changes the cursor struct for the given device and the given window.
+ * A cursor that does not have a device cursor set will use whatever the
+ * standard cursor is for the window. If all devices have a cursor set,
+ * changing the window cursor (e.g. using XDefineCursor()) will not have any
+ * visible effect. Only when one of the device cursors is set to None again,
+ * this device's cursor will display the changed standard cursor.
+ *
+ * CursorIsNone of the window struct is NOT modified if you set a device
+ * cursor.
+ *
+ * Assumption: If there is a node for a device in the list, the device has a
+ * cursor. If the cursor is set to None, it is inherited by the parent.
+ */
+int
+ChangeWindowDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev, CursorPtr pCursor)
+{
+    DevCursNodePtr pNode, pPrev;
+    CursorPtr pOldCursor = NULL;
+    ScreenPtr pScreen;
+    WindowPtr pChild;
+
+    if (!pWin->optional && !MakeWindowOptional(pWin))
+        return BadAlloc;
+
+    /* 1) Check if window has device cursor set
+     *  Yes: 1.1) swap cursor with given cursor if parent does not have same
+     *            cursor, free old cursor
+     *       1.2) free old cursor, use parent cursor
+     *  No: 1.1) add node to beginning of list.
+     *      1.2) add cursor to node if parent does not have same cursor
+     *      1.3) use parent cursor if parent does not have same cursor
+     *  2) Patch up children if child has a devcursor
+     *  2.1) if child has cursor None, it inherited from parent, set to old
+     *  cursor
+     *  2.2) if child has same cursor as new cursor, remove and set to None
+     */
+
+    pScreen = pWin->drawable.pScreen;
+
+    if (WindowSeekDeviceCursor(pWin, pDev, &pNode, &pPrev)) {
+        /* has device cursor */
+
+        if (pNode->cursor == pCursor)
+            return Success;
+
+        pOldCursor = pNode->cursor;
+
+        if (!pCursor) {         /* remove from list */
+            if (pPrev)
+                pPrev->next = pNode->next;
+            else
+                /* first item in list */
+                pWin->optional->deviceCursors = pNode->next;
+
+            free(pNode);
+            goto out;
+        }
+
+    }
+    else {
+        /* no device cursor yet */
+        DevCursNodePtr pNewNode;
+
+        if (!pCursor)
+            return Success;
+
+        pNewNode = malloc(sizeof(DevCursNodeRec));
+        pNewNode->dev = pDev;
+        pNewNode->next = pWin->optional->deviceCursors;
+        pWin->optional->deviceCursors = pNewNode;
+        pNode = pNewNode;
+
+    }
+
+    if (pCursor && WindowParentHasDeviceCursor(pWin, pDev, pCursor))
+        pNode->cursor = None;
+    else {
+        pNode->cursor = RefCursor(pCursor);
+    }
+
+    pNode = pPrev = NULL;
+    /* fix up children */
+    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
+        if (WindowSeekDeviceCursor(pChild, pDev, &pNode, &pPrev)) {
+            if (pNode->cursor == None) {        /* inherited from parent */
+                pNode->cursor = RefCursor(pOldCursor);
+            }
+            else if (pNode->cursor == pCursor) {
+                pNode->cursor = None;
+                FreeCursor(pCursor, (Cursor) 0);        /* fix up refcnt */
+            }
+        }
+    }
+
+ out:
+    CursorVisible = TRUE;
+
+    if (pWin->realized)
+        WindowHasNewCursor(pWin);
+
+    if (pOldCursor)
+        FreeCursor(pOldCursor, (Cursor) 0);
+
+    /* FIXME: We SHOULD check for an error value here XXX
+       (comment taken from ChangeWindowAttributes) */
+    (*pScreen->ChangeWindowAttributes) (pWin, CWCursor);
+
+    return Success;
+}
+
+/* Get device cursor for given device or None if none is set */
+CursorPtr
+WindowGetDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev)
+{
+    DevCursorList pList;
+
+    if (!pWin->optional || !pWin->optional->deviceCursors)
+        return NULL;
+
+    pList = pWin->optional->deviceCursors;
+
+    while (pList) {
+        if (pList->dev == pDev) {
+            if (pList->cursor == None)  /* inherited from parent */
+                return WindowGetDeviceCursor(pWin->parent, pDev);
+            else
+                return pList->cursor;
+        }
+        pList = pList->next;
+    }
+    return NULL;
+}
+
+/* Searches for a DevCursorNode for the given window and device. If one is
+ * found, return True and set pNode and pPrev to the node and to the node
+ * before the node respectively. Otherwise return False.
+ * If the device is the first in list, pPrev is set to NULL.
+ */
+static Bool
+WindowSeekDeviceCursor(WindowPtr pWin,
+                       DeviceIntPtr pDev,
+                       DevCursNodePtr * pNode, DevCursNodePtr * pPrev)
+{
+    DevCursorList pList;
+
+    if (!pWin->optional)
+        return FALSE;
+
+    pList = pWin->optional->deviceCursors;
+
+    if (pList && pList->dev == pDev) {
+        *pNode = pList;
+        *pPrev = NULL;
+        return TRUE;
+    }
+
+    while (pList) {
+        if (pList->next) {
+            if (pList->next->dev == pDev) {
+                *pNode = pList->next;
+                *pPrev = pList;
+                return TRUE;
+            }
+        }
+        pList = pList->next;
+    }
+    return FALSE;
+}
+
+/* Return True if a parent has the same device cursor set or False if
+ * otherwise
+ */
+static Bool
+WindowParentHasDeviceCursor(WindowPtr pWin,
+                            DeviceIntPtr pDev, CursorPtr pCursor)
+{
+    WindowPtr pParent;
+    DevCursNodePtr pParentNode, pParentPrev;
+
+    pParent = pWin->parent;
+    while (pParent) {
+        if (WindowSeekDeviceCursor(pParent, pDev, &pParentNode, &pParentPrev)) {
+            /* if there is a node in the list, the win has a dev cursor */
+            if (!pParentNode->cursor)   /* inherited. */
+                pParent = pParent->parent;
+            else if (pParentNode->cursor == pCursor)    /* inherit */
+                return TRUE;
+            else                /* different cursor */
+                return FALSE;
+        }
+        else
+            /* parent does not have a device cursor for our device */
+            return FALSE;
+    }
+    return FALSE;
+}
+
+/*
+ * SetRootClip --
+ *	Enable or disable rendering to the screen by
+ *	setting the root clip list and revalidating
+ *	all of the windows
+ */
+void
+SetRootClip(ScreenPtr pScreen, int enable)
+{
+    WindowPtr pWin = pScreen->root;
+    WindowPtr pChild;
+    Bool WasViewable;
+    Bool anyMarked = FALSE;
+    WindowPtr pLayerWin;
+    BoxRec box;
+    enum RootClipMode mode = enable;
+
+    if (!pWin)
+        return;
+    WasViewable = (Bool) (pWin->viewable);
+    if (WasViewable) {
+        for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
+            (void) (*pScreen->MarkOverlappedWindows) (pChild,
+                                                      pChild, &pLayerWin);
+        }
+        (*pScreen->MarkWindow) (pWin);
+        anyMarked = TRUE;
+        if (pWin->valdata) {
+            if (HasBorder(pWin)) {
+                RegionPtr borderVisible;
+
+                borderVisible = RegionCreate(NullBox, 1);
+                RegionSubtract(borderVisible,
+                               &pWin->borderClip, &pWin->winSize);
+                pWin->valdata->before.borderVisible = borderVisible;
+            }
+            pWin->valdata->before.resized = TRUE;
+        }
+    }
+
+    if (mode != ROOT_CLIP_NONE) {
+        pWin->drawable.width = pScreen->width;
+        pWin->drawable.height = pScreen->height;
+
+        box.x1 = 0;
+        box.y1 = 0;
+        box.x2 = pScreen->width;
+        box.y2 = pScreen->height;
+
+        RegionInit(&pWin->winSize, &box, 1);
+        RegionInit(&pWin->borderSize, &box, 1);
+
+        /*
+         * Use REGION_BREAK to avoid optimizations in ValidateTree
+         * that assume the root borderClip can't change well, normally
+         * it doesn't...)
+         */
+        RegionBreak(&pWin->clipList);
+
+	/* For INPUT_ONLY, empty the borderClip so no rendering will ever
+	 * be attempted to the screen pixmap (only redirected windows),
+	 * but we keep borderSize as full regardless. */
+        if (WasViewable && mode == ROOT_CLIP_FULL)
+            RegionReset(&pWin->borderClip, &box);
+        else
+            RegionEmpty(&pWin->borderClip);
+    }
+    else {
+        RegionEmpty(&pWin->borderClip);
+        RegionBreak(&pWin->clipList);
+    }
+
+    ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
+
+    if (WasViewable) {
+        if (pWin->firstChild) {
+            anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin->firstChild,
+                                                            pWin->firstChild,
+                                                            NULL);
+        }
+        else {
+            (*pScreen->MarkWindow) (pWin);
+            anyMarked = TRUE;
+        }
+
+        if (anyMarked) {
+            (*pScreen->ValidateTree) (pWin, NullWindow, VTOther);
+            (*pScreen->HandleExposures) (pWin);
+            if (pScreen->PostValidateTree)
+                (*pScreen->PostValidateTree) (pWin, NullWindow, VTOther);
+        }
+    }
+    if (pWin->realized)
+        WindowsRestructured();
+    FlushAllOutput();
+}
+
+VisualPtr
+WindowGetVisual(WindowPtr pWin)
+{
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+    VisualID vid = wVisual(pWin);
+    int i;
+
+    for (i = 0; i < pScreen->numVisuals; i++)
+        if (pScreen->visuals[i].vid == vid)
+            return &pScreen->visuals[i];
+    return 0;
+}
Index: xorg-server/create-21.1.7-black-patch/xorg-server-21.1.7-new/dix
===================================================================
--- xorg-server/create-21.1.7-black-patch/xorg-server-21.1.7-new/dix	(nonexistent)
+++ xorg-server/create-21.1.7-black-patch/xorg-server-21.1.7-new/dix	(revision 5)

Property changes on: xorg-server/create-21.1.7-black-patch/xorg-server-21.1.7-new/dix
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-black-patch/xorg-server-21.1.7-new
===================================================================
--- xorg-server/create-21.1.7-black-patch/xorg-server-21.1.7-new	(nonexistent)
+++ xorg-server/create-21.1.7-black-patch/xorg-server-21.1.7-new	(revision 5)

Property changes on: xorg-server/create-21.1.7-black-patch/xorg-server-21.1.7-new
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-black-patch
===================================================================
--- xorg-server/create-21.1.7-black-patch	(nonexistent)
+++ xorg-server/create-21.1.7-black-patch	(revision 5)

Property changes on: xorg-server/create-21.1.7-black-patch
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-dont-check-SeatId-patch/create.patch.sh
===================================================================
--- xorg-server/create-21.1.7-dont-check-SeatId-patch/create.patch.sh	(nonexistent)
+++ xorg-server/create-21.1.7-dont-check-SeatId-patch/create.patch.sh	(revision 5)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=21.1.7
+
+tar --files-from=file.list -xJvf ../xorg-server-$VERSION.tar.xz
+mv xorg-server-$VERSION xorg-server-$VERSION-orig
+
+cp -rf ./xorg-server-$VERSION-new ./xorg-server-$VERSION
+
+diff --unified -Nr  xorg-server-$VERSION-orig  xorg-server-$VERSION > xorg-server-$VERSION-dont-check-SeatId.patch
+
+mv xorg-server-$VERSION-dont-check-SeatId.patch ../patches
+
+rm -rf ./xorg-server-$VERSION
+rm -rf ./xorg-server-$VERSION-orig

Property changes on: xorg-server/create-21.1.7-dont-check-SeatId-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xorg-server/create-21.1.7-dont-check-SeatId-patch/file.list
===================================================================
--- xorg-server/create-21.1.7-dont-check-SeatId-patch/file.list	(nonexistent)
+++ xorg-server/create-21.1.7-dont-check-SeatId-patch/file.list	(revision 5)
@@ -0,0 +1 @@
+xorg-server-21.1.7/hw/kdrive/ephyr/ephyrinit.c
Index: xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new/hw/kdrive/ephyr/ephyrinit.c
===================================================================
--- xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new/hw/kdrive/ephyr/ephyrinit.c	(nonexistent)
+++ xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new/hw/kdrive/ephyr/ephyrinit.c	(revision 5)
@@ -0,0 +1,396 @@
+/*
+ * Xephyr - A kdrive X server that runs in a host X window.
+ *          Authored by Matthew Allum <mallum@o-hand.com>
+ *
+ * Copyright © 2004 Nokia
+ *
+ * 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 Nokia not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Nokia makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL NOKIA 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 "ephyr.h"
+#include "ephyrlog.h"
+#include "glx_extinit.h"
+
+extern Window EphyrPreExistingHostWin;
+extern Bool EphyrWantGrayScale;
+extern Bool EphyrWantResize;
+extern Bool EphyrWantNoHostGrab;
+extern Bool kdHasPointer;
+extern Bool kdHasKbd;
+extern Bool ephyr_glamor, ephyr_glamor_gles2, ephyr_glamor_skip_present;
+
+extern Bool ephyrNoXV;
+
+void processScreenOrOutputArg(const char *screen_size, const char *output, char *parent_id);
+void processOutputArg(const char *output, char *parent_id);
+void processScreenArg(const char *screen_size, char *parent_id);
+
+int
+main(int argc, char *argv[], char *envp[])
+{
+    hostx_use_resname(basename(argv[0]), 0);
+    return dix_main(argc, argv, envp);
+}
+
+void
+InitCard(char *name)
+{
+    EPHYR_DBG("mark");
+    KdCardInfoAdd(&ephyrFuncs, 0);
+}
+
+void
+InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
+{
+    KdInitOutput(pScreenInfo, argc, argv);
+}
+
+void
+InitInput(int argc, char **argv)
+{
+    KdKeyboardInfo *ki;
+    KdPointerInfo *pi;
+
+    KdAddKeyboardDriver(&EphyrKeyboardDriver);
+    KdAddPointerDriver(&EphyrMouseDriver);
+
+    if (!kdHasKbd) {
+        ki = KdNewKeyboard();
+        if (!ki)
+            FatalError("Couldn't create Xephyr keyboard\n");
+        ki->driver = &EphyrKeyboardDriver;
+        KdAddKeyboard(ki);
+    }
+
+    if (!kdHasPointer) {
+        pi = KdNewPointer();
+        if (!pi)
+            FatalError("Couldn't create Xephyr pointer\n");
+        pi->driver = &EphyrMouseDriver;
+        KdAddPointer(pi);
+    }
+
+    KdInitInput();
+}
+
+void
+CloseInput(void)
+{
+    KdCloseInput();
+}
+
+#if INPUTTHREAD
+/** This function is called in Xserver/os/inputthread.c when starting
+    the input thread. */
+void
+ddxInputThreadInit(void)
+{
+}
+#endif
+
+#ifdef DDXBEFORERESET
+void
+ddxBeforeReset(void)
+{
+}
+#endif
+
+void
+ddxUseMsg(void)
+{
+    KdUseMsg();
+
+    ErrorF("\nXephyr Option Usage:\n");
+    ErrorF("-parent <XID>        Use existing window as Xephyr root win\n");
+    ErrorF("-sw-cursor           Render cursors in software in Xephyr\n");
+    ErrorF("-fullscreen          Attempt to run Xephyr fullscreen\n");
+    ErrorF("-output <NAME>       Attempt to run Xephyr fullscreen (restricted to given output geometry)\n");
+    ErrorF("-grayscale           Simulate 8bit grayscale\n");
+    ErrorF("-resizeable          Make Xephyr windows resizeable\n");
+#ifdef GLAMOR
+    ErrorF("-glamor              Enable 2D acceleration using glamor\n");
+    ErrorF("-glamor_gles2        Enable 2D acceleration using glamor (with GLES2 only)\n");
+    ErrorF("-glamor-skip-present Skip presenting the output when using glamor (for internal testing optimization)\n");
+#endif
+    ErrorF
+        ("-fakexa              Simulate acceleration using software rendering\n");
+    ErrorF("-verbosity <level>   Set log verbosity level\n");
+    ErrorF("-noxv                do not use XV\n");
+    ErrorF("-name [name]         define the name in the WM_CLASS property\n");
+    ErrorF
+        ("-title [title]       set the window title in the WM_NAME property\n");
+    ErrorF("-no-host-grab        Disable grabbing the keyboard and mouse.\n");
+    ErrorF("\n");
+}
+
+void
+processScreenOrOutputArg(const char *screen_size, const char *output, char *parent_id)
+{
+    KdCardInfo *card;
+
+    InitCard(0);                /*Put each screen on a separate card */
+    card = KdCardInfoLast();
+
+    if (card) {
+        KdScreenInfo *screen;
+        unsigned long p_id = 0;
+        Bool use_geometry;
+
+        screen = KdScreenInfoAdd(card);
+        KdParseScreen(screen, screen_size);
+        screen->driver = calloc(1, sizeof(EphyrScrPriv));
+        if (!screen->driver)
+            FatalError("Couldn't alloc screen private\n");
+
+        if (parent_id) {
+            p_id = strtol(parent_id, NULL, 0);
+        }
+
+        use_geometry = (strchr(screen_size, '+') != NULL);
+        EPHYR_DBG("screen number:%d\n", screen->mynum);
+        hostx_add_screen(screen, p_id, screen->mynum, use_geometry, output);
+    }
+    else {
+        ErrorF("No matching card found!\n");
+    }
+}
+
+void
+processScreenArg(const char *screen_size, char *parent_id)
+{
+    processScreenOrOutputArg(screen_size, NULL, parent_id);
+}
+
+void
+processOutputArg(const char *output, char *parent_id)
+{
+    processScreenOrOutputArg("100x100+0+0", output, parent_id);
+}
+
+int
+ddxProcessArgument(int argc, char **argv, int i)
+{
+    static char *parent = NULL;
+
+    EPHYR_DBG("mark argv[%d]='%s'", i, argv[i]);
+
+    if (!strcmp(argv[i], "-parent")) {
+        if (i + 1 < argc) {
+            int j;
+
+            /* If parent is specified and a screen argument follows, don't do
+             * anything, let the -screen handling init the rest */
+            for (j = i; j < argc; j++) {
+                if (!strcmp(argv[j], "-screen")) {
+                    parent = argv[i + 1];
+                    return 2;
+                }
+            }
+
+            processScreenArg("100x100", argv[i + 1]);
+            return 2;
+        }
+
+        UseMsg();
+        exit(1);
+    }
+    else if (!strcmp(argv[i], "-screen")) {
+        if ((i + 1) < argc) {
+            processScreenArg(argv[i + 1], parent);
+            parent = NULL;
+            return 2;
+        }
+
+        UseMsg();
+        exit(1);
+    }
+    else if (!strcmp(argv[i], "-output")) {
+        if (i + 1 < argc) {
+            processOutputArg(argv[i + 1], NULL);
+            return 2;
+        }
+
+        UseMsg();
+        exit(1);
+    }
+    else if (!strcmp(argv[i], "-sw-cursor")) {
+        hostx_use_sw_cursor();
+        return 1;
+    }
+    else if (!strcmp(argv[i], "-host-cursor")) {
+        /* Compatibility with the old command line argument, now the default. */
+        return 1;
+    }
+    else if (!strcmp(argv[i], "-fullscreen")) {
+        hostx_use_fullscreen();
+        return 1;
+    }
+    else if (!strcmp(argv[i], "-grayscale")) {
+        EphyrWantGrayScale = 1;
+        return 1;
+    }
+    else if (!strcmp(argv[i], "-resizeable")) {
+        EphyrWantResize = 1;
+        return 1;
+    }
+#ifdef GLAMOR
+    else if (!strcmp (argv[i], "-glamor")) {
+        ephyr_glamor = TRUE;
+        ephyrFuncs.initAccel = ephyr_glamor_init;
+        ephyrFuncs.enableAccel = ephyr_glamor_enable;
+        ephyrFuncs.disableAccel = ephyr_glamor_disable;
+        ephyrFuncs.finiAccel = ephyr_glamor_fini;
+        return 1;
+    }
+    else if (!strcmp (argv[i], "-glamor_gles2")) {
+        ephyr_glamor = TRUE;
+        ephyr_glamor_gles2 = TRUE;
+        ephyrFuncs.initAccel = ephyr_glamor_init;
+        ephyrFuncs.enableAccel = ephyr_glamor_enable;
+        ephyrFuncs.disableAccel = ephyr_glamor_disable;
+        ephyrFuncs.finiAccel = ephyr_glamor_fini;
+        return 1;
+    }
+    else if (!strcmp (argv[i], "-glamor-skip-present")) {
+        ephyr_glamor_skip_present = TRUE;
+        return 1;
+    }
+#endif
+    else if (!strcmp(argv[i], "-fakexa")) {
+        ephyrFuncs.initAccel = ephyrDrawInit;
+        ephyrFuncs.enableAccel = ephyrDrawEnable;
+        ephyrFuncs.disableAccel = ephyrDrawDisable;
+        ephyrFuncs.finiAccel = ephyrDrawFini;
+        return 1;
+    }
+    else if (!strcmp(argv[i], "-verbosity")) {
+        if (i + 1 < argc && argv[i + 1][0] != '-') {
+            int verbosity = atoi(argv[i + 1]);
+
+            LogSetParameter(XLOG_VERBOSITY, verbosity);
+            EPHYR_LOG("set verbosiry to %d\n", verbosity);
+            return 2;
+        }
+        else {
+            UseMsg();
+            exit(1);
+        }
+    }
+    else if (!strcmp(argv[i], "-noxv")) {
+        ephyrNoXV = TRUE;
+        EPHYR_LOG("no XVideo enabled\n");
+        return 1;
+    }
+    else if (!strcmp(argv[i], "-name")) {
+        if (i + 1 < argc && argv[i + 1][0] != '-') {
+            hostx_use_resname(argv[i + 1], 1);
+            return 2;
+        }
+        else {
+            UseMsg();
+            return 0;
+        }
+    }
+    else if (!strcmp(argv[i], "-title")) {
+        if (i + 1 < argc && argv[i + 1][0] != '-') {
+            hostx_set_title(argv[i + 1]);
+            return 2;
+        }
+        else {
+            UseMsg();
+            return 0;
+        }
+    }
+    else if (argv[i][0] == ':') {
+        hostx_set_display_name(argv[i]);
+    }
+    /* Xnest compatibility */
+    else if (!strcmp(argv[i], "-display")) {
+        hostx_set_display_name(argv[i + 1]);
+        return 2;
+    }
+    else if (!strcmp(argv[i], "-sync") ||
+             !strcmp(argv[i], "-full") ||
+             !strcmp(argv[i], "-sss") || !strcmp(argv[i], "-install")) {
+        return 1;
+    }
+    else if (!strcmp(argv[i], "-bw") ||
+             !strcmp(argv[i], "-class") ||
+             !strcmp(argv[i], "-geometry") || !strcmp(argv[i], "-scrns")) {
+        return 2;
+    }
+    /* end Xnest compat */
+    else if (!strcmp(argv[i], "-no-host-grab")) {
+        EphyrWantNoHostGrab = 1;
+        return 1;
+    }
+    else if (!strcmp(argv[i], "-sharevts") ||
+             !strcmp(argv[i], "-novtswitch")) {
+        return 1;
+    }
+    else if (!strcmp(argv[i], "-layout")) {
+        return 2;
+    }
+
+    return KdProcessArgument(argc, argv, i);
+}
+
+void
+OsVendorInit(void)
+{
+    EPHYR_DBG("mark");
+
+    if (SeatId)
+        hostx_use_sw_cursor();
+
+    if (hostx_want_host_cursor())
+        ephyrFuncs.initCursor = &ephyrCursorInit;
+
+    if (serverGeneration == 1) {
+        if (!KdCardInfoLast()) {
+            processScreenArg("640x480", NULL);
+        }
+        hostx_init();
+    }
+}
+
+KdCardFuncs ephyrFuncs = {
+    ephyrCardInit,              /* cardinit */
+    ephyrScreenInitialize,      /* scrinit */
+    ephyrInitScreen,            /* initScreen */
+    ephyrFinishInitScreen,      /* finishInitScreen */
+    ephyrCreateResources,       /* createRes */
+    ephyrScreenFini,            /* scrfini */
+    ephyrCardFini,              /* cardfini */
+
+    0,                          /* initCursor */
+
+    0,                          /* initAccel */
+    0,                          /* enableAccel */
+    0,                          /* disableAccel */
+    0,                          /* finiAccel */
+
+    ephyrGetColors,             /* getColors */
+    ephyrPutColors,             /* putColors */
+
+    ephyrCloseScreen,           /* closeScreen */
+};
Index: xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new/hw/kdrive/ephyr
===================================================================
--- xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new/hw/kdrive/ephyr	(nonexistent)
+++ xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new/hw/kdrive/ephyr	(revision 5)

Property changes on: xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new/hw/kdrive/ephyr
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new/hw/kdrive
===================================================================
--- xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new/hw/kdrive	(nonexistent)
+++ xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new/hw/kdrive	(revision 5)

Property changes on: xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new/hw/kdrive
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new/hw
===================================================================
--- xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new/hw	(nonexistent)
+++ xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new/hw	(revision 5)

Property changes on: xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new/hw
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new
===================================================================
--- xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new	(nonexistent)
+++ xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new	(revision 5)

Property changes on: xorg-server/create-21.1.7-dont-check-SeatId-patch/xorg-server-21.1.7-new
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-dont-check-SeatId-patch
===================================================================
--- xorg-server/create-21.1.7-dont-check-SeatId-patch	(nonexistent)
+++ xorg-server/create-21.1.7-dont-check-SeatId-patch	(revision 5)

Property changes on: xorg-server/create-21.1.7-dont-check-SeatId-patch
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/create.patch.sh
===================================================================
--- xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/create.patch.sh	(nonexistent)
+++ xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/create.patch.sh	(revision 5)
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+VERSION=21.1.7
+
+tar --files-from=file.list -xJvf ../xorg-server-$VERSION.tar.xz
+patch -p0 < ../patches/xorg-server-$VERSION-modesetting-on-GeForce.patch
+mv xorg-server-$VERSION xorg-server-$VERSION-orig
+
+cp -rf ./xorg-server-$VERSION-new ./xorg-server-$VERSION
+
+diff --unified -Nr  xorg-server-$VERSION-orig  xorg-server-$VERSION > xorg-server-$VERSION-intel-ddx-only-on-pre-gen4.patch
+
+mv xorg-server-$VERSION-intel-ddx-only-on-pre-gen4.patch ../patches
+
+rm -rf ./xorg-server-$VERSION
+rm -rf ./xorg-server-$VERSION-orig

Property changes on: xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/file.list
===================================================================
--- xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/file.list	(nonexistent)
+++ xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/file.list	(revision 5)
@@ -0,0 +1 @@
+xorg-server-21.1.7/hw/xfree86/common/xf86pciBus.c
Index: xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new/hw/xfree86/common/xf86pciBus.c
===================================================================
--- xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new/hw/xfree86/common/xf86pciBus.c	(nonexistent)
+++ xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new/hw/xfree86/common/xf86pciBus.c	(revision 5)
@@ -0,0 +1,1491 @@
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * 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.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+/*
+ * This file contains the interfaces to the bus-specific code
+ */
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <X11/X.h>
+#include <pciaccess.h>
+#include "os.h"
+#include "Pci.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "dirent.h"             /* DIR, FILE type definitions */
+
+/* Bus-specific headers */
+#include "xf86Bus.h"
+
+#define XF86_OS_PRIVS
+#include "xf86_OSproc.h"
+
+#define PCI_VENDOR_GENERIC		0x00FF
+
+/* Bus-specific globals */
+int pciSlotClaimed = 0;
+
+#define PCIINFOCLASSES(c) \
+    ( (((c) & 0x00ff0000) == (PCI_CLASS_PREHISTORIC << 16)) \
+      || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \
+      || ((((c) & 0x00ffff00) \
+	   == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) \
+      || ((((c) & 0x00ffff00) \
+	   == ((PCI_CLASS_PROCESSOR << 16) | (PCI_SUBCLASS_PROCESSOR_COPROC << 8)))) )
+
+/*
+ * PCI classes that have messages printed always.  The others are only
+ * have a message printed when the vendor/dev IDs are recognised.
+ */
+#define PCIALWAYSPRINTCLASSES(c) \
+    ( (((c) & 0x00ffff00) \
+       == ((PCI_CLASS_PREHISTORIC << 16) | (PCI_SUBCLASS_PREHISTORIC_VGA << 8))) \
+      || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \
+      || ((((c) & 0x00ffff00) \
+	   == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) )
+
+#define IS_VGA(c) \
+    (((c) & 0x00ffff00) \
+	 == ((PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_VGA << 8)))
+
+static struct pci_slot_match xf86IsolateDevice = {
+    PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0
+};
+
+/*
+ * xf86Bus.c interface
+ */
+
+void
+xf86PciProbe(void)
+{
+    int i = 0, k;
+    int num = 0;
+    struct pci_device *info;
+    struct pci_device_iterator *iter;
+    struct pci_device **xf86PciVideoInfo = NULL;
+
+    if (!xf86scanpci()) {
+        xf86PciVideoInfo = NULL;
+        return;
+    }
+
+    iter = pci_slot_match_iterator_create(&xf86IsolateDevice);
+    while ((info = pci_device_next(iter)) != NULL) {
+        if (PCIINFOCLASSES(info->device_class)) {
+            num++;
+            xf86PciVideoInfo = xnfreallocarray(xf86PciVideoInfo,
+                                               num + 1,
+                                               sizeof(struct pci_device *));
+            xf86PciVideoInfo[num] = NULL;
+            xf86PciVideoInfo[num - 1] = info;
+
+            pci_device_probe(info);
+            if (primaryBus.type == BUS_NONE && pci_device_is_boot_vga(info)) {
+                primaryBus.type = BUS_PCI;
+                primaryBus.id.pci = info;
+            }
+            info->user_data = 0;
+        }
+    }
+    free(iter);
+
+    /* If we haven't found a primary device try a different heuristic */
+    if (primaryBus.type == BUS_NONE && num) {
+        for (i = 0; i < num; i++) {
+            uint16_t command;
+
+            info = xf86PciVideoInfo[i];
+            pci_device_cfg_read_u16(info, &command, 4);
+
+            if ((command & PCI_CMD_MEM_ENABLE)
+                && ((num == 1) || IS_VGA(info->device_class))) {
+                if (primaryBus.type == BUS_NONE) {
+                    primaryBus.type = BUS_PCI;
+                    primaryBus.id.pci = info;
+                }
+                else {
+                    xf86Msg(X_NOTICE,
+                            "More than one possible primary device found\n");
+                    primaryBus.type ^= (BusType) (-1);
+                }
+            }
+        }
+    }
+
+    /* Print a summary of the video devices found */
+    for (k = 0; k < num; k++) {
+        const char *prim = " ";
+        Bool memdone = FALSE, iodone = FALSE;
+
+        info = xf86PciVideoInfo[k];
+
+        if (!PCIALWAYSPRINTCLASSES(info->device_class))
+            continue;
+
+        if (xf86IsPrimaryPci(info))
+            prim = "*";
+
+        xf86Msg(X_PROBED, "PCI:%s(%u@%u:%u:%u) %04x:%04x:%04x:%04x ", prim,
+                info->bus, info->domain, info->dev, info->func,
+                info->vendor_id, info->device_id,
+                info->subvendor_id, info->subdevice_id);
+
+        xf86ErrorF("rev %d", info->revision);
+
+        for (i = 0; i < 6; i++) {
+            struct pci_mem_region *r = &info->regions[i];
+
+            if (r->size && !r->is_IO) {
+                if (!memdone) {
+                    xf86ErrorF(", Mem @ ");
+                    memdone = TRUE;
+                }
+                else
+                    xf86ErrorF(", ");
+                xf86ErrorF("0x%08lx/%ld", (long) r->base_addr, (long) r->size);
+            }
+        }
+
+        for (i = 0; i < 6; i++) {
+            struct pci_mem_region *r = &info->regions[i];
+
+            if (r->size && r->is_IO) {
+                if (!iodone) {
+                    xf86ErrorF(", I/O @ ");
+                    iodone = TRUE;
+                }
+                else
+                    xf86ErrorF(", ");
+                xf86ErrorF("0x%08lx/%ld", (long) r->base_addr, (long) r->size);
+            }
+        }
+
+        if (info->rom_size) {
+            xf86ErrorF(", BIOS @ 0x\?\?\?\?\?\?\?\?/%ld",
+                       (long) info->rom_size);
+        }
+
+        xf86ErrorF("\n");
+    }
+    free(xf86PciVideoInfo);
+}
+
+/*
+ * If the slot requested is already in use, return -1.
+ * Otherwise, claim the slot for the screen requesting it.
+ */
+
+int
+xf86ClaimPciSlot(struct pci_device *d, DriverPtr drvp,
+                 int chipset, GDevPtr dev, Bool active)
+{
+    EntityPtr p = NULL;
+    int num;
+
+    if (xf86CheckPciSlot(d)) {
+        num = xf86AllocateEntity();
+        p = xf86Entities[num];
+        p->driver = drvp;
+        p->chipset = chipset;
+        p->bus.type = BUS_PCI;
+        p->bus.id.pci = d;
+        p->active = active;
+        p->inUse = FALSE;
+        if (dev)
+            xf86AddDevToEntity(num, dev);
+        pciSlotClaimed++;
+
+        return num;
+    }
+    else
+        return -1;
+}
+
+/*
+ * Unclaim PCI slot, e.g. if probing failed, so that a different driver can claim.
+ */
+void
+xf86UnclaimPciSlot(struct pci_device *d, GDevPtr dev)
+{
+    int i;
+
+    for (i = 0; i < xf86NumEntities; i++) {
+        const EntityPtr p = xf86Entities[i];
+
+        if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) {
+            /* Probably the slot should be deallocated? */
+            xf86RemoveDevFromEntity(i, dev);
+            pciSlotClaimed--;
+            p->bus.type = BUS_NONE;
+            return;
+        }
+    }
+}
+
+/*
+ * Parse a BUS ID string, and return the PCI bus parameters if it was
+ * in the correct format for a PCI bus id.
+ */
+
+Bool
+xf86ParsePciBusString(const char *busID, int *bus, int *device, int *func)
+{
+    /*
+     * The format is assumed to be "bus[@domain]:device[:func]", where domain,
+     * bus, device and func are decimal integers.  domain and func may be
+     * omitted and assumed to be zero, although doing this isn't encouraged.
+     */
+
+    char *p, *s, *d;
+    const char *id;
+    int i;
+
+    if (StringToBusType(busID, &id) != BUS_PCI)
+        return FALSE;
+
+    s = xstrdup(id);
+    p = strtok(s, ":");
+    if (p == NULL || *p == 0) {
+        free(s);
+        return FALSE;
+    }
+    d = strpbrk(p, "@");
+    if (d != NULL) {
+        *(d++) = 0;
+        for (i = 0; d[i] != 0; i++) {
+            if (!isdigit(d[i])) {
+                free(s);
+                return FALSE;
+            }
+        }
+    }
+    for (i = 0; p[i] != 0; i++) {
+        if (!isdigit(p[i])) {
+            free(s);
+            return FALSE;
+        }
+    }
+    *bus = atoi(p);
+    if (d != NULL && *d != 0)
+        *bus += atoi(d) << 8;
+    p = strtok(NULL, ":");
+    if (p == NULL || *p == 0) {
+        free(s);
+        return FALSE;
+    }
+    for (i = 0; p[i] != 0; i++) {
+        if (!isdigit(p[i])) {
+            free(s);
+            return FALSE;
+        }
+    }
+    *device = atoi(p);
+    *func = 0;
+    p = strtok(NULL, ":");
+    if (p == NULL || *p == 0) {
+        free(s);
+        return TRUE;
+    }
+    for (i = 0; p[i] != 0; i++) {
+        if (!isdigit(p[i])) {
+            free(s);
+            return FALSE;
+        }
+    }
+    *func = atoi(p);
+    free(s);
+    return TRUE;
+}
+
+/*
+ * Compare a BUS ID string with a PCI bus id.  Return TRUE if they match.
+ */
+
+Bool
+xf86ComparePciBusString(const char *busID, int bus, int device, int func)
+{
+    int ibus, idevice, ifunc;
+
+    if (xf86ParsePciBusString(busID, &ibus, &idevice, &ifunc)) {
+        return bus == ibus && device == idevice && func == ifunc;
+    }
+    else {
+        return FALSE;
+    }
+}
+
+/*
+ * xf86IsPrimaryPci() -- return TRUE if primary device
+ * is PCI and bus, dev and func numbers match.
+ */
+
+Bool
+xf86IsPrimaryPci(struct pci_device *pPci)
+{
+    /* Add max. 1 screen for the IgnorePrimary fallback path */
+    if (xf86ProbeIgnorePrimary && xf86NumScreens == 0)
+        return TRUE;
+
+    if (primaryBus.type == BUS_PCI)
+        return pPci == primaryBus.id.pci;
+#ifdef XSERVER_PLATFORM_BUS
+    if (primaryBus.type == BUS_PLATFORM)
+        if (primaryBus.id.plat->pdev)
+            if (MATCH_PCI_DEVICES(primaryBus.id.plat->pdev, pPci))
+                return TRUE;
+#endif
+    return FALSE;
+}
+
+/*
+ * xf86GetPciInfoForEntity() -- Get the pciVideoRec of entity.
+ */
+struct pci_device *
+xf86GetPciInfoForEntity(int entityIndex)
+{
+    EntityPtr p;
+
+    if (entityIndex >= xf86NumEntities)
+        return NULL;
+
+    p = xf86Entities[entityIndex];
+    switch (p->bus.type) {
+    case BUS_PCI:
+        return p->bus.id.pci;
+    case BUS_PLATFORM:
+        return p->bus.id.plat->pdev;
+    default:
+        break;
+    }
+    return NULL;
+}
+
+/*
+ * xf86CheckPciMemBase() checks that the memory base value matches one of the
+ * PCI base address register values for the given PCI device.
+ */
+Bool
+xf86CheckPciMemBase(struct pci_device *pPci, memType base)
+{
+    int i;
+
+    for (i = 0; i < 6; i++)
+        if (base == pPci->regions[i].base_addr)
+            return TRUE;
+    return FALSE;
+}
+
+/*
+ * Check if the slot requested is free.  If it is already in use, return FALSE.
+ */
+
+Bool
+xf86CheckPciSlot(const struct pci_device *d)
+{
+    int i;
+
+    for (i = 0; i < xf86NumEntities; i++) {
+        const EntityPtr p = xf86Entities[i];
+
+        if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) {
+            return FALSE;
+        }
+#ifdef XSERVER_PLATFORM_BUS
+        if ((p->bus.type == BUS_PLATFORM) && (p->bus.id.plat->pdev)) {
+            struct pci_device *ud = p->bus.id.plat->pdev;
+            if (MATCH_PCI_DEVICES(ud, d))
+                return FALSE;
+        }
+#endif
+    }
+    return TRUE;
+}
+
+#define END_OF_MATCHES(m) \
+    (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0))
+
+Bool
+xf86PciAddMatchingDev(DriverPtr drvp)
+{
+    const struct pci_id_match *const devices = drvp->supported_devices;
+    int j;
+    struct pci_device *pPci;
+    struct pci_device_iterator *iter;
+    int numFound = 0;
+
+    iter = pci_id_match_iterator_create(NULL);
+    while ((pPci = pci_device_next(iter)) != NULL) {
+        /* Determine if this device is supported by the driver.  If it is,
+         * add it to the list of devices to configure.
+         */
+        for (j = 0; !END_OF_MATCHES(devices[j]); j++) {
+            if (PCI_ID_COMPARE(devices[j].vendor_id, pPci->vendor_id)
+                && PCI_ID_COMPARE(devices[j].device_id, pPci->device_id)
+                && ((devices[j].device_class_mask & pPci->device_class)
+                    == devices[j].device_class)) {
+                if (xf86CheckPciSlot(pPci)) {
+                    GDevPtr pGDev =
+                        xf86AddBusDeviceToConfigure(drvp->driverName, BUS_PCI,
+                                                    pPci, -1);
+                    if (pGDev != NULL) {
+                        /* After configure pass 1, chipID and chipRev are
+                         * treated as over-rides, so clobber them here.
+                         */
+                        pGDev->chipID = -1;
+                        pGDev->chipRev = -1;
+                    }
+
+                    numFound++;
+                }
+
+                break;
+            }
+        }
+    }
+
+    pci_iterator_destroy(iter);
+
+    return numFound != 0;
+}
+
+Bool
+xf86PciProbeDev(DriverPtr drvp)
+{
+    int i, j;
+    struct pci_device *pPci;
+    Bool foundScreen = FALSE;
+    const struct pci_id_match *const devices = drvp->supported_devices;
+    GDevPtr *devList;
+    const unsigned numDevs = xf86MatchDevice(drvp->driverName, &devList);
+
+    for (i = 0; i < numDevs; i++) {
+        struct pci_device_iterator *iter;
+        unsigned device_id;
+
+        /* Find the pciVideoRec associated with this device section.
+         */
+        iter = pci_id_match_iterator_create(NULL);
+        while ((pPci = pci_device_next(iter)) != NULL) {
+            if (devList[i]->busID && *devList[i]->busID) {
+                if (xf86ComparePciBusString(devList[i]->busID,
+                                            ((pPci->domain << 8)
+                                             | pPci->bus),
+                                            pPci->dev, pPci->func)) {
+                    break;
+                }
+            }
+            else if (xf86IsPrimaryPci(pPci)) {
+                break;
+            }
+        }
+
+        pci_iterator_destroy(iter);
+
+        if (pPci == NULL) {
+            continue;
+        }
+        device_id = (devList[i]->chipID > 0)
+            ? devList[i]->chipID : pPci->device_id;
+
+        /* Once the pciVideoRec is found, determine if the device is supported
+         * by the driver.  If it is, probe it!
+         */
+        for (j = 0; !END_OF_MATCHES(devices[j]); j++) {
+            if (PCI_ID_COMPARE(devices[j].vendor_id, pPci->vendor_id)
+                && PCI_ID_COMPARE(devices[j].device_id, device_id)
+                && ((devices[j].device_class_mask & pPci->device_class)
+                    == devices[j].device_class)) {
+                int entry;
+
+                /* Allow the same entity to be used more than once for
+                 * devices with multiple screens per entity.  This assumes
+                 * implicitly that there will be a screen == 0 instance.
+                 *
+                 * FIXME Need to make sure that two different drivers don't
+                 * FIXME claim the same screen > 0 instance.
+                 */
+                if ((devList[i]->screen == 0) && !xf86CheckPciSlot(pPci))
+                    continue;
+
+                DebugF("%s: card at %d:%d:%d is claimed by a Device section\n",
+                       drvp->driverName, pPci->bus, pPci->dev, pPci->func);
+
+                /* Allocate an entry in the lists to be returned */
+                entry = xf86ClaimPciSlot(pPci, drvp, device_id,
+                                         devList[i], devList[i]->active);
+
+                if ((entry == -1) && (devList[i]->screen > 0)) {
+                    unsigned k;
+
+                    for (k = 0; k < xf86NumEntities; k++) {
+                        EntityPtr pEnt = xf86Entities[k];
+
+                        if (pEnt->bus.type != BUS_PCI)
+                            continue;
+                        if (pEnt->bus.id.pci == pPci) {
+                            entry = k;
+                            xf86AddDevToEntity(k, devList[i]);
+                            break;
+                        }
+                    }
+                }
+
+                if (entry != -1) {
+                    if ((*drvp->PciProbe) (drvp, entry, pPci,
+                                           devices[j].match_data)) {
+                        foundScreen = TRUE;
+                    }
+                    else
+                        xf86UnclaimPciSlot(pPci, devList[i]);
+                }
+
+                break;
+            }
+        }
+    }
+    free(devList);
+
+    return foundScreen;
+}
+
+void
+xf86PciIsolateDevice(const char *argument)
+{
+    int bus, device, func;
+
+    if (sscanf(argument, "PCI:%d:%d:%d", &bus, &device, &func) == 3) {
+        xf86IsolateDevice.domain = PCI_DOM_FROM_BUS(bus);
+        xf86IsolateDevice.bus = PCI_BUS_NO_DOMAIN(bus);
+        xf86IsolateDevice.dev = device;
+        xf86IsolateDevice.func = func;
+    }
+    else
+        FatalError("Invalid isolated device specification\n");
+}
+
+static Bool
+pciDeviceHasBars(struct pci_device *pci)
+{
+    int i;
+
+    for (i = 0; i < 6; i++)
+        if (pci->regions[i].size)
+            return TRUE;
+
+    if (pci->rom_size)
+        return TRUE;
+
+    return FALSE;
+}
+
+struct Inst {
+    struct pci_device *pci;
+    GDevPtr dev;
+    Bool foundHW;               /* PCIid in list of supported chipsets */
+    Bool claimed;               /* BusID matches with a device section */
+    int chip;
+    int screen;
+};
+
+/**
+ * Find set of unclaimed devices matching a given vendor ID.
+ *
+ * Used by drivers to find as yet unclaimed devices matching the specified
+ * vendor ID.
+ *
+ * \param driverName     Name of the driver.  This is used to find Device
+ *                       sections in the config file.
+ * \param vendorID       PCI vendor ID of associated devices.  If zero, then
+ *                       the true vendor ID must be encoded in the \c PCIid
+ *                       fields of the \c PCIchipsets entries.
+ * \param chipsets       Symbol table used to associate chipset names with
+ *                       PCI IDs.
+ * \param devList        List of Device sections parsed from the config file.
+ * \param numDevs        Number of entries in \c devList.
+ * \param drvp           Pointer the driver's control structure.
+ * \param foundEntities  Returned list of entity indices associated with the
+ *                       driver.
+ *
+ * \returns
+ * The number of elements in returned in \c foundEntities on success or zero
+ * on failure.
+ *
+ * \todo
+ * This function does a bit more than short description says.  Fill in some
+ * more of the details of its operation.
+ *
+ * \todo
+ * The \c driverName parameter is redundant.  It is the same as
+ * \c DriverRec::driverName.  In a future version of this function, remove
+ * that parameter.
+ */
+int
+xf86MatchPciInstances(const char *driverName, int vendorID,
+                      SymTabPtr chipsets, PciChipsets * PCIchipsets,
+                      GDevPtr * devList, int numDevs, DriverPtr drvp,
+                      int **foundEntities)
+{
+    int i, j;
+    struct pci_device *pPci;
+    struct pci_device_iterator *iter;
+    struct Inst *instances = NULL;
+    int numClaimedInstances = 0;
+    int allocatedInstances = 0;
+    int numFound = 0;
+    SymTabRec *c;
+    PciChipsets *id;
+    int *retEntities = NULL;
+
+    *foundEntities = NULL;
+
+    /* Each PCI device will contribute at least one entry.  Each device
+     * section can contribute at most one entry.  The sum of the two is
+     * guaranteed to be larger than the maximum possible number of entries.
+     * Do this calculation and memory allocation once now to eliminate the
+     * need for realloc calls inside the loop.
+     */
+    if (!(xf86DoConfigure && xf86DoConfigurePass1)) {
+        unsigned max_entries = numDevs;
+
+        iter = pci_slot_match_iterator_create(NULL);
+        while ((pPci = pci_device_next(iter)) != NULL) {
+            max_entries++;
+        }
+
+        pci_iterator_destroy(iter);
+        instances = xnfallocarray(max_entries, sizeof(struct Inst));
+    }
+
+    iter = pci_slot_match_iterator_create(NULL);
+    while ((pPci = pci_device_next(iter)) != NULL) {
+        unsigned device_class = pPci->device_class;
+        Bool foundVendor = FALSE;
+
+        /* Convert the pre-PCI 2.0 device class for a VGA adapter to the
+         * 2.0 version of the same class.
+         */
+        if (device_class == 0x00000101) {
+            device_class = 0x00030000;
+        }
+
+        /* Find PCI devices that match the given vendor ID.  The vendor ID is
+         * either specified explicitly as a parameter to the function or
+         * implicitly encoded in the high bits of id->PCIid.
+         *
+         * The first device with a matching vendor is recorded, even if the
+         * device ID doesn't match.  This is done because the Device section
+         * in the xorg.conf file can over-ride the device ID.  A matching PCI
+         * ID might not be found now, but after the device ID over-ride is
+         * applied there /might/ be a match.
+         */
+        for (id = PCIchipsets; id->PCIid != -1; id++) {
+            const unsigned vendor_id = ((id->PCIid & 0xFFFF0000) >> 16)
+                | vendorID;
+            const unsigned device_id = (id->PCIid & 0x0000FFFF);
+            const unsigned match_class = 0x00030000 | id->PCIid;
+
+            if ((vendor_id == pPci->vendor_id)
+                || ((vendorID == PCI_VENDOR_GENERIC) &&
+                    (match_class == device_class))) {
+                if (!foundVendor && (instances != NULL)) {
+                    ++allocatedInstances;
+                    instances[allocatedInstances - 1].pci = pPci;
+                    instances[allocatedInstances - 1].dev = NULL;
+                    instances[allocatedInstances - 1].claimed = FALSE;
+                    instances[allocatedInstances - 1].foundHW = FALSE;
+                    instances[allocatedInstances - 1].screen = 0;
+                }
+
+                foundVendor = TRUE;
+
+                if ((device_id == pPci->device_id)
+                    || ((vendorID == PCI_VENDOR_GENERIC)
+                        && (match_class == device_class))) {
+                    if (instances != NULL) {
+                        instances[allocatedInstances - 1].foundHW = TRUE;
+                        instances[allocatedInstances - 1].chip = id->numChipset;
+                    }
+
+                    if (xf86DoConfigure && xf86DoConfigurePass1) {
+                        if (xf86CheckPciSlot(pPci)) {
+                            GDevPtr pGDev =
+                                xf86AddBusDeviceToConfigure(drvp->driverName,
+                                                            BUS_PCI, pPci, -1);
+
+                            if (pGDev) {
+                                /* After configure pass 1, chipID and chipRev
+                                 * are treated as over-rides, so clobber them
+                                 * here.
+                                 */
+                                pGDev->chipID = -1;
+                                pGDev->chipRev = -1;
+                            }
+
+                            numFound++;
+                        }
+                    }
+                    else {
+                        numFound++;
+                    }
+
+                    break;
+                }
+            }
+        }
+    }
+
+    pci_iterator_destroy(iter);
+
+    /* In "probe only" or "configure" mode (signaled by instances being NULL),
+     * our work is done.  Return the number of detected devices.
+     */
+    if (instances == NULL) {
+        return numFound;
+    }
+
+    /*
+     * This may be debatable, but if no PCI devices with a matching vendor
+     * type is found, return zero now.  It is probably not desirable to
+     * allow the config file to override this.
+     */
+    if (allocatedInstances <= 0) {
+        free(instances);
+        return 0;
+    }
+
+    DebugF("%s instances found: %d\n", driverName, allocatedInstances);
+
+    /*
+     * Check for devices that need duplicated instances.  This is required
+     * when there is more than one screen per entity.
+     *
+     * XXX This currently doesn't work for cases where the BusID isn't
+     * specified explicitly in the config file.
+     */
+
+    for (j = 0; j < numDevs; j++) {
+        if (devList[j]->screen > 0 && devList[j]->busID && *devList[j]->busID) {
+            for (i = 0; i < allocatedInstances; i++) {
+                pPci = instances[i].pci;
+                if (xf86ComparePciBusString(devList[j]->busID,
+                                            PCI_MAKE_BUS(pPci->domain,
+                                                         pPci->bus), pPci->dev,
+                                            pPci->func)) {
+                    allocatedInstances++;
+                    instances[allocatedInstances - 1] = instances[i];
+                    instances[allocatedInstances - 1].screen =
+                        devList[j]->screen;
+                    numFound++;
+                    break;
+                }
+            }
+        }
+    }
+
+    for (i = 0; i < allocatedInstances; i++) {
+        GDevPtr dev = NULL;
+        GDevPtr devBus = NULL;
+
+        pPci = instances[i].pci;
+        for (j = 0; j < numDevs; j++) {
+            if (devList[j]->busID && *devList[j]->busID) {
+                if (xf86ComparePciBusString(devList[j]->busID,
+                                            PCI_MAKE_BUS(pPci->domain,
+                                                         pPci->bus), pPci->dev,
+                                            pPci->func) &&
+                    devList[j]->screen == instances[i].screen) {
+
+                    if (devBus)
+                        xf86MsgVerb(X_WARNING, 0,
+                                    "%s: More than one matching Device section for "
+                                    "instances\n\t(BusID: %s) found: %s\n",
+                                    driverName, devList[j]->busID,
+                                    devList[j]->identifier);
+                    else
+                        devBus = devList[j];
+                }
+            }
+            else {
+                /*
+                 * if device section without BusID is found
+                 * only assign to it to the primary device.
+                 */
+                if (xf86IsPrimaryPci(pPci)) {
+                    xf86Msg(X_PROBED, "Assigning device section with no busID"
+                            " to primary device\n");
+                    if (dev || devBus)
+                        xf86MsgVerb(X_WARNING, 0,
+                                    "%s: More than one matching Device section "
+                                    "found: %s\n", driverName,
+                                    devList[j]->identifier);
+                    else
+                        dev = devList[j];
+                }
+            }
+        }
+        if (devBus)
+            dev = devBus;       /* busID preferred */
+        if (!dev) {
+            if (xf86CheckPciSlot(pPci) && pciDeviceHasBars(pPci)) {
+                xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section "
+                            "for instance (BusID PCI:%u@%u:%u:%u) found\n",
+                            driverName, pPci->bus, pPci->domain, pPci->dev,
+                            pPci->func);
+            }
+        }
+        else {
+            numClaimedInstances++;
+            instances[i].claimed = TRUE;
+            instances[i].dev = dev;
+        }
+    }
+    DebugF("%s instances found: %d\n", driverName, numClaimedInstances);
+    /*
+     * Now check that a chipset or chipID override in the device section
+     * is valid.  Chipset has precedence over chipID.
+     * If chipset is not valid ignore BusSlot completely.
+     */
+    for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) {
+        MessageType from = X_PROBED;
+
+        if (!instances[i].claimed) {
+            continue;
+        }
+        if (instances[i].dev->chipset) {
+            for (c = chipsets; c->token >= 0; c++) {
+                if (xf86NameCmp(c->name, instances[i].dev->chipset) == 0)
+                    break;
+            }
+            if (c->token == -1) {
+                instances[i].claimed = FALSE;
+                numClaimedInstances--;
+                xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device "
+                            "section \"%s\" isn't valid for this driver\n",
+                            driverName, instances[i].dev->chipset,
+                            instances[i].dev->identifier);
+            }
+            else {
+                instances[i].chip = c->token;
+
+                for (id = PCIchipsets; id->numChipset >= 0; id++) {
+                    if (id->numChipset == instances[i].chip)
+                        break;
+                }
+                if (id->numChipset >= 0) {
+                    xf86Msg(X_CONFIG, "Chipset override: %s\n",
+                            instances[i].dev->chipset);
+                    from = X_CONFIG;
+                }
+                else {
+                    instances[i].claimed = FALSE;
+                    numClaimedInstances--;
+                    xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device "
+                                "section \"%s\" isn't a valid PCI chipset\n",
+                                driverName, instances[i].dev->chipset,
+                                instances[i].dev->identifier);
+                }
+            }
+        }
+        else if (instances[i].dev->chipID > 0) {
+            for (id = PCIchipsets; id->numChipset >= 0; id++) {
+                if (id->PCIid == instances[i].dev->chipID)
+                    break;
+            }
+            if (id->numChipset == -1) {
+                instances[i].claimed = FALSE;
+                numClaimedInstances--;
+                xf86MsgVerb(X_WARNING, 0, "%s: ChipID 0x%04X in Device "
+                            "section \"%s\" isn't valid for this driver\n",
+                            driverName, instances[i].dev->chipID,
+                            instances[i].dev->identifier);
+            }
+            else {
+                instances[i].chip = id->numChipset;
+
+                xf86Msg(X_CONFIG, "ChipID override: 0x%04X\n",
+                        instances[i].dev->chipID);
+                from = X_CONFIG;
+            }
+        }
+        else if (!instances[i].foundHW) {
+            /*
+             * This means that there was no override and the PCI chipType
+             * doesn't match one that is supported
+             */
+            instances[i].claimed = FALSE;
+            numClaimedInstances--;
+        }
+        if (instances[i].claimed == TRUE) {
+            for (c = chipsets; c->token >= 0; c++) {
+                if (c->token == instances[i].chip)
+                    break;
+            }
+            xf86Msg(from, "Chipset %s found\n", c->name);
+        }
+    }
+
+    /*
+     * Of the claimed instances, check that another driver hasn't already
+     * claimed its slot.
+     */
+    numFound = 0;
+    for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) {
+        if (!instances[i].claimed)
+            continue;
+        pPci = instances[i].pci;
+
+        /*
+         * Allow the same entity to be used more than once for devices with
+         * multiple screens per entity.  This assumes implicitly that there
+         * will be a screen == 0 instance.
+         *
+         * XXX Need to make sure that two different drivers don't claim
+         * the same screen > 0 instance.
+         */
+        if (instances[i].screen == 0 && !xf86CheckPciSlot(pPci))
+            continue;
+
+        DebugF("%s: card at %d:%d:%d is claimed by a Device section\n",
+               driverName, pPci->bus, pPci->dev, pPci->func);
+
+        /* Allocate an entry in the lists to be returned */
+        numFound++;
+        retEntities = xnfreallocarray(retEntities, numFound, sizeof(int));
+        retEntities[numFound - 1] = xf86ClaimPciSlot(pPci, drvp,
+                                                     instances[i].chip,
+                                                     instances[i].dev,
+                                                     instances[i].dev->active);
+        if (retEntities[numFound - 1] == -1 && instances[i].screen > 0) {
+            for (j = 0; j < xf86NumEntities; j++) {
+                EntityPtr pEnt = xf86Entities[j];
+
+                if (pEnt->bus.type != BUS_PCI)
+                    continue;
+                if (pEnt->bus.id.pci == pPci) {
+                    retEntities[numFound - 1] = j;
+                    xf86AddDevToEntity(j, instances[i].dev);
+                    break;
+                }
+            }
+        }
+    }
+    free(instances);
+    if (numFound > 0) {
+        *foundEntities = retEntities;
+    }
+
+    return numFound;
+}
+
+/*
+ * xf86ConfigPciEntityInactive() -- This function can be used
+ * to configure an inactive entity as well as to reconfigure an
+ * previously active entity inactive. If the entity has been
+ * assigned to a screen before it will be removed. If p_chip is
+ * non-NULL all static resources listed there will be registered.
+ */
+static void
+xf86ConfigPciEntityInactive(EntityInfoPtr pEnt, PciChipsets * p_chip,
+                            EntityProc init, EntityProc enter,
+                            EntityProc leave, void *private)
+{
+    ScrnInfoPtr pScrn;
+
+    if ((pScrn = xf86FindScreenForEntity(pEnt->index)))
+        xf86RemoveEntityFromScreen(pScrn, pEnt->index);
+}
+
+ScrnInfoPtr
+xf86ConfigPciEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex,
+                    PciChipsets * p_chip, void *dummy, EntityProc init,
+                    EntityProc enter, EntityProc leave, void *private)
+{
+    EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
+
+    if (dummy || init || enter || leave)
+        FatalError("Legacy entity access functions are unsupported\n");
+
+    if (!pEnt)
+        return pScrn;
+
+    if (!(pEnt->location.type == BUS_PCI)
+        || !xf86GetPciInfoForEntity(entityIndex)) {
+        free(pEnt);
+        return pScrn;
+    }
+    if (!pEnt->active) {
+        xf86ConfigPciEntityInactive(pEnt, p_chip, init, enter, leave, private);
+        free(pEnt);
+        return pScrn;
+    }
+
+    if (!pScrn)
+        pScrn = xf86AllocateScreen(pEnt->driver, scrnFlag);
+    if (xf86IsEntitySharable(entityIndex)) {
+        xf86SetEntityShared(entityIndex);
+    }
+    xf86AddEntityToScreen(pScrn, entityIndex);
+    if (xf86IsEntityShared(entityIndex)) {
+        return pScrn;
+    }
+    free(pEnt);
+
+    return pScrn;
+}
+
+void
+xf86VideoPtrToDriverList(struct pci_device *dev, XF86MatchedDrivers *md)
+{
+    int i;
+
+    /* Add more entries here if we ever return more than 4 drivers for
+       any device */
+    const char *driverList[5] = { NULL, NULL, NULL, NULL, NULL };
+
+    switch (dev->vendor_id) {
+        /* AMD Geode LX */
+    case 0x1022:
+        if (dev->device_id == 0x2081)
+            driverList[0] = "geode";
+        break;
+        /* older Geode products acquired by AMD still carry an NSC vendor_id */
+    case 0x100b:
+        if (dev->device_id == 0x0030) {
+            /* NSC Geode GX2 specifically */
+            driverList[0] = "geode";
+            /* GX2 support started its life in the NSC tree and was later
+               forked by AMD for GEODE so we keep it as a backup */
+            driverList[1] = "nsc";
+        }
+        else
+            /* other NSC variant e.g. 0x0104 (SC1400), 0x0504 (SCx200) */
+            driverList[0] = "nsc";
+        break;
+        /* Cyrix Geode GX1 */
+    case 0x1078:
+        if (dev->device_id == 0x0104)
+            driverList[0] = "cyrix";
+        break;
+    case 0x1142:
+        driverList[0] = "apm";
+        break;
+    case 0xedd8:
+        driverList[0] = "ark";
+        break;
+    case 0x1a03:
+        driverList[0] = "ast";
+        break;
+    case 0x1002:
+        driverList[0] = "ati";
+        break;
+    case 0x102c:
+        driverList[0] = "chips";
+        break;
+    case 0x1013:
+        driverList[0] = "cirrus";
+        break;
+    case 0x3d3d:
+        driverList[0] = "glint";
+        break;
+    case 0x105d:
+        driverList[0] = "i128";
+        break;
+    case 0x8086:
+	switch (dev->device_id)
+	{
+		/* Intel i740 */
+		case 0x00d1:
+		case 0x7800:
+			driverList[0] = "i740";
+			break;
+		/* GMA500/Poulsbo */
+		case 0x8108:
+		case 0x8109:
+			/* Try psb driver on Poulsbo - if available */
+			driverList[0] = "psb";
+			driverList[1] = "psb_drv";
+			break;
+		/* GMA600/Oaktrail */
+		case 0x4100:
+		case 0x4101:
+		case 0x4102:
+		case 0x4103:
+		case 0x4104:
+		case 0x4105:
+		case 0x4106:
+		case 0x4107:
+		/* Atom E620/Oaktrail */
+		case 0x4108:
+		/* Medfield */
+		case 0x0130:
+		case 0x0131:
+		case 0x0132:
+		case 0x0133:
+		case 0x0134:
+		case 0x0135:
+		case 0x0136:
+		case 0x0137:
+		/* GMA 3600/CDV */
+		case 0x0be0:
+		case 0x0be1:
+		case 0x0be2:
+		case 0x0be3:
+		case 0x0be4:
+		case 0x0be5:
+		case 0x0be6:
+		case 0x0be7:
+		case 0x0be8:
+		case 0x0be9:
+		case 0x0bea:
+		case 0x0beb:
+		case 0x0bec:
+		case 0x0bed:
+		case 0x0bee:
+		case 0x0bef:
+			/* Use fbdev/vesa driver on Oaktrail, Medfield, CDV */
+			break;
+		/* Default to intel only on pre-gen4 chips */
+		case 0x3577:
+		case 0x2562:
+		case 0x3582:
+		case 0x358e:
+		case 0x2572:
+		case 0x2582:
+		case 0x258a:
+		case 0x2592:
+		case 0x2772:
+		case 0x27a2:
+		case 0x27ae:
+		case 0x29b2:
+		case 0x29c2:
+		case 0x29d2:
+		case 0xa001:
+		case 0xa011:
+			driverList[0] = "intel";
+			break;
+        }
+        break;
+    case 0x102b:
+        driverList[0] = "mga";
+        break;
+    case 0x10c8:
+        driverList[0] = "neomagic";
+        break;
+    case 0x10de:
+    case 0x12d2:
+    {
+        int idx = 0;
+
+#if defined(__linux__) || defined(__NetBSD__)
+        driverList[idx++] = "nouveau";
+#endif
+        driverList[idx++] = "nv";
+        break;
+    }
+    case 0x1106:
+        driverList[0] = "openchrome";
+        break;
+    case 0x1b36:
+        driverList[0] = "qxl";
+        break;
+    case 0x1163:
+        driverList[0] = "rendition";
+        break;
+    case 0x5333:
+        switch (dev->device_id) {
+        case 0x88d0:
+        case 0x88d1:
+        case 0x88f0:
+        case 0x8811:
+        case 0x8812:
+        case 0x8814:
+        case 0x8901:
+            driverList[0] = "s3";
+            break;
+        case 0x5631:
+        case 0x883d:
+        case 0x8a01:
+        case 0x8a10:
+        case 0x8c01:
+        case 0x8c03:
+        case 0x8904:
+        case 0x8a13:
+            driverList[0] = "s3virge";
+            break;
+        default:
+            driverList[0] = "savage";
+            break;
+        }
+        break;
+    case 0x1039:
+        driverList[0] = "sis";
+        break;
+    case 0x126f:
+        driverList[0] = "siliconmotion";
+        break;
+    case 0x121a:
+        if (dev->device_id < 0x0003)
+            driverList[0] = "voodoo";
+        else
+            driverList[0] = "tdfx";
+        break;
+    case 0x1011:
+        driverList[0] = "tga";
+        break;
+    case 0x1023:
+        driverList[0] = "trident";
+        break;
+    case 0x100c:
+        driverList[0] = "tseng";
+        break;
+    case 0x80ee:
+        driverList[0] = "vboxvideo";
+        break;
+    case 0x15ad:
+        driverList[0] = "vmware";
+        break;
+    case 0x18ca:
+        if (dev->device_id == 0x47)
+            driverList[0] = "xgixp";
+        else
+            driverList[0] = "xgi";
+        break;
+    default:
+        break;
+    }
+    for (i = 0; driverList[i] != NULL; i++) {
+        xf86AddMatchedDriver(md, driverList[i]);
+    }
+}
+
+#ifdef __linux__
+static int
+xchomp(char *line)
+{
+    size_t len = 0;
+
+    if (!line) {
+        return 1;
+    }
+
+    len = strlen(line);
+    if (line[len - 1] == '\n' && len > 0) {
+        line[len - 1] = '\0';
+    }
+    return 0;
+}
+
+/* This function is used to provide a workaround for binary drivers that
+ * don't export their PCI ID's properly. If distros don't end up using this
+ * feature it can and should be removed because the symbol-based resolution
+ * scheme should be the primary one */
+void
+xf86MatchDriverFromFiles(uint16_t match_vendor, uint16_t match_chip,
+                         XF86MatchedDrivers *md)
+{
+    DIR *idsdir;
+    FILE *fp;
+    struct dirent *direntry;
+    char *line = NULL, *tmpMatch;
+    size_t len;
+    ssize_t read;
+    char path_name[512], vendor_str[5], chip_str[5];
+    uint16_t vendor, chip;
+    int j;
+
+    idsdir = opendir(PCI_TXT_IDS_PATH);
+    if (!idsdir)
+        return;
+
+    xf86Msg(X_INFO,
+            "Scanning %s directory for additional PCI ID's supported by the drivers\n",
+            PCI_TXT_IDS_PATH);
+    direntry = readdir(idsdir);
+    /* Read the directory */
+    while (direntry) {
+        if (direntry->d_name[0] == '.') {
+            direntry = readdir(idsdir);
+            continue;
+        }
+        len = strlen(direntry->d_name);
+        /* A tiny bit of sanity checking. We should probably do better */
+        if (strncmp(&(direntry->d_name[len - 4]), ".ids", 4) == 0) {
+            /* We need the full path name to open the file */
+            snprintf(path_name, sizeof(path_name), "%s/%s",
+                     PCI_TXT_IDS_PATH, direntry->d_name);
+            fp = fopen(path_name, "r");
+            if (fp == NULL) {
+                xf86Msg(X_ERROR, "Could not open %s for reading. Exiting.\n",
+                        path_name);
+                goto end;
+            }
+            /* Read the file */
+#ifdef __GLIBC__
+            while ((read = getline(&line, &len, fp)) != -1) {
+#else
+            while ((line = fgetln(fp, &len)) != (char *) NULL) {
+#endif                          /* __GLIBC __ */
+                xchomp(line);
+                if (isdigit(line[0])) {
+                    strlcpy(vendor_str, line, sizeof(vendor_str));
+                    vendor = (int) strtol(vendor_str, NULL, 16);
+                    if ((strlen(&line[4])) == 0) {
+                        chip_str[0] = '\0';
+                        chip = -1;
+                    }
+                    else {
+                        /* Handle trailing whitespace */
+                        if (isspace(line[4])) {
+                            chip_str[0] = '\0';
+                            chip = -1;
+                        }
+                        else {
+                            /* Ok, it's a real ID */
+                            strlcpy(chip_str, &line[4], sizeof(chip_str));
+                            chip = (int) strtol(chip_str, NULL, 16);
+                        }
+                    }
+                    if (vendor == match_vendor && chip == match_chip) {
+                        tmpMatch =
+                            (char *) malloc(sizeof(char) *
+                                            strlen(direntry->d_name) - 3);
+                        if (!tmpMatch) {
+                            xf86Msg(X_ERROR,
+                                    "Could not allocate space for the module name. Exiting.\n");
+                            goto end;
+                        }
+                        /* hack off the .ids suffix. This should guard
+                         * against other problems, but it will end up
+                         * taking off anything after the first '.' */
+                        for (j = 0; j < (strlen(direntry->d_name) - 3); j++) {
+                            if (direntry->d_name[j] == '.') {
+                                tmpMatch[j] = '\0';
+                                break;
+                            }
+                            else {
+                                tmpMatch[j] = direntry->d_name[j];
+                            }
+                        }
+                        xf86AddMatchedDriver(md, tmpMatch);
+                        xf86Msg(X_INFO, "Matched %s from file name %s\n",
+                                tmpMatch, direntry->d_name);
+                        free(tmpMatch);
+                    }
+                }
+                else {
+                    /* TODO Handle driver overrides here */
+                }
+            }
+            fclose(fp);
+        }
+        direntry = readdir(idsdir);
+    }
+ end:
+    free(line);
+    closedir(idsdir);
+}
+#endif                          /* __linux__ */
+
+void
+xf86PciMatchDriver(XF86MatchedDrivers *md)
+{
+    struct pci_device *info = NULL;
+    struct pci_device_iterator *iter;
+
+    /* Find the primary device, and get some information about it. */
+    iter = pci_slot_match_iterator_create(NULL);
+    while ((info = pci_device_next(iter)) != NULL) {
+        if (xf86IsPrimaryPci(info)) {
+            break;
+        }
+    }
+
+    pci_iterator_destroy(iter);
+#ifdef __linux__
+    if (info)
+        xf86MatchDriverFromFiles(info->vendor_id, info->device_id, md);
+#endif
+
+    if (info != NULL) {
+        xf86VideoPtrToDriverList(info, md);
+    }
+}
+
+Bool
+xf86PciConfigure(void *busData, struct pci_device *pDev)
+{
+    struct pci_device *pVideo = NULL;
+
+    pVideo = (struct pci_device *) busData;
+    if (pDev &&
+        (pDev->domain == pVideo->domain) &&
+        (pDev->bus == pVideo->bus) &&
+        (pDev->dev == pVideo->dev) && (pDev->func == pVideo->func))
+        return 0;
+
+    return 1;
+}
+
+void
+xf86PciConfigureNewDev(void *busData, struct pci_device *pVideo,
+                       GDevRec * GDev, int *chipset)
+{
+    char busnum[8];
+    char *tmp;
+
+    pVideo = (struct pci_device *) busData;
+
+    snprintf(busnum, sizeof(busnum), "%d", pVideo->bus);
+
+    XNFasprintf(&tmp, "PCI:%s:%d:%d",
+                busnum, pVideo->dev, pVideo->func);
+    GDev->busID = tmp;
+
+    GDev->chipID = pVideo->device_id;
+    GDev->chipRev = pVideo->revision;
+
+    if (*chipset < 0)
+        *chipset = (pVideo->vendor_id << 16) | pVideo->device_id;
+}
+
+char *
+DRICreatePCIBusID(const struct pci_device *dev)
+{
+    char *busID;
+
+    if (asprintf(&busID, "pci:%04x:%02x:%02x.%d",
+                 dev->domain, dev->bus, dev->dev, dev->func) == -1)
+        return NULL;
+
+    return busID;
+}
Index: xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new/hw/xfree86/common
===================================================================
--- xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new/hw/xfree86/common	(nonexistent)
+++ xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new/hw/xfree86/common	(revision 5)

Property changes on: xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new/hw/xfree86/common
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new/hw/xfree86
===================================================================
--- xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new/hw/xfree86	(nonexistent)
+++ xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new/hw/xfree86	(revision 5)

Property changes on: xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new/hw/xfree86
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new/hw
===================================================================
--- xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new/hw	(nonexistent)
+++ xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new/hw	(revision 5)

Property changes on: xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new/hw
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new
===================================================================
--- xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new	(nonexistent)
+++ xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new	(revision 5)

Property changes on: xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch/xorg-server-21.1.7-new
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch
===================================================================
--- xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch	(nonexistent)
+++ xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch	(revision 5)

Property changes on: xorg-server/create-21.1.7-intel-ddx-only-on-pre-gen4-patch
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-modesetting-on-GeForce-patch/create.patch.sh
===================================================================
--- xorg-server/create-21.1.7-modesetting-on-GeForce-patch/create.patch.sh	(nonexistent)
+++ xorg-server/create-21.1.7-modesetting-on-GeForce-patch/create.patch.sh	(revision 5)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=21.1.7
+
+tar --files-from=file.list -xJvf ../xorg-server-$VERSION.tar.xz
+mv xorg-server-$VERSION xorg-server-$VERSION-orig
+
+cp -rf ./xorg-server-$VERSION-new ./xorg-server-$VERSION
+
+diff --unified -Nr  xorg-server-$VERSION-orig  xorg-server-$VERSION > xorg-server-$VERSION-modesetting-on-GeForce.patch
+
+mv xorg-server-$VERSION-modesetting-on-GeForce.patch ../patches
+
+rm -rf ./xorg-server-$VERSION
+rm -rf ./xorg-server-$VERSION-orig

Property changes on: xorg-server/create-21.1.7-modesetting-on-GeForce-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xorg-server/create-21.1.7-modesetting-on-GeForce-patch/file.list
===================================================================
--- xorg-server/create-21.1.7-modesetting-on-GeForce-patch/file.list	(nonexistent)
+++ xorg-server/create-21.1.7-modesetting-on-GeForce-patch/file.list	(revision 5)
@@ -0,0 +1 @@
+xorg-server-21.1.7/hw/xfree86/common/xf86pciBus.c
Index: xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new/hw/xfree86/common/xf86pciBus.c
===================================================================
--- xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new/hw/xfree86/common/xf86pciBus.c	(nonexistent)
+++ xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new/hw/xfree86/common/xf86pciBus.c	(revision 5)
@@ -0,0 +1,1495 @@
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * 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.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+/*
+ * This file contains the interfaces to the bus-specific code
+ */
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <X11/X.h>
+#include <pciaccess.h>
+#include <xf86drm.h>
+#include "os.h"
+#include "Pci.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "dirent.h"             /* DIR, FILE type definitions */
+
+/* Bus-specific headers */
+#include "xf86Bus.h"
+
+#define XF86_OS_PRIVS
+#include "xf86_OSproc.h"
+
+#define PCI_VENDOR_GENERIC		0x00FF
+
+/* Bus-specific globals */
+int pciSlotClaimed = 0;
+
+#define PCIINFOCLASSES(c) \
+    ( (((c) & 0x00ff0000) == (PCI_CLASS_PREHISTORIC << 16)) \
+      || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \
+      || ((((c) & 0x00ffff00) \
+	   == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) \
+      || ((((c) & 0x00ffff00) \
+	   == ((PCI_CLASS_PROCESSOR << 16) | (PCI_SUBCLASS_PROCESSOR_COPROC << 8)))) )
+
+/*
+ * PCI classes that have messages printed always.  The others are only
+ * have a message printed when the vendor/dev IDs are recognised.
+ */
+#define PCIALWAYSPRINTCLASSES(c) \
+    ( (((c) & 0x00ffff00) \
+       == ((PCI_CLASS_PREHISTORIC << 16) | (PCI_SUBCLASS_PREHISTORIC_VGA << 8))) \
+      || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \
+      || ((((c) & 0x00ffff00) \
+	   == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) )
+
+#define IS_VGA(c) \
+    (((c) & 0x00ffff00) \
+	 == ((PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_VGA << 8)))
+
+static struct pci_slot_match xf86IsolateDevice = {
+    PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0
+};
+
+/*
+ * xf86Bus.c interface
+ */
+
+void
+xf86PciProbe(void)
+{
+    int i = 0, k;
+    int num = 0;
+    struct pci_device *info;
+    struct pci_device_iterator *iter;
+    struct pci_device **xf86PciVideoInfo = NULL;
+
+    if (!xf86scanpci()) {
+        xf86PciVideoInfo = NULL;
+        return;
+    }
+
+    iter = pci_slot_match_iterator_create(&xf86IsolateDevice);
+    while ((info = pci_device_next(iter)) != NULL) {
+        if (PCIINFOCLASSES(info->device_class)) {
+            num++;
+            xf86PciVideoInfo = xnfreallocarray(xf86PciVideoInfo,
+                                               num + 1,
+                                               sizeof(struct pci_device *));
+            xf86PciVideoInfo[num] = NULL;
+            xf86PciVideoInfo[num - 1] = info;
+
+            pci_device_probe(info);
+            if (primaryBus.type == BUS_NONE && pci_device_is_boot_vga(info)) {
+                primaryBus.type = BUS_PCI;
+                primaryBus.id.pci = info;
+            }
+            info->user_data = 0;
+        }
+    }
+    free(iter);
+
+    /* If we haven't found a primary device try a different heuristic */
+    if (primaryBus.type == BUS_NONE && num) {
+        for (i = 0; i < num; i++) {
+            uint16_t command;
+
+            info = xf86PciVideoInfo[i];
+            pci_device_cfg_read_u16(info, &command, 4);
+
+            if ((command & PCI_CMD_MEM_ENABLE)
+                && ((num == 1) || IS_VGA(info->device_class))) {
+                if (primaryBus.type == BUS_NONE) {
+                    primaryBus.type = BUS_PCI;
+                    primaryBus.id.pci = info;
+                }
+                else {
+                    xf86Msg(X_NOTICE,
+                            "More than one possible primary device found\n");
+                    primaryBus.type ^= (BusType) (-1);
+                }
+            }
+        }
+    }
+
+    /* Print a summary of the video devices found */
+    for (k = 0; k < num; k++) {
+        const char *prim = " ";
+        Bool memdone = FALSE, iodone = FALSE;
+
+        info = xf86PciVideoInfo[k];
+
+        if (!PCIALWAYSPRINTCLASSES(info->device_class))
+            continue;
+
+        if (xf86IsPrimaryPci(info))
+            prim = "*";
+
+        xf86Msg(X_PROBED, "PCI:%s(%u@%u:%u:%u) %04x:%04x:%04x:%04x ", prim,
+                info->bus, info->domain, info->dev, info->func,
+                info->vendor_id, info->device_id,
+                info->subvendor_id, info->subdevice_id);
+
+        xf86ErrorF("rev %d", info->revision);
+
+        for (i = 0; i < 6; i++) {
+            struct pci_mem_region *r = &info->regions[i];
+
+            if (r->size && !r->is_IO) {
+                if (!memdone) {
+                    xf86ErrorF(", Mem @ ");
+                    memdone = TRUE;
+                }
+                else
+                    xf86ErrorF(", ");
+                xf86ErrorF("0x%08lx/%ld", (long) r->base_addr, (long) r->size);
+            }
+        }
+
+        for (i = 0; i < 6; i++) {
+            struct pci_mem_region *r = &info->regions[i];
+
+            if (r->size && r->is_IO) {
+                if (!iodone) {
+                    xf86ErrorF(", I/O @ ");
+                    iodone = TRUE;
+                }
+                else
+                    xf86ErrorF(", ");
+                xf86ErrorF("0x%08lx/%ld", (long) r->base_addr, (long) r->size);
+            }
+        }
+
+        if (info->rom_size) {
+            xf86ErrorF(", BIOS @ 0x\?\?\?\?\?\?\?\?/%ld",
+                       (long) info->rom_size);
+        }
+
+        xf86ErrorF("\n");
+    }
+    free(xf86PciVideoInfo);
+}
+
+/*
+ * If the slot requested is already in use, return -1.
+ * Otherwise, claim the slot for the screen requesting it.
+ */
+
+int
+xf86ClaimPciSlot(struct pci_device *d, DriverPtr drvp,
+                 int chipset, GDevPtr dev, Bool active)
+{
+    EntityPtr p = NULL;
+    int num;
+
+    if (xf86CheckPciSlot(d)) {
+        num = xf86AllocateEntity();
+        p = xf86Entities[num];
+        p->driver = drvp;
+        p->chipset = chipset;
+        p->bus.type = BUS_PCI;
+        p->bus.id.pci = d;
+        p->active = active;
+        p->inUse = FALSE;
+        if (dev)
+            xf86AddDevToEntity(num, dev);
+        pciSlotClaimed++;
+
+        return num;
+    }
+    else
+        return -1;
+}
+
+/*
+ * Unclaim PCI slot, e.g. if probing failed, so that a different driver can claim.
+ */
+void
+xf86UnclaimPciSlot(struct pci_device *d, GDevPtr dev)
+{
+    int i;
+
+    for (i = 0; i < xf86NumEntities; i++) {
+        const EntityPtr p = xf86Entities[i];
+
+        if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) {
+            /* Probably the slot should be deallocated? */
+            xf86RemoveDevFromEntity(i, dev);
+            pciSlotClaimed--;
+            p->bus.type = BUS_NONE;
+            return;
+        }
+    }
+}
+
+/*
+ * Parse a BUS ID string, and return the PCI bus parameters if it was
+ * in the correct format for a PCI bus id.
+ */
+
+Bool
+xf86ParsePciBusString(const char *busID, int *bus, int *device, int *func)
+{
+    /*
+     * The format is assumed to be "bus[@domain]:device[:func]", where domain,
+     * bus, device and func are decimal integers.  domain and func may be
+     * omitted and assumed to be zero, although doing this isn't encouraged.
+     */
+
+    char *p, *s, *d;
+    const char *id;
+    int i;
+
+    if (StringToBusType(busID, &id) != BUS_PCI)
+        return FALSE;
+
+    s = xstrdup(id);
+    p = strtok(s, ":");
+    if (p == NULL || *p == 0) {
+        free(s);
+        return FALSE;
+    }
+    d = strpbrk(p, "@");
+    if (d != NULL) {
+        *(d++) = 0;
+        for (i = 0; d[i] != 0; i++) {
+            if (!isdigit(d[i])) {
+                free(s);
+                return FALSE;
+            }
+        }
+    }
+    for (i = 0; p[i] != 0; i++) {
+        if (!isdigit(p[i])) {
+            free(s);
+            return FALSE;
+        }
+    }
+    *bus = atoi(p);
+    if (d != NULL && *d != 0)
+        *bus += atoi(d) << 8;
+    p = strtok(NULL, ":");
+    if (p == NULL || *p == 0) {
+        free(s);
+        return FALSE;
+    }
+    for (i = 0; p[i] != 0; i++) {
+        if (!isdigit(p[i])) {
+            free(s);
+            return FALSE;
+        }
+    }
+    *device = atoi(p);
+    *func = 0;
+    p = strtok(NULL, ":");
+    if (p == NULL || *p == 0) {
+        free(s);
+        return TRUE;
+    }
+    for (i = 0; p[i] != 0; i++) {
+        if (!isdigit(p[i])) {
+            free(s);
+            return FALSE;
+        }
+    }
+    *func = atoi(p);
+    free(s);
+    return TRUE;
+}
+
+/*
+ * Compare a BUS ID string with a PCI bus id.  Return TRUE if they match.
+ */
+
+Bool
+xf86ComparePciBusString(const char *busID, int bus, int device, int func)
+{
+    int ibus, idevice, ifunc;
+
+    if (xf86ParsePciBusString(busID, &ibus, &idevice, &ifunc)) {
+        return bus == ibus && device == idevice && func == ifunc;
+    }
+    else {
+        return FALSE;
+    }
+}
+
+/*
+ * xf86IsPrimaryPci() -- return TRUE if primary device
+ * is PCI and bus, dev and func numbers match.
+ */
+
+Bool
+xf86IsPrimaryPci(struct pci_device *pPci)
+{
+    /* Add max. 1 screen for the IgnorePrimary fallback path */
+    if (xf86ProbeIgnorePrimary && xf86NumScreens == 0)
+        return TRUE;
+
+    if (primaryBus.type == BUS_PCI)
+        return pPci == primaryBus.id.pci;
+#ifdef XSERVER_PLATFORM_BUS
+    if (primaryBus.type == BUS_PLATFORM)
+        if (primaryBus.id.plat->pdev)
+            if (MATCH_PCI_DEVICES(primaryBus.id.plat->pdev, pPci))
+                return TRUE;
+#endif
+    return FALSE;
+}
+
+/*
+ * xf86GetPciInfoForEntity() -- Get the pciVideoRec of entity.
+ */
+struct pci_device *
+xf86GetPciInfoForEntity(int entityIndex)
+{
+    EntityPtr p;
+
+    if (entityIndex >= xf86NumEntities)
+        return NULL;
+
+    p = xf86Entities[entityIndex];
+    switch (p->bus.type) {
+    case BUS_PCI:
+        return p->bus.id.pci;
+    case BUS_PLATFORM:
+        return p->bus.id.plat->pdev;
+    default:
+        break;
+    }
+    return NULL;
+}
+
+/*
+ * xf86CheckPciMemBase() checks that the memory base value matches one of the
+ * PCI base address register values for the given PCI device.
+ */
+Bool
+xf86CheckPciMemBase(struct pci_device *pPci, memType base)
+{
+    int i;
+
+    for (i = 0; i < 6; i++)
+        if (base == pPci->regions[i].base_addr)
+            return TRUE;
+    return FALSE;
+}
+
+/*
+ * Check if the slot requested is free.  If it is already in use, return FALSE.
+ */
+
+Bool
+xf86CheckPciSlot(const struct pci_device *d)
+{
+    int i;
+
+    for (i = 0; i < xf86NumEntities; i++) {
+        const EntityPtr p = xf86Entities[i];
+
+        if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) {
+            return FALSE;
+        }
+#ifdef XSERVER_PLATFORM_BUS
+        if ((p->bus.type == BUS_PLATFORM) && (p->bus.id.plat->pdev)) {
+            struct pci_device *ud = p->bus.id.plat->pdev;
+            if (MATCH_PCI_DEVICES(ud, d))
+                return FALSE;
+        }
+#endif
+    }
+    return TRUE;
+}
+
+#define END_OF_MATCHES(m) \
+    (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0))
+
+Bool
+xf86PciAddMatchingDev(DriverPtr drvp)
+{
+    const struct pci_id_match *const devices = drvp->supported_devices;
+    int j;
+    struct pci_device *pPci;
+    struct pci_device_iterator *iter;
+    int numFound = 0;
+
+    iter = pci_id_match_iterator_create(NULL);
+    while ((pPci = pci_device_next(iter)) != NULL) {
+        /* Determine if this device is supported by the driver.  If it is,
+         * add it to the list of devices to configure.
+         */
+        for (j = 0; !END_OF_MATCHES(devices[j]); j++) {
+            if (PCI_ID_COMPARE(devices[j].vendor_id, pPci->vendor_id)
+                && PCI_ID_COMPARE(devices[j].device_id, pPci->device_id)
+                && ((devices[j].device_class_mask & pPci->device_class)
+                    == devices[j].device_class)) {
+                if (xf86CheckPciSlot(pPci)) {
+                    GDevPtr pGDev =
+                        xf86AddBusDeviceToConfigure(drvp->driverName, BUS_PCI,
+                                                    pPci, -1);
+                    if (pGDev != NULL) {
+                        /* After configure pass 1, chipID and chipRev are
+                         * treated as over-rides, so clobber them here.
+                         */
+                        pGDev->chipID = -1;
+                        pGDev->chipRev = -1;
+                    }
+
+                    numFound++;
+                }
+
+                break;
+            }
+        }
+    }
+
+    pci_iterator_destroy(iter);
+
+    return numFound != 0;
+}
+
+Bool
+xf86PciProbeDev(DriverPtr drvp)
+{
+    int i, j;
+    struct pci_device *pPci;
+    Bool foundScreen = FALSE;
+    const struct pci_id_match *const devices = drvp->supported_devices;
+    GDevPtr *devList;
+    const unsigned numDevs = xf86MatchDevice(drvp->driverName, &devList);
+
+    for (i = 0; i < numDevs; i++) {
+        struct pci_device_iterator *iter;
+        unsigned device_id;
+
+        /* Find the pciVideoRec associated with this device section.
+         */
+        iter = pci_id_match_iterator_create(NULL);
+        while ((pPci = pci_device_next(iter)) != NULL) {
+            if (devList[i]->busID && *devList[i]->busID) {
+                if (xf86ComparePciBusString(devList[i]->busID,
+                                            ((pPci->domain << 8)
+                                             | pPci->bus),
+                                            pPci->dev, pPci->func)) {
+                    break;
+                }
+            }
+            else if (xf86IsPrimaryPci(pPci)) {
+                break;
+            }
+        }
+
+        pci_iterator_destroy(iter);
+
+        if (pPci == NULL) {
+            continue;
+        }
+        device_id = (devList[i]->chipID > 0)
+            ? devList[i]->chipID : pPci->device_id;
+
+        /* Once the pciVideoRec is found, determine if the device is supported
+         * by the driver.  If it is, probe it!
+         */
+        for (j = 0; !END_OF_MATCHES(devices[j]); j++) {
+            if (PCI_ID_COMPARE(devices[j].vendor_id, pPci->vendor_id)
+                && PCI_ID_COMPARE(devices[j].device_id, device_id)
+                && ((devices[j].device_class_mask & pPci->device_class)
+                    == devices[j].device_class)) {
+                int entry;
+
+                /* Allow the same entity to be used more than once for
+                 * devices with multiple screens per entity.  This assumes
+                 * implicitly that there will be a screen == 0 instance.
+                 *
+                 * FIXME Need to make sure that two different drivers don't
+                 * FIXME claim the same screen > 0 instance.
+                 */
+                if ((devList[i]->screen == 0) && !xf86CheckPciSlot(pPci))
+                    continue;
+
+                DebugF("%s: card at %d:%d:%d is claimed by a Device section\n",
+                       drvp->driverName, pPci->bus, pPci->dev, pPci->func);
+
+                /* Allocate an entry in the lists to be returned */
+                entry = xf86ClaimPciSlot(pPci, drvp, device_id,
+                                         devList[i], devList[i]->active);
+
+                if ((entry == -1) && (devList[i]->screen > 0)) {
+                    unsigned k;
+
+                    for (k = 0; k < xf86NumEntities; k++) {
+                        EntityPtr pEnt = xf86Entities[k];
+
+                        if (pEnt->bus.type != BUS_PCI)
+                            continue;
+                        if (pEnt->bus.id.pci == pPci) {
+                            entry = k;
+                            xf86AddDevToEntity(k, devList[i]);
+                            break;
+                        }
+                    }
+                }
+
+                if (entry != -1) {
+                    if ((*drvp->PciProbe) (drvp, entry, pPci,
+                                           devices[j].match_data)) {
+                        foundScreen = TRUE;
+                    }
+                    else
+                        xf86UnclaimPciSlot(pPci, devList[i]);
+                }
+
+                break;
+            }
+        }
+    }
+    free(devList);
+
+    return foundScreen;
+}
+
+void
+xf86PciIsolateDevice(const char *argument)
+{
+    int bus, device, func;
+
+    if (sscanf(argument, "PCI:%d:%d:%d", &bus, &device, &func) == 3) {
+        xf86IsolateDevice.domain = PCI_DOM_FROM_BUS(bus);
+        xf86IsolateDevice.bus = PCI_BUS_NO_DOMAIN(bus);
+        xf86IsolateDevice.dev = device;
+        xf86IsolateDevice.func = func;
+    }
+    else
+        FatalError("Invalid isolated device specification\n");
+}
+
+static Bool
+pciDeviceHasBars(struct pci_device *pci)
+{
+    int i;
+
+    for (i = 0; i < 6; i++)
+        if (pci->regions[i].size)
+            return TRUE;
+
+    if (pci->rom_size)
+        return TRUE;
+
+    return FALSE;
+}
+
+struct Inst {
+    struct pci_device *pci;
+    GDevPtr dev;
+    Bool foundHW;               /* PCIid in list of supported chipsets */
+    Bool claimed;               /* BusID matches with a device section */
+    int chip;
+    int screen;
+};
+
+/**
+ * Find set of unclaimed devices matching a given vendor ID.
+ *
+ * Used by drivers to find as yet unclaimed devices matching the specified
+ * vendor ID.
+ *
+ * \param driverName     Name of the driver.  This is used to find Device
+ *                       sections in the config file.
+ * \param vendorID       PCI vendor ID of associated devices.  If zero, then
+ *                       the true vendor ID must be encoded in the \c PCIid
+ *                       fields of the \c PCIchipsets entries.
+ * \param chipsets       Symbol table used to associate chipset names with
+ *                       PCI IDs.
+ * \param devList        List of Device sections parsed from the config file.
+ * \param numDevs        Number of entries in \c devList.
+ * \param drvp           Pointer the driver's control structure.
+ * \param foundEntities  Returned list of entity indices associated with the
+ *                       driver.
+ *
+ * \returns
+ * The number of elements in returned in \c foundEntities on success or zero
+ * on failure.
+ *
+ * \todo
+ * This function does a bit more than short description says.  Fill in some
+ * more of the details of its operation.
+ *
+ * \todo
+ * The \c driverName parameter is redundant.  It is the same as
+ * \c DriverRec::driverName.  In a future version of this function, remove
+ * that parameter.
+ */
+int
+xf86MatchPciInstances(const char *driverName, int vendorID,
+                      SymTabPtr chipsets, PciChipsets * PCIchipsets,
+                      GDevPtr * devList, int numDevs, DriverPtr drvp,
+                      int **foundEntities)
+{
+    int i, j;
+    struct pci_device *pPci;
+    struct pci_device_iterator *iter;
+    struct Inst *instances = NULL;
+    int numClaimedInstances = 0;
+    int allocatedInstances = 0;
+    int numFound = 0;
+    SymTabRec *c;
+    PciChipsets *id;
+    int *retEntities = NULL;
+
+    *foundEntities = NULL;
+
+    /* Each PCI device will contribute at least one entry.  Each device
+     * section can contribute at most one entry.  The sum of the two is
+     * guaranteed to be larger than the maximum possible number of entries.
+     * Do this calculation and memory allocation once now to eliminate the
+     * need for realloc calls inside the loop.
+     */
+    if (!(xf86DoConfigure && xf86DoConfigurePass1)) {
+        unsigned max_entries = numDevs;
+
+        iter = pci_slot_match_iterator_create(NULL);
+        while ((pPci = pci_device_next(iter)) != NULL) {
+            max_entries++;
+        }
+
+        pci_iterator_destroy(iter);
+        instances = xnfallocarray(max_entries, sizeof(struct Inst));
+    }
+
+    iter = pci_slot_match_iterator_create(NULL);
+    while ((pPci = pci_device_next(iter)) != NULL) {
+        unsigned device_class = pPci->device_class;
+        Bool foundVendor = FALSE;
+
+        /* Convert the pre-PCI 2.0 device class for a VGA adapter to the
+         * 2.0 version of the same class.
+         */
+        if (device_class == 0x00000101) {
+            device_class = 0x00030000;
+        }
+
+        /* Find PCI devices that match the given vendor ID.  The vendor ID is
+         * either specified explicitly as a parameter to the function or
+         * implicitly encoded in the high bits of id->PCIid.
+         *
+         * The first device with a matching vendor is recorded, even if the
+         * device ID doesn't match.  This is done because the Device section
+         * in the xorg.conf file can over-ride the device ID.  A matching PCI
+         * ID might not be found now, but after the device ID over-ride is
+         * applied there /might/ be a match.
+         */
+        for (id = PCIchipsets; id->PCIid != -1; id++) {
+            const unsigned vendor_id = ((id->PCIid & 0xFFFF0000) >> 16)
+                | vendorID;
+            const unsigned device_id = (id->PCIid & 0x0000FFFF);
+            const unsigned match_class = 0x00030000 | id->PCIid;
+
+            if ((vendor_id == pPci->vendor_id)
+                || ((vendorID == PCI_VENDOR_GENERIC) &&
+                    (match_class == device_class))) {
+                if (!foundVendor && (instances != NULL)) {
+                    ++allocatedInstances;
+                    instances[allocatedInstances - 1].pci = pPci;
+                    instances[allocatedInstances - 1].dev = NULL;
+                    instances[allocatedInstances - 1].claimed = FALSE;
+                    instances[allocatedInstances - 1].foundHW = FALSE;
+                    instances[allocatedInstances - 1].screen = 0;
+                }
+
+                foundVendor = TRUE;
+
+                if ((device_id == pPci->device_id)
+                    || ((vendorID == PCI_VENDOR_GENERIC)
+                        && (match_class == device_class))) {
+                    if (instances != NULL) {
+                        instances[allocatedInstances - 1].foundHW = TRUE;
+                        instances[allocatedInstances - 1].chip = id->numChipset;
+                    }
+
+                    if (xf86DoConfigure && xf86DoConfigurePass1) {
+                        if (xf86CheckPciSlot(pPci)) {
+                            GDevPtr pGDev =
+                                xf86AddBusDeviceToConfigure(drvp->driverName,
+                                                            BUS_PCI, pPci, -1);
+
+                            if (pGDev) {
+                                /* After configure pass 1, chipID and chipRev
+                                 * are treated as over-rides, so clobber them
+                                 * here.
+                                 */
+                                pGDev->chipID = -1;
+                                pGDev->chipRev = -1;
+                            }
+
+                            numFound++;
+                        }
+                    }
+                    else {
+                        numFound++;
+                    }
+
+                    break;
+                }
+            }
+        }
+    }
+
+    pci_iterator_destroy(iter);
+
+    /* In "probe only" or "configure" mode (signaled by instances being NULL),
+     * our work is done.  Return the number of detected devices.
+     */
+    if (instances == NULL) {
+        return numFound;
+    }
+
+    /*
+     * This may be debatable, but if no PCI devices with a matching vendor
+     * type is found, return zero now.  It is probably not desirable to
+     * allow the config file to override this.
+     */
+    if (allocatedInstances <= 0) {
+        free(instances);
+        return 0;
+    }
+
+    DebugF("%s instances found: %d\n", driverName, allocatedInstances);
+
+    /*
+     * Check for devices that need duplicated instances.  This is required
+     * when there is more than one screen per entity.
+     *
+     * XXX This currently doesn't work for cases where the BusID isn't
+     * specified explicitly in the config file.
+     */
+
+    for (j = 0; j < numDevs; j++) {
+        if (devList[j]->screen > 0 && devList[j]->busID && *devList[j]->busID) {
+            for (i = 0; i < allocatedInstances; i++) {
+                pPci = instances[i].pci;
+                if (xf86ComparePciBusString(devList[j]->busID,
+                                            PCI_MAKE_BUS(pPci->domain,
+                                                         pPci->bus), pPci->dev,
+                                            pPci->func)) {
+                    allocatedInstances++;
+                    instances[allocatedInstances - 1] = instances[i];
+                    instances[allocatedInstances - 1].screen =
+                        devList[j]->screen;
+                    numFound++;
+                    break;
+                }
+            }
+        }
+    }
+
+    for (i = 0; i < allocatedInstances; i++) {
+        GDevPtr dev = NULL;
+        GDevPtr devBus = NULL;
+
+        pPci = instances[i].pci;
+        for (j = 0; j < numDevs; j++) {
+            if (devList[j]->busID && *devList[j]->busID) {
+                if (xf86ComparePciBusString(devList[j]->busID,
+                                            PCI_MAKE_BUS(pPci->domain,
+                                                         pPci->bus), pPci->dev,
+                                            pPci->func) &&
+                    devList[j]->screen == instances[i].screen) {
+
+                    if (devBus)
+                        xf86MsgVerb(X_WARNING, 0,
+                                    "%s: More than one matching Device section for "
+                                    "instances\n\t(BusID: %s) found: %s\n",
+                                    driverName, devList[j]->busID,
+                                    devList[j]->identifier);
+                    else
+                        devBus = devList[j];
+                }
+            }
+            else {
+                /*
+                 * if device section without BusID is found
+                 * only assign to it to the primary device.
+                 */
+                if (xf86IsPrimaryPci(pPci)) {
+                    xf86Msg(X_PROBED, "Assigning device section with no busID"
+                            " to primary device\n");
+                    if (dev || devBus)
+                        xf86MsgVerb(X_WARNING, 0,
+                                    "%s: More than one matching Device section "
+                                    "found: %s\n", driverName,
+                                    devList[j]->identifier);
+                    else
+                        dev = devList[j];
+                }
+            }
+        }
+        if (devBus)
+            dev = devBus;       /* busID preferred */
+        if (!dev) {
+            if (xf86CheckPciSlot(pPci) && pciDeviceHasBars(pPci)) {
+                xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section "
+                            "for instance (BusID PCI:%u@%u:%u:%u) found\n",
+                            driverName, pPci->bus, pPci->domain, pPci->dev,
+                            pPci->func);
+            }
+        }
+        else {
+            numClaimedInstances++;
+            instances[i].claimed = TRUE;
+            instances[i].dev = dev;
+        }
+    }
+    DebugF("%s instances found: %d\n", driverName, numClaimedInstances);
+    /*
+     * Now check that a chipset or chipID override in the device section
+     * is valid.  Chipset has precedence over chipID.
+     * If chipset is not valid ignore BusSlot completely.
+     */
+    for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) {
+        MessageType from = X_PROBED;
+
+        if (!instances[i].claimed) {
+            continue;
+        }
+        if (instances[i].dev->chipset) {
+            for (c = chipsets; c->token >= 0; c++) {
+                if (xf86NameCmp(c->name, instances[i].dev->chipset) == 0)
+                    break;
+            }
+            if (c->token == -1) {
+                instances[i].claimed = FALSE;
+                numClaimedInstances--;
+                xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device "
+                            "section \"%s\" isn't valid for this driver\n",
+                            driverName, instances[i].dev->chipset,
+                            instances[i].dev->identifier);
+            }
+            else {
+                instances[i].chip = c->token;
+
+                for (id = PCIchipsets; id->numChipset >= 0; id++) {
+                    if (id->numChipset == instances[i].chip)
+                        break;
+                }
+                if (id->numChipset >= 0) {
+                    xf86Msg(X_CONFIG, "Chipset override: %s\n",
+                            instances[i].dev->chipset);
+                    from = X_CONFIG;
+                }
+                else {
+                    instances[i].claimed = FALSE;
+                    numClaimedInstances--;
+                    xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device "
+                                "section \"%s\" isn't a valid PCI chipset\n",
+                                driverName, instances[i].dev->chipset,
+                                instances[i].dev->identifier);
+                }
+            }
+        }
+        else if (instances[i].dev->chipID > 0) {
+            for (id = PCIchipsets; id->numChipset >= 0; id++) {
+                if (id->PCIid == instances[i].dev->chipID)
+                    break;
+            }
+            if (id->numChipset == -1) {
+                instances[i].claimed = FALSE;
+                numClaimedInstances--;
+                xf86MsgVerb(X_WARNING, 0, "%s: ChipID 0x%04X in Device "
+                            "section \"%s\" isn't valid for this driver\n",
+                            driverName, instances[i].dev->chipID,
+                            instances[i].dev->identifier);
+            }
+            else {
+                instances[i].chip = id->numChipset;
+
+                xf86Msg(X_CONFIG, "ChipID override: 0x%04X\n",
+                        instances[i].dev->chipID);
+                from = X_CONFIG;
+            }
+        }
+        else if (!instances[i].foundHW) {
+            /*
+             * This means that there was no override and the PCI chipType
+             * doesn't match one that is supported
+             */
+            instances[i].claimed = FALSE;
+            numClaimedInstances--;
+        }
+        if (instances[i].claimed == TRUE) {
+            for (c = chipsets; c->token >= 0; c++) {
+                if (c->token == instances[i].chip)
+                    break;
+            }
+            xf86Msg(from, "Chipset %s found\n", c->name);
+        }
+    }
+
+    /*
+     * Of the claimed instances, check that another driver hasn't already
+     * claimed its slot.
+     */
+    numFound = 0;
+    for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) {
+        if (!instances[i].claimed)
+            continue;
+        pPci = instances[i].pci;
+
+        /*
+         * Allow the same entity to be used more than once for devices with
+         * multiple screens per entity.  This assumes implicitly that there
+         * will be a screen == 0 instance.
+         *
+         * XXX Need to make sure that two different drivers don't claim
+         * the same screen > 0 instance.
+         */
+        if (instances[i].screen == 0 && !xf86CheckPciSlot(pPci))
+            continue;
+
+        DebugF("%s: card at %d:%d:%d is claimed by a Device section\n",
+               driverName, pPci->bus, pPci->dev, pPci->func);
+
+        /* Allocate an entry in the lists to be returned */
+        numFound++;
+        retEntities = xnfreallocarray(retEntities, numFound, sizeof(int));
+        retEntities[numFound - 1] = xf86ClaimPciSlot(pPci, drvp,
+                                                     instances[i].chip,
+                                                     instances[i].dev,
+                                                     instances[i].dev->active);
+        if (retEntities[numFound - 1] == -1 && instances[i].screen > 0) {
+            for (j = 0; j < xf86NumEntities; j++) {
+                EntityPtr pEnt = xf86Entities[j];
+
+                if (pEnt->bus.type != BUS_PCI)
+                    continue;
+                if (pEnt->bus.id.pci == pPci) {
+                    retEntities[numFound - 1] = j;
+                    xf86AddDevToEntity(j, instances[i].dev);
+                    break;
+                }
+            }
+        }
+    }
+    free(instances);
+    if (numFound > 0) {
+        *foundEntities = retEntities;
+    }
+
+    return numFound;
+}
+
+/*
+ * xf86ConfigPciEntityInactive() -- This function can be used
+ * to configure an inactive entity as well as to reconfigure an
+ * previously active entity inactive. If the entity has been
+ * assigned to a screen before it will be removed. If p_chip is
+ * non-NULL all static resources listed there will be registered.
+ */
+static void
+xf86ConfigPciEntityInactive(EntityInfoPtr pEnt, PciChipsets * p_chip,
+                            EntityProc init, EntityProc enter,
+                            EntityProc leave, void *private)
+{
+    ScrnInfoPtr pScrn;
+
+    if ((pScrn = xf86FindScreenForEntity(pEnt->index)))
+        xf86RemoveEntityFromScreen(pScrn, pEnt->index);
+}
+
+ScrnInfoPtr
+xf86ConfigPciEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex,
+                    PciChipsets * p_chip, void *dummy, EntityProc init,
+                    EntityProc enter, EntityProc leave, void *private)
+{
+    EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
+
+    if (dummy || init || enter || leave)
+        FatalError("Legacy entity access functions are unsupported\n");
+
+    if (!pEnt)
+        return pScrn;
+
+    if (!(pEnt->location.type == BUS_PCI)
+        || !xf86GetPciInfoForEntity(entityIndex)) {
+        free(pEnt);
+        return pScrn;
+    }
+    if (!pEnt->active) {
+        xf86ConfigPciEntityInactive(pEnt, p_chip, init, enter, leave, private);
+        free(pEnt);
+        return pScrn;
+    }
+
+    if (!pScrn)
+        pScrn = xf86AllocateScreen(pEnt->driver, scrnFlag);
+    if (xf86IsEntitySharable(entityIndex)) {
+        xf86SetEntityShared(entityIndex);
+    }
+    xf86AddEntityToScreen(pScrn, entityIndex);
+    if (xf86IsEntityShared(entityIndex)) {
+        return pScrn;
+    }
+    free(pEnt);
+
+    return pScrn;
+}
+
+void
+xf86VideoPtrToDriverList(struct pci_device *dev, XF86MatchedDrivers *md)
+{
+    int i;
+
+    /* Add more entries here if we ever return more than 4 drivers for
+       any device */
+    const char *driverList[5] = { NULL, NULL, NULL, NULL, NULL };
+
+    switch (dev->vendor_id) {
+        /* AMD Geode LX */
+    case 0x1022:
+        if (dev->device_id == 0x2081)
+            driverList[0] = "geode";
+        break;
+        /* older Geode products acquired by AMD still carry an NSC vendor_id */
+    case 0x100b:
+        if (dev->device_id == 0x0030) {
+            /* NSC Geode GX2 specifically */
+            driverList[0] = "geode";
+            /* GX2 support started its life in the NSC tree and was later
+               forked by AMD for GEODE so we keep it as a backup */
+            driverList[1] = "nsc";
+        }
+        else
+            /* other NSC variant e.g. 0x0104 (SC1400), 0x0504 (SCx200) */
+            driverList[0] = "nsc";
+        break;
+        /* Cyrix Geode GX1 */
+    case 0x1078:
+        if (dev->device_id == 0x0104)
+            driverList[0] = "cyrix";
+        break;
+    case 0x1142:
+        driverList[0] = "apm";
+        break;
+    case 0xedd8:
+        driverList[0] = "ark";
+        break;
+    case 0x1a03:
+        driverList[0] = "ast";
+        break;
+    case 0x1002:
+        driverList[0] = "ati";
+        break;
+    case 0x102c:
+        driverList[0] = "chips";
+        break;
+    case 0x1013:
+        driverList[0] = "cirrus";
+        break;
+    case 0x3d3d:
+        driverList[0] = "glint";
+        break;
+    case 0x105d:
+        driverList[0] = "i128";
+        break;
+    case 0x8086:
+	switch (dev->device_id)
+	{
+		/* Intel i740 */
+		case 0x00d1:
+		case 0x7800:
+			driverList[0] = "i740";
+			break;
+		/* GMA500/Poulsbo */
+		case 0x8108:
+		case 0x8109:
+			/* Try psb driver on Poulsbo - if available */
+			driverList[0] = "psb";
+			driverList[1] = "psb_drv";
+			break;
+		/* GMA600/Oaktrail */
+		case 0x4100:
+		case 0x4101:
+		case 0x4102:
+		case 0x4103:
+		case 0x4104:
+		case 0x4105:
+		case 0x4106:
+		case 0x4107:
+		/* Atom E620/Oaktrail */
+		case 0x4108:
+		/* Medfield */
+		case 0x0130:
+		case 0x0131:
+		case 0x0132:
+		case 0x0133:
+		case 0x0134:
+		case 0x0135:
+		case 0x0136:
+		case 0x0137:
+		/* GMA 3600/CDV */
+		case 0x0be0:
+		case 0x0be1:
+		case 0x0be2:
+		case 0x0be3:
+		case 0x0be4:
+		case 0x0be5:
+		case 0x0be6:
+		case 0x0be7:
+		case 0x0be8:
+		case 0x0be9:
+		case 0x0bea:
+		case 0x0beb:
+		case 0x0bec:
+		case 0x0bed:
+		case 0x0bee:
+		case 0x0bef:
+			/* Use fbdev/vesa driver on Oaktrail, Medfield, CDV */
+			break;
+		default:
+			driverList[0] = "intel";
+			break;
+        }
+        break;
+    case 0x102b:
+        driverList[0] = "mga";
+        break;
+    case 0x10c8:
+        driverList[0] = "neomagic";
+        break;
+    case 0x10de:
+    case 0x12d2:
+    {
+        int idx = 0;
+
+#if defined(__linux__) || defined(__NetBSD__)
+        char busid[32];
+        int fd;
+
+        snprintf(busid, sizeof(busid), "pci:%04x:%02x:%02x.%d",
+                 dev->domain, dev->bus, dev->dev, dev->func);
+
+       /* 'modesetting' is preferred for GeForce 8 and newer GPUs */
+        fd = drmOpenWithType("nouveau", busid, DRM_NODE_RENDER);
+        if (fd >= 0) {
+            uint64_t args[] = { 11 /* NOUVEAU_GETPARAM_CHIPSET_ID */, 0 };
+            int ret = drmCommandWriteRead(fd, 0 /* DRM_NOUVEAU_GETPARAM */,
+                                          &args, sizeof(args));
+            drmClose(fd);
+            if (ret == 0) {
+                if (args[1] == 0x050 || args[1] >= 0x80)
+                    break;
+            }
+        }
+
+        driverList[idx++] = "nouveau";
+#endif
+        driverList[idx++] = "nv";
+        break;
+    }
+    case 0x1106:
+        driverList[0] = "openchrome";
+        break;
+    case 0x1b36:
+        driverList[0] = "qxl";
+        break;
+    case 0x1163:
+        driverList[0] = "rendition";
+        break;
+    case 0x5333:
+        switch (dev->device_id) {
+        case 0x88d0:
+        case 0x88d1:
+        case 0x88f0:
+        case 0x8811:
+        case 0x8812:
+        case 0x8814:
+        case 0x8901:
+            driverList[0] = "s3";
+            break;
+        case 0x5631:
+        case 0x883d:
+        case 0x8a01:
+        case 0x8a10:
+        case 0x8c01:
+        case 0x8c03:
+        case 0x8904:
+        case 0x8a13:
+            driverList[0] = "s3virge";
+            break;
+        default:
+            driverList[0] = "savage";
+            break;
+        }
+        break;
+    case 0x1039:
+        driverList[0] = "sis";
+        break;
+    case 0x126f:
+        driverList[0] = "siliconmotion";
+        break;
+    case 0x121a:
+        if (dev->device_id < 0x0003)
+            driverList[0] = "voodoo";
+        else
+            driverList[0] = "tdfx";
+        break;
+    case 0x1011:
+        driverList[0] = "tga";
+        break;
+    case 0x1023:
+        driverList[0] = "trident";
+        break;
+    case 0x100c:
+        driverList[0] = "tseng";
+        break;
+    case 0x80ee:
+        driverList[0] = "vboxvideo";
+        break;
+    case 0x15ad:
+        driverList[0] = "vmware";
+        break;
+    case 0x18ca:
+        if (dev->device_id == 0x47)
+            driverList[0] = "xgixp";
+        else
+            driverList[0] = "xgi";
+        break;
+    default:
+        break;
+    }
+    for (i = 0; driverList[i] != NULL; i++) {
+        xf86AddMatchedDriver(md, driverList[i]);
+    }
+}
+
+#ifdef __linux__
+static int
+xchomp(char *line)
+{
+    size_t len = 0;
+
+    if (!line) {
+        return 1;
+    }
+
+    len = strlen(line);
+    if (line[len - 1] == '\n' && len > 0) {
+        line[len - 1] = '\0';
+    }
+    return 0;
+}
+
+/* This function is used to provide a workaround for binary drivers that
+ * don't export their PCI ID's properly. If distros don't end up using this
+ * feature it can and should be removed because the symbol-based resolution
+ * scheme should be the primary one */
+void
+xf86MatchDriverFromFiles(uint16_t match_vendor, uint16_t match_chip,
+                         XF86MatchedDrivers *md)
+{
+    DIR *idsdir;
+    FILE *fp;
+    struct dirent *direntry;
+    char *line = NULL, *tmpMatch;
+    size_t len;
+    ssize_t read;
+    char path_name[512], vendor_str[5], chip_str[5];
+    uint16_t vendor, chip;
+    int j;
+
+    idsdir = opendir(PCI_TXT_IDS_PATH);
+    if (!idsdir)
+        return;
+
+    xf86Msg(X_INFO,
+            "Scanning %s directory for additional PCI ID's supported by the drivers\n",
+            PCI_TXT_IDS_PATH);
+    direntry = readdir(idsdir);
+    /* Read the directory */
+    while (direntry) {
+        if (direntry->d_name[0] == '.') {
+            direntry = readdir(idsdir);
+            continue;
+        }
+        len = strlen(direntry->d_name);
+        /* A tiny bit of sanity checking. We should probably do better */
+        if (strncmp(&(direntry->d_name[len - 4]), ".ids", 4) == 0) {
+            /* We need the full path name to open the file */
+            snprintf(path_name, sizeof(path_name), "%s/%s",
+                     PCI_TXT_IDS_PATH, direntry->d_name);
+            fp = fopen(path_name, "r");
+            if (fp == NULL) {
+                xf86Msg(X_ERROR, "Could not open %s for reading. Exiting.\n",
+                        path_name);
+                goto end;
+            }
+            /* Read the file */
+#ifdef __GLIBC__
+            while ((read = getline(&line, &len, fp)) != -1) {
+#else
+            while ((line = fgetln(fp, &len)) != (char *) NULL) {
+#endif                          /* __GLIBC __ */
+                xchomp(line);
+                if (isdigit(line[0])) {
+                    strlcpy(vendor_str, line, sizeof(vendor_str));
+                    vendor = (int) strtol(vendor_str, NULL, 16);
+                    if ((strlen(&line[4])) == 0) {
+                        chip_str[0] = '\0';
+                        chip = -1;
+                    }
+                    else {
+                        /* Handle trailing whitespace */
+                        if (isspace(line[4])) {
+                            chip_str[0] = '\0';
+                            chip = -1;
+                        }
+                        else {
+                            /* Ok, it's a real ID */
+                            strlcpy(chip_str, &line[4], sizeof(chip_str));
+                            chip = (int) strtol(chip_str, NULL, 16);
+                        }
+                    }
+                    if (vendor == match_vendor && chip == match_chip) {
+                        tmpMatch =
+                            (char *) malloc(sizeof(char) *
+                                            strlen(direntry->d_name) - 3);
+                        if (!tmpMatch) {
+                            xf86Msg(X_ERROR,
+                                    "Could not allocate space for the module name. Exiting.\n");
+                            goto end;
+                        }
+                        /* hack off the .ids suffix. This should guard
+                         * against other problems, but it will end up
+                         * taking off anything after the first '.' */
+                        for (j = 0; j < (strlen(direntry->d_name) - 3); j++) {
+                            if (direntry->d_name[j] == '.') {
+                                tmpMatch[j] = '\0';
+                                break;
+                            }
+                            else {
+                                tmpMatch[j] = direntry->d_name[j];
+                            }
+                        }
+                        xf86AddMatchedDriver(md, tmpMatch);
+                        xf86Msg(X_INFO, "Matched %s from file name %s\n",
+                                tmpMatch, direntry->d_name);
+                        free(tmpMatch);
+                    }
+                }
+                else {
+                    /* TODO Handle driver overrides here */
+                }
+            }
+            fclose(fp);
+        }
+        direntry = readdir(idsdir);
+    }
+ end:
+    free(line);
+    closedir(idsdir);
+}
+#endif                          /* __linux__ */
+
+void
+xf86PciMatchDriver(XF86MatchedDrivers *md)
+{
+    struct pci_device *info = NULL;
+    struct pci_device_iterator *iter;
+
+    /* Find the primary device, and get some information about it. */
+    iter = pci_slot_match_iterator_create(NULL);
+    while ((info = pci_device_next(iter)) != NULL) {
+        if (xf86IsPrimaryPci(info)) {
+            break;
+        }
+    }
+
+    pci_iterator_destroy(iter);
+#ifdef __linux__
+    if (info)
+        xf86MatchDriverFromFiles(info->vendor_id, info->device_id, md);
+#endif
+
+    if (info != NULL) {
+        xf86VideoPtrToDriverList(info, md);
+    }
+}
+
+Bool
+xf86PciConfigure(void *busData, struct pci_device *pDev)
+{
+    struct pci_device *pVideo = NULL;
+
+    pVideo = (struct pci_device *) busData;
+    if (pDev &&
+        (pDev->domain == pVideo->domain) &&
+        (pDev->bus == pVideo->bus) &&
+        (pDev->dev == pVideo->dev) && (pDev->func == pVideo->func))
+        return 0;
+
+    return 1;
+}
+
+void
+xf86PciConfigureNewDev(void *busData, struct pci_device *pVideo,
+                       GDevRec * GDev, int *chipset)
+{
+    char busnum[8];
+    char *tmp;
+
+    pVideo = (struct pci_device *) busData;
+
+    snprintf(busnum, sizeof(busnum), "%d", pVideo->bus);
+
+    XNFasprintf(&tmp, "PCI:%s:%d:%d",
+                busnum, pVideo->dev, pVideo->func);
+    GDev->busID = tmp;
+
+    GDev->chipID = pVideo->device_id;
+    GDev->chipRev = pVideo->revision;
+
+    if (*chipset < 0)
+        *chipset = (pVideo->vendor_id << 16) | pVideo->device_id;
+}
+
+char *
+DRICreatePCIBusID(const struct pci_device *dev)
+{
+    char *busID;
+
+    if (asprintf(&busID, "pci:%04x:%02x:%02x.%d",
+                 dev->domain, dev->bus, dev->dev, dev->func) == -1)
+        return NULL;
+
+    return busID;
+}
Index: xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new/hw/xfree86/common
===================================================================
--- xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new/hw/xfree86/common	(nonexistent)
+++ xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new/hw/xfree86/common	(revision 5)

Property changes on: xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new/hw/xfree86/common
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new/hw/xfree86
===================================================================
--- xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new/hw/xfree86	(nonexistent)
+++ xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new/hw/xfree86	(revision 5)

Property changes on: xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new/hw/xfree86
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new/hw
===================================================================
--- xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new/hw	(nonexistent)
+++ xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new/hw	(revision 5)

Property changes on: xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new/hw
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new
===================================================================
--- xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new	(nonexistent)
+++ xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new	(revision 5)

Property changes on: xorg-server/create-21.1.7-modesetting-on-GeForce-patch/xorg-server-21.1.7-new
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-modesetting-on-GeForce-patch
===================================================================
--- xorg-server/create-21.1.7-modesetting-on-GeForce-patch	(nonexistent)
+++ xorg-server/create-21.1.7-modesetting-on-GeForce-patch	(revision 5)

Property changes on: xorg-server/create-21.1.7-modesetting-on-GeForce-patch
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-mouse-kbd-layout-patch/create.patch.sh
===================================================================
--- xorg-server/create-21.1.7-mouse-kbd-layout-patch/create.patch.sh	(nonexistent)
+++ xorg-server/create-21.1.7-mouse-kbd-layout-patch/create.patch.sh	(revision 5)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=21.1.7
+
+tar --files-from=file.list -xJvf ../xorg-server-$VERSION.tar.xz
+mv xorg-server-$VERSION xorg-server-$VERSION-orig
+
+cp -rf ./xorg-server-$VERSION-new ./xorg-server-$VERSION
+
+diff --unified -Nr  xorg-server-$VERSION-orig  xorg-server-$VERSION > xorg-server-$VERSION-mouse-kbd-layout.patch
+
+mv xorg-server-$VERSION-mouse-kbd-layout.patch ../patches
+
+rm -rf ./xorg-server-$VERSION
+rm -rf ./xorg-server-$VERSION-orig

Property changes on: xorg-server/create-21.1.7-mouse-kbd-layout-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xorg-server/create-21.1.7-mouse-kbd-layout-patch/file.list
===================================================================
--- xorg-server/create-21.1.7-mouse-kbd-layout-patch/file.list	(nonexistent)
+++ xorg-server/create-21.1.7-mouse-kbd-layout-patch/file.list	(revision 5)
@@ -0,0 +1,3 @@
+xorg-server-21.1.7/Xi/exevents.c
+xorg-server-21.1.7/dix/getevents.c
+xorg-server-21.1.7/include/inputstr.h
Index: xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/Xi/exevents.c
===================================================================
--- xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/Xi/exevents.c	(nonexistent)
+++ xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/Xi/exevents.c	(revision 5)
@@ -0,0 +1,3351 @@
+/************************************************************
+
+Copyright 1989, 1998  The Open Group
+
+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.
+
+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
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
+
+			All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Hewlett-Packard not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+********************************************************/
+
+/*
+ * Copyright © 2010 Collabora Ltd.
+ * Copyright © 2011 Red Hat, Inc.
+ *
+ * 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 (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Daniel Stone <daniel@fooishbar.org>
+ */
+
+/********************************************************************
+ *
+ *  Routines to register and initialize extension input devices.
+ *  This also contains ProcessOtherEvent, the routine called from DDX
+ *  to route extension events.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "inputstr.h"
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include <X11/extensions/XI2proto.h>
+#include <X11/extensions/geproto.h>
+#include "windowstr.h"
+#include "miscstruct.h"
+#include "region.h"
+#include "exevents.h"
+#include "extnsionst.h"
+#include "exglobals.h"
+#include "eventstr.h"
+#include "dixevents.h"          /* DeliverFocusedEvent */
+#include "dixgrabs.h"           /* CreateGrab() */
+#include "scrnintstr.h"
+#include "listdev.h"            /* for CopySwapXXXClass */
+#include "xace.h"
+#include "xiquerydevice.h"      /* For List*Info */
+#include "eventconvert.h"
+#include "eventstr.h"
+#include "inpututils.h"
+#include "mi.h"
+
+#include <X11/extensions/XKBproto.h>
+#include "xkbsrv.h"
+
+#define WID(w) ((w) ? ((w)->drawable.id) : 0)
+#define AllModifiersMask ( \
+	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
+	Mod3Mask | Mod4Mask | Mod5Mask )
+#define AllButtonsMask ( \
+	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
+
+Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
+                          Bool  /* ignoreSelectedEvents */
+    );
+static Bool MakeInputMasks(WindowPtr    /* pWin */
+    );
+
+/*
+ * Only let the given client know of core events which will affect its
+ * interpretation of input events, if the client's ClientPointer (or the
+ * paired keyboard) is the current device.
+ */
+int
+XIShouldNotify(ClientPtr client, DeviceIntPtr dev)
+{
+    DeviceIntPtr current_ptr = PickPointer(client);
+    DeviceIntPtr current_kbd = GetMaster(current_ptr, KEYBOARD_OR_FLOAT);
+
+    if (dev == current_kbd || dev == current_ptr)
+        return 1;
+
+    return 0;
+}
+
+Bool
+IsPointerEvent(InternalEvent *event)
+{
+    switch (event->any.type) {
+    case ET_ButtonPress:
+    case ET_ButtonRelease:
+    case ET_Motion:
+        /* XXX: enter/leave ?? */
+        return TRUE;
+    default:
+        break;
+    }
+    return FALSE;
+}
+
+Bool
+IsTouchEvent(InternalEvent *event)
+{
+    switch (event->any.type) {
+    case ET_TouchBegin:
+    case ET_TouchUpdate:
+    case ET_TouchEnd:
+        return TRUE;
+    default:
+        break;
+    }
+    return FALSE;
+}
+
+Bool
+IsGestureEvent(InternalEvent *event)
+{
+    switch (event->any.type) {
+    case ET_GesturePinchBegin:
+    case ET_GesturePinchUpdate:
+    case ET_GesturePinchEnd:
+    case ET_GestureSwipeBegin:
+    case ET_GestureSwipeUpdate:
+    case ET_GestureSwipeEnd:
+        return TRUE;
+    default:
+        break;
+    }
+    return FALSE;
+}
+
+Bool
+IsGestureBeginEvent(InternalEvent *event)
+{
+    switch (event->any.type) {
+    case ET_GesturePinchBegin:
+    case ET_GestureSwipeBegin:
+        return TRUE;
+    default:
+        break;
+    }
+    return FALSE;
+}
+
+Bool
+IsGestureEndEvent(InternalEvent *event)
+{
+    switch (event->any.type) {
+    case ET_GesturePinchEnd:
+    case ET_GestureSwipeEnd:
+        return TRUE;
+    default:
+        break;
+    }
+    return FALSE;
+}
+
+/**
+ * @return the device matching the deviceid of the device set in the event, or
+ * NULL if the event is not an XInput event.
+ */
+DeviceIntPtr
+XIGetDevice(xEvent *xE)
+{
+    DeviceIntPtr pDev = NULL;
+
+    if (xE->u.u.type == DeviceButtonPress ||
+        xE->u.u.type == DeviceButtonRelease ||
+        xE->u.u.type == DeviceMotionNotify ||
+        xE->u.u.type == ProximityIn ||
+        xE->u.u.type == ProximityOut || xE->u.u.type == DevicePropertyNotify) {
+        int rc;
+        int id;
+
+        id = ((deviceKeyButtonPointer *) xE)->deviceid & ~MORE_EVENTS;
+
+        rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
+        if (rc != Success)
+            ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
+    }
+    return pDev;
+}
+
+/**
+ * Copy the device->key into master->key and send a mapping notify to the
+ * clients if appropriate.
+ * master->key needs to be allocated by the caller.
+ *
+ * Device is the slave device. If it is attached to a master device, we may
+ * need to send a mapping notify to the client because it causes the MD
+ * to change state.
+ *
+ * Mapping notify needs to be sent in the following cases:
+ *      - different slave device on same master
+ *      - different master
+ *
+ * XXX: They way how the code is we also send a map notify if the slave device
+ * stays the same, but the master changes. This isn't really necessary though.
+ *
+ * XXX: this gives you funny behaviour with the ClientPointer. When a
+ * MappingNotify is sent to the client, the client usually responds with a
+ * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
+ * mapping, regardless of which keyboard sent the last mapping notify request.
+ * So depending on the CP setting, your keyboard may change layout in each
+ * app...
+ *
+ * This code is basically the old SwitchCoreKeyboard.
+ */
+
+void
+CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
+{
+    KeyClassPtr mk = master->key;
+
+    if (device == master)
+        return;
+
+    mk->sourceid = device->id;
+
+    if (!XkbDeviceApplyKeymap(master, device->key->xkbInfo->desc))
+        FatalError("Couldn't pivot keymap from device to core!\n");
+}
+
+/**
+ * Copies the feedback classes from device "from" into device "to". Classes
+ * are duplicated (not just flipping the pointers). All feedback classes are
+ * linked lists, the full list is duplicated.
+ */
+static void
+DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
+{
+    ClassesPtr classes;
+
+    if (from->intfeed) {
+        IntegerFeedbackPtr *i, it;
+
+        if (!to->intfeed) {
+            classes = to->unused_classes;
+            to->intfeed = classes->intfeed;
+            classes->intfeed = NULL;
+        }
+
+        i = &to->intfeed;
+        for (it = from->intfeed; it; it = it->next) {
+            if (!(*i)) {
+                *i = calloc(1, sizeof(IntegerFeedbackClassRec));
+                if (!(*i)) {
+                    ErrorF("[Xi] Cannot alloc memory for class copy.");
+                    return;
+                }
+            }
+            (*i)->CtrlProc = it->CtrlProc;
+            (*i)->ctrl = it->ctrl;
+
+            i = &(*i)->next;
+        }
+    }
+    else if (to->intfeed && !from->intfeed) {
+        classes = to->unused_classes;
+        classes->intfeed = to->intfeed;
+        to->intfeed = NULL;
+    }
+
+    if (from->stringfeed) {
+        StringFeedbackPtr *s, it;
+
+        if (!to->stringfeed) {
+            classes = to->unused_classes;
+            to->stringfeed = classes->stringfeed;
+            classes->stringfeed = NULL;
+        }
+
+        s = &to->stringfeed;
+        for (it = from->stringfeed; it; it = it->next) {
+            if (!(*s)) {
+                *s = calloc(1, sizeof(StringFeedbackClassRec));
+                if (!(*s)) {
+                    ErrorF("[Xi] Cannot alloc memory for class copy.");
+                    return;
+                }
+            }
+            (*s)->CtrlProc = it->CtrlProc;
+            (*s)->ctrl = it->ctrl;
+
+            s = &(*s)->next;
+        }
+    }
+    else if (to->stringfeed && !from->stringfeed) {
+        classes = to->unused_classes;
+        classes->stringfeed = to->stringfeed;
+        to->stringfeed = NULL;
+    }
+
+    if (from->bell) {
+        BellFeedbackPtr *b, it;
+
+        if (!to->bell) {
+            classes = to->unused_classes;
+            to->bell = classes->bell;
+            classes->bell = NULL;
+        }
+
+        b = &to->bell;
+        for (it = from->bell; it; it = it->next) {
+            if (!(*b)) {
+                *b = calloc(1, sizeof(BellFeedbackClassRec));
+                if (!(*b)) {
+                    ErrorF("[Xi] Cannot alloc memory for class copy.");
+                    return;
+                }
+            }
+            (*b)->BellProc = it->BellProc;
+            (*b)->CtrlProc = it->CtrlProc;
+            (*b)->ctrl = it->ctrl;
+
+            b = &(*b)->next;
+        }
+    }
+    else if (to->bell && !from->bell) {
+        classes = to->unused_classes;
+        classes->bell = to->bell;
+        to->bell = NULL;
+    }
+
+    if (from->leds) {
+        LedFeedbackPtr *l, it;
+
+        if (!to->leds) {
+            classes = to->unused_classes;
+            to->leds = classes->leds;
+            classes->leds = NULL;
+        }
+
+        l = &to->leds;
+        for (it = from->leds; it; it = it->next) {
+            if (!(*l)) {
+                *l = calloc(1, sizeof(LedFeedbackClassRec));
+                if (!(*l)) {
+                    ErrorF("[Xi] Cannot alloc memory for class copy.");
+                    return;
+                }
+            }
+            (*l)->CtrlProc = it->CtrlProc;
+            (*l)->ctrl = it->ctrl;
+            if ((*l)->xkb_sli)
+                XkbFreeSrvLedInfo((*l)->xkb_sli);
+            (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
+
+            l = &(*l)->next;
+        }
+    }
+    else if (to->leds && !from->leds) {
+        classes = to->unused_classes;
+        classes->leds = to->leds;
+        to->leds = NULL;
+    }
+}
+
+static void
+DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
+{
+    ClassesPtr classes;
+
+    /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
+     * kbdfeed to be set up properly, so let's do the feedback classes first.
+     */
+    if (from->kbdfeed) {
+        KbdFeedbackPtr *k, it;
+
+        if (!to->kbdfeed) {
+            classes = to->unused_classes;
+
+            to->kbdfeed = classes->kbdfeed;
+            if (!to->kbdfeed)
+                InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
+            classes->kbdfeed = NULL;
+        }
+
+        k = &to->kbdfeed;
+        for (it = from->kbdfeed; it; it = it->next) {
+            if (!(*k)) {
+                *k = calloc(1, sizeof(KbdFeedbackClassRec));
+                if (!*k) {
+                    ErrorF("[Xi] Cannot alloc memory for class copy.");
+                    return;
+                }
+            }
+            (*k)->BellProc = it->BellProc;
+            (*k)->CtrlProc = it->CtrlProc;
+            (*k)->ctrl = it->ctrl;
+            if ((*k)->xkb_sli)
+                XkbFreeSrvLedInfo((*k)->xkb_sli);
+            (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
+
+            k = &(*k)->next;
+        }
+    }
+    else if (to->kbdfeed && !from->kbdfeed) {
+        classes = to->unused_classes;
+        classes->kbdfeed = to->kbdfeed;
+        to->kbdfeed = NULL;
+    }
+
+    if (from->key) {
+        if (!to->key) {
+            classes = to->unused_classes;
+            to->key = classes->key;
+            if (!to->key)
+                InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
+            else
+                classes->key = NULL;
+        }
+
+        CopyKeyClass(from, to);
+    }
+    else if (to->key && !from->key) {
+        classes = to->unused_classes;
+        classes->key = to->key;
+        to->key = NULL;
+    }
+
+    /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
+     * pointer point into the xkbInfo->desc struct.  XkbCopySrvLedInfo
+     * didn't update the pointers so we need to do it manually here.
+     */
+    if (to->kbdfeed) {
+        KbdFeedbackPtr k;
+
+        for (k = to->kbdfeed; k; k = k->next) {
+            if (!k->xkb_sli)
+                continue;
+            if (k->xkb_sli->flags & XkbSLI_IsDefault) {
+                k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
+                k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
+            }
+        }
+    }
+
+    /* We can't just copy over the focus class. When an app sets the focus,
+     * it'll do so on the master device. Copying the SDs focus means losing
+     * the focus.
+     * So we only copy the focus class if the device didn't have one,
+     * otherwise we leave it as it is.
+     */
+    if (from->focus) {
+        if (!to->focus) {
+            WindowPtr *oldTrace;
+
+            classes = to->unused_classes;
+            to->focus = classes->focus;
+            if (!to->focus) {
+                to->focus = calloc(1, sizeof(FocusClassRec));
+                if (!to->focus)
+                    FatalError("[Xi] no memory for class shift.\n");
+            }
+            else
+                classes->focus = NULL;
+
+            oldTrace = to->focus->trace;
+            memcpy(to->focus, from->focus, sizeof(FocusClassRec));
+            to->focus->trace = reallocarray(oldTrace,
+                                            to->focus->traceSize,
+                                            sizeof(WindowPtr));
+            if (!to->focus->trace && to->focus->traceSize)
+                FatalError("[Xi] no memory for trace.\n");
+            memcpy(to->focus->trace, from->focus->trace,
+                   from->focus->traceSize * sizeof(WindowPtr));
+            to->focus->sourceid = from->id;
+        }
+    }
+    else if (to->focus) {
+        classes = to->unused_classes;
+        classes->focus = to->focus;
+        to->focus = NULL;
+    }
+
+}
+
+/* FIXME: this should really be shared with the InitValuatorAxisClassRec and
+ * similar */
+static void
+DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
+{
+    ClassesPtr classes;
+
+    /* Feedback classes must be copied first */
+    if (from->ptrfeed) {
+        PtrFeedbackPtr *p, it;
+
+        if (!to->ptrfeed) {
+            classes = to->unused_classes;
+            to->ptrfeed = classes->ptrfeed;
+            classes->ptrfeed = NULL;
+        }
+
+        p = &to->ptrfeed;
+        for (it = from->ptrfeed; it; it = it->next) {
+            if (!(*p)) {
+                *p = calloc(1, sizeof(PtrFeedbackClassRec));
+                if (!*p) {
+                    ErrorF("[Xi] Cannot alloc memory for class copy.");
+                    return;
+                }
+            }
+            (*p)->CtrlProc = it->CtrlProc;
+            (*p)->ctrl = it->ctrl;
+
+            p = &(*p)->next;
+        }
+    }
+    else if (to->ptrfeed && !from->ptrfeed) {
+        classes = to->unused_classes;
+        classes->ptrfeed = to->ptrfeed;
+        to->ptrfeed = NULL;
+    }
+
+    if (from->valuator) {
+        ValuatorClassPtr v;
+
+        if (!to->valuator) {
+            classes = to->unused_classes;
+            to->valuator = classes->valuator;
+            if (to->valuator)
+                classes->valuator = NULL;
+        }
+
+        v = AllocValuatorClass(to->valuator, from->valuator->numAxes);
+
+        if (!v)
+            FatalError("[Xi] no memory for class shift.\n");
+
+        to->valuator = v;
+        memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
+
+        v->sourceid = from->id;
+    }
+    else if (to->valuator && !from->valuator) {
+        classes = to->unused_classes;
+        classes->valuator = to->valuator;
+        to->valuator = NULL;
+    }
+
+    if (from->button) {
+        if (!to->button) {
+            classes = to->unused_classes;
+            to->button = classes->button;
+            if (!to->button) {
+                to->button = calloc(1, sizeof(ButtonClassRec));
+                if (!to->button)
+                    FatalError("[Xi] no memory for class shift.\n");
+            }
+            else
+                classes->button = NULL;
+        }
+
+        if (from->button->xkb_acts) {
+            if (!to->button->xkb_acts) {
+                to->button->xkb_acts = calloc(1, sizeof(XkbAction));
+                if (!to->button->xkb_acts)
+                    FatalError("[Xi] not enough memory for xkb_acts.\n");
+            }
+            memcpy(to->button->xkb_acts, from->button->xkb_acts,
+                   sizeof(XkbAction));
+        }
+        else {
+            free(to->button->xkb_acts);
+            to->button->xkb_acts = NULL;
+        }
+
+        memcpy(to->button->labels, from->button->labels,
+               from->button->numButtons * sizeof(Atom));
+        to->button->sourceid = from->id;
+    }
+    else if (to->button && !from->button) {
+        classes = to->unused_classes;
+        classes->button = to->button;
+        to->button = NULL;
+    }
+
+    if (from->proximity) {
+        if (!to->proximity) {
+            classes = to->unused_classes;
+            to->proximity = classes->proximity;
+            if (!to->proximity) {
+                to->proximity = calloc(1, sizeof(ProximityClassRec));
+                if (!to->proximity)
+                    FatalError("[Xi] no memory for class shift.\n");
+            }
+            else
+                classes->proximity = NULL;
+        }
+        memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
+        to->proximity->sourceid = from->id;
+    }
+    else if (to->proximity) {
+        classes = to->unused_classes;
+        classes->proximity = to->proximity;
+        to->proximity = NULL;
+    }
+
+    if (from->touch) {
+        TouchClassPtr t, f;
+
+        if (!to->touch) {
+            classes = to->unused_classes;
+            to->touch = classes->touch;
+            if (!to->touch) {
+                int i;
+
+                to->touch = calloc(1, sizeof(TouchClassRec));
+                if (!to->touch)
+                    FatalError("[Xi] no memory for class shift.\n");
+                to->touch->num_touches = from->touch->num_touches;
+                to->touch->touches = calloc(to->touch->num_touches,
+                                            sizeof(TouchPointInfoRec));
+                for (i = 0; i < to->touch->num_touches; i++)
+                    TouchInitTouchPoint(to->touch, to->valuator, i);
+                if (!to->touch)
+                    FatalError("[Xi] no memory for class shift.\n");
+            }
+            else
+                classes->touch = NULL;
+        }
+
+        t = to->touch;
+        f = from->touch;
+        t->sourceid = f->sourceid;
+        t->max_touches = f->max_touches;
+        t->mode = f->mode;
+        t->buttonsDown = f->buttonsDown;
+        t->state = f->state;
+        t->motionMask = f->motionMask;
+        /* to->touches and to->num_touches are separate on the master,
+         * don't copy */
+    }
+    /* Don't remove touch class if from->touch is non-existent. The to device
+     * may have an active touch grab, so we need to keep the touch class record
+     * around. */
+
+    if (from->gesture) {
+        if (!to->gesture) {
+            classes = to->unused_classes;
+            to->gesture = classes->gesture;
+            if (!to->gesture) {
+                if (!InitGestureClassDeviceStruct(to, from->gesture->max_touches))
+                    FatalError("[Xi] no memory for class shift.\n");
+            }
+            else
+                classes->gesture = NULL;
+        }
+
+        to->gesture->sourceid = from->gesture->sourceid;
+        /* to->gesture->gesture is separate on the master,  don't copy */
+    }
+    /* Don't remove gesture class if from->gesture is non-existent. The to device
+     * may have an active gesture grab, so we need to keep the gesture class record
+     * around. */
+}
+
+/**
+ * Copies the CONTENT of the classes of device from into the classes in device
+ * to. From and to are identical after finishing.
+ *
+ * If to does not have classes from currently has, the classes are stored in
+ * to's devPrivates system. Later, we recover it again from there if needed.
+ * Saves a few memory allocations.
+ */
+void
+DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to,
+                      DeviceChangedEvent *dce)
+{
+    input_lock();
+
+    /* generic feedback classes, not tied to pointer and/or keyboard */
+    DeepCopyFeedbackClasses(from, to);
+
+    if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
+        /* We need to copy to MASTER_KEYBOARD. Didn't worked with 'to'. */
+        DeepCopyKeyboardClasses(from, GetMaster(from, MASTER_KEYBOARD));
+    if ((dce->flags & DEVCHANGE_POINTER_EVENT))
+        DeepCopyPointerClasses(from, to);
+
+    input_unlock();
+}
+
+/**
+ * Send an XI2 DeviceChangedEvent to all interested clients.
+ */
+void
+XISendDeviceChangedEvent(DeviceIntPtr device, DeviceChangedEvent *dce)
+{
+    xXIDeviceChangedEvent *dcce;
+    int rc;
+
+    rc = EventToXI2((InternalEvent *) dce, (xEvent **) &dcce);
+    if (rc != Success) {
+        ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
+        return;
+    }
+
+    /* we don't actually swap if there's a NullClient, swapping is done
+     * later when event is delivered. */
+    SendEventToAllWindows(device, XI_DeviceChangedMask, (xEvent *) dcce, 1);
+    free(dcce);
+}
+
+static void
+ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
+{
+    DeviceIntPtr slave;
+    int rc;
+
+    /* For now, we don't have devices that change physically. */
+    if (!IsMaster(device))
+        return;
+
+    rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
+
+    if (rc != Success)
+        return;                 /* Device has disappeared */
+
+    if (IsMaster(slave))
+        return;
+
+    if (IsFloating(slave))
+        return;                 /* set floating since the event */
+
+    if (GetMaster(slave, MASTER_ATTACHED)->id != dce->masterid)
+        return;                 /* not our slave anymore, don't care */
+
+    /* FIXME: we probably need to send a DCE for the new slave now */
+
+    device->public.devicePrivate = slave->public.devicePrivate;
+
+    /* FIXME: the classes may have changed since we generated the event. */
+    DeepCopyDeviceClasses(slave, device, dce);
+    dce->deviceid = device->id;
+    XISendDeviceChangedEvent(device, dce);
+}
+
+/**
+ * Add state and motionMask to the filter for this event. The protocol
+ * supports some extra masks for motion when a button is down:
+ * ButtonXMotionMask and the DeviceButtonMotionMask to trigger only when at
+ * least one button (or that specific button is down). These masks need to
+ * be added to the filters for core/XI motion events.
+ *
+ * @param device The device to update the mask for
+ * @param state The current button state mask
+ * @param motion_mask The motion mask (DeviceButtonMotionMask or 0)
+ */
+static void
+UpdateDeviceMotionMask(DeviceIntPtr device, unsigned short state,
+                       Mask motion_mask)
+{
+    Mask mask;
+
+    mask = PointerMotionMask | state | motion_mask;
+    SetMaskForEvent(device->id, mask, DeviceMotionNotify);
+    SetMaskForEvent(device->id, mask, MotionNotify);
+}
+
+static void
+IncreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
+                    Mask *motion_mask, unsigned short *state)
+{
+    if (dev->valuator)
+        dev->valuator->motionHintWindow = NullWindow;
+
+    (*buttons_down)++;
+    *motion_mask = DeviceButtonMotionMask;
+    if (dev->button->map[key] <= 5)
+        *state |= (Button1Mask >> 1) << dev->button->map[key];
+}
+
+static void
+DecreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
+                    Mask *motion_mask, unsigned short *state)
+{
+    if (dev->valuator)
+        dev->valuator->motionHintWindow = NullWindow;
+
+    if (*buttons_down >= 1 && !--(*buttons_down))
+        *motion_mask = 0;
+    if (dev->button->map[key] <= 5)
+        *state &= ~((Button1Mask >> 1) << dev->button->map[key]);
+}
+
+/**
+ * Update the device state according to the data in the event.
+ *
+ * return values are
+ *   DEFAULT ... process as normal
+ *   DONT_PROCESS ... return immediately from caller
+ */
+#define DEFAULT 0
+#define DONT_PROCESS 1
+int
+UpdateDeviceState(DeviceIntPtr device, DeviceEvent *event)
+{
+    int i;
+    int key = 0, last_valuator;
+
+    KeyClassPtr k = NULL;
+    ButtonClassPtr b = NULL;
+    ValuatorClassPtr v = NULL;
+    TouchClassPtr t = NULL;
+
+    /* This event is always the first we get, before the actual events with
+     * the data. However, the way how the DDX is set up, "device" will
+     * actually be the slave device that caused the event.
+     */
+    switch (event->type) {
+    case ET_DeviceChanged:
+        ChangeMasterDeviceClasses(device, (DeviceChangedEvent *) event);
+        return DONT_PROCESS;    /* event has been sent already */
+    case ET_Motion:
+    case ET_ButtonPress:
+    case ET_ButtonRelease:
+    case ET_KeyPress:
+    case ET_KeyRelease:
+    case ET_ProximityIn:
+    case ET_ProximityOut:
+    case ET_TouchBegin:
+    case ET_TouchUpdate:
+    case ET_TouchEnd:
+        break;
+    default:
+        /* other events don't update the device */
+        return DEFAULT;
+    }
+
+    k = device->key;
+    v = device->valuator;
+    b = device->button;
+    t = device->touch;
+
+    key = event->detail.key;
+
+    /* Update device axis */
+    /* Check valuators first */
+    last_valuator = -1;
+    for (i = 0; i < MAX_VALUATORS; i++) {
+        if (BitIsOn(&event->valuators.mask, i)) {
+            if (!v) {
+                ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
+                       "Ignoring event.\n", device->name);
+                return DONT_PROCESS;
+            }
+            else if (v->numAxes < i) {
+                ErrorF("[Xi] Too many valuators reported for device '%s'. "
+                       "Ignoring event.\n", device->name);
+                return DONT_PROCESS;
+            }
+            last_valuator = i;
+        }
+    }
+
+    for (i = 0; i <= last_valuator && i < v->numAxes; i++) {
+        /* XXX: Relative/Absolute mode */
+        if (BitIsOn(&event->valuators.mask, i))
+            v->axisVal[i] = event->valuators.data[i];
+    }
+
+    if (event->type == ET_KeyPress) {
+        if (!k)
+            return DONT_PROCESS;
+
+        /* don't allow ddx to generate multiple downs, but repeats are okay */
+        if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
+            return DONT_PROCESS;
+
+        if (device->valuator)
+            device->valuator->motionHintWindow = NullWindow;
+        set_key_down(device, key, KEY_PROCESSED);
+    }
+    else if (event->type == ET_KeyRelease) {
+        if (!k)
+            return DONT_PROCESS;
+
+        if (!key_is_down(device, key, KEY_PROCESSED))   /* guard against duplicates */
+            return DONT_PROCESS;
+        if (device->valuator)
+            device->valuator->motionHintWindow = NullWindow;
+        set_key_up(device, key, KEY_PROCESSED);
+    }
+    else if (event->type == ET_ButtonPress) {
+        if (!b)
+            return DONT_PROCESS;
+
+        if (button_is_down(device, key, BUTTON_PROCESSED))
+            return DONT_PROCESS;
+
+        set_button_down(device, key, BUTTON_PROCESSED);
+
+        if (!b->map[key])
+            return DONT_PROCESS;
+
+        IncreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask,
+                            &b->state);
+        UpdateDeviceMotionMask(device, b->state, b->motionMask);
+    }
+    else if (event->type == ET_ButtonRelease) {
+        if (!b)
+            return DONT_PROCESS;
+
+        if (!button_is_down(device, key, BUTTON_PROCESSED))
+            return DONT_PROCESS;
+        if (IsMaster(device)) {
+            DeviceIntPtr sd;
+
+            /*
+             * Leave the button down if any slave has the
+             * button still down. Note that this depends on the
+             * event being delivered through the slave first
+             */
+            for (sd = inputInfo.devices; sd; sd = sd->next) {
+                if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER) != device)
+                    continue;
+                if (!sd->button)
+                    continue;
+                for (i = 1; i <= sd->button->numButtons; i++)
+                    if (sd->button->map[i] == key &&
+                        button_is_down(sd, i, BUTTON_PROCESSED))
+                        return DONT_PROCESS;
+            }
+        }
+        set_button_up(device, key, BUTTON_PROCESSED);
+        if (!b->map[key])
+            return DONT_PROCESS;
+
+        DecreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask,
+                            &b->state);
+        UpdateDeviceMotionMask(device, b->state, b->motionMask);
+    }
+    else if (event->type == ET_ProximityIn)
+        device->proximity->in_proximity = TRUE;
+    else if (event->type == ET_ProximityOut)
+        device->proximity->in_proximity = FALSE;
+    else if (event->type == ET_TouchBegin) {
+        BUG_RETURN_VAL(!b || !v, DONT_PROCESS);
+        BUG_RETURN_VAL(!t, DONT_PROCESS);
+
+        if (!b->map[key])
+            return DONT_PROCESS;
+
+        if (!(event->flags & TOUCH_POINTER_EMULATED) ||
+            (event->flags & TOUCH_REPLAYING))
+            return DONT_PROCESS;
+
+        IncreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask,
+                            &t->state);
+        UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
+    }
+    else if (event->type == ET_TouchEnd) {
+        BUG_RETURN_VAL(!b || !v, DONT_PROCESS);
+        BUG_RETURN_VAL(!t, DONT_PROCESS);
+
+        if (t->buttonsDown <= 0 || !b->map[key])
+            return DONT_PROCESS;
+
+        if (!(event->flags & TOUCH_POINTER_EMULATED))
+            return DONT_PROCESS;
+
+        DecreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask,
+                            &t->state);
+        UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
+    }
+
+    return DEFAULT;
+}
+
+/**
+ * A client that does not have the TouchOwnership mask set may not receive a
+ * TouchBegin event if there is at least one grab active.
+ *
+ * @return TRUE if the client selected for ownership events on the given
+ * window for this device, FALSE otherwise
+ */
+static inline Bool
+TouchClientWantsOwnershipEvents(ClientPtr client, DeviceIntPtr dev,
+                                WindowPtr win)
+{
+    InputClients *iclient;
+
+    nt_list_for_each_entry(iclient, wOtherInputMasks(win)->inputClients, next) {
+        if (rClient(iclient) != client)
+            continue;
+
+        return xi2mask_isset(iclient->xi2mask, dev, XI_TouchOwnership);
+    }
+
+    return FALSE;
+}
+
+static void
+TouchSendOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, int reason,
+                        XID resource)
+{
+    int nev, i;
+    InternalEvent *tel = InitEventList(GetMaximumEventsNum());
+
+    nev = GetTouchOwnershipEvents(tel, dev, ti, reason, resource, 0);
+    for (i = 0; i < nev; i++)
+        mieqProcessDeviceEvent(dev, tel + i, NULL);
+
+    FreeEventList(tel, GetMaximumEventsNum());
+}
+
+/**
+ * Attempts to deliver a touch event to the given client.
+ */
+static Bool
+DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
+                     GrabPtr grab, WindowPtr win, InternalEvent *ev)
+{
+    int err;
+    xEvent *xi2;
+    Mask filter;
+    Window child = DeepestSpriteWin(&ti->sprite)->drawable.id;
+
+    /* FIXME: owner event handling */
+
+    /* If the client does not have the ownership mask set and is not
+     * the current owner of the touch, only pretend we delivered */
+    if (!grab && ti->num_grabs != 0 &&
+        !TouchClientWantsOwnershipEvents(client, dev, win))
+        return TRUE;
+
+    /* If we fail here, we're going to leave a client hanging. */
+    err = EventToXI2(ev, &xi2);
+    if (err != Success)
+        FatalError("[Xi] %s: XI2 conversion failed in %s"
+                   " (%d)\n", dev->name, __func__, err);
+
+    FixUpEventFromWindow(&ti->sprite, xi2, win, child, FALSE);
+    filter = GetEventFilter(dev, xi2);
+    if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success)
+        return FALSE;
+    err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab);
+    free(xi2);
+
+    /* Returning the value from TryClientEvents isn't useful, since all our
+     * resource-gone cleanups will update the delivery list anyway. */
+    return TRUE;
+}
+
+static void
+ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
+{
+    ClientPtr client;
+    XID error;
+    GrabPtr grab = ti->listeners[0].grab;
+
+    BUG_RETURN(ti->listeners[0].type != TOUCH_LISTENER_GRAB &&
+               ti->listeners[0].type != TOUCH_LISTENER_POINTER_GRAB);
+    BUG_RETURN(!grab);
+
+    client = rClient(grab);
+
+    if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id,
+                          ti->listeners[0].window->drawable.id, &error) != Success)
+        ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
+}
+
+/**
+ * Find the oldest touch that still has a pointer emulation client.
+ *
+ * Pointer emulation can only be performed for the oldest touch. Otherwise, the
+ * order of events seen by the client will be wrong. This function helps us find
+ * the next touch to be emulated.
+ *
+ * @param dev The device to find touches for.
+ */
+static TouchPointInfoPtr
+FindOldestPointerEmulatedTouch(DeviceIntPtr dev)
+{
+    TouchPointInfoPtr oldest = NULL;
+    int i;
+
+    for (i = 0; i < dev->touch->num_touches; i++) {
+        TouchPointInfoPtr ti = dev->touch->touches + i;
+        int j;
+
+        if (!ti->active || !ti->emulate_pointer)
+            continue;
+
+        for (j = 0; j < ti->num_listeners; j++) {
+            if (ti->listeners[j].type == TOUCH_LISTENER_POINTER_GRAB ||
+                ti->listeners[j].type == TOUCH_LISTENER_POINTER_REGULAR)
+                break;
+        }
+        if (j == ti->num_listeners)
+            continue;
+
+        if (!oldest) {
+            oldest = ti;
+            continue;
+        }
+
+        if (oldest->client_id - ti->client_id < UINT_MAX / 2)
+            oldest = ti;
+    }
+
+    return oldest;
+}
+
+/**
+ * If the current owner has rejected the event, deliver the
+ * TouchOwnership/TouchBegin to the next item in the sprite stack.
+ */
+static void
+TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
+                     TouchOwnershipEvent *ev)
+{
+    TouchListener *listener = &ti->listeners[0]; /* new owner */
+    int accepted_early = listener->state == TOUCH_LISTENER_EARLY_ACCEPT;
+
+    /* Deliver the ownership */
+    if (listener->state == TOUCH_LISTENER_AWAITING_OWNER || accepted_early)
+        DeliverTouchEvents(dev, ti, (InternalEvent *) ev,
+                           listener->listener);
+    else if (listener->state == TOUCH_LISTENER_AWAITING_BEGIN) {
+        /* We can't punt to a pointer listener unless all older pointer
+         * emulated touches have been seen already. */
+        if ((listener->type == TOUCH_LISTENER_POINTER_GRAB ||
+             listener->type == TOUCH_LISTENER_POINTER_REGULAR) &&
+            ti != FindOldestPointerEmulatedTouch(dev))
+            return;
+
+        TouchEventHistoryReplay(ti, dev, listener->listener);
+    }
+
+    /* New owner has Begin/Update but not end. If touch is pending_finish,
+     * emulate the TouchEnd now */
+    if (ti->pending_finish) {
+        TouchEmitTouchEnd(dev, ti, 0, 0);
+
+        /* If the last owner is not a touch grab, finalise the touch, we
+           won't get more correspondence on this.
+         */
+        if (ti->num_listeners == 1 &&
+            (ti->num_grabs == 0 ||
+             listener->grab->grabtype != XI2 ||
+             !xi2mask_isset(listener->grab->xi2mask, dev, XI_TouchBegin))) {
+            TouchEndTouch(dev, ti);
+            return;
+        }
+    }
+
+    if (accepted_early)
+        ActivateEarlyAccept(dev, ti);
+}
+
+/**
+ * Check the oldest touch to see if it needs to be replayed to its pointer
+ * owner.
+ *
+ * Touch event propagation is paused if it hits a pointer listener while an
+ * older touch with a pointer listener is waiting on accept or reject. This
+ * function will restart propagation of a paused touch if needed.
+ *
+ * @param dev The device to check touches for.
+ */
+static void
+CheckOldestTouch(DeviceIntPtr dev)
+{
+    TouchPointInfoPtr oldest = FindOldestPointerEmulatedTouch(dev);
+
+    if (oldest && oldest->listeners[0].state == TOUCH_LISTENER_AWAITING_BEGIN)
+        TouchPuntToNextOwner(dev, oldest, NULL);
+}
+
+/**
+ * Process a touch rejection.
+ *
+ * @param sourcedev The source device of the touch sequence.
+ * @param ti The touchpoint info record.
+ * @param resource The resource of the client rejecting the touch.
+ * @param ev TouchOwnership event to send. Set to NULL if no event should be
+ *        sent.
+ */
+void
+TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
+              TouchOwnershipEvent *ev)
+{
+    Bool was_owner = (resource == ti->listeners[0].listener);
+    int i;
+
+    /* Send a TouchEnd event to the resource being removed, but only if they
+     * haven't received one yet already */
+    for (i = 0; i < ti->num_listeners; i++) {
+        if (ti->listeners[i].listener == resource) {
+            if (ti->listeners[i].state != TOUCH_LISTENER_HAS_END)
+                TouchEmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource);
+            break;
+        }
+    }
+
+    /* Remove the resource from the listener list, updating
+     * ti->num_listeners, as well as ti->num_grabs if it was a grab. */
+    TouchRemoveListener(ti, resource);
+
+    /* If the current owner was removed and there are further listeners, deliver
+     * the TouchOwnership or TouchBegin event to the new owner. */
+    if (ev && ti->num_listeners > 0 && was_owner)
+        TouchPuntToNextOwner(sourcedev, ti, ev);
+    else if (ti->num_listeners == 0)
+        TouchEndTouch(sourcedev, ti);
+
+    CheckOldestTouch(sourcedev);
+}
+
+/**
+ * Processes a TouchOwnership event, indicating a grab has accepted the touch
+ * it currently owns, or a grab or selection has been removed.  Will generate
+ * and send TouchEnd events to all clients removed from the delivery list, as
+ * well as possibly sending the new TouchOwnership event.  May end the
+ * touchpoint if it is pending finish.
+ */
+static void
+ProcessTouchOwnershipEvent(TouchOwnershipEvent *ev,
+                           DeviceIntPtr dev)
+{
+    TouchPointInfoPtr ti = TouchFindByClientID(dev, ev->touchid);
+
+    if (!ti) {
+        DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
+               dev->name, ev->type, ev->touchid);
+        return;
+    }
+
+    if (ev->reason == XIRejectTouch)
+        TouchRejected(dev, ti, ev->resource, ev);
+    else if (ev->reason == XIAcceptTouch) {
+        int i;
+
+
+        /* For pointer-emulated listeners that ungrabbed the active grab,
+         * the state was forced to TOUCH_LISTENER_HAS_END. Still go
+         * through the motions of ending the touch if the listener has
+         * already seen the end. This ensures that the touch record is ended in
+         * the server.
+         */
+        if (ti->listeners[0].state == TOUCH_LISTENER_HAS_END)
+            TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);
+
+        /* The touch owner has accepted the touch.  Send TouchEnd events to
+         * everyone else, and truncate the list of listeners. */
+        for (i = 1; i < ti->num_listeners; i++)
+            TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
+
+        while (ti->num_listeners > 1)
+            TouchRemoveListener(ti, ti->listeners[1].listener);
+        /* Owner accepted after receiving end */
+        if (ti->listeners[0].state == TOUCH_LISTENER_HAS_END)
+            TouchEndTouch(dev, ti);
+        else
+            ti->listeners[0].state = TOUCH_LISTENER_HAS_ACCEPTED;
+    }
+    else {  /* this is the very first ownership event for a grab */
+        DeliverTouchEvents(dev, ti, (InternalEvent *) ev, ev->resource);
+    }
+}
+
+/**
+ * Copy the event's valuator information into the touchpoint, we may need
+ * this for emulated TouchEnd events.
+ */
+static void
+TouchCopyValuatorData(DeviceEvent *ev, TouchPointInfoPtr ti)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(ev->valuators.data); i++)
+        if (BitIsOn(ev->valuators.mask, i))
+            valuator_mask_set_double(ti->valuators, i, ev->valuators.data[i]);
+}
+
+/**
+ * Given a touch event and a potential listener, retrieve info needed for
+ * processing the event.
+ *
+ * @param dev The device generating the touch event.
+ * @param ti The touch point info record for the touch event.
+ * @param ev The touch event to process.
+ * @param listener The touch event listener that may receive the touch event.
+ * @param[out] client The client that should receive the touch event.
+ * @param[out] win The window to deliver the event on.
+ * @param[out] grab The grab to deliver the event through, if any.
+ * @param[out] mask The XI 2.x event mask of the grab or selection, if any.
+ * @return TRUE if an event should be delivered to the listener, FALSE
+ *         otherwise.
+ */
+static Bool
+RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
+                          InternalEvent *ev, TouchListener * listener,
+                          ClientPtr *client, WindowPtr *win, GrabPtr *grab,
+                          XI2Mask **mask)
+{
+    int rc;
+    InputClients *iclients = NULL;
+    *mask = NULL;
+
+    if (listener->type == TOUCH_LISTENER_GRAB ||
+        listener->type == TOUCH_LISTENER_POINTER_GRAB) {
+        *grab = listener->grab;
+
+        BUG_RETURN_VAL(!*grab, FALSE);
+
+        *client = rClient(*grab);
+        *win = (*grab)->window;
+        *mask = (*grab)->xi2mask;
+    }
+    else {
+        rc = dixLookupResourceByType((void **) win, listener->listener,
+                                     listener->resource_type,
+                                     serverClient, DixSendAccess);
+        if (rc != Success)
+            return FALSE;
+
+        if (listener->level == XI2) {
+            int evtype;
+
+            if (ti->emulate_pointer &&
+                listener->type == TOUCH_LISTENER_POINTER_REGULAR)
+                evtype = GetXI2Type(TouchGetPointerEventType(ev));
+            else
+                evtype = GetXI2Type(ev->any.type);
+
+            nt_list_for_each_entry(iclients,
+                                   wOtherInputMasks(*win)->inputClients, next)
+                if (xi2mask_isset(iclients->xi2mask, dev, evtype))
+                break;
+
+            BUG_RETURN_VAL(!iclients, FALSE);
+
+            *mask = iclients->xi2mask;
+            *client = rClient(iclients);
+        }
+        else if (listener->level == XI) {
+            int xi_type = GetXIType(TouchGetPointerEventType(ev));
+            Mask xi_filter = event_get_filter_from_type(dev, xi_type);
+
+            nt_list_for_each_entry(iclients,
+                                   wOtherInputMasks(*win)->inputClients, next)
+                if (iclients->mask[dev->id] & xi_filter)
+                break;
+            BUG_RETURN_VAL(!iclients, FALSE);
+
+            *client = rClient(iclients);
+        }
+        else {
+            int coretype = GetCoreType(TouchGetPointerEventType(ev));
+            Mask core_filter = event_get_filter_from_type(dev, coretype);
+            OtherClients *oclients;
+
+            /* all others */
+            nt_list_for_each_entry(oclients,
+                                   (OtherClients *) wOtherClients(*win), next)
+                if (oclients->mask & core_filter)
+                    break;
+
+            /* if owner selected, oclients is NULL */
+            *client = oclients ? rClient(oclients) : wClient(*win);
+        }
+
+        *grab = NULL;
+    }
+
+    return TRUE;
+}
+
+static int
+DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
+                          InternalEvent *ev, TouchListener * listener,
+                          ClientPtr client, WindowPtr win, GrabPtr grab,
+                          XI2Mask *xi2mask)
+{
+    InternalEvent motion, button;
+    InternalEvent *ptrev = &motion;
+    int nevents;
+    DeviceIntPtr kbd;
+
+    /* There may be a pointer grab on the device */
+    if (!grab) {
+        grab = dev->deviceGrab.grab;
+        if (grab) {
+            win = grab->window;
+            xi2mask = grab->xi2mask;
+            client = rClient(grab);
+        }
+    }
+
+    /* We don't deliver pointer events to non-owners */
+    if (!TouchResourceIsOwner(ti, listener->listener))
+        return !Success;
+
+    if (!ti->emulate_pointer)
+        return !Success;
+
+    nevents = TouchConvertToPointerEvent(ev, &motion, &button);
+    BUG_RETURN_VAL(nevents == 0, BadValue);
+
+    /* Note that here we deliver only part of the events that are generated by the touch event:
+     *
+     * TouchBegin results in ButtonPress (motion is handled in DeliverEmulatedMotionEvent)
+     * TouchUpdate results in Motion
+     * TouchEnd results in ButtonRelease (motion is handled in DeliverEmulatedMotionEvent)
+     */
+    if (nevents > 1)
+        ptrev = &button;
+
+    kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
+    event_set_state(dev, kbd, &ptrev->device_event);
+    ptrev->device_event.corestate = event_get_corestate(dev, kbd);
+
+    if (grab) {
+        /* this side-steps the usual activation mechanisms, but... */
+        if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab)
+            ActivatePassiveGrab(dev, grab, ptrev, ev);  /* also delivers the event */
+        else {
+            int deliveries = 0;
+
+            /* 'grab' is the passive grab, but if the grab isn't active,
+             * don't deliver */
+            if (!dev->deviceGrab.grab)
+                return !Success;
+
+            if (grab->ownerEvents) {
+                WindowPtr focus = NullWindow;
+                WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite);
+
+                deliveries = DeliverDeviceEvents(sprite_win, ptrev, grab, focus, dev);
+            }
+
+            if (!deliveries)
+                deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
+
+            /* We must accept the touch sequence once a pointer listener has
+             * received one event past ButtonPress. */
+            if (deliveries && ev->any.type != ET_TouchBegin &&
+                !(ev->device_event.flags & TOUCH_CLIENT_ID))
+                TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
+
+            if (ev->any.type == ET_TouchEnd &&
+                ti->num_listeners == 1 &&
+                !dev->button->buttonsDown &&
+                dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
+                (*dev->deviceGrab.DeactivateGrab) (dev);
+                CheckOldestTouch(dev);
+                return Success;
+            }
+        }
+    }
+    else {
+        GrabPtr devgrab = dev->deviceGrab.grab;
+        WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite);
+
+        DeliverDeviceEvents(sprite_win, ptrev, grab, win, dev);
+        /* FIXME: bad hack
+         * Implicit passive grab activated in response to this event. Store
+         * the event.
+         */
+        if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) {
+            TouchListener *l;
+            GrabPtr g;
+
+            devgrab = dev->deviceGrab.grab;
+            g = AllocGrab(devgrab);
+            BUG_WARN(!g);
+
+            CopyPartialInternalEvent(dev->deviceGrab.sync.event, ev);
+
+            /* The listener array has a sequence of grabs and then one event
+             * selection. Implicit grab activation occurs through delivering an
+             * event selection. Thus, we update the last listener in the array.
+             */
+            l = &ti->listeners[ti->num_listeners - 1];
+            l->listener = g->resource;
+            l->grab = g;
+            //l->resource_type = RT_NONE;
+
+            if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin)
+                l->type = TOUCH_LISTENER_POINTER_GRAB;
+            else
+                l->type = TOUCH_LISTENER_GRAB;
+        }
+
+    }
+    if (ev->any.type == ET_TouchBegin)
+        listener->state = TOUCH_LISTENER_IS_OWNER;
+    else if (ev->any.type == ET_TouchEnd)
+        listener->state = TOUCH_LISTENER_HAS_END;
+
+    return Success;
+}
+
+static void
+DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
+                           InternalEvent *ev)
+{
+    DeviceEvent motion;
+
+    if (ti->num_listeners) {
+        ClientPtr client;
+        WindowPtr win;
+        GrabPtr grab;
+        XI2Mask *mask;
+
+        if (ti->listeners[0].type != TOUCH_LISTENER_POINTER_REGULAR &&
+            ti->listeners[0].type != TOUCH_LISTENER_POINTER_GRAB)
+            return;
+
+        motion = ev->device_event;
+        motion.type = ET_TouchUpdate;
+        motion.detail.button = 0;
+
+        if (!RetrieveTouchDeliveryData(dev, ti, (InternalEvent*)&motion,
+                                       &ti->listeners[0], &client, &win, &grab,
+                                       &mask))
+            return;
+
+        DeliverTouchEmulatedEvent(dev, ti, (InternalEvent*)&motion, &ti->listeners[0], client,
+                                  win, grab, mask);
+    }
+    else {
+        InternalEvent button;
+        int converted;
+
+        converted = TouchConvertToPointerEvent(ev, (InternalEvent*)&motion, &button);
+
+        BUG_WARN(converted == 0);
+        if (converted)
+            ProcessOtherEvent((InternalEvent*)&motion, dev);
+    }
+}
+
+/**
+ * Processes and delivers a TouchBegin, TouchUpdate, or a
+ * TouchEnd event.
+ *
+ * Due to having rather different delivery semantics (see the Xi 2.2 protocol
+ * spec for more information), this implements its own grab and event-selection
+ * delivery logic.
+ */
+static void
+ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
+{
+    TouchClassPtr t = dev->touch;
+    TouchPointInfoPtr ti;
+    uint32_t touchid;
+    int type = ev->any.type;
+    int emulate_pointer = ! !(ev->device_event.flags & TOUCH_POINTER_EMULATED);
+    DeviceIntPtr kbd;
+
+    if (!t)
+        return;
+
+    touchid = ev->device_event.touchid;
+
+    if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING)) {
+        ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
+                             emulate_pointer);
+    }
+    else
+        ti = TouchFindByClientID(dev, touchid);
+
+    /* Active pointer grab */
+    if (emulate_pointer && dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab &&
+        (dev->deviceGrab.grab->grabtype == CORE ||
+         dev->deviceGrab.grab->grabtype == XI ||
+         !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin)))
+    {
+        /* Active pointer grab on touch point and we get a TouchEnd - claim this
+         * touchpoint accepted, otherwise clients waiting for ownership will
+         * wait on this touchpoint until this client ungrabs, or the cows come
+         * home, whichever is earlier */
+        if (ti && type == ET_TouchEnd)
+            TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
+        else if (!ti && type != ET_TouchBegin) {
+            /* Under the following circumstances we create a new touch record for an
+             * existing touch:
+             *
+             * - The touch may be pointer emulated
+             * - An explicit grab is active on the device
+             * - The grab is a pointer grab
+             *
+             * This allows for an explicit grab to receive pointer events for an already
+             * active touch.
+             */
+            ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
+                                 emulate_pointer);
+            if (!ti) {
+                DebugF("[Xi] %s: Failed to create new dix record for explicitly "
+                       "grabbed touchpoint %d\n",
+                       dev->name, touchid);
+                return;
+            }
+
+            TouchBuildSprite(dev, ti, ev);
+            TouchSetupListeners(dev, ti, ev);
+        }
+    }
+
+    if (!ti) {
+        DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
+               dev->name, type, touchid);
+        goto out;
+    }
+
+    /* if emulate_pointer is set, emulate the motion event right
+     * here, so we can ignore it for button event emulation. TouchUpdate
+     * events which _only_ emulate motion just work normally */
+    if (emulate_pointer && (ev->any.type == ET_TouchBegin ||
+                           (ev->any.type == ET_TouchEnd && ti->num_listeners > 0)))
+        DeliverEmulatedMotionEvent(dev, ti, ev);
+
+    if (emulate_pointer && IsMaster(dev))
+        CheckMotion(&ev->device_event, dev);
+
+    kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
+    event_set_state(NULL, kbd, &ev->device_event);
+    ev->device_event.corestate = event_get_corestate(NULL, kbd);
+
+    /* Make sure we have a valid window trace for event delivery; must be
+     * called after event type mutation. Touch end events are always processed
+     * in order to end touch records. */
+    /* FIXME: check this */
+    if ((type == ET_TouchBegin &&
+         !(ev->device_event.flags & TOUCH_REPLAYING) &&
+         !TouchBuildSprite(dev, ti, ev)) ||
+        (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
+        return;
+
+    TouchCopyValuatorData(&ev->device_event, ti);
+    /* WARNING: the event type may change to TouchUpdate in
+     * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
+     * owner */
+    DeliverTouchEvents(dev, ti, ev, ev->device_event.resource);
+    if (ev->any.type == ET_TouchEnd)
+        TouchEndTouch(dev, ti);
+
+ out:
+    if (emulate_pointer)
+        UpdateDeviceState(dev, &ev->device_event);
+}
+
+static void
+ProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev)
+{
+    Mask filter;
+    WindowPtr pWin;
+    BarrierEvent *be = &e->barrier_event;
+    xEvent *ev;
+    int rc;
+    GrabPtr grab = dev->deviceGrab.grab;
+
+    if (!IsMaster(dev))
+        return;
+
+    if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess) != Success)
+        return;
+
+    if (grab)
+        be->flags |= XIBarrierDeviceIsGrabbed;
+
+    rc = EventToXI2(e, &ev);
+    if (rc != Success) {
+        ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__, rc);
+        return;
+    }
+
+    /* A client has a grab, deliver to this client if the grab_window is the
+       barrier window.
+
+       Otherwise, deliver normally to the client.
+     */
+    if (grab &&
+        CLIENT_ID(be->barrierid) == CLIENT_ID(grab->resource) &&
+        grab->window->drawable.id == be->window) {
+        DeliverGrabbedEvent(e, dev, FALSE);
+    } else {
+        filter = GetEventFilter(dev, ev);
+
+        DeliverEventsToWindow(dev, pWin, ev, 1,
+                              filter, NullGrab);
+    }
+    free(ev);
+}
+
+static BOOL
+IsAnotherGestureActiveOnMaster(DeviceIntPtr dev, InternalEvent* ev)
+{
+    GestureClassPtr g = dev->gesture;
+    if (g->gesture.active && g->gesture.sourceid != ev->gesture_event.sourceid) {
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/**
+ * Processes and delivers a Gesture{Pinch,Swipe}{Begin,Update,End}.
+ *
+ * Due to having rather different delivery semantics (see the Xi 2.4 protocol
+ * spec for more information), this implements its own grab and event-selection
+ * delivery logic.
+ */
+void
+ProcessGestureEvent(InternalEvent *ev, DeviceIntPtr dev)
+{
+    GestureInfoPtr gi;
+    DeviceIntPtr kbd;
+    Bool deactivateGestureGrab = FALSE;
+    Bool delivered = FALSE;
+
+    if (!dev->gesture)
+        return;
+
+    if (IsMaster(dev) && IsAnotherGestureActiveOnMaster(dev, ev))
+        return;
+
+    if (IsGestureBeginEvent(ev))
+        gi = GestureBeginGesture(dev, ev);
+    else
+        gi = GestureFindActiveByEventType(dev, ev->any.type);
+
+    if (!gi) {
+        /* This may happen if gesture is no longer active or was never started. */
+        return;
+    }
+
+    kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
+    event_set_state_gesture(kbd, &ev->gesture_event);
+
+    if (IsGestureBeginEvent(ev))
+        GestureSetupListener(dev, gi, ev);
+
+    if (IsGestureEndEvent(ev) &&
+            dev->deviceGrab.grab &&
+            dev->deviceGrab.fromPassiveGrab &&
+            GrabIsGestureGrab(dev->deviceGrab.grab))
+        deactivateGestureGrab = TRUE;
+
+    delivered = DeliverGestureEventToOwner(dev, gi, ev);
+
+    if (delivered && !deactivateGestureGrab &&
+            (IsGestureBeginEvent(ev) || IsGestureEndEvent(ev)))
+        FreezeThisEventIfNeededForSyncGrab(dev, ev);
+
+    if (IsGestureEndEvent(ev))
+        GestureEndGesture(gi);
+
+    if (deactivateGestureGrab)
+        (*dev->deviceGrab.DeactivateGrab) (dev);
+}
+
+/**
+ * Process DeviceEvents and DeviceChangedEvents.
+ */
+static void
+ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
+{
+    GrabPtr grab;
+    Bool deactivateDeviceGrab = FALSE;
+    int key = 0, rootX, rootY;
+    ButtonClassPtr b;
+    int ret = 0;
+    int corestate;
+    DeviceIntPtr mouse = NULL, kbd = NULL;
+    DeviceEvent *event = &ev->device_event;
+
+    if (IsPointerDevice(device)) {
+        kbd = GetMaster(device, KEYBOARD_OR_FLOAT);
+        mouse = device;
+        if (!kbd->key)          /* can happen with floating SDs */
+            kbd = NULL;
+    }
+    else {
+        mouse = GetMaster(device, POINTER_OR_FLOAT);
+        kbd = device;
+        if (!mouse->valuator || !mouse->button) /* may be float. SDs */
+            mouse = NULL;
+    }
+
+    corestate = event_get_corestate(mouse, kbd);
+    event_set_state(mouse, kbd, event);
+
+    ret = UpdateDeviceState(device, event);
+    if (ret == DONT_PROCESS)
+        return;
+
+    b = device->button;
+
+    if (IsMaster(device) || IsFloating(device))
+        CheckMotion(event, device);
+
+    switch (event->type) {
+    case ET_Motion:
+    case ET_ButtonPress:
+    case ET_ButtonRelease:
+    case ET_KeyPress:
+    case ET_KeyRelease:
+    case ET_ProximityIn:
+    case ET_ProximityOut:
+        GetSpritePosition(device, &rootX, &rootY);
+        event->root_x = rootX;
+        event->root_y = rootY;
+        NoticeEventTime((InternalEvent *) event, device);
+        event->corestate = corestate;
+        key = event->detail.key;
+        break;
+    default:
+        break;
+    }
+
+    /* send KeyPress and KeyRelease events to XACE plugins */
+    if (XaceHookIsSet(XACE_KEY_AVAIL) &&
+            (event->type == ET_KeyPress || event->type == ET_KeyRelease)) {
+        xEvent *core;
+        int count;
+
+        if (EventToCore(ev, &core, &count) == Success && count > 0) {
+            XaceHook(XACE_KEY_AVAIL, core, device, 0);
+            free(core);
+        }
+    }
+
+    if (DeviceEventCallback && !syncEvents.playingEvents) {
+        DeviceEventInfoRec eventinfo;
+        SpritePtr pSprite = device->spriteInfo->sprite;
+
+        /* see comment in EnqueueEvents regarding the next three lines */
+        if (ev->any.type == ET_Motion)
+            ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
+
+        eventinfo.device = device;
+        eventinfo.event = ev;
+        CallCallbacks(&DeviceEventCallback, (void *) &eventinfo);
+    }
+
+    grab = device->deviceGrab.grab;
+
+    switch (event->type) {
+    case ET_KeyPress:
+        /* Don't deliver focus events (e.g. from KeymapNotify when running
+         * nested) to clients. */
+        if (event->source_type == EVENT_SOURCE_FOCUS)
+            return;
+        if (!grab && CheckDeviceGrabs(device, ev, 0))
+            return;
+        break;
+    case ET_KeyRelease:
+        if (grab && device->deviceGrab.fromPassiveGrab &&
+            (key == device->deviceGrab.activatingKey) &&
+            GrabIsKeyboardGrab(device->deviceGrab.grab))
+            deactivateDeviceGrab = TRUE;
+        break;
+    case ET_ButtonPress:
+        if (b->map[key] == 0)   /* there's no button 0 */
+            return;
+        event->detail.button = b->map[key];
+        if (!grab && CheckDeviceGrabs(device, ev, 0)) {
+            /* if a passive grab was activated, the event has been sent
+             * already */
+            return;
+        }
+        break;
+    case ET_ButtonRelease:
+        if (b->map[key] == 0)   /* there's no button 0 */
+            return;
+        event->detail.button = b->map[key];
+        if (grab && !b->buttonsDown &&
+            device->deviceGrab.fromPassiveGrab &&
+            GrabIsPointerGrab(device->deviceGrab.grab))
+            deactivateDeviceGrab = TRUE;
+    default:
+        break;
+    }
+
+    /* Don't deliver focus events (e.g. from KeymapNotify when running
+     * nested) to clients. */
+    if (event->source_type != EVENT_SOURCE_FOCUS) {
+        if (grab)
+            DeliverGrabbedEvent((InternalEvent *) event, device,
+                                deactivateDeviceGrab);
+        else if (device->focus && !IsPointerEvent(ev))
+            DeliverFocusedEvent(device, (InternalEvent *) event,
+                                GetSpriteWindow(device));
+        else
+            DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent *) event,
+                                NullGrab, NullWindow, device);
+    }
+
+    if (deactivateDeviceGrab == TRUE) {
+        (*device->deviceGrab.DeactivateGrab) (device);
+
+        if (!IsMaster (device) && !IsFloating (device)) {
+            int flags, num_events = 0;
+            InternalEvent dce;
+
+            flags = (IsPointerDevice (device)) ?
+                DEVCHANGE_POINTER_EVENT : DEVCHANGE_KEYBOARD_EVENT;
+            UpdateFromMaster (&dce, device, flags, &num_events);
+            BUG_WARN(num_events > 1);
+
+            if (num_events == 1)
+                ChangeMasterDeviceClasses(GetMaster (device, MASTER_ATTACHED),
+                                          &dce.changed_event);
+        }
+
+    }
+
+    event->detail.key = key;
+}
+
+/**
+ * Main device event processing function.
+ * Called from when processing the events from the event queue.
+ *
+ */
+void
+ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
+{
+    verify_internal_event(ev);
+
+    switch (ev->any.type) {
+    case ET_RawKeyPress:
+    case ET_RawKeyRelease:
+    case ET_RawButtonPress:
+    case ET_RawButtonRelease:
+    case ET_RawMotion:
+    case ET_RawTouchBegin:
+    case ET_RawTouchUpdate:
+    case ET_RawTouchEnd:
+        DeliverRawEvent(&ev->raw_event, device);
+        break;
+    case ET_TouchBegin:
+    case ET_TouchUpdate:
+    case ET_TouchEnd:
+        ProcessTouchEvent(ev, device);
+        break;
+    case ET_TouchOwnership:
+        /* TouchOwnership events are handled separately from the rest, as they
+         * have more complex semantics. */
+        ProcessTouchOwnershipEvent(&ev->touch_ownership_event, device);
+        break;
+    case ET_BarrierHit:
+    case ET_BarrierLeave:
+        ProcessBarrierEvent(ev, device);
+        break;
+    case ET_GesturePinchBegin:
+    case ET_GesturePinchUpdate:
+    case ET_GesturePinchEnd:
+    case ET_GestureSwipeBegin:
+    case ET_GestureSwipeUpdate:
+    case ET_GestureSwipeEnd:
+        ProcessGestureEvent(ev, device);
+        break;
+    default:
+        ProcessDeviceEvent(ev, device);
+        break;
+    }
+}
+
+static int
+DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
+                       InternalEvent *ev, TouchListener * listener,
+                       ClientPtr client, WindowPtr win, GrabPtr grab,
+                       XI2Mask *xi2mask)
+{
+    enum TouchListenerState state;
+    int rc = Success;
+    Bool has_ownershipmask;
+
+    if (listener->type == TOUCH_LISTENER_POINTER_REGULAR ||
+        listener->type == TOUCH_LISTENER_POINTER_GRAB) {
+        rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
+                                       grab, xi2mask);
+        if (rc == Success) {
+            listener->state = TOUCH_LISTENER_IS_OWNER;
+            /* async grabs cannot replay, so automatically accept this touch */
+            if (listener->type == TOUCH_LISTENER_POINTER_GRAB &&
+                dev->deviceGrab.grab &&
+                dev->deviceGrab.fromPassiveGrab &&
+                dev->deviceGrab.grab->pointerMode == GrabModeAsync)
+                ActivateEarlyAccept(dev, ti);
+        }
+        goto out;
+    }
+
+    has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
+
+    if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
+        rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
+    if (!TouchResourceIsOwner(ti, listener->listener)) {
+        if (has_ownershipmask)
+            state = TOUCH_LISTENER_AWAITING_OWNER;
+        else
+            state = TOUCH_LISTENER_AWAITING_BEGIN;
+    }
+    else {
+        if (has_ownershipmask)
+            TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
+
+        if (listener->type == TOUCH_LISTENER_REGULAR)
+            state = TOUCH_LISTENER_HAS_ACCEPTED;
+        else
+            state = TOUCH_LISTENER_IS_OWNER;
+    }
+    listener->state = state;
+
+ out:
+    return rc;
+}
+
+static int
+DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
+                     TouchListener * listener, ClientPtr client,
+                     WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
+{
+    int rc = Success;
+
+    if (listener->type == TOUCH_LISTENER_POINTER_REGULAR ||
+        listener->type == TOUCH_LISTENER_POINTER_GRAB) {
+        /* Note: If the active grab was ungrabbed, we already changed the
+         * state to TOUCH_LISTENER_HAS_END but still get here. So we mustn't
+         * actually send the event.
+         * This is part two of the hack in DeactivatePointerGrab
+         */
+        if (listener->state != TOUCH_LISTENER_HAS_END) {
+            rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
+                                           grab, xi2mask);
+
+             /* Once we send a TouchEnd to a legacy listener, we're already well
+              * past the accepting/rejecting stage (can only happen on
+              * GrabModeSync + replay. This listener now gets the end event,
+              * and we can continue.
+              */
+            if (rc == Success)
+                listener->state = TOUCH_LISTENER_HAS_END;
+        }
+        goto out;
+    }
+
+    /* A client is waiting for the begin, don't give it a TouchEnd */
+    if (listener->state == TOUCH_LISTENER_AWAITING_BEGIN) {
+        listener->state = TOUCH_LISTENER_HAS_END;
+        goto out;
+    }
+
+    /* Event in response to reject */
+    if (ev->device_event.flags & TOUCH_REJECT ||
+        (ev->device_event.flags & TOUCH_ACCEPT && !TouchResourceIsOwner(ti, listener->listener))) {
+        /* Touch has been rejected, or accepted by its owner which is not this listener */
+        if (listener->state != TOUCH_LISTENER_HAS_END)
+            rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
+        listener->state = TOUCH_LISTENER_HAS_END;
+    }
+    else if (TouchResourceIsOwner(ti, listener->listener)) {
+        Bool normal_end = !(ev->device_event.flags & TOUCH_ACCEPT);
+
+        /* FIXME: what about early acceptance */
+        if (normal_end && listener->state != TOUCH_LISTENER_HAS_END)
+            rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
+
+        if ((ti->num_listeners > 1 ||
+             (ti->num_grabs > 0 && listener->state != TOUCH_LISTENER_HAS_ACCEPTED)) &&
+            (ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) {
+            ev->any.type = ET_TouchUpdate;
+            ev->device_event.flags |= TOUCH_PENDING_END;
+            ti->pending_finish = TRUE;
+        }
+
+        if (normal_end)
+            listener->state = TOUCH_LISTENER_HAS_END;
+    }
+
+ out:
+    return rc;
+}
+
+static int
+DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
+                  TouchListener * listener, ClientPtr client,
+                  WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
+{
+    Bool has_ownershipmask = FALSE;
+    int rc = Success;
+
+    if (xi2mask)
+        has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
+
+    if (ev->any.type == ET_TouchOwnership) {
+        ev->touch_ownership_event.deviceid = dev->id;
+        if (!TouchResourceIsOwner(ti, listener->listener))
+            goto out;
+        rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
+        listener->state = TOUCH_LISTENER_IS_OWNER;
+    }
+    else
+        ev->device_event.deviceid = dev->id;
+
+    if (ev->any.type == ET_TouchBegin) {
+        rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab,
+                                    xi2mask);
+    }
+    else if (ev->any.type == ET_TouchUpdate) {
+        if (listener->type == TOUCH_LISTENER_POINTER_REGULAR ||
+            listener->type == TOUCH_LISTENER_POINTER_GRAB)
+            DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab,
+                                      xi2mask);
+        else if (TouchResourceIsOwner(ti, listener->listener) ||
+                 has_ownershipmask)
+            rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
+    }
+    else if (ev->any.type == ET_TouchEnd)
+        rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab,
+                                  xi2mask);
+
+ out:
+    return rc;
+}
+
+/**
+ * Delivers a touch events to all interested clients.  For TouchBegin events,
+ * will update ti->listeners, ti->num_listeners, and ti->num_grabs.
+ * May also mutate ev (type and flags) upon successful delivery.  If
+ * @resource is non-zero, will only attempt delivery to the owner of that
+ * resource.
+ *
+ * @return TRUE if the event was delivered at least once, FALSE otherwise
+ */
+void
+DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
+                   InternalEvent *ev, XID resource)
+{
+    int i;
+
+    if (ev->any.type == ET_TouchBegin &&
+        !(ev->device_event.flags & (TOUCH_CLIENT_ID | TOUCH_REPLAYING)))
+        TouchSetupListeners(dev, ti, ev);
+
+    TouchEventHistoryPush(ti, &ev->device_event);
+
+    for (i = 0; i < ti->num_listeners; i++) {
+        GrabPtr grab = NULL;
+        ClientPtr client;
+        WindowPtr win;
+        XI2Mask *mask;
+        TouchListener *listener = &ti->listeners[i];
+
+        if (resource && listener->listener != resource)
+            continue;
+
+        if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win,
+                                       &grab, &mask))
+            continue;
+
+        DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
+    }
+}
+
+/**
+ * Attempts to deliver a gesture event to the given client.
+ */
+static Bool
+DeliverOneGestureEvent(ClientPtr client, DeviceIntPtr dev, GestureInfoPtr gi,
+                       GrabPtr grab, WindowPtr win, InternalEvent *ev)
+{
+    int err;
+    xEvent *xi2;
+    Mask filter;
+    Window child = DeepestSpriteWin(&gi->sprite)->drawable.id;
+
+    /* If we fail here, we're going to leave a client hanging. */
+    err = EventToXI2(ev, &xi2);
+    if (err != Success)
+        FatalError("[Xi] %s: XI2 conversion failed in %s"
+                   " (%d)\n", dev->name, __func__, err);
+
+    FixUpEventFromWindow(&gi->sprite, xi2, win, child, FALSE);
+    filter = GetEventFilter(dev, xi2);
+    if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success)
+        return FALSE;
+    err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab);
+    free(xi2);
+
+    /* Returning the value from TryClientEvents isn't useful, since all our
+     * resource-gone cleanups will update the delivery list anyway. */
+    return TRUE;
+}
+
+/**
+ * Given a gesture event and a potential listener, retrieve info needed for processing the event.
+ *
+ * @param dev The device generating the gesture event.
+ * @param ev The gesture event to process.
+ * @param listener The gesture event listener that may receive the gesture event.
+ * @param[out] client The client that should receive the gesture event.
+ * @param[out] win The window to deliver the event on.
+ * @param[out] grab The grab to deliver the event through, if any.
+ * @return TRUE if an event should be delivered to the listener, FALSE
+ *         otherwise.
+ */
+static Bool
+RetrieveGestureDeliveryData(DeviceIntPtr dev, InternalEvent *ev, GestureListener* listener,
+                            ClientPtr *client, WindowPtr *win, GrabPtr *grab)
+{
+    int rc;
+    int evtype;
+    InputClients *iclients = NULL;
+    *grab = NULL;
+
+    if (listener->type == GESTURE_LISTENER_GRAB ||
+        listener->type == GESTURE_LISTENER_NONGESTURE_GRAB) {
+        *grab = listener->grab;
+
+        BUG_RETURN_VAL(!*grab, FALSE);
+
+        *client = rClient(*grab);
+        *win = (*grab)->window;
+    }
+    else {
+        rc = dixLookupResourceByType((void **) win, listener->listener, listener->resource_type,
+                                     serverClient, DixSendAccess);
+        if (rc != Success)
+            return FALSE;
+
+        /* note that we only will have XI2 listeners as
+           listener->type == GESTURE_LISTENER_REGULAR */
+        evtype = GetXI2Type(ev->any.type);
+
+        nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next)
+            if (xi2mask_isset(iclients->xi2mask, dev, evtype))
+                break;
+
+        BUG_RETURN_VAL(!iclients, FALSE);
+
+        *client = rClient(iclients);
+    }
+
+    return TRUE;
+}
+
+/**
+ * Delivers a gesture to the owner, if possible and needed. Returns whether
+ * an event was delivered.
+ */
+Bool
+DeliverGestureEventToOwner(DeviceIntPtr dev, GestureInfoPtr gi, InternalEvent *ev)
+{
+    GrabPtr grab = NULL;
+    ClientPtr client;
+    WindowPtr win;
+
+    if (!gi->has_listener || gi->listener.type == GESTURE_LISTENER_NONGESTURE_GRAB) {
+        return 0;
+    }
+
+    if (!RetrieveGestureDeliveryData(dev, ev, &gi->listener, &client, &win, &grab))
+        return 0;
+
+    ev->gesture_event.deviceid = dev->id;
+
+    return DeliverOneGestureEvent(client, dev, gi, grab, win, ev);
+}
+
+int
+InitProximityClassDeviceStruct(DeviceIntPtr dev)
+{
+    ProximityClassPtr proxc;
+
+    BUG_RETURN_VAL(dev == NULL, FALSE);
+    BUG_RETURN_VAL(dev->proximity != NULL, FALSE);
+
+    proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
+    if (!proxc)
+        return FALSE;
+    proxc->sourceid = dev->id;
+    proxc->in_proximity = TRUE;
+    dev->proximity = proxc;
+    return TRUE;
+}
+
+/**
+ * Initialise the device's valuators. The memory must already be allocated,
+ * this function merely inits the matching axis (specified through axnum) to
+ * sane values.
+ *
+ * It is a condition that (minval < maxval).
+ *
+ * @see InitValuatorClassDeviceStruct
+ */
+Bool
+InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
+                       int maxval, int resolution, int min_res, int max_res,
+                       int mode)
+{
+    AxisInfoPtr ax;
+
+    BUG_RETURN_VAL(dev == NULL, FALSE);
+    BUG_RETURN_VAL(dev->valuator == NULL, FALSE);
+    BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE);
+    BUG_RETURN_VAL(minval > maxval && mode == Absolute, FALSE);
+
+    ax = dev->valuator->axes + axnum;
+
+    ax->min_value = minval;
+    ax->max_value = maxval;
+    ax->resolution = resolution;
+    ax->min_resolution = min_res;
+    ax->max_resolution = max_res;
+    ax->label = label;
+    ax->mode = mode;
+
+    if (mode & OutOfProximity)
+        dev->proximity->in_proximity = FALSE;
+
+    return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE);
+}
+
+/**
+ * Set the given axis number as a scrolling valuator.
+ */
+Bool
+SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type,
+                  double increment, int flags)
+{
+    AxisInfoPtr ax;
+    int *current_ax;
+    InternalEvent dce;
+    DeviceIntPtr master;
+
+    BUG_RETURN_VAL(dev == NULL, FALSE);
+    BUG_RETURN_VAL(dev->valuator == NULL, FALSE);
+    BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE);
+
+    switch (type) {
+    case SCROLL_TYPE_VERTICAL:
+        current_ax = &dev->valuator->v_scroll_axis;
+        break;
+    case SCROLL_TYPE_HORIZONTAL:
+        current_ax = &dev->valuator->h_scroll_axis;
+        break;
+    case SCROLL_TYPE_NONE:
+        ax = &dev->valuator->axes[axnum];
+        ax->scroll.type = type;
+        return TRUE;
+    default:
+        return FALSE;
+    }
+
+    if (increment == 0.0)
+        return FALSE;
+
+    if (*current_ax != -1 && axnum != *current_ax) {
+        ax = &dev->valuator->axes[*current_ax];
+        if (ax->scroll.type == type &&
+            (flags & SCROLL_FLAG_PREFERRED) &&
+            (ax->scroll.flags & SCROLL_FLAG_PREFERRED))
+            return FALSE;
+    }
+    *current_ax = axnum;
+
+    ax = &dev->valuator->axes[axnum];
+    ax->scroll.type = type;
+    ax->scroll.increment = increment;
+    ax->scroll.flags = flags;
+
+    master = GetMaster(dev, MASTER_ATTACHED);
+    CreateClassesChangedEvent(&dce, master, dev,
+                              DEVCHANGE_POINTER_EVENT |
+                              DEVCHANGE_DEVICE_CHANGE);
+    XISendDeviceChangedEvent(dev, &dce.changed_event);
+
+    /* if the current slave is us, update the master. If not, we'll update
+     * whenever the next slave switch happens anyway. CMDC sends the event
+     * for us */
+    if (master && master->lastSlave == dev)
+        ChangeMasterDeviceClasses(master, &dce.changed_event);
+
+    return TRUE;
+}
+
+int
+CheckGrabValues(ClientPtr client, GrabParameters *param)
+{
+    if (param->grabtype != CORE &&
+        param->grabtype != XI && param->grabtype != XI2) {
+        ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
+        return BadImplementation;
+    }
+
+    if ((param->this_device_mode != GrabModeSync) &&
+        (param->this_device_mode != GrabModeAsync) &&
+        (param->this_device_mode != XIGrabModeTouch)) {
+        client->errorValue = param->this_device_mode;
+        return BadValue;
+    }
+    if ((param->other_devices_mode != GrabModeSync) &&
+        (param->other_devices_mode != GrabModeAsync) &&
+        (param->other_devices_mode != XIGrabModeTouch)) {
+        client->errorValue = param->other_devices_mode;
+        return BadValue;
+    }
+
+    if (param->modifiers != AnyModifier &&
+        param->modifiers != XIAnyModifier &&
+        (param->modifiers & ~AllModifiersMask)) {
+        client->errorValue = param->modifiers;
+        return BadValue;
+    }
+
+    if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
+        client->errorValue = param->ownerEvents;
+        return BadValue;
+    }
+    return Success;
+}
+
+int
+GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
+           int button, GrabParameters *param, enum InputLevel grabtype,
+           GrabMask *mask)
+{
+    WindowPtr pWin, confineTo;
+    CursorPtr cursor;
+    GrabPtr grab;
+    int rc, type = -1;
+    Mask access_mode = DixGrabAccess;
+
+    rc = CheckGrabValues(client, param);
+    if (rc != Success)
+        return rc;
+    if (param->confineTo == None)
+        confineTo = NullWindow;
+    else {
+        rc = dixLookupWindow(&confineTo, param->confineTo, client,
+                             DixSetAttrAccess);
+        if (rc != Success)
+            return rc;
+    }
+    if (param->cursor == None)
+        cursor = NullCursor;
+    else {
+        rc = dixLookupResourceByType((void **) &cursor, param->cursor,
+                                     RT_CURSOR, client, DixUseAccess);
+        if (rc != Success) {
+            client->errorValue = param->cursor;
+            return rc;
+        }
+        access_mode |= DixForceAccess;
+    }
+    if (param->this_device_mode == GrabModeSync ||
+        param->other_devices_mode == GrabModeSync)
+        access_mode |= DixFreezeAccess;
+    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
+    if (rc != Success)
+        return rc;
+    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
+    if (rc != Success)
+        return rc;
+
+    if (grabtype == XI)
+        type = DeviceButtonPress;
+    else if (grabtype == XI2)
+        type = XI_ButtonPress;
+
+    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
+                      mask, param, type, button, confineTo, cursor);
+    if (!grab)
+        return BadAlloc;
+    return AddPassiveGrabToList(client, grab);
+}
+
+/**
+ * Grab the given key.
+ */
+int
+GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
+        int key, GrabParameters *param, enum InputLevel grabtype,
+        GrabMask *mask)
+{
+    WindowPtr pWin;
+    GrabPtr grab;
+    KeyClassPtr k = dev->key;
+    Mask access_mode = DixGrabAccess;
+    int rc, type = -1;
+
+    rc = CheckGrabValues(client, param);
+    if (rc != Success)
+        return rc;
+    if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL)
+        return BadMatch;
+    if (grabtype == XI) {
+        if ((key > k->xkbInfo->desc->max_key_code ||
+             key < k->xkbInfo->desc->min_key_code)
+            && (key != AnyKey)) {
+            client->errorValue = key;
+            return BadValue;
+        }
+        type = DeviceKeyPress;
+    }
+    else if (grabtype == XI2)
+        type = XI_KeyPress;
+
+    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
+    if (rc != Success)
+        return rc;
+    if (param->this_device_mode == GrabModeSync ||
+        param->other_devices_mode == GrabModeSync)
+        access_mode |= DixFreezeAccess;
+    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
+    if (rc != Success)
+        return rc;
+
+    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
+                      mask, param, type, key, NULL, NULL);
+    if (!grab)
+        return BadAlloc;
+    return AddPassiveGrabToList(client, grab);
+}
+
+/* Enter/FocusIn grab */
+int
+GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
+           GrabParameters *param, GrabMask *mask)
+{
+    WindowPtr pWin;
+    CursorPtr cursor;
+    GrabPtr grab;
+    Mask access_mode = DixGrabAccess;
+    int rc;
+
+    rc = CheckGrabValues(client, param);
+    if (rc != Success)
+        return rc;
+
+    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
+    if (rc != Success)
+        return rc;
+    if (param->cursor == None)
+        cursor = NullCursor;
+    else {
+        rc = dixLookupResourceByType((void **) &cursor, param->cursor,
+                                     RT_CURSOR, client, DixUseAccess);
+        if (rc != Success) {
+            client->errorValue = param->cursor;
+            return rc;
+        }
+        access_mode |= DixForceAccess;
+    }
+    if (param->this_device_mode == GrabModeSync ||
+        param->other_devices_mode == GrabModeSync)
+        access_mode |= DixFreezeAccess;
+    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
+    if (rc != Success)
+        return rc;
+
+    grab = CreateGrab(client->index, dev, dev, pWin, XI2,
+                      mask, param,
+                      (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn, 0,
+                      NULL, cursor);
+
+    if (!grab)
+        return BadAlloc;
+
+    return AddPassiveGrabToList(client, grab);
+}
+
+/* Touch grab */
+int
+GrabTouchOrGesture(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
+                   int type, GrabParameters *param, GrabMask *mask)
+{
+    WindowPtr pWin;
+    GrabPtr grab;
+    int rc;
+
+    rc = CheckGrabValues(client, param);
+    if (rc != Success)
+        return rc;
+
+    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
+    if (rc != Success)
+        return rc;
+    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGrabAccess);
+    if (rc != Success)
+        return rc;
+
+    grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2,
+                      mask, param, type, 0, NullWindow, NullCursor);
+    if (!grab)
+        return BadAlloc;
+
+    return AddPassiveGrabToList(client, grab);
+}
+
+int
+SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
+                Mask mask, Mask exclusivemasks)
+{
+    int mskidx = dev->id;
+    int i, ret;
+    Mask check;
+    InputClientsPtr others;
+
+    check = (mask & exclusivemasks);
+    if (wOtherInputMasks(pWin)) {
+        if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {
+            /* It is illegal for two different clients to select on any of
+             * the events for maskcheck. However, it is OK, for some client
+             * to continue selecting on one of those events.
+             */
+            for (others = wOtherInputMasks(pWin)->inputClients; others;
+                 others = others->next) {
+                if (!SameClient(others, client) && (check &
+                                                    others->mask[mskidx]))
+                    return BadAccess;
+            }
+        }
+        for (others = wOtherInputMasks(pWin)->inputClients; others;
+             others = others->next) {
+            if (SameClient(others, client)) {
+                check = others->mask[mskidx];
+                others->mask[mskidx] = mask;
+                if (mask == 0) {
+                    for (i = 0; i < EMASKSIZE; i++)
+                        if (i != mskidx && others->mask[i] != 0)
+                            break;
+                    if (i == EMASKSIZE) {
+                        RecalculateDeviceDeliverableEvents(pWin);
+                        if (ShouldFreeInputMasks(pWin, FALSE))
+                            FreeResource(others->resource, RT_NONE);
+                        return Success;
+                    }
+                }
+                goto maskSet;
+            }
+        }
+    }
+    check = 0;
+    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
+        return ret;
+ maskSet:
+    if (dev->valuator)
+        if ((dev->valuator->motionHintWindow == pWin) &&
+            (mask & DevicePointerMotionHintMask) &&
+            !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
+            dev->valuator->motionHintWindow = NullWindow;
+    RecalculateDeviceDeliverableEvents(pWin);
+    return Success;
+}
+
+static void
+FreeInputClient(InputClientsPtr * other)
+{
+    xi2mask_free(&(*other)->xi2mask);
+    free(*other);
+    *other = NULL;
+}
+
+static InputClientsPtr
+AllocInputClient(void)
+{
+    return calloc(1, sizeof(InputClients));
+}
+
+int
+AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
+{
+    InputClientsPtr others;
+
+    if (!pWin->optional && !MakeWindowOptional(pWin))
+        return BadAlloc;
+    others = AllocInputClient();
+    if (!others)
+        return BadAlloc;
+    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
+        goto bail;
+    others->xi2mask = xi2mask_new();
+    if (!others->xi2mask)
+        goto bail;
+    others->mask[mskidx] = mask;
+    others->resource = FakeClientID(client->index);
+    others->next = pWin->optional->inputMasks->inputClients;
+    pWin->optional->inputMasks->inputClients = others;
+    if (!AddResource(others->resource, RT_INPUTCLIENT, (void *) pWin))
+        goto bail;
+    return Success;
+
+ bail:
+    FreeInputClient(&others);
+    return BadAlloc;
+}
+
+static Bool
+MakeInputMasks(WindowPtr pWin)
+{
+    struct _OtherInputMasks *imasks;
+
+    imasks = calloc(1, sizeof(struct _OtherInputMasks));
+    if (!imasks)
+        return FALSE;
+    imasks->xi2mask = xi2mask_new();
+    if (!imasks->xi2mask) {
+        free(imasks);
+        return FALSE;
+    }
+    pWin->optional->inputMasks = imasks;
+    return TRUE;
+}
+
+static void
+FreeInputMask(OtherInputMasks ** imask)
+{
+    xi2mask_free(&(*imask)->xi2mask);
+    free(*imask);
+    *imask = NULL;
+}
+
+#define XIPropagateMask (KeyPressMask | \
+                         KeyReleaseMask | \
+                         ButtonPressMask | \
+                         ButtonReleaseMask | \
+                         PointerMotionMask)
+
+void
+RecalculateDeviceDeliverableEvents(WindowPtr pWin)
+{
+    InputClientsPtr others;
+    struct _OtherInputMasks *inputMasks;        /* default: NULL */
+    WindowPtr pChild, tmp;
+    int i;
+
+    pChild = pWin;
+    while (1) {
+        if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
+            xi2mask_zero(inputMasks->xi2mask, -1);
+            for (others = inputMasks->inputClients; others;
+                 others = others->next) {
+                for (i = 0; i < EMASKSIZE; i++)
+                    inputMasks->inputEvents[i] |= others->mask[i];
+                xi2mask_merge(inputMasks->xi2mask, others->xi2mask);
+            }
+            for (i = 0; i < EMASKSIZE; i++)
+                inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
+            for (tmp = pChild->parent; tmp; tmp = tmp->parent)
+                if (wOtherInputMasks(tmp))
+                    for (i = 0; i < EMASKSIZE; i++)
+                        inputMasks->deliverableEvents[i] |=
+                            (wOtherInputMasks(tmp)->deliverableEvents[i]
+                             & ~inputMasks->dontPropagateMask[i] &
+                             XIPropagateMask);
+        }
+        if (pChild->firstChild) {
+            pChild = pChild->firstChild;
+            continue;
+        }
+        while (!pChild->nextSib && (pChild != pWin))
+            pChild = pChild->parent;
+        if (pChild == pWin)
+            break;
+        pChild = pChild->nextSib;
+    }
+}
+
+int
+InputClientGone(WindowPtr pWin, XID id)
+{
+    InputClientsPtr other, prev;
+
+    if (!wOtherInputMasks(pWin))
+        return Success;
+    prev = 0;
+    for (other = wOtherInputMasks(pWin)->inputClients; other;
+         other = other->next) {
+        if (other->resource == id) {
+            if (prev) {
+                prev->next = other->next;
+                FreeInputClient(&other);
+            }
+            else if (!(other->next)) {
+                if (ShouldFreeInputMasks(pWin, TRUE)) {
+                    OtherInputMasks *mask = wOtherInputMasks(pWin);
+
+                    mask->inputClients = other->next;
+                    FreeInputMask(&mask);
+                    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
+                    CheckWindowOptionalNeed(pWin);
+                    FreeInputClient(&other);
+                }
+                else {
+                    other->resource = FakeClientID(0);
+                    if (!AddResource(other->resource, RT_INPUTCLIENT,
+                                     (void *) pWin))
+                        return BadAlloc;
+                }
+            }
+            else {
+                wOtherInputMasks(pWin)->inputClients = other->next;
+                FreeInputClient(&other);
+            }
+            RecalculateDeviceDeliverableEvents(pWin);
+            return Success;
+        }
+        prev = other;
+    }
+    FatalError("client not on device event list");
+}
+
+/**
+ * Search for window in each touch trace for each device. Remove the window
+ * and all its subwindows from the trace when found. The initial window
+ * order is preserved.
+ */
+void
+WindowGone(WindowPtr win)
+{
+    DeviceIntPtr dev;
+
+    for (dev = inputInfo.devices; dev; dev = dev->next) {
+        TouchClassPtr t = dev->touch;
+        int i;
+
+        if (!t)
+            continue;
+
+        for (i = 0; i < t->num_touches; i++) {
+            SpritePtr sprite = &t->touches[i].sprite;
+            int j;
+
+            for (j = 0; j < sprite->spriteTraceGood; j++) {
+                if (sprite->spriteTrace[j] == win) {
+                    sprite->spriteTraceGood = j;
+                    break;
+                }
+            }
+        }
+    }
+}
+
+int
+SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
+          xEvent *ev, Mask mask, int count)
+{
+    WindowPtr pWin;
+    WindowPtr effectiveFocus = NullWindow;      /* only set if dest==InputFocus */
+    WindowPtr spriteWin = GetSpriteWindow(d);
+
+    if (dest == PointerWindow)
+        pWin = spriteWin;
+    else if (dest == InputFocus) {
+        WindowPtr inputFocus;
+
+        if (!d->focus)
+            inputFocus = spriteWin;
+        else
+            inputFocus = d->focus->win;
+
+        if (inputFocus == FollowKeyboardWin)
+            inputFocus = inputInfo.keyboard->focus->win;
+
+        if (inputFocus == NoneWin)
+            return Success;
+
+        /* If the input focus is PointerRootWin, send the event to where
+         * the pointer is if possible, then perhaps propagate up to root. */
+        if (inputFocus == PointerRootWin)
+            inputFocus = GetCurrentRootWindow(d);
+
+        if (IsParent(inputFocus, spriteWin)) {
+            effectiveFocus = inputFocus;
+            pWin = spriteWin;
+        }
+        else
+            effectiveFocus = pWin = inputFocus;
+    }
+    else
+        dixLookupWindow(&pWin, dest, client, DixSendAccess);
+    if (!pWin)
+        return BadWindow;
+    if ((propagate != xFalse) && (propagate != xTrue)) {
+        client->errorValue = propagate;
+        return BadValue;
+    }
+    ev->u.u.type |= 0x80;
+    if (propagate) {
+        for (; pWin; pWin = pWin->parent) {
+            if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
+                return Success;
+            if (pWin == effectiveFocus)
+                return Success;
+            if (wOtherInputMasks(pWin))
+                mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
+            if (!mask)
+                break;
+        }
+    }
+    else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
+        DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
+    return Success;
+}
+
+int
+SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
+{
+    int i;
+    ButtonClassPtr b = dev->button;
+
+    if (b == NULL)
+        return BadMatch;
+
+    if (nElts != b->numButtons) {
+        client->errorValue = nElts;
+        return BadValue;
+    }
+    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
+        return BadValue;
+    for (i = 0; i < nElts; i++)
+        if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
+            return MappingBusy;
+    for (i = 0; i < nElts; i++)
+        b->map[i + 1] = map[i];
+    return Success;
+}
+
+int
+ChangeKeyMapping(ClientPtr client,
+                 DeviceIntPtr dev,
+                 unsigned len,
+                 int type,
+                 KeyCode firstKeyCode,
+                 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
+{
+    KeySymsRec keysyms;
+    KeyClassPtr k = dev->key;
+
+    if (k == NULL)
+        return BadMatch;
+
+    if (len != (keyCodes * keySymsPerKeyCode))
+        return BadLength;
+
+    if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
+        (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
+        client->errorValue = firstKeyCode;
+        return BadValue;
+    }
+    if (keySymsPerKeyCode == 0) {
+        client->errorValue = 0;
+        return BadValue;
+    }
+    keysyms.minKeyCode = firstKeyCode;
+    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
+    keysyms.mapWidth = keySymsPerKeyCode;
+    keysyms.map = map;
+
+    XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
+                          serverClient);
+
+    return Success;
+}
+
+static void
+DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
+{
+    WindowPtr parent;
+
+    /* Deactivate any grabs performed on this window, before making
+     * any input focus changes.
+     * Deactivating a device grab should cause focus events. */
+
+    if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
+        (*dev->deviceGrab.DeactivateGrab) (dev);
+
+    /* If the focus window is a root window (ie. has no parent)
+     * then don't delete the focus from it. */
+
+    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
+        int focusEventMode = NotifyNormal;
+
+        /* If a grab is in progress, then alter the mode of focus events. */
+
+        if (dev->deviceGrab.grab)
+            focusEventMode = NotifyWhileGrabbed;
+
+        switch (dev->focus->revert) {
+        case RevertToNone:
+            if (!ActivateFocusInGrab(dev, pWin, NoneWin))
+                DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
+            dev->focus->win = NoneWin;
+            dev->focus->traceGood = 0;
+            break;
+        case RevertToParent:
+            parent = pWin;
+            do {
+                parent = parent->parent;
+                dev->focus->traceGood--;
+            }
+            while (!parent->realized);
+            if (!ActivateFocusInGrab(dev, pWin, parent))
+                DoFocusEvents(dev, pWin, parent, focusEventMode);
+            dev->focus->win = parent;
+            dev->focus->revert = RevertToNone;
+            break;
+        case RevertToPointerRoot:
+            if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
+                DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
+            dev->focus->win = PointerRootWin;
+            dev->focus->traceGood = 0;
+            break;
+        case RevertToFollowKeyboard:
+        {
+            DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
+
+            if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
+                kbd = inputInfo.keyboard;
+            if (kbd->focus->win) {
+                if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
+                    DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
+                dev->focus->win = FollowKeyboardWin;
+                dev->focus->traceGood = 0;
+            }
+            else {
+                if (!ActivateFocusInGrab(dev, pWin, NoneWin))
+                    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
+                dev->focus->win = NoneWin;
+                dev->focus->traceGood = 0;
+            }
+        }
+            break;
+        }
+    }
+
+    if (dev->valuator)
+        if (dev->valuator->motionHintWindow == pWin)
+            dev->valuator->motionHintWindow = NullWindow;
+}
+
+void
+DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
+{
+    int i;
+    DeviceIntPtr dev;
+    InputClientsPtr ic;
+    struct _OtherInputMasks *inputMasks;
+
+    for (dev = inputInfo.devices; dev; dev = dev->next) {
+        DeleteDeviceFromAnyExtEvents(pWin, dev);
+    }
+
+    for (dev = inputInfo.off_devices; dev; dev = dev->next)
+        DeleteDeviceFromAnyExtEvents(pWin, dev);
+
+    if (freeResources)
+        while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
+            ic = inputMasks->inputClients;
+            for (i = 0; i < EMASKSIZE; i++)
+                inputMasks->dontPropagateMask[i] = 0;
+            FreeResource(ic->resource, RT_NONE);
+        }
+}
+
+int
+MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer *pEvents, Mask mask)
+{
+    DeviceIntPtr dev;
+
+    dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
+                    DixReadAccess);
+    if (!dev)
+        return 0;
+
+    if (pEvents->type == DeviceMotionNotify) {
+        if (mask & DevicePointerMotionHintMask) {
+            if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
+                return 1;       /* don't send, but pretend we did */
+            }
+            pEvents->detail = NotifyHint;
+        }
+        else {
+            pEvents->detail = NotifyNormal;
+        }
+    }
+    return 0;
+}
+
+void
+CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
+                             deviceKeyButtonPointer *xE, GrabPtr grab,
+                             ClientPtr client, Mask deliveryMask)
+{
+    DeviceIntPtr dev;
+
+    dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
+                    DixGrabAccess);
+    if (!dev)
+        return;
+
+    if (type == DeviceMotionNotify)
+        dev->valuator->motionHintWindow = pWin;
+    else if ((type == DeviceButtonPress) && (!grab) &&
+             (deliveryMask & DeviceButtonGrabMask)) {
+        GrabPtr tempGrab;
+
+        tempGrab = AllocGrab(NULL);
+        if (!tempGrab)
+            return;
+
+        tempGrab->device = dev;
+        tempGrab->resource = client->clientAsMask;
+        tempGrab->window = pWin;
+        tempGrab->ownerEvents =
+            (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
+        tempGrab->eventMask = deliveryMask;
+        tempGrab->keyboardMode = GrabModeAsync;
+        tempGrab->pointerMode = GrabModeAsync;
+        tempGrab->confineTo = NullWindow;
+        tempGrab->cursor = NullCursor;
+        tempGrab->next = NULL;
+        (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE);
+        FreeGrab(tempGrab);
+    }
+}
+
+static Mask
+DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
+{
+    InputClientsPtr other;
+
+    if (!wOtherInputMasks(pWin))
+        return 0;
+    for (other = wOtherInputMasks(pWin)->inputClients; other;
+         other = other->next) {
+        if (SameClient(other, client))
+            return other->mask[dev->id];
+    }
+    return 0;
+}
+
+void
+MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
+{
+    WindowPtr pWin;
+    GrabPtr grab = dev->deviceGrab.grab;
+
+    pWin = dev->valuator->motionHintWindow;
+
+    if ((grab && SameClient(grab, client) &&
+         ((grab->eventMask & DevicePointerMotionHintMask) ||
+          (grab->ownerEvents &&
+           (DeviceEventMaskForClient(dev, pWin, client) &
+            DevicePointerMotionHintMask)))) ||
+        (!grab &&
+         (DeviceEventMaskForClient(dev, pWin, client) &
+          DevicePointerMotionHintMask)))
+        dev->valuator->motionHintWindow = NullWindow;
+}
+
+int
+DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
+                             int maskndx)
+{
+    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
+
+    if (mask & ~XIPropagateMask) {
+        client->errorValue = mask;
+        return BadValue;
+    }
+
+    if (mask == 0) {
+        if (inputMasks)
+            inputMasks->dontPropagateMask[maskndx] = mask;
+    }
+    else {
+        if (!inputMasks)
+            AddExtensionClient(pWin, client, 0, 0);
+        inputMasks = wOtherInputMasks(pWin);
+        inputMasks->dontPropagateMask[maskndx] = mask;
+    }
+    RecalculateDeviceDeliverableEvents(pWin);
+    if (ShouldFreeInputMasks(pWin, FALSE))
+        FreeResource(inputMasks->inputClients->resource, RT_NONE);
+    return Success;
+}
+
+Bool
+ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
+{
+    int i;
+    Mask allInputEventMasks = 0;
+    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
+
+    for (i = 0; i < EMASKSIZE; i++)
+        allInputEventMasks |= inputMasks->dontPropagateMask[i];
+    if (!ignoreSelectedEvents)
+        for (i = 0; i < EMASKSIZE; i++)
+            allInputEventMasks |= inputMasks->inputEvents[i];
+    if (allInputEventMasks == 0)
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/***********************************************************************
+ *
+ * Walk through the window tree, finding all clients that want to know
+ * about the Event.
+ *
+ */
+
+static void
+FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
+                       xEvent *ev, int count)
+{
+    WindowPtr p2;
+
+    while (p1) {
+        p2 = p1->firstChild;
+        DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
+        FindInterestedChildren(dev, p2, mask, ev, count);
+        p1 = p1->nextSib;
+    }
+}
+
+/***********************************************************************
+ *
+ * Send an event to interested clients in all windows on all screens.
+ *
+ */
+
+void
+SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent *ev, int count)
+{
+    int i;
+    WindowPtr pWin, p1;
+
+    for (i = 0; i < screenInfo.numScreens; i++) {
+        pWin = screenInfo.screens[i]->root;
+        if (!pWin)
+            continue;
+        DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
+        p1 = pWin->firstChild;
+        FindInterestedChildren(dev, p1, mask, ev, count);
+    }
+}
+
+/**
+ * Set the XI2 mask for the given client on the given window.
+ * @param dev The device to set the mask for.
+ * @param win The window to set the mask on.
+ * @param client The client setting the mask.
+ * @param len Number of bytes in mask.
+ * @param mask Event mask in the form of (1 << eventtype)
+ */
+int
+XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
+               unsigned int len, unsigned char *mask)
+{
+    OtherInputMasks *masks;
+    InputClientsPtr others = NULL;
+
+    masks = wOtherInputMasks(win);
+    if (masks) {
+        for (others = wOtherInputMasks(win)->inputClients; others;
+             others = others->next) {
+            if (SameClient(others, client)) {
+                xi2mask_zero(others->xi2mask, dev->id);
+                break;
+            }
+        }
+    }
+
+    if (len && !others) {
+        if (AddExtensionClient(win, client, 0, 0) != Success)
+            return BadAlloc;
+        others = wOtherInputMasks(win)->inputClients;
+    }
+
+    if (others) {
+        xi2mask_zero(others->xi2mask, dev->id);
+        len = min(len, xi2mask_mask_size(others->xi2mask));
+    }
+
+    if (len) {
+        xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len);
+    }
+
+    RecalculateDeviceDeliverableEvents(win);
+
+    return Success;
+}
Index: xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/Xi
===================================================================
--- xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/Xi	(nonexistent)
+++ xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/Xi	(revision 5)

Property changes on: xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/Xi
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/dix/getevents.c
===================================================================
--- xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/dix/getevents.c	(nonexistent)
+++ xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/dix/getevents.c	(revision 5)
@@ -0,0 +1,2246 @@
+/*
+ * Copyright © 2006 Nokia Corporation
+ * Copyright © 2006-2007 Daniel Stone
+ * Copyright © 2008 Red Hat, Inc.
+ * Copyright © 2011 The Chromium Authors
+ *
+ * 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 (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Authors: Daniel Stone <daniel@fooishbar.org>
+ *          Peter Hutterer <peter.hutterer@who-t.net>
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/keysym.h>
+#include <X11/Xproto.h>
+#include <math.h>
+#include <limits.h>
+
+#include "misc.h"
+#include "resource.h"
+#include "inputstr.h"
+#include "scrnintstr.h"
+#include "cursorstr.h"
+#include "dixstruct.h"
+#include "globals.h"
+#include "dixevents.h"
+#include "mipointer.h"
+#include "eventstr.h"
+#include "eventconvert.h"
+#include "inpututils.h"
+#include "mi.h"
+#include "windowstr.h"
+
+#include <X11/extensions/XKBproto.h>
+#include "xkbsrv.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XI2.h>
+#include <X11/extensions/XIproto.h>
+#include <pixman.h>
+#include "exglobals.h"
+#include "exevents.h"
+#include "extnsionst.h"
+#include "listdev.h"            /* for sizing up DeviceClassesChangedEvent */
+#include "probes.h"
+
+/* Number of motion history events to store. */
+#define MOTION_HISTORY_SIZE 256
+
+/**
+ * InputEventList is the storage for input events generated by
+ * QueuePointerEvents, QueueKeyboardEvents, and QueueProximityEvents.
+ * This list is allocated on startup by the DIX.
+ */
+InternalEvent *InputEventList = NULL;
+
+/**
+ * Pick some arbitrary size for Xi motion history.
+ */
+int
+GetMotionHistorySize(void)
+{
+    return MOTION_HISTORY_SIZE;
+}
+
+void
+set_button_down(DeviceIntPtr pDev, int button, int type)
+{
+    if (type == BUTTON_PROCESSED)
+        SetBit(pDev->button->down, button);
+    else
+        SetBit(pDev->button->postdown, button);
+}
+
+void
+set_button_up(DeviceIntPtr pDev, int button, int type)
+{
+    if (type == BUTTON_PROCESSED)
+        ClearBit(pDev->button->down, button);
+    else
+        ClearBit(pDev->button->postdown, button);
+}
+
+Bool
+button_is_down(DeviceIntPtr pDev, int button, int type)
+{
+    Bool ret = FALSE;
+
+    if (type & BUTTON_PROCESSED)
+        ret = ret || BitIsOn(pDev->button->down, button);
+    if (type & BUTTON_POSTED)
+        ret = ret || BitIsOn(pDev->button->postdown, button);
+
+    return ret;
+}
+
+void
+set_key_down(DeviceIntPtr pDev, int key_code, int type)
+{
+    if (type == KEY_PROCESSED)
+        SetBit(pDev->key->down, key_code);
+    else
+        SetBit(pDev->key->postdown, key_code);
+}
+
+void
+set_key_up(DeviceIntPtr pDev, int key_code, int type)
+{
+    if (type == KEY_PROCESSED)
+        ClearBit(pDev->key->down, key_code);
+    else
+        ClearBit(pDev->key->postdown, key_code);
+}
+
+Bool
+key_is_down(DeviceIntPtr pDev, int key_code, int type)
+{
+    Bool ret = FALSE;
+
+    if (type & KEY_PROCESSED)
+        ret = ret || BitIsOn(pDev->key->down, key_code);
+    if (type & KEY_POSTED)
+        ret = ret || BitIsOn(pDev->key->postdown, key_code);
+
+    return ret;
+}
+
+static Bool
+key_autorepeats(DeviceIntPtr pDev, int key_code)
+{
+    return ! !(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
+               (1 << (key_code & 7)));
+}
+
+static void
+init_touch_ownership(DeviceIntPtr dev, TouchOwnershipEvent *event, Time ms)
+{
+    memset(event, 0, sizeof(TouchOwnershipEvent));
+    event->header = ET_Internal;
+    event->type = ET_TouchOwnership;
+    event->length = sizeof(TouchOwnershipEvent);
+    event->time = ms;
+    event->deviceid = dev->id;
+}
+
+static void
+init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
+{
+    memset(event, 0, sizeof(RawDeviceEvent));
+    event->header = ET_Internal;
+    event->length = sizeof(RawDeviceEvent);
+    switch (type) {
+    case MotionNotify:
+        event->type = ET_RawMotion;
+        break;
+    case ButtonPress:
+        event->type = ET_RawButtonPress;
+        break;
+    case ButtonRelease:
+        event->type = ET_RawButtonRelease;
+        break;
+    case KeyPress:
+        event->type = ET_RawKeyPress;
+        break;
+    case KeyRelease:
+        event->type = ET_RawKeyRelease;
+        break;
+    case XI_TouchBegin:
+        event->type = ET_RawTouchBegin;
+        break;
+    case XI_TouchUpdate:
+        event->type = ET_RawTouchUpdate;
+        break;
+    case XI_TouchEnd:
+        event->type = ET_RawTouchEnd;
+        break;
+    }
+    event->time = ms;
+    event->deviceid = dev->id;
+    event->sourceid = dev->id;
+    event->detail.button = detail;
+}
+
+static void
+set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask,
+                  BOOL use_unaccel, double *data)
+{
+    int i;
+
+    use_unaccel = use_unaccel && valuator_mask_has_unaccelerated(mask);
+
+    for (i = 0; i < valuator_mask_size(mask); i++) {
+        if (valuator_mask_isset(mask, i)) {
+            double v;
+
+            SetBit(event->valuators.mask, i);
+
+            if (use_unaccel)
+                v = valuator_mask_get_unaccelerated(mask, i);
+            else
+                v = valuator_mask_get_double(mask, i);
+
+            data[i] = v;
+        }
+    }
+}
+
+static void
+set_valuators(DeviceIntPtr dev, DeviceEvent *event, ValuatorMask *mask)
+{
+    int i;
+
+    /* Set the data to the previous value for unset absolute axes. The values
+     * may be used when sent as part of an XI 1.x valuator event. */
+    for (i = 0; i < valuator_mask_size(mask); i++) {
+        if (valuator_mask_isset(mask, i)) {
+            SetBit(event->valuators.mask, i);
+            if (valuator_get_mode(dev, i) == Absolute)
+                SetBit(event->valuators.mode, i);
+            event->valuators.data[i] = valuator_mask_get_double(mask, i);
+        }
+        else
+            event->valuators.data[i] = dev->valuator->axisVal[i];
+    }
+}
+
+void
+CreateClassesChangedEvent(InternalEvent *event,
+                          DeviceIntPtr master, DeviceIntPtr slave, int flags)
+{
+    int i;
+    DeviceChangedEvent *dce;
+    CARD32 ms = GetTimeInMillis();
+
+    dce = &event->changed_event;
+    memset(dce, 0, sizeof(DeviceChangedEvent));
+    dce->deviceid = slave->id;
+    dce->masterid = master ? master->id : 0;
+    dce->header = ET_Internal;
+    dce->length = sizeof(DeviceChangedEvent);
+    dce->type = ET_DeviceChanged;
+    dce->time = ms;
+    dce->flags = flags;
+    dce->sourceid = slave->id;
+
+    if (slave->button) {
+        dce->buttons.num_buttons = slave->button->numButtons;
+        for (i = 0; i < dce->buttons.num_buttons; i++)
+            dce->buttons.names[i] = slave->button->labels[i];
+    }
+    if (slave->valuator) {
+        dce->num_valuators = slave->valuator->numAxes;
+        for (i = 0; i < dce->num_valuators; i++) {
+            dce->valuators[i].min = slave->valuator->axes[i].min_value;
+            dce->valuators[i].max = slave->valuator->axes[i].max_value;
+            dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
+            dce->valuators[i].mode = slave->valuator->axes[i].mode;
+            dce->valuators[i].name = slave->valuator->axes[i].label;
+            dce->valuators[i].scroll = slave->valuator->axes[i].scroll;
+            dce->valuators[i].value = slave->valuator->axisVal[i];
+        }
+    }
+    if (slave->key) {
+        dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code;
+        dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code;
+    }
+}
+
+/**
+ * Rescale the coord between the two axis ranges.
+ */
+static double
+rescaleValuatorAxis(double coord, AxisInfoPtr from, AxisInfoPtr to,
+                    double defmin, double defmax)
+{
+    double fmin = defmin, fmax = defmax;
+    double tmin = defmin, tmax = defmax;
+
+    if (from && from->min_value < from->max_value) {
+        fmin = from->min_value;
+        fmax = from->max_value + 1;
+    }
+    if (to && to->min_value < to->max_value) {
+        tmin = to->min_value;
+        tmax = to->max_value + 1;
+    }
+
+    if (fmin == tmin && fmax == tmax)
+        return coord;
+
+    if (fmax == fmin)           /* avoid division by 0 */
+        return 0.0;
+
+    return (coord - fmin) * (tmax - tmin) / (fmax - fmin) + tmin;
+}
+
+/**
+ * Update all coordinates when changing to a different SD
+ * to ensure that relative reporting will work as expected
+ * without loss of precision.
+ *
+ * pDev->last.valuators will be in absolute device coordinates after this
+ * function.
+ */
+static void
+updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
+{
+    /* master->last.valuators[0]/[1] is in desktop-wide coords and the actual
+     * position of the pointer */
+    pDev->last.valuators[0] = master->last.valuators[0];
+    pDev->last.valuators[1] = master->last.valuators[1];
+
+    if (!pDev->valuator)
+        return;
+
+    /* scale back to device coordinates */
+    if (pDev->valuator->numAxes > 0) {
+        pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0],
+                                                      NULL,
+                                                      pDev->valuator->axes + 0,
+                                                      screenInfo.x,
+                                                      screenInfo.width);
+    }
+    if (pDev->valuator->numAxes > 1) {
+        pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1],
+                                                      NULL,
+                                                      pDev->valuator->axes + 1,
+                                                      screenInfo.y,
+                                                      screenInfo.height);
+    }
+
+    /* other axes are left as-is */
+}
+
+/**
+ * Allocate the motion history buffer.
+ */
+void
+AllocateMotionHistory(DeviceIntPtr pDev)
+{
+    int size;
+
+    free(pDev->valuator->motion);
+
+    if (pDev->valuator->numMotionEvents < 1)
+        return;
+
+    /* An MD must have a motion history size large enough to keep all
+     * potential valuators, plus the respective range of the valuators.
+     * 3 * INT32 for (min_val, max_val, curr_val))
+     */
+    if (IsMaster(pDev))
+        size = sizeof(INT32) * 3 * MAX_VALUATORS;
+    else {
+        ValuatorClassPtr v = pDev->valuator;
+        int numAxes;
+
+        /* XI1 doesn't understand mixed mode devices */
+        for (numAxes = 0; numAxes < v->numAxes; numAxes++)
+            if (valuator_get_mode(pDev, numAxes) != valuator_get_mode(pDev, 0))
+                break;
+        size = sizeof(INT32) * numAxes;
+    }
+
+    size += sizeof(Time);
+
+    pDev->valuator->motion = calloc(pDev->valuator->numMotionEvents, size);
+    pDev->valuator->first_motion = 0;
+    pDev->valuator->last_motion = 0;
+    if (!pDev->valuator->motion)
+        ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n",
+               pDev->name, size * pDev->valuator->numMotionEvents);
+}
+
+/**
+ * Dump the motion history between start and stop into the supplied buffer.
+ * Only records the event for a given screen in theory, but in practice, we
+ * sort of ignore this.
+ *
+ * If core is set, we only generate x/y, in INT16, scaled to screen coords.
+ */
+int
+GetMotionHistory(DeviceIntPtr pDev, xTimecoord ** buff, unsigned long start,
+                 unsigned long stop, ScreenPtr pScreen, BOOL core)
+{
+    char *ibuff = NULL, *obuff;
+    int i = 0, ret = 0;
+    int j, coord;
+    Time current;
+
+    /* The size of a single motion event. */
+    int size;
+    AxisInfo from, *to;         /* for scaling */
+    INT32 *ocbuf, *icbuf;       /* pointer to coordinates for copying */
+    INT16 *corebuf;
+    AxisInfo core_axis = { 0 };
+
+    if (!pDev->valuator || !pDev->valuator->numMotionEvents)
+        return 0;
+
+    if (core && !pScreen)
+        return 0;
+
+    if (IsMaster(pDev))
+        size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
+    else
+        size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
+
+    *buff = malloc(size * pDev->valuator->numMotionEvents);
+    if (!(*buff))
+        return 0;
+    obuff = (char *) *buff;
+
+    for (i = pDev->valuator->first_motion;
+         i != pDev->valuator->last_motion;
+         i = (i + 1) % pDev->valuator->numMotionEvents) {
+        /* We index the input buffer by which element we're accessing, which
+         * is not monotonic, and the output buffer by how many events we've
+         * written so far. */
+        ibuff = (char *) pDev->valuator->motion + (i * size);
+        memcpy(&current, ibuff, sizeof(Time));
+
+        if (current > stop) {
+            return ret;
+        }
+        else if (current >= start) {
+            if (core) {
+                memcpy(obuff, ibuff, sizeof(Time));     /* copy timestamp */
+
+                icbuf = (INT32 *) (ibuff + sizeof(Time));
+                corebuf = (INT16 *) (obuff + sizeof(Time));
+
+                /* fetch x coordinate + range */
+                memcpy(&from.min_value, icbuf++, sizeof(INT32));
+                memcpy(&from.max_value, icbuf++, sizeof(INT32));
+                memcpy(&coord, icbuf++, sizeof(INT32));
+
+                /* scale to screen coords */
+                to = &core_axis;
+                to->max_value = pScreen->width;
+                coord =
+                    rescaleValuatorAxis(coord, &from, to, 0, pScreen->width);
+
+                memcpy(corebuf, &coord, sizeof(INT16));
+                corebuf++;
+
+                /* fetch y coordinate + range */
+                memcpy(&from.min_value, icbuf++, sizeof(INT32));
+                memcpy(&from.max_value, icbuf++, sizeof(INT32));
+                memcpy(&coord, icbuf++, sizeof(INT32));
+
+                to->max_value = pScreen->height;
+                coord =
+                    rescaleValuatorAxis(coord, &from, to, 0, pScreen->height);
+                memcpy(corebuf, &coord, sizeof(INT16));
+
+            }
+            else if (IsMaster(pDev)) {
+                memcpy(obuff, ibuff, sizeof(Time));     /* copy timestamp */
+
+                ocbuf = (INT32 *) (obuff + sizeof(Time));
+                icbuf = (INT32 *) (ibuff + sizeof(Time));
+                for (j = 0; j < MAX_VALUATORS; j++) {
+                    if (j >= pDev->valuator->numAxes)
+                        break;
+
+                    /* fetch min/max/coordinate */
+                    memcpy(&from.min_value, icbuf++, sizeof(INT32));
+                    memcpy(&from.max_value, icbuf++, sizeof(INT32));
+                    memcpy(&coord, icbuf++, sizeof(INT32));
+
+                    to = (j <
+                          pDev->valuator->numAxes) ? &pDev->valuator->
+                        axes[j] : NULL;
+
+                    /* x/y scaled to screen if no range is present */
+                    if (j == 0 && (from.max_value < from.min_value))
+                        from.max_value = pScreen->width;
+                    else if (j == 1 && (from.max_value < from.min_value))
+                        from.max_value = pScreen->height;
+
+                    /* scale from stored range into current range */
+                    coord = rescaleValuatorAxis(coord, &from, to, 0, 0);
+                    memcpy(ocbuf, &coord, sizeof(INT32));
+                    ocbuf++;
+                }
+            }
+            else
+                memcpy(obuff, ibuff, size);
+
+            /* don't advance by size here. size may be different to the
+             * actually written size if the MD has less valuators than MAX */
+            if (core)
+                obuff += sizeof(INT32) + sizeof(Time);
+            else
+                obuff +=
+                    (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
+            ret++;
+        }
+    }
+
+    return ret;
+}
+
+/**
+ * Update the motion history for a specific device, with the list of
+ * valuators.
+ *
+ * Layout of the history buffer:
+ *   for SDs: [time] [val0] [val1] ... [valn]
+ *   for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn]
+ *
+ * For events that have some valuators unset:
+ *      min_val == max_val == val == 0.
+ */
+static void
+updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
+                    double *valuators)
+{
+    char *buff = (char *) pDev->valuator->motion;
+    ValuatorClassPtr v;
+    int i;
+
+    if (!pDev->valuator->numMotionEvents)
+        return;
+
+    v = pDev->valuator;
+    if (IsMaster(pDev)) {
+        buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
+            v->last_motion;
+
+        memcpy(buff, &ms, sizeof(Time));
+        buff += sizeof(Time);
+
+        memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);
+
+        for (i = 0; i < v->numAxes; i++) {
+            int val;
+
+            /* XI1 doesn't support mixed mode devices */
+            if (valuator_get_mode(pDev, i) != valuator_get_mode(pDev, 0))
+                break;
+            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) {
+                buff += 3 * sizeof(INT32);
+                continue;
+            }
+            memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
+            buff += sizeof(INT32);
+            memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
+            buff += sizeof(INT32);
+            val = valuators[i];
+            memcpy(buff, &val, sizeof(INT32));
+            buff += sizeof(INT32);
+        }
+    }
+    else {
+
+        buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
+            pDev->valuator->last_motion;
+
+        memcpy(buff, &ms, sizeof(Time));
+        buff += sizeof(Time);
+
+        memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
+
+        for (i = 0; i < MAX_VALUATORS; i++) {
+            int val;
+
+            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) {
+                buff += sizeof(INT32);
+                continue;
+            }
+            val = valuators[i];
+            memcpy(buff, &val, sizeof(INT32));
+            buff += sizeof(INT32);
+        }
+    }
+
+    pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
+        pDev->valuator->numMotionEvents;
+    /* If we're wrapping around, just keep the circular buffer going. */
+    if (pDev->valuator->first_motion == pDev->valuator->last_motion)
+        pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
+            pDev->valuator->numMotionEvents;
+
+    return;
+}
+
+/**
+ * Returns the maximum number of events GetKeyboardEvents
+ * and GetPointerEvents will ever return.
+ *
+ * This MUST be absolutely constant, from init until exit.
+ */
+int
+GetMaximumEventsNum(void)
+{
+    /* One raw event
+     * One device event
+     * One possible device changed event
+     * Lots of possible separate button scroll events (horiz + vert)
+     * Lots of possible separate raw button scroll events (horiz + vert)
+     */
+    return 100;
+}
+
+/**
+ * Clip an axis to its bounds, which are declared in the call to
+ * InitValuatorAxisClassStruct.
+ */
+static void
+clipAxis(DeviceIntPtr pDev, int axisNum, double *val)
+{
+    AxisInfoPtr axis;
+
+    if (axisNum >= pDev->valuator->numAxes)
+        return;
+
+    axis = pDev->valuator->axes + axisNum;
+
+    /* If a value range is defined, clip. If not, do nothing */
+    if (axis->max_value <= axis->min_value)
+        return;
+
+    if (*val < axis->min_value)
+        *val = axis->min_value;
+    if (*val > axis->max_value)
+        *val = axis->max_value;
+}
+
+/**
+ * Clip every axis in the list of valuators to its bounds.
+ */
+static void
+clipValuators(DeviceIntPtr pDev, ValuatorMask *mask)
+{
+    int i;
+
+    for (i = 0; i < valuator_mask_size(mask); i++)
+        if (valuator_mask_isset(mask, i)) {
+            double val = valuator_mask_get_double(mask, i);
+
+            clipAxis(pDev, i, &val);
+            valuator_mask_set_double(mask, i, val);
+        }
+}
+
+/**
+ * Create the DCCE event (does not update the master's device state yet, this
+ * is done in the event processing).
+ * Pull in the coordinates from the MD if necessary.
+ *
+ * @param events Pointer to a pre-allocated event array.
+ * @param dev The slave device that generated an event.
+ * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT
+ * @param num_events The current number of events, returns the number of
+ *        events if a DCCE was generated.
+ * @return The updated @events pointer.
+ */
+InternalEvent *
+UpdateFromMaster(InternalEvent *events, DeviceIntPtr dev, int type,
+                 int *num_events)
+{
+    DeviceIntPtr master;
+
+    /* Don't guess the master upon the event type. Use MASTER_ATTACHED,
+     * otherwise we'll never get a DeviceChangedEvent(reason:SlaveSwith). */
+    master = GetMaster(dev, MASTER_ATTACHED);
+    /* Need to track the slave event type. Other we'le never get a
+     * DeviceChangedEvent(reason:SlaveSwith) for the 'keyboard' if the
+     * 'pointer' has been touched before. */
+    int slave_type = (type & DEVCHANGE_KEYBOARD_EVENT) |
+                     (type & DEVCHANGE_POINTER_EVENT);
+
+    if (master &&
+        ((master->last.slave != dev) ||
+         (master->last.slave == dev && master->last.slave_type != slave_type))) {
+        master->last.slave_type = slave_type;
+        CreateClassesChangedEvent(events, master, dev,
+                                  type | DEVCHANGE_SLAVE_SWITCH);
+        if (IsPointerDevice(master)) {
+            updateSlaveDeviceCoords(master, dev);
+            master->last.numValuators = dev->last.numValuators;
+        }
+        master->last.slave = dev;
+        (*num_events)++;
+        events++;
+    }
+    return events;
+}
+
+/**
+ * Move the device's pointer to the position given in the valuators.
+ *
+ * @param dev The device whose pointer is to be moved.
+ * @param mask Valuator data for this event.
+ */
+static void
+clipAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
+{
+    int i;
+
+    for (i = 0; i < valuator_mask_size(mask); i++) {
+        double val;
+
+        if (!valuator_mask_isset(mask, i))
+            continue;
+        val = valuator_mask_get_double(mask, i);
+        clipAxis(dev, i, &val);
+        valuator_mask_set_double(mask, i, val);
+    }
+}
+
+static void
+add_to_scroll_valuator(DeviceIntPtr dev, ValuatorMask *mask, int valuator, double value)
+{
+    double v;
+
+    if (!valuator_mask_fetch_double(mask, valuator, &v))
+        return;
+
+    /* protect against scrolling overflow. INT_MAX for double, because
+     * we'll eventually write this as 32.32 fixed point */
+    if ((value > 0 && v > INT_MAX - value) || (value < 0 && v < INT_MIN - value)) {
+        v = 0;
+
+        /* reset last.scroll to avoid a button storm */
+        valuator_mask_set_double(dev->last.scroll, valuator, 0);
+    }
+    else
+        v += value;
+
+    valuator_mask_set_double(mask, valuator, v);
+}
+
+
+static void
+scale_for_device_resolution(DeviceIntPtr dev, ValuatorMask *mask)
+{
+    double y;
+    ValuatorClassPtr v = dev->valuator;
+    int xrange = v->axes[0].max_value - v->axes[0].min_value + 1;
+    int yrange = v->axes[1].max_value - v->axes[1].min_value + 1;
+
+    double screen_ratio = 1.0 * screenInfo.width/screenInfo.height;
+    double device_ratio = 1.0 * xrange/yrange;
+    double resolution_ratio = 1.0;
+    double ratio;
+
+    if (!valuator_mask_fetch_double(mask, 1, &y))
+        return;
+
+    if (v->axes[0].resolution != 0 && v->axes[1].resolution != 0)
+        resolution_ratio = 1.0 * v->axes[0].resolution/v->axes[1].resolution;
+
+    ratio = device_ratio/resolution_ratio/screen_ratio;
+    valuator_mask_set_double(mask, 1, y / ratio);
+}
+
+/**
+ * Move the device's pointer by the values given in @valuators.
+ *
+ * @param dev The device whose pointer is to be moved.
+ * @param[in,out] mask Valuator data for this event, modified in-place.
+ */
+static void
+moveRelative(DeviceIntPtr dev, int flags, ValuatorMask *mask)
+{
+    int i;
+    Bool clip_xy = IsMaster(dev) || !IsFloating(dev);
+    ValuatorClassPtr v = dev->valuator;
+
+    /* for abs devices in relative mode, we've just scaled wrong, since we
+       mapped the device's shape into the screen shape. Undo this. */
+    if ((flags & POINTER_ABSOLUTE) == 0 && v && v->numAxes > 1 &&
+        v->axes[0].min_value < v->axes[0].max_value &&
+        v->axes[1].min_value < v->axes[1].max_value) {
+        scale_for_device_resolution(dev, mask);
+    }
+
+    /* calc other axes, clip, drop back into valuators */
+    for (i = 0; i < valuator_mask_size(mask); i++) {
+        double val = dev->last.valuators[i];
+
+        if (!valuator_mask_isset(mask, i))
+            continue;
+
+        add_to_scroll_valuator(dev, mask, i, val);
+
+        /* x & y need to go over the limits to cross screens if the SD
+         * isn't currently attached; otherwise, clip to screen bounds. */
+        if (valuator_get_mode(dev, i) == Absolute &&
+            ((i != 0 && i != 1) || clip_xy)) {
+            val = valuator_mask_get_double(mask, i);
+            clipAxis(dev, i, &val);
+            valuator_mask_set_double(mask, i, val);
+        }
+    }
+}
+
+/**
+ * Accelerate the data in valuators based on the device's acceleration scheme.
+ *
+ * @param dev The device which's pointer is to be moved.
+ * @param valuators Valuator mask
+ * @param ms Current time.
+ */
+static void
+accelPointer(DeviceIntPtr dev, ValuatorMask *valuators, CARD32 ms)
+{
+    if (dev->valuator->accelScheme.AccelSchemeProc)
+        dev->valuator->accelScheme.AccelSchemeProc(dev, valuators, ms);
+}
+
+/**
+ * Scale from absolute screen coordinates to absolute coordinates in the
+ * device's coordinate range.
+ *
+ * @param dev The device to scale for.
+ * @param[in, out] mask The mask in desktop/screen coordinates, modified in place
+ * to contain device coordinate range.
+ * @param flags If POINTER_SCREEN is set, mask is in per-screen coordinates.
+ *              Otherwise, mask is in desktop coords.
+ */
+static void
+scale_from_screen(DeviceIntPtr dev, ValuatorMask *mask, int flags)
+{
+    double scaled;
+    ScreenPtr scr = miPointerGetScreen(dev);
+
+    if (valuator_mask_isset(mask, 0)) {
+        scaled = valuator_mask_get_double(mask, 0);
+        if (flags & POINTER_SCREEN)
+            scaled += scr->x;
+        scaled = rescaleValuatorAxis(scaled,
+                                     NULL, dev->valuator->axes + 0,
+                                     screenInfo.x, screenInfo.width);
+        valuator_mask_set_double(mask, 0, scaled);
+    }
+    if (valuator_mask_isset(mask, 1)) {
+        scaled = valuator_mask_get_double(mask, 1);
+        if (flags & POINTER_SCREEN)
+            scaled += scr->y;
+        scaled = rescaleValuatorAxis(scaled,
+                                     NULL, dev->valuator->axes + 1,
+                                     screenInfo.y, screenInfo.height);
+        valuator_mask_set_double(mask, 1, scaled);
+    }
+}
+
+/**
+ * Scale from (absolute) device to screen coordinates here,
+ *
+ * The coordinates provided are always absolute. see fill_pointer_events for
+ * information on coordinate systems.
+ *
+ * @param dev The device to be moved.
+ * @param mask Mask of axis values for this event
+ * @param[out] devx x desktop-wide coordinate in device coordinate system
+ * @param[out] devy y desktop-wide coordinate in device coordinate system
+ * @param[out] screenx x coordinate in desktop coordinate system
+ * @param[out] screeny y coordinate in desktop coordinate system
+ */
+static ScreenPtr
+scale_to_desktop(DeviceIntPtr dev, ValuatorMask *mask,
+                 double *devx, double *devy, double *screenx, double *screeny)
+{
+    ScreenPtr scr = miPointerGetScreen(dev);
+    double x, y;
+
+    BUG_WARN(dev->valuator && dev->valuator->numAxes < 2);
+    if (!dev->valuator || dev->valuator->numAxes < 2) {
+        /* if we have no axes, last.valuators must be in screen coords
+         * anyway */
+        *devx = *screenx = dev->last.valuators[0];
+        *devy = *screeny = dev->last.valuators[1];
+        return scr;
+    }
+
+    if (valuator_mask_isset(mask, 0))
+        x = valuator_mask_get_double(mask, 0);
+    else
+        x = dev->last.valuators[0];
+    if (valuator_mask_isset(mask, 1))
+        y = valuator_mask_get_double(mask, 1);
+    else
+        y = dev->last.valuators[1];
+
+    /* scale x&y to desktop coordinates */
+    *screenx = rescaleValuatorAxis(x, dev->valuator->axes + 0, NULL,
+                                   screenInfo.x, screenInfo.width);
+    *screeny = rescaleValuatorAxis(y, dev->valuator->axes + 1, NULL,
+                                   screenInfo.y, screenInfo.height);
+
+    *devx = x;
+    *devy = y;
+
+    return scr;
+}
+
+/**
+ * If we have HW cursors, this actually moves the visible sprite. If not, we
+ * just do all the screen crossing, etc.
+ *
+ * We use the screen coordinates here, call miPointerSetPosition() and then
+ * scale back into device coordinates (if needed). miPSP will change x/y if
+ * the screen was crossed.
+ *
+ * The coordinates provided are always absolute. The parameter mode
+ * specifies whether it was relative or absolute movement that landed us at
+ * those coordinates. see fill_pointer_events for information on coordinate
+ * systems.
+ *
+ * @param dev The device to be moved.
+ * @param mode Movement mode (Absolute or Relative)
+ * @param[out] mask Mask of axis values for this event, returns the
+ * per-screen device coordinates after confinement
+ * @param[in,out] devx x desktop-wide coordinate in device coordinate system
+ * @param[in,out] devy y desktop-wide coordinate in device coordinate system
+ * @param[in,out] screenx x coordinate in desktop coordinate system
+ * @param[in,out] screeny y coordinate in desktop coordinate system
+ * @param[out] nevents Number of barrier events added to events
+ * @param[in,out] events List of events barrier events are added to
+ */
+static ScreenPtr
+positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
+               double *devx, double *devy, double *screenx, double *screeny,
+               int *nevents, InternalEvent* events)
+{
+    ScreenPtr scr = miPointerGetScreen(dev);
+    double tmpx, tmpy;
+
+    if (!dev->valuator || dev->valuator->numAxes < 2)
+        return scr;
+
+    tmpx = *screenx;
+    tmpy = *screeny;
+
+    /* miPointerSetPosition takes care of crossing screens for us, as well as
+     * clipping to the current screen. Coordinates returned are in desktop
+     * coord system */
+    scr = miPointerSetPosition(dev, mode, screenx, screeny, nevents, events);
+
+    /* If we were constrained, rescale x/y from the screen coordinates so
+     * the device valuators reflect the correct position. For screen
+     * crossing this doesn't matter much, the coords would be 0 or max.
+     */
+    if (tmpx != *screenx)
+        *devx = rescaleValuatorAxis(*screenx, NULL, dev->valuator->axes + 0,
+                                    screenInfo.x, screenInfo.width);
+
+    if (tmpy != *screeny)
+        *devy = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1,
+                                    screenInfo.y, screenInfo.height);
+
+    /* Recalculate the per-screen device coordinates */
+    if (valuator_mask_isset(mask, 0)) {
+        double x;
+
+        x = rescaleValuatorAxis(*screenx - scr->x, NULL,
+                                dev->valuator->axes + 0, 0, scr->width);
+        valuator_mask_set_double(mask, 0, x);
+    }
+    if (valuator_mask_isset(mask, 1)) {
+        double y;
+
+        y = rescaleValuatorAxis(*screeny - scr->y, NULL,
+                                dev->valuator->axes + 1, 0, scr->height);
+        valuator_mask_set_double(mask, 1, y);
+    }
+
+    return scr;
+}
+
+/**
+ * Update the motion history for the device and (if appropriate) for its
+ * master device.
+ * @param dev Slave device to update.
+ * @param mask Bit mask of valid valuators to append to history.
+ * @param num Total number of valuators to append to history.
+ * @param ms Current time
+ */
+static void
+updateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms)
+{
+    if (!dev->valuator)
+        return;
+
+    updateMotionHistory(dev, ms, mask, dev->last.valuators);
+    if (!IsMaster(dev) && !IsFloating(dev)) {
+        DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
+
+        updateMotionHistory(master, ms, mask, dev->last.valuators);
+    }
+}
+
+static void
+queueEventList(DeviceIntPtr device, InternalEvent *events, int nevents)
+{
+    int i;
+
+    for (i = 0; i < nevents; i++)
+        mieqEnqueue(device, &events[i]);
+}
+
+static void
+event_set_root_coordinates(DeviceEvent *event, double x, double y)
+{
+    event->root_x = trunc(x);
+    event->root_y = trunc(y);
+    event->root_x_frac = x - trunc(x);
+    event->root_y_frac = y - trunc(y);
+}
+
+/**
+ * Generate internal events representing this keyboard event and enqueue
+ * them on the event queue.
+ *
+ * This function is not reentrant. Disable signals before calling.
+ *
+ * @param device The device to generate the event for
+ * @param type Event type, one of KeyPress or KeyRelease
+ * @param keycode Key code of the pressed/released key
+ *
+ */
+void
+QueueKeyboardEvents(DeviceIntPtr device, int type,
+                    int keycode)
+{
+    int nevents;
+
+    nevents = GetKeyboardEvents(InputEventList, device, type, keycode);
+    queueEventList(device, InputEventList, nevents);
+}
+
+/**
+ * Returns a set of InternalEvents for KeyPress/KeyRelease, optionally
+ * also with valuator events.
+ *
+ * The DDX is responsible for allocating the event list in the first
+ * place via InitEventList(), and for freeing it.
+ *
+ * @return the number of events written into events.
+ */
+int
+GetKeyboardEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
+                  int key_code)
+{
+    int num_events = 0;
+    CARD32 ms = 0;
+    DeviceEvent *event;
+    RawDeviceEvent *raw;
+    enum DeviceEventSource source_type = EVENT_SOURCE_NORMAL;
+
+#ifdef XSERVER_DTRACE
+    if (XSERVER_INPUT_EVENT_ENABLED()) {
+        XSERVER_INPUT_EVENT(pDev->id, type, key_code, 0, 0,
+                            NULL, NULL);
+    }
+#endif
+
+    if (type == EnterNotify) {
+        source_type = EVENT_SOURCE_FOCUS;
+        type = KeyPress;
+    } else if (type == LeaveNotify) {
+        source_type = EVENT_SOURCE_FOCUS;
+        type = KeyRelease;
+    }
+
+    /* refuse events from disabled devices */
+    if (!pDev->enabled)
+        return 0;
+
+    if (!events || !pDev->key || !pDev->focus || !pDev->kbdfeed ||
+        (type != KeyPress && type != KeyRelease) ||
+        (key_code < 8 || key_code > 255))
+        return 0;
+
+    num_events = 1;
+
+    events =
+        UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events);
+
+    /* Handle core repeating, via press/release/press/release. */
+    if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) {
+        /* If autorepeating is disabled either globally or just for that key,
+         * or we have a modifier, don't generate a repeat event. */
+        if (!pDev->kbdfeed->ctrl.autoRepeat ||
+            !key_autorepeats(pDev, key_code) ||
+            pDev->key->xkbInfo->desc->map->modmap[key_code])
+            return 0;
+    }
+
+    ms = GetTimeInMillis();
+
+    if (source_type == EVENT_SOURCE_NORMAL) {
+        raw = &events->raw_event;
+        init_raw(pDev, raw, ms, type, key_code);
+        events++;
+        num_events++;
+    }
+
+    event = &events->device_event;
+    init_device_event(event, pDev, ms, source_type);
+    event->detail.key = key_code;
+
+    if (type == KeyPress) {
+        event->type = ET_KeyPress;
+        set_key_down(pDev, key_code, KEY_POSTED);
+    }
+    else if (type == KeyRelease) {
+        event->type = ET_KeyRelease;
+        set_key_up(pDev, key_code, KEY_POSTED);
+    }
+
+    return num_events;
+}
+
+/**
+ * Initialize an event array large enough for num_events arrays.
+ * This event list is to be passed into GetPointerEvents() and
+ * GetKeyboardEvents().
+ *
+ * @param num_events Number of elements in list.
+ */
+InternalEvent *
+InitEventList(int num_events)
+{
+    InternalEvent *events = calloc(num_events, sizeof(InternalEvent));
+
+    return events;
+}
+
+/**
+ * Free an event list.
+ *
+ * @param list The list to be freed.
+ * @param num_events Number of elements in list.
+ */
+void
+FreeEventList(InternalEvent *list, int num_events)
+{
+    free(list);
+}
+
+/**
+ * Transform vector x/y according to matrix m and drop the rounded coords
+ * back into x/y.
+ */
+static void
+transform(struct pixman_f_transform *m, double *x, double *y)
+{
+    struct pixman_f_vector p = {.v = {*x, *y, 1} };
+    pixman_f_transform_point(m, &p);
+
+    *x = p.v[0];
+    *y = p.v[1];
+}
+
+static void
+transformRelative(DeviceIntPtr dev, ValuatorMask *mask)
+{
+    double x = 0, y = 0;
+
+    valuator_mask_fetch_double(mask, 0, &x);
+    valuator_mask_fetch_double(mask, 1, &y);
+
+    transform(&dev->relative_transform, &x, &y);
+
+    if (x)
+        valuator_mask_set_double(mask, 0, x);
+    else
+        valuator_mask_unset(mask, 0);
+
+    if (y)
+        valuator_mask_set_double(mask, 1, y);
+    else
+        valuator_mask_unset(mask, 1);
+}
+
+/**
+ * Apply the device's transformation matrix to the valuator mask and replace
+ * the scaled values in mask. This transformation only applies to valuators
+ * 0 and 1, others will be untouched.
+ *
+ * @param dev The device the valuators came from
+ * @param[in,out] mask The valuator mask.
+ */
+static void
+transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
+{
+    double x, y, ox = 0.0, oy = 0.0;
+    int has_x, has_y;
+
+    has_x = valuator_mask_isset(mask, 0);
+    has_y = valuator_mask_isset(mask, 1);
+
+    if (!has_x && !has_y)
+        return;
+
+    if (!has_x || !has_y) {
+        struct pixman_f_transform invert;
+
+        /* undo transformation from last event */
+        ox = dev->last.valuators[0];
+        oy = dev->last.valuators[1];
+
+        pixman_f_transform_invert(&invert, &dev->scale_and_transform);
+        transform(&invert, &ox, &oy);
+    }
+
+    if (has_x)
+        ox = valuator_mask_get_double(mask, 0);
+
+    if (has_y)
+        oy = valuator_mask_get_double(mask, 1);
+
+    x = ox;
+    y = oy;
+
+    transform(&dev->scale_and_transform, &x, &y);
+
+    if (has_x || ox != x)
+        valuator_mask_set_double(mask, 0, x);
+
+    if (has_y || oy != y)
+        valuator_mask_set_double(mask, 1, y);
+}
+
+static void
+storeLastValuators(DeviceIntPtr dev, ValuatorMask *mask,
+                   int xaxis, int yaxis, double devx, double devy)
+{
+    int i;
+
+    /* store desktop-wide in last.valuators */
+    if (valuator_mask_isset(mask, xaxis))
+        dev->last.valuators[0] = devx;
+    if (valuator_mask_isset(mask, yaxis))
+        dev->last.valuators[1] = devy;
+
+    for (i = 0; i < valuator_mask_size(mask); i++) {
+        if (i == xaxis || i == yaxis)
+            continue;
+
+        if (valuator_mask_isset(mask, i))
+            dev->last.valuators[i] = valuator_mask_get_double(mask, i);
+    }
+
+}
+
+/**
+ * Generate internal events representing this pointer event and enqueue them
+ * on the event queue.
+ *
+ * This function is not reentrant. Disable signals before calling.
+ *
+ * @param device The device to generate the event for
+ * @param type Event type, one of ButtonPress, ButtonRelease, MotionNotify
+ * @param buttons Button number of the buttons modified. Must be 0 for
+ * MotionNotify
+ * @param flags Event modification flags
+ * @param mask Valuator mask for valuators present for this event.
+ */
+void
+QueuePointerEvents(DeviceIntPtr device, int type,
+                   int buttons, int flags, const ValuatorMask *mask)
+{
+    int nevents;
+
+    nevents =
+        GetPointerEvents(InputEventList, device, type, buttons, flags, mask);
+    queueEventList(device, InputEventList, nevents);
+}
+
+/**
+ * Helper function for GetPointerEvents, which only generates motion and
+ * raw motion events for the slave device: does not update the master device.
+ *
+ * Should not be called by anyone other than GetPointerEvents.
+ *
+ * We use several different coordinate systems and need to switch between
+ * the three in fill_pointer_events, positionSprite and
+ * miPointerSetPosition. "desktop" refers to the width/height of all
+ * screenInfo.screens[n]->width/height added up. "screen" is ScreenRec, not
+ * output.
+ *
+ * Coordinate systems:
+ * - relative events have a mask_in in relative coordinates, mapped to
+ *   pixels. These events are mapped to the current position±delta.
+ * - absolute events have a mask_in in absolute device coordinates in
+ *   device-specific range. This range is mapped to the desktop.
+ * - POINTER_SCREEN absolute events (x86WarpCursor) are in screen-relative
+ *   screen coordinate range.
+ * - rootx/rooty in events must be be relative to the current screen's
+ *   origin (screen coordinate system)
+ * - XI2 valuators must be relative to the current screen's origin. On
+ *   the protocol the device min/max range maps to the current screen.
+ *
+ * For screen switching we need to get the desktop coordinates for each
+ * event, then map that to the respective position on each screen and
+ * position the cursor there.
+ * The device's last.valuator[] stores the last position in desktop-wide
+ * coordinates (in device range for slave devices, desktop range for master
+ * devices).
+ *
+ * screen-relative device coordinates requires scaling: A device coordinate
+ * x/y of range [n..m] that maps to positions Sx/Sy on Screen S must be
+ * rescaled to match Sx/Sy for [n..m]. In the simplest example, x of (m/2-1)
+ * is the last coordinate on the first screen and must be rescaled for the
+ * event to be m. XI2 clients that do their own coordinate mapping would
+ * otherwise interpret the position of the device elsewhere to the cursor.
+ * However, this scaling leads to losses:
+ * if we have two ScreenRecs we scale from e.g. [0..44704]  (Wacom I4) to
+ * [0..2048[. that gives us 2047.954 as desktop coord, or the per-screen
+ * coordinate 1023.954. Scaling that back into the device coordinate range
+ * gives us 44703. So off by one device unit. It's a bug, but we'll have to
+ * live with it because with all this scaling, we just cannot win.
+ *
+ * @return the number of events written into events.
+ */
+static int
+fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
+                    int buttons, CARD32 ms, int flags,
+                    const ValuatorMask *mask_in)
+{
+    int num_events = 0;
+    DeviceEvent *event;
+    RawDeviceEvent *raw = NULL;
+    double screenx = 0.0, screeny = 0.0;        /* desktop coordinate system */
+    double devx = 0.0, devy = 0.0;      /* desktop-wide in device coords */
+    int sx = 0, sy = 0;                 /* for POINTER_SCREEN */
+    ValuatorMask mask;
+    ScreenPtr scr;
+    int num_barrier_events = 0;
+
+    switch (type) {
+    case MotionNotify:
+        if (!pDev->valuator) {
+            ErrorF("[dix] motion events from device %d without valuators\n",
+                   pDev->id);
+            return 0;
+        }
+        if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0)
+            return 0;
+        break;
+    case ButtonPress:
+    case ButtonRelease:
+        if (!pDev->button || !buttons)
+            return 0;
+        if (mask_in && valuator_mask_size(mask_in) > 0 && !pDev->valuator) {
+            ErrorF
+                ("[dix] button event with valuator from device %d without valuators\n",
+                 pDev->id);
+            return 0;
+        }
+        break;
+    default:
+        return 0;
+    }
+
+    valuator_mask_copy(&mask, mask_in);
+
+    if ((flags & POINTER_NORAW) == 0) {
+        raw = &events->raw_event;
+        events++;
+        num_events++;
+
+        init_raw(pDev, raw, ms, type, buttons);
+
+        if (flags & POINTER_EMULATED)
+            raw->flags = XIPointerEmulated;
+
+        set_raw_valuators(raw, &mask, TRUE, raw->valuators.data_raw);
+    }
+
+    valuator_mask_drop_unaccelerated(&mask);
+
+    /* valuators are in driver-native format (rel or abs) */
+
+    if (flags & POINTER_ABSOLUTE) {
+        if (flags & (POINTER_SCREEN | POINTER_DESKTOP)) {    /* valuators are in screen/desktop coords */
+            sx = valuator_mask_get(&mask, 0);
+            sy = valuator_mask_get(&mask, 1);
+            scale_from_screen(pDev, &mask, flags);
+        }
+
+        transformAbsolute(pDev, &mask);
+        clipAbsolute(pDev, &mask);
+        if ((flags & POINTER_NORAW) == 0 && raw)
+            set_raw_valuators(raw, &mask, FALSE, raw->valuators.data);
+    }
+    else {
+        transformRelative(pDev, &mask);
+
+        if (flags & POINTER_ACCELERATE)
+            accelPointer(pDev, &mask, ms);
+        if ((flags & POINTER_NORAW) == 0 && raw)
+            set_raw_valuators(raw, &mask, FALSE, raw->valuators.data);
+
+        moveRelative(pDev, flags, &mask);
+    }
+
+    /* valuators are in device coordinate system in absolute coordinates */
+    scale_to_desktop(pDev, &mask, &devx, &devy, &screenx, &screeny);
+
+    /* #53037 XWarpPointer's scaling back and forth between screen and
+       device may leave us with rounding errors. End result is that the
+       pointer doesn't end up on the pixel it should.
+       Avoid this by forcing screenx/screeny back to what the input
+       coordinates were.
+     */
+    if (flags & POINTER_SCREEN) {
+        scr = miPointerGetScreen(pDev);
+        screenx = sx + scr->x;
+        screeny = sy + scr->y;
+    }
+
+    scr = positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
+                         &mask, &devx, &devy, &screenx, &screeny,
+                         &num_barrier_events, events);
+    num_events += num_barrier_events;
+    events += num_barrier_events;
+
+    /* screenx, screeny are in desktop coordinates,
+       mask is in device coordinates per-screen (the event data)
+       devx/devy is in device coordinate desktop-wide */
+    updateHistory(pDev, &mask, ms);
+
+    clipValuators(pDev, &mask);
+
+    storeLastValuators(pDev, &mask, 0, 1, devx, devy);
+
+    /* Update the MD's coordinates, which are always in desktop space. */
+    if (!IsMaster(pDev) && !IsFloating(pDev)) {
+        DeviceIntPtr master = GetMaster(pDev, MASTER_POINTER);
+
+        master->last.valuators[0] = screenx;
+        master->last.valuators[1] = screeny;
+    }
+
+    if ((flags & POINTER_RAWONLY) == 0) {
+        num_events++;
+
+        event = &events->device_event;
+        init_device_event(event, pDev, ms, EVENT_SOURCE_NORMAL);
+
+        if (type == MotionNotify) {
+            event->type = ET_Motion;
+            event->detail.button = 0;
+        }
+        else {
+            if (type == ButtonPress) {
+                event->type = ET_ButtonPress;
+                set_button_down(pDev, buttons, BUTTON_POSTED);
+            }
+            else if (type == ButtonRelease) {
+                event->type = ET_ButtonRelease;
+                set_button_up(pDev, buttons, BUTTON_POSTED);
+            }
+            event->detail.button = buttons;
+        }
+
+        /* root_x and root_y must be in per-screen coordinates */
+        event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y);
+
+        if (flags & POINTER_EMULATED)
+            event->flags = XIPointerEmulated;
+
+        set_valuators(pDev, event, &mask);
+    }
+
+    return num_events;
+}
+
+/**
+ * Generate events for each scroll axis that changed between before/after
+ * for the device.
+ *
+ * @param events The pointer to the event list to fill the events
+ * @param dev The device to generate the events for
+ * @param type The real type of the event
+ * @param axis The axis number to generate events for
+ * @param mask State before this event in absolute coords
+ * @param[in,out] last Last scroll state posted in absolute coords (modified
+ * in-place)
+ * @param ms Current time in ms
+ * @param max_events Max number of events to be generated
+ * @return The number of events generated
+ */
+static int
+emulate_scroll_button_events(InternalEvent *events,
+                             DeviceIntPtr dev,
+                             int type,
+                             int axis,
+                             const ValuatorMask *mask,
+                             ValuatorMask *last, CARD32 ms, int max_events)
+{
+    AxisInfoPtr ax;
+    double delta;
+    double incr;
+    int num_events = 0;
+    double total;
+    int b;
+    int flags = 0;
+
+    if (dev->valuator->axes[axis].scroll.type == SCROLL_TYPE_NONE)
+        return 0;
+
+    if (!valuator_mask_isset(mask, axis))
+        return 0;
+
+    ax = &dev->valuator->axes[axis];
+    incr = ax->scroll.increment;
+
+    BUG_WARN_MSG(incr == 0, "for device %s\n", dev->name);
+    if (incr == 0)
+        return 0;
+
+    if (type != ButtonPress && type != ButtonRelease)
+        flags |= POINTER_EMULATED;
+
+    if (!valuator_mask_isset(last, axis))
+        valuator_mask_set_double(last, axis, 0);
+
+    delta =
+        valuator_mask_get_double(mask, axis) - valuator_mask_get_double(last,
+                                                                        axis);
+    total = delta;
+    b = (ax->scroll.type == SCROLL_TYPE_VERTICAL) ? 5 : 7;
+
+    if ((incr > 0 && delta < 0) || (incr < 0 && delta > 0))
+        b--;                    /* we're scrolling up or left → button 4 or 6 */
+
+    while (fabs(delta) >= fabs(incr)) {
+        int nev_tmp;
+
+        if (delta > 0)
+            delta -= fabs(incr);
+        else if (delta < 0)
+            delta += fabs(incr);
+
+        /* fill_pointer_events() generates four events: one normal and one raw
+         * event for button press and button release.
+         * We may get a bigger scroll delta than we can generate events
+         * for. In that case, we keep decreasing delta, but skip events.
+         */
+        if (num_events + 4 < max_events) {
+            if (type != ButtonRelease) {
+                nev_tmp = fill_pointer_events(events, dev, ButtonPress, b, ms,
+                                              flags, NULL);
+                events += nev_tmp;
+                num_events += nev_tmp;
+            }
+            if (type != ButtonPress) {
+                nev_tmp = fill_pointer_events(events, dev, ButtonRelease, b, ms,
+                                              flags, NULL);
+                events += nev_tmp;
+                num_events += nev_tmp;
+            }
+        }
+    }
+
+    /* We emulated, update last.scroll */
+    if (total != delta) {
+        total -= delta;
+        valuator_mask_set_double(last, axis,
+                                 valuator_mask_get_double(last, axis) + total);
+    }
+
+    return num_events;
+}
+
+
+/**
+ * Generate a complete series of InternalEvents (filled into the EventList)
+ * representing pointer motion, or button presses.  If the device is a slave
+ * device, also potentially generate a DeviceClassesChangedEvent to update
+ * the master device.
+ *
+ * events is not NULL-terminated; the return value is the number of events.
+ * The DDX is responsible for allocating the event structure in the first
+ * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
+ *
+ * In the generated events rootX/Y will be in absolute screen coords and
+ * the valuator information in the absolute or relative device coords.
+ *
+ * last.valuators[x] of the device is always in absolute device coords.
+ * last.valuators[x] of the master device is in absolute screen coords.
+ *
+ * master->last.valuators[x] for x > 2 is undefined.
+ */
+int
+GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
+                 int buttons, int flags, const ValuatorMask *mask_in)
+{
+    CARD32 ms = GetTimeInMillis();
+    int num_events = 0, nev_tmp;
+    ValuatorMask mask;
+    ValuatorMask scroll;
+    int i;
+    int realtype = type;
+
+#ifdef XSERVER_DTRACE
+    if (XSERVER_INPUT_EVENT_ENABLED()) {
+        XSERVER_INPUT_EVENT(pDev->id, type, buttons, flags,
+                            mask_in ? mask_in->last_bit + 1 : 0,
+                            mask_in ? mask_in->mask : NULL,
+                            mask_in ? mask_in->valuators : NULL);
+    }
+#endif
+
+    BUG_RETURN_VAL(buttons >= MAX_BUTTONS, 0);
+
+    /* refuse events from disabled devices */
+    if (!pDev->enabled)
+        return 0;
+
+    if (!miPointerGetScreen(pDev))
+        return 0;
+
+    events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT,
+                              &num_events);
+
+    valuator_mask_copy(&mask, mask_in);
+
+    /* Turn a scroll button press into a smooth-scrolling event if
+     * necessary. This only needs to cater for the XIScrollFlagPreferred
+     * axis (if more than one scrolling axis is present) */
+    if (type == ButtonPress) {
+        double adj;
+        int axis;
+        int h_scroll_axis = -1;
+        int v_scroll_axis = -1;
+
+        if (pDev->valuator) {
+            h_scroll_axis = pDev->valuator->h_scroll_axis;
+            v_scroll_axis = pDev->valuator->v_scroll_axis;
+        }
+
+        /* Up is negative on valuators, down positive */
+        switch (buttons) {
+        case 4:
+            adj = -1.0;
+            axis = v_scroll_axis;
+            break;
+        case 5:
+            adj = 1.0;
+            axis = v_scroll_axis;
+            break;
+        case 6:
+            adj = -1.0;
+            axis = h_scroll_axis;
+            break;
+        case 7:
+            adj = 1.0;
+            axis = h_scroll_axis;
+            break;
+        default:
+            adj = 0.0;
+            axis = -1;
+            break;
+        }
+
+        if (adj != 0.0 && axis != -1) {
+            adj *= pDev->valuator->axes[axis].scroll.increment;
+            if (!valuator_mask_isset(&mask, axis))
+                valuator_mask_set(&mask, axis, 0);
+            add_to_scroll_valuator(pDev, &mask, axis, adj);
+            type = MotionNotify;
+            buttons = 0;
+            flags |= POINTER_EMULATED;
+        }
+    }
+
+    /* First fill out the original event set, with smooth-scrolling axes. */
+    nev_tmp = fill_pointer_events(events, pDev, type, buttons, ms, flags,
+                                  &mask);
+    events += nev_tmp;
+    num_events += nev_tmp;
+
+    valuator_mask_zero(&scroll);
+
+    /* Now turn the smooth-scrolling axes back into emulated button presses
+     * for legacy clients, based on the integer delta between before and now */
+    for (i = 0; i < valuator_mask_size(&mask); i++) {
+        if ( !pDev->valuator || (i >= pDev->valuator->numAxes))
+            break;
+
+        if (!valuator_mask_isset(&mask, i))
+            continue;
+
+        valuator_mask_set_double(&scroll, i, pDev->last.valuators[i]);
+
+        nev_tmp =
+            emulate_scroll_button_events(events, pDev, realtype, i, &scroll,
+                                         pDev->last.scroll, ms,
+                                         GetMaximumEventsNum() - num_events);
+        events += nev_tmp;
+        num_events += nev_tmp;
+    }
+
+    return num_events;
+}
+
+/**
+ * Generate internal events representing this proximity event and enqueue
+ * them on the event queue.
+ *
+ * This function is not reentrant. Disable signals before calling.
+ *
+ * @param device The device to generate the event for
+ * @param type Event type, one of ProximityIn or ProximityOut
+ * @param keycode Key code of the pressed/released key
+ * @param mask Valuator mask for valuators present for this event.
+ *
+ */
+void
+QueueProximityEvents(DeviceIntPtr device, int type, const ValuatorMask *mask)
+{
+    int nevents;
+
+    nevents = GetProximityEvents(InputEventList, device, type, mask);
+    queueEventList(device, InputEventList, nevents);
+}
+
+/**
+ * Generate ProximityIn/ProximityOut InternalEvents, accompanied by
+ * valuators.
+ *
+ * The DDX is responsible for allocating the events in the first place via
+ * InitEventList(), and for freeing it.
+ *
+ * @return the number of events written into events.
+ */
+int
+GetProximityEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
+                   const ValuatorMask *mask_in)
+{
+    int num_events = 1, i;
+    DeviceEvent *event;
+    ValuatorMask mask;
+
+#ifdef XSERVER_DTRACE
+    if (XSERVER_INPUT_EVENT_ENABLED()) {
+        XSERVER_INPUT_EVENT(pDev->id, type, 0, 0,
+                            mask_in ? mask_in->last_bit + 1 : 0,
+                            mask_in ? mask_in->mask : NULL,
+                            mask_in ? mask_in->valuators : NULL);
+    }
+#endif
+
+    /* refuse events from disabled devices */
+    if (!pDev->enabled)
+        return 0;
+
+    /* Sanity checks. */
+    if ((type != ProximityIn && type != ProximityOut) || !mask_in)
+        return 0;
+    if (!pDev->valuator || !pDev->proximity)
+        return 0;
+
+    valuator_mask_copy(&mask, mask_in);
+
+    /* ignore relative axes for proximity. */
+    for (i = 0; i < valuator_mask_size(&mask); i++) {
+        if (valuator_mask_isset(&mask, i) &&
+            valuator_get_mode(pDev, i) == Relative)
+            valuator_mask_unset(&mask, i);
+    }
+
+    /* FIXME: posting proximity events with relative valuators only results
+     * in an empty event, EventToXI() will fail to convert → no event sent
+     * to client. */
+
+    events =
+        UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
+
+    event = &events->device_event;
+    init_device_event(event, pDev, GetTimeInMillis(), EVENT_SOURCE_NORMAL);
+    event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
+
+    clipValuators(pDev, &mask);
+
+    set_valuators(pDev, event, &mask);
+
+    return num_events;
+}
+
+int
+GetTouchOwnershipEvents(InternalEvent *events, DeviceIntPtr pDev,
+                        TouchPointInfoPtr ti, uint8_t reason, XID resource,
+                        uint32_t flags)
+{
+    TouchClassPtr t = pDev->touch;
+    TouchOwnershipEvent *event;
+    CARD32 ms = GetTimeInMillis();
+
+    if (!pDev->enabled || !t || !ti)
+        return 0;
+
+    event = &events->touch_ownership_event;
+    init_touch_ownership(pDev, event, ms);
+
+    event->touchid = ti->client_id;
+    event->sourceid = ti->sourceid;
+    event->resource = resource;
+    event->flags = flags;
+    event->reason = reason;
+
+    return 1;
+}
+
+/**
+ * Generate internal events representing this touch event and enqueue them
+ * on the event queue.
+ *
+ * This function is not reentrant. Disable signals before calling.
+ *
+ * @param device The device to generate the event for
+ * @param type Event type, one of XI_TouchBegin, XI_TouchUpdate, XI_TouchEnd
+ * @param touchid Touch point ID
+ * @param flags Event modification flags
+ * @param mask Valuator mask for valuators present for this event.
+ */
+void
+QueueTouchEvents(DeviceIntPtr device, int type,
+                 uint32_t ddx_touchid, int flags, const ValuatorMask *mask)
+{
+    int nevents;
+
+    nevents =
+        GetTouchEvents(InputEventList, device, ddx_touchid, type, flags, mask);
+    queueEventList(device, InputEventList, nevents);
+}
+
+/**
+ * Get events for a touch. Generates a TouchBegin event if end is not set and
+ * the touch id is not active. Generates a TouchUpdate event if end is not set
+ * and the touch id is active. Generates a TouchEnd event if end is set and the
+ * touch id is active.
+ *
+ * events is not NULL-terminated; the return value is the number of events.
+ * The DDX is responsible for allocating the event structure in the first
+ * place via GetMaximumEventsNum(), and for freeing it.
+ *
+ * @param[out] events The list of events generated
+ * @param dev The device to generate the events for
+ * @param ddx_touchid The touch ID as assigned by the DDX
+ * @param type XI_TouchBegin, XI_TouchUpdate or XI_TouchEnd
+ * @param flags Event flags
+ * @param mask_in Valuator information for this event
+ */
+int
+GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid,
+               uint16_t type, uint32_t flags, const ValuatorMask *mask_in)
+{
+    ScreenPtr scr;
+    TouchClassPtr t = dev->touch;
+    ValuatorClassPtr v = dev->valuator;
+    DeviceEvent *event;
+    CARD32 ms = GetTimeInMillis();
+    ValuatorMask mask;
+    double screenx = 0.0, screeny = 0.0;        /* desktop coordinate system */
+    double devx = 0.0, devy = 0.0;      /* desktop-wide in device coords */
+    int i;
+    int num_events = 0;
+    RawDeviceEvent *raw;
+    DDXTouchPointInfoPtr ti;
+    int need_rawevent = TRUE;
+    Bool emulate_pointer = FALSE;
+    int client_id = 0;
+
+#ifdef XSERVER_DTRACE
+    if (XSERVER_INPUT_EVENT_ENABLED()) {
+        XSERVER_INPUT_EVENT(dev->id, type, ddx_touchid, flags,
+                            mask_in ? mask_in->last_bit + 1 : 0,
+                            mask_in ? mask_in->mask : NULL,
+                            mask_in ? mask_in->valuators : NULL);
+    }
+#endif
+
+    if (!dev->enabled || !t || !v)
+        return 0;
+
+    /* Find and/or create the DDX touch info */
+
+    ti = TouchFindByDDXID(dev, ddx_touchid, (type == XI_TouchBegin));
+    if (!ti) {
+        ErrorFSigSafe("[dix] %s: unable to %s touch point %u\n", dev->name,
+                      type == XI_TouchBegin ? "begin" : "find", ddx_touchid);
+        return 0;
+    }
+    client_id = ti->client_id;
+
+    emulate_pointer = ti->emulate_pointer;
+
+    if (!IsMaster(dev))
+        events =
+            UpdateFromMaster(events, dev, DEVCHANGE_POINTER_EVENT, &num_events);
+
+    valuator_mask_copy(&mask, mask_in);
+
+    if (need_rawevent) {
+        raw = &events->raw_event;
+        events++;
+        num_events++;
+        init_raw(dev, raw, ms, type, client_id);
+        set_raw_valuators(raw, &mask, TRUE, raw->valuators.data_raw);
+    }
+
+    event = &events->device_event;
+    num_events++;
+
+    init_device_event(event, dev, ms, EVENT_SOURCE_NORMAL);
+
+    switch (type) {
+    case XI_TouchBegin:
+        event->type = ET_TouchBegin;
+        /* If we're starting a touch, we must have x & y coordinates. */
+        if (!mask_in ||
+            !valuator_mask_isset(mask_in, 0) ||
+            !valuator_mask_isset(mask_in, 1)) {
+            ErrorFSigSafe("%s: Attempted to start touch without x/y "
+                          "(driver bug)\n", dev->name);
+            return 0;
+        }
+        break;
+    case XI_TouchUpdate:
+        event->type = ET_TouchUpdate;
+        if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0) {
+            ErrorFSigSafe("%s: TouchUpdate with no valuators? Driver bug\n",
+                          dev->name);
+        }
+        break;
+    case XI_TouchEnd:
+        event->type = ET_TouchEnd;
+        /* We can end the DDX touch here, since we don't use the active
+         * field below */
+        TouchEndDDXTouch(dev, ti);
+        break;
+    default:
+        return 0;
+    }
+
+    /* Get our screen event coordinates (root_x/root_y/event_x/event_y):
+     * these come from the touchpoint in Absolute mode, or the sprite in
+     * Relative. */
+    if (t->mode == XIDirectTouch) {
+        for (i = 0; i < max(valuator_mask_size(&mask), 2); i++) {
+            double val;
+
+            if (valuator_mask_fetch_double(&mask, i, &val))
+                valuator_mask_set_double(ti->valuators, i, val);
+            /* If the device doesn't post new X and Y axis values,
+             * use the last values posted.
+             */
+            else if (i < 2 &&
+                valuator_mask_fetch_double(ti->valuators, i, &val))
+                valuator_mask_set_double(&mask, i, val);
+        }
+
+        transformAbsolute(dev, &mask);
+        clipAbsolute(dev, &mask);
+    }
+    else {
+        screenx = dev->spriteInfo->sprite->hotPhys.x;
+        screeny = dev->spriteInfo->sprite->hotPhys.y;
+    }
+    if (need_rawevent)
+        set_raw_valuators(raw, &mask, FALSE, raw->valuators.data);
+
+    scr = dev->spriteInfo->sprite->hotPhys.pScreen;
+
+    /* Indirect device touch coordinates are not used for cursor positioning.
+     * They are merely informational, and are provided in device coordinates.
+     * The device sprite is used for positioning instead, and it is already
+     * scaled. */
+    if (t->mode == XIDirectTouch)
+        scr = scale_to_desktop(dev, &mask, &devx, &devy, &screenx, &screeny);
+    if (emulate_pointer)
+        scr = positionSprite(dev, Absolute, &mask,
+                             &devx, &devy, &screenx, &screeny, NULL, NULL);
+
+    /* see fill_pointer_events for coordinate systems */
+    if (emulate_pointer)
+        updateHistory(dev, &mask, ms);
+
+    clipValuators(dev, &mask);
+
+    if (emulate_pointer)
+        storeLastValuators(dev, &mask, 0, 1, devx, devy);
+
+    /* Update the MD's coordinates, which are always in desktop space. */
+    if (emulate_pointer && !IsMaster(dev) && !IsFloating(dev)) {
+	    DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
+
+	    master->last.valuators[0] = screenx;
+	    master->last.valuators[1] = screeny;
+    }
+
+    event->root = scr->root->drawable.id;
+
+    event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y);
+    event->touchid = client_id;
+    event->flags = flags;
+
+    if (emulate_pointer) {
+        event->flags |= TOUCH_POINTER_EMULATED;
+        event->detail.button = 1;
+    }
+
+    set_valuators(dev, event, &mask);
+    for (i = 0; i < v->numAxes; i++) {
+        if (valuator_mask_isset(&mask, i))
+            v->axisVal[i] = valuator_mask_get(&mask, i);
+    }
+
+    return num_events;
+}
+
+void
+GetDixTouchEnd(InternalEvent *ievent, DeviceIntPtr dev, TouchPointInfoPtr ti,
+               uint32_t flags)
+{
+    ScreenPtr scr = dev->spriteInfo->sprite->hotPhys.pScreen;
+    DeviceEvent *event = &ievent->device_event;
+    CARD32 ms = GetTimeInMillis();
+
+    BUG_WARN(!dev->enabled);
+
+    init_device_event(event, dev, ms, EVENT_SOURCE_NORMAL);
+
+    event->sourceid = ti->sourceid;
+    event->type = ET_TouchEnd;
+
+    event->root = scr->root->drawable.id;
+
+    /* Get screen event coordinates from the sprite.  Is this really the best
+     * we can do? */
+    event_set_root_coordinates(event,
+                               dev->last.valuators[0] - scr->x,
+                               dev->last.valuators[1] - scr->y);
+    event->touchid = ti->client_id;
+    event->flags = flags;
+
+    if (flags & TOUCH_POINTER_EMULATED) {
+        event->flags |= TOUCH_POINTER_EMULATED;
+        event->detail.button = 1;
+    }
+}
+
+/**
+ * Synthesize a single motion event for the core pointer.
+ *
+ * Used in cursor functions, e.g. when cursor confinement changes, and we need
+ * to shift the pointer to get it inside the new bounds.
+ */
+void
+PostSyntheticMotion(DeviceIntPtr pDev,
+                    int x, int y, int screen, unsigned long time)
+{
+    DeviceEvent ev;
+
+#ifdef PANORAMIX
+    /* Translate back to the sprite screen since processInputProc
+       will translate from sprite screen to screen 0 upon reentry
+       to the DIX layer. */
+    if (!noPanoramiXExtension) {
+        x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x;
+        y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y;
+    }
+#endif
+
+    memset(&ev, 0, sizeof(DeviceEvent));
+    init_device_event(&ev, pDev, time, EVENT_SOURCE_NORMAL);
+    ev.root_x = x;
+    ev.root_y = y;
+    ev.type = ET_Motion;
+    ev.time = time;
+
+    /* FIXME: MD/SD considerations? */
+    (*pDev->public.processInputProc) ((InternalEvent *) &ev, pDev);
+}
+
+void
+InitGestureEvent(InternalEvent *ievent, DeviceIntPtr dev, CARD32 ms,
+                 int type, uint16_t num_touches, uint32_t flags,
+                 double delta_x, double delta_y,
+                 double delta_unaccel_x, double delta_unaccel_y,
+                 double scale, double delta_angle)
+{
+    ScreenPtr scr = dev->spriteInfo->sprite->hotPhys.pScreen;
+    GestureEvent *event = &ievent->gesture_event;
+    double screenx = 0.0, screeny = 0.0;        /* desktop coordinate system */
+
+    init_gesture_event(event, dev, ms);
+
+    screenx = dev->spriteInfo->sprite->hotPhys.x;
+    screeny = dev->spriteInfo->sprite->hotPhys.y;
+
+    event->type = type;
+    event->root = scr->root->drawable.id;
+    event->root_x = screenx - scr->x;
+    event->root_y = screeny - scr->y;
+    event->num_touches = num_touches;
+    event->flags = flags;
+
+    event->delta_x = delta_x;
+    event->delta_y = delta_y;
+    event->delta_unaccel_x = delta_unaccel_x;
+    event->delta_unaccel_y = delta_unaccel_y;
+    event->scale = scale;
+    event->delta_angle = delta_angle;
+}
+
+/**
+ * Get events for a pinch or swipe gesture.
+ *
+ * events is not NULL-terminated; the return value is the number of events.
+ * The DDX is responsible for allocating the event structure in the first
+ * place via GetMaximumEventsNum(), and for freeing it.
+ *
+ * @param[out] events The list of events generated
+ * @param dev The device to generate the events for
+ * @param type XI_Gesture{Pinch,Swipe}{Begin,Update,End}
+ * @prama num_touches The number of touches in the gesture
+ * @param flags Event flags
+ * @param delta_x,delta_y accelerated relative motion delta
+ * @param delta_unaccel_x,delta_unaccel_y unaccelerated relative motion delta
+ * @param scale (valid only to pinch events) absolute scale of a pinch gesture
+ * @param delta_angle (valid only to pinch events) the ange delta in degrees between the last and
+ *        the current pinch event.
+ */
+int
+GetGestureEvents(InternalEvent *events, DeviceIntPtr dev,
+                 uint16_t type, uint16_t num_touches, uint32_t flags,
+                 double delta_x, double delta_y,
+                 double delta_unaccel_x, double delta_unaccel_y,
+                 double scale, double delta_angle)
+
+{
+    GestureClassPtr g = dev->gesture;
+    CARD32 ms = GetTimeInMillis();
+    enum EventType evtype;
+    int num_events = 0;
+    uint32_t evflags = 0;
+
+    if (!dev->enabled || !g)
+        return 0;
+
+    if (!IsMaster(dev))
+        events = UpdateFromMaster(events, dev, DEVCHANGE_POINTER_EVENT,
+                                  &num_events);
+
+    switch (type) {
+    case XI_GesturePinchBegin:
+        evtype = ET_GesturePinchBegin;
+        break;
+    case XI_GesturePinchUpdate:
+        evtype = ET_GesturePinchUpdate;
+        break;
+    case XI_GesturePinchEnd:
+        evtype = ET_GesturePinchEnd;
+        if (flags & XIGesturePinchEventCancelled)
+            evflags |= GESTURE_CANCELLED;
+        break;
+    case XI_GestureSwipeBegin:
+        evtype = ET_GestureSwipeBegin;
+        break;
+    case XI_GestureSwipeUpdate:
+        evtype = ET_GestureSwipeUpdate;
+        break;
+    case XI_GestureSwipeEnd:
+        evtype = ET_GestureSwipeEnd;
+        if (flags & XIGestureSwipeEventCancelled)
+            evflags |= GESTURE_CANCELLED;
+        break;
+    default:
+        return 0;
+    }
+
+    InitGestureEvent(events, dev, ms, evtype, num_touches, evflags,
+                     delta_x, delta_y, delta_unaccel_x, delta_unaccel_y,
+                     scale, delta_angle);
+    num_events++;
+
+    return num_events;
+}
+
+void
+QueueGesturePinchEvents(DeviceIntPtr dev, uint16_t type,
+                        uint16_t num_touches, uint32_t flags,
+                        double delta_x, double delta_y,
+                        double delta_unaccel_x,
+                        double delta_unaccel_y,
+                        double scale, double delta_angle)
+{
+    int nevents;
+    nevents = GetGestureEvents(InputEventList, dev, type, num_touches, flags,
+                               delta_x, delta_y,
+                               delta_unaccel_x, delta_unaccel_y,
+                               scale, delta_angle);
+    queueEventList(dev, InputEventList, nevents);
+}
+
+void
+QueueGestureSwipeEvents(DeviceIntPtr dev, uint16_t type,
+                        uint16_t num_touches, uint32_t flags,
+                        double delta_x, double delta_y,
+                        double delta_unaccel_x,
+                        double delta_unaccel_y)
+{
+    int nevents;
+    nevents = GetGestureEvents(InputEventList, dev, type, num_touches, flags,
+                               delta_x, delta_y,
+                               delta_unaccel_x, delta_unaccel_y,
+                               0.0, 0.0);
+    queueEventList(dev, InputEventList, nevents);
+}
Index: xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/dix
===================================================================
--- xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/dix	(nonexistent)
+++ xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/dix	(revision 5)

Property changes on: xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/dix
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/include/inputstr.h
===================================================================
--- xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/include/inputstr.h	(nonexistent)
+++ xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/include/inputstr.h	(revision 5)
@@ -0,0 +1,705 @@
+/************************************************************
+
+Copyright 1987, 1998  The Open Group
+
+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.
+
+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
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 INPUTSTRUCT_H
+#define INPUTSTRUCT_H
+
+#include <X11/extensions/XI2proto.h>
+
+#include <pixman.h>
+#include "input.h"
+#include "window.h"
+#include "dixstruct.h"
+#include "cursorstr.h"
+#include "geext.h"
+#include "privates.h"
+
+extern _X_EXPORT void AssignTypeAndName(DeviceIntPtr dev,
+                                        Atom type,
+                                        const char *name);
+
+#define BitIsOn(ptr, bit) (!!(((const BYTE *) (ptr))[(bit)>>3] & (1 << ((bit) & 7))))
+#define SetBit(ptr, bit)  (((BYTE *) (ptr))[(bit)>>3] |= (1 << ((bit) & 7)))
+#define ClearBit(ptr, bit) (((BYTE *)(ptr))[(bit)>>3] &= ~(1 << ((bit) & 7)))
+extern _X_EXPORT int CountBits(const uint8_t * mask, int len);
+
+#define SameClient(obj,client) \
+	(CLIENT_BITS((obj)->resource) == (client)->clientAsMask)
+
+#define EMASKSIZE	(MAXDEVICES + 2)
+
+/* This is the last XI2 event supported by the server. If you add
+ * events to the protocol, the server will not support these events until
+ * this number here is bumped.
+ */
+#define XI2LASTEVENT    XI_GestureSwipeEnd
+#define XI2MASKSIZE     ((XI2LASTEVENT >> 3) + 1)       /* no of bytes for masks */
+
+/**
+ * Scroll types for ::SetScrollValuator and the scroll type in the
+ * ::ScrollInfoPtr.
+ */
+enum ScrollType {
+    SCROLL_TYPE_NONE = 0,           /**< Not a scrolling valuator */
+    SCROLL_TYPE_VERTICAL = 8,
+    SCROLL_TYPE_HORIZONTAL = 9,
+};
+
+/**
+ * This struct stores the core event mask for each client except the client
+ * that created the window.
+ *
+ * Each window that has events selected from other clients has at least one of
+ * these masks. If multiple clients selected for events on the same window,
+ * these masks are in a linked list.
+ *
+ * The event mask for the client that created the window is stored in
+ * win->eventMask instead.
+ *
+ * The resource id is simply a fake client ID to associate this mask with a
+ * client.
+ *
+ * Kludge: OtherClients and InputClients must be compatible, see code.
+ */
+typedef struct _OtherClients {
+    OtherClientsPtr next;     /**< Pointer to the next mask */
+    XID resource;                 /**< id for putting into resource manager */
+    Mask mask;                /**< Core event mask */
+} OtherClients;
+
+/**
+ * This struct stores the XI event mask for each client.
+ *
+ * Each window that has events selected has at least one of these masks. If
+ * multiple client selected for events on the same window, these masks are in
+ * a linked list.
+ */
+typedef struct _InputClients {
+    InputClientsPtr next;     /**< Pointer to the next mask */
+    XID resource;                 /**< id for putting into resource manager */
+    Mask mask[EMASKSIZE];                /**< Actual XI event mask, deviceid is index */
+    /** XI2 event masks. One per device, each bit is a mask of (1 << type) */
+    struct _XI2Mask *xi2mask;
+} InputClients;
+
+/**
+ * Combined XI event masks from all devices.
+ *
+ * This is the XI equivalent of the deliverableEvents, eventMask and
+ * dontPropagate mask of the WindowRec (or WindowOptRec).
+ *
+ * A window that has an XI client selecting for events has exactly one
+ * OtherInputMasks struct and exactly one InputClients struct hanging off
+ * inputClients. Each further client appends to the inputClients list.
+ * Each Mask field is per-device, with the device id as the index.
+ * Exception: for non-device events (Presence events), the MAXDEVICES
+ * deviceid is used.
+ */
+typedef struct _OtherInputMasks {
+    /**
+     * Bitwise OR of all masks by all clients and the window's parent's masks.
+     */
+    Mask deliverableEvents[EMASKSIZE];
+    /**
+     * Bitwise OR of all masks by all clients on this window.
+     */
+    Mask inputEvents[EMASKSIZE];
+    /** The do-not-propagate masks for each device. */
+    Mask dontPropagateMask[EMASKSIZE];
+    /** The clients that selected for events */
+    InputClientsPtr inputClients;
+    /* XI2 event masks. One per device, each bit is a mask of (1 << type) */
+    struct _XI2Mask *xi2mask;
+} OtherInputMasks;
+
+/*
+ * The following structure gets used for both active and passive grabs. For
+ * active grabs some of the fields (e.g. modifiers) are not used. However,
+ * that is not much waste since there aren't many active grabs (one per
+ * keyboard/pointer device) going at once in the server.
+ */
+
+#define MasksPerDetailMask 8    /* 256 keycodes and 256 possible
+                                   modifier combinations, but only
+                                   3 buttons. */
+
+typedef struct _DetailRec {     /* Grab details may be bit masks */
+    unsigned int exact;
+    Mask *pMask;
+} DetailRec;
+
+union _GrabMask {
+    Mask core;
+    Mask xi;
+    struct _XI2Mask *xi2mask;
+};
+
+/**
+ * Central struct for device grabs.
+ * The same struct is used for both core grabs and device grabs, with
+ * different fields being set.
+ * If the grab is a core grab (GrabPointer/GrabKeyboard), then the eventMask
+ * is a combination of standard event masks (i.e. PointerMotionMask |
+ * ButtonPressMask).
+ * If the grab is a device grab (GrabDevice), then the eventMask is a
+ * combination of event masks for a given XI event type (see SetEventInfo).
+ *
+ * If the grab is a result of a ButtonPress, then eventMask is the core mask
+ * and deviceMask is set to the XI event mask for the grab.
+ */
+typedef struct _GrabRec {
+    GrabPtr next;               /* for chain of passive grabs */
+    XID resource;
+    DeviceIntPtr device;
+    WindowPtr window;
+    unsigned ownerEvents:1;
+    unsigned keyboardMode:1;
+    unsigned pointerMode:1;
+    enum InputLevel grabtype;
+    CARD8 type;                 /* event type for passive grabs, 0 for active grabs */
+    DetailRec modifiersDetail;
+    DeviceIntPtr modifierDevice;
+    DetailRec detail;           /* key or button */
+    WindowPtr confineTo;        /* always NULL for keyboards */
+    CursorPtr cursor;           /* always NULL for keyboards */
+    Mask eventMask;
+    Mask deviceMask;
+    /* XI2 event masks. One per device, each bit is a mask of (1 << type) */
+    struct _XI2Mask *xi2mask;
+} GrabRec;
+
+/**
+ * Sprite information for a device.
+ */
+typedef struct _SpriteRec {
+    CursorPtr current;
+    BoxRec hotLimits;           /* logical constraints of hot spot */
+    Bool confined;              /* confined to screen */
+    RegionPtr hotShape;         /* additional logical shape constraint */
+    BoxRec physLimits;          /* physical constraints of hot spot */
+    WindowPtr win;              /* window of logical position */
+    HotSpot hot;                /* logical pointer position */
+    HotSpot hotPhys;            /* physical pointer position */
+#ifdef PANORAMIX
+    ScreenPtr screen;           /* all others are in Screen 0 coordinates */
+    RegionRec Reg1;             /* Region 1 for confining motion */
+    RegionRec Reg2;             /* Region 2 for confining virtual motion */
+    WindowPtr windows[MAXSCREENS];
+    WindowPtr confineWin;       /* confine window */
+#endif
+    /* The window trace information is used at dix/events.c to avoid having
+     * to compute all the windows between the root and the current pointer
+     * window each time a button or key goes down. The grabs on each of those
+     * windows must be checked.
+     * spriteTraces should only be used at dix/events.c! */
+    WindowPtr *spriteTrace;
+    int spriteTraceSize;
+    int spriteTraceGood;
+
+    /* Due to delays between event generation and event processing, it is
+     * possible that the pointer has crossed screen boundaries between the
+     * time in which it begins generating events and the time when
+     * those events are processed.
+     *
+     * pEnqueueScreen: screen the pointer was on when the event was generated
+     * pDequeueScreen: screen the pointer was on when the event is processed
+     */
+    ScreenPtr pEnqueueScreen;
+    ScreenPtr pDequeueScreen;
+
+} SpriteRec;
+
+typedef struct _KeyClassRec {
+    int sourceid;
+    CARD8 down[DOWN_LENGTH];
+    CARD8 postdown[DOWN_LENGTH];
+    int modifierKeyCount[8];
+    struct _XkbSrvInfo *xkbInfo;
+} KeyClassRec, *KeyClassPtr;
+
+typedef struct _ScrollInfo {
+    enum ScrollType type;
+    double increment;
+    int flags;
+} ScrollInfo, *ScrollInfoPtr;
+
+typedef struct _AxisInfo {
+    int resolution;
+    int min_resolution;
+    int max_resolution;
+    int min_value;
+    int max_value;
+    Atom label;
+    CARD8 mode;
+    ScrollInfo scroll;
+} AxisInfo, *AxisInfoPtr;
+
+typedef struct _ValuatorAccelerationRec {
+    int number;
+    PointerAccelSchemeProc AccelSchemeProc;
+    void *accelData;            /* at disposal of AccelScheme */
+    PointerAccelSchemeInitProc AccelInitProc;
+    DeviceCallbackProc AccelCleanupProc;
+} ValuatorAccelerationRec, *ValuatorAccelerationPtr;
+
+typedef struct _ValuatorClassRec {
+    int sourceid;
+    int numMotionEvents;
+    int first_motion;
+    int last_motion;
+    void *motion;               /* motion history buffer. Different layout
+                                   for MDs and SDs! */
+    WindowPtr motionHintWindow;
+
+    AxisInfoPtr axes;
+    unsigned short numAxes;
+    double *axisVal;            /* always absolute, but device-coord system */
+    ValuatorAccelerationRec accelScheme;
+    int h_scroll_axis;          /* horiz smooth-scrolling axis */
+    int v_scroll_axis;          /* vert smooth-scrolling axis */
+} ValuatorClassRec;
+
+typedef struct _TouchListener {
+    XID listener;           /* grabs/event selection IDs receiving
+                             * events for this touch */
+    int resource_type;      /* listener's resource type */
+    enum TouchListenerType type;
+    enum TouchListenerState state;
+    enum InputLevel level;  /* matters only for emulating touches */
+    WindowPtr window;
+    GrabPtr grab;
+} TouchListener;
+
+typedef struct _TouchPointInfo {
+    uint32_t client_id;         /* touch ID as seen in client events */
+    int sourceid;               /* Source device's ID for this touchpoint */
+    Bool active;                /* whether or not the touch is active */
+    Bool pending_finish;        /* true if the touch is physically inactive
+                                 * but still owned by a grab */
+    SpriteRec sprite;           /* window trace for delivery */
+    ValuatorMask *valuators;    /* last recorded axis values */
+    TouchListener *listeners;   /* set of listeners */
+    int num_listeners;
+    int num_grabs;              /* number of open grabs on this touch
+                                 * which have not accepted or rejected */
+    Bool emulate_pointer;
+    DeviceEvent *history;       /* History of events on this touchpoint */
+    size_t history_elements;    /* Number of current elements in history */
+    size_t history_size;        /* Size of history in elements */
+} TouchPointInfoRec;
+
+typedef struct _DDXTouchPointInfo {
+    uint32_t client_id;         /* touch ID as seen in client events */
+    Bool active;                /* whether or not the touch is active */
+    uint32_t ddx_id;            /* touch ID given by the DDX */
+    Bool emulate_pointer;
+
+    ValuatorMask *valuators;    /* last axis values as posted, pre-transform */
+} DDXTouchPointInfoRec;
+
+typedef struct _TouchClassRec {
+    int sourceid;
+    TouchPointInfoPtr touches;
+    unsigned short num_touches; /* number of allocated touches */
+    unsigned short max_touches; /* maximum number of touches, may be 0 */
+    CARD8 mode;                 /* ::XIDirectTouch, XIDependentTouch */
+    /* for pointer-emulation */
+    CARD8 buttonsDown;          /* number of buttons down */
+    unsigned short state;       /* logical button state */
+    Mask motionMask;
+} TouchClassRec;
+
+typedef struct _GestureListener {
+    XID listener;           /* grabs/event selection IDs receiving
+                             * events for this gesture */
+    int resource_type;      /* listener's resource type */
+    enum GestureListenerType type;
+    WindowPtr window;
+    GrabPtr grab;
+} GestureListener;
+
+typedef struct _GestureInfo {
+    int sourceid;               /* Source device's ID for this gesture */
+    Bool active;                /* whether or not the gesture is active */
+    uint8_t type;               /* Gesture type: either ET_GesturePinchBegin or
+                                   ET_GestureSwipeBegin. Valid if active == TRUE */
+    int num_touches;            /* The number of touches in the gesture */
+    SpriteRec sprite;           /* window trace for delivery */
+    GestureListener listener;   /* the listener that will receive events */
+    Bool has_listener;          /* true if listener has been setup already */
+} GestureInfoRec;
+
+typedef struct _GestureClassRec {
+    int sourceid;
+    GestureInfoRec gesture;
+    unsigned short max_touches; /* maximum number of touches, may be 0 */
+} GestureClassRec;
+
+typedef struct _ButtonClassRec {
+    int sourceid;
+    CARD8 numButtons;
+    CARD8 buttonsDown;          /* number of buttons currently down
+                                   This counts logical buttons, not
+                                   physical ones, i.e if some buttons
+                                   are mapped to 0, they're not counted
+                                   here */
+    unsigned short state;
+    Mask motionMask;
+    CARD8 down[DOWN_LENGTH];
+    CARD8 postdown[DOWN_LENGTH];
+    CARD8 map[MAP_LENGTH];
+    union _XkbAction *xkb_acts;
+    Atom labels[MAX_BUTTONS];
+} ButtonClassRec, *ButtonClassPtr;
+
+typedef struct _FocusClassRec {
+    int sourceid;
+    WindowPtr win;              /* May be set to a int constant (e.g. PointerRootWin)! */
+    int revert;
+    TimeStamp time;
+    WindowPtr *trace;
+    int traceSize;
+    int traceGood;
+} FocusClassRec, *FocusClassPtr;
+
+typedef struct _ProximityClassRec {
+    int sourceid;
+    char in_proximity;
+} ProximityClassRec, *ProximityClassPtr;
+
+typedef struct _KbdFeedbackClassRec *KbdFeedbackPtr;
+typedef struct _PtrFeedbackClassRec *PtrFeedbackPtr;
+typedef struct _IntegerFeedbackClassRec *IntegerFeedbackPtr;
+typedef struct _StringFeedbackClassRec *StringFeedbackPtr;
+typedef struct _BellFeedbackClassRec *BellFeedbackPtr;
+typedef struct _LedFeedbackClassRec *LedFeedbackPtr;
+
+typedef struct _KbdFeedbackClassRec {
+    BellProcPtr BellProc;
+    KbdCtrlProcPtr CtrlProc;
+    KeybdCtrl ctrl;
+    KbdFeedbackPtr next;
+    struct _XkbSrvLedInfo *xkb_sli;
+} KbdFeedbackClassRec;
+
+typedef struct _PtrFeedbackClassRec {
+    PtrCtrlProcPtr CtrlProc;
+    PtrCtrl ctrl;
+    PtrFeedbackPtr next;
+} PtrFeedbackClassRec;
+
+typedef struct _IntegerFeedbackClassRec {
+    IntegerCtrlProcPtr CtrlProc;
+    IntegerCtrl ctrl;
+    IntegerFeedbackPtr next;
+} IntegerFeedbackClassRec;
+
+typedef struct _StringFeedbackClassRec {
+    StringCtrlProcPtr CtrlProc;
+    StringCtrl ctrl;
+    StringFeedbackPtr next;
+} StringFeedbackClassRec;
+
+typedef struct _BellFeedbackClassRec {
+    BellProcPtr BellProc;
+    BellCtrlProcPtr CtrlProc;
+    BellCtrl ctrl;
+    BellFeedbackPtr next;
+} BellFeedbackClassRec;
+
+typedef struct _LedFeedbackClassRec {
+    LedCtrlProcPtr CtrlProc;
+    LedCtrl ctrl;
+    LedFeedbackPtr next;
+    struct _XkbSrvLedInfo *xkb_sli;
+} LedFeedbackClassRec;
+
+typedef struct _ClassesRec {
+    KeyClassPtr key;
+    ValuatorClassPtr valuator;
+    TouchClassPtr touch;
+    GestureClassPtr gesture;
+    ButtonClassPtr button;
+    FocusClassPtr focus;
+    ProximityClassPtr proximity;
+    KbdFeedbackPtr kbdfeed;
+    PtrFeedbackPtr ptrfeed;
+    IntegerFeedbackPtr intfeed;
+    StringFeedbackPtr stringfeed;
+    BellFeedbackPtr bell;
+    LedFeedbackPtr leds;
+} ClassesRec;
+
+/* Device properties */
+typedef struct _XIPropertyValue {
+    Atom type;                  /* ignored by server */
+    short format;               /* format of data for swapping - 8,16,32 */
+    long size;                  /* size of data in (format/8) bytes */
+    void *data;                 /* private to client */
+} XIPropertyValueRec;
+
+typedef struct _XIProperty {
+    struct _XIProperty *next;
+    Atom propertyName;
+    BOOL deletable;             /* clients can delete this prop? */
+    XIPropertyValueRec value;
+} XIPropertyRec;
+
+typedef XIPropertyRec *XIPropertyPtr;
+typedef XIPropertyValueRec *XIPropertyValuePtr;
+
+typedef struct _XIPropertyHandler {
+    struct _XIPropertyHandler *next;
+    long id;
+    int (*SetProperty) (DeviceIntPtr dev,
+                        Atom property, XIPropertyValuePtr prop, BOOL checkonly);
+    int (*GetProperty) (DeviceIntPtr dev, Atom property);
+    int (*DeleteProperty) (DeviceIntPtr dev, Atom property);
+} XIPropertyHandler, *XIPropertyHandlerPtr;
+
+/* states for devices */
+
+#define NOT_GRABBED		0
+#define THAWED			1
+#define THAWED_BOTH		2       /* not a real state */
+#define FREEZE_NEXT_EVENT	3
+#define FREEZE_BOTH_NEXT_EVENT	4
+#define FROZEN			5       /* any state >= has device frozen */
+#define FROZEN_NO_EVENT		5
+#define FROZEN_WITH_EVENT	6
+#define THAW_OTHERS		7
+
+typedef struct _GrabInfoRec {
+    TimeStamp grabTime;
+    Bool fromPassiveGrab;       /* true if from passive grab */
+    Bool implicitGrab;          /* implicit from ButtonPress */
+    GrabPtr unused;             /* Kept for ABI stability, remove soon */
+    GrabPtr grab;
+    CARD8 activatingKey;
+    void (*ActivateGrab) (DeviceIntPtr /*device */ ,
+                          GrabPtr /*grab */ ,
+                          TimeStamp /*time */ ,
+                          Bool /*autoGrab */ );
+    void (*DeactivateGrab) (DeviceIntPtr /*device */ );
+    struct {
+        Bool frozen;
+        int state;
+        GrabPtr other;          /* if other grab has this frozen */
+        InternalEvent *event;   /* saved to be replayed */
+    } sync;
+} GrabInfoRec, *GrabInfoPtr;
+
+typedef struct _SpriteInfoRec {
+    /* sprite must always point to a valid sprite. For devices sharing the
+     * sprite, let sprite point to a paired spriteOwner's sprite. */
+    SpritePtr sprite;           /* sprite information */
+    Bool spriteOwner;           /* True if device owns the sprite */
+    DeviceIntPtr paired;        /* The paired device. Keyboard if
+                                   spriteOwner is TRUE, otherwise the
+                                   pointer that owns the sprite. */
+
+    /* keep states for animated cursor */
+    struct {
+        CursorPtr pCursor;
+        ScreenPtr pScreen;
+        int elt;
+    } anim;
+} SpriteInfoRec, *SpriteInfoPtr;
+
+/* device types */
+#define MASTER_POINTER          1
+#define MASTER_KEYBOARD         2
+#define SLAVE                   3
+/* special types for GetMaster */
+#define MASTER_ATTACHED         4       /* Master for this device */
+#define KEYBOARD_OR_FLOAT       5       /* Keyboard master for this device or this device if floating */
+#define POINTER_OR_FLOAT        6       /* Pointer master for this device or this device if floating */
+
+typedef struct _DeviceIntRec {
+    DeviceRec public;
+    DeviceIntPtr next;
+    Bool startup;               /* true if needs to be turned on at
+                                   server initialization time */
+    DeviceProc deviceProc;      /* proc(DevicePtr, DEVICE_xx). It is
+                                   used to initialize, turn on, or
+                                   turn off the device */
+    Bool inited;                /* TRUE if INIT returns Success */
+    Bool enabled;               /* TRUE if ON returns Success */
+    Bool coreEvents;            /* TRUE if device also sends core */
+    GrabInfoRec deviceGrab;     /* grab on the device */
+    int type;                   /* MASTER_POINTER, MASTER_KEYBOARD, SLAVE */
+    Atom xinput_type;
+    char *name;
+    int id;
+    KeyClassPtr key;
+    ValuatorClassPtr valuator;
+    TouchClassPtr touch;
+    GestureClassPtr gesture;
+    ButtonClassPtr button;
+    FocusClassPtr focus;
+    ProximityClassPtr proximity;
+    KbdFeedbackPtr kbdfeed;
+    PtrFeedbackPtr ptrfeed;
+    IntegerFeedbackPtr intfeed;
+    StringFeedbackPtr stringfeed;
+    BellFeedbackPtr bell;
+    LedFeedbackPtr leds;
+    struct _XkbInterest *xkb_interest;
+    char *config_info;          /* used by the hotplug layer */
+    ClassesPtr unused_classes;  /* for master devices */
+    int saved_master_id;        /* for slaves while grabbed */
+    PrivateRec *devPrivates;
+    DeviceUnwrapProc unwrapProc;
+    SpriteInfoPtr spriteInfo;
+    DeviceIntPtr master;        /* master device */
+    DeviceIntPtr lastSlave;     /* last slave device used */
+
+    /* last valuator values recorded, not posted to client;
+     * for slave devices, valuators is in device coordinates, mapped to the
+     * desktop
+     * for master devices, valuators is in desktop coordinates.
+     * see dix/getevents.c
+     * remainder supports acceleration
+     */
+    struct {
+        double valuators[MAX_VALUATORS];
+        int numValuators;
+        DeviceIntPtr slave;
+        int slave_type;
+        ValuatorMask *scroll;
+        int num_touches;        /* size of the touches array */
+        DDXTouchPointInfoPtr touches;
+    } last;
+
+    /* Input device property handling. */
+    struct {
+        XIPropertyPtr properties;
+        XIPropertyHandlerPtr handlers;  /* NULL-terminated */
+    } properties;
+
+    /* coordinate transformation matrix for relative movement. Matrix with
+     * the translation component dropped */
+    struct pixman_f_transform relative_transform;
+    /* scale matrix for absolute devices, this is the combined matrix of
+       [1/scale] . [transform] . [scale]. See DeviceSetTransform */
+    struct pixman_f_transform scale_and_transform;
+
+    /* XTest related master device id */
+    int xtest_master_id;
+
+    struct _SyncCounter *idle_counter;
+} DeviceIntRec;
+
+typedef struct {
+    int numDevices;             /* total number of devices */
+    DeviceIntPtr devices;       /* all devices turned on */
+    DeviceIntPtr off_devices;   /* all devices turned off */
+    DeviceIntPtr keyboard;      /* the main one for the server */
+    DeviceIntPtr pointer;
+    DeviceIntPtr all_devices;
+    DeviceIntPtr all_master_devices;
+} InputInfo;
+
+extern _X_EXPORT InputInfo inputInfo;
+
+/* for keeping the events for devices grabbed synchronously */
+typedef struct _QdEvent *QdEventPtr;
+typedef struct _QdEvent {
+    struct xorg_list next;
+    DeviceIntPtr device;
+    ScreenPtr pScreen;          /* what screen the pointer was on */
+    unsigned long months;       /* milliseconds is in the event */
+    InternalEvent *event;
+} QdEventRec;
+
+/**
+ * syncEvents is the global structure for queued events.
+ *
+ * Devices can be frozen through GrabModeSync pointer grabs. If this is the
+ * case, events from these devices are added to "pending" instead of being
+ * processed normally. When the device is unfrozen, events in "pending" are
+ * replayed and processed as if they would come from the device directly.
+ */
+typedef struct _EventSyncInfo {
+    struct xorg_list pending;
+
+    /** The device to replay events for. Only set in AllowEvents(), in which
+     * case it is set to the device specified in the request. */
+    DeviceIntPtr replayDev;     /* kludgy rock to put flag for */
+
+    /**
+     * The window the events are supposed to be replayed on.
+     * This window may be set to the grab's window (but only when
+     * Replay{Pointer|Keyboard} is given in the XAllowEvents()
+     * request. */
+    WindowPtr replayWin;        /*   ComputeFreezes            */
+    /**
+     * Flag to indicate whether we're in the process of
+     * replaying events. Only set in ComputeFreezes(). */
+    Bool playingEvents;
+    TimeStamp time;
+} EventSyncInfoRec, *EventSyncInfoPtr;
+
+extern EventSyncInfoRec syncEvents;
+
+/**
+ * Given a sprite, returns the window at the bottom of the trace (i.e. the
+ * furthest window from the root).
+ */
+static inline WindowPtr
+DeepestSpriteWin(SpritePtr sprite)
+{
+    assert(sprite->spriteTraceGood > 0);
+    return sprite->spriteTrace[sprite->spriteTraceGood - 1];
+}
+
+struct _XI2Mask {
+    unsigned char **masks;      /* event mask in masks[deviceid][event type byte] */
+    size_t nmasks;              /* number of masks */
+    size_t mask_size;           /* size of each mask in bytes */
+};
+
+#endif                          /* INPUTSTRUCT_H */
Index: xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/include
===================================================================
--- xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/include	(nonexistent)
+++ xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/include	(revision 5)

Property changes on: xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new/include
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new
===================================================================
--- xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new	(nonexistent)
+++ xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new	(revision 5)

Property changes on: xorg-server/create-21.1.7-mouse-kbd-layout-patch/xorg-server-21.1.7-new
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-mouse-kbd-layout-patch
===================================================================
--- xorg-server/create-21.1.7-mouse-kbd-layout-patch	(nonexistent)
+++ xorg-server/create-21.1.7-mouse-kbd-layout-patch	(revision 5)

Property changes on: xorg-server/create-21.1.7-mouse-kbd-layout-patch
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-nouveau-segfault-patch/create.patch.sh
===================================================================
--- xorg-server/create-21.1.7-nouveau-segfault-patch/create.patch.sh	(nonexistent)
+++ xorg-server/create-21.1.7-nouveau-segfault-patch/create.patch.sh	(revision 5)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=21.1.7
+
+tar --files-from=file.list -xJvf ../xorg-server-$VERSION.tar.xz
+mv xorg-server-$VERSION xorg-server-$VERSION-orig
+
+cp -rf ./xorg-server-$VERSION-new ./xorg-server-$VERSION
+
+diff --unified -Nr  xorg-server-$VERSION-orig  xorg-server-$VERSION > xorg-server-$VERSION-nouveau-segfault.patch
+
+mv xorg-server-$VERSION-nouveau-segfault.patch ../patches
+
+rm -rf ./xorg-server-$VERSION
+rm -rf ./xorg-server-$VERSION-orig

Property changes on: xorg-server/create-21.1.7-nouveau-segfault-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: xorg-server/create-21.1.7-nouveau-segfault-patch/file.list
===================================================================
--- xorg-server/create-21.1.7-nouveau-segfault-patch/file.list	(nonexistent)
+++ xorg-server/create-21.1.7-nouveau-segfault-patch/file.list	(revision 5)
@@ -0,0 +1 @@
+xorg-server-21.1.7/render/mipict.c
Index: xorg-server/create-21.1.7-nouveau-segfault-patch/xorg-server-21.1.7-new/render/mipict.c
===================================================================
--- xorg-server/create-21.1.7-nouveau-segfault-patch/xorg-server-21.1.7-new/render/mipict.c	(nonexistent)
+++ xorg-server/create-21.1.7-nouveau-segfault-patch/xorg-server-21.1.7-new/render/mipict.c	(revision 5)
@@ -0,0 +1,590 @@
+/*
+ *
+ * Copyright © 1999 Keith Packard
+ *
+ * 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 "scrnintstr.h"
+#include "gcstruct.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "mi.h"
+#include "picturestr.h"
+#include "mipict.h"
+
+int
+miCreatePicture(PicturePtr pPicture)
+{
+    return Success;
+}
+
+void
+miDestroyPicture(PicturePtr pPicture)
+{
+    if (pPicture->freeCompClip)
+        RegionDestroy(pPicture->pCompositeClip);
+}
+
+static void
+miDestroyPictureClip(PicturePtr pPicture)
+{
+    if (pPicture->clientClip)
+        RegionDestroy(pPicture->clientClip);
+    pPicture->clientClip = NULL;
+}
+
+static int
+miChangePictureClip(PicturePtr pPicture, int type, void *value, int n)
+{
+    ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+    PictureScreenPtr ps = GetPictureScreen(pScreen);
+    RegionPtr clientClip;
+
+    switch (type) {
+    case CT_PIXMAP:
+        /* convert the pixmap to a region */
+        clientClip = BitmapToRegion(pScreen, (PixmapPtr) value);
+        if (!clientClip)
+            return BadAlloc;
+        (*pScreen->DestroyPixmap) ((PixmapPtr) value);
+        break;
+    case CT_REGION:
+        clientClip = value;
+        break;
+    case CT_NONE:
+        clientClip = 0;
+        break;
+    default:
+        clientClip = RegionFromRects(n, (xRectangle *) value, type);
+        if (!clientClip)
+            return BadAlloc;
+        free(value);
+        break;
+    }
+    (*ps->DestroyPictureClip) (pPicture);
+    pPicture->clientClip = clientClip;
+    pPicture->stateChanges |= CPClipMask;
+    return Success;
+}
+
+static void
+miChangePicture(PicturePtr pPicture, Mask mask)
+{
+    return;
+}
+
+static void
+miValidatePicture(PicturePtr pPicture, Mask mask)
+{
+    DrawablePtr pDrawable = pPicture->pDrawable;
+
+    if ((mask & (CPClipXOrigin | CPClipYOrigin | CPClipMask | CPSubwindowMode))
+        || (pDrawable->serialNumber !=
+            (pPicture->serialNumber & DRAWABLE_SERIAL_BITS))) {
+        if (pDrawable->type == DRAWABLE_WINDOW) {
+            WindowPtr pWin = (WindowPtr) pDrawable;
+            RegionPtr pregWin;
+            Bool freeTmpClip, freeCompClip;
+
+            if (pPicture->subWindowMode == IncludeInferiors) {
+                pregWin = NotClippedByChildren(pWin);
+                freeTmpClip = TRUE;
+            }
+            else {
+                pregWin = &pWin->clipList;
+                freeTmpClip = FALSE;
+            }
+            freeCompClip = pPicture->freeCompClip;
+
+            /*
+             * if there is no client clip, we can get by with just keeping the
+             * pointer we got, and remembering whether or not should destroy
+             * (or maybe re-use) it later.  this way, we avoid unnecessary
+             * copying of regions.  (this wins especially if many clients clip
+             * by children and have no client clip.)
+             */
+            if (!pPicture->clientClip) {
+                if (freeCompClip)
+                    RegionDestroy(pPicture->pCompositeClip);
+                pPicture->pCompositeClip = pregWin;
+                pPicture->freeCompClip = freeTmpClip;
+            }
+            else {
+                /*
+                 * we need one 'real' region to put into the composite clip. if
+                 * pregWin the current composite clip are real, we can get rid of
+                 * one. if pregWin is real and the current composite clip isn't,
+                 * use pregWin for the composite clip. if the current composite
+                 * clip is real and pregWin isn't, use the current composite
+                 * clip. if neither is real, create a new region.
+                 */
+
+                RegionTranslate(pPicture->clientClip,
+                                pDrawable->x + pPicture->clipOrigin.x,
+                                pDrawable->y + pPicture->clipOrigin.y);
+
+                if (freeCompClip) {
+                    RegionIntersect(pPicture->pCompositeClip,
+                                    pregWin, pPicture->clientClip);
+                    if (freeTmpClip)
+                        RegionDestroy(pregWin);
+                }
+                else if (freeTmpClip) {
+                    RegionIntersect(pregWin, pregWin, pPicture->clientClip);
+                    pPicture->pCompositeClip = pregWin;
+                }
+                else {
+                    pPicture->pCompositeClip = RegionCreate(NullBox, 0);
+                    RegionIntersect(pPicture->pCompositeClip,
+                                    pregWin, pPicture->clientClip);
+                }
+                pPicture->freeCompClip = TRUE;
+                RegionTranslate(pPicture->clientClip,
+                                -(pDrawable->x + pPicture->clipOrigin.x),
+                                -(pDrawable->y + pPicture->clipOrigin.y));
+            }
+        }                       /* end of composite clip for a window */
+        else {
+            BoxRec pixbounds;
+
+            /* XXX should we translate by drawable.x/y here ? */
+            /* If you want pixmaps in offscreen memory, yes */
+            pixbounds.x1 = pDrawable->x;
+            pixbounds.y1 = pDrawable->y;
+            pixbounds.x2 = pDrawable->x + pDrawable->width;
+            pixbounds.y2 = pDrawable->y + pDrawable->height;
+
+            if (pPicture->freeCompClip) {
+                RegionReset(pPicture->pCompositeClip, &pixbounds);
+            }
+            else {
+                pPicture->freeCompClip = TRUE;
+                pPicture->pCompositeClip = RegionCreate(&pixbounds, 1);
+            }
+
+            if (pPicture->clientClip) {
+                if (pDrawable->x || pDrawable->y) {
+                    RegionTranslate(pPicture->clientClip,
+                                    pDrawable->x + pPicture->clipOrigin.x,
+                                    pDrawable->y + pPicture->clipOrigin.y);
+                    RegionIntersect(pPicture->pCompositeClip,
+                                    pPicture->pCompositeClip,
+                                    pPicture->clientClip);
+                    RegionTranslate(pPicture->clientClip,
+                                    -(pDrawable->x + pPicture->clipOrigin.x),
+                                    -(pDrawable->y + pPicture->clipOrigin.y));
+                }
+                else {
+                    RegionTranslate(pPicture->pCompositeClip,
+                                    -pPicture->clipOrigin.x,
+                                    -pPicture->clipOrigin.y);
+                    RegionIntersect(pPicture->pCompositeClip,
+                                    pPicture->pCompositeClip,
+                                    pPicture->clientClip);
+                    RegionTranslate(pPicture->pCompositeClip,
+                                    pPicture->clipOrigin.x,
+                                    pPicture->clipOrigin.y);
+                }
+            }
+        }                       /* end of composite clip for pixmap */
+    }
+}
+
+static int
+miChangePictureTransform(PicturePtr pPicture, PictTransform * transform)
+{
+    return Success;
+}
+
+static int
+miChangePictureFilter(PicturePtr pPicture,
+                      int filter, xFixed * params, int nparams)
+{
+    return Success;
+}
+
+#define BOUND(v)	(INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v))
+
+static inline pixman_bool_t
+miClipPictureReg(pixman_region16_t * pRegion,
+                 pixman_region16_t * pClip, int dx, int dy)
+{
+    if (pixman_region_n_rects(pRegion) == 1 &&
+        pixman_region_n_rects(pClip) == 1) {
+        pixman_box16_t *pRbox = pixman_region_rectangles(pRegion, NULL);
+        pixman_box16_t *pCbox = pixman_region_rectangles(pClip, NULL);
+        int v;
+
+        if (pRbox->x1 < (v = pCbox->x1 + dx))
+            pRbox->x1 = BOUND(v);
+        if (pRbox->x2 > (v = pCbox->x2 + dx))
+            pRbox->x2 = BOUND(v);
+        if (pRbox->y1 < (v = pCbox->y1 + dy))
+            pRbox->y1 = BOUND(v);
+        if (pRbox->y2 > (v = pCbox->y2 + dy))
+            pRbox->y2 = BOUND(v);
+        if (pRbox->x1 >= pRbox->x2 || pRbox->y1 >= pRbox->y2) {
+            pixman_region_init(pRegion);
+        }
+    }
+    else if (!pixman_region_not_empty(pClip))
+        return FALSE;
+    else {
+        if (dx || dy)
+            pixman_region_translate(pRegion, -dx, -dy);
+        if (!pixman_region_intersect(pRegion, pRegion, pClip))
+            return FALSE;
+        if (dx || dy)
+            pixman_region_translate(pRegion, dx, dy);
+    }
+    return pixman_region_not_empty(pRegion);
+}
+
+static inline Bool
+miClipPictureSrc(RegionPtr pRegion, PicturePtr pPicture, int dx, int dy)
+{
+    if (pPicture->clientClip) {
+        Bool result;
+
+        pixman_region_translate(pPicture->clientClip,
+                                pPicture->clipOrigin.x + dx,
+                                pPicture->clipOrigin.y + dy);
+
+        result = RegionIntersect(pRegion, pRegion, pPicture->clientClip);
+
+        pixman_region_translate(pPicture->clientClip,
+                                -(pPicture->clipOrigin.x + dx),
+                                -(pPicture->clipOrigin.y + dy));
+
+        if (!result)
+            return FALSE;
+    }
+    return TRUE;
+}
+
+static void
+SourceValidateOnePicture(PicturePtr pPicture)
+{
+    DrawablePtr pDrawable = pPicture->pDrawable;
+    ScreenPtr pScreen;
+
+    if (!pDrawable)
+        return;
+
+    pScreen = pDrawable->pScreen;
+
+    pScreen->SourceValidate(pDrawable, 0, 0, pDrawable->width,
+                            pDrawable->height, pPicture->subWindowMode);
+}
+
+void
+miCompositeSourceValidate(PicturePtr pPicture)
+{
+    SourceValidateOnePicture(pPicture);
+    if (pPicture->alphaMap)
+        SourceValidateOnePicture(pPicture->alphaMap);
+}
+
+/*
+ * returns FALSE if the final region is empty.  Indistinguishable from
+ * an allocation failure, but rendering ignores those anyways.
+ */
+
+Bool
+miComputeCompositeRegion(RegionPtr pRegion,
+                         PicturePtr pSrc,
+                         PicturePtr pMask,
+                         PicturePtr pDst,
+                         INT16 xSrc,
+                         INT16 ySrc,
+                         INT16 xMask,
+                         INT16 yMask,
+                         INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
+{
+
+    int v;
+
+    pRegion->extents.x1 = xDst;
+    v = xDst + width;
+    pRegion->extents.x2 = BOUND(v);
+    pRegion->extents.y1 = yDst;
+    v = yDst + height;
+    pRegion->extents.y2 = BOUND(v);
+    pRegion->data = 0;
+    /* Check for empty operation */
+    if (pRegion->extents.x1 >= pRegion->extents.x2 ||
+        pRegion->extents.y1 >= pRegion->extents.y2) {
+        pixman_region_init(pRegion);
+        return FALSE;
+    }
+    /* clip against dst */
+    if (!miClipPictureReg(pRegion, pDst->pCompositeClip, 0, 0)) {
+        pixman_region_fini(pRegion);
+        return FALSE;
+    }
+    if (pDst->alphaMap) {
+        if (!miClipPictureReg(pRegion, pDst->alphaMap->pCompositeClip,
+                              -pDst->alphaOrigin.x, -pDst->alphaOrigin.y)) {
+            pixman_region_fini(pRegion);
+            return FALSE;
+        }
+    }
+    /* clip against src */
+    if (!miClipPictureSrc(pRegion, pSrc, xDst - xSrc, yDst - ySrc)) {
+        pixman_region_fini(pRegion);
+        return FALSE;
+    }
+    if (pSrc->alphaMap) {
+        if (!miClipPictureSrc(pRegion, pSrc->alphaMap,
+                              xDst - (xSrc - pSrc->alphaOrigin.x),
+                              yDst - (ySrc - pSrc->alphaOrigin.y))) {
+            pixman_region_fini(pRegion);
+            return FALSE;
+        }
+    }
+    /* clip against mask */
+    if (pMask) {
+        if (!miClipPictureSrc(pRegion, pMask, xDst - xMask, yDst - yMask)) {
+            pixman_region_fini(pRegion);
+            return FALSE;
+        }
+        if (pMask->alphaMap) {
+            if (!miClipPictureSrc(pRegion, pMask->alphaMap,
+                                  xDst - (xMask - pMask->alphaOrigin.x),
+                                  yDst - (yMask - pMask->alphaOrigin.y))) {
+                pixman_region_fini(pRegion);
+                return FALSE;
+            }
+        }
+    }
+
+    miCompositeSourceValidate(pSrc);
+    if (pMask)
+        miCompositeSourceValidate(pMask);
+
+    return TRUE;
+}
+
+void
+miRenderColorToPixel(PictFormatPtr format, xRenderColor * color, CARD32 *pixel)
+{
+    CARD32 r, g, b, a;
+    miIndexedPtr pIndexed;
+
+    if(! format)
+        *pixel = (color->alpha >> 8 << 24) | (color->red >> 8 << 16) | (color->green & 0xff00) | (color->blue >> 8);
+    else
+    switch (format->type) {
+    case PictTypeDirect:
+        r = color->red >> (16 - Ones(format->direct.redMask));
+        g = color->green >> (16 - Ones(format->direct.greenMask));
+        b = color->blue >> (16 - Ones(format->direct.blueMask));
+        a = color->alpha >> (16 - Ones(format->direct.alphaMask));
+        r = r << format->direct.red;
+        g = g << format->direct.green;
+        b = b << format->direct.blue;
+        a = a << format->direct.alpha;
+        *pixel = r | g | b | a;
+        break;
+    case PictTypeIndexed:
+        pIndexed = (miIndexedPtr) (format->index.devPrivate);
+        if (pIndexed->color) {
+            r = color->red >> 11;
+            g = color->green >> 11;
+            b = color->blue >> 11;
+            *pixel = miIndexToEnt15(pIndexed, (r << 10) | (g << 5) | b);
+        }
+        else {
+            r = color->red >> 8;
+            g = color->green >> 8;
+            b = color->blue >> 8;
+            *pixel = miIndexToEntY24(pIndexed, (r << 16) | (g << 8) | b);
+        }
+        break;
+    }
+}
+
+static CARD16
+miFillColor(CARD32 pixel, int bits)
+{
+    while (bits < 16) {
+        pixel |= pixel << bits;
+        bits <<= 1;
+    }
+    return (CARD16) pixel;
+}
+
+Bool
+miIsSolidAlpha(PicturePtr pSrc)
+{
+    ScreenPtr pScreen;
+    char line[1];
+
+    if (!pSrc->pDrawable)
+        return FALSE;
+
+    pScreen = pSrc->pDrawable->pScreen;
+
+    /* Alpha-only */
+    if (PICT_FORMAT_TYPE(pSrc->format) != PICT_TYPE_A)
+        return FALSE;
+    /* repeat */
+    if (!pSrc->repeat)
+        return FALSE;
+    /* 1x1 */
+    if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1)
+        return FALSE;
+    line[0] = 1;
+    (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line);
+    switch (pSrc->pDrawable->bitsPerPixel) {
+    case 1:
+        return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80;
+    case 4:
+        return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0;
+    case 8:
+        return (CARD8) line[0] == 0xff;
+    default:
+        return FALSE;
+    }
+}
+
+void
+miRenderPixelToColor(PictFormatPtr format, CARD32 pixel, xRenderColor * color)
+{
+    CARD32 r, g, b, a;
+    miIndexedPtr pIndexed;
+
+    switch (format->type) {
+    case PictTypeDirect:
+        r = (pixel >> format->direct.red) & format->direct.redMask;
+        g = (pixel >> format->direct.green) & format->direct.greenMask;
+        b = (pixel >> format->direct.blue) & format->direct.blueMask;
+        a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
+        color->red = miFillColor(r, Ones(format->direct.redMask));
+        color->green = miFillColor(g, Ones(format->direct.greenMask));
+        color->blue = miFillColor(b, Ones(format->direct.blueMask));
+        color->alpha = miFillColor(a, Ones(format->direct.alphaMask));
+        break;
+    case PictTypeIndexed:
+        pIndexed = (miIndexedPtr) (format->index.devPrivate);
+        pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED - 1)];
+        r = (pixel >> 16) & 0xff;
+        g = (pixel >> 8) & 0xff;
+        b = (pixel) & 0xff;
+        color->red = miFillColor(r, 8);
+        color->green = miFillColor(g, 8);
+        color->blue = miFillColor(b, 8);
+        color->alpha = 0xffff;
+        break;
+    }
+}
+
+static void
+miTriStrip(CARD8 op,
+           PicturePtr pSrc,
+           PicturePtr pDst,
+           PictFormatPtr maskFormat,
+           INT16 xSrc, INT16 ySrc, int npoints, xPointFixed * points)
+{
+    xTriangle *tris, *tri;
+    int ntri;
+
+    ntri = npoints - 2;
+    tris = xallocarray(ntri, sizeof(xTriangle));
+    if (!tris)
+        return;
+
+    for (tri = tris; npoints >= 3; npoints--, points++, tri++) {
+        tri->p1 = points[0];
+        tri->p2 = points[1];
+        tri->p3 = points[2];
+    }
+    CompositeTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
+    free(tris);
+}
+
+static void
+miTriFan(CARD8 op,
+         PicturePtr pSrc,
+         PicturePtr pDst,
+         PictFormatPtr maskFormat,
+         INT16 xSrc, INT16 ySrc, int npoints, xPointFixed * points)
+{
+    xTriangle *tris, *tri;
+    xPointFixed *first;
+    int ntri;
+
+    ntri = npoints - 2;
+    tris = xallocarray(ntri, sizeof(xTriangle));
+    if (!tris)
+        return;
+
+    first = points++;
+    for (tri = tris; npoints >= 3; npoints--, points++, tri++) {
+        tri->p1 = *first;
+        tri->p2 = points[0];
+        tri->p3 = points[1];
+    }
+    CompositeTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
+    free(tris);
+}
+
+Bool
+miPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
+{
+    PictureScreenPtr ps;
+
+    if (!PictureInit(pScreen, formats, nformats))
+        return FALSE;
+    ps = GetPictureScreen(pScreen);
+    ps->CreatePicture = miCreatePicture;
+    ps->DestroyPicture = miDestroyPicture;
+    ps->ChangePictureClip = miChangePictureClip;
+    ps->DestroyPictureClip = miDestroyPictureClip;
+    ps->ChangePicture = miChangePicture;
+    ps->ValidatePicture = miValidatePicture;
+    ps->InitIndexed = miInitIndexed;
+    ps->CloseIndexed = miCloseIndexed;
+    ps->UpdateIndexed = miUpdateIndexed;
+    ps->ChangePictureTransform = miChangePictureTransform;
+    ps->ChangePictureFilter = miChangePictureFilter;
+    ps->RealizeGlyph = miRealizeGlyph;
+    ps->UnrealizeGlyph = miUnrealizeGlyph;
+
+    /* MI rendering routines */
+    ps->Composite = 0;          /* requires DDX support */
+    ps->Glyphs = miGlyphs;
+    ps->CompositeRects = miCompositeRects;
+    ps->Trapezoids = 0;
+    ps->Triangles = 0;
+
+    ps->RasterizeTrapezoid = 0; /* requires DDX support */
+    ps->AddTraps = 0;           /* requires DDX support */
+    ps->AddTriangles = 0;       /* requires DDX support */
+
+    ps->TriStrip = miTriStrip;  /* converts call to CompositeTriangles */
+    ps->TriFan = miTriFan;
+
+    return TRUE;
+}
Index: xorg-server/create-21.1.7-nouveau-segfault-patch/xorg-server-21.1.7-new/render
===================================================================
--- xorg-server/create-21.1.7-nouveau-segfault-patch/xorg-server-21.1.7-new/render	(nonexistent)
+++ xorg-server/create-21.1.7-nouveau-segfault-patch/xorg-server-21.1.7-new/render	(revision 5)

Property changes on: xorg-server/create-21.1.7-nouveau-segfault-patch/xorg-server-21.1.7-new/render
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-nouveau-segfault-patch/xorg-server-21.1.7-new
===================================================================
--- xorg-server/create-21.1.7-nouveau-segfault-patch/xorg-server-21.1.7-new	(nonexistent)
+++ xorg-server/create-21.1.7-nouveau-segfault-patch/xorg-server-21.1.7-new	(revision 5)

Property changes on: xorg-server/create-21.1.7-nouveau-segfault-patch/xorg-server-21.1.7-new
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/create-21.1.7-nouveau-segfault-patch
===================================================================
--- xorg-server/create-21.1.7-nouveau-segfault-patch	(nonexistent)
+++ xorg-server/create-21.1.7-nouveau-segfault-patch	(revision 5)

Property changes on: xorg-server/create-21.1.7-nouveau-segfault-patch
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server/patches/README
===================================================================
--- xorg-server/patches/README	(nonexistent)
+++ xorg-server/patches/README	(revision 5)
@@ -0,0 +1,22 @@
+
+/* begin *
+
+   xorg-server-21.1.7-black.patch                       - Start X with black screen
+   xorg-server-21.1.7-dont-check-SeatId.patch           - xephyr: Don't check for SeatId anymore
+   xorg-server-21.1.7-mouse-kbd-layout.patch            - Combo mouse keyboard layout patch
+   xorg-server-21.1.7-modesetting-on-GeForce.patch      - xfree86: use modesetting driver by default on GeForce 8 and newer
+   xorg-server-21.1.7-intel-ddx-only-on-pre-gen4.patch  - Use intel ddx only on pre-gen4 hw, newer ones will fall back to modesetting
+   xorg-server-21.1.7-nouveau-segfault.patch            - Fix segfault
+
+
+   Applying Order:
+   --------------
+
+   xorg-server-21.1.7-black.patch
+   xorg-server-21.1.7-dont-check-SeatId.patch
+   xorg-server-21.1.7-mouse-kbd-layout.patch
+   xorg-server-21.1.7-modesetting-on-GeForce.patch
+   xorg-server-21.1.7-intel-ddx-only-on-pre-gen4.patch
+   xorg-server-21.1.7-nouveau-segfault.patch
+
+ * end */
Index: xorg-server/patches
===================================================================
--- xorg-server/patches	(nonexistent)
+++ xorg-server/patches	(revision 5)

Property changes on: xorg-server/patches
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xorg-server
===================================================================
--- xorg-server	(nonexistent)
+++ xorg-server	(revision 5)

Property changes on: xorg-server
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: xwayland/Makefile
===================================================================
--- xwayland/Makefile	(nonexistent)
+++ xwayland/Makefile	(revision 5)
@@ -0,0 +1,47 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/X.org/xserver/xwayland
+
+versions    = 22.1.8
+pkgname     = xwayland
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s)
Index: xwayland
===================================================================
--- xwayland	(nonexistent)
+++ xwayland	(revision 5)

Property changes on: xwayland
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: .
===================================================================
--- .	(nonexistent)
+++ .	(revision 5)

Property changes on: .
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~