aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/mi
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/mi')
-rw-r--r--xorg-server/mi/micmap.c1362
-rw-r--r--xorg-server/mi/midispcur.c1168
-rw-r--r--xorg-server/mi/mieq.c938
-rw-r--r--xorg-server/mi/mipointer.c1396
-rw-r--r--xorg-server/mi/mipointrst.h114
-rw-r--r--xorg-server/mi/mispans.c1054
-rw-r--r--xorg-server/mi/mizerline.c762
7 files changed, 3397 insertions, 3397 deletions
diff --git a/xorg-server/mi/micmap.c b/xorg-server/mi/micmap.c
index ca87a8f20..3746cad7f 100644
--- a/xorg-server/mi/micmap.c
+++ b/xorg-server/mi/micmap.c
@@ -1,681 +1,681 @@
-/*
- * Copyright (c) 1987, Oracle and/or its affiliates. All rights reserved.
- *
- * 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.
- */
-
-/*
- * This is based on cfbcmap.c. The functions here are useful independently
- * of cfb, which is the reason for including them here. How "mi" these
- * are may be debatable.
- */
-
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "scrnintstr.h"
-#include "colormapst.h"
-#include "resource.h"
-#include "globals.h"
-#include "micmap.h"
-
-DevPrivateKeyRec micmapScrPrivateKeyRec;
-
-int
-miListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
-{
- if (GetInstalledmiColormap(pScreen)) {
- *pmaps = GetInstalledmiColormap(pScreen)->mid;
- return 1;
- }
- return 0;
-}
-
-void
-miInstallColormap(ColormapPtr pmap)
-{
- ColormapPtr oldpmap = GetInstalledmiColormap(pmap->pScreen);
-
- if(pmap != oldpmap)
- {
- /* Uninstall pInstalledMap. No hardware changes required, just
- * notify all interested parties. */
- if(oldpmap != (ColormapPtr)None)
- WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
- /* Install pmap */
- SetInstalledmiColormap(pmap->pScreen, pmap);
- WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
-
- }
-}
-
-void
-miUninstallColormap(ColormapPtr pmap)
-{
- ColormapPtr curpmap = GetInstalledmiColormap(pmap->pScreen);
-
- if(pmap == curpmap)
- {
- if (pmap->mid != pmap->pScreen->defColormap)
- {
- dixLookupResourceByType((pointer *)&curpmap,
- pmap->pScreen->defColormap,
- RT_COLORMAP, serverClient,
- DixUseAccess);
- (*pmap->pScreen->InstallColormap)(curpmap);
- }
- }
-}
-
-void
-miResolveColor(unsigned short *pred, unsigned short *pgreen,
- unsigned short *pblue, VisualPtr pVisual)
-{
- int shift = 16 - pVisual->bitsPerRGBValue;
- unsigned lim = (1 << pVisual->bitsPerRGBValue) - 1;
-
- if ((pVisual->class | DynamicClass) == GrayScale)
- {
- /* rescale to gray then rgb bits */
- *pred = (30L * *pred + 59L * *pgreen + 11L * *pblue) / 100;
- *pblue = *pgreen = *pred = ((*pred >> shift) * 65535) / lim;
- }
- else
- {
- /* rescale to rgb bits */
- *pred = ((*pred >> shift) * 65535) / lim;
- *pgreen = ((*pgreen >> shift) * 65535) / lim;
- *pblue = ((*pblue >> shift) * 65535) / lim;
- }
-}
-
-Bool
-miInitializeColormap(ColormapPtr pmap)
-{
- unsigned i;
- VisualPtr pVisual;
- unsigned lim, maxent, shift;
-
- pVisual = pmap->pVisual;
- lim = (1 << pVisual->bitsPerRGBValue) - 1;
- shift = 16 - pVisual->bitsPerRGBValue;
- maxent = pVisual->ColormapEntries - 1;
- if (pVisual->class == TrueColor)
- {
- unsigned limr, limg, limb;
-
- limr = pVisual->redMask >> pVisual->offsetRed;
- for(i = 0; i <= min(limr,maxent); i++)
- {
- /* rescale to [0..65535] then rgb bits */
- pmap->red[i].co.local.red =
- ((((i * 65535) / limr) >> shift) * 65535) / lim;
- }
- for(; i <= maxent; i++) pmap->red[i].co.local.red = 65535;
- limg = pVisual->greenMask >> pVisual->offsetGreen;
- for(i = 0; i <= min(limg,maxent); i++)
- {
- /* rescale to [0..65535] then rgb bits */
- pmap->green[i].co.local.green =
- ((((i * 65535) / limg) >> shift) * 65535) / lim;
- }
- for(; i <= maxent; i++) pmap->green[i].co.local.green = 65535;
- limb = pVisual->blueMask >> pVisual->offsetBlue;
- for(i = 0; i <= min(limb,maxent); i++)
- {
- /* rescale to [0..65535] then rgb bits */
- pmap->blue[i].co.local.blue =
- ((((i * 65535) / limb) >> shift) * 65535) / lim;
- }
- for(; i <= maxent; i++) pmap->blue[i].co.local.blue = 65535;
- }
- else if (pVisual->class == StaticColor)
- {
- unsigned limr, limg, limb;
-
- limr = pVisual->redMask >> pVisual->offsetRed;
- limg = pVisual->greenMask >> pVisual->offsetGreen;
- limb = pVisual->blueMask >> pVisual->offsetBlue;
- for(i = 0; i <= maxent; i++)
- {
- /* rescale to [0..65535] then rgb bits */
- pmap->red[i].co.local.red =
- ((((((i & pVisual->redMask) >> pVisual->offsetRed)
- * 65535) / limr) >> shift) * 65535) / lim;
- pmap->red[i].co.local.green =
- ((((((i & pVisual->greenMask) >> pVisual->offsetGreen)
- * 65535) / limg) >> shift) * 65535) / lim;
- pmap->red[i].co.local.blue =
- ((((((i & pVisual->blueMask) >> pVisual->offsetBlue)
- * 65535) / limb) >> shift) * 65535) / lim;
- }
- }
- else if (pVisual->class == StaticGray)
- {
- for(i = 0; i <= maxent; i++)
- {
- /* rescale to [0..65535] then rgb bits */
- pmap->red[i].co.local.red = ((((i * 65535) / maxent) >> shift)
- * 65535) / lim;
- pmap->red[i].co.local.green = pmap->red[i].co.local.red;
- pmap->red[i].co.local.blue = pmap->red[i].co.local.red;
- }
- }
- return TRUE;
-}
-
-/* When simulating DirectColor on PseudoColor hardware, multiple
- entries of the colormap must be updated
- */
-
-#define AddElement(mask) { \
- pixel = red | green | blue; \
- for (i = 0; i < nresult; i++) \
- if (outdefs[i].pixel == pixel) \
- break; \
- if (i == nresult) \
- { \
- nresult++; \
- outdefs[i].pixel = pixel; \
- outdefs[i].flags = 0; \
- } \
- outdefs[i].flags |= (mask); \
- outdefs[i].red = pmap->red[red >> pVisual->offsetRed].co.local.red; \
- outdefs[i].green = pmap->green[green >> pVisual->offsetGreen].co.local.green; \
- outdefs[i].blue = pmap->blue[blue >> pVisual->offsetBlue].co.local.blue; \
-}
-
-int
-miExpandDirectColors(ColormapPtr pmap, int ndef, xColorItem *indefs,
- xColorItem *outdefs)
-{
- int red, green, blue;
- int maxred, maxgreen, maxblue;
- int stepred, stepgreen, stepblue;
- VisualPtr pVisual;
- int pixel;
- int nresult;
- int i;
-
- pVisual = pmap->pVisual;
-
- stepred = 1 << pVisual->offsetRed;
- stepgreen = 1 << pVisual->offsetGreen;
- stepblue = 1 << pVisual->offsetBlue;
- maxred = pVisual->redMask;
- maxgreen = pVisual->greenMask;
- maxblue = pVisual->blueMask;
- nresult = 0;
- for (;ndef--; indefs++)
- {
- if (indefs->flags & DoRed)
- {
- red = indefs->pixel & pVisual->redMask;
- for (green = 0; green <= maxgreen; green += stepgreen)
- {
- for (blue = 0; blue <= maxblue; blue += stepblue)
- {
- AddElement (DoRed)
- }
- }
- }
- if (indefs->flags & DoGreen)
- {
- green = indefs->pixel & pVisual->greenMask;
- for (red = 0; red <= maxred; red += stepred)
- {
- for (blue = 0; blue <= maxblue; blue += stepblue)
- {
- AddElement (DoGreen)
- }
- }
- }
- if (indefs->flags & DoBlue)
- {
- blue = indefs->pixel & pVisual->blueMask;
- for (red = 0; red <= maxred; red += stepred)
- {
- for (green = 0; green <= maxgreen; green += stepgreen)
- {
- AddElement (DoBlue)
- }
- }
- }
- }
- return nresult;
-}
-
-Bool
-miCreateDefColormap(ScreenPtr pScreen)
-{
-/*
- * In the following sources PC X server vendors may want to delete
- * "_not_tog" from "#ifdef WIN32_not_tog"
- */
-#ifdef WIN32_not_tog
- /*
- * these are the MS-Windows desktop colors, adjusted for X's 16-bit
- * color specifications.
- */
- static xColorItem citems[] = {
- { 0, 0, 0, 0, 0, 0 },
- { 1, 0x8000, 0, 0, 0, 0 },
- { 2, 0, 0x8000, 0, 0, 0 },
- { 3, 0x8000, 0x8000, 0, 0, 0 },
- { 4, 0, 0, 0x8000, 0, 0 },
- { 5, 0x8000, 0, 0x8000, 0, 0 },
- { 6, 0, 0x8000, 0x8000, 0, 0 },
- { 7, 0xc000, 0xc000, 0xc000, 0, 0 },
- { 8, 0xc000, 0xdc00, 0xc000, 0, 0 },
- { 9, 0xa600, 0xca00, 0xf000, 0, 0 },
- { 246, 0xff00, 0xfb00, 0xf000, 0, 0 },
- { 247, 0xa000, 0xa000, 0xa400, 0, 0 },
- { 248, 0x8000, 0x8000, 0x8000, 0, 0 },
- { 249, 0xff00, 0, 0, 0, 0 },
- { 250, 0, 0xff00, 0, 0, 0 },
- { 251, 0xff00, 0xff00, 0, 0, 0 },
- { 252, 0, 0, 0xff00, 0, 0 },
- { 253, 0xff00, 0, 0xff00, 0, 0 },
- { 254, 0, 0xff00, 0xff00, 0, 0 },
- { 255, 0xff00, 0xff00, 0xff00, 0, 0 }
- };
-#define NUM_DESKTOP_COLORS sizeof citems / sizeof citems[0]
- int i;
-#else
- unsigned short zero = 0, ones = 0xFFFF;
-#endif
- Pixel wp, bp;
- VisualPtr pVisual;
- ColormapPtr cmap;
- int alloctype;
-
- if (!dixRegisterPrivateKey(&micmapScrPrivateKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
-
- for (pVisual = pScreen->visuals;
- pVisual->vid != pScreen->rootVisual;
- pVisual++)
- ;
-
- if (pScreen->rootDepth == 1 || (pVisual->class & DynamicClass))
- alloctype = AllocNone;
- else
- alloctype = AllocAll;
-
- if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap,
- alloctype, 0) != Success)
- return FALSE;
-
- if (pScreen->rootDepth > 1) {
- wp = pScreen->whitePixel;
- bp = pScreen->blackPixel;
-#ifdef WIN32_not_tog
- for (i = 0; i < NUM_DESKTOP_COLORS; i++) {
- if (AllocColor (cmap,
- &citems[i].red, &citems[i].green, &citems[i].blue,
- &citems[i].pixel, 0) != Success)
- return FALSE;
- }
-#else
- if ((AllocColor(cmap, &ones, &ones, &ones, &wp, 0) !=
- Success) ||
- (AllocColor(cmap, &zero, &zero, &zero, &bp, 0) !=
- Success))
- return FALSE;
- pScreen->whitePixel = wp;
- pScreen->blackPixel = bp;
-#endif
- }
-
- (*pScreen->InstallColormap)(cmap);
- return TRUE;
-}
-
-/*
- * Default true color bitmasks, should be overridden by
- * driver
- */
-
-#define _RZ(d) ((d + 2) / 3)
-#define _RS(d) 0
-#define _RM(d) ((1 << _RZ(d)) - 1)
-#define _GZ(d) ((d - _RZ(d) + 1) / 2)
-#define _GS(d) _RZ(d)
-#define _GM(d) (((1 << _GZ(d)) - 1) << _GS(d))
-#define _BZ(d) (d - _RZ(d) - _GZ(d))
-#define _BS(d) (_RZ(d) + _GZ(d))
-#define _BM(d) (((1 << _BZ(d)) - 1) << _BS(d))
-#define _CE(d) (1 << _RZ(d))
-
-typedef struct _miVisuals {
- struct _miVisuals *next;
- int depth;
- int bitsPerRGB;
- int visuals;
- int count;
- int preferredCVC;
- Pixel redMask, greenMask, blueMask;
-} miVisualsRec, *miVisualsPtr;
-
-static int miVisualPriority[] = {
- PseudoColor, GrayScale, StaticColor, TrueColor, DirectColor, StaticGray
-};
-
-#define NUM_PRIORITY 6
-
-static miVisualsPtr miVisuals;
-
-void
-miClearVisualTypes(void)
-{
- miVisualsPtr v;
-
- while ((v = miVisuals)) {
- miVisuals = v->next;
- free(v);
- }
-}
-
-
-Bool
-miSetVisualTypesAndMasks(int depth, int visuals, int bitsPerRGB,
- int preferredCVC,
- Pixel redMask, Pixel greenMask, Pixel blueMask)
-{
- miVisualsPtr new, *prev, v;
- int count;
-
- new = malloc(sizeof *new);
- if (!new)
- return FALSE;
- if (!redMask || !greenMask || !blueMask)
- {
- redMask = _RM(depth);
- greenMask = _GM(depth);
- blueMask = _BM(depth);
- }
- new->next = 0;
- new->depth = depth;
- new->visuals = visuals;
- new->bitsPerRGB = bitsPerRGB;
- new->preferredCVC = preferredCVC;
- new->redMask = redMask;
- new->greenMask = greenMask;
- new->blueMask = blueMask;
- count = (visuals >> 1) & 033333333333;
- count = visuals - count - ((count >> 1) & 033333333333);
- count = (((count + (count >> 3)) & 030707070707) % 077); /* HAKMEM 169 */
- new->count = count;
- for (prev = &miVisuals; (v = *prev); prev = &v->next);
- *prev = new;
- return TRUE;
-}
-
-Bool
-miSetVisualTypes(int depth, int visuals, int bitsPerRGB, int preferredCVC)
-{
- return miSetVisualTypesAndMasks (depth, visuals, bitsPerRGB,
- preferredCVC, 0, 0, 0);
-}
-
-int
-miGetDefaultVisualMask(int depth)
-{
- if (depth > MAX_PSEUDO_DEPTH)
- return LARGE_VISUALS;
- else if (depth >= MIN_TRUE_DEPTH)
- return ALL_VISUALS;
- else if (depth == 1)
- return StaticGrayMask;
- else
- return SMALL_VISUALS;
-}
-
-static Bool
-miVisualTypesSet (int depth)
-{
- miVisualsPtr visuals;
-
- for (visuals = miVisuals; visuals; visuals = visuals->next)
- if (visuals->depth == depth)
- return TRUE;
- return FALSE;
-}
-
-Bool
-miSetPixmapDepths (void)
-{
- int d, f;
-
- /* Add any unlisted depths from the pixmap formats */
- for (f = 0; f < screenInfo.numPixmapFormats; f++)
- {
- d = screenInfo.formats[f].depth;
- if (!miVisualTypesSet (d))
- {
- if (!miSetVisualTypes (d, 0, 0, -1))
- return FALSE;
- }
- }
- return TRUE;
-}
-
-/*
- * Distance to least significant one bit
- */
-static int
-maskShift (Pixel p)
-{
- int s;
-
- if (!p) return 0;
- s = 0;
- while (!(p & 1))
- {
- s++;
- p >>= 1;
- }
- return s;
-}
-
-/*
- * Given a list of formats for a screen, create a list
- * of visuals and depths for the screen which corespond to
- * the set which can be used with this version of cfb.
- */
-
-Bool
-miInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp,
- int *ndepthp, int *rootDepthp, VisualID *defaultVisp,
- unsigned long sizes, int bitsPerRGB, int preferredVis)
-
-{
- int i, j = 0, k;
- VisualPtr visual;
- DepthPtr depth;
- VisualID *vid;
- int d, b;
- int f;
- int ndepth, nvisual;
- int nvtype;
- int vtype;
- miVisualsPtr visuals, nextVisuals;
- int *preferredCVCs, *prefp;
- int first_depth;
-
- /* none specified, we'll guess from pixmap formats */
- if (!miVisuals)
- {
- for (f = 0; f < screenInfo.numPixmapFormats; f++)
- {
- d = screenInfo.formats[f].depth;
- b = screenInfo.formats[f].bitsPerPixel;
- if (sizes & (1 << (b - 1)))
- vtype = miGetDefaultVisualMask(d);
- else
- vtype = 0;
- if (!miSetVisualTypes (d, vtype, bitsPerRGB, -1))
- return FALSE;
- }
- }
- nvisual = 0;
- ndepth = 0;
- for (visuals = miVisuals; visuals; visuals = nextVisuals)
- {
- nextVisuals = visuals->next;
- ndepth++;
- nvisual += visuals->count;
- }
- depth = malloc(ndepth * sizeof (DepthRec));
- visual = malloc(nvisual * sizeof (VisualRec));
- preferredCVCs = malloc(ndepth * sizeof(int));
- if (!depth || !visual || !preferredCVCs)
- {
- free(depth);
- free(visual);
- free(preferredCVCs);
- return FALSE;
- }
- *depthp = depth;
- *visualp = visual;
- *ndepthp = ndepth;
- *nvisualp = nvisual;
- prefp = preferredCVCs;
- for (visuals = miVisuals; visuals; visuals = nextVisuals)
- {
- nextVisuals = visuals->next;
- d = visuals->depth;
- vtype = visuals->visuals;
- nvtype = visuals->count;
- *prefp = visuals->preferredCVC;
- prefp++;
- vid = NULL;
- if (nvtype)
- {
- vid = malloc(nvtype * sizeof (VisualID));
- if (!vid) {
- free(depth);
- free(visual);
- free(preferredCVCs);
- return FALSE;
- }
- }
- depth->depth = d;
- depth->numVids = nvtype;
- depth->vids = vid;
- depth++;
- for (i = 0; i < NUM_PRIORITY; i++) {
- if (! (vtype & (1 << miVisualPriority[i])))
- continue;
- visual->class = miVisualPriority[i];
- visual->bitsPerRGBValue = visuals->bitsPerRGB;
- visual->ColormapEntries = 1 << d;
- visual->nplanes = d;
- visual->vid = *vid = FakeClientID (0);
- switch (visual->class) {
- case PseudoColor:
- case GrayScale:
- case StaticGray:
- visual->redMask = 0;
- visual->greenMask = 0;
- visual->blueMask = 0;
- visual->offsetRed = 0;
- visual->offsetGreen = 0;
- visual->offsetBlue = 0;
- break;
- case DirectColor:
- case TrueColor:
- visual->ColormapEntries = _CE(d);
- /* fall through */
- case StaticColor:
- visual->redMask = visuals->redMask;
- visual->greenMask = visuals->greenMask;
- visual->blueMask = visuals->blueMask;
- visual->offsetRed = maskShift (visuals->redMask);
- visual->offsetGreen = maskShift (visuals->greenMask);
- visual->offsetBlue = maskShift (visuals->blueMask);
- }
- vid++;
- visual++;
- }
- free(visuals);
- }
- miVisuals = NULL;
- visual = *visualp;
- depth = *depthp;
-
- /*
- * if we did not supplyied by a preferred visual class
- * check if there is a preferred class in one of the depth
- * structures - if there is, we want to start looking for the
- * default visual/depth from that depth.
- */
- first_depth = 0;
- if (preferredVis < 0 && defaultColorVisualClass < 0 ) {
- for (i = 0; i < ndepth; i++) {
- if (preferredCVCs[i] >= 0) {
- first_depth = i;
- break;
- }
- }
- }
-
- for (i = first_depth; i < ndepth; i++)
- {
- int prefColorVisualClass = -1;
-
- if (defaultColorVisualClass >= 0)
- prefColorVisualClass = defaultColorVisualClass;
- else if (preferredVis >= 0)
- prefColorVisualClass = preferredVis;
- else if (preferredCVCs[i] >= 0)
- prefColorVisualClass = preferredCVCs[i];
-
- if (*rootDepthp && *rootDepthp != depth[i].depth)
- continue;
-
- for (j = 0; j < depth[i].numVids; j++)
- {
- for (k = 0; k < nvisual; k++)
- if (visual[k].vid == depth[i].vids[j])
- break;
- if (k == nvisual)
- continue;
- if (prefColorVisualClass < 0 ||
- visual[k].class == prefColorVisualClass)
- break;
- }
- if (j != depth[i].numVids)
- break;
- }
- if (i == ndepth) {
- i = 0;
- j = 0;
- }
- *rootDepthp = depth[i].depth;
- *defaultVisp = depth[i].vids[j];
- free(preferredCVCs);
-
- return TRUE;
-}
+/*
+ * Copyright (c) 1987, Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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.
+ */
+
+/*
+ * This is based on cfbcmap.c. The functions here are useful independently
+ * of cfb, which is the reason for including them here. How "mi" these
+ * are may be debatable.
+ */
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "scrnintstr.h"
+#include "colormapst.h"
+#include "resource.h"
+#include "globals.h"
+#include "micmap.h"
+
+DevPrivateKeyRec micmapScrPrivateKeyRec;
+
+int
+miListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
+{
+ if (GetInstalledmiColormap(pScreen)) {
+ *pmaps = GetInstalledmiColormap(pScreen)->mid;
+ return 1;
+ }
+ return 0;
+}
+
+void
+miInstallColormap(ColormapPtr pmap)
+{
+ ColormapPtr oldpmap = GetInstalledmiColormap(pmap->pScreen);
+
+ if(pmap != oldpmap)
+ {
+ /* Uninstall pInstalledMap. No hardware changes required, just
+ * notify all interested parties. */
+ if(oldpmap != (ColormapPtr)None)
+ WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
+ /* Install pmap */
+ SetInstalledmiColormap(pmap->pScreen, pmap);
+ WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
+
+ }
+}
+
+void
+miUninstallColormap(ColormapPtr pmap)
+{
+ ColormapPtr curpmap = GetInstalledmiColormap(pmap->pScreen);
+
+ if(pmap == curpmap)
+ {
+ if (pmap->mid != pmap->pScreen->defColormap)
+ {
+ dixLookupResourceByType((pointer *)&curpmap,
+ pmap->pScreen->defColormap,
+ RT_COLORMAP, serverClient,
+ DixUseAccess);
+ (*pmap->pScreen->InstallColormap)(curpmap);
+ }
+ }
+}
+
+void
+miResolveColor(unsigned short *pred, unsigned short *pgreen,
+ unsigned short *pblue, VisualPtr pVisual)
+{
+ int shift = 16 - pVisual->bitsPerRGBValue;
+ unsigned lim = (1 << pVisual->bitsPerRGBValue) - 1;
+
+ if ((pVisual->class | DynamicClass) == GrayScale)
+ {
+ /* rescale to gray then rgb bits */
+ *pred = (30L * *pred + 59L * *pgreen + 11L * *pblue) / 100;
+ *pblue = *pgreen = *pred = ((*pred >> shift) * 65535) / lim;
+ }
+ else
+ {
+ /* rescale to rgb bits */
+ *pred = ((*pred >> shift) * 65535) / lim;
+ *pgreen = ((*pgreen >> shift) * 65535) / lim;
+ *pblue = ((*pblue >> shift) * 65535) / lim;
+ }
+}
+
+Bool
+miInitializeColormap(ColormapPtr pmap)
+{
+ unsigned i;
+ VisualPtr pVisual;
+ unsigned lim, maxent, shift;
+
+ pVisual = pmap->pVisual;
+ lim = (1 << pVisual->bitsPerRGBValue) - 1;
+ shift = 16 - pVisual->bitsPerRGBValue;
+ maxent = pVisual->ColormapEntries - 1;
+ if (pVisual->class == TrueColor)
+ {
+ unsigned limr, limg, limb;
+
+ limr = pVisual->redMask >> pVisual->offsetRed;
+ for(i = 0; i <= min(limr,maxent); i++)
+ {
+ /* rescale to [0..65535] then rgb bits */
+ pmap->red[i].co.local.red =
+ ((((i * 65535) / limr) >> shift) * 65535) / lim;
+ }
+ for(; i <= maxent; i++) pmap->red[i].co.local.red = 65535;
+ limg = pVisual->greenMask >> pVisual->offsetGreen;
+ for(i = 0; i <= min(limg,maxent); i++)
+ {
+ /* rescale to [0..65535] then rgb bits */
+ pmap->green[i].co.local.green =
+ ((((i * 65535) / limg) >> shift) * 65535) / lim;
+ }
+ for(; i <= maxent; i++) pmap->green[i].co.local.green = 65535;
+ limb = pVisual->blueMask >> pVisual->offsetBlue;
+ for(i = 0; i <= min(limb,maxent); i++)
+ {
+ /* rescale to [0..65535] then rgb bits */
+ pmap->blue[i].co.local.blue =
+ ((((i * 65535) / limb) >> shift) * 65535) / lim;
+ }
+ for(; i <= maxent; i++) pmap->blue[i].co.local.blue = 65535;
+ }
+ else if (pVisual->class == StaticColor)
+ {
+ unsigned limr, limg, limb;
+
+ limr = pVisual->redMask >> pVisual->offsetRed;
+ limg = pVisual->greenMask >> pVisual->offsetGreen;
+ limb = pVisual->blueMask >> pVisual->offsetBlue;
+ for(i = 0; i <= maxent; i++)
+ {
+ /* rescale to [0..65535] then rgb bits */
+ pmap->red[i].co.local.red =
+ ((((((i & pVisual->redMask) >> pVisual->offsetRed)
+ * 65535) / limr) >> shift) * 65535) / lim;
+ pmap->red[i].co.local.green =
+ ((((((i & pVisual->greenMask) >> pVisual->offsetGreen)
+ * 65535) / limg) >> shift) * 65535) / lim;
+ pmap->red[i].co.local.blue =
+ ((((((i & pVisual->blueMask) >> pVisual->offsetBlue)
+ * 65535) / limb) >> shift) * 65535) / lim;
+ }
+ }
+ else if (pVisual->class == StaticGray)
+ {
+ for(i = 0; i <= maxent; i++)
+ {
+ /* rescale to [0..65535] then rgb bits */
+ pmap->red[i].co.local.red = ((((i * 65535) / maxent) >> shift)
+ * 65535) / lim;
+ pmap->red[i].co.local.green = pmap->red[i].co.local.red;
+ pmap->red[i].co.local.blue = pmap->red[i].co.local.red;
+ }
+ }
+ return TRUE;
+}
+
+/* When simulating DirectColor on PseudoColor hardware, multiple
+ entries of the colormap must be updated
+ */
+
+#define AddElement(mask) { \
+ pixel = red | green | blue; \
+ for (i = 0; i < nresult; i++) \
+ if (outdefs[i].pixel == pixel) \
+ break; \
+ if (i == nresult) \
+ { \
+ nresult++; \
+ outdefs[i].pixel = pixel; \
+ outdefs[i].flags = 0; \
+ } \
+ outdefs[i].flags |= (mask); \
+ outdefs[i].red = pmap->red[red >> pVisual->offsetRed].co.local.red; \
+ outdefs[i].green = pmap->green[green >> pVisual->offsetGreen].co.local.green; \
+ outdefs[i].blue = pmap->blue[blue >> pVisual->offsetBlue].co.local.blue; \
+}
+
+int
+miExpandDirectColors(ColormapPtr pmap, int ndef, xColorItem *indefs,
+ xColorItem *outdefs)
+{
+ int red, green, blue;
+ int maxred, maxgreen, maxblue;
+ int stepred, stepgreen, stepblue;
+ VisualPtr pVisual;
+ int pixel;
+ int nresult;
+ int i;
+
+ pVisual = pmap->pVisual;
+
+ stepred = 1 << pVisual->offsetRed;
+ stepgreen = 1 << pVisual->offsetGreen;
+ stepblue = 1 << pVisual->offsetBlue;
+ maxred = pVisual->redMask;
+ maxgreen = pVisual->greenMask;
+ maxblue = pVisual->blueMask;
+ nresult = 0;
+ for (;ndef--; indefs++)
+ {
+ if (indefs->flags & DoRed)
+ {
+ red = indefs->pixel & pVisual->redMask;
+ for (green = 0; green <= maxgreen; green += stepgreen)
+ {
+ for (blue = 0; blue <= maxblue; blue += stepblue)
+ {
+ AddElement (DoRed)
+ }
+ }
+ }
+ if (indefs->flags & DoGreen)
+ {
+ green = indefs->pixel & pVisual->greenMask;
+ for (red = 0; red <= maxred; red += stepred)
+ {
+ for (blue = 0; blue <= maxblue; blue += stepblue)
+ {
+ AddElement (DoGreen)
+ }
+ }
+ }
+ if (indefs->flags & DoBlue)
+ {
+ blue = indefs->pixel & pVisual->blueMask;
+ for (red = 0; red <= maxred; red += stepred)
+ {
+ for (green = 0; green <= maxgreen; green += stepgreen)
+ {
+ AddElement (DoBlue)
+ }
+ }
+ }
+ }
+ return nresult;
+}
+
+Bool
+miCreateDefColormap(ScreenPtr pScreen)
+{
+/*
+ * In the following sources PC X server vendors may want to delete
+ * "_not_tog" from "#ifdef WIN32_not_tog"
+ */
+#ifdef WIN32_not_tog
+ /*
+ * these are the MS-Windows desktop colors, adjusted for X's 16-bit
+ * color specifications.
+ */
+ static xColorItem citems[] = {
+ { 0, 0, 0, 0, 0, 0 },
+ { 1, 0x8000, 0, 0, 0, 0 },
+ { 2, 0, 0x8000, 0, 0, 0 },
+ { 3, 0x8000, 0x8000, 0, 0, 0 },
+ { 4, 0, 0, 0x8000, 0, 0 },
+ { 5, 0x8000, 0, 0x8000, 0, 0 },
+ { 6, 0, 0x8000, 0x8000, 0, 0 },
+ { 7, 0xc000, 0xc000, 0xc000, 0, 0 },
+ { 8, 0xc000, 0xdc00, 0xc000, 0, 0 },
+ { 9, 0xa600, 0xca00, 0xf000, 0, 0 },
+ { 246, 0xff00, 0xfb00, 0xf000, 0, 0 },
+ { 247, 0xa000, 0xa000, 0xa400, 0, 0 },
+ { 248, 0x8000, 0x8000, 0x8000, 0, 0 },
+ { 249, 0xff00, 0, 0, 0, 0 },
+ { 250, 0, 0xff00, 0, 0, 0 },
+ { 251, 0xff00, 0xff00, 0, 0, 0 },
+ { 252, 0, 0, 0xff00, 0, 0 },
+ { 253, 0xff00, 0, 0xff00, 0, 0 },
+ { 254, 0, 0xff00, 0xff00, 0, 0 },
+ { 255, 0xff00, 0xff00, 0xff00, 0, 0 }
+ };
+#define NUM_DESKTOP_COLORS sizeof citems / sizeof citems[0]
+ int i;
+#else
+ unsigned short zero = 0, ones = 0xFFFF;
+#endif
+ Pixel wp, bp;
+ VisualPtr pVisual;
+ ColormapPtr cmap;
+ int alloctype;
+
+ if (!dixRegisterPrivateKey(&micmapScrPrivateKeyRec, PRIVATE_SCREEN, 0))
+ return FALSE;
+
+ for (pVisual = pScreen->visuals;
+ pVisual->vid != pScreen->rootVisual;
+ pVisual++)
+ ;
+
+ if (pScreen->rootDepth == 1 || (pVisual->class & DynamicClass))
+ alloctype = AllocNone;
+ else
+ alloctype = AllocAll;
+
+ if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap,
+ alloctype, 0) != Success)
+ return FALSE;
+
+ if (pScreen->rootDepth > 1) {
+ wp = pScreen->whitePixel;
+ bp = pScreen->blackPixel;
+#ifdef WIN32_not_tog
+ for (i = 0; i < NUM_DESKTOP_COLORS; i++) {
+ if (AllocColor (cmap,
+ &citems[i].red, &citems[i].green, &citems[i].blue,
+ &citems[i].pixel, 0) != Success)
+ return FALSE;
+ }
+#else
+ if ((AllocColor(cmap, &ones, &ones, &ones, &wp, 0) !=
+ Success) ||
+ (AllocColor(cmap, &zero, &zero, &zero, &bp, 0) !=
+ Success))
+ return FALSE;
+ pScreen->whitePixel = wp;
+ pScreen->blackPixel = bp;
+#endif
+ }
+
+ (*pScreen->InstallColormap)(cmap);
+ return TRUE;
+}
+
+/*
+ * Default true color bitmasks, should be overridden by
+ * driver
+ */
+
+#define _RZ(d) ((d + 2) / 3)
+#define _RS(d) 0
+#define _RM(d) ((1 << _RZ(d)) - 1)
+#define _GZ(d) ((d - _RZ(d) + 1) / 2)
+#define _GS(d) _RZ(d)
+#define _GM(d) (((1 << _GZ(d)) - 1) << _GS(d))
+#define _BZ(d) (d - _RZ(d) - _GZ(d))
+#define _BS(d) (_RZ(d) + _GZ(d))
+#define _BM(d) (((1 << _BZ(d)) - 1) << _BS(d))
+#define _CE(d) (1 << _RZ(d))
+
+typedef struct _miVisuals {
+ struct _miVisuals *next;
+ int depth;
+ int bitsPerRGB;
+ int visuals;
+ int count;
+ int preferredCVC;
+ Pixel redMask, greenMask, blueMask;
+} miVisualsRec, *miVisualsPtr;
+
+static int miVisualPriority[] = {
+ PseudoColor, GrayScale, StaticColor, TrueColor, DirectColor, StaticGray
+};
+
+#define NUM_PRIORITY 6
+
+static miVisualsPtr miVisuals;
+
+void
+miClearVisualTypes(void)
+{
+ miVisualsPtr v;
+
+ while ((v = miVisuals)) {
+ miVisuals = v->next;
+ free(v);
+ }
+}
+
+
+Bool
+miSetVisualTypesAndMasks(int depth, int visuals, int bitsPerRGB,
+ int preferredCVC,
+ Pixel redMask, Pixel greenMask, Pixel blueMask)
+{
+ miVisualsPtr new, *prev, v;
+ int count;
+
+ new = malloc(sizeof *new);
+ if (!new)
+ return FALSE;
+ if (!redMask || !greenMask || !blueMask)
+ {
+ redMask = _RM(depth);
+ greenMask = _GM(depth);
+ blueMask = _BM(depth);
+ }
+ new->next = 0;
+ new->depth = depth;
+ new->visuals = visuals;
+ new->bitsPerRGB = bitsPerRGB;
+ new->preferredCVC = preferredCVC;
+ new->redMask = redMask;
+ new->greenMask = greenMask;
+ new->blueMask = blueMask;
+ count = (visuals >> 1) & 033333333333;
+ count = visuals - count - ((count >> 1) & 033333333333);
+ count = (((count + (count >> 3)) & 030707070707) % 077); /* HAKMEM 169 */
+ new->count = count;
+ for (prev = &miVisuals; (v = *prev); prev = &v->next);
+ *prev = new;
+ return TRUE;
+}
+
+Bool
+miSetVisualTypes(int depth, int visuals, int bitsPerRGB, int preferredCVC)
+{
+ return miSetVisualTypesAndMasks (depth, visuals, bitsPerRGB,
+ preferredCVC, 0, 0, 0);
+}
+
+int
+miGetDefaultVisualMask(int depth)
+{
+ if (depth > MAX_PSEUDO_DEPTH)
+ return LARGE_VISUALS;
+ else if (depth >= MIN_TRUE_DEPTH)
+ return ALL_VISUALS;
+ else if (depth == 1)
+ return StaticGrayMask;
+ else
+ return SMALL_VISUALS;
+}
+
+static Bool
+miVisualTypesSet (int depth)
+{
+ miVisualsPtr visuals;
+
+ for (visuals = miVisuals; visuals; visuals = visuals->next)
+ if (visuals->depth == depth)
+ return TRUE;
+ return FALSE;
+}
+
+Bool
+miSetPixmapDepths (void)
+{
+ int d, f;
+
+ /* Add any unlisted depths from the pixmap formats */
+ for (f = 0; f < screenInfo.numPixmapFormats; f++)
+ {
+ d = screenInfo.formats[f].depth;
+ if (!miVisualTypesSet (d))
+ {
+ if (!miSetVisualTypes (d, 0, 0, -1))
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * Distance to least significant one bit
+ */
+static int
+maskShift (Pixel p)
+{
+ int s;
+
+ if (!p) return 0;
+ s = 0;
+ while (!(p & 1))
+ {
+ s++;
+ p >>= 1;
+ }
+ return s;
+}
+
+/*
+ * Given a list of formats for a screen, create a list
+ * of visuals and depths for the screen which corespond to
+ * the set which can be used with this version of cfb.
+ */
+
+Bool
+miInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp,
+ int *ndepthp, int *rootDepthp, VisualID *defaultVisp,
+ unsigned long sizes, int bitsPerRGB, int preferredVis)
+
+{
+ int i, j = 0, k;
+ VisualPtr visual;
+ DepthPtr depth;
+ VisualID *vid;
+ int d, b;
+ int f;
+ int ndepth, nvisual;
+ int nvtype;
+ int vtype;
+ miVisualsPtr visuals, nextVisuals;
+ int *preferredCVCs, *prefp;
+ int first_depth;
+
+ /* none specified, we'll guess from pixmap formats */
+ if (!miVisuals)
+ {
+ for (f = 0; f < screenInfo.numPixmapFormats; f++)
+ {
+ d = screenInfo.formats[f].depth;
+ b = screenInfo.formats[f].bitsPerPixel;
+ if (sizes & (1 << (b - 1)))
+ vtype = miGetDefaultVisualMask(d);
+ else
+ vtype = 0;
+ if (!miSetVisualTypes (d, vtype, bitsPerRGB, -1))
+ return FALSE;
+ }
+ }
+ nvisual = 0;
+ ndepth = 0;
+ for (visuals = miVisuals; visuals; visuals = nextVisuals)
+ {
+ nextVisuals = visuals->next;
+ ndepth++;
+ nvisual += visuals->count;
+ }
+ depth = malloc(ndepth * sizeof (DepthRec));
+ visual = malloc(nvisual * sizeof (VisualRec));
+ preferredCVCs = malloc(ndepth * sizeof(int));
+ if (!depth || !visual || !preferredCVCs)
+ {
+ free(depth);
+ free(visual);
+ free(preferredCVCs);
+ return FALSE;
+ }
+ *depthp = depth;
+ *visualp = visual;
+ *ndepthp = ndepth;
+ *nvisualp = nvisual;
+ prefp = preferredCVCs;
+ for (visuals = miVisuals; visuals; visuals = nextVisuals)
+ {
+ nextVisuals = visuals->next;
+ d = visuals->depth;
+ vtype = visuals->visuals;
+ nvtype = visuals->count;
+ *prefp = visuals->preferredCVC;
+ prefp++;
+ vid = NULL;
+ if (nvtype)
+ {
+ vid = malloc(nvtype * sizeof (VisualID));
+ if (!vid) {
+ free(depth);
+ free(visual);
+ free(preferredCVCs);
+ return FALSE;
+ }
+ }
+ depth->depth = d;
+ depth->numVids = nvtype;
+ depth->vids = vid;
+ depth++;
+ for (i = 0; i < NUM_PRIORITY; i++) {
+ if (! (vtype & (1 << miVisualPriority[i])))
+ continue;
+ visual->class = miVisualPriority[i];
+ visual->bitsPerRGBValue = visuals->bitsPerRGB;
+ visual->ColormapEntries = 1 << d;
+ visual->nplanes = d;
+ visual->vid = *vid = FakeClientID (0);
+ switch (visual->class) {
+ case PseudoColor:
+ case GrayScale:
+ case StaticGray:
+ visual->redMask = 0;
+ visual->greenMask = 0;
+ visual->blueMask = 0;
+ visual->offsetRed = 0;
+ visual->offsetGreen = 0;
+ visual->offsetBlue = 0;
+ break;
+ case DirectColor:
+ case TrueColor:
+ visual->ColormapEntries = _CE(d);
+ /* fall through */
+ case StaticColor:
+ visual->redMask = visuals->redMask;
+ visual->greenMask = visuals->greenMask;
+ visual->blueMask = visuals->blueMask;
+ visual->offsetRed = maskShift (visuals->redMask);
+ visual->offsetGreen = maskShift (visuals->greenMask);
+ visual->offsetBlue = maskShift (visuals->blueMask);
+ }
+ vid++;
+ visual++;
+ }
+ free(visuals);
+ }
+ miVisuals = NULL;
+ visual = *visualp;
+ depth = *depthp;
+
+ /*
+ * if we did not supplyied by a preferred visual class
+ * check if there is a preferred class in one of the depth
+ * structures - if there is, we want to start looking for the
+ * default visual/depth from that depth.
+ */
+ first_depth = 0;
+ if (preferredVis < 0 && defaultColorVisualClass < 0 ) {
+ for (i = 0; i < ndepth; i++) {
+ if (preferredCVCs[i] >= 0) {
+ first_depth = i;
+ break;
+ }
+ }
+ }
+
+ for (i = first_depth; i < ndepth; i++)
+ {
+ int prefColorVisualClass = -1;
+
+ if (defaultColorVisualClass >= 0)
+ prefColorVisualClass = defaultColorVisualClass;
+ else if (preferredVis >= 0)
+ prefColorVisualClass = preferredVis;
+ else if (preferredCVCs[i] >= 0)
+ prefColorVisualClass = preferredCVCs[i];
+
+ if (*rootDepthp && *rootDepthp != depth[i].depth)
+ continue;
+
+ for (j = 0; j < depth[i].numVids; j++)
+ {
+ for (k = 0; k < nvisual; k++)
+ if (visual[k].vid == depth[i].vids[j])
+ break;
+ if (k == nvisual)
+ continue;
+ if (prefColorVisualClass < 0 ||
+ visual[k].class == prefColorVisualClass)
+ break;
+ }
+ if (j != depth[i].numVids)
+ break;
+ }
+ if (i == ndepth) {
+ i = 0;
+ j = 0;
+ }
+ *rootDepthp = depth[i].depth;
+ *defaultVisp = depth[i].vids[j];
+ free(preferredCVCs);
+
+ return TRUE;
+}
diff --git a/xorg-server/mi/midispcur.c b/xorg-server/mi/midispcur.c
index aebf91d5d..32c5c9df6 100644
--- a/xorg-server/mi/midispcur.c
+++ b/xorg-server/mi/midispcur.c
@@ -1,584 +1,584 @@
-/*
- * midispcur.c
- *
- * machine independent cursor display routines
- */
-
-
-/*
-
-Copyright 1989, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-*/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-# include <X11/X.h>
-# include "misc.h"
-# include "input.h"
-# include "cursorstr.h"
-# include "windowstr.h"
-# include "regionstr.h"
-# include "dixstruct.h"
-# include "scrnintstr.h"
-# include "servermd.h"
-# include "mipointer.h"
-# include "misprite.h"
-# include "gcstruct.h"
-
-#ifdef ARGB_CURSOR
-# include "picturestr.h"
-#endif
-
-# include "inputstr.h"
-
-/* per-screen private data */
-static DevPrivateKeyRec miDCScreenKeyRec;
-#define miDCScreenKey (&miDCScreenKeyRec)
-static DevScreenPrivateKeyRec miDCCursorBitsKeyRec;
-#define miDCCursorBitsKey (&miDCCursorBitsKeyRec)
-static DevScreenPrivateKeyRec miDCDeviceKeyRec;
-#define miDCDeviceKey (&miDCDeviceKeyRec)
-
-static Bool miDCCloseScreen(int index, ScreenPtr pScreen);
-
-/* per device private data */
-typedef struct {
- GCPtr pSourceGC, pMaskGC;
- GCPtr pSaveGC, pRestoreGC;
- PixmapPtr pSave;
-#ifdef ARGB_CURSOR
- PicturePtr pRootPicture;
-#endif
-} miDCBufferRec, *miDCBufferPtr;
-
-#define miGetDCDevice(dev, screen) \
- ((DevHasCursor(dev)) ? \
- (miDCBufferPtr)dixLookupScreenPrivate(&dev->devPrivates, miDCDeviceKey, screen) : \
- (miDCBufferPtr)dixLookupScreenPrivate(&GetMaster(dev, MASTER_POINTER)->devPrivates, miDCDeviceKey, screen))
-
-/*
- * The core pointer buffer will point to the index of the virtual core pointer
- * in the pCursorBuffers array.
- */
-typedef struct {
- CloseScreenProcPtr CloseScreen;
-} miDCScreenRec, *miDCScreenPtr;
-
-#define miGetDCScreen(s) ((miDCScreenPtr)(dixLookupPrivate(&(s)->devPrivates, miDCScreenKey)))
-
-/* per-cursor per-screen private data */
-typedef struct {
- PixmapPtr sourceBits; /* source bits */
- PixmapPtr maskBits; /* mask bits */
-#ifdef ARGB_CURSOR
- PicturePtr pPicture;
-#endif
-} miDCCursorRec, *miDCCursorPtr;
-
-Bool
-miDCInitialize (ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
-{
- miDCScreenPtr pScreenPriv;
-
- if (!dixRegisterPrivateKey(&miDCScreenKeyRec, PRIVATE_SCREEN, 0) ||
- !dixRegisterScreenPrivateKey(&miDCCursorBitsKeyRec, pScreen, PRIVATE_CURSOR_BITS, 0) ||
- !dixRegisterScreenPrivateKey(&miDCDeviceKeyRec, pScreen, PRIVATE_DEVICE, 0))
- return FALSE;
-
- pScreenPriv = malloc(sizeof (miDCScreenRec));
- if (!pScreenPriv)
- return FALSE;
-
- pScreenPriv->CloseScreen = pScreen->CloseScreen;
- pScreen->CloseScreen = miDCCloseScreen;
-
- dixSetPrivate(&pScreen->devPrivates, miDCScreenKey, pScreenPriv);
-
- if (!miSpriteInitialize (pScreen, screenFuncs))
- {
- free((pointer) pScreenPriv);
- return FALSE;
- }
- return TRUE;
-}
-
-static Bool
-miDCCloseScreen (int index, ScreenPtr pScreen)
-{
- miDCScreenPtr pScreenPriv;
-
- pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
- miDCScreenKey);
- pScreen->CloseScreen = pScreenPriv->CloseScreen;
- free((pointer) pScreenPriv);
- return (*pScreen->CloseScreen) (index, pScreen);
-}
-
-Bool
-miDCRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
-{
- if (pCursor->bits->refcnt <= 1)
- dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, NULL);
- return TRUE;
-}
-
-#ifdef ARGB_CURSOR
-#define EnsurePicture(picture,draw,win) (picture || miDCMakePicture(&picture,draw,win))
-
-static VisualPtr
-miDCGetWindowVisual (WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- VisualID vid = wVisual (pWin);
- int i;
-
- for (i = 0; i < pScreen->numVisuals; i++)
- if (pScreen->visuals[i].vid == vid)
- return &pScreen->visuals[i];
- return 0;
-}
-
-static PicturePtr
-miDCMakePicture (PicturePtr *ppPicture, DrawablePtr pDraw, WindowPtr pWin)
-{
- ScreenPtr pScreen = pDraw->pScreen;
- VisualPtr pVisual;
- PictFormatPtr pFormat;
- XID subwindow_mode = IncludeInferiors;
- PicturePtr pPicture;
- int error;
-
- pVisual = miDCGetWindowVisual (pWin);
- if (!pVisual)
- return 0;
- pFormat = PictureMatchVisual (pScreen, pDraw->depth, pVisual);
- if (!pFormat)
- return 0;
- pPicture = CreatePicture (0, pDraw, pFormat,
- CPSubwindowMode, &subwindow_mode,
- serverClient, &error);
- *ppPicture = pPicture;
- return pPicture;
-}
-#endif
-
-static miDCCursorPtr
-miDCRealize (ScreenPtr pScreen, CursorPtr pCursor)
-{
- miDCCursorPtr pPriv;
- GCPtr pGC;
- ChangeGCVal gcvals;
-
- pPriv = malloc(sizeof (miDCCursorRec));
- if (!pPriv)
- return NULL;
-#ifdef ARGB_CURSOR
- if (pCursor->bits->argb)
- {
- PixmapPtr pPixmap;
- PictFormatPtr pFormat;
- int error;
-
- pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8);
- if (!pFormat)
- {
- free((pointer) pPriv);
- return NULL;
- }
-
- pPriv->sourceBits = 0;
- pPriv->maskBits = 0;
- pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
- pCursor->bits->height, 32,
- CREATE_PIXMAP_USAGE_SCRATCH);
- if (!pPixmap)
- {
- free((pointer) pPriv);
- return NULL;
- }
- pGC = GetScratchGC (32, pScreen);
- if (!pGC)
- {
- (*pScreen->DestroyPixmap) (pPixmap);
- free((pointer) pPriv);
- return NULL;
- }
- ValidateGC (&pPixmap->drawable, pGC);
- (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32,
- 0, 0, pCursor->bits->width,
- pCursor->bits->height,
- 0, ZPixmap, (char *) pCursor->bits->argb);
- FreeScratchGC (pGC);
- pPriv->pPicture = CreatePicture (0, &pPixmap->drawable,
- pFormat, 0, 0, serverClient, &error);
- (*pScreen->DestroyPixmap) (pPixmap);
- if (!pPriv->pPicture)
- {
- free((pointer) pPriv);
- return NULL;
- }
- dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, pPriv);
- return pPriv;
- }
- pPriv->pPicture = 0;
-#endif
- pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0);
- if (!pPriv->sourceBits)
- {
- free((pointer) pPriv);
- return NULL;
- }
- pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0);
- if (!pPriv->maskBits)
- {
- (*pScreen->DestroyPixmap) (pPriv->sourceBits);
- free((pointer) pPriv);
- return NULL;
- }
- dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, pPriv);
-
- /* create the two sets of bits, clipping as appropriate */
-
- pGC = GetScratchGC (1, pScreen);
- if (!pGC)
- {
- (void) miDCUnrealizeCursor (pScreen, pCursor);
- return NULL;
- }
-
- ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
- (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
- 0, 0, pCursor->bits->width, pCursor->bits->height,
- 0, XYPixmap, (char *)pCursor->bits->source);
- gcvals.val = GXand;
- ChangeGC (NullClient, pGC, GCFunction, &gcvals);
- ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
- (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
- 0, 0, pCursor->bits->width, pCursor->bits->height,
- 0, XYPixmap, (char *)pCursor->bits->mask);
-
- /* mask bits -- pCursor->mask & ~pCursor->source */
- gcvals.val = GXcopy;
- ChangeGC (NullClient, pGC, GCFunction, &gcvals);
- ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
- (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
- 0, 0, pCursor->bits->width, pCursor->bits->height,
- 0, XYPixmap, (char *)pCursor->bits->mask);
- gcvals.val = GXandInverted;
- ChangeGC (NullClient, pGC, GCFunction, &gcvals);
- ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
- (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
- 0, 0, pCursor->bits->width, pCursor->bits->height,
- 0, XYPixmap, (char *)pCursor->bits->source);
- FreeScratchGC (pGC);
- return pPriv;
-}
-
-Bool
-miDCUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
-{
- miDCCursorPtr pPriv;
-
- pPriv = (miDCCursorPtr)dixLookupScreenPrivate(&pCursor->bits->devPrivates,
- miDCCursorBitsKey, pScreen);
- if (pPriv && (pCursor->bits->refcnt <= 1))
- {
- if (pPriv->sourceBits)
- (*pScreen->DestroyPixmap) (pPriv->sourceBits);
- if (pPriv->maskBits)
- (*pScreen->DestroyPixmap) (pPriv->maskBits);
-#ifdef ARGB_CURSOR
- if (pPriv->pPicture)
- FreePicture (pPriv->pPicture, 0);
-#endif
- free((pointer) pPriv);
- dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, NULL);
- }
- return TRUE;
-}
-
-static void
-miDCPutBits (
- DrawablePtr pDrawable,
- miDCCursorPtr pPriv,
- GCPtr sourceGC,
- GCPtr maskGC,
- int x_org,
- int y_org,
- unsigned w,
- unsigned h,
- unsigned long source,
- unsigned long mask)
-{
- ChangeGCVal gcval;
- int x, y;
-
- if (sourceGC->fgPixel != source)
- {
- gcval.val = source;
- ChangeGC (NullClient, sourceGC, GCForeground, &gcval);
- }
- if (sourceGC->serialNumber != pDrawable->serialNumber)
- ValidateGC (pDrawable, sourceGC);
-
- if(sourceGC->miTranslate)
- {
- x = pDrawable->x + x_org;
- y = pDrawable->y + y_org;
- }
- else
- {
- x = x_org;
- y = y_org;
- }
-
- (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y);
- if (maskGC->fgPixel != mask)
- {
- gcval.val = mask;
- ChangeGC (NullClient, maskGC, GCForeground, &gcval);
- }
- if (maskGC->serialNumber != pDrawable->serialNumber)
- ValidateGC (pDrawable, maskGC);
-
- if(maskGC->miTranslate)
- {
- x = pDrawable->x + x_org;
- y = pDrawable->y + y_org;
- }
- else
- {
- x = x_org;
- y = y_org;
- }
-
- (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y);
-}
-
-static GCPtr
-miDCMakeGC(WindowPtr pWin)
-{
- GCPtr pGC;
- int status;
- XID gcvals[2];
-
- gcvals[0] = IncludeInferiors;
- gcvals[1] = FALSE;
- pGC = CreateGC((DrawablePtr)pWin,
- GCSubwindowMode|GCGraphicsExposures, gcvals, &status,
- (XID)0, serverClient);
- return pGC;
-}
-
-
-Bool
-miDCPutUpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
- int x, int y, unsigned long source, unsigned long mask)
-{
- miDCCursorPtr pPriv;
- miDCBufferPtr pBuffer;
- WindowPtr pWin;
-
- pPriv = (miDCCursorPtr)dixLookupScreenPrivate(&pCursor->bits->devPrivates,
- miDCCursorBitsKey, pScreen);
- if (!pPriv)
- {
- pPriv = miDCRealize(pScreen, pCursor);
- if (!pPriv)
- return FALSE;
- }
-
- pWin = pScreen->root;
- pBuffer = miGetDCDevice(pDev, pScreen);
-
-#ifdef ARGB_CURSOR
- if (pPriv->pPicture)
- {
- if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin))
- return FALSE;
- CompositePicture (PictOpOver,
- pPriv->pPicture,
- NULL,
- pBuffer->pRootPicture,
- 0, 0, 0, 0,
- x, y,
- pCursor->bits->width,
- pCursor->bits->height);
- }
- else
-#endif
- {
- miDCPutBits ((DrawablePtr)pWin, pPriv,
- pBuffer->pSourceGC, pBuffer->pMaskGC,
- x, y, pCursor->bits->width, pCursor->bits->height,
- source, mask);
- }
- return TRUE;
-}
-
-Bool
-miDCSaveUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y, int w, int h)
-{
- miDCBufferPtr pBuffer;
- PixmapPtr pSave;
- WindowPtr pWin;
- GCPtr pGC;
-
- pBuffer = miGetDCDevice(pDev, pScreen);
-
- pSave = pBuffer->pSave;
- pWin = pScreen->root;
- if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h)
- {
- if (pSave)
- (*pScreen->DestroyPixmap) (pSave);
- pBuffer->pSave = pSave =
- (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth, 0);
- if (!pSave)
- return FALSE;
- }
-
- pGC = pBuffer->pSaveGC;
- if (pSave->drawable.serialNumber != pGC->serialNumber)
- ValidateGC ((DrawablePtr) pSave, pGC);
- (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
- x, y, w, h, 0, 0);
- return TRUE;
-}
-
-Bool
-miDCRestoreUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y, int w, int h)
-{
- miDCBufferPtr pBuffer;
- PixmapPtr pSave;
- WindowPtr pWin;
- GCPtr pGC;
-
- pBuffer = miGetDCDevice(pDev, pScreen);
- pSave = pBuffer->pSave;
-
- pWin = pScreen->root;
- if (!pSave)
- return FALSE;
-
- pGC = pBuffer->pRestoreGC;
- if (pWin->drawable.serialNumber != pGC->serialNumber)
- ValidateGC ((DrawablePtr) pWin, pGC);
- (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
- 0, 0, w, h, x, y);
- return TRUE;
-}
-
-Bool
-miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- miDCBufferPtr pBuffer;
- WindowPtr pWin;
- int i;
-
- if (!DevHasCursor(pDev))
- return TRUE;
-
- for (i = 0; i < screenInfo.numScreens; i++)
- {
- pScreen = screenInfo.screens[i];
-
- pBuffer = calloc(1, sizeof(miDCBufferRec));
- if (!pBuffer)
- goto failure;
-
- dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen, pBuffer);
- pWin = pScreen->root;
-
- pBuffer->pSourceGC = miDCMakeGC(pWin);
- if (!pBuffer->pSourceGC)
- goto failure;
-
- pBuffer->pMaskGC = miDCMakeGC(pWin);
- if (!pBuffer->pMaskGC)
- goto failure;
-
- pBuffer->pSaveGC = miDCMakeGC(pWin);
- if (!pBuffer->pSaveGC)
- goto failure;
-
- pBuffer->pRestoreGC = miDCMakeGC(pWin);
- if (!pBuffer->pRestoreGC)
- goto failure;
-
-#ifdef ARGB_CURSOR
- pBuffer->pRootPicture = NULL;
-#endif
-
- /* (re)allocated lazily depending on the cursor size */
- pBuffer->pSave = NULL;
- }
-
- return TRUE;
-
-failure:
-
- miDCDeviceCleanup(pDev, pScreen);
-
- return FALSE;
-}
-
-void
-miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- miDCBufferPtr pBuffer;
- int i;
-
- if (DevHasCursor(pDev))
- {
- for (i = 0; i < screenInfo.numScreens; i++)
- {
- pScreen = screenInfo.screens[i];
-
- pBuffer = miGetDCDevice(pDev, pScreen);
-
- if (pBuffer)
- {
- if (pBuffer->pSourceGC) FreeGC(pBuffer->pSourceGC, (GContext) 0);
- if (pBuffer->pMaskGC) FreeGC(pBuffer->pMaskGC, (GContext) 0);
- if (pBuffer->pSaveGC) FreeGC(pBuffer->pSaveGC, (GContext) 0);
- if (pBuffer->pRestoreGC) FreeGC(pBuffer->pRestoreGC, (GContext) 0);
-
-#ifdef ARGB_CURSOR
- /* If a pRootPicture was allocated for a root window, it
- * is freed when that root window is destroyed, so don't
- * free it again here. */
-#endif
-
- if (pBuffer->pSave) (*pScreen->DestroyPixmap)(pBuffer->pSave);
-
- free(pBuffer);
- dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen, NULL);
- }
- }
- }
-}
+/*
+ * midispcur.c
+ *
+ * machine independent cursor display routines
+ */
+
+
+/*
+
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+# include <X11/X.h>
+# include "misc.h"
+# include "input.h"
+# include "cursorstr.h"
+# include "windowstr.h"
+# include "regionstr.h"
+# include "dixstruct.h"
+# include "scrnintstr.h"
+# include "servermd.h"
+# include "mipointer.h"
+# include "misprite.h"
+# include "gcstruct.h"
+
+#ifdef ARGB_CURSOR
+# include "picturestr.h"
+#endif
+
+# include "inputstr.h"
+
+/* per-screen private data */
+static DevPrivateKeyRec miDCScreenKeyRec;
+#define miDCScreenKey (&miDCScreenKeyRec)
+static DevScreenPrivateKeyRec miDCCursorBitsKeyRec;
+#define miDCCursorBitsKey (&miDCCursorBitsKeyRec)
+static DevScreenPrivateKeyRec miDCDeviceKeyRec;
+#define miDCDeviceKey (&miDCDeviceKeyRec)
+
+static Bool miDCCloseScreen(int index, ScreenPtr pScreen);
+
+/* per device private data */
+typedef struct {
+ GCPtr pSourceGC, pMaskGC;
+ GCPtr pSaveGC, pRestoreGC;
+ PixmapPtr pSave;
+#ifdef ARGB_CURSOR
+ PicturePtr pRootPicture;
+#endif
+} miDCBufferRec, *miDCBufferPtr;
+
+#define miGetDCDevice(dev, screen) \
+ ((DevHasCursor(dev)) ? \
+ (miDCBufferPtr)dixLookupScreenPrivate(&dev->devPrivates, miDCDeviceKey, screen) : \
+ (miDCBufferPtr)dixLookupScreenPrivate(&GetMaster(dev, MASTER_POINTER)->devPrivates, miDCDeviceKey, screen))
+
+/*
+ * The core pointer buffer will point to the index of the virtual core pointer
+ * in the pCursorBuffers array.
+ */
+typedef struct {
+ CloseScreenProcPtr CloseScreen;
+} miDCScreenRec, *miDCScreenPtr;
+
+#define miGetDCScreen(s) ((miDCScreenPtr)(dixLookupPrivate(&(s)->devPrivates, miDCScreenKey)))
+
+/* per-cursor per-screen private data */
+typedef struct {
+ PixmapPtr sourceBits; /* source bits */
+ PixmapPtr maskBits; /* mask bits */
+#ifdef ARGB_CURSOR
+ PicturePtr pPicture;
+#endif
+} miDCCursorRec, *miDCCursorPtr;
+
+Bool
+miDCInitialize (ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
+{
+ miDCScreenPtr pScreenPriv;
+
+ if (!dixRegisterPrivateKey(&miDCScreenKeyRec, PRIVATE_SCREEN, 0) ||
+ !dixRegisterScreenPrivateKey(&miDCCursorBitsKeyRec, pScreen, PRIVATE_CURSOR_BITS, 0) ||
+ !dixRegisterScreenPrivateKey(&miDCDeviceKeyRec, pScreen, PRIVATE_DEVICE, 0))
+ return FALSE;
+
+ pScreenPriv = malloc(sizeof (miDCScreenRec));
+ if (!pScreenPriv)
+ return FALSE;
+
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = miDCCloseScreen;
+
+ dixSetPrivate(&pScreen->devPrivates, miDCScreenKey, pScreenPriv);
+
+ if (!miSpriteInitialize (pScreen, screenFuncs))
+ {
+ free((pointer) pScreenPriv);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static Bool
+miDCCloseScreen (int index, ScreenPtr pScreen)
+{
+ miDCScreenPtr pScreenPriv;
+
+ pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ miDCScreenKey);
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ free((pointer) pScreenPriv);
+ return (*pScreen->CloseScreen) (index, pScreen);
+}
+
+Bool
+miDCRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ if (pCursor->bits->refcnt <= 1)
+ dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, NULL);
+ return TRUE;
+}
+
+#ifdef ARGB_CURSOR
+#define EnsurePicture(picture,draw,win) (picture || miDCMakePicture(&picture,draw,win))
+
+static VisualPtr
+miDCGetWindowVisual (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ VisualID vid = wVisual (pWin);
+ int i;
+
+ for (i = 0; i < pScreen->numVisuals; i++)
+ if (pScreen->visuals[i].vid == vid)
+ return &pScreen->visuals[i];
+ return 0;
+}
+
+static PicturePtr
+miDCMakePicture (PicturePtr *ppPicture, DrawablePtr pDraw, WindowPtr pWin)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ VisualPtr pVisual;
+ PictFormatPtr pFormat;
+ XID subwindow_mode = IncludeInferiors;
+ PicturePtr pPicture;
+ int error;
+
+ pVisual = miDCGetWindowVisual (pWin);
+ if (!pVisual)
+ return 0;
+ pFormat = PictureMatchVisual (pScreen, pDraw->depth, pVisual);
+ if (!pFormat)
+ return 0;
+ pPicture = CreatePicture (0, pDraw, pFormat,
+ CPSubwindowMode, &subwindow_mode,
+ serverClient, &error);
+ *ppPicture = pPicture;
+ return pPicture;
+}
+#endif
+
+static miDCCursorPtr
+miDCRealize (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ miDCCursorPtr pPriv;
+ GCPtr pGC;
+ ChangeGCVal gcvals;
+
+ pPriv = malloc(sizeof (miDCCursorRec));
+ if (!pPriv)
+ return NULL;
+#ifdef ARGB_CURSOR
+ if (pCursor->bits->argb)
+ {
+ PixmapPtr pPixmap;
+ PictFormatPtr pFormat;
+ int error;
+
+ pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8);
+ if (!pFormat)
+ {
+ free((pointer) pPriv);
+ return NULL;
+ }
+
+ pPriv->sourceBits = 0;
+ pPriv->maskBits = 0;
+ pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
+ pCursor->bits->height, 32,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pPixmap)
+ {
+ free((pointer) pPriv);
+ return NULL;
+ }
+ pGC = GetScratchGC (32, pScreen);
+ if (!pGC)
+ {
+ (*pScreen->DestroyPixmap) (pPixmap);
+ free((pointer) pPriv);
+ return NULL;
+ }
+ ValidateGC (&pPixmap->drawable, pGC);
+ (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32,
+ 0, 0, pCursor->bits->width,
+ pCursor->bits->height,
+ 0, ZPixmap, (char *) pCursor->bits->argb);
+ FreeScratchGC (pGC);
+ pPriv->pPicture = CreatePicture (0, &pPixmap->drawable,
+ pFormat, 0, 0, serverClient, &error);
+ (*pScreen->DestroyPixmap) (pPixmap);
+ if (!pPriv->pPicture)
+ {
+ free((pointer) pPriv);
+ return NULL;
+ }
+ dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, pPriv);
+ return pPriv;
+ }
+ pPriv->pPicture = 0;
+#endif
+ pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0);
+ if (!pPriv->sourceBits)
+ {
+ free((pointer) pPriv);
+ return NULL;
+ }
+ pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0);
+ if (!pPriv->maskBits)
+ {
+ (*pScreen->DestroyPixmap) (pPriv->sourceBits);
+ free((pointer) pPriv);
+ return NULL;
+ }
+ dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, pPriv);
+
+ /* create the two sets of bits, clipping as appropriate */
+
+ pGC = GetScratchGC (1, pScreen);
+ if (!pGC)
+ {
+ (void) miDCUnrealizeCursor (pScreen, pCursor);
+ return NULL;
+ }
+
+ ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
+ 0, 0, pCursor->bits->width, pCursor->bits->height,
+ 0, XYPixmap, (char *)pCursor->bits->source);
+ gcvals.val = GXand;
+ ChangeGC (NullClient, pGC, GCFunction, &gcvals);
+ ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
+ 0, 0, pCursor->bits->width, pCursor->bits->height,
+ 0, XYPixmap, (char *)pCursor->bits->mask);
+
+ /* mask bits -- pCursor->mask & ~pCursor->source */
+ gcvals.val = GXcopy;
+ ChangeGC (NullClient, pGC, GCFunction, &gcvals);
+ ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
+ 0, 0, pCursor->bits->width, pCursor->bits->height,
+ 0, XYPixmap, (char *)pCursor->bits->mask);
+ gcvals.val = GXandInverted;
+ ChangeGC (NullClient, pGC, GCFunction, &gcvals);
+ ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
+ 0, 0, pCursor->bits->width, pCursor->bits->height,
+ 0, XYPixmap, (char *)pCursor->bits->source);
+ FreeScratchGC (pGC);
+ return pPriv;
+}
+
+Bool
+miDCUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ miDCCursorPtr pPriv;
+
+ pPriv = (miDCCursorPtr)dixLookupScreenPrivate(&pCursor->bits->devPrivates,
+ miDCCursorBitsKey, pScreen);
+ if (pPriv && (pCursor->bits->refcnt <= 1))
+ {
+ if (pPriv->sourceBits)
+ (*pScreen->DestroyPixmap) (pPriv->sourceBits);
+ if (pPriv->maskBits)
+ (*pScreen->DestroyPixmap) (pPriv->maskBits);
+#ifdef ARGB_CURSOR
+ if (pPriv->pPicture)
+ FreePicture (pPriv->pPicture, 0);
+#endif
+ free((pointer) pPriv);
+ dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, NULL);
+ }
+ return TRUE;
+}
+
+static void
+miDCPutBits (
+ DrawablePtr pDrawable,
+ miDCCursorPtr pPriv,
+ GCPtr sourceGC,
+ GCPtr maskGC,
+ int x_org,
+ int y_org,
+ unsigned w,
+ unsigned h,
+ unsigned long source,
+ unsigned long mask)
+{
+ ChangeGCVal gcval;
+ int x, y;
+
+ if (sourceGC->fgPixel != source)
+ {
+ gcval.val = source;
+ ChangeGC (NullClient, sourceGC, GCForeground, &gcval);
+ }
+ if (sourceGC->serialNumber != pDrawable->serialNumber)
+ ValidateGC (pDrawable, sourceGC);
+
+ if(sourceGC->miTranslate)
+ {
+ x = pDrawable->x + x_org;
+ y = pDrawable->y + y_org;
+ }
+ else
+ {
+ x = x_org;
+ y = y_org;
+ }
+
+ (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y);
+ if (maskGC->fgPixel != mask)
+ {
+ gcval.val = mask;
+ ChangeGC (NullClient, maskGC, GCForeground, &gcval);
+ }
+ if (maskGC->serialNumber != pDrawable->serialNumber)
+ ValidateGC (pDrawable, maskGC);
+
+ if(maskGC->miTranslate)
+ {
+ x = pDrawable->x + x_org;
+ y = pDrawable->y + y_org;
+ }
+ else
+ {
+ x = x_org;
+ y = y_org;
+ }
+
+ (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y);
+}
+
+static GCPtr
+miDCMakeGC(WindowPtr pWin)
+{
+ GCPtr pGC;
+ int status;
+ XID gcvals[2];
+
+ gcvals[0] = IncludeInferiors;
+ gcvals[1] = FALSE;
+ pGC = CreateGC((DrawablePtr)pWin,
+ GCSubwindowMode|GCGraphicsExposures, gcvals, &status,
+ (XID)0, serverClient);
+ return pGC;
+}
+
+
+Bool
+miDCPutUpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
+ int x, int y, unsigned long source, unsigned long mask)
+{
+ miDCCursorPtr pPriv;
+ miDCBufferPtr pBuffer;
+ WindowPtr pWin;
+
+ pPriv = (miDCCursorPtr)dixLookupScreenPrivate(&pCursor->bits->devPrivates,
+ miDCCursorBitsKey, pScreen);
+ if (!pPriv)
+ {
+ pPriv = miDCRealize(pScreen, pCursor);
+ if (!pPriv)
+ return FALSE;
+ }
+
+ pWin = pScreen->root;
+ pBuffer = miGetDCDevice(pDev, pScreen);
+
+#ifdef ARGB_CURSOR
+ if (pPriv->pPicture)
+ {
+ if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin))
+ return FALSE;
+ CompositePicture (PictOpOver,
+ pPriv->pPicture,
+ NULL,
+ pBuffer->pRootPicture,
+ 0, 0, 0, 0,
+ x, y,
+ pCursor->bits->width,
+ pCursor->bits->height);
+ }
+ else
+#endif
+ {
+ miDCPutBits ((DrawablePtr)pWin, pPriv,
+ pBuffer->pSourceGC, pBuffer->pMaskGC,
+ x, y, pCursor->bits->width, pCursor->bits->height,
+ source, mask);
+ }
+ return TRUE;
+}
+
+Bool
+miDCSaveUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y, int w, int h)
+{
+ miDCBufferPtr pBuffer;
+ PixmapPtr pSave;
+ WindowPtr pWin;
+ GCPtr pGC;
+
+ pBuffer = miGetDCDevice(pDev, pScreen);
+
+ pSave = pBuffer->pSave;
+ pWin = pScreen->root;
+ if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h)
+ {
+ if (pSave)
+ (*pScreen->DestroyPixmap) (pSave);
+ pBuffer->pSave = pSave =
+ (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth, 0);
+ if (!pSave)
+ return FALSE;
+ }
+
+ pGC = pBuffer->pSaveGC;
+ if (pSave->drawable.serialNumber != pGC->serialNumber)
+ ValidateGC ((DrawablePtr) pSave, pGC);
+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
+ x, y, w, h, 0, 0);
+ return TRUE;
+}
+
+Bool
+miDCRestoreUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y, int w, int h)
+{
+ miDCBufferPtr pBuffer;
+ PixmapPtr pSave;
+ WindowPtr pWin;
+ GCPtr pGC;
+
+ pBuffer = miGetDCDevice(pDev, pScreen);
+ pSave = pBuffer->pSave;
+
+ pWin = pScreen->root;
+ if (!pSave)
+ return FALSE;
+
+ pGC = pBuffer->pRestoreGC;
+ if (pWin->drawable.serialNumber != pGC->serialNumber)
+ ValidateGC ((DrawablePtr) pWin, pGC);
+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
+ 0, 0, w, h, x, y);
+ return TRUE;
+}
+
+Bool
+miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ miDCBufferPtr pBuffer;
+ WindowPtr pWin;
+ int i;
+
+ if (!DevHasCursor(pDev))
+ return TRUE;
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pScreen = screenInfo.screens[i];
+
+ pBuffer = calloc(1, sizeof(miDCBufferRec));
+ if (!pBuffer)
+ goto failure;
+
+ dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen, pBuffer);
+ pWin = pScreen->root;
+
+ pBuffer->pSourceGC = miDCMakeGC(pWin);
+ if (!pBuffer->pSourceGC)
+ goto failure;
+
+ pBuffer->pMaskGC = miDCMakeGC(pWin);
+ if (!pBuffer->pMaskGC)
+ goto failure;
+
+ pBuffer->pSaveGC = miDCMakeGC(pWin);
+ if (!pBuffer->pSaveGC)
+ goto failure;
+
+ pBuffer->pRestoreGC = miDCMakeGC(pWin);
+ if (!pBuffer->pRestoreGC)
+ goto failure;
+
+#ifdef ARGB_CURSOR
+ pBuffer->pRootPicture = NULL;
+#endif
+
+ /* (re)allocated lazily depending on the cursor size */
+ pBuffer->pSave = NULL;
+ }
+
+ return TRUE;
+
+failure:
+
+ miDCDeviceCleanup(pDev, pScreen);
+
+ return FALSE;
+}
+
+void
+miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ miDCBufferPtr pBuffer;
+ int i;
+
+ if (DevHasCursor(pDev))
+ {
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pScreen = screenInfo.screens[i];
+
+ pBuffer = miGetDCDevice(pDev, pScreen);
+
+ if (pBuffer)
+ {
+ if (pBuffer->pSourceGC) FreeGC(pBuffer->pSourceGC, (GContext) 0);
+ if (pBuffer->pMaskGC) FreeGC(pBuffer->pMaskGC, (GContext) 0);
+ if (pBuffer->pSaveGC) FreeGC(pBuffer->pSaveGC, (GContext) 0);
+ if (pBuffer->pRestoreGC) FreeGC(pBuffer->pRestoreGC, (GContext) 0);
+
+#ifdef ARGB_CURSOR
+ /* If a pRootPicture was allocated for a root window, it
+ * is freed when that root window is destroyed, so don't
+ * free it again here. */
+#endif
+
+ if (pBuffer->pSave) (*pScreen->DestroyPixmap)(pBuffer->pSave);
+
+ free(pBuffer);
+ dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen, NULL);
+ }
+ }
+ }
+}
diff --git a/xorg-server/mi/mieq.c b/xorg-server/mi/mieq.c
index f71e327ec..34d2277da 100644
--- a/xorg-server/mi/mieq.c
+++ b/xorg-server/mi/mieq.c
@@ -1,469 +1,469 @@
-/*
- *
-Copyright 1990, 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.
- *
- * Author: Keith Packard, MIT X Consortium
- */
-
-/*
- * mieq.c
- *
- * Machine independent event queue
- *
- */
-
-#if HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-# include <X11/X.h>
-# include <X11/Xmd.h>
-# include <X11/Xproto.h>
-# include "misc.h"
-# include "windowstr.h"
-# include "pixmapstr.h"
-# include "inputstr.h"
-# include "inpututils.h"
-# include "mi.h"
-# include "mipointer.h"
-# include "scrnintstr.h"
-# include <X11/extensions/XI.h>
-# include <X11/extensions/XIproto.h>
-# include <X11/extensions/geproto.h>
-# include "extinit.h"
-# include "exglobals.h"
-# include "eventstr.h"
-
-#ifdef DPMSExtension
-# include "dpmsproc.h"
-# include <X11/extensions/dpmsconst.h>
-#endif
-
-#define QUEUE_SIZE 512
-
-#define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen
-#define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen
-
-typedef struct _Event {
- InternalEvent* events;
- ScreenPtr pScreen;
- DeviceIntPtr pDev; /* device this event _originated_ from */
-} EventRec, *EventPtr;
-
-typedef struct _EventQueue {
- HWEventQueueType head, tail; /* long for SetInputCheck */
- CARD32 lastEventTime; /* to avoid time running backwards */
- int lastMotion; /* device ID if last event motion? */
- EventRec events[QUEUE_SIZE]; /* static allocation for signals */
- mieqHandler handlers[128]; /* custom event handler */
-} EventQueueRec, *EventQueuePtr;
-
-static EventQueueRec miEventQueue;
-
-#ifdef XQUARTZ
-#include <pthread.h>
-static pthread_mutex_t miEventQueueMutex = PTHREAD_MUTEX_INITIALIZER;
-
-extern BOOL serverRunning;
-extern pthread_mutex_t serverRunningMutex;
-extern pthread_cond_t serverRunningCond;
-
-static inline void wait_for_server_init(void) {
- /* If the server hasn't finished initializing, wait for it... */
- if(!serverRunning) {
- pthread_mutex_lock(&serverRunningMutex);
- while(!serverRunning)
- pthread_cond_wait(&serverRunningCond, &serverRunningMutex);
- pthread_mutex_unlock(&serverRunningMutex);
- }
-}
-#endif
-
-Bool
-mieqInit(void)
-{
- int i;
-
- miEventQueue.head = miEventQueue.tail = 0;
- miEventQueue.lastEventTime = GetTimeInMillis ();
- miEventQueue.lastMotion = FALSE;
- for (i = 0; i < 128; i++)
- miEventQueue.handlers[i] = NULL;
- for (i = 0; i < QUEUE_SIZE; i++)
- {
- if (miEventQueue.events[i].events == NULL) {
- InternalEvent* evlist = InitEventList(1);
- if (!evlist)
- FatalError("Could not allocate event queue.\n");
- miEventQueue.events[i].events = evlist;
- }
- }
-
- SetInputCheck(&miEventQueue.head, &miEventQueue.tail);
- return TRUE;
-}
-
-void
-mieqFini(void)
-{
- int i;
- for (i = 0; i < QUEUE_SIZE; i++)
- {
- if (miEventQueue.events[i].events != NULL) {
- FreeEventList(miEventQueue.events[i].events, 1);
- miEventQueue.events[i].events = NULL;
- }
- }
-}
-
-/*
- * Must be reentrant with ProcessInputEvents. Assumption: mieqEnqueue
- * will never be interrupted. If this is called from both signal
- * handlers and regular code, make sure the signal is suspended when
- * called from regular code.
- */
-
-void
-mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
-{
- unsigned int oldtail = miEventQueue.tail;
- InternalEvent* evt;
- int isMotion = 0;
- int evlen;
- Time time;
-
-#ifdef XQUARTZ
- wait_for_server_init();
- pthread_mutex_lock(&miEventQueueMutex);
-#endif
-
- verify_internal_event(e);
-
- /* avoid merging events from different devices */
- if (e->any.type == ET_Motion)
- isMotion = pDev->id;
-
- if (isMotion && isMotion == miEventQueue.lastMotion &&
- oldtail != miEventQueue.head) {
- oldtail = (oldtail - 1) % QUEUE_SIZE;
- }
- else {
- static int stuck = 0;
- /* Toss events which come in late. Usually this means your server's
- * stuck in an infinite loop somewhere, but SIGIO is still getting
- * handled. */
- if (((oldtail + 1) % QUEUE_SIZE) == miEventQueue.head) {
- if (!stuck) {
- ErrorF("[mi] EQ overflowing. The server is probably stuck "
- "in an infinite loop.\n");
- xorg_backtrace();
- stuck = 1;
- }
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
- return;
- }
- stuck = 0;
- }
-
- evlen = e->any.length;
- evt = miEventQueue.events[oldtail].events;
- memcpy(evt, e, evlen);
-
- time = e->any.time;
- /* Make sure that event times don't go backwards - this
- * is "unnecessary", but very useful. */
- if (time < miEventQueue.lastEventTime &&
- miEventQueue.lastEventTime - time < 10000)
- e->any.time = miEventQueue.lastEventTime;
-
- miEventQueue.lastEventTime = evt->any.time;
- miEventQueue.events[oldtail].pScreen = pDev ? EnqueueScreen(pDev) : NULL;
- miEventQueue.events[oldtail].pDev = pDev;
-
- miEventQueue.lastMotion = isMotion;
- miEventQueue.tail = (oldtail + 1) % QUEUE_SIZE;
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
-}
-
-void
-mieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool fromDIX)
-{
-#ifdef XQUARTZ
- pthread_mutex_lock(&miEventQueueMutex);
-#endif
- EnqueueScreen(pDev) = pScreen;
- if (fromDIX)
- DequeueScreen(pDev) = pScreen;
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
-}
-
-void
-mieqSetHandler(int event, mieqHandler handler)
-{
-#ifdef XQUARTZ
- pthread_mutex_lock(&miEventQueueMutex);
-#endif
- if (handler && miEventQueue.handlers[event])
- ErrorF("[mi] mieq: warning: overriding existing handler %p with %p for "
- "event %d\n", miEventQueue.handlers[event], handler, event);
-
- miEventQueue.handlers[event] = handler;
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
-}
-
-/**
- * Change the device id of the given event to the given device's id.
- */
-static void
-ChangeDeviceID(DeviceIntPtr dev, InternalEvent* event)
-{
- switch(event->any.type)
- {
- case ET_Motion:
- case ET_KeyPress:
- case ET_KeyRelease:
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_ProximityIn:
- case ET_ProximityOut:
- case ET_Hierarchy:
- case ET_DeviceChanged:
- event->device_event.deviceid = dev->id;
- break;
-#if XFreeXDGA
- case ET_DGAEvent:
- break;
-#endif
- case ET_RawKeyPress:
- case ET_RawKeyRelease:
- case ET_RawButtonPress:
- case ET_RawButtonRelease:
- case ET_RawMotion:
- event->raw_event.deviceid = dev->id;
- break;
- default:
- ErrorF("[mi] Unknown event type (%d), cannot change id.\n",
- event->any.type);
- }
-}
-
-static void
-FixUpEventForMaster(DeviceIntPtr mdev, DeviceIntPtr sdev,
- InternalEvent* original, InternalEvent *master)
-{
- verify_internal_event(original);
- verify_internal_event(master);
- /* Ensure chained button mappings, i.e. that the detail field is the
- * value of the mapped button on the SD, not the physical button */
- if (original->any.type == ET_ButtonPress ||
- original->any.type == ET_ButtonRelease)
- {
- int btn = original->device_event.detail.button;
- if (!sdev->button)
- return; /* Should never happen */
-
- master->device_event.detail.button = sdev->button->map[btn];
- }
-}
-
-/**
- * Copy the given event into master.
- * @param sdev The slave device the original event comes from
- * @param original The event as it came from the EQ
- * @param copy The event after being copied
- * @return The master device or NULL if the device is a floating slave.
- */
-DeviceIntPtr
-CopyGetMasterEvent(DeviceIntPtr sdev,
- InternalEvent* original, InternalEvent *copy)
-{
- DeviceIntPtr mdev;
- int len = original->any.length;
- int type = original->any.type;
- int mtype; /* which master type? */
-
- verify_internal_event(original);
-
- /* ET_XQuartz has sdev == NULL */
- if (!sdev || IsMaster(sdev) || IsFloating(sdev))
- return NULL;
-
-#if XFreeXDGA
- if (type == ET_DGAEvent)
- type = original->dga_event.subtype;
-#endif
-
- switch(type)
- {
- case ET_KeyPress:
- case ET_KeyRelease:
- mtype = MASTER_KEYBOARD;
- break;
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_Motion:
- case ET_ProximityIn:
- case ET_ProximityOut:
- mtype = MASTER_POINTER;
- break;
- default:
- mtype = MASTER_ATTACHED;
- break;
- }
-
- mdev = GetMaster(sdev, mtype);
- memcpy(copy, original, len);
- ChangeDeviceID(mdev, copy);
- FixUpEventForMaster(mdev, sdev, original, copy);
-
- return mdev;
-}
-
-
-/**
- * Post the given @event through the device hierarchy, as appropriate.
- * Use this function if an event must be posted for a given device during the
- * usual event processing cycle.
- */
-void
-mieqProcessDeviceEvent(DeviceIntPtr dev,
- InternalEvent *event,
- ScreenPtr screen)
-{
- mieqHandler handler;
- int x = 0, y = 0;
- DeviceIntPtr master;
- InternalEvent mevent; /* master event */
-
- verify_internal_event(event);
-
- /* Custom event handler */
- handler = miEventQueue.handlers[event->any.type];
-
- switch (event->any.type) {
- /* Catch events that include valuator information and check if they
- * are changing the screen */
- case ET_Motion:
- case ET_KeyPress:
- case ET_KeyRelease:
- case ET_ButtonPress:
- case ET_ButtonRelease:
- if (dev && screen && dev->spriteInfo->sprite && screen != DequeueScreen(dev) && !handler) {
- DequeueScreen(dev) = screen;
- x = event->device_event.root_x;
- y = event->device_event.root_y;
- NewCurrentScreen (dev, DequeueScreen(dev), x, y);
- }
- break;
- default:
- break;
- }
- master = CopyGetMasterEvent(dev, event, &mevent);
-
- if (master)
- master->lastSlave = dev;
-
- /* If someone's registered a custom event handler, let them
- * steal it. */
- if (handler)
- {
- int screenNum = dev && DequeueScreen(dev) ? DequeueScreen(dev)->myNum : (screen ? screen->myNum : 0);
- handler(screenNum, event, dev);
- /* Check for the SD's master in case the device got detached
- * during event processing */
- if (master && !IsFloating(dev))
- handler(screenNum, &mevent, master);
- } else
- {
- /* process slave first, then master */
- dev->public.processInputProc(event, dev);
-
- /* Check for the SD's master in case the device got detached
- * during event processing */
- if (master && !IsFloating(dev))
- master->public.processInputProc(&mevent, master);
- }
-}
-
-/* Call this from ProcessInputEvents(). */
-void
-mieqProcessInputEvents(void)
-{
- EventRec *e = NULL;
- ScreenPtr screen;
- static InternalEvent event;
- DeviceIntPtr dev = NULL,
- master = NULL;
-
-#ifdef XQUARTZ
- pthread_mutex_lock(&miEventQueueMutex);
-#endif
-
- while (miEventQueue.head != miEventQueue.tail) {
- e = &miEventQueue.events[miEventQueue.head];
-
- event = *e->events;
- dev = e->pDev;
- screen = e->pScreen;
-
- miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;
-
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
-
- master = (dev) ? GetMaster(dev, MASTER_ATTACHED) : NULL;
-
- if (screenIsSaved == SCREEN_SAVER_ON)
- dixSaveScreens (serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
-#ifdef DPMSExtension
- else if (DPMSPowerLevel != DPMSModeOn)
- SetScreenSaverTimer();
-
- if (DPMSPowerLevel != DPMSModeOn)
- DPMSSet(serverClient, DPMSModeOn);
-#endif
-
- mieqProcessDeviceEvent(dev, &event, screen);
-
- /* Update the sprite now. Next event may be from different device. */
- if (event.any.type == ET_Motion && master)
- miPointerUpdateSprite(dev);
-
-#ifdef XQUARTZ
- pthread_mutex_lock(&miEventQueueMutex);
-#endif
- }
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
-}
-
+/*
+ *
+Copyright 1990, 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.
+ *
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+/*
+ * mieq.c
+ *
+ * Machine independent event queue
+ *
+ */
+
+#if HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+# include <X11/X.h>
+# include <X11/Xmd.h>
+# include <X11/Xproto.h>
+# include "misc.h"
+# include "windowstr.h"
+# include "pixmapstr.h"
+# include "inputstr.h"
+# include "inpututils.h"
+# include "mi.h"
+# include "mipointer.h"
+# include "scrnintstr.h"
+# include <X11/extensions/XI.h>
+# include <X11/extensions/XIproto.h>
+# include <X11/extensions/geproto.h>
+# include "extinit.h"
+# include "exglobals.h"
+# include "eventstr.h"
+
+#ifdef DPMSExtension
+# include "dpmsproc.h"
+# include <X11/extensions/dpmsconst.h>
+#endif
+
+#define QUEUE_SIZE 512
+
+#define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen
+#define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen
+
+typedef struct _Event {
+ InternalEvent* events;
+ ScreenPtr pScreen;
+ DeviceIntPtr pDev; /* device this event _originated_ from */
+} EventRec, *EventPtr;
+
+typedef struct _EventQueue {
+ HWEventQueueType head, tail; /* long for SetInputCheck */
+ CARD32 lastEventTime; /* to avoid time running backwards */
+ int lastMotion; /* device ID if last event motion? */
+ EventRec events[QUEUE_SIZE]; /* static allocation for signals */
+ mieqHandler handlers[128]; /* custom event handler */
+} EventQueueRec, *EventQueuePtr;
+
+static EventQueueRec miEventQueue;
+
+#ifdef XQUARTZ
+#include <pthread.h>
+static pthread_mutex_t miEventQueueMutex = PTHREAD_MUTEX_INITIALIZER;
+
+extern BOOL serverRunning;
+extern pthread_mutex_t serverRunningMutex;
+extern pthread_cond_t serverRunningCond;
+
+static inline void wait_for_server_init(void) {
+ /* If the server hasn't finished initializing, wait for it... */
+ if(!serverRunning) {
+ pthread_mutex_lock(&serverRunningMutex);
+ while(!serverRunning)
+ pthread_cond_wait(&serverRunningCond, &serverRunningMutex);
+ pthread_mutex_unlock(&serverRunningMutex);
+ }
+}
+#endif
+
+Bool
+mieqInit(void)
+{
+ int i;
+
+ miEventQueue.head = miEventQueue.tail = 0;
+ miEventQueue.lastEventTime = GetTimeInMillis ();
+ miEventQueue.lastMotion = FALSE;
+ for (i = 0; i < 128; i++)
+ miEventQueue.handlers[i] = NULL;
+ for (i = 0; i < QUEUE_SIZE; i++)
+ {
+ if (miEventQueue.events[i].events == NULL) {
+ InternalEvent* evlist = InitEventList(1);
+ if (!evlist)
+ FatalError("Could not allocate event queue.\n");
+ miEventQueue.events[i].events = evlist;
+ }
+ }
+
+ SetInputCheck(&miEventQueue.head, &miEventQueue.tail);
+ return TRUE;
+}
+
+void
+mieqFini(void)
+{
+ int i;
+ for (i = 0; i < QUEUE_SIZE; i++)
+ {
+ if (miEventQueue.events[i].events != NULL) {
+ FreeEventList(miEventQueue.events[i].events, 1);
+ miEventQueue.events[i].events = NULL;
+ }
+ }
+}
+
+/*
+ * Must be reentrant with ProcessInputEvents. Assumption: mieqEnqueue
+ * will never be interrupted. If this is called from both signal
+ * handlers and regular code, make sure the signal is suspended when
+ * called from regular code.
+ */
+
+void
+mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
+{
+ unsigned int oldtail = miEventQueue.tail;
+ InternalEvent* evt;
+ int isMotion = 0;
+ int evlen;
+ Time time;
+
+#ifdef XQUARTZ
+ wait_for_server_init();
+ pthread_mutex_lock(&miEventQueueMutex);
+#endif
+
+ verify_internal_event(e);
+
+ /* avoid merging events from different devices */
+ if (e->any.type == ET_Motion)
+ isMotion = pDev->id;
+
+ if (isMotion && isMotion == miEventQueue.lastMotion &&
+ oldtail != miEventQueue.head) {
+ oldtail = (oldtail - 1) % QUEUE_SIZE;
+ }
+ else {
+ static int stuck = 0;
+ /* Toss events which come in late. Usually this means your server's
+ * stuck in an infinite loop somewhere, but SIGIO is still getting
+ * handled. */
+ if (((oldtail + 1) % QUEUE_SIZE) == miEventQueue.head) {
+ if (!stuck) {
+ ErrorF("[mi] EQ overflowing. The server is probably stuck "
+ "in an infinite loop.\n");
+ xorg_backtrace();
+ stuck = 1;
+ }
+#ifdef XQUARTZ
+ pthread_mutex_unlock(&miEventQueueMutex);
+#endif
+ return;
+ }
+ stuck = 0;
+ }
+
+ evlen = e->any.length;
+ evt = miEventQueue.events[oldtail].events;
+ memcpy(evt, e, evlen);
+
+ time = e->any.time;
+ /* Make sure that event times don't go backwards - this
+ * is "unnecessary", but very useful. */
+ if (time < miEventQueue.lastEventTime &&
+ miEventQueue.lastEventTime - time < 10000)
+ e->any.time = miEventQueue.lastEventTime;
+
+ miEventQueue.lastEventTime = evt->any.time;
+ miEventQueue.events[oldtail].pScreen = pDev ? EnqueueScreen(pDev) : NULL;
+ miEventQueue.events[oldtail].pDev = pDev;
+
+ miEventQueue.lastMotion = isMotion;
+ miEventQueue.tail = (oldtail + 1) % QUEUE_SIZE;
+#ifdef XQUARTZ
+ pthread_mutex_unlock(&miEventQueueMutex);
+#endif
+}
+
+void
+mieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool fromDIX)
+{
+#ifdef XQUARTZ
+ pthread_mutex_lock(&miEventQueueMutex);
+#endif
+ EnqueueScreen(pDev) = pScreen;
+ if (fromDIX)
+ DequeueScreen(pDev) = pScreen;
+#ifdef XQUARTZ
+ pthread_mutex_unlock(&miEventQueueMutex);
+#endif
+}
+
+void
+mieqSetHandler(int event, mieqHandler handler)
+{
+#ifdef XQUARTZ
+ pthread_mutex_lock(&miEventQueueMutex);
+#endif
+ if (handler && miEventQueue.handlers[event])
+ ErrorF("[mi] mieq: warning: overriding existing handler %p with %p for "
+ "event %d\n", miEventQueue.handlers[event], handler, event);
+
+ miEventQueue.handlers[event] = handler;
+#ifdef XQUARTZ
+ pthread_mutex_unlock(&miEventQueueMutex);
+#endif
+}
+
+/**
+ * Change the device id of the given event to the given device's id.
+ */
+static void
+ChangeDeviceID(DeviceIntPtr dev, InternalEvent* event)
+{
+ switch(event->any.type)
+ {
+ case ET_Motion:
+ case ET_KeyPress:
+ case ET_KeyRelease:
+ case ET_ButtonPress:
+ case ET_ButtonRelease:
+ case ET_ProximityIn:
+ case ET_ProximityOut:
+ case ET_Hierarchy:
+ case ET_DeviceChanged:
+ event->device_event.deviceid = dev->id;
+ break;
+#if XFreeXDGA
+ case ET_DGAEvent:
+ break;
+#endif
+ case ET_RawKeyPress:
+ case ET_RawKeyRelease:
+ case ET_RawButtonPress:
+ case ET_RawButtonRelease:
+ case ET_RawMotion:
+ event->raw_event.deviceid = dev->id;
+ break;
+ default:
+ ErrorF("[mi] Unknown event type (%d), cannot change id.\n",
+ event->any.type);
+ }
+}
+
+static void
+FixUpEventForMaster(DeviceIntPtr mdev, DeviceIntPtr sdev,
+ InternalEvent* original, InternalEvent *master)
+{
+ verify_internal_event(original);
+ verify_internal_event(master);
+ /* Ensure chained button mappings, i.e. that the detail field is the
+ * value of the mapped button on the SD, not the physical button */
+ if (original->any.type == ET_ButtonPress ||
+ original->any.type == ET_ButtonRelease)
+ {
+ int btn = original->device_event.detail.button;
+ if (!sdev->button)
+ return; /* Should never happen */
+
+ master->device_event.detail.button = sdev->button->map[btn];
+ }
+}
+
+/**
+ * Copy the given event into master.
+ * @param sdev The slave device the original event comes from
+ * @param original The event as it came from the EQ
+ * @param copy The event after being copied
+ * @return The master device or NULL if the device is a floating slave.
+ */
+DeviceIntPtr
+CopyGetMasterEvent(DeviceIntPtr sdev,
+ InternalEvent* original, InternalEvent *copy)
+{
+ DeviceIntPtr mdev;
+ int len = original->any.length;
+ int type = original->any.type;
+ int mtype; /* which master type? */
+
+ verify_internal_event(original);
+
+ /* ET_XQuartz has sdev == NULL */
+ if (!sdev || IsMaster(sdev) || IsFloating(sdev))
+ return NULL;
+
+#if XFreeXDGA
+ if (type == ET_DGAEvent)
+ type = original->dga_event.subtype;
+#endif
+
+ switch(type)
+ {
+ case ET_KeyPress:
+ case ET_KeyRelease:
+ mtype = MASTER_KEYBOARD;
+ break;
+ case ET_ButtonPress:
+ case ET_ButtonRelease:
+ case ET_Motion:
+ case ET_ProximityIn:
+ case ET_ProximityOut:
+ mtype = MASTER_POINTER;
+ break;
+ default:
+ mtype = MASTER_ATTACHED;
+ break;
+ }
+
+ mdev = GetMaster(sdev, mtype);
+ memcpy(copy, original, len);
+ ChangeDeviceID(mdev, copy);
+ FixUpEventForMaster(mdev, sdev, original, copy);
+
+ return mdev;
+}
+
+
+/**
+ * Post the given @event through the device hierarchy, as appropriate.
+ * Use this function if an event must be posted for a given device during the
+ * usual event processing cycle.
+ */
+void
+mieqProcessDeviceEvent(DeviceIntPtr dev,
+ InternalEvent *event,
+ ScreenPtr screen)
+{
+ mieqHandler handler;
+ int x = 0, y = 0;
+ DeviceIntPtr master;
+ InternalEvent mevent; /* master event */
+
+ verify_internal_event(event);
+
+ /* Custom event handler */
+ handler = miEventQueue.handlers[event->any.type];
+
+ switch (event->any.type) {
+ /* Catch events that include valuator information and check if they
+ * are changing the screen */
+ case ET_Motion:
+ case ET_KeyPress:
+ case ET_KeyRelease:
+ case ET_ButtonPress:
+ case ET_ButtonRelease:
+ if (dev && screen && dev->spriteInfo->sprite && screen != DequeueScreen(dev) && !handler) {
+ DequeueScreen(dev) = screen;
+ x = event->device_event.root_x;
+ y = event->device_event.root_y;
+ NewCurrentScreen (dev, DequeueScreen(dev), x, y);
+ }
+ break;
+ default:
+ break;
+ }
+ master = CopyGetMasterEvent(dev, event, &mevent);
+
+ if (master)
+ master->lastSlave = dev;
+
+ /* If someone's registered a custom event handler, let them
+ * steal it. */
+ if (handler)
+ {
+ int screenNum = dev && DequeueScreen(dev) ? DequeueScreen(dev)->myNum : (screen ? screen->myNum : 0);
+ handler(screenNum, event, dev);
+ /* Check for the SD's master in case the device got detached
+ * during event processing */
+ if (master && !IsFloating(dev))
+ handler(screenNum, &mevent, master);
+ } else
+ {
+ /* process slave first, then master */
+ dev->public.processInputProc(event, dev);
+
+ /* Check for the SD's master in case the device got detached
+ * during event processing */
+ if (master && !IsFloating(dev))
+ master->public.processInputProc(&mevent, master);
+ }
+}
+
+/* Call this from ProcessInputEvents(). */
+void
+mieqProcessInputEvents(void)
+{
+ EventRec *e = NULL;
+ ScreenPtr screen;
+ static InternalEvent event;
+ DeviceIntPtr dev = NULL,
+ master = NULL;
+
+#ifdef XQUARTZ
+ pthread_mutex_lock(&miEventQueueMutex);
+#endif
+
+ while (miEventQueue.head != miEventQueue.tail) {
+ e = &miEventQueue.events[miEventQueue.head];
+
+ event = *e->events;
+ dev = e->pDev;
+ screen = e->pScreen;
+
+ miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;
+
+#ifdef XQUARTZ
+ pthread_mutex_unlock(&miEventQueueMutex);
+#endif
+
+ master = (dev) ? GetMaster(dev, MASTER_ATTACHED) : NULL;
+
+ if (screenIsSaved == SCREEN_SAVER_ON)
+ dixSaveScreens (serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
+#ifdef DPMSExtension
+ else if (DPMSPowerLevel != DPMSModeOn)
+ SetScreenSaverTimer();
+
+ if (DPMSPowerLevel != DPMSModeOn)
+ DPMSSet(serverClient, DPMSModeOn);
+#endif
+
+ mieqProcessDeviceEvent(dev, &event, screen);
+
+ /* Update the sprite now. Next event may be from different device. */
+ if (event.any.type == ET_Motion && master)
+ miPointerUpdateSprite(dev);
+
+#ifdef XQUARTZ
+ pthread_mutex_lock(&miEventQueueMutex);
+#endif
+ }
+#ifdef XQUARTZ
+ pthread_mutex_unlock(&miEventQueueMutex);
+#endif
+}
+
diff --git a/xorg-server/mi/mipointer.c b/xorg-server/mi/mipointer.c
index 135b296fb..7680ca19b 100644
--- a/xorg-server/mi/mipointer.c
+++ b/xorg-server/mi/mipointer.c
@@ -1,698 +1,698 @@
-/*
-
-Copyright 1989, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-*/
-
-/**
- * @file
- * This file contains functions to move the pointer on the screen and/or
- * restrict its movement. These functions are divided into two sets:
- * Screen-specific functions that are used as function pointers from other
- * parts of the server (and end up heavily wrapped by e.g. animcur and
- * xfixes):
- * miPointerConstrainCursor
- * miPointerCursorLimits
- * miPointerDisplayCursor
- * miPointerRealizeCursor
- * miPointerUnrealizeCursor
- * miPointerSetCursorPosition
- * miRecolorCursor
- * miPointerDeviceInitialize
- * miPointerDeviceCleanup
- * If wrapped, these are the last element in the wrapping chain. They may
- * call into sprite-specific code through further function pointers though.
- *
- * The second type of functions are those that are directly called by the
- * DIX, DDX and some drivers.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-# include <X11/X.h>
-# include <X11/Xmd.h>
-# include <X11/Xproto.h>
-# include "misc.h"
-# include "windowstr.h"
-# include "pixmapstr.h"
-# include "mi.h"
-# include "scrnintstr.h"
-# include "mipointrst.h"
-# include "cursorstr.h"
-# include "dixstruct.h"
-# include "inputstr.h"
-# include "inpututils.h"
-# include "eventstr.h"
-
-DevPrivateKeyRec miPointerScreenKeyRec;
-
-#define GetScreenPrivate(s) ((miPointerScreenPtr) \
- dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey))
-#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s)
-
-DevPrivateKeyRec miPointerPrivKeyRec;
-
-#define MIPOINTER(dev) \
- (IsFloating(dev) ? \
- (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
- (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey))
-
-static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor);
-static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor);
-static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor);
-static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- BoxPtr pBox);
-static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor, BoxPtr pHotBox,
- BoxPtr pTopLeftBox);
-static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y,
- Bool generateEvent);
-static Bool miPointerCloseScreen(int index, ScreenPtr pScreen);
-static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y);
-static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
-static void miPointerDeviceCleanup(DeviceIntPtr pDev,
- ScreenPtr pScreen);
-static void miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y);
-
-static InternalEvent* events; /* for WarpPointer MotionNotifies */
-
-Bool
-miPointerInitialize (ScreenPtr pScreen,
- miPointerSpriteFuncPtr spriteFuncs,
- miPointerScreenFuncPtr screenFuncs,
- Bool waitForUpdate)
-{
- miPointerScreenPtr pScreenPriv;
-
- if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
-
- if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0))
- return FALSE;
-
- pScreenPriv = malloc(sizeof (miPointerScreenRec));
- if (!pScreenPriv)
- return FALSE;
- pScreenPriv->spriteFuncs = spriteFuncs;
- pScreenPriv->screenFuncs = screenFuncs;
- /*
- * check for uninitialized methods
- */
- if (!screenFuncs->EnqueueEvent)
- screenFuncs->EnqueueEvent = mieqEnqueue;
- if (!screenFuncs->NewEventScreen)
- screenFuncs->NewEventScreen = mieqSwitchScreen;
- pScreenPriv->waitForUpdate = waitForUpdate;
- pScreenPriv->showTransparent = FALSE;
- pScreenPriv->CloseScreen = pScreen->CloseScreen;
- pScreen->CloseScreen = miPointerCloseScreen;
- dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv);
- /*
- * set up screen cursor method table
- */
- pScreen->ConstrainCursor = miPointerConstrainCursor;
- pScreen->CursorLimits = miPointerCursorLimits;
- pScreen->DisplayCursor = miPointerDisplayCursor;
- pScreen->RealizeCursor = miPointerRealizeCursor;
- pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
- pScreen->SetCursorPosition = miPointerSetCursorPosition;
- pScreen->RecolorCursor = miRecolorCursor;
- pScreen->DeviceCursorInitialize = miPointerDeviceInitialize;
- pScreen->DeviceCursorCleanup = miPointerDeviceCleanup;
-
- events = NULL;
- return TRUE;
-}
-
-/**
- * Destroy screen-specific information.
- *
- * @param index Screen index of the screen in screenInfo.screens[]
- * @param pScreen The actual screen pointer
- */
-static Bool
-miPointerCloseScreen (int index, ScreenPtr pScreen)
-{
- SetupScreen(pScreen);
-
- pScreen->CloseScreen = pScreenPriv->CloseScreen;
- free((pointer) pScreenPriv);
- FreeEventList(events, GetMaximumEventsNum());
- events = NULL;
- return (*pScreen->CloseScreen) (index, pScreen);
-}
-
-/*
- * DIX/DDX interface routines
- */
-
-static Bool
-miPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
-{
- SetupScreen(pScreen);
- return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
-}
-
-static Bool
-miPointerUnrealizeCursor (DeviceIntPtr pDev,
- ScreenPtr pScreen,
- CursorPtr pCursor)
-{
- SetupScreen(pScreen);
- return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor);
-}
-
-static Bool
-miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
-{
- miPointerPtr pPointer;
-
- /* return for keyboards */
- if (!IsPointerDevice(pDev))
- return FALSE;
-
- pPointer = MIPOINTER(pDev);
-
- pPointer->pCursor = pCursor;
- pPointer->pScreen = pScreen;
- miPointerUpdateSprite(pDev);
- return TRUE;
-}
-
-/**
- * Set up the constraints for the given device. This function does not
- * actually constrain the cursor but merely copies the given box to the
- * internal constraint storage.
- *
- * @param pDev The device to constrain to the box
- * @param pBox The rectangle to constrain the cursor to
- * @param pScreen Used for copying screen confinement
- */
-static void
-miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
-{
- miPointerPtr pPointer;
-
- pPointer = MIPOINTER(pDev);
-
- pPointer->limits = *pBox;
- pPointer->confined = PointerConfinedToScreen(pDev);
-}
-
-/**
- * Should calculate the box for the given cursor, based on screen and the
- * confinement given. But we assume that whatever box is passed in is valid
- * anyway.
- *
- * @param pDev The device to calculate the cursor limits for
- * @param pScreen The screen the confinement happens on
- * @param pCursor The screen the confinement happens on
- * @param pHotBox The confinement box for the cursor
- * @param[out] pTopLeftBox The new confinement box, always *pHotBox.
- */
-static void
-miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
- BoxPtr pHotBox, BoxPtr pTopLeftBox)
-{
- *pTopLeftBox = *pHotBox;
-}
-
-/**
- * Set the device's cursor position to the x/y position on the given screen.
- * Generates and event if required.
- *
- * This function is called from:
- * - sprite init code to place onto initial position
- * - the various WarpPointer implementations (core, XI, Xinerama, dmx,…)
- * - during the cursor update path in CheckMotion
- * - in the Xinerama part of NewCurrentScreen
- * - when a RandR/RandR1.2 mode was applied (it may have moved the pointer, so
- * it's set back to the original pos)
- *
- * @param pDev The device to move
- * @param pScreen The screen the device is on
- * @param x The x coordinate in per-screen coordinates
- * @param y The y coordinate in per-screen coordinates
- * @param generateEvent True if the pointer movement should generate an
- * event.
- *
- * @return TRUE in all cases
- */
-static Bool
-miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y, Bool generateEvent)
-{
- SetupScreen (pScreen);
- miPointerPtr pPointer = MIPOINTER(pDev);
-
- pPointer->generateEvent = generateEvent;
-
- if (pScreen->ConstrainCursorHarder)
- pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y);
-
- /* device dependent - must pend signal and call miPointerWarpCursor */
- (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
- if (!generateEvent)
- miPointerUpdateSprite(pDev);
- return TRUE;
-}
-
-/**
- * Set up sprite information for the device.
- * This function will be called once for each device after it is initialized
- * in the DIX.
- *
- * @param pDev The newly created device
- * @param pScreen The initial sprite scree.
- */
-static Bool
-miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- miPointerPtr pPointer;
- SetupScreen (pScreen);
-
- pPointer = malloc(sizeof(miPointerRec));
- if (!pPointer)
- return FALSE;
-
- pPointer->pScreen = NULL;
- pPointer->pSpriteScreen = NULL;
- pPointer->pCursor = NULL;
- pPointer->pSpriteCursor = NULL;
- pPointer->limits.x1 = 0;
- pPointer->limits.x2 = 32767;
- pPointer->limits.y1 = 0;
- pPointer->limits.y2 = 32767;
- pPointer->confined = FALSE;
- pPointer->x = 0;
- pPointer->y = 0;
- pPointer->generateEvent = FALSE;
-
- if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen)))
- {
- free(pPointer);
- return FALSE;
- }
-
- dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer);
- return TRUE;
-}
-
-/**
- * Clean up after device.
- * This function will be called once before the device is freed in the DIX
- *
- * @param pDev The device to be removed from the server
- * @param pScreen Current screen of the device
- */
-static void
-miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- SetupScreen(pScreen);
-
- if (!IsMaster(pDev) && !IsFloating(pDev))
- return;
-
- (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
- free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey));
- dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL);
-}
-
-
-/**
- * Warp the pointer to the given position on the given screen. May generate
- * an event, depending on whether we're coming from miPointerSetPosition.
- *
- * Once signals are ignored, the WarpCursor function can call this
- *
- * @param pDev The device to warp
- * @param pScreen Screen to warp on
- * @param x The x coordinate in per-screen coordinates
- * @param y The y coordinate in per-screen coordinates
- */
-
-void
-miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
-{
- miPointerPtr pPointer;
- BOOL changedScreen = FALSE;
-
- SetupScreen (pScreen);
- pPointer = MIPOINTER(pDev);
-
- if (pPointer->pScreen != pScreen)
- {
- (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE);
- changedScreen = TRUE;
- }
-
- if (pPointer->generateEvent)
- miPointerMove (pDev, pScreen, x, y);
- else
- miPointerMoveNoEvent(pDev, pScreen, x, y);
-
- /* Don't call USFS if we use Xinerama, otherwise the root window is
- * updated to the second screen, and we never receive any events.
- * (FDO bug #18668) */
- if (changedScreen
-#ifdef PANORAMIX
- && noPanoramiXExtension
-#endif
- )
- UpdateSpriteForScreen (pDev, pScreen) ;
-}
-
-/**
- * Syncronize the sprite with the cursor.
- *
- * @param pDev The device to sync
- */
-void
-miPointerUpdateSprite (DeviceIntPtr pDev)
-{
- ScreenPtr pScreen;
- miPointerScreenPtr pScreenPriv;
- CursorPtr pCursor;
- int x, y, devx, devy;
- miPointerPtr pPointer;
-
- if (!pDev || !pDev->coreEvents)
- return;
-
- pPointer = MIPOINTER(pDev);
-
- if (!pPointer)
- return;
-
- pScreen = pPointer->pScreen;
- if (!pScreen)
- return;
-
- x = pPointer->x;
- y = pPointer->y;
- devx = pPointer->devx;
- devy = pPointer->devy;
-
- pScreenPriv = GetScreenPrivate (pScreen);
- /*
- * if the cursor has switched screens, disable the sprite
- * on the old screen
- */
- if (pScreen != pPointer->pSpriteScreen)
- {
- if (pPointer->pSpriteScreen)
- {
- miPointerScreenPtr pOldPriv;
-
- pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen);
- if (pPointer->pCursor)
- {
- (*pOldPriv->spriteFuncs->SetCursor)
- (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0);
- }
- (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE);
- }
- (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
- (*pScreenPriv->spriteFuncs->SetCursor)
- (pDev, pScreen, pPointer->pCursor, x, y);
- pPointer->devx = x;
- pPointer->devy = y;
- pPointer->pSpriteCursor = pPointer->pCursor;
- pPointer->pSpriteScreen = pScreen;
- }
- /*
- * if the cursor has changed, display the new one
- */
- else if (pPointer->pCursor != pPointer->pSpriteCursor)
- {
- pCursor = pPointer->pCursor;
- if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent))
- pCursor = NullCursor;
- (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y);
-
- pPointer->devx = x;
- pPointer->devy = y;
- pPointer->pSpriteCursor = pPointer->pCursor;
- }
- else if (x != devx || y != devy)
- {
- pPointer->devx = x;
- pPointer->devy = y;
- if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
- (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
- }
-}
-
-/**
- * Set the device to the coordinates on the given screen.
- *
- * @param pDev The device to move
- * @param screen_no Index of the screen to move to
- * @param x The x coordinate in per-screen coordinates
- * @param y The y coordinate in per-screen coordinates
- */
-void
-miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
-{
- miPointerScreenPtr pScreenPriv;
- ScreenPtr pScreen;
- miPointerPtr pPointer;
-
- pPointer = MIPOINTER(pDev);
-
- pScreen = screenInfo.screens[screen_no];
- pScreenPriv = GetScreenPrivate (pScreen);
- (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE);
- NewCurrentScreen (pDev, pScreen, x, y);
-
- pPointer->limits.x2 = pScreen->width;
- pPointer->limits.y2 = pScreen->height;
-}
-
-/**
- * @return The current screen of the VCP
- */
-ScreenPtr
-miPointerCurrentScreen (void)
-{
- return miPointerGetScreen(inputInfo.pointer);
-}
-
-/**
- * @return The current screen of the given device or NULL.
- */
-ScreenPtr
-miPointerGetScreen(DeviceIntPtr pDev)
-{
- miPointerPtr pPointer = MIPOINTER(pDev);
- return (pPointer) ? pPointer->pScreen : NULL;
-}
-
-/* Controls whether the cursor image should be updated immediately when
- moved (FALSE) or if something else will be responsible for updating
- it later (TRUE). Returns current setting.
- Caller is responsible for calling OsBlockSignal first.
-*/
-Bool
-miPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait)
-{
- SetupScreen(pScreen);
- Bool prevWait = pScreenPriv->waitForUpdate;
-
- pScreenPriv->waitForUpdate = wait;
- return prevWait;
-}
-
-
-/* Move the pointer on the current screen, and update the sprite. */
-static void
-miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y)
-{
- miPointerPtr pPointer;
- SetupScreen(pScreen);
-
- pPointer = MIPOINTER(pDev);
-
- /* Hack: We mustn't call into ->MoveCursor for anything but the
- * VCP, as this may cause a non-HW rendered cursor to be rendered during
- * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT.
- */
- if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer
- && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
- {
- pPointer->devx = x;
- pPointer->devy = y;
- if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
- (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
- }
-
- pPointer->x = x;
- pPointer->y = y;
- pPointer->pScreen = pScreen;
-}
-
-/**
- * Set the devices' cursor position to the given x/y position.
- *
- * This function is called during the pointer update path in
- * GetPointerEvents and friends (and the same in the xwin DDX).
- *
- * The coordinates provided are always absolute. The parameter mode whether
- * it was relative or absolute movement that landed us at those coordinates.
- *
- * @param pDev The device to move
- * @param mode Movement mode (Absolute or Relative)
- * @param[in,out] x The x coordiante in screen coordinates (in regards to total
- * desktop size)
- * @param[in,out] y The y coordiante in screen coordinates (in regards to total
- * desktop size)
- */
-void
-miPointerSetPosition(DeviceIntPtr pDev, int mode, int *x, int *y)
-{
- miPointerScreenPtr pScreenPriv;
- ScreenPtr pScreen;
- ScreenPtr newScreen;
-
- miPointerPtr pPointer;
-
- if (!pDev || !pDev->coreEvents)
- return;
-
- pPointer = MIPOINTER(pDev);
- pScreen = pPointer->pScreen;
- if (!pScreen)
- return; /* called before ready */
-
- if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
- {
- pScreenPriv = GetScreenPrivate (pScreen);
- if (!pPointer->confined)
- {
- newScreen = pScreen;
- (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y);
- if (newScreen != pScreen)
- {
- pScreen = newScreen;
- (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen,
- FALSE);
- /* Smash the confine to the new screen */
- pPointer->limits.x2 = pScreen->width;
- pPointer->limits.y2 = pScreen->height;
- }
- }
- }
- /* Constrain the sprite to the current limits. */
- if (*x < pPointer->limits.x1)
- *x = pPointer->limits.x1;
- if (*x >= pPointer->limits.x2)
- *x = pPointer->limits.x2 - 1;
- if (*y < pPointer->limits.y1)
- *y = pPointer->limits.y1;
- if (*y >= pPointer->limits.y2)
- *y = pPointer->limits.y2 - 1;
-
- if (pScreen->ConstrainCursorHarder)
- pScreen->ConstrainCursorHarder(pDev, pScreen, mode, x, y);
-
- if (pPointer->x == *x && pPointer->y == *y &&
- pPointer->pScreen == pScreen)
- return;
-
- miPointerMoveNoEvent(pDev, pScreen, *x, *y);
-}
-
-/**
- * Get the current position of the device in desktop coordinates.
- *
- * @param x Return value for the current x coordinate in desktop coordiates.
- * @param y Return value for the current y coordinate in desktop coordiates.
- */
-void
-miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
-{
- *x = MIPOINTER(pDev)->x;
- *y = MIPOINTER(pDev)->y;
-}
-
-#ifdef XQUARTZ
-#include <pthread.h>
-void darwinEvents_lock(void);
-void darwinEvents_unlock(void);
-#endif
-
-/**
- * Move the device's pointer to the x/y coordinates on the given screen.
- * This function generates and enqueues pointer events.
- *
- * @param pDev The device to move
- * @param pScreen The screen the device is on
- * @param x The x coordinate in per-screen coordinates
- * @param y The y coordinate in per-screen coordinates
- */
-void
-miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
-{
- int i, nevents;
- int valuators[2];
- ValuatorMask mask;
-
- miPointerMoveNoEvent(pDev, pScreen, x, y);
-
- /* generate motion notify */
- valuators[0] = x;
- valuators[1] = y;
-
- if (!events)
- {
- events = InitEventList(GetMaximumEventsNum());
-
- if (!events)
- {
- FatalError("Could not allocate event store.\n");
- return;
- }
- }
-
- valuator_mask_set_range(&mask, 0, 2, valuators);
- nevents = GetPointerEvents(events, pDev, MotionNotify, 0,
- POINTER_SCREEN | POINTER_ABSOLUTE | POINTER_NORAW, &mask);
-
- OsBlockSignals();
-#ifdef XQUARTZ
- darwinEvents_lock();
-#endif
- for (i = 0; i < nevents; i++)
- mieqEnqueue(pDev, &events[i]);
-#ifdef XQUARTZ
- darwinEvents_unlock();
-#endif
- OsReleaseSignals();
-}
+/*
+
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+*/
+
+/**
+ * @file
+ * This file contains functions to move the pointer on the screen and/or
+ * restrict its movement. These functions are divided into two sets:
+ * Screen-specific functions that are used as function pointers from other
+ * parts of the server (and end up heavily wrapped by e.g. animcur and
+ * xfixes):
+ * miPointerConstrainCursor
+ * miPointerCursorLimits
+ * miPointerDisplayCursor
+ * miPointerRealizeCursor
+ * miPointerUnrealizeCursor
+ * miPointerSetCursorPosition
+ * miRecolorCursor
+ * miPointerDeviceInitialize
+ * miPointerDeviceCleanup
+ * If wrapped, these are the last element in the wrapping chain. They may
+ * call into sprite-specific code through further function pointers though.
+ *
+ * The second type of functions are those that are directly called by the
+ * DIX, DDX and some drivers.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+# include <X11/X.h>
+# include <X11/Xmd.h>
+# include <X11/Xproto.h>
+# include "misc.h"
+# include "windowstr.h"
+# include "pixmapstr.h"
+# include "mi.h"
+# include "scrnintstr.h"
+# include "mipointrst.h"
+# include "cursorstr.h"
+# include "dixstruct.h"
+# include "inputstr.h"
+# include "inpututils.h"
+# include "eventstr.h"
+
+DevPrivateKeyRec miPointerScreenKeyRec;
+
+#define GetScreenPrivate(s) ((miPointerScreenPtr) \
+ dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey))
+#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s)
+
+DevPrivateKeyRec miPointerPrivKeyRec;
+
+#define MIPOINTER(dev) \
+ (IsFloating(dev) ? \
+ (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
+ (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey))
+
+static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ CursorPtr pCursor);
+static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ CursorPtr pCursor);
+static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ CursorPtr pCursor);
+static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+ BoxPtr pBox);
+static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen,
+ CursorPtr pCursor, BoxPtr pHotBox,
+ BoxPtr pTopLeftBox);
+static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y,
+ Bool generateEvent);
+static Bool miPointerCloseScreen(int index, ScreenPtr pScreen);
+static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y);
+static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
+static void miPointerDeviceCleanup(DeviceIntPtr pDev,
+ ScreenPtr pScreen);
+static void miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y);
+
+static InternalEvent* events; /* for WarpPointer MotionNotifies */
+
+Bool
+miPointerInitialize (ScreenPtr pScreen,
+ miPointerSpriteFuncPtr spriteFuncs,
+ miPointerScreenFuncPtr screenFuncs,
+ Bool waitForUpdate)
+{
+ miPointerScreenPtr pScreenPriv;
+
+ if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0))
+ return FALSE;
+
+ if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0))
+ return FALSE;
+
+ pScreenPriv = malloc(sizeof (miPointerScreenRec));
+ if (!pScreenPriv)
+ return FALSE;
+ pScreenPriv->spriteFuncs = spriteFuncs;
+ pScreenPriv->screenFuncs = screenFuncs;
+ /*
+ * check for uninitialized methods
+ */
+ if (!screenFuncs->EnqueueEvent)
+ screenFuncs->EnqueueEvent = mieqEnqueue;
+ if (!screenFuncs->NewEventScreen)
+ screenFuncs->NewEventScreen = mieqSwitchScreen;
+ pScreenPriv->waitForUpdate = waitForUpdate;
+ pScreenPriv->showTransparent = FALSE;
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = miPointerCloseScreen;
+ dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv);
+ /*
+ * set up screen cursor method table
+ */
+ pScreen->ConstrainCursor = miPointerConstrainCursor;
+ pScreen->CursorLimits = miPointerCursorLimits;
+ pScreen->DisplayCursor = miPointerDisplayCursor;
+ pScreen->RealizeCursor = miPointerRealizeCursor;
+ pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
+ pScreen->SetCursorPosition = miPointerSetCursorPosition;
+ pScreen->RecolorCursor = miRecolorCursor;
+ pScreen->DeviceCursorInitialize = miPointerDeviceInitialize;
+ pScreen->DeviceCursorCleanup = miPointerDeviceCleanup;
+
+ events = NULL;
+ return TRUE;
+}
+
+/**
+ * Destroy screen-specific information.
+ *
+ * @param index Screen index of the screen in screenInfo.screens[]
+ * @param pScreen The actual screen pointer
+ */
+static Bool
+miPointerCloseScreen (int index, ScreenPtr pScreen)
+{
+ SetupScreen(pScreen);
+
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ free((pointer) pScreenPriv);
+ FreeEventList(events, GetMaximumEventsNum());
+ events = NULL;
+ return (*pScreen->CloseScreen) (index, pScreen);
+}
+
+/*
+ * DIX/DDX interface routines
+ */
+
+static Bool
+miPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
+{
+ SetupScreen(pScreen);
+ return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
+}
+
+static Bool
+miPointerUnrealizeCursor (DeviceIntPtr pDev,
+ ScreenPtr pScreen,
+ CursorPtr pCursor)
+{
+ SetupScreen(pScreen);
+ return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor);
+}
+
+static Bool
+miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
+{
+ miPointerPtr pPointer;
+
+ /* return for keyboards */
+ if (!IsPointerDevice(pDev))
+ return FALSE;
+
+ pPointer = MIPOINTER(pDev);
+
+ pPointer->pCursor = pCursor;
+ pPointer->pScreen = pScreen;
+ miPointerUpdateSprite(pDev);
+ return TRUE;
+}
+
+/**
+ * Set up the constraints for the given device. This function does not
+ * actually constrain the cursor but merely copies the given box to the
+ * internal constraint storage.
+ *
+ * @param pDev The device to constrain to the box
+ * @param pBox The rectangle to constrain the cursor to
+ * @param pScreen Used for copying screen confinement
+ */
+static void
+miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
+{
+ miPointerPtr pPointer;
+
+ pPointer = MIPOINTER(pDev);
+
+ pPointer->limits = *pBox;
+ pPointer->confined = PointerConfinedToScreen(pDev);
+}
+
+/**
+ * Should calculate the box for the given cursor, based on screen and the
+ * confinement given. But we assume that whatever box is passed in is valid
+ * anyway.
+ *
+ * @param pDev The device to calculate the cursor limits for
+ * @param pScreen The screen the confinement happens on
+ * @param pCursor The screen the confinement happens on
+ * @param pHotBox The confinement box for the cursor
+ * @param[out] pTopLeftBox The new confinement box, always *pHotBox.
+ */
+static void
+miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
+ BoxPtr pHotBox, BoxPtr pTopLeftBox)
+{
+ *pTopLeftBox = *pHotBox;
+}
+
+/**
+ * Set the device's cursor position to the x/y position on the given screen.
+ * Generates and event if required.
+ *
+ * This function is called from:
+ * - sprite init code to place onto initial position
+ * - the various WarpPointer implementations (core, XI, Xinerama, dmx,…)
+ * - during the cursor update path in CheckMotion
+ * - in the Xinerama part of NewCurrentScreen
+ * - when a RandR/RandR1.2 mode was applied (it may have moved the pointer, so
+ * it's set back to the original pos)
+ *
+ * @param pDev The device to move
+ * @param pScreen The screen the device is on
+ * @param x The x coordinate in per-screen coordinates
+ * @param y The y coordinate in per-screen coordinates
+ * @param generateEvent True if the pointer movement should generate an
+ * event.
+ *
+ * @return TRUE in all cases
+ */
+static Bool
+miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y, Bool generateEvent)
+{
+ SetupScreen (pScreen);
+ miPointerPtr pPointer = MIPOINTER(pDev);
+
+ pPointer->generateEvent = generateEvent;
+
+ if (pScreen->ConstrainCursorHarder)
+ pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y);
+
+ /* device dependent - must pend signal and call miPointerWarpCursor */
+ (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
+ if (!generateEvent)
+ miPointerUpdateSprite(pDev);
+ return TRUE;
+}
+
+/**
+ * Set up sprite information for the device.
+ * This function will be called once for each device after it is initialized
+ * in the DIX.
+ *
+ * @param pDev The newly created device
+ * @param pScreen The initial sprite scree.
+ */
+static Bool
+miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ miPointerPtr pPointer;
+ SetupScreen (pScreen);
+
+ pPointer = malloc(sizeof(miPointerRec));
+ if (!pPointer)
+ return FALSE;
+
+ pPointer->pScreen = NULL;
+ pPointer->pSpriteScreen = NULL;
+ pPointer->pCursor = NULL;
+ pPointer->pSpriteCursor = NULL;
+ pPointer->limits.x1 = 0;
+ pPointer->limits.x2 = 32767;
+ pPointer->limits.y1 = 0;
+ pPointer->limits.y2 = 32767;
+ pPointer->confined = FALSE;
+ pPointer->x = 0;
+ pPointer->y = 0;
+ pPointer->generateEvent = FALSE;
+
+ if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen)))
+ {
+ free(pPointer);
+ return FALSE;
+ }
+
+ dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer);
+ return TRUE;
+}
+
+/**
+ * Clean up after device.
+ * This function will be called once before the device is freed in the DIX
+ *
+ * @param pDev The device to be removed from the server
+ * @param pScreen Current screen of the device
+ */
+static void
+miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ SetupScreen(pScreen);
+
+ if (!IsMaster(pDev) && !IsFloating(pDev))
+ return;
+
+ (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
+ free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey));
+ dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL);
+}
+
+
+/**
+ * Warp the pointer to the given position on the given screen. May generate
+ * an event, depending on whether we're coming from miPointerSetPosition.
+ *
+ * Once signals are ignored, the WarpCursor function can call this
+ *
+ * @param pDev The device to warp
+ * @param pScreen Screen to warp on
+ * @param x The x coordinate in per-screen coordinates
+ * @param y The y coordinate in per-screen coordinates
+ */
+
+void
+miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
+{
+ miPointerPtr pPointer;
+ BOOL changedScreen = FALSE;
+
+ SetupScreen (pScreen);
+ pPointer = MIPOINTER(pDev);
+
+ if (pPointer->pScreen != pScreen)
+ {
+ (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE);
+ changedScreen = TRUE;
+ }
+
+ if (pPointer->generateEvent)
+ miPointerMove (pDev, pScreen, x, y);
+ else
+ miPointerMoveNoEvent(pDev, pScreen, x, y);
+
+ /* Don't call USFS if we use Xinerama, otherwise the root window is
+ * updated to the second screen, and we never receive any events.
+ * (FDO bug #18668) */
+ if (changedScreen
+#ifdef PANORAMIX
+ && noPanoramiXExtension
+#endif
+ )
+ UpdateSpriteForScreen (pDev, pScreen) ;
+}
+
+/**
+ * Syncronize the sprite with the cursor.
+ *
+ * @param pDev The device to sync
+ */
+void
+miPointerUpdateSprite (DeviceIntPtr pDev)
+{
+ ScreenPtr pScreen;
+ miPointerScreenPtr pScreenPriv;
+ CursorPtr pCursor;
+ int x, y, devx, devy;
+ miPointerPtr pPointer;
+
+ if (!pDev || !pDev->coreEvents)
+ return;
+
+ pPointer = MIPOINTER(pDev);
+
+ if (!pPointer)
+ return;
+
+ pScreen = pPointer->pScreen;
+ if (!pScreen)
+ return;
+
+ x = pPointer->x;
+ y = pPointer->y;
+ devx = pPointer->devx;
+ devy = pPointer->devy;
+
+ pScreenPriv = GetScreenPrivate (pScreen);
+ /*
+ * if the cursor has switched screens, disable the sprite
+ * on the old screen
+ */
+ if (pScreen != pPointer->pSpriteScreen)
+ {
+ if (pPointer->pSpriteScreen)
+ {
+ miPointerScreenPtr pOldPriv;
+
+ pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen);
+ if (pPointer->pCursor)
+ {
+ (*pOldPriv->spriteFuncs->SetCursor)
+ (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0);
+ }
+ (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE);
+ }
+ (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
+ (*pScreenPriv->spriteFuncs->SetCursor)
+ (pDev, pScreen, pPointer->pCursor, x, y);
+ pPointer->devx = x;
+ pPointer->devy = y;
+ pPointer->pSpriteCursor = pPointer->pCursor;
+ pPointer->pSpriteScreen = pScreen;
+ }
+ /*
+ * if the cursor has changed, display the new one
+ */
+ else if (pPointer->pCursor != pPointer->pSpriteCursor)
+ {
+ pCursor = pPointer->pCursor;
+ if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent))
+ pCursor = NullCursor;
+ (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y);
+
+ pPointer->devx = x;
+ pPointer->devy = y;
+ pPointer->pSpriteCursor = pPointer->pCursor;
+ }
+ else if (x != devx || y != devy)
+ {
+ pPointer->devx = x;
+ pPointer->devy = y;
+ if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
+ (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
+ }
+}
+
+/**
+ * Set the device to the coordinates on the given screen.
+ *
+ * @param pDev The device to move
+ * @param screen_no Index of the screen to move to
+ * @param x The x coordinate in per-screen coordinates
+ * @param y The y coordinate in per-screen coordinates
+ */
+void
+miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
+{
+ miPointerScreenPtr pScreenPriv;
+ ScreenPtr pScreen;
+ miPointerPtr pPointer;
+
+ pPointer = MIPOINTER(pDev);
+
+ pScreen = screenInfo.screens[screen_no];
+ pScreenPriv = GetScreenPrivate (pScreen);
+ (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE);
+ NewCurrentScreen (pDev, pScreen, x, y);
+
+ pPointer->limits.x2 = pScreen->width;
+ pPointer->limits.y2 = pScreen->height;
+}
+
+/**
+ * @return The current screen of the VCP
+ */
+ScreenPtr
+miPointerCurrentScreen (void)
+{
+ return miPointerGetScreen(inputInfo.pointer);
+}
+
+/**
+ * @return The current screen of the given device or NULL.
+ */
+ScreenPtr
+miPointerGetScreen(DeviceIntPtr pDev)
+{
+ miPointerPtr pPointer = MIPOINTER(pDev);
+ return (pPointer) ? pPointer->pScreen : NULL;
+}
+
+/* Controls whether the cursor image should be updated immediately when
+ moved (FALSE) or if something else will be responsible for updating
+ it later (TRUE). Returns current setting.
+ Caller is responsible for calling OsBlockSignal first.
+*/
+Bool
+miPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait)
+{
+ SetupScreen(pScreen);
+ Bool prevWait = pScreenPriv->waitForUpdate;
+
+ pScreenPriv->waitForUpdate = wait;
+ return prevWait;
+}
+
+
+/* Move the pointer on the current screen, and update the sprite. */
+static void
+miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen,
+ int x, int y)
+{
+ miPointerPtr pPointer;
+ SetupScreen(pScreen);
+
+ pPointer = MIPOINTER(pDev);
+
+ /* Hack: We mustn't call into ->MoveCursor for anything but the
+ * VCP, as this may cause a non-HW rendered cursor to be rendered during
+ * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT.
+ */
+ if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer
+ && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
+ {
+ pPointer->devx = x;
+ pPointer->devy = y;
+ if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
+ (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
+ }
+
+ pPointer->x = x;
+ pPointer->y = y;
+ pPointer->pScreen = pScreen;
+}
+
+/**
+ * Set the devices' cursor position to the given x/y position.
+ *
+ * This function is called during the pointer update path in
+ * GetPointerEvents and friends (and the same in the xwin DDX).
+ *
+ * The coordinates provided are always absolute. The parameter mode whether
+ * it was relative or absolute movement that landed us at those coordinates.
+ *
+ * @param pDev The device to move
+ * @param mode Movement mode (Absolute or Relative)
+ * @param[in,out] x The x coordiante in screen coordinates (in regards to total
+ * desktop size)
+ * @param[in,out] y The y coordiante in screen coordinates (in regards to total
+ * desktop size)
+ */
+void
+miPointerSetPosition(DeviceIntPtr pDev, int mode, int *x, int *y)
+{
+ miPointerScreenPtr pScreenPriv;
+ ScreenPtr pScreen;
+ ScreenPtr newScreen;
+
+ miPointerPtr pPointer;
+
+ if (!pDev || !pDev->coreEvents)
+ return;
+
+ pPointer = MIPOINTER(pDev);
+ pScreen = pPointer->pScreen;
+ if (!pScreen)
+ return; /* called before ready */
+
+ if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
+ {
+ pScreenPriv = GetScreenPrivate (pScreen);
+ if (!pPointer->confined)
+ {
+ newScreen = pScreen;
+ (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y);
+ if (newScreen != pScreen)
+ {
+ pScreen = newScreen;
+ (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen,
+ FALSE);
+ /* Smash the confine to the new screen */
+ pPointer->limits.x2 = pScreen->width;
+ pPointer->limits.y2 = pScreen->height;
+ }
+ }
+ }
+ /* Constrain the sprite to the current limits. */
+ if (*x < pPointer->limits.x1)
+ *x = pPointer->limits.x1;
+ if (*x >= pPointer->limits.x2)
+ *x = pPointer->limits.x2 - 1;
+ if (*y < pPointer->limits.y1)
+ *y = pPointer->limits.y1;
+ if (*y >= pPointer->limits.y2)
+ *y = pPointer->limits.y2 - 1;
+
+ if (pScreen->ConstrainCursorHarder)
+ pScreen->ConstrainCursorHarder(pDev, pScreen, mode, x, y);
+
+ if (pPointer->x == *x && pPointer->y == *y &&
+ pPointer->pScreen == pScreen)
+ return;
+
+ miPointerMoveNoEvent(pDev, pScreen, *x, *y);
+}
+
+/**
+ * Get the current position of the device in desktop coordinates.
+ *
+ * @param x Return value for the current x coordinate in desktop coordiates.
+ * @param y Return value for the current y coordinate in desktop coordiates.
+ */
+void
+miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
+{
+ *x = MIPOINTER(pDev)->x;
+ *y = MIPOINTER(pDev)->y;
+}
+
+#ifdef XQUARTZ
+#include <pthread.h>
+void darwinEvents_lock(void);
+void darwinEvents_unlock(void);
+#endif
+
+/**
+ * Move the device's pointer to the x/y coordinates on the given screen.
+ * This function generates and enqueues pointer events.
+ *
+ * @param pDev The device to move
+ * @param pScreen The screen the device is on
+ * @param x The x coordinate in per-screen coordinates
+ * @param y The y coordinate in per-screen coordinates
+ */
+void
+miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
+{
+ int i, nevents;
+ int valuators[2];
+ ValuatorMask mask;
+
+ miPointerMoveNoEvent(pDev, pScreen, x, y);
+
+ /* generate motion notify */
+ valuators[0] = x;
+ valuators[1] = y;
+
+ if (!events)
+ {
+ events = InitEventList(GetMaximumEventsNum());
+
+ if (!events)
+ {
+ FatalError("Could not allocate event store.\n");
+ return;
+ }
+ }
+
+ valuator_mask_set_range(&mask, 0, 2, valuators);
+ nevents = GetPointerEvents(events, pDev, MotionNotify, 0,
+ POINTER_SCREEN | POINTER_ABSOLUTE | POINTER_NORAW, &mask);
+
+ OsBlockSignals();
+#ifdef XQUARTZ
+ darwinEvents_lock();
+#endif
+ for (i = 0; i < nevents; i++)
+ mieqEnqueue(pDev, &events[i]);
+#ifdef XQUARTZ
+ darwinEvents_unlock();
+#endif
+ OsReleaseSignals();
+}
diff --git a/xorg-server/mi/mipointrst.h b/xorg-server/mi/mipointrst.h
index 109a44c88..c912a17da 100644
--- a/xorg-server/mi/mipointrst.h
+++ b/xorg-server/mi/mipointrst.h
@@ -1,57 +1,57 @@
-/*
- * mipointrst.h
- *
- */
-
-
-/*
-
-Copyright 1989, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-*/
-
-#ifndef MIPOINTRST_H
-#define MIPOINTRST_H
-
-#include "mipointer.h"
-#include "scrnintstr.h"
-
-typedef struct {
- ScreenPtr pScreen; /* current screen */
- ScreenPtr pSpriteScreen;/* screen containing current sprite */
- CursorPtr pCursor; /* current cursor */
- CursorPtr pSpriteCursor;/* cursor on screen */
- BoxRec limits; /* current constraints */
- Bool confined; /* pointer can't change screens */
- int x, y; /* hot spot location */
- int devx, devy; /* sprite position */
- Bool generateEvent; /* generate an event during warping? */
-} miPointerRec, *miPointerPtr;
-
-typedef struct {
- miPointerSpriteFuncPtr spriteFuncs; /* sprite-specific methods */
- miPointerScreenFuncPtr screenFuncs; /* screen-specific methods */
- CloseScreenProcPtr CloseScreen;
- Bool waitForUpdate; /* don't move cursor in SIGIO */
- Bool showTransparent; /* show empty cursors */
-} miPointerScreenRec, *miPointerScreenPtr;
-#endif /* MIPOINTRST_H */
+/*
+ * mipointrst.h
+ *
+ */
+
+
+/*
+
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+*/
+
+#ifndef MIPOINTRST_H
+#define MIPOINTRST_H
+
+#include "mipointer.h"
+#include "scrnintstr.h"
+
+typedef struct {
+ ScreenPtr pScreen; /* current screen */
+ ScreenPtr pSpriteScreen;/* screen containing current sprite */
+ CursorPtr pCursor; /* current cursor */
+ CursorPtr pSpriteCursor;/* cursor on screen */
+ BoxRec limits; /* current constraints */
+ Bool confined; /* pointer can't change screens */
+ int x, y; /* hot spot location */
+ int devx, devy; /* sprite position */
+ Bool generateEvent; /* generate an event during warping? */
+} miPointerRec, *miPointerPtr;
+
+typedef struct {
+ miPointerSpriteFuncPtr spriteFuncs; /* sprite-specific methods */
+ miPointerScreenFuncPtr screenFuncs; /* screen-specific methods */
+ CloseScreenProcPtr CloseScreen;
+ Bool waitForUpdate; /* don't move cursor in SIGIO */
+ Bool showTransparent; /* show empty cursors */
+} miPointerScreenRec, *miPointerScreenPtr;
+#endif /* MIPOINTRST_H */
diff --git a/xorg-server/mi/mispans.c b/xorg-server/mi/mispans.c
index b7f05a032..21ba4da4f 100644
--- a/xorg-server/mi/mispans.c
+++ b/xorg-server/mi/mispans.c
@@ -1,527 +1,527 @@
-/***********************************************************
-
-Copyright 1989, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1989 by 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 "misc.h"
-#include "pixmapstr.h"
-#include "gcstruct.h"
-#include "mispans.h"
-
-/*
-
-These routines maintain lists of Spans, in order to implement the
-``touch-each-pixel-once'' rules of wide lines and arcs.
-
-Written by Joel McCormack, Summer 1989.
-
-*/
-
-
-void miInitSpanGroup(SpanGroup *spanGroup)
-{
- spanGroup->size = 0;
- spanGroup->count = 0;
- spanGroup->group = NULL;
- spanGroup->ymin = MAXSHORT;
- spanGroup->ymax = MINSHORT;
-} /* InitSpanGroup */
-
-#define YMIN(spans) (spans->points[0].y)
-#define YMAX(spans) (spans->points[spans->count-1].y)
-
-static void miSubtractSpans (SpanGroup *spanGroup, Spans *sub)
-{
- int i, subCount, spansCount;
- int ymin, ymax, xmin, xmax;
- Spans *spans;
- DDXPointPtr subPt, spansPt;
- int *subWid, *spansWid;
- int extra;
-
- ymin = YMIN(sub);
- ymax = YMAX(sub);
- spans = spanGroup->group;
- for (i = spanGroup->count; i; i--, spans++) {
- if (YMIN(spans) <= ymax && ymin <= YMAX(spans)) {
- subCount = sub->count;
- subPt = sub->points;
- subWid = sub->widths;
- spansCount = spans->count;
- spansPt = spans->points;
- spansWid = spans->widths;
- extra = 0;
- for (;;)
- {
- while (spansCount && spansPt->y < subPt->y)
- {
- spansPt++; spansWid++; spansCount--;
- }
- if (!spansCount)
- break;
- while (subCount && subPt->y < spansPt->y)
- {
- subPt++; subWid++; subCount--;
- }
- if (!subCount)
- break;
- if (subPt->y == spansPt->y)
- {
- xmin = subPt->x;
- xmax = xmin + *subWid;
- if (xmin >= spansPt->x + *spansWid || spansPt->x >= xmax)
- {
- ;
- }
- else if (xmin <= spansPt->x)
- {
- if (xmax >= spansPt->x + *spansWid)
- {
- memmove (spansPt, spansPt + 1, sizeof *spansPt * (spansCount - 1));
- memmove (spansWid, spansWid + 1, sizeof *spansWid * (spansCount - 1));
- spansPt--;
- spansWid--;
- spans->count--;
- extra++;
- }
- else
- {
- *spansWid = *spansWid - (xmax - spansPt->x);
- spansPt->x = xmax;
- }
- }
- else
- {
- if (xmax >= spansPt->x + *spansWid)
- {
- *spansWid = xmin - spansPt->x;
- }
- else
- {
- if (!extra) {
- DDXPointPtr newPt;
- int *newwid;
-
-#define EXTRA 8
- newPt = (DDXPointPtr) realloc(spans->points, (spans->count + EXTRA) * sizeof (DDXPointRec));
- if (!newPt)
- break;
- spansPt = newPt + (spansPt - spans->points);
- spans->points = newPt;
- newwid = (int *) realloc(spans->widths, (spans->count + EXTRA) * sizeof (int));
- if (!newwid)
- break;
- spansWid = newwid + (spansWid - spans->widths);
- spans->widths = newwid;
- extra = EXTRA;
- }
- memmove (spansPt + 1, spansPt, sizeof *spansPt * (spansCount));
- memmove (spansWid + 1, spansWid, sizeof *spansWid * (spansCount));
- spans->count++;
- extra--;
- *spansWid = xmin - spansPt->x;
- spansWid++;
- spansPt++;
- *spansWid = *spansWid - (xmax - spansPt->x);
- spansPt->x = xmax;
- }
- }
- }
- spansPt++; spansWid++; spansCount--;
- }
- }
- }
-}
-
-void miAppendSpans(SpanGroup *spanGroup, SpanGroup *otherGroup, Spans *spans)
-{
- int ymin, ymax;
- int spansCount;
-
- spansCount = spans->count;
- if (spansCount > 0) {
- if (spanGroup->size == spanGroup->count) {
- spanGroup->size = (spanGroup->size + 8) * 2;
- spanGroup->group = (Spans *)
- realloc(spanGroup->group, sizeof(Spans) * spanGroup->size);
- }
-
- spanGroup->group[spanGroup->count] = *spans;
- (spanGroup->count)++;
- ymin = spans->points[0].y;
- if (ymin < spanGroup->ymin) spanGroup->ymin = ymin;
- ymax = spans->points[spansCount - 1].y;
- if (ymax > spanGroup->ymax) spanGroup->ymax = ymax;
- if (otherGroup &&
- otherGroup->ymin < ymax &&
- ymin < otherGroup->ymax)
- {
- miSubtractSpans (otherGroup, spans);
- }
- }
- else
- {
- free(spans->points);
- free(spans->widths);
- }
-} /* AppendSpans */
-
-void miFreeSpanGroup(SpanGroup *spanGroup)
-{
- free(spanGroup->group);
-}
-
-static void QuickSortSpansX(
- DDXPointRec points[],
- int widths[],
- int numSpans )
-{
- int x;
- int i, j, m;
- DDXPointPtr r;
-
-/* Always called with numSpans > 1 */
-/* Sorts only by x, as all y should be the same */
-
-#define ExchangeSpans(a, b) \
-{ \
- DDXPointRec tpt; \
- int tw; \
- \
- tpt = points[a]; points[a] = points[b]; points[b] = tpt; \
- tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \
-}
-
- do {
- if (numSpans < 9) {
- /* Do insertion sort */
- int xprev;
-
- xprev = points[0].x;
- i = 1;
- do { /* while i != numSpans */
- x = points[i].x;
- if (xprev > x) {
- /* points[i] is out of order. Move into proper location. */
- DDXPointRec tpt;
- int tw, k;
-
- for (j = 0; x >= points[j].x; j++) {}
- tpt = points[i];
- tw = widths[i];
- for (k = i; k != j; k--) {
- points[k] = points[k-1];
- widths[k] = widths[k-1];
- }
- points[j] = tpt;
- widths[j] = tw;
- x = points[i].x;
- } /* if out of order */
- xprev = x;
- i++;
- } while (i != numSpans);
- return;
- }
-
- /* Choose partition element, stick in location 0 */
- m = numSpans / 2;
- if (points[m].x > points[0].x) ExchangeSpans(m, 0);
- if (points[m].x > points[numSpans-1].x) ExchangeSpans(m, numSpans-1);
- if (points[m].x > points[0].x) ExchangeSpans(m, 0);
- x = points[0].x;
-
- /* Partition array */
- i = 0;
- j = numSpans;
- do {
- r = &(points[i]);
- do {
- r++;
- i++;
- } while (i != numSpans && r->x < x);
- r = &(points[j]);
- do {
- r--;
- j--;
- } while (x < r->x);
- if (i < j) ExchangeSpans(i, j);
- } while (i < j);
-
- /* Move partition element back to middle */
- ExchangeSpans(0, j);
-
- /* Recurse */
- if (numSpans-j-1 > 1)
- QuickSortSpansX(&points[j+1], &widths[j+1], numSpans-j-1);
- numSpans = j;
- } while (numSpans > 1);
-} /* QuickSortSpans */
-
-
-static int UniquifySpansX(
- Spans *spans,
- DDXPointRec *newPoints,
- int *newWidths )
-{
- int newx1, newx2, oldpt, i, y;
- DDXPointRec *oldPoints;
- int *oldWidths;
- int *startNewWidths;
-
-/* Always called with numSpans > 1 */
-/* Uniquify the spans, and stash them into newPoints and newWidths. Return the
- number of unique spans. */
-
-
- startNewWidths = newWidths;
-
- oldPoints = spans->points;
- oldWidths = spans->widths;
-
- y = oldPoints->y;
- newx1 = oldPoints->x;
- newx2 = newx1 + *oldWidths;
-
- for (i = spans->count-1; i != 0; i--) {
- oldPoints++;
- oldWidths++;
- oldpt = oldPoints->x;
- if (oldpt > newx2) {
- /* Write current span, start a new one */
- newPoints->x = newx1;
- newPoints->y = y;
- *newWidths = newx2 - newx1;
- newPoints++;
- newWidths++;
- newx1 = oldpt;
- newx2 = oldpt + *oldWidths;
- } else {
- /* extend current span, if old extends beyond new */
- oldpt = oldpt + *oldWidths;
- if (oldpt > newx2) newx2 = oldpt;
- }
- } /* for */
-
- /* Write final span */
- newPoints->x = newx1;
- *newWidths = newx2 - newx1;
- newPoints->y = y;
-
- return (newWidths - startNewWidths) + 1;
-} /* UniquifySpansX */
-
-static void
-miDisposeSpanGroup (SpanGroup *spanGroup)
-{
- int i;
- Spans *spans;
-
- for (i = 0; i < spanGroup->count; i++)
- {
- spans = spanGroup->group + i;
- free(spans->points);
- free(spans->widths);
- }
-}
-
-void miFillUniqueSpanGroup(DrawablePtr pDraw, GCPtr pGC, SpanGroup *spanGroup)
-{
- int i;
- Spans *spans;
- Spans *yspans;
- int *ysizes;
- int ymin, ylength;
-
- /* Outgoing spans for one big call to FillSpans */
- DDXPointPtr points;
- int *widths;
- int count;
-
- if (spanGroup->count == 0) return;
-
- if (spanGroup->count == 1) {
- /* Already should be sorted, unique */
- spans = spanGroup->group;
- (*pGC->ops->FillSpans)
- (pDraw, pGC, spans->count, spans->points, spans->widths, TRUE);
- free(spans->points);
- free(spans->widths);
- }
- else
- {
- /* Yuck. Gross. Radix sort into y buckets, then sort x and uniquify */
- /* This seems to be the fastest thing to do. I've tried sorting on
- both x and y at the same time rather than creating into all those
- y buckets, but it was somewhat slower. */
-
- ymin = spanGroup->ymin;
- ylength = spanGroup->ymax - ymin + 1;
-
- /* Allocate Spans for y buckets */
- yspans = malloc(ylength * sizeof(Spans));
- ysizes = malloc(ylength * sizeof (int));
-
- if (!yspans || !ysizes)
- {
- free(yspans);
- free(ysizes);
- miDisposeSpanGroup (spanGroup);
- return;
- }
-
- for (i = 0; i != ylength; i++) {
- ysizes[i] = 0;
- yspans[i].count = 0;
- yspans[i].points = NULL;
- yspans[i].widths = NULL;
- }
-
- /* Go through every single span and put it into the correct bucket */
- count = 0;
- for (i = 0, spans = spanGroup->group;
- i != spanGroup->count;
- i++, spans++) {
- int index;
- int j;
-
- for (j = 0, points = spans->points, widths = spans->widths;
- j != spans->count;
- j++, points++, widths++) {
- index = points->y - ymin;
- if (index >= 0 && index < ylength) {
- Spans *newspans = &(yspans[index]);
- if (newspans->count == ysizes[index]) {
- DDXPointPtr newpoints;
- int *newwidths;
- ysizes[index] = (ysizes[index] + 8) * 2;
- newpoints = (DDXPointPtr) realloc(
- newspans->points,
- ysizes[index] * sizeof(DDXPointRec));
- newwidths = (int *) realloc(
- newspans->widths,
- ysizes[index] * sizeof(int));
- if (!newpoints || !newwidths)
- {
- int i;
-
- for (i = 0; i < ylength; i++)
- {
- free(yspans[i].points);
- free(yspans[i].widths);
- }
- free(yspans);
- free(ysizes);
- free(newpoints);
- free(newwidths);
- miDisposeSpanGroup (spanGroup);
- return;
- }
- newspans->points = newpoints;
- newspans->widths = newwidths;
- }
- newspans->points[newspans->count] = *points;
- newspans->widths[newspans->count] = *widths;
- (newspans->count)++;
- } /* if y value of span in range */
- } /* for j through spans */
- count += spans->count;
- free(spans->points);
- spans->points = NULL;
- free(spans->widths);
- spans->widths = NULL;
- } /* for i thorough Spans */
-
- /* Now sort by x and uniquify each bucket into the final array */
- points = malloc(count * sizeof(DDXPointRec));
- widths = malloc(count * sizeof(int));
- if (!points || !widths)
- {
- int i;
-
- for (i = 0; i < ylength; i++)
- {
- free(yspans[i].points);
- free(yspans[i].widths);
- }
- free(yspans);
- free(ysizes);
- free(points);
- free(widths);
- return;
- }
- count = 0;
- for (i = 0; i != ylength; i++) {
- int ycount = yspans[i].count;
- if (ycount > 0) {
- if (ycount > 1) {
- QuickSortSpansX(yspans[i].points, yspans[i].widths, ycount);
- count += UniquifySpansX
- (&(yspans[i]), &(points[count]), &(widths[count]));
- } else {
- points[count] = yspans[i].points[0];
- widths[count] = yspans[i].widths[0];
- count++;
- }
- free(yspans[i].points);
- free(yspans[i].widths);
- }
- }
-
- (*pGC->ops->FillSpans) (pDraw, pGC, count, points, widths, TRUE);
- free(points);
- free(widths);
- free(yspans);
- free(ysizes); /* use (DE)xalloc for these? */
- }
-
- spanGroup->count = 0;
- spanGroup->ymin = MAXSHORT;
- spanGroup->ymax = MINSHORT;
-}
+/***********************************************************
+
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1989 by 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 "misc.h"
+#include "pixmapstr.h"
+#include "gcstruct.h"
+#include "mispans.h"
+
+/*
+
+These routines maintain lists of Spans, in order to implement the
+``touch-each-pixel-once'' rules of wide lines and arcs.
+
+Written by Joel McCormack, Summer 1989.
+
+*/
+
+
+void miInitSpanGroup(SpanGroup *spanGroup)
+{
+ spanGroup->size = 0;
+ spanGroup->count = 0;
+ spanGroup->group = NULL;
+ spanGroup->ymin = MAXSHORT;
+ spanGroup->ymax = MINSHORT;
+} /* InitSpanGroup */
+
+#define YMIN(spans) (spans->points[0].y)
+#define YMAX(spans) (spans->points[spans->count-1].y)
+
+static void miSubtractSpans (SpanGroup *spanGroup, Spans *sub)
+{
+ int i, subCount, spansCount;
+ int ymin, ymax, xmin, xmax;
+ Spans *spans;
+ DDXPointPtr subPt, spansPt;
+ int *subWid, *spansWid;
+ int extra;
+
+ ymin = YMIN(sub);
+ ymax = YMAX(sub);
+ spans = spanGroup->group;
+ for (i = spanGroup->count; i; i--, spans++) {
+ if (YMIN(spans) <= ymax && ymin <= YMAX(spans)) {
+ subCount = sub->count;
+ subPt = sub->points;
+ subWid = sub->widths;
+ spansCount = spans->count;
+ spansPt = spans->points;
+ spansWid = spans->widths;
+ extra = 0;
+ for (;;)
+ {
+ while (spansCount && spansPt->y < subPt->y)
+ {
+ spansPt++; spansWid++; spansCount--;
+ }
+ if (!spansCount)
+ break;
+ while (subCount && subPt->y < spansPt->y)
+ {
+ subPt++; subWid++; subCount--;
+ }
+ if (!subCount)
+ break;
+ if (subPt->y == spansPt->y)
+ {
+ xmin = subPt->x;
+ xmax = xmin + *subWid;
+ if (xmin >= spansPt->x + *spansWid || spansPt->x >= xmax)
+ {
+ ;
+ }
+ else if (xmin <= spansPt->x)
+ {
+ if (xmax >= spansPt->x + *spansWid)
+ {
+ memmove (spansPt, spansPt + 1, sizeof *spansPt * (spansCount - 1));
+ memmove (spansWid, spansWid + 1, sizeof *spansWid * (spansCount - 1));
+ spansPt--;
+ spansWid--;
+ spans->count--;
+ extra++;
+ }
+ else
+ {
+ *spansWid = *spansWid - (xmax - spansPt->x);
+ spansPt->x = xmax;
+ }
+ }
+ else
+ {
+ if (xmax >= spansPt->x + *spansWid)
+ {
+ *spansWid = xmin - spansPt->x;
+ }
+ else
+ {
+ if (!extra) {
+ DDXPointPtr newPt;
+ int *newwid;
+
+#define EXTRA 8
+ newPt = (DDXPointPtr) realloc(spans->points, (spans->count + EXTRA) * sizeof (DDXPointRec));
+ if (!newPt)
+ break;
+ spansPt = newPt + (spansPt - spans->points);
+ spans->points = newPt;
+ newwid = (int *) realloc(spans->widths, (spans->count + EXTRA) * sizeof (int));
+ if (!newwid)
+ break;
+ spansWid = newwid + (spansWid - spans->widths);
+ spans->widths = newwid;
+ extra = EXTRA;
+ }
+ memmove (spansPt + 1, spansPt, sizeof *spansPt * (spansCount));
+ memmove (spansWid + 1, spansWid, sizeof *spansWid * (spansCount));
+ spans->count++;
+ extra--;
+ *spansWid = xmin - spansPt->x;
+ spansWid++;
+ spansPt++;
+ *spansWid = *spansWid - (xmax - spansPt->x);
+ spansPt->x = xmax;
+ }
+ }
+ }
+ spansPt++; spansWid++; spansCount--;
+ }
+ }
+ }
+}
+
+void miAppendSpans(SpanGroup *spanGroup, SpanGroup *otherGroup, Spans *spans)
+{
+ int ymin, ymax;
+ int spansCount;
+
+ spansCount = spans->count;
+ if (spansCount > 0) {
+ if (spanGroup->size == spanGroup->count) {
+ spanGroup->size = (spanGroup->size + 8) * 2;
+ spanGroup->group = (Spans *)
+ realloc(spanGroup->group, sizeof(Spans) * spanGroup->size);
+ }
+
+ spanGroup->group[spanGroup->count] = *spans;
+ (spanGroup->count)++;
+ ymin = spans->points[0].y;
+ if (ymin < spanGroup->ymin) spanGroup->ymin = ymin;
+ ymax = spans->points[spansCount - 1].y;
+ if (ymax > spanGroup->ymax) spanGroup->ymax = ymax;
+ if (otherGroup &&
+ otherGroup->ymin < ymax &&
+ ymin < otherGroup->ymax)
+ {
+ miSubtractSpans (otherGroup, spans);
+ }
+ }
+ else
+ {
+ free(spans->points);
+ free(spans->widths);
+ }
+} /* AppendSpans */
+
+void miFreeSpanGroup(SpanGroup *spanGroup)
+{
+ free(spanGroup->group);
+}
+
+static void QuickSortSpansX(
+ DDXPointRec points[],
+ int widths[],
+ int numSpans )
+{
+ int x;
+ int i, j, m;
+ DDXPointPtr r;
+
+/* Always called with numSpans > 1 */
+/* Sorts only by x, as all y should be the same */
+
+#define ExchangeSpans(a, b) \
+{ \
+ DDXPointRec tpt; \
+ int tw; \
+ \
+ tpt = points[a]; points[a] = points[b]; points[b] = tpt; \
+ tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \
+}
+
+ do {
+ if (numSpans < 9) {
+ /* Do insertion sort */
+ int xprev;
+
+ xprev = points[0].x;
+ i = 1;
+ do { /* while i != numSpans */
+ x = points[i].x;
+ if (xprev > x) {
+ /* points[i] is out of order. Move into proper location. */
+ DDXPointRec tpt;
+ int tw, k;
+
+ for (j = 0; x >= points[j].x; j++) {}
+ tpt = points[i];
+ tw = widths[i];
+ for (k = i; k != j; k--) {
+ points[k] = points[k-1];
+ widths[k] = widths[k-1];
+ }
+ points[j] = tpt;
+ widths[j] = tw;
+ x = points[i].x;
+ } /* if out of order */
+ xprev = x;
+ i++;
+ } while (i != numSpans);
+ return;
+ }
+
+ /* Choose partition element, stick in location 0 */
+ m = numSpans / 2;
+ if (points[m].x > points[0].x) ExchangeSpans(m, 0);
+ if (points[m].x > points[numSpans-1].x) ExchangeSpans(m, numSpans-1);
+ if (points[m].x > points[0].x) ExchangeSpans(m, 0);
+ x = points[0].x;
+
+ /* Partition array */
+ i = 0;
+ j = numSpans;
+ do {
+ r = &(points[i]);
+ do {
+ r++;
+ i++;
+ } while (i != numSpans && r->x < x);
+ r = &(points[j]);
+ do {
+ r--;
+ j--;
+ } while (x < r->x);
+ if (i < j) ExchangeSpans(i, j);
+ } while (i < j);
+
+ /* Move partition element back to middle */
+ ExchangeSpans(0, j);
+
+ /* Recurse */
+ if (numSpans-j-1 > 1)
+ QuickSortSpansX(&points[j+1], &widths[j+1], numSpans-j-1);
+ numSpans = j;
+ } while (numSpans > 1);
+} /* QuickSortSpans */
+
+
+static int UniquifySpansX(
+ Spans *spans,
+ DDXPointRec *newPoints,
+ int *newWidths )
+{
+ int newx1, newx2, oldpt, i, y;
+ DDXPointRec *oldPoints;
+ int *oldWidths;
+ int *startNewWidths;
+
+/* Always called with numSpans > 1 */
+/* Uniquify the spans, and stash them into newPoints and newWidths. Return the
+ number of unique spans. */
+
+
+ startNewWidths = newWidths;
+
+ oldPoints = spans->points;
+ oldWidths = spans->widths;
+
+ y = oldPoints->y;
+ newx1 = oldPoints->x;
+ newx2 = newx1 + *oldWidths;
+
+ for (i = spans->count-1; i != 0; i--) {
+ oldPoints++;
+ oldWidths++;
+ oldpt = oldPoints->x;
+ if (oldpt > newx2) {
+ /* Write current span, start a new one */
+ newPoints->x = newx1;
+ newPoints->y = y;
+ *newWidths = newx2 - newx1;
+ newPoints++;
+ newWidths++;
+ newx1 = oldpt;
+ newx2 = oldpt + *oldWidths;
+ } else {
+ /* extend current span, if old extends beyond new */
+ oldpt = oldpt + *oldWidths;
+ if (oldpt > newx2) newx2 = oldpt;
+ }
+ } /* for */
+
+ /* Write final span */
+ newPoints->x = newx1;
+ *newWidths = newx2 - newx1;
+ newPoints->y = y;
+
+ return (newWidths - startNewWidths) + 1;
+} /* UniquifySpansX */
+
+static void
+miDisposeSpanGroup (SpanGroup *spanGroup)
+{
+ int i;
+ Spans *spans;
+
+ for (i = 0; i < spanGroup->count; i++)
+ {
+ spans = spanGroup->group + i;
+ free(spans->points);
+ free(spans->widths);
+ }
+}
+
+void miFillUniqueSpanGroup(DrawablePtr pDraw, GCPtr pGC, SpanGroup *spanGroup)
+{
+ int i;
+ Spans *spans;
+ Spans *yspans;
+ int *ysizes;
+ int ymin, ylength;
+
+ /* Outgoing spans for one big call to FillSpans */
+ DDXPointPtr points;
+ int *widths;
+ int count;
+
+ if (spanGroup->count == 0) return;
+
+ if (spanGroup->count == 1) {
+ /* Already should be sorted, unique */
+ spans = spanGroup->group;
+ (*pGC->ops->FillSpans)
+ (pDraw, pGC, spans->count, spans->points, spans->widths, TRUE);
+ free(spans->points);
+ free(spans->widths);
+ }
+ else
+ {
+ /* Yuck. Gross. Radix sort into y buckets, then sort x and uniquify */
+ /* This seems to be the fastest thing to do. I've tried sorting on
+ both x and y at the same time rather than creating into all those
+ y buckets, but it was somewhat slower. */
+
+ ymin = spanGroup->ymin;
+ ylength = spanGroup->ymax - ymin + 1;
+
+ /* Allocate Spans for y buckets */
+ yspans = malloc(ylength * sizeof(Spans));
+ ysizes = malloc(ylength * sizeof (int));
+
+ if (!yspans || !ysizes)
+ {
+ free(yspans);
+ free(ysizes);
+ miDisposeSpanGroup (spanGroup);
+ return;
+ }
+
+ for (i = 0; i != ylength; i++) {
+ ysizes[i] = 0;
+ yspans[i].count = 0;
+ yspans[i].points = NULL;
+ yspans[i].widths = NULL;
+ }
+
+ /* Go through every single span and put it into the correct bucket */
+ count = 0;
+ for (i = 0, spans = spanGroup->group;
+ i != spanGroup->count;
+ i++, spans++) {
+ int index;
+ int j;
+
+ for (j = 0, points = spans->points, widths = spans->widths;
+ j != spans->count;
+ j++, points++, widths++) {
+ index = points->y - ymin;
+ if (index >= 0 && index < ylength) {
+ Spans *newspans = &(yspans[index]);
+ if (newspans->count == ysizes[index]) {
+ DDXPointPtr newpoints;
+ int *newwidths;
+ ysizes[index] = (ysizes[index] + 8) * 2;
+ newpoints = (DDXPointPtr) realloc(
+ newspans->points,
+ ysizes[index] * sizeof(DDXPointRec));
+ newwidths = (int *) realloc(
+ newspans->widths,
+ ysizes[index] * sizeof(int));
+ if (!newpoints || !newwidths)
+ {
+ int i;
+
+ for (i = 0; i < ylength; i++)
+ {
+ free(yspans[i].points);
+ free(yspans[i].widths);
+ }
+ free(yspans);
+ free(ysizes);
+ free(newpoints);
+ free(newwidths);
+ miDisposeSpanGroup (spanGroup);
+ return;
+ }
+ newspans->points = newpoints;
+ newspans->widths = newwidths;
+ }
+ newspans->points[newspans->count] = *points;
+ newspans->widths[newspans->count] = *widths;
+ (newspans->count)++;
+ } /* if y value of span in range */
+ } /* for j through spans */
+ count += spans->count;
+ free(spans->points);
+ spans->points = NULL;
+ free(spans->widths);
+ spans->widths = NULL;
+ } /* for i thorough Spans */
+
+ /* Now sort by x and uniquify each bucket into the final array */
+ points = malloc(count * sizeof(DDXPointRec));
+ widths = malloc(count * sizeof(int));
+ if (!points || !widths)
+ {
+ int i;
+
+ for (i = 0; i < ylength; i++)
+ {
+ free(yspans[i].points);
+ free(yspans[i].widths);
+ }
+ free(yspans);
+ free(ysizes);
+ free(points);
+ free(widths);
+ return;
+ }
+ count = 0;
+ for (i = 0; i != ylength; i++) {
+ int ycount = yspans[i].count;
+ if (ycount > 0) {
+ if (ycount > 1) {
+ QuickSortSpansX(yspans[i].points, yspans[i].widths, ycount);
+ count += UniquifySpansX
+ (&(yspans[i]), &(points[count]), &(widths[count]));
+ } else {
+ points[count] = yspans[i].points[0];
+ widths[count] = yspans[i].widths[0];
+ count++;
+ }
+ free(yspans[i].points);
+ free(yspans[i].widths);
+ }
+ }
+
+ (*pGC->ops->FillSpans) (pDraw, pGC, count, points, widths, TRUE);
+ free(points);
+ free(widths);
+ free(yspans);
+ free(ysizes); /* use (DE)xalloc for these? */
+ }
+
+ spanGroup->count = 0;
+ spanGroup->ymin = MAXSHORT;
+ spanGroup->ymax = MINSHORT;
+}
diff --git a/xorg-server/mi/mizerline.c b/xorg-server/mi/mizerline.c
index 709e93422..7077b5198 100644
--- a/xorg-server/mi/mizerline.c
+++ b/xorg-server/mi/mizerline.c
@@ -1,381 +1,381 @@
-/***********************************************************
-
-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 "misc.h"
-#include "scrnintstr.h"
-#include "gcstruct.h"
-#include "windowstr.h"
-#include "pixmap.h"
-#include "mi.h"
-#include "miline.h"
-
-/* Draw lineSolid, fillStyle-independent zero width lines.
- *
- * Must keep X and Y coordinates in "ints" at least until after they're
- * translated and clipped to accomodate CoordModePrevious lines with very
- * large coordinates.
- *
- * Draws the same pixels regardless of sign(dx) or sign(dy).
- *
- * Ken Whaley
- *
- */
-
-/* largest positive value that can fit into a component of a point.
- * Assumes that the point structure is {type x, y;} where type is
- * a signed type.
- */
-#define MAX_COORDINATE ((1 << (((sizeof(DDXPointRec) >> 1) << 3) - 1)) - 1)
-
-#define MI_OUTPUT_POINT(xx, yy)\
-{\
- if ( !new_span && yy == current_y)\
- {\
- if (xx < spans->x)\
- spans->x = xx;\
- ++*widths;\
- }\
- else\
- {\
- ++Nspans;\
- ++spans;\
- ++widths;\
- spans->x = xx;\
- spans->y = yy;\
- *widths = 1;\
- current_y = yy;\
- new_span = FALSE;\
- }\
-}
-
-void
-miZeroLine(
- DrawablePtr pDraw,
- GCPtr pGC,
- int mode, /* Origin or Previous */
- int npt, /* number of points */
- DDXPointPtr pptInit)
-{
- int Nspans, current_y = 0;
- DDXPointPtr ppt;
- DDXPointPtr pspanInit, spans;
- int *pwidthInit, *widths, list_len;
- int xleft, ytop, xright, ybottom;
- int new_x1, new_y1, new_x2, new_y2;
- int x = 0, y = 0, x1, y1, x2, y2, xstart, ystart;
- int oc1, oc2;
- int result;
- int pt1_clipped, pt2_clipped = 0;
- Bool new_span;
- int signdx, signdy;
- int clipdx, clipdy;
- int width, height;
- int adx, ady;
- int octant;
- unsigned int bias = miGetZeroLineBias(pDraw->pScreen);
- int e, e1, e2, e3; /* Bresenham error terms */
- int length; /* length of lines == # of pixels on major axis */
-
- xleft = pDraw->x;
- ytop = pDraw->y;
- xright = pDraw->x + pDraw->width - 1;
- ybottom = pDraw->y + pDraw->height - 1;
-
- if (!pGC->miTranslate)
- {
- /* do everything in drawable-relative coordinates */
- xleft = 0;
- ytop = 0;
- xright -= pDraw->x;
- ybottom -= pDraw->y;
- }
-
- /* it doesn't matter whether we're in drawable or screen coordinates,
- * FillSpans simply cannot take starting coordinates outside of the
- * range of a DDXPointRec component.
- */
- if (xright > MAX_COORDINATE)
- xright = MAX_COORDINATE;
- if (ybottom > MAX_COORDINATE)
- ybottom = MAX_COORDINATE;
-
- /* since we're clipping to the drawable's boundaries & coordinate
- * space boundaries, we're guaranteed that the larger of width/height
- * is the longest span we'll need to output
- */
- width = xright - xleft + 1;
- height = ybottom - ytop + 1;
- list_len = (height >= width) ? height : width;
- pspanInit = malloc(list_len * sizeof(DDXPointRec));
- pwidthInit = malloc(list_len * sizeof(int));
- if (!pspanInit || !pwidthInit) {
- free(pspanInit);
- free(pwidthInit);
- return;
- }
- Nspans = 0;
- new_span = TRUE;
- spans = pspanInit - 1;
- widths = pwidthInit - 1;
- ppt = pptInit;
-
- xstart = ppt->x;
- ystart = ppt->y;
- if (pGC->miTranslate)
- {
- xstart += pDraw->x;
- ystart += pDraw->y;
- }
-
- /* x2, y2, oc2 copied to x1, y1, oc1 at top of loop to simplify
- * iteration logic
- */
- x2 = xstart;
- y2 = ystart;
- oc2 = 0;
- MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
-
- while (--npt > 0)
- {
- if (Nspans > 0)
- (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit,
- pwidthInit, FALSE);
- Nspans = 0;
- new_span = TRUE;
- spans = pspanInit - 1;
- widths = pwidthInit - 1;
-
- x1 = x2;
- y1 = y2;
- oc1 = oc2;
- ++ppt;
-
- x2 = ppt->x;
- y2 = ppt->y;
- if (pGC->miTranslate && (mode != CoordModePrevious))
- {
- x2 += pDraw->x;
- y2 += pDraw->y;
- }
- else if (mode == CoordModePrevious)
- {
- x2 += x1;
- y2 += y1;
- }
-
- oc2 = 0;
- MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
-
- CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
-
- if (adx > ady)
- {
- e1 = ady << 1;
- e2 = e1 - (adx << 1);
- e = e1 - adx;
- length = adx; /* don't draw endpoint in main loop */
-
- FIXUP_ERROR(e, octant, bias);
-
- new_x1 = x1;
- new_y1 = y1;
- new_x2 = x2;
- new_y2 = y2;
- pt1_clipped = 0;
- pt2_clipped = 0;
-
- if ((oc1 | oc2) != 0)
- {
- result = miZeroClipLine(xleft, ytop, xright, ybottom,
- &new_x1, &new_y1, &new_x2, &new_y2,
- adx, ady,
- &pt1_clipped, &pt2_clipped,
- octant, bias, oc1, oc2);
- if (result == -1)
- continue;
-
- length = abs(new_x2 - new_x1);
-
- /* if we've clipped the endpoint, always draw the full length
- * of the segment, because then the capstyle doesn't matter
- */
- if (pt2_clipped)
- length++;
-
- if (pt1_clipped)
- {
- /* must calculate new error terms */
- clipdx = abs(new_x1 - x1);
- clipdy = abs(new_y1 - y1);
- e += (clipdy * e2) + ((clipdx - clipdy) * e1);
- }
- }
-
- /* draw the segment */
-
- x = new_x1;
- y = new_y1;
-
- e3 = e2 - e1;
- e = e - e1;
-
- while (length--)
- {
- MI_OUTPUT_POINT(x, y);
- e += e1;
- if (e >= 0)
- {
- y += signdy;
- e += e3;
- }
- x += signdx;
- }
- }
- else /* Y major line */
- {
- e1 = adx << 1;
- e2 = e1 - (ady << 1);
- e = e1 - ady;
- length = ady; /* don't draw endpoint in main loop */
-
- SetYMajorOctant(octant);
- FIXUP_ERROR(e, octant, bias);
-
- new_x1 = x1;
- new_y1 = y1;
- new_x2 = x2;
- new_y2 = y2;
- pt1_clipped = 0;
- pt2_clipped = 0;
-
- if ((oc1 | oc2) != 0)
- {
- result = miZeroClipLine(xleft, ytop, xright, ybottom,
- &new_x1, &new_y1, &new_x2, &new_y2,
- adx, ady,
- &pt1_clipped, &pt2_clipped,
- octant, bias, oc1, oc2);
- if (result == -1)
- continue;
-
- length = abs(new_y2 - new_y1);
-
- /* if we've clipped the endpoint, always draw the full length
- * of the segment, because then the capstyle doesn't matter
- */
- if (pt2_clipped)
- length++;
-
- if (pt1_clipped)
- {
- /* must calculate new error terms */
- clipdx = abs(new_x1 - x1);
- clipdy = abs(new_y1 - y1);
- e += (clipdx * e2) + ((clipdy - clipdx) * e1);
- }
- }
-
- /* draw the segment */
-
- x = new_x1;
- y = new_y1;
-
- e3 = e2 - e1;
- e = e - e1;
-
- while (length--)
- {
- MI_OUTPUT_POINT(x, y);
- e += e1;
- if (e >= 0)
- {
- x += signdx;
- e += e3;
- }
- y += signdy;
- }
- }
- }
-
- /* only do the capnotlast check on the last segment
- * and only if the endpoint wasn't clipped. And then, if the last
- * point is the same as the first point, do not draw it, unless the
- * line is degenerate
- */
- if ( (! pt2_clipped) && (pGC->capStyle != CapNotLast) &&
- (((xstart != x2) || (ystart != y2)) || (ppt == pptInit + 1)))
- {
- MI_OUTPUT_POINT(x, y);
- }
-
- if (Nspans > 0)
- (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit,
- pwidthInit, FALSE);
-
- free(pwidthInit);
- free(pspanInit);
-}
-
-void
-miZeroDashLine(
- DrawablePtr dst,
- GCPtr pgc,
- int mode,
- int nptInit, /* number of points in polyline */
- DDXPointRec *pptInit /* points in the polyline */
- )
-{
- /* XXX kludge until real zero-width dash code is written */
- pgc->lineWidth = 1;
- miWideDash (dst, pgc, mode, nptInit, pptInit);
- pgc->lineWidth = 0;
-}
+/***********************************************************
+
+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 "misc.h"
+#include "scrnintstr.h"
+#include "gcstruct.h"
+#include "windowstr.h"
+#include "pixmap.h"
+#include "mi.h"
+#include "miline.h"
+
+/* Draw lineSolid, fillStyle-independent zero width lines.
+ *
+ * Must keep X and Y coordinates in "ints" at least until after they're
+ * translated and clipped to accomodate CoordModePrevious lines with very
+ * large coordinates.
+ *
+ * Draws the same pixels regardless of sign(dx) or sign(dy).
+ *
+ * Ken Whaley
+ *
+ */
+
+/* largest positive value that can fit into a component of a point.
+ * Assumes that the point structure is {type x, y;} where type is
+ * a signed type.
+ */
+#define MAX_COORDINATE ((1 << (((sizeof(DDXPointRec) >> 1) << 3) - 1)) - 1)
+
+#define MI_OUTPUT_POINT(xx, yy)\
+{\
+ if ( !new_span && yy == current_y)\
+ {\
+ if (xx < spans->x)\
+ spans->x = xx;\
+ ++*widths;\
+ }\
+ else\
+ {\
+ ++Nspans;\
+ ++spans;\
+ ++widths;\
+ spans->x = xx;\
+ spans->y = yy;\
+ *widths = 1;\
+ current_y = yy;\
+ new_span = FALSE;\
+ }\
+}
+
+void
+miZeroLine(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int mode, /* Origin or Previous */
+ int npt, /* number of points */
+ DDXPointPtr pptInit)
+{
+ int Nspans, current_y = 0;
+ DDXPointPtr ppt;
+ DDXPointPtr pspanInit, spans;
+ int *pwidthInit, *widths, list_len;
+ int xleft, ytop, xright, ybottom;
+ int new_x1, new_y1, new_x2, new_y2;
+ int x = 0, y = 0, x1, y1, x2, y2, xstart, ystart;
+ int oc1, oc2;
+ int result;
+ int pt1_clipped, pt2_clipped = 0;
+ Bool new_span;
+ int signdx, signdy;
+ int clipdx, clipdy;
+ int width, height;
+ int adx, ady;
+ int octant;
+ unsigned int bias = miGetZeroLineBias(pDraw->pScreen);
+ int e, e1, e2, e3; /* Bresenham error terms */
+ int length; /* length of lines == # of pixels on major axis */
+
+ xleft = pDraw->x;
+ ytop = pDraw->y;
+ xright = pDraw->x + pDraw->width - 1;
+ ybottom = pDraw->y + pDraw->height - 1;
+
+ if (!pGC->miTranslate)
+ {
+ /* do everything in drawable-relative coordinates */
+ xleft = 0;
+ ytop = 0;
+ xright -= pDraw->x;
+ ybottom -= pDraw->y;
+ }
+
+ /* it doesn't matter whether we're in drawable or screen coordinates,
+ * FillSpans simply cannot take starting coordinates outside of the
+ * range of a DDXPointRec component.
+ */
+ if (xright > MAX_COORDINATE)
+ xright = MAX_COORDINATE;
+ if (ybottom > MAX_COORDINATE)
+ ybottom = MAX_COORDINATE;
+
+ /* since we're clipping to the drawable's boundaries & coordinate
+ * space boundaries, we're guaranteed that the larger of width/height
+ * is the longest span we'll need to output
+ */
+ width = xright - xleft + 1;
+ height = ybottom - ytop + 1;
+ list_len = (height >= width) ? height : width;
+ pspanInit = malloc(list_len * sizeof(DDXPointRec));
+ pwidthInit = malloc(list_len * sizeof(int));
+ if (!pspanInit || !pwidthInit) {
+ free(pspanInit);
+ free(pwidthInit);
+ return;
+ }
+ Nspans = 0;
+ new_span = TRUE;
+ spans = pspanInit - 1;
+ widths = pwidthInit - 1;
+ ppt = pptInit;
+
+ xstart = ppt->x;
+ ystart = ppt->y;
+ if (pGC->miTranslate)
+ {
+ xstart += pDraw->x;
+ ystart += pDraw->y;
+ }
+
+ /* x2, y2, oc2 copied to x1, y1, oc1 at top of loop to simplify
+ * iteration logic
+ */
+ x2 = xstart;
+ y2 = ystart;
+ oc2 = 0;
+ MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
+
+ while (--npt > 0)
+ {
+ if (Nspans > 0)
+ (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit,
+ pwidthInit, FALSE);
+ Nspans = 0;
+ new_span = TRUE;
+ spans = pspanInit - 1;
+ widths = pwidthInit - 1;
+
+ x1 = x2;
+ y1 = y2;
+ oc1 = oc2;
+ ++ppt;
+
+ x2 = ppt->x;
+ y2 = ppt->y;
+ if (pGC->miTranslate && (mode != CoordModePrevious))
+ {
+ x2 += pDraw->x;
+ y2 += pDraw->y;
+ }
+ else if (mode == CoordModePrevious)
+ {
+ x2 += x1;
+ y2 += y1;
+ }
+
+ oc2 = 0;
+ MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
+
+ CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
+
+ if (adx > ady)
+ {
+ e1 = ady << 1;
+ e2 = e1 - (adx << 1);
+ e = e1 - adx;
+ length = adx; /* don't draw endpoint in main loop */
+
+ FIXUP_ERROR(e, octant, bias);
+
+ new_x1 = x1;
+ new_y1 = y1;
+ new_x2 = x2;
+ new_y2 = y2;
+ pt1_clipped = 0;
+ pt2_clipped = 0;
+
+ if ((oc1 | oc2) != 0)
+ {
+ result = miZeroClipLine(xleft, ytop, xright, ybottom,
+ &new_x1, &new_y1, &new_x2, &new_y2,
+ adx, ady,
+ &pt1_clipped, &pt2_clipped,
+ octant, bias, oc1, oc2);
+ if (result == -1)
+ continue;
+
+ length = abs(new_x2 - new_x1);
+
+ /* if we've clipped the endpoint, always draw the full length
+ * of the segment, because then the capstyle doesn't matter
+ */
+ if (pt2_clipped)
+ length++;
+
+ if (pt1_clipped)
+ {
+ /* must calculate new error terms */
+ clipdx = abs(new_x1 - x1);
+ clipdy = abs(new_y1 - y1);
+ e += (clipdy * e2) + ((clipdx - clipdy) * e1);
+ }
+ }
+
+ /* draw the segment */
+
+ x = new_x1;
+ y = new_y1;
+
+ e3 = e2 - e1;
+ e = e - e1;
+
+ while (length--)
+ {
+ MI_OUTPUT_POINT(x, y);
+ e += e1;
+ if (e >= 0)
+ {
+ y += signdy;
+ e += e3;
+ }
+ x += signdx;
+ }
+ }
+ else /* Y major line */
+ {
+ e1 = adx << 1;
+ e2 = e1 - (ady << 1);
+ e = e1 - ady;
+ length = ady; /* don't draw endpoint in main loop */
+
+ SetYMajorOctant(octant);
+ FIXUP_ERROR(e, octant, bias);
+
+ new_x1 = x1;
+ new_y1 = y1;
+ new_x2 = x2;
+ new_y2 = y2;
+ pt1_clipped = 0;
+ pt2_clipped = 0;
+
+ if ((oc1 | oc2) != 0)
+ {
+ result = miZeroClipLine(xleft, ytop, xright, ybottom,
+ &new_x1, &new_y1, &new_x2, &new_y2,
+ adx, ady,
+ &pt1_clipped, &pt2_clipped,
+ octant, bias, oc1, oc2);
+ if (result == -1)
+ continue;
+
+ length = abs(new_y2 - new_y1);
+
+ /* if we've clipped the endpoint, always draw the full length
+ * of the segment, because then the capstyle doesn't matter
+ */
+ if (pt2_clipped)
+ length++;
+
+ if (pt1_clipped)
+ {
+ /* must calculate new error terms */
+ clipdx = abs(new_x1 - x1);
+ clipdy = abs(new_y1 - y1);
+ e += (clipdx * e2) + ((clipdy - clipdx) * e1);
+ }
+ }
+
+ /* draw the segment */
+
+ x = new_x1;
+ y = new_y1;
+
+ e3 = e2 - e1;
+ e = e - e1;
+
+ while (length--)
+ {
+ MI_OUTPUT_POINT(x, y);
+ e += e1;
+ if (e >= 0)
+ {
+ x += signdx;
+ e += e3;
+ }
+ y += signdy;
+ }
+ }
+ }
+
+ /* only do the capnotlast check on the last segment
+ * and only if the endpoint wasn't clipped. And then, if the last
+ * point is the same as the first point, do not draw it, unless the
+ * line is degenerate
+ */
+ if ( (! pt2_clipped) && (pGC->capStyle != CapNotLast) &&
+ (((xstart != x2) || (ystart != y2)) || (ppt == pptInit + 1)))
+ {
+ MI_OUTPUT_POINT(x, y);
+ }
+
+ if (Nspans > 0)
+ (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit,
+ pwidthInit, FALSE);
+
+ free(pwidthInit);
+ free(pspanInit);
+}
+
+void
+miZeroDashLine(
+ DrawablePtr dst,
+ GCPtr pgc,
+ int mode,
+ int nptInit, /* number of points in polyline */
+ DDXPointRec *pptInit /* points in the polyline */
+ )
+{
+ /* XXX kludge until real zero-width dash code is written */
+ pgc->lineWidth = 1;
+ miWideDash (dst, pgc, mode, nptInit, pptInit);
+ pgc->lineWidth = 0;
+}