Browse Source

[OSX] Move Drag and Drop logic to TopLevelImpl (#19731)

* Move Drag and Drop logic to TopLevelImpl

* Update src/Avalonia.Native/TopLevelImpl.cs

Co-authored-by: Max Katz <maxkatz6@outlook.com>

---------

Co-authored-by: Max Katz <maxkatz6@outlook.com>
Co-authored-by: Benedikt Stebner <Gillibald@users.noreply.github.com>
pull/19739/head
Tim Miller 4 months ago
committed by GitHub
parent
commit
650aeb20c6
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 3
      native/Avalonia.Native/src/OSX/TopLevelImpl.h
  2. 49
      native/Avalonia.Native/src/OSX/TopLevelImpl.mm
  3. 4
      native/Avalonia.Native/src/OSX/WindowBaseImpl.h
  4. 44
      native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
  5. 2
      src/Avalonia.Native/AvaloniaNativeDragSource.cs
  6. 19
      src/Avalonia.Native/TopLevelImpl.cs
  7. 6
      src/Avalonia.Native/WindowImplBase.cs
  8. 5
      src/Avalonia.Native/avn.idl

3
native/Avalonia.Native/src/OSX/TopLevelImpl.h

@ -60,6 +60,9 @@ public:
virtual HRESULT SetTransparencyMode(AvnWindowTransparencyMode mode) override;
virtual HRESULT GetCurrentDisplayId (CGDirectDisplayID* ret) override;
virtual HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
IAvnClipboard* clipboard, IAvnDndResultCallback* cb, void* sourceHandle) override;
protected:
NSCursor *cursor;
virtual void UpdateAppearance();

49
native/Avalonia.Native/src/OSX/TopLevelImpl.mm

@ -6,6 +6,7 @@
#include "TopLevelImpl.h"
#include "AvnTextInputMethod.h"
#include "AvnView.h"
#include "common.h"
TopLevelImpl::~TopLevelImpl() {
View = nullptr;
@ -271,6 +272,54 @@ void TopLevelImpl::UpdateAppearance() {
}
HRESULT TopLevelImpl::BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point, IAvnClipboard *clipboard, IAvnDndResultCallback *cb, void *sourceHandle) {
START_COM_CALL;
auto item = TryGetPasteboardItem(clipboard);
[item setString:@"" forType:GetAvnCustomDataType()];
if (item == nil)
return E_INVALIDARG;
if (View == NULL)
return E_FAIL;
auto nsevent = [NSApp currentEvent];
auto nseventType = [nsevent type];
// If current event isn't a mouse one (probably due to malfunctioning user app)
// attempt to forge a new one
if (!((nseventType >= NSEventTypeLeftMouseDown && nseventType <= NSEventTypeMouseExited)
|| (nseventType >= NSEventTypeOtherMouseDown && nseventType <= NSEventTypeOtherMouseDragged))) {
// For TopLevelImpl, we don't have a Window so we use the View's window
auto window = [View window];
if (window != nil) {
NSRect convertRect = [window convertRectToScreen:NSMakeRect(point.X, point.Y, 0.0, 0.0)];
auto nspoint = NSMakePoint(convertRect.origin.x, convertRect.origin.y);
CGPoint cgpoint = NSPointToCGPoint(nspoint);
auto cgevent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, cgpoint, kCGMouseButtonLeft);
nsevent = [NSEvent eventWithCGEvent:cgevent];
CFRelease(cgevent);
}
}
auto dragItem = [[NSDraggingItem alloc] initWithPasteboardWriter:item];
auto dragItemImage = [NSImage imageNamed:NSImageNameMultipleDocuments];
NSRect dragItemRect = {(float) point.X, (float) point.Y, [dragItemImage size].width, [dragItemImage size].height};
[dragItem setDraggingFrame:dragItemRect contents:dragItemImage];
int op = 0;
int ieffects = (int) effects;
if ((ieffects & (int) AvnDragDropEffects::Copy) != 0)
op |= NSDragOperationCopy;
if ((ieffects & (int) AvnDragDropEffects::Link) != 0)
op |= NSDragOperationLink;
if ((ieffects & (int) AvnDragDropEffects::Move) != 0)
op |= NSDragOperationMove;
[View beginDraggingSessionWithItems:@[dragItem] event:nsevent
source:CreateDraggingSource((NSDragOperation) op, cb, sourceHandle)];
return S_OK;
}
void TopLevelImpl::SetClientSize(NSSize size){
[View setFrameSize:size];
}

