gtk/gdk/win32/gdkcursor-win32.c
Owen Taylor 28c2b0a31f Renames:
Thu Jun 20 19:41:09 2002  Owen Taylor  <otaylor@redhat.com>

        * gdk/gdkdisplay.h gdk/gdkscreen.h gdk/**.c gtk/*.c
        tests/*.c: Renames:

         gdk_get_default_display => gdk_display_get_default
         gdk_get_default_screen  => gdk_screen_get_default
         gdk_open_display        => gdk_display_open
2002-06-20 23:59:27 +00:00

315 lines
8.4 KiB
C

/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Copyright (C) 1998-2002 Tor Lillqvist
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser 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 "gdkdisplay.h"
#include "gdkcursor.h"
#include "gdkprivate-win32.h"
#include "xcursors.h"
static HCURSOR
_gdk_win32_data_to_wcursor (GdkCursorType cursor_type)
{
gint i, j, x, y, ofs;
HCURSOR rv = NULL;
gint w, h;
guchar *and_plane, *xor_plane;
for (i = 0; i < G_N_ELEMENTS (cursors); i++)
if (cursors[i].type == cursor_type)
break;
if (i >= G_N_ELEMENTS (cursors) || !cursors[i].name)
return NULL;
w = GetSystemMetrics (SM_CXCURSOR);
h = GetSystemMetrics (SM_CYCURSOR);
and_plane = g_malloc ((w/8) * h);
memset (and_plane, 0xff, (w/8) * h);
xor_plane = g_malloc ((w/8) * h);
memset (xor_plane, 0, (w/8) * h);
#define SET_BIT(v,b) (v |= (1 << b))
#define RESET_BIT(v,b) (v &= ~(1 << b))
for (j = 0, y = 0; y < cursors[i].height && y < h ; y++)
{
ofs = (y * w) / 8;
j = y * cursors[i].width;
for (x = 0; x < cursors[i].width && x < w ; x++, j++)
{
gint pofs = ofs + x / 8;
guchar data = (cursors[i].data[j/4] & (0xc0 >> (2 * (j%4)))) >> (2 * (3 - (j%4)));
gint bit = 7 - (j % cursors[i].width) % 8;
if (data)
{
RESET_BIT (and_plane[pofs], bit);
if (data == 1)
SET_BIT (xor_plane[pofs], bit);
}
}
}
#undef SET_BIT
#undef RESET_BIT
rv = CreateCursor (gdk_app_hmodule, cursors[i].hotx, cursors[i].hoty,
w, h, and_plane, xor_plane);
if (rv == NULL)
WIN32_API_FAILED ("CreateCursor");
g_free (and_plane);
g_free (xor_plane);
return rv;
}
GdkCursor*
gdk_cursor_new_for_display (GdkDisplay *display,
GdkCursorType cursor_type)
{
GdkCursorPrivate *private;
GdkCursor *cursor;
HCURSOR hcursor;
g_return_val_if_fail (display == gdk_display_get_default (), NULL);
hcursor = _gdk_win32_data_to_wcursor (cursor_type);
if (hcursor == NULL)
g_warning ("gdk_cursor_new: no cursor %d found", cursor_type);
else
GDK_NOTE (MISC, g_print ("gdk_cursor_new: %d: %#x\n",
cursor_type, (guint) hcursor));
private = g_new (GdkCursorPrivate, 1);
private->hcursor = hcursor;
cursor = (GdkCursor*) private;
cursor->type = cursor_type;
cursor->ref_count = 1;
return cursor;
}
static gboolean
color_is_white (GdkColor *color)
{
return (color->red == 0xFFFF
&& color->green == 0xFFFF
&& color->blue == 0xFFFF);
}
GdkCursor*
gdk_cursor_new_from_pixmap (GdkPixmap *source,
GdkPixmap *mask,
GdkColor *fg,
GdkColor *bg,
gint x,
gint y)
{
GdkCursorPrivate *private;
GdkCursor *cursor;
GdkPixmapImplWin32 *source_impl, *mask_impl;
GdkImage *source_image, *mask_image;
HCURSOR hcursor;
guchar *p, *q, *xor_mask, *and_mask;
gint width, height, cursor_width, cursor_height;
guchar residue;
gint ix, iy;
const gboolean bg_is_white = color_is_white (bg);
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_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (source)->impl);
mask_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (mask)->impl);
g_return_val_if_fail (source_impl->width == mask_impl->width
&& source_impl->height == mask_impl->height,
NULL);
width = source_impl->width;
height = source_impl->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 = source_impl->image;
mask_image = mask_impl->image;
g_return_val_if_fail (source_image->depth == 1 && mask_image->depth == 1,
NULL);
#ifdef G_ENABLE_DEBUG
if (_gdk_debug_flags & GDK_DEBUG_CURSOR)
{
g_print ("gdk_cursor_new_from_pixmap: source=%p:\n",
source_impl->parent_instance.handle);
for (iy = 0; iy < height; iy++)
{
if (iy == 16)
break;
p = (guchar *) source_image->mem + iy*source_image->bpl;
for (ix = 0; ix < width; ix++)
{
if (ix == 79)
break;
g_print ("%c", ".X"[((*p)>>(7-(ix%8)))&1]);
if ((ix%8) == 7)
p++;
}
g_print ("\n");
}
g_print ("...mask=%p:\n", mask_impl->parent_instance.handle);
for (iy = 0; iy < height; iy++)
{
if (iy == 16)
break;
p = (guchar *) mask_image->mem + iy*source_image->bpl;
for (ix = 0; ix < width; ix++)
{
if (ix == 79)
break;
g_print ("%c", ".X"[((*p)>>(7-(ix%8)))&1]);
if ((ix%8) == 7)
p++;
}
g_print ("\n");
}
}
#endif
/* 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, *or* the other way around. Random colours won't work.
* (Well, you will get a cursor, but not in those colours.)
*/
/* Note: The comments below refer to the case fg==black and
* bg==white, as that was what was implemented first. The fg==white
* (the "if (fg->pixel)" branches) case was added later.
*/
/* 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 xor_mask.
*/
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++)
if (bg_is_white)
*p++ |= ~(*q++);
else
*p++ &= *q++;
}
/* XOR mask is initialized to zero */
xor_mask = g_malloc0 (cursor_width/8 * cursor_height);
for (iy = 0; iy < height; iy++)
{
p = (guchar *) source_image->mem + iy*source_image->bpl;
q = xor_mask + iy*cursor_width/8;
for (ix = 0; ix < ((width-1)/8+1); ix++)
if (bg_is_white)
*q++ = ~(*p++);
else
*q++ = *p++;
q[-1] &= ~residue; /* Clear left-over bits */
}
/* AND mask is initialized to ones */
and_mask = g_malloc (cursor_width/8 * cursor_height);
memset (and_mask, 0xFF, cursor_width/8 * cursor_height);
for (iy = 0; iy < height; iy++)
{
p = (guchar *) mask_image->mem + iy*mask_image->bpl;
q = and_mask + iy*cursor_width/8;
for (ix = 0; ix < ((width-1)/8+1); ix++)
*q++ = ~(*p++);
q[-1] |= residue; /* Set left-over bits */
}
hcursor = CreateCursor (gdk_app_hmodule, x, y, cursor_width, cursor_height,
and_mask, xor_mask);
GDK_NOTE (MISC, g_print ("gdk_cursor_new_from_pixmap: "
"%#x (%dx%d) %#x (%dx%d) = %#x (%dx%d)\n",
(guint) GDK_PIXMAP_HBITMAP (source),
source_impl->width, source_impl->height,
(guint) GDK_PIXMAP_HBITMAP (mask),
mask_impl->width, mask_impl->height,
(guint) hcursor, cursor_width, cursor_height));
g_free (xor_mask);
g_free (and_mask);
private = g_new (GdkCursorPrivate, 1);
private->hcursor = hcursor;
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) ? (guint) private->hcursor : 0));
if (GetCursor() == private->hcursor)
SetCursor(NULL);
if (!DestroyCursor (private->hcursor))
WIN32_API_FAILED ("DestroyCursor");
g_free (private);
}
GdkDisplay *
gdk_cursor_get_display (GdkCursor *cursor)
{
return gdk_display_get_default ();
}