Bug 559408 - Transparency lost when images are copied between GTK+ and the

2009-01-29  Tor Lillqvist  <tml@novell.com>

	Bug 559408 - Transparency lost when images are copied between GTK+
	and the clipboard on Windows

	The code in gdkselection-win32.c is simplified quite a lot. When
	an image is stored on the clipboard from GTK+, only the "PNG" and
	CF_DIB formats are advertised. PNG is our preferred format because
	it can losslessly represent any image that gdk-pixbuf can handle,
	even with alpha, unambiguously. CF_DIB is also advertised because
	of its ubiquitous support in Windows software.

	Delayed rendering is used as before, so for other data than text
	nothing is actually stored on the clipboard until some app asks
	for it.

	It's pointless to advertise images formats like "image/png" or
	"image/x-MS-bmp" that no other Windows application is going to
	look for anyway. Likewise it's pointless to store text under
	formats like "text/plain" or "UTF8_STRING". Just store
	CF_UNICODETEXT. CF_TEXT will be available as a synthesized format
	anyways.

	Office 2007 offers and asks for images in PNG format using the
	registered clipboard format name "PNG", so we do likewise. If the
	"PNG" format is available that is preferred when copying to GTK+
	from the clipboard.

	Unfortunately Word 2007 still uses CF_DIB without handling
	alpha. But PowerPoint 2007 uses PNG if available and handles alpha
	correctly. Both Word and Powerpoint offer PNG with alpha nicely.

	Firefox and IE7 offer images that contain alpha as 32-bit version
	3 BI_RGB DIBs with the undocumented "extra" bytes actually being
	alpha. Also, alpha is premultiplied into the RGB bytes, presumably
	because that is how AlphaBlend() wants such DIBs. That is also
	taken care of. At least for Firefox it easy to be sure that a
	CF_DIB on the clipboard is from Firefox.

	Also some general stylistic cleanup, comment improvements, and
	improvements of debugging printout especially in the clipboard
	handling. Those are not detailled below.

	* gdk/win32/gdkprivate-win32.h
	* gdk/win32/gdkglobals-win32.c
	* gdk/win32/gdkgmain-win32.c: Move some globals that were used
	only in gdkselection-win32.c to be local to that file.

	* gdk/win32/gdkproperty-win32.c (gdk_property_change): Don't
	bother checking if text to be placed on the clipboard consists of
	only ASCII.

	* gdk/win32/gdkselection-win32.c: Add static variables for a list
	of GdkPixbuf-supported formats, well-known registered clipboard
	formats for images, and for GdkAtoms for well-known image and text
	formats.

	(_gdk_win32_selection_init): Initialize above static variables.

	(selection_property_store) (gdk_selection_property_get)
	(_gdk_selection_property_delete): Don't use a FIFO of GdkSelProps
	for a window after all, it breaks testtext. See bug #163844.

	(gdk_selection_convert): When converting to the TARGETS format,
	i.e. when the caller wants to know what clipboard formats are
	available, if PNG is available we report just that and skip
	CF_DIB, JPEG and GIF even if advertised.

	If CF_UNICODETEXT is available, report only UTF8_STRING.

	When converting to the UTF8_STRING format, i.e. when the caller
	wants text from the clipboard, try just CF_UNICODETEXT. There is
	no point in trying CF_TEXT as Windows will synthesize
	CF_UNICODETEXT from CF_TEXT anyway, if some app has stored just
	CF_TEXT.

	When converting to the image/bmp format, i.e. when the caller
	wants an CF_DIB image from the clipboard, we check if the DIB is a
	version 3 32-bit BI_RGB one that is likely to actually contain
	alpha in the "extra" bytes. Such a DIB is likely to have
	premultiplied alpha even, at least in the case of Firefox 3 and
	IE7. We then edit the DIB in-place into a version 5 one in
	BI_BITFIELDS format and undo the alpha premultiplication.

	In any case, prepend a BMP file header before letting go of the
	data which will be fed to the gdk-pixbuf bmp loader by upper
	levels.

	(gdk_win32_selection_add_targets): If some kind of pixmap image
	format is being added, actually advertise just PNG and
	CF_DIB. Note that alpha won't be stored on the clipboard through
	CF_DIB. This is because gdk-pixbuf's bmp loader doesn't save
	alpha. Furthermore, few if any non-GTK+ Windows apps seem to
	understand a version 5 DIB with proper alpha anyway.

	(_gdk_win32_selection_convert_to_dib): Simplified muchly.



svn path=/trunk/; revision=22255
This commit is contained in:
Tor Lillqvist 2009-01-30 01:16:47 +00:00 committed by Tor Lillqvist
parent 934014af3d
commit 3f4c73d0d5
7 changed files with 778 additions and 582 deletions

View File

