]> Pileus Git - ~andy/gtk/blob - gdk/linux-fb/gdkcursor-fb.c
Fix typo, where x value was assigned to both x and y.
[~andy/gtk] / gdk / linux-fb / gdkcursor-fb.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 "gdkfb.h"
28 #include "gdkprivate-fb.h"
29 #include "gdkcursor.h"
30
31 #include "x-cursors.xbm"
32
33 static struct {
34   const guchar *bits;
35   int width, height, hotx, hoty;
36   GdkCursor *cursor;
37 } stock_cursors[] = {
38 {X_cursor_bits, X_cursor_width, X_cursor_height, X_cursor_x_hot, X_cursor_y_hot},
39 {X_cursor_mask_bits, X_cursor_mask_width, X_cursor_mask_height, X_cursor_mask_x_hot, X_cursor_mask_y_hot},
40 {arrow_bits, arrow_width, arrow_height, arrow_x_hot, arrow_y_hot},
41 {arrow_mask_bits, arrow_mask_width, arrow_mask_height, arrow_mask_x_hot, arrow_mask_y_hot},
42 {based_arrow_down_bits, based_arrow_down_width, based_arrow_down_height, based_arrow_down_x_hot, based_arrow_down_y_hot},
43 {based_arrow_down_mask_bits, based_arrow_down_mask_width, based_arrow_down_mask_height, based_arrow_down_mask_x_hot, based_arrow_down_mask_y_hot},
44 {based_arrow_up_bits, based_arrow_up_width, based_arrow_up_height, based_arrow_up_x_hot, based_arrow_up_y_hot},
45 {based_arrow_up_mask_bits, based_arrow_up_mask_width, based_arrow_up_mask_height, based_arrow_up_mask_x_hot, based_arrow_up_mask_y_hot},
46 {boat_bits, boat_width, boat_height, boat_x_hot, boat_y_hot},
47 {boat_mask_bits, boat_mask_width, boat_mask_height, boat_mask_x_hot, boat_mask_y_hot},
48 {bogosity_bits, bogosity_width, bogosity_height, bogosity_x_hot, bogosity_y_hot},
49 {bogosity_mask_bits, bogosity_mask_width, bogosity_mask_height, bogosity_mask_x_hot, bogosity_mask_y_hot},
50 {bottom_left_corner_bits, bottom_left_corner_width, bottom_left_corner_height, bottom_left_corner_x_hot, bottom_left_corner_y_hot},
51 {bottom_left_corner_mask_bits, bottom_left_corner_mask_width, bottom_left_corner_mask_height, bottom_left_corner_mask_x_hot, bottom_left_corner_mask_y_hot},
52 {bottom_right_corner_bits, bottom_right_corner_width, bottom_right_corner_height, bottom_right_corner_x_hot, bottom_right_corner_y_hot},
53 {bottom_right_corner_mask_bits, bottom_right_corner_mask_width, bottom_right_corner_mask_height, bottom_right_corner_mask_x_hot, bottom_right_corner_mask_y_hot},
54 {bottom_side_bits, bottom_side_width, bottom_side_height, bottom_side_x_hot, bottom_side_y_hot},
55 {bottom_side_mask_bits, bottom_side_mask_width, bottom_side_mask_height, bottom_side_mask_x_hot, bottom_side_mask_y_hot},
56 {bottom_tee_bits, bottom_tee_width, bottom_tee_height, bottom_tee_x_hot, bottom_tee_y_hot},
57 {bottom_tee_mask_bits, bottom_tee_mask_width, bottom_tee_mask_height, bottom_tee_mask_x_hot, bottom_tee_mask_y_hot},
58 {box_spiral_bits, box_spiral_width, box_spiral_height, box_spiral_x_hot, box_spiral_y_hot},
59 {box_spiral_mask_bits, box_spiral_mask_width, box_spiral_mask_height, box_spiral_mask_x_hot, box_spiral_mask_y_hot},
60 {center_ptr_bits, center_ptr_width, center_ptr_height, center_ptr_x_hot, center_ptr_y_hot},
61 {center_ptr_mask_bits, center_ptr_mask_width, center_ptr_mask_height, center_ptr_mask_x_hot, center_ptr_mask_y_hot},
62 {circle_bits, circle_width, circle_height, circle_x_hot, circle_y_hot},
63 {circle_mask_bits, circle_mask_width, circle_mask_height, circle_mask_x_hot, circle_mask_y_hot},
64 {clock_bits, clock_width, clock_height, clock_x_hot, clock_y_hot},
65 {clock_mask_bits, clock_mask_width, clock_mask_height, clock_mask_x_hot, clock_mask_y_hot},
66 {coffee_mug_bits, coffee_mug_width, coffee_mug_height, coffee_mug_x_hot, coffee_mug_y_hot},
67 {coffee_mug_mask_bits, coffee_mug_mask_width, coffee_mug_mask_height, coffee_mug_mask_x_hot, coffee_mug_mask_y_hot},
68 {cross_bits, cross_width, cross_height, cross_x_hot, cross_y_hot},
69 {cross_mask_bits, cross_mask_width, cross_mask_height, cross_mask_x_hot, cross_mask_y_hot},
70 {cross_reverse_bits, cross_reverse_width, cross_reverse_height, cross_reverse_x_hot, cross_reverse_y_hot},
71 {cross_reverse_mask_bits, cross_reverse_mask_width, cross_reverse_mask_height, cross_reverse_mask_x_hot, cross_reverse_mask_y_hot},
72 {crosshair_bits, crosshair_width, crosshair_height, crosshair_x_hot, crosshair_y_hot},
73 {crosshair_mask_bits, crosshair_mask_width, crosshair_mask_height, crosshair_mask_x_hot, crosshair_mask_y_hot},
74 {diamond_cross_bits, diamond_cross_width, diamond_cross_height, diamond_cross_x_hot, diamond_cross_y_hot},
75 {diamond_cross_mask_bits, diamond_cross_mask_width, diamond_cross_mask_height, diamond_cross_mask_x_hot, diamond_cross_mask_y_hot},
76 {dot_bits, dot_width, dot_height, dot_x_hot, dot_y_hot},
77 {dot_mask_bits, dot_mask_width, dot_mask_height, dot_mask_x_hot, dot_mask_y_hot},
78 {dotbox_bits, dotbox_width, dotbox_height, dotbox_x_hot, dotbox_y_hot},
79 {dotbox_mask_bits, dotbox_mask_width, dotbox_mask_height, dotbox_mask_x_hot, dotbox_mask_y_hot},
80 {double_arrow_bits, double_arrow_width, double_arrow_height, double_arrow_x_hot, double_arrow_y_hot},
81 {double_arrow_mask_bits, double_arrow_mask_width, double_arrow_mask_height, double_arrow_mask_x_hot, double_arrow_mask_y_hot},
82 {draft_large_bits, draft_large_width, draft_large_height, draft_large_x_hot, draft_large_y_hot},
83 {draft_large_mask_bits, draft_large_mask_width, draft_large_mask_height, draft_large_mask_x_hot, draft_large_mask_y_hot},
84 {draft_small_bits, draft_small_width, draft_small_height, draft_small_x_hot, draft_small_y_hot},
85 {draft_small_mask_bits, draft_small_mask_width, draft_small_mask_height, draft_small_mask_x_hot, draft_small_mask_y_hot},
86 {draped_box_bits, draped_box_width, draped_box_height, draped_box_x_hot, draped_box_y_hot},
87 {draped_box_mask_bits, draped_box_mask_width, draped_box_mask_height, draped_box_mask_x_hot, draped_box_mask_y_hot},
88 {exchange_bits, exchange_width, exchange_height, exchange_x_hot, exchange_y_hot},
89 {exchange_mask_bits, exchange_mask_width, exchange_mask_height, exchange_mask_x_hot, exchange_mask_y_hot},
90 {fleur_bits, fleur_width, fleur_height, fleur_x_hot, fleur_y_hot},
91 {fleur_mask_bits, fleur_mask_width, fleur_mask_height, fleur_mask_x_hot, fleur_mask_y_hot},
92 {gobbler_bits, gobbler_width, gobbler_height, gobbler_x_hot, gobbler_y_hot},
93 {gobbler_mask_bits, gobbler_mask_width, gobbler_mask_height, gobbler_mask_x_hot, gobbler_mask_y_hot},
94 {gumby_bits, gumby_width, gumby_height, gumby_x_hot, gumby_y_hot},
95 {gumby_mask_bits, gumby_mask_width, gumby_mask_height, gumby_mask_x_hot, gumby_mask_y_hot},
96 {hand1_bits, hand1_width, hand1_height, hand1_x_hot, hand1_y_hot},
97 {hand1_mask_bits, hand1_mask_width, hand1_mask_height, hand1_mask_x_hot, hand1_mask_y_hot},
98 {hand2_bits, hand2_width, hand2_height, hand2_x_hot, hand2_y_hot},
99 {hand2_mask_bits, hand2_mask_width, hand2_mask_height, hand2_mask_x_hot, hand2_mask_y_hot},
100 {heart_bits, heart_width, heart_height, heart_x_hot, heart_y_hot},
101 {heart_mask_bits, heart_mask_width, heart_mask_height, heart_mask_x_hot, heart_mask_y_hot},
102 {icon_bits, icon_width, icon_height, icon_x_hot, icon_y_hot},
103 {icon_mask_bits, icon_mask_width, icon_mask_height, icon_mask_x_hot, icon_mask_y_hot},
104 {iron_cross_bits, iron_cross_width, iron_cross_height, iron_cross_x_hot, iron_cross_y_hot},
105 {iron_cross_mask_bits, iron_cross_mask_width, iron_cross_mask_height, iron_cross_mask_x_hot, iron_cross_mask_y_hot},
106 {left_ptr_bits, left_ptr_width, left_ptr_height, left_ptr_x_hot, left_ptr_y_hot},
107 {left_ptr_mask_bits, left_ptr_mask_width, left_ptr_mask_height, left_ptr_mask_x_hot, left_ptr_mask_y_hot},
108 {left_side_bits, left_side_width, left_side_height, left_side_x_hot, left_side_y_hot},
109 {left_side_mask_bits, left_side_mask_width, left_side_mask_height, left_side_mask_x_hot, left_side_mask_y_hot},
110 {left_tee_bits, left_tee_width, left_tee_height, left_tee_x_hot, left_tee_y_hot},
111 {left_tee_mask_bits, left_tee_mask_width, left_tee_mask_height, left_tee_mask_x_hot, left_tee_mask_y_hot},
112 {leftbutton_bits, leftbutton_width, leftbutton_height, leftbutton_x_hot, leftbutton_y_hot},
113 {leftbutton_mask_bits, leftbutton_mask_width, leftbutton_mask_height, leftbutton_mask_x_hot, leftbutton_mask_y_hot},
114 {ll_angle_bits, ll_angle_width, ll_angle_height, ll_angle_x_hot, ll_angle_y_hot},
115 {ll_angle_mask_bits, ll_angle_mask_width, ll_angle_mask_height, ll_angle_mask_x_hot, ll_angle_mask_y_hot},
116 {lr_angle_bits, lr_angle_width, lr_angle_height, lr_angle_x_hot, lr_angle_y_hot},
117 {lr_angle_mask_bits, lr_angle_mask_width, lr_angle_mask_height, lr_angle_mask_x_hot, lr_angle_mask_y_hot},
118 {man_bits, man_width, man_height, man_x_hot, man_y_hot},
119 {man_mask_bits, man_mask_width, man_mask_height, man_mask_x_hot, man_mask_y_hot},
120 {middlebutton_bits, middlebutton_width, middlebutton_height, middlebutton_x_hot, middlebutton_y_hot},
121 {middlebutton_mask_bits, middlebutton_mask_width, middlebutton_mask_height, middlebutton_mask_x_hot, middlebutton_mask_y_hot},
122 {mouse_bits, mouse_width, mouse_height, mouse_x_hot, mouse_y_hot},
123 {mouse_mask_bits, mouse_mask_width, mouse_mask_height, mouse_mask_x_hot, mouse_mask_y_hot},
124 {pencil_bits, pencil_width, pencil_height, pencil_x_hot, pencil_y_hot},
125 {pencil_mask_bits, pencil_mask_width, pencil_mask_height, pencil_mask_x_hot, pencil_mask_y_hot},
126 {pirate_bits, pirate_width, pirate_height, pirate_x_hot, pirate_y_hot},
127 {pirate_mask_bits, pirate_mask_width, pirate_mask_height, pirate_mask_x_hot, pirate_mask_y_hot},
128 {plus_bits, plus_width, plus_height, plus_x_hot, plus_y_hot},
129 {plus_mask_bits, plus_mask_width, plus_mask_height, plus_mask_x_hot, plus_mask_y_hot},
130 {question_arrow_bits, question_arrow_width, question_arrow_height, question_arrow_x_hot, question_arrow_y_hot},
131 {question_arrow_mask_bits, question_arrow_mask_width, question_arrow_mask_height, question_arrow_mask_x_hot, question_arrow_mask_y_hot},
132 {right_ptr_bits, right_ptr_width, right_ptr_height, right_ptr_x_hot, right_ptr_y_hot},
133 {right_ptr_mask_bits, right_ptr_mask_width, right_ptr_mask_height, right_ptr_mask_x_hot, right_ptr_mask_y_hot},
134 {right_side_bits, right_side_width, right_side_height, right_side_x_hot, right_side_y_hot},
135 {right_side_mask_bits, right_side_mask_width, right_side_mask_height, right_side_mask_x_hot, right_side_mask_y_hot},
136 {right_tee_bits, right_tee_width, right_tee_height, right_tee_x_hot, right_tee_y_hot},
137 {right_tee_mask_bits, right_tee_mask_width, right_tee_mask_height, right_tee_mask_x_hot, right_tee_mask_y_hot},
138 {rightbutton_bits, rightbutton_width, rightbutton_height, rightbutton_x_hot, rightbutton_y_hot},
139 {rightbutton_mask_bits, rightbutton_mask_width, rightbutton_mask_height, rightbutton_mask_x_hot, rightbutton_mask_y_hot},
140 {rtl_logo_bits, rtl_logo_width, rtl_logo_height, rtl_logo_x_hot, rtl_logo_y_hot},
141 {rtl_logo_mask_bits, rtl_logo_mask_width, rtl_logo_mask_height, rtl_logo_mask_x_hot, rtl_logo_mask_y_hot},
142 {sailboat_bits, sailboat_width, sailboat_height, sailboat_x_hot, sailboat_y_hot},
143 {sailboat_mask_bits, sailboat_mask_width, sailboat_mask_height, sailboat_mask_x_hot, sailboat_mask_y_hot},
144 {sb_down_arrow_bits, sb_down_arrow_width, sb_down_arrow_height, sb_down_arrow_x_hot, sb_down_arrow_y_hot},
145 {sb_down_arrow_mask_bits, sb_down_arrow_mask_width, sb_down_arrow_mask_height, sb_down_arrow_mask_x_hot, sb_down_arrow_mask_y_hot},
146 {sb_h_double_arrow_bits, sb_h_double_arrow_width, sb_h_double_arrow_height, sb_h_double_arrow_x_hot, sb_h_double_arrow_y_hot},
147 {sb_h_double_arrow_mask_bits, sb_h_double_arrow_mask_width, sb_h_double_arrow_mask_height, sb_h_double_arrow_mask_x_hot, sb_h_double_arrow_mask_y_hot},
148 {sb_left_arrow_bits, sb_left_arrow_width, sb_left_arrow_height, sb_left_arrow_x_hot, sb_left_arrow_y_hot},
149 {sb_left_arrow_mask_bits, sb_left_arrow_mask_width, sb_left_arrow_mask_height, sb_left_arrow_mask_x_hot, sb_left_arrow_mask_y_hot},
150 {sb_right_arrow_bits, sb_right_arrow_width, sb_right_arrow_height, sb_right_arrow_x_hot, sb_right_arrow_y_hot},
151 {sb_right_arrow_mask_bits, sb_right_arrow_mask_width, sb_right_arrow_mask_height, sb_right_arrow_mask_x_hot, sb_right_arrow_mask_y_hot},
152 {sb_up_arrow_bits, sb_up_arrow_width, sb_up_arrow_height, sb_up_arrow_x_hot, sb_up_arrow_y_hot},
153 {sb_up_arrow_mask_bits, sb_up_arrow_mask_width, sb_up_arrow_mask_height, sb_up_arrow_mask_x_hot, sb_up_arrow_mask_y_hot},
154 {sb_v_double_arrow_bits, sb_v_double_arrow_width, sb_v_double_arrow_height, sb_v_double_arrow_x_hot, sb_v_double_arrow_y_hot},
155 {sb_v_double_arrow_mask_bits, sb_v_double_arrow_mask_width, sb_v_double_arrow_mask_height, sb_v_double_arrow_mask_x_hot, sb_v_double_arrow_mask_y_hot},
156 {shuttle_bits, shuttle_width, shuttle_height, shuttle_x_hot, shuttle_y_hot},
157 {shuttle_mask_bits, shuttle_mask_width, shuttle_mask_height, shuttle_mask_x_hot, shuttle_mask_y_hot},
158 {sizing_bits, sizing_width, sizing_height, sizing_x_hot, sizing_y_hot},
159 {sizing_mask_bits, sizing_mask_width, sizing_mask_height, sizing_mask_x_hot, sizing_mask_y_hot},
160 {spider_bits, spider_width, spider_height, spider_x_hot, spider_y_hot},
161 {spider_mask_bits, spider_mask_width, spider_mask_height, spider_mask_x_hot, spider_mask_y_hot},
162 {spraycan_bits, spraycan_width, spraycan_height, spraycan_x_hot, spraycan_y_hot},
163 {spraycan_mask_bits, spraycan_mask_width, spraycan_mask_height, spraycan_mask_x_hot, spraycan_mask_y_hot},
164 {star_bits, star_width, star_height, star_x_hot, star_y_hot},
165 {star_mask_bits, star_mask_width, star_mask_height, star_mask_x_hot, star_mask_y_hot},
166 {target_bits, target_width, target_height, target_x_hot, target_y_hot},
167 {target_mask_bits, target_mask_width, target_mask_height, target_mask_x_hot, target_mask_y_hot},
168 {tcross_bits, tcross_width, tcross_height, tcross_x_hot, tcross_y_hot},
169 {tcross_mask_bits, tcross_mask_width, tcross_mask_height, tcross_mask_x_hot, tcross_mask_y_hot},
170 {top_left_arrow_bits, top_left_arrow_width, top_left_arrow_height, top_left_arrow_x_hot, top_left_arrow_y_hot},
171 {top_left_arrow_mask_bits, top_left_arrow_mask_width, top_left_arrow_mask_height, top_left_arrow_mask_x_hot, top_left_arrow_mask_y_hot},
172 {top_left_corner_bits, top_left_corner_width, top_left_corner_height, top_left_corner_x_hot, top_left_corner_y_hot},
173 {top_left_corner_mask_bits, top_left_corner_mask_width, top_left_corner_mask_height, top_left_corner_mask_x_hot, top_left_corner_mask_y_hot},
174 {top_right_corner_bits, top_right_corner_width, top_right_corner_height, top_right_corner_x_hot, top_right_corner_y_hot},
175 {top_right_corner_mask_bits, top_right_corner_mask_width, top_right_corner_mask_height, top_right_corner_mask_x_hot, top_right_corner_mask_y_hot},
176 {top_side_bits, top_side_width, top_side_height, top_side_x_hot, top_side_y_hot},
177 {top_side_mask_bits, top_side_mask_width, top_side_mask_height, top_side_mask_x_hot, top_side_mask_y_hot},
178 {top_tee_bits, top_tee_width, top_tee_height, top_tee_x_hot, top_tee_y_hot},
179 {top_tee_mask_bits, top_tee_mask_width, top_tee_mask_height, top_tee_mask_x_hot, top_tee_mask_y_hot},
180 {trek_bits, trek_width, trek_height, trek_x_hot, trek_y_hot},
181 {trek_mask_bits, trek_mask_width, trek_mask_height, trek_mask_x_hot, trek_mask_y_hot},
182 {ul_angle_bits, ul_angle_width, ul_angle_height, ul_angle_x_hot, ul_angle_y_hot},
183 {ul_angle_mask_bits, ul_angle_mask_width, ul_angle_mask_height, ul_angle_mask_x_hot, ul_angle_mask_y_hot},
184 {umbrella_bits, umbrella_width, umbrella_height, umbrella_x_hot, umbrella_y_hot},
185 {umbrella_mask_bits, umbrella_mask_width, umbrella_mask_height, umbrella_mask_x_hot, umbrella_mask_y_hot},
186 {ur_angle_bits, ur_angle_width, ur_angle_height, ur_angle_x_hot, ur_angle_y_hot},
187 {ur_angle_mask_bits, ur_angle_mask_width, ur_angle_mask_height, ur_angle_mask_x_hot, ur_angle_mask_y_hot},
188 {watch_bits, watch_width, watch_height, watch_x_hot, watch_y_hot},
189 {watch_mask_bits, watch_mask_width, watch_mask_height, watch_mask_x_hot, watch_mask_y_hot},
190 {xterm_bits, xterm_width, xterm_height, xterm_x_hot, xterm_y_hot},
191 {xterm_mask_bits, xterm_mask_width, xterm_mask_height, xterm_mask_x_hot, xterm_mask_y_hot}
192 };
193
194 GdkCursor*
195 gdk_cursor_new (GdkCursorType cursor_type)
196 {
197   GdkCursor *cursor;
198   
199   if (cursor_type >= sizeof(stock_cursors)/sizeof(stock_cursors[0]))
200     return NULL;
201
202   cursor = stock_cursors[cursor_type].cursor;
203   if (!cursor)
204     {
205       GdkPixmap *tmp_pm, *pm, *mask;
206       GdkGC *copy_gc;
207       char *data;
208      
209       tmp_pm = gdk_bitmap_create_from_data (_gdk_parent_root,
210                                             stock_cursors[cursor_type].bits,
211                                             stock_cursors[cursor_type].width,
212                                             stock_cursors[cursor_type].height);
213
214       /* Create an empty bitmap the size of the mask */
215       data = g_malloc0 (((stock_cursors[cursor_type+1].width+7)/8) * stock_cursors[cursor_type+1].height);
216       pm = gdk_bitmap_create_from_data (_gdk_parent_root,
217                                         data,
218                                         stock_cursors[cursor_type+1].width,
219                                         stock_cursors[cursor_type+1].height);
220       copy_gc = gdk_gc_new (pm);
221       gdk_draw_drawable(pm,
222                         copy_gc,
223                         tmp_pm,
224                         0, 0,
225                         stock_cursors[cursor_type+1].hotx - stock_cursors[cursor_type].hotx,
226                         stock_cursors[cursor_type+1].hoty - stock_cursors[cursor_type].hoty,
227                         stock_cursors[cursor_type].width,
228                         stock_cursors[cursor_type].height);
229       gdk_pixmap_unref (tmp_pm);
230       g_free (data);
231       gdk_gc_unref (copy_gc);
232
233       mask =  gdk_bitmap_create_from_data (_gdk_parent_root,
234                                            stock_cursors[cursor_type+1].bits,
235                                            stock_cursors[cursor_type+1].width,
236                                            stock_cursors[cursor_type+1].height);
237
238       cursor = gdk_cursor_new_from_pixmap (pm, mask, NULL, NULL,
239                                      stock_cursors[cursor_type+1].hotx,
240                                      stock_cursors[cursor_type+1].hoty);
241
242       stock_cursors[cursor_type].cursor = cursor;
243     }
244   return gdk_cursor_ref (cursor);
245 }
246
247 GdkCursor*
248 gdk_cursor_new_from_pixmap (GdkPixmap *source,
249                             GdkPixmap *mask,
250                             GdkColor  *fg,
251                             GdkColor  *bg,
252                             gint       x,
253                             gint       y)
254 {
255   GdkCursorPrivateFB *private;
256   GdkCursor *cursor;
257
258   g_return_val_if_fail (source != NULL, NULL);
259
260   private = g_new (GdkCursorPrivateFB, 1);
261   cursor = (GdkCursor *) private;
262   cursor->type = GDK_CURSOR_IS_PIXMAP;
263   cursor->ref_count = 1;
264   private->cursor = gdk_pixmap_ref (source);
265   private->mask = gdk_pixmap_ref (mask);
266   private->hot_x = x;
267   private->hot_y = y;
268   
269   return cursor;
270 }
271
272 void
273 _gdk_cursor_destroy (GdkCursor *cursor)
274 {
275   GdkCursorPrivateFB *private;
276
277   g_return_if_fail (cursor != NULL);
278   g_return_if_fail (cursor->ref_count == 0);
279
280   private = (GdkCursorPrivateFB *) cursor;
281
282   if (private->mask)
283     gdk_pixmap_unref (private->mask);
284   gdk_pixmap_unref (private->cursor);
285   
286   g_free (private);
287 }
288
289 /* Global data to keep track of cursor */
290 static GdkPixmap *last_contents = NULL;
291 static GdkPoint last_location, last_contents_size;
292 static GdkCursor *last_cursor = NULL;
293 static GdkFBDrawingContext *gdk_fb_cursor_dc = NULL;
294 static GdkFBDrawingContext cursor_dc_dat;
295 static GdkGC *cursor_gc;
296 static gint cursor_visibility_count = 1;
297
298 static GdkFBDrawingContext *
299 gdk_fb_cursor_dc_reset (void)
300 {
301   if (gdk_fb_cursor_dc)
302     gdk_fb_drawing_context_finalize (gdk_fb_cursor_dc);
303
304   gdk_fb_cursor_dc = &cursor_dc_dat;
305   gdk_fb_drawing_context_init (gdk_fb_cursor_dc,
306                                GDK_DRAWABLE_IMPL(_gdk_parent_root),
307                                cursor_gc,
308                                TRUE,
309                                FALSE);
310
311   return gdk_fb_cursor_dc;
312 }
313
314 void
315 gdk_fb_cursor_hide (void)
316 {
317   GdkFBDrawingContext *mydc = gdk_fb_cursor_dc;
318
319   cursor_visibility_count--;
320   g_assert (cursor_visibility_count <= 0);
321   
322   if (cursor_visibility_count < 0)
323     return;
324
325   if (!mydc)
326     mydc = gdk_fb_cursor_dc_reset ();
327
328   if (last_contents)
329     {
330       gdk_gc_set_clip_mask (cursor_gc, NULL);
331       /* Restore old picture */
332       gdk_fb_draw_drawable_3 (GDK_DRAWABLE_IMPL(_gdk_parent_root),
333                               cursor_gc,
334                               GDK_DRAWABLE_IMPL(last_contents),
335                               mydc,
336                               0, 0,
337                               last_location.x,
338                               last_location.y,
339                               last_contents_size.x,
340                               last_contents_size.y);
341       gdk_shadow_fb_update (last_location.x, last_location.y,
342                             last_location.x + last_contents_size.x,
343                             last_location.y + last_contents_size.y);
344     }
345 }
346
347 void
348 gdk_fb_cursor_invalidate (void)
349 {
350   if (last_contents)
351     {
352       gdk_pixmap_unref (last_contents);
353       last_contents = NULL;
354     }
355 }
356
357 void
358 gdk_fb_cursor_unhide()
359 {
360   GdkFBDrawingContext *mydc = gdk_fb_cursor_dc;
361   GdkCursorPrivateFB *last_private;
362   GdkDrawableFBData *pixmap_last;
363   
364   last_private = GDK_CURSOR_FB (last_cursor);
365   cursor_visibility_count++;
366   g_assert (cursor_visibility_count <= 1);
367   if (cursor_visibility_count < 1)
368     return;
369
370   if (!mydc)
371     mydc = gdk_fb_cursor_dc_reset ();
372
373   if (last_cursor)
374     {
375       pixmap_last = GDK_DRAWABLE_IMPL_FBDATA (last_private->cursor);
376       
377       if (!last_contents ||
378           pixmap_last->width > GDK_DRAWABLE_IMPL_FBDATA (last_contents)->width ||
379           pixmap_last->height > GDK_DRAWABLE_IMPL_FBDATA (last_contents)->height)
380         {
381           if (last_contents)
382             gdk_pixmap_unref (last_contents);
383
384           last_contents = gdk_pixmap_new (_gdk_parent_root,
385                                           pixmap_last->width,
386                                           pixmap_last->height,
387                                           GDK_DRAWABLE_IMPL_FBDATA (_gdk_parent_root)->depth);
388         }
389
390       gdk_gc_set_clip_mask (cursor_gc, NULL);
391       gdk_fb_draw_drawable_2 (GDK_DRAWABLE_IMPL (last_contents),
392                               cursor_gc,
393                               GDK_DRAWABLE_IMPL (_gdk_parent_root),
394                               last_location.x,
395                               last_location.y,
396                               0, 0,
397                               pixmap_last->width,
398                               pixmap_last->height,
399                               TRUE, FALSE);
400       last_contents_size.x = pixmap_last->width;
401       last_contents_size.y = pixmap_last->height;
402       
403       gdk_gc_set_clip_mask (cursor_gc, last_private->mask);
404       gdk_gc_set_clip_origin (cursor_gc,
405                               last_location.x,
406                               last_location.y);
407
408       gdk_fb_cursor_dc_reset ();
409       gdk_fb_draw_drawable_3 (GDK_DRAWABLE_IMPL (_gdk_parent_root),
410                               cursor_gc,
411                               GDK_DRAWABLE_IMPL (last_private->cursor),
412                               mydc,
413                               0, 0,
414                               last_location.x, last_location.y,
415                               pixmap_last->width,
416                               pixmap_last->height);
417       gdk_shadow_fb_update (last_location.x, last_location.y,
418                             last_location.x + pixmap_last->width,
419                             last_location.y + pixmap_last->height);
420     }
421   else
422     gdk_fb_cursor_invalidate ();
423 }
424
425 gboolean
426 gdk_fb_cursor_region_need_hide (GdkRegion *region)
427 {
428   GdkRectangle testme;
429
430   if (!last_cursor)
431     return FALSE;
432
433   testme.x = last_location.x;
434   testme.y = last_location.y;
435   testme.width = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->width;
436   testme.height = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->height;
437
438   return (gdk_region_rect_in (region, &testme) != GDK_OVERLAP_RECTANGLE_OUT);
439 }
440
441 gboolean
442 gdk_fb_cursor_need_hide (GdkRectangle *rect)
443 {
444   GdkRectangle testme;
445
446   if (!last_cursor)
447     return FALSE;
448
449   testme.x = last_location.x;
450   testme.y = last_location.y;
451   testme.width = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->width;
452   testme.height = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->height;
453
454   return gdk_rectangle_intersect (rect, &testme, &testme);
455 }
456
457 void
458 gdk_fb_get_cursor_rect (GdkRectangle *rect)
459 {
460   if (last_cursor)
461     {
462       rect->x = last_location.x;
463       rect->y = last_location.y;
464       rect->width = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->width;
465       rect->height = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->height;
466     }
467   else
468     {
469       rect->x = rect->y = -1;
470       rect->width = rect->height = 0;
471     }
472 }
473
474 void
475 gdk_fb_cursor_move (gint x, gint y, GdkWindow *in_window)
476 {
477   GdkCursor *the_cursor;
478
479   if (!cursor_gc)
480     {
481       GdkColor white, black;
482       cursor_gc = gdk_gc_new (_gdk_parent_root);
483       gdk_color_black (gdk_colormap_get_system (), &black);
484       gdk_color_white (gdk_colormap_get_system (), &white);
485       gdk_gc_set_foreground (cursor_gc, &black);
486       gdk_gc_set_background (cursor_gc, &white);
487     }
488
489   gdk_fb_cursor_hide ();
490
491   if (_gdk_fb_pointer_grab_window)
492     {
493       if (_gdk_fb_pointer_grab_cursor)
494         the_cursor = _gdk_fb_pointer_grab_cursor;
495       else
496         {
497           GdkWindow *win = _gdk_fb_pointer_grab_window;
498           while (!GDK_WINDOW_IMPL_FBDATA (win)->cursor && GDK_WINDOW_OBJECT (win)->parent)
499             win = (GdkWindow *)GDK_WINDOW_OBJECT (win)->parent;
500           the_cursor = GDK_WINDOW_IMPL_FBDATA (win)->cursor;
501         }
502     }
503   else
504     {
505       while (!GDK_WINDOW_IMPL_FBDATA (in_window)->cursor && GDK_WINDOW_P (in_window)->parent)
506         in_window = (GdkWindow *)GDK_WINDOW_P (in_window)->parent;
507       the_cursor = GDK_WINDOW_IMPL_FBDATA (in_window)->cursor;
508     }
509
510   last_location.x = x - GDK_CURSOR_FB (the_cursor)->hot_x;
511   last_location.y = y - GDK_CURSOR_FB (the_cursor)->hot_y;
512
513   if (the_cursor)
514     gdk_cursor_ref (the_cursor);
515   if (last_cursor)
516     gdk_cursor_unref (last_cursor);
517   last_cursor = the_cursor;
518
519   gdk_fb_cursor_unhide ();
520 }
521
522 void
523 gdk_fb_cursor_reset(void)
524 {
525   GdkWindow *win = gdk_window_at_pointer (NULL, NULL);
526   gint x, y;
527
528   gdk_fb_mouse_get_info (&x, &y, NULL);
529   gdk_fb_cursor_move (x, y, win);
530 }