From a5f857874bf6fe73d2ac62b4a9721ac56b030f35 Mon Sep 17 00:00:00 2001 From: ElBuda Date: Sun, 7 Oct 2018 07:32:11 -0700 Subject: [PATCH] Refactoring SetCursor impl --- .../project.pbxproj | 2 + src/Avalonia.Native.OSX/common.h | 2 +- src/Avalonia.Native.OSX/cursor.h | 33 ++++++ src/Avalonia.Native.OSX/cursor.mm | 101 ++++++++---------- src/Avalonia.Native.OSX/main.mm | 4 +- src/Avalonia.Native.OSX/window.mm | 20 ++-- src/Avalonia.Native/AvaloniaNativePlatform.cs | 2 +- src/Avalonia.Native/Cursor.cs | 25 +++-- src/Avalonia.Native/WindowImplBase.cs | 4 +- src/headers/avalonia-native.h | 13 ++- 10 files changed, 125 insertions(+), 81 deletions(-) create mode 100644 src/Avalonia.Native.OSX/cursor.h diff --git a/src/Avalonia.Native.OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj b/src/Avalonia.Native.OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj index 35f7965a7b..71922a0b15 100644 --- a/src/Avalonia.Native.OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj +++ b/src/Avalonia.Native.OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ 37E2330E21583241000CB7E2 /* KeyTransform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyTransform.mm; sourceTree = ""; }; 5B21A981216530F500CEE36E /* cursor.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cursor.mm; sourceTree = ""; }; 5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = clipboard.mm; sourceTree = ""; }; + 5BF943652167AD1D009CAE35 /* cursor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cursor.h; sourceTree = ""; }; AB00E4F62147CA920032A60A /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; AB661C1D2148230F00291242 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; AB661C1F2148286E00291242 /* window.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = window.mm; sourceTree = ""; }; @@ -58,6 +59,7 @@ AB7A61E62147C814003C5833 = { isa = PBXGroup; children = ( + 5BF943652167AD1D009CAE35 /* cursor.h */, 5B21A981216530F500CEE36E /* cursor.mm */, 5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */, 379A4506214D0F6500CC143D /* headers */, diff --git a/src/Avalonia.Native.OSX/common.h b/src/Avalonia.Native.OSX/common.h index c695e42dbd..b6c4107e93 100644 --- a/src/Avalonia.Native.OSX/common.h +++ b/src/Avalonia.Native.OSX/common.h @@ -13,7 +13,7 @@ extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events); extern IAvnSystemDialogs* CreateSystemDialogs(); extern IAvnScreens* CreateScreens(); extern IAvnClipboard* CreateClipboard(); -extern IAvnCursor* CreateCursor(); +extern IAvnCursorFactory* CreateCursorFactory(); extern NSPoint ToNSPoint (AvnPoint p); extern AvnPoint ToAvnPoint (NSPoint p); diff --git a/src/Avalonia.Native.OSX/cursor.h b/src/Avalonia.Native.OSX/cursor.h new file mode 100644 index 0000000000..eb2ea5c92a --- /dev/null +++ b/src/Avalonia.Native.OSX/cursor.h @@ -0,0 +1,33 @@ +// +// cursor.h +// Avalonia.Native.OSX +// +// Created by ElBuda on 10/5/18. +// Copyright © 2018 Avalonia. All rights reserved. +// + +#ifndef cursor_h +#define cursor_h + +#include "common.h" +#include + +class Cursor : public ComSingleObject +{ +private: + NSCursor * _native; + +public: + Cursor(NSCursor * cursor) + { + _native = cursor; + } + + NSCursor* GetNative() + { + return _native; + } +}; + +extern std::map s_cursorMap; +#endif /* cursor_h */ diff --git a/src/Avalonia.Native.OSX/cursor.mm b/src/Avalonia.Native.OSX/cursor.mm index b212df1696..3db01a3ca8 100644 --- a/src/Avalonia.Native.OSX/cursor.mm +++ b/src/Avalonia.Native.OSX/cursor.mm @@ -1,67 +1,56 @@ #include "common.h" +#include "cursor.h" +#include -class Cursor : public ComSingleObject +class CursorFactory : public ComSingleObject { + Cursor * arrowCursor = new Cursor([NSCursor arrowCursor]); + Cursor * crossCursor = new Cursor([NSCursor crosshairCursor]); + Cursor * resizeUpCursor = new Cursor([NSCursor resizeUpCursor]); + Cursor * resizeDownCursor = new Cursor([NSCursor resizeDownCursor]); + Cursor * dragCopyCursor = new Cursor([NSCursor dragCopyCursor]); + Cursor * dragLinkCursor = new Cursor([NSCursor dragLinkCursor]); + Cursor * pointingHandCursor = new Cursor([NSCursor pointingHandCursor]); + Cursor * contextualMenuCursor = new Cursor([NSCursor contextualMenuCursor]); + Cursor * IBeamCursor = new Cursor([NSCursor IBeamCursor]); + Cursor * resizeLeftCursor = new Cursor([NSCursor resizeLeftCursor]); + Cursor * resizeRightCursor = new Cursor([NSCursor resizeRightCursor]); + Cursor * operationNotAllowedCursor = new Cursor([NSCursor operationNotAllowedCursor]); + + std::map s_cursorMap = + { + { CursorArrow, arrowCursor }, + { CursorAppStarting, arrowCursor }, + { CursorWait, arrowCursor }, + { CursorTopLeftCorner, crossCursor }, + { CursorTopRightCorner, crossCursor }, + { CursorBottomLeftCorner, crossCursor }, + { CursorBottomRightCorner, crossCursor }, + { CursorCross, crossCursor }, + { CursorSizeAll, crossCursor }, + { CursorTopSide, resizeUpCursor }, + { CursorUpArrow, resizeUpCursor }, + { CursorBottomSize, resizeDownCursor }, + { CursorDragCopy, dragCopyCursor }, + { CursorDragMove, dragCopyCursor }, + { CursorDragLink, dragLinkCursor }, + { CursorHand, pointingHandCursor }, + { CursorHelp, contextualMenuCursor }, + { CursorIbeam, IBeamCursor }, + { CursorLeftSide, resizeLeftCursor }, + { CursorRightSide, resizeRightCursor }, + { CursorNo, operationNotAllowedCursor } + }; + public: - virtual HRESULT GetCursor (AvnStandardCursorType cursorType, void** ptr) + virtual HRESULT GetCursor (AvnStandardCursorType cursorType, IAvnCursor** retOut) { - NSCursor * cursor; - switch (cursorType) { - case CursorArrow: - case CursorAppStarting: - case CursorWait: - cursor = [NSCursor arrowCursor]; - break; - case CursorTopLeftCorner: - case CursorTopRightCorner: - case CursorBottomLeftCorner : - case CursorBottomRightCorner: - case CursorCross: - case CursorSizeAll: - cursor = [NSCursor crosshairCursor]; - break; - case CursorTopSide: - case CursorUpArrow: - cursor = [NSCursor resizeUpCursor]; - break; - case CursorBottomSize: - cursor = [NSCursor resizeDownCursor]; - break; - case CursorDragCopy: - case CursorDragMove: - cursor = [NSCursor dragCopyCursor]; - break; - case CursorDragLink: - cursor = [NSCursor dragLinkCursor]; - break; - case CursorHand: - cursor = [NSCursor pointingHandCursor]; - break; - case CursorHelp: - cursor = [NSCursor contextualMenuCursor]; - break; - case CursorIbeam: - cursor = [NSCursor IBeamCursor]; - break; - case CursorLeftSide: - cursor = [NSCursor resizeLeftCursor]; - break; - case CursorRightSide: - cursor = [NSCursor resizeRightCursor]; - break; - case CursorNo: - cursor = [NSCursor operationNotAllowedCursor]; - break; - default: - cursor = [NSCursor operationNotAllowedCursor]; - break; - } - *ptr = (__bridge void*)cursor; + *retOut = s_cursorMap[cursorType]; return S_OK; } }; -extern IAvnCursor* CreateCursor() +extern IAvnCursorFactory* CreateCursorFactory() { - return new Cursor(); + return new CursorFactory(); } diff --git a/src/Avalonia.Native.OSX/main.mm b/src/Avalonia.Native.OSX/main.mm index ccfa04f87f..ed08711f4d 100644 --- a/src/Avalonia.Native.OSX/main.mm +++ b/src/Avalonia.Native.OSX/main.mm @@ -113,9 +113,9 @@ public: return S_OK; } - virtual HRESULT CreateCursor(IAvnCursor** ppv) + virtual HRESULT CreateCursorFactory(IAvnCursorFactory** ppv) { - *ppv = ::CreateCursor(); + *ppv = ::CreateCursorFactory(); return S_OK; } }; diff --git a/src/Avalonia.Native.OSX/window.mm b/src/Avalonia.Native.OSX/window.mm index 2c07518a64..68bce1e014 100644 --- a/src/Avalonia.Native.OSX/window.mm +++ b/src/Avalonia.Native.OSX/window.mm @@ -1,15 +1,18 @@ #include "common.h" #include "window.h" #include "KeyTransform.h" +#include "cursor.h" class WindowBaseImpl : public ComSingleObject, public INSWindowHolder { +private: + NSCursor* cursor; + public: AvnView* View; AvnWindow* Window; ComPtr BaseEvents; AvnPoint lastPositionSet; - NSCursor* cursor; WindowBaseImpl(IAvnWindowBaseEvents* events) { @@ -190,24 +193,23 @@ public: return S_OK; } - virtual HRESULT SetCursor(void* ptr) + virtual HRESULT SetCursor(IAvnCursor* cursor) { - cursor = (__bridge NSCursor*)ptr; + Cursor* avnCursor = dynamic_cast(cursor); + this->cursor = avnCursor->GetNative(); UpdateCursor(); return S_OK; } - virtual HRESULT UpdateCursor() + virtual void UpdateCursor() { [View resetCursorRects]; - if (cursor != NULL) + if (cursor != nil) { auto rect = [Window frame]; [View addCursorRect:rect cursor:cursor]; -// if ([View isMouseOver]) - [cursor set]; + [cursor set]; } - return S_OK; } protected: @@ -286,6 +288,8 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent _area = [[NSTrackingArea alloc] initWithRect:rect options:options owner:self userInfo:nullptr]; [self addTrackingArea:_area]; + _parent->UpdateCursor(); + _parent->BaseEvents->Resized(AvnSize{newSize.width, newSize.height}); } diff --git a/src/Avalonia.Native/AvaloniaNativePlatform.cs b/src/Avalonia.Native/AvaloniaNativePlatform.cs index ead102d3d9..52692fbef4 100644 --- a/src/Avalonia.Native/AvaloniaNativePlatform.cs +++ b/src/Avalonia.Native/AvaloniaNativePlatform.cs @@ -64,7 +64,7 @@ namespace Avalonia.Native AvaloniaLocator.CurrentMutable .Bind().ToConstant(new PlatformThreadingInterface(_factory.CreatePlatformThreadingInterface())) - .Bind().ToTransient() + .Bind().ToConstant(new CursorFactory(_factory.CreateCursorFactory())) .Bind().ToSingleton() .Bind().ToConstant(KeyboardDevice) .Bind().ToConstant(MouseDevice) diff --git a/src/Avalonia.Native/Cursor.cs b/src/Avalonia.Native/Cursor.cs index 4f90fb8e59..3c65367c12 100644 --- a/src/Avalonia.Native/Cursor.cs +++ b/src/Avalonia.Native/Cursor.cs @@ -5,31 +5,38 @@ using Avalonia.Native.Interop; namespace Avalonia.Native { - class Cursor : IPlatformHandle + class AvaloniaNativeCursor : IPlatformHandle, IDisposable { - public IntPtr Handle { get; } + public IAvnCursor Cursor { get; private set; } + public IntPtr Handle => IntPtr.Zero; - public string HandleDescriptor => "NSCursor"; + public string HandleDescriptor => ""; - public Cursor(IntPtr handle) + public AvaloniaNativeCursor(IAvnCursor cursor) { - Handle = handle; + Cursor = cursor; + } + + public void Dispose() + { + Cursor.Dispose(); + Cursor = null; } } class CursorFactory : IStandardCursorFactory { - IAvnCursor _native; + IAvnCursorFactory _native; - public CursorFactory(IAvnCursor native) + public CursorFactory(IAvnCursorFactory native) { _native = native; } public IPlatformHandle GetCursor(StandardCursorType cursorType) { - var handle = _native.GetCursor((AvnStandardCursorType)cursorType); - return new Cursor( handle ); + var cursor = _native.GetCursor((AvnStandardCursorType)cursorType); + return new AvaloniaNativeCursor( cursor ); } } } diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 48ca95d28f..90b31a97e1 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -312,7 +312,9 @@ namespace Avalonia.Native public void SetCursor(IPlatformHandle cursor) { - _native.Cursor = (cursor ?? _cursorFactory.GetCursor(StandardCursorType.Arrow)).Handle; + var newCursor = cursor as AvaloniaNativeCursor; + newCursor = newCursor ?? (_cursorFactory.GetCursor(StandardCursorType.Arrow) as AvaloniaNativeCursor); + _native.Cursor = newCursor.Cursor; } public void BeginResizeDrag(WindowEdge edge) diff --git a/src/headers/avalonia-native.h b/src/headers/avalonia-native.h index 2da1ae5b0d..ed489f9d93 100644 --- a/src/headers/avalonia-native.h +++ b/src/headers/avalonia-native.h @@ -1,6 +1,7 @@ #include "com.h" #include "key.h" + #define AVNCOM(name, id) COMINTERFACE(name, 2e2cda0a, 9ae5, 4f1b, 8e, 20, 08, 1a, 04, 27, 9f, id) struct IAvnWindowEvents; @@ -13,6 +14,7 @@ struct IAvnSystemDialogs; struct IAvnScreens; struct IAvnClipboard; struct IAvnCursor; +struct IAvnCursorFactory; struct AvnSize { @@ -135,7 +137,7 @@ public: virtual HRESULT CreateSystemDialogs (IAvnSystemDialogs** ppv) = 0; virtual HRESULT CreateScreens (IAvnScreens** ppv) = 0; virtual HRESULT CreateClipboard(IAvnClipboard** ppv) = 0; - virtual HRESULT CreateCursor(IAvnCursor** ppv) = 0; + virtual HRESULT CreateCursorFactory(IAvnCursorFactory** ppv) = 0; }; AVNCOM(IAvnWindowBase, 02) : virtual IUnknown @@ -156,7 +158,7 @@ AVNCOM(IAvnWindowBase, 02) : virtual IUnknown virtual HRESULT PointToScreen (AvnPoint point, AvnPoint*ret) = 0; virtual HRESULT ThreadSafeSetSwRenderedFrame(AvnFramebuffer* fb, IUnknown* dispose) = 0; virtual HRESULT SetTopMost (bool value) = 0; - virtual HRESULT SetCursor(void* ptr) = 0; + virtual HRESULT SetCursor(IAvnCursor* cursor) = 0; }; AVNCOM(IAvnPopup, 03) : virtual IAvnWindowBase @@ -272,7 +274,12 @@ AVNCOM(IAvnClipboard, 0f) : virtual IUnknown AVNCOM(IAvnCursor, 10) : virtual IUnknown { - virtual HRESULT GetCursor (AvnStandardCursorType cursorType, void** retOut) = 0; }; +AVNCOM(IAvnCursorFactory, 11) : virtual IUnknown +{ + virtual HRESULT GetCursor (AvnStandardCursorType cursorType, IAvnCursor** retOut) = 0; +}; + + extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative();