/* GDK - The GIMP Drawing Kit * * gdkclipdrop-win32.h: Private Win32-specific clipboard/DnD object * * Copyright © 2017 LRN * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library. If not, see . */ #pragma once G_BEGIN_DECLS #define _gdk_win32_clipdrop_get() (_win32_clipdrop) #define _gdk_atom_array_index(a, i) (g_array_index (a, const char *, i)) #define _gdk_win32_clipdrop_atom(i) (_gdk_atom_array_index (_gdk_win32_clipdrop_get ()->known_atoms, i)) #define _gdk_cf_array_index(a, i) (g_array_index (a, UINT, i)) #define _gdk_win32_clipdrop_cf(i) (_gdk_cf_array_index (_gdk_win32_clipdrop_get ()->known_clipboard_formats, i)) /* Maps GDK contentformats to w32formats or vice versa, depending on the * semantics of the array that holds these. * Also remembers whether the data needs to be transmuted. */ typedef struct { int w32format; /* This is assumed to be an interned string, it will be * compared by simply comparing the pointer. */ const char *contentformat; gboolean transmute; } GdkWin32ContentFormatPair; /* 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; enum _GdkWin32AtomIndex { /* atoms: properties, targets and types */ GDK_WIN32_ATOM_INDEX_GDK_SELECTION = 0, GDK_WIN32_ATOM_INDEX_CLIPBOARD_MANAGER, GDK_WIN32_ATOM_INDEX_WM_TRANSIENT_FOR, GDK_WIN32_ATOM_INDEX_TARGETS, GDK_WIN32_ATOM_INDEX_DELETE, GDK_WIN32_ATOM_INDEX_SAVE_TARGETS, GDK_WIN32_ATOM_INDEX_TEXT_PLAIN_UTF8, GDK_WIN32_ATOM_INDEX_TEXT_PLAIN, GDK_WIN32_ATOM_INDEX_TEXT_URI_LIST, GDK_WIN32_ATOM_INDEX_TEXT_HTML, GDK_WIN32_ATOM_INDEX_IMAGE_PNG, GDK_WIN32_ATOM_INDEX_IMAGE_JPEG, GDK_WIN32_ATOM_INDEX_IMAGE_BMP, GDK_WIN32_ATOM_INDEX_IMAGE_GIF, /* DND selections */ GDK_WIN32_ATOM_INDEX_LOCAL_DND_SELECTION, GDK_WIN32_ATOM_INDEX_DROPFILES_DND, GDK_WIN32_ATOM_INDEX_OLE2_DND, /* Clipboard formats */ GDK_WIN32_ATOM_INDEX_PNG, GDK_WIN32_ATOM_INDEX_JFIF, GDK_WIN32_ATOM_INDEX_GIF, GDK_WIN32_ATOM_INDEX_CF_DIB, GDK_WIN32_ATOM_INDEX_CFSTR_SHELLIDLIST, GDK_WIN32_ATOM_INDEX_CF_TEXT, GDK_WIN32_ATOM_INDEX_CF_UNICODETEXT, GDK_WIN32_ATOM_INDEX_LAST }; typedef enum _GdkWin32AtomIndex GdkWin32AtomIndex; enum _GdkWin32CFIndex { GDK_WIN32_CF_INDEX_PNG = 0, GDK_WIN32_CF_INDEX_JFIF, GDK_WIN32_CF_INDEX_GIF, GDK_WIN32_CF_INDEX_UNIFORMRESOURCELOCATORW, GDK_WIN32_CF_INDEX_CFSTR_SHELLIDLIST, GDK_WIN32_CF_INDEX_HTML_FORMAT, GDK_WIN32_CF_INDEX_TEXT_HTML, GDK_WIN32_CF_INDEX_IMAGE_PNG, GDK_WIN32_CF_INDEX_IMAGE_JPEG, GDK_WIN32_CF_INDEX_IMAGE_BMP, GDK_WIN32_CF_INDEX_IMAGE_GIF, GDK_WIN32_CF_INDEX_TEXT_URI_LIST, GDK_WIN32_CF_INDEX_TEXT_PLAIN_UTF8, GDK_WIN32_CF_INDEX_LAST }; typedef enum _GdkWin32CFIndex GdkWin32CFIndex; #define GDK_TYPE_WIN32_CLIPDROP (gdk_win32_clipdrop_get_type ()) #define GDK_WIN32_CLIPDROP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_WIN32_CLIPDROP, GdkWin32Clipdrop)) #define GDK_WIN32_CLIPDROP_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_WIN32_CLIPDROP, GdkWin32ClipdropClass)) #define GDK_IS_WIN32_CLIPDROP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_WIN32_CLIPDROP)) #define GDK_IS_WIN32_CLIPDROP_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_WIN32_CLIPDROP)) #define GDK_WIN32_CLIPDROP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_WIN32_CLIPDROP, GdkWin32ClipdropClass)) typedef struct _GdkWin32Clipdrop GdkWin32Clipdrop; typedef struct _GdkWin32ClipdropClass GdkWin32ClipdropClass; typedef BOOL (WINAPI * GetUpdatedClipboardFormatsFunc)( _Out_ PUINT lpuiFormats, _In_ UINT cFormats, _Out_ PUINT pcFormatsOut ); /* This object is just a sink to hold all the clipboard- and dnd-related data * that otherwise would be in global variables. */ struct _GdkWin32Clipdrop { GObject parent_instance; /* interned strings for well-known image formats */ const char **known_pixbuf_formats; int n_known_pixbuf_formats; /* GArray of GdkAtoms for various known Selection and DnD strings. * Size is guaranteed to be at least GDK_WIN32_ATOM_INDEX_LAST */ GArray *known_atoms; /* GArray of UINTs for various known clipboard formats. * Size is guaranteed to be at least GDK_WIN32_CF_INDEX_LAST. */ GArray *known_clipboard_formats; GdkWin32DndState dnd_target_state; /* A target-keyed hash table of GArrays of GdkWin32ContentFormatPairs describing compatibility w32formats for a contentformat */ GHashTable *compatibility_w32formats; /* A format-keyed hash table of GArrays of GdkAtoms describing compatibility contentformats for a w32format */ GHashTable *compatibility_contentformats; /* By all rights we should be able to just use this function * normally, as our target platform is Vista-or-later. * This pointer is manually retrieved only to allow * GTK to be compiled with old MinGW versions, which * don't have GetUpdatedClipboardFormats in the import libs. */ GetUpdatedClipboardFormatsFunc GetUpdatedClipboardFormats; /* The thread that tries to open the clipboard and then * do stuff with it. Since clipboard opening can * fail, we split the code into a thread, and let * it try to open the clipboard repeatedly until * the operation times out. */ GThread *clipboard_open_thread; /* Our primary means of communicating with the thread. * The communication is one-way only - the thread replies * by just queueing functions to be called in the main * thread by using g_idle_add(). */ GAsyncQueue *clipboard_open_thread_queue; /* We reply to clipboard render requests via this thing. * We can't use messages, since the clipboard thread will * stop spinning the message loop while it waits for us * to render the data. */ GAsyncQueue *clipboard_render_queue; /* Window handle for the clipboard window that we * receive from the clipboard thread. We use that * to wake up the clipboard window main loop by * posting a message to it. */ HWND clipboard_window; /* The thread that calls DoDragDrop (), which would * normally block our main thread, as it runs its own * Windows message loop. */ GThread *dnd_thread; DWORD dnd_thread_id; /* We reply to the various dnd thread requests via this thing. * We can't use messages, since the dnd thread will * stop spinning the message loop while it waits for us * to come up with a reply. */ GAsyncQueue *dnd_queue; /* This counter is atomically incremented every time * the main thread pushes something into the queue, * and atomically decremented every time the DnD thread * pops something out of it. * It can be cheaply atomically checked to see if there's * anything in the queue. If there is, then the queue * processing (which requires expensice locks) can happen. */ int dnd_queue_counter; /* We don't actually support multiple simultaneous drags, * for obvious reasons (though this might change with * the advent of multitouch support?), but there may be * circumstances where we have two drag contexts at * the same time (one of them will grab the cursor * and thus cancel the other drag operation, but * there will be a point of time when both contexts * are out there). Thus we keep them around in this hash table. * Key is the context object (which is safe, because the main * thread keeps a reference on each one of those), value * is a pointer to a GdkWin32DnDThreadDoDragDrop struct, * which we can only examine when we're sure that the * dnd thread is not active. */ GHashTable *active_source_drags; }; struct _GdkWin32ClipdropClass { GObjectClass parent_class; }; GType gdk_win32_clipdrop_get_type (void) G_GNUC_CONST; void _gdk_win32_clipdrop_init (void); gboolean _gdk_win32_format_uses_hdata (UINT w32format); char * _gdk_win32_get_clipboard_format_name (UINT fmt, gboolean *is_predefined); void _gdk_win32_add_w32format_to_pairs (UINT format, GArray *array, GdkContentFormatsBuilder *builder); int _gdk_win32_add_contentformat_to_pairs (const char *target, GArray *array); void _gdk_win32_clipboard_default_output_done (GObject *clipboard, GAsyncResult *result, gpointer user_data); gboolean _gdk_win32_transmute_contentformat (const char *from_contentformat, UINT to_w32format, const guchar *data, gsize length, guchar **set_data, gsize *set_data_length); gboolean _gdk_win32_transmute_windows_data (UINT from_w32format, const char *to_contentformat, HANDLE hdata, guchar **set_data, gsize *set_data_length); 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_advertise_clipboard_contentformats (GTask *task, GdkContentFormats *contentformats);