winex11.drv: Add Xcursor support for 32 bit cursors.

Based on patch by Henri Verbeet.
diff --git a/configure b/configure
index 17705e0..2ba7eac 100755
--- a/configure
+++ b/configure
@@ -7672,9 +7672,11 @@
 
 
 
+
 for ac_header in 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 \
@@ -14724,6 +14726,82 @@
 
 fi
 
+  { echo "$as_me:$LINENO: checking for -lXcursor soname" >&5
+echo $ECHO_N "checking for -lXcursor soname... $ECHO_C" >&6; }
+if test "${ac_cv_lib_soname_Xcursor+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_get_soname_save_LIBS=$LIBS
+LIBS="-lXcursor $X_LIBS -lX11 $X_EXTRA_LIBS $LIBS"
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XcursorImageLoadCursor ();
+int
+main ()
+{
+return XcursorImageLoadCursor ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  case "$LIBEXT" in
+    dylib) ac_cv_lib_soname_Xcursor=`otool -L conftest$ac_exeext | grep libXcursor\\.[0-9A-Za-z.]*dylib | sed -e "s/^.*\/\(libXcursor\.[0-9A-Za-z.]*dylib\).*$/\1/"';2,$d'` ;;
+    so) ac_cv_lib_soname_Xcursor=`$ac_cv_path_LDD conftest$ac_exeext | grep libXcursor\\.so | sed -e "s/^.*\(libXcursor\.so[^	 ]*\).*$/\1/"';2,$d'` ;;
+  esac
+  if test "x$ac_cv_lib_soname_Xcursor" = "x"
+  then
+     ac_cv_lib_soname_Xcursor="libXcursor.$LIBEXT"
+  fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_soname_Xcursor="libXcursor.$LIBEXT"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+  LIBS=$ac_get_soname_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_soname_Xcursor" >&5
+echo "${ECHO_T}$ac_cv_lib_soname_Xcursor" >&6; }
+if test "${ac_cv_lib_soname_Xcursor+set}" = set; then
+
+cat >>confdefs.h <<_ACEOF
+#define SONAME_LIBXCURSOR "$ac_cv_lib_soname_Xcursor"
+_ACEOF
+
+fi
+
   { echo "$as_me:$LINENO: checking for -lfreetype soname" >&5
 echo $ECHO_N "checking for -lfreetype soname... $ECHO_C" >&6; }
 if test "${ac_cv_lib_soname_freetype+set}" = set; then
diff --git a/configure.ac b/configure.ac
index 5d8cb52..066a289 100644
--- a/configure.ac
+++ b/configure.ac
@@ -335,6 +335,7 @@
     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 \
@@ -1151,6 +1152,7 @@
   WINE_GET_SONAME(Xinerama,XineramaQueryScreens,[$X_LIBS -lXext -lX11 $X_EXTRA_LIBS])
   WINE_GET_SONAME(Xrender,XRenderQueryExtension,[$X_LIBS -lXext -lX11 $X_EXTRA_LIBS])
   WINE_GET_SONAME(Xrandr,XRRQueryExtension,[$X_LIBS -lXext -lX11 $X_EXTRA_LIBS])
+  WINE_GET_SONAME(Xcursor,XcursorImageLoadCursor,[$X_LIBS -lX11 $X_EXTRA_LIBS])
   WINE_GET_SONAME(freetype,FT_Init_FreeType,[$X_LIBS])
   WINE_GET_SONAME(GL,glXQueryExtension,[$X_LIBS $X_EXTRA_LIBS])
   WINE_GET_SONAME(hal,libhal_ctx_new)
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c
index cf23866..b773f9a 100644
--- a/dlls/winex11.drv/init.c
+++ b/dlls/winex11.drv/init.c
@@ -89,6 +89,9 @@
     /* Initialize XRender */
     X11DRV_XRender_Init();
 
+    /* Init Xcursor */
+    X11DRV_Xcursor_Init();
+
     palette_size = X11DRV_PALETTE_Init();
 
     X11DRV_BITMAP_Init();
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 1016c69..e372a0f 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -2,6 +2,7 @@
  * X11 mouse driver
  *
  * Copyright 1998 Ulrich Weigand
+ * Copyright 2007 Henri Verbeet
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -19,10 +20,24 @@
  */
 
 #include "config.h"
+#include "wine/port.h"
 
 #include <X11/Xlib.h>
 #include <stdarg.h>
 
+#ifdef HAVE_X11_XCURSOR_XCURSOR_H
+# include <X11/Xcursor/Xcursor.h>
+# ifndef SONAME_LIBXCURSOR
+#  define SONAME_LIBXCURSOR "libXcursor.so"
+# endif
+static void *xcursor_handle;
+# define MAKE_FUNCPTR(f) static typeof(f) * p##f
+MAKE_FUNCPTR(XcursorImageCreate);
+MAKE_FUNCPTR(XcursorImageDestroy);
+MAKE_FUNCPTR(XcursorImageLoadCursor);
+# undef MAKE_FUNCPTR
+#endif /* HAVE_X11_XCURSOR_XCURSOR_H */
+
 #define NONAMELESSUNION
 #define NONAMELESSSTRUCT
 #include "windef.h"
@@ -32,6 +47,7 @@
 #include "win.h"
 #include "x11drv.h"
 #include "wine/server.h"
+#include "wine/library.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(cursor);
@@ -75,6 +91,32 @@
 
 BOOL X11DRV_SetCursorPos( INT x, INT y );
 
+
+/***********************************************************************
+ *		X11DRV_Xcursor_Init
+ *
+ * Load the Xcursor library for use.
+ */
+void X11DRV_Xcursor_Init(void)
+{
+#ifdef HAVE_X11_XCURSOR_XCURSOR_H
+    xcursor_handle = wine_dlopen(SONAME_LIBXCURSOR, RTLD_NOW, NULL, 0);
+    if (!xcursor_handle)  /* wine_dlopen failed. */
+    {
+        WARN("Xcursor failed to load.  Using fallback code.\n");
+        return;
+    }
+#define LOAD_FUNCPTR(f) \
+        p##f = wine_dlsym(xcursor_handle, #f, NULL, 0)
+
+    LOAD_FUNCPTR(XcursorImageCreate);
+    LOAD_FUNCPTR(XcursorImageDestroy);
+    LOAD_FUNCPTR(XcursorImageLoadCursor);
+#undef LOAD_FUNCPTR
+#endif /* HAVE_X11_XCURSOR_XCURSOR_H */
+}
+
+
 /***********************************************************************
  *		get_coords
  *
@@ -352,6 +394,165 @@
 }
 
 
+#ifdef HAVE_X11_XCURSOR_XCURSOR_H
+
+/***********************************************************************
+ *              create_cursor_image
+ *
+ * Create an XcursorImage from a CURSORICONINFO
+ */
+static XcursorImage *create_cursor_image( CURSORICONINFO *ptr )
+{
+    int x, xmax;
+    int y, ymax;
+    int and_size, xor_size;
+    unsigned char *and_bits, *and_ptr, *xor_bits, *xor_ptr;
+    int and_width_bytes, xor_width_bytes;
+    XcursorPixel *pixel_ptr;
+    XcursorImage *image;
+
+    ymax = (ptr->nHeight > 32) ? 32 : ptr->nHeight;
+    xmax = (ptr->nWidth > 32) ? 32 : ptr->nWidth;
+
+    and_width_bytes = xmax / 8;
+    xor_width_bytes = and_width_bytes * ptr->bBitsPerPixel;
+
+    and_size = ptr->nWidth * ptr->nHeight / 8;
+    and_ptr = and_bits = (unsigned char *)(ptr + 1);
+
+    xor_size = xor_width_bytes * ptr->nHeight;
+    xor_ptr = xor_bits = and_ptr + and_size;
+
+    image = pXcursorImageCreate( xmax, ymax );
+    pixel_ptr = image->pixels;
+
+    /* On windows, to calculate the color for a pixel, first an AND is done
+     * with the background and the "and" bitmap, then an XOR with the "xor"
+     * bitmap. This means that when the data in the "and" bitmap is 0, the
+     * pixel will get the color as specified in the "xor" bitmap.
+     * However, if the data in the "and" bitmap is 1, the result will be the
+     * background XOR'ed with the value in the "xor" bitmap. In case the "xor"
+     * data is completely black (0x000000) the pixel will become transparent,
+     * in case it's white (0xffffff) the pixel will become the inverse of the
+     * background color.
+     *
+     * Since we can't support inverting colors, we map the grayscale value of
+     * the "xor" data to the alpha channel, and xor the the color with either
+     * black or white.
+     */
+    for (y = 0; y < ymax; ++y)
+    {
+        and_ptr = and_bits + (y * and_width_bytes);
+        xor_ptr = xor_bits + (y * xor_width_bytes);
+
+        for (x = 0; x < xmax; ++x)
+        {
+            /* Xcursor pixel data is in ARGB format, with A in the high byte */
+            switch (ptr->bBitsPerPixel)
+            {
+                case 32:
+                    /* BGRA, 8 bits each */
+                    *pixel_ptr = *xor_ptr++;
+                    *pixel_ptr |= *xor_ptr++ << 8;
+                    *pixel_ptr |= *xor_ptr++ << 16;
+                    *pixel_ptr |= *xor_ptr++ << 24;
+                    break;
+
+                case 24:
+                    /* BGR, 8 bits each */
+                    *pixel_ptr = *xor_ptr++;
+                    *pixel_ptr |= *xor_ptr++ << 8;
+                    *pixel_ptr |= *xor_ptr++ << 16;
+                    break;
+
+                case 16:
+                    /* BGR, 5 red, 6 green, 5 blue */
+                    *pixel_ptr = *xor_ptr * 0x1f;
+                    *pixel_ptr |= (*xor_ptr & 0xe0) << 3;
+                    ++xor_ptr;
+                    *pixel_ptr |= (*xor_ptr & 0x07) << 11;
+                    *pixel_ptr |= (*xor_ptr & 0xf8) << 13;
+                    break;
+
+                case 1:
+                    if (*xor_ptr & (1 << (7 - (x & 7)))) *pixel_ptr = 0xffffff;
+                    else *pixel_ptr = 0;
+                    if ((x & 7) == 7) ++xor_ptr;
+                    break;
+
+                default:
+                    FIXME("Currently no support for cursors with %d bits per pixel\n", ptr->bBitsPerPixel);
+                    return 0;
+            }
+
+            if (ptr->bBitsPerPixel != 32)
+            {
+                /* Alpha channel */
+                if (~*and_ptr & (1 << (7 - (x & 7)))) *pixel_ptr |= 0xff << 24;
+                else if (*pixel_ptr)
+                {
+                    int alpha = (*pixel_ptr & 0xff) * 0.30f
+                            + ((*pixel_ptr & 0xff00) >> 8) * 0.55f
+                            + ((*pixel_ptr & 0xff0000) >> 16) * 0.15f;
+                    *pixel_ptr ^= ((x + y) % 2) ? 0xffffff : 0x000000;
+                    *pixel_ptr |= alpha << 24;
+                }
+                if ((x & 7) == 7) ++and_ptr;
+            }
+            ++pixel_ptr;
+        }
+    }
+
+    return image;
+}
+
+
+/***********************************************************************
+ *              create_xcursor_cursor
+ *
+ * Use Xcursor to create an X cursor from a Windows one.
+ */
+static Cursor create_xcursor_cursor( Display *display, CURSORICONINFO *ptr )
+{
+    Cursor cursor;
+    XcursorImage *image;
+
+    if (!ptr) /* Create an empty cursor */
+    {
+        image = pXcursorImageCreate( 1, 1 );
+        image->xhot = 0;
+        image->yhot = 0;
+        *(image->pixels) = 0;
+        cursor = pXcursorImageLoadCursor( display, image );
+        pXcursorImageDestroy( image );
+
+        return cursor;
+    }
+
+    image = create_cursor_image( ptr );
+    if (!image) return 0;
+
+    /* Make sure hotspot is valid */
+    image->xhot = ptr->ptHotSpot.x;
+    image->yhot = ptr->ptHotSpot.y;
+    if (image->xhot < 0 || image->xhot >= image->width ||
+        image->yhot < 0 || image->yhot >= image->height)
+    {
+        image->xhot = image->width / 2;
+        image->yhot = image->height / 2;
+    }
+
+    image->delay = 0;
+
+    cursor = pXcursorImageLoadCursor( display, image );
+    pXcursorImageDestroy( image );
+
+    return cursor;
+}
+
+#endif /* HAVE_X11_XCURSOR_XCURSOR_H */
+
+
 /***********************************************************************
  *		create_cursor
  *
@@ -363,6 +564,10 @@
     XColor fg, bg;
     Cursor cursor = None;
 
+#ifdef HAVE_X11_XCURSOR_XCURSOR_H
+    if (pXcursorImageLoadCursor) return create_xcursor_cursor( display, ptr );
+#endif
+
     if (!ptr)  /* Create an empty cursor */
     {
         static const char data[] = { 0 };
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 723a41a..4053c2f 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -228,6 +228,7 @@
 
 /* X11 driver internal functions */
 
+extern void X11DRV_Xcursor_Init(void);
 extern void X11DRV_BITMAP_Init(void);
 extern void X11DRV_FONT_Init( int log_pixels_x, int log_pixels_y );
 
diff --git a/include/config.h.in b/include/config.h.in
index 7ba145e..599ea65 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -924,6 +924,9 @@
 /* Define to 1 if you have the <X11/extensions/XShm.h> header file. */
 #undef HAVE_X11_EXTENSIONS_XSHM_H
 
+/* Define to 1 if you have the <X11/Xcursor/Xcursor.h> header file. */
+#undef HAVE_X11_XCURSOR_XCURSOR_H
+
 /* Define to 1 if you have the <X11/XKBlib.h> header file. */
 #undef HAVE_X11_XKBLIB_H
 
@@ -1029,6 +1032,9 @@
 /* Define to the soname of the libX11 library. */
 #undef SONAME_LIBX11
 
+/* Define to the soname of the libXcursor library. */
+#undef SONAME_LIBXCURSOR
+
 /* Define to the soname of the libXext library. */
 #undef SONAME_LIBXEXT