gdkcursor-win32.c

Go to the documentation of this file.
00001 /* GDK - The GIMP Drawing Kit
00002  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
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    /* Such complex bit manipulation for this simple task, sigh.
00179     * The X cursor and Windows cursor concepts are quite different.
00180     * We assume here that we are always called with fg == black and
00181     * bg == white, *or* the other way around. Random colours won't work.
00182     * (Well, you will get a cursor, but not in those colours.)
00183     */
00184 
00185    /* Note: The comments below refer to the case fg==black and
00186     * bg==white.
00187     */
00188 
00189    /* First set masked-out source bits, as all source bits matter on Windoze.
00190     * As we invert them below, they will be clear in the final XORmask.
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    /* XOR mask is initialized to zero */
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;        /* Clear left-over bits */
00216    }
00217 
00218    /* AND mask is initialized to ones */
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;         /* Set left-over bits */
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 }

Generated on Tue Jul 5 14:14:39 2011 for ROOT_528-00b_version by  doxygen 1.5.1