Compare commits
10 Commits
main
...
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));
|
||||
}
|
||||
|
||||
- (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
|
||||
|
@@ -29,7 +29,9 @@
|
||||
#import "GdkMacosWindow.h"
|
||||
|
||||
#include "gdkmacosdisplay-private.h"
|
||||
#include "gdkmacosdrop-private.h"
|
||||
#include "gdkmacosmonitor-private.h"
|
||||
#include "gdkmacospasteboard-private.h"
|
||||
#include "gdkmacossurface-private.h"
|
||||
#include "gdkmacospopupsurface-private.h"
|
||||
#include "gdkmacostoplevelsurface-private.h"
|
||||
@@ -287,6 +289,9 @@ typedef NSString *CALayerContentsGravity;
|
||||
[self setContentView:view];
|
||||
[view release];
|
||||
|
||||
/* TODO: We might want to make this more extensible at some point */
|
||||
_gdk_macos_pasteboard_register_drag_types (self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -597,25 +602,86 @@ typedef NSString *CALayerContentsGravity;
|
||||
|
||||
-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
return NSDragOperationNone;
|
||||
NSPoint location = [sender draggingLocation];
|
||||
NSDragOperation ret;
|
||||
GdkMacosDrop *drop;
|
||||
|
||||
if (!(drop = _gdk_macos_drop_new ([self gdkSurface], sender)))
|
||||
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
|
||||
{
|
||||
_gdk_macos_display_set_drop ([self gdkDisplay], [sender draggingSequenceNumber], NULL);
|
||||
}
|
||||
|
||||
-(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
|
||||
{
|
||||
return NSDragOperationNone;
|
||||
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;
|
||||
|
||||
_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
|
||||
{
|
||||
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
|
||||
|
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "gdkclipboardprivate.h"
|
||||
#include "gdkmacosdisplay-private.h"
|
||||
#include "gdkmacospasteboard-private.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -35,23 +36,12 @@ typedef NSString *NSPasteboardType;
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK, MACOS_CLIPBOARD, GdkClipboard)
|
||||
|
||||
GdkClipboard *_gdk_macos_clipboard_new (GdkMacosDisplay *display);
|
||||
void _gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self);
|
||||
NSPasteboardType _gdk_macos_clipboard_to_ns_type (const char *mime_type,
|
||||
NSPasteboardType *alternate);
|
||||
const char *_gdk_macos_clipboard_from_ns_type (NSPasteboardType ns_type);
|
||||
|
||||
@interface GdkMacosClipboardDataProvider : NSObject <NSPasteboardItemDataProvider>
|
||||
{
|
||||
GCancellable *cancellable;
|
||||
GdkClipboard *clipboard;
|
||||
char **mimeTypes;
|
||||
}
|
||||
|
||||
-(id)initClipboard:(GdkClipboard *)gdkClipboard mimetypes:(const char * const *)mime_types;
|
||||
-(NSArray<NSPasteboardType> *)types;
|
||||
|
||||
@end
|
||||
GdkClipboard *_gdk_macos_clipboard_new (GdkMacosDisplay *display);
|
||||
void _gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self);
|
||||
NSPasteboardType _gdk_macos_clipboard_to_ns_type (const char *mime_type,
|
||||
NSPasteboardType *alternate);
|
||||
const char *_gdk_macos_clipboard_from_ns_type (NSPasteboardType ns_type);
|
||||
void _gdk_macos_clipboard_register_drag_types (NSWindow *window);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "gdkmacosclipboard-private.h"
|
||||
#include "gdkmacospasteboard-private.h"
|
||||
#include "gdkmacosutils-private.h"
|
||||
#include "gdk-private.h"
|
||||
|
||||
@@ -32,165 +33,8 @@ struct _GdkMacosClipboard
|
||||
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)
|
||||
|
||||
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
|
||||
_gdk_macos_clipboard_load_contents (GdkMacosClipboard *self)
|
||||
{
|
||||
@@ -201,22 +45,13 @@ _gdk_macos_clipboard_load_contents (GdkMacosClipboard *self)
|
||||
|
||||
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_content_formats_unref (formats);
|
||||
|
||||
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
|
||||
_gdk_macos_clipboard_read_async (GdkClipboard *clipboard,
|
||||
GdkContentFormats *formats,
|
||||
@@ -225,125 +60,13 @@ _gdk_macos_clipboard_read_async (GdkClipboard *clipboard,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
GdkMacosClipboard *self = (GdkMacosClipboard *)clipboard;
|
||||
GdkContentFormats *offer_formats = NULL;
|
||||
const char *mime_type;
|
||||
GInputStream *stream = NULL;
|
||||
GTask *task = NULL;
|
||||
|
||||
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;
|
||||
_gdk_macos_pasteboard_read_async (G_OBJECT (clipboard),
|
||||
GDK_MACOS_CLIPBOARD (clipboard)->pasteboard,
|
||||
formats,
|
||||
io_priority,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
@@ -352,49 +75,33 @@ _gdk_macos_clipboard_read_finish (GdkClipboard *clipboard,
|
||||
const char **out_mime_type,
|
||||
GError **error)
|
||||
{
|
||||
GTask *task = (GTask *)result;
|
||||
|
||||
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);
|
||||
return _gdk_macos_pasteboard_read_finish (G_OBJECT (clipboard), result, out_mime_type, error);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_clipboard_send_to_pasteboard (GdkMacosClipboard *self,
|
||||
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;
|
||||
|
||||
GdkMacosClipboardDataProvider *dataProvider;
|
||||
GdkContentFormats *serializable;
|
||||
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]];
|
||||
item = [[GdkMacosPasteboardItem alloc] initForClipboard:GDK_CLIPBOARD (self) withContentProvider:content];
|
||||
items = [NSArray arrayWithObject:item];
|
||||
|
||||
[self->pasteboard clearContents];
|
||||
if ([self->pasteboard writeObjects:[NSArray arrayWithObject:item]] == NO)
|
||||
g_warning ("Failed to write object to pasteboard");
|
||||
if ([self->pasteboard writeObjects:items] == NO)
|
||||
g_warning ("Failed to send clipboard to pasteboard");
|
||||
|
||||
self->last_change_count = [self->pasteboard changeCount];
|
||||
|
||||
g_clear_pointer (&serializable, gdk_content_formats_unref);
|
||||
|
||||
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)
|
||||
_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 */
|
||||
GdkMacosSurface *keyboard_surface;
|
||||
|
||||
/* [NSDraggingInfo draggingSequenceNumber] to GdkMacosDr(ag,op) */
|
||||
GHashTable *active_drags;
|
||||
GHashTable *active_drops;
|
||||
|
||||
/* Used to translate from quartz coordinate space to GDK */
|
||||
int width;
|
||||
int height;
|
||||
@@ -160,6 +164,16 @@ void _gdk_macos_display_warp_pointer (GdkMacosDisp
|
||||
int x,
|
||||
int y);
|
||||
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
|
||||
|
||||
|
@@ -788,6 +788,9 @@ get_surface_from_ns_event (GdkMacosDisplay *self,
|
||||
NSRect view_frame;
|
||||
|
||||
view = (GdkMacosBaseView *)[nswindow contentView];
|
||||
if (!GDK_IS_MACOS_BASE_VIEW (view))
|
||||
goto find_under_pointer;
|
||||
|
||||
surface = GDK_SURFACE ([view gdkSurface]);
|
||||
|
||||
point = [nsevent locationInWindow];
|
||||
@@ -846,6 +849,8 @@ get_surface_from_ns_event (GdkMacosDisplay *self,
|
||||
}
|
||||
}
|
||||
|
||||
find_under_pointer:
|
||||
|
||||
if (!surface)
|
||||
{
|
||||
/* Fallback used when no NSSurface set. This happens e.g. when
|
||||
@@ -864,17 +869,24 @@ get_surface_from_ns_event (GdkMacosDisplay *self,
|
||||
static GdkMacosSurface *
|
||||
find_surface_for_keyboard_event (NSEvent *nsevent)
|
||||
{
|
||||
GdkMacosBaseView *view = (GdkMacosBaseView *)[[nsevent window] contentView];
|
||||
GdkSurface *surface = GDK_SURFACE ([view gdkSurface]);
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkSeat *seat = gdk_display_get_default_seat (display);
|
||||
GdkDevice *device = gdk_seat_get_keyboard (seat);
|
||||
GdkDeviceGrabInfo *grab = _gdk_display_get_last_device_grab (display, device);
|
||||
NSView *nsview = [[nsevent window] contentView];
|
||||
|
||||
if (grab && grab->surface && !grab->owner_events)
|
||||
return GDK_MACOS_SURFACE (grab->surface);
|
||||
if (GDK_IS_MACOS_BASE_VIEW (nsview))
|
||||
{
|
||||
GdkMacosBaseView *view = (GdkMacosBaseView *)nsview;
|
||||
GdkSurface *surface = GDK_SURFACE ([view gdkSurface]);
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkSeat *seat = gdk_display_get_default_seat (display);
|
||||
GdkDevice *device = gdk_seat_get_keyboard (seat);
|
||||
GdkDeviceGrabInfo *grab = _gdk_display_get_last_device_grab (display, device);
|
||||
|
||||
return GDK_MACOS_SURFACE (surface);
|
||||
if (grab && grab->surface && !grab->owner_events)
|
||||
return GDK_MACOS_SURFACE (grab->surface);
|
||||
|
||||
return GDK_MACOS_SURFACE (surface);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GdkMacosSurface *
|
||||
@@ -1090,7 +1102,8 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
|
||||
if (!(surface = find_surface_for_ns_event (self, nsevent, &x, &y)))
|
||||
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;
|
||||
|
||||
/* Ignore events and break grabs while the window is being
|
||||
|
@@ -31,6 +31,8 @@
|
||||
#include "gdkmacoscairocontext-private.h"
|
||||
#include "gdkmacoseventsource-private.h"
|
||||
#include "gdkmacosdisplay-private.h"
|
||||
#include "gdkmacosdrag-private.h"
|
||||
#include "gdkmacosdrop-private.h"
|
||||
#include "gdkmacosglcontext-private.h"
|
||||
#include "gdkmacoskeymap-private.h"
|
||||
#include "gdkmacosmonitor-private.h"
|
||||
@@ -663,6 +665,8 @@ gdk_macos_display_finalize (GObject *object)
|
||||
CFSTR ("NSUserDefaultsDidChangeNotification"),
|
||||
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_pointer (&self->frame_source, g_source_unref);
|
||||
g_clear_object (&self->monitors);
|
||||
@@ -701,6 +705,8 @@ static void
|
||||
gdk_macos_display_init (GdkMacosDisplay *self)
|
||||
{
|
||||
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_input_shapes (GDK_DISPLAY (self), FALSE);
|
||||
@@ -1113,3 +1119,55 @@ _gdk_macos_display_get_nsevent (GdkEvent *event)
|
||||
|
||||
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 "gdkmacosdragsurface-private.h"
|
||||
#include "gdkmacospasteboard-private.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -44,6 +45,8 @@ struct _GdkMacosDrag
|
||||
GdkSeat *drag_seat;
|
||||
GdkCursor *cursor;
|
||||
|
||||
NSInteger sequence;
|
||||
|
||||
int hot_x;
|
||||
int hot_y;
|
||||
|
||||
@@ -63,7 +66,11 @@ struct _GdkMacosDragClass
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
|
@@ -49,6 +49,17 @@ enum {
|
||||
|
||||
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
|
||||
ease_out_cubic (double t)
|
||||
{
|
||||
@@ -81,12 +92,12 @@ gdk_macos_zoomback_timeout (gpointer data)
|
||||
frame_clock = zb->frame_clock;
|
||||
|
||||
if (!frame_clock)
|
||||
return G_SOURCE_REMOVE;
|
||||
goto hide_surface;
|
||||
|
||||
current_time = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
f = (current_time - zb->start_time) / (double) ANIM_TIME;
|
||||
if (f >= 1.0)
|
||||
return G_SOURCE_REMOVE;
|
||||
goto hide_surface;
|
||||
|
||||
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));
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
hide_surface:
|
||||
gdk_surface_hide (GDK_SURFACE (drag->drag_surface));
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static GdkSurface *
|
||||
@@ -142,6 +158,8 @@ gdk_macos_drag_drop_done (GdkDrag *drag,
|
||||
|
||||
g_assert (GDK_IS_MACOS_DRAG (self));
|
||||
|
||||
g_print ("Drop done! success=%d\n", success);
|
||||
|
||||
if (success)
|
||||
{
|
||||
gdk_surface_hide (GDK_SURFACE (self->drag_surface));
|
||||
@@ -231,20 +249,8 @@ gdk_macos_drag_cancel (GdkDrag *drag,
|
||||
|
||||
self->cancelled = TRUE;
|
||||
drag_ungrab (self);
|
||||
gdk_drag_drop_done (drag, FALSE);
|
||||
}
|
||||
|
||||
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);
|
||||
gdk_surface_hide (GDK_SURFACE (self->drag_surface));
|
||||
gdk_macos_drag_drop_from_display (self);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -326,12 +332,10 @@ gdk_drag_update (GdkDrag *drag,
|
||||
&suggested_action,
|
||||
&possible_actions);
|
||||
|
||||
_gdk_macos_drag_surface_drag_motion (self->drag_surface,
|
||||
x_root - self->hot_x,
|
||||
y_root - self->hot_y,
|
||||
suggested_action,
|
||||
possible_actions,
|
||||
evtime);
|
||||
if (GDK_IS_MACOS_SURFACE (self->drag_surface))
|
||||
_gdk_macos_surface_move (GDK_MACOS_SURFACE (self->drag_surface),
|
||||
x_root - self->hot_x,
|
||||
y_root - self->hot_y);
|
||||
|
||||
if (!self->did_update)
|
||||
{
|
||||
@@ -339,6 +343,8 @@ gdk_drag_update (GdkDrag *drag,
|
||||
self->start_y = self->last_y;
|
||||
self->did_update = TRUE;
|
||||
}
|
||||
|
||||
gdk_drag_set_actions (drag, possible_actions);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -503,6 +509,9 @@ gdk_macos_drag_handle_event (GdkDrag *drag,
|
||||
g_assert (GDK_IS_MACOS_DRAG (drag));
|
||||
g_assert (event != NULL);
|
||||
|
||||
if (GDK_MACOS_DRAG (drag)->cancelled)
|
||||
return FALSE;
|
||||
|
||||
switch ((guint) event->event_type)
|
||||
{
|
||||
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
|
||||
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->set_cursor = gdk_macos_drag_set_cursor;
|
||||
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->dnd_finished = gdk_macos_drag_dnd_finished;
|
||||
|
||||
properties [PROP_DRAG_SURFACE] =
|
||||
g_param_spec_object ("drag-surface",
|
||||
@@ -610,11 +625,57 @@ gdk_macos_drag_init (GdkMacosDrag *self)
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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));
|
||||
|
||||
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;
|
||||
}
|
||||
|
@@ -31,19 +31,13 @@ typedef struct _GdkMacosDragSurfaceClass GdkMacosDragSurfaceClass;
|
||||
#define GDK_MACOS_DRAG_SURFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_DRAG_SURFACE, GdkMacosDragSurface))
|
||||
#define GDK_IS_MACOS_DRAG_SURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_DRAG_SURFACE))
|
||||
|
||||
GType _gdk_macos_drag_surface_get_type (void);
|
||||
GdkMacosSurface *_gdk_macos_drag_surface_new (GdkMacosDisplay *display,
|
||||
GdkFrameClock *frame_clock,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
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);
|
||||
GType _gdk_macos_drag_surface_get_type (void);
|
||||
GdkMacosSurface *_gdk_macos_drag_surface_new (GdkMacosDisplay *display,
|
||||
GdkFrameClock *frame_clock,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@@ -123,16 +123,3 @@ _gdk_macos_drag_surface_new (GdkMacosDisplay *display,
|
||||
|
||||
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 *drag_surface;
|
||||
GdkMacosDrag *drag;
|
||||
GdkDisplay *display;
|
||||
GdkCursor *cursor;
|
||||
GdkSeat *seat;
|
||||
double px;
|
||||
double py;
|
||||
int quartz_x, quartz_y;
|
||||
int sx;
|
||||
int sy;
|
||||
|
||||
@@ -326,13 +328,19 @@ gdk_macos_surface_drag_begin (GdkSurface *surface,
|
||||
g_assert (GDK_IS_MACOS_DEVICE (device));
|
||||
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);
|
||||
gdk_macos_device_query_state (device, surface, NULL, &px, &py, NULL);
|
||||
_gdk_macos_surface_get_root_coords (GDK_MACOS_SURFACE (surface), &sx, &sy);
|
||||
drag_surface = _gdk_macos_surface_new (GDK_MACOS_DISPLAY (surface->display),
|
||||
GDK_SURFACE_TEMP,
|
||||
surface,
|
||||
-99, -99, 1, 1);
|
||||
sx, sy, 1, 1);
|
||||
drag = g_object_new (GDK_TYPE_MACOS_DRAG,
|
||||
"drag-surface", drag_surface,
|
||||
"surface", surface,
|
||||
@@ -346,7 +354,7 @@ gdk_macos_surface_drag_begin (GdkSurface *surface,
|
||||
gdk_drag_get_selected_action (GDK_DRAG (drag)));
|
||||
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);
|
||||
return NULL;
|
||||
|
@@ -10,11 +10,13 @@ gdk_macos_sources = files([
|
||||
'gdkmacosdisplay-settings.c',
|
||||
'gdkmacosdisplay-translate.c',
|
||||
'gdkmacosdrag.c',
|
||||
'gdkmacosdrop.c',
|
||||
'gdkmacosdragsurface.c',
|
||||
'gdkmacosglcontext.c',
|
||||
'gdkmacoseventsource.c',
|
||||
'gdkmacoskeymap.c',
|
||||
'gdkmacosmonitor.c',
|
||||
'gdkmacospasteboard.c',
|
||||
'gdkmacospopupsurface.c',
|
||||
'gdkmacosseat.c',
|
||||
'gdkmacossurface.c',
|
||||
|
Reference in New Issue
Block a user