4
native/Avalonia.Native/src/OSX/WindowBaseImpl.h

@ -69,10 +69,6 @@ public:
virtual HRESULT SetFrameThemeVariant(AvnPlatformThemeVariant variant) override;
virtual HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
IAvnClipboard *clipboard, IAvnDndResultCallback *cb,
void *sourceHandle) override;
virtual HRESULT SetTransparencyMode(AvnWindowTransparencyMode mode) override;
virtual bool IsModal();

44
native/Avalonia.Native/src/OSX/WindowBaseImpl.mm

@ -411,50 +411,6 @@ HRESULT WindowBaseImpl::SetFrameThemeVariant(AvnPlatformThemeVariant variant) {
return S_OK;
}
HRESULT WindowBaseImpl::BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point, IAvnClipboard *clipboard, IAvnDndResultCallback *cb, void *sourceHandle) {
START_COM_CALL;
auto item = TryGetPasteboardItem(clipboard);
[item setString:@"" forType:GetAvnCustomDataType()];
if (item == nil)
return E_INVALIDARG;
if (View == NULL)
return E_FAIL;
auto nsevent = [NSApp currentEvent];
auto nseventType = [nsevent type];
// If current event isn't a mouse one (probably due to malfunctioning user app)
// attempt to forge a new one
if (!((nseventType >= NSEventTypeLeftMouseDown && nseventType <= NSEventTypeMouseExited)
|| (nseventType >= NSEventTypeOtherMouseDown && nseventType <= NSEventTypeOtherMouseDragged))) {
NSRect convertRect = [Window convertRectToScreen:NSMakeRect(point.X, point.Y, 0.0, 0.0)];
auto nspoint = NSMakePoint(convertRect.origin.x, convertRect.origin.y);
CGPoint cgpoint = NSPointToCGPoint(nspoint);
auto cgevent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, cgpoint, kCGMouseButtonLeft);
nsevent = [NSEvent eventWithCGEvent:cgevent];
CFRelease(cgevent);
}
auto dragItem = [[NSDraggingItem alloc] initWithPasteboardWriter:item];
auto dragItemImage = [NSImage imageNamed:NSImageNameMultipleDocuments];
NSRect dragItemRect = {(float) point.X, (float) point.Y, [dragItemImage size].width, [dragItemImage size].height};
[dragItem setDraggingFrame:dragItemRect contents:dragItemImage];
int op = 0;
int ieffects = (int) effects;
if ((ieffects & (int) AvnDragDropEffects::Copy) != 0)
op |= NSDragOperationCopy;
if ((ieffects & (int) AvnDragDropEffects::Link) != 0)
op |= NSDragOperationLink;
if ((ieffects & (int) AvnDragDropEffects::Move) != 0)
op |= NSDragOperationMove;
[View beginDraggingSessionWithItems:@[dragItem] event:nsevent
source:CreateDraggingSource((NSDragOperation) op, cb, sourceHandle)];
return S_OK;
}
bool WindowBaseImpl::IsModal() {
return false;
}

2
src/Avalonia.Native/AvaloniaNativeDragSource.cs

