Re: [AD] Using system mouse cursor

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


> Xcursor looks like a fairly comprehensive library for doing... X 
> cursors.  I'm wary of this sentence, though: "*Xcursor* will probably 
> change radically in the future; weak attempts will be made to retain 
> some level of source-file compatibility."  Hmm.

Hopefully the configure checks in the attached patch are sufficient to 
catch any source-file compatibility they intend to break.
The attached patch changes the X11 cursor using the Xcursor library and 
lets X handle the drawing of the mouse cursor instead of having Allegro do 
this. Tested on Linux.
I'll see if I can get it working with the DGA driver too.

I was also rather surprised to find that none of Allegro's (other) graphics 
drivers have a hardware mouse at all!

Evert
Index: aclocal.m4
===================================================================
RCS file: /cvsroot/alleg/allegro/aclocal.m4,v
retrieving revision 1.66
diff -u -r1.66 aclocal.m4
--- aclocal.m4	17 Aug 2004 19:39:43 -0000	1.66
+++ aclocal.m4	24 Aug 2004 18:38:23 -0000
@@ -252,11 +252,24 @@
     [LIBS="-lXext $LIBS"])
 
   dnl Test for Xpm library.
-  AC_CHECK_HEADER(X11/xpm.h, AC_CHECK_LIB(Xpm, XMissingExtension,
+  AC_CHECK_HEADER(X11/xpm.h, AC_CHECK_LIB(Xpm, XpmCreatePixmapFromData,
     [LIBS="-lXpm $LIBS"
     AC_DEFINE(ALLEGRO_XWINDOWS_WITH_XPM,1,[Define if xpm bitmap support is available.])
     ])
    )
+   
+  dnl Test for Xcursor library.
+  AC_CHECK_LIB(Xcursor, XcursorImageCreate,
+    AC_TRY_COMPILE([#include <X11/Xlib.h>
+                    #include <X11/Xcursor/Xcursor.h>], 
+                   [XcursorImage *xcursor_image;
+                    XcursorImageLoadCursor(0, xcursor_image);
+                    XcursorSupportsARGB(0);
+                   ],
+      [LIBS="-lXcursor $LIBS"
+      AC_DEFINE(ALLEGRO_XWINDOWS_WITH_XCURSOR,1,[Define if XCursor ARGB extension is available.])
+      ])
+   )
 
   dnl Test for SHM extension.
   if test -n "$allegro_enable_xwin_shm"; then
Index: src/x/xgfxdrv.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/x/xgfxdrv.c,v
retrieving revision 1.14
diff -u -r1.14 xgfxdrv.c
--- src/x/xgfxdrv.c	18 Aug 2004 12:45:53 -0000	1.14
+++ src/x/xgfxdrv.c	24 Aug 2004 18:38:23 -0000
@@ -39,7 +39,14 @@
    NULL, NULL, NULL,
    NULL, NULL, NULL, NULL,
    NULL, NULL,
+#ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
+   _xwin_set_mouse_sprite,
+   _xwin_show_mouse,
+   _xwin_hide_mouse,
+   _xwin_move_mouse,
+#else
    NULL, NULL, NULL, NULL,
+#endif
    _xwin_drawing_mode,
    NULL, NULL,
    NULL,
@@ -71,7 +78,14 @@
    NULL, NULL, NULL,
    NULL, NULL, NULL, NULL,
    NULL, NULL,
+#ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
+   _xwin_set_mouse_sprite,
+   _xwin_show_mouse,
+   _xwin_hide_mouse,
+   _xwin_move_mouse,
+#else
    NULL, NULL, NULL, NULL,
+#endif
    _xwin_drawing_mode,
    NULL, NULL,
    _xwin_fetch_mode_list,
Index: src/x/xwin.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/x/xwin.c,v
retrieving revision 1.66
diff -u -r1.66 xwin.c
--- src/x/xwin.c	23 Aug 2004 09:15:29 -0000	1.66
+++ src/x/xwin.c	24 Aug 2004 18:38:28 -0000
@@ -48,6 +48,10 @@
 #include <X11/extensions/xf86dga.h>
 #endif
 
+#ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
+#include <X11/Xcursor/Xcursor.h>
+#endif
+
 
 #ifdef ALLEGRO_XWINDOWS_WITH_XPM
 #include <X11/xpm.h>
@@ -70,6 +74,9 @@
    0,           /* visual */
    None,        /* colormap */
    0,           /* ximage */
+#ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
+   None,        /* ARGB cursor image */
+#endif
    None,        /* cursor */
    XC_heart,    /* cursor_shape */
 
@@ -351,6 +358,42 @@
 
 
 
+/* _xwin_hide_x_mouse:
+ * Create invisible X cursor
+ */
+static void _xwin_hide_x_mouse(void)
+{
+   unsigned long gcmask;
+   XGCValues gcvalues;
+   Pixmap pixmap;
+   
+   pixmap = XCreatePixmap(_xwin.display, _xwin.window, 1, 1, 1);
+   if (pixmap != None) {
+      GC temp_gc;
+      XColor color;
+
+      gcmask = GCFunction | GCForeground | GCBackground;
+      gcvalues.function = GXcopy;
+      gcvalues.foreground = 0;
+      gcvalues.background = 0;
+      temp_gc = XCreateGC(_xwin.display, pixmap, gcmask, &gcvalues);
+      XDrawPoint(_xwin.display, pixmap, temp_gc, 0, 0);
+      XFreeGC(_xwin.display, temp_gc);
+      color.pixel = 0;
+      color.red = color.green = color.blue = 0;
+      color.flags = DoRed | DoGreen | DoBlue;
+      _xwin.cursor = XCreatePixmapCursor(_xwin.display, pixmap, pixmap, &color, &color, 0, 0);
+      XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
+      XFreePixmap(_xwin.display, pixmap);
+   }
+   else {
+      _xwin.cursor = XCreateFontCursor(_xwin.display, _xwin.cursor_shape);
+      XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
+   }
+}
+
+
+
 /* _xwin_create_window:
  *  Wrapper for XCreateWindow.
  */
@@ -360,7 +403,6 @@
    XGCValues gcvalues;
    XSetWindowAttributes setattr;
    XWindowAttributes getattr;
-   Pixmap pixmap;
 
    if (_xwin.display == 0)
       return -1;
@@ -412,29 +454,7 @@
    _xwin.gc = XCreateGC(_xwin.display, _xwin.window, gcmask, &gcvalues);
 
    /* Create invisible X cursor.  */
-   pixmap = XCreatePixmap(_xwin.display, _xwin.window, 1, 1, 1);
-   if (pixmap != None) {
-      GC temp_gc;
-      XColor color;
-
-      gcmask = GCFunction | GCForeground | GCBackground;
-      gcvalues.function = GXcopy;
-      gcvalues.foreground = 0;
-      gcvalues.background = 0;
-      temp_gc = XCreateGC(_xwin.display, pixmap, gcmask, &gcvalues);
-      XDrawPoint(_xwin.display, pixmap, temp_gc, 0, 0);
-      XFreeGC(_xwin.display, temp_gc);
-      color.pixel = 0;
-      color.red = color.green = color.blue = 0;
-      color.flags = DoRed | DoGreen | DoBlue;
-      _xwin.cursor = XCreatePixmapCursor(_xwin.display, pixmap, pixmap, &color, &color, 0, 0);
-      XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
-      XFreePixmap(_xwin.display, pixmap);
-   }
-   else {
-      _xwin.cursor = XCreateFontCursor(_xwin.display, _xwin.cursor_shape);
-      XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
-   }
+   _xwin_hide_x_mouse();
 
    return 0;
 }
@@ -1582,6 +1602,138 @@
 
 
 
+#ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
+
+/* _xwin_set_mouse_sprite:
+ *  Set custom X cursor (if supported)
+ */
+int _xwin_set_mouse_sprite(struct BITMAP *sprite, int x, int y)
+{
+#define GET_PIXEL_DATA(depth, getpix, mask)              \
+               case depth:                               \
+                  col = getpix(mouse_sprite, ix, iy);    \
+                  r = getr ## depth(col);                \
+                  g = getg ## depth(col);                \
+                  b = getb ## depth(col);                \
+                  if (col == (mask))                     \
+                     a = 0;                              \
+                  else                                   \
+                     a = 255;
+
+   XLOCK();
+   if (!XcursorSupportsARGB(_xwin.display)) {
+      XUNLOCK();
+      return -1;
+   }
+   
+   if (_xwin.xcursor_image != None) {
+      XcursorImageDestroy(_xwin.xcursor_image);
+      _xwin.xcursor_image = None;
+   }
+   XUNLOCK();
+   
+   if (sprite) {
+      int ix, iy;
+      int r = 0, g = 0, b = 0, a = 0, c, col;
+
+      _xwin.xcursor_image = XcursorImageCreate(sprite->w, sprite->h);
+      if (_xwin.xcursor_image == None) {
+         return -1;
+      }
+      
+      c = 0;
+      for(iy=0; iy<mouse_sprite->h; iy++) {
+         for(ix=0; ix<mouse_sprite->w;  ix++) {
+            switch(bitmap_color_depth(mouse_sprite)) {
+               GET_PIXEL_DATA(8, _getpixel, MASK_COLOR_8)
+                  break;
+                  
+               GET_PIXEL_DATA(15, _getpixel15, MASK_COLOR_15)
+                  break;
+
+               GET_PIXEL_DATA(16, _getpixel16, MASK_COLOR_16)
+                  break;
+
+               GET_PIXEL_DATA(24, _getpixel24, MASK_COLOR_24)
+                  break;
+
+               GET_PIXEL_DATA(32, _getpixel32, MASK_COLOR_32)
+                  break;
+            } /* End switch */
+            _xwin.xcursor_image->pixels[c++] = (a<<24)|(r<<16)|(g<<8)|(b);
+         }
+      }
+      
+      _xwin.xcursor_image->xhot = mouse_x_focus;
+      _xwin.xcursor_image->yhot = mouse_y_focus;
+      
+      return 0;
+   }
+   
+#undef GET_PIXEL_DATA
+
+   return -1;  
+}
+
+
+
+/* _xwin_show_mouse:
+ *  Show the custom X cursor (if supported)
+ */
+int _xwin_show_mouse(struct BITMAP *bmp, int x, int y)
+{
+   XLOCK();
+   if (!XcursorSupportsARGB(_xwin.display)) {
+      XUNLOCK();
+      return -1;
+   }
+
+   if (_xwin.xcursor_image == None) {
+      XUNLOCK();
+      return -1;
+   }
+
+   if (_xwin.cursor != None) {
+      XUndefineCursor(_xwin.display, _xwin.window);
+      XFreeCursor(_xwin.display, _xwin.cursor);
+   }   
+
+   _xwin.cursor = XcursorImageLoadCursor(_xwin.display, _xwin.xcursor_image);
+   XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
+
+   XUNLOCK();   
+   return 0;
+}
+
+
+
+/* _xwin_hide_mouse:
+ *  Hide the custom X cursor (if supported)
+ */
+void _xwin_hide_mouse(void)
+{
+   XLOCK();
+   if (!XcursorSupportsARGB(_xwin.display)) {
+      XUNLOCK();
+      return;
+   }
+   _xwin_hide_x_mouse();
+   XUNLOCK();
+}
+
+
+
+/* _xwin_move_mouse:
+ *  Move the custom X cursor. This is actually done automatically.
+ */
+void _xwin_move_mouse(int x, int y)
+{
+}
+
+#endif   /* ALLEGRO_XWINDOWS_WITH_XCURSOR */
+
+
+
 #ifdef ALLEGRO_XWINDOWS_WITH_XF86DGA
 
 /* _xdga_fast_visual_depth:
@@ -3344,7 +3496,7 @@
 
    /* Wait for VBI.  */
    if (vsync)
-      _xwin_private_vsync();
+      _xwin_vsync();
 
    if (_xwin.set_colors != 0) {
       if (blitter_func) {
Index: src/x/xwin.h
===================================================================
RCS file: /cvsroot/alleg/allegro/src/x/xwin.h,v
retrieving revision 1.17
diff -u -r1.17 xwin.h
--- src/x/xwin.h	18 Aug 2004 13:03:46 -0000	1.17
+++ src/x/xwin.h	24 Aug 2004 18:38:28 -0000
@@ -51,6 +51,11 @@
 AL_FUNC(int, _xwin_get_pointer_mapping, (unsigned char map[], int nmap));
 AL_FUNC(void, _xwin_init_keyboard_tables, (void));
 
+AL_FUNC(int, _xwin_set_mouse_sprite, (struct BITMAP *sprite, int x, int y));
+AL_FUNC(int, _xwin_show_mouse, (struct BITMAP *bmp, int x, int y));
+AL_FUNC(void, _xwin_hide_mouse, (void));
+AL_FUNC(void, _xwin_move_mouse, (int x, int y));
+
 AL_FUNC(BITMAP*, _xdga_create_screen, (GFX_DRIVER *drv, int w, int h,
 				       int vw, int vh, int depth, int fullscreen));
 AL_FUNC(void, _xdga_destroy_screen, (void));
Index: include/xalleg.h
===================================================================
RCS file: /cvsroot/alleg/allegro/include/xalleg.h,v
retrieving revision 1.16
diff -u -r1.16 xalleg.h
--- include/xalleg.h	15 Nov 2002 11:07:48 -0000	1.16
+++ include/xalleg.h	24 Aug 2004 18:38:28 -0000
@@ -49,6 +49,11 @@
 #include <X11/extensions/xf86dga.h>
 #endif
 
+#ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
+#include <X11/Xcursor/Xcursor.h>
+#endif
+
+
 
 #ifdef __cplusplus
    extern "C" {
@@ -65,6 +70,9 @@
    Visual *visual;
    Colormap colormap;
    XImage *ximage;
+#ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
+   XcursorImage *xcursor_image;
+#endif
    Cursor cursor;
    int cursor_shape;
 


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/