GDK W32: Adapt to GdkDrop and GdkDragContext changes

* Remove clipdrop->dnd_target_state, it's not used anymore
* Remove non-functioning _gdk_dropfiles_store(), store dropfiles
  list in GdkWin32Drop instead
* Fix multiple comment typos
* Fix _gdk_win32_get_clipboard_format_name_as_interned_mimetype() to
  leave names that look like mime/types alone
* Refactor _gdk_win32_add_w32format_to_pairs() to populate
  GdkContentFormatsBuilder directly, instead of making a GList
* Rename context -> drag (still using GdkDragContext type,
  but [almost?] all variables and comments say "drag" now)
* Rename GdkDropContext -> GdkDrop
* Rename some parameter names for clarity
* Rewrite local protocol to look more like OLE2 protocol
  instead of mirroring the structure of the X11 API.
* Add handle_events field to GdkWin32DragContext,
  to shut off event handling (temporary fix until GTK is patched up)
* Remove _gdk_win32_drag_context_find() - the drag object is stored
  in GdkDrop instead. Use _gdk_win32_find_drag_for_dest_surface()
  to get it initially.
* Remove target_ctx_for_window, droptarget context is stored
  in the surface instead.
* Call gdk_drag_context_set_cursor() just like wayland backend does
  (slightly broken for now)
* Clean up the action choosing code (filter source actions by using
  keyboard state, pass that to GTK, get all actions supported by GTK in
  response, match them up with filtered source actions, return the
  result, falling back to COPY in case of multiple actions)
* Check drag_win32->protocol instead of the use_ole2_dnd variable where
  possible
* Remove protocol checks from functions that are only used by the local
  protocol
* Use event state to manufacture the keyboard state for WM_MOUSEMOVE
* Change function names printed by GDK_NOTE to name the actual
  functions, not their theoretical generic GDK stack ancestors
* Consistently use drag_win32 and drop_win32 variables instead of a mix
  of that and win32_drag/win32_drop
* Return FALSE from button handler to ensure that GTK gets the button
  event to break implicit grab
* Emit leave event on failed idroptarget_drop() calls
This commit is contained in:
Руслан Ижбулатов 2018-06-05 23:03:51 +00:00 committed by Benjamin Otte
parent dcf432d7d0
commit 8ee4de804c
9 changed files with 1256 additions and 1245 deletions

View File

