committed by
GitHub
19 changed files with 712 additions and 81 deletions
@ -0,0 +1,89 @@ |
|||||
|
#include "common.h" |
||||
|
|
||||
|
extern AvnDragDropEffects ConvertDragDropEffects(NSDragOperation nsop) |
||||
|
{ |
||||
|
int effects = 0; |
||||
|
if((nsop & NSDragOperationCopy) != 0) |
||||
|
effects |= (int)AvnDragDropEffects::Copy; |
||||
|
if((nsop & NSDragOperationMove) != 0) |
||||
|
effects |= (int)AvnDragDropEffects::Move; |
||||
|
if((nsop & NSDragOperationLink) != 0) |
||||
|
effects |= (int)AvnDragDropEffects::Link; |
||||
|
return (AvnDragDropEffects)effects; |
||||
|
}; |
||||
|
|
||||
|
extern NSString* GetAvnCustomDataType() |
||||
|
{ |
||||
|
char buffer[256]; |
||||
|
sprintf(buffer, "net.avaloniaui.inproc.uti.n%in", getpid()); |
||||
|
return [NSString stringWithUTF8String:buffer]; |
||||
|
} |
||||
|
|
||||
|
@interface AvnDndSource : NSObject<NSDraggingSource> |
||||
|
|
||||
|
@end |
||||
|
|
||||
|
@implementation AvnDndSource |
||||
|
{ |
||||
|
NSDragOperation _operation; |
||||
|
ComPtr<IAvnDndResultCallback> _cb; |
||||
|
void* _sourceHandle; |
||||
|
}; |
||||
|
|
||||
|
- (NSDragOperation)draggingSession:(nonnull NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context |
||||
|
{ |
||||
|
return NSDragOperationCopy; |
||||
|
} |
||||
|
|
||||
|
- (AvnDndSource*) initWithOperation: (NSDragOperation)operation |
||||
|
andCallback: (IAvnDndResultCallback*) cb |
||||
|
andSourceHandle: (void*) handle |
||||
|
{ |
||||
|
self = [super init]; |
||||
|
_operation = operation; |
||||
|
_cb = cb; |
||||
|
_sourceHandle = handle; |
||||
|
return self; |
||||
|
} |
||||
|
|
||||
|
- (void)draggingSession:(NSDraggingSession *)session |
||||
|
endedAtPoint:(NSPoint)screenPoint |
||||
|
operation:(NSDragOperation)operation |
||||
|
{ |
||||
|
if(_cb != nil) |
||||
|
{ |
||||
|
auto cb = _cb; |
||||
|
_cb = nil; |
||||
|
cb->OnDragAndDropComplete(ConvertDragDropEffects(operation)); |
||||
|
} |
||||
|
if(_sourceHandle != nil) |
||||
|
{ |
||||
|
FreeAvnGCHandle(_sourceHandle); |
||||
|
_sourceHandle = nil; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
- (void*) gcHandle |
||||
|
{ |
||||
|
return _sourceHandle; |
||||
|
} |
||||
|
|
||||
|
@end |
||||
|
|
||||
|
extern NSObject<NSDraggingSource>* CreateDraggingSource(NSDragOperation op, IAvnDndResultCallback* cb, void* handle) |
||||
|
{ |
||||
|
return [[AvnDndSource alloc] initWithOperation:op andCallback:cb andSourceHandle:handle]; |
||||
|
}; |
||||
|
|
||||
|
extern void* GetAvnDataObjectHandleFromDraggingInfo(NSObject<NSDraggingInfo>* info) |
||||
|
{ |
||||
|
id obj = [info draggingSource]; |
||||
|
if(obj == nil) |
||||
|
return nil; |
||||
|
if([obj isKindOfClass: [AvnDndSource class]]) |
||||
|
{ |
||||
|
auto src = (AvnDndSource*)obj; |
||||
|
return [src gcHandle]; |
||||
|
} |
||||
|
return nil; |
||||
|
} |
||||
@ -0,0 +1,76 @@ |
|||||
|
using System; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using System.Threading.Tasks; |
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Input; |
||||
|
using Avalonia.Input.Platform; |
||||
|
using Avalonia.Interactivity; |
||||
|
using Avalonia.Native.Interop; |
||||
|
using Avalonia.Platform; |
||||
|
using Avalonia.VisualTree; |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
class AvaloniaNativeDragSource : IPlatformDragSource |
||||
|
{ |
||||
|
private readonly IAvaloniaNativeFactory _factory; |
||||
|
|
||||
|
public AvaloniaNativeDragSource(IAvaloniaNativeFactory factory) |
||||
|
{ |
||||
|
_factory = factory; |
||||
|
} |
||||
|
|
||||
|
TopLevel FindRoot(IInteractive interactive) |
||||
|
{ |
||||
|
while (interactive != null && !(interactive is IVisual)) |
||||
|
interactive = interactive.InteractiveParent; |
||||
|
if (interactive == null) |
||||
|
return null; |
||||
|
var visual = (IVisual)interactive; |
||||
|
return visual.VisualRoot as TopLevel; |
||||
|
} |
||||
|
|
||||
|
class DndCallback : CallbackBase, IAvnDndResultCallback |
||||
|
{ |
||||
|
private TaskCompletionSource<DragDropEffects> _tcs; |
||||
|
|
||||
|
public DndCallback(TaskCompletionSource<DragDropEffects> tcs) |
||||
|
{ |
||||
|
_tcs = tcs; |
||||
|
} |
||||
|
public void OnDragAndDropComplete(AvnDragDropEffects effect) |
||||
|
{ |
||||
|
_tcs?.TrySetResult((DragDropEffects)effect); |
||||
|
_tcs = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public Task<DragDropEffects> DoDragDrop(PointerEventArgs triggerEvent, IDataObject data, DragDropEffects allowedEffects) |
||||
|
{ |
||||
|
// Sanity check
|
||||
|
var tl = FindRoot(triggerEvent.Source); |
||||
|
var view = tl?.PlatformImpl as WindowBaseImpl; |
||||
|
if (view == null) |
||||
|
throw new ArgumentException(); |
||||
|
|
||||
|
triggerEvent.Pointer.Capture(null); |
||||
|
|
||||
|
var tcs = new TaskCompletionSource<DragDropEffects>(); |
||||
|
|
||||
|
var clipboardImpl = _factory.CreateDndClipboard(); |
||||
|
using (var clipboard = new ClipboardImpl(clipboardImpl)) |
||||
|
using (var cb = new DndCallback(tcs)) |
||||
|
{ |
||||
|
if (data.Contains(DataFormats.Text)) |
||||
|
// API is synchronous, so it's OK
|
||||
|
clipboard.SetTextAsync(data.GetText()).Wait(); |
||||
|
|
||||
|
view.BeginDraggingSession((AvnDragDropEffects)allowedEffects, |
||||
|
triggerEvent.GetPosition(tl).ToAvnPoint(), clipboardImpl, cb, |
||||
|
GCHandle.ToIntPtr(GCHandle.Alloc(data))); |
||||
|
} |
||||
|
|
||||
|
return tcs.Task; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
using System.Runtime.InteropServices; |
||||
|
|
||||
|
namespace Avalonia.Native.Interop |
||||
|
{ |
||||
|
unsafe partial class IAvnString |
||||
|
{ |
||||
|
private string _managed; |
||||
|
|
||||
|
public string String |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
if (_managed == null) |
||||
|
{ |
||||
|
var ptr = Pointer(); |
||||
|
if (ptr == null) |
||||
|
return null; |
||||
|
_managed = System.Text.Encoding.UTF8.GetString((byte*)ptr.ToPointer(), Length()); |
||||
|
} |
||||
|
|
||||
|
return _managed; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override string ToString() => String; |
||||
|
} |
||||
|
|
||||
|
partial class IAvnStringArray |
||||
|
{ |
||||
|
public string[] ToStringArray() |
||||
|
{ |
||||
|
var arr = new string[Count]; |
||||
|
for(uint c = 0; c<arr.Length;c++) |
||||
|
using (var s = Get(c)) |
||||
|
arr[c] = s.String; |
||||
|
return arr; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue