]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkcursor-x11.c
6498745184155eeda71aa911d473f76bbb197bca
[~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 <X11/Xlib.h>
28 #include <X11/cursorfont.h>
29
30 #include "gdkprivate-x11.h"
31 #include "gdkcursor.h"
32 #include "gdkpixmap-x11.h"
33 #include "gdkx.h"
34 #include <gdk/gdkpixmap.h>
35
36 /**
37  * gdk_cursor_new_for_display:
38  * @display: the #GdkDisplay for which the cursor will be created
39  * @cursor_type: cursor to create
40  * 
41  * Creates a new cursor from the set of builtin cursors.
42  * Some useful ones are:
43  * <itemizedlist>
44  * <listitem><para>
45  *  <inlinegraphic format="PNG" fileref="right_ptr.png"></inlinegraphic> #GDK_RIGHT_PTR (right-facing arrow)
46  * </para></listitem>
47  * <listitem><para>
48  *  <inlinegraphic format="PNG" fileref="crosshair.png"></inlinegraphic> #GDK_CROSSHAIR (crosshair)
49  * </para></listitem>
50  * <listitem><para>
51  *  <inlinegraphic format="PNG" fileref="xterm.png"></inlinegraphic> #GDK_XTERM (I-beam)
52  * </para></listitem>
53  * <listitem><para>
54  * <inlinegraphic format="PNG" fileref="watch.png"></inlinegraphic> #GDK_WATCH (busy)
55  * </para></listitem>
56  * <listitem><para>
57  * <inlinegraphic format="PNG" fileref="fleur.png"></inlinegraphic> #GDK_FLEUR (for moving objects)
58  * </para></listitem>
59  * <listitem><para>
60  * <inlinegraphic format="PNG" fileref="hand1.png"></inlinegraphic> #GDK_HAND1 (a right-pointing hand)
61  * </para></listitem>
62  * <listitem><para>
63  * <inlinegraphic format="PNG" fileref="hand2.png"></inlinegraphic> #GDK_HAND2 (a left-pointing hand)
64  * </para></listitem>
65  * <listitem><para>
66  * <inlinegraphic format="PNG" fileref="left_side.png"></inlinegraphic> #GDK_LEFT_SIDE (resize left side)
67  * </para></listitem>
68  * <listitem><para>
69  * <inlinegraphic format="PNG" fileref="right_side.png"></inlinegraphic> #GDK_RIGHT_SIDE (resize right side)
70  * </para></listitem>
71  * <listitem><para>
72  * <inlinegraphic format="PNG" fileref="top_left_corner.png"></inlinegraphic> #GDK_TOP_LEFT_CORNER (resize northwest corner)
73  * </para></listitem>
74  * <listitem><para>
75  * <inlinegraphic format="PNG" fileref="top_right_corner.png"></inlinegraphic> #GDK_TOP_RIGHT_CORNER (resize northeast corner)
76  * </para></listitem>
77  * <listitem><para>
78  * <inlinegraphic format="PNG" fileref="bottom_left_corner.png"></inlinegraphic> #GDK_BOTTOM_LEFT_CORNER (resize southwest corner)
79  * </para></listitem>
80  * <listitem><para>
81  * <inlinegraphic format="PNG" fileref="bottom_right_corner.png"></inlinegraphic> #GDK_BOTTOM_RIGHT_CORNER (resize southeast corner)
82  * </para></listitem>
83  * <listitem><para>
84  * <inlinegraphic format="PNG" fileref="top_side.png"></inlinegraphic> #GDK_TOP_SIDE (resize top side)
85  * </para></listitem>
86  * <listitem><para>
87  * <inlinegraphic format="PNG" fileref="bottom_side.png"></inlinegraphic> #GDK_BOTTOM_SIDE (resize bottom side)
88  * </para></listitem>
89  * <listitem><para>
90  * <inlinegraphic format="PNG" fileref="sb_h_double_arrow.png"></inlinegraphic> #GDK_SB_H_DOUBLE_ARROW (move vertical splitter)
91  * </para></listitem>
92  * <listitem><para>
93  * <inlinegraphic format="PNG" fileref="sb_v_double_arrow.png"></inlinegraphic> #GDK_SB_V_DOUBLE_ARROW (move horizontal splitter)
94  * </para></listitem>
95  * </itemizedlist>
96  *
97  * To make the cursor invisible, use gdk_cursor_new_from_pixmap() to create
98  * a cursor with no pixels in it.
99  * 
100  * Return value: a new #GdkCursor
101  **/
102 GdkCursor*
103 gdk_cursor_new_for_display (GdkDisplay    *display,
104                             GdkCursorType  cursor_type)
105 {
106   GdkCursorPrivate *private;
107   GdkCursor *cursor;
108   Cursor xcursor;
109
110   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
111
112   if (display->closed)
113     xcursor = None;
114   else
115     xcursor = XCreateFontCursor (GDK_DISPLAY_XDISPLAY (display), cursor_type);
116   
117   private = g_new (GdkCursorPrivate, 1);
118   private->display = display;
119   private->xcursor = xcursor;
120   cursor = (GdkCursor *) private;
121   cursor->type = cursor_type;
122   cursor->ref_count = 1;
123   
124   return cursor;
125 }
126
127 /**
128  * gdk_cursor_new_from_pixmap:
129  * @source: the pixmap specifying the cursor.
130  * @mask: the pixmap specifying the mask, which must be the same size as 
131  *    @source.
132  * @fg: the foreground color, used for the bits in the source which are 1.
133  *    The color does not have to be allocated first. 
134  * @bg: the background color, used for the bits in the source which are 0.
135  *    The color does not have to be allocated first.
136  * @x: the horizontal offset of the 'hotspot' of the cursor. 
137  * @y: the vertical offset of the 'hotspot' of the cursor.
138  * 
139  * Creates a new cursor from a given pixmap and mask. Both the pixmap and mask
140  * must have a depth of 1 (i.e. each pixel has only 2 values - on or off).
141  * The standard cursor size is 16 by 16 pixels. You can create a bitmap 
142  * from inline data as in the below example.
143  * 
144  * <example><title>Creating a custom cursor</title>
145  * <programlisting>
146  * /<!-- -->* This data is in X bitmap format, and can be created with the 'bitmap'
147  *    utility. *<!-- -->/
148  * &num;define cursor1_width 16
149  * &num;define cursor1_height 16
150  * static unsigned char cursor1_bits[] = {
151  *   0x80, 0x01, 0x40, 0x02, 0x20, 0x04, 0x10, 0x08, 0x08, 0x10, 0x04, 0x20,
152  *   0x82, 0x41, 0x41, 0x82, 0x41, 0x82, 0x82, 0x41, 0x04, 0x20, 0x08, 0x10,
153  *   0x10, 0x08, 0x20, 0x04, 0x40, 0x02, 0x80, 0x01};
154  *  
155  * static unsigned char cursor1mask_bits[] = {
156  *   0x80, 0x01, 0xc0, 0x03, 0x60, 0x06, 0x30, 0x0c, 0x18, 0x18, 0x8c, 0x31,
157  *   0xc6, 0x63, 0x63, 0xc6, 0x63, 0xc6, 0xc6, 0x63, 0x8c, 0x31, 0x18, 0x18,
158  *   0x30, 0x0c, 0x60, 0x06, 0xc0, 0x03, 0x80, 0x01};
159  *  
160  *  
161  *  GdkCursor *cursor;
162  *  GdkPixmap *source, *mask;
163  *  GdkColor fg = { 0, 65535, 0, 0 }; /<!-- -->* Red. *<!-- -->/
164  *  GdkColor bg = { 0, 0, 0, 65535 }; /<!-- -->* Blue. *<!-- -->/
165  *  
166  *  
167  *  source = gdk_bitmap_create_from_data (NULL, cursor1_bits,
168  *                                        cursor1_width, cursor1_height);
169  *  mask = gdk_bitmap_create_from_data (NULL, cursor1mask_bits,
170  *                                      cursor1_width, cursor1_height);
171  *  cursor = gdk_cursor_new_from_pixmap (source, mask, &amp;fg, &amp;bg, 8, 8);
172  *  gdk_pixmap_unref (source);
173  *  gdk_pixmap_unref (mask);
174  *  
175  *  
176  *  gdk_window_set_cursor (widget->window, cursor);
177  * </programlisting>
178  * </example>
179  *
180  * Return value: a new #GdkCursor.
181  **/
182 GdkCursor*
183 gdk_cursor_new_from_pixmap (GdkPixmap *source,
184                             GdkPixmap *mask,
185                             GdkColor  *fg,
186                             GdkColor  *bg,
187                             gint       x,
188                             gint       y)
189 {
190   GdkCursorPrivate *private;
191   GdkCursor *cursor;
192   Pixmap source_pixmap, mask_pixmap;
193   Cursor xcursor;
194   XColor xfg, xbg;
195   GdkDisplay *display;
196
197   g_return_val_if_fail (GDK_IS_PIXMAP (source), NULL);
198   g_return_val_if_fail (GDK_IS_PIXMAP (mask), NULL);
199   g_return_val_if_fail (fg != NULL, NULL);
200   g_return_val_if_fail (bg != NULL, NULL);
201
202   source_pixmap = GDK_PIXMAP_XID (source);
203   mask_pixmap   = GDK_PIXMAP_XID (mask);
204   display = GDK_PIXMAP_DISPLAY (source);
205
206   xfg.pixel = fg->pixel;
207   xfg.red = fg->red;
208   xfg.blue = fg->blue;
209   xfg.green = fg->green;
210   xbg.pixel = bg->pixel;
211   xbg.red = bg->red;
212   xbg.blue = bg->blue;
213   xbg.green = bg->green;
214   
215   if (display->closed)
216     xcursor = None;
217   else
218     xcursor = XCreatePixmapCursor (GDK_DISPLAY_XDISPLAY (display),
219                                    source_pixmap, mask_pixmap, &xfg, &xbg, x, y);
220   private = g_new (GdkCursorPrivate, 1);
221   private->display = display;
222   private->xcursor = xcursor;
223   cursor = (GdkCursor *) private;
224   cursor->type = GDK_CURSOR_IS_PIXMAP;
225   cursor->ref_count = 1;
226   
227   return cursor;
228 }
229
230 void
231 _gdk_cursor_destroy (GdkCursor *cursor)
232 {
233   GdkCursorPrivate *private;
234
235   g_return_if_fail (cursor != NULL);
236   g_return_if_fail (cursor->ref_count == 0);
237
238   private = (GdkCursorPrivate *) cursor;
239   if (!private->display->closed && private->xcursor)
240     XFreeCursor (GDK_DISPLAY_XDISPLAY (private->display), private->xcursor);
241
242   g_free (private);
243 }
244
245 /**
246  * gdk_x11_cursor_get_xdisplay:
247  * @cursor: a #GdkCursor.
248  * 
249  * Returns the display of a #GdkCursor.
250  * 
251  * Return value: an Xlib <type>Display*</type>.
252  **/
253 Display *
254 gdk_x11_cursor_get_xdisplay (GdkCursor *cursor)
255 {
256   g_return_val_if_fail (cursor != NULL, NULL);
257
258   return GDK_DISPLAY_XDISPLAY(((GdkCursorPrivate *)cursor)->display);
259 }
260
261 /**
262  * gdk_x11_cursor_get_xcursor:
263  * @cursor: a #GdkCursor.
264  * 
265  * Returns the X cursor belonging to a #GdkCursor.
266  * 
267  * Return value: an Xlib <type>Cursor</type>.
268  **/
269 Cursor
270 gdk_x11_cursor_get_xcursor (GdkCursor *cursor)
271 {
272   g_return_val_if_fail (cursor != NULL, None);
273
274   return ((GdkCursorPrivate *)cursor)->xcursor;
275 }
276
277 /** 
278  * gdk_cursor_get_display:
279  * @cursor : a #GdkCursor.
280  *
281  * Returns the display on which the GdkCursor is defined
282  *
283  * Returns : the #GdkDisplay associated to @cursor
284  */
285
286 GdkDisplay *
287 gdk_cursor_get_display (GdkCursor *cursor)
288 {
289   g_return_val_if_fail (cursor != NULL, NULL);
290
291   return ((GdkCursorPrivate *)cursor)->display;
292 }