00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "config.h"
00021
00022 #include "gdkcursor.h"
00023 #include "gdkwin32.h"
00024
00025 static const struct {
00026 const char *name;
00027 int type;
00028 } cursors[] = {
00029 {
00030 "x_cursor", 0}, {
00031 "arrow", 2}, {
00032 "bottom_left_corner", 12}, {
00033 "bottom_right_corner", 14}, {
00034 "bottom_side", 16}, {
00035 "busy", 21}, {
00036 "center_ptr", 22}, {
00037 "circle", 24}, {
00038 "kr", 34}, {
00039 "dot", 38}, {
00040 "dotbox", 40}, {
00041 "double_arrow", 42}, {
00042 "exchange", 50}, {
00043 "fleur", 52}, {
00044 "gobbler", 54}, {
00045 "gumby", 56}, {
00046 "hand1", 58}, {
00047 "hand2", 60}, {
00048 "heart", 62}, {
00049 "left_ptr", 68}, {
00050 "left_side", 70}, {
00051 "pencil", 86}, {
00052 "pirate", 88}, {
00053 "plus", 90}, {
00054 "question_arrow", 92}, {
00055 "right_ptr", 94}, {
00056 "right_side", 96}, {
00057 "sb_down_arrow", 106}, {
00058 "sb_h_double_arrow", 108}, {
00059 "sb_left_arrow", 110}, {
00060 "sb_right_arrow", 112}, {
00061 "sb_up_arrow", 114}, {
00062 "sb_v_double_arrow", 116}, {
00063 "shuttle", 118}, {
00064 "spider", 122}, {
00065 "spraycan", 124}, {
00066 "star", 126}, {
00067 "top_left_arrow", 132}, {
00068 "top_left_corner", 134}, {
00069 "top_right_corner", 136}, {
00070 "top_side", 138}, {
00071 "umbrella", 146}, {
00072 "watch", 150}, {
00073 "xterm", 152}, {
00074 NULL, 0}
00075 };
00076
00077 GdkCursor *gdk_cursor_new(GdkCursorType cursor_type)
00078 {
00079 GdkCursorPrivate *private;
00080 GdkCursor *cursor;
00081 HCURSOR xcursor;
00082 int i;
00083
00084 for (i = 0; cursors[i].name != NULL && cursors[i].type != cursor_type;
00085 i++);
00086 if (cursors[i].name != NULL) {
00087 xcursor = LoadImage(gdk_DLLInstance, cursors[i].name, IMAGE_CURSOR,
00088 0, 0, 0);
00089 if (xcursor == NULL)
00090 WIN32_API_FAILED("LoadImage");
00091 GDK_NOTE(MISC, g_print("gdk_cursor_new: %#x %d\n",
00092 xcursor, cursor_type));
00093 } else {
00094 g_warning("gdk_cursor_new: no cursor %d found", cursor_type);
00095 xcursor = NULL;
00096 }
00097
00098 private = g_new(GdkCursorPrivate, 1);
00099 private->xcursor = xcursor;
00100 cursor = (GdkCursor *) private;
00101 cursor->type = cursor_type;
00102 cursor->ref_count = 1;
00103
00104 return cursor;
00105 }
00106
00107 GdkCursor *gdk_syscursor_new(unsigned long syscur)
00108 {
00109 GdkCursorPrivate *private;
00110 GdkCursor *cursor;
00111 HCURSOR xcursor;
00112 xcursor = LoadCursor(NULL, (LPCTSTR)syscur);
00113 if (xcursor == NULL)
00114 WIN32_API_FAILED("LoadCursor");
00115 GDK_NOTE(MISC, g_print("gdk_syscursor_new: %#x %ld\n",
00116 xcursor, syscur));
00117
00118 private = g_new(GdkCursorPrivate, 1);
00119 private->xcursor = xcursor;
00120 cursor = (GdkCursor *) private;
00121 cursor->type = LOWORD(syscur);
00122 cursor->ref_count = 1;
00123
00124 return cursor;
00125 }
00126
00127 static gboolean color_is_white(GdkColor * color)
00128 {
00129 return (color->red == 0xFFFF
00130 && color->green == 0xFFFF && color->blue == 0xFFFF);
00131 }
00132
00133 GdkCursor *gdk_cursor_new_from_pixmap(GdkPixmap * source,
00134 GdkPixmap * mask,
00135 GdkColor * fg,
00136 GdkColor * bg, gint x, gint y)
00137 {
00138 GdkCursorPrivate *private;
00139 GdkCursor *cursor;
00140 GdkDrawablePrivate *source_private, *mask_private;
00141 GdkImage *source_image, *mask_image;
00142 HCURSOR xcursor;
00143 guchar *p, *q, *XORmask, *ANDmask;
00144 gint width, height, cursor_width, cursor_height;
00145 guchar residue;
00146 gint ix, iy;
00147 gboolean bg_is_white = color_is_white(bg);
00148
00149 g_return_val_if_fail(source != NULL, NULL);
00150 g_return_val_if_fail(mask != NULL, NULL);
00151
00152 source_private = (GdkDrawablePrivate *) source;
00153 mask_private = (GdkDrawablePrivate *) mask;
00154
00155 g_return_val_if_fail(source_private->width == mask_private->width
00156 && source_private->height == mask_private->height,
00157 NULL);
00158 width = source_private->width;
00159 height = source_private->height;
00160 cursor_width = GetSystemMetrics(SM_CXCURSOR);
00161 cursor_height = GetSystemMetrics(SM_CYCURSOR);
00162
00163 g_return_val_if_fail(width <= cursor_width
00164 && height <= cursor_height, NULL);
00165
00166 residue = (1 << ((8 - (width % 8)) % 8)) - 1;
00167
00168 source_image = gdk_image_get(source, 0, 0, width, height);
00169 mask_image = gdk_image_get(mask, 0, 0, width, height);
00170
00171 if (source_image->depth != 1 || mask_image->depth != 1) {
00172 gdk_image_unref(source_image);
00173 gdk_image_unref(mask_image);
00174 g_return_val_if_fail(source_image->depth == 1
00175 && mask_image->depth == 1, NULL);
00176 }
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 for (iy = 0; iy < height; iy++) {
00193 p = (guchar *) source_image->mem + iy * source_image->bpl;
00194 q = (guchar *) mask_image->mem + iy * mask_image->bpl;
00195
00196 for (ix = 0; ix < ((width - 1) / 8 + 1); ix++)
00197 if (bg_is_white)
00198 *p++ |= ~(*q++);
00199 else
00200 *p++ &= *q++;
00201 }
00202
00203
00204 XORmask = g_malloc0(cursor_width / 8 * cursor_height);
00205
00206 for (iy = 0; iy < height; iy++) {
00207 p = (guchar *) source_image->mem + iy * source_image->bpl;
00208 q = XORmask + iy * cursor_width / 8;
00209
00210 for (ix = 0; ix < ((width - 1) / 8 + 1); ix++)
00211 if (bg_is_white)
00212 *q++ = ~(*p++);
00213 else
00214 *q++ = *p++;
00215 q[-1] &= ~residue;
00216 }
00217
00218
00219 ANDmask = g_malloc(cursor_width / 8 * cursor_height);
00220 memset(ANDmask, 0xFF, cursor_width / 8 * cursor_height);
00221
00222 for (iy = 0; iy < height; iy++) {
00223 p = (guchar *) mask_image->mem + iy * mask_image->bpl;
00224 q = ANDmask + iy * cursor_width / 8;
00225
00226 for (ix = 0; ix < ((width - 1) / 8 + 1); ix++)
00227 *q++ = ~(*p++);
00228 q[-1] |= residue;
00229 }
00230
00231 xcursor =
00232 CreateCursor(gdk_ProgInstance, x, y, cursor_width, cursor_height,
00233 ANDmask, XORmask);
00234
00235 GDK_NOTE(MISC, g_print("gdk_cursor_new_from_pixmap: "
00236 "%#x (%dx%d) %#x (%dx%d) = %#x (%dx%d)\n",
00237 GDK_DRAWABLE_XID(source),
00238 source_private->width, source_private->height,
00239 GDK_DRAWABLE_XID(mask),
00240 mask_private->width, mask_private->height,
00241 xcursor, cursor_width, cursor_height));
00242
00243 g_free(XORmask);
00244 g_free(ANDmask);
00245
00246 gdk_image_unref(source_image);
00247 gdk_image_unref(mask_image);
00248
00249 private = g_new(GdkCursorPrivate, 1);
00250 private->xcursor = xcursor;
00251 cursor = (GdkCursor *) private;
00252 cursor->type = GDK_CURSOR_IS_PIXMAP;
00253 cursor->ref_count = 1;
00254
00255 return cursor;
00256 }
00257
00258 void _gdk_cursor_destroy(GdkCursor * cursor)
00259 {
00260 GdkCursorPrivate *private;
00261
00262 g_return_if_fail(cursor != NULL);
00263 private = (GdkCursorPrivate *) cursor;
00264
00265 GDK_NOTE(MISC, g_print("_gdk_cursor_destroy: %#x\n",
00266 (cursor->type ==
00267 GDK_CURSOR_IS_PIXMAP) ? private->xcursor : 0));
00268
00269 if (cursor->type == GDK_CURSOR_IS_PIXMAP) {
00270 if (!DestroyCursor(private->xcursor))
00271 WIN32_API_FAILED("DestroyCursor");
00272 }
00273 g_free(private);
00274 }