The handling is done similar to drag targets.
Note that dragging is a modal action on macos: no events
are sent to the main window. This could cause trouble when
we finish the drag, and not finish the gesture in GTK.
#import "GdkMacosWindow.h"
#include "gdkmacosdisplay-private.h"
+#include "gdkmacosdrag-private.h"
#include "gdkmacosdrop-private.h"
#include "gdkmacosmonitor-private.h"
#include "gdkmacospasteboard-private.h"
}
// NSDraggingSource protocol
-// ...
+
+- (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context
+{
+ NSInteger sequence_number = [session draggingSequenceNumber];
+ GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
+ GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number);
+ GdkModifierType state = _gdk_macos_display_get_current_keyboard_modifiers (GDK_MACOS_DISPLAY (display));
+
+ _gdk_macos_drag_set_actions (GDK_MACOS_DRAG (drag), state);
+
+ return _gdk_macos_drag_operation (GDK_MACOS_DRAG (drag));
+}
+
+- (void)draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint
+{
+ NSInteger sequence_number = [session draggingSequenceNumber];
+ GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
+ GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number);
+ int x, y;
+
+ _gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (display), screenPoint.x, screenPoint.y, &x, &y);
+ _gdk_macos_drag_set_start_position (GDK_MACOS_DRAG (drag), x, y);
+ _gdk_macos_drag_surface_move (GDK_MACOS_DRAG (drag), x, y);
+}
+
+- (void)draggingSession:(NSDraggingSession *)session movedToPoint:(NSPoint)screenPoint
+{
+ NSInteger sequence_number = [session draggingSequenceNumber];
+ GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
+ GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number);
+ int x, y;
+
+ _gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (display), screenPoint.x, screenPoint.y, &x, &y);
+ _gdk_macos_drag_surface_move (GDK_MACOS_DRAG (drag), x, y);
+}
+
+- (void)draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation
+{
+ NSInteger sequence_number = [session draggingSequenceNumber];
+ GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
+ GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number);
+
+ if (gdk_drag_get_selected_action (drag) != 0)
+ g_signal_emit_by_name (drag, "drop-performed");
+ else
+ gdk_drag_cancel (drag, GDK_DRAG_CANCEL_NO_TARGET);
+
+ _gdk_macos_display_set_drag (GDK_MACOS_DISPLAY (display), [session draggingSequenceNumber], NULL);
+}
+
// end
-(void)setStyleMask:(NSWindowStyleMask)styleMask
#define GDK_IS_MACOS_WINDOW(obj) ([obj isKindOfClass:[GdkMacosWindow class]])
-@interface GdkMacosWindow : NSWindow {
+@interface GdkMacosWindow : NSWindow <NSDraggingSource, NSDraggingDestination> {
GdkMacosSurface *gdk_surface;
BOOL inMove;
int x,
int y);
NSEvent *_gdk_macos_display_get_nsevent (GdkEvent *event);
+NSEvent *_gdk_macos_display_get_last_nsevent (void);
GdkDrag *_gdk_macos_display_find_drag (GdkMacosDisplay *self,
NSInteger sequence_number);
GdkDrop *_gdk_macos_display_find_drop (GdkMacosDisplay *self,
return NULL;
}
+NSEvent *
+_gdk_macos_display_get_last_nsevent ()
+{
+ const GdkToNSEventMap *map = g_queue_peek_tail (&event_map);
+ if (map)
+ return map->nsevent;
+
+ return NULL;
+}
+
GdkDrag *
_gdk_macos_display_find_drag (GdkMacosDisplay *self,
NSInteger sequence_number)
GdkDragClass parent_class;
};
-GType gdk_macos_drag_get_type (void) G_GNUC_CONST;
-gboolean _gdk_macos_drag_begin (GdkMacosDrag *self);
+GType gdk_macos_drag_get_type (void) G_GNUC_CONST;
+gboolean _gdk_macos_drag_begin (GdkMacosDrag *self,
+ GdkContentProvider *content,
+ GdkMacosWindow *window);
+NSDragOperation _gdk_macos_drag_operation (GdkMacosDrag *self);
+void _gdk_macos_drag_surface_move (GdkMacosDrag *self,
+ int x_root,
+ int y_root);
+void _gdk_macos_drag_set_start_position (GdkMacosDrag *self,
+ int start_x,
+ int start_y);
+void _gdk_macos_drag_set_actions (GdkMacosDrag *self,
+ GdkModifierType mods);
+
G_END_DECLS
#include "gdkmacoscursor-private.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacosdragsurface-private.h"
+#include "gdkmacospasteboard-private.h"
#include "gdk/gdkdeviceprivate.h"
#include "gdk/gdkeventsprivate.h"
}
gboolean
-_gdk_macos_drag_begin (GdkMacosDrag *self)
+_gdk_macos_drag_begin (GdkMacosDrag *self,
+ GdkContentProvider *content,
+ GdkMacosWindow *window)
{
+ NSArray<NSDraggingItem *> *items;
+ NSDraggingSession *session;
+ NSPasteboardItem *item;
+ NSEvent *nsevent;
+
g_return_val_if_fail (GDK_IS_MACOS_DRAG (self), FALSE);
+ g_return_val_if_fail (GDK_IS_MACOS_WINDOW (window), FALSE);
+
+ GDK_BEGIN_MACOS_ALLOC_POOL;
+
+ item = [[GdkMacosPasteboardItem alloc] initForDrag:GDK_DRAG (self) withContentProvider:content];
+ items = [NSArray arrayWithObject:item];
+ nsevent = _gdk_macos_display_get_last_nsevent ();
+
+ session = [[window contentView] beginDraggingSessionWithItems:items
+ event:nsevent
+ source:window];
+
+ GDK_END_MACOS_ALLOC_POOL;
+
+ _gdk_macos_display_set_drag (GDK_MACOS_DISPLAY (gdk_drag_get_display (GDK_DRAG (self))),
+ [session draggingSequenceNumber],
+ GDK_DRAG (self));
+
+ return TRUE;
+}
+
+NSDragOperation
+_gdk_macos_drag_operation (GdkMacosDrag *self)
+{
+ NSDragOperation operation = NSDragOperationNone;
+ GdkDragAction actions;
- _gdk_macos_surface_show (GDK_MACOS_SURFACE (self->drag_surface));
+ g_return_val_if_fail (GDK_IS_MACOS_DRAG (self), NSDragOperationNone);
+
+ actions = gdk_drag_get_actions (GDK_DRAG (self));
+
+ if (actions & GDK_ACTION_LINK)
+ operation |= NSDragOperationLink;
+
+ if (actions & GDK_ACTION_MOVE)
+ operation |= NSDragOperationMove;
+
+ if (actions & GDK_ACTION_COPY)
+ operation |= NSDragOperationCopy;
+
+ return operation;
+}
+
+void
+_gdk_macos_drag_surface_move (GdkMacosDrag *self,
+ int x_root,
+ int y_root)
+{
+ g_return_if_fail (GDK_IS_MACOS_DRAG (self));
+
+ self->last_x = x_root;
+ self->last_y = y_root;
+
+ 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);
+}
+
+void
+_gdk_macos_drag_set_start_position (GdkMacosDrag *self,
+ int start_x,
+ int start_y)
+{
+ g_return_if_fail (GDK_IS_MACOS_DRAG (self));
+
+ self->start_x = start_x;
+ self->start_y = start_y;
+}
+
+void
+_gdk_macos_drag_set_actions (GdkMacosDrag *self,
+ GdkModifierType mods)
+{
+ GdkDragAction suggested_action;
+ GdkDragAction possible_actions;
+
+ g_assert (GDK_IS_MACOS_DRAG (self));
+
+ gdk_drag_get_current_actions (mods,
+ GDK_BUTTON_PRIMARY,
+ gdk_drag_get_actions (GDK_DRAG (self)),
+ &suggested_action,
+ &possible_actions);
- return drag_grab (self);
+ gdk_drag_set_selected_action (GDK_DRAG (self), suggested_action);
+ gdk_drag_set_actions (GDK_DRAG (self), possible_actions);
}
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))
{
g_object_unref (drag);
return NULL;