From c78b11011060511104ff922f12471f820b604ccd Mon Sep 17 00:00:00 2001 From: Vlad K Date: Wed, 7 Jun 2017 17:56:46 +0300 Subject: [PATCH] MacOS d&d support --- .../Platform/MacOS/Cocoa/NSDragOperation.cs | 46 ++++++++++++++++ .../Platform/MacOS/CocoaNativeWindow.cs | 55 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 Source/OpenTK/Platform/MacOS/Cocoa/NSDragOperation.cs diff --git a/Source/OpenTK/Platform/MacOS/Cocoa/NSDragOperation.cs b/Source/OpenTK/Platform/MacOS/Cocoa/NSDragOperation.cs new file mode 100644 index 00000000..8babb01e --- /dev/null +++ b/Source/OpenTK/Platform/MacOS/Cocoa/NSDragOperation.cs @@ -0,0 +1,46 @@ +#region License +// +// NSEventType.cs +// +// Author: +// Olle Håkansson +// +// Copyright (c) 2014 Olle Håkansson +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#endregion + +using System; + +namespace OpenTK.Platform.MacOS +{ + enum NSDragOperation : int + { + None = 0, + Copy = 1, + Link = 2, + Generic = 4, + Private = 8, + AllObsolete = 15, + Move = 16, + Delete = 32, + Every = Int32.MaxValue, + } +} \ No newline at end of file diff --git a/src/OpenTK/Platform/MacOS/CocoaNativeWindow.cs b/src/OpenTK/Platform/MacOS/CocoaNativeWindow.cs index 0795e1cb..c1155678 100644 --- a/src/OpenTK/Platform/MacOS/CocoaNativeWindow.cs +++ b/src/OpenTK/Platform/MacOS/CocoaNativeWindow.cs @@ -38,6 +38,9 @@ using System.Threading; using OpenTK.Graphics; using OpenTK.Input; +//using MonoMac.AppKit; +//using MonoMac.Foundation; + namespace OpenTK.Platform.MacOS { class CocoaNativeWindow : NativeWindowBase @@ -116,6 +119,7 @@ namespace OpenTK.Platform.MacOS static readonly IntPtr NSImage; static readonly IntPtr NSBitmapImageRep; static readonly IntPtr NSDeviceRGBColorSpace = Cocoa.ToNSString("NSDeviceRGBColorSpace"); + static readonly IntPtr NSFilenamesPboardType; static CocoaNativeWindow() { @@ -125,6 +129,7 @@ namespace OpenTK.Platform.MacOS NSCursor = Class.Get("NSCursor"); NSImage = Class.Get("NSImage"); NSBitmapImageRep = Class.Get("NSBitmapImageRep"); + NSFilenamesPboardType = Cocoa.GetStringConstant(Cocoa.AppKitLibrary, "NSFilenamesPboardType"); } private CocoaWindowInfo windowInfo; @@ -165,6 +170,8 @@ namespace OpenTK.Platform.MacOS CanBecomeKeyWindowHandler = CanBecomeKeyWindow; CanBecomeMainWindowHandler = CanBecomeMainWindow; ResetCursorRectsHandler = ResetCursorRects; + PerformDragOperationHandler = PerformDragOperation; + DraggingEnteredHandler = DraggingEntered; // Create the window class int unique_id = Interlocked.Increment(ref UniqueId); @@ -182,6 +189,9 @@ namespace OpenTK.Platform.MacOS Class.RegisterMethod(windowClass, AcceptsFirstResponderHandler, "acceptsFirstResponder", "b@:"); Class.RegisterMethod(windowClass, CanBecomeKeyWindowHandler, "canBecomeKeyWindow", "b@:"); Class.RegisterMethod(windowClass, CanBecomeMainWindowHandler, "canBecomeMainWindow", "b@:"); + Class.RegisterMethod(windowClass, DraggingEnteredHandler, "draggingEntered:", "@@:@"); + Class.RegisterMethod(windowClass, PerformDragOperationHandler, "performDragOperation:", "b@:@"); + Class.RegisterClass(windowClass); IntPtr viewClass = Class.AllocateClass("OpenTK_NSView" + unique_id, "NSView"); @@ -257,6 +267,16 @@ namespace OpenTK.Platform.MacOS exists = true; NSApplication.Quit += ApplicationQuit; + + // Enable drag and drop + Cocoa.SendIntPtr( + windowPtr, + Selector.Get("registerForDraggedTypes:"), + Cocoa.SendIntPtr( + Class.Get("NSArray"), + Selector.Get("arrayWithObjects:"), + NSFilenamesPboardType, + IntPtr.Zero)); } [UnmanagedFunctionPointer(CallingConvention.Winapi)] @@ -287,6 +307,10 @@ namespace OpenTK.Platform.MacOS delegate bool CanBecomeMainWindowDelegate(IntPtr self, IntPtr cmd); [UnmanagedFunctionPointer(CallingConvention.Winapi)] delegate void ResetCursorRectsDelegate(IntPtr self, IntPtr cmd); + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + delegate IntPtr DraggingEnteredDelegate(IntPtr self, IntPtr cmd, IntPtr sender); + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + delegate bool PerformDragOperationDelegate(IntPtr self, IntPtr cmd, IntPtr sender); WindowKeyDownDelegate WindowKeyDownHandler; WindowDidResizeDelegate WindowDidResizeHandler; @@ -302,6 +326,37 @@ namespace OpenTK.Platform.MacOS CanBecomeKeyWindowDelegate CanBecomeKeyWindowHandler; CanBecomeMainWindowDelegate CanBecomeMainWindowHandler; ResetCursorRectsDelegate ResetCursorRectsHandler; + DraggingEnteredDelegate DraggingEnteredHandler; + PerformDragOperationDelegate PerformDragOperationHandler; + + private IntPtr DraggingEntered(IntPtr self, IntPtr cmd, IntPtr sender) + { + int mask = Cocoa.SendInt(sender, Selector.Get("draggingSourceOperationMask")); + + if ((mask & (int)NSDragOperation.Generic) == (int)NSDragOperation.Generic) + { + return new IntPtr((int)NSDragOperation.Generic); + } + + return new IntPtr((int)NSDragOperation.None); + } + + private bool PerformDragOperation(IntPtr self, IntPtr cmd, IntPtr sender) + { + IntPtr pboard = Cocoa.SendIntPtr(sender, Selector.Get("draggingPasteboard")); + + IntPtr files = Cocoa.SendIntPtr(pboard, Selector.Get("propertyListForType:"), NSFilenamesPboardType); + + int count = Cocoa.SendInt(files, Selector.Get("count")); + for (int i = 0; i < count; ++i) + { + IntPtr obj = Cocoa.SendIntPtr(files, Selector.Get("objectAtIndex:"), new IntPtr(i)); + IntPtr str = Cocoa.SendIntPtr(obj, Selector.Get("cStringUsingEncoding:"), new IntPtr(1)); + OnDrop(Marshal.PtrToStringAnsi(str)); + } + + return true; + } private void WindowKeyDown(IntPtr self, IntPtr cmd, IntPtr notification) {