Compare commits
10 Commits
fix_toolti
...
wip/cherge
Author | SHA1 | Date | |
---|---|---|---|
|
f76ccf5a40 | ||
|
ee9000212c | ||
|
96690acd6a | ||
|
a674417000 | ||
|
40933bb28c | ||
|
1acc2ccca1 | ||
|
f8cab84406 | ||
|
b8ae8ccf63 | ||
|
87d5b6f69b | ||
|
daa4263965 |
@@ -696,4 +696,24 @@
|
|||||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)draggingSession:(NSDraggingSession *)session
|
||||||
|
endedAtPoint:(NSPoint)screenPoint
|
||||||
|
operation:(NSDragOperation)operation
|
||||||
|
{
|
||||||
|
NSInteger sequence = [session draggingSequenceNumber];
|
||||||
|
GdkMacosDisplay *display = [self gdkDisplay];
|
||||||
|
GdkDrag *drag = _gdk_macos_display_find_drag (display, sequence);
|
||||||
|
gboolean success = operation != NSDragOperationNone;
|
||||||
|
|
||||||
|
if (drag == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_print ("Dragging session ended!: success=%d\n", success);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_ERROR);
|
||||||
|
else
|
||||||
|
g_signal_emit_by_name (drag, "dnd-finished");
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@@ -29,7 +29,9 @@
|
|||||||
#import "GdkMacosWindow.h"
|
#import "GdkMacosWindow.h"
|
||||||
|
|
||||||
#include "gdkmacosdisplay-private.h"
|
#include "gdkmacosdisplay-private.h"
|
||||||
|
#include "gdkmacosdrop-private.h"
|
||||||
#include "gdkmacosmonitor-private.h"
|
#include "gdkmacosmonitor-private.h"
|
||||||
|
#include "gdkmacospasteboard-private.h"
|
||||||
#include "gdkmacossurface-private.h"
|
#include "gdkmacossurface-private.h"
|
||||||
#include "gdkmacospopupsurface-private.h"
|
#include "gdkmacospopupsurface-private.h"
|
||||||
#include "gdkmacostoplevelsurface-private.h"
|
#include "gdkmacostoplevelsurface-private.h"
|
||||||
@@ -287,6 +289,9 @@ typedef NSString *CALayerContentsGravity;
|
|||||||
[self setContentView:view];
|
[self setContentView:view];
|
||||||
[view release];
|
[view release];
|
||||||
|
|
||||||
|
/* TODO: We might want to make this more extensible at some point */
|
||||||
|
_gdk_macos_pasteboard_register_drag_types (self);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -597,25 +602,86 @@ typedef NSString *CALayerContentsGravity;
|
|||||||
|
|
||||||
-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
|
-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
|
||||||
{
|
{
|
||||||
|
NSPoint location = [sender draggingLocation];
|
||||||
|
NSDragOperation ret;
|
||||||
|
GdkMacosDrop *drop;
|
||||||
|
|
||||||
|
if (!(drop = _gdk_macos_drop_new ([self gdkSurface], sender)))
|
||||||
return NSDragOperationNone;
|
return NSDragOperationNone;
|
||||||
|
|
||||||
|
_gdk_macos_display_set_drop ([self gdkDisplay],
|
||||||
|
[sender draggingSequenceNumber],
|
||||||
|
GDK_DROP (drop));
|
||||||
|
|
||||||
|
gdk_drop_emit_enter_event (GDK_DROP (drop),
|
||||||
|
TRUE,
|
||||||
|
location.x,
|
||||||
|
GDK_SURFACE (gdk_surface)->height - location.y,
|
||||||
|
GDK_CURRENT_TIME);
|
||||||
|
|
||||||
|
ret = _gdk_macos_drop_operation (drop);
|
||||||
|
|
||||||
|
g_object_unref (drop);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)draggingEnded:(id <NSDraggingInfo>)sender
|
-(void)draggingEnded:(id <NSDraggingInfo>)sender
|
||||||
{
|
{
|
||||||
|
_gdk_macos_display_set_drop ([self gdkDisplay], [sender draggingSequenceNumber], NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)draggingExited:(id <NSDraggingInfo>)sender
|
-(void)draggingExited:(id <NSDraggingInfo>)sender
|
||||||
{
|
{
|
||||||
|
NSInteger sequence_number = [sender draggingSequenceNumber];
|
||||||
|
GdkDrop *drop = _gdk_macos_display_find_drop ([self gdkDisplay], sequence_number);
|
||||||
|
|
||||||
|
if (drop != NULL)
|
||||||
|
gdk_drop_emit_leave_event (drop, TRUE, GDK_CURRENT_TIME);
|
||||||
|
|
||||||
|
_gdk_macos_display_set_drop ([self gdkDisplay], sequence_number, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
|
-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
|
||||||
{
|
{
|
||||||
|
NSInteger sequence_number = [sender draggingSequenceNumber];
|
||||||
|
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
|
||||||
|
GdkDrop *drop = _gdk_macos_display_find_drop (GDK_MACOS_DISPLAY (display), sequence_number);
|
||||||
|
NSPoint location = [sender draggingLocation];
|
||||||
|
|
||||||
|
if (drop == NULL)
|
||||||
return NSDragOperationNone;
|
return NSDragOperationNone;
|
||||||
|
|
||||||
|
_gdk_macos_drop_update_actions (GDK_MACOS_DROP (drop), sender);
|
||||||
|
|
||||||
|
gdk_drop_emit_motion_event (drop,
|
||||||
|
TRUE,
|
||||||
|
location.x,
|
||||||
|
GDK_SURFACE (gdk_surface)->height - location.y,
|
||||||
|
GDK_CURRENT_TIME);
|
||||||
|
|
||||||
|
return _gdk_macos_drop_operation (GDK_MACOS_DROP (drop));
|
||||||
}
|
}
|
||||||
|
|
||||||
-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
|
-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
|
||||||
{
|
{
|
||||||
return YES;
|
NSInteger sequence_number = [sender draggingSequenceNumber];
|
||||||
|
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
|
||||||
|
GdkDrop *drop = _gdk_macos_display_find_drop (GDK_MACOS_DISPLAY (display), sequence_number);
|
||||||
|
NSPoint location = [sender draggingLocation];
|
||||||
|
|
||||||
|
if (drop == NULL)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
gdk_drop_emit_drop_event (drop,
|
||||||
|
TRUE,
|
||||||
|
location.x,
|
||||||
|
GDK_SURFACE (gdk_surface)->height - location.y,
|
||||||
|
GDK_CURRENT_TIME);
|
||||||
|
|
||||||
|
gdk_drop_emit_leave_event (drop, TRUE, GDK_CURRENT_TIME);
|
||||||
|
|
||||||
|
return GDK_MACOS_DROP (drop)->finish_action != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
-(BOOL)wantsPeriodicDraggingUpdates
|
-(BOOL)wantsPeriodicDraggingUpdates
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "gdkclipboardprivate.h"
|
#include "gdkclipboardprivate.h"
|
||||||
#include "gdkmacosdisplay-private.h"
|
#include "gdkmacosdisplay-private.h"
|
||||||
|
#include "gdkmacospasteboard-private.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@@ -40,18 +41,7 @@ void _gdk_macos_clipboard_check_externally_modified (GdkMacosClipbo
|
|||||||
NSPasteboardType _gdk_macos_clipboard_to_ns_type (const char *mime_type,
|
NSPasteboardType _gdk_macos_clipboard_to_ns_type (const char *mime_type,
|
||||||
NSPasteboardType *alternate);
|
NSPasteboardType *alternate);
|
||||||
const char *_gdk_macos_clipboard_from_ns_type (NSPasteboardType ns_type);
|
const char *_gdk_macos_clipboard_from_ns_type (NSPasteboardType ns_type);
|
||||||
|
void _gdk_macos_clipboard_register_drag_types (NSWindow *window);
|
||||||
@interface GdkMacosClipboardDataProvider : NSObject <NSPasteboardItemDataProvider>
|
|
||||||
{
|
|
||||||
GCancellable *cancellable;
|
|
||||||
GdkClipboard *clipboard;
|
|
||||||
char **mimeTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
-(id)initClipboard:(GdkClipboard *)gdkClipboard mimetypes:(const char * const *)mime_types;
|
|
||||||
-(NSArray<NSPasteboardType> *)types;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
#include "gdkmacosclipboard-private.h"
|
#include "gdkmacosclipboard-private.h"
|
||||||
|
#include "gdkmacospasteboard-private.h"
|
||||||
#include "gdkmacosutils-private.h"
|
#include "gdkmacosutils-private.h"
|
||||||
#include "gdk-private.h"
|
#include "gdk-private.h"
|
||||||
|
|
||||||
@@ -32,165 +33,8 @@ struct _GdkMacosClipboard
|
|||||||
NSInteger last_change_count;
|
NSInteger last_change_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
GMemoryOutputStream *stream;
|
|
||||||
NSPasteboardItem *item;
|
|
||||||
NSPasteboardType type;
|
|
||||||
GMainContext *main_context;
|
|
||||||
guint done : 1;
|
|
||||||
} WriteRequest;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
TYPE_STRING,
|
|
||||||
TYPE_PBOARD,
|
|
||||||
TYPE_URL,
|
|
||||||
TYPE_FILE_URL,
|
|
||||||
TYPE_COLOR,
|
|
||||||
TYPE_TIFF,
|
|
||||||
TYPE_PNG,
|
|
||||||
TYPE_LAST
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PTYPE(k) (get_pasteboard_type(TYPE_##k))
|
|
||||||
|
|
||||||
static NSPasteboardType pasteboard_types[TYPE_LAST];
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK_TYPE_CLIPBOARD)
|
G_DEFINE_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK_TYPE_CLIPBOARD)
|
||||||
|
|
||||||
static NSPasteboardType
|
|
||||||
get_pasteboard_type (int type)
|
|
||||||
{
|
|
||||||
static gsize initialized = FALSE;
|
|
||||||
|
|
||||||
g_assert (type >= 0);
|
|
||||||
g_assert (type < TYPE_LAST);
|
|
||||||
|
|
||||||
if (g_once_init_enter (&initialized))
|
|
||||||
{
|
|
||||||
pasteboard_types[TYPE_PNG] = NSPasteboardTypePNG;
|
|
||||||
pasteboard_types[TYPE_STRING] = NSPasteboardTypeString;
|
|
||||||
pasteboard_types[TYPE_TIFF] = NSPasteboardTypeTIFF;
|
|
||||||
pasteboard_types[TYPE_COLOR] = NSPasteboardTypeColor;
|
|
||||||
|
|
||||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
|
||||||
pasteboard_types[TYPE_PBOARD] = NSStringPboardType;
|
|
||||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
|
||||||
|
|
||||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER
|
|
||||||
pasteboard_types[TYPE_URL] = NSPasteboardTypeURL;
|
|
||||||
pasteboard_types[TYPE_FILE_URL] = NSPasteboardTypeFileURL;
|
|
||||||
#else
|
|
||||||
pasteboard_types[TYPE_URL] = [[NSString alloc] initWithUTF8String:"public.url"];
|
|
||||||
pasteboard_types[TYPE_FILE_URL] = [[NSString alloc] initWithUTF8String:"public.file-url"];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
g_once_init_leave (&initialized, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pasteboard_types[type];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_request_free (WriteRequest *wr)
|
|
||||||
{
|
|
||||||
g_clear_pointer (&wr->main_context, g_main_context_unref);
|
|
||||||
g_clear_object (&wr->stream);
|
|
||||||
[wr->item release];
|
|
||||||
g_slice_free (WriteRequest, wr);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
_gdk_macos_clipboard_from_ns_type (NSPasteboardType type)
|
|
||||||
{
|
|
||||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
|
||||||
|
|
||||||
if ([type isEqualToString:PTYPE(STRING)] ||
|
|
||||||
[type isEqualToString:PTYPE(PBOARD)])
|
|
||||||
return g_intern_string ("text/plain;charset=utf-8");
|
|
||||||
else if ([type isEqualToString:PTYPE(URL)] ||
|
|
||||||
[type isEqualToString:PTYPE(FILE_URL)])
|
|
||||||
return g_intern_string ("text/uri-list");
|
|
||||||
else if ([type isEqualToString:PTYPE(COLOR)])
|
|
||||||
return g_intern_string ("application/x-color");
|
|
||||||
else if ([type isEqualToString:PTYPE(TIFF)])
|
|
||||||
return g_intern_string ("image/tiff");
|
|
||||||
else if ([type isEqualToString:PTYPE(PNG)])
|
|
||||||
return g_intern_string ("image/png");
|
|
||||||
|
|
||||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSPasteboardType
|
|
||||||
_gdk_macos_clipboard_to_ns_type (const char *mime_type,
|
|
||||||
NSPasteboardType *alternate)
|
|
||||||
{
|
|
||||||
if (alternate)
|
|
||||||
*alternate = NULL;
|
|
||||||
|
|
||||||
if (g_strcmp0 (mime_type, "text/plain;charset=utf-8") == 0)
|
|
||||||
{
|
|
||||||
return PTYPE(STRING);
|
|
||||||
}
|
|
||||||
else if (g_strcmp0 (mime_type, "text/uri-list") == 0)
|
|
||||||
{
|
|
||||||
if (alternate)
|
|
||||||
*alternate = PTYPE(URL);
|
|
||||||
return PTYPE(FILE_URL);
|
|
||||||
}
|
|
||||||
else if (g_strcmp0 (mime_type, "application/x-color") == 0)
|
|
||||||
{
|
|
||||||
return PTYPE(COLOR);
|
|
||||||
}
|
|
||||||
else if (g_strcmp0 (mime_type, "image/tiff") == 0)
|
|
||||||
{
|
|
||||||
return PTYPE(TIFF);
|
|
||||||
}
|
|
||||||
else if (g_strcmp0 (mime_type, "image/png") == 0)
|
|
||||||
{
|
|
||||||
return PTYPE(PNG);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
populate_content_formats (GdkContentFormatsBuilder *builder,
|
|
||||||
NSPasteboardType type)
|
|
||||||
{
|
|
||||||
const char *mime_type;
|
|
||||||
|
|
||||||
g_return_if_fail (builder != NULL);
|
|
||||||
g_return_if_fail (type != NULL);
|
|
||||||
|
|
||||||
mime_type = _gdk_macos_clipboard_from_ns_type (type);
|
|
||||||
|
|
||||||
if (mime_type != NULL)
|
|
||||||
gdk_content_formats_builder_add_mime_type (builder, mime_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GdkContentFormats *
|
|
||||||
load_offer_formats (GdkMacosClipboard *self)
|
|
||||||
{
|
|
||||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
|
||||||
|
|
||||||
GdkContentFormatsBuilder *builder;
|
|
||||||
GdkContentFormats *formats;
|
|
||||||
|
|
||||||
g_assert (GDK_IS_MACOS_CLIPBOARD (self));
|
|
||||||
|
|
||||||
builder = gdk_content_formats_builder_new ();
|
|
||||||
for (NSPasteboardType type in [self->pasteboard types])
|
|
||||||
populate_content_formats (builder, type);
|
|
||||||
formats = gdk_content_formats_builder_free_to_formats (builder);
|
|
||||||
|
|
||||||
GDK_END_MACOS_ALLOC_POOL;
|
|
||||||
|
|
||||||
return g_steal_pointer (&formats);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_gdk_macos_clipboard_load_contents (GdkMacosClipboard *self)
|
_gdk_macos_clipboard_load_contents (GdkMacosClipboard *self)
|
||||||
{
|
{
|
||||||
@@ -201,22 +45,13 @@ _gdk_macos_clipboard_load_contents (GdkMacosClipboard *self)
|
|||||||
|
|
||||||
change_count = [self->pasteboard changeCount];
|
change_count = [self->pasteboard changeCount];
|
||||||
|
|
||||||
formats = load_offer_formats (self);
|
formats = _gdk_macos_pasteboard_load_formats (self->pasteboard);
|
||||||
gdk_clipboard_claim_remote (GDK_CLIPBOARD (self), formats);
|
gdk_clipboard_claim_remote (GDK_CLIPBOARD (self), formats);
|
||||||
gdk_content_formats_unref (formats);
|
gdk_content_formats_unref (formats);
|
||||||
|
|
||||||
self->last_change_count = change_count;
|
self->last_change_count = change_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GInputStream *
|
|
||||||
create_stream_from_nsdata (NSData *data)
|
|
||||||
{
|
|
||||||
const guint8 *bytes = [data bytes];
|
|
||||||
gsize len = [data length];
|
|
||||||
|
|
||||||
return g_memory_input_stream_new_from_data (g_memdup2 (bytes, len), len, g_free);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_gdk_macos_clipboard_read_async (GdkClipboard *clipboard,
|
_gdk_macos_clipboard_read_async (GdkClipboard *clipboard,
|
||||||
GdkContentFormats *formats,
|
GdkContentFormats *formats,
|
||||||
@@ -225,125 +60,13 @@ _gdk_macos_clipboard_read_async (GdkClipboard *clipboard,
|
|||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
_gdk_macos_pasteboard_read_async (G_OBJECT (clipboard),
|
||||||
|
GDK_MACOS_CLIPBOARD (clipboard)->pasteboard,
|
||||||
GdkMacosClipboard *self = (GdkMacosClipboard *)clipboard;
|
formats,
|
||||||
GdkContentFormats *offer_formats = NULL;
|
io_priority,
|
||||||
const char *mime_type;
|
cancellable,
|
||||||
GInputStream *stream = NULL;
|
callback,
|
||||||
GTask *task = NULL;
|
user_data);
|
||||||
|
|
||||||
g_assert (GDK_IS_MACOS_CLIPBOARD (self));
|
|
||||||
g_assert (formats != NULL);
|
|
||||||
|
|
||||||
task = g_task_new (self, cancellable, callback, user_data);
|
|
||||||
g_task_set_source_tag (task, _gdk_macos_clipboard_read_async);
|
|
||||||
g_task_set_priority (task, io_priority);
|
|
||||||
|
|
||||||
offer_formats = load_offer_formats (GDK_MACOS_CLIPBOARD (clipboard));
|
|
||||||
mime_type = gdk_content_formats_match_mime_type (formats, offer_formats);
|
|
||||||
|
|
||||||
if (mime_type == NULL)
|
|
||||||
{
|
|
||||||
g_task_return_new_error (task,
|
|
||||||
G_IO_ERROR,
|
|
||||||
G_IO_ERROR_NOT_SUPPORTED,
|
|
||||||
"%s",
|
|
||||||
_("No compatible transfer format found"));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp (mime_type, "text/plain;charset=utf-8") == 0)
|
|
||||||
{
|
|
||||||
NSString *nsstr = [self->pasteboard stringForType:NSPasteboardTypeString];
|
|
||||||
|
|
||||||
if (nsstr != NULL)
|
|
||||||
{
|
|
||||||
const char *str = [nsstr UTF8String];
|
|
||||||
stream = g_memory_input_stream_new_from_data (g_strdup (str),
|
|
||||||
strlen (str) + 1,
|
|
||||||
g_free);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strcmp (mime_type, "text/uri-list") == 0)
|
|
||||||
{
|
|
||||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
|
||||||
|
|
||||||
if ([[self->pasteboard types] containsObject:PTYPE(FILE_URL)])
|
|
||||||
{
|
|
||||||
GString *str = g_string_new (NULL);
|
|
||||||
NSArray *files = [self->pasteboard propertyListForType:NSFilenamesPboardType];
|
|
||||||
gsize n_files = [files count];
|
|
||||||
char *data;
|
|
||||||
guint len;
|
|
||||||
|
|
||||||
for (gsize i = 0; i < n_files; ++i)
|
|
||||||
{
|
|
||||||
NSString* uriString = [files objectAtIndex:i];
|
|
||||||
uriString = [@"file://" stringByAppendingString:uriString];
|
|
||||||
uriString = [uriString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
|
||||||
|
|
||||||
g_string_append_printf (str,
|
|
||||||
"%s\r\n",
|
|
||||||
[uriString cStringUsingEncoding:NSUTF8StringEncoding]);
|
|
||||||
}
|
|
||||||
|
|
||||||
len = str->len;
|
|
||||||
data = g_string_free (str, FALSE);
|
|
||||||
stream = g_memory_input_stream_new_from_data (data, len, g_free);
|
|
||||||
}
|
|
||||||
|
|
||||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
|
||||||
}
|
|
||||||
else if (strcmp (mime_type, "application/x-color") == 0)
|
|
||||||
{
|
|
||||||
NSColorSpace *colorspace;
|
|
||||||
NSColor *nscolor;
|
|
||||||
guint16 color[4];
|
|
||||||
|
|
||||||
colorspace = [NSColorSpace genericRGBColorSpace];
|
|
||||||
nscolor = [[NSColor colorFromPasteboard:self->pasteboard]
|
|
||||||
colorUsingColorSpace:colorspace];
|
|
||||||
|
|
||||||
color[0] = 0xffff * [nscolor redComponent];
|
|
||||||
color[1] = 0xffff * [nscolor greenComponent];
|
|
||||||
color[2] = 0xffff * [nscolor blueComponent];
|
|
||||||
color[3] = 0xffff * [nscolor alphaComponent];
|
|
||||||
|
|
||||||
stream = g_memory_input_stream_new_from_data (g_memdup2 (&color, sizeof color),
|
|
||||||
sizeof color,
|
|
||||||
g_free);
|
|
||||||
}
|
|
||||||
else if (strcmp (mime_type, "image/tiff") == 0)
|
|
||||||
{
|
|
||||||
NSData *data = [self->pasteboard dataForType:PTYPE(TIFF)];
|
|
||||||
stream = create_stream_from_nsdata (data);
|
|
||||||
}
|
|
||||||
else if (strcmp (mime_type, "image/png") == 0)
|
|
||||||
{
|
|
||||||
NSData *data = [self->pasteboard dataForType:PTYPE(PNG)];
|
|
||||||
stream = create_stream_from_nsdata (data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stream != NULL)
|
|
||||||
{
|
|
||||||
g_task_set_task_data (task, g_strdup (mime_type), g_free);
|
|
||||||
g_task_return_pointer (task, g_steal_pointer (&stream), g_object_unref);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_task_return_new_error (task,
|
|
||||||
G_IO_ERROR,
|
|
||||||
G_IO_ERROR_FAILED,
|
|
||||||
_("Failed to decode contents with mime-type of '%s'"),
|
|
||||||
mime_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
g_clear_object (&task);
|
|
||||||
g_clear_pointer (&offer_formats, gdk_content_formats_unref);
|
|
||||||
|
|
||||||
GDK_END_MACOS_ALLOC_POOL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GInputStream *
|
static GInputStream *
|
||||||
@@ -352,49 +75,33 @@ _gdk_macos_clipboard_read_finish (GdkClipboard *clipboard,
|
|||||||
const char **out_mime_type,
|
const char **out_mime_type,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GTask *task = (GTask *)result;
|
return _gdk_macos_pasteboard_read_finish (G_OBJECT (clipboard), result, out_mime_type, error);
|
||||||
|
|
||||||
g_assert (GDK_IS_MACOS_CLIPBOARD (clipboard));
|
|
||||||
g_assert (G_IS_TASK (task));
|
|
||||||
|
|
||||||
if (out_mime_type != NULL)
|
|
||||||
*out_mime_type = g_strdup (g_task_get_task_data (task));
|
|
||||||
|
|
||||||
return g_task_propagate_pointer (task, error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_gdk_macos_clipboard_send_to_pasteboard (GdkMacosClipboard *self,
|
_gdk_macos_clipboard_send_to_pasteboard (GdkMacosClipboard *self,
|
||||||
GdkContentProvider *content)
|
GdkContentProvider *content)
|
||||||
{
|
{
|
||||||
|
GdkMacosPasteboardItem *item;
|
||||||
|
NSArray<NSPasteboardItem *> *items;
|
||||||
|
|
||||||
|
g_assert (GDK_IS_MACOS_CLIPBOARD (self));
|
||||||
|
g_assert (GDK_IS_CONTENT_PROVIDER (content));
|
||||||
|
|
||||||
|
if (self->pasteboard == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||||
|
|
||||||
GdkMacosClipboardDataProvider *dataProvider;
|
item = [[GdkMacosPasteboardItem alloc] initForClipboard:GDK_CLIPBOARD (self) withContentProvider:content];
|
||||||
GdkContentFormats *serializable;
|
items = [NSArray arrayWithObject:item];
|
||||||
NSPasteboardItem *item;
|
|
||||||
const char * const *mime_types;
|
|
||||||
gsize n_mime_types;
|
|
||||||
|
|
||||||
g_return_if_fail (GDK_IS_MACOS_CLIPBOARD (self));
|
|
||||||
g_return_if_fail (GDK_IS_CONTENT_PROVIDER (content));
|
|
||||||
|
|
||||||
serializable = gdk_content_provider_ref_storable_formats (content);
|
|
||||||
serializable = gdk_content_formats_union_serialize_mime_types (serializable);
|
|
||||||
mime_types = gdk_content_formats_get_mime_types (serializable, &n_mime_types);
|
|
||||||
|
|
||||||
dataProvider = [[GdkMacosClipboardDataProvider alloc] initClipboard:GDK_CLIPBOARD (self)
|
|
||||||
mimetypes:mime_types];
|
|
||||||
item = [[NSPasteboardItem alloc] init];
|
|
||||||
[item setDataProvider:dataProvider forTypes:[dataProvider types]];
|
|
||||||
|
|
||||||
[self->pasteboard clearContents];
|
[self->pasteboard clearContents];
|
||||||
if ([self->pasteboard writeObjects:[NSArray arrayWithObject:item]] == NO)
|
if ([self->pasteboard writeObjects:items] == NO)
|
||||||
g_warning ("Failed to write object to pasteboard");
|
g_warning ("Failed to send clipboard to pasteboard");
|
||||||
|
|
||||||
self->last_change_count = [self->pasteboard changeCount];
|
self->last_change_count = [self->pasteboard changeCount];
|
||||||
|
|
||||||
g_clear_pointer (&serializable, gdk_content_formats_unref);
|
|
||||||
|
|
||||||
GDK_END_MACOS_ALLOC_POOL;
|
GDK_END_MACOS_ALLOC_POOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,139 +194,3 @@ _gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self)
|
|||||||
if ([self->pasteboard changeCount] != self->last_change_count)
|
if ([self->pasteboard changeCount] != self->last_change_count)
|
||||||
_gdk_macos_clipboard_load_contents (self);
|
_gdk_macos_clipboard_load_contents (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@implementation GdkMacosClipboardDataProvider
|
|
||||||
|
|
||||||
-(id)initClipboard:(GdkClipboard *)gdkClipboard mimetypes:(const char * const *)mime_types;
|
|
||||||
{
|
|
||||||
[super init];
|
|
||||||
|
|
||||||
self->mimeTypes = g_strdupv ((char **)mime_types);
|
|
||||||
self->clipboard = g_object_ref (gdkClipboard);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
-(void)dealloc
|
|
||||||
{
|
|
||||||
g_cancellable_cancel (self->cancellable);
|
|
||||||
|
|
||||||
g_clear_pointer (&self->mimeTypes, g_strfreev);
|
|
||||||
g_clear_object (&self->clipboard);
|
|
||||||
g_clear_object (&self->cancellable);
|
|
||||||
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
-(void)pasteboardFinishedWithDataProvider:(NSPasteboard *)pasteboard
|
|
||||||
{
|
|
||||||
g_clear_object (&self->clipboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
-(NSArray<NSPasteboardType> *)types
|
|
||||||
{
|
|
||||||
NSMutableArray *ret = [[NSMutableArray alloc] init];
|
|
||||||
|
|
||||||
for (guint i = 0; self->mimeTypes[i]; i++)
|
|
||||||
{
|
|
||||||
const char *mime_type = self->mimeTypes[i];
|
|
||||||
NSPasteboardType type;
|
|
||||||
NSPasteboardType alternate = nil;
|
|
||||||
|
|
||||||
if ((type = _gdk_macos_clipboard_to_ns_type (mime_type, &alternate)))
|
|
||||||
{
|
|
||||||
[ret addObject:type];
|
|
||||||
if (alternate)
|
|
||||||
[ret addObject:alternate];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return g_steal_pointer (&ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_data_ready_cb (GObject *object,
|
|
||||||
GAsyncResult *result,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
|
||||||
|
|
||||||
GdkClipboard *clipboard = (GdkClipboard *)object;
|
|
||||||
WriteRequest *wr = user_data;
|
|
||||||
GError *error = NULL;
|
|
||||||
NSData *data = nil;
|
|
||||||
|
|
||||||
g_assert (GDK_IS_CLIPBOARD (clipboard));
|
|
||||||
g_assert (G_IS_ASYNC_RESULT (result));
|
|
||||||
g_assert (wr != NULL);
|
|
||||||
g_assert (G_IS_MEMORY_OUTPUT_STREAM (wr->stream));
|
|
||||||
g_assert ([wr->item isKindOfClass:[NSPasteboardItem class]]);
|
|
||||||
|
|
||||||
if (gdk_clipboard_write_finish (clipboard, result, &error))
|
|
||||||
{
|
|
||||||
gsize size;
|
|
||||||
gpointer bytes;
|
|
||||||
|
|
||||||
g_output_stream_close (G_OUTPUT_STREAM (wr->stream), NULL, NULL);
|
|
||||||
|
|
||||||
size = g_memory_output_stream_get_size (wr->stream);
|
|
||||||
bytes = g_memory_output_stream_steal_data (wr->stream);
|
|
||||||
data = [[NSData alloc] initWithBytesNoCopy:bytes
|
|
||||||
length:size
|
|
||||||
deallocator:^(void *alloc, NSUInteger length) { g_free (alloc); }];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_warning ("Failed to serialize clipboard contents: %s",
|
|
||||||
error->message);
|
|
||||||
g_clear_error (&error);
|
|
||||||
}
|
|
||||||
|
|
||||||
[wr->item setData:data forType:wr->type];
|
|
||||||
|
|
||||||
wr->done = TRUE;
|
|
||||||
|
|
||||||
GDK_END_MACOS_ALLOC_POOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
-(void) pasteboard:(NSPasteboard *)pasteboard
|
|
||||||
item:(NSPasteboardItem *)item
|
|
||||||
provideDataForType:(NSPasteboardType)type
|
|
||||||
{
|
|
||||||
const char *mime_type = _gdk_macos_clipboard_from_ns_type (type);
|
|
||||||
GMainContext *main_context = g_main_context_default ();
|
|
||||||
WriteRequest *wr;
|
|
||||||
|
|
||||||
if (self->clipboard == NULL || mime_type == NULL)
|
|
||||||
{
|
|
||||||
[item setData:[NSData data] forType:type];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wr = g_slice_new0 (WriteRequest);
|
|
||||||
wr->item = [item retain];
|
|
||||||
wr->stream = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new_resizable ());
|
|
||||||
wr->type = type;
|
|
||||||
wr->main_context = g_main_context_ref (main_context);
|
|
||||||
wr->done = FALSE;
|
|
||||||
|
|
||||||
gdk_clipboard_write_async (self->clipboard,
|
|
||||||
mime_type,
|
|
||||||
G_OUTPUT_STREAM (wr->stream),
|
|
||||||
G_PRIORITY_DEFAULT,
|
|
||||||
self->cancellable,
|
|
||||||
on_data_ready_cb,
|
|
||||||
wr);
|
|
||||||
|
|
||||||
/* We're forced to provide data synchronously via this API
|
|
||||||
* so we must block on the main loop. Using another main loop
|
|
||||||
* than the default tends to get us locked up here, so that is
|
|
||||||
* what we'll do for now.
|
|
||||||
*/
|
|
||||||
while (!wr->done)
|
|
||||||
g_main_context_iteration (wr->main_context, TRUE);
|
|
||||||
|
|
||||||
write_request_free (wr);
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
@@ -81,6 +81,10 @@ struct _GdkMacosDisplay
|
|||||||
/* The surface that is receiving keyboard events */
|
/* The surface that is receiving keyboard events */
|
||||||
GdkMacosSurface *keyboard_surface;
|
GdkMacosSurface *keyboard_surface;
|
||||||
|
|
||||||
|
/* [NSDraggingInfo draggingSequenceNumber] to GdkMacosDr(ag,op) */
|
||||||
|
GHashTable *active_drags;
|
||||||
|
GHashTable *active_drops;
|
||||||
|
|
||||||
/* Used to translate from quartz coordinate space to GDK */
|
/* Used to translate from quartz coordinate space to GDK */
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
@@ -160,6 +164,16 @@ void _gdk_macos_display_warp_pointer (GdkMacosDisp
|
|||||||
int x,
|
int x,
|
||||||
int y);
|
int y);
|
||||||
NSEvent *_gdk_macos_display_get_nsevent (GdkEvent *event);
|
NSEvent *_gdk_macos_display_get_nsevent (GdkEvent *event);
|
||||||
|
GdkDrag *_gdk_macos_display_find_drag (GdkMacosDisplay *self,
|
||||||
|
NSInteger sequence_number);
|
||||||
|
GdkDrop *_gdk_macos_display_find_drop (GdkMacosDisplay *self,
|
||||||
|
NSInteger sequence_number);
|
||||||
|
void _gdk_macos_display_set_drag (GdkMacosDisplay *self,
|
||||||
|
NSInteger sequence_number,
|
||||||
|
GdkDrag *drag);
|
||||||
|
void _gdk_macos_display_set_drop (GdkMacosDisplay *self,
|
||||||
|
NSInteger sequence_number,
|
||||||
|
GdkDrop *drop);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@@ -788,6 +788,9 @@ get_surface_from_ns_event (GdkMacosDisplay *self,
|
|||||||
NSRect view_frame;
|
NSRect view_frame;
|
||||||
|
|
||||||
view = (GdkMacosBaseView *)[nswindow contentView];
|
view = (GdkMacosBaseView *)[nswindow contentView];
|
||||||
|
if (!GDK_IS_MACOS_BASE_VIEW (view))
|
||||||
|
goto find_under_pointer;
|
||||||
|
|
||||||
surface = GDK_SURFACE ([view gdkSurface]);
|
surface = GDK_SURFACE ([view gdkSurface]);
|
||||||
|
|
||||||
point = [nsevent locationInWindow];
|
point = [nsevent locationInWindow];
|
||||||
@@ -846,6 +849,8 @@ get_surface_from_ns_event (GdkMacosDisplay *self,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
find_under_pointer:
|
||||||
|
|
||||||
if (!surface)
|
if (!surface)
|
||||||
{
|
{
|
||||||
/* Fallback used when no NSSurface set. This happens e.g. when
|
/* Fallback used when no NSSurface set. This happens e.g. when
|
||||||
@@ -864,7 +869,11 @@ get_surface_from_ns_event (GdkMacosDisplay *self,
|
|||||||
static GdkMacosSurface *
|
static GdkMacosSurface *
|
||||||
find_surface_for_keyboard_event (NSEvent *nsevent)
|
find_surface_for_keyboard_event (NSEvent *nsevent)
|
||||||
{
|
{
|
||||||
GdkMacosBaseView *view = (GdkMacosBaseView *)[[nsevent window] contentView];
|
NSView *nsview = [[nsevent window] contentView];
|
||||||
|
|
||||||
|
if (GDK_IS_MACOS_BASE_VIEW (nsview))
|
||||||
|
{
|
||||||
|
GdkMacosBaseView *view = (GdkMacosBaseView *)nsview;
|
||||||
GdkSurface *surface = GDK_SURFACE ([view gdkSurface]);
|
GdkSurface *surface = GDK_SURFACE ([view gdkSurface]);
|
||||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||||
GdkSeat *seat = gdk_display_get_default_seat (display);
|
GdkSeat *seat = gdk_display_get_default_seat (display);
|
||||||
@@ -875,6 +884,9 @@ find_surface_for_keyboard_event (NSEvent *nsevent)
|
|||||||
return GDK_MACOS_SURFACE (grab->surface);
|
return GDK_MACOS_SURFACE (grab->surface);
|
||||||
|
|
||||||
return GDK_MACOS_SURFACE (surface);
|
return GDK_MACOS_SURFACE (surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GdkMacosSurface *
|
static GdkMacosSurface *
|
||||||
@@ -1090,7 +1102,8 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
|
|||||||
if (!(surface = find_surface_for_ns_event (self, nsevent, &x, &y)))
|
if (!(surface = find_surface_for_ns_event (self, nsevent, &x, &y)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!(window = (GdkMacosWindow *)_gdk_macos_surface_get_native (surface)))
|
if (!(window = (GdkMacosWindow *)_gdk_macos_surface_get_native (surface)) ||
|
||||||
|
!GDK_IS_MACOS_WINDOW (window))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Ignore events and break grabs while the window is being
|
/* Ignore events and break grabs while the window is being
|
||||||
|
@@ -31,6 +31,8 @@
|
|||||||
#include "gdkmacoscairocontext-private.h"
|
#include "gdkmacoscairocontext-private.h"
|
||||||
#include "gdkmacoseventsource-private.h"
|
#include "gdkmacoseventsource-private.h"
|
||||||
#include "gdkmacosdisplay-private.h"
|
#include "gdkmacosdisplay-private.h"
|
||||||
|
#include "gdkmacosdrag-private.h"
|
||||||
|
#include "gdkmacosdrop-private.h"
|
||||||
#include "gdkmacosglcontext-private.h"
|
#include "gdkmacosglcontext-private.h"
|
||||||
#include "gdkmacoskeymap-private.h"
|
#include "gdkmacoskeymap-private.h"
|
||||||
#include "gdkmacosmonitor-private.h"
|
#include "gdkmacosmonitor-private.h"
|
||||||
@@ -663,6 +665,8 @@ gdk_macos_display_finalize (GObject *object)
|
|||||||
CFSTR ("NSUserDefaultsDidChangeNotification"),
|
CFSTR ("NSUserDefaultsDidChangeNotification"),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
g_clear_pointer (&self->active_drags, g_hash_table_unref);
|
||||||
|
g_clear_pointer (&self->active_drops, g_hash_table_unref);
|
||||||
g_clear_object (&GDK_DISPLAY (self)->clipboard);
|
g_clear_object (&GDK_DISPLAY (self)->clipboard);
|
||||||
g_clear_pointer (&self->frame_source, g_source_unref);
|
g_clear_pointer (&self->frame_source, g_source_unref);
|
||||||
g_clear_object (&self->monitors);
|
g_clear_object (&self->monitors);
|
||||||
@@ -701,6 +705,8 @@ static void
|
|||||||
gdk_macos_display_init (GdkMacosDisplay *self)
|
gdk_macos_display_init (GdkMacosDisplay *self)
|
||||||
{
|
{
|
||||||
self->monitors = g_list_store_new (GDK_TYPE_MONITOR);
|
self->monitors = g_list_store_new (GDK_TYPE_MONITOR);
|
||||||
|
self->active_drags = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
|
||||||
|
self->active_drops = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
|
||||||
|
|
||||||
gdk_display_set_composited (GDK_DISPLAY (self), TRUE);
|
gdk_display_set_composited (GDK_DISPLAY (self), TRUE);
|
||||||
gdk_display_set_input_shapes (GDK_DISPLAY (self), FALSE);
|
gdk_display_set_input_shapes (GDK_DISPLAY (self), FALSE);
|
||||||
@@ -1113,3 +1119,55 @@ _gdk_macos_display_get_nsevent (GdkEvent *event)
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GdkDrag *
|
||||||
|
_gdk_macos_display_find_drag (GdkMacosDisplay *self,
|
||||||
|
NSInteger sequence_number)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), NULL);
|
||||||
|
|
||||||
|
return g_hash_table_lookup (self->active_drags, GSIZE_TO_POINTER (sequence_number));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gdk_macos_display_set_drag (GdkMacosDisplay *self,
|
||||||
|
NSInteger sequence_number,
|
||||||
|
GdkDrag *drag)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
|
||||||
|
g_return_if_fail (!drag || GDK_IS_MACOS_DRAG (drag));
|
||||||
|
|
||||||
|
if (drag)
|
||||||
|
g_hash_table_insert (self->active_drags,
|
||||||
|
GSIZE_TO_POINTER (sequence_number),
|
||||||
|
g_object_ref (drag));
|
||||||
|
else
|
||||||
|
g_hash_table_remove (self->active_drags,
|
||||||
|
GSIZE_TO_POINTER (sequence_number));
|
||||||
|
}
|
||||||
|
|
||||||
|
GdkDrop *
|
||||||
|
_gdk_macos_display_find_drop (GdkMacosDisplay *self,
|
||||||
|
NSInteger sequence_number)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), NULL);
|
||||||
|
|
||||||
|
return g_hash_table_lookup (self->active_drops, GSIZE_TO_POINTER (sequence_number));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gdk_macos_display_set_drop (GdkMacosDisplay *self,
|
||||||
|
NSInteger sequence_number,
|
||||||
|
GdkDrop *drop)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
|
||||||
|
g_return_if_fail (!drop || GDK_IS_MACOS_DROP (drop));
|
||||||
|
|
||||||
|
if (drop)
|
||||||
|
g_hash_table_insert (self->active_drops,
|
||||||
|
GSIZE_TO_POINTER (sequence_number),
|
||||||
|
g_object_ref (drop));
|
||||||
|
else
|
||||||
|
g_hash_table_remove (self->active_drops,
|
||||||
|
GSIZE_TO_POINTER (sequence_number));
|
||||||
|
}
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
#include "gdkdragprivate.h"
|
#include "gdkdragprivate.h"
|
||||||
|
|
||||||
#include "gdkmacosdragsurface-private.h"
|
#include "gdkmacosdragsurface-private.h"
|
||||||
|
#include "gdkmacospasteboard-private.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@@ -44,6 +45,8 @@ struct _GdkMacosDrag
|
|||||||
GdkSeat *drag_seat;
|
GdkSeat *drag_seat;
|
||||||
GdkCursor *cursor;
|
GdkCursor *cursor;
|
||||||
|
|
||||||
|
NSInteger sequence;
|
||||||
|
|
||||||
int hot_x;
|
int hot_x;
|
||||||
int hot_y;
|
int hot_y;
|
||||||
|
|
||||||
@@ -63,7 +66,11 @@ struct _GdkMacosDragClass
|
|||||||
};
|
};
|
||||||
|
|
||||||
GType gdk_macos_drag_get_type (void) G_GNUC_CONST;
|
GType gdk_macos_drag_get_type (void) G_GNUC_CONST;
|
||||||
gboolean _gdk_macos_drag_begin (GdkMacosDrag *self);
|
gboolean _gdk_macos_drag_begin (GdkMacosDrag *self,
|
||||||
|
GdkContentProvider *provider,
|
||||||
|
NSWindow *window,
|
||||||
|
double quartz_x,
|
||||||
|
double quartz_y);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@@ -49,6 +49,17 @@ enum {
|
|||||||
|
|
||||||
static GParamSpec *properties [N_PROPS];
|
static GParamSpec *properties [N_PROPS];
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_macos_drag_drop_from_display (GdkMacosDrag *self)
|
||||||
|
{
|
||||||
|
GdkDisplay *display;
|
||||||
|
|
||||||
|
g_assert (GDK_IS_MACOS_DRAG (self));
|
||||||
|
|
||||||
|
display = gdk_drag_get_display (GDK_DRAG (self));
|
||||||
|
_gdk_macos_display_set_drag (GDK_MACOS_DISPLAY (display), self->sequence, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
ease_out_cubic (double t)
|
ease_out_cubic (double t)
|
||||||
{
|
{
|
||||||
@@ -81,12 +92,12 @@ gdk_macos_zoomback_timeout (gpointer data)
|
|||||||
frame_clock = zb->frame_clock;
|
frame_clock = zb->frame_clock;
|
||||||
|
|
||||||
if (!frame_clock)
|
if (!frame_clock)
|
||||||
return G_SOURCE_REMOVE;
|
goto hide_surface;
|
||||||
|
|
||||||
current_time = gdk_frame_clock_get_frame_time (frame_clock);
|
current_time = gdk_frame_clock_get_frame_time (frame_clock);
|
||||||
f = (current_time - zb->start_time) / (double) ANIM_TIME;
|
f = (current_time - zb->start_time) / (double) ANIM_TIME;
|
||||||
if (f >= 1.0)
|
if (f >= 1.0)
|
||||||
return G_SOURCE_REMOVE;
|
goto hide_surface;
|
||||||
|
|
||||||
t = ease_out_cubic (f);
|
t = ease_out_cubic (f);
|
||||||
|
|
||||||
@@ -101,6 +112,11 @@ gdk_macos_zoomback_timeout (gpointer data)
|
|||||||
_gdk_macos_surface_show (GDK_MACOS_SURFACE (drag->drag_surface));
|
_gdk_macos_surface_show (GDK_MACOS_SURFACE (drag->drag_surface));
|
||||||
|
|
||||||
return G_SOURCE_CONTINUE;
|
return G_SOURCE_CONTINUE;
|
||||||
|
|
||||||
|
hide_surface:
|
||||||
|
gdk_surface_hide (GDK_SURFACE (drag->drag_surface));
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GdkSurface *
|
static GdkSurface *
|
||||||
@@ -142,6 +158,8 @@ gdk_macos_drag_drop_done (GdkDrag *drag,
|
|||||||
|
|
||||||
g_assert (GDK_IS_MACOS_DRAG (self));
|
g_assert (GDK_IS_MACOS_DRAG (self));
|
||||||
|
|
||||||
|
g_print ("Drop done! success=%d\n", success);
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
gdk_surface_hide (GDK_SURFACE (self->drag_surface));
|
gdk_surface_hide (GDK_SURFACE (self->drag_surface));
|
||||||
@@ -231,20 +249,8 @@ gdk_macos_drag_cancel (GdkDrag *drag,
|
|||||||
|
|
||||||
self->cancelled = TRUE;
|
self->cancelled = TRUE;
|
||||||
drag_ungrab (self);
|
drag_ungrab (self);
|
||||||
gdk_drag_drop_done (drag, FALSE);
|
gdk_surface_hide (GDK_SURFACE (self->drag_surface));
|
||||||
}
|
gdk_macos_drag_drop_from_display (self);
|
||||||
|
|
||||||
static void
|
|
||||||
gdk_macos_drag_drop_performed (GdkDrag *drag,
|
|
||||||
guint32 time)
|
|
||||||
{
|
|
||||||
GdkMacosDrag *self = (GdkMacosDrag *)drag;
|
|
||||||
|
|
||||||
g_assert (GDK_IS_MACOS_DRAG (self));
|
|
||||||
|
|
||||||
drag_ungrab (self);
|
|
||||||
g_signal_emit_by_name (drag, "dnd-finished");
|
|
||||||
gdk_drag_drop_done (drag, TRUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -326,12 +332,10 @@ gdk_drag_update (GdkDrag *drag,
|
|||||||
&suggested_action,
|
&suggested_action,
|
||||||
&possible_actions);
|
&possible_actions);
|
||||||
|
|
||||||
_gdk_macos_drag_surface_drag_motion (self->drag_surface,
|
if (GDK_IS_MACOS_SURFACE (self->drag_surface))
|
||||||
|
_gdk_macos_surface_move (GDK_MACOS_SURFACE (self->drag_surface),
|
||||||
x_root - self->hot_x,
|
x_root - self->hot_x,
|
||||||
y_root - self->hot_y,
|
y_root - self->hot_y);
|
||||||
suggested_action,
|
|
||||||
possible_actions,
|
|
||||||
evtime);
|
|
||||||
|
|
||||||
if (!self->did_update)
|
if (!self->did_update)
|
||||||
{
|
{
|
||||||
@@ -339,6 +343,8 @@ gdk_drag_update (GdkDrag *drag,
|
|||||||
self->start_y = self->last_y;
|
self->start_y = self->last_y;
|
||||||
self->did_update = TRUE;
|
self->did_update = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gdk_drag_set_actions (drag, possible_actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -503,6 +509,9 @@ gdk_macos_drag_handle_event (GdkDrag *drag,
|
|||||||
g_assert (GDK_IS_MACOS_DRAG (drag));
|
g_assert (GDK_IS_MACOS_DRAG (drag));
|
||||||
g_assert (event != NULL);
|
g_assert (event != NULL);
|
||||||
|
|
||||||
|
if (GDK_MACOS_DRAG (drag)->cancelled)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
switch ((guint) event->event_type)
|
switch ((guint) event->event_type)
|
||||||
{
|
{
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
@@ -523,6 +532,12 @@ gdk_macos_drag_handle_event (GdkDrag *drag,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_macos_drag_dnd_finished (GdkDrag *drag)
|
||||||
|
{
|
||||||
|
gdk_macos_drag_drop_from_display (GDK_MACOS_DRAG (drag));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gdk_macos_drag_finalize (GObject *object)
|
gdk_macos_drag_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
@@ -591,8 +606,8 @@ gdk_macos_drag_class_init (GdkMacosDragClass *klass)
|
|||||||
drag_class->drop_done = gdk_macos_drag_drop_done;
|
drag_class->drop_done = gdk_macos_drag_drop_done;
|
||||||
drag_class->set_cursor = gdk_macos_drag_set_cursor;
|
drag_class->set_cursor = gdk_macos_drag_set_cursor;
|
||||||
drag_class->cancel = gdk_macos_drag_cancel;
|
drag_class->cancel = gdk_macos_drag_cancel;
|
||||||
drag_class->drop_performed = gdk_macos_drag_drop_performed;
|
|
||||||
drag_class->handle_event = gdk_macos_drag_handle_event;
|
drag_class->handle_event = gdk_macos_drag_handle_event;
|
||||||
|
drag_class->dnd_finished = gdk_macos_drag_dnd_finished;
|
||||||
|
|
||||||
properties [PROP_DRAG_SURFACE] =
|
properties [PROP_DRAG_SURFACE] =
|
||||||
g_param_spec_object ("drag-surface",
|
g_param_spec_object ("drag-surface",
|
||||||
@@ -610,11 +625,57 @@ gdk_macos_drag_init (GdkMacosDrag *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_gdk_macos_drag_begin (GdkMacosDrag *self)
|
_gdk_macos_drag_begin (GdkMacosDrag *self,
|
||||||
|
GdkContentProvider *content,
|
||||||
|
NSWindow *window,
|
||||||
|
double quartz_x,
|
||||||
|
double quartz_y)
|
||||||
{
|
{
|
||||||
|
NSArray<NSDraggingItem *> *items;
|
||||||
|
NSDraggingSession *session;
|
||||||
|
NSPasteboardItem *item;
|
||||||
|
NSTimeInterval nstime;
|
||||||
|
NSEvent *nsevent;
|
||||||
|
|
||||||
g_return_val_if_fail (GDK_IS_MACOS_DRAG (self), FALSE);
|
g_return_val_if_fail (GDK_IS_MACOS_DRAG (self), FALSE);
|
||||||
|
|
||||||
|
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||||
|
|
||||||
|
item = [[GdkMacosPasteboardItem alloc] initForDrag:GDK_DRAG (self) withContentProvider:content];
|
||||||
|
items = [NSArray arrayWithObject:item];
|
||||||
|
|
||||||
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||||
|
nstime = [[NSDate dateWithTimeIntervalSince1970: (gint64)time / 1000L] timeIntervalSinceReferenceDate];
|
||||||
|
nsevent = [NSEvent mouseEventWithType: NSEventTypeLeftMouseDown
|
||||||
|
location: NSMakePoint (quartz_x, quartz_y)
|
||||||
|
modifierFlags: 0
|
||||||
|
timestamp: nstime
|
||||||
|
windowNumber: [window windowNumber]
|
||||||
|
context: [window graphicsContext]
|
||||||
|
eventNumber: 0
|
||||||
|
clickCount: 1
|
||||||
|
pressure: 0.0];
|
||||||
|
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||||
|
|
||||||
|
session = [[window contentView] beginDraggingSessionWithItems:items
|
||||||
|
event:nsevent
|
||||||
|
source:[window contentView]];
|
||||||
|
self->sequence = [session draggingSequenceNumber];
|
||||||
|
|
||||||
|
GDK_END_MACOS_ALLOC_POOL;
|
||||||
|
|
||||||
|
gdk_surface_hide (GDK_SURFACE (self->drag_surface));
|
||||||
|
#if 0
|
||||||
_gdk_macos_surface_show (GDK_MACOS_SURFACE (self->drag_surface));
|
_gdk_macos_surface_show (GDK_MACOS_SURFACE (self->drag_surface));
|
||||||
|
|
||||||
return drag_grab (self);
|
if (drag_grab (self))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
_gdk_macos_display_set_drag (GDK_MACOS_DISPLAY (gdk_drag_get_display (GDK_DRAG (self))),
|
||||||
|
self->sequence,
|
||||||
|
GDK_DRAG (self));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//return FALSE;
|
||||||
}
|
}
|
||||||
|
@@ -38,12 +38,6 @@ GdkMacosSurface *_gdk_macos_drag_surface_new (GdkMacosDisplay *display,
|
|||||||
int y,
|
int y,
|
||||||
int width,
|
int width,
|
||||||
int height);
|
int height);
|
||||||
void _gdk_macos_drag_surface_drag_motion (GdkMacosDragSurface *self,
|
|
||||||
int x_root,
|
|
||||||
int y_root,
|
|
||||||
GdkDragAction suggested_action,
|
|
||||||
GdkDragAction possible_actions,
|
|
||||||
guint32 evtime);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@@ -123,16 +123,3 @@ _gdk_macos_drag_surface_new (GdkMacosDisplay *display,
|
|||||||
|
|
||||||
return g_steal_pointer (&self);
|
return g_steal_pointer (&self);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
_gdk_macos_drag_surface_drag_motion (GdkMacosDragSurface *self,
|
|
||||||
int x_root,
|
|
||||||
int y_root,
|
|
||||||
GdkDragAction suggested_action,
|
|
||||||
GdkDragAction possible_actions,
|
|
||||||
guint32 evtime)
|
|
||||||
{
|
|
||||||
g_return_if_fail (GDK_IS_MACOS_DRAG_SURFACE (self));
|
|
||||||
|
|
||||||
_gdk_macos_surface_move (GDK_MACOS_SURFACE (self), x_root, y_root);
|
|
||||||
}
|
|
||||||
|
66
gdk/macos/gdkmacosdrop-private.h
Normal file
66
gdk/macos/gdkmacosdrop-private.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021 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/>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDK_MACOS_DROP_PRIVATE_H__
|
||||||
|
#define __GDK_MACOS_DROP_PRIVATE_H__
|
||||||
|
|
||||||
|
#include <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
#include "gdkdropprivate.h"
|
||||||
|
|
||||||
|
#include "gdkmacossurface-private.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDK_TYPE_MACOS_DROP (gdk_macos_drop_get_type ())
|
||||||
|
#define GDK_MACOS_DROP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_DROP, GdkMacosDrop))
|
||||||
|
#define GDK_MACOS_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_MACOS_DROP, GdkMacosDropClass))
|
||||||
|
#define GDK_IS_MACOS_DROP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_DROP))
|
||||||
|
#define GDK_IS_MACOS_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_MACOS_DROP))
|
||||||
|
#define GDK_MACOS_DROP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_MACOS_DROP, GdkMacosDropClass))
|
||||||
|
|
||||||
|
typedef struct _GdkMacosDrop GdkMacosDrop;
|
||||||
|
typedef struct _GdkMacosDropClass GdkMacosDropClass;
|
||||||
|
|
||||||
|
struct _GdkMacosDrop
|
||||||
|
{
|
||||||
|
GdkDrop parent_instance;
|
||||||
|
|
||||||
|
NSPasteboard *pasteboard;
|
||||||
|
|
||||||
|
GdkDragAction all_actions;
|
||||||
|
GdkDragAction preferred_action;
|
||||||
|
GdkDragAction finish_action;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GdkMacosDropClass
|
||||||
|
{
|
||||||
|
GdkDropClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gdk_macos_drop_get_type (void) G_GNUC_CONST;
|
||||||
|
GdkMacosDrop *_gdk_macos_drop_new (GdkMacosSurface *surface,
|
||||||
|
id<NSDraggingInfo> info);
|
||||||
|
NSDragOperation _gdk_macos_drop_operation (GdkMacosDrop *self);
|
||||||
|
void _gdk_macos_drop_update_actions (GdkMacosDrop *self,
|
||||||
|
id<NSDraggingInfo> info);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDK_MACOS_DROP_PRIVATE_H__ */
|
183
gdk/macos/gdkmacosdrop.c
Normal file
183
gdk/macos/gdkmacosdrop.c
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021 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/>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gdkmacosclipboard-private.h"
|
||||||
|
#include "gdkmacosdisplay-private.h"
|
||||||
|
#include "gdkmacosdrag-private.h"
|
||||||
|
#include "gdkmacosdrop-private.h"
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdkMacosDrop, gdk_macos_drop, GDK_TYPE_DROP)
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_macos_drop_status (GdkDrop *drop,
|
||||||
|
GdkDragAction actions,
|
||||||
|
GdkDragAction preferred)
|
||||||
|
{
|
||||||
|
GdkMacosDrop *self = (GdkMacosDrop *)drop;
|
||||||
|
|
||||||
|
g_assert (GDK_IS_MACOS_DROP (self));
|
||||||
|
|
||||||
|
self->all_actions = actions;
|
||||||
|
self->preferred_action = preferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_macos_drop_read_async (GdkDrop *drop,
|
||||||
|
GdkContentFormats *content_formats,
|
||||||
|
int io_priority,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
_gdk_macos_pasteboard_read_async (G_OBJECT (drop),
|
||||||
|
GDK_MACOS_DROP (drop)->pasteboard,
|
||||||
|
content_formats,
|
||||||
|
io_priority,
|
||||||
|
cancellable,
|
||||||
|
callback,
|
||||||
|
user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GInputStream *
|
||||||
|
gdk_macos_drop_read_finish (GdkDrop *drop,
|
||||||
|
GAsyncResult *result,
|
||||||
|
const char **out_mime_type,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
return _gdk_macos_pasteboard_read_finish (G_OBJECT (drop), result, out_mime_type, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_macos_drop_finish (GdkDrop *drop,
|
||||||
|
GdkDragAction action)
|
||||||
|
{
|
||||||
|
g_assert (GDK_IS_MACOS_DROP (drop));
|
||||||
|
|
||||||
|
GDK_MACOS_DROP (drop)->finish_action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_macos_drop_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdkMacosDrop *self = (GdkMacosDrop *)object;
|
||||||
|
|
||||||
|
if (self->pasteboard)
|
||||||
|
{
|
||||||
|
[self->pasteboard release];
|
||||||
|
self->pasteboard = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdk_macos_drop_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_macos_drop_class_init (GdkMacosDropClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
GdkDropClass *drop_class = GDK_DROP_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gdk_macos_drop_finalize;
|
||||||
|
|
||||||
|
drop_class->status = gdk_macos_drop_status;
|
||||||
|
drop_class->read_async = gdk_macos_drop_read_async;
|
||||||
|
drop_class->read_finish = gdk_macos_drop_read_finish;
|
||||||
|
drop_class->finish = gdk_macos_drop_finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_macos_drop_init (GdkMacosDrop *self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gdk_macos_drop_update_actions (GdkMacosDrop *self,
|
||||||
|
id<NSDraggingInfo> info)
|
||||||
|
{
|
||||||
|
NSDragOperation op;
|
||||||
|
GdkDragAction actions = 0;
|
||||||
|
|
||||||
|
g_assert (GDK_IS_MACOS_DROP (self));
|
||||||
|
|
||||||
|
op = [info draggingSourceOperationMask];
|
||||||
|
|
||||||
|
if (op & NSDragOperationCopy)
|
||||||
|
actions |= GDK_ACTION_COPY;
|
||||||
|
|
||||||
|
if (op & NSDragOperationLink)
|
||||||
|
actions |= GDK_ACTION_LINK;
|
||||||
|
|
||||||
|
if (op & NSDragOperationMove)
|
||||||
|
actions |= GDK_ACTION_MOVE;
|
||||||
|
|
||||||
|
gdk_drop_set_actions (GDK_DROP (self), actions);
|
||||||
|
}
|
||||||
|
|
||||||
|
GdkMacosDrop *
|
||||||
|
_gdk_macos_drop_new (GdkMacosSurface *surface,
|
||||||
|
id<NSDraggingInfo> info)
|
||||||
|
{
|
||||||
|
GdkDrag *drag = NULL;
|
||||||
|
GdkContentFormats *content_formats;
|
||||||
|
GdkMacosDrop *self;
|
||||||
|
GdkDisplay *display;
|
||||||
|
GdkDevice *device;
|
||||||
|
GdkSeat *seat;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDK_IS_MACOS_SURFACE (surface), NULL);
|
||||||
|
g_return_val_if_fail (info != NULL, NULL);
|
||||||
|
|
||||||
|
display = gdk_surface_get_display (GDK_SURFACE (surface));
|
||||||
|
seat = gdk_display_get_default_seat (display);
|
||||||
|
device = gdk_seat_get_pointer (seat);
|
||||||
|
drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), [info draggingSequenceNumber]);
|
||||||
|
|
||||||
|
content_formats = _gdk_macos_pasteboard_load_formats ([info draggingPasteboard]);
|
||||||
|
|
||||||
|
self = g_object_new (GDK_TYPE_MACOS_DROP,
|
||||||
|
"device", device,
|
||||||
|
"drag", drag,
|
||||||
|
"formats", content_formats,
|
||||||
|
"surface", surface,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
self->pasteboard = [[info draggingPasteboard] retain];
|
||||||
|
|
||||||
|
_gdk_macos_drop_update_actions (self, info);
|
||||||
|
|
||||||
|
gdk_content_formats_unref (content_formats);
|
||||||
|
|
||||||
|
return g_steal_pointer (&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
NSDragOperation
|
||||||
|
_gdk_macos_drop_operation (GdkMacosDrop *self)
|
||||||
|
{
|
||||||
|
if (self->preferred_action & GDK_ACTION_LINK)
|
||||||
|
return NSDragOperationLink;
|
||||||
|
|
||||||
|
if (self->preferred_action & GDK_ACTION_MOVE)
|
||||||
|
return NSDragOperationMove;
|
||||||
|
|
||||||
|
if (self->preferred_action & GDK_ACTION_COPY)
|
||||||
|
return NSDragOperationCopy;
|
||||||
|
|
||||||
|
return NSDragOperationNone;
|
||||||
|
}
|
76
gdk/macos/gdkmacospasteboard-private.h
Normal file
76
gdk/macos/gdkmacospasteboard-private.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021 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/>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDK_MACOS_PASTEBOARD_PRIVATE_H__
|
||||||
|
#define __GDK_MACOS_PASTEBOARD_PRIVATE_H__
|
||||||
|
|
||||||
|
#include <AppKit/AppKit.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "gdkclipboardprivate.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDK_MACOS_LOCAL_DND_MIME_TYPE "application/x-gtk-local-dnd"
|
||||||
|
|
||||||
|
@interface GdkMacosPasteboardItemDataProvider : NSObject <NSPasteboardItemDataProvider>
|
||||||
|
{
|
||||||
|
GdkContentProvider *_contentProvider;
|
||||||
|
GdkClipboard *_clipboard;
|
||||||
|
GdkDrag *_drag;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(id)initForClipboard:(GdkClipboard *)clipboard withContentProvider:(GdkContentProvider *)contentProvider;
|
||||||
|
-(id)initForDrag:(GdkDrag *)drag withContentProvider:(GdkContentProvider *)contentProvider;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface GdkMacosPasteboardItem : NSPasteboardItem
|
||||||
|
{
|
||||||
|
GdkContentProvider *_contentProvider;
|
||||||
|
GdkClipboard *_clipboard;
|
||||||
|
GdkDrag *_drag;
|
||||||
|
NSRect _draggingFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(id)initForClipboard:(GdkClipboard *)clipboard withContentProvider:(GdkContentProvider *)contentProvider;
|
||||||
|
-(id)initForDrag:(GdkDrag *)drag withContentProvider:(GdkContentProvider *)contentProvider;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NSPasteboardType _gdk_macos_pasteboard_to_ns_type (const char *mime_type,
|
||||||
|
NSPasteboardType *alternate);
|
||||||
|
const char *_gdk_macos_pasteboard_from_ns_type (NSPasteboardType type);
|
||||||
|
GdkContentFormats *_gdk_macos_pasteboard_load_formats (NSPasteboard *pasteboard);
|
||||||
|
void _gdk_macos_pasteboard_register_drag_types (NSWindow *window);
|
||||||
|
void _gdk_macos_pasteboard_read_async (GObject *object,
|
||||||
|
NSPasteboard *pasteboard,
|
||||||
|
GdkContentFormats *formats,
|
||||||
|
int io_priority,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
GInputStream *_gdk_macos_pasteboard_read_finish (GObject *object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
const char **out_mime_type,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDK_MACOS_PASTEBOARD_PRIVATE_H__ */
|
605
gdk/macos/gdkmacospasteboard.c
Normal file
605
gdk/macos/gdkmacospasteboard.c
Normal file
@@ -0,0 +1,605 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021 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/>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
#include "gdkmacospasteboard-private.h"
|
||||||
|
#include "gdkmacosutils-private.h"
|
||||||
|
#include "gdk-private.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TYPE_STRING,
|
||||||
|
TYPE_PBOARD,
|
||||||
|
TYPE_URL,
|
||||||
|
TYPE_FILE_URL,
|
||||||
|
TYPE_COLOR,
|
||||||
|
TYPE_TIFF,
|
||||||
|
TYPE_PNG,
|
||||||
|
TYPE_INTERNAL,
|
||||||
|
TYPE_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PTYPE(k) (get_pasteboard_type(TYPE_##k))
|
||||||
|
|
||||||
|
static NSPasteboardType pasteboard_types[TYPE_LAST];
|
||||||
|
|
||||||
|
static NSPasteboardType
|
||||||
|
get_pasteboard_type (int type)
|
||||||
|
{
|
||||||
|
static gsize initialized = FALSE;
|
||||||
|
|
||||||
|
g_assert (type >= 0);
|
||||||
|
g_assert (type < TYPE_LAST);
|
||||||
|
|
||||||
|
if (g_once_init_enter (&initialized))
|
||||||
|
{
|
||||||
|
pasteboard_types[TYPE_PNG] = NSPasteboardTypePNG;
|
||||||
|
pasteboard_types[TYPE_STRING] = NSPasteboardTypeString;
|
||||||
|
pasteboard_types[TYPE_TIFF] = NSPasteboardTypeTIFF;
|
||||||
|
pasteboard_types[TYPE_COLOR] = NSPasteboardTypeColor;
|
||||||
|
|
||||||
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||||
|
pasteboard_types[TYPE_PBOARD] = NSStringPboardType;
|
||||||
|
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||||
|
|
||||||
|
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER
|
||||||
|
pasteboard_types[TYPE_URL] = NSPasteboardTypeURL;
|
||||||
|
pasteboard_types[TYPE_FILE_URL] = NSPasteboardTypeFileURL;
|
||||||
|
#else
|
||||||
|
pasteboard_types[TYPE_URL] = [[NSString alloc] initWithUTF8String:"public.url"];
|
||||||
|
pasteboard_types[TYPE_FILE_URL] = [[NSString alloc] initWithUTF8String:"public.file-url"];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pasteboard_types[TYPE_INTERNAL] = [[NSString alloc] initWithUTF8String:"org.gtk.pasteboard.internal"];
|
||||||
|
|
||||||
|
g_once_init_leave (&initialized, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pasteboard_types[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
_gdk_macos_pasteboard_from_ns_type (NSPasteboardType type)
|
||||||
|
{
|
||||||
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||||
|
|
||||||
|
if ([type isEqualToString:PTYPE(STRING)] ||
|
||||||
|
[type isEqualToString:PTYPE(PBOARD)])
|
||||||
|
return g_intern_string ("text/plain;charset=utf-8");
|
||||||
|
else if ([type isEqualToString:PTYPE(URL)] ||
|
||||||
|
[type isEqualToString:PTYPE(FILE_URL)])
|
||||||
|
return g_intern_string ("text/uri-list");
|
||||||
|
else if ([type isEqualToString:PTYPE(COLOR)])
|
||||||
|
return g_intern_string ("application/x-color");
|
||||||
|
else if ([type isEqualToString:PTYPE(TIFF)])
|
||||||
|
return g_intern_string ("image/tiff");
|
||||||
|
else if ([type isEqualToString:PTYPE(PNG)])
|
||||||
|
return g_intern_string ("image/png");
|
||||||
|
else if ([type isEqualToString:PTYPE(INTERNAL)])
|
||||||
|
return g_intern_string (GDK_MACOS_LOCAL_DND_MIME_TYPE);
|
||||||
|
|
||||||
|
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSPasteboardType
|
||||||
|
_gdk_macos_pasteboard_to_ns_type (const char *mime_type,
|
||||||
|
NSPasteboardType *alternate)
|
||||||
|
{
|
||||||
|
if (alternate)
|
||||||
|
*alternate = NULL;
|
||||||
|
|
||||||
|
if (g_strcmp0 (mime_type, "text/plain;charset=utf-8") == 0)
|
||||||
|
{
|
||||||
|
return PTYPE(STRING);
|
||||||
|
}
|
||||||
|
else if (g_strcmp0 (mime_type, "text/uri-list") == 0)
|
||||||
|
{
|
||||||
|
if (alternate)
|
||||||
|
*alternate = PTYPE(URL);
|
||||||
|
return PTYPE(FILE_URL);
|
||||||
|
}
|
||||||
|
else if (g_strcmp0 (mime_type, "application/x-color") == 0)
|
||||||
|
{
|
||||||
|
return PTYPE(COLOR);
|
||||||
|
}
|
||||||
|
else if (g_strcmp0 (mime_type, "image/tiff") == 0)
|
||||||
|
{
|
||||||
|
return PTYPE(TIFF);
|
||||||
|
}
|
||||||
|
else if (g_strcmp0 (mime_type, "image/png") == 0)
|
||||||
|
{
|
||||||
|
return PTYPE(PNG);
|
||||||
|
}
|
||||||
|
else if (g_strcmp0 (mime_type, GDK_MACOS_LOCAL_DND_MIME_TYPE) == 0)
|
||||||
|
{
|
||||||
|
return PTYPE(INTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
populate_content_formats (GdkContentFormatsBuilder *builder,
|
||||||
|
NSPasteboardType type)
|
||||||
|
{
|
||||||
|
const char *mime_type;
|
||||||
|
|
||||||
|
g_assert (builder != NULL);
|
||||||
|
g_assert (type != NULL);
|
||||||
|
|
||||||
|
if ((mime_type = _gdk_macos_pasteboard_from_ns_type (type)))
|
||||||
|
gdk_content_formats_builder_add_mime_type (builder, mime_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkContentFormats *
|
||||||
|
load_offer_formats (NSPasteboard *pasteboard)
|
||||||
|
{
|
||||||
|
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||||
|
|
||||||
|
GdkContentFormatsBuilder *builder;
|
||||||
|
GdkContentFormats *formats;
|
||||||
|
|
||||||
|
builder = gdk_content_formats_builder_new ();
|
||||||
|
for (NSPasteboardType type in [pasteboard types])
|
||||||
|
populate_content_formats (builder, type);
|
||||||
|
formats = gdk_content_formats_builder_free_to_formats (builder);
|
||||||
|
|
||||||
|
GDK_END_MACOS_ALLOC_POOL;
|
||||||
|
|
||||||
|
return g_steal_pointer (&formats);
|
||||||
|
}
|
||||||
|
|
||||||
|
GdkContentFormats *
|
||||||
|
_gdk_macos_pasteboard_load_formats (NSPasteboard *pasteboard)
|
||||||
|
{
|
||||||
|
return load_offer_formats (pasteboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GInputStream *
|
||||||
|
create_stream_from_nsdata (NSData *data)
|
||||||
|
{
|
||||||
|
const guint8 *bytes = [data bytes];
|
||||||
|
gsize len = [data length];
|
||||||
|
|
||||||
|
return g_memory_input_stream_new_from_data (g_memdup2 (bytes, len), len, g_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gdk_macos_pasteboard_read_async (GObject *object,
|
||||||
|
NSPasteboard *pasteboard,
|
||||||
|
GdkContentFormats *formats,
|
||||||
|
int io_priority,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||||
|
|
||||||
|
GdkContentFormats *offer_formats = NULL;
|
||||||
|
const char *mime_type;
|
||||||
|
GInputStream *stream = NULL;
|
||||||
|
GTask *task = NULL;
|
||||||
|
|
||||||
|
g_assert (G_IS_OBJECT (object));
|
||||||
|
g_assert (pasteboard != NULL);
|
||||||
|
g_assert (formats != NULL);
|
||||||
|
|
||||||
|
task = g_task_new (object, cancellable, callback, user_data);
|
||||||
|
g_task_set_source_tag (task, _gdk_macos_pasteboard_read_async);
|
||||||
|
g_task_set_priority (task, io_priority);
|
||||||
|
|
||||||
|
offer_formats = load_offer_formats (pasteboard);
|
||||||
|
mime_type = gdk_content_formats_match_mime_type (formats, offer_formats);
|
||||||
|
|
||||||
|
if (mime_type == NULL)
|
||||||
|
{
|
||||||
|
g_task_return_new_error (task,
|
||||||
|
G_IO_ERROR,
|
||||||
|
G_IO_ERROR_NOT_SUPPORTED,
|
||||||
|
"%s",
|
||||||
|
_("No compatible transfer format found"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp (mime_type, "text/plain;charset=utf-8") == 0)
|
||||||
|
{
|
||||||
|
NSString *nsstr = [pasteboard stringForType:NSPasteboardTypeString];
|
||||||
|
|
||||||
|
if (nsstr != NULL)
|
||||||
|
{
|
||||||
|
const char *str = [nsstr UTF8String];
|
||||||
|
stream = g_memory_input_stream_new_from_data (g_strdup (str),
|
||||||
|
strlen (str) + 1,
|
||||||
|
g_free);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp (mime_type, "text/uri-list") == 0)
|
||||||
|
{
|
||||||
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||||
|
|
||||||
|
if ([[pasteboard types] containsObject:PTYPE(FILE_URL)])
|
||||||
|
{
|
||||||
|
GString *str = g_string_new (NULL);
|
||||||
|
NSArray *files = [pasteboard propertyListForType:NSFilenamesPboardType];
|
||||||
|
gsize n_files = [files count];
|
||||||
|
char *data;
|
||||||
|
guint len;
|
||||||
|
|
||||||
|
for (gsize i = 0; i < n_files; ++i)
|
||||||
|
{
|
||||||
|
NSString* uriString = [files objectAtIndex:i];
|
||||||
|
uriString = [@"file://" stringByAppendingString:uriString];
|
||||||
|
uriString = [uriString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
|
||||||
|
g_string_append_printf (str,
|
||||||
|
"%s\r\n",
|
||||||
|
[uriString cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||||
|
}
|
||||||
|
|
||||||
|
len = str->len;
|
||||||
|
data = g_string_free (str, FALSE);
|
||||||
|
stream = g_memory_input_stream_new_from_data (data, len, g_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||||
|
}
|
||||||
|
else if (strcmp (mime_type, "application/x-color") == 0)
|
||||||
|
{
|
||||||
|
NSColorSpace *colorspace;
|
||||||
|
NSColor *nscolor;
|
||||||
|
guint16 color[4];
|
||||||
|
|
||||||
|
colorspace = [NSColorSpace genericRGBColorSpace];
|
||||||
|
nscolor = [[NSColor colorFromPasteboard:pasteboard]
|
||||||
|
colorUsingColorSpace:colorspace];
|
||||||
|
|
||||||
|
color[0] = 0xffff * [nscolor redComponent];
|
||||||
|
color[1] = 0xffff * [nscolor greenComponent];
|
||||||
|
color[2] = 0xffff * [nscolor blueComponent];
|
||||||
|
color[3] = 0xffff * [nscolor alphaComponent];
|
||||||
|
|
||||||
|
stream = g_memory_input_stream_new_from_data (g_memdup2 (&color, sizeof color),
|
||||||
|
sizeof color,
|
||||||
|
g_free);
|
||||||
|
}
|
||||||
|
else if (strcmp (mime_type, "image/tiff") == 0)
|
||||||
|
{
|
||||||
|
NSData *data = [pasteboard dataForType:PTYPE(TIFF)];
|
||||||
|
stream = create_stream_from_nsdata (data);
|
||||||
|
}
|
||||||
|
else if (strcmp (mime_type, "image/png") == 0)
|
||||||
|
{
|
||||||
|
NSData *data = [pasteboard dataForType:PTYPE(PNG)];
|
||||||
|
stream = create_stream_from_nsdata (data);
|
||||||
|
}
|
||||||
|
else if (strcmp (mime_type, GDK_MACOS_LOCAL_DND_MIME_TYPE) == 0)
|
||||||
|
{
|
||||||
|
/* Should be internal copy */
|
||||||
|
g_warn_if_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream != NULL)
|
||||||
|
{
|
||||||
|
g_task_set_task_data (task, g_strdup (mime_type), g_free);
|
||||||
|
g_task_return_pointer (task, g_steal_pointer (&stream), g_object_unref);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_task_return_new_error (task,
|
||||||
|
G_IO_ERROR,
|
||||||
|
G_IO_ERROR_FAILED,
|
||||||
|
_("Failed to decode contents with mime-type of '%s'"),
|
||||||
|
mime_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
g_clear_object (&task);
|
||||||
|
g_clear_pointer (&offer_formats, gdk_content_formats_unref);
|
||||||
|
|
||||||
|
GDK_END_MACOS_ALLOC_POOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GInputStream *
|
||||||
|
_gdk_macos_pasteboard_read_finish (GObject *object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
const char **out_mime_type,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GTask *task = (GTask *)result;
|
||||||
|
|
||||||
|
g_assert (G_IS_OBJECT (object));
|
||||||
|
g_assert (G_IS_TASK (task));
|
||||||
|
|
||||||
|
if (out_mime_type != NULL)
|
||||||
|
*out_mime_type = g_strdup (g_task_get_task_data (task));
|
||||||
|
|
||||||
|
return g_task_propagate_pointer (task, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gdk_macos_pasteboard_register_drag_types (NSWindow *window)
|
||||||
|
{
|
||||||
|
[window registerForDraggedTypes:[NSArray arrayWithObjects:PTYPE(STRING),
|
||||||
|
PTYPE(PBOARD),
|
||||||
|
PTYPE(URL),
|
||||||
|
PTYPE(FILE_URL),
|
||||||
|
PTYPE(COLOR),
|
||||||
|
PTYPE(TIFF),
|
||||||
|
PTYPE(PNG),
|
||||||
|
PTYPE(INTERNAL),
|
||||||
|
nil]];
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation GdkMacosPasteboardItemDataProvider
|
||||||
|
|
||||||
|
-(id)initForClipboard:(GdkClipboard*)clipboard withContentProvider:(GdkContentProvider*)contentProvider
|
||||||
|
{
|
||||||
|
[super init];
|
||||||
|
g_set_object (&self->_clipboard, clipboard);
|
||||||
|
g_set_object (&self->_contentProvider, contentProvider);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(id)initForDrag:(GdkDrag*)drag withContentProvider:(GdkContentProvider*)contentProvider
|
||||||
|
{
|
||||||
|
[super init];
|
||||||
|
g_set_object (&self->_drag, drag);
|
||||||
|
g_set_object (&self->_contentProvider, contentProvider);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)dealloc
|
||||||
|
{
|
||||||
|
g_clear_object (&self->_contentProvider);
|
||||||
|
g_clear_object (&self->_clipboard);
|
||||||
|
g_clear_object (&self->_drag);
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(NSArray<NSPasteboardType> *)types
|
||||||
|
{
|
||||||
|
NSMutableArray *ret = [[NSMutableArray alloc] init];
|
||||||
|
GdkContentFormats *serializable;
|
||||||
|
const char * const *mime_types;
|
||||||
|
gsize n_mime_types;
|
||||||
|
|
||||||
|
serializable = gdk_content_provider_ref_storable_formats (self->_contentProvider);
|
||||||
|
serializable = gdk_content_formats_union_serialize_mime_types (serializable);
|
||||||
|
mime_types = gdk_content_formats_get_mime_types (serializable, &n_mime_types);
|
||||||
|
|
||||||
|
for (guint i = 0; mime_types[i]; i++)
|
||||||
|
{
|
||||||
|
const char *mime_type = mime_types[i];
|
||||||
|
NSPasteboardType type;
|
||||||
|
NSPasteboardType alternate = nil;
|
||||||
|
|
||||||
|
if ((type = _gdk_macos_pasteboard_to_ns_type (mime_type, &alternate)))
|
||||||
|
{
|
||||||
|
[ret addObject:type];
|
||||||
|
if (alternate)
|
||||||
|
[ret addObject:alternate];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([ret count] == 0)
|
||||||
|
{
|
||||||
|
NSPasteboardType type;
|
||||||
|
NSPasteboardType alternate = nil;
|
||||||
|
|
||||||
|
if ((type = _gdk_macos_pasteboard_to_ns_type (GDK_MACOS_LOCAL_DND_MIME_TYPE, &alternate)))
|
||||||
|
[ret addObject:type];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return g_steal_pointer (&ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GMemoryOutputStream *stream;
|
||||||
|
NSPasteboardItem *item;
|
||||||
|
NSPasteboardType type;
|
||||||
|
GMainContext *main_context;
|
||||||
|
guint done : 1;
|
||||||
|
} WriteRequest;
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_request_free (WriteRequest *wr)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&wr->main_context, g_main_context_unref);
|
||||||
|
g_clear_object (&wr->stream);
|
||||||
|
[wr->item release];
|
||||||
|
g_slice_free (WriteRequest, wr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_data_ready_cb (GObject *object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||||
|
|
||||||
|
WriteRequest *wr = user_data;
|
||||||
|
GError *error = NULL;
|
||||||
|
NSData *data = nil;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_assert (G_IS_OBJECT (object));
|
||||||
|
g_assert (GDK_IS_CLIPBOARD (object) || GDK_IS_DRAG (object));
|
||||||
|
g_assert (G_IS_ASYNC_RESULT (result));
|
||||||
|
g_assert (wr != NULL);
|
||||||
|
g_assert (G_IS_MEMORY_OUTPUT_STREAM (wr->stream));
|
||||||
|
g_assert ([wr->item isKindOfClass:[NSPasteboardItem class]]);
|
||||||
|
|
||||||
|
if (GDK_IS_CLIPBOARD (object))
|
||||||
|
ret = gdk_clipboard_write_finish (GDK_CLIPBOARD (object), result, &error);
|
||||||
|
else
|
||||||
|
ret = gdk_drag_write_finish (GDK_DRAG (object), result, &error);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
gsize size;
|
||||||
|
gpointer bytes;
|
||||||
|
|
||||||
|
g_output_stream_close (G_OUTPUT_STREAM (wr->stream), NULL, NULL);
|
||||||
|
|
||||||
|
size = g_memory_output_stream_get_size (wr->stream);
|
||||||
|
bytes = g_memory_output_stream_steal_data (wr->stream);
|
||||||
|
data = [[NSData alloc] initWithBytesNoCopy:bytes
|
||||||
|
length:size
|
||||||
|
deallocator:^(void *alloc, NSUInteger length) { g_free (alloc); }];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_warning ("Failed to serialize pasteboard contents: %s", error->message);
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
|
||||||
|
[wr->item setData:data forType:wr->type];
|
||||||
|
|
||||||
|
wr->done = TRUE;
|
||||||
|
|
||||||
|
GDK_END_MACOS_ALLOC_POOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)pasteboard:(NSPasteboard *)pasteboard item:(NSPasteboardItem *)item provideDataForType:(NSPasteboardType)type
|
||||||
|
{
|
||||||
|
const char *mime_type = _gdk_macos_pasteboard_from_ns_type (type);
|
||||||
|
GMainContext *main_context = g_main_context_default ();
|
||||||
|
WriteRequest *wr;
|
||||||
|
|
||||||
|
if (self->_contentProvider == NULL || mime_type == NULL)
|
||||||
|
{
|
||||||
|
[item setData:[NSData data] forType:type];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wr = g_slice_new0 (WriteRequest);
|
||||||
|
wr->item = [item retain];
|
||||||
|
wr->stream = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new_resizable ());
|
||||||
|
wr->type = type;
|
||||||
|
wr->main_context = g_main_context_ref (main_context);
|
||||||
|
wr->done = FALSE;
|
||||||
|
|
||||||
|
if (GDK_IS_CLIPBOARD (self->_clipboard))
|
||||||
|
gdk_clipboard_write_async (self->_clipboard,
|
||||||
|
mime_type,
|
||||||
|
G_OUTPUT_STREAM (wr->stream),
|
||||||
|
G_PRIORITY_DEFAULT,
|
||||||
|
NULL,
|
||||||
|
on_data_ready_cb,
|
||||||
|
wr);
|
||||||
|
else if (GDK_IS_DRAG (self->_drag))
|
||||||
|
gdk_drag_write_async (self->_drag,
|
||||||
|
mime_type,
|
||||||
|
G_OUTPUT_STREAM (wr->stream),
|
||||||
|
G_PRIORITY_DEFAULT,
|
||||||
|
NULL,
|
||||||
|
on_data_ready_cb,
|
||||||
|
wr);
|
||||||
|
else
|
||||||
|
g_return_if_reached ();
|
||||||
|
|
||||||
|
/* We're forced to provide data synchronously via this API
|
||||||
|
* so we must block on the main loop. Using another main loop
|
||||||
|
* than the default tends to get us locked up here, so that is
|
||||||
|
* what we'll do for now.
|
||||||
|
*/
|
||||||
|
while (!wr->done)
|
||||||
|
g_main_context_iteration (wr->main_context, TRUE);
|
||||||
|
|
||||||
|
write_request_free (wr);
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)pasteboardFinishedWithDataProvider:(NSPasteboard *)pasteboard
|
||||||
|
{
|
||||||
|
g_clear_object (&self->_clipboard);
|
||||||
|
g_clear_object (&self->_drag);
|
||||||
|
g_clear_object (&self->_contentProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GdkMacosPasteboardItem
|
||||||
|
|
||||||
|
-(id)initForClipboard:(GdkClipboard*)clipboard withContentProvider:(GdkContentProvider*)contentProvider
|
||||||
|
{
|
||||||
|
GdkMacosPasteboardItemDataProvider *dataProvider;
|
||||||
|
|
||||||
|
dataProvider = [[GdkMacosPasteboardItemDataProvider alloc] initForClipboard:clipboard withContentProvider:contentProvider];
|
||||||
|
|
||||||
|
[super init];
|
||||||
|
g_set_object (&self->_clipboard, clipboard);
|
||||||
|
g_set_object (&self->_contentProvider, contentProvider);
|
||||||
|
[self setDataProvider:dataProvider forTypes:[dataProvider types]];
|
||||||
|
|
||||||
|
[dataProvider release];
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(id)initForDrag:(GdkDrag*)drag withContentProvider:(GdkContentProvider*)contentProvider
|
||||||
|
{
|
||||||
|
GdkMacosPasteboardItemDataProvider *dataProvider;
|
||||||
|
|
||||||
|
dataProvider = [[GdkMacosPasteboardItemDataProvider alloc] initForDrag:drag withContentProvider:contentProvider];
|
||||||
|
|
||||||
|
[super init];
|
||||||
|
g_set_object (&self->_drag, drag);
|
||||||
|
g_set_object (&self->_contentProvider, contentProvider);
|
||||||
|
[self setDataProvider:dataProvider forTypes:[dataProvider types]];
|
||||||
|
|
||||||
|
[dataProvider release];
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)dealloc
|
||||||
|
{
|
||||||
|
g_clear_object (&self->_contentProvider);
|
||||||
|
g_clear_object (&self->_clipboard);
|
||||||
|
g_clear_object (&self->_drag);
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(NSRect)draggingFrame
|
||||||
|
{
|
||||||
|
return self->_draggingFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)setDraggingFrame:(NSRect)draggingFrame;
|
||||||
|
{
|
||||||
|
self->_draggingFrame = draggingFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(id)item
|
||||||
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(NSArray* (^) (void))imageComponentsProvider
|
||||||
|
{
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
@@ -313,10 +313,12 @@ gdk_macos_surface_drag_begin (GdkSurface *surface,
|
|||||||
GdkMacosSurface *self = (GdkMacosSurface *)surface;
|
GdkMacosSurface *self = (GdkMacosSurface *)surface;
|
||||||
GdkMacosSurface *drag_surface;
|
GdkMacosSurface *drag_surface;
|
||||||
GdkMacosDrag *drag;
|
GdkMacosDrag *drag;
|
||||||
|
GdkDisplay *display;
|
||||||
GdkCursor *cursor;
|
GdkCursor *cursor;
|
||||||
GdkSeat *seat;
|
GdkSeat *seat;
|
||||||
double px;
|
double px;
|
||||||
double py;
|
double py;
|
||||||
|
int quartz_x, quartz_y;
|
||||||
int sx;
|
int sx;
|
||||||
int sy;
|
int sy;
|
||||||
|
|
||||||
@@ -326,13 +328,19 @@ gdk_macos_surface_drag_begin (GdkSurface *surface,
|
|||||||
g_assert (GDK_IS_MACOS_DEVICE (device));
|
g_assert (GDK_IS_MACOS_DEVICE (device));
|
||||||
g_assert (GDK_IS_CONTENT_PROVIDER (content));
|
g_assert (GDK_IS_CONTENT_PROVIDER (content));
|
||||||
|
|
||||||
|
display = gdk_surface_get_display (surface);
|
||||||
|
_gdk_macos_display_to_display_coords (GDK_MACOS_DISPLAY (display),
|
||||||
|
surface->x + dx,
|
||||||
|
surface->y + dy,
|
||||||
|
&quartz_x, &quartz_y);
|
||||||
|
|
||||||
seat = gdk_device_get_seat (device);
|
seat = gdk_device_get_seat (device);
|
||||||
gdk_macos_device_query_state (device, surface, NULL, &px, &py, NULL);
|
gdk_macos_device_query_state (device, surface, NULL, &px, &py, NULL);
|
||||||
_gdk_macos_surface_get_root_coords (GDK_MACOS_SURFACE (surface), &sx, &sy);
|
_gdk_macos_surface_get_root_coords (GDK_MACOS_SURFACE (surface), &sx, &sy);
|
||||||
drag_surface = _gdk_macos_surface_new (GDK_MACOS_DISPLAY (surface->display),
|
drag_surface = _gdk_macos_surface_new (GDK_MACOS_DISPLAY (surface->display),
|
||||||
GDK_SURFACE_TEMP,
|
GDK_SURFACE_TEMP,
|
||||||
surface,
|
surface,
|
||||||
-99, -99, 1, 1);
|
sx, sy, 1, 1);
|
||||||
drag = g_object_new (GDK_TYPE_MACOS_DRAG,
|
drag = g_object_new (GDK_TYPE_MACOS_DRAG,
|
||||||
"drag-surface", drag_surface,
|
"drag-surface", drag_surface,
|
||||||
"surface", surface,
|
"surface", surface,
|
||||||
@@ -346,7 +354,7 @@ gdk_macos_surface_drag_begin (GdkSurface *surface,
|
|||||||
gdk_drag_get_selected_action (GDK_DRAG (drag)));
|
gdk_drag_get_selected_action (GDK_DRAG (drag)));
|
||||||
gdk_drag_set_cursor (GDK_DRAG (drag), cursor);
|
gdk_drag_set_cursor (GDK_DRAG (drag), cursor);
|
||||||
|
|
||||||
if (!_gdk_macos_drag_begin (drag))
|
if (!_gdk_macos_drag_begin (drag, content, self->window, quartz_x, quartz_y))
|
||||||
{
|
{
|
||||||
g_object_unref (drag);
|
g_object_unref (drag);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@@ -10,11 +10,13 @@ gdk_macos_sources = files([
|
|||||||
'gdkmacosdisplay-settings.c',
|
'gdkmacosdisplay-settings.c',
|
||||||
'gdkmacosdisplay-translate.c',
|
'gdkmacosdisplay-translate.c',
|
||||||
'gdkmacosdrag.c',
|
'gdkmacosdrag.c',
|
||||||
|
'gdkmacosdrop.c',
|
||||||
'gdkmacosdragsurface.c',
|
'gdkmacosdragsurface.c',
|
||||||
'gdkmacosglcontext.c',
|
'gdkmacosglcontext.c',
|
||||||
'gdkmacoseventsource.c',
|
'gdkmacoseventsource.c',
|
||||||
'gdkmacoskeymap.c',
|
'gdkmacoskeymap.c',
|
||||||
'gdkmacosmonitor.c',
|
'gdkmacosmonitor.c',
|
||||||
|
'gdkmacospasteboard.c',
|
||||||
'gdkmacospopupsurface.c',
|
'gdkmacospopupsurface.c',
|
||||||
'gdkmacosseat.c',
|
'gdkmacosseat.c',
|
||||||
'gdkmacossurface.c',
|
'gdkmacossurface.c',
|
||||||
|
Reference in New Issue
Block a user