]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkcursor-x11.c
x11: Create empty cursor without old functions
[~andy/gtk] / gdk / x11 / gdkcursor-x11.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "config.h"
28
29 #define GDK_PIXBUF_ENABLE_BACKEND
30
31 #include <X11/Xlib.h>
32 #include <X11/cursorfont.h>
33 #ifdef HAVE_XCURSOR
34 #include <X11/Xcursor/Xcursor.h>
35 #endif
36 #ifdef HAVE_XFIXES
37 #include <X11/extensions/Xfixes.h>
38 #endif
39 #include <string.h>
40
41 #include "gdkprivate-x11.h"
42 #include "gdkcursor.h"
43 #include "gdkdisplay-x11.h"
44 #include "gdkpixmap-x11.h"
45 #include "gdkx.h"
46 #include <gdk/gdkpixmap.h>
47 #include <gdk-pixbuf/gdk-pixbuf.h>
48
49 static guint theme_serial = 0;
50
51 /* cursor_cache holds a cache of non-pixmap cursors to avoid expensive 
52  * libXcursor searches, cursors are added to it but only removed when
53  * their display is closed. We make the assumption that since there are 
54  * a small number of display's and a small number of cursor's that this 
55  * list will stay small enough not to be a problem.
56  */
57 static GSList* cursor_cache = NULL;
58
59 struct cursor_cache_key
60 {
61   GdkDisplay* display;
62   GdkCursorType type;
63   const char* name;
64 };
65
66 /* Caller should check if there is already a match first.
67  * Cursor MUST be either a typed cursor or a pixmap with 
68  * a non-NULL name.
69  */
70 static void
71 add_to_cache (GdkCursorPrivate* cursor)
72 {
73   cursor_cache = g_slist_prepend (cursor_cache, cursor);
74
75   /* Take a ref so that if the caller frees it we still have it */
76   gdk_cursor_ref ((GdkCursor*) cursor);
77 }
78
79 /* Returns 0 on a match
80  */
81 static gint
82 cache_compare_func (gconstpointer listelem, 
83                     gconstpointer target)
84 {
85   GdkCursorPrivate* cursor = (GdkCursorPrivate*)listelem;
86   struct cursor_cache_key* key = (struct cursor_cache_key*)target;
87
88   if ((cursor->cursor.type != key->type) ||
89       (cursor->display != key->display))
90     return 1; /* No match */
91   
92   /* Elements marked as pixmap must be named cursors 
93    * (since we don't store normal pixmap cursors 
94    */
95   if (key->type == GDK_CURSOR_IS_PIXMAP)
96     return strcmp (key->name, cursor->name);
97
98   return 0; /* Match */
99 }
100
101 /* Returns the cursor if there is a match, NULL if not
102  * For named cursors type shall be GDK_CURSOR_IS_PIXMAP
103  * For unnamed, typed cursors, name shall be NULL
104  */
105 static GdkCursorPrivate*
106 find_in_cache (GdkDisplay    *display, 
107                GdkCursorType  type,
108                const char    *name)
109 {
110   GSList* res;
111   struct cursor_cache_key key;
112
113   key.display = display;
114   key.type = type;
115   key.name = name;
116
117   res = g_slist_find_custom (cursor_cache, &key, cache_compare_func);
118
119   if (res)
120     return (GdkCursorPrivate *) res->data;
121
122   return NULL;
123 }
124
125 /* Called by gdk_display_x11_finalize to flush any cached cursors
126  * for a dead display.
127  */
128 void 
129 _gdk_x11_cursor_display_finalize (GdkDisplay *display)
130 {
131   GSList* item;
132   GSList** itemp; /* Pointer to the thing to fix when we delete an item */
133   item = cursor_cache;
134   itemp = &cursor_cache;
135   while (item)
136     {
137       GdkCursorPrivate* cursor = (GdkCursorPrivate*)(item->data);
138       if (cursor->display == display)
139         {
140           GSList* olditem;
141           gdk_cursor_unref ((GdkCursor*) cursor);
142           /* Remove this item from the list */
143           *(itemp) = item->next;
144           olditem = item;
145           item = g_slist_next (item);
146           g_slist_free_1 (olditem);
147         } 
148       else 
149         {
150           itemp = &(item->next);
151           item = g_slist_next (item);
152         }
153     }
154 }
155
156 static Cursor
157 get_blank_cursor (GdkDisplay *display)
158 {
159   GdkScreen *screen;
160   GdkPixmap *pixmap;
161   Pixmap source_pixmap;
162   XColor color;
163   Cursor cursor;
164   cairo_t *cr;
165
166   screen = gdk_display_get_default_screen (display);
167   pixmap = gdk_pixmap_new (gdk_screen_get_root_window (screen), 1, 1, 1);
168   /* Clear Pixmap */
169   cr = gdk_cairo_create (pixmap);
170   cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
171   cairo_paint (cr);
172   cairo_destroy (cr);
173  
174   source_pixmap = GDK_PIXMAP_XID (pixmap);
175
176   color.pixel = 0; 
177   color.red = color.blue = color.green = 0;
178   
179   if (display->closed)
180     cursor = None;
181   else
182     cursor = XCreatePixmapCursor (GDK_DISPLAY_XDISPLAY (display),
183                                   source_pixmap, source_pixmap,
184                                   &color, &color, 1, 1);
185   g_object_unref (pixmap);
186
187   return cursor;
188 }
189
190 /**
191  * gdk_cursor_new_for_display:
192  * @display: the #GdkDisplay for which the cursor will be created
193  * @cursor_type: cursor to create
194  * 
195  * Creates a new cursor from the set of builtin cursors.
196  * Some useful ones are:
197  * <itemizedlist>
198  * <listitem><para>
199  *  <inlinegraphic format="PNG" fileref="right_ptr.png"></inlinegraphic> #GDK_RIGHT_PTR (right-facing arrow)
200  * </para></listitem>
201  * <listitem><para>
202  *  <inlinegraphic format="PNG" fileref="crosshair.png"></inlinegraphic> #GDK_CROSSHAIR (crosshair)
203  * </para></listitem>
204  * <listitem><para>
205  *  <inlinegraphic format="PNG" fileref="xterm.png"></inlinegraphic> #GDK_XTERM (I-beam)
206  * </para></listitem>
207  * <listitem><para>
208  * <inlinegraphic format="PNG" fileref="watch.png"></inlinegraphic> #GDK_WATCH (busy)
209  * </para></listitem>
210  * <listitem><para>
211  * <inlinegraphic format="PNG" fileref="fleur.png"></inlinegraphic> #GDK_FLEUR (for moving objects)
212  * </para></listitem>
213  * <listitem><para>
214  * <inlinegraphic format="PNG" fileref="hand1.png"></inlinegraphic> #GDK_HAND1 (a right-pointing hand)
215  * </para></listitem>
216  * <listitem><para>
217  * <inlinegraphic format="PNG" fileref="hand2.png"></inlinegraphic> #GDK_HAND2 (a left-pointing hand)
218  * </para></listitem>
219  * <listitem><para>
220  * <inlinegraphic format="PNG" fileref="left_side.png"></inlinegraphic> #GDK_LEFT_SIDE (resize left side)
221  * </para></listitem>
222  * <listitem><para>
223  * <inlinegraphic format="PNG" fileref="right_side.png"></inlinegraphic> #GDK_RIGHT_SIDE (resize right side)
224  * </para></listitem>
225  * <listitem><para>
226  * <inlinegraphic format="PNG" fileref="top_left_corner.png"></inlinegraphic> #GDK_TOP_LEFT_CORNER (resize northwest corner)
227  * </para></listitem>
228  * <listitem><para>
229  * <inlinegraphic format="PNG" fileref="top_right_corner.png"></inlinegraphic> #GDK_TOP_RIGHT_CORNER (resize northeast corner)
230  * </para></listitem>
231  * <listitem><para>
232  * <inlinegraphic format="PNG" fileref="bottom_left_corner.png"></inlinegraphic> #GDK_BOTTOM_LEFT_CORNER (resize southwest corner)
233  * </para></listitem>
234  * <listitem><para>
235  * <inlinegraphic format="PNG" fileref="bottom_right_corner.png"></inlinegraphic> #GDK_BOTTOM_RIGHT_CORNER (resize southeast corner)
236  * </para></listitem>
237  * <listitem><para>
238  * <inlinegraphic format="PNG" fileref="top_side.png"></inlinegraphic> #GDK_TOP_SIDE (resize top side)
239  * </para></listitem>
240  * <listitem><para>
241  * <inlinegraphic format="PNG" fileref="bottom_side.png"></inlinegraphic> #GDK_BOTTOM_SIDE (resize bottom side)
242  * </para></listitem>
243  * <listitem><para>
244  * <inlinegraphic format="PNG" fileref="sb_h_double_arrow.png"></inlinegraphic> #GDK_SB_H_DOUBLE_ARROW (move vertical splitter)
245  * </para></listitem>
246  * <listitem><para>
247  * <inlinegraphic format="PNG" fileref="sb_v_double_arrow.png"></inlinegraphic> #GDK_SB_V_DOUBLE_ARROW (move horizontal splitter)
248  * </para></listitem>
249  * <listitem><para>
250  * #GDK_BLANK_CURSOR (Blank cursor). Since 2.16
251  * </para></listitem>
252  * </itemizedlist>
253  *
254  * Return value: a new #GdkCursor
255  *
256  * Since: 2.2
257  **/
258 GdkCursor*
259 gdk_cursor_new_for_display (GdkDisplay    *display,
260                             GdkCursorType  cursor_type)
261 {
262   GdkCursorPrivate *private;
263   GdkCursor *cursor;
264   Cursor xcursor;
265
266   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
267
268   if (display->closed)
269     {
270       xcursor = None;
271     } 
272   else 
273     {
274       private = find_in_cache (display, cursor_type, NULL);
275
276       if (private)
277         {
278           /* Cache had it, add a ref for this user */
279           gdk_cursor_ref ((GdkCursor*) private);
280        
281           return (GdkCursor*) private;
282         } 
283       else 
284         {
285           if (cursor_type != GDK_BLANK_CURSOR)
286             xcursor = XCreateFontCursor (GDK_DISPLAY_XDISPLAY (display),
287                                          cursor_type);
288           else
289             xcursor = get_blank_cursor (display);
290        }
291     }
292   
293   private = g_new (GdkCursorPrivate, 1);
294   private->display = display;
295   private->xcursor = xcursor;
296   private->name = NULL;
297   private->serial = theme_serial;
298
299   cursor = (GdkCursor *) private;
300   cursor->type = cursor_type;
301   cursor->ref_count = 1;
302   
303   if (xcursor != None)
304     add_to_cache (private);
305
306   return cursor;
307 }
308
309 /**
310  * gdk_cursor_new_from_pixmap:
311  * @source: the pixmap specifying the cursor.
312  * @mask: the pixmap specifying the mask, which must be the same size as 
313  *    @source.
314  * @fg: the foreground color, used for the bits in the source which are 1.
315  *    The color does not have to be allocated first. 
316  * @bg: the background color, used for the bits in the source which are 0.
317  *    The color does not have to be allocated first.
318  * @x: the horizontal offset of the 'hotspot' of the cursor. 
319  * @y: the vertical offset of the 'hotspot' of the cursor.
320  * 
321  * Creates a new cursor from a given pixmap and mask. Both the pixmap and mask
322  * must have a depth of 1 (i.e. each pixel has only 2 values - on or off).
323  * The standard cursor size is 16 by 16 pixels. You can create a bitmap 
324  * from inline data as in the below example.
325  * 
326  * <example><title>Creating a custom cursor</title>
327  * <programlisting>
328  * /<!-- -->* This data is in X bitmap format, and can be created with the 'bitmap'
329  *    utility. *<!-- -->/
330  * &num;define cursor1_width 16
331  * &num;define cursor1_height 16
332  * static unsigned char cursor1_bits[] = {
333  *   0x80, 0x01, 0x40, 0x02, 0x20, 0x04, 0x10, 0x08, 0x08, 0x10, 0x04, 0x20,
334  *   0x82, 0x41, 0x41, 0x82, 0x41, 0x82, 0x82, 0x41, 0x04, 0x20, 0x08, 0x10,
335  *   0x10, 0x08, 0x20, 0x04, 0x40, 0x02, 0x80, 0x01};
336  *  
337  * static unsigned char cursor1mask_bits[] = {
338  *   0x80, 0x01, 0xc0, 0x03, 0x60, 0x06, 0x30, 0x0c, 0x18, 0x18, 0x8c, 0x31,
339  *   0xc6, 0x63, 0x63, 0xc6, 0x63, 0xc6, 0xc6, 0x63, 0x8c, 0x31, 0x18, 0x18,
340  *   0x30, 0x0c, 0x60, 0x06, 0xc0, 0x03, 0x80, 0x01};
341  *  
342  *  
343  *  GdkCursor *cursor;
344  *  GdkPixmap *source, *mask;
345  *  GdkColor fg = { 0, 65535, 0, 0 }; /<!-- -->* Red. *<!-- -->/
346  *  GdkColor bg = { 0, 0, 0, 65535 }; /<!-- -->* Blue. *<!-- -->/
347  *  
348  *  
349  *  source = gdk_bitmap_create_from_data (NULL, cursor1_bits,
350  *                                        cursor1_width, cursor1_height);
351  *  mask = gdk_bitmap_create_from_data (NULL, cursor1mask_bits,
352  *                                      cursor1_width, cursor1_height);
353  *  cursor = gdk_cursor_new_from_pixmap (source, mask, &amp;fg, &amp;bg, 8, 8);
354  *  g_object_unref (source);
355  *  g_object_unref (mask);
356  *  
357  *  
358  *  gdk_window_set_cursor (widget->window, cursor);
359  * </programlisting>
360  * </example>
361  *
362  * Return value: a new #GdkCursor.
363  **/
364 GdkCursor*
365 gdk_cursor_new_from_pixmap (GdkPixmap      *source,
366                             GdkPixmap      *mask,
367                             const GdkColor *fg,
368                             const GdkColor *bg,
369                             gint            x,
370                             gint            y)
371 {
372   GdkCursorPrivate *private;
373   GdkCursor *cursor;
374   Pixmap source_pixmap, mask_pixmap;
375   Cursor xcursor;
376   XColor xfg, xbg;
377   GdkDisplay *display;
378
379   g_return_val_if_fail (GDK_IS_PIXMAP (source), NULL);
380   g_return_val_if_fail (GDK_IS_PIXMAP (mask), NULL);
381   g_return_val_if_fail (fg != NULL, NULL);
382   g_return_val_if_fail (bg != NULL, NULL);
383
384   source_pixmap = GDK_PIXMAP_XID (source);
385   mask_pixmap   = GDK_PIXMAP_XID (mask);
386   display = GDK_PIXMAP_DISPLAY (source);
387
388   xfg.pixel = fg->pixel;
389   xfg.red = fg->red;
390   xfg.blue = fg->blue;
391   xfg.green = fg->green;
392   xbg.pixel = bg->pixel;
393   xbg.red = bg->red;
394   xbg.blue = bg->blue;
395   xbg.green = bg->green;
396   
397   if (display->closed)
398     xcursor = None;
399   else
400     xcursor = XCreatePixmapCursor (GDK_DISPLAY_XDISPLAY (display),
401                                    source_pixmap, mask_pixmap, &xfg, &xbg, x, y);
402   private = g_new (GdkCursorPrivate, 1);
403   private->display = display;
404   private->xcursor = xcursor;
405   private->name = NULL;
406   private->serial = theme_serial;
407
408   cursor = (GdkCursor *) private;
409   cursor->type = GDK_CURSOR_IS_PIXMAP;
410   cursor->ref_count = 1;
411   
412   return cursor;
413 }
414
415 void
416 _gdk_cursor_destroy (GdkCursor *cursor)
417 {
418   GdkCursorPrivate *private;
419
420   g_return_if_fail (cursor != NULL);
421   g_return_if_fail (cursor->ref_count == 0);
422
423   private = (GdkCursorPrivate *) cursor;
424   if (!private->display->closed && private->xcursor)
425     XFreeCursor (GDK_DISPLAY_XDISPLAY (private->display), private->xcursor);
426
427   g_free (private->name);
428   g_free (private);
429 }
430
431 /**
432  * gdk_x11_cursor_get_xdisplay:
433  * @cursor: a #GdkCursor.
434  * 
435  * Returns the display of a #GdkCursor.
436  * 
437  * Return value: an Xlib <type>Display*</type>.
438  **/
439 Display *
440 gdk_x11_cursor_get_xdisplay (GdkCursor *cursor)
441 {
442   g_return_val_if_fail (cursor != NULL, NULL);
443
444   return GDK_DISPLAY_XDISPLAY(((GdkCursorPrivate *)cursor)->display);
445 }
446
447 /**
448  * gdk_x11_cursor_get_xcursor:
449  * @cursor: a #GdkCursor.
450  * 
451  * Returns the X cursor belonging to a #GdkCursor.
452  * 
453  * Return value: an Xlib <type>Cursor</type>.
454  **/
455 Cursor
456 gdk_x11_cursor_get_xcursor (GdkCursor *cursor)
457 {
458   g_return_val_if_fail (cursor != NULL, None);
459
460   return ((GdkCursorPrivate *)cursor)->xcursor;
461 }
462
463 /** 
464  * gdk_cursor_get_display:
465  * @cursor: a #GdkCursor.
466  *
467  * Returns the display on which the #GdkCursor is defined.
468  *
469  * Returns: the #GdkDisplay associated to @cursor
470  *
471  * Since: 2.2
472  */
473
474 GdkDisplay *
475 gdk_cursor_get_display (GdkCursor *cursor)
476 {
477   g_return_val_if_fail (cursor != NULL, NULL);
478
479   return ((GdkCursorPrivate *)cursor)->display;
480 }
481
482 #if defined(HAVE_XCURSOR) && defined(HAVE_XFIXES) && XFIXES_MAJOR >= 2
483
484 /**
485  * gdk_cursor_get_image:
486  * @cursor: a #GdkCursor
487  *
488  * Returns a #GdkPixbuf with the image used to display the cursor.
489  *
490  * Note that depending on the capabilities of the windowing system and 
491  * on the cursor, GDK may not be able to obtain the image data. In this 
492  * case, %NULL is returned.
493  *
494  * Returns: a #GdkPixbuf representing @cursor, or %NULL
495  *
496  * Since: 2.8
497  */
498 GdkPixbuf*  
499 gdk_cursor_get_image (GdkCursor *cursor)
500 {
501   Display *xdisplay;
502   GdkCursorPrivate *private;
503   XcursorImages *images = NULL;
504   XcursorImage *image;
505   gint size;
506   gchar buf[32];
507   guchar *data, *p, tmp;
508   GdkPixbuf *pixbuf;
509   gchar *theme;
510   
511   g_return_val_if_fail (cursor != NULL, NULL);
512
513   private = (GdkCursorPrivate *) cursor;
514     
515   xdisplay = GDK_DISPLAY_XDISPLAY (private->display);
516
517   size = XcursorGetDefaultSize (xdisplay);
518   theme = XcursorGetTheme (xdisplay);
519
520   if (cursor->type == GDK_CURSOR_IS_PIXMAP)
521     {
522       if (private->name)
523         images = XcursorLibraryLoadImages (private->name, theme, size);
524     }
525   else 
526     images = XcursorShapeLoadImages (cursor->type, theme, size);
527
528   if (!images)
529     return NULL;
530   
531   image = images->images[0];
532
533   data = g_malloc (4 * image->width * image->height);
534   memcpy (data, image->pixels, 4 * image->width * image->height);
535
536   for (p = data; p < data + (4 * image->width * image->height); p += 4)
537     {
538       tmp = p[0];
539       p[0] = p[2];
540       p[2] = tmp;
541     }
542
543   pixbuf = gdk_pixbuf_new_from_data (data, GDK_COLORSPACE_RGB, TRUE,
544                                      8, image->width, image->height,
545                                      4 * image->width, 
546                                      (GdkPixbufDestroyNotify)g_free, NULL);
547
548   if (private->name)
549     gdk_pixbuf_set_option (pixbuf, "name", private->name);
550   g_snprintf (buf, 32, "%d", image->xhot);
551   gdk_pixbuf_set_option (pixbuf, "x_hot", buf);
552   g_snprintf (buf, 32, "%d", image->yhot);
553   gdk_pixbuf_set_option (pixbuf, "y_hot", buf);
554
555   XcursorImagesDestroy (images);
556
557   return pixbuf;
558 }
559
560 void
561 _gdk_x11_cursor_update_theme (GdkCursor *cursor)
562 {
563   Display *xdisplay;
564   GdkCursorPrivate *private;
565   Cursor new_cursor = None;
566   GdkDisplayX11 *display_x11;
567
568   private = (GdkCursorPrivate *) cursor;
569   xdisplay = GDK_DISPLAY_XDISPLAY (private->display);
570   display_x11 = GDK_DISPLAY_X11 (private->display);
571
572   if (!display_x11->have_xfixes)
573     return;
574
575   if (private->serial == theme_serial)
576     return;
577
578   private->serial = theme_serial;
579
580   if (private->xcursor != None)
581     {
582       if (cursor->type == GDK_BLANK_CURSOR)
583         return;
584
585       if (cursor->type == GDK_CURSOR_IS_PIXMAP)
586         {
587           if (private->name)
588             new_cursor = XcursorLibraryLoadCursor (xdisplay, private->name);
589         }
590       else 
591         new_cursor = XcursorShapeLoadCursor (xdisplay, cursor->type);
592       
593       if (new_cursor != None)
594         {
595           XFixesChangeCursor (xdisplay, new_cursor, private->xcursor);
596           private->xcursor = new_cursor;
597         }
598     }
599 }
600
601 static void
602 update_cursor (gpointer data,
603                gpointer user_data)
604 {
605   GdkCursor *cursor;
606
607   cursor = (GdkCursor*)(data);
608
609   if (!cursor)
610     return;
611   
612   _gdk_x11_cursor_update_theme (cursor);
613 }
614
615 /**
616  * gdk_x11_display_set_cursor_theme:
617  * @display: a #GdkDisplay
618  * @theme: the name of the cursor theme to use, or %NULL to unset
619  *         a previously set value 
620  * @size: the cursor size to use, or 0 to keep the previous size
621  *
622  * Sets the cursor theme from which the images for cursor
623  * should be taken. 
624  * 
625  * If the windowing system supports it, existing cursors created 
626  * with gdk_cursor_new(), gdk_cursor_new_for_display() and 
627  * gdk_cursor_new_for_name() are updated to reflect the theme 
628  * change. Custom cursors constructed with gdk_cursor_new_from_pixmap() 
629  * or gdk_cursor_new_from_pixbuf() will have to be handled
630  * by the application (GTK+ applications can learn about 
631  * cursor theme changes by listening for change notification
632  * for the corresponding #GtkSetting).
633  *
634  * Since: 2.8
635  */
636 void
637 gdk_x11_display_set_cursor_theme (GdkDisplay  *display,
638                                   const gchar *theme,
639                                   const gint   size)
640 {
641   GdkDisplayX11 *display_x11;
642   Display *xdisplay;
643   gchar *old_theme;
644   gint old_size;
645
646   g_return_if_fail (GDK_IS_DISPLAY (display));
647
648   display_x11 = GDK_DISPLAY_X11 (display);
649   xdisplay = GDK_DISPLAY_XDISPLAY (display);
650
651   old_theme = XcursorGetTheme (xdisplay);
652   old_size = XcursorGetDefaultSize (xdisplay);
653
654   if (old_size == size &&
655       (old_theme == theme ||
656        (old_theme && theme && strcmp (old_theme, theme) == 0)))
657     return;
658
659   theme_serial++;
660
661   XcursorSetTheme (xdisplay, theme);
662   if (size > 0)
663     XcursorSetDefaultSize (xdisplay, size);
664     
665   g_slist_foreach (cursor_cache, update_cursor, NULL);
666 }
667
668 #else
669
670 GdkPixbuf*  
671 gdk_cursor_get_image (GdkCursor *cursor)
672 {
673   g_return_val_if_fail (cursor != NULL, NULL);
674   
675   return NULL;
676 }
677
678 void
679 gdk_x11_display_set_cursor_theme (GdkDisplay  *display,
680                                   const gchar *theme,
681                                   const gint   size)
682 {
683   g_return_if_fail (GDK_IS_DISPLAY (display));
684 }
685
686 void
687 _gdk_x11_cursor_update_theme (GdkCursor *cursor)
688 {
689   g_return_if_fail (cursor != NULL);
690 }
691
692 #endif
693
694 #ifdef HAVE_XCURSOR
695
696 static XcursorImage*
697 create_cursor_image (GdkPixbuf *pixbuf,
698                      gint       x,
699                      gint       y)
700 {
701   guint width, height, rowstride, n_channels;
702   guchar *pixels, *src;
703   XcursorImage *xcimage;
704   XcursorPixel *dest;
705
706   width = gdk_pixbuf_get_width (pixbuf);
707   height = gdk_pixbuf_get_height (pixbuf);
708
709   n_channels = gdk_pixbuf_get_n_channels (pixbuf);
710   rowstride = gdk_pixbuf_get_rowstride (pixbuf);
711   pixels = gdk_pixbuf_get_pixels (pixbuf);
712
713   xcimage = XcursorImageCreate (width, height);
714
715   xcimage->xhot = x;
716   xcimage->yhot = y;
717
718   dest = xcimage->pixels;
719
720   if (n_channels == 3)
721     {
722       gint i, j;
723
724       for (j = 0; j < height; j++)
725         {
726           src = pixels + j * rowstride;
727           for (i = 0; i < width; i++)
728             {
729               *dest = (0xff << 24) | (src[0] << 16) | (src[1] << 8) | src[2];
730             }
731
732           src += n_channels;
733           dest++;
734         }
735     }
736   else
737     {
738       _gdk_x11_convert_to_format (pixels, rowstride,
739                                   (guchar *) dest, 4 * width,
740                                   GDK_X11_FORMAT_ARGB,
741                                   (G_BYTE_ORDER == G_BIG_ENDIAN) ?
742                                   GDK_MSB_FIRST : GDK_LSB_FIRST,
743                                   width, height);
744     }
745
746   return xcimage;
747 }
748
749
750 /**
751  * gdk_cursor_new_from_pixbuf:
752  * @display: the #GdkDisplay for which the cursor will be created
753  * @pixbuf: the #GdkPixbuf containing the cursor image
754  * @x: the horizontal offset of the 'hotspot' of the cursor. 
755  * @y: the vertical offset of the 'hotspot' of the cursor.
756  *
757  * Creates a new cursor from a pixbuf. 
758  *
759  * Not all GDK backends support RGBA cursors. If they are not 
760  * supported, a monochrome approximation will be displayed. 
761  * The functions gdk_display_supports_cursor_alpha() and 
762  * gdk_display_supports_cursor_color() can be used to determine
763  * whether RGBA cursors are supported; 
764  * gdk_display_get_default_cursor_size() and 
765  * gdk_display_get_maximal_cursor_size() give information about 
766  * cursor sizes.
767  *
768  * On the X backend, support for RGBA cursors requires a
769  * sufficently new version of the X Render extension. 
770  *
771  * Returns: a new #GdkCursor.
772  * 
773  * Since: 2.4
774  */
775 GdkCursor *
776 gdk_cursor_new_from_pixbuf (GdkDisplay *display, 
777                             GdkPixbuf  *pixbuf,
778                             gint        x,
779                             gint        y)
780 {
781   XcursorImage *xcimage;
782   Cursor xcursor;
783   GdkCursorPrivate *private;
784   GdkCursor *cursor;
785
786   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
787   g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
788   g_return_val_if_fail (0 <= x && x < gdk_pixbuf_get_width (pixbuf), NULL);
789   g_return_val_if_fail (0 <= y && y < gdk_pixbuf_get_height (pixbuf), NULL);
790
791   if (display->closed)
792     xcursor = None;
793   else 
794     {
795       xcimage = create_cursor_image (pixbuf, x, y);
796       xcursor = XcursorImageLoadCursor (GDK_DISPLAY_XDISPLAY (display), xcimage);
797       XcursorImageDestroy (xcimage);
798     }
799
800   private = g_new (GdkCursorPrivate, 1);
801   private->display = display;
802   private->xcursor = xcursor;
803   private->name = NULL;
804   private->serial = theme_serial;
805
806   cursor = (GdkCursor *) private;
807   cursor->type = GDK_CURSOR_IS_PIXMAP;
808   cursor->ref_count = 1;
809   
810   return cursor;
811 }
812
813 /**
814  * gdk_cursor_new_from_name:
815  * @display: the #GdkDisplay for which the cursor will be created
816  * @name: the name of the cursor
817  *
818  * Creates a new cursor by looking up @name in the current cursor
819  * theme. 
820  * 
821  * Returns: a new #GdkCursor, or %NULL if there is no cursor with 
822  *   the given name 
823  *
824  * Since: 2.8
825  */
826 GdkCursor*  
827 gdk_cursor_new_from_name (GdkDisplay  *display,
828                           const gchar *name)
829 {
830   Cursor xcursor;
831   Display *xdisplay;
832   GdkCursorPrivate *private;
833   GdkCursor *cursor;
834
835   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
836
837   if (display->closed)
838     xcursor = None;
839   else 
840     {
841       private = find_in_cache (display, GDK_CURSOR_IS_PIXMAP, name);
842
843       if (private)
844         {
845           /* Cache had it, add a ref for this user */
846           gdk_cursor_ref ((GdkCursor*) private);
847
848           return (GdkCursor*) private;
849         }
850
851       xdisplay = GDK_DISPLAY_XDISPLAY (display);
852       xcursor = XcursorLibraryLoadCursor (xdisplay, name);
853       if (xcursor == None)
854         return NULL;
855     }
856
857   private = g_new (GdkCursorPrivate, 1);
858   private->display = display;
859   private->xcursor = xcursor;
860   private->name = g_strdup (name);
861   private->serial = theme_serial;
862
863   cursor = (GdkCursor *) private;
864   cursor->type = GDK_CURSOR_IS_PIXMAP;
865   cursor->ref_count = 1;
866   add_to_cache (private);
867
868   return cursor;
869 }
870
871 /**
872  * gdk_display_supports_cursor_alpha:
873  * @display: a #GdkDisplay
874  *
875  * Returns %TRUE if cursors can use an 8bit alpha channel 
876  * on @display. Otherwise, cursors are restricted to bilevel 
877  * alpha (i.e. a mask).
878  *
879  * Returns: whether cursors can have alpha channels.
880  *
881  * Since: 2.4
882  */
883 gboolean 
884 gdk_display_supports_cursor_alpha (GdkDisplay *display)
885 {
886   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
887
888   return XcursorSupportsARGB (GDK_DISPLAY_XDISPLAY (display));
889 }
890
891 /**
892  * gdk_display_supports_cursor_color:
893  * @display: a #GdkDisplay
894  *
895  * Returns %TRUE if multicolored cursors are supported
896  * on @display. Otherwise, cursors have only a forground
897  * and a background color.
898  *
899  * Returns: whether cursors can have multiple colors.
900  *
901  * Since: 2.4
902  */
903 gboolean 
904 gdk_display_supports_cursor_color (GdkDisplay *display)
905 {
906   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
907
908   return XcursorSupportsARGB (GDK_DISPLAY_XDISPLAY (display));
909 }
910
911 /**
912  * gdk_display_get_default_cursor_size:
913  * @display: a #GdkDisplay
914  *
915  * Returns the default size to use for cursors on @display.
916  *
917  * Returns: the default cursor size.
918  *
919  * Since: 2.4
920  */
921 guint     
922 gdk_display_get_default_cursor_size (GdkDisplay *display)
923 {
924   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
925
926   return XcursorGetDefaultSize (GDK_DISPLAY_XDISPLAY (display));
927 }
928
929 #else
930
931 GdkCursor *
932 gdk_cursor_new_from_pixbuf (GdkDisplay *display, 
933                             GdkPixbuf  *pixbuf,
934                             gint        x,
935                             gint        y)
936 {
937   GdkCursor *cursor;
938   GdkPixmap *pixmap, *mask;
939   guint width, height, n_channels, rowstride, data_stride, i, j;
940   guint8 *data, *mask_data, *pixels;
941   GdkColor fg = { 0, 0, 0, 0 };
942   GdkColor bg = { 0, 0xffff, 0xffff, 0xffff };
943   GdkScreen *screen;
944   cairo_surface_t *image;
945   cairo_t *cr;
946
947   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
948   g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
949
950   width = gdk_pixbuf_get_width (pixbuf);
951   height = gdk_pixbuf_get_height (pixbuf);
952
953   g_return_val_if_fail (0 <= x && x < width, NULL);
954   g_return_val_if_fail (0 <= y && y < height, NULL);
955
956   n_channels = gdk_pixbuf_get_n_channels (pixbuf);
957   rowstride = gdk_pixbuf_get_rowstride (pixbuf);
958   pixels = gdk_pixbuf_get_pixels (pixbuf);
959
960   data_stride = 4 * ((width + 31) / 32);
961   data = g_new0 (guint8, data_stride * height);
962   mask_data = g_new0 (guint8, data_stride * height);
963
964   for (j = 0; j < height; j++)
965     {
966       guint8 *src = pixels + j * rowstride;
967       guint8 *d = data + data_stride * j;
968       guint8 *md = mask_data + data_stride * j;
969         
970       for (i = 0; i < width; i++)
971         {
972           if (src[1] < 0x80)
973             *d |= 1 << (i % 8);
974           
975           if (n_channels == 3 || src[3] >= 0x80)
976             *md |= 1 << (i % 8);
977           
978           src += n_channels;
979           if (i % 8 == 7)
980             {
981               d++; 
982               md++;
983             }
984         }
985     }
986       
987   screen = gdk_display_get_default_screen (display);
988
989   pixmap = gdk_pixmap_new (gdk_screen_get_root_window (screen), 
990                            width, height, 1);
991   cr = gdk_cairo_create (pixmap);
992   image = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_A1,
993                                                width, height, data_stride);
994   cairo_set_source_surface (cr, image, 0, 0);
995   cairo_surface_destroy (image);
996   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
997   cairo_paint (cr);
998   cairo_destroy (cr);
999  
1000   mask = gdk_pixmap_new (gdk_screen_get_root_window (screen), 
1001                          width, height, 1);
1002   cr = gdk_cairo_create (mask);
1003   image = cairo_image_surface_create_for_data (mask_data, CAIRO_FORMAT_A1,
1004                                                width, height, data_stride);
1005   cairo_set_source_surface (cr, image, 0, 0);
1006   cairo_surface_destroy (image);
1007   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
1008   cairo_paint (cr);
1009   cairo_destroy (cr);
1010  
1011   cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg, x, y);
1012    
1013   g_object_unref (pixmap);
1014   g_object_unref (mask);
1015
1016   g_free (data);
1017   g_free (mask_data);
1018   
1019   return cursor;
1020 }
1021
1022 GdkCursor*  
1023 gdk_cursor_new_from_name (GdkDisplay  *display,
1024                           const gchar *name)
1025 {
1026   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1027
1028   return NULL;
1029 }
1030
1031 gboolean 
1032 gdk_display_supports_cursor_alpha (GdkDisplay    *display)
1033 {
1034   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1035
1036   return FALSE;
1037 }
1038
1039 gboolean 
1040 gdk_display_supports_cursor_color (GdkDisplay    *display)
1041 {
1042   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1043
1044   return FALSE;
1045 }
1046
1047 guint     
1048 gdk_display_get_default_cursor_size (GdkDisplay    *display)
1049 {
1050   g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
1051   
1052   /* no idea, really */
1053   return 20; 
1054 }
1055
1056 #endif
1057
1058
1059 /**
1060  * gdk_display_get_maximal_cursor_size:
1061  * @display: a #GdkDisplay
1062  * @width: (out): the return location for the maximal cursor width
1063  * @height: (out): the return location for the maximal cursor height
1064  *
1065  * Gets the maximal size to use for cursors on @display.
1066  *
1067  * Since: 2.4
1068  */
1069 void     
1070 gdk_display_get_maximal_cursor_size (GdkDisplay *display,
1071                                      guint       *width,
1072                                      guint       *height)
1073 {
1074   GdkScreen *screen;
1075   GdkWindow *window;
1076
1077   g_return_if_fail (GDK_IS_DISPLAY (display));
1078   
1079   screen = gdk_display_get_default_screen (display);
1080   window = gdk_screen_get_root_window (screen);
1081   XQueryBestCursor (GDK_DISPLAY_XDISPLAY (display), 
1082                     GDK_WINDOW_XWINDOW (window), 
1083                     128, 128, width, height);
1084 }