@ -1540,8 +1540,6 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
win32_clipdrop->GetUpdatedClipboardFormats = GetProcAddress (user32, "GetUpdatedClipboardFormats");
FreeLibrary (user32);
win32_clipdrop->dnd_target_state = GDK_WIN32_DND_NONE;
atoms = g_array_sized_new (FALSE, TRUE, sizeof (GdkAtom), GDK_WIN32_ATOM_INDEX_LAST);
g_array_set_size (atoms, GDK_WIN32_ATOM_INDEX_LAST);
cfs = g_array_sized_new (FALSE, TRUE, sizeof (UINT), GDK_WIN32_CF_INDEX_LAST);
@ -1875,32 +1873,6 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
win32_clipdrop->dnd_thread_id = GPOINTER_TO_UINT (g_async_queue_pop (win32_clipdrop->dnd_queue));
}
void
_gdk_dropfiles_store (gchar *data)
{
/* FIXME: REMOVE ALL THAT STUFF
if (data != NULL)
{
g_assert (clipdrop->dropfiles_prop == NULL);
clipdrop->dropfiles_prop = g_new (GdkSelProp, 1);
clipdrop->dropfiles_prop->data = (guchar *) data;
clipdrop->dropfiles_prop->length = strlen (data) + 1;
clipdrop->dropfiles_prop->bitness = 8;
clipdrop->dropfiles_prop->target = _gdk_win32_clipdrop_atom (GDK_WIN32_ATOM_INDEX_TEXT_URI_LIST);
}
else
{
if (clipdrop->dropfiles_prop != NULL)
{
g_free (clipdrop->dropfiles_prop->data);
g_free (clipdrop->dropfiles_prop);
}
clipdrop->dropfiles_prop = NULL;
}
*/
}
#define CLIPBOARD_IDLE_ABORT_TIME 30
static const gchar *
@ -1967,7 +1939,7 @@ _gdk_win32_get_clipboard_format_name (UINT fmt,
}
/* If GetClipboardFormatNameW() used up all the space, it means that
* we probably need a bigger buffer, but cap this at 1 kilobyte.
* we probably need a bigger buffer, but cap this at 1 megabyte.
*/
if (gcfn_result == 0 || registered_name_w_len > 1024 * 1024)
{
@ -1994,12 +1966,22 @@ _gdk_win32_get_clipboard_format_name (UINT fmt,
/* This turns an arbitrary string into a string that
* *looks* like a mime/type, such as:
* "application/x.windows.FOO_BAR" from "FOO_BAR".
* Does nothing for strings that already look like a mime/type
* (no spaces, one slash, with at least one char on each side of the slash).
*/
const gchar *
_gdk_win32_get_clipboard_format_name_as_interned_mimetype (gchar *w32format_name)
{
gchar *mime_type;
const gchar *result;
gchar *space = strchr (w32format_name, ' ');
gchar *slash = strchr (w32format_name, '/');
if (space == NULL &&
slash > w32format_name &&
slash[1] != '\0' &&
strchr (&slash[1], '/') == NULL)
return g_intern_string (w32format_name);
mime_type = g_strdup_printf ("application/x.windows.%s", w32format_name);
result = g_intern_string (mime_type);
@ -2058,15 +2040,16 @@ _gdk_win32_get_compatibility_contentformats_for_w32format (UINT w32format)
/* Turn W32 format into a GDK content format and add it
* to the array of W32 format <-> GDK content format pairs
* and/or to a list of GDK content formats.
* and/or to a GDK contentformat builder.
* Also add compatibility GDK content formats for that W32 format.
* The added content format string is always interned.
* Ensures that duplicates are not added.
* Ensures that duplicates are not added to the pairs array
* (builder already takes care of that for itself).
*/
void
_gdk_win32_add_w32format_to_pairs (UINT w32format,
GArray *array,
GList **list)
_gdk_win32_add_w32format_to_pairs (UINT w32format,
GArray *pairs,
GdkContentFormatsBuilder *builder)
{
gboolean predef;
gchar *w32format_name = _gdk_win32_get_clipboard_format_name (w32format, &predef);
@ -2081,47 +2064,45 @@ _gdk_win32_add_w32format_to_pairs (UINT w32format,
GDK_NOTE (DND, g_print ("Maybe add as-is format %s (%s) (0x%p)\n", w32format_name, interned_w32format_name, interned_w32format_name));
g_free (w32format_name);
if (array && interned_w32format_name != 0)
if (pairs && interned_w32format_name != 0)
{
for (j = 0; j < array->len; j++)
if (g_array_index (array, GdkWin32ContentFormatPair, j).contentformat == interned_w32format_name)
for (j = 0; j < pairs->len; j++)
if (g_array_index (pairs, GdkWin32ContentFormatPair, j).contentformat == interned_w32format_name)
break;
if (j == array->len)
if (j == pairs->len)
{
pair.w32format = w32format;
pair.contentformat = interned_w32format_name;
pair.transmute = FALSE;
g_array_append_val (array, pair);
g_array_append_val (pairs, pair);
}
}
if (list && interned_w32format_name != 0 && g_list_find (*list, interned_w32format_name) == NULL)
*list = g_list_prepend (*list, (gpointer) interned_w32format_name);
if (builder != NULL && interned_w32format_name != 0)
gdk_content_formats_builder_add_mime_type (builder, interned_w32format_name);
}
comp_pairs = _gdk_win32_get_compatibility_contentformats_for_w32format (w32format);
if (array && comp_pairs != NULL)
if (pairs != NULL && comp_pairs != NULL)
for (i = 0; i < comp_pairs->len; i++)
{
pair = g_array_index (comp_pairs, GdkWin32ContentFormatPair, i);
for (j = 0; j < array->len; j++)
if (g_array_index (array, GdkWin32ContentFormatPair, j).contentformat == pair.contentformat &&
g_array_index (array, GdkWin32ContentFormatPair, j).w32format == pair.w32format)
for (j = 0; j < pairs->len; j++)
if (g_array_index (pairs, GdkWin32ContentFormatPair, j).contentformat == pair.contentformat &&
g_array_index (pairs, GdkWin32ContentFormatPair, j).w32format == pair.w32format)
break;
if (j == array->len)
g_array_append_val (array, pair);
if (j == pairs->len)
g_array_append_val (pairs, pair);
}
if (list && comp_pairs != NULL)
if (builder != NULL && comp_pairs != NULL)
for (i = 0; i < comp_pairs->len; i++)
{
pair = g_array_index (comp_pairs, GdkWin32ContentFormatPair, i);
if (g_list_find (*list, pair.contentformat) == NULL)
*list = g_list_prepend (*list, (gpointer) pair.contentformat);
gdk_content_formats_builder_add_mime_type (builder, pair.contentformat);
}
}

View File

@ -236,42 +236,42 @@ GType gdk_win32_clipdrop_get_type (void) G_GNUC
void _gdk_win32_clipdrop_init (void);
gboolean _gdk_win32_format_uses_hdata (UINT w32format);
gboolean _gdk_win32_format_uses_hdata (UINT w32format);
gchar * _gdk_win32_get_clipboard_format_name (UINT fmt,
gboolean *is_predefined);
void _gdk_win32_add_w32format_to_pairs (UINT format,
GArray *array,
GList **list);
gint _gdk_win32_add_contentformat_to_pairs (GdkAtom target,
GArray *array);
gchar * _gdk_win32_get_clipboard_format_name (UINT fmt,
gboolean *is_predefined);
void _gdk_win32_add_w32format_to_pairs (UINT format,
GArray *array,
GdkContentFormatsBuilder *builder);
gint _gdk_win32_add_contentformat_to_pairs (GdkAtom target,
GArray *array);
void _gdk_win32_clipboard_default_output_done (GObject *clipboard,
GAsyncResult *result,
gpointer user_data);
gboolean _gdk_win32_transmute_contentformat (const gchar *from_contentformat,
UINT to_w32format,
const guchar *data,
gint length,
guchar **set_data,
gsize *set_data_length);
void _gdk_win32_clipboard_default_output_done (GObject *clipboard,
GAsyncResult *result,
gpointer user_data);
gboolean _gdk_win32_transmute_contentformat (const gchar *from_contentformat,
UINT to_w32format,
const guchar *data,
gint length,
guchar **set_data,
gsize *set_data_length);
gboolean _gdk_win32_transmute_windows_data (UINT from_w32format,
const gchar *to_contentformat,
HANDLE hdata,
guchar **set_data,
gsize *set_data_length);
gboolean _gdk_win32_transmute_windows_data (UINT from_w32format,
const gchar *to_contentformat,
HANDLE hdata,
guchar **set_data,
gsize *set_data_length);
gboolean _gdk_win32_store_clipboard_contentformats (GdkClipboard *cb,
GTask *task,
GdkContentFormats *contentformats);
gboolean _gdk_win32_store_clipboard_contentformats (GdkClipboard *cb,
GTask *task,
GdkContentFormats *contentformats);
void _gdk_win32_retrieve_clipboard_contentformats (GTask *task,
GdkContentFormats *contentformats);
void _gdk_win32_retrieve_clipboard_contentformats (GTask *task,
GdkContentFormats *contentformats);
void _gdk_win32_advertise_clipboard_contentformats (GTask *task,
GdkContentFormats *contentformats);
void _gdk_win32_advertise_clipboard_contentformats (GTask *task,
GdkContentFormats *contentformats);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -202,8 +202,6 @@ void _gdk_win32_adjust_client_rect (GdkSurface *window,
void _gdk_selection_property_delete (GdkSurface *);
void _gdk_dropfiles_store (gchar *data);
void _gdk_push_modal_window (GdkSurface *window);
void _gdk_remove_modal_window (GdkSurface *window);
GdkSurface *_gdk_modal_current (void);
@ -424,6 +422,8 @@ void _gdk_win32_display_create_surface_impl (GdkDisplay *display,
/* stray GdkSurfaceImplWin32 members */
void _gdk_win32_surface_register_dnd (GdkSurface *window);
void _gdk_win32_surface_unregister_dnd (GdkSurface *window);
GdkDragContext *_gdk_win32_surface_drag_begin (GdkSurface *window,
GdkDevice *device,
GdkContentProvider *content,

View File

@ -250,6 +250,9 @@ gdk_surface_impl_win32_finalize (GObject *object)
surface_impl->cache_surface = NULL;
}
_gdk_win32_surface_unregister_dnd (wrapper);
g_clear_object (&surface_impl->drop);
g_assert (surface_impl->transient_owner == NULL);
g_assert (surface_impl->transient_children == NULL);

View File

@ -216,6 +216,9 @@ struct _GdkW32DragMoveResizeContext
typedef struct _GdkW32DragMoveResizeContext GdkW32DragMoveResizeContext;
/* defined in gdkdrop-win32.c */
typedef struct _drop_target_context drop_target_context;
struct _GdkSurfaceImplWin32
{
GdkSurfaceImpl parent_instance;
@ -243,6 +246,15 @@ struct _GdkSurfaceImplWin32
GdkEventMask native_event_mask;
/* Non-NULL for any window that is registered as a drop target.
* For OLE2 protocol only.
*/
drop_target_context *drop_target;
/* Temporarily holds the GdkDrop currently associated with this window.
* For LOCAL protocol only.
*/
GdkDrop *drop;
GdkSurfaceTypeHint type_hint;
GdkSurface *transient_owner;

View File

@ -38,13 +38,12 @@ struct _GdkWin32DragContextUtilityData
struct _GdkWin32DragContext
{
GdkDragContext context;
GdkDragContext drag;
GdkDragProtocol protocol;
GdkSurface *ipc_window;
GdkSurface *drag_surface;
GdkCursor *cursor;
GdkSeat *grab_seat;
GdkDragAction actions;
GdkDragAction current_action;
GdkWin32DragContextUtilityData util_data;
@ -57,6 +56,7 @@ struct _GdkWin32DragContext
guint drag_status : 4; /* Current status of drag */
guint drop_failed : 1; /* Whether the drop was unsuccessful */
guint handle_events : 1; /* Whether handle_event() should do anything */
};
struct _GdkWin32DragContextClass
@ -64,51 +64,54 @@ struct _GdkWin32DragContextClass
GdkDragContextClass parent_class;
};
struct _GdkWin32DropContext
{
GdkDragContext context;
GdkDragProtocol protocol;
GdkDragAction actions;
GdkDragAction current_action;
guint scale; /* Temporarily caches the HiDPI scale */
gint last_x; /* Coordinates from last event, in GDK space */
gint last_y;
DWORD last_key_state; /* Key state from last event */
gpointer _gdk_win32_dnd_thread_main (gpointer data);
/* Just like context->formats, but an array, and with format IDs
* stored inside.
*/
GArray *droptarget_w32format_contentformat_map;
GdkDragContext *_gdk_win32_find_drag_for_dest_surface (GdkSurface *dest_surface);
GdkWin32DragContext *local_source_context;
void _gdk_win32_drag_send_local_status_event (GdkDragContext *drag,
GdkDragAction action);
void _gdk_win32_local_send_enter (GdkDragContext *drag,
GdkSurface *dest_surface,
guint32 time);
guint drag_status : 4; /* Current status of drag */
guint drop_failed : 1; /* Whether the drop was unsuccessful */
};
GdkDragContext *_gdk_win32_drag_context_find (GdkSurface *source,
GdkSurface *dest);
GdkDrop *_gdk_win32_get_drop_for_dest_surface (GdkSurface *dest);
struct _GdkWin32DropContextClass
{
GdkDragContextClass parent_class;
};
void _gdk_win32_drag_do_leave (GdkDragContext *context,
guint32 time);
gpointer _gdk_win32_dnd_thread_main (gpointer data);
gboolean _gdk_win32_local_drop_target_will_emit_motion (GdkDrop *drop,
gint x_root,
gint y_root,
DWORD grfKeyState);
GdkDragContext *_gdk_win32_find_source_context_for_dest_surface (GdkSurface *dest_surface);
void _gdk_win32_local_drop_target_dragenter (GdkDragContext *drag,
GdkSurface *dest_surface,
gint x_root,
gint y_root,
DWORD grfKeyState,
guint32 time_,
GdkDragAction *actions);
void _gdk_win32_local_drop_target_dragover (GdkDrop *drop,
GdkDragContext *drag,
gint x_root,
gint y_root,
DWORD grfKeyState,
guint32 time_,
GdkDragAction *actions);
void _gdk_win32_local_drop_target_dragleave (GdkDrop *drop,
guint32 time_);
void _gdk_win32_local_drop_target_drop (GdkDrop *drop,
GdkDragContext *drag,
guint32 time_,
GdkDragAction *actions);
void _gdk_win32_drag_context_send_local_status_event (GdkDragContext *src_context,
GdkDragAction action);
void _gdk_win32_local_send_enter (GdkDragContext *context,
guint32 time);
GdkDragContext *_gdk_win32_drag_context_find (GdkSurface *source,
GdkSurface *dest);
GdkDragContext *_gdk_win32_drop_context_find (GdkSurface *source,
GdkSurface *dest);
void _gdk_win32_drag_do_leave (GdkDragContext *context,
guint32 time);
void _gdk_win32_local_drag_give_feedback (GdkDragContext *drag,
GdkDragAction actions);
void _gdk_win32_local_drag_context_drop_response (GdkDragContext *drag,
GdkDragAction action);
G_END_DECLS

View File

@ -43,23 +43,6 @@ typedef struct _GdkWin32DragContextClass GdkWin32DragContextClass;
GDK_AVAILABLE_IN_ALL
GType gdk_win32_drag_context_get_type (void);
#define GDK_TYPE_WIN32_DROP_CONTEXT (gdk_win32_drop_context_get_type ())
#define GDK_WIN32_DROP_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WIN32_DROP_CONTEXT, GdkWin32DropContext))
#define GDK_WIN32_DROP_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WIN32_DROP_CONTEXT, GdkWin32DropContextClass))
#define GDK_IS_WIN32_DROP_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WIN32_DROP_CONTEXT))
#define GDK_IS_WIN32_DROP_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WIN32_DROP_CONTEXT))
#define GDK_WIN32_DROP_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WIN32_DROP_CONTEXT, GdkWin32DropContextClass))
#ifdef GDK_COMPILATION
typedef struct _GdkWin32DropContext GdkWin32DropContext;
#else
typedef GdkDragContext GdkWin32DropContext;
#endif
typedef struct _GdkWin32DropContextClass GdkWin32DropContextClass;
GDK_AVAILABLE_IN_ALL
GType gdk_win32_drop_context_get_type (void);
G_END_DECLS
#endif /* __GDK_WIN32_DRAG_CONTEXT_H__ */