gtk2/gdk/win32/gdkcursor-win32.c
Tor Lillqvist a1260f864d Handle also WM_SYSCHAR, and other changes to get handling of Alt+nnn or
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.
2000-07-04 06:12:54 +00:00

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);
}