Logo Search packages:      
Sourcecode: ia32-libs-gtk version File versions  Download package

cursor.c

/*
 * $Id: cursor.c,v 1.6 2005/07/03 07:00:56 daniels Exp $
 *
 * Copyright © 2002 Keith Packard
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Keith Packard not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Keith Packard makes no
 * representations about the suitability of this software for any purpose.  It
 * is provided "as is" without express or implied warranty.
 *
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

#include "xcursorint.h"
#include <X11/Xlibint.h>
#include <X11/Xutil.h>

XcursorCursors *
XcursorCursorsCreate (Display *dpy, int size)
{
    XcursorCursors  *cursors;

    cursors = malloc (sizeof (XcursorCursors) +
                  size * sizeof (Cursor));
    if (!cursors)
      return 0;
    cursors->ref = 1;
    cursors->dpy = dpy;
    cursors->ncursor = 0;
    cursors->cursors = (Cursor *) (cursors + 1);
    return cursors;
}

void
XcursorCursorsDestroy (XcursorCursors *cursors)
{
    int         n;

    --cursors->ref;
    if (cursors->ref > 0)
      return;
    
    for (n = 0; n < cursors->ncursor; n++)
      XFreeCursor (cursors->dpy, cursors->cursors[n]);
    free (cursors);
}

XcursorAnimate *
XcursorAnimateCreate (XcursorCursors *cursors)
{
    XcursorAnimate  *animate;

    animate = malloc (sizeof (XcursorAnimate));
    if (!animate)
      return 0;
    animate->cursors = cursors;
    cursors->ref++;
    animate->sequence = 0;
    return animate;
}

void
XcursorAnimateDestroy (XcursorAnimate *animate)
{
    XcursorCursorsDestroy (animate->cursors);
    free (animate);
}

Cursor
XcursorAnimateNext (XcursorAnimate *animate)
{
    Cursor  cursor = animate->cursors->cursors[animate->sequence++];

    if (animate->sequence >= animate->cursors->ncursor)
      animate->sequence = 0;
    return cursor;
}

static int
nativeByteOrder (void)
{
    int     x = 1;

    return (*((char *) &x) == 1) ? LSBFirst : MSBFirst;
}

static XcursorUInt
_XcursorPixelBrightness (XcursorPixel p)
{
    XcursorPixel    alpha = p >> 24;
    XcursorPixel    r, g, b;

    if (!alpha)
      return 0;
    r = ((p >> 8) & 0xff00) / alpha;
    if (r > 0xff) r = 0xff;
    g = ((p >> 0) & 0xff00) / alpha;
    if (g > 0xff) g = 0xff;
    b = ((p << 8) & 0xff00) / alpha;
    if (b > 0xff) b = 0xff;
    return (r * 153 + g * 301 + b * 58) >> 9;
}

static unsigned short
_XcursorDivideAlpha (XcursorUInt value, XcursorUInt alpha)
{
    if (!alpha)
      return 0;
    value = value * 255 / alpha;
    if (value > 255)
      value = 255;
    return value | (value << 8);
}

static void
_XcursorPixelToColor (XcursorPixel p, XColor *color)
{
    XcursorPixel    alpha = p >> 24;

    color->pixel = 0;
    color->red =   _XcursorDivideAlpha ((p >> 16) & 0xff, alpha);
    color->green = _XcursorDivideAlpha ((p >>  8) & 0xff, alpha);
    color->blue =  _XcursorDivideAlpha ((p >>  0) & 0xff, alpha);
    color->flags = DoRed|DoGreen|DoBlue;
}

#undef DEBUG_IMAGE
#ifdef DEBUG_IMAGE
static void
_XcursorDumpImage (XImage *image)
{
    FILE    *f = fopen ("/tmp/images", "a");
    int         x, y;
    if (!f)
      return;
    fprintf (f, "%d x %x\n", image->width, image->height);
    for (y = 0; y < image->height; y++)
    {
      for (x = 0; x < image->width; x++)
          fprintf (f, "%c", XGetPixel (image, x, y) ? '*' : ' ');
      fprintf (f, "\n");
    }
    fflush (f);
    fclose (f);
}

static void
_XcursorDumpColor (XColor *color, char *name)
{
    FILE    *f = fopen ("/tmp/images", "a");
    fprintf (f, "%s: %x %x %x\n", name,
           color->red, color->green, color->blue);
    fflush (f);
    fclose (f);
}
#endif

static int
_XcursorCompareRed (const void *a, const void *b)
{
    const XcursorPixel    *ap = a, *bp = b;

    return (int) (((*ap >> 16) & 0xff) - ((*bp >> 16) & 0xff));
}

static int
_XcursorCompareGreen (const void *a, const void *b)
{
    const XcursorPixel    *ap = a, *bp = b;

    return (int) (((*ap >> 8) & 0xff) - ((*bp >> 8) & 0xff));
}

static int
_XcursorCompareBlue (const void *a, const void *b)
{
    const XcursorPixel    *ap = a, *bp = b;

    return (int) (((*ap >> 0) & 0xff) - ((*bp >> 0) & 0xff));
}

static XcursorPixel
_XcursorAverageColor (XcursorPixel *pixels, int npixels)
{
    XcursorPixel    p;
    XcursorPixel    red, green, blue;
    int               n = npixels;

    blue = green = red = 0;
    while (n--)
    {
      p = *pixels++;
      red += (p >> 16) & 0xff;
      green += (p >> 8) & 0xff;
      blue += (p >> 0) & 0xff;
    }
    if (!n)
      return 0;
    return (0xff << 24) | ((red/npixels) << 16) | ((green/npixels) << 8) | (blue/npixels);
}

typedef struct XcursorCoreCursor {
    XImage  *src_image;
    XImage  *msk_image;
    XColor  on_color;
    XColor  off_color;
} XcursorCoreCursor;

static Bool
_XcursorHeckbertMedianCut (const XcursorImage *image, XcursorCoreCursor *core)
{
    XImage      *src_image = core->src_image, *msk_image = core->msk_image;
    int               npixels = image->width * image->height;
    int               ncolors;
    int               n;
    XcursorPixel    *po, *pn, *pc;
    XcursorPixel    p;
    XcursorPixel    red, green, blue, alpha;
    XcursorPixel    max_red, min_red, max_green, min_green, max_blue, min_blue;
    XcursorPixel    *temp, *pixels, *colors;
    int               split;
    XcursorPixel    leftColor, centerColor, rightColor;
    int               (*compare) (const void *, const void *);
    int               x, y;
    
    /*
     * Temp space for converted image and converted colors
     */
    temp = malloc (npixels * sizeof (XcursorPixel) * 2);
    if (!temp)
      return False;
    
    pixels = temp;
    colors = pixels + npixels;
    
    /*
     * Convert to 2-value alpha and build
     * array of opaque color values and an
     */
    po = image->pixels;
    pn = pixels;
    pc = colors;
    max_blue = max_green = max_red = 0;
    min_blue = min_green = min_red = 255;
    n = npixels;
    while (n--)
    {
      p = *po++;
      alpha = (p >> 24) & 0xff;
      red = (p >> 16) & 0xff;
      green = (p >> 8) & 0xff;
      blue = (p >> 0) & 0xff;
      if (alpha >= 0x80)
      {
          red = red * 255 / alpha;
          green = green * 255 / alpha;
          blue = blue * 255 / alpha;
          if (red < min_red) min_red = red;
          if (red > max_red) max_red = red;
          if (green < min_green) min_green = green;
          if (green > max_green) max_green = green;
          if (blue < min_blue) min_blue = blue;
          if (blue > max_blue) max_blue = blue;
          p = ((0xff << 24) | (red << 16) | 
             (green << 8) | (blue << 0));
          *pc++ = p;
      }
      else
          p = 0;
      *pn++ = p;
    }
    ncolors = pc - colors;
    
    /*
     * Compute longest dimension and sort
     */
    if ((max_green - min_green) >= (max_red - min_red) &&
      (max_green - min_green) >= (max_blue - min_blue))
      compare = _XcursorCompareGreen;
    else if ((max_red - min_red) >= (max_blue - min_blue))
      compare = _XcursorCompareRed;
    else
      compare = _XcursorCompareBlue;
    qsort (colors, ncolors, sizeof (XcursorPixel), compare);
    /*
     * Compute average colors on both sides of the cut
     */
    split = ncolors >> 1;
    leftColor  = _XcursorAverageColor (colors, split);
    centerColor = colors[split];
    rightColor = _XcursorAverageColor (colors + split, ncolors - split);
    /*
     * Select best color for each pixel
     */
    pn = pixels;
    for (y = 0; y < image->height; y++)
      for (x = 0; x < image->width; x++)
      {
          p = *pn++;
          if (p & 0xff000000)
          {
            XPutPixel (msk_image, x, y, 1);
            if ((*compare) (&p, &centerColor) >= 0)
                XPutPixel (src_image, x, y, 0);
            else
                XPutPixel (src_image, x, y, 1);
          }
          else
          {
            XPutPixel (msk_image, x, y, 0);
            XPutPixel (src_image, x, y, 0);
          }
      }
    free (temp);
    _XcursorPixelToColor (rightColor, &core->off_color);
    _XcursorPixelToColor (leftColor, &core->on_color);
    return True;
}

