[2/6] X11DRV: Support loading of multicolor and animated cursors
H. Verbeet
hverbeet at gmail.com
Tue Apr 18 16:50:00 CDT 2006
This patch adds support for loading multicolor and animated cursors to
x11drv, if Xcursor is present.
Changelog:
- Support loading of multicolor and animated cursors.
-------------- next part --------------
diff --git a/configure.ac b/configure.ac
index c61e554..7ada95e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -319,6 +319,7 @@ then
AC_CHECK_HEADERS([X11/Xlib.h \
X11/XKBlib.h \
X11/Xutil.h \
+ X11/Xcursor/Xcursor.h \
X11/extensions/shape.h \
X11/extensions/XInput.h \
X11/extensions/XShm.h \
@@ -341,6 +342,17 @@ then
$X_LIBS -lXext -lX11 $X_EXTRA_LIBS)
fi
+ dnl *** Check for X cursor extension
+ if test "$ac_cv_header_X11_Xcursor_Xcursor_h" = "yes"
+ then
+ AC_CHECK_LIB(Xcursor, XcursorImagesLoadCursor,
+ [AC_DEFINE(HAVE_LIBXCURSOR, 1,
+ [Define if you have the X cursor extension])
+ X_PRE_LIBS="$X_PRE_LIBS -lXcursor"
+ ],,
+ $X_LIBS -lXext -lX11 $X_EXTRA_LIBS)
+ fi
+
dnl *** Check for X Shm extension
if test "$ac_cv_header_X11_extensions_XShm_h" = "yes"
then
diff --git a/dlls/x11drv/mouse.c b/dlls/x11drv/mouse.c
index e9ae7f8..8a9507c 100644
--- a/dlls/x11drv/mouse.c
+++ b/dlls/x11drv/mouse.c
@@ -2,6 +2,7 @@
* X11 mouse driver
*
* Copyright 1998 Ulrich Weigand
+ * Copyright (C) 2006 Henri Verbeet
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,6 +25,9 @@
#ifdef HAVE_LIBXXF86DGA2
#include <X11/extensions/xf86dga.h>
#endif
+#ifdef HAVE_LIBXCURSOR
+#include <X11/Xcursor/Xcursor.h>
+#endif
#include <stdarg.h>
#define NONAMELESSUNION
@@ -359,6 +363,115 @@ void X11DRV_send_mouse_input( HWND hwnd,
*
* Create an X cursor from a Windows one.
*/
+#ifdef HAVE_LIBXCURSOR
+static Cursor create_cursor(Display *display, CURSORANIINFO *ani_info)
+{
+ Cursor cursor;
+ XcursorImages *images = 0;
+ int image_count = 0;
+ CURSORICONINFO *ptr = (CURSORICONINFO *)(ani_info + 1);
+
+ if (!ani_info) /* Create an empty cursor */
+ {
+ XcursorImage *image = XcursorImageCreate(1, 1);
+ image->xhot = 0;
+ image->yhot = 0;
+ *(image->pixels) = 0;
+ cursor = XcursorImageLoadCursor(display, image);
+ XcursorImageDestroy(image);
+
+ return cursor;
+ }
+
+ image_count = ani_info->num_frames;
+ images = XcursorImagesCreate(image_count);
+
+ while(image_count--)
+ {
+ int mask_size = (ptr->nWidth >> 3) * ptr->nHeight; /* Mask data is 1 bit per pixel */
+ int img_size = (ptr->nWidth * ptr->bBitsPerPixel * ptr->nHeight) >> 3;
+ unsigned char *mask_ptr = (unsigned char *)(ptr + 1);
+ unsigned char *img_ptr = mask_ptr + mask_size;
+ XcursorImage *image = XcursorImageCreate(ptr->nWidth, ptr->nHeight);
+ XcursorPixel *pixel_ptr = 0;
+ XcursorPixel *pixel_end = 0;
+ int pixel_idx = 0;
+ POINT hotspot;
+
+ /* Make sure hotspot is valid */
+ hotspot.x = ptr->ptHotSpot.x;
+ hotspot.y = ptr->ptHotSpot.y;
+ if (hotspot.x < 0 || hotspot.x >= ptr->nWidth ||
+ hotspot.y < 0 || hotspot.y >= ptr->nHeight)
+ {
+ hotspot.x = ptr->nWidth / 2;
+ hotspot.y = ptr->nHeight / 2;
+ }
+
+ image->xhot = hotspot.x;
+ image->yhot = hotspot.y;
+ image->delay = ani_info->delay;
+
+ pixel_ptr = image->pixels;
+ pixel_end = pixel_ptr + (image->width * image->height);
+
+ /* On windows, to calculate the color for a pixel, first an AND is done with the mask,
+ * then an XOR with the color data. What it comes down to is that when the mask bit
+ * is 0, the pixel will get the color specified in the color data. When the mask bit
+ * is 1, the result is the background XOR'ed with the color data. In case the
+ * color data is completely black (0x000000) the pixel will become transparent, in case
+ * the color is white (0xffffff) the pixel will become the inverse of the background color.
+ *
+ * Since we can't support inverting colors, we map the mask to the alpha channel,
+ * making the pixel opaque if the mask bit isn't set, and transparent when it is. */
+ while(pixel_ptr < pixel_end)
+ {
+ /* Xcursor pixel data is in ARGB format, with A in the high byte */
+ switch (ptr->bBitsPerPixel)
+ {
+ case 24:
+ /* BGR, 8 bits each */
+ *pixel_ptr = *img_ptr++;
+ *pixel_ptr |= *img_ptr++ << 8;
+ *pixel_ptr |= *img_ptr++ << 16;
+ break;
+
+ case 16:
+ /* BGR, 5 red, 6 green, 5 blue */
+ *pixel_ptr = (*img_ptr & 0xf8) | ((*img_ptr & 0x07) << 13);
+ ++img_ptr;
+ *pixel_ptr |= ((*img_ptr & 0xe0) << 5) | ((*img_ptr & 0x1f) << 19);
+ break;
+
+ case 1:
+ if (img_ptr[pixel_idx >> 3] & (0x80 >> (pixel_idx & 7))) *pixel_ptr = 0xffffff;
+ else *pixel_ptr = 0;
+ break;
+
+ default:
+ FIXME("Currently no support for cursors with %d bits per pixel\n", ptr->bBitsPerPixel);
+ XcursorImagesDestroy (images);
+ return 0;
+ }
+ /* Alpha channel */
+ if (~mask_ptr[pixel_idx >> 3] & (0x80 >> (pixel_idx & 7))) *pixel_ptr |= 0xff << 24;
+
+ ++pixel_ptr;
+ ++pixel_idx;
+ }
+
+ images->images[images->nimage] = image;
+ ++images->nimage;
+
+ /* advance to the next image */
+ ptr = (CURSORICONINFO *)(((char *)ptr) + (sizeof(CURSORICONINFO) + img_size+ mask_size));
+ }
+
+ cursor = XcursorImagesLoadCursor(display, images);
+ XcursorImagesDestroy(images);
+ return cursor;
+}
+#else
static Cursor create_cursor( Display *display, CURSORANIINFO *ani_info )
{
Pixmap pixmapBits, pixmapMask, pixmapMaskInv, pixmapAll;
@@ -643,6 +756,7 @@ static Cursor create_cursor( Display *di
}
return cursor;
}
+#endif /* HAVE_LIBXCURSOR */
/***********************************************************************
More information about the wine-patches
mailing list