Work on OLE2-based generic DND

Intermediate commit of work in progress on integrating the old code
for OLE2-based generic drag and drop from Arhaeopteryx Software, from
a long time ago in the GTK+ 1.3 timeframe. Does still not work and is
as before not compiled in unless OLE2_DND is defined in
gdkdnd-win32.c. (Thus, for inter-process DND, still only WM_DROPFILES
style dropping of files on GTK+ apps works.)

Related slight refactoring of other code that shouldn't change how it
works. Add more global variables for run-time constants (once
initialized) representing well-known GdkAtoms and registered Windows
clipboard formats, as they with the generic DND code will be needed in
several source files. Some improved debugging output.
This commit is contained in:
Tor Lillqvist 2009-12-16 13:04:29 +02:00 committed by Tristan Van Berkom
parent e5b4a51b6b
commit af37f76bc6
9 changed files with 1066 additions and 468 deletions

File diff suppressed because it is too large Load Diff

View File

@ -825,7 +825,7 @@ _gdk_win32_print_event (const GdkEvent *event)
default: g_assert_not_reached ();
}
g_print (" %p ", GDK_WINDOW_HWND (event->any.window));
g_print (" %p ", event->any.window ? GDK_WINDOW_HWND (event->any.window) : NULL);
switch (event->any.type)
{
@ -889,9 +889,14 @@ _gdk_win32_print_event (const GdkEvent *event)
case GDK_FOCUS_CHANGE:
g_print ("%s", (event->focus_change.in ? "IN" : "OUT"));
break;
case GDK_CONFIGURE:
g_print ("x:%d y:%d w:%d h:%d",
event->configure.x, event->configure.y,
event->configure.width, event->configure.height);
break;
case GDK_SELECTION_CLEAR:
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);
@ -901,10 +906,19 @@ _gdk_win32_print_event (const GdkEvent *event)
g_free (target_name);
g_free (property_name);
break;
case GDK_CONFIGURE:
g_print ("x:%d y:%d w:%d h:%d",
event->configure.x, event->configure.y,
event->configure.width, event->configure.height);
case GDK_DRAG_ENTER:
case GDK_DRAG_LEAVE:
case GDK_DRAG_MOTION:
case GDK_DRAG_STATUS:
case GDK_DROP_START:
case GDK_DROP_FINISHED:
if (event->dnd.context != NULL)
g_print ("ctx:%p: %s %s src:%p dest:%p",
event->dnd.context,
_gdk_win32_drag_protocol_to_string (event->dnd.context->protocol),
event->dnd.context->is_source ? "SOURCE" : "DEST",
event->dnd.context->source_window == NULL ? NULL : GDK_WINDOW_HWND (event->dnd.context->source_window),
event->dnd.context->dest_window == NULL ? NULL : GDK_WINDOW_HWND (event->dnd.context->dest_window));
break;
case GDK_CLIENT_EVENT:
g_print ("%s %d %ld %ld %ld %ld %ld",
@ -1628,22 +1642,44 @@ handle_wm_paint (MSG *msg,
DeleteObject (hrgn);
}
static void
handle_stuff_while_moving_or_resizing (void)
{
int arbitrary_limit = 1;
while (g_main_context_pending (NULL) && arbitrary_limit--)
g_main_context_iteration (NULL, FALSE);
}
static VOID CALLBACK
static VOID CALLBACK
modal_timer_proc (HWND hwnd,
UINT msg,
UINT_PTR id,
DWORD time)
{
if (_sizemove_in_progress)
handle_stuff_while_moving_or_resizing ();
int arbitrary_limit = 1;
while (_modal_operation_in_progress &&
g_main_context_pending (NULL) &&
arbitrary_limit--)
g_main_context_iteration (NULL, FALSE);
}
void
_gdk_win32_begin_modal_call (void)
{
g_assert (!_modal_operation_in_progress);
_modal_operation_in_progress = TRUE;
modal_timer = SetTimer (NULL, 0, 10, modal_timer_proc);
if (modal_timer == 0)
WIN32_API_FAILED ("SetTimer");
}
void
_gdk_win32_end_modal_call (void)
{
g_assert (_modal_operation_in_progress);
_modal_operation_in_progress = FALSE;
if (modal_timer != 0)
{
API_CALL (KillTimer, (NULL, modal_timer));
modal_timer = 0;
}
}
static VOID CALLBACK
@ -2702,23 +2738,13 @@ gdk_event_translate (MSG *msg,
break;
case WM_ENTERSIZEMOVE:
_sizemove_in_progress = TRUE;
modal_timer = SetTimer (NULL, 0, 20, modal_timer_proc);
case WM_ENTERMENULOOP:
_gdk_win32_begin_modal_call ();
break;
case WM_EXITSIZEMOVE:
_sizemove_in_progress = FALSE;
KillTimer (NULL, modal_timer);
break;
case WM_ENTERMENULOOP:
_sizemove_in_progress = TRUE;
modal_timer = SetTimer (NULL, 0, 20, modal_timer_proc);
break;
case WM_EXITMENULOOP:
_sizemove_in_progress = FALSE;
KillTimer (NULL, modal_timer);
_gdk_win32_end_modal_call ();
break;
case WM_WINDOWPOSCHANGING:
@ -2751,7 +2777,7 @@ gdk_event_translate (MSG *msg,
windowpos->cx, windowpos->cy, windowpos->x, windowpos->y));
/* If position and size haven't changed, don't do anything */
if (_sizemove_in_progress &&
if (_modal_operation_in_progress &&
(windowpos->flags & SWP_NOMOVE) &&
(windowpos->flags & SWP_NOSIZE))
break;
@ -2759,7 +2785,7 @@ gdk_event_translate (MSG *msg,
/* Once we've entered the moving or sizing modal loop, we won't
* return to the main loop until we're done sizing or moving.
*/
if (_sizemove_in_progress &&
if (_modal_operation_in_progress &&
GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
!GDK_WINDOW_DESTROYED (window))
{
@ -2768,13 +2794,13 @@ gdk_event_translate (MSG *msg,
GDK_NOTE (EVENTS, g_print (" do magic"));
if (((GdkWindowObject *) window)->resize_count > 1)
((GdkWindowObject *) window)->resize_count -= 1;
handle_configure_event (msg, window);
g_main_context_iteration (NULL, FALSE);
#if 0
/* Dispatch main loop - to realize resizes... */
handle_stuff_while_moving_or_resizing ();
modal_timer_proc (msg->hwnd, msg->message, 0, msg->time);
#endif
/* Claim as handled, so that WM_SIZE and WM_MOVE are avoided */
return_val = TRUE;
*ret_valp = 1;
@ -3352,6 +3378,14 @@ gdk_event_dispatch (GSource *source,
(*_gdk_event_func) (event, _gdk_event_data);
gdk_event_free (event);
/* Do drag & drop if it is still pending */
if (_dnd_source_state == GDK_WIN32_DND_PENDING)
{
_dnd_source_state = GDK_WIN32_DND_DRAGGING;
_gdk_win32_dnd_do_dragdrop ();
_dnd_source_state = GDK_WIN32_DND_NONE;
}
}
GDK_THREADS_LEAVE ();

View File

@ -49,11 +49,13 @@ UINT _gdk_input_codepage;
GdkAtom _gdk_selection;
GdkAtom _wm_transient_for;
GdkAtom _targets;
GdkAtom _delete;
GdkAtom _save_targets;
GdkAtom _utf8_string;
GdkAtom _text;
GdkAtom _compound_text;
GdkAtom _text_uri_list;
GdkAtom _text_html;
GdkAtom _image_png;
GdkAtom _image_jpeg;
GdkAtom _image_bmp;
@ -63,10 +65,20 @@ GdkAtom _local_dnd;
GdkAtom _gdk_win32_dropfiles;
GdkAtom _gdk_ole2_dnd;
UINT _cf_png;
UINT _cf_jfif;
UINT _cf_gif;
UINT _cf_url;
UINT _cf_html_format;
UINT _cf_text_html;
GdkWin32DndState _dnd_target_state = GDK_WIN32_DND_NONE;
GdkWin32DndState _dnd_source_state = GDK_WIN32_DND_NONE;
gint _gdk_input_ignore_wintab = FALSE;
gint _gdk_max_colors = 0;
gboolean _sizemove_in_progress = FALSE;
gboolean _modal_operation_in_progress = FALSE;
gboolean _ignore_destroy_clipboard = FALSE;
HGLOBAL _delayed_rendering_data = NULL;

View File

@ -898,7 +898,7 @@ _gdk_input_other_event (GdkEvent *event,
/* Don't produce any button or motion events while a window is being
* moved or resized, see bug #151090.
*/
if (_sizemove_in_progress)
if (_modal_operation_in_progress)
{
GDK_NOTE (EVENTS_OR_INPUT, g_print ("... ignored when moving/sizing\n"));
return FALSE;

View File

@ -100,22 +100,37 @@ _gdk_windowing_init (void)
CoInitialize (NULL);
_gdk_selection = gdk_atom_intern ("GDK_SELECTION", FALSE);
_wm_transient_for = gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE);
_targets = gdk_atom_intern ("TARGETS", FALSE);
_save_targets = gdk_atom_intern ("SAVE_TARGETS", FALSE);
_utf8_string = gdk_atom_intern ("UTF8_STRING", FALSE);
_text = gdk_atom_intern ("TEXT", FALSE);
_compound_text = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
_text_uri_list = gdk_atom_intern ("text/uri-list", FALSE);
_image_png = gdk_atom_intern ("image/png", FALSE);
_image_jpeg = gdk_atom_intern ("image/jpeg", FALSE);
_image_bmp = gdk_atom_intern ("image/bmp", FALSE);
_image_gif = gdk_atom_intern ("image/gif", FALSE);
_gdk_selection = gdk_atom_intern_static_string ("GDK_SELECTION");
_wm_transient_for = gdk_atom_intern_static_string ("WM_TRANSIENT_FOR");
_targets = gdk_atom_intern_static_string ("TARGETS");
_delete = gdk_atom_intern_static_string ("DELETE");
_save_targets = gdk_atom_intern_static_string ("SAVE_TARGETS");
_utf8_string = gdk_atom_intern_static_string ("UTF8_STRING");
_text = gdk_atom_intern_static_string ("TEXT");
_compound_text = gdk_atom_intern_static_string ("COMPOUND_TEXT");
_text_uri_list = gdk_atom_intern_static_string ("text/uri-list");
_text_html = gdk_atom_intern_static_string ("text/html");
_image_png = gdk_atom_intern_static_string ("image/png");
_image_jpeg = gdk_atom_intern_static_string ("image/jpeg");
_image_bmp = gdk_atom_intern_static_string ("image/bmp");
_image_gif = gdk_atom_intern_static_string ("image/gif");
_local_dnd = gdk_atom_intern ("LocalDndSelection", FALSE);
_gdk_win32_dropfiles = gdk_atom_intern ("DROPFILES_DND", FALSE);
_gdk_ole2_dnd = gdk_atom_intern ("OLE2_DND", FALSE);
_local_dnd = gdk_atom_intern_static_string ("LocalDndSelection");
_gdk_win32_dropfiles = gdk_atom_intern_static_string ("DROPFILES_DND");
_gdk_ole2_dnd = gdk_atom_intern_static_string ("OLE2_DND");
/* MS Office 2007, at least, offers images in common file formats
* using clipboard format names like "PNG" and "JFIF". So we follow
* the lead and map the GDK target name "image/png" to the clipboard
* format name "PNG" etc.
*/
_cf_png = RegisterClipboardFormat ("PNG");
_cf_jfif = RegisterClipboardFormat ("JFIF");
_cf_gif = RegisterClipboardFormat ("GIF");
_cf_url = RegisterClipboardFormat ("UniformResourceLocatorW");
_cf_html_format = RegisterClipboardFormat ("HTML Format");
_cf_text_html = RegisterClipboardFormat ("text/html");
_gdk_win32_selection_init ();
}

View File

@ -304,7 +304,7 @@ void _gdk_wchar_text_handle (GdkFont *font,
void _gdk_push_modal_window (GdkWindow *window);
void _gdk_remove_modal_window (GdkWindow *window);
GdkWindow *_gdk_modal_current ();
GdkWindow *_gdk_modal_current (void);
#ifdef G_ENABLE_DEBUG
@ -411,11 +411,13 @@ extern guint _scancode_rshift;
extern GdkAtom _gdk_selection;
extern GdkAtom _wm_transient_for;
extern GdkAtom _targets;
extern GdkAtom _delete;
extern GdkAtom _save_targets;
extern GdkAtom _utf8_string;
extern GdkAtom _text;
extern GdkAtom _compound_text;
extern GdkAtom _text_uri_list;
extern GdkAtom _text_html;
extern GdkAtom _image_png;
extern GdkAtom _image_jpeg;
extern GdkAtom _image_bmp;
@ -426,14 +428,44 @@ extern GdkAtom _local_dnd;
extern GdkAtom _gdk_win32_dropfiles;
extern GdkAtom _gdk_ole2_dnd;
/* Clipboard formats */
extern UINT _cf_png;
extern UINT _cf_jfif;
extern UINT _cf_gif;
extern UINT _cf_url;
extern UINT _cf_html_format;
extern UINT _cf_text_html;
/* OLE-based DND state */
typedef enum {
GDK_WIN32_DND_NONE,
GDK_WIN32_DND_PENDING,
GDK_WIN32_DND_DROPPED,
GDK_WIN32_DND_FAILED,
GDK_WIN32_DND_DRAGGING,
} GdkWin32DndState;
extern GdkWin32DndState _dnd_target_state;
extern GdkWin32DndState _dnd_source_state;
void _gdk_win32_dnd_do_dragdrop (void);
void _gdk_win32_ole2_dnd_property_change (GdkAtom type,
gint format,
const guchar *data,
gint nelements);
void _gdk_win32_begin_modal_call (void);
void _gdk_win32_end_modal_call (void);
/* Options */
extern gboolean _gdk_input_ignore_wintab;
extern gint _gdk_max_colors;
#define GDK_WIN32_COLORMAP_DATA(cmap) ((GdkColormapPrivateWin32 *) GDK_COLORMAP (cmap)->windowing_data)
/* TRUE while a user-initiated window move or resize operation is in progress */
extern gboolean _sizemove_in_progress;
/* TRUE while a modal sizing, moving, or dnd operation is in progress */
extern gboolean _modal_operation_in_progress;
/* TRUE when we are emptying the clipboard ourselves */
extern gboolean _ignore_destroy_clipboard;

View File

@ -258,6 +258,11 @@ gdk_property_change (GdkWindow *window,
_delayed_rendering_data = hdata;
}
}
else if (property == _gdk_ole2_dnd)
{
/* Will happen only if gdkdnd-win32.c has OLE2 dnd support compiled in */
_gdk_win32_ole2_dnd_property_change (type, format, data, nelements);
}
else
g_warning ("gdk_property_change: General case not implemented");
}

View File

@ -55,11 +55,6 @@ static GdkSelProp *dropfiles_prop = NULL;
*/
static GHashTable *sel_owner_table = NULL;
/* Well-known registered clipboard image formats */
static UINT cf_png;
static UINT cf_jfif;
static UINT cf_gif;
/* GdkAtoms for well-known image formats */
static GdkAtom *known_pixbuf_formats;
static int n_known_pixbuf_formats;
@ -79,15 +74,6 @@ _gdk_win32_selection_init (void)
sel_owner_table = g_hash_table_new (NULL, NULL);
_format_atom_table = g_hash_table_new (NULL, NULL);
/* MS Office 2007, at least, offers images in common file formats
* using clipboard format names like "PNG" and "JFIF". So we follow
* the lead and map the GDK target name "image/png" to the clipboard
* format name "PNG" etc.
*/
cf_png = RegisterClipboardFormat ("PNG");
cf_jfif = RegisterClipboardFormat ("JFIF");
cf_gif = RegisterClipboardFormat ("GIF");
pixbuf_formats = gdk_pixbuf_get_formats ();
n_known_pixbuf_formats = 0;
@ -123,7 +109,7 @@ _gdk_win32_selection_init (void)
text_plain_charset_CP1252 = gdk_atom_intern ("text/plain;charset=CP1252", FALSE);
g_hash_table_replace (_format_atom_table,
GINT_TO_POINTER (cf_png),
GINT_TO_POINTER (_cf_png),
_image_png);
g_hash_table_replace (_format_atom_table,
@ -442,7 +428,7 @@ gdk_selection_convert (GdkWindow *requestor,
for (fmt = 0; 0 != (fmt = EnumClipboardFormats (fmt)); )
{
if (fmt == cf_png)
if (fmt == _cf_png)
{
targets[ntargets++] = _image_png;
has_png = TRUE;
@ -460,7 +446,7 @@ gdk_selection_convert (GdkWindow *requestor,
targets[ntargets++] = _utf8_string;
has_text = TRUE;
}
else if (fmt == cf_png)
else if (fmt == _cf_png)
{
/* Already handled above */
}
@ -475,13 +461,13 @@ gdk_selection_convert (GdkWindow *requestor,
targets[ntargets++] = _image_bmp;
has_bmp = TRUE;
}
else if (fmt == cf_jfif)
else if (fmt == _cf_jfif)
{
/* Ditto for JPEG */
if (!has_png)
targets[ntargets++] = _image_jpeg;
}
else if (fmt == cf_gif)
else if (fmt == _cf_gif)
{
/* Ditto for GIF.
*/
@ -1215,7 +1201,7 @@ gdk_win32_selection_add_targets (GdkWindow *owner,
if (!has_image)
{
GDK_NOTE (DND, g_print ("... SetClipboardData(PNG,NULL)\n"));
SetClipboardData (cf_png, NULL);
SetClipboardData (_cf_png, NULL);
GDK_NOTE (DND, g_print ("... SetClipboardData(CF_DIB,NULL)\n"));
SetClipboardData (CF_DIB, NULL);

View File

@ -1835,7 +1835,7 @@ _gdk_remove_modal_window (GdkWindow *window)
}
GdkWindow *
_gdk_modal_current ()
_gdk_modal_current (void)
{
if (modal_window_stack != NULL)
{