#if 0
#define DITHER_DIM  4
static XcursorPixel orderedDither[4][4] = {
    {  1,  9,  3, 11 },
    { 13,  5, 15,  7 },
    {  4, 12,  2, 10 },
    { 16,  8, 14,  6 }
};
#else
#define DITHER_DIM 2
static XcursorPixel orderedDither[2][2] = {
    {  1,  3,  },
    {  4,  2,  },
};
#endif

#define DITHER_SIZE  ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1)

static Bool
_XcursorBayerOrderedDither (const XcursorImage *image, XcursorCoreCursor *core)
{
    int               x, y;
    XcursorPixel    *pixel, p;
    XcursorPixel    a, i, d;

    pixel = image->pixels;
    for (y = 0; y < image->height; y++)
      for (x = 0; x < image->width; x++)
      {
          p = *pixel++;
          a = ((p >> 24) * DITHER_SIZE + 127) / 255;
          i = (_XcursorPixelBrightness (p) * DITHER_SIZE + 127) / 255;
          d = orderedDither[y&(DITHER_DIM-1)][x&(DITHER_DIM-1)];
          if (a > d)
          {
            XPutPixel (core->msk_image, x, y, 1);
            if (i > d)
                XPutPixel (core->src_image, x, y, 0);   /* white */
            else
                XPutPixel (core->src_image, x, y, 1);   /* black */
          }
          else
          {
            XPutPixel (core->msk_image, x, y, 0);
            XPutPixel (core->src_image, x, y, 0);
          }
      }
    core->on_color.red = 0;
    core->on_color.green = 0;
    core->on_color.blue = 0;
    core->off_color.red = 0xffff;
    core->off_color.green = 0xffff;
    core->off_color.blue = 0xffff;
    return True;
}