@ -1,3 +1,100 @@
2009-01-29 Tor Lillqvist <tml@novell.com>
Bug 559408 - Transparency lost when images are copied between GTK+
and the clipboard on Windows
The code in gdkselection-win32.c is simplified quite a lot. When
an image is stored on the clipboard from GTK+, only the "PNG" and
CF_DIB formats are advertised. PNG is our preferred format because
it can losslessly represent any image that gdk-pixbuf can handle,
even with alpha, unambiguously. CF_DIB is also advertised because
of its ubiquitous support in Windows software.
Delayed rendering is used as before, so for other data than text
nothing is actually stored on the clipboard until some app asks
for it.
It's pointless to advertise images formats like "image/png" or
"image/x-MS-bmp" that no other Windows application is going to
look for anyway. Likewise it's pointless to store text under
formats like "text/plain" or "UTF8_STRING". Just store
CF_UNICODETEXT. CF_TEXT will be available as a synthesized format
anyways.
Office 2007 offers and asks for images in PNG format using the
registered clipboard format name "PNG", so we do likewise. If the
"PNG" format is available that is preferred when copying to GTK+
from the clipboard.
Unfortunately Word 2007 still uses CF_DIB without handling
alpha. But PowerPoint 2007 uses PNG if available and handles alpha
correctly. Both Word and Powerpoint offer PNG with alpha nicely.
Firefox and IE7 offer images that contain alpha as 32-bit version
3 BI_RGB DIBs with the undocumented "extra" bytes actually being
alpha. Also, alpha is premultiplied into the RGB bytes, presumably
because that is how AlphaBlend() wants such DIBs. That is also
taken care of. At least for Firefox it easy to be sure that a
CF_DIB on the clipboard is from Firefox.
Also some general stylistic cleanup, comment improvements, and
improvements of debugging printout especially in the clipboard
handling. Those are not detailled below.
* gdk/win32/gdkprivate-win32.h
* gdk/win32/gdkglobals-win32.c
* gdk/win32/gdkgmain-win32.c: Move some globals that were used
only in gdkselection-win32.c to be local to that file.
* gdk/win32/gdkproperty-win32.c (gdk_property_change): Don't
bother checking if text to be placed on the clipboard consists of
only ASCII.
* gdk/win32/gdkselection-win32.c: Add static variables for a list
of GdkPixbuf-supported formats, well-known registered clipboard
formats for images, and for GdkAtoms for well-known image and text
formats.
(_gdk_win32_selection_init): Initialize above static variables.
(selection_property_store) (gdk_selection_property_get)
(_gdk_selection_property_delete): Don't use a FIFO of GdkSelProps
for a window after all, it breaks testtext. See bug #163844.
(gdk_selection_convert): When converting to the TARGETS format,
i.e. when the caller wants to know what clipboard formats are
available, if PNG is available we report just that and skip
CF_DIB, JPEG and GIF even if advertised.
If CF_UNICODETEXT is available, report only UTF8_STRING.
When converting to the UTF8_STRING format, i.e. when the caller
wants text from the clipboard, try just CF_UNICODETEXT. There is
no point in trying CF_TEXT as Windows will synthesize
CF_UNICODETEXT from CF_TEXT anyway, if some app has stored just
CF_TEXT.
When converting to the image/bmp format, i.e. when the caller
wants an CF_DIB image from the clipboard, we check if the DIB is a
version 3 32-bit BI_RGB one that is likely to actually contain
alpha in the "extra" bytes. Such a DIB is likely to have
premultiplied alpha even, at least in the case of Firefox 3 and
IE7. We then edit the DIB in-place into a version 5 one in
BI_BITFIELDS format and undo the alpha premultiplication.
In any case, prepend a BMP file header before letting go of the
data which will be fed to the gdk-pixbuf bmp loader by upper
levels.
(gdk_win32_selection_add_targets): If some kind of pixmap image
format is being added, actually advertise just PNG and
CF_DIB. Note that alpha won't be stored on the clipboard through
CF_DIB. This is because gdk-pixbuf's bmp loader doesn't save
alpha. Furthermore, few if any non-GTK+ Windows apps seem to
understand a version 5 DIB with proper alpha anyway.
(_gdk_win32_selection_convert_to_dib): Simplified muchly.
2009-01-29 Tor Lillqvist <tml@novell.com> 2009-01-29 Tor Lillqvist <tml@novell.com>
Bug 145058 - Inputting "^^" requires four keystrokes on Win32, Bug 145058 - Inputting "^^" requires four keystrokes on Win32,

View File

