forked from AuroraMiddleware/gtk
GDK W32: Another massive clipboard and DnD update
Rename GdkWin32Selection to GdkWin32Clipdrop, since GdkSelection is mostly gone, and the word "selection" does not reflect the functionality of this object too well. Clipboard is now handled by a separate thread, most of the code for it now lives in gdkclipdrop-win32.c, gdkclipboard-win32.c just uses clipdrop as a backend. The DnD source part is also put into a thread. The DnD target part does not spin the main loop, it just emits a GDK event and returns a default value if it doesn't get a reply by the time the event is processed. Both clipboard and DnD use a new GOutputStream subclass to get data from GTK and put it into a HGLOBAL. GdkWin32DragContext is split into GdkWin32DragContext and GdkWin32DropContext, anticipating a similar change that slated to happen to GdkDragContext. OLE2 DnD protocol is now used by default, set GDK_WIN32_OLE2_DND envvar to 0 to make GDK use the old LOCAL and DROPFILES protocols. https://bugzilla.gnome.org/show_bug.cgi?id=773299
This commit is contained in:
parent
6ad33a274b
commit
54a4307128
299
gdk/win32/gdkclipboard-win32.c
Normal file
299
gdk/win32/gdkclipboard-win32.c
Normal file
@ -0,0 +1,299 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2017 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkclipboardprivate.h"
|
||||
#include "gdkclipboard-win32.h"
|
||||
|
||||
#include "gdkintl.h"
|
||||
#include "gdkprivate-win32.h"
|
||||
#include "gdkhdataoutputstream-win32.h"
|
||||
#include "gdk/gdk-private.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct _GdkWin32ClipboardClass GdkWin32ClipboardClass;
|
||||
|
||||
typedef struct _RetrievalInfo RetrievalInfo;
|
||||
|
||||
struct _GdkWin32Clipboard
|
||||
{
|
||||
GdkClipboard parent;
|
||||
|
||||
/* Taken from the OS, the OS increments it every time
|
||||
* clipboard data changes.
|
||||
* -1 means that clipboard data that we claim to
|
||||
* have access to is actually just an empty set that
|
||||
* we made up. Thus any real data from the OS will
|
||||
* override anything we make up.
|
||||
*/
|
||||
gint64 sequence_number;
|
||||
};
|
||||
|
||||
struct _GdkWin32ClipboardClass
|
||||
{
|
||||
GdkClipboardClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GdkWin32Clipboard, gdk_win32_clipboard, GDK_TYPE_CLIPBOARD)
|
||||
|
||||
static GdkContentFormats *
|
||||
gdk_win32_clipboard_request_contentformats (GdkWin32Clipboard *cb)
|
||||
{
|
||||
BOOL success;
|
||||
UINT *w32_formats = NULL;
|
||||
UINT w32_formats_len = 0;
|
||||
UINT w32_formats_allocated;
|
||||
gsize i;
|
||||
GArray *formatpairs;
|
||||
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
|
||||
DWORD error_code;
|
||||
|
||||
SetLastError (0);
|
||||
success = clipdrop->GetUpdatedClipboardFormats (NULL, 0, &w32_formats_allocated);
|
||||
error_code = GetLastError ();
|
||||
|
||||
if (!success && error_code != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
g_warning ("Initial call to GetUpdatedClipboardFormats() failed with error %lu", error_code);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
w32_formats = g_new0 (UINT, w32_formats_allocated);
|
||||
|
||||
SetLastError (0);
|
||||
success = clipdrop->GetUpdatedClipboardFormats (w32_formats, w32_formats_allocated, &w32_formats_len);
|
||||
error_code = GetLastError ();
|
||||
|
||||
if (!success)
|
||||
{
|
||||
g_warning ("Second call to GetUpdatedClipboardFormats() failed with error %lu", error_code);
|
||||
g_free (w32_formats);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
formatpairs = g_array_sized_new (FALSE,
|
||||
FALSE,
|
||||
sizeof (GdkWin32ContentFormatPair),
|
||||
MIN (w32_formats_len, w32_formats_allocated));
|
||||
|
||||
for (i = 0; i < MIN (w32_formats_len, w32_formats_allocated); i++)
|
||||
_gdk_win32_add_w32format_to_pairs (w32_formats[i], formatpairs, NULL);
|
||||
|
||||
g_free (w32_formats);
|
||||
|
||||
GDK_NOTE (DND, {
|
||||
g_print ("... ");
|
||||
for (i = 0; i < formatpairs->len; i++)
|
||||
{
|
||||
const char *mime_type = (const char *) g_array_index (formatpairs, GdkWin32ContentFormatPair, i).contentformat;
|
||||
|
||||
g_print ("%s", mime_type);
|
||||
if (i < formatpairs->len - 1)
|
||||
g_print (", ");
|
||||
}
|
||||
g_print ("\n");
|
||||
});
|
||||
|
||||
if (formatpairs->len > 0)
|
||||
{
|
||||
GdkContentFormatsBuilder *builder = gdk_content_formats_builder_new ();
|
||||
|
||||
for (i = 0; i < formatpairs->len; i++)
|
||||
gdk_content_formats_builder_add_mime_type (builder, g_array_index (formatpairs, GdkWin32ContentFormatPair, i).contentformat);
|
||||
|
||||
g_array_free (formatpairs, TRUE);
|
||||
|
||||
return gdk_content_formats_builder_free (builder);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_array_free (formatpairs, TRUE);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gdk_win32_clipboard_claim_remote (GdkWin32Clipboard *cb)
|
||||
{
|
||||
GdkContentFormats *formats;
|
||||
|
||||
/* Claim empty first, in case the format request fails */
|
||||
formats = gdk_content_formats_new (NULL, 0);
|
||||
gdk_clipboard_claim_remote (GDK_CLIPBOARD (cb), formats);
|
||||
gdk_content_formats_unref (formats);
|
||||
cb->sequence_number = -1;
|
||||
|
||||
formats = gdk_win32_clipboard_request_contentformats (cb);
|
||||
gdk_clipboard_claim_remote (GDK_CLIPBOARD (cb), formats);
|
||||
gdk_content_formats_unref (formats);
|
||||
cb->sequence_number = GetClipboardSequenceNumber ();
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_clipboard_finalize (GObject *object)
|
||||
{
|
||||
GdkWin32Clipboard *cb = GDK_WIN32_CLIPBOARD (object);
|
||||
|
||||
G_OBJECT_CLASS (gdk_win32_clipboard_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_clipboard_claim (GdkClipboard *clipboard,
|
||||
GdkContentFormats *formats,
|
||||
gboolean local,
|
||||
GdkContentProvider *content)
|
||||
{
|
||||
if (local)
|
||||
_gdk_win32_advertise_clipboard_contentformats (NULL, content ? formats : NULL);
|
||||
|
||||
return GDK_CLIPBOARD_CLASS (gdk_win32_clipboard_parent_class)->claim (clipboard, formats, local, content);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_clipboard_store_async (GdkClipboard *clipboard,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkWin32Clipboard *cb = GDK_WIN32_CLIPBOARD (clipboard);
|
||||
GdkContentProvider *content;
|
||||
GdkContentFormats *formats;
|
||||
GTask *store_task;
|
||||
|
||||
store_task = g_task_new (clipboard, cancellable, callback, user_data);
|
||||
g_task_set_priority (store_task, io_priority);
|
||||
g_task_set_source_tag (store_task, gdk_win32_clipboard_store_async);
|
||||
|
||||
content = gdk_clipboard_get_content (clipboard);
|
||||
|
||||
if (content == NULL)
|
||||
{
|
||||
GDK_NOTE (CLIPBOARD, g_printerr ("storing empty clipboard: SUCCESS!\n"));
|
||||
g_task_return_boolean (store_task, TRUE);
|
||||
g_clear_object (&store_task);
|
||||
return;
|
||||
}
|
||||
|
||||
formats = gdk_content_provider_ref_storable_formats (content);
|
||||
formats = gdk_content_formats_union_serialize_mime_types (formats);
|
||||
|
||||
if (!_gdk_win32_store_clipboard_contentformats (cb, store_task, formats))
|
||||
{
|
||||
GDK_NOTE (CLIPBOARD, g_printerr ("clipdrop says there's nothing to store: SUCCESS!\n"));
|
||||
g_task_return_boolean (store_task, TRUE);
|
||||
g_clear_object (&store_task);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_clipboard_store_finish (GdkClipboard *clipboard,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, clipboard), FALSE);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_win32_clipboard_store_async, FALSE);
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_clipboard_read_async (GdkClipboard *clipboard,
|
||||
GdkContentFormats *contentformats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkWin32Clipboard *cb = GDK_WIN32_CLIPBOARD (clipboard);
|
||||
GSList *targets;
|
||||
GTask *task;
|
||||
GdkWin32Clipdrop *clipdrop = _gdk_win32_clipdrop_get ();
|
||||
|
||||
task = g_task_new (clipboard, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, io_priority);
|
||||
g_task_set_source_tag (task, gdk_win32_clipboard_read_async);
|
||||
|
||||
_gdk_win32_retrieve_clipboard_contentformats (task, contentformats);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_win32_clipboard_read_finish (GdkClipboard *clipboard,
|
||||
const char **out_mime_type,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
GTask *task;
|
||||
GInputStream *stream;
|
||||
|
||||
g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (clipboard)), NULL);
|
||||
task = G_TASK (result);
|
||||
g_return_val_if_fail (g_task_get_source_tag (task) == gdk_win32_clipboard_read_async, NULL);
|
||||
|
||||
stream = g_task_propagate_pointer (task, error);
|
||||
|
||||
if (stream == NULL)
|
||||
return stream;
|
||||
|
||||
if (out_mime_type)
|
||||
*out_mime_type = g_object_get_data (G_OBJECT (stream), "gdk-clipboard-stream-contenttype");
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_clipboard_class_init (GdkWin32ClipboardClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GdkClipboardClass *clipboard_class = GDK_CLIPBOARD_CLASS (class);
|
||||
|
||||
object_class->finalize = gdk_win32_clipboard_finalize;
|
||||
|
||||
clipboard_class->claim = gdk_win32_clipboard_claim;
|
||||
clipboard_class->store_async = gdk_win32_clipboard_store_async;
|
||||
clipboard_class->store_finish = gdk_win32_clipboard_store_finish;
|
||||
clipboard_class->read_async = gdk_win32_clipboard_read_async;
|
||||
clipboard_class->read_finish = gdk_win32_clipboard_read_finish;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_clipboard_init (GdkWin32Clipboard *cb)
|
||||
{
|
||||
cb->sequence_number = -1;
|
||||
}
|
||||
|
||||
GdkClipboard *
|
||||
gdk_win32_clipboard_new (GdkDisplay *display)
|
||||
{
|
||||
GdkWin32Clipboard *cb;
|
||||
|
||||
cb = g_object_new (GDK_TYPE_WIN32_CLIPBOARD,
|
||||
"display", display,
|
||||
NULL);
|
||||
|
||||
gdk_win32_clipboard_claim_remote (cb);
|
||||
|
||||
return GDK_CLIPBOARD (cb);
|
||||
}
|
||||
|
39
gdk/win32/gdkclipboard-win32.h
Normal file
39
gdk/win32/gdkclipboard-win32.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2017 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_CLIPBOARD_WIN32_H__
|
||||
#define __GDK_CLIPBOARD_WIN32_H__
|
||||
|
||||
#include "gdk/gdkclipboard.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_WIN32_CLIPBOARD (gdk_win32_clipboard_get_type ())
|
||||
#define GDK_WIN32_CLIPBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_WIN32_CLIPBOARD, GdkWin32Clipboard))
|
||||
#define GDK_IS_WIN32_CLIPBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_WIN32_CLIPBOARD))
|
||||
|
||||
typedef struct _GdkWin32Clipboard GdkWin32Clipboard;
|
||||
|
||||
GType gdk_win32_clipboard_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GdkClipboard * gdk_win32_clipboard_new (GdkDisplay *display);
|
||||
|
||||
void gdk_win32_clipboard_claim_remote (GdkWin32Clipboard *cb);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_CLIPBOARD_WIN32_H__ */
|
3289
gdk/win32/gdkclipdrop-win32.c
Normal file
3289
gdk/win32/gdkclipdrop-win32.c
Normal file
File diff suppressed because it is too large
Load Diff
278
gdk/win32/gdkclipdrop-win32.h
Normal file
278
gdk/win32/gdkclipdrop-win32.h
Normal file
@ -0,0 +1,278 @@
|
||||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_CLIPDROP_WIN32_H__
|
||||
#define __GDK_CLIPDROP_WIN32_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define _gdk_win32_clipdrop_get() (_win32_clipdrop)
|
||||
#define _gdk_atom_array_index(a, i) (g_array_index (a, GdkAtom, 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 {
|
||||
gint w32format;
|
||||
/* This is assumed to be an interned string, it will be
|
||||
* compared by simply comparing the pointer.
|
||||
*/
|
||||
const gchar *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
|
||||
{
|
||||
/* GdkAtoms: 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 gchar **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 tha 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.
|
||||
*/
|
||||
gint 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);
|
||||
|
||||
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);
|
||||
|
||||
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,
|
||||
gint *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);
|
||||
|
||||
void _gdk_win32_retrieve_clipboard_contentformats (GTask *task,
|
||||
GdkContentFormats *contentformats);
|
||||
|
||||
void _gdk_win32_advertise_clipboard_contentformats (GTask *task,
|
||||
GdkContentFormats *contentformats);
|
||||
|
||||
|
||||
|
||||
#endif /* __GDK_CLIPDROP_WIN32_H__ */
|
@ -23,6 +23,8 @@
|
||||
|
||||
#include "gdk.h"
|
||||
#include "gdkprivate-win32.h"
|
||||
#include "gdkclipboardprivate.h"
|
||||
#include "gdkclipboard-win32.h"
|
||||
#include "gdkdisplay-win32.h"
|
||||
#include "gdkdevicemanager-win32.h"
|
||||
#include "gdkglcontext-win32.h"
|
||||
@ -412,7 +414,11 @@ _gdk_win32_display_open (const gchar *display_name)
|
||||
NULL);
|
||||
_gdk_device_manager->display = _gdk_display;
|
||||
|
||||
_gdk_dnd_init ();
|
||||
_gdk_drag_init ();
|
||||
_gdk_drop_init ();
|
||||
|
||||
_gdk_display->clipboard = gdk_win32_clipboard_new (_gdk_display);
|
||||
_gdk_display->primary_clipboard = gdk_clipboard_new (_gdk_display);
|
||||
|
||||
/* Precalculate display name */
|
||||
(void) gdk_display_get_name (_gdk_display);
|
||||
@ -502,183 +508,6 @@ gdk_win32_display_get_default_group (GdkDisplay *display)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static HWND _hwnd_next_viewer = NULL;
|
||||
|
||||
/*
|
||||
* maybe this should be integrated with the default message loop - or maybe not ;-)
|
||||
*/
|
||||
static LRESULT CALLBACK
|
||||
inner_clipboard_window_procedure (HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_DESTROY: /* remove us from chain */
|
||||
{
|
||||
ChangeClipboardChain (hwnd, _hwnd_next_viewer);
|
||||
PostQuitMessage (0);
|
||||
return 0;
|
||||
}
|
||||
case WM_CHANGECBCHAIN:
|
||||
{
|
||||
HWND hwndRemove = (HWND) wparam; /* handle of window being removed */
|
||||
HWND hwndNext = (HWND) lparam; /* handle of next window in chain */
|
||||
|
||||
if (hwndRemove == _hwnd_next_viewer)
|
||||
_hwnd_next_viewer = hwndNext == hwnd ? NULL : hwndNext;
|
||||
else if (_hwnd_next_viewer != NULL)
|
||||
return SendMessage (_hwnd_next_viewer, message, wparam, lparam);
|
||||
|
||||
return 0;
|
||||
}
|
||||
case WM_CLIPBOARDUPDATE:
|
||||
case WM_DRAWCLIPBOARD:
|
||||
{
|
||||
HWND hwnd_owner;
|
||||
HWND hwnd_opener;
|
||||
/*
|
||||
GdkEvent *event;
|
||||
*/
|
||||
GdkWin32Selection *win32_sel = _gdk_win32_selection_get ();
|
||||
|
||||
hwnd_owner = GetClipboardOwner ();
|
||||
|
||||
if ((hwnd_owner == NULL) &&
|
||||
(GetLastError () != ERROR_SUCCESS))
|
||||
WIN32_API_FAILED ("GetClipboardOwner");
|
||||
|
||||
hwnd_opener = GetOpenClipboardWindow ();
|
||||
|
||||
GDK_NOTE (DND, g_print (" drawclipboard owner: %p; opener %p ", hwnd_owner, hwnd_opener));
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (_gdk_debug_flags & GDK_DEBUG_DND)
|
||||
{
|
||||
if (win32_sel->clipboard_opened_for != INVALID_HANDLE_VALUE ||
|
||||
OpenClipboard (hwnd))
|
||||
{
|
||||
UINT nFormat = 0;
|
||||
|
||||
while ((nFormat = EnumClipboardFormats (nFormat)) != 0)
|
||||
g_print ("%s ", _gdk_win32_cf_to_string (nFormat));
|
||||
|
||||
if (win32_sel->clipboard_opened_for == INVALID_HANDLE_VALUE)
|
||||
CloseClipboard ();
|
||||
}
|
||||
else
|
||||
{
|
||||
WIN32_API_FAILED ("OpenClipboard");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
GDK_NOTE (DND, g_print (" \n"));
|
||||
|
||||
if (win32_sel->stored_hwnd_owner != hwnd_owner)
|
||||
{
|
||||
if (win32_sel->clipboard_opened_for != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseClipboard ();
|
||||
GDK_NOTE (DND, g_print ("Closed clipboard @ %s:%d\n", __FILE__, __LINE__));
|
||||
}
|
||||
|
||||
win32_sel->clipboard_opened_for = INVALID_HANDLE_VALUE;
|
||||
win32_sel->stored_hwnd_owner = hwnd_owner;
|
||||
|
||||
_gdk_win32_clear_clipboard_queue ();
|
||||
}
|
||||
/* GDK_OWNER_CHANGE does not exist anymore since 437d70f56919916e884a81d3bff0170322ab2906
|
||||
event = gdk_event_new (GDK_OWNER_CHANGE);
|
||||
event->owner_change.window = NULL;
|
||||
event->owner_change.reason = GDK_OWNER_CHANGE_NEW_OWNER;
|
||||
event->owner_change.selection = GDK_SELECTION_CLIPBOARD;
|
||||
event->owner_change.time = _gdk_win32_get_next_tick (0);
|
||||
event->owner_change.selection_time = GDK_CURRENT_TIME;
|
||||
_gdk_win32_append_event (event);
|
||||
*/
|
||||
|
||||
if (_hwnd_next_viewer != NULL)
|
||||
return SendMessage (_hwnd_next_viewer, message, wparam, lparam);
|
||||
|
||||
/* clear error to avoid confusing SetClipboardViewer() return */
|
||||
SetLastError (0);
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
/* Otherwise call DefWindowProcW(). */
|
||||
GDK_NOTE (EVENTS, g_print (" DefWindowProcW"));
|
||||
return DefWindowProc (hwnd, message, wparam, lparam);
|
||||
}
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK
|
||||
_clipboard_window_procedure (HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam)
|
||||
{
|
||||
LRESULT retval;
|
||||
|
||||
GDK_NOTE (EVENTS, g_print ("%s%*s%s %p",
|
||||
(debug_indent > 0 ? "\n" : ""),
|
||||
debug_indent, "",
|
||||
_gdk_win32_message_to_string (message), hwnd));
|
||||
debug_indent += 2;
|
||||
retval = inner_clipboard_window_procedure (hwnd, message, wparam, lparam);
|
||||
debug_indent -= 2;
|
||||
|
||||
GDK_NOTE (EVENTS, g_print (" => %" G_GINT64_FORMAT "%s", (gint64) retval, (debug_indent == 0 ? "\n" : "")));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a hidden window and adds it to the clipboard chain
|
||||
*/
|
||||
static gboolean
|
||||
register_clipboard_notification (GdkDisplay *display)
|
||||
{
|
||||
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
|
||||
WNDCLASS wclass = { 0, };
|
||||
ATOM klass;
|
||||
|
||||
wclass.lpszClassName = "GdkClipboardNotification";
|
||||
wclass.lpfnWndProc = _clipboard_window_procedure;
|
||||
wclass.hInstance = _gdk_app_hmodule;
|
||||
|
||||
klass = RegisterClass (&wclass);
|
||||
if (!klass)
|
||||
return FALSE;
|
||||
|
||||
display_win32->clipboard_hwnd = CreateWindow (MAKEINTRESOURCE (klass),
|
||||
NULL, WS_POPUP,
|
||||
0, 0, 0, 0, NULL, NULL,
|
||||
_gdk_app_hmodule, NULL);
|
||||
|
||||
if (display_win32->clipboard_hwnd == NULL)
|
||||
goto failed;
|
||||
|
||||
SetLastError (0);
|
||||
_hwnd_next_viewer = SetClipboardViewer (display_win32->clipboard_hwnd);
|
||||
|
||||
if (_hwnd_next_viewer == NULL && GetLastError() != 0)
|
||||
goto failed;
|
||||
|
||||
/* FIXME: http://msdn.microsoft.com/en-us/library/ms649033(v=VS.85).aspx */
|
||||
/* This is only supported by Vista, and not yet by mingw64 */
|
||||
/* if (AddClipboardFormatListener (hwnd) == FALSE) */
|
||||
/* goto failed; */
|
||||
|
||||
return TRUE;
|
||||
|
||||
failed:
|
||||
g_critical ("Failed to install clipboard viewer");
|
||||
UnregisterClass (MAKEINTRESOURCE (klass), _gdk_app_hmodule);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_display_supports_shapes (GdkDisplay *display)
|
||||
{
|
||||
@ -731,13 +560,6 @@ gdk_win32_display_dispose (GObject *object)
|
||||
display_win32->hwnd = NULL;
|
||||
}
|
||||
|
||||
if (display_win32->clipboard_hwnd != NULL)
|
||||
{
|
||||
DestroyWindow (display_win32->clipboard_hwnd);
|
||||
display_win32->clipboard_hwnd = NULL;
|
||||
_hwnd_next_viewer = NULL;
|
||||
}
|
||||
|
||||
if (display_win32->have_at_least_win81)
|
||||
{
|
||||
if (display_win32->shcore_funcs.hshcore != NULL)
|
||||
|
@ -75,7 +75,6 @@ struct _GdkWin32Display
|
||||
int cursor_theme_size;
|
||||
|
||||
HWND hwnd;
|
||||
HWND clipboard_hwnd;
|
||||
|
||||
/* WGL/OpenGL Items */
|
||||
guint have_wgl : 1;
|
||||
|
2893
gdk/win32/gdkdrag-win32.c
Normal file
2893
gdk/win32/gdkdrag-win32.c
Normal file
File diff suppressed because it is too large
Load Diff
1262
gdk/win32/gdkdrop-win32.c
Normal file
1262
gdk/win32/gdkdrop-win32.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -57,7 +57,7 @@
|
||||
#include "gdkdevice-wintab.h"
|
||||
#include "gdkwin32dnd.h"
|
||||
#include "gdkdisplay-win32.h"
|
||||
#include "gdkselection-win32.h"
|
||||
//#include "gdkselection-win32.h"
|
||||
#include "gdkdndprivate.h"
|
||||
|
||||
#include <windowsx.h>
|
||||
@ -780,18 +780,12 @@ _gdk_win32_print_event (const GdkEvent *event)
|
||||
CASE (GDK_CONFIGURE);
|
||||
CASE (GDK_MAP);
|
||||
CASE (GDK_UNMAP);
|
||||
CASE (GDK_PROPERTY_NOTIFY);
|
||||
CASE (GDK_SELECTION_CLEAR);
|
||||
CASE (GDK_SELECTION_REQUEST);
|
||||
CASE (GDK_SELECTION_NOTIFY);
|
||||
CASE (GDK_PROXIMITY_IN);
|
||||
CASE (GDK_PROXIMITY_OUT);
|
||||
CASE (GDK_DRAG_ENTER);
|
||||
CASE (GDK_DRAG_LEAVE);
|
||||
CASE (GDK_DRAG_MOTION);
|
||||
CASE (GDK_DRAG_STATUS);
|
||||
CASE (GDK_DROP_START);
|
||||
CASE (GDK_DROP_FINISHED);
|
||||
CASE (GDK_SCROLL);
|
||||
CASE (GDK_GRAB_BROKEN);
|
||||
#undef CASE
|
||||
@ -866,21 +860,10 @@ _gdk_win32_print_event (const GdkEvent *event)
|
||||
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:
|
||||
selection_name = (const char *)event->selection.selection;
|
||||
target_name = (const char *)event->selection.target;
|
||||
property_name = (const char *)event->selection.property;
|
||||
g_print ("sel:%s tgt:%s prop:%s",
|
||||
selection_name, target_name, property_name);
|
||||
break;
|
||||
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,
|
||||
@ -942,11 +925,6 @@ fixup_event (GdkEvent *event)
|
||||
(event->any.type == GDK_LEAVE_NOTIFY)) &&
|
||||
(event->crossing.child_window != NULL))
|
||||
g_object_ref (event->crossing.child_window);
|
||||
if (((event->any.type == GDK_SELECTION_CLEAR) ||
|
||||
(event->any.type == GDK_SELECTION_NOTIFY) ||
|
||||
(event->any.type == GDK_SELECTION_REQUEST)) &&
|
||||
(event->selection.requestor != NULL))
|
||||
g_object_ref (event->selection.requestor);
|
||||
event->any.send_event = InSendMessage ();
|
||||
}
|
||||
|
||||
@ -2306,7 +2284,7 @@ gdk_event_translate (MSG *msg,
|
||||
|
||||
int i;
|
||||
|
||||
GdkWin32Selection *win32_sel = NULL;
|
||||
GdkWin32Clipdrop *clipdrop = NULL;
|
||||
|
||||
STGMEDIUM *property_change_data;
|
||||
|
||||
@ -3700,118 +3678,6 @@ gdk_event_translate (MSG *msg,
|
||||
_gdk_win32_surface_enable_transparency (window);
|
||||
break;
|
||||
|
||||
case WM_DESTROYCLIPBOARD:
|
||||
win32_sel = _gdk_win32_selection_get ();
|
||||
|
||||
if (!win32_sel->ignore_destroy_clipboard)
|
||||
{
|
||||
event = gdk_event_new (GDK_SELECTION_CLEAR);
|
||||
event->selection.window = window;
|
||||
event->selection.selection = GDK_SELECTION_CLIPBOARD;
|
||||
event->selection.time = _gdk_win32_get_next_tick (msg->time);
|
||||
_gdk_win32_append_event (event);
|
||||
}
|
||||
else
|
||||
{
|
||||
return_val = TRUE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WM_RENDERFORMAT:
|
||||
GDK_NOTE (EVENTS, g_print (" %s", _gdk_win32_cf_to_string (msg->wParam)));
|
||||
|
||||
*ret_valp = 0;
|
||||
return_val = TRUE;
|
||||
|
||||
win32_sel = _gdk_win32_selection_get ();
|
||||
|
||||
for (target = NULL, i = 0;
|
||||
i < win32_sel->clipboard_selection_targets->len;
|
||||
i++)
|
||||
{
|
||||
GdkSelTargetFormat target_format = g_array_index (win32_sel->clipboard_selection_targets, GdkSelTargetFormat, i);
|
||||
|
||||
if (target_format.format == msg->wParam)
|
||||
{
|
||||
target = target_format.target;
|
||||
win32_sel->property_change_transmute = target_format.transmute;
|
||||
}
|
||||
}
|
||||
|
||||
if (target == NULL)
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_print (" (target not found)"));
|
||||
break;
|
||||
}
|
||||
|
||||
/* We need to render to clipboard immediately, don't call
|
||||
* _gdk_win32_append_event()
|
||||
*/
|
||||
event = gdk_event_new (GDK_SELECTION_REQUEST);
|
||||
event->selection.window = window;
|
||||
event->selection.send_event = FALSE;
|
||||
event->selection.selection = GDK_SELECTION_CLIPBOARD;
|
||||
event->selection.target = target;
|
||||
event->selection.property = _gdk_win32_selection_atom (GDK_WIN32_ATOM_INDEX_GDK_SELECTION);
|
||||
event->selection.requestor = gdk_win32_handle_table_lookup (msg->hwnd);
|
||||
event->selection.time = msg->time;
|
||||
property_change_data = g_new0 (STGMEDIUM, 1);
|
||||
win32_sel->property_change_data = property_change_data;
|
||||
win32_sel->property_change_format = msg->wParam;
|
||||
win32_sel->property_change_target_atom = target;
|
||||
|
||||
fixup_event (event);
|
||||
GDK_NOTE (EVENTS, g_print (" (calling _gdk_event_emit)"));
|
||||
GDK_NOTE (EVENTS, _gdk_win32_print_event (event));
|
||||
_gdk_event_emit (event);
|
||||
gdk_event_free (event);
|
||||
win32_sel->property_change_format = 0;
|
||||
|
||||
/* Now the clipboard owner should have rendered */
|
||||
if (!property_change_data->hGlobal)
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_print (" (no _delayed_rendering_data?)"));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The requestor is holding the clipboard, no
|
||||
* OpenClipboard() is required/possible
|
||||
*/
|
||||
GDK_NOTE (DND,
|
||||
g_print (" SetClipboardData(%s,%p)",
|
||||
_gdk_win32_cf_to_string (msg->wParam),
|
||||
property_change_data->hGlobal));
|
||||
|
||||
API_CALL (SetClipboardData, (msg->wParam, property_change_data->hGlobal));
|
||||
}
|
||||
|
||||
g_clear_pointer (&property_change_data, g_free);
|
||||
*ret_valp = 0;
|
||||
return_val = TRUE;
|
||||
break;
|
||||
|
||||
case WM_RENDERALLFORMATS:
|
||||
*ret_valp = 0;
|
||||
return_val = TRUE;
|
||||
|
||||
win32_sel = _gdk_win32_selection_get ();
|
||||
|
||||
if (API_CALL (OpenClipboard, (msg->hwnd)))
|
||||
{
|
||||
for (target = NULL, i = 0;
|
||||
i < win32_sel->clipboard_selection_targets->len;
|
||||
i++)
|
||||
{
|
||||
GdkSelTargetFormat target_format = g_array_index (win32_sel->clipboard_selection_targets, GdkSelTargetFormat, i);
|
||||
if (target_format.format != 0)
|
||||
SendMessage (msg->hwnd, WM_RENDERFORMAT, target_format.format, 0);
|
||||
}
|
||||
|
||||
API_CALL (CloseClipboard, ());
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_ACTIVATE:
|
||||
GDK_NOTE (EVENTS, g_print (" %s%s %p",
|
||||
(LOWORD (msg->wParam) == WA_ACTIVE ? "ACTIVE" :
|
||||
@ -3968,19 +3834,9 @@ gdk_event_dispatch (GSource *source,
|
||||
|
||||
if (event)
|
||||
{
|
||||
GdkWin32Selection *sel_win32 = _gdk_win32_selection_get ();
|
||||
|
||||
_gdk_event_emit (event);
|
||||
|
||||
gdk_event_free (event);
|
||||
|
||||
/* Do drag & drop if it is still pending */
|
||||
if (sel_win32->dnd_source_state == GDK_WIN32_DND_PENDING)
|
||||
{
|
||||
sel_win32->dnd_source_state = GDK_WIN32_DND_DRAGGING;
|
||||
_gdk_win32_dnd_do_dragdrop ();
|
||||
sel_win32->dnd_source_state = GDK_WIN32_DND_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -48,5 +48,7 @@ gint _gdk_max_colors = 0;
|
||||
GdkWin32ModalOpKind _modal_operation_in_progress = GDK_WIN32_MODAL_OP_NONE;
|
||||
HWND _modal_move_resize_window = NULL;
|
||||
|
||||
/* The singleton selection object pointer */
|
||||
GdkWin32Selection *_win32_selection = NULL;
|
||||
/* The singleton clipdrop object pointer */
|
||||
GdkWin32Clipdrop *_win32_clipdrop = NULL;
|
||||
|
||||
GThread *_win32_main_thread = NULL;
|
403
gdk/win32/gdkhdataoutputstream-win32.c
Normal file
403
gdk/win32/gdkhdataoutputstream-win32.c
Normal file
@ -0,0 +1,403 @@
|
||||
/* GDK HData Output Stream - a stream backed by a global memory buffer
|
||||
*
|
||||
* Copyright (C) 2018 Руслан Ижбулатов
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Руслан Ижбулатов <lrn1986@gmail.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "gdkprivate-win32.h"
|
||||
#include "gdkhdataoutputstream-win32.h"
|
||||
|
||||
#include "gdkclipboard-win32.h"
|
||||
#include "gdkdisplay-win32.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkwin32display.h"
|
||||
#include "gdkwin32surface.h"
|
||||
|
||||
#include "gdkinternals.h"
|
||||
|
||||
typedef struct _GdkWin32HDataOutputStreamPrivate GdkWin32HDataOutputStreamPrivate;
|
||||
|
||||
struct _GdkWin32HDataOutputStreamPrivate
|
||||
{
|
||||
HANDLE handle;
|
||||
guchar *data;
|
||||
gsize data_allocated_size;
|
||||
gsize data_length;
|
||||
GdkWin32ContentFormatPair pair;
|
||||
guint handle_is_buffer : 1;
|
||||
guint closed : 1;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GdkWin32HDataOutputStream, gdk_win32_hdata_output_stream, G_TYPE_OUTPUT_STREAM);
|
||||
|
||||
static gssize
|
||||
write_stream (GdkWin32HDataOutputStream *stream,
|
||||
GdkWin32HDataOutputStreamPrivate *priv,
|
||||
const void *buffer,
|
||||
gsize count,
|
||||
GError **error)
|
||||
{
|
||||
gsize spillover = (priv->data_length + count) - priv->data_allocated_size;
|
||||
gsize to_copy = count;
|
||||
|
||||
if (priv->closed)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("writing a closed stream"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spillover > 0 && !priv->handle_is_buffer)
|
||||
{
|
||||
guchar *new_data;
|
||||
HANDLE new_handle = GlobalReAlloc (priv->handle, priv->data_allocated_size + spillover, 0);
|
||||
|
||||
if (new_handle != NULL)
|
||||
{
|
||||
new_data = g_try_realloc (priv->data, priv->data_allocated_size + spillover);
|
||||
|
||||
if (new_data != NULL)
|
||||
{
|
||||
priv->handle = new_handle;
|
||||
priv->data = new_data;
|
||||
priv->data_allocated_size += spillover;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("g_try_realloc () failed"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD error_code = GetLastError ();
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"%s%lu", _("GlobalReAlloc() failed: "), error_code);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->handle_is_buffer)
|
||||
{
|
||||
to_copy = MIN (count, priv->data_allocated_size - priv->data_length);
|
||||
|
||||
if (to_copy == 0)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("Ran out of buffer space (buffer size is fixed)"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy (&((guchar *) priv->handle)[priv->data_length], buffer, to_copy);
|
||||
}
|
||||
else
|
||||
memcpy (&priv->data[priv->data_length], buffer, to_copy);
|
||||
|
||||
priv->data_length += to_copy;
|
||||
|
||||
return to_copy;
|
||||
}
|
||||
|
||||
static gssize
|
||||
gdk_win32_hdata_output_stream_write (GOutputStream *output_stream,
|
||||
const void *buffer,
|
||||
gsize count,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GdkWin32HDataOutputStream *stream = GDK_WIN32_HDATA_OUTPUT_STREAM (output_stream);
|
||||
GdkWin32HDataOutputStreamPrivate *priv = gdk_win32_hdata_output_stream_get_instance_private (stream);
|
||||
gssize result = write_stream (stream, priv, buffer, count, error);
|
||||
|
||||
if (result != -1)
|
||||
GDK_NOTE(SELECTION, g_printerr ("CLIPBOARD: wrote %zd bytes, %u total now\n",
|
||||
result, priv->data_length));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_hdata_output_stream_write_async (GOutputStream *output_stream,
|
||||
const void *buffer,
|
||||
gsize count,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkWin32HDataOutputStream *stream = GDK_WIN32_HDATA_OUTPUT_STREAM (output_stream);
|
||||
GdkWin32HDataOutputStreamPrivate *priv = gdk_win32_hdata_output_stream_get_instance_private (stream);
|
||||
GTask *task;
|
||||
gssize result;
|
||||
GError *error = NULL;
|
||||
|
||||
task = g_task_new (stream, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, gdk_win32_hdata_output_stream_write_async);
|
||||
g_task_set_priority (task, io_priority);
|
||||
|
||||
result = write_stream (stream, priv, buffer, count, &error);
|
||||
|
||||
if (result != -1)
|
||||
{
|
||||
GDK_NOTE (SELECTION, g_printerr ("CLIPBOARD async wrote %zd bytes, %u total now\n",
|
||||
result, priv->data_length));
|
||||
g_task_return_int (task, result);
|
||||
}
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
|
||||
g_object_unref (task);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static gssize
|
||||
gdk_win32_hdata_output_stream_write_finish (GOutputStream *stream,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, stream), -1);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_win32_hdata_output_stream_write_async, -1);
|
||||
|
||||
return g_task_propagate_int (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_hdata_output_stream_close (GOutputStream *output_stream,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GdkWin32HDataOutputStream *stream = GDK_WIN32_HDATA_OUTPUT_STREAM (output_stream);
|
||||
GdkWin32HDataOutputStreamPrivate *priv = gdk_win32_hdata_output_stream_get_instance_private (stream);
|
||||
guchar *hdata;
|
||||
|
||||
if (priv->closed)
|
||||
return TRUE;
|
||||
|
||||
if (priv->pair.transmute)
|
||||
{
|
||||
guchar *transmuted_data = NULL;
|
||||
gint transmuted_data_length;
|
||||
|
||||
if (priv->handle_is_buffer)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("Can't transmute a single handle"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!_gdk_win32_transmute_contentformat (priv->pair.contentformat,
|
||||
priv->pair.w32format,
|
||||
priv->data,
|
||||
priv->data_length,
|
||||
&transmuted_data,
|
||||
&transmuted_data_length))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("Failed to transmute %zu bytes of data from %s to %u"),
|
||||
priv->data_length,
|
||||
priv->pair.contentformat,
|
||||
priv->pair.w32format);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
HANDLE new_handle;
|
||||
|
||||
new_handle = GlobalReAlloc (priv->handle, transmuted_data_length, 0);
|
||||
|
||||
if (new_handle == NULL)
|
||||
{
|
||||
DWORD error_code = GetLastError ();
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"%s%lu", _("GlobalReAlloc() failed: "), error_code);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
priv->handle = new_handle;
|
||||
priv->data_length = transmuted_data_length;
|
||||
g_clear_pointer (&priv->data, g_free);
|
||||
priv->data = transmuted_data;
|
||||
}
|
||||
}
|
||||
|
||||
if (!priv->handle_is_buffer)
|
||||
{
|
||||
hdata = GlobalLock (priv->handle);
|
||||
|
||||
if (hdata == NULL)
|
||||
{
|
||||
DWORD error_code = GetLastError ();
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"%s%lu", _("GlobalLock() failed: "), error_code);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy (hdata, priv->data, priv->data_length);
|
||||
GlobalUnlock (priv->handle);
|
||||
g_clear_pointer (&priv->data, g_free);
|
||||
}
|
||||
|
||||
priv->closed = 1;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_hdata_output_stream_close_async (GOutputStream *stream,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
GError *error = NULL;
|
||||
|
||||
task = g_task_new (stream, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, gdk_win32_hdata_output_stream_close_async);
|
||||
g_task_set_priority (task, io_priority);
|
||||
|
||||
if (gdk_win32_hdata_output_stream_close (stream, NULL, &error))
|
||||
g_task_return_boolean (task, TRUE);
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_hdata_output_stream_close_finish (GOutputStream *stream,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
|
||||
g_return_val_if_fail (g_async_result_is_tagged (result, gdk_win32_hdata_output_stream_close_async), FALSE);
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_hdata_output_stream_finalize (GObject *object)
|
||||
{
|
||||
GdkWin32HDataOutputStream *stream = GDK_WIN32_HDATA_OUTPUT_STREAM (object);
|
||||
GdkWin32HDataOutputStreamPrivate *priv = gdk_win32_hdata_output_stream_get_instance_private (stream);
|
||||
|
||||
g_clear_pointer (&priv->data, g_free);
|
||||
|
||||
/* We deliberately don't close the memory object,
|
||||
* as it will be used elsewhere (it's a shame that
|
||||
* MS global memory handles are not refcounted and
|
||||
* not duplicateable).
|
||||
* Except when the stream isn't closed, which means
|
||||
* that the caller never bothered to get the handle.
|
||||
*/
|
||||
if (!priv->closed && priv->handle)
|
||||
{
|
||||
if (_gdk_win32_format_uses_hdata (priv->pair.w32format))
|
||||
GlobalFree (priv->handle);
|
||||
else
|
||||
CloseHandle (priv->handle);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gdk_win32_hdata_output_stream_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_hdata_output_stream_class_init (GdkWin32HDataOutputStreamClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GOutputStreamClass *output_stream_class = G_OUTPUT_STREAM_CLASS (klass);
|
||||
|
||||
object_class->finalize = gdk_win32_hdata_output_stream_finalize;
|
||||
|
||||
output_stream_class->write_fn = gdk_win32_hdata_output_stream_write;
|
||||
output_stream_class->close_fn = gdk_win32_hdata_output_stream_close;
|
||||
|
||||
output_stream_class->write_async = gdk_win32_hdata_output_stream_write_async;
|
||||
output_stream_class->write_finish = gdk_win32_hdata_output_stream_write_finish;
|
||||
output_stream_class->close_async = gdk_win32_hdata_output_stream_close_async;
|
||||
output_stream_class->close_finish = gdk_win32_hdata_output_stream_close_finish;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_hdata_output_stream_init (GdkWin32HDataOutputStream *stream)
|
||||
{
|
||||
GdkWin32HDataOutputStreamPrivate *priv = gdk_win32_hdata_output_stream_get_instance_private (stream);
|
||||
}
|
||||
|
||||
GOutputStream *
|
||||
gdk_win32_hdata_output_stream_new (GdkWin32ContentFormatPair *pair,
|
||||
GError **error)
|
||||
{
|
||||
GdkWin32HDataOutputStream *stream;
|
||||
GdkWin32HDataOutputStreamPrivate *priv;
|
||||
HANDLE handle;
|
||||
gboolean hmem;
|
||||
|
||||
hmem = _gdk_win32_format_uses_hdata (pair->w32format);
|
||||
|
||||
if (hmem)
|
||||
{
|
||||
handle = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, 0);
|
||||
|
||||
if (handle == NULL)
|
||||
{
|
||||
DWORD error_code = GetLastError ();
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"%s%lu", _("GlobalAlloc() failed: "), error_code);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
stream = g_object_new (GDK_TYPE_WIN32_HDATA_OUTPUT_STREAM, NULL);
|
||||
priv = gdk_win32_hdata_output_stream_get_instance_private (stream);
|
||||
priv->pair = *pair;
|
||||
|
||||
if (hmem)
|
||||
{
|
||||
priv->handle = handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->data_allocated_size = sizeof (priv->handle);
|
||||
priv->handle_is_buffer = 1;
|
||||
}
|
||||
|
||||
return G_OUTPUT_STREAM (stream);
|
||||
}
|
||||
|
||||
HANDLE
|
||||
gdk_win32_hdata_output_stream_get_handle (GdkWin32HDataOutputStream *stream,
|
||||
gboolean *is_hdata)
|
||||
{
|
||||
GdkWin32HDataOutputStreamPrivate *priv;
|
||||
priv = gdk_win32_hdata_output_stream_get_instance_private (stream);
|
||||
|
||||
if (!priv->closed)
|
||||
return NULL;
|
||||
|
||||
if (is_hdata)
|
||||
*is_hdata = _gdk_win32_format_uses_hdata (priv->pair.w32format);
|
||||
|
||||
return priv->handle;
|
||||
}
|
63
gdk/win32/gdkhdataoutputstream-win32.h
Normal file
63
gdk/win32/gdkhdataoutputstream-win32.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* GIO - GLib Output, Output and Streaming Library
|
||||
*
|
||||
* Copyright (C) 2017 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Benjamin Otte <otte@gnome.org>
|
||||
* Christian Kellner <gicmo@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GDK_WIN32_HDATA_OUTPUT_STREAM_H__
|
||||
#define __GDK_WIN32_HDATA_OUTPUT_STREAM_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include "gdktypes.h"
|
||||
#include "gdkclipdrop-win32.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_WIN32_HDATA_OUTPUT_STREAM (gdk_win32_hdata_output_stream_get_type ())
|
||||
#define GDK_WIN32_HDATA_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_WIN32_HDATA_OUTPUT_STREAM, GdkWin32HDataOutputStream))
|
||||
#define GDK_WIN32_HDATA_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDK_TYPE_WIN32_HDATA_OUTPUT_STREAM, GdkWin32HDataOutputStreamClass))
|
||||
#define GDK_IS_WIN32_HDATA_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_WIN32_HDATA_OUTPUT_STREAM))
|
||||
#define GDK_IS_WIN32_HDATA_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDK_TYPE_WIN32_HDATA_OUTPUT_STREAM))
|
||||
#define GDK_WIN32_HDATA_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_WIN32_HDATA_OUTPUT_STREAM, GdkWin32HDataOutputStreamClass))
|
||||
|
||||
typedef struct GdkWin32HDataOutputStream GdkWin32HDataOutputStream;
|
||||
typedef struct GdkWin32HDataOutputStreamClass GdkWin32HDataOutputStreamClass;
|
||||
|
||||
typedef void (* GdkWin32HDataOutputHandler) (GOutputStream *stream, GdkWin32ContentFormatPair pair, gpointer user_data);
|
||||
|
||||
struct GdkWin32HDataOutputStream
|
||||
{
|
||||
GOutputStream parent_instance;
|
||||
};
|
||||
|
||||
struct GdkWin32HDataOutputStreamClass
|
||||
{
|
||||
GOutputStreamClass parent_class;
|
||||
};
|
||||
|
||||
GType gdk_win32_hdata_output_stream_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GOutputStream *gdk_win32_hdata_output_stream_new (GdkWin32ContentFormatPair *pair,
|
||||
GError **error);
|
||||
|
||||
HANDLE gdk_win32_hdata_output_stream_get_handle (GdkWin32HDataOutputStream *stream,
|
||||
gboolean *is_hdata);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_WIN32_HDATA_OUTPUT_STREAM_H__ */
|
@ -91,7 +91,7 @@ _gdk_win32_surfaceing_init (void)
|
||||
GDK_NOTE (EVENTS, g_print ("input_locale:%p, codepage:%d\n",
|
||||
_gdk_input_locale, _gdk_input_codepage));
|
||||
|
||||
_gdk_win32_selection_init ();
|
||||
_gdk_win32_clipdrop_init ();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -40,7 +40,8 @@
|
||||
#include <gdk/win32/gdkwin32screen.h>
|
||||
#include <gdk/win32/gdkwin32keys.h>
|
||||
#include <gdk/win32/gdkdevicemanager-win32.h>
|
||||
#include <gdk/win32/gdkselection-win32.h>
|
||||
#include <gdk/win32/gdkclipdrop-win32.h>
|
||||
//#include <gdk/win32/gdkselection-win32.h>
|
||||
|
||||
#include "gdkinternals.h"
|
||||
|
||||
@ -282,8 +283,11 @@ extern UINT _gdk_input_codepage;
|
||||
|
||||
extern guint _gdk_keymap_serial;
|
||||
|
||||
/* The singleton selection object pointer */
|
||||
GdkWin32Selection *_win32_selection;
|
||||
/* The singleton clipdrop object pointer */
|
||||
GdkWin32Clipdrop *_win32_clipdrop;
|
||||
|
||||
/* Used to identify the main thread */
|
||||
GThread *_win32_main_thread;
|
||||
|
||||
void _gdk_win32_dnd_do_dragdrop (void);
|
||||
void _gdk_win32_ole2_dnd_property_change (GdkAtom type,
|
||||
@ -412,11 +416,11 @@ void _gdk_win32_display_create_surface_impl (GdkDisplay *display,
|
||||
/* stray GdkSurfaceImplWin32 members */
|
||||
void _gdk_win32_surface_register_dnd (GdkSurface *window);
|
||||
GdkDragContext *_gdk_win32_surface_drag_begin (GdkSurface *window,
|
||||
GdkDevice *device,
|
||||
GdkContentFormats *formats,
|
||||
GdkDragAction actions,
|
||||
gint x_root,
|
||||
gint y_root);
|
||||
GdkDevice *device,
|
||||
GdkContentProvider *content,
|
||||
GdkDragAction actions,
|
||||
gint x_root,
|
||||
gint y_root);
|
||||
|
||||
/* Stray GdkWin32Screen members */
|
||||
gboolean _gdk_win32_get_setting (const gchar *name, GValue *value);
|
||||
@ -458,7 +462,8 @@ BOOL WINAPI GtkShowWindow (GdkSurface *window,
|
||||
|
||||
/* Initialization */
|
||||
void _gdk_win32_surfaceing_init (void);
|
||||
void _gdk_dnd_init (void);
|
||||
void _gdk_drag_init (void);
|
||||
void _gdk_drop_init (void);
|
||||
void _gdk_events_init (GdkDisplay *display);
|
||||
|
||||
#endif /* __GDK_PRIVATE_WIN32_H__ */
|
||||
|
@ -26,6 +26,16 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GdkWin32DragContextUtilityData GdkWin32DragContextUtilityData;
|
||||
|
||||
struct _GdkWin32DragContextUtilityData
|
||||
{
|
||||
gint last_x; /* Coordinates from last event, in GDK space */
|
||||
gint last_y;
|
||||
DWORD last_key_state; /* Key state from last event */
|
||||
GdkWin32DndState state;
|
||||
};
|
||||
|
||||
struct _GdkWin32DragContext
|
||||
{
|
||||
GdkDragContext context;
|
||||
@ -36,23 +46,16 @@ struct _GdkWin32DragContext
|
||||
GdkDragAction actions;
|
||||
GdkDragAction current_action;
|
||||
|
||||
GdkWin32DragContextUtilityData util_data;
|
||||
|
||||
guint scale; /* Temporarily caches the HiDPI scale */
|
||||
gint hot_x; /* Hotspot offset from the top-left of the drag-window, scaled (can be added to GDK space coordinates) */
|
||||
gint hot_y;
|
||||
gint start_x; /* Coordinates of the drag start, in GDK space */
|
||||
gint start_y;
|
||||
|
||||
guint drag_status : 4; /* Current status of drag */
|
||||
guint drop_failed : 1; /* Whether the drop was unsuccessful */
|
||||
guint has_image_format : 1;
|
||||
|
||||
guint scale; /* Temporarily caches the HiDPI scale */
|
||||
gint hot_x; /* Hotspot offset from the top-left of the drag-window, scaled (can be added to GDK space coordinates) */
|
||||
gint hot_y;
|
||||
gint last_x; /* Coordinates from last event, in GDK space */
|
||||
gint last_y;
|
||||
gint start_x; /* Coordinates of the drag start, in GDK space */
|
||||
gint start_y;
|
||||
DWORD last_key_state; /* Key state from last event */
|
||||
|
||||
/* Just like context->targets, but an array, and with format IDs
|
||||
* stored inside.
|
||||
*/
|
||||
GArray *droptarget_format_target_map;
|
||||
};
|
||||
|
||||
struct _GdkWin32DragContextClass
|
||||
@ -60,6 +63,52 @@ struct _GdkWin32DragContextClass
|
||||
GdkDragContextClass parent_class;
|
||||
};
|
||||
|
||||
struct _GdkWin32DropContext
|
||||
{
|
||||
GdkDragContext context;
|
||||
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 */
|
||||
|
||||
/* Just like context->formats, but an array, and with format IDs
|
||||
* stored inside.
|
||||
*/
|
||||
GArray *droptarget_w32format_contentformat_map;
|
||||
|
||||
GdkWin32DragContext *local_source_context;
|
||||
|
||||
guint drag_status : 4; /* Current status of drag */
|
||||
guint drop_failed : 1; /* Whether the drop was unsuccessful */
|
||||
};
|
||||
|
||||
struct _GdkWin32DropContextClass
|
||||
{
|
||||
GdkDragContextClass parent_class;
|
||||
};
|
||||
|
||||
gpointer _gdk_win32_dnd_thread_main (gpointer data);
|
||||
|
||||
GdkDragContext *_gdk_win32_find_source_context_for_dest_surface (GdkSurface *dest_surface);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_WIN32_DND_PRIVATE_H__ */
|
||||
|
@ -43,6 +43,23 @@ 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__ */
|
||||
|
@ -1,22 +1,25 @@
|
||||
gdk_win32_sources = files([
|
||||
'gdkcursor-win32.c',
|
||||
'gdkclipboard-win32.c',
|
||||
'gdkclipdrop-win32.c',
|
||||
'gdkdevicemanager-win32.c',
|
||||
'gdkdevice-virtual.c',
|
||||
'gdkdevice-win32.c',
|
||||
'gdkdevice-wintab.c',
|
||||
'gdkdisplay-win32.c',
|
||||
'gdkdisplaymanager-win32.c',
|
||||
'gdkdnd-win32.c',
|
||||
'gdkdrag-win32.c',
|
||||
'gdkdrop-win32.c',
|
||||
'gdkevents-win32.c',
|
||||
'gdkgeometry-win32.c',
|
||||
'gdkglcontext-win32.c',
|
||||
'gdkglobals-win32.c',
|
||||
'gdkhdataoutputstream-win32.c',
|
||||
'gdkkeys-win32.c',
|
||||
'gdkmain-win32.c',
|
||||
'gdkmonitor-win32.c',
|
||||
'gdkproperty-win32.c',
|
||||
'gdkscreen-win32.c',
|
||||
'gdkselection-win32.c',
|
||||
'gdkvulkancontext-win32.c',
|
||||
'gdkwin32cursor.h',
|
||||
'gdkwin32display.h',
|
||||
|
Loading…
Reference in New Issue
Block a user