static Bool
_XcursorFloydSteinberg (const XcursorImage *image, XcursorCoreCursor *core)
{
    int               *aPicture, *iPicture, *aP, *iP;
    XcursorPixel    *pixel, p;
    int               aR, iR, aA, iA;
    int               npixels = image->width * image->height;
    int               n;
    int               right = 1;
    int               belowLeft = image->width - 1;
    int               below = image->width;
    int               belowRight = image->width + 1;
    int               iError, aError;
    int               iErrorRight, aErrorRight;
    int               iErrorBelowLeft, aErrorBelowLeft;
    int               iErrorBelow, aErrorBelow;
    int               iErrorBelowRight, aErrorBelowRight;
    int               x, y;
    int               max_inten, min_inten, mean_inten;

    iPicture = malloc (npixels * sizeof (int) * 2);
    if (!iPicture)
      return False;
    aPicture = iPicture + npixels;

    /*
     * Compute raw gray and alpha arrays
     */
    pixel = image->pixels;
    iP = iPicture;
    aP = aPicture;
    n = npixels;
    max_inten = 0;
    min_inten = 0xff;
    while (n--)
    {
      p = *pixel++;
      *aP++ = (int) (p >> 24);
      iR = (int) _XcursorPixelBrightness (p);
      if (iR > max_inten) max_inten = iR;
      if (iR < min_inten) min_inten = iR;
      *iP++ = iR;
    }
    /*
     * Draw the image while diffusing the error
     */
    iP = iPicture;
    aP = aPicture;
    mean_inten = (max_inten + min_inten + 1) >> 1;
    for (y = 0; y < image->height; y++)
      for (x = 0; x < image->width; x++)
      {
          aR = *aP;
          iR = *iP;
          if (aR >= 0x80)
          {
            XPutPixel (core->msk_image, x, y, 1);
            aA = 0xff;
          }
          else
          {
            XPutPixel (core->msk_image, x, y, 0);
            aA = 0x00;
          }
          if (iR >= mean_inten)
          {
            XPutPixel (core->src_image, x, y, 0);
            iA = max_inten;
          }
          else
          {
            XPutPixel (core->src_image, x, y, 1);
            iA = min_inten;
          }
          iError = iR - iA;
          aError = aR - aA;
          iErrorRight = (iError * 7) >> 4;
          iErrorBelowLeft = (iError * 3) >> 4;
          iErrorBelow = (iError * 5) >> 4;
          iErrorBelowRight = (iError - iErrorRight - 
                        iErrorBelowLeft - iErrorBelow);
          aErrorRight = (aError * 7) >> 4;
          aErrorBelowLeft = (aError * 3) >> 4;
          aErrorBelow = (aError * 5) >> 4;
          aErrorBelowRight = (aError - aErrorRight - 
                        aErrorBelowLeft - aErrorBelow);
          if (x < image->width - 1)
          {
            iP[right] += iErrorRight; 
            aP[right] += aErrorRight;
          }
          if (y < image->height - 1)
          {
            if (x)
            {
                iP[belowLeft] += iErrorBelowLeft;
                aP[belowLeft] += aErrorBelowLeft;
            }
            iP[below] += iErrorBelow;
            aP[below] += aErrorBelow;
            if (x < image->width - 1)
            {
                iP[belowRight] += iErrorBelowRight;
                aP[belowRight] += aErrorBelowRight;
            }
          }
          aP++;
          iP++;
      }
    free (iPicture);
    core->on_color.red =
    core->on_color.green = 
    core->on_color.blue = (min_inten | min_inten << 8);
    core->off_color.red = 
    core->off_color.green =
    core->off_color.blue = (max_inten | max_inten << 8);
    return True;
}

