diff options
Diffstat (limited to 'xorg-server/mi')
-rw-r--r-- | xorg-server/mi/micmap.c | 1362 | ||||
-rw-r--r-- | xorg-server/mi/midispcur.c | 1168 | ||||
-rw-r--r-- | xorg-server/mi/mieq.c | 938 | ||||
-rw-r--r-- | xorg-server/mi/mipointer.c | 1396 | ||||
-rw-r--r-- | xorg-server/mi/mipointrst.h | 114 | ||||
-rw-r--r-- | xorg-server/mi/mispans.c | 1054 | ||||
-rw-r--r-- | xorg-server/mi/mizerline.c | 762 |
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; +} |