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 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 gdk_cursor_new_from_pixmap (GdkPixmap *source,
151 GdkCursorPrivate *private;
153 GdkPixmapImplWin32 *source_impl, *mask_impl;
154 GdkImage *source_image, *mask_image;
156 guchar *p, *q, *xor_mask, *and_mask;
157 gint width, height, cursor_width, cursor_height;
161 g_return_val_if_fail (GDK_IS_PIXMAP (source), NULL);
162 g_return_val_if_fail (GDK_IS_PIXMAP (mask), NULL);
163 g_return_val_if_fail (fg != NULL, NULL);
164 g_return_val_if_fail (bg != NULL, NULL);
166 source_impl = GDK_PIXMAP_IMPL_WIN32 (source);
167 mask_impl = GDK_PIXMAP_IMPL_WIN32 (mask);
169 g_return_val_if_fail (source_impl->width == mask_impl->width
170 && source_impl->height == mask_impl->height,
172 width = source_impl->width;
173 height = source_impl->height;
174 cursor_width = GetSystemMetrics (SM_CXCURSOR);
175 cursor_height = GetSystemMetrics (SM_CYCURSOR);
177 g_return_val_if_fail (width <= cursor_width && height <= cursor_height,
180 residue = (1 << ((8-(width%8))%8)) - 1;
182 source_image = gdk_image_get (source, 0, 0, width, height);
183 mask_image = gdk_image_get (mask, 0, 0, width, height);
185 if (source_image->depth != 1 || mask_image->depth != 1)
187 gdk_image_unref (source_image);
188 gdk_image_unref (mask_image);
189 g_return_val_if_fail (source_image->depth == 1 && mask_image->depth == 1,
193 /* Such complex bit manipulation for this simple task, sigh.
194 * The X cursor and Windows cursor concepts are quite different.
195 * We assume here that we are always called with fg == black and
199 /* First set masked-out source bits, as all source bits matter on Windoze.
200 * As we invert them below, they will be clear in the final xor_mask.
202 for (iy = 0; iy < height; iy++)
204 p = (guchar *) source_image->mem + iy*source_image->bpl;
205 q = (guchar *) mask_image->mem + iy*mask_image->bpl;
207 for (ix = 0; ix < ((width-1)/8+1); ix++)
211 /* XOR mask is initialized to zero */
212 xor_mask = g_malloc0 (cursor_width/8 * cursor_height);
214 for (iy = 0; iy < height; iy++)
216 p = (guchar *) source_image->mem + iy*source_image->bpl;
217 q = xor_mask + iy*cursor_width/8;
219 for (ix = 0; ix < ((width-1)/8+1); ix++)
221 q[-1] &= ~residue; /* Clear left-over bits */
224 /* AND mask is initialized to ones */
225 and_mask = g_malloc (cursor_width/8 * cursor_height);
226 memset (and_mask, 0xFF, cursor_width/8 * cursor_height);
228 for (iy = 0; iy < height; iy++)
230 p = (guchar *) mask_image->mem + iy*mask_image->bpl;
231 q = and_mask + iy*cursor_width/8;
233 for (ix = 0; ix < ((width-1)/8+1); ix++)
235 q[-1] |= residue; /* Set left-over bits */
238 hcursor = CreateCursor (gdk_app_hmodule, x, y, cursor_width, cursor_height,
241 GDK_NOTE (MISC, g_print ("gdk_cursor_new_from_pixmap: "
242 "%#x (%dx%d) %#x (%dx%d) = %#x (%dx%d)\n",
243 GDK_PIXMAP_HBITMAP (source),
244 source_impl->width, source_impl->height,
245 GDK_PIXMAP_HBITMAP (mask),
246 mask_impl->width, mask_impl->height,
247 hcursor, cursor_width, cursor_height));
252 gdk_image_unref (source_image);
253 gdk_image_unref (mask_image);
255 private = g_new (GdkCursorPrivate, 1);
256 private->hcursor = hcursor;
257 cursor = (GdkCursor*) private;
258 cursor->type = GDK_CURSOR_IS_PIXMAP;
259 cursor->ref_count = 1;
265 _gdk_cursor_destroy (GdkCursor *cursor)
267 GdkCursorPrivate *private;
269 g_return_if_fail (cursor != NULL);
270 private = (GdkCursorPrivate *) cursor;
272 GDK_NOTE (MISC, g_print ("_gdk_cursor_destroy: %#x\n",
273 (cursor->type == GDK_CURSOR_IS_PIXMAP) ? private->hcursor : 0));
275 if (cursor->type == GDK_CURSOR_IS_PIXMAP)
276 if (!DestroyCursor (private->hcursor))
277 WIN32_API_FAILED ("DestroyCursor");