static Bool
_XcursorThreshold (const XcursorImage *image, XcursorCoreCursor *core)
{
    XcursorPixel    *pixel, p;
    int               x, y;

    /*
     * Draw the image, picking black for dark pixels and white for light
     */
    pixel = image->pixels;
    for (y = 0; y < image->height; y++)
      for (x = 0; x < image->width; x++)
      {
          p = *pixel++;
          if ((p >> 24) >= 0x80)
          {
            XPutPixel (core->msk_image, x, y, 1);
            if (_XcursorPixelBrightness (p) > 0x80)
                XPutPixel (core->src_image, x, y, 0);
            else
                XPutPixel (core->src_image, x, y, 1);
          }
          else
          {
            XPutPixel (core->msk_image, x, y, 0);
            XPutPixel (core->src_image, x, y, 0);
          }
      }
    core->on_color.red =
    core->on_color.green = 
    core->on_color.blue = 0;
    core->off_color.red = 
    core->off_color.green =
    core->off_color.blue = 0xffff;
    return True;
}

Cursor
XcursorImageLoadCursor (Display *dpy, const XcursorImage *image)
{
    Cursor  cursor;
    
#if RENDER_MAJOR > 0 || RENDER_MINOR >= 5
    if (XcursorSupportsARGB (dpy))
    {
      XImage                ximage;
      int             screen = DefaultScreen (dpy);
      Pixmap                pixmap;
      Picture               picture;
      GC              gc;
      XRenderPictFormat   *format;

      ximage.width = image->width;
      ximage.height = image->height;
      ximage.xoffset = 0;
      ximage.format = ZPixmap;
      ximage.data = (char *) image->pixels;
      ximage.byte_order = nativeByteOrder ();
      ximage.bitmap_unit = 32;
      ximage.bitmap_bit_order = ximage.byte_order;
      ximage.bitmap_pad = 32;
      ximage.depth = 32;
      ximage.bits_per_pixel = 32;
      ximage.bytes_per_line = image->width * 4;
      ximage.red_mask = 0xff0000;
      ximage.green_mask = 0x00ff00;
      ximage.blue_mask = 0x0000ff;
      ximage.obdata = 0;
      if (!XInitImage (&ximage))
          return None;
      pixmap = XCreatePixmap (dpy, RootWindow (dpy, screen),
                        image->width, image->height, 32);
      gc = XCreateGC (dpy, pixmap, 0, 0);
      XPutImage (dpy, pixmap, gc, &ximage, 
               0, 0, 0, 0, image->width, image->height);
      XFreeGC (dpy, gc);
      format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
      picture = XRenderCreatePicture (dpy, pixmap, format, 0, 0);
      XFreePixmap (dpy, pixmap);
      cursor = XRenderCreateCursor (dpy, picture, 
                              image->xhot, image->yhot);
      XRenderFreePicture (dpy, picture);
    }
    else
#endif
    {
      XcursorDisplayInfo  *info = _XcursorGetDisplayInfo (dpy);
      int             screen = DefaultScreen (dpy);
      XcursorCoreCursor   core;
      Pixmap                src_pixmap, msk_pixmap;
      GC              gc;
      XGCValues       gcv;

      core.src_image = XCreateImage (dpy, 0, 1, ZPixmap,
                               0, 0, image->width, image->height,
                               32, 0);
      core.src_image->data = Xmalloc (image->height * 
                              core.src_image->bytes_per_line);
      core.msk_image = XCreateImage (dpy, 0, 1, ZPixmap,
                               0, 0, image->width, image->height,
                               32, 0);
      core.msk_image->data = Xmalloc (image->height * 
                              core.msk_image->bytes_per_line);

      switch (info->dither) {
      case XcursorDitherThreshold:
          if (!_XcursorThreshold (image, &core))
            return 0;
          break;
      case XcursorDitherMedian:
          if (!_XcursorHeckbertMedianCut (image, &core))
            return 0;
          break;
      case XcursorDitherOrdered:
          if (!_XcursorBayerOrderedDither (image, &core))
            return 0;
          break;
      case XcursorDitherDiffuse:
          if (!_XcursorFloydSteinberg (image, &core))
            return 0;
          break;
      default:
          return 0;
      }

      /*
       * Create the cursor
       */
      src_pixmap = XCreatePixmap (dpy, RootWindow (dpy, screen),
                            image->width, image->height, 1);
      msk_pixmap = XCreatePixmap (dpy, RootWindow (dpy, screen),
                            image->width, image->height, 1);
      gcv.foreground = 1;
      gcv.background = 0;
      gc = XCreateGC (dpy, src_pixmap, 
                  GCForeground|GCBackground,
                  &gcv);
      XPutImage (dpy, src_pixmap, gc, core.src_image,
               0, 0, 0, 0, image->width, image->height);
      
      XPutImage (dpy, msk_pixmap, gc, core.msk_image,
               0, 0, 0, 0, image->width, image->height);
      XFreeGC (dpy, gc);
      
#ifdef DEBUG_IMAGE
      _XcursorDumpColor (&core.on_color, "on_color");
      _XcursorDumpColor (&core.off_color, "off_color");
      _XcursorDumpImage (core.src_image);
      _XcursorDumpImage (core.msk_image);
#endif
      XDestroyImage (core.src_image);
      XDestroyImage (core.msk_image);

      cursor = XCreatePixmapCursor (dpy, src_pixmap, msk_pixmap,
                              &core.on_color, &core.off_color,
                              image->xhot, image->yhot);
      XFreePixmap (dpy, src_pixmap);
      XFreePixmap (dpy, msk_pixmap);
    }
    return cursor;
}

