forked from AuroraMiddleware/gtk
a1260f864d
2000-07-04 Tor Lillqvist <tml@iki.fi> * gdk/win32/gdkevents-win32.c (gdk_event_translate): Handle also WM_SYSCHAR, and other changes to get handling of Alt+nnn or Alt+0nnn on the numpad (used to enter characters by numeric code from current DOS or ANSI codepage) working correctly, as in other Windows apps. * gdk/win32/gdkcursor-win32.c (gdk_cursor_new_from_pixmap): Use same argument validity tests as in X11 version. (_gdk_cursor_destroy): Use DestroyCursor, not DestroyIcon. * gdk/win32/gdkwin32.h: Add also WM_MOUSEWHEEL and CopyCursor definitions in case missing from headers. * gdk/win32/gdkwindow-win32.c (gdk_win32_window_destroy): ALso destroy the window-specific cursor. (RegisterGdkClass): Use the global gdk_ProgInstance instead of calling GetModuleHandle(NULL). (gdk_window_set_cursor): Reworked to always copy the passed cursor with CopyCursor before setting it. It is OK for the caller to destroy the GdkCursor (and thus also the Windows cursor) after calling this function. Also, destroy any previous cursor for this window. 2000-05-29 Tor Lillqvist <tml@iki.fi> * gdk/win32/gdkevents-win32.c (gdk_WindowProc): The local "event" variable should be of type GdkEventPrivate.
279 lines
7.5 KiB
C
279 lines
7.5 KiB
C
/* GDK - The GIMP Drawing Kit
|
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "gdkcursor.h"
|
|
#include "gdkinternals.h"
|
|
#include "gdkprivate-win32.h"
|
|
|
|
static const struct { const char *name; int type; } cursors[] = {
|
|
{ "x_cursor", 0 },
|
|
{ "arrow", 2 },
|
|
{ "based_arrow_down", 4 },
|
|
{ "based_arrow_up", 6 },
|
|
{ "boat", 8 },
|
|
{ "bogosity", 10 },
|
|
{ "bottom_left_corner", 12 },
|
|
{ "bottom_right_corner", 14 },
|
|
{ "bottom_side", 16 },
|
|
{ "bottom_tee", 18 },
|
|
{ "box_spiral", 20 },
|
|
{ "center_ptr", 22 },
|
|
{ "circle", 24 },
|
|
{ "clock", 26 },
|
|
{ "coffee_mug", 28 },
|
|
{ "cross", 30 },
|
|
{ "cross_reverse", 32 },
|
|
{ "crosshair", 34 },
|
|
{ "diamond_cross", 36 },
|
|
{ "dot", 38 },
|
|
{ "dotbox", 40 },
|
|
{ "double_arrow", 42 },
|
|
{ "draft_large", 44 },
|
|
{ "draft_small", 46 },
|
|
{ "draped_box", 48 },
|
|
{ "exchange", 50 },
|
|
{ "fleur", 52 },
|
|
{ "gobbler", 54 },
|
|
{ "gumby", 56 },
|
|
{ "hand1", 58 },
|
|
{ "hand2", 60 },
|
|
{ "heart", 62 },
|
|
{ "icon", 64 },
|
|
{ "iron_cross", 66 },
|
|
{ "left_ptr", 68 },
|
|
{ "left_side", 70 },
|
|
{ "left_tee", 72 },
|
|
{ "leftbutton", 74 },
|
|
{ "ll_angle", 76 },
|
|
{ "lr_angle", 78 },
|
|
{ "man", 80 },
|
|
{ "middlebutton", 82 },
|
|
{ "mouse", 84 },
|
|
{ "pencil", 86 },
|
|
{ "pirate", 88 },
|
|
{ "plus", 90 },
|
|
{ "question_arrow", 92 },
|
|
{ "right_ptr", 94 },
|
|
{ "right_side", 96 },
|
|
{ "right_tee", 98 },
|
|
{ "rightbutton", 100 },
|
|
{ "rtl_logo", 102 },
|
|
{ "sailboat", 104 },
|
|
{ "sb_down_arrow", 106 },
|
|
{ "sb_h_double_arrow", 108 },
|
|
{ "sb_left_arrow", 110 },
|
|
{ "sb_right_arrow", 112 },
|
|
{ "sb_up_arrow", 114 },
|
|
{ "sb_v_double_arrow", 116 },
|
|
{ "shuttle", 118 },
|
|
{ "sizing", 120 },
|
|
{ "spider", 122 },
|
|
{ "spraycan", 124 },
|
|
{ "star", 126 },
|
|
{ "target", 128 },
|
|
{ "tcross", 130 },
|
|
{ "top_left_arrow", 132 },
|
|
{ "top_left_corner", 134 },
|
|
{ "top_right_corner", 136 },
|
|
{ "top_side", 138 },
|
|
{ "top_tee", 140 },
|
|
{ "trek", 142 },
|
|
{ "ul_angle", 144 },
|
|
{ "umbrella", 146 },
|
|
{ "ur_angle", 148 },
|
|
{ "watch", 150 },
|
|
{ "xterm", 152 },
|
|
{ NULL, 0 }
|
|
};
|
|
|
|
GdkCursor*
|
|
gdk_cursor_new (GdkCursorType cursor_type)
|
|
{
|
|
GdkCursorPrivate *private;
|
|
GdkCursor *cursor;
|
|
HCURSOR xcursor;
|
|
int i;
|
|
|
|
for (i = 0; cursors[i].name != NULL && cursors[i].type != cursor_type; i++)
|
|
;
|
|
if (cursors[i].name != NULL)
|
|
{
|
|
xcursor = LoadCursor (gdk_DLLInstance, cursors[i].name);
|
|
if (xcursor == NULL)
|
|
WIN32_API_FAILED ("LoadCursor");
|
|
GDK_NOTE (MISC, g_print ("gdk_cursor_new: %#x %d\n",
|
|
xcursor, cursor_type));
|
|
}
|
|
else
|
|
{
|
|
g_warning ("gdk_cursor_new: no cursor %d found",
|
|
cursor_type);
|
|
xcursor = NULL;
|
|
}
|
|
|
|
private = g_new (GdkCursorPrivate, 1);
|
|
private->xcursor = xcursor;
|
|
cursor = (GdkCursor*) private;
|
|
cursor->type = cursor_type;
|
|
cursor->ref_count = 1;
|
|
|
|
return cursor;
|
|
}
|
|
|
|
GdkCursor*
|
|
gdk_cursor_new_from_pixmap (GdkPixmap *source,
|
|
GdkPixmap *mask,
|
|
GdkColor *fg,
|
|
GdkColor *bg,
|
|
gint x,
|
|
gint y)
|
|
{
|
|
GdkCursorPrivate *private;
|
|
GdkCursor *cursor;
|
|
GdkDrawablePrivate *source_private, *mask_private;
|
|
GdkImage *source_image, *mask_image;
|
|
HCURSOR xcursor;
|
|
guchar *p, *q, *XORmask, *ANDmask;
|
|
gint width, height, cursor_width, cursor_height;
|
|
guchar residue;
|
|
gint ix, iy;
|
|
|
|
g_return_val_if_fail (GDK_IS_PIXMAP (source), NULL);
|
|
g_return_val_if_fail (GDK_IS_PIXMAP (mask), NULL);
|
|
g_return_val_if_fail (fg != NULL, NULL);
|
|
g_return_val_if_fail (bg != NULL, NULL);
|
|
|
|
source_private = (GdkDrawablePrivate *) source;
|
|
mask_private = (GdkDrawablePrivate *) mask;
|
|
|
|
g_return_val_if_fail (source_private->width == mask_private->width
|
|
&& source_private->height == mask_private->height,
|
|
NULL);
|
|
width = source_private->width;
|
|
height = source_private->height;
|
|
cursor_width = GetSystemMetrics (SM_CXCURSOR);
|
|
cursor_height = GetSystemMetrics (SM_CYCURSOR);
|
|
|
|
g_return_val_if_fail (width <= cursor_width
|
|
&& height <= cursor_height, NULL);
|
|
|
|
residue = (1 << ((8-(width%8))%8)) - 1;
|
|
|
|
source_image = gdk_image_get (source, 0, 0, width, height);
|
|
mask_image = gdk_image_get (mask, 0, 0, width, height);
|
|
|
|
if (source_image->depth != 1 || mask_image->depth != 1)
|
|
{
|
|
gdk_image_unref (source_image);
|
|
gdk_image_unref (mask_image);
|
|
g_return_val_if_fail (source_image->depth == 1 && mask_image->depth == 1,
|
|
NULL);
|
|
}
|
|
|
|
/* Such complex bit manipulation for this simple task, sigh.
|
|
* The X cursor and Windows cursor concepts are quite different.
|
|
* We assume here that we are always called with fg == black and
|
|
* bg == white.
|
|
*/
|
|
|
|
/* First set masked-out source bits, as all source bits matter on Windoze.
|
|
* As we invert them below, they will be clear in the final XORmask.
|
|
*/
|
|
for (iy = 0; iy < height; iy++)
|
|
{
|
|
p = (guchar *) source_image->mem + iy*source_image->bpl;
|
|
q = (guchar *) mask_image->mem + iy*mask_image->bpl;
|
|
|
|
for (ix = 0; ix < ((width-1)/8+1); ix++)
|
|
*p++ |= ~(*q++);
|
|
}
|
|
|
|
/* XOR mask is initialized to zero */
|
|
XORmask = g_malloc0 (cursor_width/8 * cursor_height);
|
|
|
|
for (iy = 0; iy < height; iy++)
|
|
{
|
|
p = (guchar *) source_image->mem + iy*source_image->bpl;
|
|
q = XORmask + iy*cursor_width/8;
|
|
|
|
for (ix = 0; ix < ((width-1)/8+1); ix++)
|
|
*q++ = ~(*p++);
|
|
q[-1] &= ~residue; /* Clear left-over bits */
|
|
}
|
|
|
|
/* AND mask is initialized to ones */
|
|
ANDmask = g_malloc (cursor_width/8 * cursor_height);
|
|
memset (ANDmask, 0xFF, cursor_width/8 * cursor_height);
|
|
|
|
for (iy = 0; iy < height; iy++)
|
|
{
|
|
p = (guchar *) mask_image->mem + iy*mask_image->bpl;
|
|
q = ANDmask + iy*cursor_width/8;
|
|
|
|
for (ix = 0; ix < ((width-1)/8+1); ix++)
|
|
*q++ = ~(*p++);
|
|
q[-1] |= residue; /* Set left-over bits */
|
|
}
|
|
|
|
xcursor = CreateCursor (gdk_ProgInstance, x, y, cursor_width, cursor_height,
|
|
ANDmask, XORmask);
|
|
|
|
GDK_NOTE (MISC, g_print ("gdk_cursor_new_from_pixmap: "
|
|
"%#x (%dx%d) %#x (%dx%d) = %#x (%dx%d)\n",
|
|
GDK_DRAWABLE_XID (source),
|
|
source_private->width, source_private->height,
|
|
GDK_DRAWABLE_XID (mask),
|
|
mask_private->width, mask_private->height,
|
|
xcursor, cursor_width, cursor_height));
|
|
|
|
g_free (XORmask);
|
|
g_free (ANDmask);
|
|
|
|
gdk_image_unref (source_image);
|
|
gdk_image_unref (mask_image);
|
|
|
|
private = g_new (GdkCursorPrivate, 1);
|
|
private->xcursor = xcursor;
|
|
cursor = (GdkCursor*) private;
|
|
cursor->type = GDK_CURSOR_IS_PIXMAP;
|
|
cursor->ref_count = 1;
|
|
|
|
return cursor;
|
|
}
|
|
|
|
void
|
|
_gdk_cursor_destroy (GdkCursor *cursor)
|
|
{
|
|
GdkCursorPrivate *private;
|
|
|
|
g_return_if_fail (cursor != NULL);
|
|
private = (GdkCursorPrivate *) cursor;
|
|
|
|
GDK_NOTE (MISC, g_print ("_gdk_cursor_destroy: %#x\n",
|
|
(cursor->type == GDK_CURSOR_IS_PIXMAP) ? private->xcursor : 0));
|
|
|
|
if (cursor->type == GDK_CURSOR_IS_PIXMAP)
|
|
if (!DestroyCursor (private->xcursor))
|
|
WIN32_API_FAILED ("DestroyCursor");
|
|
|
|
g_free (private);
|
|
}
|