@ -36,7 +36,7 @@ namespace Avalonia.Native
{
// Sanity check
var tl = TopLevel.GetTopLevel(triggerEvent.Source as Visual);
var view = tl?.PlatformImpl as WindowBaseImpl;
var view = tl?.PlatformImpl as TopLevelImpl;
if (view == null)
throw new ArgumentException();

19
src/Avalonia.Native/TopLevelImpl.cs

@ -52,7 +52,7 @@ internal class MacOSTopLevelHandle : IPlatformHandle, IMacOSTopLevelPlatformHand
{
return Native.ObtainNSViewHandleRetained();
}
public IntPtr NSWindow => (Native as IAvnWindowBase)?.ObtainNSWindowHandle() ?? IntPtr.Zero;
public IntPtr GetNSWindowRetained()
@ -98,13 +98,18 @@ internal class TopLevelImpl : ITopLevelImpl, IFramebufferPlatformSurface
{
_handle = handle;
_savedLogicalSize = ClientSize;
_savedScaling = Native?.Scaling ?? 1;;
_savedScaling = Native?.Scaling ?? 1;
_nativeControlHost = new NativeControlHostImpl(Native!.CreateNativeControlHost());
_platformBehaviorInhibition = new PlatformBehaviorInhibition(Factory.CreatePlatformBehaviorInhibition());
_surfaces = new object[] { new GlPlatformSurface(Native), new MetalPlatformSurface(Native), this };
InputMethod = new AvaloniaNativeTextInputMethod(Native);
}
internal void BeginDraggingSession(AvnDragDropEffects effects, AvnPoint point, IAvnClipboard clipboard, IAvnDndResultCallback callback, IntPtr sourceHandle)
{
Native?.BeginDragAndDropOperation(effects, point, clipboard, callback, sourceHandle);
}
public double DesktopScaling => 1;
public IAvnTopLevel? Native => _handle?.Native;
@ -118,7 +123,7 @@ internal class TopLevelImpl : ITopLevelImpl, IFramebufferPlatformSurface
{
return default;
}
var s = Native.ClientSize;
return new Size(s.Width, s.Height);
@ -135,7 +140,7 @@ internal class TopLevelImpl : ITopLevelImpl, IFramebufferPlatformSurface
public Compositor Compositor => AvaloniaNativePlatform.Compositor;
public Action? Closed { get; set; }
public Action? LostFocus { get; set; }
public WindowTransparencyLevel TransparencyLevel
{
get => _transparencyLevel;
@ -397,7 +402,7 @@ internal class TopLevelImpl : ITopLevelImpl, IFramebufferPlatformSurface
{
throw new RenderTargetNotReadyException();
}
return new FramebufferRenderTarget(this, nativeRenderTarget);
}
@ -439,7 +444,7 @@ internal class TopLevelImpl : ITopLevelImpl, IFramebufferPlatformSurface
{
return;
}
var s = new Size(size->Width, size->Height);
_parent._savedLogicalSize = s;
_parent.Resized?.Invoke(s, (WindowResizeReason)reason);
@ -492,7 +497,7 @@ internal class TopLevelImpl : ITopLevelImpl, IFramebufferPlatformSurface
{
return AvnDragDropEffects.None;
}
IDataObject? dataObject = null;
if (dataObjectHandle != IntPtr.Zero)
dataObject = GCHandle.FromIntPtr(dataObjectHandle).Target as IDataObject;

6
src/Avalonia.Native/WindowImplBase.cs

@ -116,12 +116,6 @@ namespace Avalonia.Native
Native?.SetMinMaxSize(minSize.ToAvnSize(), maxSize.ToAvnSize());
}
internal void BeginDraggingSession(AvnDragDropEffects effects, AvnPoint point, IAvnClipboard clipboard,
IAvnDndResultCallback callback, IntPtr sourceHandle)
{
Native?.BeginDragAndDropOperation(effects, point, clipboard, callback, sourceHandle);
}
protected class WindowBaseEvents : TopLevelEvents, IAvnWindowBaseEvents
{
private readonly WindowBaseImpl _parent;

5
src/Avalonia.Native/avn.idl

@ -735,6 +735,9 @@ interface IAvnTopLevel : IUnknown
HRESULT SetTransparencyMode(AvnWindowTransparencyMode mode);
HRESULT GetCurrentDisplayId(uint* ret);
HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
IAvnClipboard* clipboard, IAvnDndResultCallback* cb, [intptr]void* sourceHandle);
}
[uuid(e5aca675-02b7-4129-aa79-d6e417210bda), cpp-virtual-inherits]
@ -757,8 +760,6 @@ interface IAvnWindowBase : IAvnTopLevel
HRESULT SetMainMenu(IAvnMenu* menu);
HRESULT ObtainNSWindowHandle([intptr]void** retOut);
HRESULT ObtainNSWindowHandleRetained([intptr]void** retOut);
HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
IAvnClipboard* clipboard, IAvnDndResultCallback* cb, [intptr]void* sourceHandle);
}
[uuid(83e588f3-6981-4e48-9ea0-e1e569f79a91), cpp-virtual-inherits]

Loading…
Cancel
Save