aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/dix
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2010-06-11 12:14:52 +0000
committermarha <marha@users.sourceforge.net>2010-06-11 12:14:52 +0000
commit4c61bf84b11e26e6f22648668c95ea760a379163 (patch)
tree0ac762ab2815eae283dded7447ad7cb5a54b926a /xorg-server/dix
parente1dabd2ce8be0d70c6c15353b58de256129dfd1f (diff)
downloadvcxsrv-4c61bf84b11e26e6f22648668c95ea760a379163.tar.gz
vcxsrv-4c61bf84b11e26e6f22648668c95ea760a379163.tar.bz2
vcxsrv-4c61bf84b11e26e6f22648668c95ea760a379163.zip
xserver git update 11/6/2010
Diffstat (limited to 'xorg-server/dix')
-rw-r--r--xorg-server/dix/Makefile.am147
-rw-r--r--xorg-server/dix/colormap.c5527
-rw-r--r--xorg-server/dix/cursor.c39
-rw-r--r--xorg-server/dix/devices.c107
-rw-r--r--xorg-server/dix/dispatch.c166
-rw-r--r--xorg-server/dix/dixfonts.c20
-rw-r--r--xorg-server/dix/dixutils.c12
-rw-r--r--xorg-server/dix/enterleave.c2770
-rw-r--r--xorg-server/dix/events.c288
-rw-r--r--xorg-server/dix/extension.c17
-rw-r--r--xorg-server/dix/gc.c15
-rw-r--r--xorg-server/dix/getevents.c26
-rw-r--r--xorg-server/dix/globals.c276
-rw-r--r--xorg-server/dix/grabs.c8
-rw-r--r--xorg-server/dix/inpututils.c6
-rw-r--r--xorg-server/dix/main.c28
-rw-r--r--xorg-server/dix/pixmap.c17
-rw-r--r--xorg-server/dix/privates.c537
-rw-r--r--xorg-server/dix/property.c47
-rw-r--r--xorg-server/dix/ptrveloc.c2
-rw-r--r--xorg-server/dix/region.c1659
-rw-r--r--xorg-server/dix/resource.c4
-rw-r--r--xorg-server/dix/selection.c3
-rw-r--r--xorg-server/dix/swapreq.c2198
-rw-r--r--xorg-server/dix/window.c383
25 files changed, 8122 insertions, 6180 deletions
diff --git a/xorg-server/dix/Makefile.am b/xorg-server/dix/Makefile.am
index 42b5121fe..8e6f7dd6a 100644
--- a/xorg-server/dix/Makefile.am
+++ b/xorg-server/dix/Makefile.am
@@ -1,73 +1,74 @@
-noinst_LTLIBRARIES = libdix.la libmain.la
-
-AM_CFLAGS = $(DIX_CFLAGS)
-
-libmain_la_SOURCES = \
- main.c
-
-libdix_la_SOURCES = \
- atom.c \
- colormap.c \
- cursor.c \
- deprecated.c \
- devices.c \
- dispatch.c \
- dispatch.h \
- dixfonts.c \
- dixutils.c \
- enterleave.c \
- enterleave.h \
- events.c \
- eventconvert.c \
- extension.c \
- ffs.c \
- gc.c \
- getevents.c \
- globals.c \
- glyphcurs.c \
- grabs.c \
- initatoms.c \
- inpututils.c \
- pixmap.c \
- privates.c \
- property.c \
- ptrveloc.c \
- registry.c \
- resource.c \
- selection.c \
- swaprep.c \
- swapreq.c \
- tables.c \
- window.c
-
-EXTRA_DIST = buildatoms BuiltInAtoms Xserver.d Xserver-dtrace.h.in
-
-# Install list of protocol names
-miscconfigdir = $(SERVER_MISC_CONFIG_PATH)
-dist_miscconfig_DATA = protocol.txt
-
-if XSERVER_DTRACE
-# Generate dtrace header file for C sources to include
-BUILT_SOURCES = Xserver-dtrace.h
-
-Xserver-dtrace.h: $(srcdir)/Xserver.d
- $(AM_V_GEN)$(DTRACE) -C -h -o $@ -s $(srcdir)/Xserver.d \
- || cp Xserver-dtrace.h.in $@
-
-endif
-
-if SPECIAL_DTRACE_OBJECTS
-# Generate dtrace object code for probes in libdix
-dtrace-dix.o: $(top_srcdir)/dix/Xserver.d $(am_libdix_la_OBJECTS)
- $(AM_V_GEN)$(DTRACE) -G -C -o $@ -s $(top_srcdir)/dix/Xserver.d $(am_libdix_la_OBJECTS:%.lo=.libs/%.o)
-
-noinst_PROGRAMS = dix.O
-
-dix.O: dtrace-dix.o $(am_libdix_la_OBJECTS)
- $(AM_V_GEN)ld -r -o $@ $(am_libdix_la_OBJECTS:%.lo=.libs/%.o)
-endif
-
-dix.c:
- touch $@
-
-CLEANFILES = dix.c Xserver-dtrace.h
+noinst_LTLIBRARIES = libdix.la libmain.la
+
+AM_CFLAGS = $(DIX_CFLAGS)
+
+libmain_la_SOURCES = \
+ main.c
+
+libdix_la_SOURCES = \
+ atom.c \
+ colormap.c \
+ cursor.c \
+ deprecated.c \
+ devices.c \
+ dispatch.c \
+ dispatch.h \
+ dixfonts.c \
+ dixutils.c \
+ enterleave.c \
+ enterleave.h \
+ events.c \
+ eventconvert.c \
+ extension.c \
+ ffs.c \
+ gc.c \
+ getevents.c \
+ globals.c \
+ glyphcurs.c \
+ grabs.c \
+ initatoms.c \
+ inpututils.c \
+ pixmap.c \
+ privates.c \
+ property.c \
+ ptrveloc.c \
+ region.c \
+ registry.c \
+ resource.c \
+ selection.c \
+ swaprep.c \
+ swapreq.c \
+ tables.c \
+ window.c
+
+EXTRA_DIST = buildatoms BuiltInAtoms Xserver.d Xserver-dtrace.h.in
+
+# Install list of protocol names
+miscconfigdir = $(SERVER_MISC_CONFIG_PATH)
+dist_miscconfig_DATA = protocol.txt
+
+if XSERVER_DTRACE
+# Generate dtrace header file for C sources to include
+BUILT_SOURCES = Xserver-dtrace.h
+
+Xserver-dtrace.h: $(srcdir)/Xserver.d
+ $(AM_V_GEN)$(DTRACE) -C -h -o $@ -s $(srcdir)/Xserver.d \
+ || cp Xserver-dtrace.h.in $@
+
+endif
+
+if SPECIAL_DTRACE_OBJECTS
+# Generate dtrace object code for probes in libdix
+dtrace-dix.o: $(top_srcdir)/dix/Xserver.d $(am_libdix_la_OBJECTS)
+ $(AM_V_GEN)$(DTRACE) -G -C -o $@ -s $(top_srcdir)/dix/Xserver.d $(am_libdix_la_OBJECTS:%.lo=.libs/%.o)
+
+noinst_PROGRAMS = dix.O
+
+dix.O: dtrace-dix.o $(am_libdix_la_OBJECTS)
+ $(AM_V_GEN)ld -r -o $@ $(am_libdix_la_OBJECTS:%.lo=.libs/%.o)
+endif
+
+dix.c:
+ touch $@
+
+CLEANFILES = dix.c Xserver-dtrace.h
diff --git a/xorg-server/dix/colormap.c b/xorg-server/dix/colormap.c
index 12197acde..b04739ad0 100644
--- a/xorg-server/dix/colormap.c
+++ b/xorg-server/dix/colormap.c
@@ -1,2758 +1,2769 @@
-/***********************************************************
-
-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.
-
-******************************************************************/
-
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include "misc.h"
-#include "dix.h"
-#include "dixstruct.h"
-#include "colormapst.h"
-#include "os.h"
-#include "scrnintstr.h"
-#include "resource.h"
-#include "windowstr.h"
-#include "privates.h"
-#include "xace.h"
-
-static Pixel FindBestPixel(
- EntryPtr /*pentFirst*/,
- int /*size*/,
- xrgb * /*prgb*/,
- int /*channel*/
-);
-
-static int AllComp(
- EntryPtr /*pent*/,
- xrgb * /*prgb*/
-);
-
-static int RedComp(
- EntryPtr /*pent*/,
- xrgb * /*prgb*/
-);
-
-static int GreenComp(
- EntryPtr /*pent*/,
- xrgb * /*prgb*/
-);
-
-static int BlueComp(
- EntryPtr /*pent*/,
- xrgb * /*prgb*/
-);
-
-static void FreePixels(
- ColormapPtr /*pmap*/,
- int /*client*/
-);
-
-static void CopyFree(
- int /*channel*/,
- int /*client*/,
- ColormapPtr /*pmapSrc*/,
- ColormapPtr /*pmapDst*/
-);
-
-static void FreeCell(
- ColormapPtr /*pmap*/,
- Pixel /*i*/,
- int /*channel*/
-);
-
-static void UpdateColors(
- ColormapPtr /*pmap*/
-);
-
-static int AllocDirect(
- int /*client*/,
- ColormapPtr /*pmap*/,
- int /*c*/,
- int /*r*/,
- int /*g*/,
- int /*b*/,
- Bool /*contig*/,
- Pixel * /*pixels*/,
- Pixel * /*prmask*/,
- Pixel * /*pgmask*/,
- Pixel * /*pbmask*/
-);
-
-static int AllocPseudo(
- int /*client*/,
- ColormapPtr /*pmap*/,
- int /*c*/,
- int /*r*/,
- Bool /*contig*/,
- Pixel * /*pixels*/,
- Pixel * /*pmask*/,
- Pixel ** /*pppixFirst*/
-);
-
-static Bool AllocCP(
- ColormapPtr /*pmap*/,
- EntryPtr /*pentFirst*/,
- int /*count*/,
- int /*planes*/,
- Bool /*contig*/,
- Pixel * /*pixels*/,
- Pixel * /*pMask*/
-);
-
-static Bool AllocShared(
- ColormapPtr /*pmap*/,
- Pixel * /*ppix*/,
- int /*c*/,
- int /*r*/,
- int /*g*/,
- int /*b*/,
- Pixel /*rmask*/,
- Pixel /*gmask*/,
- Pixel /*bmask*/,
- Pixel * /*ppixFirst*/
-);
-
-static int FreeCo(
- ColormapPtr /*pmap*/,
- int /*client*/,
- int /*color*/,
- int /*npixIn*/,
- Pixel * /*ppixIn*/,
- Pixel /*mask*/
-);
-
-static int TellNoMap(
- WindowPtr /*pwin*/,
- Colormap * /*pmid*/
-);
-
-static void FindColorInRootCmap (
- ColormapPtr /* pmap */,
- EntryPtr /* pentFirst */,
- int /* size */,
- xrgb* /* prgb */,
- Pixel* /* pPixel */,
- int /* channel */,
- ColorCompareProcPtr /* comp */
-);
-
-#define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1)
-#define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1)
-#define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1)
-#if COMPOSITE
-#define ALPHAMASK(vis) ((vis)->nplanes < 32 ? 0 : \
- (CARD32) ~((vis)->redMask|(vis)->greenMask|(vis)->blueMask))
-#else
-#define ALPHAMASK(vis) 0
-#endif
-
-#define RGBMASK(vis) (vis->redMask | vis->greenMask | vis->blueMask | ALPHAMASK(vis))
-
-/* GetNextBitsOrBreak(bits, mask, base) --
- * (Suggestion: First read the macro, then read this explanation.
- *
- * Either generate the next value to OR in to a pixel or break out of this
- * while loop
- *
- * This macro is used when we're trying to generate all 2^n combinations of
- * bits in mask. What we're doing here is counting in binary, except that
- * the bits we use to count may not be contiguous. This macro will be
- * called 2^n times, returning a different value in bits each time. Then
- * it will cause us to break out of a surrounding loop. (It will always be
- * called from within a while loop.)
- * On call: mask is the value we want to find all the combinations for
- * base has 1 bit set where the least significant bit of mask is set
- *
- * For example,if mask is 01010, base should be 0010 and we count like this:
- * 00010 (see this isn't so hard),
- * then we add base to bits and get 0100. (bits & ~mask) is (0100 & 0100) so
- * we add that to bits getting (0100 + 0100) =
- * 01000 for our next value.
- * then we add 0010 to get
- * 01010 and we're done (easy as 1, 2, 3)
- */
-#define GetNextBitsOrBreak(bits, mask, base) \
- if((bits) == (mask)) \
- break; \
- (bits) += (base); \
- while((bits) & ~(mask)) \
- (bits) += ((bits) & ~(mask));
-/* ID of server as client */
-#define SERVER_ID 0
-
-typedef struct _colorResource
-{
- Colormap mid;
- int client;
-} colorResource;
-
-/* Invariants:
- * refcnt == 0 means entry is empty
- * refcnt > 0 means entry is useable by many clients, so it can't be changed
- * refcnt == AllocPrivate means entry owned by one client only
- * fShared should only be set if refcnt == AllocPrivate, and only in red map
- */
-
-
-/**
- * Create and initialize the color map
- *
- * \param mid resource to use for this colormap
- * \param alloc 1 iff all entries are allocated writable
- */
-int
-CreateColormap (Colormap mid, ScreenPtr pScreen, VisualPtr pVisual,
- ColormapPtr *ppcmap, int alloc, int client)
-{
- int class, size;
- unsigned long sizebytes;
- ColormapPtr pmap;
- EntryPtr pent;
- int i;
- Pixel *ppix, **pptr;
-
- class = pVisual->class;
- if(!(class & DynamicClass) && (alloc != AllocNone) && (client != SERVER_ID))
- return (BadMatch);
-
- size = pVisual->ColormapEntries;
- sizebytes = (size * sizeof(Entry)) +
- (MAXCLIENTS * sizeof(Pixel *)) +
- (MAXCLIENTS * sizeof(int));
- if ((class | DynamicClass) == DirectColor)
- sizebytes *= 3;
- sizebytes += sizeof(ColormapRec);
- pmap = malloc(sizebytes);
- if (!pmap)
- return (BadAlloc);
-#if defined(_XSERVER64)
- pmap->pad0 = 0;
- pmap->pad1 = 0;
-#if (X_BYTE_ORDER == X_LITTLE_ENDIAN)
- pmap->pad2 = 0;
-#endif
-#endif
- pmap->red = (EntryPtr)((char *)pmap + sizeof(ColormapRec));
- sizebytes = size * sizeof(Entry);
- pmap->clientPixelsRed = (Pixel **)((char *)pmap->red + sizebytes);
- pmap->numPixelsRed = (int *)((char *)pmap->clientPixelsRed +
- (MAXCLIENTS * sizeof(Pixel *)));
- pmap->mid = mid;
- pmap->flags = 0; /* start out with all flags clear */
- if(mid == pScreen->defColormap)
- pmap->flags |= IsDefault;
- pmap->pScreen = pScreen;
- pmap->pVisual = pVisual;
- pmap->class = class;
- if ((class | DynamicClass) == DirectColor)
- size = NUMRED(pVisual);
- pmap->freeRed = size;
- bzero ((char *) pmap->red, (int)sizebytes);
- bzero((char *) pmap->numPixelsRed, MAXCLIENTS * sizeof(int));
- for (pptr = &pmap->clientPixelsRed[MAXCLIENTS]; --pptr >= pmap->clientPixelsRed; )
- *pptr = (Pixel *)NULL;
- if (alloc == AllocAll)
- {
- if (class & DynamicClass)
- pmap->flags |= AllAllocated;
- for (pent = &pmap->red[size - 1]; pent >= pmap->red; pent--)
- pent->refcnt = AllocPrivate;
- pmap->freeRed = 0;
- ppix = malloc(size * sizeof(Pixel));
- if (!ppix)
- {
- free(pmap);
- return (BadAlloc);
- }
- pmap->clientPixelsRed[client] = ppix;
- for(i = 0; i < size; i++)
- ppix[i] = i;
- pmap->numPixelsRed[client] = size;
- }
-
- if ((class | DynamicClass) == DirectColor)
- {
- pmap->freeGreen = NUMGREEN(pVisual);
- pmap->green = (EntryPtr)((char *)pmap->numPixelsRed +
- (MAXCLIENTS * sizeof(int)));
- pmap->clientPixelsGreen = (Pixel **)((char *)pmap->green + sizebytes);
- pmap->numPixelsGreen = (int *)((char *)pmap->clientPixelsGreen +
- (MAXCLIENTS * sizeof(Pixel *)));
- pmap->freeBlue = NUMBLUE(pVisual);
- pmap->blue = (EntryPtr)((char *)pmap->numPixelsGreen +
- (MAXCLIENTS * sizeof(int)));
- pmap->clientPixelsBlue = (Pixel **)((char *)pmap->blue + sizebytes);
- pmap->numPixelsBlue = (int *)((char *)pmap->clientPixelsBlue +
- (MAXCLIENTS * sizeof(Pixel *)));
-
- bzero ((char *) pmap->green, (int)sizebytes);
- bzero ((char *) pmap->blue, (int)sizebytes);
-
- memmove((char *) pmap->clientPixelsGreen,
- (char *) pmap->clientPixelsRed,
- MAXCLIENTS * sizeof(Pixel *));
- memmove((char *) pmap->clientPixelsBlue,
- (char *) pmap->clientPixelsRed,
- MAXCLIENTS * sizeof(Pixel *));
- bzero((char *) pmap->numPixelsGreen, MAXCLIENTS * sizeof(int));
- bzero((char *) pmap->numPixelsBlue, MAXCLIENTS * sizeof(int));
-
- /* If every cell is allocated, mark its refcnt */
- if (alloc == AllocAll)
- {
- size = pmap->freeGreen;
- for(pent = &pmap->green[size-1]; pent >= pmap->green; pent--)
- pent->refcnt = AllocPrivate;
- pmap->freeGreen = 0;
- ppix = malloc(size * sizeof(Pixel));
- if (!ppix)
- {
- free(pmap->clientPixelsRed[client]);
- free(pmap);
- return(BadAlloc);
- }
- pmap->clientPixelsGreen[client] = ppix;
- for(i = 0; i < size; i++)
- ppix[i] = i;
- pmap->numPixelsGreen[client] = size;
-
- size = pmap->freeBlue;
- for(pent = &pmap->blue[size-1]; pent >= pmap->blue; pent--)
- pent->refcnt = AllocPrivate;
- pmap->freeBlue = 0;
- ppix = malloc(size * sizeof(Pixel));
- if (!ppix)
- {
- free(pmap->clientPixelsGreen[client]);
- free(pmap->clientPixelsRed[client]);
- free(pmap);
- return(BadAlloc);
- }
- pmap->clientPixelsBlue[client] = ppix;
- for(i = 0; i < size; i++)
- ppix[i] = i;
- pmap->numPixelsBlue[client] = size;
- }
- }
- pmap->devPrivates = NULL;
- pmap->flags |= BeingCreated;
-
- if (!AddResource(mid, RT_COLORMAP, (pointer)pmap))
- return (BadAlloc);
-
- /*
- * Security creation/labeling check
- */
- i = XaceHook(XACE_RESOURCE_ACCESS, clients[client], mid, RT_COLORMAP,
- pmap, RT_NONE, NULL, DixCreateAccess);
- if (i != Success) {
- FreeResource(mid, RT_NONE);
- return i;
- }
-
- /* If the device wants a chance to initialize the colormap in any way,
- * this is it. In specific, if this is a Static colormap, this is the
- * time to fill in the colormap's values */
- if (!(*pScreen->CreateColormap)(pmap))
- {
- FreeResource (mid, RT_NONE);
- return BadAlloc;
- }
- pmap->flags &= ~BeingCreated;
- *ppcmap = pmap;
- return (Success);
-}
-
-/**
- *
- * \param value must conform to DeleteType
- */
-int
-FreeColormap (pointer value, XID mid)
-{
- int i;
- EntryPtr pent;
- ColormapPtr pmap = (ColormapPtr)value;
-
- if(CLIENT_ID(mid) != SERVER_ID)
- {
- (*pmap->pScreen->UninstallColormap) (pmap);
- WalkTree(pmap->pScreen, (VisitWindowProcPtr)TellNoMap, (pointer) &mid);
- }
-
- /* This is the device's chance to undo anything it needs to, especially
- * to free any storage it allocated */
- (*pmap->pScreen->DestroyColormap)(pmap);
-
- if(pmap->clientPixelsRed)
- {
- for(i = 0; i < MAXCLIENTS; i++)
- free(pmap->clientPixelsRed[i]);
- }
-
- if ((pmap->class == PseudoColor) || (pmap->class == GrayScale))
- {
- for(pent = &pmap->red[pmap->pVisual->ColormapEntries - 1];
- pent >= pmap->red;
- pent--)
- {
- if(pent->fShared)
- {
- if (--pent->co.shco.red->refcnt == 0)
- free(pent->co.shco.red);
- if (--pent->co.shco.green->refcnt == 0)
- free(pent->co.shco.green);
- if (--pent->co.shco.blue->refcnt == 0)
- free(pent->co.shco.blue);
- }
- }
- }
- if((pmap->class | DynamicClass) == DirectColor)
- {
- for(i = 0; i < MAXCLIENTS; i++)
- {
- free(pmap->clientPixelsGreen[i]);
- free(pmap->clientPixelsBlue[i]);
- }
- }
-
- dixFreePrivates(pmap->devPrivates);
- free(pmap);
- return(Success);
-}
-
-/* Tell window that pmid has disappeared */
-static int
-TellNoMap (WindowPtr pwin, Colormap *pmid)
-{
- xEvent xE;
-
- if (wColormap(pwin) == *pmid)
- {
- /* This should be call to DeliverEvent */
- xE.u.u.type = ColormapNotify;
- xE.u.colormap.window = pwin->drawable.id;
- xE.u.colormap.colormap = None;
- xE.u.colormap.new = TRUE;
- xE.u.colormap.state = ColormapUninstalled;
-#ifdef PANORAMIX
- if(noPanoramiXExtension || !pwin->drawable.pScreen->myNum)
-#endif
- DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL);
- if (pwin->optional) {
- pwin->optional->colormap = None;
- CheckWindowOptionalNeed (pwin);
- }
- }
-
- return (WT_WALKCHILDREN);
-}
-
-/* Tell window that pmid got uninstalled */
-int
-TellLostMap (WindowPtr pwin, pointer value)
-{
- Colormap *pmid = (Colormap *)value;
- xEvent xE;
-
-#ifdef PANORAMIX
- if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum)
- return WT_STOPWALKING;
-#endif
- if (wColormap(pwin) == *pmid)
- {
- /* This should be call to DeliverEvent */
- xE.u.u.type = ColormapNotify;
- xE.u.colormap.window = pwin->drawable.id;
- xE.u.colormap.colormap = *pmid;
- xE.u.colormap.new = FALSE;
- xE.u.colormap.state = ColormapUninstalled;
- DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL);
- }
-
- return (WT_WALKCHILDREN);
-}
-
-/* Tell window that pmid got installed */
-int
-TellGainedMap (WindowPtr pwin, pointer value)
-{
- Colormap *pmid = (Colormap *)value;
- xEvent xE;
-
-#ifdef PANORAMIX
- if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum)
- return WT_STOPWALKING;
-#endif
- if (wColormap (pwin) == *pmid)
- {
- /* This should be call to DeliverEvent */
- xE.u.u.type = ColormapNotify;
- xE.u.colormap.window = pwin->drawable.id;
- xE.u.colormap.colormap = *pmid;
- xE.u.colormap.new = FALSE;
- xE.u.colormap.state = ColormapInstalled;
- DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL);
- }
-
- return (WT_WALKCHILDREN);
-}
-
-
-int
-CopyColormapAndFree (Colormap mid, ColormapPtr pSrc, int client)
-{
- ColormapPtr pmap = (ColormapPtr) NULL;
- int result, alloc, size;
- Colormap midSrc;
- ScreenPtr pScreen;
- VisualPtr pVisual;
-
- pScreen = pSrc->pScreen;
- pVisual = pSrc->pVisual;
- midSrc = pSrc->mid;
- alloc = ((pSrc->flags & AllAllocated) && CLIENT_ID(midSrc) == client) ?
- AllocAll : AllocNone;
- size = pVisual->ColormapEntries;
-
- /* If the create returns non-0, it failed */
- result = CreateColormap (mid, pScreen, pVisual, &pmap, alloc, client);
- if(result != Success)
- return(result);
- if(alloc == AllocAll)
- {
- memmove((char *)pmap->red, (char *)pSrc->red, size * sizeof(Entry));
- if((pmap->class | DynamicClass) == DirectColor)
- {
- memmove((char *)pmap->green, (char *)pSrc->green, size * sizeof(Entry));
- memmove((char *)pmap->blue, (char *)pSrc->blue, size * sizeof(Entry));
- }
- pSrc->flags &= ~AllAllocated;
- FreePixels(pSrc, client);
- UpdateColors(pmap);
- return(Success);
- }
-
- CopyFree(REDMAP, client, pSrc, pmap);
- if ((pmap->class | DynamicClass) == DirectColor)
- {
- CopyFree(GREENMAP, client, pSrc, pmap);
- CopyFree(BLUEMAP, client, pSrc, pmap);
- }
- if (pmap->class & DynamicClass)
- UpdateColors(pmap);
- /* XXX should worry about removing any RT_CMAPENTRY resource */
- return(Success);
-}
-
-/* Helper routine for freeing large numbers of cells from a map */
-static void
-CopyFree (int channel, int client, ColormapPtr pmapSrc, ColormapPtr pmapDst)
-{
- int z, npix;
- EntryPtr pentSrcFirst, pentDstFirst;
- EntryPtr pentSrc, pentDst;
- Pixel *ppix;
- int nalloc;
-
- switch(channel)
- {
- default: /* so compiler can see that everything gets initialized */
- case REDMAP:
- ppix = (pmapSrc->clientPixelsRed)[client];
- npix = (pmapSrc->numPixelsRed)[client];
- pentSrcFirst = pmapSrc->red;
- pentDstFirst = pmapDst->red;
- break;
- case GREENMAP:
- ppix = (pmapSrc->clientPixelsGreen)[client];
- npix = (pmapSrc->numPixelsGreen)[client];
- pentSrcFirst = pmapSrc->green;
- pentDstFirst = pmapDst->green;
- break;
- case BLUEMAP:
- ppix = (pmapSrc->clientPixelsBlue)[client];
- npix = (pmapSrc->numPixelsBlue)[client];
- pentSrcFirst = pmapSrc->blue;
- pentDstFirst = pmapDst->blue;
- break;
- }
- nalloc = 0;
- if (pmapSrc->class & DynamicClass)
- {
- for(z = npix; --z >= 0; ppix++)
- {
- /* Copy entries */
- pentSrc = pentSrcFirst + *ppix;
- pentDst = pentDstFirst + *ppix;
- if (pentDst->refcnt > 0)
- {
- pentDst->refcnt++;
- }
- else
- {
- *pentDst = *pentSrc;
- nalloc++;
- if (pentSrc->refcnt > 0)
- pentDst->refcnt = 1;
- else
- pentSrc->fShared = FALSE;
- }
- FreeCell(pmapSrc, *ppix, channel);
- }
- }
-
- /* Note that FreeCell has already fixed pmapSrc->free{Color} */
- switch(channel)
- {
- case REDMAP:
- pmapDst->freeRed -= nalloc;
- (pmapDst->clientPixelsRed)[client] =
- (pmapSrc->clientPixelsRed)[client];
- (pmapSrc->clientPixelsRed)[client] = (Pixel *) NULL;
- (pmapDst->numPixelsRed)[client] = (pmapSrc->numPixelsRed)[client];
- (pmapSrc->numPixelsRed)[client] = 0;
- break;
- case GREENMAP:
- pmapDst->freeGreen -= nalloc;
- (pmapDst->clientPixelsGreen)[client] =
- (pmapSrc->clientPixelsGreen)[client];
- (pmapSrc->clientPixelsGreen)[client] = (Pixel *) NULL;
- (pmapDst->numPixelsGreen)[client] = (pmapSrc->numPixelsGreen)[client];
- (pmapSrc->numPixelsGreen)[client] = 0;
- break;
- case BLUEMAP:
- pmapDst->freeBlue -= nalloc;
- pmapDst->clientPixelsBlue[client] = pmapSrc->clientPixelsBlue[client];
- pmapSrc->clientPixelsBlue[client] = (Pixel *) NULL;
- pmapDst->numPixelsBlue[client] = pmapSrc->numPixelsBlue[client];
- pmapSrc->numPixelsBlue[client] = 0;
- break;
- }
-}
-
-/* Free the ith entry in a color map. Must handle freeing of
- * colors allocated through AllocColorPlanes */
-static void
-FreeCell (ColormapPtr pmap, Pixel i, int channel)
-{
- EntryPtr pent;
- int *pCount;
-
-
- switch (channel)
- {
- default: /* so compiler can see that everything gets initialized */
- case PSEUDOMAP:
- case REDMAP:
- pent = (EntryPtr) &pmap->red[i];
- pCount = &pmap->freeRed;
- break;
- case GREENMAP:
- pent = (EntryPtr) &pmap->green[i];
- pCount = &pmap->freeGreen;
- break;
- case BLUEMAP:
- pent = (EntryPtr) &pmap->blue[i];
- pCount = &pmap->freeBlue;
- break;
- }
- /* If it's not privately allocated and it's not time to free it, just
- * decrement the count */
- if (pent->refcnt > 1)
- pent->refcnt--;
- else
- {
- /* If the color type is shared, find the sharedcolor. If decremented
- * refcnt is 0, free the shared cell. */
- if (pent->fShared)
- {
- if(--pent->co.shco.red->refcnt == 0)
- free(pent->co.shco.red);
- if(--pent->co.shco.green->refcnt == 0)
- free(pent->co.shco.green);
- if(--pent->co.shco.blue->refcnt == 0)
- free(pent->co.shco.blue);
- pent->fShared = FALSE;
- }
- pent->refcnt = 0;
- *pCount += 1;
- }
-}
-
-static void
-UpdateColors (ColormapPtr pmap)
-{
- xColorItem *defs;
- xColorItem *pdef;
- EntryPtr pent;
- VisualPtr pVisual;
- int i, n, size;
-
- pVisual = pmap->pVisual;
- size = pVisual->ColormapEntries;
- defs = malloc(size * sizeof(xColorItem));
- if (!defs)
- return;
- n = 0;
- pdef = defs;
- if (pmap->class == DirectColor)
- {
- for (i = 0; i < size; i++)
- {
- if (!pmap->red[i].refcnt &&
- !pmap->green[i].refcnt &&
- !pmap->blue[i].refcnt)
- continue;
- pdef->pixel = ((Pixel)i << pVisual->offsetRed) |
- ((Pixel)i << pVisual->offsetGreen) |
- ((Pixel)i << pVisual->offsetBlue);
- pdef->red = pmap->red[i].co.local.red;
- pdef->green = pmap->green[i].co.local.green;
- pdef->blue = pmap->blue[i].co.local.blue;
- pdef->flags = DoRed|DoGreen|DoBlue;
- pdef++;
- n++;
- }
- }
- else
- {
- for (i = 0, pent = pmap->red; i < size; i++, pent++)
- {
- if (!pent->refcnt)
- continue;
- pdef->pixel = i;
- if(pent->fShared)
- {
- pdef->red = pent->co.shco.red->color;
- pdef->green = pent->co.shco.green->color;
- pdef->blue = pent->co.shco.blue->color;
- }
- else
- {
- pdef->red = pent->co.local.red;
- pdef->green = pent->co.local.green;
- pdef->blue = pent->co.local.blue;
- }
- pdef->flags = DoRed|DoGreen|DoBlue;
- pdef++;
- n++;
- }
- }
- if (n)
- (*pmap->pScreen->StoreColors)(pmap, n, defs);
- free(defs);
-}
-
-/* Get a read-only color from a ColorMap (probably slow for large maps)
- * Returns by changing the value in pred, pgreen, pblue and pPix
- */
-int
-AllocColor (ColormapPtr pmap,
- unsigned short *pred, unsigned short *pgreen, unsigned short *pblue,
- Pixel *pPix, int client)
-{
- Pixel pixR, pixG, pixB;
- int entries;
- xrgb rgb;
- int class;
- VisualPtr pVisual;
- int npix;
- Pixel *ppix;
-
- pVisual = pmap->pVisual;
- (*pmap->pScreen->ResolveColor) (pred, pgreen, pblue, pVisual);
- rgb.red = *pred;
- rgb.green = *pgreen;
- rgb.blue = *pblue;
- class = pmap->class;
- entries = pVisual->ColormapEntries;
-
- /* If the colormap is being created, then we want to be able to change
- * the colormap, even if it's a static type. Otherwise, we'd never be
- * able to initialize static colormaps
- */
- if(pmap->flags & BeingCreated)
- class |= DynamicClass;
-
- /* If this is one of the static storage classes, and we're not initializing
- * it, the best we can do is to find the closest color entry to the
- * requested one and return that.
- */
- switch (class) {
- case StaticColor:
- case StaticGray:
- /* Look up all three components in the same pmap */
- *pPix = pixR = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP);
- *pred = pmap->red[pixR].co.local.red;
- *pgreen = pmap->red[pixR].co.local.green;
- *pblue = pmap->red[pixR].co.local.blue;
- npix = pmap->numPixelsRed[client];
- ppix = (Pixel *) realloc(pmap->clientPixelsRed[client],
- (npix + 1) * sizeof(Pixel));
- if (!ppix)
- return (BadAlloc);
- ppix[npix] = pixR;
- pmap->clientPixelsRed[client] = ppix;
- pmap->numPixelsRed[client]++;
- break;
-
- case TrueColor:
- /* Look up each component in its own map, then OR them together */
- pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP);
- pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP);
- pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP);
- *pPix = (pixR << pVisual->offsetRed) |
- (pixG << pVisual->offsetGreen) |
- (pixB << pVisual->offsetBlue) |
- ALPHAMASK(pVisual);
-
- *pred = pmap->red[pixR].co.local.red;
- *pgreen = pmap->green[pixG].co.local.green;
- *pblue = pmap->blue[pixB].co.local.blue;
- npix = pmap->numPixelsRed[client];
- ppix = (Pixel *) realloc(pmap->clientPixelsRed[client],
- (npix + 1) * sizeof(Pixel));
- if (!ppix)
- return (BadAlloc);
- ppix[npix] = pixR;
- pmap->clientPixelsRed[client] = ppix;
- npix = pmap->numPixelsGreen[client];
- ppix = (Pixel *) realloc(pmap->clientPixelsGreen[client],
- (npix + 1) * sizeof(Pixel));
- if (!ppix)
- return (BadAlloc);
- ppix[npix] = pixG;
- pmap->clientPixelsGreen[client] = ppix;
- npix = pmap->numPixelsBlue[client];
- ppix = (Pixel *) realloc(pmap->clientPixelsBlue[client],
- (npix + 1) * sizeof(Pixel));
- if (!ppix)
- return (BadAlloc);
- ppix[npix] = pixB;
- pmap->clientPixelsBlue[client] = ppix;
- pmap->numPixelsRed[client]++;
- pmap->numPixelsGreen[client]++;
- pmap->numPixelsBlue[client]++;
- break;
-
- case GrayScale:
- case PseudoColor:
- if (pmap->mid != pmap->pScreen->defColormap &&
- pmap->pVisual->vid == pmap->pScreen->rootVisual)
- {
- ColormapPtr prootmap;
- dixLookupResourceByType((pointer *)&prootmap, pmap->pScreen->defColormap,
- RT_COLORMAP, clients[client], DixReadAccess);
-
- if (pmap->class == prootmap->class)
- FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb,
- pPix, PSEUDOMAP, AllComp);
- }
- if (FindColor(pmap, pmap->red, entries, &rgb, pPix, PSEUDOMAP,
- client, AllComp) != Success)
- return (BadAlloc);
- break;
-
- case DirectColor:
- if (pmap->mid != pmap->pScreen->defColormap &&
- pmap->pVisual->vid == pmap->pScreen->rootVisual)
- {
- ColormapPtr prootmap;
- dixLookupResourceByType((pointer *)&prootmap, pmap->pScreen->defColormap,
- RT_COLORMAP, clients[client], DixReadAccess);
-
- if (pmap->class == prootmap->class)
- {
- pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed;
- FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb,
- &pixR, REDMAP, RedComp);
- pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen;
- FindColorInRootCmap (prootmap, prootmap->green, entries, &rgb,
- &pixG, GREENMAP, GreenComp);
- pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue;
- FindColorInRootCmap (prootmap, prootmap->blue, entries, &rgb,
- &pixB, BLUEMAP, BlueComp);
- *pPix = pixR | pixG | pixB;
- }
- }
-
- pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed;
- if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP,
- client, RedComp) != Success)
- return (BadAlloc);
- pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen;
- if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG,
- GREENMAP, client, GreenComp) != Success)
- {
- (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0);
- return (BadAlloc);
- }
- pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue;
- if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP,
- client, BlueComp) != Success)
- {
- (void)FreeCo(pmap, client, GREENMAP, 1, &pixG, (Pixel)0);
- (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0);
- return (BadAlloc);
- }
- *pPix = pixR | pixG | pixB | ALPHAMASK(pVisual);
-
- break;
- }
-
- /* if this is the client's first pixel in this colormap, tell the
- * resource manager that the client has pixels in this colormap which
- * should be freed when the client dies */
- if ((pmap->numPixelsRed[client] == 1) &&
- (CLIENT_ID(pmap->mid) != client) &&
- !(pmap->flags & BeingCreated))
- {
- colorResource *pcr;
-
- pcr = malloc(sizeof(colorResource));
- if (!pcr)
- {
- (void)FreeColors(pmap, client, 1, pPix, (Pixel)0);
- return (BadAlloc);
- }
- pcr->mid = pmap->mid;
- pcr->client = client;
- if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr))
- return (BadAlloc);
- }
- return (Success);
-}
-
-/*
- * FakeAllocColor -- fake an AllocColor request by
- * returning a free pixel if availible, otherwise returning
- * the closest matching pixel. This is used by the mi
- * software sprite code to recolor cursors. A nice side-effect
- * is that this routine will never return failure.
- */
-
-void
-FakeAllocColor (ColormapPtr pmap, xColorItem *item)
-{
- Pixel pixR, pixG, pixB;
- Pixel temp;
- int entries;
- xrgb rgb;
- int class;
- VisualPtr pVisual;
-
- pVisual = pmap->pVisual;
- rgb.red = item->red;
- rgb.green = item->green;
- rgb.blue = item->blue;
- (*pmap->pScreen->ResolveColor) (&rgb.red, &rgb.green, &rgb.blue, pVisual);
- class = pmap->class;
- entries = pVisual->ColormapEntries;
-
- switch (class) {
- case GrayScale:
- case PseudoColor:
- temp = 0;
- item->pixel = 0;
- if (FindColor(pmap, pmap->red, entries, &rgb, &temp, PSEUDOMAP,
- -1, AllComp) == Success) {
- item->pixel = temp;
- break;
- }
- /* fall through ... */
- case StaticColor:
- case StaticGray:
- item->pixel = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP);
- break;
-
- case DirectColor:
- /* Look up each component in its own map, then OR them together */
- pixR = (item->pixel & pVisual->redMask) >> pVisual->offsetRed;
- pixG = (item->pixel & pVisual->greenMask) >> pVisual->offsetGreen;
- pixB = (item->pixel & pVisual->blueMask) >> pVisual->offsetBlue;
- if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP,
- -1, RedComp) != Success)
- pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP)
- << pVisual->offsetRed;
- if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG,
- GREENMAP, -1, GreenComp) != Success)
- pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb,
- GREENMAP) << pVisual->offsetGreen;
- if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP,
- -1, BlueComp) != Success)
- pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP)
- << pVisual->offsetBlue;
- item->pixel = pixR | pixG | pixB;
- break;
-
- case TrueColor:
- /* Look up each component in its own map, then OR them together */
- pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP);
- pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP);
- pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP);
- item->pixel = (pixR << pVisual->offsetRed) |
- (pixG << pVisual->offsetGreen) |
- (pixB << pVisual->offsetBlue);
- break;
- }
-}
-
-/* free a pixel value obtained from FakeAllocColor */
-void
-FakeFreeColor(ColormapPtr pmap, Pixel pixel)
-{
- VisualPtr pVisual;
- Pixel pixR, pixG, pixB;
-
- switch (pmap->class) {
- case GrayScale:
- case PseudoColor:
- if (pmap->red[pixel].refcnt == AllocTemporary)
- pmap->red[pixel].refcnt = 0;
- break;
- case DirectColor:
- pVisual = pmap->pVisual;
- pixR = (pixel & pVisual->redMask) >> pVisual->offsetRed;
- pixG = (pixel & pVisual->greenMask) >> pVisual->offsetGreen;
- pixB = (pixel & pVisual->blueMask) >> pVisual->offsetBlue;
- if (pmap->red[pixR].refcnt == AllocTemporary)
- pmap->red[pixR].refcnt = 0;
- if (pmap->green[pixG].refcnt == AllocTemporary)
- pmap->green[pixG].refcnt = 0;
- if (pmap->blue[pixB].refcnt == AllocTemporary)
- pmap->blue[pixB].refcnt = 0;
- break;
- }
-}
-
-typedef unsigned short BigNumUpper;
-typedef unsigned long BigNumLower;
-
-#define BIGNUMLOWERBITS 24
-#define BIGNUMUPPERBITS 16
-#define BIGNUMLOWER (1 << BIGNUMLOWERBITS)
-#define BIGNUMUPPER (1 << BIGNUMUPPERBITS)
-#define UPPERPART(i) ((i) >> BIGNUMLOWERBITS)
-#define LOWERPART(i) ((i) & (BIGNUMLOWER - 1))
-
-typedef struct _bignum {
- BigNumUpper upper;
- BigNumLower lower;
-} BigNumRec, *BigNumPtr;
-
-#define BigNumGreater(x,y) (((x)->upper > (y)->upper) ||\
- ((x)->upper == (y)->upper && (x)->lower > (y)->lower))
-
-#define UnsignedToBigNum(u,r) (((r)->upper = UPPERPART(u)), \
- ((r)->lower = LOWERPART(u)))
-
-#define MaxBigNum(r) (((r)->upper = BIGNUMUPPER-1), \
- ((r)->lower = BIGNUMLOWER-1))
-
-static void
-BigNumAdd (BigNumPtr x, BigNumPtr y, BigNumPtr r)
-{
- BigNumLower lower, carry = 0;
-
- lower = x->lower + y->lower;
- if (lower >= BIGNUMLOWER) {
- lower -= BIGNUMLOWER;
- carry = 1;
- }
- r->lower = lower;
- r->upper = x->upper + y->upper + carry;
-}
-
-static Pixel
-FindBestPixel(EntryPtr pentFirst, int size, xrgb *prgb, int channel)
-{
- EntryPtr pent;
- Pixel pixel, final;
- long dr, dg, db;
- unsigned long sq;
- BigNumRec minval, sum, temp;
-
- final = 0;
- MaxBigNum(&minval);
- /* look for the minimal difference */
- for (pent = pentFirst, pixel = 0; pixel < size; pent++, pixel++)
- {
- dr = dg = db = 0;
- switch(channel)
- {
- case PSEUDOMAP:
- dg = (long) pent->co.local.green - prgb->green;
- db = (long) pent->co.local.blue - prgb->blue;
- case REDMAP:
- dr = (long) pent->co.local.red - prgb->red;
- break;
- case GREENMAP:
- dg = (long) pent->co.local.green - prgb->green;
- break;
- case BLUEMAP:
- db = (long) pent->co.local.blue - prgb->blue;
- break;
- }
- sq = dr * dr;
- UnsignedToBigNum (sq, &sum);
- sq = dg * dg;
- UnsignedToBigNum (sq, &temp);
- BigNumAdd (&sum, &temp, &sum);
- sq = db * db;
- UnsignedToBigNum (sq, &temp);
- BigNumAdd (&sum, &temp, &sum);
- if (BigNumGreater (&minval, &sum))
- {
- final = pixel;
- minval = sum;
- }
- }
- return(final);
-}
-
-static void
-FindColorInRootCmap (ColormapPtr pmap, EntryPtr pentFirst, int size,
- xrgb *prgb, Pixel *pPixel, int channel,
- ColorCompareProcPtr comp)
-{
- EntryPtr pent;
- Pixel pixel;
- int count;
-
- if ((pixel = *pPixel) >= size)
- pixel = 0;
- for (pent = pentFirst + pixel, count = size; --count >= 0; pent++, pixel++)
- {
- if (pent->refcnt > 0 && (*comp) (pent, prgb))
- {
- switch (channel)
- {
- case REDMAP:
- pixel <<= pmap->pVisual->offsetRed;
- break;
- case GREENMAP:
- pixel <<= pmap->pVisual->offsetGreen;
- break;
- case BLUEMAP:
- pixel <<= pmap->pVisual->offsetBlue;
- break;
- default: /* PSEUDOMAP */
- break;
- }
- *pPixel = pixel;
- }
- }
-}
-
-/* Tries to find a color in pmap that exactly matches the one requested in prgb
- * if it can't it allocates one.
- * Starts looking at pentFirst + *pPixel, so if you want a specific pixel,
- * load *pPixel with that value, otherwise set it to 0
- */
-int
-FindColor (ColormapPtr pmap, EntryPtr pentFirst, int size, xrgb *prgb,
- Pixel *pPixel, int channel, int client,
- ColorCompareProcPtr comp)
-{
- EntryPtr pent;
- Bool foundFree;
- Pixel pixel, Free = 0;
- int npix, count, *nump = NULL;
- Pixel **pixp = NULL, *ppix;
- xColorItem def;
-
- foundFree = FALSE;
-
- if((pixel = *pPixel) >= size)
- pixel = 0;
- /* see if there is a match, and also look for a free entry */
- for (pent = pentFirst + pixel, count = size; --count >= 0; )
- {
- if (pent->refcnt > 0)
- {
- if ((*comp) (pent, prgb))
- {
- if (client >= 0)
- pent->refcnt++;
- *pPixel = pixel;
- switch(channel)
- {
- case REDMAP:
- *pPixel <<= pmap->pVisual->offsetRed;
- case PSEUDOMAP:
- break;
- case GREENMAP:
- *pPixel <<= pmap->pVisual->offsetGreen;
- break;
- case BLUEMAP:
- *pPixel <<= pmap->pVisual->offsetBlue;
- break;
- }
- goto gotit;
- }
- }
- else if (!foundFree && pent->refcnt == 0)
- {
- Free = pixel;
- foundFree = TRUE;
- /* If we're initializing the colormap, then we are looking for
- * the first free cell we can find, not to minimize the number
- * of entries we use. So don't look any further. */
- if(pmap->flags & BeingCreated)
- break;
- }
- pixel++;
- if(pixel >= size)
- {
- pent = pentFirst;
- pixel = 0;
- }
- else
- pent++;
- }
-
- /* If we got here, we didn't find a match. If we also didn't find
- * a free entry, we're out of luck. Otherwise, we'll usurp a free
- * entry and fill it in */
- if (!foundFree)
- return (BadAlloc);
- pent = pentFirst + Free;
- pent->fShared = FALSE;
- pent->refcnt = (client >= 0) ? 1 : AllocTemporary;
-
- switch (channel)
- {
- case PSEUDOMAP:
- pent->co.local.red = prgb->red;
- pent->co.local.green = prgb->green;
- pent->co.local.blue = prgb->blue;
- def.red = prgb->red;
- def.green = prgb->green;
- def.blue = prgb->blue;
- def.flags = (DoRed|DoGreen|DoBlue);
- if (client >= 0)
- pmap->freeRed--;
- def.pixel = Free;
- break;
-
- case REDMAP:
- pent->co.local.red = prgb->red;
- def.red = prgb->red;
- def.green = pmap->green[0].co.local.green;
- def.blue = pmap->blue[0].co.local.blue;
- def.flags = DoRed;
- if (client >= 0)
- pmap->freeRed--;
- def.pixel = Free << pmap->pVisual->offsetRed;
- break;
-
- case GREENMAP:
- pent->co.local.green = prgb->green;
- def.red = pmap->red[0].co.local.red;
- def.green = prgb->green;
- def.blue = pmap->blue[0].co.local.blue;
- def.flags = DoGreen;
- if (client >= 0)
- pmap->freeGreen--;
- def.pixel = Free << pmap->pVisual->offsetGreen;
- break;
-
- case BLUEMAP:
- pent->co.local.blue = prgb->blue;
- def.red = pmap->red[0].co.local.red;
- def.green = pmap->green[0].co.local.green;
- def.blue = prgb->blue;
- def.flags = DoBlue;
- if (client >= 0)
- pmap->freeBlue--;
- def.pixel = Free << pmap->pVisual->offsetBlue;
- break;
- }
- (*pmap->pScreen->StoreColors) (pmap, 1, &def);
- pixel = Free;
- *pPixel = def.pixel;
-
-gotit:
- if (pmap->flags & BeingCreated || client == -1)
- return(Success);
- /* Now remember the pixel, for freeing later */
- switch (channel)
- {
- case PSEUDOMAP:
- case REDMAP:
- nump = pmap->numPixelsRed;
- pixp = pmap->clientPixelsRed;
- break;
-
- case GREENMAP:
- nump = pmap->numPixelsGreen;
- pixp = pmap->clientPixelsGreen;
- break;
-
- case BLUEMAP:
- nump = pmap->numPixelsBlue;
- pixp = pmap->clientPixelsBlue;
- break;
- }
- npix = nump[client];
- ppix = (Pixel *) realloc(pixp[client], (npix + 1) * sizeof(Pixel));
- if (!ppix)
- {
- pent->refcnt--;
- if (!pent->fShared)
- switch (channel)
- {
- case PSEUDOMAP:
- case REDMAP:
- pmap->freeRed++;
- break;
- case GREENMAP:
- pmap->freeGreen++;
- break;
- case BLUEMAP:
- pmap->freeBlue++;
- break;
- }
- return(BadAlloc);
- }
- ppix[npix] = pixel;
- pixp[client] = ppix;
- nump[client]++;
-
- return(Success);
-}
-
-/* Comparison functions -- passed to FindColor to determine if an
- * entry is already the color we're looking for or not */
-static int
-AllComp (EntryPtr pent, xrgb *prgb)
-{
- if((pent->co.local.red == prgb->red) &&
- (pent->co.local.green == prgb->green) &&
- (pent->co.local.blue == prgb->blue) )
- return (1);
- return (0);
-}
-
-static int
-RedComp (EntryPtr pent, xrgb *prgb)
-{
- if (pent->co.local.red == prgb->red)
- return (1);
- return (0);
-}
-
-static int
-GreenComp (EntryPtr pent, xrgb *prgb)
-{
- if (pent->co.local.green == prgb->green)
- return (1);
- return (0);
-}
-
-static int
-BlueComp (EntryPtr pent, xrgb *prgb)
-{
- if (pent->co.local.blue == prgb->blue)
- return (1);
- return (0);
-}
-
-
-/* Read the color value of a cell */
-
-int
-QueryColors (ColormapPtr pmap, int count, Pixel *ppixIn, xrgb *prgbList, ClientPtr client)
-{
- Pixel *ppix, pixel;
- xrgb *prgb;
- VisualPtr pVisual;
- EntryPtr pent;
- Pixel i;
- int errVal = Success;
-
- pVisual = pmap->pVisual;
- if ((pmap->class | DynamicClass) == DirectColor)
- {
- int numred, numgreen, numblue;
- Pixel rgbbad;
-
- numred = NUMRED(pVisual);
- numgreen = NUMGREEN(pVisual);
- numblue = NUMBLUE(pVisual);
- rgbbad = ~RGBMASK(pVisual);
- for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++)
- {
- pixel = *ppix;
- if (pixel & rgbbad) {
- client->errorValue = pixel;
- errVal = BadValue;
- continue;
- }
- i = (pixel & pVisual->redMask) >> pVisual->offsetRed;
- if (i >= numred)
- {
- client->errorValue = pixel;
- errVal = BadValue;
- continue;
- }
- prgb->red = pmap->red[i].co.local.red;
- i = (pixel & pVisual->greenMask) >> pVisual->offsetGreen;
- if (i >= numgreen)
- {
- client->errorValue = pixel;
- errVal = BadValue;
- continue;
- }
- prgb->green = pmap->green[i].co.local.green;
- i = (pixel & pVisual->blueMask) >> pVisual->offsetBlue;
- if (i >= numblue)
- {
- client->errorValue = pixel;
- errVal = BadValue;
- continue;
- }
- prgb->blue = pmap->blue[i].co.local.blue;
- }
- }
- else
- {
- for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++)
- {
- pixel = *ppix;
- if (pixel >= pVisual->ColormapEntries)
- {
- client->errorValue = pixel;
- errVal = BadValue;
- }
- else
- {
- pent = (EntryPtr)&pmap->red[pixel];
- if (pent->fShared)
- {
- prgb->red = pent->co.shco.red->color;
- prgb->green = pent->co.shco.green->color;
- prgb->blue = pent->co.shco.blue->color;
- }
- else
- {
- prgb->red = pent->co.local.red;
- prgb->green = pent->co.local.green;
- prgb->blue = pent->co.local.blue;
- }
- }
- }
- }
- return (errVal);
-}
-
-static void
-FreePixels(ColormapPtr pmap, int client)
-{
- Pixel *ppix, *ppixStart;
- int n;
- int class;
-
- class = pmap->class;
- ppixStart = pmap->clientPixelsRed[client];
- if (class & DynamicClass)
- {
- n = pmap->numPixelsRed[client];
- for (ppix = ppixStart; --n >= 0; )
- {
- FreeCell(pmap, *ppix, REDMAP);
- ppix++;
- }
- }
-
- free(ppixStart);
- pmap->clientPixelsRed[client] = (Pixel *) NULL;
- pmap->numPixelsRed[client] = 0;
- if ((class | DynamicClass) == DirectColor)
- {
- ppixStart = pmap->clientPixelsGreen[client];
- if (class & DynamicClass)
- for (ppix = ppixStart, n = pmap->numPixelsGreen[client]; --n >= 0;)
- FreeCell(pmap, *ppix++, GREENMAP);
- free(ppixStart);
- pmap->clientPixelsGreen[client] = (Pixel *) NULL;
- pmap->numPixelsGreen[client] = 0;
-
- ppixStart = pmap->clientPixelsBlue[client];
- if (class & DynamicClass)
- for (ppix = ppixStart, n = pmap->numPixelsBlue[client]; --n >= 0; )
- FreeCell(pmap, *ppix++, BLUEMAP);
- free(ppixStart);
- pmap->clientPixelsBlue[client] = (Pixel *) NULL;
- pmap->numPixelsBlue[client] = 0;
- }
-}
-
-/**
- * Frees all of a client's colors and cells.
- *
- * \param value must conform to DeleteType
- * \unused fakeid
- */
-int
-FreeClientPixels (pointer value, XID fakeid)
-{
- pointer pmap;
- colorResource *pcr = value;
- int rc;
-
- rc = dixLookupResourceByType(&pmap, pcr->mid, RT_COLORMAP, serverClient,
- DixRemoveAccess);
- if (rc == Success)
- FreePixels((ColormapPtr)pmap, pcr->client);
- free(pcr);
- return Success;
-}
-
-int
-AllocColorCells (int client, ColormapPtr pmap, int colors, int planes,
- Bool contig, Pixel *ppix, Pixel *masks)
-{
- Pixel rmask, gmask, bmask, *ppixFirst, r, g, b;
- int n, class;
- int ok;
- int oldcount;
- colorResource *pcr = (colorResource *)NULL;
-
- class = pmap->class;
- if (!(class & DynamicClass))
- return (BadAlloc); /* Shouldn't try on this type */
- oldcount = pmap->numPixelsRed[client];
- if (pmap->class == DirectColor)
- oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client];
- if (!oldcount && (CLIENT_ID(pmap->mid) != client))
- {
- pcr = malloc(sizeof(colorResource));
- if (!pcr)
- return (BadAlloc);
- }
-
- if (pmap->class == DirectColor)
- {
- ok = AllocDirect (client, pmap, colors, planes, planes, planes,
- contig, ppix, &rmask, &gmask, &bmask);
- if(ok == Success)
- {
- for (r = g = b = 1, n = planes; --n >= 0; r += r, g += g, b += b)
- {
- while(!(rmask & r))
- r += r;
- while(!(gmask & g))
- g += g;
- while(!(bmask & b))
- b += b;
- *masks++ = r | g | b;
- }
- }
- }
- else
- {
- ok = AllocPseudo (client, pmap, colors, planes, contig, ppix, &rmask,
- &ppixFirst);
- if(ok == Success)
- {
- for (r = 1, n = planes; --n >= 0; r += r)
- {
- while(!(rmask & r))
- r += r;
- *masks++ = r;
- }
- }
- }
-
- /* if this is the client's first pixels in this colormap, tell the
- * resource manager that the client has pixels in this colormap which
- * should be freed when the client dies */
- if ((ok == Success) && pcr)
- {
- pcr->mid = pmap->mid;
- pcr->client = client;
- if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr))
- ok = BadAlloc;
- } else if (pcr)
- free(pcr);
-
- return (ok);
-}
-
-
-int
-AllocColorPlanes (int client, ColormapPtr pmap, int colors,
- int r, int g, int b, Bool contig, Pixel *pixels,
- Pixel *prmask, Pixel *pgmask, Pixel *pbmask)
-{
- int ok;
- Pixel mask, *ppixFirst;
- Pixel shift;
- int i;
- int class;
- int oldcount;
- colorResource *pcr = (colorResource *)NULL;
-
- class = pmap->class;
- if (!(class & DynamicClass))
- return (BadAlloc); /* Shouldn't try on this type */
- oldcount = pmap->numPixelsRed[client];
- if (class == DirectColor)
- oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client];
- if (!oldcount && (CLIENT_ID(pmap->mid) != client))
- {
- pcr = malloc(sizeof(colorResource));
- if (!pcr)
- return (BadAlloc);
- }
-
- if (class == DirectColor)
- {
- ok = AllocDirect (client, pmap, colors, r, g, b, contig, pixels,
- prmask, pgmask, pbmask);
- }
- else
- {
- /* Allocate the proper pixels */
- /* XXX This is sort of bad, because of contig is set, we force all
- * r + g + b bits to be contiguous. Should only force contiguity
- * per mask
- */
- ok = AllocPseudo (client, pmap, colors, r + g + b, contig, pixels,
- &mask, &ppixFirst);
-
- if(ok == Success)
- {
- /* now split that mask into three */
- *prmask = *pgmask = *pbmask = 0;
- shift = 1;
- for (i = r; --i >= 0; shift += shift)
- {
- while (!(mask & shift))
- shift += shift;
- *prmask |= shift;
- }
- for (i = g; --i >= 0; shift += shift)
- {
- while (!(mask & shift))
- shift += shift;
- *pgmask |= shift;
- }
- for (i = b; --i >= 0; shift += shift)
- {
- while (!(mask & shift))
- shift += shift;
- *pbmask |= shift;
- }
-
- /* set up the shared color cells */
- if (!AllocShared(pmap, pixels, colors, r, g, b,
- *prmask, *pgmask, *pbmask, ppixFirst))
- {
- (void)FreeColors(pmap, client, colors, pixels, mask);
- ok = BadAlloc;
- }
- }
- }
-
- /* if this is the client's first pixels in this colormap, tell the
- * resource manager that the client has pixels in this colormap which
- * should be freed when the client dies */
- if ((ok == Success) && pcr)
- {
- pcr->mid = pmap->mid;
- pcr->client = client;
- if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr))
- ok = BadAlloc;
- } else if (pcr)
- free(pcr);
-
- return (ok);
-}
-
-static int
-AllocDirect (int client, ColormapPtr pmap, int c, int r, int g, int b, Bool contig,
- Pixel *pixels, Pixel *prmask, Pixel *pgmask, Pixel *pbmask)
-{
- Pixel *ppixRed, *ppixGreen, *ppixBlue;
- Pixel *ppix, *pDst, *p;
- int npix, npixR, npixG, npixB;
- Bool okR, okG, okB;
- Pixel *rpix = 0, *gpix = 0, *bpix = 0;
-
- npixR = c << r;
- npixG = c << g;
- npixB = c << b;
- if ((r >= 32) || (g >= 32) || (b >= 32) ||
- (npixR > pmap->freeRed) || (npixR < c) ||
- (npixG > pmap->freeGreen) || (npixG < c) ||
- (npixB > pmap->freeBlue) || (npixB < c))
- return BadAlloc;
-
- /* start out with empty pixels */
- for(p = pixels; p < pixels + c; p++)
- *p = 0;
-
- ppixRed = malloc(npixR * sizeof(Pixel));
- ppixGreen = malloc(npixG * sizeof(Pixel));
- ppixBlue = malloc(npixB * sizeof(Pixel));
- if (!ppixRed || !ppixGreen || !ppixBlue)
- {
- if (ppixBlue) free(ppixBlue);
- if (ppixGreen) free(ppixGreen);
- if (ppixRed) free(ppixRed);
- return(BadAlloc);
- }
-
- okR = AllocCP(pmap, pmap->red, c, r, contig, ppixRed, prmask);
- okG = AllocCP(pmap, pmap->green, c, g, contig, ppixGreen, pgmask);
- okB = AllocCP(pmap, pmap->blue, c, b, contig, ppixBlue, pbmask);
-
- if (okR && okG && okB)
- {
- rpix = (Pixel *) realloc(pmap->clientPixelsRed[client],
- (pmap->numPixelsRed[client] + (c << r)) *
- sizeof(Pixel));
- if (rpix)
- pmap->clientPixelsRed[client] = rpix;
- gpix = (Pixel *) realloc(pmap->clientPixelsGreen[client],
- (pmap->numPixelsGreen[client] + (c << g)) *
- sizeof(Pixel));
- if (gpix)
- pmap->clientPixelsGreen[client] = gpix;
- bpix = (Pixel *) realloc(pmap->clientPixelsBlue[client],
- (pmap->numPixelsBlue[client] + (c << b)) *
- sizeof(Pixel));
- if (bpix)
- pmap->clientPixelsBlue[client] = bpix;
- }
-
- if (!okR || !okG || !okB || !rpix || !gpix || !bpix)
- {
- if (okR)
- for(ppix = ppixRed, npix = npixR; --npix >= 0; ppix++)
- pmap->red[*ppix].refcnt = 0;
- if (okG)
- for(ppix = ppixGreen, npix = npixG; --npix >= 0; ppix++)
- pmap->green[*ppix].refcnt = 0;
- if (okB)
- for(ppix = ppixBlue, npix = npixB; --npix >= 0; ppix++)
- pmap->blue[*ppix].refcnt = 0;
- free(ppixBlue);
- free(ppixGreen);
- free(ppixRed);
- return(BadAlloc);
- }
-
- *prmask <<= pmap->pVisual->offsetRed;
- *pgmask <<= pmap->pVisual->offsetGreen;
- *pbmask <<= pmap->pVisual->offsetBlue;
-
- ppix = rpix + pmap->numPixelsRed[client];
- for (pDst = pixels, p = ppixRed; p < ppixRed + npixR; p++)
- {
- *ppix++ = *p;
- if(p < ppixRed + c)
- *pDst++ |= *p << pmap->pVisual->offsetRed;
- }
- pmap->numPixelsRed[client] += npixR;
- pmap->freeRed -= npixR;
-
- ppix = gpix + pmap->numPixelsGreen[client];
- for (pDst = pixels, p = ppixGreen; p < ppixGreen + npixG; p++)
- {
- *ppix++ = *p;
- if(p < ppixGreen + c)
- *pDst++ |= *p << pmap->pVisual->offsetGreen;
- }
- pmap->numPixelsGreen[client] += npixG;
- pmap->freeGreen -= npixG;
-
- ppix = bpix + pmap->numPixelsBlue[client];
- for (pDst = pixels, p = ppixBlue; p < ppixBlue + npixB; p++)
- {
- *ppix++ = *p;
- if(p < ppixBlue + c)
- *pDst++ |= *p << pmap->pVisual->offsetBlue;
- }
- pmap->numPixelsBlue[client] += npixB;
- pmap->freeBlue -= npixB;
-
-
- for (pDst = pixels; pDst < pixels + c; pDst++)
- *pDst |= ALPHAMASK(pmap->pVisual);
-
- free(ppixBlue);
- free(ppixGreen);
- free(ppixRed);
-
- return (Success);
-}
-
-static int
-AllocPseudo (int client, ColormapPtr pmap, int c, int r, Bool contig,
- Pixel *pixels, Pixel *pmask, Pixel **pppixFirst)
-{
- Pixel *ppix, *p, *pDst, *ppixTemp;
- int npix;
- Bool ok;
-
- npix = c << r;
- if ((r >= 32) || (npix > pmap->freeRed) || (npix < c))
- return(BadAlloc);
- if(!(ppixTemp = malloc(npix * sizeof(Pixel))))
- return(BadAlloc);
- ok = AllocCP(pmap, pmap->red, c, r, contig, ppixTemp, pmask);
-
- if (ok)
- {
-
- /* all the allocated pixels are added to the client pixel list,
- * but only the unique ones are returned to the client */
- ppix = (Pixel *)realloc(pmap->clientPixelsRed[client],
- (pmap->numPixelsRed[client] + npix) * sizeof(Pixel));
- if (!ppix)
- {
- for (p = ppixTemp; p < ppixTemp + npix; p++)
- pmap->red[*p].refcnt = 0;
- return (BadAlloc);
- }
- pmap->clientPixelsRed[client] = ppix;
- ppix += pmap->numPixelsRed[client];
- *pppixFirst = ppix;
- pDst = pixels;
- for (p = ppixTemp; p < ppixTemp + npix; p++)
- {
- *ppix++ = *p;
- if(p < ppixTemp + c)
- *pDst++ = *p;
- }
- pmap->numPixelsRed[client] += npix;
- pmap->freeRed -= npix;
- }
- free(ppixTemp);
- return (ok ? Success : BadAlloc);
-}
-
-/* Allocates count << planes pixels from colormap pmap for client. If
- * contig, then the plane mask is made of consecutive bits. Returns
- * all count << pixels in the array pixels. The first count of those
- * pixels are the unique pixels. *pMask has the mask to Or with the
- * unique pixels to get the rest of them.
- *
- * Returns True iff all pixels could be allocated
- * All cells allocated will have refcnt set to AllocPrivate and shared to FALSE
- * (see AllocShared for why we care)
- */
-static Bool
-AllocCP (ColormapPtr pmap, EntryPtr pentFirst, int count, int planes,
- Bool contig, Pixel *pixels, Pixel *pMask)
-{
- EntryPtr ent;
- Pixel pixel, base, entries, maxp, save;
- int dplanes, found;
- Pixel *ppix;
- Pixel mask;
- Pixel finalmask;
-
- dplanes = pmap->pVisual->nplanes;
-
- /* Easy case. Allocate pixels only */
- if (planes == 0)
- {
- /* allocate writable entries */
- ppix = pixels;
- ent = pentFirst;
- pixel = 0;
- while (--count >= 0)
- {
- /* Just find count unallocated cells */
- while (ent->refcnt)
- {
- ent++;
- pixel++;
- }
- ent->refcnt = AllocPrivate;
- *ppix++ = pixel;
- ent->fShared = FALSE;
- }
- *pMask = 0;
- return (TRUE);
- }
- else if (planes > dplanes)
- {
- return (FALSE);
- }
-
- /* General case count pixels * 2 ^ planes cells to be allocated */
-
- /* make room for new pixels */
- ent = pentFirst;
-
- /* first try for contiguous planes, since it's fastest */
- for (mask = (((Pixel)1) << planes) - 1, base = 1, dplanes -= (planes - 1);
- --dplanes >= 0;
- mask += mask, base += base)
- {
- ppix = pixels;
- found = 0;
- pixel = 0;
- entries = pmap->pVisual->ColormapEntries - mask;
- while (pixel < entries)
- {
- save = pixel;
- maxp = pixel + mask + base;
- /* check if all are free */
- while (pixel != maxp && ent[pixel].refcnt == 0)
- pixel += base;
- if (pixel == maxp)
- {
- /* this one works */
- *ppix++ = save;
- found++;
- if (found == count)
- {
- /* found enough, allocate them all */
- while (--count >= 0)
- {
- pixel = pixels[count];
- maxp = pixel + mask;
- while (1)
- {
- ent[pixel].refcnt = AllocPrivate;
- ent[pixel].fShared = FALSE;
- if (pixel == maxp)
- break;
- pixel += base;
- *ppix++ = pixel;
- }
- }
- *pMask = mask;
- return (TRUE);
- }
- }
- pixel = save + 1;
- if (pixel & mask)
- pixel += mask;
- }
- }
-
- dplanes = pmap->pVisual->nplanes;
- if (contig || planes == 1 || dplanes < 3)
- return (FALSE);
-
- /* this will be very slow for large maps, need a better algorithm */
-
- /*
- we can generate the smallest and largest numbers that fits in dplanes
- bits and contain exactly planes bits set as follows. First, we need to
- check that it is possible to generate such a mask at all.
- (Non-contiguous masks need one more bit than contiguous masks). Then
- the smallest such mask consists of the rightmost planes-1 bits set, then
- a zero, then a one in position planes + 1. The formula is
- (3 << (planes-1)) -1
- The largest such masks consists of the leftmost planes-1 bits set, then
- a zero, then a one bit in position dplanes-planes-1. If dplanes is
- smaller than 32 (the number of bits in a word) then the formula is:
- (1<<dplanes) - (1<<(dplanes-planes+1) + (1<<dplanes-planes-1)
- If dplanes = 32, then we can't calculate (1<<dplanes) and we have
- to use:
- ( (1<<(planes-1)) - 1) << (dplanes-planes+1) + (1<<(dplanes-planes-1))
-
- << Thank you, Loretta>>>
-
- */
-
- finalmask =
- (((((Pixel)1)<<(planes-1)) - 1) << (dplanes-planes+1)) +
- (((Pixel)1)<<(dplanes-planes-1));
- for (mask = (((Pixel)3) << (planes -1)) - 1; mask <= finalmask; mask++)
- {
- /* next 3 magic statements count number of ones (HAKMEM #169) */
- pixel = (mask >> 1) & 033333333333;
- pixel = mask - pixel - ((pixel >> 1) & 033333333333);
- if ((((pixel + (pixel >> 3)) & 030707070707) % 077) != planes)
- continue;
- ppix = pixels;
- found = 0;
- entries = pmap->pVisual->ColormapEntries - mask;
- base = lowbit (mask);
- for (pixel = 0; pixel < entries; pixel++)
- {
- if (pixel & mask)
- continue;
- maxp = 0;
- /* check if all are free */
- while (ent[pixel + maxp].refcnt == 0)
- {
- GetNextBitsOrBreak(maxp, mask, base);
- }
- if ((maxp < mask) || (ent[pixel + mask].refcnt != 0))
- continue;
- /* this one works */
- *ppix++ = pixel;
- found++;
- if (found < count)
- continue;
- /* found enough, allocate them all */
- while (--count >= 0)
- {
- pixel = (pixels)[count];
- maxp = 0;
- while (1)
- {
- ent[pixel + maxp].refcnt = AllocPrivate;
- ent[pixel + maxp].fShared = FALSE;
- GetNextBitsOrBreak(maxp, mask, base);
- *ppix++ = pixel + maxp;
- }
- }
-
- *pMask = mask;
- return (TRUE);
- }
- }
- return (FALSE);
-}
-
-/**
- *
- * \param ppixFirst First of the client's new pixels
- */
-static Bool
-AllocShared (ColormapPtr pmap, Pixel *ppix, int c, int r, int g, int b,
- Pixel rmask, Pixel gmask, Pixel bmask, Pixel *ppixFirst)
-{
- Pixel *pptr, *cptr;
- int npix, z, npixClientNew, npixShared;
- Pixel basemask, base, bits, common;
- SHAREDCOLOR *pshared, **ppshared, **psharedList;
-
- npixClientNew = c << (r + g + b);
- npixShared = (c << r) + (c << g) + (c << b);
- psharedList = malloc(npixShared * sizeof(SHAREDCOLOR *));
- if (!psharedList)
- return FALSE;
- ppshared = psharedList;
- for (z = npixShared; --z >= 0; )
- {
- if (!(ppshared[z] = malloc(sizeof(SHAREDCOLOR))))
- {
- for (z++ ; z < npixShared; z++)
- free(ppshared[z]);
- return FALSE;
- }
- }
- for(pptr = ppix, npix = c; --npix >= 0; pptr++)
- {
- basemask = ~(gmask | bmask);
- common = *pptr & basemask;
- if (rmask)
- {
- bits = 0;
- base = lowbit (rmask);
- while(1)
- {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (g + b);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
- {
- if ((*cptr & basemask) == (common | bits))
- {
- pmap->red[*cptr].fShared = TRUE;
- pmap->red[*cptr].co.shco.red = pshared;
- }
- }
- GetNextBitsOrBreak(bits, rmask, base);
- }
- }
- else
- {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (g + b);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
- {
- if ((*cptr & basemask) == common)
- {
- pmap->red[*cptr].fShared = TRUE;
- pmap->red[*cptr].co.shco.red = pshared;
- }
- }
- }
- basemask = ~(rmask | bmask);
- common = *pptr & basemask;
- if (gmask)
- {
- bits = 0;
- base = lowbit (gmask);
- while(1)
- {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (r + b);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
- {
- if ((*cptr & basemask) == (common | bits))
- {
- pmap->red[*cptr].co.shco.green = pshared;
- }
- }
- GetNextBitsOrBreak(bits, gmask, base);
- }
- }
- else
- {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (g + b);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
- {
- if ((*cptr & basemask) == common)
- {
- pmap->red[*cptr].co.shco.green = pshared;
- }
- }
- }
- basemask = ~(rmask | gmask);
- common = *pptr & basemask;
- if (bmask)
- {
- bits = 0;
- base = lowbit (bmask);
- while(1)
- {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (r + g);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
- {
- if ((*cptr & basemask) == (common | bits))
- {
- pmap->red[*cptr].co.shco.blue = pshared;
- }
- }
- GetNextBitsOrBreak(bits, bmask, base);
- }
- }
- else
- {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (g + b);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
- {
- if ((*cptr & basemask) == common)
- {
- pmap->red[*cptr].co.shco.blue = pshared;
- }
- }
- }
- }
- free(psharedList);
- return TRUE;
-}
-
-
-/** FreeColors
- * Free colors and/or cells (probably slow for large numbers)
- */
-int
-FreeColors (ColormapPtr pmap, int client, int count, Pixel *pixels, Pixel mask)
-{
- int rval, result, class;
- Pixel rmask;
-
- class = pmap->class;
- if (pmap->flags & AllAllocated)
- return(BadAccess);
- if ((class | DynamicClass) == DirectColor)
- {
- rmask = mask & RGBMASK(pmap->pVisual);
- result = FreeCo(pmap, client, REDMAP, count, pixels,
- mask & pmap->pVisual->redMask);
- /* If any of the three calls fails, we must report that, if more
- * than one fails, it's ok that we report the last one */
- rval = FreeCo(pmap, client, GREENMAP, count, pixels,
- mask & pmap->pVisual->greenMask);
- if(rval != Success)
- result = rval;
- rval = FreeCo(pmap, client, BLUEMAP, count, pixels,
- mask & pmap->pVisual->blueMask);
- if(rval != Success)
- result = rval;
- }
- else
- {
- rmask = mask & ((((Pixel)1) << pmap->pVisual->nplanes) - 1);
- result = FreeCo(pmap, client, PSEUDOMAP, count, pixels, rmask);
- }
- if ((mask != rmask) && count)
- {
- clients[client]->errorValue = *pixels | mask;
- result = BadValue;
- }
- /* XXX should worry about removing any RT_CMAPENTRY resource */
- return (result);
-}
-
-/**
- * Helper for FreeColors -- frees all combinations of *newpixels and mask bits
- * which the client has allocated in channel colormap cells of pmap.
- * doesn't change newpixels if it doesn't need to
- *
- * \param pmap which colormap head
- * \param color which sub-map, eg, RED, BLUE, PSEUDO
- * \param npixIn number of pixels passed in
- * \param ppixIn number of base pixels
- * \param mask mask client gave us
- */
-static int
-FreeCo (ColormapPtr pmap, int client, int color, int npixIn, Pixel *ppixIn, Pixel mask)
-{
- Pixel *ppixClient, pixTest;
- int npixClient, npixNew, npix;
- Pixel bits, base, cmask, rgbbad;
- Pixel *pptr, *cptr;
- int n, zapped;
- int errVal = Success;
- int offset, numents;
-
- if (npixIn == 0)
- return (errVal);
- bits = 0;
- zapped = 0;
- base = lowbit (mask);
-
- switch(color)
- {
- case REDMAP:
- cmask = pmap->pVisual->redMask;
- rgbbad = ~RGBMASK(pmap->pVisual);
- offset = pmap->pVisual->offsetRed;
- numents = (cmask >> offset) + 1;
- ppixClient = pmap->clientPixelsRed[client];
- npixClient = pmap->numPixelsRed[client];
- break;
- case GREENMAP:
- cmask = pmap->pVisual->greenMask;
- rgbbad = ~RGBMASK(pmap->pVisual);
- offset = pmap->pVisual->offsetGreen;
- numents = (cmask >> offset) + 1;
- ppixClient = pmap->clientPixelsGreen[client];
- npixClient = pmap->numPixelsGreen[client];
- break;
- case BLUEMAP:
- cmask = pmap->pVisual->blueMask;
- rgbbad = ~RGBMASK(pmap->pVisual);
- offset = pmap->pVisual->offsetBlue;
- numents = (cmask >> offset) + 1;
- ppixClient = pmap->clientPixelsBlue[client];
- npixClient = pmap->numPixelsBlue[client];
- break;
- default: /* so compiler can see that everything gets initialized */
- case PSEUDOMAP:
- cmask = ~((Pixel)0);
- rgbbad = 0;
- offset = 0;
- numents = pmap->pVisual->ColormapEntries;
- ppixClient = pmap->clientPixelsRed[client];
- npixClient = pmap->numPixelsRed[client];
- break;
- }
-
-
- /* zap all pixels which match */
- while (1)
- {
- /* go through pixel list */
- for (pptr = ppixIn, n = npixIn; --n >= 0; pptr++)
- {
- pixTest = ((*pptr | bits) & cmask) >> offset;
- if ((pixTest >= numents) || (*pptr & rgbbad))
- {
- clients[client]->errorValue = *pptr | bits;
- errVal = BadValue;
- continue;
- }
-
- /* find match in client list */
- for (cptr = ppixClient, npix = npixClient;
- --npix >= 0 && *cptr != pixTest;
- cptr++) ;
-
- if (npix >= 0)
- {
- if (pmap->class & DynamicClass)
- {
- FreeCell(pmap, pixTest, color);
- }
- *cptr = ~((Pixel)0);
- zapped++;
- }
- else
- errVal = BadAccess;
- }
- /* generate next bits value */
- GetNextBitsOrBreak(bits, mask, base);
- }
-
- /* delete freed pixels from client pixel list */
- if (zapped)
- {
- npixNew = npixClient - zapped;
- if (npixNew)
- {
- /* Since the list can only get smaller, we can do a copy in
- * place and then realloc to a smaller size */
- pptr = cptr = ppixClient;
-
- /* If we have all the new pixels, we don't have to examine the
- * rest of the old ones */
- for(npix = 0; npix < npixNew; cptr++)
- {
- if (*cptr != ~((Pixel)0))
- {
- *pptr++ = *cptr;
- npix++;
- }
- }
- pptr = (Pixel *)realloc(ppixClient, npixNew * sizeof(Pixel));
- if (pptr)
- ppixClient = pptr;
- npixClient = npixNew;
- }
- else
- {
- npixClient = 0;
- free(ppixClient);
- ppixClient = (Pixel *)NULL;
- }
- switch(color)
- {
- case PSEUDOMAP:
- case REDMAP:
- pmap->clientPixelsRed[client] = ppixClient;
- pmap->numPixelsRed[client] = npixClient;
- break;
- case GREENMAP:
- pmap->clientPixelsGreen[client] = ppixClient;
- pmap->numPixelsGreen[client] = npixClient;
- break;
- case BLUEMAP:
- pmap->clientPixelsBlue[client] = ppixClient;
- pmap->numPixelsBlue[client] = npixClient;
- break;
- }
- }
- return (errVal);
-}
-
-
-
-/* Redefine color values */
-int
-StoreColors (ColormapPtr pmap, int count, xColorItem *defs, ClientPtr client)
-{
- Pixel pix;
- xColorItem *pdef;
- EntryPtr pent, pentT, pentLast;
- VisualPtr pVisual;
- SHAREDCOLOR *pred, *pgreen, *pblue;
- int n, ChgRed, ChgGreen, ChgBlue, idef;
- int class, errVal = Success;
- int ok;
-
-
- class = pmap->class;
- if(!(class & DynamicClass) && !(pmap->flags & BeingCreated))
- {
- return(BadAccess);
- }
- pVisual = pmap->pVisual;
-
- idef = 0;
- if((class | DynamicClass) == DirectColor)
- {
- int numred, numgreen, numblue;
- Pixel rgbbad;
-
- numred = NUMRED(pVisual);
- numgreen = NUMGREEN(pVisual);
- numblue = NUMBLUE(pVisual);
- rgbbad = ~RGBMASK(pVisual);
- for (pdef = defs, n = 0; n < count; pdef++, n++)
- {
- ok = TRUE;
- (*pmap->pScreen->ResolveColor)
- (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual);
-
- if (pdef->pixel & rgbbad)
- {
- errVal = BadValue;
- client->errorValue = pdef->pixel;
- continue;
- }
- pix = (pdef->pixel & pVisual->redMask) >> pVisual->offsetRed;
- if (pix >= numred)
- {
- errVal = BadValue;
- ok = FALSE;
- }
- else if (pmap->red[pix].refcnt != AllocPrivate)
- {
- errVal = BadAccess;
- ok = FALSE;
- }
- else if (pdef->flags & DoRed)
- {
- pmap->red[pix].co.local.red = pdef->red;
- }
- else
- {
- pdef->red = pmap->red[pix].co.local.red;
- }
-
- pix = (pdef->pixel & pVisual->greenMask) >> pVisual->offsetGreen;
- if (pix >= numgreen)
- {
- errVal = BadValue;
- ok = FALSE;
- }
- else if (pmap->green[pix].refcnt != AllocPrivate)
- {
- errVal = BadAccess;
- ok = FALSE;
- }
- else if (pdef->flags & DoGreen)
- {
- pmap->green[pix].co.local.green = pdef->green;
- }
- else
- {
- pdef->green = pmap->green[pix].co.local.green;
- }
-
- pix = (pdef->pixel & pVisual->blueMask) >> pVisual->offsetBlue;
- if (pix >= numblue)
- {
- errVal = BadValue;
- ok = FALSE;
- }
- else if (pmap->blue[pix].refcnt != AllocPrivate)
- {
- errVal = BadAccess;
- ok = FALSE;
- }
- else if (pdef->flags & DoBlue)
- {
- pmap->blue[pix].co.local.blue = pdef->blue;
- }
- else
- {
- pdef->blue = pmap->blue[pix].co.local.blue;
- }
- /* If this is an o.k. entry, then it gets added to the list
- * to be sent to the hardware. If not, skip it. Once we've
- * skipped one, we have to copy all the others.
- */
- if(ok)
- {
- if(idef != n)
- defs[idef] = defs[n];
- idef++;
- } else
- client->errorValue = pdef->pixel;
- }
- }
- else
- {
- for (pdef = defs, n = 0; n < count; pdef++, n++)
- {
-
- ok = TRUE;
- if (pdef->pixel >= pVisual->ColormapEntries)
- {
- client->errorValue = pdef->pixel;
- errVal = BadValue;
- ok = FALSE;
- }
- else if (pmap->red[pdef->pixel].refcnt != AllocPrivate)
- {
- errVal = BadAccess;
- ok = FALSE;
- }
-
- /* If this is an o.k. entry, then it gets added to the list
- * to be sent to the hardware. If not, skip it. Once we've
- * skipped one, we have to copy all the others.
- */
- if(ok)
- {
- if(idef != n)
- defs[idef] = defs[n];
- idef++;
- }
- else
- continue;
-
- (*pmap->pScreen->ResolveColor)
- (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual);
-
- pent = &pmap->red[pdef->pixel];
-
- if(pdef->flags & DoRed)
- {
- if(pent->fShared)
- {
- pent->co.shco.red->color = pdef->red;
- if (pent->co.shco.red->refcnt > 1)
- ok = FALSE;
- }
- else
- pent->co.local.red = pdef->red;
- }
- else
- {
- if(pent->fShared)
- pdef->red = pent->co.shco.red->color;
- else
- pdef->red = pent->co.local.red;
- }
- if(pdef->flags & DoGreen)
- {
- if(pent->fShared)
- {
- pent->co.shco.green->color = pdef->green;
- if (pent->co.shco.green->refcnt > 1)
- ok = FALSE;
- }
- else
- pent->co.local.green = pdef->green;
- }
- else
- {
- if(pent->fShared)
- pdef->green = pent->co.shco.green->color;
- else
- pdef->green = pent->co.local.green;
- }
- if(pdef->flags & DoBlue)
- {
- if(pent->fShared)
- {
- pent->co.shco.blue->color = pdef->blue;
- if (pent->co.shco.blue->refcnt > 1)
- ok = FALSE;
- }
- else
- pent->co.local.blue = pdef->blue;
- }
- else
- {
- if(pent->fShared)
- pdef->blue = pent->co.shco.blue->color;
- else
- pdef->blue = pent->co.local.blue;
- }
-
- if(!ok)
- {
- /* have to run through the colormap and change anybody who
- * shares this value */
- pred = pent->co.shco.red;
- pgreen = pent->co.shco.green;
- pblue = pent->co.shco.blue;
- ChgRed = pdef->flags & DoRed;
- ChgGreen = pdef->flags & DoGreen;
- ChgBlue = pdef->flags & DoBlue;
- pentLast = pmap->red + pVisual->ColormapEntries;
-
- for(pentT = pmap->red; pentT < pentLast; pentT++)
- {
- if(pentT->fShared && (pentT != pent))
- {
- xColorItem defChg;
-
- /* There are, alas, devices in this world too dumb
- * to read their own hardware colormaps. Sick, but
- * true. So we're going to be really nice and load
- * the xColorItem with the proper value for all the
- * fields. We will only set the flags for those
- * fields that actually change. Smart devices can
- * arrange to change only those fields. Dumb devices
- * can rest assured that we have provided for them,
- * and can change all three fields */
-
- defChg.flags = 0;
- if(ChgRed && pentT->co.shco.red == pred)
- {
- defChg.flags |= DoRed;
- }
- if(ChgGreen && pentT->co.shco.green == pgreen)
- {
- defChg.flags |= DoGreen;
- }
- if(ChgBlue && pentT->co.shco.blue == pblue)
- {
- defChg.flags |= DoBlue;
- }
- if(defChg.flags != 0)
- {
- defChg.pixel = pentT - pmap->red;
- defChg.red = pentT->co.shco.red->color;
- defChg.green = pentT->co.shco.green->color;
- defChg.blue = pentT->co.shco.blue->color;
- (*pmap->pScreen->StoreColors) (pmap, 1, &defChg);
- }
- }
- }
-
- }
- }
- }
- /* Note that we use idef, the count of acceptable entries, and not
- * count, the count of proposed entries */
- if (idef != 0)
- ( *pmap->pScreen->StoreColors) (pmap, idef, defs);
- return (errVal);
-}
-
-int
-IsMapInstalled(Colormap map, WindowPtr pWin)
-{
- Colormap *pmaps;
- int imap, nummaps, found;
-
- pmaps = malloc(pWin->drawable.pScreen->maxInstalledCmaps*sizeof(Colormap));
- if(!pmaps)
- return(FALSE);
- nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
- (pWin->drawable.pScreen, pmaps);
- found = FALSE;
- for(imap = 0; imap < nummaps; imap++)
- {
- if(pmaps[imap] == map)
- {
- found = TRUE;
- break;
- }
- }
- free(pmaps);
- return (found);
-}
-
-struct colormap_lookup_data {
- ScreenPtr pScreen;
- VisualPtr visuals;
-};
-
-static void _colormap_find_resource(pointer value, XID id,
- pointer cdata)
-{
- struct colormap_lookup_data *cmap_data = cdata;
- VisualPtr visuals = cmap_data->visuals;
- ScreenPtr pScreen = cmap_data->pScreen;
- ColormapPtr cmap = value;
- int j;
-
- if (pScreen != cmap->pScreen)
- return;
-
- j = cmap->pVisual - pScreen->visuals;
- cmap->pVisual = &visuals[j];
-}
-
-/* something has realloced the visuals, instead of breaking
- ABI fix it up here - glx and compsite did this wrong */
-Bool
-ResizeVisualArray(ScreenPtr pScreen, int new_visual_count,
- DepthPtr depth)
-{
- struct colormap_lookup_data cdata;
- int numVisuals;
- VisualPtr visuals;
- XID *vids, vid;
- int first_new_vid, first_new_visual, i;
-
- first_new_vid = depth->numVids;
- first_new_visual = pScreen->numVisuals;
-
- vids = realloc(depth->vids, (depth->numVids + new_visual_count) * sizeof(XID));
- if (!vids)
- return FALSE;
-
- /* its realloced now no going back if we fail the next one */
- depth->vids = vids;
-
- numVisuals = pScreen->numVisuals + new_visual_count;
- visuals = realloc(pScreen->visuals, numVisuals * sizeof(VisualRec));
- if (!visuals) {
- return FALSE;
- }
-
- cdata.visuals = visuals;
- cdata.pScreen = pScreen;
- FindClientResourcesByType(serverClient, RT_COLORMAP, _colormap_find_resource, &cdata);
-
- pScreen->visuals = visuals;
-
- for (i = 0; i < new_visual_count; i++) {
- vid = FakeClientID(0);
- pScreen->visuals[first_new_visual + i].vid = vid;
- vids[first_new_vid + i] = vid;
- }
-
- depth->numVids += new_visual_count;
- pScreen->numVisuals += new_visual_count;
-
- return TRUE;
-}
+/***********************************************************
+
+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.
+
+******************************************************************/
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include "misc.h"
+#include "dix.h"
+#include "dixstruct.h"
+#include "colormapst.h"
+#include "os.h"
+#include "scrnintstr.h"
+#include "resource.h"
+#include "windowstr.h"
+#include "privates.h"
+#include "xace.h"
+
+static Pixel FindBestPixel(
+ EntryPtr /*pentFirst*/,
+ int /*size*/,
+ xrgb * /*prgb*/,
+ int /*channel*/
+);
+
+static int AllComp(
+ EntryPtr /*pent*/,
+ xrgb * /*prgb*/
+);
+
+static int RedComp(
+ EntryPtr /*pent*/,
+ xrgb * /*prgb*/
+);
+
+static int GreenComp(
+ EntryPtr /*pent*/,
+ xrgb * /*prgb*/
+);
+
+static int BlueComp(
+ EntryPtr /*pent*/,
+ xrgb * /*prgb*/
+);
+
+static void FreePixels(
+ ColormapPtr /*pmap*/,
+ int /*client*/
+);
+
+static void CopyFree(
+ int /*channel*/,
+ int /*client*/,
+ ColormapPtr /*pmapSrc*/,
+ ColormapPtr /*pmapDst*/
+);
+
+static void FreeCell(
+ ColormapPtr /*pmap*/,
+ Pixel /*i*/,
+ int /*channel*/
+);
+
+static void UpdateColors(
+ ColormapPtr /*pmap*/
+);
+
+static int AllocDirect(
+ int /*client*/,
+ ColormapPtr /*pmap*/,
+ int /*c*/,
+ int /*r*/,
+ int /*g*/,
+ int /*b*/,
+ Bool /*contig*/,
+ Pixel * /*pixels*/,
+ Pixel * /*prmask*/,
+ Pixel * /*pgmask*/,
+ Pixel * /*pbmask*/
+);
+
+static int AllocPseudo(
+ int /*client*/,
+ ColormapPtr /*pmap*/,
+ int /*c*/,
+ int /*r*/,
+ Bool /*contig*/,
+ Pixel * /*pixels*/,
+ Pixel * /*pmask*/,
+ Pixel ** /*pppixFirst*/
+);
+
+static Bool AllocCP(
+ ColormapPtr /*pmap*/,
+ EntryPtr /*pentFirst*/,
+ int /*count*/,
+ int /*planes*/,
+ Bool /*contig*/,
+ Pixel * /*pixels*/,
+ Pixel * /*pMask*/
+);
+
+static Bool AllocShared(
+ ColormapPtr /*pmap*/,
+ Pixel * /*ppix*/,
+ int /*c*/,
+ int /*r*/,
+ int /*g*/,
+ int /*b*/,
+ Pixel /*rmask*/,
+ Pixel /*gmask*/,
+ Pixel /*bmask*/,
+ Pixel * /*ppixFirst*/
+);
+
+static int FreeCo(
+ ColormapPtr /*pmap*/,
+ int /*client*/,
+ int /*color*/,
+ int /*npixIn*/,
+ Pixel * /*ppixIn*/,
+ Pixel /*mask*/
+);
+
+static int TellNoMap(
+ WindowPtr /*pwin*/,
+ Colormap * /*pmid*/
+);
+
+static void FindColorInRootCmap (
+ ColormapPtr /* pmap */,
+ EntryPtr /* pentFirst */,
+ int /* size */,
+ xrgb* /* prgb */,
+ Pixel* /* pPixel */,
+ int /* channel */,
+ ColorCompareProcPtr /* comp */
+);
+
+#define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1)
+#define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1)
+#define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1)
+#if COMPOSITE
+#define ALPHAMASK(vis) ((vis)->nplanes < 32 ? 0 : \
+ (CARD32) ~((vis)->redMask|(vis)->greenMask|(vis)->blueMask))
+#else
+#define ALPHAMASK(vis) 0
+#endif
+
+#define RGBMASK(vis) (vis->redMask | vis->greenMask | vis->blueMask | ALPHAMASK(vis))
+
+/* GetNextBitsOrBreak(bits, mask, base) --
+ * (Suggestion: First read the macro, then read this explanation.
+ *
+ * Either generate the next value to OR in to a pixel or break out of this
+ * while loop
+ *
+ * This macro is used when we're trying to generate all 2^n combinations of
+ * bits in mask. What we're doing here is counting in binary, except that
+ * the bits we use to count may not be contiguous. This macro will be
+ * called 2^n times, returning a different value in bits each time. Then
+ * it will cause us to break out of a surrounding loop. (It will always be
+ * called from within a while loop.)
+ * On call: mask is the value we want to find all the combinations for
+ * base has 1 bit set where the least significant bit of mask is set
+ *
+ * For example,if mask is 01010, base should be 0010 and we count like this:
+ * 00010 (see this isn't so hard),
+ * then we add base to bits and get 0100. (bits & ~mask) is (0100 & 0100) so
+ * we add that to bits getting (0100 + 0100) =
+ * 01000 for our next value.
+ * then we add 0010 to get
+ * 01010 and we're done (easy as 1, 2, 3)
+ */
+#define GetNextBitsOrBreak(bits, mask, base) \
+ if((bits) == (mask)) \
+ break; \
+ (bits) += (base); \
+ while((bits) & ~(mask)) \
+ (bits) += ((bits) & ~(mask));
+/* ID of server as client */
+#define SERVER_ID 0
+
+typedef struct _colorResource
+{
+ Colormap mid;
+ int client;
+} colorResource;
+
+/* Invariants:
+ * refcnt == 0 means entry is empty
+ * refcnt > 0 means entry is useable by many clients, so it can't be changed
+ * refcnt == AllocPrivate means entry owned by one client only
+ * fShared should only be set if refcnt == AllocPrivate, and only in red map
+ */
+
+
+/**
+ * Create and initialize the color map
+ *
+ * \param mid resource to use for this colormap
+ * \param alloc 1 iff all entries are allocated writable
+ */
+int
+CreateColormap (Colormap mid, ScreenPtr pScreen, VisualPtr pVisual,
+ ColormapPtr *ppcmap, int alloc, int client)
+{
+ int class, size;
+ unsigned long sizebytes;
+ ColormapPtr pmap;
+ EntryPtr pent;
+ int i;
+ Pixel *ppix, **pptr;
+
+ class = pVisual->class;
+ if(!(class & DynamicClass) && (alloc != AllocNone) && (client != SERVER_ID))
+ return BadMatch;
+
+ size = pVisual->ColormapEntries;
+ sizebytes = (size * sizeof(Entry)) +
+ (MAXCLIENTS * sizeof(Pixel *)) +
+ (MAXCLIENTS * sizeof(int));
+ if ((class | DynamicClass) == DirectColor)
+ sizebytes *= 3;
+ sizebytes += sizeof(ColormapRec);
+ if (mid == pScreen->defColormap) {
+ pmap = malloc(sizebytes);
+ if (!pmap)
+ return BadAlloc;
+ if (!dixAllocatePrivates(&pmap->devPrivates, PRIVATE_COLORMAP)) {
+ free (pmap);
+ return BadAlloc;
+ }
+ } else {
+ pmap = _dixAllocateObjectWithPrivates(sizebytes, sizebytes,
+ offsetof(ColormapRec, devPrivates), PRIVATE_COLORMAP);
+ if (!pmap)
+ return BadAlloc;
+ }
+#if defined(_XSERVER64)
+ pmap->pad0 = 0;
+ pmap->pad1 = 0;
+#if (X_BYTE_ORDER == X_LITTLE_ENDIAN)
+ pmap->pad2 = 0;
+#endif
+#endif
+ pmap->red = (EntryPtr)((char *)pmap + sizeof(ColormapRec));
+ sizebytes = size * sizeof(Entry);
+ pmap->clientPixelsRed = (Pixel **)((char *)pmap->red + sizebytes);
+ pmap->numPixelsRed = (int *)((char *)pmap->clientPixelsRed +
+ (MAXCLIENTS * sizeof(Pixel *)));
+ pmap->mid = mid;
+ pmap->flags = 0; /* start out with all flags clear */
+ if(mid == pScreen->defColormap)
+ pmap->flags |= IsDefault;
+ pmap->pScreen = pScreen;
+ pmap->pVisual = pVisual;
+ pmap->class = class;
+ if ((class | DynamicClass) == DirectColor)
+ size = NUMRED(pVisual);
+ pmap->freeRed = size;
+ memset((char *) pmap->red, 0, (int)sizebytes);
+ memset((char *) pmap->numPixelsRed, 0, MAXCLIENTS * sizeof(int));
+ for (pptr = &pmap->clientPixelsRed[MAXCLIENTS]; --pptr >= pmap->clientPixelsRed; )
+ *pptr = (Pixel *)NULL;
+ if (alloc == AllocAll)
+ {
+ if (class & DynamicClass)
+ pmap->flags |= AllAllocated;
+ for (pent = &pmap->red[size - 1]; pent >= pmap->red; pent--)
+ pent->refcnt = AllocPrivate;
+ pmap->freeRed = 0;
+ ppix = malloc(size * sizeof(Pixel));
+ if (!ppix)
+ {
+ free(pmap);
+ return BadAlloc;
+ }
+ pmap->clientPixelsRed[client] = ppix;
+ for(i = 0; i < size; i++)
+ ppix[i] = i;
+ pmap->numPixelsRed[client] = size;
+ }
+
+ if ((class | DynamicClass) == DirectColor)
+ {
+ pmap->freeGreen = NUMGREEN(pVisual);
+ pmap->green = (EntryPtr)((char *)pmap->numPixelsRed +
+ (MAXCLIENTS * sizeof(int)));
+ pmap->clientPixelsGreen = (Pixel **)((char *)pmap->green + sizebytes);
+ pmap->numPixelsGreen = (int *)((char *)pmap->clientPixelsGreen +
+ (MAXCLIENTS * sizeof(Pixel *)));
+ pmap->freeBlue = NUMBLUE(pVisual);
+ pmap->blue = (EntryPtr)((char *)pmap->numPixelsGreen +
+ (MAXCLIENTS * sizeof(int)));
+ pmap->clientPixelsBlue = (Pixel **)((char *)pmap->blue + sizebytes);
+ pmap->numPixelsBlue = (int *)((char *)pmap->clientPixelsBlue +
+ (MAXCLIENTS * sizeof(Pixel *)));
+
+ memset((char *) pmap->green, 0, (int)sizebytes);
+ memset((char *) pmap->blue, 0, (int)sizebytes);
+
+ memmove((char *) pmap->clientPixelsGreen,
+ (char *) pmap->clientPixelsRed,
+ MAXCLIENTS * sizeof(Pixel *));
+ memmove((char *) pmap->clientPixelsBlue,
+ (char *) pmap->clientPixelsRed,
+ MAXCLIENTS * sizeof(Pixel *));
+ memset((char *) pmap->numPixelsGreen, 0, MAXCLIENTS * sizeof(int));
+ memset((char *) pmap->numPixelsBlue, 0, MAXCLIENTS * sizeof(int));
+
+ /* If every cell is allocated, mark its refcnt */
+ if (alloc == AllocAll)
+ {
+ size = pmap->freeGreen;
+ for(pent = &pmap->green[size-1]; pent >= pmap->green; pent--)
+ pent->refcnt = AllocPrivate;
+ pmap->freeGreen = 0;
+ ppix = malloc(size * sizeof(Pixel));
+ if (!ppix)
+ {
+ free(pmap->clientPixelsRed[client]);
+ free(pmap);
+ return BadAlloc;
+ }
+ pmap->clientPixelsGreen[client] = ppix;
+ for(i = 0; i < size; i++)
+ ppix[i] = i;
+ pmap->numPixelsGreen[client] = size;
+
+ size = pmap->freeBlue;
+ for(pent = &pmap->blue[size-1]; pent >= pmap->blue; pent--)
+ pent->refcnt = AllocPrivate;
+ pmap->freeBlue = 0;
+ ppix = malloc(size * sizeof(Pixel));
+ if (!ppix)
+ {
+ free(pmap->clientPixelsGreen[client]);
+ free(pmap->clientPixelsRed[client]);
+ free(pmap);
+ return BadAlloc;
+ }
+ pmap->clientPixelsBlue[client] = ppix;
+ for(i = 0; i < size; i++)
+ ppix[i] = i;
+ pmap->numPixelsBlue[client] = size;
+ }
+ }
+ pmap->flags |= BeingCreated;
+
+ if (!AddResource(mid, RT_COLORMAP, (pointer)pmap))
+ return BadAlloc;
+
+ /*
+ * Security creation/labeling check
+ */
+ i = XaceHook(XACE_RESOURCE_ACCESS, clients[client], mid, RT_COLORMAP,
+ pmap, RT_NONE, NULL, DixCreateAccess);
+ if (i != Success) {
+ FreeResource(mid, RT_NONE);
+ return i;
+ }
+
+ /* If the device wants a chance to initialize the colormap in any way,
+ * this is it. In specific, if this is a Static colormap, this is the
+ * time to fill in the colormap's values */
+ if (!(*pScreen->CreateColormap)(pmap))
+ {
+ FreeResource (mid, RT_NONE);
+ return BadAlloc;
+ }
+ pmap->flags &= ~BeingCreated;
+ *ppcmap = pmap;
+ return Success;
+}
+
+/**
+ *
+ * \param value must conform to DeleteType
+ */
+int
+FreeColormap (pointer value, XID mid)
+{
+ int i;
+ EntryPtr pent;
+ ColormapPtr pmap = (ColormapPtr)value;
+
+ if(CLIENT_ID(mid) != SERVER_ID)
+ {
+ (*pmap->pScreen->UninstallColormap) (pmap);
+ WalkTree(pmap->pScreen, (VisitWindowProcPtr)TellNoMap, (pointer) &mid);
+ }
+
+ /* This is the device's chance to undo anything it needs to, especially
+ * to free any storage it allocated */
+ (*pmap->pScreen->DestroyColormap)(pmap);
+
+ if(pmap->clientPixelsRed)
+ {
+ for(i = 0; i < MAXCLIENTS; i++)
+ free(pmap->clientPixelsRed[i]);
+ }
+
+ if ((pmap->class == PseudoColor) || (pmap->class == GrayScale))
+ {
+ for(pent = &pmap->red[pmap->pVisual->ColormapEntries - 1];
+ pent >= pmap->red;
+ pent--)
+ {
+ if(pent->fShared)
+ {
+ if (--pent->co.shco.red->refcnt == 0)
+ free(pent->co.shco.red);
+ if (--pent->co.shco.green->refcnt == 0)
+ free(pent->co.shco.green);
+ if (--pent->co.shco.blue->refcnt == 0)
+ free(pent->co.shco.blue);
+ }
+ }
+ }
+ if((pmap->class | DynamicClass) == DirectColor)
+ {
+ for(i = 0; i < MAXCLIENTS; i++)
+ {
+ free(pmap->clientPixelsGreen[i]);
+ free(pmap->clientPixelsBlue[i]);
+ }
+ }
+
+ if (pmap->flags & IsDefault) {
+ dixFreePrivates(pmap->devPrivates, PRIVATE_COLORMAP);
+ free(pmap);
+ } else
+ dixFreeObjectWithPrivates(pmap, PRIVATE_COLORMAP);
+ return Success;
+}
+
+/* Tell window that pmid has disappeared */
+static int
+TellNoMap (WindowPtr pwin, Colormap *pmid)
+{
+ xEvent xE;
+
+ if (wColormap(pwin) == *pmid)
+ {
+ /* This should be call to DeliverEvent */
+ xE.u.u.type = ColormapNotify;
+ xE.u.colormap.window = pwin->drawable.id;
+ xE.u.colormap.colormap = None;
+ xE.u.colormap.new = TRUE;
+ xE.u.colormap.state = ColormapUninstalled;
+#ifdef PANORAMIX
+ if(noPanoramiXExtension || !pwin->drawable.pScreen->myNum)
+#endif
+ DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL);
+ if (pwin->optional) {
+ pwin->optional->colormap = None;
+ CheckWindowOptionalNeed (pwin);
+ }
+ }
+
+ return WT_WALKCHILDREN;
+}
+
+/* Tell window that pmid got uninstalled */
+int
+TellLostMap (WindowPtr pwin, pointer value)
+{
+ Colormap *pmid = (Colormap *)value;
+ xEvent xE;
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum)
+ return WT_STOPWALKING;
+#endif
+ if (wColormap(pwin) == *pmid)
+ {
+ /* This should be call to DeliverEvent */
+ xE.u.u.type = ColormapNotify;
+ xE.u.colormap.window = pwin->drawable.id;
+ xE.u.colormap.colormap = *pmid;
+ xE.u.colormap.new = FALSE;
+ xE.u.colormap.state = ColormapUninstalled;
+ DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL);
+ }
+
+ return WT_WALKCHILDREN;
+}
+
+/* Tell window that pmid got installed */
+int
+TellGainedMap (WindowPtr pwin, pointer value)
+{
+ Colormap *pmid = (Colormap *)value;
+ xEvent xE;
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum)
+ return WT_STOPWALKING;
+#endif
+ if (wColormap (pwin) == *pmid)
+ {
+ /* This should be call to DeliverEvent */
+ xE.u.u.type = ColormapNotify;
+ xE.u.colormap.window = pwin->drawable.id;
+ xE.u.colormap.colormap = *pmid;
+ xE.u.colormap.new = FALSE;
+ xE.u.colormap.state = ColormapInstalled;
+ DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL);
+ }
+
+ return WT_WALKCHILDREN;
+}
+
+
+int
+CopyColormapAndFree (Colormap mid, ColormapPtr pSrc, int client)
+{
+ ColormapPtr pmap = (ColormapPtr) NULL;
+ int result, alloc, size;
+ Colormap midSrc;
+ ScreenPtr pScreen;
+ VisualPtr pVisual;
+
+ pScreen = pSrc->pScreen;
+ pVisual = pSrc->pVisual;
+ midSrc = pSrc->mid;
+ alloc = ((pSrc->flags & AllAllocated) && CLIENT_ID(midSrc) == client) ?
+ AllocAll : AllocNone;
+ size = pVisual->ColormapEntries;
+
+ /* If the create returns non-0, it failed */
+ result = CreateColormap (mid, pScreen, pVisual, &pmap, alloc, client);
+ if(result != Success)
+ return result;
+ if(alloc == AllocAll)
+ {
+ memmove((char *)pmap->red, (char *)pSrc->red, size * sizeof(Entry));
+ if((pmap->class | DynamicClass) == DirectColor)
+ {
+ memmove((char *)pmap->green, (char *)pSrc->green, size * sizeof(Entry));
+ memmove((char *)pmap->blue, (char *)pSrc->blue, size * sizeof(Entry));
+ }
+ pSrc->flags &= ~AllAllocated;
+ FreePixels(pSrc, client);
+ UpdateColors(pmap);
+ return Success;
+ }
+
+ CopyFree(REDMAP, client, pSrc, pmap);
+ if ((pmap->class | DynamicClass) == DirectColor)
+ {
+ CopyFree(GREENMAP, client, pSrc, pmap);
+ CopyFree(BLUEMAP, client, pSrc, pmap);
+ }
+ if (pmap->class & DynamicClass)
+ UpdateColors(pmap);
+ /* XXX should worry about removing any RT_CMAPENTRY resource */
+ return Success;
+}
+
+/* Helper routine for freeing large numbers of cells from a map */
+static void
+CopyFree (int channel, int client, ColormapPtr pmapSrc, ColormapPtr pmapDst)
+{
+ int z, npix;
+ EntryPtr pentSrcFirst, pentDstFirst;
+ EntryPtr pentSrc, pentDst;
+ Pixel *ppix;
+ int nalloc;
+
+ switch(channel)
+ {
+ default: /* so compiler can see that everything gets initialized */
+ case REDMAP:
+ ppix = (pmapSrc->clientPixelsRed)[client];
+ npix = (pmapSrc->numPixelsRed)[client];
+ pentSrcFirst = pmapSrc->red;
+ pentDstFirst = pmapDst->red;
+ break;
+ case GREENMAP:
+ ppix = (pmapSrc->clientPixelsGreen)[client];
+ npix = (pmapSrc->numPixelsGreen)[client];
+ pentSrcFirst = pmapSrc->green;
+ pentDstFirst = pmapDst->green;
+ break;
+ case BLUEMAP:
+ ppix = (pmapSrc->clientPixelsBlue)[client];
+ npix = (pmapSrc->numPixelsBlue)[client];
+ pentSrcFirst = pmapSrc->blue;
+ pentDstFirst = pmapDst->blue;
+ break;
+ }
+ nalloc = 0;
+ if (pmapSrc->class & DynamicClass)
+ {
+ for(z = npix; --z >= 0; ppix++)
+ {
+ /* Copy entries */
+ pentSrc = pentSrcFirst + *ppix;
+ pentDst = pentDstFirst + *ppix;
+ if (pentDst->refcnt > 0)
+ {
+ pentDst->refcnt++;
+ }
+ else
+ {
+ *pentDst = *pentSrc;
+ nalloc++;
+ if (pentSrc->refcnt > 0)
+ pentDst->refcnt = 1;
+ else
+ pentSrc->fShared = FALSE;
+ }
+ FreeCell(pmapSrc, *ppix, channel);
+ }
+ }
+
+ /* Note that FreeCell has already fixed pmapSrc->free{Color} */
+ switch(channel)
+ {
+ case REDMAP:
+ pmapDst->freeRed -= nalloc;
+ (pmapDst->clientPixelsRed)[client] =
+ (pmapSrc->clientPixelsRed)[client];
+ (pmapSrc->clientPixelsRed)[client] = (Pixel *) NULL;
+ (pmapDst->numPixelsRed)[client] = (pmapSrc->numPixelsRed)[client];
+ (pmapSrc->numPixelsRed)[client] = 0;
+ break;
+ case GREENMAP:
+ pmapDst->freeGreen -= nalloc;
+ (pmapDst->clientPixelsGreen)[client] =
+ (pmapSrc->clientPixelsGreen)[client];
+ (pmapSrc->clientPixelsGreen)[client] = (Pixel *) NULL;
+ (pmapDst->numPixelsGreen)[client] = (pmapSrc->numPixelsGreen)[client];
+ (pmapSrc->numPixelsGreen)[client] = 0;
+ break;
+ case BLUEMAP:
+ pmapDst->freeBlue -= nalloc;
+ pmapDst->clientPixelsBlue[client] = pmapSrc->clientPixelsBlue[client];
+ pmapSrc->clientPixelsBlue[client] = (Pixel *) NULL;
+ pmapDst->numPixelsBlue[client] = pmapSrc->numPixelsBlue[client];
+ pmapSrc->numPixelsBlue[client] = 0;
+ break;
+ }
+}
+
+/* Free the ith entry in a color map. Must handle freeing of
+ * colors allocated through AllocColorPlanes */
+static void
+FreeCell (ColormapPtr pmap, Pixel i, int channel)
+{
+ EntryPtr pent;
+ int *pCount;
+
+
+ switch (channel)
+ {
+ default: /* so compiler can see that everything gets initialized */
+ case PSEUDOMAP:
+ case REDMAP:
+ pent = (EntryPtr) &pmap->red[i];
+ pCount = &pmap->freeRed;
+ break;
+ case GREENMAP:
+ pent = (EntryPtr) &pmap->green[i];
+ pCount = &pmap->freeGreen;
+ break;
+ case BLUEMAP:
+ pent = (EntryPtr) &pmap->blue[i];
+ pCount = &pmap->freeBlue;
+ break;
+ }
+ /* If it's not privately allocated and it's not time to free it, just
+ * decrement the count */
+ if (pent->refcnt > 1)
+ pent->refcnt--;
+ else
+ {
+ /* If the color type is shared, find the sharedcolor. If decremented
+ * refcnt is 0, free the shared cell. */
+ if (pent->fShared)
+ {
+ if(--pent->co.shco.red->refcnt == 0)
+ free(pent->co.shco.red);
+ if(--pent->co.shco.green->refcnt == 0)
+ free(pent->co.shco.green);
+ if(--pent->co.shco.blue->refcnt == 0)
+ free(pent->co.shco.blue);
+ pent->fShared = FALSE;
+ }
+ pent->refcnt = 0;
+ *pCount += 1;
+ }
+}
+
+static void
+UpdateColors (ColormapPtr pmap)
+{
+ xColorItem *defs;
+ xColorItem *pdef;
+ EntryPtr pent;
+ VisualPtr pVisual;
+ int i, n, size;
+
+ pVisual = pmap->pVisual;
+ size = pVisual->ColormapEntries;
+ defs = malloc(size * sizeof(xColorItem));
+ if (!defs)
+ return;
+ n = 0;
+ pdef = defs;
+ if (pmap->class == DirectColor)
+ {
+ for (i = 0; i < size; i++)
+ {
+ if (!pmap->red[i].refcnt &&
+ !pmap->green[i].refcnt &&
+ !pmap->blue[i].refcnt)
+ continue;
+ pdef->pixel = ((Pixel)i << pVisual->offsetRed) |
+ ((Pixel)i << pVisual->offsetGreen) |
+ ((Pixel)i << pVisual->offsetBlue);
+ pdef->red = pmap->red[i].co.local.red;
+ pdef->green = pmap->green[i].co.local.green;
+ pdef->blue = pmap->blue[i].co.local.blue;
+ pdef->flags = DoRed|DoGreen|DoBlue;
+ pdef++;
+ n++;
+ }
+ }
+ else
+ {
+ for (i = 0, pent = pmap->red; i < size; i++, pent++)
+ {
+ if (!pent->refcnt)
+ continue;
+ pdef->pixel = i;
+ if(pent->fShared)
+ {
+ pdef->red = pent->co.shco.red->color;
+ pdef->green = pent->co.shco.green->color;
+ pdef->blue = pent->co.shco.blue->color;
+ }
+ else
+ {
+ pdef->red = pent->co.local.red;
+ pdef->green = pent->co.local.green;
+ pdef->blue = pent->co.local.blue;
+ }
+ pdef->flags = DoRed|DoGreen|DoBlue;
+ pdef++;
+ n++;
+ }
+ }
+ if (n)
+ (*pmap->pScreen->StoreColors)(pmap, n, defs);
+ free(defs);
+}
+
+/* Get a read-only color from a ColorMap (probably slow for large maps)
+ * Returns by changing the value in pred, pgreen, pblue and pPix
+ */
+int
+AllocColor (ColormapPtr pmap,
+ unsigned short *pred, unsigned short *pgreen, unsigned short *pblue,
+ Pixel *pPix, int client)
+{
+ Pixel pixR, pixG, pixB;
+ int entries;
+ xrgb rgb;
+ int class;
+ VisualPtr pVisual;
+ int npix;
+ Pixel *ppix;
+
+ pVisual = pmap->pVisual;
+ (*pmap->pScreen->ResolveColor) (pred, pgreen, pblue, pVisual);
+ rgb.red = *pred;
+ rgb.green = *pgreen;
+ rgb.blue = *pblue;
+ class = pmap->class;
+ entries = pVisual->ColormapEntries;
+
+ /* If the colormap is being created, then we want to be able to change
+ * the colormap, even if it's a static type. Otherwise, we'd never be
+ * able to initialize static colormaps
+ */
+ if(pmap->flags & BeingCreated)
+ class |= DynamicClass;
+
+ /* If this is one of the static storage classes, and we're not initializing
+ * it, the best we can do is to find the closest color entry to the
+ * requested one and return that.
+ */
+ switch (class) {
+ case StaticColor:
+ case StaticGray:
+ /* Look up all three components in the same pmap */
+ *pPix = pixR = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP);
+ *pred = pmap->red[pixR].co.local.red;
+ *pgreen = pmap->red[pixR].co.local.green;
+ *pblue = pmap->red[pixR].co.local.blue;
+ npix = pmap->numPixelsRed[client];
+ ppix = (Pixel *) realloc(pmap->clientPixelsRed[client],
+ (npix + 1) * sizeof(Pixel));
+ if (!ppix)
+ return BadAlloc;
+ ppix[npix] = pixR;
+ pmap->clientPixelsRed[client] = ppix;
+ pmap->numPixelsRed[client]++;
+ break;
+
+ case TrueColor:
+ /* Look up each component in its own map, then OR them together */
+ pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP);
+ pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP);
+ pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP);
+ *pPix = (pixR << pVisual->offsetRed) |
+ (pixG << pVisual->offsetGreen) |
+ (pixB << pVisual->offsetBlue) |
+ ALPHAMASK(pVisual);
+
+ *pred = pmap->red[pixR].co.local.red;
+ *pgreen = pmap->green[pixG].co.local.green;
+ *pblue = pmap->blue[pixB].co.local.blue;
+ npix = pmap->numPixelsRed[client];
+ ppix = (Pixel *) realloc(pmap->clientPixelsRed[client],
+ (npix + 1) * sizeof(Pixel));
+ if (!ppix)
+ return BadAlloc;
+ ppix[npix] = pixR;
+ pmap->clientPixelsRed[client] = ppix;
+ npix = pmap->numPixelsGreen[client];
+ ppix = (Pixel *) realloc(pmap->clientPixelsGreen[client],
+ (npix + 1) * sizeof(Pixel));
+ if (!ppix)
+ return BadAlloc;
+ ppix[npix] = pixG;
+ pmap->clientPixelsGreen[client] = ppix;
+ npix = pmap->numPixelsBlue[client];
+ ppix = (Pixel *) realloc(pmap->clientPixelsBlue[client],
+ (npix + 1) * sizeof(Pixel));
+ if (!ppix)
+ return BadAlloc;
+ ppix[npix] = pixB;
+ pmap->clientPixelsBlue[client] = ppix;
+ pmap->numPixelsRed[client]++;
+ pmap->numPixelsGreen[client]++;
+ pmap->numPixelsBlue[client]++;
+ break;
+
+ case GrayScale:
+ case PseudoColor:
+ if (pmap->mid != pmap->pScreen->defColormap &&
+ pmap->pVisual->vid == pmap->pScreen->rootVisual)
+ {
+ ColormapPtr prootmap;
+ dixLookupResourceByType((pointer *)&prootmap, pmap->pScreen->defColormap,
+ RT_COLORMAP, clients[client], DixReadAccess);
+
+ if (pmap->class == prootmap->class)
+ FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb,
+ pPix, PSEUDOMAP, AllComp);
+ }
+ if (FindColor(pmap, pmap->red, entries, &rgb, pPix, PSEUDOMAP,
+ client, AllComp) != Success)
+ return BadAlloc;
+ break;
+
+ case DirectColor:
+ if (pmap->mid != pmap->pScreen->defColormap &&
+ pmap->pVisual->vid == pmap->pScreen->rootVisual)
+ {
+ ColormapPtr prootmap;
+ dixLookupResourceByType((pointer *)&prootmap, pmap->pScreen->defColormap,
+ RT_COLORMAP, clients[client], DixReadAccess);
+
+ if (pmap->class == prootmap->class)
+ {
+ pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed;
+ FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb,
+ &pixR, REDMAP, RedComp);
+ pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen;
+ FindColorInRootCmap (prootmap, prootmap->green, entries, &rgb,
+ &pixG, GREENMAP, GreenComp);
+ pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue;
+ FindColorInRootCmap (prootmap, prootmap->blue, entries, &rgb,
+ &pixB, BLUEMAP, BlueComp);
+ *pPix = pixR | pixG | pixB;
+ }
+ }
+
+ pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed;
+ if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP,
+ client, RedComp) != Success)
+ return BadAlloc;
+ pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen;
+ if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG,
+ GREENMAP, client, GreenComp) != Success)
+ {
+ (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0);
+ return BadAlloc;
+ }
+ pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue;
+ if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP,
+ client, BlueComp) != Success)
+ {
+ (void)FreeCo(pmap, client, GREENMAP, 1, &pixG, (Pixel)0);
+ (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0);
+ return BadAlloc;
+ }
+ *pPix = pixR | pixG | pixB | ALPHAMASK(pVisual);
+
+ break;
+ }
+
+ /* if this is the client's first pixel in this colormap, tell the
+ * resource manager that the client has pixels in this colormap which
+ * should be freed when the client dies */
+ if ((pmap->numPixelsRed[client] == 1) &&
+ (CLIENT_ID(pmap->mid) != client) &&
+ !(pmap->flags & BeingCreated))
+ {
+ colorResource *pcr;
+
+ pcr = malloc(sizeof(colorResource));
+ if (!pcr)
+ {
+ (void)FreeColors(pmap, client, 1, pPix, (Pixel)0);
+ return BadAlloc;
+ }
+ pcr->mid = pmap->mid;
+ pcr->client = client;
+ if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr))
+ return BadAlloc;
+ }
+ return Success;
+}
+
+/*
+ * FakeAllocColor -- fake an AllocColor request by
+ * returning a free pixel if availible, otherwise returning
+ * the closest matching pixel. This is used by the mi
+ * software sprite code to recolor cursors. A nice side-effect
+ * is that this routine will never return failure.
+ */
+
+void
+FakeAllocColor (ColormapPtr pmap, xColorItem *item)
+{
+ Pixel pixR, pixG, pixB;
+ Pixel temp;
+ int entries;
+ xrgb rgb;
+ int class;
+ VisualPtr pVisual;
+
+ pVisual = pmap->pVisual;
+ rgb.red = item->red;
+ rgb.green = item->green;
+ rgb.blue = item->blue;
+ (*pmap->pScreen->ResolveColor) (&rgb.red, &rgb.green, &rgb.blue, pVisual);
+ class = pmap->class;
+ entries = pVisual->ColormapEntries;
+
+ switch (class) {
+ case GrayScale:
+ case PseudoColor:
+ temp = 0;
+ item->pixel = 0;
+ if (FindColor(pmap, pmap->red, entries, &rgb, &temp, PSEUDOMAP,
+ -1, AllComp) == Success) {
+ item->pixel = temp;
+ break;
+ }
+ /* fall through ... */
+ case StaticColor:
+ case StaticGray:
+ item->pixel = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP);
+ break;
+
+ case DirectColor:
+ /* Look up each component in its own map, then OR them together */
+ pixR = (item->pixel & pVisual->redMask) >> pVisual->offsetRed;
+ pixG = (item->pixel & pVisual->greenMask) >> pVisual->offsetGreen;
+ pixB = (item->pixel & pVisual->blueMask) >> pVisual->offsetBlue;
+ if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP,
+ -1, RedComp) != Success)
+ pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP)
+ << pVisual->offsetRed;
+ if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG,
+ GREENMAP, -1, GreenComp) != Success)
+ pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb,
+ GREENMAP) << pVisual->offsetGreen;
+ if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP,
+ -1, BlueComp) != Success)
+ pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP)
+ << pVisual->offsetBlue;
+ item->pixel = pixR | pixG | pixB;
+ break;
+
+ case TrueColor:
+ /* Look up each component in its own map, then OR them together */
+ pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP);
+ pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP);
+ pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP);
+ item->pixel = (pixR << pVisual->offsetRed) |
+ (pixG << pVisual->offsetGreen) |
+ (pixB << pVisual->offsetBlue);
+ break;
+ }
+}
+
+/* free a pixel value obtained from FakeAllocColor */
+void
+FakeFreeColor(ColormapPtr pmap, Pixel pixel)
+{
+ VisualPtr pVisual;
+ Pixel pixR, pixG, pixB;
+
+ switch (pmap->class) {
+ case GrayScale:
+ case PseudoColor:
+ if (pmap->red[pixel].refcnt == AllocTemporary)
+ pmap->red[pixel].refcnt = 0;
+ break;
+ case DirectColor:
+ pVisual = pmap->pVisual;
+ pixR = (pixel & pVisual->redMask) >> pVisual->offsetRed;
+ pixG = (pixel & pVisual->greenMask) >> pVisual->offsetGreen;
+ pixB = (pixel & pVisual->blueMask) >> pVisual->offsetBlue;
+ if (pmap->red[pixR].refcnt == AllocTemporary)
+ pmap->red[pixR].refcnt = 0;
+ if (pmap->green[pixG].refcnt == AllocTemporary)
+ pmap->green[pixG].refcnt = 0;
+ if (pmap->blue[pixB].refcnt == AllocTemporary)
+ pmap->blue[pixB].refcnt = 0;
+ break;
+ }
+}
+
+typedef unsigned short BigNumUpper;
+typedef unsigned long BigNumLower;
+
+#define BIGNUMLOWERBITS 24
+#define BIGNUMUPPERBITS 16
+#define BIGNUMLOWER (1 << BIGNUMLOWERBITS)
+#define BIGNUMUPPER (1 << BIGNUMUPPERBITS)
+#define UPPERPART(i) ((i) >> BIGNUMLOWERBITS)
+#define LOWERPART(i) ((i) & (BIGNUMLOWER - 1))
+
+typedef struct _bignum {
+ BigNumUpper upper;
+ BigNumLower lower;
+} BigNumRec, *BigNumPtr;
+
+#define BigNumGreater(x,y) (((x)->upper > (y)->upper) ||\
+ ((x)->upper == (y)->upper && (x)->lower > (y)->lower))
+
+#define UnsignedToBigNum(u,r) (((r)->upper = UPPERPART(u)), \
+ ((r)->lower = LOWERPART(u)))
+
+#define MaxBigNum(r) (((r)->upper = BIGNUMUPPER-1), \
+ ((r)->lower = BIGNUMLOWER-1))
+
+static void
+BigNumAdd (BigNumPtr x, BigNumPtr y, BigNumPtr r)
+{
+ BigNumLower lower, carry = 0;
+
+ lower = x->lower + y->lower;
+ if (lower >= BIGNUMLOWER) {
+ lower -= BIGNUMLOWER;
+ carry = 1;
+ }
+ r->lower = lower;
+ r->upper = x->upper + y->upper + carry;
+}
+
+static Pixel
+FindBestPixel(EntryPtr pentFirst, int size, xrgb *prgb, int channel)
+{
+ EntryPtr pent;
+ Pixel pixel, final;
+ long dr, dg, db;
+ unsigned long sq;
+ BigNumRec minval, sum, temp;
+
+ final = 0;
+ MaxBigNum(&minval);
+ /* look for the minimal difference */
+ for (pent = pentFirst, pixel = 0; pixel < size; pent++, pixel++)
+ {
+ dr = dg = db = 0;
+ switch(channel)
+ {
+ case PSEUDOMAP:
+ dg = (long) pent->co.local.green - prgb->green;
+ db = (long) pent->co.local.blue - prgb->blue;
+ case REDMAP:
+ dr = (long) pent->co.local.red - prgb->red;
+ break;
+ case GREENMAP:
+ dg = (long) pent->co.local.green - prgb->green;
+ break;
+ case BLUEMAP:
+ db = (long) pent->co.local.blue - prgb->blue;
+ break;
+ }
+ sq = dr * dr;
+ UnsignedToBigNum (sq, &sum);
+ sq = dg * dg;
+ UnsignedToBigNum (sq, &temp);
+ BigNumAdd (&sum, &temp, &sum);
+ sq = db * db;
+ UnsignedToBigNum (sq, &temp);
+ BigNumAdd (&sum, &temp, &sum);
+ if (BigNumGreater (&minval, &sum))
+ {
+ final = pixel;
+ minval = sum;
+ }
+ }
+ return final;
+}
+
+static void
+FindColorInRootCmap (ColormapPtr pmap, EntryPtr pentFirst, int size,
+ xrgb *prgb, Pixel *pPixel, int channel,
+ ColorCompareProcPtr comp)
+{
+ EntryPtr pent;
+ Pixel pixel;
+ int count;
+
+ if ((pixel = *pPixel) >= size)
+ pixel = 0;
+ for (pent = pentFirst + pixel, count = size; --count >= 0; pent++, pixel++)
+ {
+ if (pent->refcnt > 0 && (*comp) (pent, prgb))
+ {
+ switch (channel)
+ {
+ case REDMAP:
+ pixel <<= pmap->pVisual->offsetRed;
+ break;
+ case GREENMAP:
+ pixel <<= pmap->pVisual->offsetGreen;
+ break;
+ case BLUEMAP:
+ pixel <<= pmap->pVisual->offsetBlue;
+ break;
+ default: /* PSEUDOMAP */
+ break;
+ }
+ *pPixel = pixel;
+ }
+ }
+}
+
+/* Tries to find a color in pmap that exactly matches the one requested in prgb
+ * if it can't it allocates one.
+ * Starts looking at pentFirst + *pPixel, so if you want a specific pixel,
+ * load *pPixel with that value, otherwise set it to 0
+ */
+int
+FindColor (ColormapPtr pmap, EntryPtr pentFirst, int size, xrgb *prgb,
+ Pixel *pPixel, int channel, int client,
+ ColorCompareProcPtr comp)
+{
+ EntryPtr pent;
+ Bool foundFree;
+ Pixel pixel, Free = 0;
+ int npix, count, *nump = NULL;
+ Pixel **pixp = NULL, *ppix;
+ xColorItem def;
+
+ foundFree = FALSE;
+
+ if((pixel = *pPixel) >= size)
+ pixel = 0;
+ /* see if there is a match, and also look for a free entry */
+ for (pent = pentFirst + pixel, count = size; --count >= 0; )
+ {
+ if (pent->refcnt > 0)
+ {
+ if ((*comp) (pent, prgb))
+ {
+ if (client >= 0)
+ pent->refcnt++;
+ *pPixel = pixel;
+ switch(channel)
+ {
+ case REDMAP:
+ *pPixel <<= pmap->pVisual->offsetRed;
+ case PSEUDOMAP:
+ break;
+ case GREENMAP:
+ *pPixel <<= pmap->pVisual->offsetGreen;
+ break;
+ case BLUEMAP:
+ *pPixel <<= pmap->pVisual->offsetBlue;
+ break;
+ }
+ goto gotit;
+ }
+ }
+ else if (!foundFree && pent->refcnt == 0)
+ {
+ Free = pixel;
+ foundFree = TRUE;
+ /* If we're initializing the colormap, then we are looking for
+ * the first free cell we can find, not to minimize the number
+ * of entries we use. So don't look any further. */
+ if(pmap->flags & BeingCreated)
+ break;
+ }
+ pixel++;
+ if(pixel >= size)
+ {
+ pent = pentFirst;
+ pixel = 0;
+ }
+ else
+ pent++;
+ }
+
+ /* If we got here, we didn't find a match. If we also didn't find
+ * a free entry, we're out of luck. Otherwise, we'll usurp a free
+ * entry and fill it in */
+ if (!foundFree)
+ return BadAlloc;
+ pent = pentFirst + Free;
+ pent->fShared = FALSE;
+ pent->refcnt = (client >= 0) ? 1 : AllocTemporary;
+
+ switch (channel)
+ {
+ case PSEUDOMAP:
+ pent->co.local.red = prgb->red;
+ pent->co.local.green = prgb->green;
+ pent->co.local.blue = prgb->blue;
+ def.red = prgb->red;
+ def.green = prgb->green;
+ def.blue = prgb->blue;
+ def.flags = (DoRed|DoGreen|DoBlue);
+ if (client >= 0)
+ pmap->freeRed--;
+ def.pixel = Free;
+ break;
+
+ case REDMAP:
+ pent->co.local.red = prgb->red;
+ def.red = prgb->red;
+ def.green = pmap->green[0].co.local.green;
+ def.blue = pmap->blue[0].co.local.blue;
+ def.flags = DoRed;
+ if (client >= 0)
+ pmap->freeRed--;
+ def.pixel = Free << pmap->pVisual->offsetRed;
+ break;
+
+ case GREENMAP:
+ pent->co.local.green = prgb->green;
+ def.red = pmap->red[0].co.local.red;
+ def.green = prgb->green;
+ def.blue = pmap->blue[0].co.local.blue;
+ def.flags = DoGreen;
+ if (client >= 0)
+ pmap->freeGreen--;
+ def.pixel = Free << pmap->pVisual->offsetGreen;
+ break;
+
+ case BLUEMAP:
+ pent->co.local.blue = prgb->blue;
+ def.red = pmap->red[0].co.local.red;
+ def.green = pmap->green[0].co.local.green;
+ def.blue = prgb->blue;
+ def.flags = DoBlue;
+ if (client >= 0)
+ pmap->freeBlue--;
+ def.pixel = Free << pmap->pVisual->offsetBlue;
+ break;
+ }
+ (*pmap->pScreen->StoreColors) (pmap, 1, &def);
+ pixel = Free;
+ *pPixel = def.pixel;
+
+gotit:
+ if (pmap->flags & BeingCreated || client == -1)
+ return Success;
+ /* Now remember the pixel, for freeing later */
+ switch (channel)
+ {
+ case PSEUDOMAP:
+ case REDMAP:
+ nump = pmap->numPixelsRed;
+ pixp = pmap->clientPixelsRed;
+ break;
+
+ case GREENMAP:
+ nump = pmap->numPixelsGreen;
+ pixp = pmap->clientPixelsGreen;
+ break;
+
+ case BLUEMAP:
+ nump = pmap->numPixelsBlue;
+ pixp = pmap->clientPixelsBlue;
+ break;
+ }
+ npix = nump[client];
+ ppix = (Pixel *) realloc(pixp[client], (npix + 1) * sizeof(Pixel));
+ if (!ppix)
+ {
+ pent->refcnt--;
+ if (!pent->fShared)
+ switch (channel)
+ {
+ case PSEUDOMAP:
+ case REDMAP:
+ pmap->freeRed++;
+ break;
+ case GREENMAP:
+ pmap->freeGreen++;
+ break;
+ case BLUEMAP:
+ pmap->freeBlue++;
+ break;
+ }
+ return BadAlloc;
+ }
+ ppix[npix] = pixel;
+ pixp[client] = ppix;
+ nump[client]++;
+
+ return Success;
+}
+
+/* Comparison functions -- passed to FindColor to determine if an
+ * entry is already the color we're looking for or not */
+static int
+AllComp (EntryPtr pent, xrgb *prgb)
+{
+ if((pent->co.local.red == prgb->red) &&
+ (pent->co.local.green == prgb->green) &&
+ (pent->co.local.blue == prgb->blue) )
+ return 1;
+ return 0;
+}
+
+static int
+RedComp (EntryPtr pent, xrgb *prgb)
+{
+ if (pent->co.local.red == prgb->red)
+ return 1;
+ return 0;
+}
+
+static int
+GreenComp (EntryPtr pent, xrgb *prgb)
+{
+ if (pent->co.local.green == prgb->green)
+ return 1;
+ return 0;
+}
+
+static int
+BlueComp (EntryPtr pent, xrgb *prgb)
+{
+ if (pent->co.local.blue == prgb->blue)
+ return 1;
+ return 0;
+}
+
+
+/* Read the color value of a cell */
+
+int
+QueryColors (ColormapPtr pmap, int count, Pixel *ppixIn, xrgb *prgbList, ClientPtr client)
+{
+ Pixel *ppix, pixel;
+ xrgb *prgb;
+ VisualPtr pVisual;
+ EntryPtr pent;
+ Pixel i;
+ int errVal = Success;
+
+ pVisual = pmap->pVisual;
+ if ((pmap->class | DynamicClass) == DirectColor)
+ {
+ int numred, numgreen, numblue;
+ Pixel rgbbad;
+
+ numred = NUMRED(pVisual);
+ numgreen = NUMGREEN(pVisual);
+ numblue = NUMBLUE(pVisual);
+ rgbbad = ~RGBMASK(pVisual);
+ for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++)
+ {
+ pixel = *ppix;
+ if (pixel & rgbbad) {
+ client->errorValue = pixel;
+ errVal = BadValue;
+ continue;
+ }
+ i = (pixel & pVisual->redMask) >> pVisual->offsetRed;
+ if (i >= numred)
+ {
+ client->errorValue = pixel;
+ errVal = BadValue;
+ continue;
+ }
+ prgb->red = pmap->red[i].co.local.red;
+ i = (pixel & pVisual->greenMask) >> pVisual->offsetGreen;
+ if (i >= numgreen)
+ {
+ client->errorValue = pixel;
+ errVal = BadValue;
+ continue;
+ }
+ prgb->green = pmap->green[i].co.local.green;
+ i = (pixel & pVisual->blueMask) >> pVisual->offsetBlue;
+ if (i >= numblue)
+ {
+ client->errorValue = pixel;
+ errVal = BadValue;
+ continue;
+ }
+ prgb->blue = pmap->blue[i].co.local.blue;
+ }
+ }
+ else
+ {
+ for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++)
+ {
+ pixel = *ppix;
+ if (pixel >= pVisual->ColormapEntries)
+ {
+ client->errorValue = pixel;
+ errVal = BadValue;
+ }
+ else
+ {
+ pent = (EntryPtr)&pmap->red[pixel];
+ if (pent->fShared)
+ {
+ prgb->red = pent->co.shco.red->color;
+ prgb->green = pent->co.shco.green->color;
+ prgb->blue = pent->co.shco.blue->color;
+ }
+ else
+ {
+ prgb->red = pent->co.local.red;
+ prgb->green = pent->co.local.green;
+ prgb->blue = pent->co.local.blue;
+ }
+ }
+ }
+ }
+ return errVal;
+}
+
+static void
+FreePixels(ColormapPtr pmap, int client)
+{
+ Pixel *ppix, *ppixStart;
+ int n;
+ int class;
+
+ class = pmap->class;
+ ppixStart = pmap->clientPixelsRed[client];
+ if (class & DynamicClass)
+ {
+ n = pmap->numPixelsRed[client];
+ for (ppix = ppixStart; --n >= 0; )
+ {
+ FreeCell(pmap, *ppix, REDMAP);
+ ppix++;
+ }
+ }
+
+ free(ppixStart);
+ pmap->clientPixelsRed[client] = (Pixel *) NULL;
+ pmap->numPixelsRed[client] = 0;
+ if ((class | DynamicClass) == DirectColor)
+ {
+ ppixStart = pmap->clientPixelsGreen[client];
+ if (class & DynamicClass)
+ for (ppix = ppixStart, n = pmap->numPixelsGreen[client]; --n >= 0;)
+ FreeCell(pmap, *ppix++, GREENMAP);
+ free(ppixStart);
+ pmap->clientPixelsGreen[client] = (Pixel *) NULL;
+ pmap->numPixelsGreen[client] = 0;
+
+ ppixStart = pmap->clientPixelsBlue[client];
+ if (class & DynamicClass)
+ for (ppix = ppixStart, n = pmap->numPixelsBlue[client]; --n >= 0; )
+ FreeCell(pmap, *ppix++, BLUEMAP);
+ free(ppixStart);
+ pmap->clientPixelsBlue[client] = (Pixel *) NULL;
+ pmap->numPixelsBlue[client] = 0;
+ }
+}
+
+/**
+ * Frees all of a client's colors and cells.
+ *
+ * \param value must conform to DeleteType
+ * \unused fakeid
+ */
+int
+FreeClientPixels (pointer value, XID fakeid)
+{
+ pointer pmap;
+ colorResource *pcr = value;
+ int rc;
+
+ rc = dixLookupResourceByType(&pmap, pcr->mid, RT_COLORMAP, serverClient,
+ DixRemoveAccess);
+ if (rc == Success)
+ FreePixels((ColormapPtr)pmap, pcr->client);
+ free(pcr);
+ return Success;
+}
+
+int
+AllocColorCells (int client, ColormapPtr pmap, int colors, int planes,
+ Bool contig, Pixel *ppix, Pixel *masks)
+{
+ Pixel rmask, gmask, bmask, *ppixFirst, r, g, b;
+ int n, class;
+ int ok;
+ int oldcount;
+ colorResource *pcr = (colorResource *)NULL;
+
+ class = pmap->class;
+ if (!(class & DynamicClass))
+ return BadAlloc; /* Shouldn't try on this type */
+ oldcount = pmap->numPixelsRed[client];
+ if (pmap->class == DirectColor)
+ oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client];
+ if (!oldcount && (CLIENT_ID(pmap->mid) != client))
+ {
+ pcr = malloc(sizeof(colorResource));
+ if (!pcr)
+ return BadAlloc;
+ }
+
+ if (pmap->class == DirectColor)
+ {
+ ok = AllocDirect (client, pmap, colors, planes, planes, planes,
+ contig, ppix, &rmask, &gmask, &bmask);
+ if(ok == Success)
+ {
+ for (r = g = b = 1, n = planes; --n >= 0; r += r, g += g, b += b)
+ {
+ while(!(rmask & r))
+ r += r;
+ while(!(gmask & g))
+ g += g;
+ while(!(bmask & b))
+ b += b;
+ *masks++ = r | g | b;
+ }
+ }
+ }
+ else
+ {
+ ok = AllocPseudo (client, pmap, colors, planes, contig, ppix, &rmask,
+ &ppixFirst);
+ if(ok == Success)
+ {
+ for (r = 1, n = planes; --n >= 0; r += r)
+ {
+ while(!(rmask & r))
+ r += r;
+ *masks++ = r;
+ }
+ }
+ }
+
+ /* if this is the client's first pixels in this colormap, tell the
+ * resource manager that the client has pixels in this colormap which
+ * should be freed when the client dies */
+ if ((ok == Success) && pcr)
+ {
+ pcr->mid = pmap->mid;
+ pcr->client = client;
+ if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr))
+ ok = BadAlloc;
+ } else free(pcr);
+
+ return ok;
+}
+
+
+int
+AllocColorPlanes (int client, ColormapPtr pmap, int colors,
+ int r, int g, int b, Bool contig, Pixel *pixels,
+ Pixel *prmask, Pixel *pgmask, Pixel *pbmask)
+{
+ int ok;
+ Pixel mask, *ppixFirst;
+ Pixel shift;
+ int i;
+ int class;
+ int oldcount;
+ colorResource *pcr = (colorResource *)NULL;
+
+ class = pmap->class;
+ if (!(class & DynamicClass))
+ return BadAlloc; /* Shouldn't try on this type */
+ oldcount = pmap->numPixelsRed[client];
+ if (class == DirectColor)
+ oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client];
+ if (!oldcount && (CLIENT_ID(pmap->mid) != client))
+ {
+ pcr = malloc(sizeof(colorResource));
+ if (!pcr)
+ return BadAlloc;
+ }
+
+ if (class == DirectColor)
+ {
+ ok = AllocDirect (client, pmap, colors, r, g, b, contig, pixels,
+ prmask, pgmask, pbmask);
+ }
+ else
+ {
+ /* Allocate the proper pixels */
+ /* XXX This is sort of bad, because of contig is set, we force all
+ * r + g + b bits to be contiguous. Should only force contiguity
+ * per mask
+ */
+ ok = AllocPseudo (client, pmap, colors, r + g + b, contig, pixels,
+ &mask, &ppixFirst);
+
+ if(ok == Success)
+ {
+ /* now split that mask into three */
+ *prmask = *pgmask = *pbmask = 0;
+ shift = 1;
+ for (i = r; --i >= 0; shift += shift)
+ {
+ while (!(mask & shift))
+ shift += shift;
+ *prmask |= shift;
+ }
+ for (i = g; --i >= 0; shift += shift)
+ {
+ while (!(mask & shift))
+ shift += shift;
+ *pgmask |= shift;
+ }
+ for (i = b; --i >= 0; shift += shift)
+ {
+ while (!(mask & shift))
+ shift += shift;
+ *pbmask |= shift;
+ }
+
+ /* set up the shared color cells */
+ if (!AllocShared(pmap, pixels, colors, r, g, b,
+ *prmask, *pgmask, *pbmask, ppixFirst))
+ {
+ (void)FreeColors(pmap, client, colors, pixels, mask);
+ ok = BadAlloc;
+ }
+ }
+ }
+
+ /* if this is the client's first pixels in this colormap, tell the
+ * resource manager that the client has pixels in this colormap which
+ * should be freed when the client dies */
+ if ((ok == Success) && pcr)
+ {
+ pcr->mid = pmap->mid;
+ pcr->client = client;
+ if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr))
+ ok = BadAlloc;
+ } else free(pcr);
+
+ return ok;
+}
+
+static int
+AllocDirect (int client, ColormapPtr pmap, int c, int r, int g, int b, Bool contig,
+ Pixel *pixels, Pixel *prmask, Pixel *pgmask, Pixel *pbmask)
+{
+ Pixel *ppixRed, *ppixGreen, *ppixBlue;
+ Pixel *ppix, *pDst, *p;
+ int npix, npixR, npixG, npixB;
+ Bool okR, okG, okB;
+ Pixel *rpix = 0, *gpix = 0, *bpix = 0;
+
+ npixR = c << r;
+ npixG = c << g;
+ npixB = c << b;
+ if ((r >= 32) || (g >= 32) || (b >= 32) ||
+ (npixR > pmap->freeRed) || (npixR < c) ||
+ (npixG > pmap->freeGreen) || (npixG < c) ||
+ (npixB > pmap->freeBlue) || (npixB < c))
+ return BadAlloc;
+
+ /* start out with empty pixels */
+ for(p = pixels; p < pixels + c; p++)
+ *p = 0;
+
+ ppixRed = malloc(npixR * sizeof(Pixel));
+ ppixGreen = malloc(npixG * sizeof(Pixel));
+ ppixBlue = malloc(npixB * sizeof(Pixel));
+ if (!ppixRed || !ppixGreen || !ppixBlue)
+ {
+ free(ppixBlue);
+ free(ppixGreen);
+ free(ppixRed);
+ return BadAlloc;
+ }
+
+ okR = AllocCP(pmap, pmap->red, c, r, contig, ppixRed, prmask);
+ okG = AllocCP(pmap, pmap->green, c, g, contig, ppixGreen, pgmask);
+ okB = AllocCP(pmap, pmap->blue, c, b, contig, ppixBlue, pbmask);
+
+ if (okR && okG && okB)
+ {
+ rpix = (Pixel *) realloc(pmap->clientPixelsRed[client],
+ (pmap->numPixelsRed[client] + (c << r)) *
+ sizeof(Pixel));
+ if (rpix)
+ pmap->clientPixelsRed[client] = rpix;
+ gpix = (Pixel *) realloc(pmap->clientPixelsGreen[client],
+ (pmap->numPixelsGreen[client] + (c << g)) *
+ sizeof(Pixel));
+ if (gpix)
+ pmap->clientPixelsGreen[client] = gpix;
+ bpix = (Pixel *) realloc(pmap->clientPixelsBlue[client],
+ (pmap->numPixelsBlue[client] + (c << b)) *
+ sizeof(Pixel));
+ if (bpix)
+ pmap->clientPixelsBlue[client] = bpix;
+ }
+
+ if (!okR || !okG || !okB || !rpix || !gpix || !bpix)
+ {
+ if (okR)
+ for(ppix = ppixRed, npix = npixR; --npix >= 0; ppix++)
+ pmap->red[*ppix].refcnt = 0;
+ if (okG)
+ for(ppix = ppixGreen, npix = npixG; --npix >= 0; ppix++)
+ pmap->green[*ppix].refcnt = 0;
+ if (okB)
+ for(ppix = ppixBlue, npix = npixB; --npix >= 0; ppix++)
+ pmap->blue[*ppix].refcnt = 0;
+ free(ppixBlue);
+ free(ppixGreen);
+ free(ppixRed);
+ return BadAlloc;
+ }
+
+ *prmask <<= pmap->pVisual->offsetRed;
+ *pgmask <<= pmap->pVisual->offsetGreen;
+ *pbmask <<= pmap->pVisual->offsetBlue;
+
+ ppix = rpix + pmap->numPixelsRed[client];
+ for (pDst = pixels, p = ppixRed; p < ppixRed + npixR; p++)
+ {
+ *ppix++ = *p;
+ if(p < ppixRed + c)
+ *pDst++ |= *p << pmap->pVisual->offsetRed;
+ }
+ pmap->numPixelsRed[client] += npixR;
+ pmap->freeRed -= npixR;
+
+ ppix = gpix + pmap->numPixelsGreen[client];
+ for (pDst = pixels, p = ppixGreen; p < ppixGreen + npixG; p++)
+ {
+ *ppix++ = *p;
+ if(p < ppixGreen + c)
+ *pDst++ |= *p << pmap->pVisual->offsetGreen;
+ }
+ pmap->numPixelsGreen[client] += npixG;
+ pmap->freeGreen -= npixG;
+
+ ppix = bpix + pmap->numPixelsBlue[client];
+ for (pDst = pixels, p = ppixBlue; p < ppixBlue + npixB; p++)
+ {
+ *ppix++ = *p;
+ if(p < ppixBlue + c)
+ *pDst++ |= *p << pmap->pVisual->offsetBlue;
+ }
+ pmap->numPixelsBlue[client] += npixB;
+ pmap->freeBlue -= npixB;
+
+
+ for (pDst = pixels; pDst < pixels + c; pDst++)
+ *pDst |= ALPHAMASK(pmap->pVisual);
+
+ free(ppixBlue);
+ free(ppixGreen);
+ free(ppixRed);
+
+ return Success;
+}
+
+static int
+AllocPseudo (int client, ColormapPtr pmap, int c, int r, Bool contig,
+ Pixel *pixels, Pixel *pmask, Pixel **pppixFirst)
+{
+ Pixel *ppix, *p, *pDst, *ppixTemp;
+ int npix;
+ Bool ok;
+
+ npix = c << r;
+ if ((r >= 32) || (npix > pmap->freeRed) || (npix < c))
+ return BadAlloc;
+ if(!(ppixTemp = malloc(npix * sizeof(Pixel))))
+ return BadAlloc;
+ ok = AllocCP(pmap, pmap->red, c, r, contig, ppixTemp, pmask);
+
+ if (ok)
+ {
+
+ /* all the allocated pixels are added to the client pixel list,
+ * but only the unique ones are returned to the client */
+ ppix = (Pixel *)realloc(pmap->clientPixelsRed[client],
+ (pmap->numPixelsRed[client] + npix) * sizeof(Pixel));
+ if (!ppix)
+ {
+ for (p = ppixTemp; p < ppixTemp + npix; p++)
+ pmap->red[*p].refcnt = 0;
+ return BadAlloc;
+ }
+ pmap->clientPixelsRed[client] = ppix;
+ ppix += pmap->numPixelsRed[client];
+ *pppixFirst = ppix;
+ pDst = pixels;
+ for (p = ppixTemp; p < ppixTemp + npix; p++)
+ {
+ *ppix++ = *p;
+ if(p < ppixTemp + c)
+ *pDst++ = *p;
+ }
+ pmap->numPixelsRed[client] += npix;
+ pmap->freeRed -= npix;
+ }
+ free(ppixTemp);
+ return ok ? Success : BadAlloc;
+}
+
+/* Allocates count << planes pixels from colormap pmap for client. If
+ * contig, then the plane mask is made of consecutive bits. Returns
+ * all count << pixels in the array pixels. The first count of those
+ * pixels are the unique pixels. *pMask has the mask to Or with the
+ * unique pixels to get the rest of them.
+ *
+ * Returns True iff all pixels could be allocated
+ * All cells allocated will have refcnt set to AllocPrivate and shared to FALSE
+ * (see AllocShared for why we care)
+ */
+static Bool
+AllocCP (ColormapPtr pmap, EntryPtr pentFirst, int count, int planes,
+ Bool contig, Pixel *pixels, Pixel *pMask)
+{
+ EntryPtr ent;
+ Pixel pixel, base, entries, maxp, save;
+ int dplanes, found;
+ Pixel *ppix;
+ Pixel mask;
+ Pixel finalmask;
+
+ dplanes = pmap->pVisual->nplanes;
+
+ /* Easy case. Allocate pixels only */
+ if (planes == 0)
+ {
+ /* allocate writable entries */
+ ppix = pixels;
+ ent = pentFirst;
+ pixel = 0;
+ while (--count >= 0)
+ {
+ /* Just find count unallocated cells */
+ while (ent->refcnt)
+ {
+ ent++;
+ pixel++;
+ }
+ ent->refcnt = AllocPrivate;
+ *ppix++ = pixel;
+ ent->fShared = FALSE;
+ }
+ *pMask = 0;
+ return TRUE;
+ }
+ else if (planes > dplanes)
+ {
+ return FALSE;
+ }
+
+ /* General case count pixels * 2 ^ planes cells to be allocated */
+
+ /* make room for new pixels */
+ ent = pentFirst;
+
+ /* first try for contiguous planes, since it's fastest */
+ for (mask = (((Pixel)1) << planes) - 1, base = 1, dplanes -= (planes - 1);
+ --dplanes >= 0;
+ mask += mask, base += base)
+ {
+ ppix = pixels;
+ found = 0;
+ pixel = 0;
+ entries = pmap->pVisual->ColormapEntries - mask;
+ while (pixel < entries)
+ {
+ save = pixel;
+ maxp = pixel + mask + base;
+ /* check if all are free */
+ while (pixel != maxp && ent[pixel].refcnt == 0)
+ pixel += base;
+ if (pixel == maxp)
+ {
+ /* this one works */
+ *ppix++ = save;
+ found++;
+ if (found == count)
+ {
+ /* found enough, allocate them all */
+ while (--count >= 0)
+ {
+ pixel = pixels[count];
+ maxp = pixel + mask;
+ while (1)
+ {
+ ent[pixel].refcnt = AllocPrivate;
+ ent[pixel].fShared = FALSE;
+ if (pixel == maxp)
+ break;
+ pixel += base;
+ *ppix++ = pixel;
+ }
+ }
+ *pMask = mask;
+ return TRUE;
+ }
+ }
+ pixel = save + 1;
+ if (pixel & mask)
+ pixel += mask;
+ }
+ }
+
+ dplanes = pmap->pVisual->nplanes;
+ if (contig || planes == 1 || dplanes < 3)
+ return FALSE;
+
+ /* this will be very slow for large maps, need a better algorithm */
+
+ /*
+ we can generate the smallest and largest numbers that fits in dplanes
+ bits and contain exactly planes bits set as follows. First, we need to
+ check that it is possible to generate such a mask at all.
+ (Non-contiguous masks need one more bit than contiguous masks). Then
+ the smallest such mask consists of the rightmost planes-1 bits set, then
+ a zero, then a one in position planes + 1. The formula is
+ (3 << (planes-1)) -1
+ The largest such masks consists of the leftmost planes-1 bits set, then
+ a zero, then a one bit in position dplanes-planes-1. If dplanes is
+ smaller than 32 (the number of bits in a word) then the formula is:
+ (1<<dplanes) - (1<<(dplanes-planes+1) + (1<<dplanes-planes-1)
+ If dplanes = 32, then we can't calculate (1<<dplanes) and we have
+ to use:
+ ( (1<<(planes-1)) - 1) << (dplanes-planes+1) + (1<<(dplanes-planes-1))
+
+ << Thank you, Loretta>>>
+
+ */
+
+ finalmask =
+ (((((Pixel)1)<<(planes-1)) - 1) << (dplanes-planes+1)) +
+ (((Pixel)1)<<(dplanes-planes-1));
+ for (mask = (((Pixel)3) << (planes -1)) - 1; mask <= finalmask; mask++)
+ {
+ /* next 3 magic statements count number of ones (HAKMEM #169) */
+ pixel = (mask >> 1) & 033333333333;
+ pixel = mask - pixel - ((pixel >> 1) & 033333333333);
+ if ((((pixel + (pixel >> 3)) & 030707070707) % 077) != planes)
+ continue;
+ ppix = pixels;
+ found = 0;
+ entries = pmap->pVisual->ColormapEntries - mask;
+ base = lowbit (mask);
+ for (pixel = 0; pixel < entries; pixel++)
+ {
+ if (pixel & mask)
+ continue;
+ maxp = 0;
+ /* check if all are free */
+ while (ent[pixel + maxp].refcnt == 0)
+ {
+ GetNextBitsOrBreak(maxp, mask, base);
+ }
+ if ((maxp < mask) || (ent[pixel + mask].refcnt != 0))
+ continue;
+ /* this one works */
+ *ppix++ = pixel;
+ found++;
+ if (found < count)
+ continue;
+ /* found enough, allocate them all */
+ while (--count >= 0)
+ {
+ pixel = (pixels)[count];
+ maxp = 0;
+ while (1)
+ {
+ ent[pixel + maxp].refcnt = AllocPrivate;
+ ent[pixel + maxp].fShared = FALSE;
+ GetNextBitsOrBreak(maxp, mask, base);
+ *ppix++ = pixel + maxp;
+ }
+ }
+
+ *pMask = mask;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ *
+ * \param ppixFirst First of the client's new pixels
+ */
+static Bool
+AllocShared (ColormapPtr pmap, Pixel *ppix, int c, int r, int g, int b,
+ Pixel rmask, Pixel gmask, Pixel bmask, Pixel *ppixFirst)
+{
+ Pixel *pptr, *cptr;
+ int npix, z, npixClientNew, npixShared;
+ Pixel basemask, base, bits, common;
+ SHAREDCOLOR *pshared, **ppshared, **psharedList;
+
+ npixClientNew = c << (r + g + b);
+ npixShared = (c << r) + (c << g) + (c << b);
+ psharedList = malloc(npixShared * sizeof(SHAREDCOLOR *));
+ if (!psharedList)
+ return FALSE;
+ ppshared = psharedList;
+ for (z = npixShared; --z >= 0; )
+ {
+ if (!(ppshared[z] = malloc(sizeof(SHAREDCOLOR))))
+ {
+ for (z++ ; z < npixShared; z++)
+ free(ppshared[z]);
+ return FALSE;
+ }
+ }
+ for(pptr = ppix, npix = c; --npix >= 0; pptr++)
+ {
+ basemask = ~(gmask | bmask);
+ common = *pptr & basemask;
+ if (rmask)
+ {
+ bits = 0;
+ base = lowbit (rmask);
+ while(1)
+ {
+ pshared = *ppshared++;
+ pshared->refcnt = 1 << (g + b);
+ for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
+ {
+ if ((*cptr & basemask) == (common | bits))
+ {
+ pmap->red[*cptr].fShared = TRUE;
+ pmap->red[*cptr].co.shco.red = pshared;
+ }
+ }
+ GetNextBitsOrBreak(bits, rmask, base);
+ }
+ }
+ else
+ {
+ pshared = *ppshared++;
+ pshared->refcnt = 1 << (g + b);
+ for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
+ {
+ if ((*cptr & basemask) == common)
+ {
+ pmap->red[*cptr].fShared = TRUE;
+ pmap->red[*cptr].co.shco.red = pshared;
+ }
+ }
+ }
+ basemask = ~(rmask | bmask);
+ common = *pptr & basemask;
+ if (gmask)
+ {
+ bits = 0;
+ base = lowbit (gmask);
+ while(1)
+ {
+ pshared = *ppshared++;
+ pshared->refcnt = 1 << (r + b);
+ for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
+ {
+ if ((*cptr & basemask) == (common | bits))
+ {
+ pmap->red[*cptr].co.shco.green = pshared;
+ }
+ }
+ GetNextBitsOrBreak(bits, gmask, base);
+ }
+ }
+ else
+ {
+ pshared = *ppshared++;
+ pshared->refcnt = 1 << (g + b);
+ for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
+ {
+ if ((*cptr & basemask) == common)
+ {
+ pmap->red[*cptr].co.shco.green = pshared;
+ }
+ }
+ }
+ basemask = ~(rmask | gmask);
+ common = *pptr & basemask;
+ if (bmask)
+ {
+ bits = 0;
+ base = lowbit (bmask);
+ while(1)
+ {
+ pshared = *ppshared++;
+ pshared->refcnt = 1 << (r + g);
+ for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
+ {
+ if ((*cptr & basemask) == (common | bits))
+ {
+ pmap->red[*cptr].co.shco.blue = pshared;
+ }
+ }
+ GetNextBitsOrBreak(bits, bmask, base);
+ }
+ }
+ else
+ {
+ pshared = *ppshared++;
+ pshared->refcnt = 1 << (g + b);
+ for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
+ {
+ if ((*cptr & basemask) == common)
+ {
+ pmap->red[*cptr].co.shco.blue = pshared;
+ }
+ }
+ }
+ }
+ free(psharedList);
+ return TRUE;
+}
+
+
+/** FreeColors
+ * Free colors and/or cells (probably slow for large numbers)
+ */
+int
+FreeColors (ColormapPtr pmap, int client, int count, Pixel *pixels, Pixel mask)
+{
+ int rval, result, class;
+ Pixel rmask;
+
+ class = pmap->class;
+ if (pmap->flags & AllAllocated)
+ return BadAccess;
+ if ((class | DynamicClass) == DirectColor)
+ {
+ rmask = mask & RGBMASK(pmap->pVisual);
+ result = FreeCo(pmap, client, REDMAP, count, pixels,
+ mask & pmap->pVisual->redMask);
+ /* If any of the three calls fails, we must report that, if more
+ * than one fails, it's ok that we report the last one */
+ rval = FreeCo(pmap, client, GREENMAP, count, pixels,
+ mask & pmap->pVisual->greenMask);
+ if(rval != Success)
+ result = rval;
+ rval = FreeCo(pmap, client, BLUEMAP, count, pixels,
+ mask & pmap->pVisual->blueMask);
+ if(rval != Success)
+ result = rval;
+ }
+ else
+ {
+ rmask = mask & ((((Pixel)1) << pmap->pVisual->nplanes) - 1);
+ result = FreeCo(pmap, client, PSEUDOMAP, count, pixels, rmask);
+ }
+ if ((mask != rmask) && count)
+ {
+ clients[client]->errorValue = *pixels | mask;
+ result = BadValue;
+ }
+ /* XXX should worry about removing any RT_CMAPENTRY resource */
+ return result;
+}
+
+/**
+ * Helper for FreeColors -- frees all combinations of *newpixels and mask bits
+ * which the client has allocated in channel colormap cells of pmap.
+ * doesn't change newpixels if it doesn't need to
+ *
+ * \param pmap which colormap head
+ * \param color which sub-map, eg, RED, BLUE, PSEUDO
+ * \param npixIn number of pixels passed in
+ * \param ppixIn number of base pixels
+ * \param mask mask client gave us
+ */
+static int
+FreeCo (ColormapPtr pmap, int client, int color, int npixIn, Pixel *ppixIn, Pixel mask)
+{
+ Pixel *ppixClient, pixTest;
+ int npixClient, npixNew, npix;
+ Pixel bits, base, cmask, rgbbad;
+ Pixel *pptr, *cptr;
+ int n, zapped;
+ int errVal = Success;
+ int offset, numents;
+
+ if (npixIn == 0)
+ return errVal;
+ bits = 0;
+ zapped = 0;
+ base = lowbit (mask);
+
+ switch(color)
+ {
+ case REDMAP:
+ cmask = pmap->pVisual->redMask;
+ rgbbad = ~RGBMASK(pmap->pVisual);
+ offset = pmap->pVisual->offsetRed;
+ numents = (cmask >> offset) + 1;
+ ppixClient = pmap->clientPixelsRed[client];
+ npixClient = pmap->numPixelsRed[client];
+ break;
+ case GREENMAP:
+ cmask = pmap->pVisual->greenMask;
+ rgbbad = ~RGBMASK(pmap->pVisual);
+ offset = pmap->pVisual->offsetGreen;
+ numents = (cmask >> offset) + 1;
+ ppixClient = pmap->clientPixelsGreen[client];
+ npixClient = pmap->numPixelsGreen[client];
+ break;
+ case BLUEMAP:
+ cmask = pmap->pVisual->blueMask;
+ rgbbad = ~RGBMASK(pmap->pVisual);
+ offset = pmap->pVisual->offsetBlue;
+ numents = (cmask >> offset) + 1;
+ ppixClient = pmap->clientPixelsBlue[client];
+ npixClient = pmap->numPixelsBlue[client];
+ break;
+ default: /* so compiler can see that everything gets initialized */
+ case PSEUDOMAP:
+ cmask = ~((Pixel)0);
+ rgbbad = 0;
+ offset = 0;
+ numents = pmap->pVisual->ColormapEntries;
+ ppixClient = pmap->clientPixelsRed[client];
+ npixClient = pmap->numPixelsRed[client];
+ break;
+ }
+
+
+ /* zap all pixels which match */
+ while (1)
+ {
+ /* go through pixel list */
+ for (pptr = ppixIn, n = npixIn; --n >= 0; pptr++)
+ {
+ pixTest = ((*pptr | bits) & cmask) >> offset;
+ if ((pixTest >= numents) || (*pptr & rgbbad))
+ {
+ clients[client]->errorValue = *pptr | bits;
+ errVal = BadValue;
+ continue;
+ }
+
+ /* find match in client list */
+ for (cptr = ppixClient, npix = npixClient;
+ --npix >= 0 && *cptr != pixTest;
+ cptr++) ;
+
+ if (npix >= 0)
+ {
+ if (pmap->class & DynamicClass)
+ {
+ FreeCell(pmap, pixTest, color);
+ }
+ *cptr = ~((Pixel)0);
+ zapped++;
+ }
+ else
+ errVal = BadAccess;
+ }
+ /* generate next bits value */
+ GetNextBitsOrBreak(bits, mask, base);
+ }
+
+ /* delete freed pixels from client pixel list */
+ if (zapped)
+ {
+ npixNew = npixClient - zapped;
+ if (npixNew)
+ {
+ /* Since the list can only get smaller, we can do a copy in
+ * place and then realloc to a smaller size */
+ pptr = cptr = ppixClient;
+
+ /* If we have all the new pixels, we don't have to examine the
+ * rest of the old ones */
+ for(npix = 0; npix < npixNew; cptr++)
+ {
+ if (*cptr != ~((Pixel)0))
+ {
+ *pptr++ = *cptr;
+ npix++;
+ }
+ }
+ pptr = (Pixel *)realloc(ppixClient, npixNew * sizeof(Pixel));
+ if (pptr)
+ ppixClient = pptr;
+ npixClient = npixNew;
+ }
+ else
+ {
+ npixClient = 0;
+ free(ppixClient);
+ ppixClient = (Pixel *)NULL;
+ }
+ switch(color)
+ {
+ case PSEUDOMAP:
+ case REDMAP:
+ pmap->clientPixelsRed[client] = ppixClient;
+ pmap->numPixelsRed[client] = npixClient;
+ break;
+ case GREENMAP:
+ pmap->clientPixelsGreen[client] = ppixClient;
+ pmap->numPixelsGreen[client] = npixClient;
+ break;
+ case BLUEMAP:
+ pmap->clientPixelsBlue[client] = ppixClient;
+ pmap->numPixelsBlue[client] = npixClient;
+ break;
+ }
+ }
+ return errVal;
+}
+
+
+
+/* Redefine color values */
+int
+StoreColors (ColormapPtr pmap, int count, xColorItem *defs, ClientPtr client)
+{
+ Pixel pix;
+ xColorItem *pdef;
+ EntryPtr pent, pentT, pentLast;
+ VisualPtr pVisual;
+ SHAREDCOLOR *pred, *pgreen, *pblue;
+ int n, ChgRed, ChgGreen, ChgBlue, idef;
+ int class, errVal = Success;
+ int ok;
+
+
+ class = pmap->class;
+ if(!(class & DynamicClass) && !(pmap->flags & BeingCreated))
+ {
+ return BadAccess;
+ }
+ pVisual = pmap->pVisual;
+
+ idef = 0;
+ if((class | DynamicClass) == DirectColor)
+ {
+ int numred, numgreen, numblue;
+ Pixel rgbbad;
+
+ numred = NUMRED(pVisual);
+ numgreen = NUMGREEN(pVisual);
+ numblue = NUMBLUE(pVisual);
+ rgbbad = ~RGBMASK(pVisual);
+ for (pdef = defs, n = 0; n < count; pdef++, n++)
+ {
+ ok = TRUE;
+ (*pmap->pScreen->ResolveColor)
+ (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual);
+
+ if (pdef->pixel & rgbbad)
+ {
+ errVal = BadValue;
+ client->errorValue = pdef->pixel;
+ continue;
+ }
+ pix = (pdef->pixel & pVisual->redMask) >> pVisual->offsetRed;
+ if (pix >= numred)
+ {
+ errVal = BadValue;
+ ok = FALSE;
+ }
+ else if (pmap->red[pix].refcnt != AllocPrivate)
+ {
+ errVal = BadAccess;
+ ok = FALSE;
+ }
+ else if (pdef->flags & DoRed)
+ {
+ pmap->red[pix].co.local.red = pdef->red;
+ }
+ else
+ {
+ pdef->red = pmap->red[pix].co.local.red;
+ }
+
+ pix = (pdef->pixel & pVisual->greenMask) >> pVisual->offsetGreen;
+ if (pix >= numgreen)
+ {
+ errVal = BadValue;
+ ok = FALSE;
+ }
+ else if (pmap->green[pix].refcnt != AllocPrivate)
+ {
+ errVal = BadAccess;
+ ok = FALSE;
+ }
+ else if (pdef->flags & DoGreen)
+ {
+ pmap->green[pix].co.local.green = pdef->green;
+ }
+ else
+ {
+ pdef->green = pmap->green[pix].co.local.green;
+ }
+
+ pix = (pdef->pixel & pVisual->blueMask) >> pVisual->offsetBlue;
+ if (pix >= numblue)
+ {
+ errVal = BadValue;
+ ok = FALSE;
+ }
+ else if (pmap->blue[pix].refcnt != AllocPrivate)
+ {
+ errVal = BadAccess;
+ ok = FALSE;
+ }
+ else if (pdef->flags & DoBlue)
+ {
+ pmap->blue[pix].co.local.blue = pdef->blue;
+ }
+ else
+ {
+ pdef->blue = pmap->blue[pix].co.local.blue;
+ }
+ /* If this is an o.k. entry, then it gets added to the list
+ * to be sent to the hardware. If not, skip it. Once we've
+ * skipped one, we have to copy all the others.
+ */
+ if(ok)
+ {
+ if(idef != n)
+ defs[idef] = defs[n];
+ idef++;
+ } else
+ client->errorValue = pdef->pixel;
+ }
+ }
+ else
+ {
+ for (pdef = defs, n = 0; n < count; pdef++, n++)
+ {
+
+ ok = TRUE;
+ if (pdef->pixel >= pVisual->ColormapEntries)
+ {
+ client->errorValue = pdef->pixel;
+ errVal = BadValue;
+ ok = FALSE;
+ }
+ else if (pmap->red[pdef->pixel].refcnt != AllocPrivate)
+ {
+ errVal = BadAccess;
+ ok = FALSE;
+ }
+
+ /* If this is an o.k. entry, then it gets added to the list
+ * to be sent to the hardware. If not, skip it. Once we've
+ * skipped one, we have to copy all the others.
+ */
+ if(ok)
+ {
+ if(idef != n)
+ defs[idef] = defs[n];
+ idef++;
+ }
+ else
+ continue;
+
+ (*pmap->pScreen->ResolveColor)
+ (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual);
+
+ pent = &pmap->red[pdef->pixel];
+
+ if(pdef->flags & DoRed)
+ {
+ if(pent->fShared)
+ {
+ pent->co.shco.red->color = pdef->red;
+ if (pent->co.shco.red->refcnt > 1)
+ ok = FALSE;
+ }
+ else
+ pent->co.local.red = pdef->red;
+ }
+ else
+ {
+ if(pent->fShared)
+ pdef->red = pent->co.shco.red->color;
+ else
+ pdef->red = pent->co.local.red;
+ }
+ if(pdef->flags & DoGreen)
+ {
+ if(pent->fShared)
+ {
+ pent->co.shco.green->color = pdef->green;
+ if (pent->co.shco.green->refcnt > 1)
+ ok = FALSE;
+ }
+ else
+ pent->co.local.green = pdef->green;
+ }
+ else
+ {
+ if(pent->fShared)
+ pdef->green = pent->co.shco.green->color;
+ else
+ pdef->green = pent->co.local.green;
+ }
+ if(pdef->flags & DoBlue)
+ {
+ if(pent->fShared)
+ {
+ pent->co.shco.blue->color = pdef->blue;
+ if (pent->co.shco.blue->refcnt > 1)
+ ok = FALSE;
+ }
+ else
+ pent->co.local.blue = pdef->blue;
+ }
+ else
+ {
+ if(pent->fShared)
+ pdef->blue = pent->co.shco.blue->color;
+ else
+ pdef->blue = pent->co.local.blue;
+ }
+
+ if(!ok)
+ {
+ /* have to run through the colormap and change anybody who
+ * shares this value */
+ pred = pent->co.shco.red;
+ pgreen = pent->co.shco.green;
+ pblue = pent->co.shco.blue;
+ ChgRed = pdef->flags & DoRed;
+ ChgGreen = pdef->flags & DoGreen;
+ ChgBlue = pdef->flags & DoBlue;
+ pentLast = pmap->red + pVisual->ColormapEntries;
+
+ for(pentT = pmap->red; pentT < pentLast; pentT++)
+ {
+ if(pentT->fShared && (pentT != pent))
+ {
+ xColorItem defChg;
+
+ /* There are, alas, devices in this world too dumb
+ * to read their own hardware colormaps. Sick, but
+ * true. So we're going to be really nice and load
+ * the xColorItem with the proper value for all the
+ * fields. We will only set the flags for those
+ * fields that actually change. Smart devices can
+ * arrange to change only those fields. Dumb devices
+ * can rest assured that we have provided for them,
+ * and can change all three fields */
+
+ defChg.flags = 0;
+ if(ChgRed && pentT->co.shco.red == pred)
+ {
+ defChg.flags |= DoRed;
+ }
+ if(ChgGreen && pentT->co.shco.green == pgreen)
+ {
+ defChg.flags |= DoGreen;
+ }
+ if(ChgBlue && pentT->co.shco.blue == pblue)
+ {
+ defChg.flags |= DoBlue;
+ }
+ if(defChg.flags != 0)
+ {
+ defChg.pixel = pentT - pmap->red;
+ defChg.red = pentT->co.shco.red->color;
+ defChg.green = pentT->co.shco.green->color;
+ defChg.blue = pentT->co.shco.blue->color;
+ (*pmap->pScreen->StoreColors) (pmap, 1, &defChg);
+ }
+ }
+ }
+
+ }
+ }
+ }
+ /* Note that we use idef, the count of acceptable entries, and not
+ * count, the count of proposed entries */
+ if (idef != 0)
+ ( *pmap->pScreen->StoreColors) (pmap, idef, defs);
+ return errVal;
+}
+
+int
+IsMapInstalled(Colormap map, WindowPtr pWin)
+{
+ Colormap *pmaps;
+ int imap, nummaps, found;
+
+ pmaps = malloc(pWin->drawable.pScreen->maxInstalledCmaps*sizeof(Colormap));
+ if(!pmaps)
+ return FALSE;
+ nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
+ (pWin->drawable.pScreen, pmaps);
+ found = FALSE;
+ for(imap = 0; imap < nummaps; imap++)
+ {
+ if(pmaps[imap] == map)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ free(pmaps);
+ return found;
+}
+
+struct colormap_lookup_data {
+ ScreenPtr pScreen;
+ VisualPtr visuals;
+};
+
+static void _colormap_find_resource(pointer value, XID id,
+ pointer cdata)
+{
+ struct colormap_lookup_data *cmap_data = cdata;
+ VisualPtr visuals = cmap_data->visuals;
+ ScreenPtr pScreen = cmap_data->pScreen;
+ ColormapPtr cmap = value;
+ int j;
+
+ if (pScreen != cmap->pScreen)
+ return;
+
+ j = cmap->pVisual - pScreen->visuals;
+ cmap->pVisual = &visuals[j];
+}
+
+/* something has realloced the visuals, instead of breaking
+ ABI fix it up here - glx and compsite did this wrong */
+Bool
+ResizeVisualArray(ScreenPtr pScreen, int new_visual_count,
+ DepthPtr depth)
+{
+ struct colormap_lookup_data cdata;
+ int numVisuals;
+ VisualPtr visuals;
+ XID *vids, vid;
+ int first_new_vid, first_new_visual, i;
+
+ first_new_vid = depth->numVids;
+ first_new_visual = pScreen->numVisuals;
+
+ vids = realloc(depth->vids, (depth->numVids + new_visual_count) * sizeof(XID));
+ if (!vids)
+ return FALSE;
+
+ /* its realloced now no going back if we fail the next one */
+ depth->vids = vids;
+
+ numVisuals = pScreen->numVisuals + new_visual_count;
+ visuals = realloc(pScreen->visuals, numVisuals * sizeof(VisualRec));
+ if (!visuals) {
+ return FALSE;
+ }
+
+ cdata.visuals = visuals;
+ cdata.pScreen = pScreen;
+ FindClientResourcesByType(serverClient, RT_COLORMAP, _colormap_find_resource, &cdata);
+
+ pScreen->visuals = visuals;
+
+ for (i = 0; i < new_visual_count; i++) {
+ vid = FakeClientID(0);
+ pScreen->visuals[first_new_visual + i].vid = vid;
+ vids[first_new_vid + i] = vid;
+ }
+
+ depth->numVids += new_visual_count;
+ pScreen->numVisuals += new_visual_count;
+
+ return TRUE;
+}
diff --git a/xorg-server/dix/cursor.c b/xorg-server/dix/cursor.c
index c8253bba0..acd118a1c 100644
--- a/xorg-server/dix/cursor.c
+++ b/xorg-server/dix/cursor.c
@@ -72,6 +72,8 @@ typedef struct _GlyphShare {
static GlyphSharePtr sharedGlyphs = (GlyphSharePtr)NULL;
+DevPrivateKeyRec cursorScreenDevPriv[MAXSCREENS];
+
#ifdef XFIXES
static CARD32 cursorSerial;
#endif
@@ -86,8 +88,7 @@ FreeCursorBits(CursorBitsPtr bits)
#ifdef ARGB_CURSOR
free(bits->argb);
#endif
- dixFreePrivates(bits->devPrivates);
- bits->devPrivates = NULL;
+ dixFiniPrivates(bits, PRIVATE_CURSOR_BITS);
if (bits->refcnt == 0)
{
GlyphSharePtr *prev, this;
@@ -121,17 +122,17 @@ FreeCursor(pointer value, XID cid)
DeviceIntPtr pDev = NULL; /* unused anyway */
if ( --pCurs->refcnt != 0)
- return(Success);
+ return Success;
for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
{
pscr = screenInfo.screens[nscr];
(void)( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
}
- dixFreePrivates(pCurs->devPrivates);
FreeCursorBits(pCurs->bits);
+ dixFiniPrivates(pCurs, PRIVATE_CURSOR);
free( pCurs);
- return(Success);
+ return Success;
}
@@ -217,6 +218,7 @@ RealizeCursorAllScreens(CursorPtr pCurs)
return Success;
}
+
/**
* does nothing about the resource table, just creates the data structure.
* does not copy the src and mask bits
@@ -237,14 +239,16 @@ AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits,
int rc;
*ppCurs = NULL;
- pCurs = (CursorPtr)calloc(sizeof(CursorRec) + sizeof(CursorBits), 1);
+ pCurs = (CursorPtr)calloc(CURSOR_REC_SIZE + CURSOR_BITS_SIZE, 1);
if (!pCurs)
{
free(psrcbits);
free(pmaskbits);
return BadAlloc;
}
- bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec));
+ bits = (CursorBitsPtr)((char *)pCurs + CURSOR_REC_SIZE);
+ dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR);
+ dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS)
bits->source = psrcbits;
bits->mask = pmaskbits;
#ifdef ARGB_CURSOR
@@ -255,7 +259,6 @@ AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits,
bits->xhot = cm->xhot;
bits->yhot = cm->yhot;
pCurs->refcnt = 1;
- bits->devPrivates = NULL;
bits->refcnt = -1;
CheckForEmptyMask(bits);
pCurs->bits = bits;
@@ -273,7 +276,6 @@ AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits,
pCurs->backBlue = backBlue;
pCurs->id = cid;
- pCurs->devPrivates = NULL;
/* security creation/labeling check */
rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR,
@@ -289,8 +291,8 @@ AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits,
return Success;
error:
- dixFreePrivates(pCurs->devPrivates);
FreeCursorBits(bits);
+ dixFiniPrivates(pCurs, PRIVATE_CURSOR);
free(pCurs);
return rc;
@@ -339,9 +341,10 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
}
if (pShare)
{
- pCurs = (CursorPtr)calloc(sizeof(CursorRec), 1);
+ pCurs = (CursorPtr)calloc(CURSOR_REC_SIZE, 1);
if (!pCurs)
return BadAlloc;
+ dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR);
bits = pShare->bits;
bits->refcnt++;
}
@@ -382,17 +385,17 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
if (sourcefont != maskfont)
{
pCurs =
- (CursorPtr)calloc(sizeof(CursorRec) + sizeof(CursorBits), 1);
+ (CursorPtr)calloc(CURSOR_REC_SIZE + CURSOR_BITS_SIZE, 1);
if (pCurs)
- bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec));
+ bits = (CursorBitsPtr)((char *)pCurs + CURSOR_REC_SIZE);
else
bits = (CursorBitsPtr)NULL;
}
else
{
- pCurs = (CursorPtr)calloc(sizeof(CursorRec), 1);
+ pCurs = (CursorPtr)calloc(CURSOR_REC_SIZE, 1);
if (pCurs)
- bits = (CursorBitsPtr)calloc(sizeof(CursorBits), 1);
+ bits = (CursorBitsPtr)calloc(CURSOR_BITS_SIZE, 1);
else
bits = (CursorBitsPtr)NULL;
}
@@ -403,6 +406,8 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
free(srcbits);
return BadAlloc;
}
+ dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR);
+ dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS);
bits->source = srcbits;
bits->mask = mskbits;
#ifdef ARGB_CURSOR
@@ -412,7 +417,6 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
bits->height = cm.height;
bits->xhot = cm.xhot;
bits->yhot = cm.yhot;
- bits->devPrivates = NULL;
if (sourcefont != maskfont)
bits->refcnt = -1;
else
@@ -451,7 +455,6 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
pCurs->backBlue = backBlue;
pCurs->id = cid;
- pCurs->devPrivates = NULL;
/* security creation/labeling check */
rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR,
@@ -467,8 +470,8 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
return Success;
error:
- dixFreePrivates(pCurs->devPrivates);
FreeCursorBits(bits);
+ dixFiniPrivates(pCurs, PRIVATE_CURSOR);
free(pCurs);
return rc;
diff --git a/xorg-server/dix/devices.c b/xorg-server/dix/devices.c
index 85a008004..9c9ca5496 100644
--- a/xorg-server/dix/devices.c
+++ b/xorg-server/dix/devices.c
@@ -77,6 +77,8 @@ SOFTWARE.
#include <X11/extensions/XI.h>
#include <X11/extensions/XI2.h>
#include <X11/extensions/XIproto.h>
+#include <math.h>
+#include <pixman.h>
#include "exglobals.h"
#include "exevents.h"
#include "xiquerydevice.h" /* for SizeDeviceClasses */
@@ -91,6 +93,48 @@ SOFTWARE.
static void RecalculateMasterButtons(DeviceIntPtr slave);
+static void
+DeviceSetTransform(DeviceIntPtr dev, float *transform)
+{
+ struct pixman_f_transform scale;
+ double sx, sy;
+ int x, y;
+
+ /**
+ * calculate combined transformation matrix:
+ *
+ * M = InvScale * Transform * Scale
+ *
+ * So we can later transform points using M * p
+ *
+ * Where:
+ * Scale scales coordinates into 0..1 range
+ * Transform is the user supplied (affine) transform
+ * InvScale scales coordinates back up into their native range
+ */
+ sx = dev->valuator->axes[0].max_value - dev->valuator->axes[0].min_value;
+ sy = dev->valuator->axes[1].max_value - dev->valuator->axes[1].min_value;
+
+ /* invscale */
+ pixman_f_transform_init_scale(&scale, sx, sy);
+ scale.m[0][2] = dev->valuator->axes[0].min_value;
+ scale.m[1][2] = dev->valuator->axes[1].min_value;
+
+ /* transform */
+ for (y=0; y<3; y++)
+ for (x=0; x<3; x++)
+ dev->transform.m[y][x] = *transform++;
+
+ pixman_f_transform_multiply(&dev->transform, &scale, &dev->transform);
+
+ /* scale */
+ pixman_f_transform_init_scale(&scale, 1.0 / sx, 1.0 / sy);
+ scale.m[0][2] = -dev->valuator->axes[0].min_value / sx;
+ scale.m[1][2] = -dev->valuator->axes[1].min_value / sy;
+
+ pixman_f_transform_multiply(&dev->transform, &dev->transform, &scale);
+}
+
/**
* DIX property handler.
*/
@@ -115,6 +159,21 @@ DeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
else if (!(*((CARD8*)prop->data)) && dev->enabled)
DisableDevice(dev, TRUE);
}
+ } else if (property == XIGetKnownProperty(XI_PROP_TRANSFORM))
+ {
+ float *f = (float*)prop->data;
+ int i;
+
+ if (prop->format != 32 || prop->size != 9 ||
+ prop->type != XIGetKnownProperty(XATOM_FLOAT))
+ return BadValue;
+
+ for (i=0; i<9; i++)
+ if (!isfinite(f[i]))
+ return BadValue;
+
+ if (!checkonly)
+ DeviceSetTransform(dev, f);
}
return Success;
@@ -183,6 +242,7 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
int devid;
char devind[MAXDEVICES];
BOOL enabled;
+ float transform[9];
/* Find next available id, 0 and 1 are reserved */
memset(devind, 0, sizeof(char)*MAXDEVICES);
@@ -195,7 +255,9 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
if (devid >= MAXDEVICES)
return (DeviceIntPtr)NULL;
- dev = calloc(sizeof(DeviceIntRec) + sizeof(SpriteInfoRec), 1);
+ dev = _dixAllocateObjectWithPrivates(sizeof(DeviceIntRec) + sizeof(SpriteInfoRec),
+ sizeof(DeviceIntRec) + sizeof(SpriteInfoRec),
+ offsetof(DeviceIntRec, devPrivates), PRIVATE_DEVICE);
if (!dev)
return (DeviceIntPtr)NULL;
dev->id = devid;
@@ -234,6 +296,17 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
XA_INTEGER, 8, PropModeReplace, 1, &enabled,
FALSE);
XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_ENABLED), FALSE);
+
+ /* unity matrix */
+ memset(transform, 0, sizeof(transform));
+ transform[0] = transform[4] = transform[8] = 1.0f;
+
+ XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_TRANSFORM),
+ XIGetKnownProperty(XATOM_FLOAT), 32,
+ PropModeReplace, 9, transform, FALSE);
+ XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_TRANSFORM),
+ FALSE);
+
XIRegisterPropertyHandler(dev, DeviceSetProperty, NULL, NULL);
return dev;
@@ -289,9 +362,9 @@ EnableDevice(DeviceIntPtr dev, BOOL sendevent)
/* Sprites appear on first root window, so we can hardcode it */
if (dev->spriteInfo->spriteOwner)
{
- InitializeSprite(dev, WindowTable[0]);
+ InitializeSprite(dev, screenInfo.screens[0]->root);
/* mode doesn't matter */
- EnterWindow(dev, WindowTable[0], NotifyAncestor);
+ EnterWindow(dev, screenInfo.screens[0]->root, NotifyAncestor);
}
else if ((other = NextFreePointerDevice()) == NULL)
{
@@ -667,8 +740,7 @@ FreeDeviceClass(int type, pointer *class)
case ButtonClass:
{
ButtonClassPtr *b = (ButtonClassPtr*)class;
- if ((*b)->xkb_acts)
- free((*b)->xkb_acts);
+ free((*b)->xkb_acts);
free((*b));
break;
}
@@ -676,8 +748,7 @@ FreeDeviceClass(int type, pointer *class)
{
ValuatorClassPtr *v = (ValuatorClassPtr*)class;
- if ((*v)->motion)
- free((*v)->motion);
+ free((*v)->motion);
free((*v));
break;
}
@@ -865,8 +936,7 @@ CloseDevice(DeviceIntPtr dev)
}
free(dev->deviceGrab.sync.event);
- dixFreePrivates(dev->devPrivates);
- free(dev);
+ dixFreeObjectWithPrivates(dev, PRIVATE_DEVICE);
}
/**
@@ -1393,10 +1463,8 @@ InitStringFeedbackClassDeviceStruct (
feedc->ctrl.symbols_displayed = malloc(sizeof (KeySym) * max_symbols);
if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed)
{
- if (feedc->ctrl.symbols_supported)
- free(feedc->ctrl.symbols_supported);
- if (feedc->ctrl.symbols_displayed)
- free(feedc->ctrl.symbols_displayed);
+ free(feedc->ctrl.symbols_supported);
+ free(feedc->ctrl.symbols_displayed);
free(feedc);
return FALSE;
}
@@ -1950,7 +2018,7 @@ ProcChangeKeyboardControl (ClientPtr client)
keyboard = PickKeyboard(client);
for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
- if ((pDev == keyboard || (!IsMaster(keyboard) && pDev->u.master == keyboard)) &&
+ if ((pDev == keyboard || (!IsMaster(pDev) && pDev->u.master == keyboard)) &&
pDev->kbdfeed && pDev->kbdfeed->CtrlProc) {
ret = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
if (ret != Success)
@@ -1959,7 +2027,7 @@ ProcChangeKeyboardControl (ClientPtr client)
}
for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
- if ((pDev == keyboard || (!IsMaster(keyboard) && pDev->u.master == keyboard)) &&
+ if ((pDev == keyboard || (!IsMaster(pDev) && pDev->u.master == keyboard)) &&
pDev->kbdfeed && pDev->kbdfeed->CtrlProc) {
ret = DoChangeKeyboardControl(client, pDev, vlist, vmask);
if (ret != Success)
@@ -2049,11 +2117,11 @@ ProcChangePointerControl(ClientPtr client)
ctrl = mouse->ptrfeed->ctrl;
if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) {
client->errorValue = stuff->doAccel;
- return(BadValue);
+ return BadValue;
}
if ((stuff->doThresh != xTrue) && (stuff->doThresh != xFalse)) {
client->errorValue = stuff->doThresh;
- return(BadValue);
+ return BadValue;
}
if (stuff->doAccel) {
if (stuff->accelNum == -1) {
@@ -2211,8 +2279,7 @@ ProcGetMotionEvents(ClientPtr client)
WriteSwappedDataToClient(client, nEvents * sizeof(xTimecoord),
(char *)coords);
}
- if (coords)
- free(coords);
+ free(coords);
return Success;
}
@@ -2364,7 +2431,7 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
if (dev->spriteInfo->sprite)
currentRoot = dev->spriteInfo->sprite->spriteTrace[0];
else /* new device auto-set to floating */
- currentRoot = WindowTable[0];
+ currentRoot = screenInfo.screens[0]->root;
/* we need to init a fake sprite */
screen = currentRoot->drawable.pScreen;
diff --git a/xorg-server/dix/dispatch.c b/xorg-server/dix/dispatch.c
index a14853624..7d5b8ecbf 100644
--- a/xorg-server/dix/dispatch.c
+++ b/xorg-server/dix/dispatch.c
@@ -562,7 +562,7 @@ CreateConnectionBlock(void)
VisualPtr pVisual;
pScreen = screenInfo.screens[i];
- root.windowId = WindowTable[i]->drawable.id;
+ root.windowId = pScreen->root->drawable.id;
root.defaultColormap = pScreen->defColormap;
root.whitePixel = pScreen->whitePixel;
root.blackPixel = pScreen->blackPixel;
@@ -631,7 +631,7 @@ CreateConnectionBlock(void)
int
ProcBadRequest(ClientPtr client)
{
- return (BadRequest);
+ return BadRequest;
}
int
@@ -912,7 +912,7 @@ GetGeometry(ClientPtr client, xGetGeometryReply *rep)
rep->type = X_Reply;
rep->length = 0;
rep->sequenceNumber = client->sequence;
- rep->root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
+ rep->root = pDraw->pScreen->root->drawable.id;
rep->depth = pDraw->depth;
rep->width = pDraw->width;
rep->height = pDraw->height;
@@ -972,7 +972,7 @@ ProcQueryTree(ClientPtr client)
return rc;
memset(&reply, 0, sizeof(xQueryTreeReply));
reply.type = X_Reply;
- reply.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
+ reply.root = pWin->drawable.pScreen->root->drawable.id;
reply.sequenceNumber = client->sequence;
if (pWin->parent)
reply.parent = pWin->parent->drawable.id;
@@ -1017,7 +1017,7 @@ ProcInternAtom(ClientPtr client)
if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse))
{
client->errorValue = stuff->onlyIfExists;
- return(BadValue);
+ return BadValue;
}
tchar = (char *) &stuff[1];
atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists);
@@ -1033,7 +1033,7 @@ ProcInternAtom(ClientPtr client)
return Success;
}
else
- return (BadAlloc);
+ return BadAlloc;
}
int
@@ -1060,7 +1060,7 @@ ProcGetAtomName(ClientPtr client)
else
{
client->errorValue = stuff->id;
- return (BadAtom);
+ return BadAtom;
}
}
@@ -1179,14 +1179,12 @@ ProcTranslateCoords(ClientPtr client)
* borderSize
*/
&& (!wBoundingShape(pWin) ||
- POINT_IN_REGION(pWin->drawable.pScreen,
- &pWin->borderSize, x, y, &box))
+ RegionContainsPoint(&pWin->borderSize, x, y, &box))
&& (!wInputShape(pWin) ||
- POINT_IN_REGION(pWin->drawable.pScreen,
- wInputShape(pWin),
- x - pWin->drawable.x,
- y - pWin->drawable.y, &box))
+ RegionContainsPoint(wInputShape(pWin),
+ x - pWin->drawable.x,
+ y - pWin->drawable.y, &box))
)
{
rep.child = pWin->drawable.id;
@@ -1277,7 +1275,7 @@ ProcQueryFont(ClientPtr client)
reply = calloc(1, rlength);
if(!reply)
{
- return(BadAlloc);
+ return BadAlloc;
}
reply->type = X_Reply;
@@ -1311,11 +1309,11 @@ ProcQueryTextExtents(ClientPtr client)
if (stuff->oddLength)
{
if (length == 0)
- return(BadLength);
+ return BadLength;
length--;
}
if (!QueryTextExtents(pFont, length, (unsigned char *)&stuff[1], &info))
- return(BadAlloc);
+ return BadAlloc;
reply.type = X_Reply;
reply.length = 0;
reply.sequenceNumber = client->sequence;
@@ -1432,7 +1430,7 @@ CreatePmap:
return Success;
(*pDraw->pScreen->DestroyPixmap)(pMap);
}
- return (BadAlloc);
+ return BadAlloc;
}
int
@@ -1482,7 +1480,7 @@ ProcCreateGC(ClientPtr client)
if (error != Success)
return error;
if (!AddResource(stuff->gc, RT_GC, (pointer)pGC))
- return (BadAlloc);
+ return BadAlloc;
return Success;
}
@@ -1522,7 +1520,7 @@ ProcCopyGC(ClientPtr client)
if (result != Success)
return result;
if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth))
- return (BadMatch);
+ return BadMatch;
if (stuff->mask & ~GCAllBits)
{
client->errorValue = stuff->mask;
@@ -1576,7 +1574,7 @@ ProcSetClipRectangles(ClientPtr client)
nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq);
if (nr & 4)
- return(BadLength);
+ return BadLength;
nr >>= 3;
return SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin,
nr, (xRectangle *)&stuff[1], (int)stuff->ordering);
@@ -1612,12 +1610,12 @@ ProcClearToBackground(ClientPtr client)
if (pWin->drawable.class == InputOnly)
{
client->errorValue = stuff->window;
- return (BadMatch);
+ return BadMatch;
}
if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse))
{
client->errorValue = stuff->exposures;
- return(BadValue);
+ return BadValue;
}
(*pWin->drawable.pScreen->ClearToBackground)(pWin, stuff->x, stuff->y,
stuff->width, stuff->height,
@@ -1647,7 +1645,7 @@ ProcCopyArea(ClientPtr client)
if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth))
{
client->errorValue = stuff->dstDrawable;
- return (BadMatch);
+ return BadMatch;
}
}
else
@@ -1661,7 +1659,7 @@ ProcCopyArea(ClientPtr client)
(*pDst->pScreen->SendGraphicsExpose)
(client, pRgn, stuff->dstDrawable, X_CopyArea, 0);
if (pRgn)
- REGION_DESTROY(pDst->pScreen, pRgn);
+ RegionDestroy(pRgn);
}
return Success;
@@ -1689,7 +1687,7 @@ ProcCopyPlane(ClientPtr client)
if (pdstDraw->pScreen != psrcDraw->pScreen)
{
client->errorValue = stuff->dstDrawable;
- return (BadMatch);
+ return BadMatch;
}
}
else
@@ -1700,7 +1698,7 @@ ProcCopyPlane(ClientPtr client)
(stuff->bitPlane > (1L << (psrcDraw->depth - 1))))
{
client->errorValue = stuff->bitPlane;
- return(BadValue);
+ return BadValue;
}
pRgn = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, stuff->srcX, stuff->srcY,
@@ -1711,7 +1709,7 @@ ProcCopyPlane(ClientPtr client)
(*pdstDraw->pScreen->SendGraphicsExpose)
(client, pRgn, stuff->dstDrawable, X_CopyPlane, 0);
if (pRgn)
- REGION_DESTROY(pdstDraw->pScreen, pRgn);
+ RegionDestroy(pRgn);
}
return Success;
}
@@ -1774,7 +1772,7 @@ ProcPolySegment(ClientPtr client)
VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq);
if (nsegs & 4)
- return(BadLength);
+ return BadLength;
nsegs >>= 3;
if (nsegs)
(*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]);
@@ -1793,7 +1791,7 @@ ProcPolyRectangle (ClientPtr client)
VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq);
if (nrects & 4)
- return(BadLength);
+ return BadLength;
nrects >>= 3;
if (nrects)
(*pGC->ops->PolyRectangle)(pDraw, pGC,
@@ -1813,7 +1811,7 @@ ProcPolyArc(ClientPtr client)
VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
narcs = (client->req_len << 2) - sizeof(xPolyArcReq);
if (narcs % sizeof(xArc))
- return(BadLength);
+ return BadLength;
narcs /= sizeof(xArc);
if (narcs)
(*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]);
@@ -1863,7 +1861,7 @@ ProcPolyFillRectangle(ClientPtr client)
VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq);
if (things & 4)
- return(BadLength);
+ return BadLength;
things >>= 3;
if (things)
@@ -1884,7 +1882,7 @@ ProcPolyFillArc(ClientPtr client)
VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
if (narcs % sizeof(xArc))
- return(BadLength);
+ return BadLength;
narcs /= sizeof(xArc);
if (narcs)
(*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
@@ -2021,7 +2019,7 @@ DoGetImage(ClientPtr client, int format, Drawable drawable,
if ((format != XYPixmap) && (format != ZPixmap))
{
client->errorValue = format;
- return(BadValue);
+ return BadValue;
}
rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess);
if (rc != Success)
@@ -2055,7 +2053,7 @@ DoGetImage(ClientPtr client, int format, Drawable drawable,
}
else
{
- pBoundingDraw = (DrawablePtr)WindowTable[pDraw->pScreen->myNum];
+ pBoundingDraw = (DrawablePtr)pDraw->pScreen->root;
}
xgi.visual = wVisual (pWin);
@@ -2105,7 +2103,7 @@ DoGetImage(ClientPtr client, int format, Drawable drawable,
if (im_return) {
pBuf = calloc(1, sz_xGetImageReply + length);
if (!pBuf)
- return (BadAlloc);
+ return BadAlloc;
if (widthBytesLine == 0)
linesPerBuf = 0;
else
@@ -2142,7 +2140,7 @@ DoGetImage(ClientPtr client, int format, Drawable drawable,
}
}
if(!(pBuf = calloc(1, length)))
- return (BadAlloc);
+ return BadAlloc;
WriteReplyToClient(client, sizeof (xGetImageReply), &xgi);
}
@@ -2151,8 +2149,7 @@ DoGetImage(ClientPtr client, int format, Drawable drawable,
pVisibleRegion = NotClippedByChildren((WindowPtr)pDraw);
if (pVisibleRegion)
{
- REGION_TRANSLATE(pDraw->pScreen, pVisibleRegion,
- -pDraw->x, -pDraw->y);
+ RegionTranslate(pVisibleRegion, -pDraw->x, -pDraw->y);
}
}
@@ -2240,7 +2237,7 @@ DoGetImage(ClientPtr client, int format, Drawable drawable,
}
}
if (pVisibleRegion)
- REGION_DESTROY(pDraw->pScreen, pVisibleRegion);
+ RegionDestroy(pVisibleRegion);
if (!im_return)
free(pBuf);
return Success;
@@ -2365,7 +2362,7 @@ ProcCreateColormap(ClientPtr client)
if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll))
{
client->errorValue = stuff->alloc;
- return(BadValue);
+ return BadValue;
}
mid = stuff->mid;
LEGAL_NEW_RESOURCE(mid, client);
@@ -2384,7 +2381,7 @@ ProcCreateColormap(ClientPtr client)
(int)stuff->alloc, client->index);
}
client->errorValue = stuff->visual;
- return(BadMatch);
+ return BadMatch;
}
int
@@ -2510,7 +2507,7 @@ ProcListInstalledColormaps(ClientPtr client)
pWin->drawable.pScreen->maxInstalledCmaps *
sizeof(Colormap));
if(!preply)
- return(BadAlloc);
+ return BadAlloc;
preply->type = X_Reply;
preply->sequenceNumber = client->sequence;
@@ -2598,7 +2595,7 @@ ProcAllocNamedColor (ClientPtr client)
return Success;
}
else
- return(BadName);
+ return BadName;
}
else
@@ -2629,18 +2626,18 @@ ProcAllocColorCells (ClientPtr client)
if (!npixels)
{
client->errorValue = npixels;
- return (BadValue);
+ return BadValue;
}
if (stuff->contiguous != xTrue && stuff->contiguous != xFalse)
{
client->errorValue = stuff->contiguous;
- return (BadValue);
+ return BadValue;
}
nmasks = stuff->planes;
length = ((long)npixels + (long)nmasks) * sizeof(Pixel);
ppixels = malloc(length);
if(!ppixels)
- return(BadAlloc);
+ return BadAlloc;
pmasks = ppixels + npixels;
if( (rc = AllocColorCells(client->index, pcmp, npixels, nmasks,
@@ -2693,12 +2690,12 @@ ProcAllocColorPlanes(ClientPtr client)
if (!npixels)
{
client->errorValue = npixels;
- return (BadValue);
+ return BadValue;
}
if (stuff->contiguous != xTrue && stuff->contiguous != xFalse)
{
client->errorValue = stuff->contiguous;
- return (BadValue);
+ return BadValue;
}
acpr.type = X_Reply;
acpr.sequenceNumber = client->sequence;
@@ -2706,7 +2703,7 @@ ProcAllocColorPlanes(ClientPtr client)
length = (long)npixels * sizeof(Pixel);
ppixels = malloc(length);
if(!ppixels)
- return(BadAlloc);
+ return BadAlloc;
if( (rc = AllocColorPlanes(client->index, pcmp, npixels,
(int)stuff->red, (int)stuff->green, (int)stuff->blue,
(Bool)stuff->contiguous, ppixels,
@@ -2749,7 +2746,7 @@ ProcFreeColors(ClientPtr client)
int count;
if(pcmp->flags & AllAllocated)
- return(BadAccess);
+ return BadAccess;
count = bytes_to_int32((client->req_len << 2) - sizeof(xFreeColorsReq));
return FreeColors(pcmp, client->index, count,
(Pixel *)&stuff[1], (Pixel)stuff->planeMask);
@@ -2777,7 +2774,7 @@ ProcStoreColors (ClientPtr client)
count = (client->req_len << 2) - sizeof(xStoreColorsReq);
if (count % sizeof(xColorItem))
- return(BadLength);
+ return BadLength;
count /= sizeof(xColorItem);
return StoreColors(pcmp, count, (xColorItem *)&stuff[1], client);
}
@@ -2809,7 +2806,7 @@ ProcStoreNamedColor (ClientPtr client)
def.pixel = stuff->pixel;
return StoreColors(pcmp, 1, &def, client);
}
- return (BadName);
+ return BadName;
}
else
{
@@ -2837,10 +2834,10 @@ ProcQueryColors(ClientPtr client)
count = bytes_to_int32((client->req_len << 2) - sizeof(xQueryColorsReq));
prgbs = calloc(1, count * sizeof(xrgb));
if(!prgbs && count)
- return(BadAlloc);
+ return BadAlloc;
if( (rc = QueryColors(pcmp, count, (Pixel *)&stuff[1], prgbs, client)) )
{
- if (prgbs) free(prgbs);
+ free(prgbs);
return rc;
}
memset(&qcr, 0, sizeof(xQueryColorsReply));
@@ -2854,7 +2851,7 @@ ProcQueryColors(ClientPtr client)
client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend;
WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs);
}
- if (prgbs) free(prgbs);
+ free(prgbs);
return Success;
}
@@ -2895,7 +2892,7 @@ ProcLookupColor(ClientPtr client)
WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr);
return Success;
}
- return (BadName);
+ return BadName;
}
else
{
@@ -2943,24 +2940,24 @@ ProcCreateCursor (ClientPtr client)
|| src->drawable.height != msk->drawable.height
|| src->drawable.depth != 1
|| msk->drawable.depth != 1)
- return (BadMatch);
+ return BadMatch;
width = src->drawable.width;
height = src->drawable.height;
if ( stuff->x > width
|| stuff->y > height )
- return (BadMatch);
+ return BadMatch;
n = BitmapBytePad(width)*height;
srcbits = calloc(1, n);
if (!srcbits)
- return (BadAlloc);
+ return BadAlloc;
mskbits = malloc(n);
if (!mskbits)
{
free(srcbits);
- return (BadAlloc);
+ return BadAlloc;
}
(* src->drawable.pScreen->GetImage)( (DrawablePtr)src, 0, 0, width, height,
@@ -2974,7 +2971,7 @@ ProcCreateCursor (ClientPtr client)
else
{
/* zeroing the (pad) bits helps some ddx cursor handling */
- bzero((char *)mskbits, n);
+ memset((char *)mskbits, 0, n);
(* msk->drawable.pScreen->GetImage)( (DrawablePtr)msk, 0, 0, width,
height, XYPixmap, 1, (pointer)mskbits);
}
@@ -3056,7 +3053,7 @@ ProcQueryBestSize (ClientPtr client)
(stuff->class != StippleShape))
{
client->errorValue = stuff->class;
- return(BadValue);
+ return BadValue;
}
rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
@@ -3064,7 +3061,7 @@ ProcQueryBestSize (ClientPtr client)
if (rc != Success)
return rc;
if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW)
- return (BadMatch);
+ return BadMatch;
pScreen = pDraw->pScreen;
rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess);
if (rc != Success)
@@ -3204,7 +3201,7 @@ ProcListHosts(ClientPtr client)
result = GetHosts(&pdata, &nHosts, &len, &reply.enabled);
if (result != Success)
- return(result);
+ return result;
reply.type = X_Reply;
reply.sequenceNumber = client->sequence;
reply.nHosts = nHosts;
@@ -3279,7 +3276,7 @@ ProcKillClient(ClientPtr client)
* doesn't try to touch client
*/
isItTimeToYield = TRUE;
- return (Success);
+ return Success;
}
return Success;
}
@@ -3305,12 +3302,12 @@ ProcSetFontPath(ClientPtr client)
while (--nfonts >= 0)
{
if ((total == 0) || (total < (n = (*ptr + 1))))
- return(BadLength);
+ return BadLength;
total -= n;
ptr += n;
}
if (total >= 4)
- return(BadLength);
+ return BadLength;
return SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1]);
}
@@ -3359,7 +3356,7 @@ ProcChangeCloseDownMode(ClientPtr client)
else
{
client->errorValue = stuff->mode;
- return (BadValue);
+ return BadValue;
}
}
@@ -3498,8 +3495,7 @@ CloseDownClient(ClientPtr client)
nextFreeClientID = client->index;
clients[client->index] = NullClient;
SmartLastClient = NullClient;
- dixFreePrivates(client->devPrivates);
- free(client);
+ dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
while (!clients[currentMaxClients-1])
currentMaxClients--;
@@ -3520,7 +3516,6 @@ KillAllClients(void)
void InitClient(ClientPtr client, int i, pointer ospriv)
{
- memset(client, 0, sizeof(*client));
client->index = i;
client->clientAsMask = ((Mask)i) << CLIENTOFFSET;
client->closeDownMode = i ? DestroyAll : RetainPermanent;
@@ -3548,13 +3543,13 @@ ClientPtr NextAvailableClient(pointer ospriv)
i = nextFreeClientID;
if (i == MAXCLIENTS)
return (ClientPtr)NULL;
- clients[i] = client = malloc(sizeof(ClientRec));
+ clients[i] = client = dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT);
if (!client)
return (ClientPtr)NULL;
InitClient(client, i, ospriv);
if (!InitClientResources(client))
{
- free(client);
+ dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
return (ClientPtr)NULL;
}
data.reqType = 1;
@@ -3562,7 +3557,7 @@ ClientPtr NextAvailableClient(pointer ospriv)
if (!InsertFakeRequest(client, (char *)&data, sz_xReq))
{
FreeClientResources(client);
- free(client);
+ dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
return (ClientPtr)NULL;
}
if (i == currentMaxClients)
@@ -3578,7 +3573,7 @@ ClientPtr NextAvailableClient(pointer ospriv)
clientinfo.setup = (xConnSetup *) NULL;
CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
}
- return(client);
+ return client;
}
int
@@ -3590,7 +3585,7 @@ ProcInitialConnection(ClientPtr client)
prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq);
if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B'))
- return (client->noClientException = -1);
+ return client->noClientException = -1;
if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) ||
(!(*(char *) &whichbyte) && (prefix->byteOrder == 'l')))
{
@@ -3631,7 +3626,7 @@ SendConnSetup(ClientPtr client, char *reason)
else
(void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp);
(void)WriteToClient(client, (int)csp.lengthReason, reason);
- return (client->noClientException = -1);
+ return client->noClientException = -1;
}
numScreens = screenInfo.numScreens;
@@ -3666,9 +3661,9 @@ SendConnSetup(ClientPtr client, char *reason)
{
unsigned int j;
xDepth *pDepth;
+ WindowPtr pRoot = screenInfo.screens[i]->root;
- root->currentInputMask = WindowTable[i]->eventMask |
- wOtherEventMasks (WindowTable[i]);
+ root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot);
pDepth = (xDepth *)(root + 1);
for (j = 0; j < root->nDepths; j++)
{
@@ -3868,9 +3863,12 @@ AddScreen(
if (!pScreen)
return -1;
- pScreen->devPrivates = NULL;
+ if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) {
+ free (pScreen);
+ return -1;
+ }
pScreen->myNum = i;
- pScreen->totalPixmapSize = BitmapBytePad(sizeof(PixmapRec)*8);
+ pScreen->totalPixmapSize = 0; /* computed in CreateScratchPixmapForScreen */
pScreen->ClipNotify = 0; /* for R4 ddx compatibility */
pScreen->CreateScreenResources = 0;
@@ -3916,15 +3914,17 @@ AddScreen(
any of the strings pointed to by argv. They may be passed to
multiple screens.
*/
- WindowTable[i] = NullWindow;
screenInfo.screens[i] = pScreen;
screenInfo.numScreens++;
if (!(*pfnInit)(i, pScreen, argc, argv))
{
- dixFreePrivates(pScreen->devPrivates);
+ dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
free(pScreen);
screenInfo.numScreens--;
return -1;
}
+
+ dixRegisterPrivateKey(&cursorScreenDevPriv[i], PRIVATE_CURSOR, 0);
+
return i;
}
diff --git a/xorg-server/dix/dixfonts.c b/xorg-server/dix/dixfonts.c
index d6ddf04e1..d3cb8823f 100644
--- a/xorg-server/dix/dixfonts.c
+++ b/xorg-server/dix/dixfonts.c
@@ -482,7 +482,7 @@ CloseFont(pointer value, XID fid)
FontPtr pfont = (FontPtr)value;
if (pfont == NullFont)
- return (Success);
+ return Success;
if (--pfont->refcnt == 0) {
if (patternCache)
RemoveCachedFontPattern (patternCache, pfont);
@@ -504,7 +504,7 @@ CloseFont(pointer value, XID fid)
(*fpe_functions[fpe->type].close_font) (fpe, pfont);
FreeFPE(fpe);
}
- return (Success);
+ return Success;
}
@@ -677,7 +677,7 @@ doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
return TRUE;
}
if (err == FontNameAlias) {
- if (resolved) free(resolved);
+ free(resolved);
resolved = malloc(resolvedlen + 1);
if (resolved)
memmove(resolved, tmpname, resolvedlen + 1);
@@ -731,8 +731,7 @@ doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
{
c->saved = c->current;
c->haveSaved = TRUE;
- if (c->savedName)
- free(c->savedName);
+ free(c->savedName);
c->savedName = malloc(namelen + 1);
if (c->savedName)
memmove(c->savedName, name, namelen + 1);
@@ -828,10 +827,10 @@ bail:
for (i = 0; i < c->num_fpes; i++)
FreeFPE(c->fpe_list[i]);
free(c->fpe_list);
- if (c->savedName) free(c->savedName);
+ free(c->savedName);
FreeFontNames(names);
free(c);
- if (resolved) free(resolved);
+ free(resolved);
return TRUE;
}
@@ -994,8 +993,7 @@ doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
c->saved = c->current;
c->haveSaved = TRUE;
c->savedNumFonts = numFonts;
- if (c->savedName)
- free(c->savedName);
+ free(c->savedName);
c->savedName = malloc(namelen + 1);
if (c->savedName)
memmove(c->savedName, name, namelen + 1);
@@ -1093,7 +1091,7 @@ doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
}
finish:
length = sizeof(xListFontsWithInfoReply);
- bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply));
+ memset((char *) &finalReply, 0, sizeof(xListFontsWithInfoReply));
finalReply.type = X_Reply;
finalReply.sequenceNumber = client->sequence;
finalReply.length = bytes_to_int32(sizeof(xListFontsWithInfoReply)
@@ -1106,7 +1104,7 @@ bail:
FreeFPE(c->fpe_list[i]);
free(c->reply);
free(c->fpe_list);
- if (c->savedName) free(c->savedName);
+ free(c->savedName);
free(c);
return TRUE;
}
diff --git a/xorg-server/dix/dixutils.c b/xorg-server/dix/dixutils.c
index 6b6b41d0d..d9d9d8c7d 100644
--- a/xorg-server/dix/dixutils.c
+++ b/xorg-server/dix/dixutils.c
@@ -296,17 +296,17 @@ AlterSaveSetForClient(ClientPtr client, WindowPtr pWin, unsigned mode,
if (mode == SetModeInsert)
{
if (j < numnow) /* duplicate */
- return(Success);
+ return Success;
numnow++;
pTmp = (SaveSetElt *)realloc(client->saveSet, sizeof(*pTmp) * numnow);
if (!pTmp)
- return(BadAlloc);
+ return BadAlloc;
client->saveSet = pTmp;
client->numSaved = numnow;
SaveSetAssignWindow(client->saveSet[numnow - 1], pWin);
SaveSetAssignToRoot(client->saveSet[numnow - 1], toRoot);
SaveSetAssignMap(client->saveSet[numnow - 1], map);
- return(Success);
+ return Success;
}
else if ((mode == SetModeDelete) && (j < numnow))
{
@@ -328,9 +328,9 @@ AlterSaveSetForClient(ClientPtr client, WindowPtr pWin, unsigned mode,
client->saveSet = (SaveSetElt *)NULL;
}
client->numSaved = numnow;
- return(Success);
+ return Success;
}
- return(Success);
+ return Success;
}
void
@@ -893,7 +893,7 @@ InitCallbackManager(void)
{
DeleteCallbackList(listsToCleanup[i]);
}
- if (listsToCleanup) free(listsToCleanup);
+ free(listsToCleanup);
numCallbackListsToCleanup = 0;
listsToCleanup = NULL;
diff --git a/xorg-server/dix/enterleave.c b/xorg-server/dix/enterleave.c
index c08cc3100..73e007dda 100644
--- a/xorg-server/dix/enterleave.c
+++ b/xorg-server/dix/enterleave.c
@@ -1,1385 +1,1385 @@
-/*
- * Copyright © 2008 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.
- *
- * Authors: Peter Hutterer
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/extensions/XI2.h>
-#include "inputstr.h"
-#include "windowstr.h"
-#include "scrnintstr.h"
-#include "exglobals.h"
-#include "enterleave.h"
-
-/**
- * @file
- * This file describes the model for sending core enter/leave events and
- * focus in/out in the case of multiple pointers/keyboard foci.
- *
- * Since we can't send more than one Enter or Leave/Focus in or out event per
- * window to a core client without confusing it, this is a rather complicated
- * approach.
- *
- * For a full description of the enter/leave model from a window's
- * perspective, see
- * http://lists.freedesktop.org/archives/xorg/2008-August/037606.html
- *
- * For a full description of the focus in/out model from a window's
- * perspective, see
- * http://lists.freedesktop.org/archives/xorg/2008-December/041740.html
- *
- * Additional notes:
- * - The core protocol spec says that "In a LeaveNotify event, if a child of the
- * event window contains the initial position of the pointer, then the child
- * component is set to that child. Otherwise, it is None. For an EnterNotify
- * event, if a child of the event window contains the final pointer position,
- * then the child component is set to that child. Otherwise, it is None."
- *
- * By inference, this means that only NotifyVirtual or NotifyNonlinearVirtual
- * events may have a subwindow set to other than None.
- *
- * - NotifyPointer events may be sent if the focus changes from window A to
- * B. The assumption used in this model is that NotifyPointer events are only
- * sent for the pointer paired with the keyboard that is involved in the focus
- * events. For example, if F(W) changes because of keyboard 2, then
- * NotifyPointer events are only sent for pointer 2.
- */
-
-static WindowPtr PointerWindows[MAXDEVICES];
-static WindowPtr FocusWindows[MAXDEVICES];
-
-/**
- * Return TRUE if 'win' has a pointer within its boundaries, excluding child
- * window.
- */
-static BOOL
-HasPointer(WindowPtr win)
-{
- int i;
-
- for (i = 0; i < MAXDEVICES; i++)
- if (PointerWindows[i] == win)
- return TRUE;
-
- return FALSE;
-}
-
-/**
- * Return TRUE if at least one keyboard focus is set to 'win' (excluding
- * descendants of win).
- */
-static BOOL
-HasFocus(WindowPtr win)
-{
- int i;
- for (i = 0; i < MAXDEVICES; i++)
- if (FocusWindows[i] == win)
- return TRUE;
-
- return FALSE;
-}
-
-/**
- * Return the window the device dev is currently on.
- */
-static WindowPtr
-PointerWin(DeviceIntPtr dev)
-{
- return PointerWindows[dev->id];
-}
-
-/**
- * Search for the first window below 'win' that has a pointer directly within
- * it's boundaries (excluding boundaries of its own descendants).
- *
- * @return The child window that has the pointer within its boundaries or
- * NULL.
- */
-static WindowPtr
-FirstPointerChild(WindowPtr win)
-{
- int i;
- for (i = 0; i < MAXDEVICES; i++)
- {
- if (PointerWindows[i] && IsParent(win, PointerWindows[i]))
- return PointerWindows[i];
- }
-
- return NULL;
-}
-
-/**
- * Search for the first window below 'win' that has a focus directly within
- * it's boundaries (excluding boundaries of its own descendants).
- *
- * @return The child window that has the pointer within its boundaries or
- * NULL.
- */
-static WindowPtr
-FirstFocusChild(WindowPtr win)
-{
- int i;
- for (i = 0; i < MAXDEVICES; i++)
- {
- if (FocusWindows[i] && FocusWindows[i] != PointerRootWin &&
- IsParent(win, FocusWindows[i]))
- return FocusWindows[i];
- }
-
- return NULL;
-}
-
-/**
- * Set the presence flag for dev to mark that it is now in 'win'.
- */
-void
-EnterWindow(DeviceIntPtr dev, WindowPtr win, int mode)
-{
- PointerWindows[dev->id] = win;
-}
-
-/**
- * Unset the presence flag for dev to mark that it is not in 'win' anymore.
- */
-void
-LeaveWindow(DeviceIntPtr dev)
-{
- PointerWindows[dev->id] = NULL;
-}
-
-/**
- * Set the presence flag for dev to mark that it is now in 'win'.
- */
-void
-SetFocusIn(DeviceIntPtr dev, WindowPtr win)
-{
- FocusWindows[dev->id] = win;
-}
-
-/**
- * Unset the presence flag for dev to mark that it is not in 'win' anymore.
- */
-void
-SetFocusOut(DeviceIntPtr dev)
-{
- FocusWindows[dev->id] = NULL;
-}
-
-
-
-
-/**
- * Return the common ancestor of 'a' and 'b' (if one exists).
- * @param a A window with the same ancestor as b.
- * @param b A window with the same ancestor as a.
- * @return The window that is the first ancestor of both 'a' and 'b', or the
- * NullWindow if they do not have a common ancestor.
- */
-WindowPtr
-CommonAncestor(
- WindowPtr a,
- WindowPtr b)
-{
- for (b = b->parent; b; b = b->parent)
- if (IsParent(b, a)) return b;
- return NullWindow;
-}
-
-
-/**
- * Send enter notifies to all windows between 'ancestor' and 'child' (excluding
- * both). Events are sent running up the window hierarchy. This function
- * recurses.
- */
-static void
-DeviceEnterNotifies(DeviceIntPtr dev,
- int sourceid,
- WindowPtr ancestor,
- WindowPtr child,
- int mode,
- int detail)
-{
- WindowPtr parent = child->parent;
-
- if (ancestor == parent)
- return;
- DeviceEnterNotifies(dev, sourceid, ancestor, parent, mode, detail);
- DeviceEnterLeaveEvent(dev, sourceid, XI_Enter, mode, detail, parent,
- child->drawable.id);
-}
-
-/**
- * Send enter notifies to all windows between 'ancestor' and 'child' (excluding
- * both). Events are sent running down the window hierarchy. This function
- * recurses.
- */
-static void
-CoreEnterNotifies(DeviceIntPtr dev,
- WindowPtr ancestor,
- WindowPtr child,
- int mode,
- int detail)
-{
- WindowPtr parent = child->parent;
- if (ancestor == parent)
- return;
- CoreEnterNotifies(dev, ancestor, parent, mode, detail);
-
-
- /* Case 3:
- A is above W, B is a descendant
-
- Classically: The move generates an EnterNotify on W with a detail of
- Virtual or NonlinearVirtual
-
- MPX:
- Case 3A: There is at least one other pointer on W itself
- P(W) doesn't change, so the event should be suppressed
- Case 3B: Otherwise, if there is at least one other pointer in a
- descendant
- P(W) stays on the same descendant, or changes to a different
- descendant. The event should be suppressed.
- Case 3C: Otherwise:
- P(W) moves from a window above W to a descendant. The subwindow
- field is set to the child containing the descendant. The detail
- may need to be changed from Virtual to NonlinearVirtual depending
- on the previous P(W). */
-
- if (!HasPointer(parent) && !FirstPointerChild(parent))
- CoreEnterLeaveEvent(dev, EnterNotify, mode, detail, parent,
- child->drawable.id);
-}
-
-static void
-CoreLeaveNotifies(DeviceIntPtr dev,
- WindowPtr child,
- WindowPtr ancestor,
- int mode,
- int detail)
-{
- WindowPtr win;
-
- if (ancestor == child)
- return;
-
- for (win = child->parent; win != ancestor; win = win->parent)
- {
- /*Case 7:
- A is a descendant of W, B is above W
-
- Classically: A LeaveNotify is generated on W with a detail of Virtual
- or NonlinearVirtual.
-
- MPX:
- Case 3A: There is at least one other pointer on W itself
- P(W) doesn't change, the event should be suppressed.
- Case 3B: Otherwise, if there is at least one other pointer in a
- descendant
- P(W) stays on the same descendant, or changes to a different
- descendant. The event should be suppressed.
- Case 3C: Otherwise:
- P(W) changes from the descendant of W to a window above W.
- The detail may need to be changed from Virtual to NonlinearVirtual
- or vice-versa depending on the new P(W).*/
-
- /* If one window has a pointer or a child with a pointer, skip some
- * work and exit. */
- if (HasPointer(win) || FirstPointerChild(win))
- return;
-
- CoreEnterLeaveEvent(dev, LeaveNotify, mode, detail, win, child->drawable.id);
-
- child = win;
- }
-}
-
-/**
- * Send leave notifies to all windows between 'child' and 'ancestor'.
- * Events are sent running up the hierarchy.
- */
-static void
-DeviceLeaveNotifies(DeviceIntPtr dev,
- int sourceid,
- WindowPtr child,
- WindowPtr ancestor,
- int mode,
- int detail)
-{
- WindowPtr win;
-
- if (ancestor == child)
- return;
- for (win = child->parent; win != ancestor; win = win->parent)
- {
- DeviceEnterLeaveEvent(dev, sourceid, XI_Leave, mode, detail, win,
- child->drawable.id);
- child = win;
- }
-}
-
-/**
- * Pointer dev moves from A to B and A neither a descendant of B nor is
- * B a descendant of A.
- */
-static void
-CoreEnterLeaveNonLinear(DeviceIntPtr dev,
- WindowPtr A,
- WindowPtr B,
- int mode)
-{
- WindowPtr X = CommonAncestor(A, B);
- /* Case 4:
- A is W, B is above W
-
- Classically: The move generates a LeaveNotify on W with a detail of
- Ancestor or Nonlinear
-
- MPX:
- Case 3A: There is at least one other pointer on W itself
- P(W) doesn't change, the event should be suppressed
- Case 3B: Otherwise, if there is at least one other pointer in a
- descendant of W
- P(W) changes from W to a descendant of W. The subwindow field
- is set to the child containing the new P(W), the detail field
- is set to Inferior
- Case 3C: Otherwise:
- The pointer window moves from W to a window above W.
- The detail may need to be changed from Ancestor to Nonlinear or
- vice versa depending on the the new P(W)
- */
-
- if (!HasPointer(A))
- {
- WindowPtr child = FirstPointerChild(A);
- if (child)
- CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, None);
- else
- CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyNonlinear, A, None);
- }
-
-
- CoreLeaveNotifies(dev, A, X, mode, NotifyNonlinearVirtual);
-
- /*
- Case 9:
- A is a descendant of W, B is a descendant of W
-
- Classically: No events are generated on W
- MPX: The pointer window stays the same or moves to a different
- descendant of W. No events should be generated on W.
-
-
- Therefore, no event to X.
- */
-
- CoreEnterNotifies(dev, X, B, mode, NotifyNonlinearVirtual);
-
- /* Case 2:
- A is above W, B=W
-
- Classically: The move generates an EnterNotify on W with a detail of
- Ancestor or Nonlinear
-
- MPX:
- Case 2A: There is at least one other pointer on W itself
- P(W) doesn't change, so the event should be suppressed
- Case 2B: Otherwise, if there is at least one other pointer in a
- descendant
- P(W) moves from a descendant to W. detail is changed to Inferior,
- subwindow is set to the child containing the previous P(W)
- Case 2C: Otherwise:
- P(W) changes from a window above W to W itself.
- The detail may need to be changed from Ancestor to Nonlinear
- or vice-versa depending on the previous P(W). */
-
- if (!HasPointer(B))
- {
- WindowPtr child = FirstPointerChild(B);
- if (child)
- CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyInferior, B, None);
- else
- CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyNonlinear, B, None);
- }
-}
-
-/**
- * Pointer dev moves from A to B and A is a descendant of B.
- */
-static void
-CoreEnterLeaveToAncestor(DeviceIntPtr dev,
- WindowPtr A,
- WindowPtr B,
- int mode)
-{
- /* Case 4:
- A is W, B is above W
-
- Classically: The move generates a LeaveNotify on W with a detail of
- Ancestor or Nonlinear
-
- MPX:
- Case 3A: There is at least one other pointer on W itself
- P(W) doesn't change, the event should be suppressed
- Case 3B: Otherwise, if there is at least one other pointer in a
- descendant of W
- P(W) changes from W to a descendant of W. The subwindow field
- is set to the child containing the new P(W), the detail field
- is set to Inferior
- Case 3C: Otherwise:
- The pointer window moves from W to a window above W.
- The detail may need to be changed from Ancestor to Nonlinear or
- vice versa depending on the the new P(W)
- */
- if (!HasPointer(A))
- {
- WindowPtr child = FirstPointerChild(A);
- if (child)
- CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, None);
- else
- CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyAncestor, A, None);
- }
-
- CoreLeaveNotifies(dev, A, B, mode, NotifyVirtual);
-
- /* Case 8:
- A is a descendant of W, B is W
-
- Classically: A EnterNotify is generated on W with a detail of
- NotifyInferior
-
- MPX:
- Case 3A: There is at least one other pointer on W itself
- P(W) doesn't change, the event should be suppressed
- Case 3B: Otherwise:
- P(W) changes from a descendant to W itself. The subwindow
- field should be set to the child containing the old P(W) <<< WRONG */
-
- if (!HasPointer(B))
- CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyInferior, B, None);
-
-}
-
-
-/**
- * Pointer dev moves from A to B and B is a descendant of A.
- */
-static void
-CoreEnterLeaveToDescendant(DeviceIntPtr dev,
- WindowPtr A,
- WindowPtr B,
- int mode)
-{
- /* Case 6:
- A is W, B is a descendant of W
-
- Classically: A LeaveNotify is generated on W with a detail of
- NotifyInferior
-
- MPX:
- Case 3A: There is at least one other pointer on W itself
- P(W) doesn't change, the event should be suppressed
- Case 3B: Otherwise:
- P(W) changes from W to a descendant of W. The subwindow field
- is set to the child containing the new P(W) <<< THIS IS WRONG */
-
- if (!HasPointer(A))
- CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, None);
-
-
- CoreEnterNotifies(dev, A, B, mode, NotifyVirtual);
-
- /* Case 2:
- A is above W, B=W
-
- Classically: The move generates an EnterNotify on W with a detail of
- Ancestor or Nonlinear
-
- MPX:
- Case 2A: There is at least one other pointer on W itself
- P(W) doesn't change, so the event should be suppressed
- Case 2B: Otherwise, if there is at least one other pointer in a
- descendant
- P(W) moves from a descendant to W. detail is changed to Inferior,
- subwindow is set to the child containing the previous P(W)
- Case 2C: Otherwise:
- P(W) changes from a window above W to W itself.
- The detail may need to be changed from Ancestor to Nonlinear
- or vice-versa depending on the previous P(W). */
-
- if (!HasPointer(B))
- {
- WindowPtr child = FirstPointerChild(B);
- if (child)
- CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyInferior, B, None);
- else
- CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyAncestor, B, None);
- }
-}
-
-static void
-CoreEnterLeaveEvents(DeviceIntPtr dev,
- WindowPtr from,
- WindowPtr to,
- int mode)
-{
- if (!IsMaster(dev))
- return;
-
- LeaveWindow(dev);
-
- if (IsParent(from, to))
- CoreEnterLeaveToDescendant(dev, from, to, mode);
- else if (IsParent(to, from))
- CoreEnterLeaveToAncestor(dev, from, to, mode);
- else
- CoreEnterLeaveNonLinear(dev, from, to, mode);
-
- EnterWindow(dev, to, mode);
-}
-
-static void
-DeviceEnterLeaveEvents(DeviceIntPtr dev,
- int sourceid,
- WindowPtr from,
- WindowPtr to,
- int mode)
-{
- if (IsParent(from, to))
- {
- DeviceEnterLeaveEvent(dev, sourceid, XI_Leave, mode, NotifyInferior, from, None);
- DeviceEnterNotifies(dev, sourceid, from, to, mode, NotifyVirtual);
- DeviceEnterLeaveEvent(dev, sourceid, XI_Enter, mode, NotifyAncestor, to, None);
- }
- else if (IsParent(to, from))
- {
- DeviceEnterLeaveEvent(dev, sourceid, XI_Leave, mode, NotifyAncestor, from, None);
- DeviceLeaveNotifies(dev, sourceid, from, to, mode, NotifyVirtual);
- DeviceEnterLeaveEvent(dev, sourceid, XI_Enter, mode, NotifyInferior, to, None);
- }
- else
- { /* neither from nor to is descendent of the other */
- WindowPtr common = CommonAncestor(to, from);
- /* common == NullWindow ==> different screens */
- DeviceEnterLeaveEvent(dev, sourceid, XI_Leave, mode, NotifyNonlinear, from, None);
- DeviceLeaveNotifies(dev, sourceid, from, common, mode, NotifyNonlinearVirtual);
- DeviceEnterNotifies(dev, sourceid, common, to, mode, NotifyNonlinearVirtual);
- DeviceEnterLeaveEvent(dev, sourceid, XI_Enter, mode, NotifyNonlinear, to, None);
- }
-}
-
-/**
- * Figure out if enter/leave events are necessary and send them to the
- * appropriate windows.
- *
- * @param fromWin Window the sprite moved out of.
- * @param toWin Window the sprite moved into.
- */
-void
-DoEnterLeaveEvents(DeviceIntPtr pDev,
- int sourceid,
- WindowPtr fromWin,
- WindowPtr toWin,
- int mode)
-{
- if (!IsPointerDevice(pDev))
- return;
-
- if (fromWin == toWin)
- return;
-
- if (mode != XINotifyPassiveGrab && mode != XINotifyPassiveUngrab)
- CoreEnterLeaveEvents(pDev, fromWin, toWin, mode);
- DeviceEnterLeaveEvents(pDev, sourceid, fromWin, toWin, mode);
-}
-
-/**
- * Send focus out events to all windows between 'child' and 'ancestor'.
- * Events are sent running up the hierarchy.
- */
-static void
-DeviceFocusOutEvents(DeviceIntPtr dev,
- WindowPtr child,
- WindowPtr ancestor,
- int mode,
- int detail)
-{
- WindowPtr win;
-
- if (ancestor == child)
- return;
- for (win = child->parent; win != ancestor; win = win->parent)
- DeviceFocusEvent(dev, XI_FocusOut, mode, detail, win);
-}
-
-
-/**
- * Send enter notifies to all windows between 'ancestor' and 'child' (excluding
- * both). Events are sent running up the window hierarchy. This function
- * recurses.
- */
-static void
-DeviceFocusInEvents(DeviceIntPtr dev,
- WindowPtr ancestor,
- WindowPtr child,
- int mode,
- int detail)
-{
- WindowPtr parent = child->parent;
-
- if (ancestor == parent || !parent)
- return;
- DeviceFocusInEvents(dev, ancestor, parent, mode, detail);
- DeviceFocusEvent(dev, XI_FocusIn, mode, detail, parent);
-}
-
-/**
- * Send FocusIn events to all windows between 'ancestor' and 'child' (excluding
- * both). Events are sent running down the window hierarchy. This function
- * recurses.
- */
-static void
-CoreFocusInEvents(DeviceIntPtr dev,
- WindowPtr ancestor,
- WindowPtr child,
- int mode,
- int detail)
-{
- WindowPtr parent = child->parent;
- if (ancestor == parent)
- return;
- CoreFocusInEvents(dev, ancestor, parent, mode, detail);
-
-
- /* Case 3:
- A is above W, B is a descendant
-
- Classically: The move generates an FocusIn on W with a detail of
- Virtual or NonlinearVirtual
-
- MPX:
- Case 3A: There is at least one other focus on W itself
- F(W) doesn't change, so the event should be suppressed
- Case 3B: Otherwise, if there is at least one other focus in a
- descendant
- F(W) stays on the same descendant, or changes to a different
- descendant. The event should be suppressed.
- Case 3C: Otherwise:
- F(W) moves from a window above W to a descendant. The detail may
- need to be changed from Virtual to NonlinearVirtual depending
- on the previous F(W). */
-
- if (!HasFocus(parent) && !FirstFocusChild(parent))
- CoreFocusEvent(dev, FocusIn, mode, detail, parent);
-}
-
-static void
-CoreFocusOutEvents(DeviceIntPtr dev,
- WindowPtr child,
- WindowPtr ancestor,
- int mode,
- int detail)
-{
- WindowPtr win;
-
- if (ancestor == child)
- return;
-
- for (win = child->parent; win != ancestor; win = win->parent)
- {
- /*Case 7:
- A is a descendant of W, B is above W
-
- Classically: A FocusOut is generated on W with a detail of Virtual
- or NonlinearVirtual.
-
- MPX:
- Case 3A: There is at least one other focus on W itself
- F(W) doesn't change, the event should be suppressed.
- Case 3B: Otherwise, if there is at least one other focus in a
- descendant
- F(W) stays on the same descendant, or changes to a different
- descendant. The event should be suppressed.
- Case 3C: Otherwise:
- F(W) changes from the descendant of W to a window above W.
- The detail may need to be changed from Virtual to NonlinearVirtual
- or vice-versa depending on the new P(W).*/
-
- /* If one window has a focus or a child with a focuspointer, skip some
- * work and exit. */
- if (HasFocus(win) || FirstFocusChild(win))
- return;
-
- CoreFocusEvent(dev, FocusOut, mode, detail, win);
- }
-}
-
-/**
- * Send FocusOut(NotifyPointer) events from the current pointer window (which
- * is a descendant of pwin_parent) up to (excluding) pwin_parent.
- *
- * NotifyPointer events are only sent for the device paired with dev.
- *
- * If the current pointer window is a descendant of 'exclude' or an ancestor of
- * 'exclude', no events are sent. If the current pointer IS 'exclude', events
- * are sent!
- */
-static void
-CoreFocusOutNotifyPointerEvents(DeviceIntPtr dev,
- WindowPtr pwin_parent,
- WindowPtr exclude,
- int mode,
- int inclusive)
-{
- WindowPtr P, stopAt;
-
- P = PointerWin(GetPairedDevice(dev));
-
- if (!P)
- return;
- if (!IsParent(pwin_parent, P))
- if (!(pwin_parent == P && inclusive))
- return;
-
- if (exclude != None && exclude != PointerRootWin &&
- (IsParent(exclude, P) || IsParent(P, exclude)))
- return;
-
- stopAt = (inclusive) ? pwin_parent->parent : pwin_parent;
-
- for (; P && P != stopAt; P = P->parent)
- CoreFocusEvent(dev, FocusOut, mode, NotifyPointer, P);
-}
-
-/**
- * DO NOT CALL DIRECTLY.
- * Recursion helper for CoreFocusInNotifyPointerEvents.
- */
-static void
-CoreFocusInRecurse(DeviceIntPtr dev,
- WindowPtr win,
- WindowPtr stopAt,
- int mode,
- int inclusive)
-{
- if ((!inclusive && win == stopAt) || !win)
- return;
-
- CoreFocusInRecurse(dev, win->parent, stopAt, mode, inclusive);
- CoreFocusEvent(dev, FocusIn, mode, NotifyPointer, win);
-}
-
-
-/**
- * Send FocusIn(NotifyPointer) events from pwin_parent down to
- * including the current pointer window (which is a descendant of pwin_parent).
- *
- * @param pwin The pointer window.
- * @param exclude If the pointer window is a child of 'exclude', no events are
- * sent.
- * @param inclusive If TRUE, pwin_parent will receive the event too.
- */
-static void
-CoreFocusInNotifyPointerEvents(DeviceIntPtr dev,
- WindowPtr pwin_parent,
- WindowPtr exclude,
- int mode,
- int inclusive)
-{
- WindowPtr P;
-
- P = PointerWin(GetPairedDevice(dev));
-
- if (!P || P == exclude || (pwin_parent != P && !IsParent(pwin_parent, P)))
- return;
-
- if (exclude != None && (IsParent(exclude, P) || IsParent(P, exclude)))
- return;
-
- CoreFocusInRecurse(dev, P, pwin_parent, mode, inclusive);
-}
-
-
-/**
- * Focus of dev moves from A to B and A neither a descendant of B nor is
- * B a descendant of A.
- */
-static void
-CoreFocusNonLinear(DeviceIntPtr dev,
- WindowPtr A,
- WindowPtr B,
- int mode)
-{
- WindowPtr X = CommonAncestor(A, B);
-
- /* Case 4:
- A is W, B is above W
-
- Classically: The change generates a FocusOut on W with a detail of
- Ancestor or Nonlinear
-
- MPX:
- Case 3A: There is at least one other focus on W itself
- F(W) doesn't change, the event should be suppressed
- Case 3B: Otherwise, if there is at least one other focus in a
- descendant of W
- F(W) changes from W to a descendant of W. The detail field
- is set to Inferior
- Case 3C: Otherwise:
- The focus window moves from W to a window above W.
- The detail may need to be changed from Ancestor to Nonlinear or
- vice versa depending on the the new F(W)
- */
-
- if (!HasFocus(A))
- {
- WindowPtr child = FirstFocusChild(A);
- if (child)
- {
- /* NotifyPointer P-A unless P is child or below*/
- CoreFocusOutNotifyPointerEvents(dev, A, child, mode, FALSE);
- CoreFocusEvent(dev, FocusOut, mode, NotifyInferior, A);
- } else
- {
- /* NotifyPointer P-A */
- CoreFocusOutNotifyPointerEvents(dev, A, None, mode, FALSE);
- CoreFocusEvent(dev, FocusOut, mode, NotifyNonlinear, A);
- }
- }
-
-
- CoreFocusOutEvents(dev, A, X, mode, NotifyNonlinearVirtual);
-
- /*
- Case 9:
- A is a descendant of W, B is a descendant of W
-
- Classically: No events are generated on W
- MPX: The focus window stays the same or moves to a different
- descendant of W. No events should be generated on W.
-
-
- Therefore, no event to X.
- */
-
- CoreFocusInEvents(dev, X, B, mode, NotifyNonlinearVirtual);
-
- /* Case 2:
- A is above W, B=W
-
- Classically: The move generates an EnterNotify on W with a detail of
- Ancestor or Nonlinear
-
- MPX:
- Case 2A: There is at least one other focus on W itself
- F(W) doesn't change, so the event should be suppressed
- Case 2B: Otherwise, if there is at least one other focus in a
- descendant
- F(W) moves from a descendant to W. detail is changed to Inferior.
- Case 2C: Otherwise:
- F(W) changes from a window above W to W itself.
- The detail may need to be changed from Ancestor to Nonlinear
- or vice-versa depending on the previous F(W). */
-
- if (!HasFocus(B))
- {
- WindowPtr child = FirstFocusChild(B);
- if (child)
- {
- CoreFocusEvent(dev, FocusIn, mode, NotifyInferior, B);
- /* NotifyPointer B-P unless P is child or below. */
- CoreFocusInNotifyPointerEvents(dev, B, child, mode, FALSE);
- } else {
- CoreFocusEvent(dev, FocusIn, mode, NotifyNonlinear, B);
- /* NotifyPointer B-P unless P is child or below. */
- CoreFocusInNotifyPointerEvents(dev, B, None, mode, FALSE);
- }
- }
-}
-
-
-/**
- * Focus of dev moves from A to B and A is a descendant of B.
- */
-static void
-CoreFocusToAncestor(DeviceIntPtr dev,
- WindowPtr A,
- WindowPtr B,
- int mode)
-{
- /* Case 4:
- A is W, B is above W
-
- Classically: The change generates a FocusOut on W with a detail of
- Ancestor or Nonlinear
-
- MPX:
- Case 3A: There is at least one other focus on W itself
- F(W) doesn't change, the event should be suppressed
- Case 3B: Otherwise, if there is at least one other focus in a
- descendant of W
- F(W) changes from W to a descendant of W. The detail field
- is set to Inferior
- Case 3C: Otherwise:
- The focus window moves from W to a window above W.
- The detail may need to be changed from Ancestor to Nonlinear or
- vice versa depending on the the new F(W)
- */
- if (!HasFocus(A))
- {
- WindowPtr child = FirstFocusChild(A);
- if (child)
- {
- /* NotifyPointer P-A unless P is child or below*/
- CoreFocusOutNotifyPointerEvents(dev, A, child, mode, FALSE);
- CoreFocusEvent(dev, FocusOut, mode, NotifyInferior, A);
- } else
- CoreFocusEvent(dev, FocusOut, mode, NotifyAncestor, A);
- }
-
- CoreFocusOutEvents(dev, A, B, mode, NotifyVirtual);
-
- /* Case 8:
- A is a descendant of W, B is W
-
- Classically: A FocusOut is generated on W with a detail of
- NotifyInferior
-
- MPX:
- Case 3A: There is at least one other focus on W itself
- F(W) doesn't change, the event should be suppressed
- Case 3B: Otherwise:
- F(W) changes from a descendant to W itself. */
-
- if (!HasFocus(B))
- {
- CoreFocusEvent(dev, FocusIn, mode, NotifyInferior, B);
- /* NotifyPointer B-P unless P is A or below. */
- CoreFocusInNotifyPointerEvents(dev, B, A, mode, FALSE);
- }
-}
-
-/**
- * Focus of dev moves from A to B and B is a descendant of A.
- */
-static void
-CoreFocusToDescendant(DeviceIntPtr dev,
- WindowPtr A,
- WindowPtr B,
- int mode)
-{
- /* Case 6:
- A is W, B is a descendant of W
-
- Classically: A FocusOut is generated on W with a detail of
- NotifyInferior
-
- MPX:
- Case 3A: There is at least one other focus on W itself
- F(W) doesn't change, the event should be suppressed
- Case 3B: Otherwise:
- F(W) changes from W to a descendant of W. */
-
- if (!HasFocus(A))
- {
- /* NotifyPointer P-A unless P is B or below*/
- CoreFocusOutNotifyPointerEvents(dev, A, B, mode, FALSE);
- CoreFocusEvent(dev, FocusOut, mode, NotifyInferior, A);
- }
-
-
- CoreFocusInEvents(dev, A, B, mode, NotifyVirtual);
-
- /* Case 2:
- A is above W, B=W
-
- Classically: The move generates an FocusIn on W with a detail of
- Ancestor or Nonlinear
-
- MPX:
- Case 2A: There is at least one other focus on W itself
- F(W) doesn't change, so the event should be suppressed
- Case 2B: Otherwise, if there is at least one other focus in a
- descendant
- F(W) moves from a descendant to W. detail is changed to Inferior.
- Case 2C: Otherwise:
- F(W) changes from a window above W to W itself.
- The detail may need to be changed from Ancestor to Nonlinear
- or vice-versa depending on the previous F(W). */
-
- if (!HasFocus(B))
- {
- WindowPtr child = FirstFocusChild(B);
- if (child)
- {
- CoreFocusEvent(dev, FocusIn, mode, NotifyInferior, B);
- /* NotifyPointer B-P unless P is child or below. */
- CoreFocusInNotifyPointerEvents(dev, B, child, mode, FALSE);
- } else
- CoreFocusEvent(dev, FocusIn, mode, NotifyAncestor, B);
- }
-}
-
-static BOOL
-HasOtherPointer(WindowPtr win, DeviceIntPtr exclude)
-{
- int i;
-
- for (i = 0; i < MAXDEVICES; i++)
- if (i != exclude->id && PointerWindows[i] == win)
- return TRUE;
-
- return FALSE;
-}
-
-/**
- * Focus moves from PointerRoot to None or from None to PointerRoot.
- * Assumption: Neither A nor B are valid windows.
- */
-static void
-CoreFocusPointerRootNoneSwitch(DeviceIntPtr dev,
- WindowPtr A, /* PointerRootWin or NoneWin */
- WindowPtr B, /* NoneWin or PointerRootWin */
- int mode)
-{
- WindowPtr root;
- int i;
- int nscreens = screenInfo.numScreens;
-
-#ifdef PANORAMIX
- if (!noPanoramiXExtension)
- nscreens = 1;
-#endif
-
- for (i = 0; i < nscreens; i++)
- {
- root = WindowTable[i];
- if (!HasOtherPointer(root, GetPairedDevice(dev)) && !FirstFocusChild(root))
- {
- /* If pointer was on PointerRootWin and changes to NoneWin, and
- * the pointer paired with dev is below the current root window,
- * do a NotifyPointer run. */
- if (dev->focus && dev->focus->win == PointerRootWin &&
- B != PointerRootWin)
- {
- WindowPtr ptrwin = PointerWin(GetPairedDevice(dev));
- if (ptrwin && IsParent(root, ptrwin))
- CoreFocusOutNotifyPointerEvents(dev, root, None, mode, TRUE);
- }
- CoreFocusEvent(dev, FocusOut, mode, A ? NotifyPointerRoot : NotifyDetailNone, root);
- CoreFocusEvent(dev, FocusIn, mode, B ? NotifyPointerRoot : NotifyDetailNone, root);
- if (B == PointerRootWin)
- CoreFocusInNotifyPointerEvents(dev, root, None, mode, TRUE);
- }
-
- }
-}
-
-/**
- * Focus moves from window A to PointerRoot or to None.
- * Assumption: A is a valid window and not PointerRoot or None.
- */
-static void
-CoreFocusToPointerRootOrNone(DeviceIntPtr dev,
- WindowPtr A,
- WindowPtr B, /* PointerRootWin or NoneWin */
- int mode)
-{
- WindowPtr root;
- int i;
- int nscreens = screenInfo.numScreens;
-
-#ifdef PANORAMIX
- if (!noPanoramiXExtension)
- nscreens = 1;
-#endif
-
- if (!HasFocus(A))
- {
- WindowPtr child = FirstFocusChild(A);
- if (child)
- {
- /* NotifyPointer P-A unless P is B or below*/
- CoreFocusOutNotifyPointerEvents(dev, A, B, mode, FALSE);
- CoreFocusEvent(dev, FocusOut, mode, NotifyInferior, A);
- } else {
- /* NotifyPointer P-A */
- CoreFocusOutNotifyPointerEvents(dev, A, None, mode, FALSE);
- CoreFocusEvent(dev, FocusOut, mode, NotifyNonlinear, A);
- }
- }
-
- /* NullWindow means we include the root window */
- CoreFocusOutEvents(dev, A, NullWindow, mode, NotifyNonlinearVirtual);
-
- for (i = 0; i < nscreens; i++)
- {
- root = WindowTable[i];
- if (!HasFocus(root) && !FirstFocusChild(root))
- {
- CoreFocusEvent(dev, FocusIn, mode, B ? NotifyPointerRoot : NotifyDetailNone, root);
- if (B == PointerRootWin)
- CoreFocusInNotifyPointerEvents(dev, root, None, mode, TRUE);
- }
- }
-}
-
-/**
- * Focus moves from PointerRoot or None to a window B.
- * Assumption: B is a valid window and not PointerRoot or None.
- */
-static void
-CoreFocusFromPointerRootOrNone(DeviceIntPtr dev,
- WindowPtr A, /* PointerRootWin or NoneWin */
- WindowPtr B,
- int mode)
-{
- WindowPtr root;
- int i;
- int nscreens = screenInfo.numScreens;
-
-#ifdef PANORAMIX
- if (!noPanoramiXExtension)
- nscreens = 1;
-#endif
-
- for (i = 0; i < nscreens; i++)
- {
- root = WindowTable[i];
- if (!HasFocus(root) && !FirstFocusChild(root))
- {
- /* If pointer was on PointerRootWin and changes to NoneWin, and
- * the pointer paired with dev is below the current root window,
- * do a NotifyPointer run. */
- if (dev->focus && dev->focus->win == PointerRootWin &&
- B != PointerRootWin)
- {
- WindowPtr ptrwin = PointerWin(GetPairedDevice(dev));
- if (ptrwin)
- CoreFocusOutNotifyPointerEvents(dev, root, None, mode, TRUE);
- }
- CoreFocusEvent(dev, FocusOut, mode, A ? NotifyPointerRoot : NotifyDetailNone, root);
- }
- }
-
- root = B; /* get B's root window */
- while(root->parent)
- root = root->parent;
-
- if (B != root)
- {
- CoreFocusEvent(dev, FocusIn, mode, NotifyNonlinearVirtual, root);
- CoreFocusInEvents(dev, root, B, mode, NotifyNonlinearVirtual);
- }
-
-
- if (!HasFocus(B))
- {
- WindowPtr child = FirstFocusChild(B);
- if (child)
- {
- CoreFocusEvent(dev, FocusIn, mode, NotifyInferior, B);
- /* NotifyPointer B-P unless P is child or below. */
- CoreFocusInNotifyPointerEvents(dev, B, child, mode, FALSE);
- } else {
- CoreFocusEvent(dev, FocusIn, mode, NotifyNonlinear, B);
- /* NotifyPointer B-P unless P is child or below. */
- CoreFocusInNotifyPointerEvents(dev, B, None, mode, FALSE);
- }
- }
-
-}
-
-static void
-CoreFocusEvents(DeviceIntPtr dev,
- WindowPtr from,
- WindowPtr to,
- int mode)
-{
- if (!IsMaster(dev))
- return;
-
- SetFocusOut(dev);
-
- if (((to == NullWindow) || (to == PointerRootWin)) &&
- ((from == NullWindow) || (from == PointerRootWin)))
- CoreFocusPointerRootNoneSwitch(dev, from, to, mode);
- else if ((to == NullWindow) || (to == PointerRootWin))
- CoreFocusToPointerRootOrNone(dev, from, to, mode);
- else if ((from == NullWindow) || (from == PointerRootWin))
- CoreFocusFromPointerRootOrNone(dev, from, to, mode);
- else if (IsParent(from, to))
- CoreFocusToDescendant(dev, from, to, mode);
- else if (IsParent(to, from))
- CoreFocusToAncestor(dev, from, to, mode);
- else
- CoreFocusNonLinear(dev, from, to, mode);
-
- SetFocusIn(dev, to);
-}
-
-/**
- * The root window the given device is currently on.
- */
-#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0]
-
-static void
-DeviceFocusEvents(DeviceIntPtr dev,
- WindowPtr from,
- WindowPtr to,
- int mode)
-{
- int out, in; /* for holding details for to/from
- PointerRoot/None */
- int i;
- int nscreens = screenInfo.numScreens;
- SpritePtr sprite = dev->spriteInfo->sprite;
-
- if (from == to)
- return;
- out = (from == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
- in = (to == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
- /* wrong values if neither, but then not referenced */
-
-#ifdef PANORAMIX
- if (!noPanoramiXExtension)
- nscreens = 1;
-#endif
-
- if ((to == NullWindow) || (to == PointerRootWin))
- {
- if ((from == NullWindow) || (from == PointerRootWin))
- {
- if (from == PointerRootWin)
- DeviceFocusOutEvents(dev, sprite->win, RootWindow(dev), mode,
- NotifyPointer);
- /* Notify all the roots */
- for (i = 0; i < nscreens; i++)
- DeviceFocusEvent(dev, XI_FocusOut, mode, out, WindowTable[i]);
- }
- else
- {
- if (IsParent(from, sprite->win))
- DeviceFocusOutEvents(dev, sprite->win, from, mode,
- NotifyPointer);
- DeviceFocusEvent(dev, XI_FocusOut, mode, NotifyNonlinear, from);
- /* next call catches the root too, if the screen changed */
- DeviceFocusOutEvents(dev, from->parent, NullWindow, mode,
- NotifyNonlinearVirtual);
- }
- /* Notify all the roots */
- for (i = 0; i < nscreens; i++)
- DeviceFocusEvent(dev, XI_FocusIn, mode, in, WindowTable[i]);
- if (to == PointerRootWin)
- DeviceFocusInEvents(dev, RootWindow(dev), sprite->win, mode, NotifyPointer);
- }
- else
- {
- if ((from == NullWindow) || (from == PointerRootWin))
- {
- if (from == PointerRootWin)
- DeviceFocusOutEvents(dev, sprite->win, RootWindow(dev), mode,
- NotifyPointer);
- for (i = 0; i < nscreens; i++)
- DeviceFocusEvent(dev, XI_FocusOut, mode, out, WindowTable[i]);
- if (to->parent != NullWindow)
- DeviceFocusInEvents(dev, RootWindow(dev), to, mode, NotifyNonlinearVirtual);
- DeviceFocusEvent(dev, XI_FocusIn, mode, NotifyNonlinear, to);
- if (IsParent(to, sprite->win))
- DeviceFocusInEvents(dev, to, sprite->win, mode, NotifyPointer);
- }
- else
- {
- if (IsParent(to, from))
- {
- DeviceFocusEvent(dev, XI_FocusOut, mode, NotifyAncestor, from);
- DeviceFocusOutEvents(dev, from->parent, to, mode,
- NotifyVirtual);
- DeviceFocusEvent(dev, XI_FocusIn, mode, NotifyInferior, to);
- if ((IsParent(to, sprite->win)) &&
- (sprite->win != from) &&
- (!IsParent(from, sprite->win)) &&
- (!IsParent(sprite->win, from)))
- DeviceFocusInEvents(dev, to, sprite->win, mode, NotifyPointer);
- }
- else
- if (IsParent(from, to))
- {
- if ((IsParent(from, sprite->win)) &&
- (sprite->win != from) &&
- (!IsParent(to, sprite->win)) &&
- (!IsParent(sprite->win, to)))
- DeviceFocusOutEvents(dev, sprite->win, from, mode,
- NotifyPointer);
- DeviceFocusEvent(dev, XI_FocusOut, mode, NotifyInferior, from);
- DeviceFocusInEvents(dev, from, to, mode, NotifyVirtual);
- DeviceFocusEvent(dev, XI_FocusIn, mode, NotifyAncestor, to);
- }
- else
- {
- /* neither from or to is child of other */
- WindowPtr common = CommonAncestor(to, from);
- /* common == NullWindow ==> different screens */
- if (IsParent(from, sprite->win))
- DeviceFocusOutEvents(dev, sprite->win, from, mode,
- NotifyPointer);
- DeviceFocusEvent(dev, XI_FocusOut, mode, NotifyNonlinear, from);
- if (from->parent != NullWindow)
- DeviceFocusOutEvents(dev, from->parent, common, mode,
- NotifyNonlinearVirtual);
- if (to->parent != NullWindow)
- DeviceFocusInEvents(dev, common, to, mode, NotifyNonlinearVirtual);
- DeviceFocusEvent(dev, XI_FocusIn, mode, NotifyNonlinear, to);
- if (IsParent(to, sprite->win))
- DeviceFocusInEvents(dev, to, sprite->win, mode, NotifyPointer);
- }
- }
- }
-}
-
-/**
- * Figure out if focus events are necessary and send them to the
- * appropriate windows.
- *
- * @param from Window the focus moved out of.
- * @param to Window the focus moved into.
- */
-void
-DoFocusEvents(DeviceIntPtr pDev,
- WindowPtr from,
- WindowPtr to,
- int mode)
-{
- if (!IsKeyboardDevice(pDev))
- return;
-
- if (from == to)
- return;
-
- CoreFocusEvents(pDev, from, to, mode);
- DeviceFocusEvents(pDev, from, to, mode);
-}
+/*
+ * Copyright © 2008 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.
+ *
+ * Authors: Peter Hutterer
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/extensions/XI2.h>
+#include "inputstr.h"
+#include "windowstr.h"
+#include "scrnintstr.h"
+#include "exglobals.h"
+#include "enterleave.h"
+
+/**
+ * @file
+ * This file describes the model for sending core enter/leave events and
+ * focus in/out in the case of multiple pointers/keyboard foci.
+ *
+ * Since we can't send more than one Enter or Leave/Focus in or out event per
+ * window to a core client without confusing it, this is a rather complicated
+ * approach.
+ *
+ * For a full description of the enter/leave model from a window's
+ * perspective, see
+ * http://lists.freedesktop.org/archives/xorg/2008-August/037606.html
+ *
+ * For a full description of the focus in/out model from a window's
+ * perspective, see
+ * http://lists.freedesktop.org/archives/xorg/2008-December/041740.html
+ *
+ * Additional notes:
+ * - The core protocol spec says that "In a LeaveNotify event, if a child of the
+ * event window contains the initial position of the pointer, then the child
+ * component is set to that child. Otherwise, it is None. For an EnterNotify
+ * event, if a child of the event window contains the final pointer position,
+ * then the child component is set to that child. Otherwise, it is None."
+ *
+ * By inference, this means that only NotifyVirtual or NotifyNonlinearVirtual
+ * events may have a subwindow set to other than None.
+ *
+ * - NotifyPointer events may be sent if the focus changes from window A to
+ * B. The assumption used in this model is that NotifyPointer events are only
+ * sent for the pointer paired with the keyboard that is involved in the focus
+ * events. For example, if F(W) changes because of keyboard 2, then
+ * NotifyPointer events are only sent for pointer 2.
+ */
+
+static WindowPtr PointerWindows[MAXDEVICES];
+static WindowPtr FocusWindows[MAXDEVICES];
+
+/**
+ * Return TRUE if 'win' has a pointer within its boundaries, excluding child
+ * window.
+ */
+static BOOL
+HasPointer(WindowPtr win)
+{
+ int i;
+
+ for (i = 0; i < MAXDEVICES; i++)
+ if (PointerWindows[i] == win)
+ return TRUE;
+
+ return FALSE;
+}
+
+/**
+ * Return TRUE if at least one keyboard focus is set to 'win' (excluding
+ * descendants of win).
+ */
+static BOOL
+HasFocus(WindowPtr win)
+{
+ int i;
+ for (i = 0; i < MAXDEVICES; i++)
+ if (FocusWindows[i] == win)
+ return TRUE;
+
+ return FALSE;
+}
+
+/**
+ * Return the window the device dev is currently on.
+ */
+static WindowPtr
+PointerWin(DeviceIntPtr dev)
+{
+ return PointerWindows[dev->id];
+}
+
+/**
+ * Search for the first window below 'win' that has a pointer directly within
+ * it's boundaries (excluding boundaries of its own descendants).
+ *
+ * @return The child window that has the pointer within its boundaries or
+ * NULL.
+ */
+static WindowPtr
+FirstPointerChild(WindowPtr win)
+{
+ int i;
+ for (i = 0; i < MAXDEVICES; i++)
+ {
+ if (PointerWindows[i] && IsParent(win, PointerWindows[i]))
+ return PointerWindows[i];
+ }
+
+ return NULL;
+}
+
+/**
+ * Search for the first window below 'win' that has a focus directly within
+ * it's boundaries (excluding boundaries of its own descendants).
+ *
+ * @return The child window that has the pointer within its boundaries or
+ * NULL.
+ */
+static WindowPtr
+FirstFocusChild(WindowPtr win)
+{
+ int i;
+ for (i = 0; i < MAXDEVICES; i++)
+ {
+ if (FocusWindows[i] && FocusWindows[i] != PointerRootWin &&
+ IsParent(win, FocusWindows[i]))
+ return FocusWindows[i];
+ }
+
+ return NULL;
+}
+
+/**
+ * Set the presence flag for dev to mark that it is now in 'win'.
+ */
+void
+EnterWindow(DeviceIntPtr dev, WindowPtr win, int mode)
+{
+ PointerWindows[dev->id] = win;
+}
+
+/**
+ * Unset the presence flag for dev to mark that it is not in 'win' anymore.
+ */
+void
+LeaveWindow(DeviceIntPtr dev)
+{
+ PointerWindows[dev->id] = NULL;
+}
+
+/**
+ * Set the presence flag for dev to mark that it is now in 'win'.
+ */
+void
+SetFocusIn(DeviceIntPtr dev, WindowPtr win)
+{
+ FocusWindows[dev->id] = win;
+}
+
+/**
+ * Unset the presence flag for dev to mark that it is not in 'win' anymore.
+ */
+void
+SetFocusOut(DeviceIntPtr dev)
+{
+ FocusWindows[dev->id] = NULL;
+}
+
+
+
+
+/**
+ * Return the common ancestor of 'a' and 'b' (if one exists).
+ * @param a A window with the same ancestor as b.
+ * @param b A window with the same ancestor as a.
+ * @return The window that is the first ancestor of both 'a' and 'b', or the
+ * NullWindow if they do not have a common ancestor.
+ */
+WindowPtr
+CommonAncestor(
+ WindowPtr a,
+ WindowPtr b)
+{
+ for (b = b->parent; b; b = b->parent)
+ if (IsParent(b, a)) return b;
+ return NullWindow;
+}
+
+
+/**
+ * Send enter notifies to all windows between 'ancestor' and 'child' (excluding
+ * both). Events are sent running up the window hierarchy. This function
+ * recurses.
+ */
+static void
+DeviceEnterNotifies(DeviceIntPtr dev,
+ int sourceid,
+ WindowPtr ancestor,
+ WindowPtr child,
+ int mode,
+ int detail)
+{
+ WindowPtr parent = child->parent;
+
+ if (ancestor == parent)
+ return;
+ DeviceEnterNotifies(dev, sourceid, ancestor, parent, mode, detail);
+ DeviceEnterLeaveEvent(dev, sourceid, XI_Enter, mode, detail, parent,
+ child->drawable.id);
+}
+
+/**
+ * Send enter notifies to all windows between 'ancestor' and 'child' (excluding
+ * both). Events are sent running down the window hierarchy. This function
+ * recurses.
+ */
+static void
+CoreEnterNotifies(DeviceIntPtr dev,
+ WindowPtr ancestor,
+ WindowPtr child,
+ int mode,
+ int detail)
+{
+ WindowPtr parent = child->parent;
+ if (ancestor == parent)
+ return;
+ CoreEnterNotifies(dev, ancestor, parent, mode, detail);
+
+
+ /* Case 3:
+ A is above W, B is a descendant
+
+ Classically: The move generates an EnterNotify on W with a detail of
+ Virtual or NonlinearVirtual
+
+ MPX:
+ Case 3A: There is at least one other pointer on W itself
+ P(W) doesn't change, so the event should be suppressed
+ Case 3B: Otherwise, if there is at least one other pointer in a
+ descendant
+ P(W) stays on the same descendant, or changes to a different
+ descendant. The event should be suppressed.
+ Case 3C: Otherwise:
+ P(W) moves from a window above W to a descendant. The subwindow
+ field is set to the child containing the descendant. The detail
+ may need to be changed from Virtual to NonlinearVirtual depending
+ on the previous P(W). */
+
+ if (!HasPointer(parent) && !FirstPointerChild(parent))
+ CoreEnterLeaveEvent(dev, EnterNotify, mode, detail, parent,
+ child->drawable.id);
+}
+
+static void
+CoreLeaveNotifies(DeviceIntPtr dev,
+ WindowPtr child,
+ WindowPtr ancestor,
+ int mode,
+ int detail)
+{
+ WindowPtr win;
+
+ if (ancestor == child)
+ return;
+
+ for (win = child->parent; win != ancestor; win = win->parent)
+ {
+ /*Case 7:
+ A is a descendant of W, B is above W
+
+ Classically: A LeaveNotify is generated on W with a detail of Virtual
+ or NonlinearVirtual.
+
+ MPX:
+ Case 3A: There is at least one other pointer on W itself
+ P(W) doesn't change, the event should be suppressed.
+ Case 3B: Otherwise, if there is at least one other pointer in a
+ descendant
+ P(W) stays on the same descendant, or changes to a different
+ descendant. The event should be suppressed.
+ Case 3C: Otherwise:
+ P(W) changes from the descendant of W to a window above W.
+ The detail may need to be changed from Virtual to NonlinearVirtual
+ or vice-versa depending on the new P(W).*/
+
+ /* If one window has a pointer or a child with a pointer, skip some
+ * work and exit. */
+ if (HasPointer(win) || FirstPointerChild(win))
+ return;
+
+ CoreEnterLeaveEvent(dev, LeaveNotify, mode, detail, win, child->drawable.id);
+
+ child = win;
+ }
+}
+
+/**
+ * Send leave notifies to all windows between 'child' and 'ancestor'.
+ * Events are sent running up the hierarchy.
+ */
+static void
+DeviceLeaveNotifies(DeviceIntPtr dev,
+ int sourceid,
+ WindowPtr child,
+ WindowPtr ancestor,
+ int mode,
+ int detail)
+{
+ WindowPtr win;
+
+ if (ancestor == child)
+ return;
+ for (win = child->parent; win != ancestor; win = win->parent)
+ {
+ DeviceEnterLeaveEvent(dev, sourceid, XI_Leave, mode, detail, win,
+ child->drawable.id);
+ child = win;
+ }
+}
+
+/**
+ * Pointer dev moves from A to B and A neither a descendant of B nor is
+ * B a descendant of A.
+ */
+static void
+CoreEnterLeaveNonLinear(DeviceIntPtr dev,
+ WindowPtr A,
+ WindowPtr B,
+ int mode)
+{
+ WindowPtr X = CommonAncestor(A, B);
+ /* Case 4:
+ A is W, B is above W
+
+ Classically: The move generates a LeaveNotify on W with a detail of
+ Ancestor or Nonlinear
+
+ MPX:
+ Case 3A: There is at least one other pointer on W itself
+ P(W) doesn't change, the event should be suppressed
+ Case 3B: Otherwise, if there is at least one other pointer in a
+ descendant of W
+ P(W) changes from W to a descendant of W. The subwindow field
+ is set to the child containing the new P(W), the detail field
+ is set to Inferior
+ Case 3C: Otherwise:
+ The pointer window moves from W to a window above W.
+ The detail may need to be changed from Ancestor to Nonlinear or
+ vice versa depending on the the new P(W)
+ */
+
+ if (!HasPointer(A))
+ {
+ WindowPtr child = FirstPointerChild(A);
+ if (child)
+ CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, None);
+ else
+ CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyNonlinear, A, None);
+ }
+
+
+ CoreLeaveNotifies(dev, A, X, mode, NotifyNonlinearVirtual);
+
+ /*
+ Case 9:
+ A is a descendant of W, B is a descendant of W
+
+ Classically: No events are generated on W
+ MPX: The pointer window stays the same or moves to a different
+ descendant of W. No events should be generated on W.
+
+
+ Therefore, no event to X.
+ */
+
+ CoreEnterNotifies(dev, X, B, mode, NotifyNonlinearVirtual);
+
+ /* Case 2:
+ A is above W, B=W
+
+ Classically: The move generates an EnterNotify on W with a detail of
+ Ancestor or Nonlinear
+
+ MPX:
+ Case 2A: There is at least one other pointer on W itself
+ P(W) doesn't change, so the event should be suppressed
+ Case 2B: Otherwise, if there is at least one other pointer in a
+ descendant
+ P(W) moves from a descendant to W. detail is changed to Inferior,
+ subwindow is set to the child containing the previous P(W)
+ Case 2C: Otherwise:
+ P(W) changes from a window above W to W itself.
+ The detail may need to be changed from Ancestor to Nonlinear
+ or vice-versa depending on the previous P(W). */
+
+ if (!HasPointer(B))
+ {
+ WindowPtr child = FirstPointerChild(B);
+ if (child)
+ CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyInferior, B, None);
+ else
+ CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyNonlinear, B, None);
+ }
+}
+
+/**
+ * Pointer dev moves from A to B and A is a descendant of B.
+ */
+static void
+CoreEnterLeaveToAncestor(DeviceIntPtr dev,
+ WindowPtr A,
+ WindowPtr B,
+ int mode)
+{
+ /* Case 4:
+ A is W, B is above W
+
+ Classically: The move generates a LeaveNotify on W with a detail of
+ Ancestor or Nonlinear
+
+ MPX:
+ Case 3A: There is at least one other pointer on W itself
+ P(W) doesn't change, the event should be suppressed
+ Case 3B: Otherwise, if there is at least one other pointer in a
+ descendant of W
+ P(W) changes from W to a descendant of W. The subwindow field
+ is set to the child containing the new P(W), the detail field
+ is set to Inferior
+ Case 3C: Otherwise:
+ The pointer window moves from W to a window above W.
+ The detail may need to be changed from Ancestor to Nonlinear or
+ vice versa depending on the the new P(W)
+ */
+ if (!HasPointer(A))
+ {
+ WindowPtr child = FirstPointerChild(A);
+ if (child)
+ CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, None);
+ else
+ CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyAncestor, A, None);
+ }
+
+ CoreLeaveNotifies(dev, A, B, mode, NotifyVirtual);
+
+ /* Case 8:
+ A is a descendant of W, B is W
+
+ Classically: A EnterNotify is generated on W with a detail of
+ NotifyInferior
+
+ MPX:
+ Case 3A: There is at least one other pointer on W itself
+ P(W) doesn't change, the event should be suppressed
+ Case 3B: Otherwise:
+ P(W) changes from a descendant to W itself. The subwindow
+ field should be set to the child containing the old P(W) <<< WRONG */
+
+ if (!HasPointer(B))
+ CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyInferior, B, None);
+
+}
+
+
+/**
+ * Pointer dev moves from A to B and B is a descendant of A.
+ */
+static void
+CoreEnterLeaveToDescendant(DeviceIntPtr dev,
+ WindowPtr A,
+ WindowPtr B,
+ int mode)
+{
+ /* Case 6:
+ A is W, B is a descendant of W
+
+ Classically: A LeaveNotify is generated on W with a detail of
+ NotifyInferior
+
+ MPX:
+ Case 3A: There is at least one other pointer on W itself
+ P(W) doesn't change, the event should be suppressed
+ Case 3B: Otherwise:
+ P(W) changes from W to a descendant of W. The subwindow field
+ is set to the child containing the new P(W) <<< THIS IS WRONG */
+
+ if (!HasPointer(A))
+ CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, None);
+
+
+ CoreEnterNotifies(dev, A, B, mode, NotifyVirtual);
+
+ /* Case 2:
+ A is above W, B=W
+
+ Classically: The move generates an EnterNotify on W with a detail of
+ Ancestor or Nonlinear
+
+ MPX:
+ Case 2A: There is at least one other pointer on W itself
+ P(W) doesn't change, so the event should be suppressed
+ Case 2B: Otherwise, if there is at least one other pointer in a
+ descendant
+ P(W) moves from a descendant to W. detail is changed to Inferior,
+ subwindow is set to the child containing the previous P(W)
+ Case 2C: Otherwise:
+ P(W) changes from a window above W to W itself.
+ The detail may need to be changed from Ancestor to Nonlinear
+ or vice-versa depending on the previous P(W). */
+
+ if (!HasPointer(B))
+ {
+ WindowPtr child = FirstPointerChild(B);
+ if (child)
+ CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyInferior, B, None);
+ else
+ CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyAncestor, B, None);
+ }
+}
+
+static void
+CoreEnterLeaveEvents(DeviceIntPtr dev,
+ WindowPtr from,
+ WindowPtr to,
+ int mode)
+{
+ if (!IsMaster(dev))
+ return;
+
+ LeaveWindow(dev);
+
+ if (IsParent(from, to))
+ CoreEnterLeaveToDescendant(dev, from, to, mode);
+ else if (IsParent(to, from))
+ CoreEnterLeaveToAncestor(dev, from, to, mode);
+ else
+ CoreEnterLeaveNonLinear(dev, from, to, mode);
+
+ EnterWindow(dev, to, mode);
+}
+
+static void
+DeviceEnterLeaveEvents(DeviceIntPtr dev,
+ int sourceid,
+ WindowPtr from,
+ WindowPtr to,
+ int mode)
+{
+ if (IsParent(from, to))
+ {
+ DeviceEnterLeaveEvent(dev, sourceid, XI_Leave, mode, NotifyInferior, from, None);
+ DeviceEnterNotifies(dev, sourceid, from, to, mode, NotifyVirtual);
+ DeviceEnterLeaveEvent(dev, sourceid, XI_Enter, mode, NotifyAncestor, to, None);
+ }
+ else if (IsParent(to, from))
+ {
+ DeviceEnterLeaveEvent(dev, sourceid, XI_Leave, mode, NotifyAncestor, from, None);
+ DeviceLeaveNotifies(dev, sourceid, from, to, mode, NotifyVirtual);
+ DeviceEnterLeaveEvent(dev, sourceid, XI_Enter, mode, NotifyInferior, to, None);
+ }
+ else
+ { /* neither from nor to is descendent of the other */
+ WindowPtr common = CommonAncestor(to, from);
+ /* common == NullWindow ==> different screens */
+ DeviceEnterLeaveEvent(dev, sourceid, XI_Leave, mode, NotifyNonlinear, from, None);
+ DeviceLeaveNotifies(dev, sourceid, from, common, mode, NotifyNonlinearVirtual);
+ DeviceEnterNotifies(dev, sourceid, common, to, mode, NotifyNonlinearVirtual);
+ DeviceEnterLeaveEvent(dev, sourceid, XI_Enter, mode, NotifyNonlinear, to, None);
+ }
+}
+
+/**
+ * Figure out if enter/leave events are necessary and send them to the
+ * appropriate windows.
+ *
+ * @param fromWin Window the sprite moved out of.
+ * @param toWin Window the sprite moved into.
+ */
+void
+DoEnterLeaveEvents(DeviceIntPtr pDev,
+ int sourceid,
+ WindowPtr fromWin,
+ WindowPtr toWin,
+ int mode)
+{
+ if (!IsPointerDevice(pDev))
+ return;
+
+ if (fromWin == toWin)
+ return;
+
+ if (mode != XINotifyPassiveGrab && mode != XINotifyPassiveUngrab)
+ CoreEnterLeaveEvents(pDev, fromWin, toWin, mode);
+ DeviceEnterLeaveEvents(pDev, sourceid, fromWin, toWin, mode);
+}
+
+/**
+ * Send focus out events to all windows between 'child' and 'ancestor'.
+ * Events are sent running up the hierarchy.
+ */
+static void
+DeviceFocusOutEvents(DeviceIntPtr dev,
+ WindowPtr child,
+ WindowPtr ancestor,
+ int mode,
+ int detail)
+{
+ WindowPtr win;
+
+ if (ancestor == child)
+ return;
+ for (win = child->parent; win != ancestor; win = win->parent)
+ DeviceFocusEvent(dev, XI_FocusOut, mode, detail, win);
+}
+
+
+/**
+ * Send enter notifies to all windows between 'ancestor' and 'child' (excluding
+ * both). Events are sent running up the window hierarchy. This function
+ * recurses.
+ */
+static void
+DeviceFocusInEvents(DeviceIntPtr dev,
+ WindowPtr ancestor,
+ WindowPtr child,
+ int mode,
+ int detail)
+{
+ WindowPtr parent = child->parent;
+
+ if (ancestor == parent || !parent)
+ return;
+ DeviceFocusInEvents(dev, ancestor, parent, mode, detail);
+ DeviceFocusEvent(dev, XI_FocusIn, mode, detail, parent);
+}
+
+/**
+ * Send FocusIn events to all windows between 'ancestor' and 'child' (excluding
+ * both). Events are sent running down the window hierarchy. This function
+ * recurses.
+ */
+static void
+CoreFocusInEvents(DeviceIntPtr dev,
+ WindowPtr ancestor,
+ WindowPtr child,
+ int mode,
+ int detail)
+{
+ WindowPtr parent = child->parent;
+ if (ancestor == parent)
+ return;
+ CoreFocusInEvents(dev, ancestor, parent, mode, detail);
+
+
+ /* Case 3:
+ A is above W, B is a descendant
+
+ Classically: The move generates an FocusIn on W with a detail of
+ Virtual or NonlinearVirtual
+
+ MPX:
+ Case 3A: There is at least one other focus on W itself
+ F(W) doesn't change, so the event should be suppressed
+ Case 3B: Otherwise, if there is at least one other focus in a
+ descendant
+ F(W) stays on the same descendant, or changes to a different
+ descendant. The event should be suppressed.
+ Case 3C: Otherwise:
+ F(W) moves from a window above W to a descendant. The detail may
+ need to be changed from Virtual to NonlinearVirtual depending
+ on the previous F(W). */
+
+ if (!HasFocus(parent) && !FirstFocusChild(parent))
+ CoreFocusEvent(dev, FocusIn, mode, detail, parent);
+}
+
+static void
+CoreFocusOutEvents(DeviceIntPtr dev,
+ WindowPtr child,
+ WindowPtr ancestor,
+ int mode,
+ int detail)
+{
+ WindowPtr win;
+
+ if (ancestor == child)
+ return;
+
+ for (win = child->parent; win != ancestor; win = win->parent)
+ {
+ /*Case 7:
+ A is a descendant of W, B is above W
+
+ Classically: A FocusOut is generated on W with a detail of Virtual
+ or NonlinearVirtual.
+
+ MPX:
+ Case 3A: There is at least one other focus on W itself
+ F(W) doesn't change, the event should be suppressed.
+ Case 3B: Otherwise, if there is at least one other focus in a
+ descendant
+ F(W) stays on the same descendant, or changes to a different
+ descendant. The event should be suppressed.
+ Case 3C: Otherwise:
+ F(W) changes from the descendant of W to a window above W.
+ The detail may need to be changed from Virtual to NonlinearVirtual
+ or vice-versa depending on the new P(W).*/
+
+ /* If one window has a focus or a child with a focuspointer, skip some
+ * work and exit. */
+ if (HasFocus(win) || FirstFocusChild(win))
+ return;
+
+ CoreFocusEvent(dev, FocusOut, mode, detail, win);
+ }
+}
+
+/**
+ * Send FocusOut(NotifyPointer) events from the current pointer window (which
+ * is a descendant of pwin_parent) up to (excluding) pwin_parent.
+ *
+ * NotifyPointer events are only sent for the device paired with dev.
+ *
+ * If the current pointer window is a descendant of 'exclude' or an ancestor of
+ * 'exclude', no events are sent. If the current pointer IS 'exclude', events
+ * are sent!
+ */
+static void
+CoreFocusOutNotifyPointerEvents(DeviceIntPtr dev,
+ WindowPtr pwin_parent,
+ WindowPtr exclude,
+ int mode,
+ int inclusive)
+{
+ WindowPtr P, stopAt;
+
+ P = PointerWin(GetPairedDevice(dev));
+
+ if (!P)
+ return;
+ if (!IsParent(pwin_parent, P))
+ if (!(pwin_parent == P && inclusive))
+ return;
+
+ if (exclude != None && exclude != PointerRootWin &&
+ (IsParent(exclude, P) || IsParent(P, exclude)))
+ return;
+
+ stopAt = (inclusive) ? pwin_parent->parent : pwin_parent;
+
+ for (; P && P != stopAt; P = P->parent)
+ CoreFocusEvent(dev, FocusOut, mode, NotifyPointer, P);
+}
+
+/**
+ * DO NOT CALL DIRECTLY.
+ * Recursion helper for CoreFocusInNotifyPointerEvents.
+ */
+static void
+CoreFocusInRecurse(DeviceIntPtr dev,
+ WindowPtr win,
+ WindowPtr stopAt,
+ int mode,
+ int inclusive)
+{
+ if ((!inclusive && win == stopAt) || !win)
+ return;
+
+ CoreFocusInRecurse(dev, win->parent, stopAt, mode, inclusive);
+ CoreFocusEvent(dev, FocusIn, mode, NotifyPointer, win);
+}
+
+
+/**
+ * Send FocusIn(NotifyPointer) events from pwin_parent down to
+ * including the current pointer window (which is a descendant of pwin_parent).
+ *
+ * @param pwin The pointer window.
+ * @param exclude If the pointer window is a child of 'exclude', no events are
+ * sent.
+ * @param inclusive If TRUE, pwin_parent will receive the event too.
+ */
+static void
+CoreFocusInNotifyPointerEvents(DeviceIntPtr dev,
+ WindowPtr pwin_parent,
+ WindowPtr exclude,
+ int mode,
+ int inclusive)
+{
+ WindowPtr P;
+
+ P = PointerWin(GetPairedDevice(dev));
+
+ if (!P || P == exclude || (pwin_parent != P && !IsParent(pwin_parent, P)))
+ return;
+
+ if (exclude != None && (IsParent(exclude, P) || IsParent(P, exclude)))
+ return;
+
+ CoreFocusInRecurse(dev, P, pwin_parent, mode, inclusive);
+}
+
+
+/**
+ * Focus of dev moves from A to B and A neither a descendant of B nor is
+ * B a descendant of A.
+ */
+static void
+CoreFocusNonLinear(DeviceIntPtr dev,
+ WindowPtr A,
+ WindowPtr B,
+ int mode)
+{
+ WindowPtr X = CommonAncestor(A, B);
+
+ /* Case 4:
+ A is W, B is above W
+
+ Classically: The change generates a FocusOut on W with a detail of
+ Ancestor or Nonlinear
+
+ MPX:
+ Case 3A: There is at least one other focus on W itself
+ F(W) doesn't change, the event should be suppressed
+ Case 3B: Otherwise, if there is at least one other focus in a
+ descendant of W
+ F(W) changes from W to a descendant of W. The detail field
+ is set to Inferior
+ Case 3C: Otherwise:
+ The focus window moves from W to a window above W.
+ The detail may need to be changed from Ancestor to Nonlinear or
+ vice versa depending on the the new F(W)
+ */
+
+ if (!HasFocus(A))
+ {
+ WindowPtr child = FirstFocusChild(A);
+ if (child)
+ {
+ /* NotifyPointer P-A unless P is child or below*/
+ CoreFocusOutNotifyPointerEvents(dev, A, child, mode, FALSE);
+ CoreFocusEvent(dev, FocusOut, mode, NotifyInferior, A);
+ } else
+ {
+ /* NotifyPointer P-A */
+ CoreFocusOutNotifyPointerEvents(dev, A, None, mode, FALSE);
+ CoreFocusEvent(dev, FocusOut, mode, NotifyNonlinear, A);
+ }
+ }
+
+
+ CoreFocusOutEvents(dev, A, X, mode, NotifyNonlinearVirtual);
+
+ /*
+ Case 9:
+ A is a descendant of W, B is a descendant of W
+
+ Classically: No events are generated on W
+ MPX: The focus window stays the same or moves to a different
+ descendant of W. No events should be generated on W.
+
+
+ Therefore, no event to X.
+ */
+
+ CoreFocusInEvents(dev, X, B, mode, NotifyNonlinearVirtual);
+
+ /* Case 2:
+ A is above W, B=W
+
+ Classically: The move generates an EnterNotify on W with a detail of
+ Ancestor or Nonlinear
+
+ MPX:
+ Case 2A: There is at least one other focus on W itself
+ F(W) doesn't change, so the event should be suppressed
+ Case 2B: Otherwise, if there is at least one other focus in a
+ descendant
+ F(W) moves from a descendant to W. detail is changed to Inferior.
+ Case 2C: Otherwise:
+ F(W) changes from a window above W to W itself.
+ The detail may need to be changed from Ancestor to Nonlinear
+ or vice-versa depending on the previous F(W). */
+
+ if (!HasFocus(B))
+ {
+ WindowPtr child = FirstFocusChild(B);
+ if (child)
+ {
+ CoreFocusEvent(dev, FocusIn, mode, NotifyInferior, B);
+ /* NotifyPointer B-P unless P is child or below. */
+ CoreFocusInNotifyPointerEvents(dev, B, child, mode, FALSE);
+ } else {
+ CoreFocusEvent(dev, FocusIn, mode, NotifyNonlinear, B);
+ /* NotifyPointer B-P unless P is child or below. */
+ CoreFocusInNotifyPointerEvents(dev, B, None, mode, FALSE);
+ }
+ }
+}
+
+
+/**
+ * Focus of dev moves from A to B and A is a descendant of B.
+ */
+static void
+CoreFocusToAncestor(DeviceIntPtr dev,
+ WindowPtr A,
+ WindowPtr B,
+ int mode)
+{
+ /* Case 4:
+ A is W, B is above W
+
+ Classically: The change generates a FocusOut on W with a detail of
+ Ancestor or Nonlinear
+
+ MPX:
+ Case 3A: There is at least one other focus on W itself
+ F(W) doesn't change, the event should be suppressed
+ Case 3B: Otherwise, if there is at least one other focus in a
+ descendant of W
+ F(W) changes from W to a descendant of W. The detail field
+ is set to Inferior
+ Case 3C: Otherwise:
+ The focus window moves from W to a window above W.
+ The detail may need to be changed from Ancestor to Nonlinear or
+ vice versa depending on the the new F(W)
+ */
+ if (!HasFocus(A))
+ {
+ WindowPtr child = FirstFocusChild(A);
+ if (child)
+ {
+ /* NotifyPointer P-A unless P is child or below*/
+ CoreFocusOutNotifyPointerEvents(dev, A, child, mode, FALSE);
+ CoreFocusEvent(dev, FocusOut, mode, NotifyInferior, A);
+ } else
+ CoreFocusEvent(dev, FocusOut, mode, NotifyAncestor, A);
+ }
+
+ CoreFocusOutEvents(dev, A, B, mode, NotifyVirtual);
+
+ /* Case 8:
+ A is a descendant of W, B is W
+
+ Classically: A FocusOut is generated on W with a detail of
+ NotifyInferior
+
+ MPX:
+ Case 3A: There is at least one other focus on W itself
+ F(W) doesn't change, the event should be suppressed
+ Case 3B: Otherwise:
+ F(W) changes from a descendant to W itself. */
+
+ if (!HasFocus(B))
+ {
+ CoreFocusEvent(dev, FocusIn, mode, NotifyInferior, B);
+ /* NotifyPointer B-P unless P is A or below. */
+ CoreFocusInNotifyPointerEvents(dev, B, A, mode, FALSE);
+ }
+}
+
+/**
+ * Focus of dev moves from A to B and B is a descendant of A.
+ */
+static void
+CoreFocusToDescendant(DeviceIntPtr dev,
+ WindowPtr A,
+ WindowPtr B,
+ int mode)
+{
+ /* Case 6:
+ A is W, B is a descendant of W
+
+ Classically: A FocusOut is generated on W with a detail of
+ NotifyInferior
+
+ MPX:
+ Case 3A: There is at least one other focus on W itself
+ F(W) doesn't change, the event should be suppressed
+ Case 3B: Otherwise:
+ F(W) changes from W to a descendant of W. */
+
+ if (!HasFocus(A))
+ {
+ /* NotifyPointer P-A unless P is B or below*/
+ CoreFocusOutNotifyPointerEvents(dev, A, B, mode, FALSE);
+ CoreFocusEvent(dev, FocusOut, mode, NotifyInferior, A);
+ }
+
+
+ CoreFocusInEvents(dev, A, B, mode, NotifyVirtual);
+
+ /* Case 2:
+ A is above W, B=W
+
+ Classically: The move generates an FocusIn on W with a detail of
+ Ancestor or Nonlinear
+
+ MPX:
+ Case 2A: There is at least one other focus on W itself
+ F(W) doesn't change, so the event should be suppressed
+ Case 2B: Otherwise, if there is at least one other focus in a
+ descendant
+ F(W) moves from a descendant to W. detail is changed to Inferior.
+ Case 2C: Otherwise:
+ F(W) changes from a window above W to W itself.
+ The detail may need to be changed from Ancestor to Nonlinear
+ or vice-versa depending on the previous F(W). */
+
+ if (!HasFocus(B))
+ {
+ WindowPtr child = FirstFocusChild(B);
+ if (child)
+ {
+ CoreFocusEvent(dev, FocusIn, mode, NotifyInferior, B);
+ /* NotifyPointer B-P unless P is child or below. */
+ CoreFocusInNotifyPointerEvents(dev, B, child, mode, FALSE);
+ } else
+ CoreFocusEvent(dev, FocusIn, mode, NotifyAncestor, B);
+ }
+}
+
+static BOOL
+HasOtherPointer(WindowPtr win, DeviceIntPtr exclude)
+{
+ int i;
+
+ for (i = 0; i < MAXDEVICES; i++)
+ if (i != exclude->id && PointerWindows[i] == win)
+ return TRUE;
+
+ return FALSE;
+}
+
+/**
+ * Focus moves from PointerRoot to None or from None to PointerRoot.
+ * Assumption: Neither A nor B are valid windows.
+ */
+static void
+CoreFocusPointerRootNoneSwitch(DeviceIntPtr dev,
+ WindowPtr A, /* PointerRootWin or NoneWin */
+ WindowPtr B, /* NoneWin or PointerRootWin */
+ int mode)
+{
+ WindowPtr root;
+ int i;
+ int nscreens = screenInfo.numScreens;
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ nscreens = 1;
+#endif
+
+ for (i = 0; i < nscreens; i++)
+ {
+ root = screenInfo.screens[i]->root;
+ if (!HasOtherPointer(root, GetPairedDevice(dev)) && !FirstFocusChild(root))
+ {
+ /* If pointer was on PointerRootWin and changes to NoneWin, and
+ * the pointer paired with dev is below the current root window,
+ * do a NotifyPointer run. */
+ if (dev->focus && dev->focus->win == PointerRootWin &&
+ B != PointerRootWin)
+ {
+ WindowPtr ptrwin = PointerWin(GetPairedDevice(dev));
+ if (ptrwin && IsParent(root, ptrwin))
+ CoreFocusOutNotifyPointerEvents(dev, root, None, mode, TRUE);
+ }
+ CoreFocusEvent(dev, FocusOut, mode, A ? NotifyPointerRoot : NotifyDetailNone, root);
+ CoreFocusEvent(dev, FocusIn, mode, B ? NotifyPointerRoot : NotifyDetailNone, root);
+ if (B == PointerRootWin)
+ CoreFocusInNotifyPointerEvents(dev, root, None, mode, TRUE);
+ }
+
+ }
+}
+
+/**
+ * Focus moves from window A to PointerRoot or to None.
+ * Assumption: A is a valid window and not PointerRoot or None.
+ */
+static void
+CoreFocusToPointerRootOrNone(DeviceIntPtr dev,
+ WindowPtr A,
+ WindowPtr B, /* PointerRootWin or NoneWin */
+ int mode)
+{
+ WindowPtr root;
+ int i;
+ int nscreens = screenInfo.numScreens;
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ nscreens = 1;
+#endif
+
+ if (!HasFocus(A))
+ {
+ WindowPtr child = FirstFocusChild(A);
+ if (child)
+ {
+ /* NotifyPointer P-A unless P is B or below*/
+ CoreFocusOutNotifyPointerEvents(dev, A, B, mode, FALSE);
+ CoreFocusEvent(dev, FocusOut, mode, NotifyInferior, A);
+ } else {
+ /* NotifyPointer P-A */
+ CoreFocusOutNotifyPointerEvents(dev, A, None, mode, FALSE);
+ CoreFocusEvent(dev, FocusOut, mode, NotifyNonlinear, A);
+ }
+ }
+
+ /* NullWindow means we include the root window */
+ CoreFocusOutEvents(dev, A, NullWindow, mode, NotifyNonlinearVirtual);
+
+ for (i = 0; i < nscreens; i++)
+ {
+ root = screenInfo.screens[i]->root;
+ if (!HasFocus(root) && !FirstFocusChild(root))
+ {
+ CoreFocusEvent(dev, FocusIn, mode, B ? NotifyPointerRoot : NotifyDetailNone, root);
+ if (B == PointerRootWin)
+ CoreFocusInNotifyPointerEvents(dev, root, None, mode, TRUE);
+ }
+ }
+}
+
+/**
+ * Focus moves from PointerRoot or None to a window B.
+ * Assumption: B is a valid window and not PointerRoot or None.
+ */
+static void
+CoreFocusFromPointerRootOrNone(DeviceIntPtr dev,
+ WindowPtr A, /* PointerRootWin or NoneWin */
+ WindowPtr B,
+ int mode)
+{
+ WindowPtr root;
+ int i;
+ int nscreens = screenInfo.numScreens;
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ nscreens = 1;
+#endif
+
+ for (i = 0; i < nscreens; i++)
+ {
+ root = screenInfo.screens[i]->root;
+ if (!HasFocus(root) && !FirstFocusChild(root))
+ {
+ /* If pointer was on PointerRootWin and changes to NoneWin, and
+ * the pointer paired with dev is below the current root window,
+ * do a NotifyPointer run. */
+ if (dev->focus && dev->focus->win == PointerRootWin &&
+ B != PointerRootWin)
+ {
+ WindowPtr ptrwin = PointerWin(GetPairedDevice(dev));
+ if (ptrwin)
+ CoreFocusOutNotifyPointerEvents(dev, root, None, mode, TRUE);
+ }
+ CoreFocusEvent(dev, FocusOut, mode, A ? NotifyPointerRoot : NotifyDetailNone, root);
+ }
+ }
+
+ root = B; /* get B's root window */
+ while(root->parent)
+ root = root->parent;
+
+ if (B != root)
+ {
+ CoreFocusEvent(dev, FocusIn, mode, NotifyNonlinearVirtual, root);
+ CoreFocusInEvents(dev, root, B, mode, NotifyNonlinearVirtual);
+ }
+
+
+ if (!HasFocus(B))
+ {
+ WindowPtr child = FirstFocusChild(B);
+ if (child)
+ {
+ CoreFocusEvent(dev, FocusIn, mode, NotifyInferior, B);
+ /* NotifyPointer B-P unless P is child or below. */
+ CoreFocusInNotifyPointerEvents(dev, B, child, mode, FALSE);
+ } else {
+ CoreFocusEvent(dev, FocusIn, mode, NotifyNonlinear, B);
+ /* NotifyPointer B-P unless P is child or below. */
+ CoreFocusInNotifyPointerEvents(dev, B, None, mode, FALSE);
+ }
+ }
+
+}
+
+static void
+CoreFocusEvents(DeviceIntPtr dev,
+ WindowPtr from,
+ WindowPtr to,
+ int mode)
+{
+ if (!IsMaster(dev))
+ return;
+
+ SetFocusOut(dev);
+
+ if (((to == NullWindow) || (to == PointerRootWin)) &&
+ ((from == NullWindow) || (from == PointerRootWin)))
+ CoreFocusPointerRootNoneSwitch(dev, from, to, mode);
+ else if ((to == NullWindow) || (to == PointerRootWin))
+ CoreFocusToPointerRootOrNone(dev, from, to, mode);
+ else if ((from == NullWindow) || (from == PointerRootWin))
+ CoreFocusFromPointerRootOrNone(dev, from, to, mode);
+ else if (IsParent(from, to))
+ CoreFocusToDescendant(dev, from, to, mode);
+ else if (IsParent(to, from))
+ CoreFocusToAncestor(dev, from, to, mode);
+ else
+ CoreFocusNonLinear(dev, from, to, mode);
+
+ SetFocusIn(dev, to);
+}
+
+/**
+ * The root window the given device is currently on.
+ */
+#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0]
+
+static void
+DeviceFocusEvents(DeviceIntPtr dev,
+ WindowPtr from,
+ WindowPtr to,
+ int mode)
+{
+ int out, in; /* for holding details for to/from
+ PointerRoot/None */
+ int i;
+ int nscreens = screenInfo.numScreens;
+ SpritePtr sprite = dev->spriteInfo->sprite;
+
+ if (from == to)
+ return;
+ out = (from == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
+ in = (to == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
+ /* wrong values if neither, but then not referenced */
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ nscreens = 1;
+#endif
+
+ if ((to == NullWindow) || (to == PointerRootWin))
+ {
+ if ((from == NullWindow) || (from == PointerRootWin))
+ {
+ if (from == PointerRootWin)
+ DeviceFocusOutEvents(dev, sprite->win, RootWindow(dev), mode,
+ NotifyPointer);
+ /* Notify all the roots */
+ for (i = 0; i < nscreens; i++)
+ DeviceFocusEvent(dev, XI_FocusOut, mode, out, screenInfo.screens[i]->root);
+ }
+ else
+ {
+ if (IsParent(from, sprite->win))
+ DeviceFocusOutEvents(dev, sprite->win, from, mode,
+ NotifyPointer);
+ DeviceFocusEvent(dev, XI_FocusOut, mode, NotifyNonlinear, from);
+ /* next call catches the root too, if the screen changed */
+ DeviceFocusOutEvents(dev, from->parent, NullWindow, mode,
+ NotifyNonlinearVirtual);
+ }
+ /* Notify all the roots */
+ for (i = 0; i < nscreens; i++)
+ DeviceFocusEvent(dev, XI_FocusIn, mode, in, screenInfo.screens[i]->root);
+ if (to == PointerRootWin)
+ DeviceFocusInEvents(dev, RootWindow(dev), sprite->win, mode, NotifyPointer);
+ }
+ else
+ {
+ if ((from == NullWindow) || (from == PointerRootWin))
+ {
+ if (from == PointerRootWin)
+ DeviceFocusOutEvents(dev, sprite->win, RootWindow(dev), mode,
+ NotifyPointer);
+ for (i = 0; i < nscreens; i++)
+ DeviceFocusEvent(dev, XI_FocusOut, mode, out, screenInfo.screens[i]->root);
+ if (to->parent != NullWindow)
+ DeviceFocusInEvents(dev, RootWindow(dev), to, mode, NotifyNonlinearVirtual);
+ DeviceFocusEvent(dev, XI_FocusIn, mode, NotifyNonlinear, to);
+ if (IsParent(to, sprite->win))
+ DeviceFocusInEvents(dev, to, sprite->win, mode, NotifyPointer);
+ }
+ else
+ {
+ if (IsParent(to, from))
+ {
+ DeviceFocusEvent(dev, XI_FocusOut, mode, NotifyAncestor, from);
+ DeviceFocusOutEvents(dev, from->parent, to, mode,
+ NotifyVirtual);
+ DeviceFocusEvent(dev, XI_FocusIn, mode, NotifyInferior, to);
+ if ((IsParent(to, sprite->win)) &&
+ (sprite->win != from) &&
+ (!IsParent(from, sprite->win)) &&
+ (!IsParent(sprite->win, from)))
+ DeviceFocusInEvents(dev, to, sprite->win, mode, NotifyPointer);
+ }
+ else
+ if (IsParent(from, to))
+ {
+ if ((IsParent(from, sprite->win)) &&
+ (sprite->win != from) &&
+ (!IsParent(to, sprite->win)) &&
+ (!IsParent(sprite->win, to)))
+ DeviceFocusOutEvents(dev, sprite->win, from, mode,
+ NotifyPointer);
+ DeviceFocusEvent(dev, XI_FocusOut, mode, NotifyInferior, from);
+ DeviceFocusInEvents(dev, from, to, mode, NotifyVirtual);
+ DeviceFocusEvent(dev, XI_FocusIn, mode, NotifyAncestor, to);
+ }
+ else
+ {
+ /* neither from or to is child of other */
+ WindowPtr common = CommonAncestor(to, from);
+ /* common == NullWindow ==> different screens */
+ if (IsParent(from, sprite->win))
+ DeviceFocusOutEvents(dev, sprite->win, from, mode,
+ NotifyPointer);
+ DeviceFocusEvent(dev, XI_FocusOut, mode, NotifyNonlinear, from);
+ if (from->parent != NullWindow)
+ DeviceFocusOutEvents(dev, from->parent, common, mode,
+ NotifyNonlinearVirtual);
+ if (to->parent != NullWindow)
+ DeviceFocusInEvents(dev, common, to, mode, NotifyNonlinearVirtual);
+ DeviceFocusEvent(dev, XI_FocusIn, mode, NotifyNonlinear, to);
+ if (IsParent(to, sprite->win))
+ DeviceFocusInEvents(dev, to, sprite->win, mode, NotifyPointer);
+ }
+ }
+ }
+}
+
+/**
+ * Figure out if focus events are necessary and send them to the
+ * appropriate windows.
+ *
+ * @param from Window the focus moved out of.
+ * @param to Window the focus moved into.
+ */
+void
+DoFocusEvents(DeviceIntPtr pDev,
+ WindowPtr from,
+ WindowPtr to,
+ int mode)
+{
+ if (!IsKeyboardDevice(pDev))
+ return;
+
+ if (from == to)
+ return;
+
+ CoreFocusEvents(pDev, from, to, mode);
+ DeviceFocusEvents(pDev, from, to, mode);
+}
diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c
index d68eeee62..dfe951ea7 100644
--- a/xorg-server/dix/events.c
+++ b/xorg-server/dix/events.c
@@ -331,7 +331,7 @@ IsKeyboardDevice(DeviceIntPtr dev)
Bool
IsMaster(DeviceIntPtr dev)
{
- return (dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD);
+ return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
}
static WindowPtr XYToWindow(
@@ -486,6 +486,13 @@ SyntheticMotion(DeviceIntPtr dev, int x, int y) {
static void PostNewCursor(DeviceIntPtr pDev);
static Bool
+pointOnScreen(ScreenPtr pScreen, int x, int y)
+{
+ return x >= pScreen->x && x < pScreen->x + pScreen->width &&
+ y >= pScreen->y && y < pScreen->y + pScreen->height;
+}
+
+static Bool
XineramaSetCursorPosition(
DeviceIntPtr pDev,
int x,
@@ -493,7 +500,6 @@ XineramaSetCursorPosition(
Bool generateEvent
){
ScreenPtr pScreen;
- BoxRec box;
int i;
SpritePtr pSprite = pDev->spriteInfo->sprite;
@@ -502,17 +508,16 @@ XineramaSetCursorPosition(
that screen are. */
pScreen = pSprite->screen;
- x += panoramiXdataPtr[0].x;
- y += panoramiXdataPtr[0].y;
+ x += screenInfo.screens[0]->x;
+ y += screenInfo.screens[0]->y;
- if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum],
- x, y, &box))
+ if(!pointOnScreen(pScreen, x, y))
{
FOR_NSCREENS(i)
{
if(i == pScreen->myNum)
continue;
- if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box))
+ if(pointOnScreen(screenInfo.screens[i], x, y))
{
pScreen = screenInfo.screens[i];
break;
@@ -521,10 +526,10 @@ XineramaSetCursorPosition(
}
pSprite->screen = pScreen;
- pSprite->hotPhys.x = x - panoramiXdataPtr[0].x;
- pSprite->hotPhys.y = y - panoramiXdataPtr[0].y;
- x -= panoramiXdataPtr[pScreen->myNum].x;
- y -= panoramiXdataPtr[pScreen->myNum].y;
+ pSprite->hotPhys.x = x - screenInfo.screens[0]->x;
+ pSprite->hotPhys.y = y - screenInfo.screens[0]->y;
+ x -= pScreen->x;
+ y -= pScreen->y;
return (*pScreen->SetCursorPosition)(pDev, pScreen, x, y, generateEvent);
}
@@ -542,10 +547,10 @@ XineramaConstrainCursor(DeviceIntPtr pDev)
/* Translate the constraining box to the screen
the sprite is actually on */
- newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x;
- newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x;
- newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
- newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
+ newBox.x1 += screenInfo.screens[0]->x - pScreen->x;
+ newBox.x2 += screenInfo.screens[0]->x - pScreen->x;
+ newBox.y1 += screenInfo.screens[0]->y - pScreen->y;
+ newBox.y2 += screenInfo.screens[0]->y - pScreen->y;
(* pScreen->ConstrainCursor)(pDev, pScreen, &newBox);
}
@@ -556,9 +561,10 @@ XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
{
SpritePtr pSprite = pDev->spriteInfo->sprite;
- if(pWin == WindowTable[0]) {
- memcpy(pSprite->windows, WindowTable,
- PanoramiXNumScreens*sizeof(WindowPtr));
+ if(pWin == screenInfo.screens[0]->root) {
+ int i;
+ for (i = 0; i < PanoramiXNumScreens; i++)
+ pSprite->windows[i] = screenInfo.screens[i]->root;
} else {
PanoramiXRes *win;
int rc, i;
@@ -592,34 +598,34 @@ XineramaConfineCursorToWindow(DeviceIntPtr pDev,
i = PanoramiXNumScreens - 1;
- REGION_COPY(pSprite->screen, &pSprite->Reg1,
+ RegionCopy(&pSprite->Reg1,
&pSprite->windows[i]->borderSize);
- off_x = panoramiXdataPtr[i].x;
- off_y = panoramiXdataPtr[i].y;
+ off_x = screenInfo.screens[i]->x;
+ off_y = screenInfo.screens[i]->y;
while(i--) {
- x = off_x - panoramiXdataPtr[i].x;
- y = off_y - panoramiXdataPtr[i].y;
+ x = off_x - screenInfo.screens[i]->x;
+ y = off_y - screenInfo.screens[i]->y;
if(x || y)
- REGION_TRANSLATE(pSprite->screen, &pSprite->Reg1, x, y);
+ RegionTranslate(&pSprite->Reg1, x, y);
- REGION_UNION(pSprite->screen, &pSprite->Reg1, &pSprite->Reg1,
+ RegionUnion(&pSprite->Reg1, &pSprite->Reg1,
&pSprite->windows[i]->borderSize);
- off_x = panoramiXdataPtr[i].x;
- off_y = panoramiXdataPtr[i].y;
+ off_x = screenInfo.screens[i]->x;
+ off_y = screenInfo.screens[i]->y;
}
- pSprite->hotLimits = *REGION_EXTENTS(pSprite->screen, &pSprite->Reg1);
+ pSprite->hotLimits = *RegionExtents(&pSprite->Reg1);
- if(REGION_NUM_RECTS(&pSprite->Reg1) > 1)
+ if(RegionNumRects(&pSprite->Reg1) > 1)
pSprite->hotShape = &pSprite->Reg1;
else
pSprite->hotShape = NullRegion;
pSprite->confined = FALSE;
- pSprite->confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin;
+ pSprite->confineWin = (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin;
CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL);
}
@@ -665,9 +671,9 @@ ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
SpritePtr pSprite;
pSprite = pDev->spriteInfo->sprite;
- if (POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box))
+ if (RegionContainsPoint(shape, x, y, &box))
return;
- box = *REGION_EXTENTS(pSprite->hot.pScreen, shape);
+ box = *RegionExtents(shape);
/* this is rather crude */
do {
x += incx;
@@ -689,7 +695,7 @@ ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
else if (y < box.y1)
return; /* should never get here! */
}
- } while (!POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box));
+ } while (!RegionContainsPoint(shape, x, y, &box));
*px = x;
*py = y;
}
@@ -811,23 +817,23 @@ CheckVirtualMotion(
i = PanoramiXNumScreens - 1;
- REGION_COPY(pSprite->screen, &pSprite->Reg2,
+ RegionCopy(&pSprite->Reg2,
&pSprite->windows[i]->borderSize);
- off_x = panoramiXdataPtr[i].x;
- off_y = panoramiXdataPtr[i].y;
+ off_x = screenInfo.screens[i]->x;
+ off_y = screenInfo.screens[i]->y;
while(i--) {
- x = off_x - panoramiXdataPtr[i].x;
- y = off_y - panoramiXdataPtr[i].y;
+ x = off_x - screenInfo.screens[i]->x;
+ y = off_y - screenInfo.screens[i]->y;
if(x || y)
- REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2, x, y);
+ RegionTranslate(&pSprite->Reg2, x, y);
- REGION_UNION(pSprite->screen, &pSprite->Reg2, &pSprite->Reg2,
+ RegionUnion(&pSprite->Reg2, &pSprite->Reg2,
&pSprite->windows[i]->borderSize);
- off_x = panoramiXdataPtr[i].x;
- off_y = panoramiXdataPtr[i].y;
+ off_x = screenInfo.screens[i]->x;
+ off_y = screenInfo.screens[i]->y;
}
} else
#endif
@@ -839,7 +845,7 @@ CheckVirtualMotion(
}
}
- lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize);
+ lims = *RegionExtents(&pWin->borderSize);
if (pSprite->hot.x < lims.x1)
pSprite->hot.x = lims.x1;
else if (pSprite->hot.x >= lims.x2)
@@ -852,7 +858,7 @@ CheckVirtualMotion(
#ifdef PANORAMIX
if (!noPanoramiXExtension)
{
- if (REGION_NUM_RECTS(&pSprite->Reg2) > 1)
+ if (RegionNumRects(&pSprite->Reg2) > 1)
reg = &pSprite->Reg2;
} else
@@ -875,13 +881,12 @@ CheckVirtualMotion(
#ifdef PANORAMIX
if (noPanoramiXExtension) /* No typo. Only set the root win if disabled */
#endif
- RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum];
+ RootWindow(pDev) = pSprite->hot.pScreen->root;
}
static void
ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
{
- ScreenPtr pScreen = pWin->drawable.pScreen;
SpritePtr pSprite = pDev->spriteInfo->sprite;
if (syncEvents.playingEvents)
@@ -897,11 +902,11 @@ ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bo
return;
}
#endif
- pSprite->hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize);
+ pSprite->hotLimits = *RegionExtents(&pWin->borderSize);
pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
: NullRegion;
CheckPhysLimits(pDev, pSprite->current, generateEvents,
- confineToScreen, pScreen);
+ confineToScreen, pWin->drawable.pScreen);
}
}
@@ -1123,7 +1128,7 @@ EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
* updated yet.
*/
if (ev->any.type == ET_Motion)
- ev->device_event.root = WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id;
+ ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
eventinfo.event = ev;
eventinfo.device = device;
@@ -1134,10 +1139,8 @@ EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
{
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
- event->root_x += panoramiXdataPtr[pSprite->screen->myNum].x -
- panoramiXdataPtr[0].x;
- event->root_y += panoramiXdataPtr[pSprite->screen->myNum].y -
- panoramiXdataPtr[0].y;
+ event->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
+ event->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
}
#endif
pSprite->hotPhys.x = event->root_x;
@@ -1217,10 +1220,10 @@ PlayReleasedEvents(void)
case ET_KeyRelease:
case ET_ProximityIn:
case ET_ProximityOut:
- ev->root_x += panoramiXdataPtr[0].x -
- panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].x;
- ev->root_y += panoramiXdataPtr[0].y -
- panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].y;
+ ev->root_x += screenInfo.screens[0]->x -
+ pDev->spriteInfo->sprite->screen->x;
+ ev->root_y += screenInfo.screens[0]->y -
+ pDev->spriteInfo->sprite->screen->y;
break;
default:
break;
@@ -1339,7 +1342,7 @@ playmore:
}
else
ConfineCursorToWindow(dev,
- WindowTable[dev->spriteInfo->sprite->hotPhys.pScreen->myNum],
+ dev->spriteInfo->sprite->hotPhys.pScreen->root,
TRUE, FALSE);
PostNewCursor(dev);
}
@@ -1369,7 +1372,7 @@ ScreenRestructured (ScreenPtr pScreen)
}
else
ConfineCursorToWindow(pDev,
- WindowTable[pDev->spriteInfo->sprite->hotPhys.pScreen->myNum],
+ pDev->spriteInfo->sprite->hotPhys.pScreen->root,
TRUE, FALSE);
}
}
@@ -2548,7 +2551,7 @@ PointInBorderSize(WindowPtr pWin, int x, int y)
{
BoxRec box;
- if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box))
+ if(RegionContainsPoint(&pWin->borderSize, x, y, &box))
return TRUE;
#ifdef PANORAMIX
@@ -2558,11 +2561,10 @@ PointInBorderSize(WindowPtr pWin, int x, int y)
int i;
for(i = 1; i < PanoramiXNumScreens; i++) {
- if(POINT_IN_REGION(pSprite->screen,
- &pSprite->windows[i]->borderSize,
- x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x,
- y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y,
- &box))
+ if(RegionContainsPoint(&pSprite->windows[i]->borderSize,
+ x + screenInfo.screens[0]->x - screenInfo.screens[i]->x,
+ y + screenInfo.screens[0]->y - screenInfo.screens[i]->y,
+ &box))
return TRUE;
}
}
@@ -2606,10 +2608,9 @@ XYToWindow(DeviceIntPtr pDev, int x, int y)
*/
&& (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
&& (!wInputShape(pWin) ||
- POINT_IN_REGION(pWin->drawable.pScreen,
- wInputShape(pWin),
- x - pWin->drawable.x,
- y - pWin->drawable.y, &box))
+ RegionContainsPoint(wInputShape(pWin),
+ x - pWin->drawable.x,
+ y - pWin->drawable.y, &box))
#ifdef ROOTLESS
/* In rootless mode windows may be offscreen, even when
* they're in X's stack. (E.g. if the native window system
@@ -2756,17 +2757,15 @@ CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
/* Motion events entering DIX get translated to Screen 0
coordinates. Replayed events have already been
translated since they've entered DIX before */
- ev->root_x += panoramiXdataPtr[pSprite->screen->myNum].x -
- panoramiXdataPtr[0].x;
- ev->root_y += panoramiXdataPtr[pSprite->screen->myNum].y -
- panoramiXdataPtr[0].y;
+ ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
+ ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
} else
#endif
{
if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen)
{
pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
- RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum];
+ RootWindow(pDev) = pSprite->hot.pScreen->root;
}
}
@@ -2849,7 +2848,7 @@ WindowsRestructured(void)
#ifdef PANORAMIX
/* This was added to support reconfiguration under Xdmx. The problem is
- * that if the 0th screen (i.e., WindowTable[0]) is moved to an origin
+ * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin
* other than 0,0, the information in the private sprite structure must
* be updated accordingly, or XYToWindow (and other routines) will not
* compute correctly. */
@@ -2878,10 +2877,10 @@ void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
pSprite->hotLimits.x2 -= xoff;
pSprite->hotLimits.y2 -= yoff;
- if (REGION_NOTEMPTY(pSprite->screen, &pSprite->Reg1))
- REGION_TRANSLATE(pSprite->screen, &pSprite->Reg1, xoff, yoff);
- if (REGION_NOTEMPTY(pSprite->screen, &pSprite->Reg2))
- REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2, xoff, yoff);
+ if (RegionNotEmpty(&pSprite->Reg1))
+ RegionTranslate(&pSprite->Reg1, xoff, yoff);
+ if (RegionNotEmpty(&pSprite->Reg2))
+ RegionTranslate(&pSprite->Reg2, xoff, yoff);
/* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
@@ -2892,7 +2891,7 @@ void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
} else
ConfineCursorToWindow(
pDev,
- WindowTable[pSprite->hotPhys.pScreen->myNum],
+ pSprite->hotPhys.pScreen->root,
TRUE, FALSE);
}
@@ -3007,17 +3006,17 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
}
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
- pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x;
- pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y;
- pSprite->hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x;
- pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
+ pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
+ pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
+ pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
+ pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
pSprite->physLimits = pSprite->hotLimits;
pSprite->confineWin = NullWindow;
pSprite->hotShape = NullRegion;
pSprite->screen = pScreen;
/* gotta UNINIT these someplace */
- REGION_NULL(pScreen, &pSprite->Reg1);
- REGION_NULL(pScreen, &pSprite->Reg2);
+ RegionNull(&pSprite->Reg1);
+ RegionNull(&pSprite->Reg2);
}
#endif
}
@@ -3051,7 +3050,7 @@ UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
pSprite = pDev->spriteInfo->sprite;
- win = WindowTable[pScreen->myNum];
+ win = pScreen->root;
pSprite->hotPhys.pScreen = pScreen;
pSprite->hot = pSprite->hotPhys;
@@ -3077,10 +3076,10 @@ UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
- pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x;
- pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y;
- pSprite->hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x;
- pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
+ pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
+ pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
+ pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
+ pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
pSprite->physLimits = pSprite->hotLimits;
pSprite->screen = pScreen;
}
@@ -3113,10 +3112,8 @@ NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
pSprite->hotPhys.y = y;
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
- pSprite->hotPhys.x += panoramiXdataPtr[newScreen->myNum].x -
- panoramiXdataPtr[0].x;
- pSprite->hotPhys.y += panoramiXdataPtr[newScreen->myNum].y -
- panoramiXdataPtr[0].y;
+ pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x;
+ pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y;
if (newScreen != pSprite->screen) {
pSprite->screen = newScreen;
/* Make sure we tell the DDX to update its copy of the screen */
@@ -3124,23 +3121,22 @@ NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
XineramaConfineCursorToWindow(pDev,
pSprite->confineWin, TRUE);
else
- XineramaConfineCursorToWindow(pDev, WindowTable[0], TRUE);
+ XineramaConfineCursorToWindow(pDev, screenInfo.screens[0]->root, TRUE);
/* if the pointer wasn't confined, the DDX won't get
told of the pointer warp so we reposition it here */
if(!syncEvents.playingEvents)
(*pSprite->screen->SetCursorPosition)(
pDev,
pSprite->screen,
- pSprite->hotPhys.x + panoramiXdataPtr[0].x -
- panoramiXdataPtr[pSprite->screen->myNum].x,
- pSprite->hotPhys.y + panoramiXdataPtr[0].y -
- panoramiXdataPtr[pSprite->screen->myNum].y, FALSE);
+ pSprite->hotPhys.x + screenInfo.screens[0]->x -
+ pSprite->screen->x,
+ pSprite->hotPhys.y + screenInfo.screens[0]->y -
+ pSprite->screen->y, FALSE);
}
} else
#endif
if (newScreen != pSprite->hotPhys.pScreen)
- ConfineCursorToWindow(pDev, WindowTable[newScreen->myNum],
- TRUE, FALSE);
+ ConfineCursorToWindow(pDev, newScreen->root, TRUE, FALSE);
}
#ifdef PANORAMIX
@@ -3152,32 +3148,29 @@ XineramaPointInWindowIsVisible(
int y
)
{
- ScreenPtr pScreen = pWin->drawable.pScreen;
BoxRec box;
int i, xoff, yoff;
if (!pWin->realized) return FALSE;
- if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box))
+ if (RegionContainsPoint(&pWin->borderClip, x, y, &box))
return TRUE;
if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE;
- xoff = x + panoramiXdataPtr[0].x;
- yoff = y + panoramiXdataPtr[0].y;
+ xoff = x + screenInfo.screens[0]->x;
+ yoff = y + screenInfo.screens[0]->y;
for(i = 1; i < PanoramiXNumScreens; i++) {
pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
- pScreen = pWin->drawable.pScreen;
- x = xoff - panoramiXdataPtr[i].x;
- y = yoff - panoramiXdataPtr[i].y;
+ x = xoff - screenInfo.screens[i]->x;
+ y = yoff - screenInfo.screens[i]->y;
- if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)
+ if(RegionContainsPoint(&pWin->borderClip, x, y, &box)
&& (!wInputShape(pWin) ||
- POINT_IN_REGION(pWin->drawable.pScreen,
- wInputShape(pWin),
- x - pWin->drawable.x,
- y - pWin->drawable.y, &box)))
+ RegionContainsPoint(wInputShape(pWin),
+ x - pWin->drawable.x,
+ y - pWin->drawable.y, &box)))
return TRUE;
}
@@ -3215,9 +3208,9 @@ XineramaWarpPointer(ClientPtr client)
winX = source->drawable.x;
winY = source->drawable.y;
- if(source == WindowTable[0]) {
- winX -= panoramiXdataPtr[0].x;
- winY -= panoramiXdataPtr[0].y;
+ if(source == screenInfo.screens[0]->root) {
+ winX -= screenInfo.screens[0]->x;
+ winY -= screenInfo.screens[0]->y;
}
if (x < winX + stuff->srcX ||
y < winY + stuff->srcY ||
@@ -3231,9 +3224,9 @@ XineramaWarpPointer(ClientPtr client)
if (dest) {
x = dest->drawable.x;
y = dest->drawable.y;
- if(dest == WindowTable[0]) {
- x -= panoramiXdataPtr[0].x;
- y -= panoramiXdataPtr[0].y;
+ if(dest == screenInfo.screens[0]->root) {
+ x -= screenInfo.screens[0]->x;
+ y -= screenInfo.screens[0]->y;
}
}
@@ -3368,7 +3361,7 @@ ProcWarpPointer(ClientPtr client)
static Bool
BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
{
- if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->hotPhys.pScreen, &pWin->borderSize))
+ if(RegionNotEmpty(&pWin->borderSize))
return TRUE;
#ifdef PANORAMIX
@@ -3376,8 +3369,7 @@ BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
int i;
for(i = 1; i < PanoramiXNumScreens; i++) {
- if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->screen,
- &pDev->spriteInfo->sprite->windows[i]->borderSize))
+ if(RegionNotEmpty(&pDev->spriteInfo->sprite->windows[i]->borderSize))
return TRUE;
}
}
@@ -3801,10 +3793,8 @@ DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
}
unwind:
- if (xE)
- free(xE);
- if (xi2)
- free(xi2);
+ free(xE);
+ free(xi2);
return;
}
@@ -3984,10 +3974,8 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
}
}
- if (xi)
- free(xi);
- if (xi2)
- free(xi2);
+ free(xi);
+ free(xi2);
}
/* This function is used to set the key pressed or key released state -
@@ -4095,7 +4083,7 @@ OtherClientGone(pointer value, XID id)
}
free(other);
RecalculateDeliverableEvents(pWin);
- return(Success);
+ return Success;
}
prev = other;
}
@@ -4318,7 +4306,7 @@ CoreEnterLeaveEvent(
xKeymapEvent ke;
ClientPtr client = grab ? rClient(grab) : wClient(pWin);
if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess))
- bzero((char *)&ke.map[0], 31);
+ memset((char *)&ke.map[0], 0, 31);
else
memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
@@ -4428,7 +4416,7 @@ CoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
xKeymapEvent ke;
ClientPtr client = wClient(pWin);
if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess))
- bzero((char *)&ke.map[0], 31);
+ memset((char *)&ke.map[0], 0, 31);
else
memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
@@ -4500,7 +4488,7 @@ SetInputFocus(
/* It is a match error to try to set the input focus to an
unviewable window. */
if(!focusWin->realized)
- return(BadMatch);
+ return BadMatch;
}
rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess);
if (rc != Success)
@@ -4997,11 +4985,11 @@ ProcQueryPointer(ClientPtr client)
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
- rep.rootX += panoramiXdataPtr[0].x;
- rep.rootY += panoramiXdataPtr[0].y;
+ rep.rootX += screenInfo.screens[0]->x;
+ rep.rootY += screenInfo.screens[0]->y;
if(stuff->id == rep.root) {
- rep.winX += panoramiXdataPtr[0].x;
- rep.winY += panoramiXdataPtr[0].y;
+ rep.winX += screenInfo.screens[0]->x;
+ rep.winY += screenInfo.screens[0]->y;
}
}
#endif
@@ -5017,7 +5005,7 @@ ProcQueryPointer(ClientPtr client)
WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
- return(Success);
+ return Success;
}
/**
@@ -5221,8 +5209,8 @@ ProcUngrabKey(ClientPtr client)
tempGrab.next = NULL;
if (!DeletePassiveGrabFromList(&tempGrab))
- return(BadAlloc);
- return(Success);
+ return BadAlloc;
+ return Success;
}
/**
@@ -5416,8 +5404,8 @@ ProcUngrabButton(ClientPtr client)
tempGrab.next = NULL;
if (!DeletePassiveGrabFromList(&tempGrab))
- return(BadAlloc);
- return(Success);
+ return BadAlloc;
+ return Success;
}
/**
@@ -5631,7 +5619,7 @@ ProcRecolorCursor(ClientPtr client)
( *pscr->RecolorCursor)(PickPointer(client), pscr, pCursor,
(pCursor == pSprite->current) && displayed);
}
- return (Success);
+ return Success;
}
/**
@@ -5670,7 +5658,7 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
#ifdef PANORAMIX
if(!noPanoramiXExtension &&
- (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y))
+ (screenInfo.screens[0]->x || screenInfo.screens[0]->y))
{
switch(events->u.u.type) {
case MotionNotify:
@@ -5687,13 +5675,13 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
*/
count = 1; /* should always be 1 */
memcpy(&eventCopy, events, sizeof(xEvent));
- eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x;
- eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y;
+ eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x;
+ eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y;
if(eventCopy.u.keyButtonPointer.event ==
eventCopy.u.keyButtonPointer.root)
{
- eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x;
- eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y;
+ eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x;
+ eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y;
}
events = &eventCopy;
break;
diff --git a/xorg-server/dix/extension.c b/xorg-server/dix/extension.c
index 57aef003f..f6b33d64c 100644
--- a/xorg-server/dix/extension.c
+++ b/xorg-server/dix/extension.c
@@ -89,15 +89,19 @@ AddExtension(char *name, int NumEvents, int NumErrors,
return((ExtensionEntry *) NULL);
}
- ext = malloc(sizeof(ExtensionEntry));
+ ext = calloc(sizeof (ExtensionEntry), 1);
if (!ext)
- return(NULL);
+ return NULL;
+ if (!dixAllocatePrivates(&ext->devPrivates, PRIVATE_EXTENSION)) {
+ free(ext);
+ return NULL;
+ }
ext->name = malloc(strlen(name) + 1);
ext->num_aliases = 0;
ext->aliases = (char **)NULL;
- ext->devPrivates = NULL;
if (!ext->name)
{
+ dixFreePrivates(ext->devPrivates, PRIVATE_EXTENSION);
free(ext);
return((ExtensionEntry *) NULL);
}
@@ -108,6 +112,7 @@ AddExtension(char *name, int NumEvents, int NumErrors,
if (!newexts)
{
free(ext->name);
+ dixFreePrivates(ext->devPrivates, PRIVATE_EXTENSION);
free(ext);
return((ExtensionEntry *) NULL);
}
@@ -144,7 +149,7 @@ AddExtension(char *name, int NumEvents, int NumErrors,
}
RegisterExtensionNames(ext);
- return(ext);
+ return ext;
}
Bool AddExtensionAlias(char *alias, ExtensionEntry *ext)
@@ -253,7 +258,7 @@ CloseDownExtensions(void)
for (j = extensions[i]->num_aliases; --j >= 0;)
free(extensions[i]->aliases[j]);
free(extensions[i]->aliases);
- dixFreePrivates(extensions[i]->devPrivates);
+ dixFreePrivates(extensions[i]->devPrivates, PRIVATE_EXTENSION);
free(extensions[i]);
}
free(extensions);
@@ -330,7 +335,7 @@ ProcListExtensions(ClientPtr client)
reply.length = bytes_to_int32(total_length);
buffer = bufptr = malloc(total_length);
if (!buffer)
- return(BadAlloc);
+ return BadAlloc;
for (i=0; i<NumExtensions; i++)
{
int len;
diff --git a/xorg-server/dix/gc.c b/xorg-server/dix/gc.c
index d39a5a76a..902f20675 100644
--- a/xorg-server/dix/gc.c
+++ b/xorg-server/dix/gc.c
@@ -479,7 +479,7 @@ CreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus,
{
GCPtr pGC;
- pGC = malloc(sizeof(GC));
+ pGC = dixAllocateObjectWithPrivates(GC, PRIVATE_GC);
if (!pGC)
{
*pStatus = BadAlloc;
@@ -492,7 +492,6 @@ CreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus,
pGC->planemask = ~0;
pGC->serialNumber = GC_CHANGE_SERIAL_BIT;
pGC->funcs = 0;
- pGC->devPrivates = NULL;
pGC->fgPixel = 0;
pGC->bgPixel = 1;
pGC->lineWidth = 0;
@@ -563,7 +562,7 @@ out:
pGC = (GCPtr)NULL;
}
- return (pGC);
+ return pGC;
}
static Bool
@@ -785,9 +784,8 @@ FreeGC(pointer value, XID gid)
(*pGC->funcs->DestroyGC) (pGC);
if (pGC->dash != DefaultDash)
free(pGC->dash);
- dixFreePrivates(pGC->devPrivates);
- free(pGC);
- return(Success);
+ dixFreeObjectWithPrivates(pGC, PRIVATE_GC);
+ return Success;
}
/* CreateScratchGC(pScreen, depth)
@@ -808,7 +806,7 @@ CreateScratchGC(ScreenPtr pScreen, unsigned depth)
{
GCPtr pGC;
- pGC = malloc(sizeof(GC));
+ pGC = dixAllocateObjectWithPrivates(GC, PRIVATE_GC);
if (!pGC)
return (GCPtr)NULL;
@@ -817,7 +815,6 @@ CreateScratchGC(ScreenPtr pScreen, unsigned depth)
pGC->alu = GXcopy; /* dst <- src */
pGC->planemask = ~0;
pGC->serialNumber = 0;
- pGC->devPrivates = NULL;
pGC->fgPixel = 0;
pGC->bgPixel = 1;
pGC->lineWidth = 0;
@@ -1069,7 +1066,7 @@ SetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects,
newct = VerifyRectOrder(nrects, prects, ordering);
if (newct < 0)
- return(BadMatch);
+ return BadMatch;
size = nrects * sizeof(xRectangle);
prectsNew = malloc(size);
if (!prectsNew && size)
diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c
index 7a24b801e..ea19e0cac 100644
--- a/xorg-server/dix/getevents.c
+++ b/xorg-server/dix/getevents.c
@@ -33,6 +33,7 @@
#include <X11/X.h>
#include <X11/keysym.h>
#include <X11/Xproto.h>
+#include <math.h>
#include "misc.h"
#include "resource.h"
@@ -56,6 +57,7 @@
#include <X11/extensions/XI.h>
#include <X11/extensions/XIproto.h>
+#include <pixman.h>
#include "exglobals.h"
#include "exevents.h"
#include "exglobals.h"
@@ -325,8 +327,7 @@ void
AllocateMotionHistory(DeviceIntPtr pDev)
{
int size;
- if (pDev->valuator->motion)
- free(pDev->valuator->motion);
+ free(pDev->valuator->motion);
if (pDev->valuator->numMotionEvents < 1)
return;
@@ -997,6 +998,22 @@ FreeEventList(EventListPtr list, int num_events)
free(list);
}
+static void
+transformAbsolute(DeviceIntPtr dev, int v[MAX_VALUATORS])
+{
+ struct pixman_f_vector p;
+
+ /* p' = M * p in homogeneous coordinates */
+ p.v[0] = v[0];
+ p.v[1] = v[1];
+ p.v[2] = 1.0;
+
+ pixman_f_transform_point(&dev->transform, &p);
+
+ v[0] = lround(p.v[0]);
+ v[1] = lround(p.v[1]);
+}
+
/**
* Generate a series of xEvents (filled into the EventList) representing
* pointer motion, or button presses. Xi and XKB-aware.
@@ -1068,6 +1085,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
scr->height);
}
+ transformAbsolute(pDev, valuators);
moveAbsolute(pDev, &x, &y, first_valuator, num_valuators, valuators);
} else {
if (flags & POINTER_ACCELERATE) {
@@ -1191,8 +1209,8 @@ PostSyntheticMotion(DeviceIntPtr pDev,
will translate from sprite screen to screen 0 upon reentry
to the DIX layer. */
if (!noPanoramiXExtension) {
- x += panoramiXdataPtr[0].x - panoramiXdataPtr[screen].x;
- y += panoramiXdataPtr[0].y - panoramiXdataPtr[screen].y;
+ x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x;
+ y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y;
}
#endif
diff --git a/xorg-server/dix/globals.c b/xorg-server/dix/globals.c
index c24a94fbe..622e50f81 100644
--- a/xorg-server/dix/globals.c
+++ b/xorg-server/dix/globals.c
@@ -1,141 +1,135 @@
-/************************************************************
-
-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.
-
-********************************************************/
-
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xmd.h>
-#include "misc.h"
-#include "windowstr.h"
-#include "scrnintstr.h"
-#include "input.h"
-#include "dixfont.h"
-#include "site.h"
-#include "dixstruct.h"
-#include "os.h"
-
-ScreenInfo screenInfo;
-KeybdCtrl defaultKeyboardControl = {
- DEFAULT_KEYBOARD_CLICK,
- DEFAULT_BELL,
- DEFAULT_BELL_PITCH,
- DEFAULT_BELL_DURATION,
- DEFAULT_AUTOREPEAT,
- DEFAULT_AUTOREPEATS,
- DEFAULT_LEDS,
- 0};
-
-PtrCtrl defaultPointerControl = {
- DEFAULT_PTR_NUMERATOR,
- DEFAULT_PTR_DENOMINATOR,
- DEFAULT_PTR_THRESHOLD,
- 0};
-
-ClientPtr clients[MAXCLIENTS];
-ClientPtr serverClient;
-int currentMaxClients; /* current size of clients array */
-long maxBigRequestSize = MAX_BIG_REQUEST_SIZE;
-
-WindowPtr WindowTable[MAXSCREENS];
-
-unsigned long globalSerialNumber = 0;
-unsigned long serverGeneration = 0;
-
-/* these next four are initialized in main.c */
-CARD32 ScreenSaverTime;
-CARD32 ScreenSaverInterval;
-int ScreenSaverBlanking;
-int ScreenSaverAllowExposures;
-
-#ifdef DPMSExtension
-CARD16 DPMSPowerLevel = 0;
-Bool DPMSDisabledSwitch = FALSE;
-Bool DPMSCapableFlag = FALSE;
-CARD32 DPMSStandbyTime;
-CARD32 DPMSSuspendTime;
-CARD32 DPMSOffTime;
-Bool DPMSEnabled;
-#endif
-
-CARD32 defaultScreenSaverTime = DEFAULT_SCREEN_SAVER_TIME;
-CARD32 defaultScreenSaverInterval = DEFAULT_SCREEN_SAVER_INTERVAL;
-int defaultScreenSaverBlanking = DEFAULT_SCREEN_SAVER_BLANKING;
-int defaultScreenSaverAllowExposures = DEFAULT_SCREEN_SAVER_EXPOSURES;
-#ifndef NOLOGOHACK
-int logoScreenSaver = DEFAULT_LOGO_SCREEN_SAVER;
-#endif
-
-#ifdef SCREENSAVER
-Bool screenSaverSuspended = FALSE;
-#endif
-
-char *defaultFontPath = COMPILEDDEFAULTFONTPATH;
-char *defaultTextFont = COMPILEDDEFAULTFONT;
-char *defaultCursorFont = COMPILEDCURSORFONT;
-FontPtr defaultFont; /* not declared in dix.h to avoid including font.h in
- every compilation of dix code */
-CursorPtr rootCursor;
-Bool party_like_its_1989 = FALSE;
-Bool whiteRoot = FALSE;
-
-int cursorScreenDevPriv[MAXSCREENS];
-
-TimeStamp currentTime;
-TimeStamp lastDeviceEventTime;
-
-int defaultColorVisualClass = -1;
-int monitorResolution = 0;
-
-char *display;
-char *ConnectionInfo;
-
-CARD32 TimeOutValue = DEFAULT_TIMEOUT * MILLI_PER_SECOND;
-
-DDXPointRec dixScreenOrigins[MAXSCREENS];
+/************************************************************
+
+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.
+
+********************************************************/
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xmd.h>
+#include "misc.h"
+#include "windowstr.h"
+#include "scrnintstr.h"
+#include "input.h"
+#include "dixfont.h"
+#include "site.h"
+#include "dixstruct.h"
+#include "os.h"
+
+ScreenInfo screenInfo;
+KeybdCtrl defaultKeyboardControl = {
+ DEFAULT_KEYBOARD_CLICK,
+ DEFAULT_BELL,
+ DEFAULT_BELL_PITCH,
+ DEFAULT_BELL_DURATION,
+ DEFAULT_AUTOREPEAT,
+ DEFAULT_AUTOREPEATS,
+ DEFAULT_LEDS,
+ 0};
+
+PtrCtrl defaultPointerControl = {
+ DEFAULT_PTR_NUMERATOR,
+ DEFAULT_PTR_DENOMINATOR,
+ DEFAULT_PTR_THRESHOLD,
+ 0};
+
+ClientPtr clients[MAXCLIENTS];
+ClientPtr serverClient;
+int currentMaxClients; /* current size of clients array */
+long maxBigRequestSize = MAX_BIG_REQUEST_SIZE;
+
+unsigned long globalSerialNumber = 0;
+unsigned long serverGeneration = 0;
+
+/* these next four are initialized in main.c */
+CARD32 ScreenSaverTime;
+CARD32 ScreenSaverInterval;
+int ScreenSaverBlanking;
+int ScreenSaverAllowExposures;
+
+#ifdef DPMSExtension
+CARD16 DPMSPowerLevel = 0;
+Bool DPMSDisabledSwitch = FALSE;
+Bool DPMSCapableFlag = FALSE;
+CARD32 DPMSStandbyTime;
+CARD32 DPMSSuspendTime;
+CARD32 DPMSOffTime;
+Bool DPMSEnabled;
+#endif
+
+CARD32 defaultScreenSaverTime = DEFAULT_SCREEN_SAVER_TIME;
+CARD32 defaultScreenSaverInterval = DEFAULT_SCREEN_SAVER_INTERVAL;
+int defaultScreenSaverBlanking = DEFAULT_SCREEN_SAVER_BLANKING;
+int defaultScreenSaverAllowExposures = DEFAULT_SCREEN_SAVER_EXPOSURES;
+#ifndef NOLOGOHACK
+int logoScreenSaver = DEFAULT_LOGO_SCREEN_SAVER;
+#endif
+
+#ifdef SCREENSAVER
+Bool screenSaverSuspended = FALSE;
+#endif
+
+char *defaultFontPath = COMPILEDDEFAULTFONTPATH;
+char *defaultTextFont = COMPILEDDEFAULTFONT;
+char *defaultCursorFont = COMPILEDCURSORFONT;
+FontPtr defaultFont; /* not declared in dix.h to avoid including font.h in
+ every compilation of dix code */
+CursorPtr rootCursor;
+Bool party_like_its_1989 = FALSE;
+Bool whiteRoot = FALSE;
+
+TimeStamp currentTime;
+TimeStamp lastDeviceEventTime;
+
+int defaultColorVisualClass = -1;
+int monitorResolution = 0;
+
+char *display;
+char *ConnectionInfo;
+
+CARD32 TimeOutValue = DEFAULT_TIMEOUT * MILLI_PER_SECOND;
diff --git a/xorg-server/dix/grabs.c b/xorg-server/dix/grabs.c
index 1bc4998b2..c588afc7c 100644
--- a/xorg-server/dix/grabs.c
+++ b/xorg-server/dix/grabs.c
@@ -441,10 +441,10 @@ DeletePassiveGrabFromList(GrabPtr pMinuendGrab)
details = malloc(i * sizeof(Mask *));
if (!deletes || !adds || !updates || !details)
{
- if (details) free(details);
- if (updates) free(updates);
- if (adds) free(adds);
- if (deletes) free(deletes);
+ free(details);
+ free(updates);
+ free(adds);
+ free(deletes);
return FALSE;
}
diff --git a/xorg-server/dix/inpututils.c b/xorg-server/dix/inpututils.c
index 6d730be2d..9e6ba0325 100644
--- a/xorg-server/dix/inpututils.c
+++ b/xorg-server/dix/inpututils.c
@@ -357,6 +357,10 @@ DuplicateInputAttributes(InputAttributes *attrs)
goto unwind;
if (attrs->device && !(new_attr->device = strdup(attrs->device)))
goto unwind;
+ if (attrs->pnp_id && !(new_attr->pnp_id = strdup(attrs->pnp_id)))
+ goto unwind;
+ if (attrs->usb_id && !(new_attr->usb_id = strdup(attrs->usb_id)))
+ goto unwind;
new_attr->flags = attrs->flags;
@@ -401,6 +405,8 @@ FreeInputAttributes(InputAttributes *attrs)
free(attrs->product);
free(attrs->vendor);
free(attrs->device);
+ free(attrs->pnp_id);
+ free(attrs->usb_id);
if ((tags = attrs->tags))
while(*tags)
diff --git a/xorg-server/dix/main.c b/xorg-server/dix/main.c
index 259093236..69f11938b 100644
--- a/xorg-server/dix/main.c
+++ b/xorg-server/dix/main.c
@@ -174,7 +174,7 @@ int main(int argc, char *argv[], char *envp[])
InitProcVectors();
for (i=1; i<MAXCLIENTS; i++)
clients[i] = NullClient;
- serverClient = malloc(sizeof(ClientRec));
+ serverClient = calloc(sizeof(ClientRec), 1);
if (!serverClient)
FatalError("couldn't create server client");
InitClient(serverClient, 0, (pointer)NULL);
@@ -184,6 +184,12 @@ int main(int argc, char *argv[], char *envp[])
clients[0] = serverClient;
currentMaxClients = 1;
+ /* Initialize server client devPrivates, to be reallocated as
+ * more client privates are registered
+ */
+ if (!dixAllocatePrivates(&serverClient->devPrivates, PRIVATE_CLIENT))
+ FatalError("failed to create server client privates");
+
if (!InitClientResources(serverClient)) /* for root resources */
FatalError("couldn't init server resources");
@@ -194,8 +200,7 @@ int main(int argc, char *argv[], char *envp[])
InitEvents();
InitSelections();
InitGlyphCaching();
- if (!dixResetPrivates())
- FatalError("couldn't init private data storage");
+ dixResetPrivates();
dixResetRegistry();
ResetFontPrivateIndex();
InitCallbackManager();
@@ -204,6 +209,7 @@ int main(int argc, char *argv[], char *envp[])
if (screenInfo.numScreens < 1)
FatalError("no screens found");
InitExtensions(argc, argv);
+
for (i = 0; i < screenInfo.numScreens; i++)
{
ScreenPtr pScreen = screenInfo.screens[i];
@@ -249,7 +255,7 @@ int main(int argc, char *argv[], char *envp[])
#endif
for (i = 0; i < screenInfo.numScreens; i++)
- InitRootWindow(WindowTable[i]);
+ InitRootWindow(screenInfo.screens[i]->root);
InitCoreDevices();
InitInput(argc, argv);
@@ -303,7 +309,8 @@ int main(int argc, char *argv[], char *envp[])
CloseInput();
- memset(WindowTable, 0, sizeof(WindowTable));
+ for (i = 0; i < screenInfo.numScreens; i++)
+ screenInfo.screens[i]->root = NullWindow;
CloseDownDevices();
CloseDownEvents();
@@ -313,17 +320,18 @@ int main(int argc, char *argv[], char *envp[])
FreeGCperDepth(i);
FreeDefaultStipple(i);
(* screenInfo.screens[i]->CloseScreen)(i, screenInfo.screens[i]);
- dixFreePrivates(screenInfo.screens[i]->devPrivates);
+ dixFreePrivates(screenInfo.screens[i]->devPrivates, PRIVATE_SCREEN);
free(screenInfo.screens[i]);
screenInfo.numScreens = i;
}
+
+ dixFreePrivates(serverClient->devPrivates, PRIVATE_CLIENT);
+ serverClient->devPrivates = NULL;
+
FreeFonts();
FreeAuditTimer();
- dixFreePrivates(serverClient->devPrivates);
- serverClient->devPrivates = NULL;
-
if (dispatchException & DE_TERMINATE)
{
CloseWellKnownConnections();
@@ -340,6 +348,6 @@ int main(int argc, char *argv[], char *envp[])
free(ConnectionInfo);
ConnectionInfo = NULL;
}
- return(0);
+ return 0;
}
diff --git a/xorg-server/dix/pixmap.c b/xorg-server/dix/pixmap.c
index 460da771e..3943f5582 100644
--- a/xorg-server/dix/pixmap.c
+++ b/xorg-server/dix/pixmap.c
@@ -91,6 +91,11 @@ FreeScratchPixmapHeader(PixmapPtr pPixmap)
Bool
CreateScratchPixmapsForScreen(int scrnum)
{
+ unsigned int pixmap_size;
+
+ pixmap_size = sizeof(PixmapRec) + dixPrivatesSize(PRIVATE_PIXMAP);
+ screenInfo.screens[scrnum]->totalPixmapSize = BitmapBytePad(pixmap_size * 8);
+
/* let it be created on first use */
screenInfo.screens[scrnum]->pScratchPixmap = NULL;
return TRUE;
@@ -110,6 +115,8 @@ AllocatePixmap(ScreenPtr pScreen, int pixDataSize)
{
PixmapPtr pPixmap;
+ assert(pScreen->totalPixmapSize > 0);
+
if (pScreen->totalPixmapSize > ((size_t)-1) - pixDataSize)
return NullPixmap;
@@ -117,6 +124,14 @@ AllocatePixmap(ScreenPtr pScreen, int pixDataSize)
if (!pPixmap)
return NullPixmap;
- pPixmap->devPrivates = NULL;
+ dixInitPrivates(pPixmap, pPixmap + 1, PRIVATE_PIXMAP);
return pPixmap;
}
+
+/* callable by ddx */
+void
+FreePixmap(PixmapPtr pPixmap)
+{
+ dixFiniPrivates(pPixmap, PRIVATE_PIXMAP);
+ free(pPixmap);
+}
diff --git a/xorg-server/dix/privates.c b/xorg-server/dix/privates.c
index 52a8df3f6..6d76ccff2 100644
--- a/xorg-server/dix/privates.c
+++ b/xorg-server/dix/privates.c
@@ -25,6 +25,28 @@ other dealings in this Software without prior written authorization
from The Open Group.
*/
+/*
+ * Copyright © 2010, Keith Packard
+ * Copyright © 2010, Jamey Sharp
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
@@ -38,177 +60,327 @@ from The Open Group.
#include "cursorstr.h"
#include "colormapst.h"
#include "inputstr.h"
-
-struct _Private {
- int state;
- pointer value;
+#include "scrnintstr.h"
+#include "extnsionst.h"
+
+static struct {
+ DevPrivateKey key;
+ unsigned offset;
+ int created;
+ int allocated;
+} keys[PRIVATE_LAST];
+
+static const Bool xselinux_private[PRIVATE_LAST] = {
+ [PRIVATE_CLIENT] = TRUE,
+ [PRIVATE_WINDOW] = TRUE,
+ [PRIVATE_PIXMAP] = TRUE,
+ [PRIVATE_GC] = TRUE,
+ [PRIVATE_CURSOR] = TRUE,
+ [PRIVATE_COLORMAP] = TRUE,
+ [PRIVATE_DEVICE] = TRUE,
+ [PRIVATE_EXTENSION] = TRUE,
+ [PRIVATE_SELECTION] = TRUE,
+ [PRIVATE_PROPERTY] = TRUE,
+ [PRIVATE_PICTURE] = TRUE,
+ [PRIVATE_GLYPHSET] = TRUE,
};
-typedef struct _PrivateDesc {
- DevPrivateKey key;
- unsigned size;
-} PrivateDescRec;
+typedef Bool (*FixupFunc)(PrivatePtr *privates, int offset, unsigned bytes);
-#define PRIV_MAX 256
-#define PRIV_STEP 16
+static Bool
+dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes)
+{
+ void *new_privates;
-/* list of all allocated privates */
-static PrivateDescRec items[PRIV_MAX];
-static int nextPriv;
+ new_privates = realloc(*privates, old_offset + bytes);
+ if (!new_privates)
+ return FALSE;
+ memset((char *) new_privates + old_offset, '\0', bytes);
+ *privates = new_privates;
+ return TRUE;
+}
-static PrivateDescRec *
-findItem(const DevPrivateKey key)
+static Bool
+dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes)
{
- if (!*key) {
- if (nextPriv >= PRIV_MAX)
- return NULL;
+ memmove((char *) *privates + bytes, *privates, new_offset - bytes);
+ memset(*privates, '\0', bytes);
+ return TRUE;
+}
- items[nextPriv].key = key;
- *key = nextPriv;
- nextPriv++;
- }
+static Bool
+fixupScreens(FixupFunc fixup, unsigned bytes)
+{
+ int s;
+ for (s = 0; s < screenInfo.numScreens; s++)
+ if (!fixup(&screenInfo.screens[s]->devPrivates, keys[PRIVATE_SCREEN].offset, bytes))
+ return FALSE;
+ return TRUE;
+}
- return items + *key;
+static Bool
+fixupServerClient(FixupFunc fixup, unsigned bytes)
+{
+ if (serverClient)
+ return fixup(&serverClient->devPrivates, keys[PRIVATE_CLIENT].offset, bytes);
+ return TRUE;
}
-static _X_INLINE int
-privateExists(PrivateRec **privates, const DevPrivateKey key)
+static Bool
+fixupExtensions(FixupFunc fixup, unsigned bytes)
{
- return *key && *privates &&
- (*privates)[0].state > *key &&
- (*privates)[*key].state;
+ unsigned char major;
+ ExtensionEntry *extension;
+ for (major = EXTENSION_BASE; (extension = GetExtensionEntry(major)); major++)
+ if (!fixup(&extension->devPrivates, keys[PRIVATE_EXTENSION].offset, bytes))
+ return FALSE;
+ return TRUE;
}
-/*
- * Request pre-allocated space.
- */
-int
-dixRequestPrivate(const DevPrivateKey key, unsigned size)
+static Bool
+fixupDefaultColormaps(FixupFunc fixup, unsigned bytes)
{
- PrivateDescRec *item = findItem(key);
- if (!item)
- return FALSE;
- if (size > item->size)
- item->size = size;
+ int s;
+ for (s = 0; s < screenInfo.numScreens; s++) {
+ ColormapPtr cmap;
+ dixLookupResourceByType((pointer *) &cmap, screenInfo.screens[s]->defColormap,
+ RT_COLORMAP, serverClient, DixCreateAccess);
+ if (cmap && !fixup(&cmap->devPrivates, keys[PRIVATE_COLORMAP].offset, bytes))
+ return FALSE;
+ }
return TRUE;
}
+static Bool (* const allocated_early[PRIVATE_LAST])(FixupFunc, unsigned) = {
+ [PRIVATE_SCREEN] = fixupScreens,
+ [PRIVATE_CLIENT] = fixupServerClient,
+ [PRIVATE_EXTENSION] = fixupExtensions,
+ [PRIVATE_COLORMAP] = fixupDefaultColormaps,
+};
+
/*
- * Allocate a private and attach it to an existing object.
+ * Register a private key. This takes the type of object the key will
+ * be used with, which may be PRIVATE_ALL indicating that this key
+ * will be used with all of the private objects. If 'size' is
+ * non-zero, then the specified amount of space will be allocated in
+ * the private storage. Otherwise, space for a single pointer will
+ * be allocated which can be set with dixSetPrivate
*/
-pointer *
-dixAllocatePrivate(PrivateRec **privates, const DevPrivateKey key)
+Bool
+dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size)
{
- PrivateDescRec *item = findItem(key);
- PrivateRec *ptr;
- pointer value;
- int oldsize, newsize;
-
- newsize = (*key / PRIV_STEP + 1) * PRIV_STEP;
-
- /* resize or init privates array */
- if (!item)
- return NULL;
+ DevPrivateType t;
+ int offset;
+ unsigned bytes;
- /* initialize privates array if necessary */
- if (!*privates) {
- ptr = calloc(newsize, sizeof(*ptr));
- if (!ptr)
- return NULL;
- *privates = ptr;
- (*privates)[0].state = newsize;
+ if (key->initialized) {
+ assert (size == key->size);
+ return TRUE;
}
- oldsize = (*privates)[0].state;
+ /* Compute required space */
+ bytes = size;
+ if (size == 0)
+ bytes = sizeof (void *);
+
+ /* align to void * size */
+ bytes = (bytes + sizeof (void *) - 1) & ~(sizeof (void *) - 1);
+
+ /* Update offsets for all affected keys */
+ if (type == PRIVATE_XSELINUX) {
+ DevPrivateKey k;
+
+ /* Resize if we can, or make sure nothing's allocated if we can't
+ */
+ for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++)
+ if (xselinux_private[t]) {
+ if (!allocated_early[t])
+ assert (!keys[t].created);
+ else if (!allocated_early[t](dixReallocPrivates, bytes))
+ return FALSE;
+ }
- /* resize privates array if necessary */
- if (*key >= oldsize) {
- ptr = realloc(*privates, newsize * sizeof(*ptr));
- if (!ptr)
- return NULL;
- memset(ptr + oldsize, 0, (newsize - oldsize) * sizeof(*ptr));
- *privates = ptr;
- (*privates)[0].state = newsize;
- }
+ /* Move all existing keys up in the privates space to make
+ * room for this new global key
+ */
+ for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
+ if (xselinux_private[t]) {
+ for (k = keys[t].key; k; k = k->next)
+ k->offset += bytes;
+ keys[t].offset += bytes;
+ if (allocated_early[t])
+ allocated_early[t](dixMovePrivates, bytes);
+ }
+ }
- /* initialize slot */
- ptr = *privates + *key;
- ptr->state = 1;
- if (item->size) {
- value = calloc(item->size, 1);
- if (!value)
- return NULL;
- ptr->value = value;
+ offset = 0;
+ } else {
+ /* Resize if we can, or make sure nothing's allocated if we can't */
+ if (!allocated_early[type])
+ assert(!keys[type].created);
+ else if (!allocated_early[type](dixReallocPrivates, bytes))
+ return FALSE;
+ offset = keys[type].offset;
+ keys[type].offset += bytes;
}
- return &ptr->value;
+ /* Setup this key */
+ key->offset = offset;
+ key->size = size;
+ key->initialized = TRUE;
+ key->type = type;
+ key->allocated = FALSE;
+ key->next = keys[type].key;
+ keys[type].key = key;
+
+ return TRUE;
}
/*
- * Look up a private pointer.
+ * Allocate a new private key.
+ *
+ * This manages the storage of the key object itself, freeing it when the
+ * privates system is restarted at server reset time. All other keys
+ * are expected to be statically allocated as the privates must be
+ * reset after all objects have been freed
*/
-pointer
-dixLookupPrivate(PrivateRec **privates, const DevPrivateKey key)
+DevPrivateKey
+dixCreatePrivateKey(DevPrivateType type, unsigned size)
{
- pointer *ptr;
+ DevPrivateKey key;
- if (privateExists(privates, key))
- return (*privates)[*key].value;
+ key = calloc(sizeof (DevPrivateKeyRec), 1);
+ if (!key)
+ return NULL;
+ if (!dixRegisterPrivateKey(key, type, size)) {
+ free(key);
+ return NULL;
+ }
+ key->allocated = TRUE;
+ return key;
+}
+
+/*
+ * Initialize privates by zeroing them
+ */
+void
+_dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type)
+{
+ keys[type].created++;
+ if (xselinux_private[type])
+ keys[PRIVATE_XSELINUX].created++;
+ if (keys[type].offset == 0)
+ addr = 0;
+ *privates = addr;
+ memset(addr, '\0', keys[type].offset);
+}
- ptr = dixAllocatePrivate(privates, key);
- return ptr ? *ptr : NULL;
+/*
+ * Clean up privates
+ */
+void
+_dixFiniPrivates(PrivatePtr privates, DevPrivateType type)
+{
+ keys[type].created--;
+ if (xselinux_private[type])
+ keys[PRIVATE_XSELINUX].created--;
}
/*
- * Look up the address of a private pointer.
+ * Allocate new object with privates.
+ *
+ * This is expected to be invoked from the
+ * dixAllocateObjectWithPrivates macro
*/
-pointer *
-dixLookupPrivateAddr(PrivateRec **privates, const DevPrivateKey key)
+void *
+_dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear, unsigned offset, DevPrivateType type)
{
- if (privateExists(privates, key))
- return &(*privates)[*key].value;
+ unsigned totalSize;
+ void *object;
+ PrivatePtr privates;
+ PrivatePtr *devPrivates;
+
+ assert (type > PRIVATE_SCREEN && type < PRIVATE_LAST);
+
+ /* round up so that void * is aligned */
+ baseSize = (baseSize + sizeof (void *) - 1) & ~(sizeof (void *) - 1);
+ totalSize = baseSize + keys[type].offset;
+ object = malloc(totalSize);
+ if (!object)
+ return NULL;
+
+ memset(object, '\0', clear);
+ privates = (PrivatePtr) (((char *) object) + baseSize);
+ devPrivates = (PrivatePtr *) ((char *) object + offset);
+
+ _dixInitPrivates(devPrivates, privates, type);
- return dixAllocatePrivate(privates, key);
+ return object;
}
/*
- * Set a private pointer.
+ * Allocate privates separately from containing object.
+ * Used for clients and screens.
*/
-int
-dixSetPrivate(PrivateRec **privates, const DevPrivateKey key, pointer val)
+Bool
+dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type)
{
- top:
- if (privateExists(privates, key)) {
- (*privates)[*key].value = val;
- return TRUE;
+ unsigned size;
+ PrivatePtr p;
+
+ assert (type > PRIVATE_XSELINUX && type < PRIVATE_LAST);
+
+ size = keys[type].offset;
+ if (!size) {
+ p = NULL;
+ } else {
+ if (!(p = malloc(size)))
+ return FALSE;
}
- if (!dixAllocatePrivate(privates, key))
- return FALSE;
- goto top;
+ _dixInitPrivates(privates, p, type);
+ ++keys[type].allocated;
+
+ return TRUE;
}
/*
- * Called to free privates at object deletion time.
+ * Free an object that has privates
+ *
+ * This is expected to be invoked from the
+ * dixFreeObjectWithPrivates macro
*/
void
-dixFreePrivates(PrivateRec *privates)
+_dixFreeObjectWithPrivates(void *object, PrivatePtr privates, DevPrivateType type)
{
- int i;
-
- if (privates)
- for (i = 1; i < privates->state; i++)
- if (privates[i].state) {
- /* free pre-allocated memory */
- if (items[i].size)
- free(privates[i].value);
- }
+ _dixFiniPrivates(privates, type);
+ free(object);
+}
+/*
+ * Called to free screen or client privates
+ */
+void
+dixFreePrivates(PrivatePtr privates, DevPrivateType type)
+{
+ _dixFiniPrivates(privates, type);
+ --keys[type].allocated;
free(privates);
}
+/*
+ * Return size of privates for the specified type
+ */
+extern _X_EXPORT int
+dixPrivatesSize(DevPrivateType type)
+{
+ assert (type >= PRIVATE_SCREEN && type < PRIVATE_LAST);
+
+ return keys[type].offset;
+}
+
/* Table of devPrivates offsets */
-static const int offsetDefaults[] = {
+static const int offsets[] = {
-1, /* RT_NONE */
offsetof(WindowRec, devPrivates), /* RT_WINDOW */
offsetof(PixmapRec, devPrivates), /* RT_PIXMAP */
@@ -216,67 +388,106 @@ static const int offsetDefaults[] = {
-1, /* RT_FONT */
offsetof(CursorRec, devPrivates), /* RT_CURSOR */
offsetof(ColormapRec, devPrivates), /* RT_COLORMAP */
- -1, /* RT_CMAPENTRY */
- -1, /* RT_OTHERCLIENT */
- -1 /* RT_PASSIVEGRAB */
};
-
-static int *offsets = NULL;
-static int offsetsSize = 0;
-/*
- * Specify where the devPrivates field is located in a structure type
- */
+#define NUM_OFFSETS (sizeof (offsets) / sizeof (offsets[0]))
+
int
-dixRegisterPrivateOffset(RESTYPE type, int offset)
+dixLookupPrivateOffset(RESTYPE type)
{
- type = type & TypeMask;
-
- /* resize offsets table if necessary */
- while (type >= offsetsSize) {
- unsigned i = offsetsSize * 2 * sizeof(int);
- offsets = (int *)realloc(offsets, i);
- if (!offsets) {
- offsetsSize = 0;
- return FALSE;
- }
- for (i=offsetsSize; i < 2*offsetsSize; i++)
- offsets[i] = -1;
- offsetsSize *= 2;
+ /*
+ * Special kludge for DBE which registers a new resource type that
+ * points at pixmaps (thanks, DBE)
+ */
+ if (type & RC_DRAWABLE) {
+ if (type == RT_WINDOW)
+ return offsets[RT_WINDOW & TypeMask];
+ else
+ return offsets[RT_PIXMAP & TypeMask];
}
-
- offsets[type] = offset;
- return TRUE;
+ type = type & TypeMask;
+ if (type < NUM_OFFSETS)
+ return offsets[type];
+ return -1;
}
-int
-dixLookupPrivateOffset(RESTYPE type)
+static const char *key_names[PRIVATE_LAST] = {
+ /* XSELinux uses the same private keys for numerous objects */
+ [PRIVATE_XSELINUX] = "XSELINUX",
+
+ /* Otherwise, you get a private in just the requested structure
+ */
+ /* These can have objects created before all of the keys are registered */
+ [PRIVATE_SCREEN] = "SCREEN",
+ [PRIVATE_EXTENSION] = "EXTENSION",
+ [PRIVATE_COLORMAP] = "COLORMAP",
+
+ /* These cannot have any objects before all relevant keys are registered */
+ [PRIVATE_DEVICE] = "DEVICE",
+ [PRIVATE_CLIENT] = "CLIENT",
+ [PRIVATE_PROPERTY] = "PROPERTY",
+ [PRIVATE_SELECTION] = "SELECTION",
+ [PRIVATE_WINDOW] = "WINDOW",
+ [PRIVATE_PIXMAP] = "PIXMAP",
+ [PRIVATE_GC] = "GC",
+ [PRIVATE_CURSOR] = "CURSOR",
+ [PRIVATE_CURSOR_BITS] = "CURSOR_BITS",
+
+ /* extension privates */
+ [PRIVATE_DBE_WINDOW] = "DBE_WINDOW",
+ [PRIVATE_DAMAGE] = "DAMAGE",
+ [PRIVATE_GLYPH] = "GLYPH",
+ [PRIVATE_GLYPHSET] = "GLYPHSET",
+ [PRIVATE_PICTURE] = "PICTURE",
+};
+
+void
+dixPrivateUsage(void)
{
- type = type & TypeMask;
- assert(type < offsetsSize);
- return offsets[type];
+ int objects = 0;
+ int bytes = 0;
+ int alloc = 0;
+ DevPrivateType t;
+
+ for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) {
+ if (keys[t].offset) {
+ ErrorF("%s: %d objects of %d bytes = %d total bytes %d private allocs\n",
+ key_names[t], keys[t].created, keys[t].offset, keys[t].created * keys[t].offset,
+ keys[t].allocated);
+ bytes += keys[t].created * keys[t].offset;
+ objects += keys[t].created;
+ alloc += keys[t].allocated;
+ }
+ }
+ ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n",
+ objects, bytes, alloc);
}
-int
+void
dixResetPrivates(void)
{
- int i;
-
- /* reset private descriptors */
- for (i = 1; i < nextPriv; i++) {
- *items[i].key = 0;
- items[i].size = 0;
+ DevPrivateType t;
+
+ for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
+ DevPrivateKey key, next;
+
+ for (key = keys[t].key; key; key = next) {
+ next = key->next;
+ key->offset = 0;
+ key->initialized = FALSE;
+ key->size = 0;
+ key->type = 0;
+ if (key->allocated)
+ free(key);
+ }
+ if (keys[t].created) {
+ ErrorF("%d %ss still allocated at reset\n",
+ keys[t].created, key_names[t]);
+ dixPrivateUsage();
+ }
+ keys[t].key = NULL;
+ keys[t].offset = 0;
+ keys[t].created = 0;
+ keys[t].allocated = 0;
}
- nextPriv = 1;
-
- /* reset offsets */
- if (offsets)
- free(offsets);
- offsetsSize = sizeof(offsetDefaults);
- offsets = malloc(offsetsSize);
- offsetsSize /= sizeof(int);
- if (!offsets)
- return FALSE;
- memcpy(offsets, offsetDefaults, sizeof(offsetDefaults));
- return TRUE;
}
diff --git a/xorg-server/dix/property.c b/xorg-server/dix/property.c
index 7c4bd62d2..9d30e726d 100644
--- a/xorg-server/dix/property.c
+++ b/xorg-server/dix/property.c
@@ -230,12 +230,12 @@ ProcChangeProperty(ClientPtr client)
if (!ValidAtom(stuff->property))
{
client->errorValue = stuff->property;
- return(BadAtom);
+ return BadAtom;
}
if (!ValidAtom(stuff->type))
{
client->errorValue = stuff->type;
- return(BadAtom);
+ return BadAtom;
}
err = dixChangeWindowProperty(client, pWin, stuff->property, stuff->type,
@@ -268,15 +268,15 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
if (rc == BadMatch) /* just add to list */
{
if (!pWin->optional && !MakeWindowOptional (pWin))
- return(BadAlloc);
- pProp = malloc(sizeof(PropertyRec));
+ return BadAlloc;
+ pProp = dixAllocateObjectWithPrivates(PropertyRec, PRIVATE_PROPERTY);
if (!pProp)
- return(BadAlloc);
+ return BadAlloc;
data = malloc(totalSize);
if (!data && len)
{
- free(pProp);
- return(BadAlloc);
+ dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
+ return BadAlloc;
}
memcpy(data, value, totalSize);
pProp->propertyName = property;
@@ -289,7 +289,7 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
DixCreateAccess|DixWriteAccess);
if (rc != Success) {
free(data);
- free(pProp);
+ dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
pClient->errorValue = property;
return rc;
}
@@ -304,9 +304,9 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
"PropModeReplace" since they will be written over. */
if ((format != pProp->format) && (mode != PropModeReplace))
- return(BadMatch);
+ return BadMatch;
if ((pProp->type != type) && (mode != PropModeReplace))
- return(BadMatch);
+ return BadMatch;
/* save the old values for later */
savedProp = *pProp;
@@ -315,7 +315,7 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
{
data = malloc(totalSize);
if (!data && len)
- return(BadAlloc);
+ return BadAlloc;
memcpy(data, value, totalSize);
pProp->data = data;
pProp->size = len;
@@ -330,7 +330,7 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
{
data = malloc((pProp->size + len) * sizeInBytes);
if (!data)
- return(BadAlloc);
+ return BadAlloc;
memcpy(data, pProp->data, pProp->size * sizeInBytes);
memcpy(data + pProp->size * sizeInBytes, value, totalSize);
pProp->data = data;
@@ -340,7 +340,7 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
{
data = malloc(sizeInBytes * (len + pProp->size));
if (!data)
- return(BadAlloc);
+ return BadAlloc;
memcpy(data + totalSize, pProp->data, pProp->size * sizeInBytes);
memcpy(data, value, totalSize);
pProp->data = data;
@@ -369,7 +369,7 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
if (sendevent)
deliverPropertyNotifyEvent(pWin, PropertyNewValue, pProp->propertyName);
- return(Success);
+ return Success;
}
int
@@ -405,9 +405,8 @@ DeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName)
}
deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
- dixFreePrivates(pProp->devPrivates);
free(pProp->data);
- free(pProp);
+ dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
}
return rc;
}
@@ -422,9 +421,8 @@ DeleteAllWindowProperties(WindowPtr pWin)
{
deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
pNextProp = pProp->next;
- dixFreePrivates(pProp->devPrivates);
free(pProp->data);
- free(pProp);
+ dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
pProp = pNextProp;
}
}
@@ -479,17 +477,17 @@ ProcGetProperty(ClientPtr client)
if (!ValidAtom(stuff->property))
{
client->errorValue = stuff->property;
- return(BadAtom);
+ return BadAtom;
}
if ((stuff->delete != xTrue) && (stuff->delete != xFalse))
{
client->errorValue = stuff->delete;
- return(BadValue);
+ return BadValue;
}
if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type))
{
client->errorValue = stuff->type;
- return(BadAtom);
+ return BadAtom;
}
memset(&reply, 0, sizeof(xGetPropertyReply));
@@ -515,7 +513,7 @@ ProcGetProperty(ClientPtr client)
reply.nItems = 0;
reply.propertyType = pProp->type;
WriteReplyToClient(client, sizeof(xGenericReply), &reply);
- return(Success);
+ return Success;
}
/*
@@ -570,9 +568,8 @@ ProcGetProperty(ClientPtr client)
prevProp->next = pProp->next;
}
- dixFreePrivates(pProp->devPrivates);
free(pProp->data);
- free(pProp);
+ dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
}
return Success;
}
@@ -638,7 +635,7 @@ ProcDeleteProperty(ClientPtr client)
if (!ValidAtom(stuff->property))
{
client->errorValue = stuff->property;
- return (BadAtom);
+ return BadAtom;
}
return DeleteProperty(client, pWin, stuff->property);
diff --git a/xorg-server/dix/ptrveloc.c b/xorg-server/dix/ptrveloc.c
index 37dd0548c..eeedb83dd 100644
--- a/xorg-server/dix/ptrveloc.c
+++ b/xorg-server/dix/ptrveloc.c
@@ -494,7 +494,7 @@ CalcTracker(DeviceVelocityPtr vel, int offset, int cur_t){
+ vel->tracker[index].dy * vel->tracker[index].dy);
int dtime = cur_t - vel->tracker[index].time;
if(dtime > 0)
- return (dist / dtime);
+ return dist / dtime;
else
return 0;/* synonymous for NaN, since we're not C99 */
}
diff --git a/xorg-server/dix/region.c b/xorg-server/dix/region.c
new file mode 100644
index 000000000..c0add6ca9
--- /dev/null
+++ b/xorg-server/dix/region.c
@@ -0,0 +1,1659 @@
+/***********************************************************
+
+Copyright 1987, 1988, 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 1987, 1988, 1989 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 "regionstr.h"
+#include <X11/Xprotostr.h>
+#include <X11/Xfuncproto.h>
+#include "gc.h"
+#include <pixman.h>
+
+#undef assert
+#ifdef REGION_DEBUG
+#define assert(expr) { \
+ CARD32 *foo = NULL; \
+ if (!(expr)) { \
+ ErrorF("Assertion failed file %s, line %d: %s\n", \
+ __FILE__, __LINE__, #expr); \
+ *foo = 0xdeadbeef; /* to get a backtrace */ \
+ } \
+ }
+#else
+#define assert(expr)
+#endif
+
+#define good(reg) assert(RegionIsValid(reg))
+
+/*
+ * The functions in this file implement the Region abstraction used extensively
+ * throughout the X11 sample server. A Region is simply a set of disjoint
+ * (non-overlapping) rectangles, plus an "extent" rectangle which is the
+ * smallest single rectangle that contains all the non-overlapping rectangles.
+ *
+ * A Region is implemented as a "y-x-banded" array of rectangles. This array
+ * imposes two degrees of order. First, all rectangles are sorted by top side
+ * y coordinate first (y1), and then by left side x coordinate (x1).
+ *
+ * Furthermore, the rectangles are grouped into "bands". Each rectangle in a
+ * band has the same top y coordinate (y1), and each has the same bottom y
+ * coordinate (y2). Thus all rectangles in a band differ only in their left
+ * and right side (x1 and x2). Bands are implicit in the array of rectangles:
+ * there is no separate list of band start pointers.
+ *
+ * The y-x band representation does not minimize rectangles. In particular,
+ * if a rectangle vertically crosses a band (the rectangle has scanlines in
+ * the y1 to y2 area spanned by the band), then the rectangle may be broken
+ * down into two or more smaller rectangles stacked one atop the other.
+ *
+ * ----------- -----------
+ * | | | | band 0
+ * | | -------- ----------- --------
+ * | | | | in y-x banded | | | | band 1
+ * | | | | form is | | | |
+ * ----------- | | ----------- --------
+ * | | | | band 2
+ * -------- --------
+ *
+ * An added constraint on the rectangles is that they must cover as much
+ * horizontal area as possible: no two rectangles within a band are allowed
+ * to touch.
+ *
+ * Whenever possible, bands will be merged together to cover a greater vertical
+ * distance (and thus reduce the number of rectangles). Two bands can be merged
+ * only if the bottom of one touches the top of the other and they have
+ * rectangles in the same places (of the same width, of course).
+ *
+ * Adam de Boor wrote most of the original region code. Joel McCormack
+ * substantially modified or rewrote most of the core arithmetic routines,
+ * and added RegionValidate in order to support several speed improvements
+ * to miValidateTree. Bob Scheifler changed the representation to be more
+ * compact when empty or a single rectangle, and did a bunch of gratuitous
+ * reformatting.
+ */
+
+/* true iff two Boxes overlap */
+#define EXTENTCHECK(r1,r2) \
+ (!( ((r1)->x2 <= (r2)->x1) || \
+ ((r1)->x1 >= (r2)->x2) || \
+ ((r1)->y2 <= (r2)->y1) || \
+ ((r1)->y1 >= (r2)->y2) ) )
+
+/* true iff (x,y) is in Box */
+#define INBOX(r,x,y) \
+ ( ((r)->x2 > x) && \
+ ((r)->x1 <= x) && \
+ ((r)->y2 > y) && \
+ ((r)->y1 <= y) )
+
+/* true iff Box r1 contains Box r2 */
+#define SUBSUMES(r1,r2) \
+ ( ((r1)->x1 <= (r2)->x1) && \
+ ((r1)->x2 >= (r2)->x2) && \
+ ((r1)->y1 <= (r2)->y1) && \
+ ((r1)->y2 >= (r2)->y2) )
+
+#define xallocData(n) malloc(RegionSizeof(n))
+#define xfreeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data)
+
+#define RECTALLOC_BAIL(pReg,n,bail) \
+if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
+ if (!RegionRectAlloc(pReg, n)) { goto bail; }
+
+#define RECTALLOC(pReg,n) \
+if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
+ if (!RegionRectAlloc(pReg, n)) { return FALSE; }
+
+#define ADDRECT(pNextRect,nx1,ny1,nx2,ny2) \
+{ \
+ pNextRect->x1 = nx1; \
+ pNextRect->y1 = ny1; \
+ pNextRect->x2 = nx2; \
+ pNextRect->y2 = ny2; \
+ pNextRect++; \
+}
+
+#define NEWRECT(pReg,pNextRect,nx1,ny1,nx2,ny2) \
+{ \
+ if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\
+ { \
+ if (!RegionRectAlloc(pReg, 1)) \
+ return FALSE; \
+ pNextRect = RegionTop(pReg); \
+ } \
+ ADDRECT(pNextRect,nx1,ny1,nx2,ny2); \
+ pReg->data->numRects++; \
+ assert(pReg->data->numRects<=pReg->data->size); \
+}
+
+
+#define DOWNSIZE(reg,numRects) \
+if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \
+{ \
+ RegDataPtr NewData; \
+ NewData = (RegDataPtr)realloc((reg)->data, RegionSizeof(numRects)); \
+ if (NewData) \
+ { \
+ NewData->size = (numRects); \
+ (reg)->data = NewData; \
+ } \
+}
+
+
+BoxRec RegionEmptyBox = {0, 0, 0, 0};
+RegDataRec RegionEmptyData = {0, 0};
+
+RegDataRec RegionBrokenData = {0, 0};
+static RegionRec RegionBrokenRegion = { { 0, 0, 0, 0 }, &RegionBrokenData };
+
+void
+InitRegions (void)
+{
+ pixman_region_set_static_pointers (&RegionEmptyBox, &RegionEmptyData, &RegionBrokenData);
+}
+
+/*****************************************************************
+ * RegionCreate(rect, size)
+ * This routine does a simple malloc to make a structure of
+ * REGION of "size" number of rectangles.
+ *****************************************************************/
+
+RegionPtr
+RegionCreate(BoxPtr rect, int size)
+{
+ RegionPtr pReg;
+
+ pReg = (RegionPtr)malloc(sizeof(RegionRec));
+ if (!pReg)
+ return &RegionBrokenRegion;
+
+ RegionInit (pReg, rect, size);
+
+ return pReg;
+}
+
+void
+RegionDestroy(RegionPtr pReg)
+{
+ pixman_region_fini (pReg);
+ if (pReg != &RegionBrokenRegion)
+ free(pReg);
+}
+
+void
+RegionPrint(RegionPtr rgn)
+{
+ int num, size;
+ int i;
+ BoxPtr rects;
+
+ num = RegionNumRects(rgn);
+ size = RegionSize(rgn);
+ rects = RegionRects(rgn);
+ ErrorF("[mi] num: %d size: %d\n", num, size);
+ ErrorF("[mi] extents: %d %d %d %d\n",
+ rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2);
+ for (i = 0; i < num; i++)
+ ErrorF("[mi] %d %d %d %d \n",
+ rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
+ ErrorF("[mi] \n");
+}
+
+#ifdef DEBUG
+Bool
+RegionIsValid(RegionPtr reg)
+{
+ int i, numRects;
+
+ if ((reg->extents.x1 > reg->extents.x2) ||
+ (reg->extents.y1 > reg->extents.y2))
+ return FALSE;
+ numRects = RegionNumRects(reg);
+ if (!numRects)
+ return ((reg->extents.x1 == reg->extents.x2) &&
+ (reg->extents.y1 == reg->extents.y2) &&
+ (reg->data->size || (reg->data == &RegionEmptyData)));
+ else if (numRects == 1)
+ return !reg->data;
+ else
+ {
+ BoxPtr pboxP, pboxN;
+ BoxRec box;
+
+ pboxP = RegionRects(reg);
+ box = *pboxP;
+ box.y2 = pboxP[numRects-1].y2;
+ pboxN = pboxP + 1;
+ for (i = numRects; --i > 0; pboxP++, pboxN++)
+ {
+ if ((pboxN->x1 >= pboxN->x2) ||
+ (pboxN->y1 >= pboxN->y2))
+ return FALSE;
+ if (pboxN->x1 < box.x1)
+ box.x1 = pboxN->x1;
+ if (pboxN->x2 > box.x2)
+ box.x2 = pboxN->x2;
+ if ((pboxN->y1 < pboxP->y1) ||
+ ((pboxN->y1 == pboxP->y1) &&
+ ((pboxN->x1 < pboxP->x2) || (pboxN->y2 != pboxP->y2))))
+ return FALSE;
+ }
+ return ((box.x1 == reg->extents.x1) &&
+ (box.x2 == reg->extents.x2) &&
+ (box.y1 == reg->extents.y1) &&
+ (box.y2 == reg->extents.y2));
+ }
+}
+#endif /* DEBUG */
+
+Bool
+RegionBreak (RegionPtr pReg)
+{
+ xfreeData (pReg);
+ pReg->extents = RegionEmptyBox;
+ pReg->data = &RegionBrokenData;
+ return FALSE;
+}
+
+Bool
+RegionRectAlloc(RegionPtr pRgn, int n)
+{
+ RegDataPtr data;
+
+ if (!pRgn->data)
+ {
+ n++;
+ pRgn->data = xallocData(n);
+ if (!pRgn->data)
+ return RegionBreak (pRgn);
+ pRgn->data->numRects = 1;
+ *RegionBoxptr(pRgn) = pRgn->extents;
+ }
+ else if (!pRgn->data->size)
+ {
+ pRgn->data = xallocData(n);
+ if (!pRgn->data)
+ return RegionBreak (pRgn);
+ pRgn->data->numRects = 0;
+ }
+ else
+ {
+ if (n == 1)
+ {
+ n = pRgn->data->numRects;
+ if (n > 500) /* XXX pick numbers out of a hat */
+ n = 250;
+ }
+ n += pRgn->data->numRects;
+ data = (RegDataPtr)realloc(pRgn->data, RegionSizeof(n));
+ if (!data)
+ return RegionBreak (pRgn);
+ pRgn->data = data;
+ }
+ pRgn->data->size = n;
+ return TRUE;
+}
+
+/*======================================================================
+ * Generic Region Operator
+ *====================================================================*/
+
+/*-
+ *-----------------------------------------------------------------------
+ * RegionCoalesce --
+ * Attempt to merge the boxes in the current band with those in the
+ * previous one. We are guaranteed that the current band extends to
+ * the end of the rects array. Used only by RegionOp.
+ *
+ * Results:
+ * The new index for the previous band.
+ *
+ * Side Effects:
+ * If coalescing takes place:
+ * - rectangles in the previous band will have their y2 fields
+ * altered.
+ * - pReg->data->numRects will be decreased.
+ *
+ *-----------------------------------------------------------------------
+ */
+_X_INLINE static int
+RegionCoalesce (
+ RegionPtr pReg, /* Region to coalesce */
+ int prevStart, /* Index of start of previous band */
+ int curStart) /* Index of start of current band */
+{
+ BoxPtr pPrevBox; /* Current box in previous band */
+ BoxPtr pCurBox; /* Current box in current band */
+ int numRects; /* Number rectangles in both bands */
+ int y2; /* Bottom of current band */
+ /*
+ * Figure out how many rectangles are in the band.
+ */
+ numRects = curStart - prevStart;
+ assert(numRects == pReg->data->numRects - curStart);
+
+ if (!numRects) return curStart;
+
+ /*
+ * The bands may only be coalesced if the bottom of the previous
+ * matches the top scanline of the current.
+ */
+ pPrevBox = RegionBox(pReg, prevStart);
+ pCurBox = RegionBox(pReg, curStart);
+ if (pPrevBox->y2 != pCurBox->y1) return curStart;
+
+ /*
+ * Make sure the bands have boxes in the same places. This
+ * assumes that boxes have been added in such a way that they
+ * cover the most area possible. I.e. two boxes in a band must
+ * have some horizontal space between them.
+ */
+ y2 = pCurBox->y2;
+
+ do {
+ if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2)) {
+ return curStart;
+ }
+ pPrevBox++;
+ pCurBox++;
+ numRects--;
+ } while (numRects);
+
+ /*
+ * The bands may be merged, so set the bottom y of each box
+ * in the previous band to the bottom y of the current band.
+ */
+ numRects = curStart - prevStart;
+ pReg->data->numRects -= numRects;
+ do {
+ pPrevBox--;
+ pPrevBox->y2 = y2;
+ numRects--;
+ } while (numRects);
+ return prevStart;
+}
+
+
+/* Quicky macro to avoid trivial reject procedure calls to RegionCoalesce */
+
+#define Coalesce(newReg, prevBand, curBand) \
+ if (curBand - prevBand == newReg->data->numRects - curBand) { \
+ prevBand = RegionCoalesce(newReg, prevBand, curBand); \
+ } else { \
+ prevBand = curBand; \
+ }
+
+/*-
+ *-----------------------------------------------------------------------
+ * RegionAppendNonO --
+ * Handle a non-overlapping band for the union and subtract operations.
+ * Just adds the (top/bottom-clipped) rectangles into the region.
+ * Doesn't have to check for subsumption or anything.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * pReg->data->numRects is incremented and the rectangles overwritten
+ * with the rectangles we're passed.
+ *
+ *-----------------------------------------------------------------------
+ */
+
+_X_INLINE static Bool
+RegionAppendNonO (
+ RegionPtr pReg,
+ BoxPtr r,
+ BoxPtr rEnd,
+ int y1,
+ int y2)
+{
+ BoxPtr pNextRect;
+ int newRects;
+
+ newRects = rEnd - r;
+
+ assert(y1 < y2);
+ assert(newRects != 0);
+
+ /* Make sure we have enough space for all rectangles to be added */
+ RECTALLOC(pReg, newRects);
+ pNextRect = RegionTop(pReg);
+ pReg->data->numRects += newRects;
+ do {
+ assert(r->x1 < r->x2);
+ ADDRECT(pNextRect, r->x1, y1, r->x2, y2);
+ r++;
+ } while (r != rEnd);
+
+ return TRUE;
+}
+
+#define FindBand(r, rBandEnd, rEnd, ry1) \
+{ \
+ ry1 = r->y1; \
+ rBandEnd = r+1; \
+ while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) { \
+ rBandEnd++; \
+ } \
+}
+
+#define AppendRegions(newReg, r, rEnd) \
+{ \
+ int newRects; \
+ if ((newRects = rEnd - r)) { \
+ RECTALLOC(newReg, newRects); \
+ memmove((char *)RegionTop(newReg),(char *)r, \
+ newRects * sizeof(BoxRec)); \
+ newReg->data->numRects += newRects; \
+ } \
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * RegionOp --
+ * Apply an operation to two regions. Called by RegionUnion, RegionInverse,
+ * RegionSubtract, RegionIntersect.... Both regions MUST have at least one
+ * rectangle, and cannot be the same object.
+ *
+ * Results:
+ * TRUE if successful.
+ *
+ * Side Effects:
+ * The new region is overwritten.
+ * pOverlap set to TRUE if overlapFunc ever returns TRUE.
+ *
+ * Notes:
+ * The idea behind this function is to view the two regions as sets.
+ * Together they cover a rectangle of area that this function divides
+ * into horizontal bands where points are covered only by one region
+ * or by both. For the first case, the nonOverlapFunc is called with
+ * each the band and the band's upper and lower extents. For the
+ * second, the overlapFunc is called to process the entire band. It
+ * is responsible for clipping the rectangles in the band, though
+ * this function provides the boundaries.
+ * At the end of each band, the new region is coalesced, if possible,
+ * to reduce the number of rectangles in the region.
+ *
+ *-----------------------------------------------------------------------
+ */
+
+typedef Bool (*OverlapProcPtr)(
+ RegionPtr pReg,
+ BoxPtr r1,
+ BoxPtr r1End,
+ BoxPtr r2,
+ BoxPtr r2End,
+ short y1,
+ short y2,
+ Bool *pOverlap);
+
+static Bool
+RegionOp(
+ RegionPtr newReg, /* Place to store result */
+ RegionPtr reg1, /* First region in operation */
+ RegionPtr reg2, /* 2d region in operation */
+ OverlapProcPtr overlapFunc, /* Function to call for over-
+ * lapping bands */
+ Bool appendNon1, /* Append non-overlapping bands */
+ /* in region 1 ? */
+ Bool appendNon2, /* Append non-overlapping bands */
+ /* in region 2 ? */
+ Bool *pOverlap)
+{
+ BoxPtr r1; /* Pointer into first region */
+ BoxPtr r2; /* Pointer into 2d region */
+ BoxPtr r1End; /* End of 1st region */
+ BoxPtr r2End; /* End of 2d region */
+ short ybot; /* Bottom of intersection */
+ short ytop; /* Top of intersection */
+ RegDataPtr oldData; /* Old data for newReg */
+ int prevBand; /* Index of start of
+ * previous band in newReg */
+ int curBand; /* Index of start of current
+ * band in newReg */
+ BoxPtr r1BandEnd; /* End of current band in r1 */
+ BoxPtr r2BandEnd; /* End of current band in r2 */
+ short top; /* Top of non-overlapping band */
+ short bot; /* Bottom of non-overlapping band*/
+ int r1y1; /* Temps for r1->y1 and r2->y1 */
+ int r2y1;
+ int newSize;
+ int numRects;
+
+ /*
+ * Break any region computed from a broken region
+ */
+ if (RegionNar (reg1) || RegionNar(reg2))
+ return RegionBreak (newReg);
+
+ /*
+ * Initialization:
+ * set r1, r2, r1End and r2End appropriately, save the rectangles
+ * of the destination region until the end in case it's one of
+ * the two source regions, then mark the "new" region empty, allocating
+ * another array of rectangles for it to use.
+ */
+
+ r1 = RegionRects(reg1);
+ newSize = RegionNumRects(reg1);
+ r1End = r1 + newSize;
+ numRects = RegionNumRects(reg2);
+ r2 = RegionRects(reg2);
+ r2End = r2 + numRects;
+ assert(r1 != r1End);
+ assert(r2 != r2End);
+
+ oldData = NULL;
+ if (((newReg == reg1) && (newSize > 1)) ||
+ ((newReg == reg2) && (numRects > 1)))
+ {
+ oldData = newReg->data;
+ newReg->data = &RegionEmptyData;
+ }
+ /* guess at new size */
+ if (numRects > newSize)
+ newSize = numRects;
+ newSize <<= 1;
+ if (!newReg->data)
+ newReg->data = &RegionEmptyData;
+ else if (newReg->data->size)
+ newReg->data->numRects = 0;
+ if (newSize > newReg->data->size)
+ if (!RegionRectAlloc(newReg, newSize))
+ return FALSE;
+
+ /*
+ * Initialize ybot.
+ * In the upcoming loop, ybot and ytop serve different functions depending
+ * on whether the band being handled is an overlapping or non-overlapping
+ * band.
+ * In the case of a non-overlapping band (only one of the regions
+ * has points in the band), ybot is the bottom of the most recent
+ * intersection and thus clips the top of the rectangles in that band.
+ * ytop is the top of the next intersection between the two regions and
+ * serves to clip the bottom of the rectangles in the current band.
+ * For an overlapping band (where the two regions intersect), ytop clips
+ * the top of the rectangles of both regions and ybot clips the bottoms.
+ */
+
+ ybot = min(r1->y1, r2->y1);
+
+ /*
+ * prevBand serves to mark the start of the previous band so rectangles
+ * can be coalesced into larger rectangles. qv. RegionCoalesce, above.
+ * In the beginning, there is no previous band, so prevBand == curBand
+ * (curBand is set later on, of course, but the first band will always
+ * start at index 0). prevBand and curBand must be indices because of
+ * the possible expansion, and resultant moving, of the new region's
+ * array of rectangles.
+ */
+ prevBand = 0;
+
+ do {
+ /*
+ * This algorithm proceeds one source-band (as opposed to a
+ * destination band, which is determined by where the two regions
+ * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
+ * rectangle after the last one in the current band for their
+ * respective regions.
+ */
+ assert(r1 != r1End);
+ assert(r2 != r2End);
+
+ FindBand(r1, r1BandEnd, r1End, r1y1);
+ FindBand(r2, r2BandEnd, r2End, r2y1);
+
+ /*
+ * First handle the band that doesn't intersect, if any.
+ *
+ * Note that attention is restricted to one band in the
+ * non-intersecting region at once, so if a region has n
+ * bands between the current position and the next place it overlaps
+ * the other, this entire loop will be passed through n times.
+ */
+ if (r1y1 < r2y1) {
+ if (appendNon1) {
+ top = max(r1y1, ybot);
+ bot = min(r1->y2, r2y1);
+ if (top != bot) {
+ curBand = newReg->data->numRects;
+ RegionAppendNonO(newReg, r1, r1BandEnd, top, bot);
+ Coalesce(newReg, prevBand, curBand);
+ }
+ }
+ ytop = r2y1;
+ } else if (r2y1 < r1y1) {
+ if (appendNon2) {
+ top = max(r2y1, ybot);
+ bot = min(r2->y2, r1y1);
+ if (top != bot) {
+ curBand = newReg->data->numRects;
+ RegionAppendNonO(newReg, r2, r2BandEnd, top, bot);
+ Coalesce(newReg, prevBand, curBand);
+ }
+ }
+ ytop = r1y1;
+ } else {
+ ytop = r1y1;
+ }
+
+ /*
+ * Now see if we've hit an intersecting band. The two bands only
+ * intersect if ybot > ytop
+ */
+ ybot = min(r1->y2, r2->y2);
+ if (ybot > ytop) {
+ curBand = newReg->data->numRects;
+ (* overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot,
+ pOverlap);
+ Coalesce(newReg, prevBand, curBand);
+ }
+
+ /*
+ * If we've finished with a band (y2 == ybot) we skip forward
+ * in the region to the next band.
+ */
+ if (r1->y2 == ybot) r1 = r1BandEnd;
+ if (r2->y2 == ybot) r2 = r2BandEnd;
+
+ } while (r1 != r1End && r2 != r2End);
+
+ /*
+ * Deal with whichever region (if any) still has rectangles left.
+ *
+ * We only need to worry about banding and coalescing for the very first
+ * band left. After that, we can just group all remaining boxes,
+ * regardless of how many bands, into one final append to the list.
+ */
+
+ if ((r1 != r1End) && appendNon1) {
+ /* Do first nonOverlap1Func call, which may be able to coalesce */
+ FindBand(r1, r1BandEnd, r1End, r1y1);
+ curBand = newReg->data->numRects;
+ RegionAppendNonO(newReg, r1, r1BandEnd, max(r1y1, ybot), r1->y2);
+ Coalesce(newReg, prevBand, curBand);
+ /* Just append the rest of the boxes */
+ AppendRegions(newReg, r1BandEnd, r1End);
+
+ } else if ((r2 != r2End) && appendNon2) {
+ /* Do first nonOverlap2Func call, which may be able to coalesce */
+ FindBand(r2, r2BandEnd, r2End, r2y1);
+ curBand = newReg->data->numRects;
+ RegionAppendNonO(newReg, r2, r2BandEnd, max(r2y1, ybot), r2->y2);
+ Coalesce(newReg, prevBand, curBand);
+ /* Append rest of boxes */
+ AppendRegions(newReg, r2BandEnd, r2End);
+ }
+
+ free(oldData);
+
+ if (!(numRects = newReg->data->numRects))
+ {
+ xfreeData(newReg);
+ newReg->data = &RegionEmptyData;
+ }
+ else if (numRects == 1)
+ {
+ newReg->extents = *RegionBoxptr(newReg);
+ xfreeData(newReg);
+ newReg->data = NULL;
+ }
+ else
+ {
+ DOWNSIZE(newReg, numRects);
+ }
+
+ return TRUE;
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * RegionSetExtents --
+ * Reset the extents of a region to what they should be. Called by
+ * Subtract and Intersect as they can't figure it out along the
+ * way or do so easily, as Union can.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The region's 'extents' structure is overwritten.
+ *
+ *-----------------------------------------------------------------------
+ */
+static void
+RegionSetExtents (RegionPtr pReg)
+{
+ BoxPtr pBox, pBoxEnd;
+
+ if (!pReg->data)
+ return;
+ if (!pReg->data->size)
+ {
+ pReg->extents.x2 = pReg->extents.x1;
+ pReg->extents.y2 = pReg->extents.y1;
+ return;
+ }
+
+ pBox = RegionBoxptr(pReg);
+ pBoxEnd = RegionEnd(pReg);
+
+ /*
+ * Since pBox is the first rectangle in the region, it must have the
+ * smallest y1 and since pBoxEnd is the last rectangle in the region,
+ * it must have the largest y2, because of banding. Initialize x1 and
+ * x2 from pBox and pBoxEnd, resp., as good things to initialize them
+ * to...
+ */
+ pReg->extents.x1 = pBox->x1;
+ pReg->extents.y1 = pBox->y1;
+ pReg->extents.x2 = pBoxEnd->x2;
+ pReg->extents.y2 = pBoxEnd->y2;
+
+ assert(pReg->extents.y1 < pReg->extents.y2);
+ while (pBox <= pBoxEnd) {
+ if (pBox->x1 < pReg->extents.x1)
+ pReg->extents.x1 = pBox->x1;
+ if (pBox->x2 > pReg->extents.x2)
+ pReg->extents.x2 = pBox->x2;
+ pBox++;
+ };
+
+ assert(pReg->extents.x1 < pReg->extents.x2);
+}
+
+/*======================================================================
+ * Region Intersection
+ *====================================================================*/
+/*-
+ *-----------------------------------------------------------------------
+ * RegionIntersectO --
+ * Handle an overlapping band for RegionIntersect.
+ *
+ * Results:
+ * TRUE if successful.
+ *
+ * Side Effects:
+ * Rectangles may be added to the region.
+ *
+ *-----------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+
+#define MERGERECT(r) \
+{ \
+ if (r->x1 <= x2) { \
+ /* Merge with current rectangle */ \
+ if (r->x1 < x2) *pOverlap = TRUE; \
+ if (x2 < r->x2) x2 = r->x2; \
+ } else { \
+ /* Add current rectangle, start new one */ \
+ NEWRECT(pReg, pNextRect, x1, y1, x2, y2); \
+ x1 = r->x1; \
+ x2 = r->x2; \
+ } \
+ r++; \
+}
+
+/*======================================================================
+ * Region Union
+ *====================================================================*/
+
+/*-
+ *-----------------------------------------------------------------------
+ * RegionUnionO --
+ * Handle an overlapping band for the union operation. Picks the
+ * left-most rectangle each time and merges it into the region.
+ *
+ * Results:
+ * TRUE if successful.
+ *
+ * Side Effects:
+ * pReg is overwritten.
+ * pOverlap is set to TRUE if any boxes overlap.
+ *
+ *-----------------------------------------------------------------------
+ */
+static Bool
+RegionUnionO (
+ RegionPtr pReg,
+ BoxPtr r1,
+ BoxPtr r1End,
+ BoxPtr r2,
+ BoxPtr r2End,
+ short y1,
+ short y2,
+ Bool *pOverlap)
+{
+ BoxPtr pNextRect;
+ int x1; /* left and right side of current union */
+ int x2;
+
+ assert (y1 < y2);
+ assert(r1 != r1End && r2 != r2End);
+
+ pNextRect = RegionTop(pReg);
+
+ /* Start off current rectangle */
+ if (r1->x1 < r2->x1)
+ {
+ x1 = r1->x1;
+ x2 = r1->x2;
+ r1++;
+ }
+ else
+ {
+ x1 = r2->x1;
+ x2 = r2->x2;
+ r2++;
+ }
+ while (r1 != r1End && r2 != r2End)
+ {
+ if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2);
+ }
+
+ /* Finish off whoever (if any) is left */
+ if (r1 != r1End)
+ {
+ do
+ {
+ MERGERECT(r1);
+ } while (r1 != r1End);
+ }
+ else if (r2 != r2End)
+ {
+ do
+ {
+ MERGERECT(r2);
+ } while (r2 != r2End);
+ }
+
+ /* Add current rectangle */
+ NEWRECT(pReg, pNextRect, x1, y1, x2, y2);
+
+ return TRUE;
+}
+
+/*======================================================================
+ * Batch Rectangle Union
+ *====================================================================*/
+
+/*-
+ *-----------------------------------------------------------------------
+ * RegionAppend --
+ *
+ * "Append" the rgn rectangles onto the end of dstrgn, maintaining
+ * knowledge of YX-banding when it's easy. Otherwise, dstrgn just
+ * becomes a non-y-x-banded random collection of rectangles, and not
+ * yet a true region. After a sequence of appends, the caller must
+ * call RegionValidate to ensure that a valid region is constructed.
+ *
+ * Results:
+ * TRUE if successful.
+ *
+ * Side Effects:
+ * dstrgn is modified if rgn has rectangles.
+ *
+ */
+Bool
+RegionAppend(RegionPtr dstrgn, RegionPtr rgn)
+{
+ int numRects, dnumRects, size;
+ BoxPtr new, old;
+ Bool prepend;
+
+ if (RegionNar(rgn))
+ return RegionBreak (dstrgn);
+
+ if (!rgn->data && (dstrgn->data == &RegionEmptyData))
+ {
+ dstrgn->extents = rgn->extents;
+ dstrgn->data = NULL;
+ return TRUE;
+ }
+
+ numRects = RegionNumRects(rgn);
+ if (!numRects)
+ return TRUE;
+ prepend = FALSE;
+ size = numRects;
+ dnumRects = RegionNumRects(dstrgn);
+ if (!dnumRects && (size < 200))
+ size = 200; /* XXX pick numbers out of a hat */
+ RECTALLOC(dstrgn, size);
+ old = RegionRects(rgn);
+ if (!dnumRects)
+ dstrgn->extents = rgn->extents;
+ else if (dstrgn->extents.x2 > dstrgn->extents.x1)
+ {
+ BoxPtr first, last;
+
+ first = old;
+ last = RegionBoxptr(dstrgn) + (dnumRects - 1);
+ if ((first->y1 > last->y2) ||
+ ((first->y1 == last->y1) && (first->y2 == last->y2) &&
+ (first->x1 > last->x2)))
+ {
+ if (rgn->extents.x1 < dstrgn->extents.x1)
+ dstrgn->extents.x1 = rgn->extents.x1;
+ if (rgn->extents.x2 > dstrgn->extents.x2)
+ dstrgn->extents.x2 = rgn->extents.x2;
+ dstrgn->extents.y2 = rgn->extents.y2;
+ }
+ else
+ {
+ first = RegionBoxptr(dstrgn);
+ last = old + (numRects - 1);
+ if ((first->y1 > last->y2) ||
+ ((first->y1 == last->y1) && (first->y2 == last->y2) &&
+ (first->x1 > last->x2)))
+ {
+ prepend = TRUE;
+ if (rgn->extents.x1 < dstrgn->extents.x1)
+ dstrgn->extents.x1 = rgn->extents.x1;
+ if (rgn->extents.x2 > dstrgn->extents.x2)
+ dstrgn->extents.x2 = rgn->extents.x2;
+ dstrgn->extents.y1 = rgn->extents.y1;
+ }
+ else
+ dstrgn->extents.x2 = dstrgn->extents.x1;
+ }
+ }
+ if (prepend)
+ {
+ new = RegionBox(dstrgn, numRects);
+ if (dnumRects == 1)
+ *new = *RegionBoxptr(dstrgn);
+ else
+ memmove((char *)new,(char *)RegionBoxptr(dstrgn),
+ dnumRects * sizeof(BoxRec));
+ new = RegionBoxptr(dstrgn);
+ }
+ else
+ new = RegionBoxptr(dstrgn) + dnumRects;
+ if (numRects == 1)
+ *new = *old;
+ else
+ memmove((char *)new, (char *)old, numRects * sizeof(BoxRec));
+ dstrgn->data->numRects += numRects;
+ return TRUE;
+}
+
+
+#define ExchangeRects(a, b) \
+{ \
+ BoxRec t; \
+ t = rects[a]; \
+ rects[a] = rects[b]; \
+ rects[b] = t; \
+}
+
+static void
+QuickSortRects(
+ BoxRec rects[],
+ int numRects)
+{
+ int y1;
+ int x1;
+ int i, j;
+ BoxPtr r;
+
+ /* Always called with numRects > 1 */
+
+ do
+ {
+ if (numRects == 2)
+ {
+ if (rects[0].y1 > rects[1].y1 ||
+ (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1))
+ ExchangeRects(0, 1);
+ return;
+ }
+
+ /* Choose partition element, stick in location 0 */
+ ExchangeRects(0, numRects >> 1);
+ y1 = rects[0].y1;
+ x1 = rects[0].x1;
+
+ /* Partition array */
+ i = 0;
+ j = numRects;
+ do
+ {
+ r = &(rects[i]);
+ do
+ {
+ r++;
+ i++;
+ } while (i != numRects &&
+ (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)));
+ r = &(rects[j]);
+ do
+ {
+ r--;
+ j--;
+ } while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1));
+ if (i < j)
+ ExchangeRects(i, j);
+ } while (i < j);
+
+ /* Move partition element back to middle */
+ ExchangeRects(0, j);
+
+ /* Recurse */
+ if (numRects-j-1 > 1)
+ QuickSortRects(&rects[j+1], numRects-j-1);
+ numRects = j;
+ } while (numRects > 1);
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * RegionValidate --
+ *
+ * Take a ``region'' which is a non-y-x-banded random collection of
+ * rectangles, and compute a nice region which is the union of all the
+ * rectangles.
+ *
+ * Results:
+ * TRUE if successful.
+ *
+ * Side Effects:
+ * The passed-in ``region'' may be modified.
+ * pOverlap set to TRUE if any retangles overlapped, else FALSE;
+ *
+ * Strategy:
+ * Step 1. Sort the rectangles into ascending order with primary key y1
+ * and secondary key x1.
+ *
+ * Step 2. Split the rectangles into the minimum number of proper y-x
+ * banded regions. This may require horizontally merging
+ * rectangles, and vertically coalescing bands. With any luck,
+ * this step in an identity tranformation (ala the Box widget),
+ * or a coalescing into 1 box (ala Menus).
+ *
+ * Step 3. Merge the separate regions down to a single region by calling
+ * Union. Maximize the work each Union call does by using
+ * a binary merge.
+ *
+ *-----------------------------------------------------------------------
+ */
+
+Bool
+RegionValidate(RegionPtr badreg, Bool *pOverlap)
+{
+ /* Descriptor for regions under construction in Step 2. */
+ typedef struct {
+ RegionRec reg;
+ int prevBand;
+ int curBand;
+ } RegionInfo;
+
+ int numRects; /* Original numRects for badreg */
+ RegionInfo *ri; /* Array of current regions */
+ int numRI; /* Number of entries used in ri */
+ int sizeRI; /* Number of entries available in ri */
+ int i; /* Index into rects */
+ int j; /* Index into ri */
+ RegionInfo *rit; /* &ri[j] */
+ RegionPtr reg; /* ri[j].reg */
+ BoxPtr box; /* Current box in rects */
+ BoxPtr riBox; /* Last box in ri[j].reg */
+ RegionPtr hreg; /* ri[j_half].reg */
+ Bool ret = TRUE;
+
+ *pOverlap = FALSE;
+ if (!badreg->data)
+ {
+ good(badreg);
+ return TRUE;
+ }
+ numRects = badreg->data->numRects;
+ if (!numRects)
+ {
+ if (RegionNar(badreg))
+ return FALSE;
+ good(badreg);
+ return TRUE;
+ }
+ if (badreg->extents.x1 < badreg->extents.x2)
+ {
+ if ((numRects) == 1)
+ {
+ xfreeData(badreg);
+ badreg->data = (RegDataPtr) NULL;
+ }
+ else
+ {
+ DOWNSIZE(badreg, numRects);
+ }
+ good(badreg);
+ return TRUE;
+ }
+
+ /* Step 1: Sort the rects array into ascending (y1, x1) order */
+ QuickSortRects(RegionBoxptr(badreg), numRects);
+
+ /* Step 2: Scatter the sorted array into the minimum number of regions */
+
+ /* Set up the first region to be the first rectangle in badreg */
+ /* Note that step 2 code will never overflow the ri[0].reg rects array */
+ ri = (RegionInfo *) malloc(4 * sizeof(RegionInfo));
+ if (!ri)
+ return RegionBreak (badreg);
+ sizeRI = 4;
+ numRI = 1;
+ ri[0].prevBand = 0;
+ ri[0].curBand = 0;
+ ri[0].reg = *badreg;
+ box = RegionBoxptr(&ri[0].reg);
+ ri[0].reg.extents = *box;
+ ri[0].reg.data->numRects = 1;
+
+ /* Now scatter rectangles into the minimum set of valid regions. If the
+ next rectangle to be added to a region would force an existing rectangle
+ in the region to be split up in order to maintain y-x banding, just
+ forget it. Try the next region. If it doesn't fit cleanly into any
+ region, make a new one. */
+
+ for (i = numRects; --i > 0;)
+ {
+ box++;
+ /* Look for a region to append box to */
+ for (j = numRI, rit = ri; --j >= 0; rit++)
+ {
+ reg = &rit->reg;
+ riBox = RegionEnd(reg);
+
+ if (box->y1 == riBox->y1 && box->y2 == riBox->y2)
+ {
+ /* box is in same band as riBox. Merge or append it */
+ if (box->x1 <= riBox->x2)
+ {
+ /* Merge it with riBox */
+ if (box->x1 < riBox->x2) *pOverlap = TRUE;
+ if (box->x2 > riBox->x2) riBox->x2 = box->x2;
+ }
+ else
+ {
+ RECTALLOC_BAIL(reg, 1, bail);
+ *RegionTop(reg) = *box;
+ reg->data->numRects++;
+ }
+ goto NextRect; /* So sue me */
+ }
+ else if (box->y1 >= riBox->y2)
+ {
+ /* Put box into new band */
+ if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
+ if (reg->extents.x1 > box->x1) reg->extents.x1 = box->x1;
+ Coalesce(reg, rit->prevBand, rit->curBand);
+ rit->curBand = reg->data->numRects;
+ RECTALLOC_BAIL(reg, 1, bail);
+ *RegionTop(reg) = *box;
+ reg->data->numRects++;
+ goto NextRect;
+ }
+ /* Well, this region was inappropriate. Try the next one. */
+ } /* for j */
+
+ /* Uh-oh. No regions were appropriate. Create a new one. */
+ if (sizeRI == numRI)
+ {
+ /* Oops, allocate space for new region information */
+ sizeRI <<= 1;
+ rit = (RegionInfo *) realloc(ri, sizeRI * sizeof(RegionInfo));
+ if (!rit)
+ goto bail;
+ ri = rit;
+ rit = &ri[numRI];
+ }
+ numRI++;
+ rit->prevBand = 0;
+ rit->curBand = 0;
+ rit->reg.extents = *box;
+ rit->reg.data = NULL;
+ if (!RegionRectAlloc(&rit->reg, (i+numRI) / numRI)) /* MUST force allocation */
+ goto bail;
+NextRect: ;
+ } /* for i */
+
+ /* Make a final pass over each region in order to Coalesce and set
+ extents.x2 and extents.y2 */
+
+ for (j = numRI, rit = ri; --j >= 0; rit++)
+ {
+ reg = &rit->reg;
+ riBox = RegionEnd(reg);
+ reg->extents.y2 = riBox->y2;
+ if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
+ Coalesce(reg, rit->prevBand, rit->curBand);
+ if (reg->data->numRects == 1) /* keep unions happy below */
+ {
+ xfreeData(reg);
+ reg->data = NULL;
+ }
+ }
+
+ /* Step 3: Union all regions into a single region */
+ while (numRI > 1)
+ {
+ int half = numRI/2;
+ for (j = numRI & 1; j < (half + (numRI & 1)); j++)
+ {
+ reg = &ri[j].reg;
+ hreg = &ri[j+half].reg;
+ if (!RegionOp(reg, reg, hreg, RegionUnionO, TRUE, TRUE, pOverlap))
+ ret = FALSE;
+ if (hreg->extents.x1 < reg->extents.x1)
+ reg->extents.x1 = hreg->extents.x1;
+ if (hreg->extents.y1 < reg->extents.y1)
+ reg->extents.y1 = hreg->extents.y1;
+ if (hreg->extents.x2 > reg->extents.x2)
+ reg->extents.x2 = hreg->extents.x2;
+ if (hreg->extents.y2 > reg->extents.y2)
+ reg->extents.y2 = hreg->extents.y2;
+ xfreeData(hreg);
+ }
+ numRI -= half;
+ }
+ *badreg = ri[0].reg;
+ free(ri);
+ good(badreg);
+ return ret;
+bail:
+ for (i = 0; i < numRI; i++)
+ xfreeData(&ri[i].reg);
+ free(ri);
+ return RegionBreak (badreg);
+}
+
+RegionPtr
+RegionFromRects(int nrects, xRectangle *prect, int ctype)
+{
+
+ RegionPtr pRgn;
+ RegDataPtr pData;
+ BoxPtr pBox;
+ int i;
+ int x1, y1, x2, y2;
+
+ pRgn = RegionCreate(NullBox, 0);
+ if (RegionNar (pRgn))
+ return pRgn;
+ if (!nrects)
+ return pRgn;
+ if (nrects == 1)
+ {
+ x1 = prect->x;
+ y1 = prect->y;
+ if ((x2 = x1 + (int) prect->width) > MAXSHORT)
+ x2 = MAXSHORT;
+ if ((y2 = y1 + (int) prect->height) > MAXSHORT)
+ y2 = MAXSHORT;
+ if (x1 != x2 && y1 != y2)
+ {
+ pRgn->extents.x1 = x1;
+ pRgn->extents.y1 = y1;
+ pRgn->extents.x2 = x2;
+ pRgn->extents.y2 = y2;
+ pRgn->data = NULL;
+ }
+ return pRgn;
+ }
+ pData = xallocData(nrects);
+ if (!pData)
+ {
+ RegionBreak (pRgn);
+ return pRgn;
+ }
+ pBox = (BoxPtr) (pData + 1);
+ for (i = nrects; --i >= 0; prect++)
+ {
+ x1 = prect->x;
+ y1 = prect->y;
+ if ((x2 = x1 + (int) prect->width) > MAXSHORT)
+ x2 = MAXSHORT;
+ if ((y2 = y1 + (int) prect->height) > MAXSHORT)
+ y2 = MAXSHORT;
+ if (x1 != x2 && y1 != y2)
+ {
+ pBox->x1 = x1;
+ pBox->y1 = y1;
+ pBox->x2 = x2;
+ pBox->y2 = y2;
+ pBox++;
+ }
+ }
+ if (pBox != (BoxPtr) (pData + 1))
+ {
+ pData->size = nrects;
+ pData->numRects = pBox - (BoxPtr) (pData + 1);
+ pRgn->data = pData;
+ if (ctype != CT_YXBANDED)
+ {
+ Bool overlap; /* result ignored */
+ pRgn->extents.x1 = pRgn->extents.x2 = 0;
+ RegionValidate(pRgn, &overlap);
+ }
+ else
+ RegionSetExtents(pRgn);
+ good(pRgn);
+ }
+ else
+ {
+ free(pData);
+ }
+ return pRgn;
+}
+
+#define ExchangeSpans(a, b) \
+{ \
+ DDXPointRec tpt; \
+ int tw; \
+ \
+ tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt; \
+ tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \
+}
+
+/* ||| I should apply the merge sort code to rectangle sorting above, and see
+ if mapping time can be improved. But right now I've been at work 12 hours,
+ so forget it.
+*/
+
+static void QuickSortSpans(
+ DDXPointRec spans[],
+ int widths[],
+ int numSpans)
+{
+ int y;
+ int i, j, m;
+ DDXPointPtr r;
+
+ /* Always called with numSpans > 1 */
+ /* Sorts only by y, doesn't bother to sort by x */
+
+ do
+ {
+ if (numSpans < 9)
+ {
+ /* Do insertion sort */
+ int yprev;
+
+ yprev = spans[0].y;
+ i = 1;
+ do
+ { /* while i != numSpans */
+ y = spans[i].y;
+ if (yprev > y)
+ {
+ /* spans[i] is out of order. Move into proper location. */
+ DDXPointRec tpt;
+ int tw, k;
+
+ for (j = 0; y >= spans[j].y; j++) {}
+ tpt = spans[i];
+ tw = widths[i];
+ for (k = i; k != j; k--)
+ {
+ spans[k] = spans[k-1];
+ widths[k] = widths[k-1];
+ }
+ spans[j] = tpt;
+ widths[j] = tw;
+ y = spans[i].y;
+ } /* if out of order */
+ yprev = y;
+ i++;
+ } while (i != numSpans);
+ return;
+ }
+
+ /* Choose partition element, stick in location 0 */
+ m = numSpans / 2;
+ if (spans[m].y > spans[0].y) ExchangeSpans(m, 0);
+ if (spans[m].y > spans[numSpans-1].y) ExchangeSpans(m, numSpans-1);
+ if (spans[m].y > spans[0].y) ExchangeSpans(m, 0);
+ y = spans[0].y;
+
+ /* Partition array */
+ i = 0;
+ j = numSpans;
+ do
+ {
+ r = &(spans[i]);
+ do
+ {
+ r++;
+ i++;
+ } while (i != numSpans && r->y < y);
+ r = &(spans[j]);
+ do
+ {
+ r--;
+ j--;
+ } while (y < r->y);
+ if (i < j)
+ ExchangeSpans(i, j);
+ } while (i < j);
+
+ /* Move partition element back to middle */
+ ExchangeSpans(0, j);
+
+ /* Recurse */
+ if (numSpans-j-1 > 1)
+ QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1);
+ numSpans = j;
+ } while (numSpans > 1);
+}
+
+#define NextBand() \
+{ \
+ clipy1 = pboxBandStart->y1; \
+ clipy2 = pboxBandStart->y2; \
+ pboxBandEnd = pboxBandStart + 1; \
+ while (pboxBandEnd != pboxLast && pboxBandEnd->y1 == clipy1) { \
+ pboxBandEnd++; \
+ } \
+ for (; ppt != pptLast && ppt->y < clipy1; ppt++, pwidth++) {} \
+}
+
+/*
+ Clip a list of scanlines to a region. The caller has allocated the
+ space. FSorted is non-zero if the scanline origins are in ascending
+ order.
+ returns the number of new, clipped scanlines.
+*/
+
+int
+RegionClipSpans(
+ RegionPtr prgnDst,
+ DDXPointPtr ppt,
+ int *pwidth,
+ int nspans,
+ DDXPointPtr pptNew,
+ int *pwidthNew,
+ int fSorted)
+{
+ DDXPointPtr pptLast;
+ int *pwidthNewStart; /* the vengeance of Xerox! */
+ int y, x1, x2;
+ int numRects;
+
+ good(prgnDst);
+ pptLast = ppt + nspans;
+ pwidthNewStart = pwidthNew;
+
+ if (!prgnDst->data)
+ {
+ /* Do special fast code with clip boundaries in registers(?) */
+ /* It doesn't pay much to make use of fSorted in this case,
+ so we lump everything together. */
+
+ int clipx1, clipx2, clipy1, clipy2;
+
+ clipx1 = prgnDst->extents.x1;
+ clipy1 = prgnDst->extents.y1;
+ clipx2 = prgnDst->extents.x2;
+ clipy2 = prgnDst->extents.y2;
+
+ for (; ppt != pptLast; ppt++, pwidth++)
+ {
+ y = ppt->y;
+ x1 = ppt->x;
+ if (clipy1 <= y && y < clipy2)
+ {
+ x2 = x1 + *pwidth;
+ if (x1 < clipx1) x1 = clipx1;
+ if (x2 > clipx2) x2 = clipx2;
+ if (x1 < x2)
+ {
+ /* part of span in clip rectangle */
+ pptNew->x = x1;
+ pptNew->y = y;
+ *pwidthNew = x2 - x1;
+ pptNew++;
+ pwidthNew++;
+ }
+ }
+ } /* end for */
+
+ }
+ else if ((numRects = prgnDst->data->numRects))
+ {
+ /* Have to clip against many boxes */
+ BoxPtr pboxBandStart, pboxBandEnd;
+ BoxPtr pbox;
+ BoxPtr pboxLast;
+ int clipy1, clipy2;
+
+ /* In this case, taking advantage of sorted spans gains more than
+ the sorting costs. */
+ if ((! fSorted) && (nspans > 1))
+ QuickSortSpans(ppt, pwidth, nspans);
+
+ pboxBandStart = RegionBoxptr(prgnDst);
+ pboxLast = pboxBandStart + numRects;
+
+ NextBand();
+
+ for (; ppt != pptLast; )
+ {
+ y = ppt->y;
+ if (y < clipy2)
+ {
+ /* span is in the current band */
+ pbox = pboxBandStart;
+ x1 = ppt->x;
+ x2 = x1 + *pwidth;
+ do
+ { /* For each box in band */
+ int newx1, newx2;
+
+ newx1 = x1;
+ newx2 = x2;
+ if (newx1 < pbox->x1) newx1 = pbox->x1;
+ if (newx2 > pbox->x2) newx2 = pbox->x2;
+ if (newx1 < newx2)
+ {
+ /* Part of span in clip rectangle */
+ pptNew->x = newx1;
+ pptNew->y = y;
+ *pwidthNew = newx2 - newx1;
+ pptNew++;
+ pwidthNew++;
+ }
+ pbox++;
+ } while (pbox != pboxBandEnd);
+ ppt++;
+ pwidth++;
+ }
+ else
+ {
+ /* Move to next band, adjust ppt as needed */
+ pboxBandStart = pboxBandEnd;
+ if (pboxBandStart == pboxLast)
+ break; /* We're completely done */
+ NextBand();
+ }
+ }
+ }
+ return pwidthNew - pwidthNewStart;
+}
diff --git a/xorg-server/dix/resource.c b/xorg-server/dix/resource.c
index 1d33c9aad..178935701 100644
--- a/xorg-server/dix/resource.c
+++ b/xorg-server/dix/resource.c
@@ -254,8 +254,6 @@ CreateNewResourceType(DeleteType deleteFunc, char *name)
types = realloc(resourceTypes, (next + 1) * sizeof(*resourceTypes));
if (!types)
return 0;
- if (!dixRegisterPrivateOffset(next, -1))
- return 0;
lastResourceType = next;
resourceTypes = types;
@@ -903,7 +901,7 @@ LegalNewID(XID id, ClientPtr client)
rc = dixLookupResourceByClass(&val, id, RC_ANY, serverClient,
DixGetAttrAccess);
- return (rc == BadValue);
+ return rc == BadValue;
}
return FALSE;
}
diff --git a/xorg-server/dix/selection.c b/xorg-server/dix/selection.c
index 8763a2d5a..428408f8e 100644
--- a/xorg-server/dix/selection.c
+++ b/xorg-server/dix/selection.c
@@ -94,8 +94,7 @@ InitSelections(void)
pSel = CurrentSelections;
while (pSel) {
pNextSel = pSel->next;
- dixFreePrivates(pSel->devPrivates);
- free(pSel);
+ dixFreeObjectWithPrivates(pSel, PRIVATE_SELECTION);
pSel = pNextSel;
}
diff --git a/xorg-server/dix/swapreq.c b/xorg-server/dix/swapreq.c
index 5d7d71c8f..4fbb6ebda 100644
--- a/xorg-server/dix/swapreq.c
+++ b/xorg-server/dix/swapreq.c
@@ -1,1099 +1,1099 @@
-/************************************************************
-
-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.
-
-********************************************************/
-
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/Xprotostr.h>
-#include "misc.h"
-#include "dixstruct.h"
-#include "extnsionst.h" /* for SendEvent */
-#include "swapreq.h"
-
-/* Thanks to Jack Palevich for testing and subsequently rewriting all this */
-
-/* Byte swap a list of longs */
-void
-SwapLongs (CARD32 *list, unsigned long count)
-{
- char n;
-
- while (count >= 8) {
- swapl(list+0, n);
- swapl(list+1, n);
- swapl(list+2, n);
- swapl(list+3, n);
- swapl(list+4, n);
- swapl(list+5, n);
- swapl(list+6, n);
- swapl(list+7, n);
- list += 8;
- count -= 8;
- }
- if (count != 0) {
- do {
- swapl(list, n);
- list++;
- } while (--count != 0);
- }
-}
-
-/* Byte swap a list of shorts */
-void
-SwapShorts (short *list, unsigned long count)
-{
- char n;
-
- while (count >= 16) {
- swaps(list+0, n);
- swaps(list+1, n);
- swaps(list+2, n);
- swaps(list+3, n);
- swaps(list+4, n);
- swaps(list+5, n);
- swaps(list+6, n);
- swaps(list+7, n);
- swaps(list+8, n);
- swaps(list+9, n);
- swaps(list+10, n);
- swaps(list+11, n);
- swaps(list+12, n);
- swaps(list+13, n);
- swaps(list+14, n);
- swaps(list+15, n);
- list += 16;
- count -= 16;
- }
- if (count != 0) {
- do {
- swaps(list, n);
- list++;
- } while (--count != 0);
- }
-}
-
-/* The following is used for all requests that have
- no fields to be swapped (except "length") */
-int
-SProcSimpleReq(ClientPtr client)
-{
- char n;
-
- REQUEST(xReq);
- swaps(&stuff->length, n);
- return(*ProcVector[stuff->reqType])(client);
-}
-
-/* The following is used for all requests that have
- only a single 32-bit field to be swapped, coming
- right after the "length" field */
-int
-SProcResourceReq(ClientPtr client)
-{
- char n;
-
- REQUEST(xResourceReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xResourceReq); /* not EXACT */
- swapl(&stuff->id, n);
- return(*ProcVector[stuff->reqType])(client);
-}
-
-int
-SProcCreateWindow(ClientPtr client)
-{
- char n;
-
- REQUEST(xCreateWindowReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
- swapl(&stuff->wid, n);
- swapl(&stuff->parent, n);
- swaps(&stuff->x, n);
- swaps(&stuff->y, n);
- swaps(&stuff->width, n);
- swaps(&stuff->height, n);
- swaps(&stuff->borderWidth, n);
- swaps(&stuff->class, n);
- swapl(&stuff->visual, n);
- swapl(&stuff->mask, n);
- SwapRestL(stuff);
- return((* ProcVector[X_CreateWindow])(client));
-}
-
-int
-SProcChangeWindowAttributes(ClientPtr client)
-{
- char n;
-
- REQUEST(xChangeWindowAttributesReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
- swapl(&stuff->window, n);
- swapl(&stuff->valueMask, n);
- SwapRestL(stuff);
- return((* ProcVector[X_ChangeWindowAttributes])(client));
-}
-
-int
-SProcReparentWindow(ClientPtr client)
-{
- char n;
- REQUEST(xReparentWindowReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xReparentWindowReq);
- swapl(&stuff->window, n);
- swapl(&stuff->parent, n);
- swaps(&stuff->x, n);
- swaps(&stuff->y, n);
- return((* ProcVector[X_ReparentWindow])(client));
-}
-
-int
-SProcConfigureWindow(ClientPtr client)
-{
- char n;
- REQUEST(xConfigureWindowReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
- swapl(&stuff->window, n);
- swaps(&stuff->mask, n);
- SwapRestL(stuff);
- return((* ProcVector[X_ConfigureWindow])(client));
-
-}
-
-
-int
-SProcInternAtom(ClientPtr client)
-{
- char n;
- REQUEST(xInternAtomReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xInternAtomReq);
- swaps(&stuff->nbytes, n);
- return((* ProcVector[X_InternAtom])(client));
-}
-
-int
-SProcChangeProperty(ClientPtr client)
-{
- char n;
- REQUEST(xChangePropertyReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xChangePropertyReq);
- swapl(&stuff->window, n);
- swapl(&stuff->property, n);
- swapl(&stuff->type, n);
- swapl(&stuff->nUnits, n);
- switch ( stuff->format ) {
- case 8 :
- break;
- case 16:
- SwapRestS(stuff);
- break;
- case 32:
- SwapRestL(stuff);
- break;
- }
- return((* ProcVector[X_ChangeProperty])(client));
-}
-
-int
-SProcDeleteProperty(ClientPtr client)
-{
- char n;
- REQUEST(xDeletePropertyReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xDeletePropertyReq);
- swapl(&stuff->window, n);
- swapl(&stuff->property, n);
- return((* ProcVector[X_DeleteProperty])(client));
-
-}
-
-int
-SProcGetProperty(ClientPtr client)
-{
- char n;
- REQUEST(xGetPropertyReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xGetPropertyReq);
- swapl(&stuff->window, n);
- swapl(&stuff->property, n);
- swapl(&stuff->type, n);
- swapl(&stuff->longOffset, n);
- swapl(&stuff->longLength, n);
- return((* ProcVector[X_GetProperty])(client));
-}
-
-int
-SProcSetSelectionOwner(ClientPtr client)
-{
- char n;
- REQUEST(xSetSelectionOwnerReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);
- swapl(&stuff->window, n);
- swapl(&stuff->selection, n);
- swapl(&stuff->time, n);
- return((* ProcVector[X_SetSelectionOwner])(client));
-}
-
-int
-SProcConvertSelection(ClientPtr client)
-{
- char n;
- REQUEST(xConvertSelectionReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xConvertSelectionReq);
- swapl(&stuff->requestor, n);
- swapl(&stuff->selection, n);
- swapl(&stuff->target, n);
- swapl(&stuff->property, n);
- swapl(&stuff->time, n);
- return((* ProcVector[X_ConvertSelection])(client));
-}
-
-int
-SProcSendEvent(ClientPtr client)
-{
- char n;
- xEvent eventT;
- EventSwapPtr proc;
- REQUEST(xSendEventReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xSendEventReq);
- swapl(&stuff->destination, n);
- swapl(&stuff->eventMask, n);
-
- /* Swap event */
- proc = EventSwapVector[stuff->event.u.u.type & 0177];
- if (!proc || proc == NotImplemented) /* no swapping proc; invalid event type? */
- return (BadValue);
- (*proc)(&stuff->event, &eventT);
- stuff->event = eventT;
-
- return((* ProcVector[X_SendEvent])(client));
-}
-
-int
-SProcGrabPointer(ClientPtr client)
-{
- char n;
- REQUEST(xGrabPointerReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xGrabPointerReq);
- swapl(&stuff->grabWindow, n);
- swaps(&stuff->eventMask, n);
- swapl(&stuff->confineTo, n);
- swapl(&stuff->cursor, n);
- swapl(&stuff->time, n);
- return((* ProcVector[X_GrabPointer])(client));
-}
-
-int
-SProcGrabButton(ClientPtr client)
-{
- char n;
- REQUEST(xGrabButtonReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xGrabButtonReq);
- swapl(&stuff->grabWindow, n);
- swaps(&stuff->eventMask, n);
- swapl(&stuff->confineTo, n);
- swapl(&stuff->cursor, n);
- swaps(&stuff->modifiers, n);
- return((* ProcVector[X_GrabButton])(client));
-}
-
-int
-SProcUngrabButton(ClientPtr client)
-{
- char n;
- REQUEST(xUngrabButtonReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xUngrabButtonReq);
- swapl(&stuff->grabWindow, n);
- swaps(&stuff->modifiers, n);
- return((* ProcVector[X_UngrabButton])(client));
-}
-
-int
-SProcChangeActivePointerGrab(ClientPtr client)
-{
- char n;
- REQUEST(xChangeActivePointerGrabReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
- swapl(&stuff->cursor, n);
- swapl(&stuff->time, n);
- swaps(&stuff->eventMask, n);
- return((* ProcVector[X_ChangeActivePointerGrab])(client));
-}
-
-int
-SProcGrabKeyboard(ClientPtr client)
-{
- char n;
- REQUEST(xGrabKeyboardReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xGrabKeyboardReq);
- swapl(&stuff->grabWindow, n);
- swapl(&stuff->time, n);
- return((* ProcVector[X_GrabKeyboard])(client));
-}
-
-int
-SProcGrabKey(ClientPtr client)
-{
- char n;
- REQUEST(xGrabKeyReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xGrabKeyReq);
- swapl(&stuff->grabWindow, n);
- swaps(&stuff->modifiers, n);
- return((* ProcVector[X_GrabKey])(client));
-}
-
-int
-SProcUngrabKey(ClientPtr client)
-{
- char n;
- REQUEST(xUngrabKeyReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xUngrabKeyReq);
- swapl(&stuff->grabWindow, n);
- swaps(&stuff->modifiers, n);
- return((* ProcVector[X_UngrabKey])(client));
-}
-
-int
-SProcGetMotionEvents(ClientPtr client)
-{
- char n;
- REQUEST(xGetMotionEventsReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xGetMotionEventsReq);
- swapl(&stuff->window, n);
- swapl(&stuff->start, n);
- swapl(&stuff->stop, n);
- return((* ProcVector[X_GetMotionEvents])(client));
-}
-
-int
-SProcTranslateCoords(ClientPtr client)
-{
- char n;
- REQUEST(xTranslateCoordsReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xTranslateCoordsReq);
- swapl(&stuff->srcWid, n);
- swapl(&stuff->dstWid, n);
- swaps(&stuff->srcX, n);
- swaps(&stuff->srcY, n);
- return((* ProcVector[X_TranslateCoords])(client));
-}
-
-int
-SProcWarpPointer(ClientPtr client)
-{
- char n;
- REQUEST(xWarpPointerReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xWarpPointerReq);
- swapl(&stuff->srcWid, n);
- swapl(&stuff->dstWid, n);
- swaps(&stuff->srcX, n);
- swaps(&stuff->srcY, n);
- swaps(&stuff->srcWidth, n);
- swaps(&stuff->srcHeight, n);
- swaps(&stuff->dstX, n);
- swaps(&stuff->dstY, n);
- return((* ProcVector[X_WarpPointer])(client));
-}
-
-int
-SProcSetInputFocus(ClientPtr client)
-{
- char n;
- REQUEST(xSetInputFocusReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xSetInputFocusReq);
- swapl(&stuff->focus, n);
- swapl(&stuff->time, n);
- return((* ProcVector[X_SetInputFocus])(client));
-}
-
-int
-SProcOpenFont(ClientPtr client)
-{
- char n;
- REQUEST(xOpenFontReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xOpenFontReq);
- swapl(&stuff->fid, n);
- swaps(&stuff->nbytes, n);
- return((* ProcVector[X_OpenFont])(client));
-}
-
-int
-SProcListFonts(ClientPtr client)
-{
- char n;
- REQUEST(xListFontsReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xListFontsReq);
- swaps(&stuff->maxNames, n);
- swaps(&stuff->nbytes, n);
- return((* ProcVector[X_ListFonts])(client));
-}
-
-int
-SProcListFontsWithInfo(ClientPtr client)
-{
- char n;
- REQUEST(xListFontsWithInfoReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xListFontsWithInfoReq);
- swaps(&stuff->maxNames, n);
- swaps(&stuff->nbytes, n);
- return((* ProcVector[X_ListFontsWithInfo])(client));
-}
-
-int
-SProcSetFontPath(ClientPtr client)
-{
- char n;
- REQUEST(xSetFontPathReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
- swaps(&stuff->nFonts, n);
- return((* ProcVector[X_SetFontPath])(client));
-}
-
-int
-SProcCreatePixmap(ClientPtr client)
-{
- char n;
- REQUEST(xCreatePixmapReq);
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xCreatePixmapReq);
- swapl(&stuff->pid, n);
- swapl(&stuff->drawable, n);
- swaps(&stuff->width, n);
- swaps(&stuff->height, n);
- return((* ProcVector[X_CreatePixmap])(client));
-}
-
-int
-SProcCreateGC(ClientPtr client)
-{
- char n;
- REQUEST(xCreateGCReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xCreateGCReq);
- swapl(&stuff->gc, n);
- swapl(&stuff->drawable, n);
- swapl(&stuff->mask, n);
- SwapRestL(stuff);
- return((* ProcVector[X_CreateGC])(client));
-}
-
-int
-SProcChangeGC(ClientPtr client)
-{
- char n;
- REQUEST(xChangeGCReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xChangeGCReq);
- swapl(&stuff->gc, n);
- swapl(&stuff->mask, n);
- SwapRestL(stuff);
- return((* ProcVector[X_ChangeGC])(client));
-}
-
-int
-SProcCopyGC(ClientPtr client)
-{
- char n;
- REQUEST(xCopyGCReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xCopyGCReq);
- swapl(&stuff->srcGC, n);
- swapl(&stuff->dstGC, n);
- swapl(&stuff->mask, n);
- return((* ProcVector[X_CopyGC])(client));
-}
-
-int
-SProcSetDashes(ClientPtr client)
-{
- char n;
- REQUEST(xSetDashesReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xSetDashesReq);
- swapl(&stuff->gc, n);
- swaps(&stuff->dashOffset, n);
- swaps(&stuff->nDashes, n);
- return((* ProcVector[X_SetDashes])(client));
-
-}
-
-int
-SProcSetClipRectangles(ClientPtr client)
-{
- char n;
- REQUEST(xSetClipRectanglesReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
- swapl(&stuff->gc, n);
- swaps(&stuff->xOrigin, n);
- swaps(&stuff->yOrigin, n);
- SwapRestS(stuff);
- return((* ProcVector[X_SetClipRectangles])(client));
-}
-
-int
-SProcClearToBackground(ClientPtr client)
-{
- char n;
- REQUEST(xClearAreaReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xClearAreaReq);
- swapl(&stuff->window, n);
- swaps(&stuff->x, n);
- swaps(&stuff->y, n);
- swaps(&stuff->width, n);
- swaps(&stuff->height, n);
- return((* ProcVector[X_ClearArea])(client));
-}
-
-int
-SProcCopyArea(ClientPtr client)
-{
- char n;
- REQUEST(xCopyAreaReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xCopyAreaReq);
- swapl(&stuff->srcDrawable, n);
- swapl(&stuff->dstDrawable, n);
- swapl(&stuff->gc, n);
- swaps(&stuff->srcX, n);
- swaps(&stuff->srcY, n);
- swaps(&stuff->dstX, n);
- swaps(&stuff->dstY, n);
- swaps(&stuff->width, n);
- swaps(&stuff->height, n);
- return((* ProcVector[X_CopyArea])(client));
-}
-
-int
-SProcCopyPlane(ClientPtr client)
-{
- char n;
- REQUEST(xCopyPlaneReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xCopyPlaneReq);
- swapl(&stuff->srcDrawable, n);
- swapl(&stuff->dstDrawable, n);
- swapl(&stuff->gc, n);
- swaps(&stuff->srcX, n);
- swaps(&stuff->srcY, n);
- swaps(&stuff->dstX, n);
- swaps(&stuff->dstY, n);
- swaps(&stuff->width, n);
- swaps(&stuff->height, n);
- swapl(&stuff->bitPlane, n);
- return((* ProcVector[X_CopyPlane])(client));
-}
-
-/* The following routine is used for all Poly drawing requests
- (except FillPoly, which uses a different request format) */
-int
-SProcPoly(ClientPtr client)
-{
- char n;
-
- REQUEST(xPolyPointReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xPolyPointReq);
- swapl(&stuff->drawable, n);
- swapl(&stuff->gc, n);
- SwapRestS(stuff);
- return((* ProcVector[stuff->reqType])(client));
-}
-
-/* cannot use SProcPoly for this one, because xFillPolyReq
- is longer than xPolyPointReq, and we don't want to swap
- the difference as shorts! */
-int
-SProcFillPoly(ClientPtr client)
-{
- char n;
-
- REQUEST(xFillPolyReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xFillPolyReq);
- swapl(&stuff->drawable, n);
- swapl(&stuff->gc, n);
- SwapRestS(stuff);
- return((* ProcVector[X_FillPoly])(client));
-}
-
-int
-SProcPutImage(ClientPtr client)
-{
- char n;
- REQUEST(xPutImageReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xPutImageReq);
- swapl(&stuff->drawable, n);
- swapl(&stuff->gc, n);
- swaps(&stuff->width, n);
- swaps(&stuff->height, n);
- swaps(&stuff->dstX, n);
- swaps(&stuff->dstY, n);
- /* Image should already be swapped */
- return((* ProcVector[X_PutImage])(client));
-
-}
-
-int
-SProcGetImage(ClientPtr client)
-{
- char n;
- REQUEST(xGetImageReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xGetImageReq);
- swapl(&stuff->drawable, n);
- swaps(&stuff->x, n);
- swaps(&stuff->y, n);
- swaps(&stuff->width, n);
- swaps(&stuff->height, n);
- swapl(&stuff->planeMask, n);
- return((* ProcVector[X_GetImage])(client));
-}
-
-/* ProcPolyText used for both PolyText8 and PolyText16 */
-
-int
-SProcPolyText(ClientPtr client)
-{
- char n;
- REQUEST(xPolyTextReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xPolyTextReq);
- swapl(&stuff->drawable, n);
- swapl(&stuff->gc, n);
- swaps(&stuff->x, n);
- swaps(&stuff->y, n);
- return((* ProcVector[stuff->reqType])(client));
-}
-
-/* ProcImageText used for both ImageText8 and ImageText16 */
-
-int
-SProcImageText(ClientPtr client)
-{
- char n;
- REQUEST(xImageTextReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xImageTextReq);
- swapl(&stuff->drawable, n);
- swapl(&stuff->gc, n);
- swaps(&stuff->x, n);
- swaps(&stuff->y, n);
- return((* ProcVector[stuff->reqType])(client));
-}
-
-int
-SProcCreateColormap(ClientPtr client)
-{
- char n;
- REQUEST(xCreateColormapReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xCreateColormapReq);
- swapl(&stuff->mid, n);
- swapl(&stuff->window, n);
- swapl(&stuff->visual, n);
- return((* ProcVector[X_CreateColormap])(client));
-}
-
-
-int
-SProcCopyColormapAndFree(ClientPtr client)
-{
- char n;
- REQUEST(xCopyColormapAndFreeReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq);
- swapl(&stuff->mid, n);
- swapl(&stuff->srcCmap, n);
- return((* ProcVector[X_CopyColormapAndFree])(client));
-
-}
-
-int
-SProcAllocColor(ClientPtr client)
-{
- char n;
- REQUEST(xAllocColorReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xAllocColorReq);
- swapl(&stuff->cmap, n);
- swaps(&stuff->red, n);
- swaps(&stuff->green, n);
- swaps(&stuff->blue, n);
- return((* ProcVector[X_AllocColor])(client));
-}
-
-int
-SProcAllocNamedColor(ClientPtr client)
-{
- char n;
-
- REQUEST(xAllocNamedColorReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xAllocNamedColorReq);
- swapl(&stuff->cmap, n);
- swaps(&stuff->nbytes, n);
- return((* ProcVector[X_AllocNamedColor])(client));
-}
-
-int
-SProcAllocColorCells(ClientPtr client)
-{
- char n;
- REQUEST(xAllocColorCellsReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xAllocColorCellsReq);
- swapl(&stuff->cmap, n);
- swaps(&stuff->colors, n);
- swaps(&stuff->planes, n);
- return((* ProcVector[X_AllocColorCells])(client));
-}
-
-int
-SProcAllocColorPlanes(ClientPtr client)
-{
- char n;
- REQUEST(xAllocColorPlanesReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xAllocColorPlanesReq);
- swapl(&stuff->cmap, n);
- swaps(&stuff->colors, n);
- swaps(&stuff->red, n);
- swaps(&stuff->green, n);
- swaps(&stuff->blue, n);
- return((* ProcVector[X_AllocColorPlanes])(client));
-}
-
-int
-SProcFreeColors(ClientPtr client)
-{
- char n;
- REQUEST(xFreeColorsReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
- swapl(&stuff->cmap, n);
- swapl(&stuff->planeMask, n);
- SwapRestL(stuff);
- return((* ProcVector[X_FreeColors])(client));
-
-}
-
-void
-SwapColorItem(xColorItem *pItem)
-{
- char n;
-
- swapl(&pItem->pixel, n);
- swaps(&pItem->red, n);
- swaps(&pItem->green, n);
- swaps(&pItem->blue, n);
-}
-
-int
-SProcStoreColors(ClientPtr client)
-{
- char n;
- long count;
- xColorItem *pItem;
-
- REQUEST(xStoreColorsReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
- swapl(&stuff->cmap, n);
- pItem = (xColorItem *) &stuff[1];
- for(count = LengthRestB(stuff)/sizeof(xColorItem); --count >= 0; )
- SwapColorItem(pItem++);
- return((* ProcVector[X_StoreColors])(client));
-}
-
-int
-SProcStoreNamedColor (ClientPtr client)
-{
- char n;
- REQUEST(xStoreNamedColorReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xStoreNamedColorReq);
- swapl(&stuff->cmap, n);
- swapl(&stuff->pixel, n);
- swaps(&stuff->nbytes, n);
- return((* ProcVector[X_StoreNamedColor])(client));
-}
-
-int
-SProcQueryColors (ClientPtr client)
-{
- char n;
- REQUEST(xQueryColorsReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xQueryColorsReq);
- swapl(&stuff->cmap, n);
- SwapRestL(stuff);
- return((* ProcVector[X_QueryColors])(client));
-}
-
-int
-SProcLookupColor (ClientPtr client)
-{
- char n;
- REQUEST(xLookupColorReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xLookupColorReq);
- swapl(&stuff->cmap, n);
- swaps(&stuff->nbytes, n);
- return((* ProcVector[X_LookupColor])(client));
-}
-
-int
-SProcCreateCursor (ClientPtr client)
-{
- char n;
- REQUEST(xCreateCursorReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xCreateCursorReq);
- swapl(&stuff->cid, n);
- swapl(&stuff->source, n);
- swapl(&stuff->mask, n);
- swaps(&stuff->foreRed, n);
- swaps(&stuff->foreGreen, n);
- swaps(&stuff->foreBlue, n);
- swaps(&stuff->backRed, n);
- swaps(&stuff->backGreen, n);
- swaps(&stuff->backBlue, n);
- swaps(&stuff->x, n);
- swaps(&stuff->y, n);
- return((* ProcVector[X_CreateCursor])(client));
-}
-
-int
-SProcCreateGlyphCursor (ClientPtr client)
-{
- char n;
- REQUEST(xCreateGlyphCursorReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xCreateGlyphCursorReq);
- swapl(&stuff->cid, n);
- swapl(&stuff->source, n);
- swapl(&stuff->mask, n);
- swaps(&stuff->sourceChar, n);
- swaps(&stuff->maskChar, n);
- swaps(&stuff->foreRed, n);
- swaps(&stuff->foreGreen, n);
- swaps(&stuff->foreBlue, n);
- swaps(&stuff->backRed, n);
- swaps(&stuff->backGreen, n);
- swaps(&stuff->backBlue, n);
- return((* ProcVector[X_CreateGlyphCursor])(client));
-}
-
-
-int
-SProcRecolorCursor (ClientPtr client)
-{
- char n;
- REQUEST(xRecolorCursorReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xRecolorCursorReq);
- swapl(&stuff->cursor, n);
- swaps(&stuff->foreRed, n);
- swaps(&stuff->foreGreen, n);
- swaps(&stuff->foreBlue, n);
- swaps(&stuff->backRed, n);
- swaps(&stuff->backGreen, n);
- swaps(&stuff->backBlue, n);
- return((* ProcVector[X_RecolorCursor])(client));
-}
-
-int
-SProcQueryBestSize (ClientPtr client)
-{
- char n;
- REQUEST(xQueryBestSizeReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xQueryBestSizeReq);
- swapl(&stuff->drawable, n);
- swaps(&stuff->width, n);
- swaps(&stuff->height, n);
- return((* ProcVector[X_QueryBestSize])(client));
-
-}
-
-int
-SProcQueryExtension (ClientPtr client)
-{
- char n;
- REQUEST(xQueryExtensionReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xQueryExtensionReq);
- swaps(&stuff->nbytes, n);
- return((* ProcVector[X_QueryExtension])(client));
-}
-
-int
-SProcChangeKeyboardMapping (ClientPtr client)
-{
- char n;
- REQUEST(xChangeKeyboardMappingReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq);
- SwapRestL(stuff);
- return((* ProcVector[X_ChangeKeyboardMapping])(client));
-}
-
-
-int
-SProcChangeKeyboardControl (ClientPtr client)
-{
- char n;
- REQUEST(xChangeKeyboardControlReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq);
- swapl(&stuff->mask, n);
- SwapRestL(stuff);
- return((* ProcVector[X_ChangeKeyboardControl])(client));
-}
-
-int
-SProcChangePointerControl (ClientPtr client)
-{
- char n;
- REQUEST(xChangePointerControlReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xChangePointerControlReq);
- swaps(&stuff->accelNum, n);
- swaps(&stuff->accelDenum, n);
- swaps(&stuff->threshold, n);
- return((* ProcVector[X_ChangePointerControl])(client));
-}
-
-
-int
-SProcSetScreenSaver (ClientPtr client)
-{
- char n;
- REQUEST(xSetScreenSaverReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xSetScreenSaverReq);
- swaps(&stuff->timeout, n);
- swaps(&stuff->interval, n);
- return((* ProcVector[X_SetScreenSaver])(client));
-}
-
-int
-SProcChangeHosts (ClientPtr client)
-{
- char n;
-
- REQUEST(xChangeHostsReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xChangeHostsReq);
- swaps(&stuff->hostLength, n);
- return((* ProcVector[X_ChangeHosts])(client));
-
-}
-
-int SProcRotateProperties (ClientPtr client)
-{
- char n;
- REQUEST(xRotatePropertiesReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xRotatePropertiesReq);
- swapl(&stuff->window, n);
- swaps(&stuff->nAtoms, n);
- swaps(&stuff->nPositions, n);
- SwapRestL(stuff);
- return ((* ProcVector[X_RotateProperties])(client));
-}
-
-int
-SProcNoOperation(ClientPtr client)
-{
- char n;
- REQUEST(xReq);
- swaps(&stuff->length, n);
- return ((* ProcVector[X_NoOperation])(client));
-}
-
-void
-SwapConnClientPrefix(xConnClientPrefix *pCCP)
-{
- char n;
-
- swaps(&pCCP->majorVersion, n);
- swaps(&pCCP->minorVersion, n);
- swaps(&pCCP->nbytesAuthProto, n);
- swaps(&pCCP->nbytesAuthString, n);
-}
+/************************************************************
+
+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.
+
+********************************************************/
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/Xprotostr.h>
+#include "misc.h"
+#include "dixstruct.h"
+#include "extnsionst.h" /* for SendEvent */
+#include "swapreq.h"
+
+/* Thanks to Jack Palevich for testing and subsequently rewriting all this */
+
+/* Byte swap a list of longs */
+void
+SwapLongs (CARD32 *list, unsigned long count)
+{
+ char n;
+
+ while (count >= 8) {
+ swapl(list+0, n);
+ swapl(list+1, n);
+ swapl(list+2, n);
+ swapl(list+3, n);
+ swapl(list+4, n);
+ swapl(list+5, n);
+ swapl(list+6, n);
+ swapl(list+7, n);
+ list += 8;
+ count -= 8;
+ }
+ if (count != 0) {
+ do {
+ swapl(list, n);
+ list++;
+ } while (--count != 0);
+ }
+}
+
+/* Byte swap a list of shorts */
+void
+SwapShorts (short *list, unsigned long count)
+{
+ char n;
+
+ while (count >= 16) {
+ swaps(list+0, n);
+ swaps(list+1, n);
+ swaps(list+2, n);
+ swaps(list+3, n);
+ swaps(list+4, n);
+ swaps(list+5, n);
+ swaps(list+6, n);
+ swaps(list+7, n);
+ swaps(list+8, n);
+ swaps(list+9, n);
+ swaps(list+10, n);
+ swaps(list+11, n);
+ swaps(list+12, n);
+ swaps(list+13, n);
+ swaps(list+14, n);
+ swaps(list+15, n);
+ list += 16;
+ count -= 16;
+ }
+ if (count != 0) {
+ do {
+ swaps(list, n);
+ list++;
+ } while (--count != 0);
+ }
+}
+
+/* The following is used for all requests that have
+ no fields to be swapped (except "length") */
+int
+SProcSimpleReq(ClientPtr client)
+{
+ char n;
+
+ REQUEST(xReq);
+ swaps(&stuff->length, n);
+ return(*ProcVector[stuff->reqType])(client);
+}
+
+/* The following is used for all requests that have
+ only a single 32-bit field to be swapped, coming
+ right after the "length" field */
+int
+SProcResourceReq(ClientPtr client)
+{
+ char n;
+
+ REQUEST(xResourceReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xResourceReq); /* not EXACT */
+ swapl(&stuff->id, n);
+ return(*ProcVector[stuff->reqType])(client);
+}
+
+int
+SProcCreateWindow(ClientPtr client)
+{
+ char n;
+
+ REQUEST(xCreateWindowReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
+ swapl(&stuff->wid, n);
+ swapl(&stuff->parent, n);
+ swaps(&stuff->x, n);
+ swaps(&stuff->y, n);
+ swaps(&stuff->width, n);
+ swaps(&stuff->height, n);
+ swaps(&stuff->borderWidth, n);
+ swaps(&stuff->class, n);
+ swapl(&stuff->visual, n);
+ swapl(&stuff->mask, n);
+ SwapRestL(stuff);
+ return((* ProcVector[X_CreateWindow])(client));
+}
+
+int
+SProcChangeWindowAttributes(ClientPtr client)
+{
+ char n;
+
+ REQUEST(xChangeWindowAttributesReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
+ swapl(&stuff->window, n);
+ swapl(&stuff->valueMask, n);
+ SwapRestL(stuff);
+ return((* ProcVector[X_ChangeWindowAttributes])(client));
+}
+
+int
+SProcReparentWindow(ClientPtr client)
+{
+ char n;
+ REQUEST(xReparentWindowReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xReparentWindowReq);
+ swapl(&stuff->window, n);
+ swapl(&stuff->parent, n);
+ swaps(&stuff->x, n);
+ swaps(&stuff->y, n);
+ return((* ProcVector[X_ReparentWindow])(client));
+}
+
+int
+SProcConfigureWindow(ClientPtr client)
+{
+ char n;
+ REQUEST(xConfigureWindowReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
+ swapl(&stuff->window, n);
+ swaps(&stuff->mask, n);
+ SwapRestL(stuff);
+ return((* ProcVector[X_ConfigureWindow])(client));
+
+}
+
+
+int
+SProcInternAtom(ClientPtr client)
+{
+ char n;
+ REQUEST(xInternAtomReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xInternAtomReq);
+ swaps(&stuff->nbytes, n);
+ return((* ProcVector[X_InternAtom])(client));
+}
+
+int
+SProcChangeProperty(ClientPtr client)
+{
+ char n;
+ REQUEST(xChangePropertyReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xChangePropertyReq);
+ swapl(&stuff->window, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->nUnits, n);
+ switch ( stuff->format ) {
+ case 8 :
+ break;
+ case 16:
+ SwapRestS(stuff);
+ break;
+ case 32:
+ SwapRestL(stuff);
+ break;
+ }
+ return((* ProcVector[X_ChangeProperty])(client));
+}
+
+int
+SProcDeleteProperty(ClientPtr client)
+{
+ char n;
+ REQUEST(xDeletePropertyReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDeletePropertyReq);
+ swapl(&stuff->window, n);
+ swapl(&stuff->property, n);
+ return((* ProcVector[X_DeleteProperty])(client));
+
+}
+
+int
+SProcGetProperty(ClientPtr client)
+{
+ char n;
+ REQUEST(xGetPropertyReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xGetPropertyReq);
+ swapl(&stuff->window, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->longOffset, n);
+ swapl(&stuff->longLength, n);
+ return((* ProcVector[X_GetProperty])(client));
+}
+
+int
+SProcSetSelectionOwner(ClientPtr client)
+{
+ char n;
+ REQUEST(xSetSelectionOwnerReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);
+ swapl(&stuff->window, n);
+ swapl(&stuff->selection, n);
+ swapl(&stuff->time, n);
+ return((* ProcVector[X_SetSelectionOwner])(client));
+}
+
+int
+SProcConvertSelection(ClientPtr client)
+{
+ char n;
+ REQUEST(xConvertSelectionReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xConvertSelectionReq);
+ swapl(&stuff->requestor, n);
+ swapl(&stuff->selection, n);
+ swapl(&stuff->target, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->time, n);
+ return((* ProcVector[X_ConvertSelection])(client));
+}
+
+int
+SProcSendEvent(ClientPtr client)
+{
+ char n;
+ xEvent eventT;
+ EventSwapPtr proc;
+ REQUEST(xSendEventReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xSendEventReq);
+ swapl(&stuff->destination, n);
+ swapl(&stuff->eventMask, n);
+
+ /* Swap event */
+ proc = EventSwapVector[stuff->event.u.u.type & 0177];
+ if (!proc || proc == NotImplemented) /* no swapping proc; invalid event type? */
+ return BadValue;
+ (*proc)(&stuff->event, &eventT);
+ stuff->event = eventT;
+
+ return((* ProcVector[X_SendEvent])(client));
+}
+
+int
+SProcGrabPointer(ClientPtr client)
+{
+ char n;
+ REQUEST(xGrabPointerReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xGrabPointerReq);
+ swapl(&stuff->grabWindow, n);
+ swaps(&stuff->eventMask, n);
+ swapl(&stuff->confineTo, n);
+ swapl(&stuff->cursor, n);
+ swapl(&stuff->time, n);
+ return((* ProcVector[X_GrabPointer])(client));
+}
+
+int
+SProcGrabButton(ClientPtr client)
+{
+ char n;
+ REQUEST(xGrabButtonReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xGrabButtonReq);
+ swapl(&stuff->grabWindow, n);
+ swaps(&stuff->eventMask, n);
+ swapl(&stuff->confineTo, n);
+ swapl(&stuff->cursor, n);
+ swaps(&stuff->modifiers, n);
+ return((* ProcVector[X_GrabButton])(client));
+}
+
+int
+SProcUngrabButton(ClientPtr client)
+{
+ char n;
+ REQUEST(xUngrabButtonReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xUngrabButtonReq);
+ swapl(&stuff->grabWindow, n);
+ swaps(&stuff->modifiers, n);
+ return((* ProcVector[X_UngrabButton])(client));
+}
+
+int
+SProcChangeActivePointerGrab(ClientPtr client)
+{
+ char n;
+ REQUEST(xChangeActivePointerGrabReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
+ swapl(&stuff->cursor, n);
+ swapl(&stuff->time, n);
+ swaps(&stuff->eventMask, n);
+ return((* ProcVector[X_ChangeActivePointerGrab])(client));
+}
+
+int
+SProcGrabKeyboard(ClientPtr client)
+{
+ char n;
+ REQUEST(xGrabKeyboardReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xGrabKeyboardReq);
+ swapl(&stuff->grabWindow, n);
+ swapl(&stuff->time, n);
+ return((* ProcVector[X_GrabKeyboard])(client));
+}
+
+int
+SProcGrabKey(ClientPtr client)
+{
+ char n;
+ REQUEST(xGrabKeyReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xGrabKeyReq);
+ swapl(&stuff->grabWindow, n);
+ swaps(&stuff->modifiers, n);
+ return((* ProcVector[X_GrabKey])(client));
+}
+
+int
+SProcUngrabKey(ClientPtr client)
+{
+ char n;
+ REQUEST(xUngrabKeyReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xUngrabKeyReq);
+ swapl(&stuff->grabWindow, n);
+ swaps(&stuff->modifiers, n);
+ return((* ProcVector[X_UngrabKey])(client));
+}
+
+int
+SProcGetMotionEvents(ClientPtr client)
+{
+ char n;
+ REQUEST(xGetMotionEventsReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xGetMotionEventsReq);
+ swapl(&stuff->window, n);
+ swapl(&stuff->start, n);
+ swapl(&stuff->stop, n);
+ return((* ProcVector[X_GetMotionEvents])(client));
+}
+
+int
+SProcTranslateCoords(ClientPtr client)
+{
+ char n;
+ REQUEST(xTranslateCoordsReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xTranslateCoordsReq);
+ swapl(&stuff->srcWid, n);
+ swapl(&stuff->dstWid, n);
+ swaps(&stuff->srcX, n);
+ swaps(&stuff->srcY, n);
+ return((* ProcVector[X_TranslateCoords])(client));
+}
+
+int
+SProcWarpPointer(ClientPtr client)
+{
+ char n;
+ REQUEST(xWarpPointerReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xWarpPointerReq);
+ swapl(&stuff->srcWid, n);
+ swapl(&stuff->dstWid, n);
+ swaps(&stuff->srcX, n);
+ swaps(&stuff->srcY, n);
+ swaps(&stuff->srcWidth, n);
+ swaps(&stuff->srcHeight, n);
+ swaps(&stuff->dstX, n);
+ swaps(&stuff->dstY, n);
+ return((* ProcVector[X_WarpPointer])(client));
+}
+
+int
+SProcSetInputFocus(ClientPtr client)
+{
+ char n;
+ REQUEST(xSetInputFocusReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xSetInputFocusReq);
+ swapl(&stuff->focus, n);
+ swapl(&stuff->time, n);
+ return((* ProcVector[X_SetInputFocus])(client));
+}
+
+int
+SProcOpenFont(ClientPtr client)
+{
+ char n;
+ REQUEST(xOpenFontReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xOpenFontReq);
+ swapl(&stuff->fid, n);
+ swaps(&stuff->nbytes, n);
+ return((* ProcVector[X_OpenFont])(client));
+}
+
+int
+SProcListFonts(ClientPtr client)
+{
+ char n;
+ REQUEST(xListFontsReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xListFontsReq);
+ swaps(&stuff->maxNames, n);
+ swaps(&stuff->nbytes, n);
+ return((* ProcVector[X_ListFonts])(client));
+}
+
+int
+SProcListFontsWithInfo(ClientPtr client)
+{
+ char n;
+ REQUEST(xListFontsWithInfoReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xListFontsWithInfoReq);
+ swaps(&stuff->maxNames, n);
+ swaps(&stuff->nbytes, n);
+ return((* ProcVector[X_ListFontsWithInfo])(client));
+}
+
+int
+SProcSetFontPath(ClientPtr client)
+{
+ char n;
+ REQUEST(xSetFontPathReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
+ swaps(&stuff->nFonts, n);
+ return((* ProcVector[X_SetFontPath])(client));
+}
+
+int
+SProcCreatePixmap(ClientPtr client)
+{
+ char n;
+ REQUEST(xCreatePixmapReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCreatePixmapReq);
+ swapl(&stuff->pid, n);
+ swapl(&stuff->drawable, n);
+ swaps(&stuff->width, n);
+ swaps(&stuff->height, n);
+ return((* ProcVector[X_CreatePixmap])(client));
+}
+
+int
+SProcCreateGC(ClientPtr client)
+{
+ char n;
+ REQUEST(xCreateGCReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xCreateGCReq);
+ swapl(&stuff->gc, n);
+ swapl(&stuff->drawable, n);
+ swapl(&stuff->mask, n);
+ SwapRestL(stuff);
+ return((* ProcVector[X_CreateGC])(client));
+}
+
+int
+SProcChangeGC(ClientPtr client)
+{
+ char n;
+ REQUEST(xChangeGCReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xChangeGCReq);
+ swapl(&stuff->gc, n);
+ swapl(&stuff->mask, n);
+ SwapRestL(stuff);
+ return((* ProcVector[X_ChangeGC])(client));
+}
+
+int
+SProcCopyGC(ClientPtr client)
+{
+ char n;
+ REQUEST(xCopyGCReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCopyGCReq);
+ swapl(&stuff->srcGC, n);
+ swapl(&stuff->dstGC, n);
+ swapl(&stuff->mask, n);
+ return((* ProcVector[X_CopyGC])(client));
+}
+
+int
+SProcSetDashes(ClientPtr client)
+{
+ char n;
+ REQUEST(xSetDashesReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSetDashesReq);
+ swapl(&stuff->gc, n);
+ swaps(&stuff->dashOffset, n);
+ swaps(&stuff->nDashes, n);
+ return((* ProcVector[X_SetDashes])(client));
+
+}
+
+int
+SProcSetClipRectangles(ClientPtr client)
+{
+ char n;
+ REQUEST(xSetClipRectanglesReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
+ swapl(&stuff->gc, n);
+ swaps(&stuff->xOrigin, n);
+ swaps(&stuff->yOrigin, n);
+ SwapRestS(stuff);
+ return((* ProcVector[X_SetClipRectangles])(client));
+}
+
+int
+SProcClearToBackground(ClientPtr client)
+{
+ char n;
+ REQUEST(xClearAreaReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xClearAreaReq);
+ swapl(&stuff->window, n);
+ swaps(&stuff->x, n);
+ swaps(&stuff->y, n);
+ swaps(&stuff->width, n);
+ swaps(&stuff->height, n);
+ return((* ProcVector[X_ClearArea])(client));
+}
+
+int
+SProcCopyArea(ClientPtr client)
+{
+ char n;
+ REQUEST(xCopyAreaReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCopyAreaReq);
+ swapl(&stuff->srcDrawable, n);
+ swapl(&stuff->dstDrawable, n);
+ swapl(&stuff->gc, n);
+ swaps(&stuff->srcX, n);
+ swaps(&stuff->srcY, n);
+ swaps(&stuff->dstX, n);
+ swaps(&stuff->dstY, n);
+ swaps(&stuff->width, n);
+ swaps(&stuff->height, n);
+ return((* ProcVector[X_CopyArea])(client));
+}
+
+int
+SProcCopyPlane(ClientPtr client)
+{
+ char n;
+ REQUEST(xCopyPlaneReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCopyPlaneReq);
+ swapl(&stuff->srcDrawable, n);
+ swapl(&stuff->dstDrawable, n);
+ swapl(&stuff->gc, n);
+ swaps(&stuff->srcX, n);
+ swaps(&stuff->srcY, n);
+ swaps(&stuff->dstX, n);
+ swaps(&stuff->dstY, n);
+ swaps(&stuff->width, n);
+ swaps(&stuff->height, n);
+ swapl(&stuff->bitPlane, n);
+ return((* ProcVector[X_CopyPlane])(client));
+}
+
+/* The following routine is used for all Poly drawing requests
+ (except FillPoly, which uses a different request format) */
+int
+SProcPoly(ClientPtr client)
+{
+ char n;
+
+ REQUEST(xPolyPointReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xPolyPointReq);
+ swapl(&stuff->drawable, n);
+ swapl(&stuff->gc, n);
+ SwapRestS(stuff);
+ return((* ProcVector[stuff->reqType])(client));
+}
+
+/* cannot use SProcPoly for this one, because xFillPolyReq
+ is longer than xPolyPointReq, and we don't want to swap
+ the difference as shorts! */
+int
+SProcFillPoly(ClientPtr client)
+{
+ char n;
+
+ REQUEST(xFillPolyReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xFillPolyReq);
+ swapl(&stuff->drawable, n);
+ swapl(&stuff->gc, n);
+ SwapRestS(stuff);
+ return((* ProcVector[X_FillPoly])(client));
+}
+
+int
+SProcPutImage(ClientPtr client)
+{
+ char n;
+ REQUEST(xPutImageReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xPutImageReq);
+ swapl(&stuff->drawable, n);
+ swapl(&stuff->gc, n);
+ swaps(&stuff->width, n);
+ swaps(&stuff->height, n);
+ swaps(&stuff->dstX, n);
+ swaps(&stuff->dstY, n);
+ /* Image should already be swapped */
+ return((* ProcVector[X_PutImage])(client));
+
+}
+
+int
+SProcGetImage(ClientPtr client)
+{
+ char n;
+ REQUEST(xGetImageReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xGetImageReq);
+ swapl(&stuff->drawable, n);
+ swaps(&stuff->x, n);
+ swaps(&stuff->y, n);
+ swaps(&stuff->width, n);
+ swaps(&stuff->height, n);
+ swapl(&stuff->planeMask, n);
+ return((* ProcVector[X_GetImage])(client));
+}
+
+/* ProcPolyText used for both PolyText8 and PolyText16 */
+
+int
+SProcPolyText(ClientPtr client)
+{
+ char n;
+ REQUEST(xPolyTextReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xPolyTextReq);
+ swapl(&stuff->drawable, n);
+ swapl(&stuff->gc, n);
+ swaps(&stuff->x, n);
+ swaps(&stuff->y, n);
+ return((* ProcVector[stuff->reqType])(client));
+}
+
+/* ProcImageText used for both ImageText8 and ImageText16 */
+
+int
+SProcImageText(ClientPtr client)
+{
+ char n;
+ REQUEST(xImageTextReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xImageTextReq);
+ swapl(&stuff->drawable, n);
+ swapl(&stuff->gc, n);
+ swaps(&stuff->x, n);
+ swaps(&stuff->y, n);
+ return((* ProcVector[stuff->reqType])(client));
+}
+
+int
+SProcCreateColormap(ClientPtr client)
+{
+ char n;
+ REQUEST(xCreateColormapReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCreateColormapReq);
+ swapl(&stuff->mid, n);
+ swapl(&stuff->window, n);
+ swapl(&stuff->visual, n);
+ return((* ProcVector[X_CreateColormap])(client));
+}
+
+
+int
+SProcCopyColormapAndFree(ClientPtr client)
+{
+ char n;
+ REQUEST(xCopyColormapAndFreeReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq);
+ swapl(&stuff->mid, n);
+ swapl(&stuff->srcCmap, n);
+ return((* ProcVector[X_CopyColormapAndFree])(client));
+
+}
+
+int
+SProcAllocColor(ClientPtr client)
+{
+ char n;
+ REQUEST(xAllocColorReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xAllocColorReq);
+ swapl(&stuff->cmap, n);
+ swaps(&stuff->red, n);
+ swaps(&stuff->green, n);
+ swaps(&stuff->blue, n);
+ return((* ProcVector[X_AllocColor])(client));
+}
+
+int
+SProcAllocNamedColor(ClientPtr client)
+{
+ char n;
+
+ REQUEST(xAllocNamedColorReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xAllocNamedColorReq);
+ swapl(&stuff->cmap, n);
+ swaps(&stuff->nbytes, n);
+ return((* ProcVector[X_AllocNamedColor])(client));
+}
+
+int
+SProcAllocColorCells(ClientPtr client)
+{
+ char n;
+ REQUEST(xAllocColorCellsReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xAllocColorCellsReq);
+ swapl(&stuff->cmap, n);
+ swaps(&stuff->colors, n);
+ swaps(&stuff->planes, n);
+ return((* ProcVector[X_AllocColorCells])(client));
+}
+
+int
+SProcAllocColorPlanes(ClientPtr client)
+{
+ char n;
+ REQUEST(xAllocColorPlanesReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xAllocColorPlanesReq);
+ swapl(&stuff->cmap, n);
+ swaps(&stuff->colors, n);
+ swaps(&stuff->red, n);
+ swaps(&stuff->green, n);
+ swaps(&stuff->blue, n);
+ return((* ProcVector[X_AllocColorPlanes])(client));
+}
+
+int
+SProcFreeColors(ClientPtr client)
+{
+ char n;
+ REQUEST(xFreeColorsReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
+ swapl(&stuff->cmap, n);
+ swapl(&stuff->planeMask, n);
+ SwapRestL(stuff);
+ return((* ProcVector[X_FreeColors])(client));
+
+}
+
+void
+SwapColorItem(xColorItem *pItem)
+{
+ char n;
+
+ swapl(&pItem->pixel, n);
+ swaps(&pItem->red, n);
+ swaps(&pItem->green, n);
+ swaps(&pItem->blue, n);
+}
+
+int
+SProcStoreColors(ClientPtr client)
+{
+ char n;
+ long count;
+ xColorItem *pItem;
+
+ REQUEST(xStoreColorsReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
+ swapl(&stuff->cmap, n);
+ pItem = (xColorItem *) &stuff[1];
+ for(count = LengthRestB(stuff)/sizeof(xColorItem); --count >= 0; )
+ SwapColorItem(pItem++);
+ return((* ProcVector[X_StoreColors])(client));
+}
+
+int
+SProcStoreNamedColor (ClientPtr client)
+{
+ char n;
+ REQUEST(xStoreNamedColorReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xStoreNamedColorReq);
+ swapl(&stuff->cmap, n);
+ swapl(&stuff->pixel, n);
+ swaps(&stuff->nbytes, n);
+ return((* ProcVector[X_StoreNamedColor])(client));
+}
+
+int
+SProcQueryColors (ClientPtr client)
+{
+ char n;
+ REQUEST(xQueryColorsReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xQueryColorsReq);
+ swapl(&stuff->cmap, n);
+ SwapRestL(stuff);
+ return((* ProcVector[X_QueryColors])(client));
+}
+
+int
+SProcLookupColor (ClientPtr client)
+{
+ char n;
+ REQUEST(xLookupColorReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xLookupColorReq);
+ swapl(&stuff->cmap, n);
+ swaps(&stuff->nbytes, n);
+ return((* ProcVector[X_LookupColor])(client));
+}
+
+int
+SProcCreateCursor (ClientPtr client)
+{
+ char n;
+ REQUEST(xCreateCursorReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCreateCursorReq);
+ swapl(&stuff->cid, n);
+ swapl(&stuff->source, n);
+ swapl(&stuff->mask, n);
+ swaps(&stuff->foreRed, n);
+ swaps(&stuff->foreGreen, n);
+ swaps(&stuff->foreBlue, n);
+ swaps(&stuff->backRed, n);
+ swaps(&stuff->backGreen, n);
+ swaps(&stuff->backBlue, n);
+ swaps(&stuff->x, n);
+ swaps(&stuff->y, n);
+ return((* ProcVector[X_CreateCursor])(client));
+}
+
+int
+SProcCreateGlyphCursor (ClientPtr client)
+{
+ char n;
+ REQUEST(xCreateGlyphCursorReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCreateGlyphCursorReq);
+ swapl(&stuff->cid, n);
+ swapl(&stuff->source, n);
+ swapl(&stuff->mask, n);
+ swaps(&stuff->sourceChar, n);
+ swaps(&stuff->maskChar, n);
+ swaps(&stuff->foreRed, n);
+ swaps(&stuff->foreGreen, n);
+ swaps(&stuff->foreBlue, n);
+ swaps(&stuff->backRed, n);
+ swaps(&stuff->backGreen, n);
+ swaps(&stuff->backBlue, n);
+ return((* ProcVector[X_CreateGlyphCursor])(client));
+}
+
+
+int
+SProcRecolorCursor (ClientPtr client)
+{
+ char n;
+ REQUEST(xRecolorCursorReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xRecolorCursorReq);
+ swapl(&stuff->cursor, n);
+ swaps(&stuff->foreRed, n);
+ swaps(&stuff->foreGreen, n);
+ swaps(&stuff->foreBlue, n);
+ swaps(&stuff->backRed, n);
+ swaps(&stuff->backGreen, n);
+ swaps(&stuff->backBlue, n);
+ return((* ProcVector[X_RecolorCursor])(client));
+}
+
+int
+SProcQueryBestSize (ClientPtr client)
+{
+ char n;
+ REQUEST(xQueryBestSizeReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xQueryBestSizeReq);
+ swapl(&stuff->drawable, n);
+ swaps(&stuff->width, n);
+ swaps(&stuff->height, n);
+ return((* ProcVector[X_QueryBestSize])(client));
+
+}
+
+int
+SProcQueryExtension (ClientPtr client)
+{
+ char n;
+ REQUEST(xQueryExtensionReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xQueryExtensionReq);
+ swaps(&stuff->nbytes, n);
+ return((* ProcVector[X_QueryExtension])(client));
+}
+
+int
+SProcChangeKeyboardMapping (ClientPtr client)
+{
+ char n;
+ REQUEST(xChangeKeyboardMappingReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq);
+ SwapRestL(stuff);
+ return((* ProcVector[X_ChangeKeyboardMapping])(client));
+}
+
+
+int
+SProcChangeKeyboardControl (ClientPtr client)
+{
+ char n;
+ REQUEST(xChangeKeyboardControlReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq);
+ swapl(&stuff->mask, n);
+ SwapRestL(stuff);
+ return((* ProcVector[X_ChangeKeyboardControl])(client));
+}
+
+int
+SProcChangePointerControl (ClientPtr client)
+{
+ char n;
+ REQUEST(xChangePointerControlReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xChangePointerControlReq);
+ swaps(&stuff->accelNum, n);
+ swaps(&stuff->accelDenum, n);
+ swaps(&stuff->threshold, n);
+ return((* ProcVector[X_ChangePointerControl])(client));
+}
+
+
+int
+SProcSetScreenSaver (ClientPtr client)
+{
+ char n;
+ REQUEST(xSetScreenSaverReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xSetScreenSaverReq);
+ swaps(&stuff->timeout, n);
+ swaps(&stuff->interval, n);
+ return((* ProcVector[X_SetScreenSaver])(client));
+}
+
+int
+SProcChangeHosts (ClientPtr client)
+{
+ char n;
+
+ REQUEST(xChangeHostsReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xChangeHostsReq);
+ swaps(&stuff->hostLength, n);
+ return((* ProcVector[X_ChangeHosts])(client));
+
+}
+
+int SProcRotateProperties (ClientPtr client)
+{
+ char n;
+ REQUEST(xRotatePropertiesReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xRotatePropertiesReq);
+ swapl(&stuff->window, n);
+ swaps(&stuff->nAtoms, n);
+ swaps(&stuff->nPositions, n);
+ SwapRestL(stuff);
+ return ((* ProcVector[X_RotateProperties])(client));
+}
+
+int
+SProcNoOperation(ClientPtr client)
+{
+ char n;
+ REQUEST(xReq);
+ swaps(&stuff->length, n);
+ return ((* ProcVector[X_NoOperation])(client));
+}
+
+void
+SwapConnClientPrefix(xConnClientPrefix *pCCP)
+{
+ char n;
+
+ swaps(&pCCP->majorVersion, n);
+ swaps(&pCCP->minorVersion, n);
+ swaps(&pCCP->nbytesAuthProto, n);
+ swaps(&pCCP->nbytesAuthString, n);
+}
diff --git a/xorg-server/dix/window.c b/xorg-server/dix/window.c
index 5109885e9..62f790c08 100644
--- a/xorg-server/dix/window.c
+++ b/xorg-server/dix/window.c
@@ -151,13 +151,7 @@ WindowSeekDeviceCursor(WindowPtr pWin,
int screenIsSaved = SCREEN_SAVER_OFF;
-ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
-
-static int FocusPrivatesKeyIndex;
-DevPrivateKey FocusPrivatesKey = &FocusPrivatesKeyIndex;
-
-static Bool TileScreenSaver(int i, int kind);
-
+static Bool TileScreenSaver(ScreenPtr pScreen, int kind);
#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \
CWDontPropagate | CWOverrideRedirect | CWCursor )
@@ -197,7 +191,7 @@ PrintChildren(WindowPtr p1, int indent)
ErrorF("[dix] ");
for (i=0; i<indent; i++) ErrorF(" ");
ErrorF("%lx\n", p1->drawable.id);
- miPrintRegion(&p1->clipList);
+ RegionPrint(&p1->clipList);
PrintChildren(p2, indent+4);
p1 = p1->nextSib;
}
@@ -212,8 +206,8 @@ PrintWindowTree(void)
for (i=0; i<screenInfo.numScreens; i++)
{
ErrorF("[dix] WINDOW %d\n", i);
- pWin = WindowTable[i];
- miPrintRegion(&pWin->clipList);
+ pWin = screenInfo.screens[i]->root;
+ RegionPrint(&pWin->clipList);
p1 = pWin->firstChild;
PrintChildren(p1, 4);
}
@@ -227,12 +221,12 @@ TraverseTree(WindowPtr pWin, VisitWindowProcPtr func, pointer data)
WindowPtr pChild;
if (!(pChild = pWin))
- return(WT_NOMATCH);
+ return WT_NOMATCH;
while (1)
{
result = (* func)(pChild, data);
if (result == WT_STOPWALKING)
- return(WT_STOPWALKING);
+ return WT_STOPWALKING;
if ((result == WT_WALKCHILDREN) && pChild->firstChild)
{
pChild = pChild->firstChild;
@@ -244,7 +238,7 @@ TraverseTree(WindowPtr pWin, VisitWindowProcPtr func, pointer data)
break;
pChild = pChild->nextSib;
}
- return(WT_NOMATCH);
+ return WT_NOMATCH;
}
/*****
@@ -258,7 +252,7 @@ TraverseTree(WindowPtr pWin, VisitWindowProcPtr func, pointer data)
int
WalkTree(ScreenPtr pScreen, VisitWindowProcPtr func, pointer data)
{
- return(TraverseTree(WindowTable[pScreen->myNum], func, data));
+ return(TraverseTree(pScreen->root, func, data));
}
/* hack for forcing backing store on all windows */
@@ -359,20 +353,19 @@ CreateRootWindow(ScreenPtr pScreen)
BoxRec box;
PixmapFormatRec *format;
- pWin = malloc(sizeof(WindowRec));
+ pWin = dixAllocateObjectWithPrivates(WindowRec, PRIVATE_WINDOW);
if (!pWin)
return FALSE;
- savedScreenInfo[pScreen->myNum].pWindow = NULL;
- savedScreenInfo[pScreen->myNum].wid = FakeClientID(0);
- savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL;
+ pScreen->screensaver.pWindow = NULL;
+ pScreen->screensaver.wid = FakeClientID(0);
+ pScreen->screensaver.ExternalScreenSaver = NULL;
screenIsSaved = SCREEN_SAVER_OFF;
- WindowTable[pScreen->myNum] = pWin;
+ pScreen->root = pWin;
pWin->drawable.pScreen = pScreen;
pWin->drawable.type = DRAWABLE_WINDOW;
- pWin->devPrivates = NULL;
pWin->drawable.depth = pScreen->rootDepth;
for (format = screenInfo.formats;
@@ -418,10 +411,10 @@ CreateRootWindow(ScreenPtr pScreen)
box.y1 = 0;
box.x2 = pScreen->width;
box.y2 = pScreen->height;
- REGION_INIT(pScreen, &pWin->clipList, &box, 1);
- REGION_INIT(pScreen, &pWin->winSize, &box, 1);
- REGION_INIT(pScreen, &pWin->borderSize, &box, 1);
- REGION_INIT(pScreen, &pWin->borderClip, &box, 1);
+ 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;
@@ -496,12 +489,8 @@ ClippedRegionFromBox(WindowPtr pWin, RegionPtr Rgn,
int x, int y,
int w, int h)
{
- ScreenPtr pScreen;
- BoxRec box;
-
- pScreen = pWin->drawable.pScreen;
+ BoxRec box = *RegionExtents(&pWin->winSize);
- box = *(REGION_EXTENTS(pScreen, &pWin->winSize));
/* we do these calculations to avoid overflows */
if (x > box.x1)
box.x1 = x;
@@ -517,8 +506,8 @@ ClippedRegionFromBox(WindowPtr pWin, RegionPtr Rgn,
box.x2 = box.x1;
if (box.y1 > box.y2)
box.y2 = box.y1;
- REGION_RESET(pScreen, Rgn, &box);
- REGION_INTERSECT(pScreen, Rgn, Rgn, &pWin->winSize);
+ RegionReset(Rgn, &box);
+ RegionIntersect(Rgn, Rgn, &pWin->winSize);
}
static RealChildHeadProc realChildHeadProc = NULL;
@@ -539,10 +528,10 @@ RealChildHead(WindowPtr pWin)
if (!pWin->parent &&
(screenIsSaved == SCREEN_SAVER_ON) &&
- (HasSaverWindow (pWin->drawable.pScreen->myNum)))
- return (pWin->firstChild);
+ (HasSaverWindow (pWin->drawable.pScreen)))
+ return pWin->firstChild;
else
- return (NullWindow);
+ return NullWindow;
}
/*****
@@ -639,14 +628,13 @@ CreateWindow(Window wid, WindowPtr pParent, int x, int y, unsigned w,
return NullWindow;
}
- pWin = malloc(sizeof(WindowRec));
+ pWin = dixAllocateObjectWithPrivates(WindowRec, PRIVATE_WINDOW);
if (!pWin)
{
*error = BadAlloc;
return NullWindow;
}
pWin->drawable = pParent->drawable;
- pWin->devPrivates = NULL;
pWin->drawable.depth = depth;
if (depth == pParent->drawable.depth)
pWin->drawable.bitsPerPixel = pParent->drawable.bitsPerPixel;
@@ -670,7 +658,7 @@ CreateWindow(Window wid, WindowPtr pParent, int x, int y, unsigned w,
{
if (!MakeWindowOptional (pWin))
{
- free(pWin);
+ dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
*error = BadAlloc;
return NullWindow;
}
@@ -685,7 +673,7 @@ CreateWindow(Window wid, WindowPtr pParent, int x, int y, unsigned w,
*error = XaceHook(XACE_RESOURCE_ACCESS, client, wid, RT_WINDOW, pWin,
RT_WINDOW, pWin->parent, DixCreateAccess|DixSetAttrAccess);
if (*error != Success) {
- free(pWin);
+ dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
return NullWindow;
}
@@ -705,10 +693,10 @@ CreateWindow(Window wid, WindowPtr pParent, int x, int y, unsigned w,
pWin->drawable.y = pParent->drawable.y + y + (int)bw;
/* set up clip list correctly for unobscured WindowPtr */
- REGION_NULL(pScreen, &pWin->clipList);
- REGION_NULL(pScreen, &pWin->borderClip);
- REGION_NULL(pScreen, &pWin->winSize);
- REGION_NULL(pScreen, &pWin->borderSize);
+ RegionNull(&pWin->clipList);
+ RegionNull(&pWin->borderClip);
+ RegionNull(&pWin->winSize);
+ RegionNull(&pWin->borderSize);
pHead = RealChildHead(pParent);
if (pHead)
@@ -826,16 +814,16 @@ FreeWindowResources(WindowPtr pWin)
DeleteWindowFromAnySaveSet(pWin);
DeleteWindowFromAnySelections(pWin);
DeleteWindowFromAnyEvents(pWin, TRUE);
- REGION_UNINIT(pScreen, &pWin->clipList);
- REGION_UNINIT(pScreen, &pWin->winSize);
- REGION_UNINIT(pScreen, &pWin->borderClip);
- REGION_UNINIT(pScreen, &pWin->borderSize);
+ RegionUninit(&pWin->clipList);
+ RegionUninit(&pWin->winSize);
+ RegionUninit(&pWin->borderClip);
+ RegionUninit(&pWin->borderSize);
if (wBoundingShape (pWin))
- REGION_DESTROY(pScreen, wBoundingShape (pWin));
+ RegionDestroy(wBoundingShape (pWin));
if (wClipShape (pWin))
- REGION_DESTROY(pScreen, wClipShape (pWin));
+ RegionDestroy(wClipShape (pWin));
if (wInputShape (pWin))
- REGION_DESTROY(pScreen, wInputShape (pWin));
+ RegionDestroy(wInputShape (pWin));
if (pWin->borderIsPixel == FALSE)
(*pScreen->DestroyPixmap)(pWin->border.pixmap);
if (pWin->backgroundState == BackgroundPixmap)
@@ -883,8 +871,7 @@ CrushTree(WindowPtr pWin)
(*UnrealizeWindow)(pChild);
}
FreeWindowResources(pChild);
- dixFreePrivates(pChild->devPrivates);
- free(pChild);
+ dixFreeObjectWithPrivates(pChild, PRIVATE_WINDOW);
if ( (pChild = pSib) )
break;
pChild = pParent;
@@ -934,9 +921,7 @@ DeleteWindow(pointer value, XID wid)
if (pWin->prevSib)
pWin->prevSib->nextSib = pWin->nextSib;
}
- free(dixLookupPrivate(&pWin->devPrivates, FocusPrivatesKey));
- dixFreePrivates(pWin->devPrivates);
- free(pWin);
+ dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
return Success;
}
@@ -1329,7 +1314,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client)
*/
if ( cursorID == None)
{
- if (pWin == WindowTable[pWin->drawable.pScreen->myNum])
+ if (pWin == pWin->drawable.pScreen->root)
pCursor = rootCursor;
else
pCursor = (CursorPtr) None;
@@ -1433,10 +1418,10 @@ PatchUp:
{
RegionRec exposed;
- REGION_NULL(pScreen, &exposed);
- REGION_SUBTRACT(pScreen, &exposed, &pWin->borderClip, &pWin->winSize);
+ RegionNull(&exposed);
+ RegionSubtract(&exposed, &pWin->borderClip, &pWin->winSize);
miPaintWindow(pWin, &exposed, PW_BORDER);
- REGION_UNINIT(pScreen, &exposed);
+ RegionUninit(&exposed);
}
return error;
}
@@ -1564,7 +1549,7 @@ MoveWindowInStack(WindowPtr pWin, WindowPtr pNextSib)
(*pWin->drawable.pScreen->RestackWindow)(pWin, pWin->nextSib);
#endif
- return( pFirstChange );
+ return pFirstChange;
}
void
@@ -1583,7 +1568,7 @@ SetWinSize (WindowPtr pWin)
box.y1 = pWin->drawable.y;
box.x2 = pWin->drawable.x + pWin->drawable.width;
box.y2 = pWin->drawable.y + pWin->drawable.height;
- REGION_RESET (pScreen, &pWin->winSize, &box);
+ RegionReset(&pWin->winSize, &box);
}
else
#endif
@@ -1592,18 +1577,15 @@ SetWinSize (WindowPtr pWin)
(int)pWin->drawable.width,
(int)pWin->drawable.height);
if (wBoundingShape (pWin) || wClipShape (pWin)) {
- ScreenPtr pScreen;
- pScreen = pWin->drawable.pScreen;
-
- REGION_TRANSLATE(pScreen, &pWin->winSize, - pWin->drawable.x,
+ RegionTranslate(&pWin->winSize, - pWin->drawable.x,
- pWin->drawable.y);
if (wBoundingShape (pWin))
- REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize,
+ RegionIntersect(&pWin->winSize, &pWin->winSize,
wBoundingShape (pWin));
if (wClipShape (pWin))
- REGION_INTERSECT(pScreen, &pWin->winSize, &pWin->winSize,
+ RegionIntersect(&pWin->winSize, &pWin->winSize,
wClipShape (pWin));
- REGION_TRANSLATE(pScreen, &pWin->winSize, pWin->drawable.x,
+ RegionTranslate(&pWin->winSize, pWin->drawable.x,
pWin->drawable.y);
}
}
@@ -1628,7 +1610,7 @@ SetBorderSize (WindowPtr pWin)
box.y1 = pWin->drawable.y - bw;
box.x2 = pWin->drawable.x + pWin->drawable.width + bw;
box.y2 = pWin->drawable.y + pWin->drawable.height + bw;
- REGION_RESET (pScreen, &pWin->borderSize, &box);
+ RegionReset(&pWin->borderSize, &box);
}
else
#endif
@@ -1637,21 +1619,17 @@ SetBorderSize (WindowPtr pWin)
(int)(pWin->drawable.width + (bw<<1)),
(int)(pWin->drawable.height + (bw<<1)));
if (wBoundingShape (pWin)) {
- ScreenPtr pScreen;
- pScreen = pWin->drawable.pScreen;
-
- REGION_TRANSLATE(pScreen, &pWin->borderSize, - pWin->drawable.x,
+ RegionTranslate(&pWin->borderSize, - pWin->drawable.x,
- pWin->drawable.y);
- REGION_INTERSECT(pScreen, &pWin->borderSize, &pWin->borderSize,
+ RegionIntersect(&pWin->borderSize, &pWin->borderSize,
wBoundingShape (pWin));
- REGION_TRANSLATE(pScreen, &pWin->borderSize, pWin->drawable.x,
+ RegionTranslate(&pWin->borderSize, pWin->drawable.x,
pWin->drawable.y);
- REGION_UNION(pScreen, &pWin->borderSize, &pWin->borderSize,
+ RegionUnion(&pWin->borderSize, &pWin->borderSize,
&pWin->winSize);
}
} else {
- REGION_COPY(pWin->drawable.pScreen, &pWin->borderSize,
- &pWin->winSize);
+ RegionCopy(&pWin->borderSize, &pWin->winSize);
}
}
@@ -1817,12 +1795,12 @@ IsSiblingAboveMe(
while (pWin)
{
if (pWin == pSib)
- return(Above);
+ return Above;
else if (pWin == pMe)
- return(Below);
+ return Below;
pWin = pWin->nextSib;
}
- return(Below);
+ return Below;
}
static BoxPtr
@@ -1836,7 +1814,7 @@ WindowExtents(
+ wBorderWidth (pWin);
pBox->y2 = pWin->drawable.y + (int)pWin->drawable.height
+ wBorderWidth (pWin);
- return(pBox);
+ return pBox;
}
#define IS_SHAPED(pWin) (wBoundingShape (pWin) != (RegionPtr) NULL)
@@ -1846,17 +1824,11 @@ MakeBoundingRegion (
WindowPtr pWin,
BoxPtr pBox)
{
- RegionPtr pRgn;
- ScreenPtr pScreen;
- pScreen = pWin->drawable.pScreen;
-
- pRgn = REGION_CREATE(pScreen, pBox, 1);
+ RegionPtr pRgn = RegionCreate(pBox, 1);
if (wBoundingShape (pWin)) {
- REGION_TRANSLATE(pScreen, pRgn, -pWin->origin.x,
- -pWin->origin.y);
- REGION_INTERSECT(pScreen, pRgn, pRgn, wBoundingShape (pWin));
- REGION_TRANSLATE(pScreen, pRgn, pWin->origin.x,
- pWin->origin.y);
+ RegionTranslate(pRgn, -pWin->origin.x, -pWin->origin.y);
+ RegionIntersect(pRgn, pRgn, wBoundingShape (pWin));
+ RegionTranslate(pRgn, pWin->origin.x, pWin->origin.y);
}
return pRgn;
}
@@ -1869,18 +1841,16 @@ ShapeOverlap (
BoxPtr pSibBox)
{
RegionPtr pWinRgn, pSibRgn;
- ScreenPtr pScreen;
Bool ret;
if (!IS_SHAPED(pWin) && !IS_SHAPED(pSib))
return TRUE;
- pScreen = pWin->drawable.pScreen;
pWinRgn = MakeBoundingRegion (pWin, pWinBox);
pSibRgn = MakeBoundingRegion (pSib, pSibBox);
- REGION_INTERSECT(pScreen, pWinRgn, pWinRgn, pSibRgn);
- ret = REGION_NOTEMPTY(pScreen, pWinRgn);
- REGION_DESTROY(pScreen, pWinRgn);
- REGION_DESTROY(pScreen, pSibRgn);
+ RegionIntersect(pWinRgn, pWinRgn, pSibRgn);
+ ret = RegionNotEmpty(pWinRgn);
+ RegionDestroy(pWinRgn);
+ RegionDestroy(pSibRgn);
return ret;
}
@@ -1902,10 +1872,10 @@ AnyWindowOverlapsMe(
if (BOXES_OVERLAP(sbox, box)
&& ShapeOverlap (pWin, box, pSib, sbox)
)
- return(TRUE);
+ return TRUE;
}
}
- return(FALSE);
+ return FALSE;
}
static Bool
@@ -1925,10 +1895,10 @@ IOverlapAnyWindow(
if (BOXES_OVERLAP(sbox, box)
&& ShapeOverlap (pWin, box, pSib, sbox)
)
- return(TRUE);
+ return TRUE;
}
}
- return(FALSE);
+ return FALSE;
}
/*
@@ -1970,7 +1940,6 @@ WhereDoIGoInTheStack(
int smode)
{
BoxRec box;
- ScreenPtr pScreen;
WindowPtr pHead, pFirst;
if ((pWin == pWin->parent->firstChild) &&
@@ -1978,7 +1947,6 @@ WhereDoIGoInTheStack(
return((WindowPtr ) NULL);
pHead = RealChildHead(pWin->parent);
pFirst = pHead ? pHead->nextSib : pWin->parent->firstChild;
- pScreen = pWin->drawable.pScreen;
box.x1 = x;
box.y1 = y;
box.x2 = x + (int)w;
@@ -1987,63 +1955,63 @@ WhereDoIGoInTheStack(
{
case Above:
if (pSib)
- return(pSib);
+ return pSib;
else if (pWin == pFirst)
- return(pWin->nextSib);
+ return pWin->nextSib;
else
- return(pFirst);
+ return pFirst;
case Below:
if (pSib)
if (pSib->nextSib != pWin)
- return(pSib->nextSib);
+ return pSib->nextSib;
else
- return(pWin->nextSib);
+ return pWin->nextSib;
else
return NullWindow;
case TopIf:
if ((!pWin->mapped || (pSib && !pSib->mapped)))
- return(pWin->nextSib);
+ return pWin->nextSib;
else if (pSib)
{
if ((IsSiblingAboveMe(pWin, pSib) == Above) &&
- (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT))
- return(pFirst);
+ (RegionContainsRect(&pSib->borderSize, &box) != rgnOUT))
+ return pFirst;
else
- return(pWin->nextSib);
+ return pWin->nextSib;
}
else if (AnyWindowOverlapsMe(pWin, pHead, &box))
- return(pFirst);
+ return pFirst;
else
- return(pWin->nextSib);
+ return pWin->nextSib;
case BottomIf:
if ((!pWin->mapped || (pSib && !pSib->mapped)))
- return(pWin->nextSib);
+ return pWin->nextSib;
else if (pSib)
{
if ((IsSiblingAboveMe(pWin, pSib) == Below) &&
- (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT))
+ (RegionContainsRect(&pSib->borderSize, &box) != rgnOUT))
return NullWindow;
else
- return(pWin->nextSib);
+ return pWin->nextSib;
}
else if (IOverlapAnyWindow(pWin, &box))
return NullWindow;
else
- return(pWin->nextSib);
+ return pWin->nextSib;
case Opposite:
if ((!pWin->mapped || (pSib && !pSib->mapped)))
- return(pWin->nextSib);
+ return pWin->nextSib;
else if (pSib)
{
- if (RECT_IN_REGION(pScreen, &pSib->borderSize, &box) != rgnOUT)
+ if (RegionContainsRect(&pSib->borderSize, &box) != rgnOUT)
{
if (IsSiblingAboveMe(pWin, pSib) == Above)
- return(pFirst);
+ return pFirst;
else
return NullWindow;
}
else
- return(pWin->nextSib);
+ return pWin->nextSib;
}
else if (AnyWindowOverlapsMe(pWin, pHead, &box))
{
@@ -2051,7 +2019,7 @@ WhereDoIGoInTheStack(
* if (pWin == pWin->parent->firstChild)
* return pWin->nextSib;
*/
- return(pFirst);
+ return pFirst;
}
else if (IOverlapAnyWindow(pWin, &box))
return NullWindow;
@@ -2126,10 +2094,10 @@ ConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client)
xEvent event;
if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask))
- return(BadMatch);
+ return BadMatch;
if ((mask & CWSibling) && !(mask & CWStackMode))
- return(BadMatch);
+ return BadMatch;
pVlist = vlist;
@@ -2186,9 +2154,9 @@ ConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client)
return rc;
}
if (pSib->parent != pParent)
- return(BadMatch);
+ return BadMatch;
if (pSib == pWin)
- return(BadMatch);
+ return BadMatch;
break;
case CWStackMode:
GET_CARD8(CWStackMode, smode);
@@ -2196,12 +2164,12 @@ ConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client)
(smode != Opposite) && (smode != Above) && (smode != Below))
{
client->errorValue = smode;
- return(BadValue);
+ return BadValue;
}
break;
default:
client->errorValue = mask;
- return(BadValue);
+ return BadValue;
}
}
/* root really can't be reconfigured, so just return */
@@ -2238,8 +2206,8 @@ ConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client)
event.u.configureRequest.y = y;
#ifdef PANORAMIX
if(!noPanoramiXExtension && (!pParent || !pParent->parent)) {
- event.u.configureRequest.x += panoramiXdataPtr[0].x;
- event.u.configureRequest.y += panoramiXdataPtr[0].y;
+ event.u.configureRequest.x += screenInfo.screens[0]->x;
+ event.u.configureRequest.y += screenInfo.screens[0]->y;
}
#endif
event.u.configureRequest.width = w;
@@ -2249,7 +2217,7 @@ ConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client)
event.u.configureRequest.parent = pParent->drawable.id;
if (MaybeDeliverEventsToClient(pParent, &event, 1,
SubstructureRedirectMask, client) == 1)
- return(Success);
+ return Success;
}
if (action == RESIZE_WIN)
{
@@ -2300,11 +2268,18 @@ ConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client)
#endif
goto ActuallyDoSomething;
}
- return(Success);
+ return Success;
ActuallyDoSomething:
if (pWin->drawable.pScreen->ConfigNotify)
- (*pWin->drawable.pScreen->ConfigNotify)(pWin, x, y, w, h, bw, pSib);
+ {
+ 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))
{
@@ -2319,8 +2294,8 @@ ActuallyDoSomething:
event.u.configureNotify.y = y;
#ifdef PANORAMIX
if(!noPanoramiXExtension && (!pParent || !pParent->parent)) {
- event.u.configureNotify.x += panoramiXdataPtr[0].x;
- event.u.configureNotify.y += panoramiXdataPtr[0].y;
+ event.u.configureNotify.x += screenInfo.screens[0]->x;
+ event.u.configureNotify.y += screenInfo.screens[0]->y;
}
#endif
event.u.configureNotify.width = w;
@@ -2356,7 +2331,7 @@ ActuallyDoSomething:
if (action != RESTACK_WIN)
CheckCursorConfinement(pWin);
- return(Success);
+ return Success;
#undef RESTACK_WIN
#undef MOVE_WIN
#undef RESIZE_WIN
@@ -2417,7 +2392,7 @@ CirculateWindow(WindowPtr pParent, int direction, ClientPtr client)
event.u.u.type = CirculateRequest;
if (MaybeDeliverEventsToClient(pParent, &event, 1,
SubstructureRedirectMask, client) == 1)
- return(Success);
+ return Success;
}
event.u.u.type = CirculateNotify;
@@ -2426,7 +2401,7 @@ CirculateWindow(WindowPtr pParent, int direction, ClientPtr client)
(direction == RaiseLowest) ? pFirst : NullWindow,
VTStack);
- return(Success);
+ return Success;
}
static int
@@ -2437,9 +2412,9 @@ CompareWIDs(
Window *wid = (Window *)value;
if (pWin->drawable.id == *wid)
- return(WT_STOPWALKING);
+ return WT_STOPWALKING;
else
- return(WT_WALKCHILDREN);
+ return WT_WALKCHILDREN;
}
/*****
@@ -2458,9 +2433,9 @@ ReparentWindow(WindowPtr pWin, WindowPtr pParent,
pScreen = pWin->drawable.pScreen;
if (TraverseTree(pWin, CompareWIDs, (pointer)&pParent->drawable.id) == WT_STOPWALKING)
- return(BadMatch);
+ return BadMatch;
if (!MakeWindowOptional(pWin))
- return(BadAlloc);
+ return BadAlloc;
if (WasMapped)
UnmapWindow(pWin, FALSE);
@@ -2473,8 +2448,8 @@ ReparentWindow(WindowPtr pWin, WindowPtr pParent,
event.u.reparent.y = y;
#ifdef PANORAMIX
if(!noPanoramiXExtension && !pParent->parent) {
- event.u.reparent.x += panoramiXdataPtr[0].x;
- event.u.reparent.y += panoramiXdataPtr[0].y;
+ event.u.reparent.x += screenInfo.screens[0]->x;
+ event.u.reparent.y += screenInfo.screens[0]->y;
}
#endif
event.u.reparent.override = pWin->overrideRedirect;
@@ -2536,7 +2511,7 @@ ReparentWindow(WindowPtr pWin, WindowPtr pParent,
if (WasMapped)
MapWindow(pWin, client);
RecalculateDeliverableEvents(pWin);
- return(Success);
+ return Success;
}
static void
@@ -2609,7 +2584,7 @@ MapWindow(WindowPtr pWin, ClientPtr client)
WindowPtr pLayerWin;
if (pWin->mapped)
- return(Success);
+ return Success;
/* general check for permission to map window */
if (XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id, RT_WINDOW,
@@ -2633,7 +2608,7 @@ MapWindow(WindowPtr pWin, ClientPtr client)
if (MaybeDeliverEventsToClient(pParent, &event, 1,
SubstructureRedirectMask, client) == 1)
- return(Success);
+ return Success;
}
pWin->mapped = TRUE;
@@ -2647,7 +2622,7 @@ MapWindow(WindowPtr pWin, ClientPtr client)
}
if (!pParent->realized)
- return(Success);
+ return Success;
RealizeTree(pWin);
if (pWin->viewable)
{
@@ -2676,13 +2651,13 @@ MapWindow(WindowPtr pWin, ClientPtr client)
(*pScreen->ClipNotify) (pWin, 0, 0);
if (pScreen->PostValidateTree)
(*pScreen->PostValidateTree)(NullWindow, pWin, VTMap);
- REGION_NULL(pScreen, &temp);
- REGION_COPY(pScreen, &temp, &pWin->clipList);
+ RegionNull(&temp);
+ RegionCopy(&temp, &pWin->clipList);
(*pScreen->WindowExposures) (pWin, &temp, NullRegion);
- REGION_UNINIT(pScreen, &temp);
+ RegionUninit(&temp);
}
- return(Success);
+ return Success;
}
@@ -2838,7 +2813,7 @@ UnmapWindow(WindowPtr pWin, Bool fromConfigure)
WindowPtr pLayerWin = pWin;
if ((!pWin->mapped) || (!(pParent = pWin->parent)))
- return(Success);
+ return Success;
if (SubStrSend(pWin, pParent) && MapUnmapEventsEnabled(pWin))
{
memset(&event, 0, sizeof(xEvent));
@@ -2868,7 +2843,7 @@ UnmapWindow(WindowPtr pWin, Bool fromConfigure)
}
if (wasRealized && !fromConfigure)
WindowsRestructured ();
- return(Success);
+ return Success;
}
/*****
@@ -2966,7 +2941,7 @@ HandleSaveSet(ClientPtr client)
pWin = SaveSetWindow(client->saveSet[j]);
#ifdef XFIXES
if (SaveSetToRoot(client->saveSet[j]))
- pParent = WindowTable[pWin->drawable.pScreen->myNum];
+ pParent = pWin->drawable.pScreen->root;
else
#endif
{
@@ -3011,43 +2986,37 @@ PointInWindowIsVisible(WindowPtr pWin, int x, int y)
BoxRec box;
if (!pWin->realized)
- return (FALSE);
- if (POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderClip,
+ return FALSE;
+ if (RegionContainsPoint(&pWin->borderClip,
x, y, &box)
&& (!wInputShape(pWin) ||
- POINT_IN_REGION(pWin->drawable.pScreen,
- wInputShape(pWin),
- x - pWin->drawable.x,
- y - pWin->drawable.y, &box)))
- return(TRUE);
- return(FALSE);
+ RegionContainsPoint(wInputShape(pWin),
+ x - pWin->drawable.x,
+ y - pWin->drawable.y, &box)))
+ return TRUE;
+ return FALSE;
}
RegionPtr
NotClippedByChildren(WindowPtr pWin)
{
- ScreenPtr pScreen;
- RegionPtr pReg;
-
- pScreen = pWin->drawable.pScreen;
- pReg = REGION_CREATE(pScreen, NullBox, 1);
+ RegionPtr pReg = RegionCreate(NullBox, 1);
if (pWin->parent ||
screenIsSaved != SCREEN_SAVER_ON ||
- !HasSaverWindow (pWin->drawable.pScreen->myNum))
+ !HasSaverWindow (pWin->drawable.pScreen))
{
- REGION_INTERSECT(pScreen, pReg, &pWin->borderClip, &pWin->winSize);
+ RegionIntersect(pReg, &pWin->borderClip, &pWin->winSize);
}
- return(pReg);
+ return pReg;
}
void
SendVisibilityNotify(WindowPtr pWin)
{
xEvent event;
-#ifndef NO_XINERAMA_PORT
unsigned int visibility = pWin->visibility;
-#endif
+
if (!MapUnmapEventsEnabled(pWin))
return;
#ifdef PANORAMIX
@@ -3152,33 +3121,33 @@ dixSaveScreens(ClientPtr client, int on, int mode)
}
for (i = 0; i < screenInfo.numScreens; i++)
{
+ ScreenPtr pScreen = screenInfo.screens[i];
if (on == SCREEN_SAVER_FORCER)
- (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], on);
- if (savedScreenInfo[i].ExternalScreenSaver)
+ (* pScreen->SaveScreen) (pScreen, on);
+ if (pScreen->screensaver.ExternalScreenSaver)
{
- if ((*savedScreenInfo[i].ExternalScreenSaver)
- (screenInfo.screens[i], type, on == SCREEN_SAVER_FORCER))
+ if ((*pScreen->screensaver.ExternalScreenSaver)
+ (pScreen, type, on == SCREEN_SAVER_FORCER))
continue;
}
if (type == screenIsSaved)
continue;
switch (type) {
case SCREEN_SAVER_OFF:
- if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED)
+ if (pScreen->screensaver.blanked == SCREEN_IS_BLANKED)
{
- (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i],
- what);
+ (* pScreen->SaveScreen) (pScreen, what);
}
- else if (HasSaverWindow (i))
+ else if (HasSaverWindow (pScreen))
{
- savedScreenInfo[i].pWindow = NullWindow;
- FreeResource(savedScreenInfo[i].wid, RT_NONE);
+ pScreen->screensaver.pWindow = NullWindow;
+ FreeResource(pScreen->screensaver.wid, RT_NONE);
}
break;
case SCREEN_SAVER_CYCLE:
- if (savedScreenInfo[i].blanked == SCREEN_IS_TILED)
+ if (pScreen->screensaver.blanked == SCREEN_IS_TILED)
{
- WindowPtr pWin = savedScreenInfo[i].pWindow;
+ 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 miPaintWindow works
@@ -3202,35 +3171,33 @@ dixSaveScreens(ClientPtr client, int on, int mode)
* Call the DDX saver in case it wants to do something
* at cycle time
*/
- else if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED)
+ else if (pScreen->screensaver.blanked == SCREEN_IS_BLANKED)
{
- (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i],
- type);
+ (* pScreen->SaveScreen) (pScreen, type);
}
break;
case SCREEN_SAVER_ON:
if (ScreenSaverBlanking != DontPreferBlanking)
{
- if ((* screenInfo.screens[i]->SaveScreen)
- (screenInfo.screens[i], what))
+ if ((* pScreen->SaveScreen) (pScreen, what))
{
- savedScreenInfo[i].blanked = SCREEN_IS_BLANKED;
+ pScreen->screensaver.blanked = SCREEN_IS_BLANKED;
continue;
}
if ((ScreenSaverAllowExposures != DontAllowExposures) &&
- TileScreenSaver(i, SCREEN_IS_BLACK))
+ TileScreenSaver(pScreen, SCREEN_IS_BLACK))
{
- savedScreenInfo[i].blanked = SCREEN_IS_BLACK;
+ pScreen->screensaver.blanked = SCREEN_IS_BLACK;
continue;
}
}
if ((ScreenSaverAllowExposures != DontAllowExposures) &&
- TileScreenSaver(i, SCREEN_IS_TILED))
+ TileScreenSaver(pScreen, SCREEN_IS_TILED))
{
- savedScreenInfo[i].blanked = SCREEN_IS_TILED;
+ pScreen->screensaver.blanked = SCREEN_IS_TILED;
}
else
- savedScreenInfo[i].blanked = SCREEN_ISNT_SAVED;
+ pScreen->screensaver.blanked = SCREEN_ISNT_SAVED;
break;
}
}
@@ -3252,7 +3219,7 @@ SaveScreens(int on, int mode)
}
static Bool
-TileScreenSaver(int i, int kind)
+TileScreenSaver(ScreenPtr pScreen, int kind)
{
int j;
int result;
@@ -3269,9 +3236,9 @@ TileScreenSaver(int i, int kind)
attri = 0;
switch (kind) {
case SCREEN_IS_TILED:
- switch (WindowTable[i]->backgroundState) {
+ switch (pScreen->root->backgroundState) {
case BackgroundPixel:
- attributes[attri++] = WindowTable[i]->background.pixel;
+ attributes[attri++] = pScreen->root->background.pixel;
mask |= CWBackPixel;
break;
case BackgroundPixmap:
@@ -3283,7 +3250,7 @@ TileScreenSaver(int i, int kind)
}
break;
case SCREEN_IS_BLACK:
- attributes[attri++] = WindowTable[i]->drawable.pScreen->blackPixel;
+ attributes[attri++] = pScreen->root->drawable.pScreen->blackPixel;
mask |= CWBackPixel;
break;
}
@@ -3330,14 +3297,14 @@ TileScreenSaver(int i, int kind)
}
}
- pWin = savedScreenInfo[i].pWindow =
- CreateWindow(savedScreenInfo[i].wid,
- WindowTable[i],
+ pWin = pScreen->screensaver.pWindow =
+ CreateWindow(pScreen->screensaver.wid,
+ pScreen->root,
-RANDOM_WIDTH, -RANDOM_WIDTH,
- (unsigned short)screenInfo.screens[i]->width + RANDOM_WIDTH,
- (unsigned short)screenInfo.screens[i]->height + RANDOM_WIDTH,
+ (unsigned short)pScreen->width + RANDOM_WIDTH,
+ (unsigned short)pScreen->height + RANDOM_WIDTH,
0, InputOutput, mask, attributes, 0, serverClient,
- wVisual (WindowTable[i]), &result);
+ wVisual (pScreen->root), &result);
if (cursor)
FreeResource (cursorID, RT_NONE);
@@ -3346,7 +3313,7 @@ TileScreenSaver(int i, int kind)
return FALSE;
if (!AddResource(pWin->drawable.id, RT_WINDOW,
- (pointer)savedScreenInfo[i].pWindow))
+ (pointer)pScreen->screensaver.pWindow))
return FALSE;
if (mask & CWBackPixmap)