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 71922a0b15..e44345cfbc 100644 --- a/src/Avalonia.Native.OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj +++ b/src/Avalonia.Native.OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj @@ -121,7 +121,7 @@ AB7A61E72147C814003C5833 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0830; + LastUpgradeCheck = 1000; ORGANIZATIONNAME = Avalonia; TargetAttributes = { AB7A61EE2147C814003C5833 = { @@ -176,15 +176,23 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -224,15 +232,23 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; diff --git a/src/Avalonia.Native.OSX/Avalonia.Native.OSX.xcodeproj/xcshareddata/xcschemes/Avalonia.Native.OSX.xcscheme b/src/Avalonia.Native.OSX/Avalonia.Native.OSX.xcodeproj/xcshareddata/xcschemes/Avalonia.Native.OSX.xcscheme index c094e29797..96588581bf 100644 --- a/src/Avalonia.Native.OSX/Avalonia.Native.OSX.xcodeproj/xcshareddata/xcschemes/Avalonia.Native.OSX.xcscheme +++ b/src/Avalonia.Native.OSX/Avalonia.Native.OSX.xcodeproj/xcshareddata/xcschemes/Avalonia.Native.OSX.xcscheme @@ -1,6 +1,6 @@ s_KeyMap = { - {0, A}, - {1, S}, + {kVK_ANSI_A, A}, + {kVK_ANSI_S, S}, {kVK_ANSI_D, D}, {kVK_ANSI_F, F}, {kVK_ANSI_H, H}, diff --git a/src/Avalonia.Native.OSX/Screens.mm b/src/Avalonia.Native.OSX/Screens.mm index 7cb3e157c7..bf6cb46e27 100644 --- a/src/Avalonia.Native.OSX/Screens.mm +++ b/src/Avalonia.Native.OSX/Screens.mm @@ -1,38 +1,46 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + #include "common.h" class Screens : public ComSingleObject { public: - virtual HRESULT GetScreenCount (int* ret) { - *ret = (int)[NSScreen screens].count; - - return S_OK; + @autoreleasepool + { + *ret = (int)[NSScreen screens].count; + + return S_OK; + } } virtual HRESULT GetScreen (int index, AvnScreen* ret) { - if(index < 0 || index >= [NSScreen screens].count) + @autoreleasepool { - return E_INVALIDARG; + if(index < 0 || index >= [NSScreen screens].count) + { + return E_INVALIDARG; + } + + auto screen = [[NSScreen screens] objectAtIndex:index]; + + ret->Bounds.X = [screen frame].origin.x; + ret->Bounds.Y = [screen frame].origin.y; + ret->Bounds.Height = [screen frame].size.height; + ret->Bounds.Width = [screen frame].size.width; + + ret->WorkingArea.X = [screen visibleFrame].origin.x; + ret->WorkingArea.Y = [screen visibleFrame].origin.y; + ret->WorkingArea.Height = [screen visibleFrame].size.height; + ret->WorkingArea.Width = [screen visibleFrame].size.width; + + ret->Primary = index == 0; + + return S_OK; } - - auto screen = [[NSScreen screens] objectAtIndex:index]; - - ret->Bounds.X = [screen frame].origin.x; - ret->Bounds.Y = [screen frame].origin.y; - ret->Bounds.Height = [screen frame].size.height; - ret->Bounds.Width = [screen frame].size.width; - - ret->WorkingArea.X = [screen visibleFrame].origin.x; - ret->WorkingArea.Y = [screen visibleFrame].origin.y; - ret->WorkingArea.Height = [screen visibleFrame].size.height; - ret->WorkingArea.Width = [screen visibleFrame].size.width; - - ret->Primary = index == 0; - - return S_OK; } }; diff --git a/src/Avalonia.Native.OSX/SystemDialogs.mm b/src/Avalonia.Native.OSX/SystemDialogs.mm index 4b5a995e56..e67df996f8 100644 --- a/src/Avalonia.Native.OSX/SystemDialogs.mm +++ b/src/Avalonia.Native.OSX/SystemDialogs.mm @@ -1,3 +1,6 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + #include "common.h" #include "window.h" diff --git a/src/Avalonia.Native.OSX/clipboard.mm b/src/Avalonia.Native.OSX/clipboard.mm index 9b3c64d4d3..5c0f483d98 100644 --- a/src/Avalonia.Native.OSX/clipboard.mm +++ b/src/Avalonia.Native.OSX/clipboard.mm @@ -1,3 +1,6 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + #include "common.h" class Clipboard : public ComSingleObject @@ -5,28 +8,34 @@ class Clipboard : public ComSingleObject public: virtual HRESULT GetText (void** retOut) { - @autoreleasepool { + @autoreleasepool + { NSString *str = [[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString]; *retOut = (void *)str.UTF8String; } + return S_OK; } virtual HRESULT SetText (char* text) { - @autoreleasepool { + @autoreleasepool + { NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; [pasteBoard clearContents]; [pasteBoard setString:@(text) forType:NSPasteboardTypeString]; } + return S_OK; } virtual HRESULT Clear() { - @autoreleasepool { + @autoreleasepool + { [[NSPasteboard generalPasteboard] clearContents]; } + return S_OK; } }; diff --git a/src/Avalonia.Native.OSX/common.h b/src/Avalonia.Native.OSX/common.h index b6c4107e93..7a60c52e15 100644 --- a/src/Avalonia.Native.OSX/common.h +++ b/src/Avalonia.Native.OSX/common.h @@ -1,3 +1,6 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + #ifndef common_h #define common_h #include "com.h" @@ -18,4 +21,5 @@ extern IAvnCursorFactory* CreateCursorFactory(); extern NSPoint ToNSPoint (AvnPoint p); extern AvnPoint ToAvnPoint (NSPoint p); extern AvnPoint ConvertPointY (AvnPoint p); +extern NSSize ToNSSize (AvnSize s); #endif diff --git a/src/Avalonia.Native.OSX/cursor.h b/src/Avalonia.Native.OSX/cursor.h index eb2ea5c92a..aefbfbb15f 100644 --- a/src/Avalonia.Native.OSX/cursor.h +++ b/src/Avalonia.Native.OSX/cursor.h @@ -1,10 +1,5 @@ -// -// cursor.h -// Avalonia.Native.OSX -// -// Created by ElBuda on 10/5/18. -// Copyright © 2018 Avalonia. All rights reserved. -// +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. #ifndef cursor_h #define cursor_h diff --git a/src/Avalonia.Native.OSX/cursor.mm b/src/Avalonia.Native.OSX/cursor.mm index 602da6f7de..ecd0bec8a9 100644 --- a/src/Avalonia.Native.OSX/cursor.mm +++ b/src/Avalonia.Native.OSX/cursor.mm @@ -1,3 +1,6 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + #include "common.h" #include "cursor.h" #include @@ -53,5 +56,8 @@ public: extern IAvnCursorFactory* CreateCursorFactory() { - return new CursorFactory(); + @autoreleasepool + { + return new CursorFactory(); + } } diff --git a/src/Avalonia.Native.OSX/main.mm b/src/Avalonia.Native.OSX/main.mm index ed08711f4d..adc17a588d 100644 --- a/src/Avalonia.Native.OSX/main.mm +++ b/src/Avalonia.Native.OSX/main.mm @@ -1,3 +1,6 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + //This file will contain actual IID structures #define COM_GUIDS_MATERIALIZE #include "common.h" @@ -125,40 +128,39 @@ extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative() return new AvaloniaNative(); }; +NSSize ToNSSize (AvnSize s) +{ + NSSize result; + result.width = s.Width; + result.height = s.Height; + + return result; +} + NSPoint ToNSPoint (AvnPoint p) { - @autoreleasepool - { - NSPoint result; - result.x = p.X; - result.y = p.Y; - - return result; - } + NSPoint result; + result.x = p.X; + result.y = p.Y; + + return result; } AvnPoint ToAvnPoint (NSPoint p) { - @autoreleasepool - { - AvnPoint result; - result.X = p.x; - result.Y = p.y; - - return result; - } + AvnPoint result; + result.X = p.x; + result.Y = p.y; + + return result; } - AvnPoint ConvertPointY (AvnPoint p) { - @autoreleasepool - { - auto sw = [NSScreen.screens objectAtIndex:0].frame; - - auto t = MAX(sw.origin.y, sw.origin.y + sw.size.height); - p.Y = t - p.Y; - - return p; - } + auto sw = [NSScreen.screens objectAtIndex:0].frame; + + auto t = MAX(sw.origin.y, sw.origin.y + sw.size.height); + p.Y = t - p.Y; + + return p; } diff --git a/src/Avalonia.Native.OSX/platformthreading.mm b/src/Avalonia.Native.OSX/platformthreading.mm index ed63bec2fa..0fa402e03c 100644 --- a/src/Avalonia.Native.OSX/platformthreading.mm +++ b/src/Avalonia.Native.OSX/platformthreading.mm @@ -1,3 +1,6 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + #include "common.h" class PlatformThreadingInterface; diff --git a/src/Avalonia.Native.OSX/window.h b/src/Avalonia.Native.OSX/window.h index e0aaa5bb4e..3a9ef22df1 100644 --- a/src/Avalonia.Native.OSX/window.h +++ b/src/Avalonia.Native.OSX/window.h @@ -1,10 +1,5 @@ -// -// window.h -// Avalonia.Native.OSX -// -// Created by Dan Walmsley on 23/09/2018. -// Copyright © 2018 Avalonia. All rights reserved. -// +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. #ifndef window_h #define window_h @@ -12,21 +7,21 @@ class WindowBaseImpl; @interface AvnView : NSView --(AvnView*) initWithParent: (WindowBaseImpl*) parent; --(NSEvent*) lastMouseDownEvent; +-(AvnView* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent; +-(NSEvent* _Nonnull) lastMouseDownEvent; -(AvnPoint) translateLocalPoint:(AvnPoint)pt; --(void) setSwRenderedFrame: (AvnFramebuffer*) fb dispose: (IUnknown*) dispose; +-(void) setSwRenderedFrame: (AvnFramebuffer* _Nonnull) fb dispose: (IUnknown* _Nonnull) dispose; @end @interface AvnWindow : NSWindow --(AvnWindow*) initWithParent: (WindowBaseImpl*) parent; +-(AvnWindow* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent; -(void) setCanBecomeKeyAndMain; --(void) pollModalSession: (nonnull NSModalSession) session; +-(void) pollModalSession: (NSModalSession _Nonnull) session; @end struct INSWindowHolder { - virtual AvnWindow* GetNSWindow () = 0; + virtual AvnWindow* _Nonnull GetNSWindow () = 0; }; struct IWindowStateChanged diff --git a/src/Avalonia.Native.OSX/window.mm b/src/Avalonia.Native.OSX/window.mm index fb81fbf89e..82c63845c5 100644 --- a/src/Avalonia.Native.OSX/window.mm +++ b/src/Avalonia.Native.OSX/window.mm @@ -1,3 +1,6 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + #include "common.h" #include "window.h" #include "KeyTransform.h" @@ -35,26 +38,37 @@ public: virtual HRESULT Show() { - SetPosition(lastPositionSet); - UpdateStyle(); - [Window makeKeyAndOrderFront:Window]; - return S_OK; + @autoreleasepool + { + SetPosition(lastPositionSet); + UpdateStyle(); + [Window makeKeyAndOrderFront:Window]; + + return S_OK; + } } virtual HRESULT Hide () { - if(Window != nullptr) + @autoreleasepool { - [Window orderOut:Window]; + if(Window != nullptr) + { + [Window orderOut:Window]; + } + + return S_OK; } - return S_OK; } virtual HRESULT Activate () { - if(Window != nullptr) + @autoreleasepool { - [Window makeKeyWindow]; + if(Window != nullptr) + { + [Window makeKeyWindow]; + } } return S_OK; @@ -62,129 +76,186 @@ public: virtual HRESULT SetTopMost (bool value) { - [Window setLevel: value ? NSFloatingWindowLevel : NSNormalWindowLevel]; - - return S_OK; + @autoreleasepool + { + [Window setLevel: value ? NSFloatingWindowLevel : NSNormalWindowLevel]; + + return S_OK; + } } virtual HRESULT Close() { - [Window close]; - return S_OK; + @autoreleasepool + { + [Window close]; + return S_OK; + } } virtual HRESULT GetClientSize(AvnSize* ret) { - if(ret == nullptr) - return E_POINTER; - auto frame = [View frame]; - ret->Width = frame.size.width; - ret->Height = frame.size.height; - return S_OK; + @autoreleasepool + { + if(ret == nullptr) + return E_POINTER; + auto frame = [View frame]; + ret->Width = frame.size.width; + ret->Height = frame.size.height; + return S_OK; + } } virtual HRESULT GetMaxClientSize(AvnSize* ret) { - if(ret == nullptr) - return E_POINTER; - - auto size = [NSScreen.screens objectAtIndex:0].frame.size; - - ret->Height = size.height; - ret->Width = size.width; - - return S_OK; + @autoreleasepool + { + if(ret == nullptr) + return E_POINTER; + + auto size = [NSScreen.screens objectAtIndex:0].frame.size; + + ret->Height = size.height; + ret->Width = size.width; + + return S_OK; + } } virtual HRESULT GetScaling (double* ret) { - if(ret == nullptr) - return E_POINTER; - - if(Window == nullptr) + @autoreleasepool { - *ret = 1; + if(ret == nullptr) + return E_POINTER; + + if(Window == nullptr) + { + *ret = 1; + return S_OK; + } + + *ret = [Window backingScaleFactor]; return S_OK; } + } + + virtual HRESULT SetMinMaxSize (AvnSize minSize, AvnSize maxSize) + { + @autoreleasepool + { + [Window setMinSize: ToNSSize(minSize)]; + [Window setMaxSize: ToNSSize(maxSize)]; - *ret = [Window backingScaleFactor]; - return S_OK; + return S_OK; + } } virtual HRESULT Resize(double x, double y) { - [Window setContentSize:NSSize{x, y}]; - return S_OK; + @autoreleasepool + { + [Window setContentSize:NSSize{x, y}]; + return S_OK; + } } - virtual void Invalidate (AvnRect rect) + virtual HRESULT Invalidate (AvnRect rect) { - [View setNeedsDisplayInRect:[View frame]]; + @autoreleasepool + { + [View setNeedsDisplayInRect:[View frame]]; + + return S_OK; + } } - virtual void BeginMoveDrag () + virtual HRESULT BeginMoveDrag () { - auto lastEvent = [View lastMouseDownEvent]; - - if(lastEvent == nullptr) + @autoreleasepool { - return; + auto lastEvent = [View lastMouseDownEvent]; + + if(lastEvent == nullptr) + { + return S_OK; + } + + [Window performWindowDragWithEvent:lastEvent]; + + return S_OK; } - - [Window performWindowDragWithEvent:lastEvent]; } + virtual HRESULT BeginResizeDrag (AvnWindowEdge edge) + { + return S_OK; + } virtual HRESULT GetPosition (AvnPoint* ret) { - if(ret == nullptr) + @autoreleasepool { - return E_POINTER; + if(ret == nullptr) + { + return E_POINTER; + } + + auto frame = [Window frame]; + + ret->X = frame.origin.x; + ret->Y = frame.origin.y + frame.size.height; + + *ret = ConvertPointY(*ret); + + return S_OK; } - - auto frame = [Window frame]; - - ret->X = frame.origin.x; - ret->Y = frame.origin.y + frame.size.height; - - *ret = ConvertPointY(*ret); - - return S_OK; } - virtual void SetPosition (AvnPoint point) + virtual HRESULT SetPosition (AvnPoint point) { - lastPositionSet = point; - [Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(point))]; + @autoreleasepool + { + lastPositionSet = point; + [Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(point))]; + + return S_OK; + } } virtual HRESULT PointToClient (AvnPoint point, AvnPoint* ret) { - if(ret == nullptr) + @autoreleasepool { - return E_POINTER; + if(ret == nullptr) + { + return E_POINTER; + } + + point = ConvertPointY(point); + auto viewPoint = [Window convertScreenToBase:ToNSPoint(point)]; + + *ret = [View translateLocalPoint:ToAvnPoint(viewPoint)]; + + return S_OK; } - - point = ConvertPointY(point); - auto viewPoint = [Window convertScreenToBase:ToNSPoint(point)]; - - *ret = [View translateLocalPoint:ToAvnPoint(viewPoint)]; - - return S_OK; } virtual HRESULT PointToScreen (AvnPoint point, AvnPoint* ret) { - if(ret == nullptr) + @autoreleasepool { - return E_POINTER; + if(ret == nullptr) + { + return E_POINTER; + } + + auto cocoaViewPoint = ToNSPoint([View translateLocalPoint:point]); + auto cocoaScreenPoint = [Window convertBaseToScreen:cocoaViewPoint]; + *ret = ConvertPointY(ToAvnPoint(cocoaScreenPoint)); + + return S_OK; } - - auto cocoaViewPoint = ToNSPoint([View translateLocalPoint:point]); - auto cocoaScreenPoint = [Window convertBaseToScreen:cocoaViewPoint]; - *ret = ConvertPointY(ToAvnPoint(cocoaScreenPoint)); - - return S_OK; } virtual HRESULT ThreadSafeSetSwRenderedFrame(AvnFramebuffer* fb, IUnknown* dispose) @@ -195,10 +266,13 @@ public: virtual HRESULT SetCursor(IAvnCursor* cursor) { - Cursor* avnCursor = dynamic_cast(cursor); - this->cursor = avnCursor->GetNative(); - UpdateCursor(); - return S_OK; + @autoreleasepool + { + Cursor* avnCursor = dynamic_cast(cursor); + this->cursor = avnCursor->GetNative(); + UpdateCursor(); + return S_OK; + } } virtual void UpdateCursor() @@ -841,75 +915,87 @@ private: virtual HRESULT SetCanResize(bool value) { - _canResize = value; - UpdateStyle(); - return S_OK; + @autoreleasepool + { + _canResize = value; + UpdateStyle(); + return S_OK; + } } virtual HRESULT SetHasDecorations(bool value) { - _hasDecorations = value; - UpdateStyle(); - return S_OK; + @autoreleasepool + { + _hasDecorations = value; + UpdateStyle(); + return S_OK; + } } virtual HRESULT GetWindowState (AvnWindowState*ret) { - if(ret == nullptr) - { - return E_POINTER; - } - - if([Window isMiniaturized]) - { - *ret = Minimized; - return S_OK; - } - - if([Window isZoomed]) + @autoreleasepool { - *ret = Maximized; + if(ret == nullptr) + { + return E_POINTER; + } + + if([Window isMiniaturized]) + { + *ret = Minimized; + return S_OK; + } + + if([Window isZoomed]) + { + *ret = Maximized; + return S_OK; + } + + *ret = Normal; + return S_OK; } - - *ret = Normal; - - return S_OK; } virtual HRESULT SetWindowState (AvnWindowState state) { - switch (state) { - case Maximized: - if([Window isMiniaturized]) - { - [Window deminiaturize:Window]; - } - - if(!IsZoomed()) - { - DoZoom(); - } - break; - - case Minimized: - [Window miniaturize:Window]; - break; - - default: - if([Window isMiniaturized]) - { - [Window deminiaturize:Window]; - } - - if(IsZoomed()) - { - DoZoom(); - } - break; + @autoreleasepool + { + switch (state) { + case Maximized: + if([Window isMiniaturized]) + { + [Window deminiaturize:Window]; + } + + if(!IsZoomed()) + { + DoZoom(); + } + break; + + case Minimized: + [Window miniaturize:Window]; + break; + + default: + if([Window isMiniaturized]) + { + [Window deminiaturize:Window]; + } + + if(IsZoomed()) + { + DoZoom(); + } + break; + } + + return S_OK; } - - return S_OK; } protected: @@ -939,6 +1025,9 @@ protected: extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events) { - IAvnWindow* ptr = dynamic_cast(new WindowImpl(events)); - return ptr; + @autoreleasepool + { + IAvnWindow* ptr = dynamic_cast(new WindowImpl(events)); + return ptr; + } } diff --git a/src/Avalonia.Native/AvaloniaNativePlatform.cs b/src/Avalonia.Native/AvaloniaNativePlatform.cs index 52692fbef4..6ba26d4923 100644 --- a/src/Avalonia.Native/AvaloniaNativePlatform.cs +++ b/src/Avalonia.Native/AvaloniaNativePlatform.cs @@ -1,11 +1,12 @@ -using System; +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; -using Avalonia.Controls; using Avalonia.Controls.Platform; using Avalonia.Input; using Avalonia.Input.Platform; -using Avalonia.Native; using Avalonia.Native.Interop; using Avalonia.Platform; using Avalonia.Rendering; @@ -73,8 +74,7 @@ namespace Avalonia.Native .Bind().ToConstant(new ClipboardImpl(_factory.CreateClipboard())) .Bind().ToConstant(new RenderLoop()) .Bind().ToConstant(new DefaultRenderTimer(60)) - .Bind().ToConstant(new SystemDialogs(_factory.CreateSystemDialogs())); - + .Bind().ToConstant(new SystemDialogs(_factory.CreateSystemDialogs())); } public IWindowImpl CreateWindow() @@ -126,22 +126,3 @@ namespace Avalonia.Native } } - -namespace Avalonia -{ - - public static class AvaloniaNativePlatformExtensions - { - public static T UseAvaloniaNative(this T builder, - string libraryPath = null, - Action configure = null) - where T : AppBuilderBase, new() - { - if (libraryPath == null) - builder.UseWindowingSubsystem(() => AvaloniaNativePlatform.Initialize(configure)); - else - builder.UseWindowingSubsystem(() => AvaloniaNativePlatform.Initialize(libraryPath, configure)); - return builder; - } - } -} diff --git a/src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs b/src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs new file mode 100644 index 0000000000..d455eb47bc --- /dev/null +++ b/src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs @@ -0,0 +1,29 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; +using Avalonia.Controls; +using Avalonia.Native; + +namespace Avalonia +{ + public static class AvaloniaNativePlatformExtensions + { + public static T UseAvaloniaNative(this T builder, + string libraryPath = null, + Action configure = null) + where T : AppBuilderBase, new() + { + if (libraryPath == null) + { + builder.UseWindowingSubsystem(() => AvaloniaNativePlatform.Initialize(configure)); + } + else + { + builder.UseWindowingSubsystem(() => AvaloniaNativePlatform.Initialize(libraryPath, configure)); + } + + return builder; + } + } +} diff --git a/src/Avalonia.Native/CallbackBase.cs b/src/Avalonia.Native/CallbackBase.cs index 5326f0e568..67c383f6ae 100644 --- a/src/Avalonia.Native/CallbackBase.cs +++ b/src/Avalonia.Native/CallbackBase.cs @@ -1,13 +1,16 @@ -using System; +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; using SharpGen.Runtime; namespace Avalonia.Native { public class CallbackBase : SharpGen.Runtime.IUnknown { - uint _refCount; - bool _disposed; - object _lock = new object(); + private uint _refCount; + private bool _disposed; + private readonly object _lock = new object(); private ShadowContainer _shadow; public CallbackBase() @@ -23,7 +26,10 @@ namespace Avalonia.Native lock (_lock) { if (_disposed && value != null) + { throw new ObjectDisposedException("CallbackBase"); + } + _shadow = value; } } @@ -32,17 +38,21 @@ namespace Avalonia.Native public uint AddRef() { lock (_lock) + { return ++_refCount; + } } public void Dispose() { lock (_lock) + { if (!_disposed) { _disposed = true; Release(); } + } } public uint Release() @@ -50,12 +60,14 @@ namespace Avalonia.Native lock (_lock) { _refCount--; + if (_refCount == 0) { Shadow?.Dispose(); Shadow = null; Destroyed(); } + return _refCount; } } diff --git a/src/Avalonia.Native/ClipboardImpl.cs b/src/Avalonia.Native/ClipboardImpl.cs index 011c3a2368..d54bc95fbb 100644 --- a/src/Avalonia.Native/ClipboardImpl.cs +++ b/src/Avalonia.Native/ClipboardImpl.cs @@ -1,18 +1,16 @@ -using System; -using System.IO; +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + using System.Threading.Tasks; using System.Runtime.InteropServices; -using Avalonia.Controls; -using Avalonia.Controls.Platform; using Avalonia.Input.Platform; -using Avalonia.Platform; using Avalonia.Native.Interop; namespace Avalonia.Native -{ +{ class ClipboardImpl : IClipboard { - IAvnClipboard _native; + private IAvnClipboard _native; public ClipboardImpl(IAvnClipboard native) { @@ -22,6 +20,7 @@ namespace Avalonia.Native public Task ClearAsync() { _native.Clear(); + return Task.CompletedTask; } @@ -29,14 +28,19 @@ namespace Avalonia.Native { var outPtr = _native.GetText(); var text = Marshal.PtrToStringAnsi(outPtr); + return Task.FromResult(text); } public Task SetTextAsync(string text) { _native.Clear(); - if(text != null) + + if (text != null) + { _native.SetText(text); + } + return Task.CompletedTask; } } diff --git a/src/Avalonia.Native/Cursor.cs b/src/Avalonia.Native/Cursor.cs index 3c65367c12..1093eca1a4 100644 --- a/src/Avalonia.Native/Cursor.cs +++ b/src/Avalonia.Native/Cursor.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; using Avalonia.Input; using Avalonia.Platform; using Avalonia.Native.Interop; diff --git a/src/Avalonia.Native/DeferredFramebuffer.cs b/src/Avalonia.Native/DeferredFramebuffer.cs index 395d9bb0d3..4bee59266c 100644 --- a/src/Avalonia.Native/DeferredFramebuffer.cs +++ b/src/Avalonia.Native/DeferredFramebuffer.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; using System.Runtime.InteropServices; using Avalonia.Native.Interop; using Avalonia.Platform; @@ -9,6 +12,7 @@ namespace Avalonia.Native public class DeferredFramebuffer : ILockedFramebuffer { private readonly Func, bool> _lockWindow; + public DeferredFramebuffer(Func, bool> lockWindow, int width, int height, Vector dpi) { @@ -28,7 +32,6 @@ namespace Avalonia.Native public Vector Dpi { get; set; } public PixelFormat Format { get; set; } - class Disposer : CallbackBase { private IntPtr _ptr; @@ -52,6 +55,7 @@ namespace Avalonia.Native { if (Address == IntPtr.Zero) return; + if (!_lockWindow(win => { var fb = new AvnFramebuffer @@ -67,10 +71,16 @@ namespace Avalonia.Native PixelFormat = (AvnPixelFormat)Format, Stride = RowBytes }; + using (var d = new Disposer(Address)) + { win.ThreadSafeSetSwRenderedFrame(ref fb, d); + } })) + { Marshal.FreeHGlobal(Address); + } + Address = IntPtr.Zero; } } diff --git a/src/Avalonia.Native/DeferredRendererProxy.cs b/src/Avalonia.Native/DeferredRendererProxy.cs index 099275eaa6..2abc371b21 100644 --- a/src/Avalonia.Native/DeferredRendererProxy.cs +++ b/src/Avalonia.Native/DeferredRendererProxy.cs @@ -1,6 +1,8 @@ -using System; +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; using System.Collections.Generic; -using Avalonia.Platform; using Avalonia.Rendering; using Avalonia.VisualTree; @@ -19,9 +21,9 @@ namespace Avalonia.Native AvaloniaLocator.Current.GetService().Remove(this); } + private DeferredRenderer _renderer; + private IRenderLoopTask _rendererTask; - DeferredRenderer _renderer; - IRenderLoopTask _rendererTask; public DeferredRendererProxy(IRenderRoot root) { _renderer = new DeferredRenderer(root, this); @@ -52,7 +54,10 @@ namespace Avalonia.Native public void Paint(Rect rect) { if (NeedsUpdate) + { Update(TimeSpan.FromMilliseconds(Environment.TickCount)); + } + Render(); } diff --git a/src/Avalonia.Native/DynLoader.cs b/src/Avalonia.Native/DynLoader.cs index 45355e5894..c9c064fb95 100644 --- a/src/Avalonia.Native/DynLoader.cs +++ b/src/Avalonia.Native/DynLoader.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; using System.Runtime.InteropServices; /* @@ -6,7 +9,6 @@ using System.Runtime.InteropServices; * Source is provided under MIT license for Avalonia project and derived works */ - namespace Avalonia.Native { internal interface IDynLoader @@ -37,10 +39,9 @@ namespace Avalonia.Native DlError = dlerror; } } + static class OsXImports { - - [DllImport("/usr/lib/libSystem.dylib")] private static extern IntPtr dlopen(string path, int flags); @@ -59,7 +60,6 @@ namespace Avalonia.Native } - [DllImport("libc")] static extern int uname(IntPtr buf); diff --git a/src/Avalonia.Native/Helpers.cs b/src/Avalonia.Native/Helpers.cs index 68b977d8b2..c9d1256e91 100644 --- a/src/Avalonia.Native/Helpers.cs +++ b/src/Avalonia.Native/Helpers.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + using Avalonia.Native.Interop; namespace Avalonia.Native @@ -15,6 +17,11 @@ namespace Avalonia.Native return new AvnPoint { X = pt.X, Y = pt.Y }; } + public static AvnSize ToAvnSize (this Size size) + { + return new AvnSize { Height = size.Height, Width = size.Width }; + } + public static Size ToAvaloniaSize (this AvnSize size) { return new Size(size.Width, size.Height); diff --git a/src/Avalonia.Native/IconLoader.cs b/src/Avalonia.Native/IconLoader.cs index a63c5c11e8..608c24d031 100644 --- a/src/Avalonia.Native/IconLoader.cs +++ b/src/Avalonia.Native/IconLoader.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + using System.IO; using Avalonia.Platform; diff --git a/src/Avalonia.Native/PlatformThreadingInterface.cs b/src/Avalonia.Native/PlatformThreadingInterface.cs index 7ba83940f5..514ddf03a9 100644 --- a/src/Avalonia.Native/PlatformThreadingInterface.cs +++ b/src/Avalonia.Native/PlatformThreadingInterface.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; using System.Threading; using Avalonia.Native.Interop; using Avalonia.Platform; diff --git a/src/Avalonia.Native/PopupImpl.cs b/src/Avalonia.Native/PopupImpl.cs index 8f662aa519..e02a4fa07f 100644 --- a/src/Avalonia.Native/PopupImpl.cs +++ b/src/Avalonia.Native/PopupImpl.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; using Avalonia.Native.Interop; using Avalonia.Platform; @@ -11,7 +14,9 @@ namespace Avalonia.Native public PopupImpl(IAvaloniaNativeFactory factory) { using (var e = new PopupEvents(this)) + { Init(_native = factory.CreatePopup(e), factory.CreateScreens()); + } } public override void Dispose() diff --git a/src/Avalonia.Native/ScreenImpl.cs b/src/Avalonia.Native/ScreenImpl.cs index ddee8cbc56..c956cb09ff 100644 --- a/src/Avalonia.Native/ScreenImpl.cs +++ b/src/Avalonia.Native/ScreenImpl.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; using Avalonia.Native.Interop; using Avalonia.Platform; diff --git a/src/Avalonia.Native/SystemDialogs.cs b/src/Avalonia.Native/SystemDialogs.cs index cb16ec1239..696322adb2 100644 --- a/src/Avalonia.Native/SystemDialogs.cs +++ b/src/Avalonia.Native/SystemDialogs.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; using System.Linq; using System.Runtime.InteropServices; using System.Threading.Tasks; diff --git a/src/Avalonia.Native/WindowImpl.cs b/src/Avalonia.Native/WindowImpl.cs index 8a2b0a2af4..75f92156b0 100644 --- a/src/Avalonia.Native/WindowImpl.cs +++ b/src/Avalonia.Native/WindowImpl.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; using Avalonia.Controls; using Avalonia.Native.Interop; using Avalonia.Platform; @@ -11,7 +14,9 @@ namespace Avalonia.Native public WindowImpl(IAvaloniaNativeFactory factory) { using (var e = new WindowEvents(this)) + { Init(_native = factory.CreateWindow(e), factory.CreateScreens()); + } } class WindowEvents : WindowBaseEvents, IAvnWindowEvents @@ -36,7 +41,6 @@ namespace Avalonia.Native return _native.ShowDialog(); } - public void CanResize(bool value) { _native.CanResize = value; @@ -67,10 +71,14 @@ namespace Avalonia.Native public void ShowTaskbarIcon(bool value) { + // NO OP On OSX } + public void SetIcon(IWindowIconImpl icon) { + // NO OP on OSX } + public Func Closing { get; set; } } } diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 90b31a97e1..7f455b078c 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; using System.Collections.Generic; using Avalonia.Controls; using Avalonia.Controls.Platform.Surfaces; @@ -291,36 +294,35 @@ namespace Avalonia.Native public Action Deactivated { get; set; } public Action Activated { get; set; } - #region Stubs + public void SetCursor(IPlatformHandle cursor) + { + var newCursor = cursor as AvaloniaNativeCursor; + newCursor = newCursor ?? (_cursorFactory.GetCursor(StandardCursorType.Arrow) as AvaloniaNativeCursor); + _native.Cursor = newCursor.Cursor; + } public Action PositionChanged { get; set; } public Action Input { get; set; } Action ScalingChanged { get; set; } - public IPlatformHandle Handle => new PlatformHandle(IntPtr.Zero, "NOT SUPPORTED"); + Action ITopLevelImpl.ScalingChanged { get; set; } public IScreenImpl Screen { get; private set; } - Action ITopLevelImpl.ScalingChanged { get; set; } + // TODO public void SetMinMaxSize(Size minSize, Size maxSize) { - } - - - public void SetCursor(IPlatformHandle cursor) - { - var newCursor = cursor as AvaloniaNativeCursor; - newCursor = newCursor ?? (_cursorFactory.GetCursor(StandardCursorType.Arrow) as AvaloniaNativeCursor); - _native.Cursor = newCursor.Cursor; + _native.SetMinMaxSize(minSize.ToAvnSize(), maxSize.ToAvnSize()); } public void BeginResizeDrag(WindowEdge edge) { + } - #endregion + public IPlatformHandle Handle => new PlatformHandle(IntPtr.Zero, "NOT SUPPORTED"); } } diff --git a/src/headers/avalonia-native-guids.h b/src/headers/avalonia-native-guids.h index 64fec729a2..439008fd4b 100644 --- a/src/headers/avalonia-native-guids.h +++ b/src/headers/avalonia-native-guids.h @@ -1,2 +1,5 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + #define COM_GUIDS_MATERIALIZE #include "avalonia-native.h" diff --git a/src/headers/avalonia-native.h b/src/headers/avalonia-native.h index da0ec5a060..eaa0571e7b 100644 --- a/src/headers/avalonia-native.h +++ b/src/headers/avalonia-native.h @@ -1,7 +1,9 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + #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; @@ -126,6 +128,18 @@ enum AvnStandardCursorType CursorDragLink, }; +enum AvnWindowEdge +{ + WindowEdgeNorthWest, + WindowEdgeNorth, + WindowEdgeNorthEast, + WindowEdgeWest, + WindowEdgeEast, + WindowEdgeSouthWest, + WindowEdgeSouth, + WindowEdgeSouthEast +}; + AVNCOM(IAvaloniaNativeFactory, 01) : virtual IUnknown { public: @@ -149,11 +163,13 @@ AVNCOM(IAvnWindowBase, 02) : virtual IUnknown virtual HRESULT GetClientSize(AvnSize*ret) = 0; virtual HRESULT GetMaxClientSize(AvnSize* ret) = 0; virtual HRESULT GetScaling(double*ret)=0; + virtual HRESULT SetMinMaxSize(AvnSize minSize, AvnSize maxSize) = 0; virtual HRESULT Resize(double width, double height) = 0; - virtual void Invalidate (AvnRect rect) = 0; - virtual void BeginMoveDrag () = 0; + virtual HRESULT Invalidate (AvnRect rect) = 0; + virtual HRESULT BeginMoveDrag () = 0; + virtual HRESULT BeginResizeDrag (AvnWindowEdge edge) = 0; virtual HRESULT GetPosition (AvnPoint*ret) = 0; - virtual void SetPosition (AvnPoint point) = 0; + virtual HRESULT SetPosition (AvnPoint point) = 0; virtual HRESULT PointToClient (AvnPoint point, AvnPoint*ret) = 0; virtual HRESULT PointToScreen (AvnPoint point, AvnPoint*ret) = 0; virtual HRESULT ThreadSafeSetSwRenderedFrame(AvnFramebuffer* fb, IUnknown* dispose) = 0; diff --git a/src/headers/com.h b/src/headers/com.h index 7b4b41c688..728cec3e05 100644 --- a/src/headers/com.h +++ b/src/headers/com.h @@ -1,3 +1,6 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + #pragma clang diagnostic push #pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection" #ifndef COM_H_INCLUDED diff --git a/src/headers/key.h b/src/headers/key.h index 12d283cc17..cdc9658e29 100644 --- a/src/headers/key.h +++ b/src/headers/key.h @@ -1,3 +1,6 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + #ifndef _KEY_H_ #define _KEY_H_