@ -694,12 +694,12 @@ gdk_keyboard_grab (GdkWindow *window,
g_return_val_if_fail (window != NULL, 0); g_return_val_if_fail (window != NULL, 0);
g_return_val_if_fail (GDK_IS_WINDOW (window), 0); g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
GDK_NOTE (EVENTS, g_print ("gdk_keyboard_grab %p\n", GDK_NOTE (EVENTS, g_print ("gdk_keyboard_grab %p%s\n",
GDK_WINDOW_HWND (window))); GDK_WINDOW_HWND (window), owner_events ? " OWNER_EVENTS" : ""));
if (!GDK_WINDOW_DESTROYED (window)) if (!GDK_WINDOW_DESTROYED (window))
{ {
k_grab_owner_events = owner_events != 0; k_grab_owner_events = owner_events;
return_val = GDK_GRAB_SUCCESS; return_val = GDK_GRAB_SUCCESS;
} }
else else
@ -746,7 +746,7 @@ gdk_display_keyboard_ungrab (GdkDisplay *display,
g_return_if_fail (display == _gdk_display); g_return_if_fail (display == _gdk_display);
GDK_NOTE (EVENTS, g_print ("gdk_keyboard_ungrab\n")); GDK_NOTE (EVENTS, g_print ("gdk_display_keyboard_ungrab\n"));
if (k_grab_window && !k_grab_owner_events) if (k_grab_window && !k_grab_owner_events)
{ {
@ -955,6 +955,7 @@ static void
print_event (GdkEvent *event) print_event (GdkEvent *event)
{ {
gchar *escaped, *kvname; gchar *escaped, *kvname;
gchar *selection_name, *target_name, *property_name;
g_print ("%s%*s===> ", (debug_indent > 0 ? "\n" : ""), debug_indent, ""); g_print ("%s%*s===> ", (debug_indent > 0 ? "\n" : ""), debug_indent, "");
switch (event->any.type) switch (event->any.type)
@ -1065,6 +1066,18 @@ print_event (GdkEvent *event)
case GDK_FOCUS_CHANGE: case GDK_FOCUS_CHANGE:
g_print ("%s", (event->focus_change.in ? "IN" : "OUT")); g_print ("%s", (event->focus_change.in ? "IN" : "OUT"));
break; break;
case GDK_SELECTION_REQUEST:
case GDK_SELECTION_NOTIFY:
case GDK_SELECTION_CLEAR:
selection_name = gdk_atom_name (event->selection.selection);
target_name = gdk_atom_name (event->selection.target);
property_name = gdk_atom_name (event->selection.property);
g_print ("sel:%s tgt:%s prop:%s",
selection_name, target_name, property_name);
g_free (selection_name);
g_free (target_name);
g_free (property_name);
break;
case GDK_CONFIGURE: case GDK_CONFIGURE:
g_print ("x:%d y:%d w:%d h:%d", g_print ("x:%d y:%d w:%d h:%d",
event->configure.x, event->configure.y, event->configure.x, event->configure.y,
@ -1682,7 +1695,8 @@ translate_mouse_coords (GdkWindow *window1,
/* The check_extended flag controls whether to check if the windows want /* The check_extended flag controls whether to check if the windows want
* events from extended input devices and if the message should be skipped * events from extended input devices and if the message should be skipped
* because an extended input device is active */ * because an extended input device is active
*/
static gboolean static gboolean
propagate (GdkWindow **window, propagate (GdkWindow **window,
MSG *msg, MSG *msg,
@ -1693,14 +1707,13 @@ propagate (GdkWindow **window,
MSG *msg), MSG *msg),
gboolean check_extended) gboolean check_extended)
{ {
gboolean in_propagation = FALSE;
if (grab_window != NULL && !grab_owner_events) if (grab_window != NULL && !grab_owner_events)
{ {
/* Event source is grabbed with owner_events FALSE */ /* Event source is grabbed with owner_events FALSE */
/* See if the event should be ignored because an extended input device /* See if the event should be ignored because an extended input
* is used */ * device is used
*/
if (check_extended && if (check_extended &&
((GdkWindowObject *) grab_window)->extension_events != 0 && ((GdkWindowObject *) grab_window)->extension_events != 0 &&
_gdk_input_ignore_core) _gdk_input_ignore_core)
@ -1720,10 +1733,12 @@ propagate (GdkWindow **window,
return TRUE; return TRUE;
} }
} }
/* If we come here, we know that if grab_window != NULL then
* grab_owner_events is TRUE
*/
while (TRUE) while (TRUE)
{ {
/* See if the event should be ignored because an extended input device
* is used */
if (check_extended && if (check_extended &&
((GdkWindowObject *) *window)->extension_events != 0 && ((GdkWindowObject *) *window)->extension_events != 0 &&
_gdk_input_ignore_core) _gdk_input_ignore_core)
@ -1742,8 +1757,6 @@ propagate (GdkWindow **window,
{ {
/* Event source is grabbed with owner_events TRUE */ /* Event source is grabbed with owner_events TRUE */
/* See if the event should be ignored because an extended
* input device is used */
if (check_extended && if (check_extended &&
((GdkWindowObject *) grab_window)->extension_events != 0 && ((GdkWindowObject *) grab_window)->extension_events != 0 &&
_gdk_input_ignore_core) _gdk_input_ignore_core)
@ -1774,7 +1787,6 @@ propagate (GdkWindow **window,
else else
{ {
assign_object (window, parent); assign_object (window, parent);
in_propagation = TRUE;
/* The only branch where we actually continue the loop */ /* The only branch where we actually continue the loop */
} }
} }
@ -2867,7 +2879,7 @@ gdk_event_translate (MSG *msg,
break; break;
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
GDK_NOTE (EVENTS, g_print (" %d", HIWORD (msg->wParam))); GDK_NOTE (EVENTS, g_print (" %d", (short) HIWORD (msg->wParam)));
/* WM_MOUSEWHEEL is delivered to the focus window. Work around /* WM_MOUSEWHEEL is delivered to the focus window. Work around
* that. Also, the position is in screen coordinates, not client * that. Also, the position is in screen coordinates, not client
@ -2917,6 +2929,42 @@ gdk_event_translate (MSG *msg,
return_val = TRUE; return_val = TRUE;
break; break;
case WM_HSCROLL:
GDK_NOTE (EVENTS,
(g_print (" %s",
(LOWORD (msg->wParam) == SB_ENDSCROLL ? "ENDSCROLL" :
(LOWORD (msg->wParam) == SB_LEFT ? "LEFT" :
(LOWORD (msg->wParam) == SB_RIGHT ? "RIGHT" :
(LOWORD (msg->wParam) == SB_LINELEFT ? "LINELEFT" :
(LOWORD (msg->wParam) == SB_LINERIGHT ? "LINERIGHT" :
(LOWORD (msg->wParam) == SB_PAGELEFT ? "PAGELEFT" :
(LOWORD (msg->wParam) == SB_PAGERIGHT ? "PAGERIGHT" :
(LOWORD (msg->wParam) == SB_THUMBPOSITION ? "THUMBPOSITION" :
(LOWORD (msg->wParam) == SB_THUMBTRACK ? "THUMBTRACK" :
"???")))))))))),
(LOWORD (msg->wParam) == SB_THUMBPOSITION ||
LOWORD (msg->wParam) == SB_THUMBTRACK) ?
g_print (" %d", HIWORD (msg->wParam)) : 0));
break;
case WM_VSCROLL:
GDK_NOTE (EVENTS,
(g_print (" %s",
(LOWORD (msg->wParam) == SB_ENDSCROLL ? "ENDSCROLL" :
(LOWORD (msg->wParam) == SB_BOTTOM ? "BOTTOM" :
(LOWORD (msg->wParam) == SB_TOP ? "TOP" :
(LOWORD (msg->wParam) == SB_LINEDOWN ? "LINDOWN" :
(LOWORD (msg->wParam) == SB_LINEUP ? "LINEIP" :
(LOWORD (msg->wParam) == SB_PAGEDOWN ? "PAGEDOWN" :
(LOWORD (msg->wParam) == SB_PAGEUP ? "PAGEUP" :
(LOWORD (msg->wParam) == SB_THUMBPOSITION ? "THUMBPOSITION" :
(LOWORD (msg->wParam) == SB_THUMBTRACK ? "THUMBTRACK" :
"???")))))))))),
(LOWORD (msg->wParam) == SB_THUMBPOSITION ||
LOWORD (msg->wParam) == SB_THUMBTRACK) ?
g_print (" %d", HIWORD (msg->wParam)) : 0));
break;
case WM_QUERYNEWPALETTE: case WM_QUERYNEWPALETTE:
if (gdk_visual_get_system ()->type == GDK_VISUAL_PSEUDO_COLOR) if (gdk_visual_get_system ()->type == GDK_VISUAL_PSEUDO_COLOR)
{ {
@ -3608,7 +3656,7 @@ gdk_event_translate (MSG *msg,
event->selection.send_event = FALSE; event->selection.send_event = FALSE;
event->selection.selection = GDK_SELECTION_CLIPBOARD; event->selection.selection = GDK_SELECTION_CLIPBOARD;
event->selection.target = target; event->selection.target = target;
event->selection.property = _gdk_selection_property; event->selection.property = _gdk_selection;
event->selection.requestor = msg->hwnd; event->selection.requestor = msg->hwnd;
event->selection.time = msg->time; event->selection.time = msg->time;
@ -3640,6 +3688,11 @@ gdk_event_translate (MSG *msg,
/* The requestor is holding the clipboard, no /* The requestor is holding the clipboard, no
* OpenClipboard() is required/possible * OpenClipboard() is required/possible
*/ */
GDK_NOTE (DND,
g_print (" SetClipboardData(%s,%p)",
_gdk_win32_cf_to_string (msg->wParam),
_delayed_rendering_data));
API_CALL (SetClipboardData, (msg->wParam, _delayed_rendering_data)); API_CALL (SetClipboardData, (msg->wParam, _delayed_rendering_data));
_delayed_rendering_data = NULL; _delayed_rendering_data = NULL;
} }
@ -3679,7 +3732,6 @@ gdk_event_translate (MSG *msg,
GDK_NOTE (EVENTS, g_print (" %s thread: %I64d", GDK_NOTE (EVENTS, g_print (" %s thread: %I64d",
msg->wParam ? "YES" : "NO", msg->wParam ? "YES" : "NO",
(gint64) msg->lParam)); (gint64) msg->lParam));
if (msg->wParam && GDK_WINDOW_IS_MAPPED (window)) if (msg->wParam && GDK_WINDOW_IS_MAPPED (window))
ensure_stacking_on_activate_app (msg, window); ensure_stacking_on_activate_app (msg, window);
break; break;

View File

@ -46,10 +46,7 @@ HKL _gdk_input_locale;
gboolean _gdk_input_locale_is_ime; gboolean _gdk_input_locale_is_ime;
UINT _gdk_input_codepage; UINT _gdk_input_codepage;
WORD _cf_utf8_string; GdkAtom _gdk_selection;
WORD _cf_image_bmp;
GdkAtom _gdk_selection_property;
GdkAtom _wm_transient_for; GdkAtom _wm_transient_for;
GdkAtom _targets; GdkAtom _targets;
GdkAtom _save_targets; GdkAtom _save_targets;
@ -57,7 +54,6 @@ GdkAtom _utf8_string;
GdkAtom _text; GdkAtom _text;
GdkAtom _compound_text; GdkAtom _compound_text;
GdkAtom _text_uri_list; GdkAtom _text_uri_list;
GdkAtom _image_bmp;
GdkAtom _local_dnd; GdkAtom _local_dnd;
GdkAtom _gdk_win32_dropfiles; GdkAtom _gdk_win32_dropfiles;

View File

@ -100,10 +100,7 @@ _gdk_windowing_init (void)
CoInitialize (NULL); CoInitialize (NULL);
_cf_utf8_string = RegisterClipboardFormat ("UTF8_STRING"); _gdk_selection = gdk_atom_intern ("GDK_SELECTION", FALSE);
_cf_image_bmp = RegisterClipboardFormat ("image/bmp");
_gdk_selection_property = gdk_atom_intern ("GDK_SELECTION", FALSE);
_wm_transient_for = gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE); _wm_transient_for = gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE);
_targets = gdk_atom_intern ("TARGETS", FALSE); _targets = gdk_atom_intern ("TARGETS", FALSE);
_save_targets = gdk_atom_intern ("SAVE_TARGETS", FALSE); _save_targets = gdk_atom_intern ("SAVE_TARGETS", FALSE);
@ -111,7 +108,6 @@ _gdk_windowing_init (void)
_text = gdk_atom_intern ("TEXT", FALSE); _text = gdk_atom_intern ("TEXT", FALSE);
_compound_text = gdk_atom_intern ("COMPOUND_TEXT", FALSE); _compound_text = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
_text_uri_list = gdk_atom_intern ("text/uri-list", FALSE); _text_uri_list = gdk_atom_intern ("text/uri-list", FALSE);
_image_bmp = gdk_atom_intern ("image/bmp", FALSE);
_local_dnd = gdk_atom_intern ("LocalDndSelection", FALSE); _local_dnd = gdk_atom_intern ("LocalDndSelection", FALSE);
_gdk_win32_dropfiles = gdk_atom_intern ("DROPFILES_DND", FALSE); _gdk_win32_dropfiles = gdk_atom_intern ("DROPFILES_DND", FALSE);
@ -1039,9 +1035,7 @@ _gdk_win32_cf_to_string (UINT format)
#define CASE(x) case CF_##x: return "CF_" #x #define CASE(x) case CF_##x: return "CF_" #x
CASE (BITMAP); CASE (BITMAP);
CASE (DIB); CASE (DIB);
#ifdef CF_DIBV5
CASE (DIBV5); CASE (DIBV5);
#endif
CASE (DIF); CASE (DIF);
CASE (DSPBITMAP); CASE (DSPBITMAP);
CASE (DSPENHMETAFILE); CASE (DSPENHMETAFILE);

View File

@ -93,6 +93,11 @@
#define WM_APPCOMMAND 0x319 #define WM_APPCOMMAND 0x319
#endif #endif
#ifndef CF_DIBV5
#define CF_DIBV5 17
#endif
/* Define some combinations of GdkDebugFlags */ /* Define some combinations of GdkDebugFlags */
#define GDK_DEBUG_EVENTS_OR_COLORMAP (GDK_DEBUG_EVENTS|GDK_DEBUG_COLORMAP) #define GDK_DEBUG_EVENTS_OR_COLORMAP (GDK_DEBUG_EVENTS|GDK_DEBUG_COLORMAP)
#define GDK_DEBUG_EVENTS_OR_INPUT (GDK_DEBUG_EVENTS|GDK_DEBUG_INPUT) #define GDK_DEBUG_EVENTS_OR_INPUT (GDK_DEBUG_EVENTS|GDK_DEBUG_INPUT)
@ -400,12 +405,8 @@ extern guint _gdk_keymap_serial;
extern gboolean _gdk_keyboard_has_altgr; extern gboolean _gdk_keyboard_has_altgr;
extern guint _scancode_rshift; extern guint _scancode_rshift;
/* Registered clipboard formats */
extern WORD _cf_utf8_string;
extern WORD _cf_image_bmp;
/* GdkAtoms: properties, targets and types */ /* GdkAtoms: properties, targets and types */
extern GdkAtom _gdk_selection_property; extern GdkAtom _gdk_selection;
extern GdkAtom _wm_transient_for; extern GdkAtom _wm_transient_for;
extern GdkAtom _targets; extern GdkAtom _targets;
extern GdkAtom _save_targets; extern GdkAtom _save_targets;
@ -413,7 +414,6 @@ extern GdkAtom _utf8_string;
extern GdkAtom _text; extern GdkAtom _text;
extern GdkAtom _compound_text; extern GdkAtom _compound_text;
extern GdkAtom _text_uri_list; extern GdkAtom _text_uri_list;
extern GdkAtom _image_bmp;
/* DND selections */ /* DND selections */
extern GdkAtom _local_dnd; extern GdkAtom _local_dnd;

View File

@ -99,7 +99,8 @@ gdk_atom_name (GdkAtom atom)
ATOM win32_atom; ATOM win32_atom;
gchar name[256]; gchar name[256];
if (GDK_SELECTION_PRIMARY == atom) return g_strdup ("PRIMARY"); if (GDK_NONE == atom) return g_strdup ("<none>");
else if (GDK_SELECTION_PRIMARY == atom) return g_strdup ("PRIMARY");
else if (GDK_SELECTION_SECONDARY == atom) return g_strdup ("SECONDARY"); else if (GDK_SELECTION_SECONDARY == atom) return g_strdup ("SECONDARY");
else if (GDK_SELECTION_CLIPBOARD == atom) return g_strdup ("CLIPBOARD"); else if (GDK_SELECTION_CLIPBOARD == atom) return g_strdup ("CLIPBOARD");
else if (GDK_SELECTION_TYPE_ATOM == atom) return g_strdup ("ATOM"); else if (GDK_SELECTION_TYPE_ATOM == atom) return g_strdup ("ATOM");
@ -153,14 +154,10 @@ gdk_property_change (GdkWindow *window,
gint nelements) gint nelements)
{ {
HGLOBAL hdata; HGLOBAL hdata;
UINT cf = 0; gint i, size;
gint i, size, nchars;
gchar *prop_name, *type_name;
guchar *ucptr, *buf = NULL; guchar *ucptr, *buf = NULL;
wchar_t *wcptr; wchar_t *wcptr, *p;
glong wclen; glong wclen;
enum { SYSTEM_CODEPAGE, UNICODE_TEXT } method;
gboolean ok = TRUE;
g_return_if_fail (window != NULL); g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window)); g_return_if_fail (GDK_IS_WINDOW (window));
@ -168,21 +165,23 @@ gdk_property_change (GdkWindow *window,
if (GDK_WINDOW_DESTROYED (window)) if (GDK_WINDOW_DESTROYED (window))
return; return;
GDK_NOTE (DND, GDK_NOTE (DND, {
(prop_name = gdk_atom_name (property), gchar *prop_name = gdk_atom_name (property);
type_name = gdk_atom_name (type), gchar *type_name = gdk_atom_name (type);
g_print ("gdk_property_change: %p %p (%s) %p (%s) %s %d*%d bytes: %s\n",
g_print ("gdk_property_change: %p %s %s %s %d*%d bits: %s\n",
GDK_WINDOW_HWND (window), GDK_WINDOW_HWND (window),
property, prop_name, prop_name,
type, type_name, type_name,
(mode == GDK_PROP_MODE_REPLACE ? "REPLACE" : (mode == GDK_PROP_MODE_REPLACE ? "REPLACE" :
(mode == GDK_PROP_MODE_PREPEND ? "PREPEND" : (mode == GDK_PROP_MODE_PREPEND ? "PREPEND" :
(mode == GDK_PROP_MODE_APPEND ? "APPEND" : (mode == GDK_PROP_MODE_APPEND ? "APPEND" :
"???"))), "???"))),
format, nelements, format, nelements,
_gdk_win32_data_to_string (data, MIN (10, format*nelements/8))), _gdk_win32_data_to_string (data, MIN (10, format*nelements/8)));
g_free (prop_name), g_free (prop_name);
g_free (type_name))); g_free (type_name);
});
/* We should never come here for these types */ /* We should never come here for these types */
g_return_if_fail (type != GDK_TARGET_STRING); g_return_if_fail (type != GDK_TARGET_STRING);
@ -190,9 +189,9 @@ gdk_property_change (GdkWindow *window,
g_return_if_fail (type != _compound_text); g_return_if_fail (type != _compound_text);
g_return_if_fail (type != _save_targets); g_return_if_fail (type != _save_targets);
if (property == _gdk_selection_property if (property == _gdk_selection &&
&& format == 8 format == 8 &&
&& mode == GDK_PROP_MODE_REPLACE) mode == GDK_PROP_MODE_REPLACE)
{ {
if (type == _utf8_string) if (type == _utf8_string)
{ {
@ -202,29 +201,6 @@ gdk_property_change (GdkWindow *window,
return; return;
} }
nchars = g_utf8_strlen ((char*) data, nelements);
/* Check if only ASCII */
for (i = 0; i < nelements; i++)
if (data[i] >= 0200)
break;
if (i == nelements)
{
/* If only ASCII, use CF_TEXT and the data as such */
method = SYSTEM_CODEPAGE;
size = nelements;
for (i = 0; i < nelements; i++)
if (data[i] == '\n')
size++;
size++;
GDK_NOTE (DND, g_print ("... as text: %.40s\n", data));
}
else
{
/* Use CF_UNICODETEXT */
method = UNICODE_TEXT;
wcptr = g_utf8_to_utf16 ((char *) data, nelements, NULL, &wclen, NULL); wcptr = g_utf8_to_utf16 ((char *) data, nelements, NULL, &wclen, NULL);
wclen++; /* Terminating 0 */ wclen++; /* Terminating 0 */
@ -232,8 +208,6 @@ gdk_property_change (GdkWindow *window,
for (i = 0; i < wclen; i++) for (i = 0; i < wclen; i++)
if (wcptr[i] == '\n') if (wcptr[i] == '\n')
size += 2; size += 2;
GDK_NOTE (DND, g_print ("... as Unicode\n"));
}
if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, size))) if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, size)))
{ {
@ -246,23 +220,7 @@ gdk_property_change (GdkWindow *window,
ucptr = GlobalLock (hdata); ucptr = GlobalLock (hdata);
switch (method) p = (wchar_t *) ucptr;
{
case SYSTEM_CODEPAGE:
cf = CF_TEXT;
for (i = 0; i < nelements; i++)
{
if (data[i] == '\n')
*ucptr++ = '\r';
*ucptr++ = data[i];
}
*ucptr++ = '\0';
break;
case UNICODE_TEXT:
{
wchar_t *p = (wchar_t *) ucptr;
cf = CF_UNICODETEXT;
for (i = 0; i < wclen; i++) for (i = 0; i < wclen; i++)
{ {
if (wcptr[i] == '\n') if (wcptr[i] == '\n')
@ -270,29 +228,24 @@ gdk_property_change (GdkWindow *window,
*p++ = wcptr[i]; *p++ = wcptr[i];
} }
g_free (wcptr); g_free (wcptr);
}
break;
default:
g_assert_not_reached ();
}
GlobalUnlock (hdata); GlobalUnlock (hdata);
GDK_NOTE (DND, g_print ("... SetClipboardData(%s,%p)\n", GDK_NOTE (DND, g_print ("... SetClipboardData(CF_UNICODETEXT,%p)\n",
_gdk_win32_cf_to_string (cf), hdata)); hdata));
if (ok && !SetClipboardData (cf, hdata)) if (!SetClipboardData (CF_UNICODETEXT, hdata))
WIN32_API_FAILED ("SetClipboardData"), ok = FALSE; WIN32_API_FAILED ("SetClipboardData");
if (!CloseClipboard ()) if (!CloseClipboard ())
WIN32_API_FAILED ("CloseClipboard"); WIN32_API_FAILED ("CloseClipboard");
} }
else else
{ {
GDK_NOTE (DND, g_print ("... delayed rendering\n")); /* We use delayed rendering for everything else than
/* Delayed Rendering. We can't assign hdata to the clipboard * text. We can't assign hdata to the clipboard here as type
* here as type may be "image/png", "image/jpg", etc. In * may be "image/png", "image/jpg", etc. In this case
* this case there's a further conversion afterwards. * there's a further conversion afterwards.
*/ */
GDK_NOTE (DND, g_print ("... delayed rendering\n"));
_delayed_rendering_data = NULL; _delayed_rendering_data = NULL;
if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, nelements > 0 ? nelements : 1))) if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, nelements > 0 ? nelements : 1)))
{ {
@ -318,14 +271,16 @@ gdk_property_delete (GdkWindow *window,
g_return_if_fail (window != NULL); g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window)); g_return_if_fail (GDK_IS_WINDOW (window));
GDK_NOTE (DND, GDK_NOTE (DND, {
(prop_name = gdk_atom_name (property), prop_name = gdk_atom_name (property);
g_print ("gdk_property_delete: %p %p (%s)\n",
GDK_WINDOW_HWND (window),
property, prop_name),
g_free (prop_name)));
if (property == _gdk_selection_property) g_print ("gdk_property_delete: %p %s\n",
GDK_WINDOW_HWND (window),
prop_name);
g_free (prop_name);
});
if (property == _gdk_selection)
_gdk_selection_property_delete (window); _gdk_selection_property_delete (window);
else if (property == _wm_transient_for) else if (property == _wm_transient_for)
gdk_window_set_transient_for (window, _gdk_root); gdk_window_set_transient_for (window, _gdk_root);
@ -339,37 +294,56 @@ gdk_property_delete (GdkWindow *window,
} }
/* /*
for reference copied from gdk/x11/gdkevents-x11.c For reference, from gdk/x11/gdksettings.c:
{ "Net/DoubleClickTime", "gtk-double-click-time" }, "Net/DoubleClickTime\0" "gtk-double-click-time\0"
{ "Net/DoubleClickDistance", "gtk-double-click-distance" }, "Net/DoubleClickDistance\0" "gtk-double-click-distance\0"
{ "Net/DndDragThreshold", "gtk-dnd-drag-threshold" }, "Net/DndDragThreshold\0" "gtk-dnd-drag-threshold\0"
{ "Gtk/CanChangeAccels", "gtk-can-change-accels" }, "Net/CursorBlink\0" "gtk-cursor-blink\0"
{ "Gtk/ColorPalette", "gtk-color-palette" }, "Net/CursorBlinkTime\0" "gtk-cursor-blink-time\0"
{ "Gtk/FontName", "gtk-font-name" }, "Net/ThemeName\0" "gtk-theme-name\0"
{ "Gtk/IconSizes", "gtk-icon-sizes" }, "Net/IconThemeName\0" "gtk-icon-theme-name\0"
{ "Gtk/KeyThemeName", "gtk-key-theme-name" }, "Gtk/CanChangeAccels\0" "gtk-can-change-accels\0"
{ "Gtk/ToolbarStyle", "gtk-toolbar-style" }, "Gtk/ColorPalette\0" "gtk-color-palette\0"
{ "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" }, "Gtk/FontName\0" "gtk-font-name\0"
{ "Gtk/IMPreeditStyle", "gtk-im-preedit-style" }, "Gtk/IconSizes\0" "gtk-icon-sizes\0"
{ "Gtk/IMStatusStyle", "gtk-im-status-style" }, "Gtk/KeyThemeName\0" "gtk-key-theme-name\0"
{ "Gtk/IMModule", "gtk-im-module" }, "Gtk/ToolbarStyle\0" "gtk-toolbar-style\0"
{ "Net/CursorBlink", "gtk-cursor-blink" }, "Gtk/ToolbarIconSize\0" "gtk-toolbar-icon-size\0"
{ "Net/CursorBlinkTime", "gtk-cursor-blink-time" }, "Gtk/IMPreeditStyle\0" "gtk-im-preedit-style\0"
{ "Net/ThemeName", "gtk-theme-name" }, "Gtk/IMStatusStyle\0" "gtk-im-status-style\0"
{ "Net/IconThemeName", "gtk-icon-theme-name" }, "Gtk/Modules\0" "gtk-modules\0"
{ "Gtk/ButtonImages", "gtk-button-images" }, "Gtk/FileChooserBackend\0" "gtk-file-chooser-backend\0"
{ "Gtk/MenuImages", "gtk-menu-images" }, "Gtk/ButtonImages\0" "gtk-button-images\0"
{ "Xft/Antialias", "gtk-xft-antialias" }, "Gtk/MenuImages\0" "gtk-menu-images\0"
{ "Xft/Hinting", "gtk-xft-hinting" }, "Gtk/MenuBarAccel\0" "gtk-menu-bar-accel\0"
{ "Xft/HintStyle", "gtk-xft-hintstyle" }, "Gtk/CursorThemeName\0" "gtk-cursor-theme-name\0"
{ "Xft/RGBA", "gtk-xft-rgba" }, "Gtk/CursorThemeSize\0" "gtk-cursor-theme-size\0"
{ "Xft/DPI", "gtk-xft-dpi" }, "Gtk/ShowInputMethodMenu\0" "gtk-show-input-method-menu\0"
"Gtk/ShowUnicodeMenu\0" "gtk-show-unicode-menu\0"
"Gtk/TimeoutInitial\0" "gtk-timeout-initial\0"
"Gtk/TimeoutRepeat\0" "gtk-timeout-repeat\0"
"Gtk/ColorScheme\0" "gtk-color-scheme\0"
"Gtk/EnableAnimations\0" "gtk-enable-animations\0"
"Xft/Antialias\0" "gtk-xft-antialias\0"
"Xft/Hinting\0" "gtk-xft-hinting\0"
"Xft/HintStyle\0" "gtk-xft-hintstyle\0"
"Xft/RGBA\0" "gtk-xft-rgba\0"
"Xft/DPI\0" "gtk-xft-dpi\0"
"Net/FallbackIconTheme\0" "gtk-fallback-icon-theme\0"
"Gtk/TouchscreenMode\0" "gtk-touchscreen-mode\0"
"Gtk/EnableAccels\0" "gtk-enable-accels\0"
"Gtk/EnableMnemonics\0" "gtk-enable-mnemonics\0"
"Gtk/ScrolledWindowPlacement\0" "gtk-scrolled-window-placement\0"
"Gtk/IMModule\0" "gtk-im-module\0"
"Fontconfig/Timestamp\0" "gtk-fontconfig-timestamp\0"
"Net/SoundThemeName\0" "gtk-sound-theme-name\0"
"Net/EnableInputFeedbackSounds\0" "gtk-enable-input-feedback-sounds\0"
"Net/EnableEventSounds\0" "gtk-enable-event-sounds\0";
More, from various places in gtk sources:
// more spread in gtk sources
gtk-entry-select-on-focus gtk-entry-select-on-focus
gtk-cursor-blink
gtk-cursor-blink-time
gtk-split-cursor gtk-split-cursor
*/ */
@ -463,6 +437,5 @@ gdk_screen_get_setting (GdkScreen *screen,
} }
#endif #endif
GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) not handled\n", name));
return FALSE; return FALSE;
} }

File diff suppressed because it is too large Load Diff