XcursorCursors *
XcursorImagesLoadCursors (Display *dpy, const XcursorImages *images)
{
    XcursorCursors  *cursors = XcursorCursorsCreate (dpy, images->nimage);
    int               n;

    if (!cursors)
      return 0;
    for (n = 0; n < images->nimage; n++)
    {
      cursors->cursors[n] = XcursorImageLoadCursor (dpy, images->images[n]);
      if (!cursors->cursors[n])
      {
          XcursorCursorsDestroy (cursors);
          return 0;
      }
      cursors->ncursor++;
    }
    return cursors;
}

Cursor
XcursorImagesLoadCursor (Display *dpy, const XcursorImages *images)
{
    Cursor  cursor;
    if (images->nimage == 1 || !XcursorSupportsAnim (dpy))
      cursor = XcursorImageLoadCursor (dpy, images->images[0]);
    else
    {
      XcursorCursors    *cursors = XcursorImagesLoadCursors (dpy, images);
      XAnimCursor *anim;
      int         n;
      
      if (!cursors)
          return 0;
      anim = malloc (cursors->ncursor * sizeof (XAnimCursor));
      if (!anim)
      {
          XcursorCursorsDestroy (cursors);
          return 0;
      }
      for (n = 0; n < cursors->ncursor; n++)
      {
          anim[n].cursor = cursors->cursors[n];
          anim[n].delay = images->images[n]->delay;
      }
      cursor = XRenderCreateAnimCursor (dpy, cursors->ncursor, anim);
      XcursorCursorsDestroy(cursors);
      free (anim);
    }
#if defined HAVE_XFIXES && XFIXES_MAJOR >= 2
    if (images->name)
      XFixesSetCursorName (dpy, cursor, images->name);
#endif
    return cursor;
}


