1999-11-11 22:01:55 +00:00
|
|
|
/* GDK - The GIMP Drawing Kit
|
|
|
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
Massive changes. Too many to list here, but I'll try a summary:
2002-02-17 Tor Lillqvist <tml@iki.fi>
* gdk/win32/*.c: Massive changes. Too many to list here, but I'll
try a summary:
1) Unify GdkPixmap and GdkImage implementation: For each
GdkPixmap, allocate a GdkImage, and vice versa.
GdkPixmapImplWin32Data has a pointer to the GdkImage.
GdkImage::windowing_data is a pointer to the GdkPixmap.
This simplifies many pixmap and image related functions a lot, and
reduces duplicated code snippets. For instance, there is only one
place in gdk/win32 where CreateDIBSection() is called, in the
function _gdk_win32_new_pixmap(). Converting a bitmap (GdkPixmap)
to a Windows region is almost trivial, with the bitmap bits being
readily accessible in the associated GdkImage.
All blitting between GdkPixmaps, GdkWindows and GdkImages goes
through handled the _gdk_win32_blit() function, which calls
different functions to handle the cases of blitting from pixmaps,
inside windows (scrolling), or from windows, which all require
somewhat different handling.
2) Support 256-color mode. This has long been very broken, now it
works more or less OK. Keep the logical palette for each colormap
as small as possible while allocating and freeing colors. Select
and realize the logical palette associated with a GdkColormap into
a DC before drawing or blitting.
When the display is in 256-color mode, make it possible for the
user to override the size of the palette(s) used with either the
GDK_WIN32_MAX_COLORS environment variable, or a -max-colors
command line option. It is possible to reduce the palette size all
the way down to using just the 16 static colors (which causes the
system visual to be of type GDK_VISUAL_STATIC_COLOR. This could
possibly be useful if one desperately wants to avoid color
flashing. (Note that in order for this to work properly, an as of
yet not commited fix to gdkrgb.c is needed.)
Handle the palette messages. On WM_PALETTECHANGED, call
UpdateColors() for the given window hierarchy. Do this only if a
window in some other top-level window hierarchy caused the palette
change (realized a palette). Do this max five times in a row (an
arbitrarily chosen limit), though, otherwise redraw by generating
expose events. On WM_QUERYNEWPALETTE, cause a redraw of the whole
window hierarchy by generating GDK_EXPOSE events.
3) Code cleanup in general. For instance, remove the "emulated"
X11 structs ColormapStruct, Visual and XStandardColormap. Use the
new GDK_DEBUG_* flags for debugging output in the relevant source
files. Remove the unused colormap hash table in gdkcolor-win32.c
4) Plug some resource leaks.
2002-02-14 Tor Lillqvist <tml@iki.fi>
* gdk/win32/gdkdnd-win32.c (gdk_dropfiles_filter): Use
g_filename_to_uri() to actually create legal URIs in the
text/uri-list data.
2002-02-17 00:25:05 +00:00
|
|
|
* Copyright (C) 1998-2002 Tor Lillqvist
|
1999-11-11 22:01:55 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
2000-07-26 11:33:08 +00:00
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
1999-11-11 22:01:55 +00:00
|
|
|
* 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
|
2000-07-26 11:33:08 +00:00
|
|
|
* Lesser General Public License for more details.
|
1999-11-11 22:01:55 +00:00
|
|
|
*
|
2000-07-26 11:33:08 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-02-27 13:01:10 +00:00
|
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
1999-11-11 22:01:55 +00:00
|
|
|
*/
|
|
|
|
|
2008-06-22 14:28:52 +00:00
|
|
|
#include "config.h"
|
2005-07-05 22:50:54 +00:00
|
|
|
#define GDK_PIXBUF_ENABLE_BACKEND /* Ugly? */
|
2002-06-18 20:59:44 +00:00
|
|
|
#include "gdkdisplay.h"
|
1999-11-11 22:01:55 +00:00
|
|
|
#include "gdkcursor.h"
|
2013-05-28 06:59:46 +00:00
|
|
|
#include "gdkwin32.h"
|
2017-11-07 07:39:48 +00:00
|
|
|
#include "gdktextureprivate.h"
|
1999-11-11 22:01:55 +00:00
|
|
|
|
2015-05-13 07:45:40 +00:00
|
|
|
#include "gdkdisplay-win32.h"
|
|
|
|
|
2007-02-04 00:19:53 +00:00
|
|
|
#ifdef __MINGW32__
|
|
|
|
#include <w32api.h>
|
|
|
|
#endif
|
|
|
|
|
2001-02-23 03:51:41 +00:00
|
|
|
#include "xcursors.h"
|
|
|
|
|
2015-05-13 07:45:40 +00:00
|
|
|
typedef struct _DefaultCursor {
|
|
|
|
char *name;
|
|
|
|
char *id;
|
|
|
|
} DefaultCursor;
|
|
|
|
|
|
|
|
static DefaultCursor default_cursors[] = {
|
|
|
|
{ "appstarting", IDC_APPSTARTING },
|
|
|
|
{ "arrow", IDC_ARROW },
|
|
|
|
{ "cross", IDC_CROSS },
|
|
|
|
{ "hand", IDC_HAND },
|
|
|
|
{ "help", IDC_HELP },
|
|
|
|
{ "ibeam", IDC_IBEAM },
|
|
|
|
/* an X cursor name, for compatibility with GTK: */
|
|
|
|
{ "left_ptr_watch", IDC_APPSTARTING },
|
|
|
|
{ "sizeall", IDC_SIZEALL },
|
|
|
|
{ "sizenesw", IDC_SIZENESW },
|
|
|
|
{ "sizens", IDC_SIZENS },
|
|
|
|
{ "sizenwse", IDC_SIZENWSE },
|
|
|
|
{ "sizewe", IDC_SIZEWE },
|
|
|
|
{ "uparrow", IDC_UPARROW },
|
|
|
|
{ "wait", IDC_WAIT },
|
|
|
|
/* css cursor names: */
|
|
|
|
{ "default", IDC_ARROW },
|
|
|
|
{ "pointer", IDC_HAND },
|
|
|
|
{ "progress", IDC_APPSTARTING },
|
|
|
|
{ "crosshair", IDC_CROSS },
|
|
|
|
{ "text", IDC_IBEAM },
|
|
|
|
{ "move", IDC_SIZEALL },
|
|
|
|
{ "not-allowed", IDC_NO },
|
|
|
|
{ "ew-resize", IDC_SIZEWE },
|
2015-07-26 05:34:38 +00:00
|
|
|
{ "e-resize", IDC_SIZEWE },
|
|
|
|
{ "w-resize", IDC_SIZEWE },
|
|
|
|
{ "col-resize", IDC_SIZEWE },
|
2015-05-13 07:45:40 +00:00
|
|
|
{ "ns-resize", IDC_SIZENS },
|
2015-07-26 05:34:38 +00:00
|
|
|
{ "n-resize", IDC_SIZENS },
|
|
|
|
{ "s-resize", IDC_SIZENS },
|
|
|
|
{ "row-resize", IDC_SIZENS },
|
2015-05-13 07:45:40 +00:00
|
|
|
{ "nesw-resize", IDC_SIZENESW },
|
2015-07-26 05:34:38 +00:00
|
|
|
{ "ne-resize", IDC_SIZENESW },
|
|
|
|
{ "sw-resize", IDC_SIZENESW },
|
2015-08-14 12:12:01 +00:00
|
|
|
{ "nwse-resize", IDC_SIZENWSE },
|
|
|
|
{ "nw-resize", IDC_SIZENWSE },
|
2015-07-26 05:34:38 +00:00
|
|
|
{ "se-resize", IDC_SIZENWSE }
|
2015-05-13 07:45:40 +00:00
|
|
|
};
|
|
|
|
|
2001-02-23 03:51:41 +00:00
|
|
|
static HCURSOR
|
2017-11-07 07:39:48 +00:00
|
|
|
hcursor_from_x_cursor (gint i,
|
|
|
|
const gchar *name)
|
2001-02-23 03:51:41 +00:00
|
|
|
{
|
2015-05-13 07:45:40 +00:00
|
|
|
gint j, x, y, ofs;
|
2009-01-21 20:51:22 +00:00
|
|
|
HCURSOR rv;
|
2001-02-23 03:51:41 +00:00
|
|
|
gint w, h;
|
Massive changes. Too many to list here, but I'll try a summary:
2002-02-17 Tor Lillqvist <tml@iki.fi>
* gdk/win32/*.c: Massive changes. Too many to list here, but I'll
try a summary:
1) Unify GdkPixmap and GdkImage implementation: For each
GdkPixmap, allocate a GdkImage, and vice versa.
GdkPixmapImplWin32Data has a pointer to the GdkImage.
GdkImage::windowing_data is a pointer to the GdkPixmap.
This simplifies many pixmap and image related functions a lot, and
reduces duplicated code snippets. For instance, there is only one
place in gdk/win32 where CreateDIBSection() is called, in the
function _gdk_win32_new_pixmap(). Converting a bitmap (GdkPixmap)
to a Windows region is almost trivial, with the bitmap bits being
readily accessible in the associated GdkImage.
All blitting between GdkPixmaps, GdkWindows and GdkImages goes
through handled the _gdk_win32_blit() function, which calls
different functions to handle the cases of blitting from pixmaps,
inside windows (scrolling), or from windows, which all require
somewhat different handling.
2) Support 256-color mode. This has long been very broken, now it
works more or less OK. Keep the logical palette for each colormap
as small as possible while allocating and freeing colors. Select
and realize the logical palette associated with a GdkColormap into
a DC before drawing or blitting.
When the display is in 256-color mode, make it possible for the
user to override the size of the palette(s) used with either the
GDK_WIN32_MAX_COLORS environment variable, or a -max-colors
command line option. It is possible to reduce the palette size all
the way down to using just the 16 static colors (which causes the
system visual to be of type GDK_VISUAL_STATIC_COLOR. This could
possibly be useful if one desperately wants to avoid color
flashing. (Note that in order for this to work properly, an as of
yet not commited fix to gdkrgb.c is needed.)
Handle the palette messages. On WM_PALETTECHANGED, call
UpdateColors() for the given window hierarchy. Do this only if a
window in some other top-level window hierarchy caused the palette
change (realized a palette). Do this max five times in a row (an
arbitrarily chosen limit), though, otherwise redraw by generating
expose events. On WM_QUERYNEWPALETTE, cause a redraw of the whole
window hierarchy by generating GDK_EXPOSE events.
3) Code cleanup in general. For instance, remove the "emulated"
X11 structs ColormapStruct, Visual and XStandardColormap. Use the
new GDK_DEBUG_* flags for debugging output in the relevant source
files. Remove the unused colormap hash table in gdkcolor-win32.c
4) Plug some resource leaks.
2002-02-14 Tor Lillqvist <tml@iki.fi>
* gdk/win32/gdkdnd-win32.c (gdk_dropfiles_filter): Use
g_filename_to_uri() to actually create legal URIs in the
text/uri-list data.
2002-02-17 00:25:05 +00:00
|
|
|
guchar *and_plane, *xor_plane;
|
2001-02-23 03:51:41 +00:00
|
|
|
|
|
|
|
w = GetSystemMetrics (SM_CXCURSOR);
|
|
|
|
h = GetSystemMetrics (SM_CYCURSOR);
|
|
|
|
|
Massive changes. Too many to list here, but I'll try a summary:
2002-02-17 Tor Lillqvist <tml@iki.fi>
* gdk/win32/*.c: Massive changes. Too many to list here, but I'll
try a summary:
1) Unify GdkPixmap and GdkImage implementation: For each
GdkPixmap, allocate a GdkImage, and vice versa.
GdkPixmapImplWin32Data has a pointer to the GdkImage.
GdkImage::windowing_data is a pointer to the GdkPixmap.
This simplifies many pixmap and image related functions a lot, and
reduces duplicated code snippets. For instance, there is only one
place in gdk/win32 where CreateDIBSection() is called, in the
function _gdk_win32_new_pixmap(). Converting a bitmap (GdkPixmap)
to a Windows region is almost trivial, with the bitmap bits being
readily accessible in the associated GdkImage.
All blitting between GdkPixmaps, GdkWindows and GdkImages goes
through handled the _gdk_win32_blit() function, which calls
different functions to handle the cases of blitting from pixmaps,
inside windows (scrolling), or from windows, which all require
somewhat different handling.
2) Support 256-color mode. This has long been very broken, now it
works more or less OK. Keep the logical palette for each colormap
as small as possible while allocating and freeing colors. Select
and realize the logical palette associated with a GdkColormap into
a DC before drawing or blitting.
When the display is in 256-color mode, make it possible for the
user to override the size of the palette(s) used with either the
GDK_WIN32_MAX_COLORS environment variable, or a -max-colors
command line option. It is possible to reduce the palette size all
the way down to using just the 16 static colors (which causes the
system visual to be of type GDK_VISUAL_STATIC_COLOR. This could
possibly be useful if one desperately wants to avoid color
flashing. (Note that in order for this to work properly, an as of
yet not commited fix to gdkrgb.c is needed.)
Handle the palette messages. On WM_PALETTECHANGED, call
UpdateColors() for the given window hierarchy. Do this only if a
window in some other top-level window hierarchy caused the palette
change (realized a palette). Do this max five times in a row (an
arbitrarily chosen limit), though, otherwise redraw by generating
expose events. On WM_QUERYNEWPALETTE, cause a redraw of the whole
window hierarchy by generating GDK_EXPOSE events.
3) Code cleanup in general. For instance, remove the "emulated"
X11 structs ColormapStruct, Visual and XStandardColormap. Use the
new GDK_DEBUG_* flags for debugging output in the relevant source
files. Remove the unused colormap hash table in gdkcolor-win32.c
4) Plug some resource leaks.
2002-02-14 Tor Lillqvist <tml@iki.fi>
* gdk/win32/gdkdnd-win32.c (gdk_dropfiles_filter): Use
g_filename_to_uri() to actually create legal URIs in the
text/uri-list data.
2002-02-17 00:25:05 +00:00
|
|
|
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);
|
2001-02-23 03:51:41 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
if (strcmp (name, "none") != 0)
|
2009-01-21 20:51:22 +00:00
|
|
|
{
|
|
|
|
|
2001-02-23 03:51:41 +00:00
|
|
|
#define SET_BIT(v,b) (v |= (1 << b))
|
|
|
|
#define RESET_BIT(v,b) (v &= ~(1 << b))
|
|
|
|
|
2009-01-21 20:51:22 +00:00
|
|
|
for (j = 0, y = 0; y < cursors[i].height && y < h ; y++)
|
|
|
|
{
|
|
|
|
ofs = (y * w) / 8;
|
|
|
|
j = y * cursors[i].width;
|
2015-04-29 07:31:08 +00:00
|
|
|
|
2009-01-21 20:51:22 +00:00
|
|
|
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;
|
2015-04-29 07:31:08 +00:00
|
|
|
|
2009-01-21 20:51:22 +00:00
|
|
|
if (data)
|
|
|
|
{
|
|
|
|
RESET_BIT (and_plane[pofs], bit);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2009-01-21 20:51:22 +00:00
|
|
|
if (data == 1)
|
|
|
|
SET_BIT (xor_plane[pofs], bit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-02-23 03:51:41 +00:00
|
|
|
|
|
|
|
#undef SET_BIT
|
|
|
|
#undef RESET_BIT
|
|
|
|
|
2009-01-21 20:51:22 +00:00
|
|
|
rv = CreateCursor (_gdk_app_hmodule, cursors[i].hotx, cursors[i].hoty,
|
|
|
|
w, h, and_plane, xor_plane);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rv = CreateCursor (_gdk_app_hmodule, 0, 0,
|
|
|
|
w, h, and_plane, xor_plane);
|
|
|
|
}
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2002-01-11 23:56:28 +00:00
|
|
|
if (rv == NULL)
|
|
|
|
WIN32_API_FAILED ("CreateCursor");
|
2015-05-13 07:45:40 +00:00
|
|
|
|
Massive changes. Too many to list here, but I'll try a summary:
2002-02-17 Tor Lillqvist <tml@iki.fi>
* gdk/win32/*.c: Massive changes. Too many to list here, but I'll
try a summary:
1) Unify GdkPixmap and GdkImage implementation: For each
GdkPixmap, allocate a GdkImage, and vice versa.
GdkPixmapImplWin32Data has a pointer to the GdkImage.
GdkImage::windowing_data is a pointer to the GdkPixmap.
This simplifies many pixmap and image related functions a lot, and
reduces duplicated code snippets. For instance, there is only one
place in gdk/win32 where CreateDIBSection() is called, in the
function _gdk_win32_new_pixmap(). Converting a bitmap (GdkPixmap)
to a Windows region is almost trivial, with the bitmap bits being
readily accessible in the associated GdkImage.
All blitting between GdkPixmaps, GdkWindows and GdkImages goes
through handled the _gdk_win32_blit() function, which calls
different functions to handle the cases of blitting from pixmaps,
inside windows (scrolling), or from windows, which all require
somewhat different handling.
2) Support 256-color mode. This has long been very broken, now it
works more or less OK. Keep the logical palette for each colormap
as small as possible while allocating and freeing colors. Select
and realize the logical palette associated with a GdkColormap into
a DC before drawing or blitting.
When the display is in 256-color mode, make it possible for the
user to override the size of the palette(s) used with either the
GDK_WIN32_MAX_COLORS environment variable, or a -max-colors
command line option. It is possible to reduce the palette size all
the way down to using just the 16 static colors (which causes the
system visual to be of type GDK_VISUAL_STATIC_COLOR. This could
possibly be useful if one desperately wants to avoid color
flashing. (Note that in order for this to work properly, an as of
yet not commited fix to gdkrgb.c is needed.)
Handle the palette messages. On WM_PALETTECHANGED, call
UpdateColors() for the given window hierarchy. Do this only if a
window in some other top-level window hierarchy caused the palette
change (realized a palette). Do this max five times in a row (an
arbitrarily chosen limit), though, otherwise redraw by generating
expose events. On WM_QUERYNEWPALETTE, cause a redraw of the whole
window hierarchy by generating GDK_EXPOSE events.
3) Code cleanup in general. For instance, remove the "emulated"
X11 structs ColormapStruct, Visual and XStandardColormap. Use the
new GDK_DEBUG_* flags for debugging output in the relevant source
files. Remove the unused colormap hash table in gdkcolor-win32.c
4) Plug some resource leaks.
2002-02-14 Tor Lillqvist <tml@iki.fi>
* gdk/win32/gdkdnd-win32.c (gdk_dropfiles_filter): Use
g_filename_to_uri() to actually create legal URIs in the
text/uri-list data.
2002-02-17 00:25:05 +00:00
|
|
|
g_free (and_plane);
|
|
|
|
g_free (xor_plane);
|
2015-04-29 07:31:08 +00:00
|
|
|
|
2001-02-23 03:51:41 +00:00
|
|
|
return rv;
|
|
|
|
}
|
1999-11-11 22:01:55 +00:00
|
|
|
|
2015-05-13 07:45:40 +00:00
|
|
|
static HCURSOR
|
2017-11-07 07:39:48 +00:00
|
|
|
win32_cursor_create_hcursor (Win32Cursor *cursor,
|
|
|
|
const gchar *name)
|
2015-05-13 07:45:40 +00:00
|
|
|
{
|
|
|
|
HCURSOR result;
|
|
|
|
|
|
|
|
switch (cursor->load_type)
|
|
|
|
{
|
|
|
|
case GDK_WIN32_CURSOR_LOAD_FROM_FILE:
|
|
|
|
result = LoadImageW (NULL,
|
|
|
|
cursor->resource_name,
|
|
|
|
IMAGE_CURSOR,
|
|
|
|
cursor->width,
|
|
|
|
cursor->height,
|
|
|
|
cursor->load_flags);
|
|
|
|
break;
|
|
|
|
case GDK_WIN32_CURSOR_LOAD_FROM_RESOURCE_NULL:
|
|
|
|
result = LoadImageA (NULL,
|
|
|
|
(const gchar *) cursor->resource_name,
|
|
|
|
IMAGE_CURSOR,
|
|
|
|
cursor->width,
|
|
|
|
cursor->height,
|
|
|
|
cursor->load_flags);
|
|
|
|
break;
|
|
|
|
case GDK_WIN32_CURSOR_LOAD_FROM_RESOURCE_THIS:
|
|
|
|
result = LoadImageA (_gdk_app_hmodule,
|
|
|
|
(const gchar *) cursor->resource_name,
|
|
|
|
IMAGE_CURSOR,
|
|
|
|
cursor->width,
|
|
|
|
cursor->height,
|
|
|
|
cursor->load_flags);
|
|
|
|
break;
|
|
|
|
case GDK_WIN32_CURSOR_CREATE:
|
|
|
|
result = hcursor_from_x_cursor (cursor->xcursor_number,
|
2017-11-07 07:39:48 +00:00
|
|
|
name);
|
2015-05-13 07:45:40 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
result = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Win32Cursor *
|
|
|
|
win32_cursor_new (GdkWin32CursorLoadType load_type,
|
|
|
|
gpointer resource_name,
|
|
|
|
gint width,
|
|
|
|
gint height,
|
|
|
|
guint load_flags,
|
2017-11-07 07:39:48 +00:00
|
|
|
gint xcursor_number)
|
2015-05-13 07:45:40 +00:00
|
|
|
{
|
|
|
|
Win32Cursor *result;
|
|
|
|
|
|
|
|
result = g_new (Win32Cursor, 1);
|
|
|
|
result->load_type = load_type;
|
|
|
|
result->resource_name = resource_name;
|
|
|
|
result->width = width;
|
|
|
|
result->height = height;
|
|
|
|
result->load_flags = load_flags;
|
|
|
|
result->xcursor_number = xcursor_number;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
win32_cursor_destroy (gpointer data)
|
|
|
|
{
|
|
|
|
Win32Cursor *cursor = data;
|
|
|
|
|
|
|
|
/* resource_name could be a resource ID (uint16_t stored as a pointer),
|
|
|
|
* which shouldn't be freed.
|
|
|
|
*/
|
|
|
|
if (cursor->load_type == GDK_WIN32_CURSOR_LOAD_FROM_FILE)
|
|
|
|
g_free (cursor->resource_name);
|
|
|
|
|
|
|
|
g_free (cursor);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
win32_cursor_theme_load_from (Win32CursorTheme *theme,
|
|
|
|
gint size,
|
|
|
|
const gchar *dir)
|
|
|
|
{
|
|
|
|
GDir *gdir;
|
|
|
|
const gchar *filename;
|
|
|
|
HCURSOR hcursor;
|
|
|
|
|
|
|
|
gdir = g_dir_open (dir, 0, NULL);
|
|
|
|
|
|
|
|
if (gdir == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
while ((filename = g_dir_read_name (gdir)) != NULL)
|
|
|
|
{
|
|
|
|
gchar *fullname;
|
|
|
|
gunichar2 *filenamew;
|
|
|
|
gchar *cursor_name;
|
|
|
|
gchar *dot;
|
|
|
|
Win32Cursor *cursor;
|
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
fullname = g_build_filename (dir, filename, NULL);
|
2015-05-13 07:45:40 +00:00
|
|
|
filenamew = g_utf8_to_utf16 (fullname, -1, NULL, NULL, NULL);
|
|
|
|
g_free (fullname);
|
|
|
|
|
|
|
|
if (filenamew == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
hcursor = LoadImageW (NULL, filenamew, IMAGE_CURSOR, size, size,
|
|
|
|
LR_LOADFROMFILE | (size == 0 ? LR_DEFAULTSIZE : 0));
|
|
|
|
|
|
|
|
if (hcursor == NULL)
|
|
|
|
{
|
|
|
|
g_free (filenamew);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
DestroyCursor (hcursor);
|
|
|
|
dot = strchr (filename, '.');
|
|
|
|
|
|
|
|
cursor_name = dot ? g_strndup (filename, dot - filename) : g_strdup (filename);
|
|
|
|
|
|
|
|
cursor = win32_cursor_new (GDK_WIN32_CURSOR_LOAD_FROM_FILE,
|
|
|
|
filenamew,
|
|
|
|
size,
|
|
|
|
size,
|
|
|
|
LR_LOADFROMFILE | (size == 0 ? LR_DEFAULTSIZE : 0),
|
|
|
|
0);
|
2017-11-07 07:39:48 +00:00
|
|
|
|
2015-05-13 07:45:40 +00:00
|
|
|
g_hash_table_insert (theme->named_cursors, cursor_name, cursor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
win32_cursor_theme_load_from_dirs (Win32CursorTheme *theme,
|
|
|
|
const gchar *name,
|
|
|
|
gint size)
|
|
|
|
{
|
|
|
|
gchar *theme_dir;
|
|
|
|
const gchar * const *dirs;
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
dirs = g_get_system_data_dirs ();
|
|
|
|
|
|
|
|
/* <prefix>/share/icons */
|
|
|
|
for (i = 0; dirs[i]; i++)
|
|
|
|
{
|
2017-11-07 07:39:48 +00:00
|
|
|
theme_dir = g_build_filename (dirs[i], "icons", name, "cursors", NULL);
|
2015-05-13 07:45:40 +00:00
|
|
|
win32_cursor_theme_load_from (theme, size, theme_dir);
|
|
|
|
g_free (theme_dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ~/.icons */
|
2017-11-07 07:39:48 +00:00
|
|
|
theme_dir = g_build_filename (g_get_home_dir (), "icons", name, "cursors", NULL);
|
2015-05-13 07:45:40 +00:00
|
|
|
win32_cursor_theme_load_from (theme, size, theme_dir);
|
|
|
|
g_free (theme_dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
win32_cursor_theme_load_system (Win32CursorTheme *theme,
|
|
|
|
gint size)
|
|
|
|
{
|
|
|
|
gint i;
|
|
|
|
HCURSOR hcursor;
|
|
|
|
Win32Cursor *cursor;
|
|
|
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (cursors); i++)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (cursors[i].name == NULL)
|
|
|
|
break;
|
|
|
|
|
|
|
|
hcursor = NULL;
|
|
|
|
|
|
|
|
/* Prefer W32 cursors */
|
|
|
|
if (cursors[i].builtin)
|
|
|
|
hcursor = LoadImageA (NULL, cursors[i].builtin, IMAGE_CURSOR,
|
|
|
|
size, size,
|
|
|
|
LR_SHARED | (size == 0 ? LR_DEFAULTSIZE : 0));
|
|
|
|
|
|
|
|
/* Fall back to X cursors, but only if we've got no theme cursor */
|
|
|
|
if (hcursor == NULL && g_hash_table_lookup (theme->named_cursors, cursors[i].name) == NULL)
|
2017-11-07 07:39:48 +00:00
|
|
|
hcursor = hcursor_from_x_cursor (i, cursors[i].name);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
|
|
|
if (hcursor == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
DestroyCursor (hcursor);
|
|
|
|
cursor = win32_cursor_new (GDK_WIN32_CURSOR_LOAD_FROM_RESOURCE_NULL,
|
|
|
|
(gpointer) cursors[i].builtin,
|
|
|
|
size,
|
|
|
|
size,
|
|
|
|
LR_SHARED | (size == 0 ? LR_DEFAULTSIZE : 0),
|
|
|
|
0);
|
|
|
|
g_hash_table_insert (theme->named_cursors,
|
|
|
|
g_strdup (cursors[i].name),
|
|
|
|
cursor);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (default_cursors); i++)
|
|
|
|
{
|
|
|
|
if (default_cursors[i].name == NULL)
|
|
|
|
break;
|
|
|
|
|
|
|
|
hcursor = LoadImageA (NULL, default_cursors[i].id, IMAGE_CURSOR, size, size,
|
|
|
|
LR_SHARED | (size == 0 ? LR_DEFAULTSIZE : 0));
|
|
|
|
|
|
|
|
if (hcursor == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
DestroyCursor (hcursor);
|
|
|
|
cursor = win32_cursor_new (GDK_WIN32_CURSOR_LOAD_FROM_RESOURCE_NULL,
|
|
|
|
(gpointer) default_cursors[i].id,
|
|
|
|
size,
|
|
|
|
size,
|
|
|
|
LR_SHARED | (size == 0 ? LR_DEFAULTSIZE : 0),
|
|
|
|
0);
|
|
|
|
g_hash_table_insert (theme->named_cursors,
|
|
|
|
g_strdup (default_cursors[i].name),
|
|
|
|
cursor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Win32CursorTheme *
|
|
|
|
win32_cursor_theme_load (const gchar *name,
|
2017-11-07 07:39:48 +00:00
|
|
|
gint size)
|
2015-05-13 07:45:40 +00:00
|
|
|
{
|
|
|
|
Win32CursorTheme *result = g_new0 (Win32CursorTheme, 1);
|
|
|
|
|
|
|
|
result->named_cursors = g_hash_table_new_full (g_str_hash,
|
|
|
|
g_str_equal,
|
|
|
|
g_free,
|
|
|
|
win32_cursor_destroy);
|
|
|
|
|
|
|
|
if (strcmp (name, "system") == 0)
|
|
|
|
{
|
|
|
|
win32_cursor_theme_load_from_dirs (result, "Adwaita", size);
|
|
|
|
win32_cursor_theme_load_system (result, size);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
win32_cursor_theme_load_from_dirs (result, name, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_hash_table_size (result->named_cursors) > 0)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
win32_cursor_theme_destroy (result);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
win32_cursor_theme_destroy (Win32CursorTheme *theme)
|
|
|
|
{
|
|
|
|
g_hash_table_destroy (theme->named_cursors);
|
|
|
|
g_free (theme);
|
|
|
|
}
|
|
|
|
|
|
|
|
Win32Cursor *
|
|
|
|
win32_cursor_theme_get_cursor (Win32CursorTheme *theme,
|
|
|
|
const gchar *name)
|
|
|
|
{
|
|
|
|
return g_hash_table_lookup (theme->named_cursors, name);
|
|
|
|
}
|
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
static void
|
|
|
|
gdk_win32_cursor_remove_from_cache (gpointer data, GObject *cursor)
|
2015-05-13 07:45:40 +00:00
|
|
|
{
|
2017-11-07 07:39:48 +00:00
|
|
|
GdkDisplay *display = data;
|
|
|
|
HCURSOR hcursor;
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
hcursor = g_hash_table_lookup (GDK_WIN32_DISPLAY (display)->cursors, cursor);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
if (GetCursor () == hcursor)
|
|
|
|
SetCursor (NULL);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
if (!DestroyCursor (hcursor))
|
|
|
|
g_warning (G_STRLOC ": DestroyCursor (%p) failed: %lu", hcursor, GetLastError ());
|
2015-05-13 07:45:40 +00:00
|
|
|
}
|
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
void
|
|
|
|
_gdk_win32_display_finalize_cursors (GdkWin32Display *display)
|
2011-01-02 10:51:25 +00:00
|
|
|
{
|
2017-11-07 07:39:48 +00:00
|
|
|
GHashTableIter iter;
|
|
|
|
gpointer cursor;
|
2011-01-02 10:51:25 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
if (display->cursors)
|
|
|
|
{
|
|
|
|
g_hash_table_iter_init (&iter, display->cursors);
|
|
|
|
while (g_hash_table_iter_next (&iter, &cursor, NULL))
|
|
|
|
g_object_weak_unref (G_OBJECT (cursor),
|
|
|
|
gdk_win32_cursor_remove_from_cache,
|
|
|
|
GDK_DISPLAY (display));
|
|
|
|
g_hash_table_unref (display->cursors);
|
|
|
|
}
|
2011-01-02 10:51:25 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
g_free (display->cursor_theme_name);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
if (display->cursor_theme)
|
|
|
|
win32_cursor_theme_destroy (display->cursor_theme);
|
|
|
|
}
|
2011-01-02 10:51:25 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
void
|
|
|
|
_gdk_win32_display_init_cursors (GdkWin32Display *display)
|
|
|
|
{
|
|
|
|
display->cursors = g_hash_table_new (gdk_cursor_hash,
|
|
|
|
gdk_cursor_equal);
|
|
|
|
display->cursor_theme_name = g_strdup ("system");
|
2011-01-02 10:51:25 +00:00
|
|
|
}
|
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
/* This is where we use the names mapped to the equivilants that Windows define by default */
|
2015-05-13 07:45:40 +00:00
|
|
|
static HCURSOR
|
|
|
|
hcursor_idc_from_name (const gchar *name)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (default_cursors); i++)
|
|
|
|
{
|
|
|
|
if (strcmp (default_cursors[i].name, name) != 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
return LoadImageA (NULL, default_cursors[i].id, IMAGE_CURSOR, 0, 0,
|
|
|
|
LR_SHARED | LR_DEFAULTSIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HCURSOR
|
|
|
|
hcursor_x_from_name (const gchar *name)
|
|
|
|
{
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (cursors); i++)
|
|
|
|
if (cursors[i].name == NULL || strcmp (cursors[i].name, name) == 0)
|
2017-11-07 07:39:48 +00:00
|
|
|
return hcursor_from_x_cursor (i, name);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HCURSOR
|
|
|
|
hcursor_from_theme (GdkDisplay *display,
|
|
|
|
const gchar *name)
|
|
|
|
{
|
|
|
|
Win32CursorTheme *theme;
|
|
|
|
Win32Cursor *theme_cursor;
|
|
|
|
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (display);
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
theme = _gdk_win32_display_get_cursor_theme (win32_display);
|
|
|
|
theme_cursor = win32_cursor_theme_get_cursor (theme, name);
|
|
|
|
|
|
|
|
if (theme_cursor == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
return win32_cursor_create_hcursor (theme_cursor, name);
|
2015-05-13 07:45:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HCURSOR
|
|
|
|
hcursor_from_name (GdkDisplay *display,
|
|
|
|
const gchar *name)
|
|
|
|
{
|
|
|
|
HCURSOR hcursor;
|
|
|
|
|
|
|
|
/* Try current theme first */
|
|
|
|
hcursor = hcursor_from_theme (display, name);
|
|
|
|
|
|
|
|
if (hcursor != NULL)
|
|
|
|
return hcursor;
|
|
|
|
|
|
|
|
hcursor = hcursor_idc_from_name (name);
|
|
|
|
|
|
|
|
if (hcursor != NULL)
|
|
|
|
return hcursor;
|
|
|
|
|
|
|
|
hcursor = hcursor_x_from_name (name);
|
|
|
|
|
|
|
|
return hcursor;
|
|
|
|
}
|
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
/* Create a blank cursor */
|
|
|
|
static HCURSOR
|
|
|
|
create_blank_cursor (void)
|
2005-06-04 21:43:03 +00:00
|
|
|
{
|
2017-11-07 07:39:48 +00:00
|
|
|
gint w, h;
|
|
|
|
guchar *and_plane, *xor_plane;
|
|
|
|
HCURSOR rv;
|
2005-06-04 21:43:03 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
w = GetSystemMetrics (SM_CXCURSOR);
|
|
|
|
h = GetSystemMetrics (SM_CYCURSOR);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
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);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
rv = CreateCursor (_gdk_app_hmodule, 0, 0,
|
|
|
|
w, h, and_plane, xor_plane);
|
2005-06-04 21:43:03 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
if (rv == NULL)
|
|
|
|
WIN32_API_FAILED ("CreateCursor");
|
|
|
|
|
|
|
|
return rv;
|
2005-06-04 21:43:03 +00:00
|
|
|
}
|
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
static HCURSOR
|
|
|
|
gdk_win32_cursor_create_for_name (GdkDisplay *display,
|
|
|
|
const gchar *name)
|
2015-05-13 07:45:40 +00:00
|
|
|
{
|
|
|
|
HCURSOR hcursor = NULL;
|
2017-11-07 07:39:48 +00:00
|
|
|
GdkCursor *result;
|
|
|
|
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (display);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
/* Blank cursor case */
|
|
|
|
if (strcmp (name, "none") == 0)
|
|
|
|
return create_blank_cursor ();
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
hcursor = hcursor_from_name (display, name);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
/* allow to load named cursor resources linked into the executable */
|
|
|
|
if (!hcursor)
|
|
|
|
hcursor = LoadCursor (_gdk_app_hmodule, name);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
|
|
|
if (hcursor == NULL)
|
2017-11-07 07:39:48 +00:00
|
|
|
return NULL;
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
return hcursor;
|
|
|
|
}
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
static HICON
|
|
|
|
pixbuf_to_hicon (GdkPixbuf *pixbuf,
|
|
|
|
gboolean is_icon,
|
|
|
|
gint x,
|
|
|
|
gint y);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
static HCURSOR
|
|
|
|
gdk_win32_cursor_create_for_texture (GdkDisplay *display,
|
|
|
|
GdkTexture *texture,
|
|
|
|
int x,
|
|
|
|
int y)
|
|
|
|
{
|
|
|
|
cairo_surface_t *surface;
|
|
|
|
GdkPixbuf *pixbuf;
|
|
|
|
gint width, height;
|
|
|
|
HICON icon;
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
surface = gdk_texture_download_surface (texture);
|
|
|
|
width = cairo_image_surface_get_width (surface);
|
|
|
|
height = cairo_image_surface_get_height (surface);
|
|
|
|
|
|
|
|
pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, width, height);
|
|
|
|
|
|
|
|
icon = pixbuf_to_hicon (pixbuf, TRUE, 0, 0);
|
|
|
|
|
|
|
|
g_object_unref (pixbuf);
|
|
|
|
|
|
|
|
return (HCURSOR)icon;
|
2015-05-13 07:45:40 +00:00
|
|
|
}
|
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
GdkCursor *
|
|
|
|
gdk_win32_display_cursor_from_hcursor (GdkDisplay *display,
|
|
|
|
HCURSOR hcursor)
|
2015-05-13 07:45:40 +00:00
|
|
|
{
|
|
|
|
GHashTableIter iter;
|
2017-11-07 07:39:48 +00:00
|
|
|
gpointer cursor_current, hcursor_current;
|
|
|
|
|
|
|
|
GdkCursor *cursor = NULL;
|
|
|
|
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (display);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
if (win32_display->cursors)
|
|
|
|
{
|
|
|
|
g_hash_table_iter_init (&iter, win32_display->cursors);
|
|
|
|
while (g_hash_table_iter_next (&iter, &cursor_current, &hcursor_current))
|
|
|
|
if ((HCURSOR)hcursor_current == hcursor)
|
|
|
|
{
|
|
|
|
cursor = (GdkCursor*) cursor_current;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
return cursor;
|
2015-05-13 07:45:40 +00:00
|
|
|
}
|
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
HCURSOR
|
|
|
|
_gdk_win32_display_get_cursor_for_surface (GdkDisplay *display,
|
|
|
|
cairo_surface_t *surface,
|
|
|
|
gdouble x,
|
|
|
|
gdouble y)
|
2015-05-13 07:45:40 +00:00
|
|
|
{
|
2017-11-07 07:39:48 +00:00
|
|
|
HCURSOR hcursor;
|
|
|
|
GdkPixbuf *pixbuf;
|
|
|
|
gint width, height;
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
g_return_val_if_fail (surface != NULL, NULL);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
width = cairo_image_surface_get_width (surface);
|
|
|
|
height = cairo_image_surface_get_height (surface);
|
|
|
|
pixbuf = gdk_pixbuf_get_from_surface (surface,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
width,
|
|
|
|
height);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
|
|
|
|
g_return_val_if_fail (0 <= x && x < gdk_pixbuf_get_width (pixbuf), NULL);
|
|
|
|
g_return_val_if_fail (0 <= y && y < gdk_pixbuf_get_height (pixbuf), NULL);
|
1999-11-11 22:01:55 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
hcursor = _gdk_win32_pixbuf_to_hcursor (pixbuf, x, y);
|
Changes multihead reorganizing code for win32 support, mostly from a patch
Wed Jun 5 18:34:47 2002 Owen Taylor <otaylor@redhat.com>
Changes multihead reorganizing code for win32 support,
mostly from a patch by Hans Breuer.
* gdk/gdkcolor.c gdk/x11/gdkcolor-x11.c gdk/gdkcursor.c
gdk/x11/gdkcursor-x11.c gdk/gdkevents.c gdk/x11/gdkevents-x11.c
gdk/gdkfont.c gdk/x11/gdkfont-x11.c gdk/gdkkeys.c
gdk/x11/gdkkeys-x11.c gdk/gdkimage.c gdk/x11/gdkimage-x11.c
gdk/gdkscreen.c gdk/x11/gdkmain-x11.c
gdk/gdkdisplay.c gdk/gdkevents-x11.c gdk/gdkpango.c
gdk/x11/gdkpango-x11.c gdk/gdkselection.c
gdk/x11/gdkselection-x11.c gdk/gdkwindow.c
gdk/x11/gdkwindow-x11.c gdk/gdkvisual.c gdk/x11/gdkvisual-x11.c:
Move port-independent singlehead wrapper functions into
port-independent part of GDK. (#80009)
* gdk/win32/gdkcolor-win32.c gdk/win32/gdkcursor-win32.c
gdk/win32/gdkevents-win32.c gdk/win32/gdkfont-win32.c
gdk/win32/gdkimage-win32.c gdk/win32/gdkkeys-win32.c
gdk/win32/gdkmain-win32.c gdk/win32/gdkproperty-win32.c
gdk/win32/gdkselection-win32.c gdk/win32/gkwindow-win32.c:
Turn singlehead functions into "multihead" functions that ignore
their GdkDisplay or GdkScreen arguments.
* gdk/win32/gdkdrawable-win32.c gdk/win32/gdkevents-win32.c
gdk/win32/gdkinput-win32.c gdk/win32/gdkprivate-win32.h:
Misc multihead-compatibility changes.
* gtk/gtk.def gdk/gdk.def: Update for multihead functions.
* gdk/gdkcolormap.h gdk/gdkvisual.h gdk/x11/gdkcolormap-x11.c
gdk/x11/gdkvisual-x11.c: Remove the screen fields
from the public parts of the colormap/visual structures, add accessors
instead.
* gdk/gdkpixbuf-render.c gdk/gdkpixmap.c gdk/gdkrgb.c
gdk/x11/gdkcolormap-x11.c gdk/x11/gdkimage-x11.c
gdk/x11/gdkimage-x11.c gdk/x11/gdkprivate-x11.h gtk/gtkgc.c
gtk/gtkstyle.c gtk/gtkwidget.c: Use accessors to get the screen
for colormaps, visuals; move the fields into the private
structures for the x11 backend.
* gdk/gdkdisplay.[ch] gdk/x11/gdkdisplay-x11.[ch]
gdk/gdkscreen.[ch] gdk/x11/gdkscreen-x11.c:
Remove virtualization of screen and display functions.
(#79990, patch from Erwann Chenede)
* gdk/win32/gdkdisplay-x11.c gdk/win32/gdkscreen-win32.c
gdk/win32/{Makefile.am, makefile.msc, makefile.mingw}:
New files containing stub implementations of Display,
Screen functions.
* gdk/x11/gdkscreen-x11.[ch] gdk/x11/gdkdisplay-x11.[ch]
gdk/x11/gdkx.h: Clean up function exports and what
headers they are in. (#79954)
* gdk/x11/gdkx.h: Fix macro that was referring to a non-existant
screen->screen_num. (In the patch for #79972, Erwann Chenede)
* gdk/gdkscreen.c gdk/gdkwindow.c gdk/x11/gdkinternals.h
gdk/x11/gdkscreen-x11.c: Fix gdk_screen_get_window_at_pointer()
to use window hooks. (#79972, patch partly from Erwann Chenede)
* gdk/x11/gdkdisplay-x11.c gdk/x11/gdkevents-x11.c: Fix
some warnings.
2002-06-06 00:26:42 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
g_object_unref (pixbuf);
|
|
|
|
|
|
|
|
return hcursor;
|
|
|
|
}
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
static gboolean
|
|
|
|
_gdk_win32_cursor_update (GdkWin32Display *win32_display,
|
|
|
|
GdkCursor *cursor,
|
|
|
|
HCURSOR hcursor)
|
|
|
|
{
|
|
|
|
HCURSOR hcursor_new = NULL;
|
|
|
|
Win32CursorTheme *theme;
|
|
|
|
Win32Cursor *theme_cursor;
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
const gchar *name = gdk_cursor_get_name (cursor);
|
2001-02-23 03:51:41 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
/* Do nothing if this is not a named cursor. */
|
|
|
|
if (name == NULL)
|
|
|
|
return FALSE;
|
1999-11-11 22:01:55 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
theme = _gdk_win32_display_get_cursor_theme (win32_display);
|
|
|
|
theme_cursor = win32_cursor_theme_get_cursor (theme, name);
|
1999-11-11 22:01:55 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
if (theme_cursor != NULL)
|
|
|
|
hcursor_new = win32_cursor_create_hcursor (theme_cursor, name);
|
2005-07-05 22:50:54 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
if (hcursor_new == NULL)
|
2015-05-13 07:45:40 +00:00
|
|
|
{
|
2017-11-07 07:39:48 +00:00
|
|
|
g_warning (G_STRLOC ": Unable to load %s from the cursor theme", name);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
hcursor_new = hcursor_idc_from_name (name);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
if (hcursor_new == NULL)
|
|
|
|
hcursor_new = hcursor_x_from_name (name);
|
2005-07-03 15:47:42 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
if (hcursor_new == NULL)
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-07-03 15:47:42 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
if (GetCursor () == hcursor)
|
|
|
|
SetCursor (hcursor_new);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
if (!DestroyCursor (hcursor))
|
|
|
|
g_warning (G_STRLOC ": DestroyCursor (%p) failed: %lu", hcursor, GetLastError ());
|
2005-07-05 22:50:54 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
g_hash_table_replace (win32_display->cursors, cursor, hcursor_new);
|
2005-07-03 15:47:42 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
void
|
|
|
|
_gdk_win32_display_update_cursors (GdkWin32Display *display)
|
|
|
|
{
|
|
|
|
GHashTableIter iter;
|
|
|
|
GdkCursor *cursor;
|
|
|
|
HCURSOR hcursor;
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
g_hash_table_iter_init (&iter, display->cursors);
|
2015-05-13 07:45:40 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
while (g_hash_table_iter_next (&iter, (gpointer *) &cursor, &hcursor))
|
|
|
|
_gdk_win32_cursor_update (display, cursor, hcursor);
|
2005-07-03 15:47:42 +00:00
|
|
|
}
|
|
|
|
|
2005-07-05 22:50:54 +00:00
|
|
|
GdkPixbuf *
|
2013-08-21 13:54:09 +00:00
|
|
|
gdk_win32_icon_to_pixbuf_libgtk_only (HICON hicon,
|
|
|
|
gdouble *x_hot,
|
|
|
|
gdouble *y_hot)
|
2005-07-05 22:50:54 +00:00
|
|
|
{
|
|
|
|
GdkPixbuf *pixbuf = NULL;
|
|
|
|
ICONINFO ii;
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
BITMAPINFOHEADER bi;
|
|
|
|
RGBQUAD colors[2];
|
|
|
|
} bmi;
|
|
|
|
HDC hdc;
|
2008-08-04 23:21:36 +00:00
|
|
|
guchar *pixels, *bits;
|
2005-07-05 22:50:54 +00:00
|
|
|
gint rowstride, x, y, w, h;
|
|
|
|
|
|
|
|
if (!GDI_CALL (GetIconInfo, (hicon, &ii)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(hdc = CreateCompatibleDC (NULL)))
|
|
|
|
{
|
|
|
|
WIN32_GDI_FAILED ("CreateCompatibleDC");
|
|
|
|
goto out0;
|
|
|
|
}
|
|
|
|
|
2005-07-06 15:30:10 +00:00
|
|
|
memset (&bmi, 0, sizeof (bmi));
|
|
|
|
bmi.bi.biSize = sizeof (bmi.bi);
|
|
|
|
|
2006-10-29 00:17:11 +00:00
|
|
|
if (ii.hbmColor != NULL)
|
|
|
|
{
|
|
|
|
/* Colour cursor */
|
2005-07-05 22:50:54 +00:00
|
|
|
|
2006-10-29 00:17:11 +00:00
|
|
|
gboolean no_alpha;
|
2015-04-29 07:31:08 +00:00
|
|
|
|
2006-10-29 00:17:11 +00:00
|
|
|
if (!GDI_CALL (GetDIBits, (hdc, ii.hbmColor, 0, 1, NULL, (BITMAPINFO *)&bmi, DIB_RGB_COLORS)))
|
|
|
|
goto out1;
|
|
|
|
|
|
|
|
w = bmi.bi.biWidth;
|
|
|
|
h = bmi.bi.biHeight;
|
|
|
|
|
|
|
|
bmi.bi.biBitCount = 32;
|
|
|
|
bmi.bi.biCompression = BI_RGB;
|
|
|
|
bmi.bi.biHeight = -h;
|
2005-07-06 15:30:10 +00:00
|
|
|
|
2006-10-29 00:17:11 +00:00
|
|
|
bits = g_malloc0 (4 * w * h);
|
2015-04-29 07:31:08 +00:00
|
|
|
|
2006-10-29 00:17:11 +00:00
|
|
|
/* color data */
|
|
|
|
if (!GDI_CALL (GetDIBits, (hdc, ii.hbmColor, 0, h, bits, (BITMAPINFO *)&bmi, DIB_RGB_COLORS)))
|
|
|
|
goto out2;
|
|
|
|
|
|
|
|
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, w, h);
|
|
|
|
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
|
|
|
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
|
|
|
no_alpha = TRUE;
|
|
|
|
for (y = 0; y < h; y++)
|
2005-07-05 22:50:54 +00:00
|
|
|
{
|
2006-10-29 00:17:11 +00:00
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
{
|
|
|
|
pixels[2] = bits[(x+y*w) * 4];
|
|
|
|
pixels[1] = bits[(x+y*w) * 4 + 1];
|
|
|
|
pixels[0] = bits[(x+y*w) * 4 + 2];
|
|
|
|
pixels[3] = bits[(x+y*w) * 4 + 3];
|
|
|
|
if (no_alpha && pixels[3] > 0)
|
|
|
|
no_alpha = FALSE;
|
|
|
|
pixels += 4;
|
|
|
|
}
|
|
|
|
pixels += (w * 4 - rowstride);
|
2005-07-05 22:50:54 +00:00
|
|
|
}
|
|
|
|
|
2006-10-29 00:17:11 +00:00
|
|
|
/* mask */
|
|
|
|
if (no_alpha &&
|
|
|
|
GDI_CALL (GetDIBits, (hdc, ii.hbmMask, 0, h, bits, (BITMAPINFO *)&bmi, DIB_RGB_COLORS)))
|
|
|
|
{
|
|
|
|
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
|
|
|
for (y = 0; y < h; y++)
|
|
|
|
{
|
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
{
|
|
|
|
pixels[3] = 255 - bits[(x + y * w) * 4];
|
|
|
|
pixels += 4;
|
|
|
|
}
|
|
|
|
pixels += (w * 4 - rowstride);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2005-07-05 22:50:54 +00:00
|
|
|
{
|
2006-10-29 00:17:11 +00:00
|
|
|
/* B&W cursor */
|
|
|
|
|
|
|
|
int bpl;
|
|
|
|
|
|
|
|
if (!GDI_CALL (GetDIBits, (hdc, ii.hbmMask, 0, 0, NULL, (BITMAPINFO *)&bmi, DIB_RGB_COLORS)))
|
|
|
|
goto out1;
|
|
|
|
|
|
|
|
w = bmi.bi.biWidth;
|
|
|
|
h = ABS (bmi.bi.biHeight) / 2;
|
2015-04-29 07:31:08 +00:00
|
|
|
|
2006-10-29 00:17:11 +00:00
|
|
|
bits = g_malloc0 (4 * w * h);
|
2015-04-29 07:31:08 +00:00
|
|
|
|
2006-10-29 00:17:11 +00:00
|
|
|
/* masks */
|
|
|
|
if (!GDI_CALL (GetDIBits, (hdc, ii.hbmMask, 0, h*2, bits, (BITMAPINFO *)&bmi, DIB_RGB_COLORS)))
|
|
|
|
goto out2;
|
|
|
|
|
|
|
|
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, w, h);
|
2005-07-05 22:50:54 +00:00
|
|
|
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
2006-10-29 00:17:11 +00:00
|
|
|
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
|
|
|
bpl = ((w-1)/32 + 1)*4;
|
|
|
|
#if 0
|
|
|
|
for (y = 0; y < h*2; y++)
|
|
|
|
{
|
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
{
|
|
|
|
const gint bit = 7 - (x % 8);
|
|
|
|
printf ("%c ", ((bits[bpl*y+x/8])&(1<<bit)) ? ' ' : 'X');
|
|
|
|
}
|
|
|
|
printf ("\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-07-05 22:50:54 +00:00
|
|
|
for (y = 0; y < h; y++)
|
|
|
|
{
|
2006-10-29 00:17:11 +00:00
|
|
|
const guchar *andp, *xorp;
|
|
|
|
if (bmi.bi.biHeight < 0)
|
|
|
|
{
|
|
|
|
andp = bits + bpl*y;
|
|
|
|
xorp = bits + bpl*(h+y);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
andp = bits + bpl*(h-y-1);
|
|
|
|
xorp = bits + bpl*(h+h-y-1);
|
|
|
|
}
|
2005-07-05 22:50:54 +00:00
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
{
|
2006-10-29 00:17:11 +00:00
|
|
|
const gint bit = 7 - (x % 8);
|
|
|
|
if ((*andp) & (1<<bit))
|
|
|
|
{
|
|
|
|
if ((*xorp) & (1<<bit))
|
|
|
|
pixels[2] = pixels[1] = pixels[0] = 0xFF;
|
|
|
|
else
|
|
|
|
pixels[2] = pixels[1] = pixels[0] = 0;
|
|
|
|
pixels[3] = 0xFF;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pixels[2] = pixels[1] = pixels[0] = 0;
|
|
|
|
pixels[3] = 0;
|
|
|
|
}
|
2005-07-05 22:50:54 +00:00
|
|
|
pixels += 4;
|
2006-10-29 00:17:11 +00:00
|
|
|
if (bit == 0)
|
|
|
|
{
|
|
|
|
andp++;
|
|
|
|
xorp++;
|
|
|
|
}
|
2005-07-05 22:50:54 +00:00
|
|
|
}
|
|
|
|
pixels += (w * 4 - rowstride);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-06 14:21:05 +00:00
|
|
|
if (x_hot)
|
|
|
|
*x_hot = ii.xHotspot;
|
|
|
|
if (y_hot)
|
|
|
|
*y_hot = ii.yHotspot;
|
2005-07-05 22:50:54 +00:00
|
|
|
|
|
|
|
/* release temporary resources */
|
|
|
|
out2:
|
|
|
|
g_free (bits);
|
|
|
|
out1:
|
|
|
|
DeleteDC (hdc);
|
|
|
|
out0:
|
|
|
|
DeleteObject (ii.hbmColor);
|
|
|
|
DeleteObject (ii.hbmMask);
|
|
|
|
|
|
|
|
return pixbuf;
|
|
|
|
}
|
|
|
|
|
2011-01-02 10:51:25 +00:00
|
|
|
gboolean
|
|
|
|
_gdk_win32_display_supports_cursor_alpha (GdkDisplay *display)
|
2004-03-05 23:26:07 +00:00
|
|
|
{
|
2015-04-19 23:04:53 +00:00
|
|
|
return TRUE;
|
2004-03-05 23:26:07 +00:00
|
|
|
}
|
|
|
|
|
2015-04-29 07:31:08 +00:00
|
|
|
gboolean
|
2011-01-02 10:51:25 +00:00
|
|
|
_gdk_win32_display_supports_cursor_color (GdkDisplay *display)
|
2004-03-05 23:26:07 +00:00
|
|
|
{
|
2005-06-04 21:43:03 +00:00
|
|
|
return TRUE;
|
2004-03-05 23:26:07 +00:00
|
|
|
}
|
|
|
|
|
2011-01-02 10:51:25 +00:00
|
|
|
void
|
|
|
|
_gdk_win32_display_get_default_cursor_size (GdkDisplay *display,
|
2016-02-06 04:53:51 +00:00
|
|
|
guint *width,
|
|
|
|
guint *height)
|
2004-03-05 23:26:07 +00:00
|
|
|
{
|
2015-05-13 07:45:40 +00:00
|
|
|
/* TODO: Use per-monitor DPI functions (8.1 and newer) or
|
|
|
|
* calculate DPI ourselves and use that, assuming that 72 dpi
|
|
|
|
* corresponds to 32x32 cursors. Take into account that DPI
|
|
|
|
* can be artificially increased by the user to make stuff bigger.
|
|
|
|
*/
|
|
|
|
|
2011-01-02 10:51:25 +00:00
|
|
|
if (width)
|
|
|
|
*width = GetSystemMetrics (SM_CXCURSOR);
|
|
|
|
if (height)
|
|
|
|
*height = GetSystemMetrics (SM_CYCURSOR);
|
2004-03-05 23:26:07 +00:00
|
|
|
}
|
|
|
|
|
2015-04-29 07:31:08 +00:00
|
|
|
void
|
2011-01-02 10:51:25 +00:00
|
|
|
_gdk_win32_display_get_maximal_cursor_size (GdkDisplay *display,
|
|
|
|
guint *width,
|
|
|
|
guint *height)
|
2004-03-05 23:26:07 +00:00
|
|
|
{
|
|
|
|
if (width)
|
|
|
|
*width = GetSystemMetrics (SM_CXCURSOR);
|
|
|
|
if (height)
|
|
|
|
*height = GetSystemMetrics (SM_CYCURSOR);
|
|
|
|
}
|
2005-06-04 21:43:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Convert a pixbuf to an HICON (or HCURSOR). Supports alpha under
|
|
|
|
* Windows XP, thresholds alpha otherwise. Also used from
|
|
|
|
* gdkwindow-win32.c for creating application icons.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static HBITMAP
|
2006-04-06 10:34:15 +00:00
|
|
|
create_alpha_bitmap (gint size,
|
|
|
|
guchar **outdata)
|
2005-06-04 21:43:03 +00:00
|
|
|
{
|
|
|
|
BITMAPV5HEADER bi;
|
|
|
|
HDC hdc;
|
|
|
|
HBITMAP hBitmap;
|
|
|
|
|
|
|
|
ZeroMemory (&bi, sizeof (BITMAPV5HEADER));
|
|
|
|
bi.bV5Size = sizeof (BITMAPV5HEADER);
|
2006-04-06 10:34:15 +00:00
|
|
|
bi.bV5Height = bi.bV5Width = size;
|
2005-06-04 21:43:03 +00:00
|
|
|
bi.bV5Planes = 1;
|
|
|
|
bi.bV5BitCount = 32;
|
|
|
|
bi.bV5Compression = BI_BITFIELDS;
|
|
|
|
/* The following mask specification specifies a supported 32 BPP
|
|
|
|
* alpha format for Windows XP (BGRA format).
|
|
|
|
*/
|
|
|
|
bi.bV5RedMask = 0x00FF0000;
|
|
|
|
bi.bV5GreenMask = 0x0000FF00;
|
|
|
|
bi.bV5BlueMask = 0x000000FF;
|
|
|
|
bi.bV5AlphaMask = 0xFF000000;
|
|
|
|
|
|
|
|
/* Create the DIB section with an alpha channel. */
|
|
|
|
hdc = GetDC (NULL);
|
|
|
|
if (!hdc)
|
|
|
|
{
|
|
|
|
WIN32_GDI_FAILED ("GetDC");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
hBitmap = CreateDIBSection (hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS,
|
|
|
|
(PVOID *) outdata, NULL, (DWORD)0);
|
|
|
|
if (hBitmap == NULL)
|
|
|
|
WIN32_GDI_FAILED ("CreateDIBSection");
|
|
|
|
ReleaseDC (NULL, hdc);
|
|
|
|
|
|
|
|
return hBitmap;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HBITMAP
|
2006-04-06 10:34:15 +00:00
|
|
|
create_color_bitmap (gint size,
|
2005-11-06 05:36:49 +00:00
|
|
|
guchar **outdata,
|
|
|
|
gint bits)
|
2005-06-04 21:43:03 +00:00
|
|
|
{
|
2005-11-06 05:36:49 +00:00
|
|
|
struct {
|
|
|
|
BITMAPV4HEADER bmiHeader;
|
|
|
|
RGBQUAD bmiColors[2];
|
|
|
|
} bmi;
|
2005-06-04 21:43:03 +00:00
|
|
|
HDC hdc;
|
|
|
|
HBITMAP hBitmap;
|
|
|
|
|
2005-11-06 05:36:49 +00:00
|
|
|
ZeroMemory (&bmi, sizeof (bmi));
|
|
|
|
bmi.bmiHeader.bV4Size = sizeof (BITMAPV4HEADER);
|
2006-04-06 10:34:15 +00:00
|
|
|
bmi.bmiHeader.bV4Height = bmi.bmiHeader.bV4Width = size;
|
2005-11-06 05:36:49 +00:00
|
|
|
bmi.bmiHeader.bV4Planes = 1;
|
|
|
|
bmi.bmiHeader.bV4BitCount = bits;
|
|
|
|
bmi.bmiHeader.bV4V4Compression = BI_RGB;
|
|
|
|
|
|
|
|
/* when bits is 1, these will be used.
|
|
|
|
* bmiColors[0] already zeroed from ZeroMemory()
|
|
|
|
*/
|
|
|
|
bmi.bmiColors[1].rgbBlue = 0xFF;
|
|
|
|
bmi.bmiColors[1].rgbGreen = 0xFF;
|
|
|
|
bmi.bmiColors[1].rgbRed = 0xFF;
|
2005-06-04 21:43:03 +00:00
|
|
|
|
|
|
|
hdc = GetDC (NULL);
|
|
|
|
if (!hdc)
|
|
|
|
{
|
|
|
|
WIN32_GDI_FAILED ("GetDC");
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-11-06 05:36:49 +00:00
|
|
|
hBitmap = CreateDIBSection (hdc, (BITMAPINFO *)&bmi, DIB_RGB_COLORS,
|
2005-06-04 21:43:03 +00:00
|
|
|
(PVOID *) outdata, NULL, (DWORD)0);
|
|
|
|
if (hBitmap == NULL)
|
|
|
|
WIN32_GDI_FAILED ("CreateDIBSection");
|
|
|
|
ReleaseDC (NULL, hdc);
|
|
|
|
|
|
|
|
return hBitmap;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
pixbuf_to_hbitmaps_alpha_winxp (GdkPixbuf *pixbuf,
|
|
|
|
HBITMAP *color,
|
|
|
|
HBITMAP *mask)
|
|
|
|
{
|
|
|
|
/* Based on code from
|
|
|
|
* http://www.dotnet247.com/247reference/msgs/13/66301.aspx
|
|
|
|
*/
|
|
|
|
HBITMAP hColorBitmap, hMaskBitmap;
|
2005-11-06 05:36:49 +00:00
|
|
|
guchar *indata, *inrow;
|
|
|
|
guchar *colordata, *colorrow, *maskdata, *maskbyte;
|
2006-04-06 10:34:15 +00:00
|
|
|
gint width, height, size, i, i_offset, j, j_offset, rowstride;
|
2005-11-06 05:36:49 +00:00
|
|
|
guint maskstride, mask_bit;
|
2005-06-04 21:43:03 +00:00
|
|
|
|
|
|
|
width = gdk_pixbuf_get_width (pixbuf); /* width of icon */
|
|
|
|
height = gdk_pixbuf_get_height (pixbuf); /* height of icon */
|
|
|
|
|
2006-04-06 10:34:15 +00:00
|
|
|
/* The bitmaps are created square */
|
|
|
|
size = MAX (width, height);
|
|
|
|
|
|
|
|
hColorBitmap = create_alpha_bitmap (size, &colordata);
|
2005-06-04 21:43:03 +00:00
|
|
|
if (!hColorBitmap)
|
|
|
|
return FALSE;
|
2006-04-06 10:34:15 +00:00
|
|
|
hMaskBitmap = create_color_bitmap (size, &maskdata, 1);
|
2005-06-04 21:43:03 +00:00
|
|
|
if (!hMaskBitmap)
|
|
|
|
{
|
|
|
|
DeleteObject (hColorBitmap);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2005-11-06 05:36:49 +00:00
|
|
|
/* MSDN says mask rows are aligned to "LONG" boundaries */
|
2006-04-06 10:34:15 +00:00
|
|
|
maskstride = (((size + 31) & ~31) >> 3);
|
2005-11-03 13:29:30 +00:00
|
|
|
|
2005-06-04 21:43:03 +00:00
|
|
|
indata = gdk_pixbuf_get_pixels (pixbuf);
|
|
|
|
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
2006-04-06 10:34:15 +00:00
|
|
|
|
|
|
|
if (width > height)
|
|
|
|
{
|
|
|
|
i_offset = 0;
|
|
|
|
j_offset = (width - height) / 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
i_offset = (height - width) / 2;
|
|
|
|
j_offset = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = 0; j < height; j++)
|
2005-06-04 21:43:03 +00:00
|
|
|
{
|
2006-04-06 10:34:15 +00:00
|
|
|
colorrow = colordata + 4*(j+j_offset)*size + 4*i_offset;
|
|
|
|
maskbyte = maskdata + (j+j_offset)*maskstride + i_offset/8;
|
|
|
|
mask_bit = (0x80 >> (i_offset % 8));
|
|
|
|
inrow = indata + (height-j-1)*rowstride;
|
|
|
|
for (i = 0; i < width; i++)
|
2005-06-04 21:43:03 +00:00
|
|
|
{
|
2005-11-03 13:29:30 +00:00
|
|
|
colorrow[4*i+0] = inrow[4*i+2];
|
|
|
|
colorrow[4*i+1] = inrow[4*i+1];
|
|
|
|
colorrow[4*i+2] = inrow[4*i+0];
|
|
|
|
colorrow[4*i+3] = inrow[4*i+3];
|
|
|
|
if (inrow[4*i+3] == 0)
|
2005-11-06 05:36:49 +00:00
|
|
|
maskbyte[0] |= mask_bit; /* turn ON bit */
|
2005-11-03 13:29:30 +00:00
|
|
|
else
|
2005-11-06 05:36:49 +00:00
|
|
|
maskbyte[0] &= ~mask_bit; /* turn OFF bit */
|
|
|
|
mask_bit >>= 1;
|
|
|
|
if (mask_bit == 0)
|
|
|
|
{
|
|
|
|
mask_bit = 0x80;
|
|
|
|
maskbyte++;
|
|
|
|
}
|
2005-06-04 21:43:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-03 13:29:30 +00:00
|
|
|
*color = hColorBitmap;
|
|
|
|
*mask = hMaskBitmap;
|
2005-06-04 21:43:03 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
pixbuf_to_hbitmaps_normal (GdkPixbuf *pixbuf,
|
|
|
|
HBITMAP *color,
|
|
|
|
HBITMAP *mask)
|
|
|
|
{
|
|
|
|
/* Based on code from
|
|
|
|
* http://www.dotnet247.com/247reference/msgs/13/66301.aspx
|
|
|
|
*/
|
|
|
|
HBITMAP hColorBitmap, hMaskBitmap;
|
|
|
|
guchar *indata, *inrow;
|
2005-11-06 05:36:49 +00:00
|
|
|
guchar *colordata, *colorrow, *maskdata, *maskbyte;
|
2006-04-06 10:34:15 +00:00
|
|
|
gint width, height, size, i, i_offset, j, j_offset, rowstride, nc, bmstride;
|
2005-06-04 21:43:03 +00:00
|
|
|
gboolean has_alpha;
|
2005-11-06 05:36:49 +00:00
|
|
|
guint maskstride, mask_bit;
|
2005-06-04 21:43:03 +00:00
|
|
|
|
|
|
|
width = gdk_pixbuf_get_width (pixbuf); /* width of icon */
|
|
|
|
height = gdk_pixbuf_get_height (pixbuf); /* height of icon */
|
|
|
|
|
2006-04-06 10:34:15 +00:00
|
|
|
/* The bitmaps are created square */
|
|
|
|
size = MAX (width, height);
|
|
|
|
|
|
|
|
hColorBitmap = create_color_bitmap (size, &colordata, 24);
|
2005-06-04 21:43:03 +00:00
|
|
|
if (!hColorBitmap)
|
|
|
|
return FALSE;
|
2006-04-06 10:34:15 +00:00
|
|
|
hMaskBitmap = create_color_bitmap (size, &maskdata, 1);
|
2005-06-04 21:43:03 +00:00
|
|
|
if (!hMaskBitmap)
|
|
|
|
{
|
|
|
|
DeleteObject (hColorBitmap);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* rows are always aligned on 4-byte boundarys */
|
2006-04-06 10:34:15 +00:00
|
|
|
bmstride = size * 3;
|
2005-06-04 21:43:03 +00:00
|
|
|
if (bmstride % 4 != 0)
|
|
|
|
bmstride += 4 - (bmstride % 4);
|
|
|
|
|
2005-11-06 05:36:49 +00:00
|
|
|
/* MSDN says mask rows are aligned to "LONG" boundaries */
|
2006-04-06 10:34:15 +00:00
|
|
|
maskstride = (((size + 31) & ~31) >> 3);
|
2005-11-06 05:36:49 +00:00
|
|
|
|
2005-06-04 21:43:03 +00:00
|
|
|
indata = gdk_pixbuf_get_pixels (pixbuf);
|
|
|
|
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
|
|
|
nc = gdk_pixbuf_get_n_channels (pixbuf);
|
|
|
|
has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
|
|
|
|
|
2006-04-06 10:34:15 +00:00
|
|
|
if (width > height)
|
|
|
|
{
|
|
|
|
i_offset = 0;
|
|
|
|
j_offset = (width - height) / 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
i_offset = (height - width) / 2;
|
|
|
|
j_offset = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = 0; j < height; j++)
|
2005-06-04 21:43:03 +00:00
|
|
|
{
|
2006-04-06 10:34:15 +00:00
|
|
|
colorrow = colordata + (j+j_offset)*bmstride + 3*i_offset;
|
|
|
|
maskbyte = maskdata + (j+j_offset)*maskstride + i_offset/8;
|
|
|
|
mask_bit = (0x80 >> (i_offset % 8));
|
|
|
|
inrow = indata + (height-j-1)*rowstride;
|
|
|
|
for (i = 0; i < width; i++)
|
2005-06-04 21:43:03 +00:00
|
|
|
{
|
|
|
|
if (has_alpha && inrow[nc*i+3] < 128)
|
|
|
|
{
|
|
|
|
colorrow[3*i+0] = colorrow[3*i+1] = colorrow[3*i+2] = 0;
|
2005-11-06 05:36:49 +00:00
|
|
|
maskbyte[0] |= mask_bit; /* turn ON bit */
|
2005-06-04 21:43:03 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
colorrow[3*i+0] = inrow[nc*i+2];
|
|
|
|
colorrow[3*i+1] = inrow[nc*i+1];
|
|
|
|
colorrow[3*i+2] = inrow[nc*i+0];
|
2005-11-06 05:36:49 +00:00
|
|
|
maskbyte[0] &= ~mask_bit; /* turn OFF bit */
|
|
|
|
}
|
|
|
|
mask_bit >>= 1;
|
|
|
|
if (mask_bit == 0)
|
|
|
|
{
|
|
|
|
mask_bit = 0x80;
|
|
|
|
maskbyte++;
|
2005-06-04 21:43:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-03 13:29:30 +00:00
|
|
|
*color = hColorBitmap;
|
|
|
|
*mask = hMaskBitmap;
|
2005-06-04 21:43:03 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HICON
|
|
|
|
pixbuf_to_hicon (GdkPixbuf *pixbuf,
|
|
|
|
gboolean is_icon,
|
|
|
|
gint x,
|
|
|
|
gint y)
|
|
|
|
{
|
|
|
|
ICONINFO ii;
|
|
|
|
HICON icon;
|
|
|
|
gboolean success;
|
|
|
|
|
|
|
|
if (pixbuf == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2015-04-19 23:04:53 +00:00
|
|
|
if (gdk_pixbuf_get_has_alpha (pixbuf))
|
2005-06-04 21:43:03 +00:00
|
|
|
success = pixbuf_to_hbitmaps_alpha_winxp (pixbuf, &ii.hbmColor, &ii.hbmMask);
|
|
|
|
else
|
|
|
|
success = pixbuf_to_hbitmaps_normal (pixbuf, &ii.hbmColor, &ii.hbmMask);
|
|
|
|
|
|
|
|
if (!success)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ii.fIcon = is_icon;
|
|
|
|
ii.xHotspot = x;
|
|
|
|
ii.yHotspot = y;
|
|
|
|
icon = CreateIconIndirect (&ii);
|
|
|
|
DeleteObject (ii.hbmColor);
|
|
|
|
DeleteObject (ii.hbmMask);
|
|
|
|
return icon;
|
|
|
|
}
|
|
|
|
|
|
|
|
HICON
|
2017-11-07 07:39:48 +00:00
|
|
|
_gdk_win32_texture_to_hicon (GdkTexture *texture)
|
2005-06-04 21:43:03 +00:00
|
|
|
{
|
2017-11-07 07:39:48 +00:00
|
|
|
cairo_surface_t *surface;
|
|
|
|
GdkPixbuf *pixbuf;
|
|
|
|
gint width, height;
|
|
|
|
HICON icon;
|
|
|
|
|
|
|
|
surface = gdk_texture_download_surface (texture);
|
|
|
|
width = cairo_image_surface_get_width (surface);
|
|
|
|
height = cairo_image_surface_get_height (surface);
|
|
|
|
|
|
|
|
pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, width, height);
|
|
|
|
|
|
|
|
icon = pixbuf_to_hicon (pixbuf, TRUE, 0, 0);
|
|
|
|
|
|
|
|
g_object_unref (pixbuf);
|
|
|
|
|
|
|
|
return icon;
|
2005-06-04 21:43:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
HICON
|
|
|
|
_gdk_win32_pixbuf_to_hcursor (GdkPixbuf *pixbuf,
|
|
|
|
gint x_hotspot,
|
|
|
|
gint y_hotspot)
|
|
|
|
{
|
|
|
|
return pixbuf_to_hicon (pixbuf, FALSE, x_hotspot, y_hotspot);
|
|
|
|
}
|
|
|
|
|
2011-01-02 10:51:25 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* gdk_win32_display_get_hcursor:
|
|
|
|
* @display: (type GdkWin32Display): a #GdkDisplay
|
|
|
|
* @cursor: a #GdkCursor.
|
|
|
|
*
|
|
|
|
* Returns the Win32 HCURSOR belonging to a #GdkCursor, potentially
|
|
|
|
* creating the cursor.
|
|
|
|
*
|
|
|
|
* Be aware that the returned cursor may not be unique to @cursor.
|
|
|
|
* It may for example be shared with its fallback cursor.
|
|
|
|
*
|
|
|
|
* Returns: a Win32 HCURSOR.
|
|
|
|
**/
|
|
|
|
HCURSOR
|
|
|
|
gdk_win32_display_get_hcursor (GdkDisplay *display,
|
|
|
|
GdkCursor *cursor)
|
2011-01-02 10:51:25 +00:00
|
|
|
{
|
2017-11-07 07:39:48 +00:00
|
|
|
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (display);
|
|
|
|
HCURSOR hcursor;
|
|
|
|
|
|
|
|
g_return_val_if_fail (cursor != NULL, NULL);
|
|
|
|
|
|
|
|
if (gdk_display_is_closed (display))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
hcursor = g_hash_table_lookup (win32_display->cursors, cursor);
|
|
|
|
if (hcursor != NULL)
|
|
|
|
return hcursor;
|
2011-01-02 10:51:25 +00:00
|
|
|
|
2017-11-07 07:39:48 +00:00
|
|
|
if (gdk_cursor_get_name (cursor))
|
|
|
|
hcursor = gdk_win32_cursor_create_for_name (display, gdk_cursor_get_name (cursor));
|
|
|
|
else
|
|
|
|
hcursor = gdk_win32_cursor_create_for_texture (display,
|
|
|
|
gdk_cursor_get_texture (cursor),
|
|
|
|
gdk_cursor_get_hotspot_x (cursor),
|
|
|
|
gdk_cursor_get_hotspot_y (cursor));
|
|
|
|
|
|
|
|
if (hcursor != NULL)
|
|
|
|
{
|
|
|
|
g_object_weak_ref (G_OBJECT (cursor), gdk_win32_cursor_remove_from_cache, display);
|
|
|
|
g_hash_table_insert (win32_display->cursors, cursor, hcursor);
|
|
|
|
return hcursor;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gdk_cursor_get_fallback (cursor))
|
|
|
|
return gdk_win32_display_get_hcursor (display, gdk_cursor_get_fallback (cursor));
|
|
|
|
|
|
|
|
return NULL;
|
2011-01-02 10:51:25 +00:00
|
|
|
}
|