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(¤t, 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
+*~