Cursor
XcursorFilenameLoadCursor (Display *dpy, const char *file)
{
    int               size = XcursorGetDefaultSize (dpy);
    XcursorImages   *images = XcursorFilenameLoadImages (file, size);
    Cursor      cursor;
    
    if (!images)
      return None;
    cursor = XcursorImagesLoadCursor (dpy, images);
    XcursorImagesDestroy (images);
    return cursor;
}

XcursorCursors *
XcursorFilenameLoadCursors (Display *dpy, const char *file)
{
    int               size = XcursorGetDefaultSize (dpy);
    XcursorImages   *images = XcursorFilenameLoadImages (file, size);
    XcursorCursors  *cursors;
    
    if (!images)
      return 0;
    cursors = XcursorImagesLoadCursors (dpy, images);
    XcursorImagesDestroy (images);
    return cursors;
}

/*
 * Stolen from XCreateGlyphCursor (which we cruelly override)
 */

Cursor
_XcursorCreateGlyphCursor(Display       *dpy,
                    Font                source_font,
                    Font                mask_font,
                    unsigned int        source_char,
                    unsigned int        mask_char,
                    XColor _Xconst    *foreground,
                    XColor _Xconst    *background)
{       
    Cursor cid;
    register xCreateGlyphCursorReq *req;

    LockDisplay(dpy);
    GetReq(CreateGlyphCursor, req);
    cid = req->cid = XAllocID(dpy);
    req->source = source_font;
    req->mask = mask_font;
    req->sourceChar = source_char;
    req->maskChar = mask_char;
    req->foreRed = foreground->red;
    req->foreGreen = foreground->green;
    req->foreBlue = foreground->blue;
    req->backRed = background->red;
    req->backGreen = background->green;
    req->backBlue = background->blue;
    UnlockDisplay(dpy);
    SyncHandle();
    return (cid);
}

/*
 * Stolen from XCreateFontCursor (which we cruelly override)
 */

Cursor
_XcursorCreateFontCursor (Display *dpy, unsigned int shape)
{
    static XColor _Xconst foreground = { 0,    0,     0,     0  };  /* black */
    static XColor _Xconst background = { 0, 65535, 65535, 65535 };  /* white */

    /* 
     * the cursor font contains the shape glyph followed by the mask
     * glyph; so character position 0 contains a shape, 1 the mask for 0,
     * 2 a shape, etc.  <X11/cursorfont.h> contains hash define names
     * for all of these.
     */

    if (dpy->cursor_font == None) 
    {
      dpy->cursor_font = XLoadFont (dpy, CURSORFONT);
      if (dpy->cursor_font == None)
          return None;
    }

    return _XcursorCreateGlyphCursor (dpy, dpy->cursor_font, dpy->cursor_font, 
                              shape, shape + 1, &foreground, &background);
}


Generated by  Doxygen 1.6.0   Back to index