1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
23 #include "gdkcursor.h"
24 #include "gdkinternals.h"
25 #include "gdkpixmap-win32.h"
26 #include "gdkprivate-win32.h"
28 static const struct { const char *name; int type; } cursors[] = {
31 { "based_arrow_down", 4 },
32 { "based_arrow_up", 6 },
35 { "bottom_left_corner", 12 },
36 { "bottom_right_corner", 14 },
37 { "bottom_side", 16 },
45 { "cross_reverse", 32 },
47 { "diamond_cross", 36 },
50 { "double_arrow", 42 },
51 { "draft_large", 44 },
52 { "draft_small", 46 },
70 { "middlebutton", 82 },
75 { "question_arrow", 92 },
79 { "rightbutton", 100 },
82 { "sb_down_arrow", 106 },
83 { "sb_h_double_arrow", 108 },
84 { "sb_left_arrow", 110 },
85 { "sb_right_arrow", 112 },
86 { "sb_up_arrow", 114 },
87 { "sb_v_double_arrow", 116 },
95 { "top_left_arrow", 132 },
96 { "top_left_corner", 134 },
97 { "top_right_corner", 136 },
110 gdk_cursor_new (GdkCursorType cursor_type)
112 GdkCursorPrivate *private;
117 for (i = 0; cursors[i].name != NULL && cursors[i].type != cursor_type; i++)
119 if (cursors[i].name != NULL)
121 hcursor = LoadCursor (gdk_dll_hinstance, cursors[i].name);
123 WIN32_API_FAILED ("LoadCursor");
124 GDK_NOTE (MISC, g_print ("gdk_cursor_new: %#x %d\n",
125 (guint) hcursor, cursor_type));
129 g_warning ("gdk_cursor_new: no cursor %d found",
134 private = g_new (GdkCursorPrivate, 1);
135 private->hcursor = hcursor;
136 cursor = (GdkCursor*) private;
137 cursor->type = cursor_type;
138 cursor->ref_count = 1;
144 color_is_white (GdkColor *color)
146 return (color->red == 0xFFFF
147 && color->green == 0xFFFF
148 && color->blue == 0xFFFF);
152 gdk_cursor_new_from_pixmap (GdkPixmap *source,
159 GdkCursorPrivate *private;
161 GdkPixmapImplWin32 *source_impl, *mask_impl;
162 GdkImage *source_image, *mask_image;
164 guchar *p, *q, *xor_mask, *and_mask;
165 gint width, height, cursor_width, cursor_height;
168 const gboolean bg_is_white = color_is_white (bg);
170 g_return_val_if_fail (GDK_IS_PIXMAP (source), NULL);
171 g_return_val_if_fail (GDK_IS_PIXMAP (mask), NULL);
172 g_return_val_if_fail (fg != NULL, NULL);
173 g_return_val_if_fail (bg != NULL, NULL);
175 source_impl = GDK_PIXMAP_IMPL_WIN32 (source);
176 mask_impl = GDK_PIXMAP_IMPL_WIN32 (mask);
178 g_return_val_if_fail (source_impl->width == mask_impl->width
179 && source_impl->height == mask_impl->height,
181 width = source_impl->width;
182 height = source_impl->height;
183 cursor_width = GetSystemMetrics (SM_CXCURSOR);
184 cursor_height = GetSystemMetrics (SM_CYCURSOR);
186 g_return_val_if_fail (width <= cursor_width && height <= cursor_height,
189 residue = (1 << ((8-(width%8))%8)) - 1;
191 source_image = gdk_image_get (source, 0, 0, width, height);
192 mask_image = gdk_image_get (mask, 0, 0, width, height);
194 if (source_image->depth != 1 || mask_image->depth != 1)
196 gdk_image_unref (source_image);
197 gdk_image_unref (mask_image);
198 g_return_val_if_fail (source_image->depth == 1 && mask_image->depth == 1,
202 /* Such complex bit manipulation for this simple task, sigh.
203 * The X cursor and Windows cursor concepts are quite different.
204 * We assume here that we are always called with fg == black and
205 * bg == white, *or* the other way around. Random colours won't work.
206 * (Well, you will get a cursor, but not in those colours.)
209 /* Note: The comments below refer to the case fg==black and
210 * bg==white, as that was what was implemented first. The fg==white
211 * (the "if (fg->pixel)" branches) case was added later.
214 /* First set masked-out source bits, as all source bits matter on Windoze.
215 * As we invert them below, they will be clear in the final xor_mask.
217 for (iy = 0; iy < height; iy++)
219 p = (guchar *) source_image->mem + iy*source_image->bpl;
220 q = (guchar *) mask_image->mem + iy*mask_image->bpl;
222 for (ix = 0; ix < ((width-1)/8+1); ix++)
229 /* XOR mask is initialized to zero */
230 xor_mask = g_malloc0 (cursor_width/8 * cursor_height);
232 for (iy = 0; iy < height; iy++)
234 p = (guchar *) source_image->mem + iy*source_image->bpl;
235 q = xor_mask + iy*cursor_width/8;
237 for (ix = 0; ix < ((width-1)/8+1); ix++)
243 q[-1] &= ~residue; /* Clear left-over bits */
246 /* AND mask is initialized to ones */
247 and_mask = g_malloc (cursor_width/8 * cursor_height);
248 memset (and_mask, 0xFF, cursor_width/8 * cursor_height);
250 for (iy = 0; iy < height; iy++)
252 p = (guchar *) mask_image->mem + iy*mask_image->bpl;
253 q = and_mask + iy*cursor_width/8;
255 for (ix = 0; ix < ((width-1)/8+1); ix++)
258 q[-1] |= residue; /* Set left-over bits */
261 hcursor = CreateCursor (gdk_app_hmodule, x, y, cursor_width, cursor_height,
264 GDK_NOTE (MISC, g_print ("gdk_cursor_new_from_pixmap: "
265 "%#x (%dx%d) %#x (%dx%d) = %#x (%dx%d)\n",
266 (guint) GDK_PIXMAP_HBITMAP (source),
267 source_impl->width, source_impl->height,
268 (guint) GDK_PIXMAP_HBITMAP (mask),
269 mask_impl->width, mask_impl->height,
270 (guint) hcursor, cursor_width, cursor_height));
275 gdk_image_unref (source_image);
276 gdk_image_unref (mask_image);
278 private = g_new (GdkCursorPrivate, 1);
279 private->hcursor = hcursor;
280 cursor = (GdkCursor*) private;
281 cursor->type = GDK_CURSOR_IS_PIXMAP;
282 cursor->ref_count = 1;
288 _gdk_cursor_destroy (GdkCursor *cursor)
290 GdkCursorPrivate *private;
292 g_return_if_fail (cursor != NULL);
293 private = (GdkCursorPrivate *) cursor;
295 GDK_NOTE (MISC, g_print ("_gdk_cursor_destroy: %#x\n",
296 (cursor->type == GDK_CURSOR_IS_PIXMAP) ? (guint) private->hcursor : 0));
298 if (cursor->type == GDK_CURSOR_IS_PIXMAP)
299 if (!DestroyCursor (private->hcursor))
300 WIN32_API_FAILED ("DestroyCursor");