diff options
author | Bret Johnson <bret.johnson@microsoft.com> | 2022-03-16 07:37:39 +0300 |
---|---|---|
committer | Bret Johnson <bret.johnson@microsoft.com> | 2022-03-16 07:37:39 +0300 |
commit | 5e4abd898f9644bb4c2e836417895590f2faabea (patch) | |
tree | 34b748b37ea0161fd86bf103c14654e37b7aa8aa | |
parent | 9bea461cd0627be7fba3410f914f70df6d8e6b8e (diff) |
Use BeginDraggingSession for drag/drop
This allows sending the OnDragFinished notification
when the drag/drop is complete, in turn calling
DragOperation.Finished. Calling Finished is expected
for Xwt - it did before for Gtk and this makes
the Cocoa backend behave the same.
-rw-r--r-- | Xwt.XamMac/Xwt.Mac/ViewBackend.cs | 71 |
1 files changed, 57 insertions, 14 deletions
diff --git a/Xwt.XamMac/Xwt.Mac/ViewBackend.cs b/Xwt.XamMac/Xwt.Mac/ViewBackend.cs index f9848881..4d44b9dd 100644 --- a/Xwt.XamMac/Xwt.Mac/ViewBackend.cs +++ b/Xwt.XamMac/Xwt.Mac/ViewBackend.cs @@ -581,18 +581,29 @@ namespace Xwt.Mac public void DragStart (DragStartData sdata) { - var lo = Widget.ConvertPointToBase (new CGPoint (Widget.Bounds.X, Widget.Bounds.Y)); - lo = Widget.Window.ConvertBaseToScreen (lo); - var ml = NSEvent.CurrentMouseLocation; - var pb = NSPasteboard.FromName (NSPasteboard.NSDragPasteboardName); - if (pb == null) - throw new InvalidOperationException ("Could not get pasteboard"); if (sdata.Data == null) throw new ArgumentNullException ("data"); - InitPasteboard (pb, sdata.Data); - var img = (NSImage)sdata.ImageBackend; + + var pasteboardItem = new NSPasteboardItem(); + InitPasteboardItem(pasteboardItem, sdata.Data); + +#if false + var lo = Widget.ConvertPointToBase(new CGPoint(Widget.Bounds.X, Widget.Bounds.Y)); + lo = Widget.Window.ConvertBaseToScreen(lo); + var ml = NSEvent.CurrentMouseLocation; + var pos = new CGPoint (ml.X - lo.X - (float)sdata.HotX, lo.Y - ml.Y - (float)sdata.HotY + img.Size.Height); Widget.DragImage (img, pos, new CGSize (0, 0), NSApplication.SharedApplication.CurrentEvent, pb, Widget, true); +#endif + + var dragItem = new NSDraggingItem(pasteboardItem); + + var img = (NSImage)sdata.ImageBackend; + var frame = new CGRect(0, 0, img.Size.Width, img.Size.Height); + dragItem.SetDraggingFrame(frame, img); + + var draggingSource = new DraggingSource (this); + Widget.BeginDraggingSession(new[] { dragItem }, NSApplication.SharedApplication.CurrentEvent, draggingSource); } public void SetDragSource (TransferDataType[] types, DragDropAction dragAction) @@ -720,16 +731,20 @@ namespace Xwt.Mac eventSink.OnDragOver (args); }); } - - void InitPasteboard (NSPasteboard pb, TransferDataSource data) + + public virtual void OnDragFinished (DragFinishedEventArgs args) { - pb.ClearContents (); + ApplicationContext.InvokeUserCode(delegate { + eventSink.OnDragFinished (args); + }); + } + void InitPasteboardItem (NSPasteboardItem pasteboardItem, TransferDataSource data) + { foreach (var t in data.DataTypes) { // Support dragging text internally and externally if (t == TransferDataType.Text) { - pb.AddTypes(new string[] { NSPasteboard.NSStringType }, null); - pb.SetStringForType((string)data.GetValue(t), NSPasteboard.NSStringType); + pasteboardItem.SetStringForType((string)data.GetValue(t), NSPasteboard.NSStringType); } // For other well known types, we don't currently support dragging them else if (t == TransferDataType.Uri || t == TransferDataType.Image || t == TransferDataType.Rtf || t == TransferDataType.Html) @@ -738,7 +753,7 @@ namespace Xwt.Mac else { object value = data.GetValue (t); NSData serializedData = NSData.FromArray (TransferDataSource.SerializeValue (value)); - pb.SetDataForType (serializedData, t.Id); + pasteboardItem.SetDataForType (serializedData, t.Id); } } } @@ -895,6 +910,34 @@ namespace Xwt.Mac } } + class DraggingSource : NSDraggingSource + { + WeakReference<ViewBackend> weakViewBackend; + + public DraggingSource(ViewBackend viewBackend) + { + weakViewBackend = new WeakReference<ViewBackend>(viewBackend); + } + + [Export("draggingSession:willBeginAtPoint:")] + public void DraggingSessionWillBeginAtPoint(NSDraggingSession session, CGPoint screenPoint) + { + } + + [Export("draggingSession:endedAtPoint:operation:")] + public void DraggingSessionEndedAtPoint(NSDraggingSession session, CGPoint screenPoint, NSDragOperation operation) + { + if (weakViewBackend.TryGetTarget(out var viewBackend)) + { + bool deleteSource = operation == NSDragOperation.Move || operation == NSDragOperation.Delete; + var args = new DragFinishedEventArgs(deleteSource); + + viewBackend.OnDragFinished(args); + } + } + } + + #if false public class DragPasteboardDataProvider : NSObject, INSPasteboardItemDataProvider { |