Browse Source

Merge branch 'master' into transform-3d

pull/8184/head
Jumar Macato 4 years ago
committed by GitHub
parent
commit
4b4bd45fcd
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      build/ApiCompatAttributeExcludeList.txt
  2. 2
      build/CoreLibraries.props
  3. 5
      native/Avalonia.Native/inc/rendertarget.h
  4. 4
      native/Avalonia.Native/src/OSX/AutoFitContentView.h
  5. 6
      native/Avalonia.Native/src/OSX/AutoFitContentView.mm
  6. 30
      native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
  7. 11
      native/Avalonia.Native/src/OSX/AvnPanelWindow.mm
  8. 10
      native/Avalonia.Native/src/OSX/AvnView.h
  9. 10
      native/Avalonia.Native/src/OSX/AvnView.mm
  10. 223
      native/Avalonia.Native/src/OSX/AvnWindow.mm
  11. 4
      native/Avalonia.Native/src/OSX/INSWindowHolder.h
  12. 9
      native/Avalonia.Native/src/OSX/PopupImpl.h
  13. 61
      native/Avalonia.Native/src/OSX/PopupImpl.mm
  14. 1
      native/Avalonia.Native/src/OSX/ResizeScope.h
  15. 2
      native/Avalonia.Native/src/OSX/ResizeScope.mm
  16. 1
      native/Avalonia.Native/src/OSX/SystemDialogs.mm
  17. 57
      native/Avalonia.Native/src/OSX/WindowBaseImpl.h
  18. 194
      native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
  19. 6
      native/Avalonia.Native/src/OSX/WindowImpl.h
  20. 83
      native/Avalonia.Native/src/OSX/WindowImpl.mm
  21. 17
      native/Avalonia.Native/src/OSX/WindowInterfaces.h
  22. 21
      native/Avalonia.Native/src/OSX/WindowProtocol.h
  23. 3
      native/Avalonia.Native/src/OSX/automation.h
  24. 7
      native/Avalonia.Native/src/OSX/automation.mm
  25. 1
      native/Avalonia.Native/src/OSX/main.mm
  26. 1
      native/Avalonia.Native/src/OSX/menu.mm
  27. 1
      samples/BindingDemo/BindingDemo.csproj
  28. 2
      samples/ControlCatalog/ControlCatalog.csproj
  29. 3
      samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml
  30. 6
      samples/ControlCatalog/Pages/TextBoxPage.xaml
  31. 2
      samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
  32. 3
      samples/IntegrationTestApp/IntegrationTestApp.csproj
  33. 1
      samples/PlatformSanityChecks/PlatformSanityChecks.csproj
  34. 3
      samples/Previewer/Previewer.csproj
  35. 1
      samples/RenderDemo/RenderDemo.csproj
  36. 1
      samples/Sandbox/Sandbox.csproj
  37. 1
      samples/VirtualizationDemo/VirtualizationDemo.csproj
  38. 1
      samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj
  39. 1
      samples/interop/NativeEmbedSample/NativeEmbedSample.csproj
  40. 2
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  41. 2
      src/Avalonia.Base/Animation/IAnimation.cs
  42. 3
      src/Avalonia.Base/Animation/IAnimationSetter.cs
  43. 2
      src/Avalonia.Base/Animation/IAnimator.cs
  44. 4
      src/Avalonia.Base/Animation/IClock.cs
  45. 5
      src/Avalonia.Base/Animation/IGlobalClock.cs
  46. 2
      src/Avalonia.Base/Animation/ITransition.cs
  47. 6
      src/Avalonia.Base/Collections/AvaloniaList.cs
  48. 4
      src/Avalonia.Base/Controls/INameScope.cs
  49. 2
      src/Avalonia.Base/Controls/IPseudoClasses.cs
  50. 4
      src/Avalonia.Base/Controls/IResourceHost.cs
  51. 4
      src/Avalonia.Base/Controls/IResourceNode.cs
  52. 3
      src/Avalonia.Base/Controls/ISetInheritanceParent.cs
  53. 4
      src/Avalonia.Base/Controls/ISetLogicalParent.cs
  54. 46
      src/Avalonia.Base/Data/Core/ExpressionNode.cs
  55. 2
      src/Avalonia.Base/Data/Core/IPropertyInfo.cs
  56. 19
      src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs
  57. 3
      src/Avalonia.Base/Data/IBinding.cs
  58. 5
      src/Avalonia.Base/DirectPropertyBase.cs
  59. 2
      src/Avalonia.Base/IAvaloniaObject.cs
  60. 3
      src/Avalonia.Base/IDataContextProvider.cs
  61. 1
      src/Avalonia.Base/IDirectPropertyAccessor.cs
  62. 3
      src/Avalonia.Base/IDirectPropertyMetadata.cs
  63. 4
      src/Avalonia.Base/IStyledElement.cs
  64. 3
      src/Avalonia.Base/IStyledPropertyMetadata.cs
  65. 3
      src/Avalonia.Base/Input/IAccessKeyHandler.cs
  66. 3
      src/Avalonia.Base/Input/IFocusManager.cs
  67. 2
      src/Avalonia.Base/Input/IInputDevice.cs
  68. 2
      src/Avalonia.Base/Input/IInputElement.cs
  69. 2
      src/Avalonia.Base/Input/IInputManager.cs
  70. 3
      src/Avalonia.Base/Input/IInputRoot.cs
  71. 2
      src/Avalonia.Base/Input/IKeyboardDevice.cs
  72. 3
      src/Avalonia.Base/Input/IKeyboardNavigationHandler.cs
  73. 2
      src/Avalonia.Base/Input/IMainMenu.cs
  74. 2
      src/Avalonia.Base/Input/IMouseDevice.cs
  75. 3
      src/Avalonia.Base/Input/IPointer.cs
  76. 2
      src/Avalonia.Base/Input/IPointerDevice.cs
  77. 18
      src/Avalonia.Base/Input/InputElement.cs
  78. 2
      src/Avalonia.Base/Input/Platform/IClipboard.cs
  79. 2
      src/Avalonia.Base/Input/Platform/IPlatformDragSource.cs
  80. 5
      src/Avalonia.Base/Input/Raw/IDragDropDevice.cs
  81. 4
      src/Avalonia.Base/Input/TextInput/ITextInputMethodImpl.cs
  82. 2
      src/Avalonia.Base/Interactivity/IInteractive.cs
  83. 4
      src/Avalonia.Base/Layout/ILayoutManager.cs
  84. 3
      src/Avalonia.Base/Layout/ILayoutRoot.cs
  85. 4
      src/Avalonia.Base/Layout/ILayoutable.cs
  86. 20
      src/Avalonia.Base/Layout/Layoutable.cs
  87. 2
      src/Avalonia.Base/Layout/UniformGridLayout.cs
  88. 2
      src/Avalonia.Base/LogicalTree/ILogical.cs
  89. 5
      src/Avalonia.Base/LogicalTree/ILogicalRoot.cs
  90. 4
      src/Avalonia.Base/Media/ConicGradientBrush.cs
  91. 2
      src/Avalonia.Base/Media/IBrush.cs
  92. 5
      src/Avalonia.Base/Media/IConicGradientBrush.cs
  93. 2
      src/Avalonia.Base/Media/IDashStyle.cs
  94. 5
      src/Avalonia.Base/Media/IExperimentalAcrylicMaterial.cs
  95. 2
      src/Avalonia.Base/Media/IGradientBrush.cs
  96. 5
      src/Avalonia.Base/Media/IGradientStop.cs
  97. 4
      src/Avalonia.Base/Media/IImageBrush.cs
  98. 7
      src/Avalonia.Base/Media/ILinearGradientBrush.cs
  99. 2
      src/Avalonia.Base/Media/IMutableBrush.cs
  100. 5
      src/Avalonia.Base/Media/IMutableExperimentalAcrylicMaterial.cs

2
build/ApiCompatAttributeExcludeList.txt

@ -0,0 +1,2 @@
T:Avalonia.Metadata.NotClientImplementableAttribute
T:Avalonia.Metadata.UnstableAttribute

2
build/CoreLibraries.props

@ -3,8 +3,6 @@
<ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Base/Avalonia.Base.csproj" /> <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Base/Avalonia.Base.csproj" />
<ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Controls/Avalonia.Controls.csproj" /> <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Controls/Avalonia.Controls.csproj" />
<ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj" /> <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj" />
<ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj" />
<ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj" />
<ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.OpenGL/Avalonia.OpenGL.csproj" /> <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.OpenGL/Avalonia.OpenGL.csproj" />
<ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Dialogs/Avalonia.Dialogs.csproj" /> <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Dialogs/Avalonia.Dialogs.csproj" />
<ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Markup/Avalonia.Markup/Avalonia.Markup.csproj" /> <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Markup/Avalonia.Markup/Avalonia.Markup.csproj" />

5
native/Avalonia.Native/inc/rendertarget.h

@ -1,3 +1,8 @@
#pragma once
#include "com.h"
#include "comimpl.h"
#include "avalonia-native.h"
@protocol IRenderTarget @protocol IRenderTarget
-(void) setNewLayer: (CALayer*) layer; -(void) setNewLayer: (CALayer*) layer;

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

@ -3,8 +3,10 @@
// Copyright (c) 2022 Avalonia. All rights reserved. // Copyright (c) 2022 Avalonia. All rights reserved.
// //
#pragma once
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "avalonia-native.h" #include "avalonia-native.h"
@interface AutoFitContentView : NSView @interface AutoFitContentView : NSView
-(AutoFitContentView* _Nonnull) initWithContent: (NSView* _Nonnull) content; -(AutoFitContentView* _Nonnull) initWithContent: (NSView* _Nonnull) content;

6
native/Avalonia.Native/src/OSX/AutoFitContentView.mm

@ -4,7 +4,9 @@
// //
#include "AvnView.h" #include "AvnView.h"
#import "AutoFitContentView.h" #include "AutoFitContentView.h"
#include "WindowInterfaces.h"
#include "WindowProtocol.h"
@implementation AutoFitContentView @implementation AutoFitContentView
{ {
@ -83,7 +85,7 @@
_settingSize = true; _settingSize = true;
[super setFrameSize:newSize]; [super setFrameSize:newSize];
auto window = objc_cast<AvnWindow>([self window]); auto window = (id <AvnWindowProtocol>) [self window];
// TODO get actual titlebar size // TODO get actual titlebar size

30
native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj

@ -9,16 +9,22 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
18391068E48EF96E3DB5FDAB /* ResizeScope.mm in Sources */ = {isa = PBXBuildFile; fileRef = 18391E45702740FE9DD69695 /* ResizeScope.mm */; }; 18391068E48EF96E3DB5FDAB /* ResizeScope.mm in Sources */ = {isa = PBXBuildFile; fileRef = 18391E45702740FE9DD69695 /* ResizeScope.mm */; };
1839125F057B0A4EB1760058 /* WindowImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 183919BF108EB72A029F7671 /* WindowImpl.mm */; }; 1839125F057B0A4EB1760058 /* WindowImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 183919BF108EB72A029F7671 /* WindowImpl.mm */; };
183914E50CF6D2EFC1667F7C /* WindowInterfaces.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391DB45C7D892E61BF388C /* WindowInterfaces.h */; };
1839151F32D1BB1AB51A7BB6 /* AvnPanelWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = 18391884C7476DA4E53A492D /* AvnPanelWindow.mm */; };
183916173528EC2737DBE5E1 /* WindowBaseImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 183915BFF0E234CD3604A7CD /* WindowBaseImpl.h */; }; 183916173528EC2737DBE5E1 /* WindowBaseImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 183915BFF0E234CD3604A7CD /* WindowBaseImpl.h */; };
1839171DCC651B0638603AC4 /* INSWindowHolder.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391BBB7782C296D424071F /* INSWindowHolder.h */; }; 1839171DCC651B0638603AC4 /* INSWindowHolder.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391BBB7782C296D424071F /* INSWindowHolder.h */; };
1839179A55FC1421BEE83330 /* WindowBaseImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 18391676ECF0E983F4964357 /* WindowBaseImpl.mm */; }; 1839179A55FC1421BEE83330 /* WindowBaseImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 18391676ECF0E983F4964357 /* WindowBaseImpl.mm */; };
183919D91DB9AAB5D700C2EA /* WindowImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391CD090AA776E7E841AC9 /* WindowImpl.h */; }; 183919D91DB9AAB5D700C2EA /* WindowImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391CD090AA776E7E841AC9 /* WindowImpl.h */; };
18391AA7E0BBA74D184C5734 /* AutoFitContentView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1839166350F32661F3ABD70F /* AutoFitContentView.mm */; }; 18391AA7E0BBA74D184C5734 /* AutoFitContentView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1839166350F32661F3ABD70F /* AutoFitContentView.mm */; };
18391AC16726CBC45856233B /* AvnWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1839155B28B20FFB672D29C6 /* AvnWindow.mm */; };
18391AC65ADD7DDD33FBE737 /* PopupImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 183910513F396141938832B5 /* PopupImpl.h */; };
18391C28BF1823B5464FDD36 /* ResizeScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 1839171D898F9BFC1373631A /* ResizeScope.h */; }; 18391C28BF1823B5464FDD36 /* ResizeScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 1839171D898F9BFC1373631A /* ResizeScope.h */; };
18391CF07316F819E76B617C /* IWindowStateChanged.h in Headers */ = {isa = PBXBuildFile; fileRef = 183913C6BFD6856BD42D19FD /* IWindowStateChanged.h */; }; 18391CF07316F819E76B617C /* IWindowStateChanged.h in Headers */ = {isa = PBXBuildFile; fileRef = 183913C6BFD6856BD42D19FD /* IWindowStateChanged.h */; };
18391D4EB311BC7EF8B8C0A6 /* AvnView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1839132D0E2454D911F1D1F9 /* AvnView.mm */; }; 18391D4EB311BC7EF8B8C0A6 /* AvnView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1839132D0E2454D911F1D1F9 /* AvnView.mm */; };
18391D8CD1756DC858DC1A09 /* PopupImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 18391BB698579F40F1783F31 /* PopupImpl.mm */; };
18391E1381E2D5BFD60265A9 /* AutoFitContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391654EF0E7AB3D3AB4071 /* AutoFitContentView.h */; }; 18391E1381E2D5BFD60265A9 /* AutoFitContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391654EF0E7AB3D3AB4071 /* AutoFitContentView.h */; };
18391ED5F611FF62C45F196D /* AvnView.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391D1669284AD2EC9E866A /* AvnView.h */; }; 18391ED5F611FF62C45F196D /* AvnView.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391D1669284AD2EC9E866A /* AvnView.h */; };
18391F1E2411C79405A9943A /* WindowProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 1839122E037567BDD1D09DEB /* WindowProtocol.h */; };
1A002B9E232135EE00021753 /* app.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A002B9D232135EE00021753 /* app.mm */; }; 1A002B9E232135EE00021753 /* app.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A002B9D232135EE00021753 /* app.mm */; };
1A1852DC23E05814008F0DED /* deadlock.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A1852DB23E05814008F0DED /* deadlock.mm */; }; 1A1852DC23E05814008F0DED /* deadlock.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A1852DB23E05814008F0DED /* deadlock.mm */; };
1A3E5EA823E9E83B00EDE661 /* rendertarget.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A3E5EA723E9E83B00EDE661 /* rendertarget.mm */; }; 1A3E5EA823E9E83B00EDE661 /* rendertarget.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A3E5EA723E9E83B00EDE661 /* rendertarget.mm */; };
@ -40,24 +46,29 @@
AB00E4F72147CA920032A60A /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB00E4F62147CA920032A60A /* main.mm */; }; AB00E4F72147CA920032A60A /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB00E4F62147CA920032A60A /* main.mm */; };
AB1E522C217613570091CD71 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB1E522B217613570091CD71 /* OpenGL.framework */; }; AB1E522C217613570091CD71 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB1E522B217613570091CD71 /* OpenGL.framework */; };
AB661C1E2148230F00291242 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB661C1D2148230F00291242 /* AppKit.framework */; }; AB661C1E2148230F00291242 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB661C1D2148230F00291242 /* AppKit.framework */; };
AB661C202148286E00291242 /* window.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB661C1F2148286E00291242 /* window.mm */; };
AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */; }; AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */; };
BC11A5BE2608D58F0017BAD0 /* automation.h in Headers */ = {isa = PBXBuildFile; fileRef = BC11A5BC2608D58F0017BAD0 /* automation.h */; }; BC11A5BE2608D58F0017BAD0 /* automation.h in Headers */ = {isa = PBXBuildFile; fileRef = BC11A5BC2608D58F0017BAD0 /* automation.h */; };
BC11A5BF2608D58F0017BAD0 /* automation.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC11A5BD2608D58F0017BAD0 /* automation.mm */; }; BC11A5BF2608D58F0017BAD0 /* automation.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC11A5BD2608D58F0017BAD0 /* automation.mm */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
183910513F396141938832B5 /* PopupImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PopupImpl.h; sourceTree = "<group>"; };
1839122E037567BDD1D09DEB /* WindowProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowProtocol.h; sourceTree = "<group>"; };
1839132D0E2454D911F1D1F9 /* AvnView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnView.mm; sourceTree = "<group>"; }; 1839132D0E2454D911F1D1F9 /* AvnView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnView.mm; sourceTree = "<group>"; };
183913C6BFD6856BD42D19FD /* IWindowStateChanged.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IWindowStateChanged.h; sourceTree = "<group>"; }; 183913C6BFD6856BD42D19FD /* IWindowStateChanged.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IWindowStateChanged.h; sourceTree = "<group>"; };
1839155B28B20FFB672D29C6 /* AvnWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnWindow.mm; sourceTree = "<group>"; };
183915BFF0E234CD3604A7CD /* WindowBaseImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowBaseImpl.h; sourceTree = "<group>"; }; 183915BFF0E234CD3604A7CD /* WindowBaseImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowBaseImpl.h; sourceTree = "<group>"; };
18391654EF0E7AB3D3AB4071 /* AutoFitContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutoFitContentView.h; sourceTree = "<group>"; }; 18391654EF0E7AB3D3AB4071 /* AutoFitContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutoFitContentView.h; sourceTree = "<group>"; };
1839166350F32661F3ABD70F /* AutoFitContentView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AutoFitContentView.mm; sourceTree = "<group>"; }; 1839166350F32661F3ABD70F /* AutoFitContentView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AutoFitContentView.mm; sourceTree = "<group>"; };
18391676ECF0E983F4964357 /* WindowBaseImpl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WindowBaseImpl.mm; sourceTree = "<group>"; }; 18391676ECF0E983F4964357 /* WindowBaseImpl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WindowBaseImpl.mm; sourceTree = "<group>"; };
1839171D898F9BFC1373631A /* ResizeScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResizeScope.h; sourceTree = "<group>"; }; 1839171D898F9BFC1373631A /* ResizeScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResizeScope.h; sourceTree = "<group>"; };
18391884C7476DA4E53A492D /* AvnPanelWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnPanelWindow.mm; sourceTree = "<group>"; };
183919BF108EB72A029F7671 /* WindowImpl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WindowImpl.mm; sourceTree = "<group>"; }; 183919BF108EB72A029F7671 /* WindowImpl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WindowImpl.mm; sourceTree = "<group>"; };
18391BB698579F40F1783F31 /* PopupImpl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PopupImpl.mm; sourceTree = "<group>"; };
18391BBB7782C296D424071F /* INSWindowHolder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = INSWindowHolder.h; sourceTree = "<group>"; }; 18391BBB7782C296D424071F /* INSWindowHolder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = INSWindowHolder.h; sourceTree = "<group>"; };
18391CD090AA776E7E841AC9 /* WindowImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowImpl.h; sourceTree = "<group>"; }; 18391CD090AA776E7E841AC9 /* WindowImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowImpl.h; sourceTree = "<group>"; };
18391D1669284AD2EC9E866A /* AvnView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AvnView.h; sourceTree = "<group>"; }; 18391D1669284AD2EC9E866A /* AvnView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AvnView.h; sourceTree = "<group>"; };
18391DB45C7D892E61BF388C /* WindowInterfaces.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowInterfaces.h; sourceTree = "<group>"; };
18391E45702740FE9DD69695 /* ResizeScope.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ResizeScope.mm; sourceTree = "<group>"; }; 18391E45702740FE9DD69695 /* ResizeScope.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ResizeScope.mm; sourceTree = "<group>"; };
1A002B9D232135EE00021753 /* app.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = app.mm; sourceTree = "<group>"; }; 1A002B9D232135EE00021753 /* app.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = app.mm; sourceTree = "<group>"; };
1A1852DB23E05814008F0DED /* deadlock.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = deadlock.mm; sourceTree = "<group>"; }; 1A1852DB23E05814008F0DED /* deadlock.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = deadlock.mm; sourceTree = "<group>"; };
@ -72,7 +83,6 @@
37A4E71A2178846A00EACBCD /* headers */ = {isa = PBXFileReference; lastKnownFileType = folder; name = headers; path = ../../inc; sourceTree = "<group>"; }; 37A4E71A2178846A00EACBCD /* headers */ = {isa = PBXFileReference; lastKnownFileType = folder; name = headers; path = ../../inc; sourceTree = "<group>"; };
37A517B22159597E00FBA241 /* Screens.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Screens.mm; sourceTree = "<group>"; }; 37A517B22159597E00FBA241 /* Screens.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Screens.mm; sourceTree = "<group>"; };
37C09D8721580FE4006A6758 /* SystemDialogs.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SystemDialogs.mm; sourceTree = "<group>"; }; 37C09D8721580FE4006A6758 /* SystemDialogs.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SystemDialogs.mm; sourceTree = "<group>"; };
37C09D8A21581EF2006A6758 /* window.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = window.h; sourceTree = "<group>"; };
37DDA9AF219330F8002E132B /* AvnString.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnString.mm; sourceTree = "<group>"; }; 37DDA9AF219330F8002E132B /* AvnString.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnString.mm; sourceTree = "<group>"; };
37DDA9B121933371002E132B /* AvnString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AvnString.h; sourceTree = "<group>"; }; 37DDA9B121933371002E132B /* AvnString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AvnString.h; sourceTree = "<group>"; };
37E2330E21583241000CB7E2 /* KeyTransform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyTransform.mm; sourceTree = "<group>"; }; 37E2330E21583241000CB7E2 /* KeyTransform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyTransform.mm; sourceTree = "<group>"; };
@ -86,7 +96,6 @@
AB00E4F62147CA920032A60A /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; }; AB00E4F62147CA920032A60A /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
AB1E522B217613570091CD71 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; AB1E522B217613570091CD71 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
AB661C1D2148230F00291242 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 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 = "<group>"; };
AB661C212148288600291242 /* common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = "<group>"; }; AB661C212148288600291242 /* common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = "<group>"; };
AB7A61EF2147C815003C5833 /* libAvalonia.Native.OSX.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libAvalonia.Native.OSX.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; AB7A61EF2147C815003C5833 /* libAvalonia.Native.OSX.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libAvalonia.Native.OSX.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = platformthreading.mm; sourceTree = "<group>"; }; AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = platformthreading.mm; sourceTree = "<group>"; };
@ -142,8 +151,6 @@
AB661C212148288600291242 /* common.h */, AB661C212148288600291242 /* common.h */,
379860FE214DA0C000CD0246 /* KeyTransform.h */, 379860FE214DA0C000CD0246 /* KeyTransform.h */,
37E2330E21583241000CB7E2 /* KeyTransform.mm */, 37E2330E21583241000CB7E2 /* KeyTransform.mm */,
AB661C1F2148286E00291242 /* window.mm */,
37C09D8A21581EF2006A6758 /* window.h */,
AB00E4F62147CA920032A60A /* main.mm */, AB00E4F62147CA920032A60A /* main.mm */,
37155CE3233C00EB0034DCE9 /* menu.h */, 37155CE3233C00EB0034DCE9 /* menu.h */,
520624B222973F4100C4DCEF /* menu.mm */, 520624B222973F4100C4DCEF /* menu.mm */,
@ -166,6 +173,12 @@
18391D1669284AD2EC9E866A /* AvnView.h */, 18391D1669284AD2EC9E866A /* AvnView.h */,
1839166350F32661F3ABD70F /* AutoFitContentView.mm */, 1839166350F32661F3ABD70F /* AutoFitContentView.mm */,
18391654EF0E7AB3D3AB4071 /* AutoFitContentView.h */, 18391654EF0E7AB3D3AB4071 /* AutoFitContentView.h */,
18391884C7476DA4E53A492D /* AvnPanelWindow.mm */,
1839122E037567BDD1D09DEB /* WindowProtocol.h */,
1839155B28B20FFB672D29C6 /* AvnWindow.mm */,
18391DB45C7D892E61BF388C /* WindowInterfaces.h */,
18391BB698579F40F1783F31 /* PopupImpl.mm */,
183910513F396141938832B5 /* PopupImpl.h */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@ -193,6 +206,9 @@
18391C28BF1823B5464FDD36 /* ResizeScope.h in Headers */, 18391C28BF1823B5464FDD36 /* ResizeScope.h in Headers */,
18391ED5F611FF62C45F196D /* AvnView.h in Headers */, 18391ED5F611FF62C45F196D /* AvnView.h in Headers */,
18391E1381E2D5BFD60265A9 /* AutoFitContentView.h in Headers */, 18391E1381E2D5BFD60265A9 /* AutoFitContentView.h in Headers */,
18391F1E2411C79405A9943A /* WindowProtocol.h in Headers */,
183914E50CF6D2EFC1667F7C /* WindowInterfaces.h in Headers */,
18391AC65ADD7DDD33FBE737 /* PopupImpl.h in Headers */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -271,12 +287,14 @@
1A465D10246AB61600C5858B /* dnd.mm in Sources */, 1A465D10246AB61600C5858B /* dnd.mm in Sources */,
AB00E4F72147CA920032A60A /* main.mm in Sources */, AB00E4F72147CA920032A60A /* main.mm in Sources */,
37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */, 37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */,
AB661C202148286E00291242 /* window.mm in Sources */,
1839179A55FC1421BEE83330 /* WindowBaseImpl.mm in Sources */, 1839179A55FC1421BEE83330 /* WindowBaseImpl.mm in Sources */,
1839125F057B0A4EB1760058 /* WindowImpl.mm in Sources */, 1839125F057B0A4EB1760058 /* WindowImpl.mm in Sources */,
18391068E48EF96E3DB5FDAB /* ResizeScope.mm in Sources */, 18391068E48EF96E3DB5FDAB /* ResizeScope.mm in Sources */,
18391D4EB311BC7EF8B8C0A6 /* AvnView.mm in Sources */, 18391D4EB311BC7EF8B8C0A6 /* AvnView.mm in Sources */,
18391AA7E0BBA74D184C5734 /* AutoFitContentView.mm in Sources */, 18391AA7E0BBA74D184C5734 /* AutoFitContentView.mm in Sources */,
1839151F32D1BB1AB51A7BB6 /* AvnPanelWindow.mm in Sources */,
18391AC16726CBC45856233B /* AvnWindow.mm in Sources */,
18391D8CD1756DC858DC1A09 /* PopupImpl.mm in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

11
native/Avalonia.Native/src/OSX/AvnPanelWindow.mm

@ -0,0 +1,11 @@
//
// Created by Dan Walmsley on 06/05/2022.
// Copyright (c) 2022 Avalonia. All rights reserved.
//
#pragma once
#define IS_NSPANEL
#include "AvnWindow.mm"

10
native/Avalonia.Native/src/OSX/AvnView.h

@ -2,17 +2,15 @@
// Created by Dan Walmsley on 05/05/2022. // Created by Dan Walmsley on 05/05/2022.
// Copyright (c) 2022 Avalonia. All rights reserved. // Copyright (c) 2022 Avalonia. All rights reserved.
// //
#pragma once
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
#include "window.h" #include "common.h"
#import "comimpl.h" #include "WindowImpl.h"
#import "common.h" #include "KeyTransform.h"
#import "WindowImpl.h"
#import "KeyTransform.h"
@class AvnAccessibilityElement; @class AvnAccessibilityElement;

10
native/Avalonia.Native/src/OSX/AvnView.mm

@ -4,8 +4,9 @@
// //
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
#import "AvnView.h" #include "AvnView.h"
#include "automation.h" #include "automation.h"
#import "WindowInterfaces.h"
@implementation AvnView @implementation AvnView
{ {
@ -194,7 +195,12 @@
- (bool) ignoreUserInput:(bool)trigerInputWhenDisabled - (bool) ignoreUserInput:(bool)trigerInputWhenDisabled
{ {
auto parentWindow = objc_cast<AvnWindow>([self window]); if(_parent == nullptr)
{
return TRUE;
}
auto parentWindow = _parent->GetWindowProtocol();
if(parentWindow == nil || ![parentWindow shouldTryToHandleEvents]) if(parentWindow == nil || ![parentWindow shouldTryToHandleEvents])
{ {

223
native/Avalonia.Native/src/OSX/window.mm → native/Avalonia.Native/src/OSX/AvnWindow.mm

@ -1,18 +1,37 @@
//
// Created by Dan Walmsley on 06/05/2022.
// Copyright (c) 2022 Avalonia. All rights reserved.
//
#import <AppKit/AppKit.h>
#import "WindowProtocol.h"
#import "WindowBaseImpl.h"
#ifdef IS_NSPANEL
#define BASE_CLASS NSPanel
#define CLASS_NAME AvnPanel
#else
#define BASE_CLASS NSWindow
#define CLASS_NAME AvnWindow
#endif
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
#include "common.h" #include "common.h"
#import "window.h"
#include "menu.h" #include "menu.h"
#include "automation.h" #include "automation.h"
#import "WindowBaseImpl.h" #include "WindowBaseImpl.h"
#include "WindowImpl.h" #include "WindowImpl.h"
#include "AvnView.h" #include "AvnView.h"
#include "WindowInterfaces.h"
#include "PopupImpl.h"
@implementation AvnWindow @implementation CLASS_NAME
{ {
ComPtr<WindowBaseImpl> _parent; ComPtr<WindowBaseImpl> _parent;
bool _canBecomeKeyAndMain;
bool _closed; bool _closed;
bool _isEnabled; bool _isEnabled;
bool _canBecomeKeyWindow;
bool _isExtended; bool _isExtended;
AvnMenu* _menu; AvnMenu* _menu;
} }
@ -66,7 +85,7 @@
- (void)pollModalSession:(nonnull NSModalSession)session - (void)pollModalSession:(nonnull NSModalSession)session
{ {
auto response = [NSApp runModalSession:session]; auto response = [NSApp runModalSession:session];
if(response == NSModalResponseContinue) if(response == NSModalResponseContinue)
{ {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
@ -85,18 +104,18 @@
if(_menu != nullptr) if(_menu != nullptr)
{ {
auto appMenuItem = ::GetAppMenuItem(); auto appMenuItem = ::GetAppMenuItem();
if(appMenuItem != nullptr) if(appMenuItem != nullptr)
{ {
auto appMenu = [appMenuItem menu]; auto appMenu = [appMenuItem menu];
[appMenu removeItem:appMenuItem]; [appMenu removeItem:appMenuItem];
[_menu insertItem:appMenuItem atIndex:0]; [_menu insertItem:appMenuItem atIndex:0];
[_menu setHasGlobalMenuItem:true]; [_menu setHasGlobalMenuItem:true];
} }
[NSApp setMenu:_menu]; [NSApp setMenu:_menu];
} }
else else
@ -108,22 +127,22 @@
-(void) showAppMenuOnly -(void) showAppMenuOnly
{ {
auto appMenuItem = ::GetAppMenuItem(); auto appMenuItem = ::GetAppMenuItem();
if(appMenuItem != nullptr) if(appMenuItem != nullptr)
{ {
auto appMenu = ::GetAppMenu(); auto appMenu = ::GetAppMenu();
auto nativeAppMenu = dynamic_cast<AvnAppMenu*>(appMenu); auto nativeAppMenu = dynamic_cast<AvnAppMenu*>(appMenu);
[[appMenuItem menu] removeItem:appMenuItem]; [[appMenuItem menu] removeItem:appMenuItem];
if(_menu != nullptr) if(_menu != nullptr)
{ {
[_menu setHasGlobalMenuItem:false]; [_menu setHasGlobalMenuItem:false];
} }
[nativeAppMenu->GetNative() addItem:appMenuItem]; [nativeAppMenu->GetNative() addItem:appMenuItem];
[NSApp setMenu:nativeAppMenu->GetNative()]; [NSApp setMenu:nativeAppMenu->GetNative()];
} }
} }
@ -134,40 +153,45 @@
{ {
menu = [AvnMenu new]; menu = [AvnMenu new];
} }
_menu = menu; _menu = menu;
} }
-(void) setCanBecomeKeyAndMain -(CLASS_NAME*) initWithParent: (WindowBaseImpl*) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask;
{ {
_canBecomeKeyAndMain = true; // https://jameshfisher.com/2020/07/10/why-is-the-contentrect-of-my-nswindow-ignored/
} // create nswindow with specific contentRect, otherwise we wont be able to resize the window
// until several ms after the window is physically on the screen.
self = [super initWithContentRect:contentRect styleMask: styleMask backing:NSBackingStoreBuffered defer:false];
-(AvnWindow*) initWithParent: (WindowBaseImpl*) parent
{
self = [super init];
[self setReleasedWhenClosed:false]; [self setReleasedWhenClosed:false];
_parent = parent; _parent = parent;
[self setDelegate:self]; [self setDelegate:self];
_closed = false; _closed = false;
_isEnabled = true; _isEnabled = true;
[self backingScaleFactor]; [self backingScaleFactor];
[self setOpaque:NO]; [self setOpaque:NO];
[self setBackgroundColor: [NSColor clearColor]]; [self setBackgroundColor: [NSColor clearColor]];
_isExtended = false; _isExtended = false;
#ifdef IS_NSPANEL
[self setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces|NSWindowCollectionBehaviorFullScreenAuxiliary];
#endif
return self; return self;
} }
- (BOOL)windowShouldClose:(NSWindow *)sender - (BOOL)windowShouldClose:(NSWindow *)sender
{ {
auto window = dynamic_cast<WindowImpl*>(_parent.getRaw()); auto window = dynamic_cast<WindowImpl*>(_parent.getRaw());
if(window != nullptr) if(window != nullptr)
{ {
return !window->WindowEvents->Closing(); return !window->WindowEvents->Closing();
} }
return true; return true;
} }
@ -176,6 +200,8 @@
[self backingScaleFactor]; [self backingScaleFactor];
} }
- (void)windowWillClose:(NSNotification *)notification - (void)windowWillClose:(NSNotification *)notification
{ {
_closed = true; _closed = true;
@ -191,27 +217,38 @@
-(BOOL)canBecomeKeyWindow -(BOOL)canBecomeKeyWindow
{ {
if (_canBecomeKeyAndMain) if(_canBecomeKeyWindow)
{ {
// If the window has a child window being shown as a dialog then don't allow it to become the key window. // If the window has a child window being shown as a dialog then don't allow it to become the key window.
for(NSWindow* uch in [self childWindows]) for(NSWindow* uch in [self childWindows])
{ {
auto ch = objc_cast<AvnWindow>(uch); if (![uch conformsToProtocol:@protocol(AvnWindowProtocol)])
if(ch == nil) {
continue; continue;
if (ch.isDialog) }
id <AvnWindowProtocol> ch = (id <AvnWindowProtocol>) uch;
if(ch.isDialog)
return false; return false;
} }
return true; return true;
} }
return false; return false;
} }
#ifndef IS_NSPANEL
-(BOOL)canBecomeMainWindow -(BOOL)canBecomeMainWindow
{ {
return _canBecomeKeyAndMain; return true;
}
#endif
-(void)setCanBecomeKeyWindow:(bool)value
{
_canBecomeKeyWindow = value;
} }
-(bool)shouldTryToHandleEvents -(bool)shouldTryToHandleEvents
@ -227,7 +264,7 @@
-(void)becomeKeyWindow -(void)becomeKeyWindow
{ {
[self showWindowMenuWithAppMenu]; [self showWindowMenuWithAppMenu];
if(_parent != nullptr) if(_parent != nullptr)
{ {
_parent->BaseEvents->Activated(); _parent->BaseEvents->Activated();
@ -238,7 +275,8 @@
-(void) restoreParentWindow; -(void) restoreParentWindow;
{ {
auto parent = objc_cast<AvnWindow>([self parentWindow]); auto parent = [self parentWindow];
if(parent != nil) if(parent != nil)
{ {
[parent removeChildWindow:self]; [parent removeChildWindow:self];
@ -248,7 +286,7 @@
- (void)windowDidMiniaturize:(NSNotification *)notification - (void)windowDidMiniaturize:(NSNotification *)notification
{ {
auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->()); auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->());
if(parent != nullptr) if(parent != nullptr)
{ {
parent->WindowStateChanged(); parent->WindowStateChanged();
@ -258,7 +296,7 @@
- (void)windowDidDeminiaturize:(NSNotification *)notification - (void)windowDidDeminiaturize:(NSNotification *)notification
{ {
auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->()); auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->());
if(parent != nullptr) if(parent != nullptr)
{ {
parent->WindowStateChanged(); parent->WindowStateChanged();
@ -268,7 +306,7 @@
- (void)windowDidResize:(NSNotification *)notification - (void)windowDidResize:(NSNotification *)notification
{ {
auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->()); auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->());
if(parent != nullptr) if(parent != nullptr)
{ {
parent->WindowStateChanged(); parent->WindowStateChanged();
@ -278,7 +316,7 @@
- (void)windowWillExitFullScreen:(NSNotification *)notification - (void)windowWillExitFullScreen:(NSNotification *)notification
{ {
auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->()); auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->());
if(parent != nullptr) if(parent != nullptr)
{ {
parent->StartStateTransition(); parent->StartStateTransition();
@ -288,22 +326,22 @@
- (void)windowDidExitFullScreen:(NSNotification *)notification - (void)windowDidExitFullScreen:(NSNotification *)notification
{ {
auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->()); auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->());
if(parent != nullptr) if(parent != nullptr)
{ {
parent->EndStateTransition(); parent->EndStateTransition();
if(parent->Decorations() != SystemDecorationsFull && parent->WindowState() == Maximized) if(parent->Decorations() != SystemDecorationsFull && parent->WindowState() == Maximized)
{ {
NSRect screenRect = [[self screen] visibleFrame]; NSRect screenRect = [[self screen] visibleFrame];
[self setFrame:screenRect display:YES]; [self setFrame:screenRect display:YES];
} }
if(parent->WindowState() == Minimized) if(parent->WindowState() == Minimized)
{ {
[self miniaturize:nullptr]; [self miniaturize:nullptr];
} }
parent->WindowStateChanged(); parent->WindowStateChanged();
} }
} }
@ -311,7 +349,7 @@
- (void)windowWillEnterFullScreen:(NSNotification *)notification - (void)windowWillEnterFullScreen:(NSNotification *)notification
{ {
auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->()); auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->());
if(parent != nullptr) if(parent != nullptr)
{ {
parent->StartStateTransition(); parent->StartStateTransition();
@ -321,7 +359,7 @@
- (void)windowDidEnterFullScreen:(NSNotification *)notification - (void)windowDidEnterFullScreen:(NSNotification *)notification
{ {
auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->()); auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->());
if(parent != nullptr) if(parent != nullptr)
{ {
parent->EndStateTransition(); parent->EndStateTransition();
@ -338,28 +376,33 @@
{ {
if(_parent) if(_parent)
_parent->BaseEvents->Deactivated(); _parent->BaseEvents->Deactivated();
[self showAppMenuOnly]; [self showAppMenuOnly];
[super resignKeyWindow]; [super resignKeyWindow];
} }
- (void)windowDidMove:(NSNotification *)notification - (void)windowDidMove:(NSNotification *)notification
{ {
AvnPoint position; AvnPoint position;
if(_parent != nullptr) if(_parent != nullptr)
{ {
auto cparent = dynamic_cast<WindowImpl*>(_parent.getRaw()); auto cparent = dynamic_cast<WindowImpl*>(_parent.getRaw());
if(cparent != nullptr) if(cparent != nullptr)
{ {
if(!cparent->IsShown())
{
return;
}
if(cparent->WindowState() == Maximized) if(cparent->WindowState() == Maximized)
{ {
cparent->SetWindowState(Normal); cparent->SetWindowState(Normal);
} }
} }
_parent->GetPosition(&position); _parent->GetPosition(&position);
_parent->BaseEvents->PositionChanged(position); _parent->BaseEvents->PositionChanged(position);
} }
@ -374,7 +417,7 @@
- (void)sendEvent:(NSEvent *)event - (void)sendEvent:(NSEvent *)event
{ {
[super sendEvent:event]; [super sendEvent:event];
/// This is to detect non-client clicks. This can only be done on Windows... not popups, hence the dynamic_cast. /// This is to detect non-client clicks. This can only be done on Windows... not popups, hence the dynamic_cast.
if(_parent != nullptr && dynamic_cast<WindowImpl*>(_parent.getRaw()) != nullptr) if(_parent != nullptr && dynamic_cast<WindowImpl*>(_parent.getRaw()) != nullptr)
{ {
@ -385,95 +428,39 @@
AvnView* view = _parent->View; AvnView* view = _parent->View;
NSPoint windowPoint = [event locationInWindow]; NSPoint windowPoint = [event locationInWindow];
NSPoint viewPoint = [view convertPoint:windowPoint fromView:nil]; NSPoint viewPoint = [view convertPoint:windowPoint fromView:nil];
if (!NSPointInRect(viewPoint, view.bounds)) if (!NSPointInRect(viewPoint, view.bounds))
{ {
auto avnPoint = [AvnView toAvnPoint:windowPoint]; auto avnPoint = [AvnView toAvnPoint:windowPoint];
auto point = [self translateLocalPoint:avnPoint]; auto point = [self translateLocalPoint:avnPoint];
AvnVector delta = { 0, 0 }; AvnVector delta = { 0, 0 };
_parent->BaseEvents->RawMouseEvent(NonClientLeftButtonDown, static_cast<uint32>([event timestamp] * 1000), AvnInputModifiersNone, point, delta); _parent->BaseEvents->RawMouseEvent(NonClientLeftButtonDown, static_cast<uint32>([event timestamp] * 1000), AvnInputModifiersNone, point, delta);
} }
} }
break; break;
case NSEventTypeMouseEntered: case NSEventTypeMouseEntered:
{ {
_parent->UpdateCursor(); _parent->UpdateCursor();
} }
break; break;
case NSEventTypeMouseExited: case NSEventTypeMouseExited:
{ {
[[NSCursor arrowCursor] set]; [[NSCursor arrowCursor] set];
} }
break; break;
default: default:
break; break;
} }
} }
} }
@end - (void)disconnectParent {
_parent = nullptr;
class PopupImpl : public virtual WindowBaseImpl, public IAvnPopup
{
private:
BEGIN_INTERFACE_MAP()
INHERIT_INTERFACE_MAP(WindowBaseImpl)
INTERFACE_MAP_ENTRY(IAvnPopup, IID_IAvnPopup)
END_INTERFACE_MAP()
virtual ~PopupImpl(){}
ComPtr<IAvnWindowEvents> WindowEvents;
PopupImpl(IAvnWindowEvents* events, IAvnGlContext* gl) : WindowBaseImpl(events, gl)
{
WindowEvents = events;
[Window setLevel:NSPopUpMenuWindowLevel];
}
protected:
virtual NSWindowStyleMask GetStyle() override
{
return NSWindowStyleMaskBorderless;
}
virtual HRESULT Resize(double x, double y, AvnPlatformResizeReason reason) override
{
START_COM_CALL;
@autoreleasepool
{
if (Window != nullptr)
{
[Window setContentSize:NSSize{x, y}];
[Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(lastPositionSet))];
}
return S_OK;
}
}
public:
virtual bool ShouldTakeFocusOnShow() override
{
return false;
}
};
extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events, IAvnGlContext* gl)
{
@autoreleasepool
{
IAvnPopup* ptr = dynamic_cast<IAvnPopup*>(new PopupImpl(events, gl));
return ptr;
}
} }
extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events, IAvnGlContext* gl) @end
{
@autoreleasepool
{
IAvnWindow* ptr = (IAvnWindow*)new WindowImpl(events, gl);
return ptr;
}
}

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

@ -10,8 +10,8 @@
struct INSWindowHolder struct INSWindowHolder
{ {
virtual AvnWindow* _Nonnull GetNSWindow () = 0; virtual NSWindow* _Nonnull GetNSWindow () = 0;
virtual AvnView* _Nonnull GetNSView () = 0; virtual NSView* _Nonnull GetNSView () = 0;
}; };
#endif //AVALONIA_NATIVE_OSX_INSWINDOWHOLDER_H #endif //AVALONIA_NATIVE_OSX_INSWINDOWHOLDER_H

9
native/Avalonia.Native/src/OSX/PopupImpl.h

@ -0,0 +1,9 @@
//
// Created by Dan Walmsley on 06/05/2022.
// Copyright (c) 2022 Avalonia. All rights reserved.
//
#ifndef AVALONIA_NATIVE_OSX_POPUPIMPL_H
#define AVALONIA_NATIVE_OSX_POPUPIMPL_H
#endif //AVALONIA_NATIVE_OSX_POPUPIMPL_H

61
native/Avalonia.Native/src/OSX/PopupImpl.mm

@ -0,0 +1,61 @@
//
// Created by Dan Walmsley on 06/05/2022.
// Copyright (c) 2022 Avalonia. All rights reserved.
//
#include "WindowInterfaces.h"
#include "AvnView.h"
#include "WindowImpl.h"
#include "automation.h"
#include "menu.h"
#include "common.h"
#import "WindowBaseImpl.h"
#import "WindowProtocol.h"
#import <AppKit/AppKit.h>
#include "PopupImpl.h"
class PopupImpl : public virtual WindowBaseImpl, public IAvnPopup
{
private:
BEGIN_INTERFACE_MAP()
INHERIT_INTERFACE_MAP(WindowBaseImpl)
INTERFACE_MAP_ENTRY(IAvnPopup, IID_IAvnPopup)
END_INTERFACE_MAP()
virtual ~PopupImpl(){}
ComPtr<IAvnWindowEvents> WindowEvents;
PopupImpl(IAvnWindowEvents* events, IAvnGlContext* gl) : WindowBaseImpl(events, gl)
{
WindowEvents = events;
}
protected:
virtual NSWindowStyleMask GetStyle() override
{
return NSWindowStyleMaskBorderless;
}
virtual void OnInitialiseNSWindow () override
{
[Window setLevel:NSPopUpMenuWindowLevel];
}
public:
virtual bool ShouldTakeFocusOnShow() override
{
return false;
}
virtual HRESULT Show(bool activate, bool isDialog) override
{
return WindowBaseImpl::Show(activate, true);
}
};
extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events, IAvnGlContext* gl)
{
@autoreleasepool
{
IAvnPopup* ptr = dynamic_cast<IAvnPopup*>(new PopupImpl(events, gl));
return ptr;
}
}

1
native/Avalonia.Native/src/OSX/ResizeScope.h

@ -6,7 +6,6 @@
#ifndef AVALONIA_NATIVE_OSX_RESIZESCOPE_H #ifndef AVALONIA_NATIVE_OSX_RESIZESCOPE_H
#define AVALONIA_NATIVE_OSX_RESIZESCOPE_H #define AVALONIA_NATIVE_OSX_RESIZESCOPE_H
#include "window.h"
#include "avalonia-native.h" #include "avalonia-native.h"
@class AvnView; @class AvnView;

2
native/Avalonia.Native/src/OSX/ResizeScope.mm

@ -5,7 +5,7 @@
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
#include "ResizeScope.h" #include "ResizeScope.h"
#import "AvnView.h" #include "AvnView.h"
ResizeScope::ResizeScope(AvnView *view, AvnPlatformResizeReason reason) { ResizeScope::ResizeScope(AvnView *view, AvnPlatformResizeReason reason) {
_view = view; _view = view;

1
native/Avalonia.Native/src/OSX/SystemDialogs.mm

@ -1,5 +1,4 @@
#include "common.h" #include "common.h"
#include "window.h"
#include "INSWindowHolder.h" #include "INSWindowHolder.h"
class SystemDialogs : public ComSingleObject<IAvnSystemDialogs, &IID_IAvnSystemDialogs> class SystemDialogs : public ComSingleObject<IAvnSystemDialogs, &IID_IAvnSystemDialogs>

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

@ -6,16 +6,16 @@
#ifndef AVALONIA_NATIVE_OSX_WINDOWBASEIMPL_H #ifndef AVALONIA_NATIVE_OSX_WINDOWBASEIMPL_H
#define AVALONIA_NATIVE_OSX_WINDOWBASEIMPL_H #define AVALONIA_NATIVE_OSX_WINDOWBASEIMPL_H
#import "rendertarget.h" #include "rendertarget.h"
#include "INSWindowHolder.h" #include "INSWindowHolder.h"
@class AutoFitContentView; @class AutoFitContentView;
@class AvnMenu;
@protocol AvnWindowProtocol;
class WindowBaseImpl : public virtual ComObject, class WindowBaseImpl : public virtual ComObject,
public virtual IAvnWindowBase, public virtual IAvnWindowBase,
public INSWindowHolder { public INSWindowHolder {
private:
NSCursor *cursor;
public: public:
FORWARD_IUNKNOWN() FORWARD_IUNKNOWN()
@ -24,22 +24,7 @@ BEGIN_INTERFACE_MAP()
INTERFACE_MAP_ENTRY(IAvnWindowBase, IID_IAvnWindowBase) INTERFACE_MAP_ENTRY(IAvnWindowBase, IID_IAvnWindowBase)
END_INTERFACE_MAP() END_INTERFACE_MAP()
virtual ~WindowBaseImpl() { virtual ~WindowBaseImpl();
View = NULL;
Window = NULL;
}
AutoFitContentView *StandardContainer;
AvnView *View;
AvnWindow *Window;
ComPtr<IAvnWindowBaseEvents> BaseEvents;
ComPtr<IAvnGlContext> _glContext;
NSObject <IRenderTarget> *renderTarget;
AvnPoint lastPositionSet;
NSString *_lastTitle;
bool _shown;
bool _inResize;
WindowBaseImpl(IAvnWindowBaseEvents *events, IAvnGlContext *gl); WindowBaseImpl(IAvnWindowBaseEvents *events, IAvnGlContext *gl);
@ -51,12 +36,14 @@ BEGIN_INTERFACE_MAP()
virtual HRESULT ObtainNSViewHandleRetained(void **ret) override; virtual HRESULT ObtainNSViewHandleRetained(void **ret) override;
virtual AvnWindow *GetNSWindow() override; virtual NSWindow *GetNSWindow() override;
virtual AvnView *GetNSView() override; virtual NSView *GetNSView() override;
virtual HRESULT Show(bool activate, bool isDialog) override; virtual HRESULT Show(bool activate, bool isDialog) override;
virtual bool IsShown ();
virtual bool ShouldTakeFocusOnShow(); virtual bool ShouldTakeFocusOnShow();
virtual HRESULT Hide() override; virtual HRESULT Hide() override;
@ -111,11 +98,39 @@ BEGIN_INTERFACE_MAP()
virtual bool IsDialog(); virtual bool IsDialog();
id<AvnWindowProtocol> GetWindowProtocol ();
protected: protected:
virtual NSWindowStyleMask GetStyle(); virtual NSWindowStyleMask GetStyle();
void UpdateStyle(); void UpdateStyle();
virtual void OnInitialiseNSWindow ();
private:
void CreateNSWindow (bool isDialog);
void CleanNSWindow ();
void InitialiseNSWindow ();
NSCursor *cursor;
ComPtr<IAvnGlContext> _glContext;
bool hasPosition;
NSSize lastSize;
NSSize lastMinSize;
NSSize lastMaxSize;
AvnMenu* lastMenu;
bool _inResize;
protected:
AvnPoint lastPositionSet;
AutoFitContentView *StandardContainer;
bool _shown;
public:
NSObject <IRenderTarget> *renderTarget;
NSWindow * Window;
ComPtr<IAvnWindowBaseEvents> BaseEvents;
AvnView *View;
}; };
#endif //AVALONIA_NATIVE_OSX_WINDOWBASEIMPL_H #endif //AVALONIA_NATIVE_OSX_WINDOWBASEIMPL_H

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

@ -5,13 +5,21 @@
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
#include "common.h" #include "common.h"
#import "window.h" #include "AvnView.h"
#import "AvnView.h"
#include "menu.h" #include "menu.h"
#include "automation.h" #include "automation.h"
#import "cursor.h" #include "cursor.h"
#include "ResizeScope.h" #include "ResizeScope.h"
#import "AutoFitContentView.h" #include "AutoFitContentView.h"
#import "WindowProtocol.h"
#import "WindowInterfaces.h"
#include "WindowBaseImpl.h"
WindowBaseImpl::~WindowBaseImpl() {
View = nullptr;
Window = nullptr;
}
WindowBaseImpl::WindowBaseImpl(IAvnWindowBaseEvents *events, IAvnGlContext *gl) { WindowBaseImpl::WindowBaseImpl(IAvnWindowBaseEvents *events, IAvnGlContext *gl) {
_shown = false; _shown = false;
@ -22,17 +30,14 @@ WindowBaseImpl::WindowBaseImpl(IAvnWindowBaseEvents *events, IAvnGlContext *gl)
View = [[AvnView alloc] initWithParent:this]; View = [[AvnView alloc] initWithParent:this];
StandardContainer = [[AutoFitContentView new] initWithContent:View]; StandardContainer = [[AutoFitContentView new] initWithContent:View];
Window = [[AvnWindow alloc] initWithParent:this]; lastPositionSet = { 0, 0 };
[Window setContentView:StandardContainer]; hasPosition = false;
lastSize = NSSize { 100, 100 };
lastPositionSet.X = 100; lastMaxSize = NSSize { CGFLOAT_MAX, CGFLOAT_MAX};
lastPositionSet.Y = 100; lastMinSize = NSSize { 0, 0 };
_lastTitle = @"";
[Window setStyleMask:NSWindowStyleMaskBorderless]; Window = nullptr;
[Window setBackingType:NSBackingStoreBuffered]; lastMenu = nullptr;
[Window setOpaque:false];
} }
HRESULT WindowBaseImpl::ObtainNSViewHandle(void **ret) { HRESULT WindowBaseImpl::ObtainNSViewHandle(void **ret) {
@ -59,11 +64,11 @@ HRESULT WindowBaseImpl::ObtainNSViewHandleRetained(void **ret) {
return S_OK; return S_OK;
} }
AvnWindow *WindowBaseImpl::GetNSWindow() { NSWindow *WindowBaseImpl::GetNSWindow() {
return Window; return Window;
} }
AvnView *WindowBaseImpl::GetNSView() { NSView *WindowBaseImpl::GetNSView() {
return View; return View;
} }
@ -83,10 +88,18 @@ HRESULT WindowBaseImpl::Show(bool activate, bool isDialog) {
START_COM_CALL; START_COM_CALL;
@autoreleasepool { @autoreleasepool {
SetPosition(lastPositionSet); CreateNSWindow(isDialog);
UpdateStyle(); InitialiseNSWindow();
if(hasPosition)
{
SetPosition(lastPositionSet);
} else
{
[Window center];
}
[Window setTitle:_lastTitle]; UpdateStyle();
if (ShouldTakeFocusOnShow() && activate) { if (ShouldTakeFocusOnShow() && activate) {
[Window orderFront:Window]; [Window orderFront:Window];
@ -103,6 +116,11 @@ HRESULT WindowBaseImpl::Show(bool activate, bool isDialog) {
} }
} }
bool WindowBaseImpl::IsShown ()
{
return _shown;
}
bool WindowBaseImpl::ShouldTakeFocusOnShow() { bool WindowBaseImpl::ShouldTakeFocusOnShow() {
return true; return true;
} }
@ -125,7 +143,8 @@ HRESULT WindowBaseImpl::Hide() {
@autoreleasepool { @autoreleasepool {
if (Window != nullptr) { if (Window != nullptr) {
[Window orderOut:Window]; [Window orderOut:Window];
[Window restoreParentWindow];
[GetWindowProtocol() restoreParentWindow];
} }
return S_OK; return S_OK;
@ -181,9 +200,8 @@ HRESULT WindowBaseImpl::GetClientSize(AvnSize *ret) {
if (ret == nullptr) if (ret == nullptr)
return E_POINTER; return E_POINTER;
auto frame = [View frame]; ret->Width = lastSize.width;
ret->Width = frame.size.width; ret->Height = lastSize.height;
ret->Height = frame.size.height;
return S_OK; return S_OK;
} }
@ -196,9 +214,11 @@ HRESULT WindowBaseImpl::GetFrameSize(AvnSize *ret) {
if (ret == nullptr) if (ret == nullptr)
return E_POINTER; return E_POINTER;
auto frame = [Window frame]; if(Window != nullptr){
ret->Width = frame.size.width; auto frame = [Window frame];
ret->Height = frame.size.height; ret->Width = frame.size.width;
ret->Height = frame.size.height;
}
return S_OK; return S_OK;
} }
@ -225,8 +245,13 @@ HRESULT WindowBaseImpl::SetMinMaxSize(AvnSize minSize, AvnSize maxSize) {
START_COM_CALL; START_COM_CALL;
@autoreleasepool { @autoreleasepool {
[Window setContentMinSize:ToNSSize(minSize)]; lastMinSize = ToNSSize(minSize);
[Window setContentMaxSize:ToNSSize(maxSize)]; lastMaxSize = ToNSSize(maxSize);
if(Window != nullptr) {
[Window setContentMinSize:lastMinSize];
[Window setContentMaxSize:lastMaxSize];
}
return S_OK; return S_OK;
} }
@ -243,8 +268,8 @@ HRESULT WindowBaseImpl::Resize(double x, double y, AvnPlatformResizeReason reaso
auto resizeBlock = ResizeScope(View, reason); auto resizeBlock = ResizeScope(View, reason);
@autoreleasepool { @autoreleasepool {
auto maxSize = [Window contentMaxSize]; auto maxSize = lastMaxSize;
auto minSize = [Window contentMinSize]; auto minSize = lastMinSize;
if (x < minSize.width) { if (x < minSize.width) {
x = minSize.width; x = minSize.width;
@ -263,12 +288,15 @@ HRESULT WindowBaseImpl::Resize(double x, double y, AvnPlatformResizeReason reaso
} }
@try { @try {
lastSize = NSSize {x, y};
if (!_shown) { if (!_shown) {
BaseEvents->Resized(AvnSize{x, y}, reason); BaseEvents->Resized(AvnSize{x, y}, reason);
} }
[Window setContentSize:NSSize{x, y}]; if(Window != nullptr) {
[Window invalidateShadow]; [Window setContentSize:lastSize];
}
} }
@finally { @finally {
_inResize = false; _inResize = false;
@ -293,12 +321,14 @@ HRESULT WindowBaseImpl::SetMainMenu(IAvnMenu *menu) {
auto nativeMenu = dynamic_cast<AvnAppMenu *>(menu); auto nativeMenu = dynamic_cast<AvnAppMenu *>(menu);
auto nsmenu = nativeMenu->GetNative(); lastMenu = nativeMenu->GetNative();
[Window applyMenu:nsmenu]; if(Window != nullptr) {
[GetWindowProtocol() applyMenu:lastMenu];
if ([Window isKeyWindow]) { if ([Window isKeyWindow]) {
[Window showWindowMenuWithAppMenu]; [GetWindowProtocol() showWindowMenuWithAppMenu];
}
} }
return S_OK; return S_OK;
@ -334,12 +364,17 @@ HRESULT WindowBaseImpl::GetPosition(AvnPoint *ret) {
return E_POINTER; return E_POINTER;
} }
auto frame = [Window frame]; if(Window != nullptr) {
auto frame = [Window frame];
ret->X = frame.origin.x; ret->X = frame.origin.x;
ret->Y = frame.origin.y + frame.size.height; ret->Y = frame.origin.y + frame.size.height;
*ret = ConvertPointY(*ret); *ret = ConvertPointY(*ret);
} else
{
*ret = lastPositionSet;
}
return S_OK; return S_OK;
} }
@ -350,7 +385,11 @@ HRESULT WindowBaseImpl::SetPosition(AvnPoint point) {
@autoreleasepool { @autoreleasepool {
lastPositionSet = point; lastPositionSet = point;
[Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(point))]; hasPosition = true;
if(Window != nullptr) {
[Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(point))];
}
return S_OK; return S_OK;
} }
@ -502,4 +541,75 @@ NSWindowStyleMask WindowBaseImpl::GetStyle() {
void WindowBaseImpl::UpdateStyle() { void WindowBaseImpl::UpdateStyle() {
[Window setStyleMask:GetStyle()]; [Window setStyleMask:GetStyle()];
} }
void WindowBaseImpl::CleanNSWindow() {
if(Window != nullptr) {
[GetWindowProtocol() disconnectParent];
[Window close];
Window = nullptr;
}
}
void WindowBaseImpl::CreateNSWindow(bool isDialog) {
if (isDialog) {
if (![Window isKindOfClass:[AvnPanel class]]) {
CleanNSWindow();
Window = [[AvnPanel alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:GetStyle()];
}
} else {
if (![Window isKindOfClass:[AvnWindow class]]) {
CleanNSWindow();
Window = [[AvnWindow alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:GetStyle()];
}
}
}
void WindowBaseImpl::OnInitialiseNSWindow()
{
}
void WindowBaseImpl::InitialiseNSWindow() {
if(Window != nullptr) {
[Window setContentView:StandardContainer];
[Window setStyleMask:NSWindowStyleMaskBorderless];
[Window setBackingType:NSBackingStoreBuffered];
[Window setContentSize:lastSize];
[Window setContentMinSize:lastMinSize];
[Window setContentMaxSize:lastMaxSize];
[Window setOpaque:false];
if (lastMenu != nullptr) {
[GetWindowProtocol() applyMenu:lastMenu];
if ([Window isKeyWindow]) {
[GetWindowProtocol() showWindowMenuWithAppMenu];
}
}
OnInitialiseNSWindow();
}
}
id <AvnWindowProtocol> WindowBaseImpl::GetWindowProtocol() {
if(Window == nullptr)
{
return nullptr;
}
return (id <AvnWindowProtocol>) Window;
}
extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events, IAvnGlContext* gl)
{
@autoreleasepool
{
IAvnWindow* ptr = (IAvnWindow*)new WindowImpl(events, gl);
return ptr;
}
}

6
native/Avalonia.Native/src/OSX/WindowImpl.h

@ -6,7 +6,6 @@
#ifndef AVALONIA_NATIVE_OSX_WINDOWIMPL_H #ifndef AVALONIA_NATIVE_OSX_WINDOWIMPL_H
#define AVALONIA_NATIVE_OSX_WINDOWIMPL_H #define AVALONIA_NATIVE_OSX_WINDOWIMPL_H
#import "WindowBaseImpl.h" #import "WindowBaseImpl.h"
#include "IWindowStateChanged.h" #include "IWindowStateChanged.h"
@ -89,9 +88,14 @@ BEGIN_INTERFACE_MAP()
virtual HRESULT SetWindowState (AvnWindowState state) override; virtual HRESULT SetWindowState (AvnWindowState state) override;
virtual bool IsDialog() override; virtual bool IsDialog() override;
virtual void OnInitialiseNSWindow() override;
protected: protected:
virtual NSWindowStyleMask GetStyle() override; virtual NSWindowStyleMask GetStyle() override;
private:
NSString *_lastTitle;
}; };
#endif //AVALONIA_NATIVE_OSX_WINDOWIMPL_H #endif //AVALONIA_NATIVE_OSX_WINDOWIMPL_H

83
native/Avalonia.Native/src/OSX/WindowImpl.mm

@ -4,10 +4,10 @@
// //
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
#import "window.h" #include "AutoFitContentView.h"
#import "AutoFitContentView.h" #include "AvnView.h"
#import "AvnView.h"
#include "automation.h" #include "automation.h"
#include "WindowProtocol.h"
WindowImpl::WindowImpl(IAvnWindowEvents *events, IAvnGlContext *gl) : WindowBaseImpl(events, gl) { WindowImpl::WindowImpl(IAvnWindowEvents *events, IAvnGlContext *gl) : WindowBaseImpl(events, gl) {
_isClientAreaExtended = false; _isClientAreaExtended = false;
@ -19,11 +19,8 @@ WindowImpl::WindowImpl(IAvnWindowEvents *events, IAvnGlContext *gl) : WindowBase
_inSetWindowState = false; _inSetWindowState = false;
_lastWindowState = Normal; _lastWindowState = Normal;
_actualWindowState = Normal; _actualWindowState = Normal;
_lastTitle = @"";
WindowEvents = events; WindowEvents = events;
[Window setCanBecomeKeyAndMain];
[Window disableCursorRects];
[Window setTabbingMode:NSWindowTabbingModeDisallowed];
[Window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
} }
void WindowImpl::HideOrShowTrafficLights() { void WindowImpl::HideOrShowTrafficLights() {
@ -51,11 +48,27 @@ void WindowImpl::HideOrShowTrafficLights() {
} }
} }
void WindowImpl::OnInitialiseNSWindow(){
[GetWindowProtocol() setCanBecomeKeyWindow:true];
[Window disableCursorRects];
[Window setTabbingMode:NSWindowTabbingModeDisallowed];
[Window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
[Window setTitle:_lastTitle];
if(_isClientAreaExtended)
{
[GetWindowProtocol() setIsExtended:true];
SetExtendClientArea(true);
}
}
HRESULT WindowImpl::Show(bool activate, bool isDialog) { HRESULT WindowImpl::Show(bool activate, bool isDialog) {
START_COM_CALL; START_COM_CALL;
@autoreleasepool { @autoreleasepool {
_isDialog = isDialog; _isDialog = isDialog;
WindowBaseImpl::Show(activate, isDialog); WindowBaseImpl::Show(activate, isDialog);
HideOrShowTrafficLights(); HideOrShowTrafficLights();
@ -68,7 +81,7 @@ HRESULT WindowImpl::SetEnabled(bool enable) {
START_COM_CALL; START_COM_CALL;
@autoreleasepool { @autoreleasepool {
[Window setEnabled:enable]; [GetWindowProtocol() setEnabled:enable];
return S_OK; return S_OK;
} }
} }
@ -328,37 +341,39 @@ HRESULT WindowImpl::SetExtendClientArea(bool enable) {
@autoreleasepool { @autoreleasepool {
_isClientAreaExtended = enable; _isClientAreaExtended = enable;
if (enable) { if(Window != nullptr) {
Window.titleVisibility = NSWindowTitleHidden; if (enable) {
Window.titleVisibility = NSWindowTitleHidden;
[Window setTitlebarAppearsTransparent:true]; [Window setTitlebarAppearsTransparent:true];
auto wantsTitleBar = (_extendClientHints & AvnSystemChrome) || (_extendClientHints & AvnPreferSystemChrome); auto wantsTitleBar = (_extendClientHints & AvnSystemChrome) || (_extendClientHints & AvnPreferSystemChrome);
if (wantsTitleBar) { if (wantsTitleBar) {
[StandardContainer ShowTitleBar:true]; [StandardContainer ShowTitleBar:true];
} else { } else {
[StandardContainer ShowTitleBar:false]; [StandardContainer ShowTitleBar:false];
} }
if (_extendClientHints & AvnOSXThickTitleBar) { if (_extendClientHints & AvnOSXThickTitleBar) {
Window.toolbar = [NSToolbar new]; Window.toolbar = [NSToolbar new];
Window.toolbar.showsBaselineSeparator = false; Window.toolbar.showsBaselineSeparator = false;
} else {
Window.toolbar = nullptr;
}
} else { } else {
Window.titleVisibility = NSWindowTitleVisible;
Window.toolbar = nullptr; Window.toolbar = nullptr;
[Window setTitlebarAppearsTransparent:false];
View.layer.zPosition = 0;
} }
} else {
Window.titleVisibility = NSWindowTitleVisible;
Window.toolbar = nullptr;
[Window setTitlebarAppearsTransparent:false];
View.layer.zPosition = 0;
}
[Window setIsExtended:enable]; [GetWindowProtocol() setIsExtended:enable];
HideOrShowTrafficLights(); HideOrShowTrafficLights();
UpdateStyle(); UpdateStyle();
}
return S_OK; return S_OK;
} }
@ -383,7 +398,7 @@ HRESULT WindowImpl::GetExtendTitleBarHeight(double *ret) {
return E_POINTER; return E_POINTER;
} }
*ret = [Window getExtendedTitleBarHeight]; *ret = [GetWindowProtocol() getExtendedTitleBarHeight];
return S_OK; return S_OK;
} }
@ -417,6 +432,9 @@ HRESULT WindowImpl::SetWindowState(AvnWindowState state) {
START_COM_CALL; START_COM_CALL;
@autoreleasepool { @autoreleasepool {
auto currentState = _actualWindowState;
_lastWindowState = state;
if (Window == nullptr) { if (Window == nullptr) {
return S_OK; return S_OK;
} }
@ -427,9 +445,6 @@ HRESULT WindowImpl::SetWindowState(AvnWindowState state) {
_inSetWindowState = true; _inSetWindowState = true;
auto currentState = _actualWindowState;
_lastWindowState = state;
if (currentState == Normal) { if (currentState == Normal) {
_preZoomSize = [Window frame]; _preZoomSize = [Window frame];
} }
@ -508,7 +523,7 @@ bool WindowImpl::IsDialog() {
} }
NSWindowStyleMask WindowImpl::GetStyle() { NSWindowStyleMask WindowImpl::GetStyle() {
unsigned long s = NSWindowStyleMaskBorderless; unsigned long s = this->_isDialog ? NSWindowStyleMaskUtilityWindow : NSWindowStyleMaskBorderless;
switch (_decorations) { switch (_decorations) {
case SystemDecorationsNone: case SystemDecorationsNone:

17
native/Avalonia.Native/src/OSX/WindowInterfaces.h

@ -0,0 +1,17 @@
//
// Created by Dan Walmsley on 06/05/2022.
// Copyright (c) 2022 Avalonia. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#include "WindowProtocol.h"
#include "WindowBaseImpl.h"
@interface AvnWindow : NSWindow <AvnWindowProtocol, NSWindowDelegate>
-(AvnWindow* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask;
@end
@interface AvnPanel : NSPanel <AvnWindowProtocol, NSWindowDelegate>
-(AvnPanel* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask;
@end

21
native/Avalonia.Native/src/OSX/window.h → native/Avalonia.Native/src/OSX/WindowProtocol.h

@ -1,15 +1,15 @@
#ifndef window_h //
#define window_h // Created by Dan Walmsley on 06/05/2022.
// Copyright (c) 2022 Avalonia. All rights reserved.
//
#import "avalonia-native.h" #pragma once
@class AvnMenu; #import <AppKit/AppKit.h>
class WindowBaseImpl; @class AvnMenu;
@interface AvnWindow : NSWindow <NSWindowDelegate> @protocol AvnWindowProtocol
-(AvnWindow* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent;
-(void) setCanBecomeKeyAndMain;
-(void) pollModalSession: (NSModalSession _Nonnull) session; -(void) pollModalSession: (NSModalSession _Nonnull) session;
-(void) restoreParentWindow; -(void) restoreParentWindow;
-(bool) shouldTryToHandleEvents; -(bool) shouldTryToHandleEvents;
@ -20,7 +20,8 @@ class WindowBaseImpl;
-(double) getExtendedTitleBarHeight; -(double) getExtendedTitleBarHeight;
-(void) setIsExtended:(bool)value; -(void) setIsExtended:(bool)value;
-(void) disconnectParent;
-(bool) isDialog; -(bool) isDialog;
@end
#endif /* window_h */ -(void) setCanBecomeKeyWindow:(bool)value;
@end

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

@ -1,5 +1,6 @@
#import <Cocoa/Cocoa.h> #pragma once
#import <Cocoa/Cocoa.h>
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
class IAvnAutomationPeer; class IAvnAutomationPeer;

7
native/Avalonia.Native/src/OSX/automation.mm

@ -1,9 +1,8 @@
#include "common.h" #include "common.h"
#import "automation.h" #include "automation.h"
#import "window.h"
#include "AvnString.h" #include "AvnString.h"
#import "INSWindowHolder.h" #include "INSWindowHolder.h"
#import "AvnView.h" #include "AvnView.h"
@interface AvnAccessibilityElement (Events) @interface AvnAccessibilityElement (Events)
- (void) raiseChildrenChanged; - (void) raiseChildrenChanged;

1
native/Avalonia.Native/src/OSX/main.mm

@ -1,7 +1,6 @@
//This file will contain actual IID structures //This file will contain actual IID structures
#define COM_GUIDS_MATERIALIZE #define COM_GUIDS_MATERIALIZE
#include "common.h" #include "common.h"
#include "window.h"
static NSString* s_appTitle = @"Avalonia"; static NSString* s_appTitle = @"Avalonia";

1
native/Avalonia.Native/src/OSX/menu.mm

@ -1,7 +1,6 @@
#include "common.h" #include "common.h"
#include "menu.h" #include "menu.h"
#import "window.h"
#include "KeyTransform.h" #include "KeyTransform.h"
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#include <Carbon/Carbon.h> /* For kVK_ constants, and TIS functions. */ #include <Carbon/Carbon.h> /* For kVK_ constants, and TIS functions. */

1
samples/BindingDemo/BindingDemo.csproj

@ -5,6 +5,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
<ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" /> <ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" />
<ProjectReference Include="..\MiniMvvm\MiniMvvm.csproj" /> <ProjectReference Include="..\MiniMvvm\MiniMvvm.csproj" />
</ItemGroup> </ItemGroup>

2
samples/ControlCatalog/ControlCatalog.csproj

@ -25,6 +25,8 @@
<ProjectReference Include="..\..\packages\Avalonia\Avalonia.csproj" /> <ProjectReference Include="..\..\packages\Avalonia\Avalonia.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Controls.ColorPicker\Avalonia.Controls.ColorPicker.csproj" /> <ProjectReference Include="..\..\src\Avalonia.Controls.ColorPicker\Avalonia.Controls.ColorPicker.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Controls.DataGrid\Avalonia.Controls.DataGrid.csproj" /> <ProjectReference Include="..\..\src\Avalonia.Controls.DataGrid\Avalonia.Controls.DataGrid.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj" />
<ProjectReference Include="..\MiniMvvm\MiniMvvm.csproj" /> <ProjectReference Include="..\MiniMvvm\MiniMvvm.csproj" />
<ProjectReference Include="..\SampleControls\ControlSamples.csproj" /> <ProjectReference Include="..\SampleControls\ControlSamples.csproj" />
</ItemGroup> </ItemGroup>

3
samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml

@ -10,8 +10,7 @@
Margin="0,16,0,0" Margin="0,16,0,0"
HorizontalAlignment="Center" HorizontalAlignment="Center"
Spacing="16"> Spacing="16">
<StackPanel Orientation="Vertical" <StackPanel Orientation="Vertical">
Width="200">
<TextBlock Text="SelectedDateFormat: Short"/> <TextBlock Text="SelectedDateFormat: Short"/>
<CalendarDatePicker Name="DatePicker1" <CalendarDatePicker Name="DatePicker1"
SelectedDateFormat="Short" SelectedDateFormat="Short"

6
samples/ControlCatalog/Pages/TextBoxPage.xaml

@ -66,6 +66,12 @@
FontFamily="Comic Sans MS" FontFamily="Comic Sans MS"
InputMethod.IsInputMethodEnabled="False" InputMethod.IsInputMethodEnabled="False"
Foreground="Red"/> Foreground="Red"/>
<TextBox AcceptsReturn="True"
TextWrapping="Wrap"
Width="200"
Height="125"
LineHeight="32"
Text="Multiline TextBox with TextWrapping and increased LineHeight.&#xD;&#xD;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est." />
</StackPanel> </StackPanel>
<StackPanel Orientation="Vertical" Spacing="8" Margin="8"> <StackPanel Orientation="Vertical" Spacing="8" Margin="8">
<Label Classes="h2" Target="{Binding #firstResMFont}">res_m fonts</Label> <Label Classes="h2" Target="{Binding #firstResMFont}">res_m fonts</Label>

2
samples/ControlCatalog/ViewModels/MainWindowViewModel.cs

@ -18,7 +18,7 @@ namespace ControlCatalog.ViewModels
private WindowState _windowState; private WindowState _windowState;
private WindowState[] _windowStates; private WindowState[] _windowStates;
private int _transparencyLevel; private int _transparencyLevel;
private ExtendClientAreaChromeHints _chromeHints; private ExtendClientAreaChromeHints _chromeHints = ExtendClientAreaChromeHints.PreferSystemChrome;
private bool _extendClientAreaEnabled; private bool _extendClientAreaEnabled;
private bool _systemTitleBarEnabled; private bool _systemTitleBarEnabled;
private bool _preferSystemChromeEnabled; private bool _preferSystemChromeEnabled;

3
samples/IntegrationTestApp/IntegrationTestApp.csproj

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
@ -18,6 +18,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\BuildTargets.targets" /> <Import Project="..\..\build\BuildTargets.targets" />

1
samples/PlatformSanityChecks/PlatformSanityChecks.csproj

@ -7,6 +7,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Desktop\Avalonia.Desktop.csproj" /> <ProjectReference Include="..\..\src\Avalonia.Desktop\Avalonia.Desktop.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
<ProjectReference Include="..\..\src\Avalonia.X11\Avalonia.X11.csproj" /> <ProjectReference Include="..\..\src\Avalonia.X11\Avalonia.X11.csproj" />
</ItemGroup> </ItemGroup>

3
samples/Previewer/Previewer.csproj

@ -9,6 +9,9 @@
</Compile> </Compile>
<EmbeddedResource Include="**\*.xaml" /> <EmbeddedResource Include="**\*.xaml" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
</ItemGroup>
<Import Project="..\..\build\SampleApp.props" /> <Import Project="..\..\build\SampleApp.props" />
<Import Project="..\..\build\ReferenceCoreLibraries.props" /> <Import Project="..\..\build\ReferenceCoreLibraries.props" />

1
samples/RenderDemo/RenderDemo.csproj

@ -12,6 +12,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj" />
<ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" /> <ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" />
<ProjectReference Include="..\MiniMvvm\MiniMvvm.csproj" /> <ProjectReference Include="..\MiniMvvm\MiniMvvm.csproj" />
<ProjectReference Include="..\SampleControls\ControlSamples.csproj" /> <ProjectReference Include="..\SampleControls\ControlSamples.csproj" />

1
samples/Sandbox/Sandbox.csproj

@ -10,6 +10,7 @@
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Controls.ColorPicker\Avalonia.Controls.ColorPicker.csproj" /> <ProjectReference Include="..\..\src\Avalonia.Controls.ColorPicker\Avalonia.Controls.ColorPicker.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Controls.DataGrid\Avalonia.Controls.DataGrid.csproj" /> <ProjectReference Include="..\..\src\Avalonia.Controls.DataGrid\Avalonia.Controls.DataGrid.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\SampleApp.props" /> <Import Project="..\..\build\SampleApp.props" />

1
samples/VirtualizationDemo/VirtualizationDemo.csproj

@ -5,6 +5,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
<ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" /> <ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" />
<ProjectReference Include="..\MiniMvvm\MiniMvvm.csproj" /> <ProjectReference Include="..\MiniMvvm\MiniMvvm.csproj" />
</ItemGroup> </ItemGroup>

1
samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj

@ -22,6 +22,7 @@
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
<ProjectReference Include="..\..\..\src\Windows\Avalonia.Direct2D1\Avalonia.Direct2D1.csproj" /> <ProjectReference Include="..\..\..\src\Windows\Avalonia.Direct2D1\Avalonia.Direct2D1.csproj" />
<ProjectReference Include="..\..\..\src\Windows\Avalonia.Win32\Avalonia.Win32.csproj" /> <ProjectReference Include="..\..\..\src\Windows\Avalonia.Win32\Avalonia.Win32.csproj" />
<ProjectReference Include="..\..\MiniMvvm\MiniMvvm.csproj" /> <ProjectReference Include="..\..\MiniMvvm\MiniMvvm.csproj" />

1
samples/interop/NativeEmbedSample/NativeEmbedSample.csproj

@ -9,6 +9,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="MonoMac.NetStandard" Version="0.0.4" /> <PackageReference Include="MonoMac.NetStandard" Version="0.0.4" />
<ProjectReference Include="..\..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
<ProjectReference Include="..\..\..\src\Windows\Avalonia.Direct2D1\Avalonia.Direct2D1.csproj" /> <ProjectReference Include="..\..\..\src\Windows\Avalonia.Direct2D1\Avalonia.Direct2D1.csproj" />
<ProjectReference Include="..\..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> <ProjectReference Include="..\..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
<ProjectReference Include="..\..\..\src\Avalonia.X11\Avalonia.X11.csproj" /> <ProjectReference Include="..\..\..\src\Avalonia.X11\Avalonia.X11.csproj" />

2
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -40,7 +40,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
_gl = GlPlatformSurface.TryCreate(this); _gl = GlPlatformSurface.TryCreate(this);
_framebuffer = new FramebufferManager(this); _framebuffer = new FramebufferManager(this);
RenderScaling = (int)_view.Scaling; RenderScaling = _view.Scaling;
MaxClientSize = new PixelSize(_view.Resources.DisplayMetrics.WidthPixels, MaxClientSize = new PixelSize(_view.Resources.DisplayMetrics.WidthPixels,
_view.Resources.DisplayMetrics.HeightPixels).ToSize(RenderScaling); _view.Resources.DisplayMetrics.HeightPixels).ToSize(RenderScaling);

2
src/Avalonia.Base/Animation/IAnimation.cs

@ -1,12 +1,14 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Metadata;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
/// <summary> /// <summary>
/// Interface for Animation objects /// Interface for Animation objects
/// </summary> /// </summary>
[NotClientImplementable]
public interface IAnimation public interface IAnimation
{ {
/// <summary> /// <summary>

3
src/Avalonia.Base/Animation/IAnimationSetter.cs

@ -1,5 +1,8 @@
using Avalonia.Metadata;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
[NotClientImplementable]
public interface IAnimationSetter public interface IAnimationSetter
{ {
AvaloniaProperty? Property { get; set; } AvaloniaProperty? Property { get; set; }

2
src/Avalonia.Base/Animation/IAnimator.cs

@ -1,11 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Avalonia.Metadata;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
/// <summary> /// <summary>
/// Interface for Animator objects /// Interface for Animator objects
/// </summary> /// </summary>
[NotClientImplementable]
public interface IAnimator : IList<AnimatorKeyFrame> public interface IAnimator : IList<AnimatorKeyFrame>
{ {
/// <summary> /// <summary>

4
src/Avalonia.Base/Animation/IClock.cs

@ -1,9 +1,9 @@
using System; using System;
using System.Collections.Generic; using Avalonia.Metadata;
using System.Text;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
[NotClientImplementable]
public interface IClock : IObservable<TimeSpan> public interface IClock : IObservable<TimeSpan>
{ {
PlayState PlayState { get; set; } PlayState PlayState { get; set; }

5
src/Avalonia.Base/Animation/IGlobalClock.cs

@ -1,9 +1,8 @@
using System; using Avalonia.Metadata;
using System.Collections.Generic;
using System.Text;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
[NotClientImplementable]
public interface IGlobalClock : IClock public interface IGlobalClock : IClock
{ {
} }

2
src/Avalonia.Base/Animation/ITransition.cs

@ -1,10 +1,12 @@
using System; using System;
using Avalonia.Metadata;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
/// <summary> /// <summary>
/// Interface for Transition objects. /// Interface for Transition objects.
/// </summary> /// </summary>
[NotClientImplementable]
public interface ITransition public interface ITransition
{ {
/// <summary> /// <summary>

6
src/Avalonia.Base/Collections/AvaloniaList.cs

@ -394,7 +394,13 @@ namespace Avalonia.Collections
} while (en.MoveNext()); } while (en.MoveNext());
if (notificationItems is not null) if (notificationItems is not null)
{
NotifyAdd(notificationItems, index); NotifyAdd(notificationItems, index);
}
else
{
NotifyCountChanged();
}
} }
} }
} }

4
src/Avalonia.Base/Controls/INameScope.cs

@ -1,5 +1,4 @@
using System; using Avalonia.Metadata;
using System.Threading.Tasks;
using Avalonia.Utilities; using Avalonia.Utilities;
namespace Avalonia.Controls namespace Avalonia.Controls
@ -7,6 +6,7 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Defines a name scope. /// Defines a name scope.
/// </summary> /// </summary>
[NotClientImplementable]
public interface INameScope public interface INameScope
{ {
/// <summary> /// <summary>

2
src/Avalonia.Base/Controls/IPseudoClasses.cs

@ -1,9 +1,11 @@
using Avalonia.Metadata;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
/// <summary> /// <summary>
/// Exposes an interface for setting pseudoclasses on a <see cref="Classes"/> collection. /// Exposes an interface for setting pseudoclasses on a <see cref="Classes"/> collection.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IPseudoClasses public interface IPseudoClasses
{ {
/// <summary> /// <summary>

4
src/Avalonia.Base/Controls/IResourceHost.cs

@ -1,6 +1,5 @@
using System; using System;
using Avalonia.Metadata;
#nullable enable
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
@ -10,6 +9,7 @@ namespace Avalonia.Controls
/// <remarks> /// <remarks>
/// This interface is implemented by <see cref="StyledElement"/> and `Application`. /// This interface is implemented by <see cref="StyledElement"/> and `Application`.
/// </remarks> /// </remarks>
[NotClientImplementable]
public interface IResourceHost : IResourceNode public interface IResourceHost : IResourceNode
{ {
/// <summary> /// <summary>

4
src/Avalonia.Base/Controls/IResourceNode.cs

@ -1,6 +1,5 @@
using System; using System;
using Avalonia.Metadata;
#nullable enable
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
@ -12,6 +11,7 @@ namespace Avalonia.Controls
/// (<see cref="IResourceHost"/>) and resource providers such as <see cref="ResourceDictionary"/> /// (<see cref="IResourceHost"/>) and resource providers such as <see cref="ResourceDictionary"/>
/// (see <see cref="IResourceProvider"/>). /// (see <see cref="IResourceProvider"/>).
/// </remarks> /// </remarks>
[NotClientImplementable]
public interface IResourceNode public interface IResourceNode
{ {
/// <summary> /// <summary>

3
src/Avalonia.Base/Controls/ISetInheritanceParent.cs

@ -1,4 +1,4 @@
#nullable enable using Avalonia.Metadata;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
@ -10,6 +10,7 @@ namespace Avalonia.Controls
/// Additionally, <see cref="ISetLogicalParent"/> also sets the inheritance parent; this /// Additionally, <see cref="ISetLogicalParent"/> also sets the inheritance parent; this
/// interface is only needed where the logical and inheritance parents differ. /// interface is only needed where the logical and inheritance parents differ.
/// </remarks> /// </remarks>
[NotClientImplementable]
public interface ISetInheritanceParent public interface ISetInheritanceParent
{ {
/// <summary> /// <summary>

4
src/Avalonia.Base/Controls/ISetLogicalParent.cs

@ -1,6 +1,5 @@
using Avalonia.LogicalTree; using Avalonia.LogicalTree;
using Avalonia.Metadata;
#nullable enable
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
@ -10,6 +9,7 @@ namespace Avalonia.Controls
/// <remarks> /// <remarks>
/// You should not usually need to use this interface - it is for advanced scenarios only. /// You should not usually need to use this interface - it is for advanced scenarios only.
/// </remarks> /// </remarks>
[NotClientImplementable]
public interface ISetLogicalParent public interface ISetLogicalParent
{ {
/// <summary> /// <summary>

46
src/Avalonia.Base/Data/Core/ExpressionNode.cs

@ -98,36 +98,36 @@ namespace Avalonia.Data.Core
private void ValueChanged(object? value, bool notify) private void ValueChanged(object? value, bool notify)
{ {
if (_subscriber is null) if (_subscriber is { } subscriber)
return;
var notification = value as BindingNotification;
if (notification == null)
{ {
LastValue = value != null ? new WeakReference<object?>(value) : NullReference; var notification = value as BindingNotification;
var next = Next;
if (Next != null) if (notification == null)
{ {
Next.Target = LastValue; LastValue = value != null ? new WeakReference<object?>(value) : NullReference;
if (next != null)
{
next.Target = LastValue;
}
else if (notify)
{
subscriber(value);
}
} }
else if (notify) else
{ {
_subscriber(value); LastValue = notification.Value != null ? new WeakReference<object?>(notification.Value) : NullReference;
}
}
else
{
LastValue = notification.Value != null ? new WeakReference<object?>(notification.Value) : NullReference;
if (Next != null) if (next != null)
{ {
Next.Target = LastValue; next.Target = LastValue;
} }
if (Next == null || notification.Error != null) if (next == null || notification.Error != null)
{ {
_subscriber(value); subscriber(value);
}
} }
} }
} }

2
src/Avalonia.Base/Data/Core/IPropertyInfo.cs

@ -1,7 +1,9 @@
using System; using System;
using Avalonia.Metadata;
namespace Avalonia.Data.Core namespace Avalonia.Data.Core
{ {
[NotClientImplementable]
public interface IPropertyInfo public interface IPropertyInfo
{ {
string Name { get; } string Name { get; }

19
src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs

@ -17,7 +17,7 @@ namespace Avalonia.Data.Core.Plugins
new Dictionary<(Type, string), PropertyInfo?>(); new Dictionary<(Type, string), PropertyInfo?>();
/// <inheritdoc/> /// <inheritdoc/>
public bool Match(object obj, string propertyName) => GetFirstPropertyWithName(obj.GetType(), propertyName) != null; public bool Match(object obj, string propertyName) => GetFirstPropertyWithName(obj, propertyName) != null;
/// <summary> /// <summary>
/// Starts monitoring the value of a property on an object. /// Starts monitoring the value of a property on an object.
@ -36,7 +36,7 @@ namespace Avalonia.Data.Core.Plugins
if (!reference.TryGetTarget(out var instance) || instance is null) if (!reference.TryGetTarget(out var instance) || instance is null)
return null; return null;
var p = GetFirstPropertyWithName(instance.GetType(), propertyName); var p = GetFirstPropertyWithName(instance, propertyName);
if (p != null) if (p != null)
{ {
@ -50,8 +50,16 @@ namespace Avalonia.Data.Core.Plugins
} }
} }
private PropertyInfo? GetFirstPropertyWithName(Type type, string propertyName) private const BindingFlags PropertyBindingFlags =
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
private PropertyInfo? GetFirstPropertyWithName(object instance, string propertyName)
{ {
if (instance is IReflectableType reflectableType)
return reflectableType.GetTypeInfo().GetProperty(propertyName, PropertyBindingFlags);
var type = instance.GetType();
var key = (type, propertyName); var key = (type, propertyName);
if (!_propertyLookup.TryGetValue(key, out var propertyInfo)) if (!_propertyLookup.TryGetValue(key, out var propertyInfo))
@ -66,10 +74,7 @@ namespace Avalonia.Data.Core.Plugins
{ {
PropertyInfo? found = null; PropertyInfo? found = null;
const BindingFlags bindingFlags = var properties = type.GetProperties(PropertyBindingFlags);
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
var properties = type.GetProperties(bindingFlags);
foreach (PropertyInfo propertyInfo in properties) foreach (PropertyInfo propertyInfo in properties)
{ {

3
src/Avalonia.Base/Data/IBinding.cs

@ -1,8 +1,11 @@
using Avalonia.Metadata;
namespace Avalonia.Data namespace Avalonia.Data
{ {
/// <summary> /// <summary>
/// Holds a binding that can be applied to a property on an object. /// Holds a binding that can be applied to a property on an object.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IBinding public interface IBinding
{ {
/// <summary> /// <summary>

5
src/Avalonia.Base/DirectPropertyBase.cs

@ -2,7 +2,6 @@
using Avalonia.Data; using Avalonia.Data;
using Avalonia.Reactive; using Avalonia.Reactive;
using Avalonia.Styling; using Avalonia.Styling;
using Avalonia.Utilities;
namespace Avalonia namespace Avalonia
{ {
@ -188,10 +187,10 @@ namespace Avalonia
} }
else if (value is ITemplate template && !typeof(ITemplate).IsAssignableFrom(PropertyType)) else if (value is ITemplate template && !typeof(ITemplate).IsAssignableFrom(PropertyType))
{ {
return new PropertySetterLazyInstance<TValue>( return new PropertySetterTemplateInstance<TValue>(
target, target,
this, this,
() => (TValue)template.Build()); template);
} }
else else
{ {

2
src/Avalonia.Base/IAvaloniaObject.cs

@ -1,11 +1,13 @@
using System; using System;
using Avalonia.Data; using Avalonia.Data;
using Avalonia.Metadata;
namespace Avalonia namespace Avalonia
{ {
/// <summary> /// <summary>
/// Interface for getting/setting <see cref="AvaloniaProperty"/> values on an object. /// Interface for getting/setting <see cref="AvaloniaProperty"/> values on an object.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IAvaloniaObject public interface IAvaloniaObject
{ {
/// <summary> /// <summary>

3
src/Avalonia.Base/IDataContextProvider.cs

@ -1,10 +1,11 @@
#nullable enable using Avalonia.Metadata;
namespace Avalonia namespace Avalonia
{ {
/// <summary> /// <summary>
/// Defines an element with a data context that can be used for binding. /// Defines an element with a data context that can be used for binding.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IDataContextProvider : IAvaloniaObject public interface IDataContextProvider : IAvaloniaObject
{ {
/// <summary> /// <summary>

1
src/Avalonia.Base/IDirectPropertyAccessor.cs

@ -1,4 +1,5 @@
using System; using System;
using Avalonia.Metadata;
namespace Avalonia namespace Avalonia
{ {

3
src/Avalonia.Base/IDirectPropertyMetadata.cs

@ -1,8 +1,11 @@
using Avalonia.Metadata;
namespace Avalonia namespace Avalonia
{ {
/// <summary> /// <summary>
/// Untyped interface to <see cref="DirectPropertyMetadata{TValue}"/> /// Untyped interface to <see cref="DirectPropertyMetadata{TValue}"/>
/// </summary> /// </summary>
[NotClientImplementable]
public interface IDirectPropertyMetadata public interface IDirectPropertyMetadata
{ {
/// <summary> /// <summary>

4
src/Avalonia.Base/IStyledElement.cs

@ -2,12 +2,12 @@
using System.ComponentModel; using System.ComponentModel;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.LogicalTree; using Avalonia.LogicalTree;
using Avalonia.Metadata;
using Avalonia.Styling; using Avalonia.Styling;
#nullable enable
namespace Avalonia namespace Avalonia
{ {
[NotClientImplementable]
public interface IStyledElement : public interface IStyledElement :
IStyleable, IStyleable,
IStyleHost, IStyleHost,

3
src/Avalonia.Base/IStyledPropertyMetadata.cs

@ -1,8 +1,11 @@
using Avalonia.Metadata;
namespace Avalonia namespace Avalonia
{ {
/// <summary> /// <summary>
/// Untyped interface to <see cref="StyledPropertyMetadata{TValue}"/> /// Untyped interface to <see cref="StyledPropertyMetadata{TValue}"/>
/// </summary> /// </summary>
[NotClientImplementable]
public interface IStyledPropertyMetadata public interface IStyledPropertyMetadata
{ {
/// <summary> /// <summary>

3
src/Avalonia.Base/Input/IAccessKeyHandler.cs

@ -1,8 +1,11 @@
using Avalonia.Metadata;
namespace Avalonia.Input namespace Avalonia.Input
{ {
/// <summary> /// <summary>
/// Defines the interface for classes that handle access keys for a window. /// Defines the interface for classes that handle access keys for a window.
/// </summary> /// </summary>
[Unstable]
public interface IAccessKeyHandler public interface IAccessKeyHandler
{ {
/// <summary> /// <summary>

3
src/Avalonia.Base/Input/IFocusManager.cs

@ -1,8 +1,11 @@
using Avalonia.Metadata;
namespace Avalonia.Input namespace Avalonia.Input
{ {
/// <summary> /// <summary>
/// Manages focus for the application. /// Manages focus for the application.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IFocusManager public interface IFocusManager
{ {
/// <summary> /// <summary>

2
src/Avalonia.Base/Input/IInputDevice.cs

@ -1,7 +1,9 @@
using Avalonia.Input.Raw; using Avalonia.Input.Raw;
using Avalonia.Metadata;
namespace Avalonia.Input namespace Avalonia.Input
{ {
[NotClientImplementable]
public interface IInputDevice public interface IInputDevice
{ {
/// <summary> /// <summary>

2
src/Avalonia.Base/Input/IInputElement.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Metadata;
using Avalonia.VisualTree; using Avalonia.VisualTree;
#nullable enable #nullable enable
@ -10,6 +11,7 @@ namespace Avalonia.Input
/// <summary> /// <summary>
/// Defines input-related functionality for a control. /// Defines input-related functionality for a control.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IInputElement : IInteractive, IVisual public interface IInputElement : IInteractive, IVisual
{ {
/// <summary> /// <summary>

2
src/Avalonia.Base/Input/IInputManager.cs

@ -1,5 +1,6 @@
using System; using System;
using Avalonia.Input.Raw; using Avalonia.Input.Raw;
using Avalonia.Metadata;
namespace Avalonia.Input namespace Avalonia.Input
{ {
@ -7,6 +8,7 @@ namespace Avalonia.Input
/// Receives input from the windowing subsystem and dispatches it to interested parties /// Receives input from the windowing subsystem and dispatches it to interested parties
/// for processing. /// for processing.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IInputManager public interface IInputManager
{ {
/// <summary> /// <summary>

3
src/Avalonia.Base/Input/IInputRoot.cs

@ -1,8 +1,11 @@
using Avalonia.Metadata;
namespace Avalonia.Input namespace Avalonia.Input
{ {
/// <summary> /// <summary>
/// Defines the interface for top-level input elements. /// Defines the interface for top-level input elements.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IInputRoot : IInputElement public interface IInputRoot : IInputElement
{ {
/// <summary> /// <summary>

2
src/Avalonia.Base/Input/IKeyboardDevice.cs

@ -1,5 +1,6 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using Avalonia.Metadata;
namespace Avalonia.Input namespace Avalonia.Input
{ {
@ -50,6 +51,7 @@ namespace Avalonia.Input
KeyboardMask = Alt | Control | Shift | Meta KeyboardMask = Alt | Control | Shift | Meta
} }
[NotClientImplementable]
public interface IKeyboardDevice : IInputDevice, INotifyPropertyChanged public interface IKeyboardDevice : IInputDevice, INotifyPropertyChanged
{ {
IInputElement? FocusedElement { get; } IInputElement? FocusedElement { get; }

3
src/Avalonia.Base/Input/IKeyboardNavigationHandler.cs

@ -1,8 +1,11 @@
using Avalonia.Metadata;
namespace Avalonia.Input namespace Avalonia.Input
{ {
/// <summary> /// <summary>
/// Defines the interface for classes that handle keyboard navigation for a window. /// Defines the interface for classes that handle keyboard navigation for a window.
/// </summary> /// </summary>
[Unstable]
public interface IKeyboardNavigationHandler public interface IKeyboardNavigationHandler
{ {
/// <summary> /// <summary>

2
src/Avalonia.Base/Input/IMainMenu.cs

@ -1,5 +1,6 @@
using System; using System;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Metadata;
using Avalonia.VisualTree; using Avalonia.VisualTree;
namespace Avalonia.Input namespace Avalonia.Input
@ -7,6 +8,7 @@ namespace Avalonia.Input
/// <summary> /// <summary>
/// Defines the interface for a window's main menu. /// Defines the interface for a window's main menu.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IMainMenu : IVisual public interface IMainMenu : IVisual
{ {
/// <summary> /// <summary>

2
src/Avalonia.Base/Input/IMouseDevice.cs

@ -1,10 +1,12 @@
using System; using System;
using Avalonia.Metadata;
namespace Avalonia.Input namespace Avalonia.Input
{ {
/// <summary> /// <summary>
/// Represents a mouse device. /// Represents a mouse device.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IMouseDevice : IPointerDevice public interface IMouseDevice : IPointerDevice
{ {
/// <summary> /// <summary>

3
src/Avalonia.Base/Input/IPointer.cs

@ -1,5 +1,8 @@
using Avalonia.Metadata;
namespace Avalonia.Input namespace Avalonia.Input
{ {
[NotClientImplementable]
public interface IPointer public interface IPointer
{ {
int Id { get; } int Id { get; }

2
src/Avalonia.Base/Input/IPointerDevice.cs

@ -1,9 +1,11 @@
using System; using System;
using Avalonia.VisualTree; using Avalonia.VisualTree;
using Avalonia.Input.Raw; using Avalonia.Input.Raw;
using Avalonia.Metadata;
namespace Avalonia.Input namespace Avalonia.Input
{ {
[NotClientImplementable]
public interface IPointerDevice : IInputDevice public interface IPointerDevice : IInputDevice
{ {
/// <inheritdoc cref="IPointer.Captured" /> /// <inheritdoc cref="IPointer.Captured" />

18
src/Avalonia.Base/Input/InputElement.cs

@ -94,7 +94,7 @@ namespace Avalonia.Input
/// </summary> /// </summary>
public static readonly RoutedEvent<KeyEventArgs> KeyDownEvent = public static readonly RoutedEvent<KeyEventArgs> KeyDownEvent =
RoutedEvent.Register<InputElement, KeyEventArgs>( RoutedEvent.Register<InputElement, KeyEventArgs>(
"KeyDown", nameof(KeyDown),
RoutingStrategies.Tunnel | RoutingStrategies.Bubble); RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
/// <summary> /// <summary>
@ -102,7 +102,7 @@ namespace Avalonia.Input
/// </summary> /// </summary>
public static readonly RoutedEvent<KeyEventArgs> KeyUpEvent = public static readonly RoutedEvent<KeyEventArgs> KeyUpEvent =
RoutedEvent.Register<InputElement, KeyEventArgs>( RoutedEvent.Register<InputElement, KeyEventArgs>(
"KeyUp", nameof(KeyUp),
RoutingStrategies.Tunnel | RoutingStrategies.Bubble); RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
/// <summary> /// <summary>
@ -116,7 +116,7 @@ namespace Avalonia.Input
/// </summary> /// </summary>
public static readonly RoutedEvent<TextInputEventArgs> TextInputEvent = public static readonly RoutedEvent<TextInputEventArgs> TextInputEvent =
RoutedEvent.Register<InputElement, TextInputEventArgs>( RoutedEvent.Register<InputElement, TextInputEventArgs>(
"TextInput", nameof(TextInput),
RoutingStrategies.Tunnel | RoutingStrategies.Bubble); RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
/// <summary> /// <summary>
@ -124,7 +124,7 @@ namespace Avalonia.Input
/// </summary> /// </summary>
public static readonly RoutedEvent<TextInputMethodClientRequestedEventArgs> TextInputMethodClientRequestedEvent = public static readonly RoutedEvent<TextInputMethodClientRequestedEventArgs> TextInputMethodClientRequestedEvent =
RoutedEvent.Register<InputElement, TextInputMethodClientRequestedEventArgs>( RoutedEvent.Register<InputElement, TextInputMethodClientRequestedEventArgs>(
"TextInputMethodClientRequested", nameof(TextInputMethodClientRequested),
RoutingStrategies.Tunnel | RoutingStrategies.Bubble); RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
/// <summary> /// <summary>
@ -144,7 +144,7 @@ namespace Avalonia.Input
/// </summary> /// </summary>
public static readonly RoutedEvent<PointerEventArgs> PointerMovedEvent = public static readonly RoutedEvent<PointerEventArgs> PointerMovedEvent =
RoutedEvent.Register<InputElement, PointerEventArgs>( RoutedEvent.Register<InputElement, PointerEventArgs>(
"PointerMove", nameof(PointerMoved),
RoutingStrategies.Tunnel | RoutingStrategies.Bubble); RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
/// <summary> /// <summary>
@ -152,7 +152,7 @@ namespace Avalonia.Input
/// </summary> /// </summary>
public static readonly RoutedEvent<PointerPressedEventArgs> PointerPressedEvent = public static readonly RoutedEvent<PointerPressedEventArgs> PointerPressedEvent =
RoutedEvent.Register<InputElement, PointerPressedEventArgs>( RoutedEvent.Register<InputElement, PointerPressedEventArgs>(
"PointerPressed", nameof(PointerPressed),
RoutingStrategies.Tunnel | RoutingStrategies.Bubble); RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
/// <summary> /// <summary>
@ -160,7 +160,7 @@ namespace Avalonia.Input
/// </summary> /// </summary>
public static readonly RoutedEvent<PointerReleasedEventArgs> PointerReleasedEvent = public static readonly RoutedEvent<PointerReleasedEventArgs> PointerReleasedEvent =
RoutedEvent.Register<InputElement, PointerReleasedEventArgs>( RoutedEvent.Register<InputElement, PointerReleasedEventArgs>(
"PointerReleased", nameof(PointerReleased),
RoutingStrategies.Tunnel | RoutingStrategies.Bubble); RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
/// <summary> /// <summary>
@ -168,7 +168,7 @@ namespace Avalonia.Input
/// </summary> /// </summary>
public static readonly RoutedEvent<PointerCaptureLostEventArgs> PointerCaptureLostEvent = public static readonly RoutedEvent<PointerCaptureLostEventArgs> PointerCaptureLostEvent =
RoutedEvent.Register<InputElement, PointerCaptureLostEventArgs>( RoutedEvent.Register<InputElement, PointerCaptureLostEventArgs>(
"PointerCaptureLost", nameof(PointerCaptureLost),
RoutingStrategies.Direct); RoutingStrategies.Direct);
/// <summary> /// <summary>
@ -176,7 +176,7 @@ namespace Avalonia.Input
/// </summary> /// </summary>
public static readonly RoutedEvent<PointerWheelEventArgs> PointerWheelChangedEvent = public static readonly RoutedEvent<PointerWheelEventArgs> PointerWheelChangedEvent =
RoutedEvent.Register<InputElement, PointerWheelEventArgs>( RoutedEvent.Register<InputElement, PointerWheelEventArgs>(
"PointerWheelChanged", nameof(PointerWheelChanged),
RoutingStrategies.Tunnel | RoutingStrategies.Bubble); RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
/// <summary> /// <summary>

2
src/Avalonia.Base/Input/Platform/IClipboard.cs

@ -1,7 +1,9 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Metadata;
namespace Avalonia.Input.Platform namespace Avalonia.Input.Platform
{ {
[NotClientImplementable]
public interface IClipboard public interface IClipboard
{ {
Task<string> GetTextAsync(); Task<string> GetTextAsync();

2
src/Avalonia.Base/Input/Platform/IPlatformDragSource.cs

@ -1,7 +1,9 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Metadata;
namespace Avalonia.Input.Platform namespace Avalonia.Input.Platform
{ {
[Unstable]
public interface IPlatformDragSource public interface IPlatformDragSource
{ {
Task<DragDropEffects> DoDragDrop(PointerEventArgs triggerEvent, IDataObject data, DragDropEffects allowedEffects); Task<DragDropEffects> DoDragDrop(PointerEventArgs triggerEvent, IDataObject data, DragDropEffects allowedEffects);

5
src/Avalonia.Base/Input/Raw/IDragDropDevice.cs

@ -1,5 +1,8 @@
namespace Avalonia.Input.Raw using Avalonia.Metadata;
namespace Avalonia.Input.Raw
{ {
[NotClientImplementable]
public interface IDragDropDevice : IInputDevice public interface IDragDropDevice : IInputDevice
{ {
} }

4
src/Avalonia.Base/Input/TextInput/ITextInputMethodImpl.cs

@ -1,5 +1,8 @@
using Avalonia.Metadata;
namespace Avalonia.Input.TextInput namespace Avalonia.Input.TextInput
{ {
[Unstable]
public interface ITextInputMethodImpl public interface ITextInputMethodImpl
{ {
void SetClient(ITextInputMethodClient? client); void SetClient(ITextInputMethodClient? client);
@ -8,6 +11,7 @@ namespace Avalonia.Input.TextInput
void Reset(); void Reset();
} }
[NotClientImplementable]
public interface ITextInputMethodRoot : IInputRoot public interface ITextInputMethodRoot : IInputRoot
{ {
ITextInputMethodImpl? InputMethod { get; } ITextInputMethodImpl? InputMethod { get; }

2
src/Avalonia.Base/Interactivity/IInteractive.cs

@ -1,4 +1,5 @@
using System; using System;
using Avalonia.Metadata;
#nullable enable #nullable enable
@ -7,6 +8,7 @@ namespace Avalonia.Interactivity
/// <summary> /// <summary>
/// Interface for objects that raise routed events. /// Interface for objects that raise routed events.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IInteractive public interface IInteractive
{ {
/// <summary> /// <summary>

4
src/Avalonia.Base/Layout/ILayoutManager.cs

@ -1,12 +1,12 @@
using System; using System;
using Avalonia.Metadata;
#nullable enable
namespace Avalonia.Layout namespace Avalonia.Layout
{ {
/// <summary> /// <summary>
/// Manages measuring and arranging of controls. /// Manages measuring and arranging of controls.
/// </summary> /// </summary>
[NotClientImplementable]
public interface ILayoutManager : IDisposable public interface ILayoutManager : IDisposable
{ {
/// <summary> /// <summary>

3
src/Avalonia.Base/Layout/ILayoutRoot.cs

@ -1,8 +1,11 @@
using Avalonia.Metadata;
namespace Avalonia.Layout namespace Avalonia.Layout
{ {
/// <summary> /// <summary>
/// Defines the root of a layoutable tree. /// Defines the root of a layoutable tree.
/// </summary> /// </summary>
[NotClientImplementable]
public interface ILayoutRoot : ILayoutable public interface ILayoutRoot : ILayoutable
{ {
/// <summary> /// <summary>

4
src/Avalonia.Base/Layout/ILayoutable.cs

@ -1,12 +1,12 @@
using Avalonia.Metadata;
using Avalonia.VisualTree; using Avalonia.VisualTree;
#nullable enable
namespace Avalonia.Layout namespace Avalonia.Layout
{ {
/// <summary> /// <summary>
/// Defines layout-related functionality for a control. /// Defines layout-related functionality for a control.
/// </summary> /// </summary>
[NotClientImplementable]
public interface ILayoutable : IVisual public interface ILayoutable : IVisual
{ {
/// <summary> /// <summary>

20
src/Avalonia.Base/Layout/Layoutable.cs

@ -141,7 +141,6 @@ namespace Avalonia.Layout
static Layoutable() static Layoutable()
{ {
AffectsMeasure<Layoutable>( AffectsMeasure<Layoutable>(
IsVisibleProperty,
WidthProperty, WidthProperty,
HeightProperty, HeightProperty,
MinWidthProperty, MinWidthProperty,
@ -791,6 +790,25 @@ namespace Avalonia.Layout
{ {
} }
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == IsVisibleProperty)
{
DesiredSize = default;
// All changes to visibility cause the parent element to be notified.
this.GetVisualParent<ILayoutable>()?.ChildDesiredSizeChanged(this);
// We only invalidate outselves when visibility is changed to true.
if (change.GetNewValue<bool>())
{
InvalidateMeasure();
}
}
}
/// <inheritdoc/> /// <inheritdoc/>
protected sealed override void OnVisualParentChanged(IVisual? oldParent, IVisual? newParent) protected sealed override void OnVisualParentChanged(IVisual? oldParent, IVisual? newParent)
{ {

2
src/Avalonia.Base/Layout/UniformGridLayout.cs

@ -116,7 +116,7 @@ namespace Avalonia.Layout
/// Defines the <see cref="MaximumRowsOrColumnsProperty"/> property. /// Defines the <see cref="MaximumRowsOrColumnsProperty"/> property.
/// </summary> /// </summary>
public static readonly StyledProperty<int> MaximumRowsOrColumnsProperty = public static readonly StyledProperty<int> MaximumRowsOrColumnsProperty =
AvaloniaProperty.Register<UniformGridLayout, int>(nameof(MinItemWidth)); AvaloniaProperty.Register<UniformGridLayout, int>(nameof(MaximumRowsOrColumns));
/// <summary> /// <summary>
/// Defines the <see cref="Orientation"/> property. /// Defines the <see cref="Orientation"/> property.

2
src/Avalonia.Base/LogicalTree/ILogical.cs

@ -1,12 +1,14 @@
using System; using System;
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Metadata;
namespace Avalonia.LogicalTree namespace Avalonia.LogicalTree
{ {
/// <summary> /// <summary>
/// Represents a node in the logical tree. /// Represents a node in the logical tree.
/// </summary> /// </summary>
[NotClientImplementable]
public interface ILogical public interface ILogical
{ {
/// <summary> /// <summary>

5
src/Avalonia.Base/LogicalTree/ILogicalRoot.cs

@ -1,8 +1,11 @@
namespace Avalonia.LogicalTree using Avalonia.Metadata;
namespace Avalonia.LogicalTree
{ {
/// <summary> /// <summary>
/// Represents a root of a logical tree. /// Represents a root of a logical tree.
/// </summary> /// </summary>
[NotClientImplementable]
public interface ILogicalRoot : ILogical public interface ILogicalRoot : ILogical
{ {
} }

4
src/Avalonia.Base/Media/ConicGradientBrush.cs

@ -11,7 +11,7 @@ namespace Avalonia.Media
/// Defines the <see cref="Center"/> property. /// Defines the <see cref="Center"/> property.
/// </summary> /// </summary>
public static readonly StyledProperty<RelativePoint> CenterProperty = public static readonly StyledProperty<RelativePoint> CenterProperty =
AvaloniaProperty.Register<RadialGradientBrush, RelativePoint>( AvaloniaProperty.Register<ConicGradientBrush, RelativePoint>(
nameof(Center), nameof(Center),
RelativePoint.Center); RelativePoint.Center);
@ -19,7 +19,7 @@ namespace Avalonia.Media
/// Defines the <see cref="Angle"/> property. /// Defines the <see cref="Angle"/> property.
/// </summary> /// </summary>
public static readonly StyledProperty<double> AngleProperty = public static readonly StyledProperty<double> AngleProperty =
AvaloniaProperty.Register<RadialGradientBrush, double>( AvaloniaProperty.Register<ConicGradientBrush, double>(
nameof(Angle), nameof(Angle),
0); 0);

2
src/Avalonia.Base/Media/IBrush.cs

@ -1,4 +1,5 @@
using System.ComponentModel; using System.ComponentModel;
using Avalonia.Metadata;
namespace Avalonia.Media namespace Avalonia.Media
{ {
@ -6,6 +7,7 @@ namespace Avalonia.Media
/// Describes how an area is painted. /// Describes how an area is painted.
/// </summary> /// </summary>
[TypeConverter(typeof(BrushConverter))] [TypeConverter(typeof(BrushConverter))]
[NotClientImplementable]
public interface IBrush public interface IBrush
{ {
/// <summary> /// <summary>

5
src/Avalonia.Base/Media/IConicGradientBrush.cs

@ -1,8 +1,11 @@
namespace Avalonia.Media using Avalonia.Metadata;
namespace Avalonia.Media
{ {
/// <summary> /// <summary>
/// Paints an area with a conic gradient. /// Paints an area with a conic gradient.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IConicGradientBrush : IGradientBrush public interface IConicGradientBrush : IGradientBrush
{ {
/// <summary> /// <summary>

2
src/Avalonia.Base/Media/IDashStyle.cs

@ -1,10 +1,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using Avalonia.Metadata;
namespace Avalonia.Media namespace Avalonia.Media
{ {
/// <summary> /// <summary>
/// Represents the sequence of dashes and gaps that will be applied by a <see cref="Pen"/>. /// Represents the sequence of dashes and gaps that will be applied by a <see cref="Pen"/>.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IDashStyle public interface IDashStyle
{ {
/// <summary> /// <summary>

5
src/Avalonia.Base/Media/IExperimentalAcrylicMaterial.cs

@ -1,8 +1,11 @@
namespace Avalonia.Media using Avalonia.Metadata;
namespace Avalonia.Media
{ {
/// <summary> /// <summary>
/// Experimental Interface for producing Acrylic-like materials. /// Experimental Interface for producing Acrylic-like materials.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IExperimentalAcrylicMaterial public interface IExperimentalAcrylicMaterial
{ {
/// <summary> /// <summary>

2
src/Avalonia.Base/Media/IGradientBrush.cs

@ -1,10 +1,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using Avalonia.Metadata;
namespace Avalonia.Media namespace Avalonia.Media
{ {
/// <summary> /// <summary>
/// A brush that draws with a gradient. /// A brush that draws with a gradient.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IGradientBrush : IBrush public interface IGradientBrush : IBrush
{ {
/// <summary> /// <summary>

5
src/Avalonia.Base/Media/IGradientStop.cs

@ -1,8 +1,11 @@
namespace Avalonia.Media using Avalonia.Metadata;
namespace Avalonia.Media
{ {
/// <summary> /// <summary>
/// Describes the location and color of a transition point in a gradient. /// Describes the location and color of a transition point in a gradient.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IGradientStop public interface IGradientStop
{ {
/// <summary> /// <summary>

4
src/Avalonia.Base/Media/IImageBrush.cs

@ -1,10 +1,12 @@
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.Metadata;
namespace Avalonia.Media namespace Avalonia.Media
{ {
/// <summary> /// <summary>
/// Paints an area with an <see cref="IBitmap"/>. /// Paints an area with an <see cref="IBitmap"/>.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IImageBrush : ITileBrush public interface IImageBrush : ITileBrush
{ {
/// <summary> /// <summary>
@ -12,4 +14,4 @@ namespace Avalonia.Media
/// </summary> /// </summary>
IBitmap Source { get; } IBitmap Source { get; }
} }
} }

7
src/Avalonia.Base/Media/ILinearGradientBrush.cs

@ -1,8 +1,11 @@
namespace Avalonia.Media using Avalonia.Metadata;
namespace Avalonia.Media
{ {
/// <summary> /// <summary>
/// A brush that draws with a linear gradient. /// A brush that draws with a linear gradient.
/// </summary> /// </summary>
[NotClientImplementable]
public interface ILinearGradientBrush : IGradientBrush public interface ILinearGradientBrush : IGradientBrush
{ {
/// <summary> /// <summary>
@ -15,4 +18,4 @@
/// </summary> /// </summary>
RelativePoint EndPoint { get; } RelativePoint EndPoint { get; }
} }
} }

2
src/Avalonia.Base/Media/IMutableBrush.cs

@ -1,10 +1,12 @@
using System; using System;
using Avalonia.Metadata;
namespace Avalonia.Media namespace Avalonia.Media
{ {
/// <summary> /// <summary>
/// Represents a mutable brush which can return an immutable clone of itself. /// Represents a mutable brush which can return an immutable clone of itself.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IMutableBrush : IBrush, IAffectsRender public interface IMutableBrush : IBrush, IAffectsRender
{ {
/// <summary> /// <summary>

5
src/Avalonia.Base/Media/IMutableExperimentalAcrylicMaterial.cs

@ -1,8 +1,11 @@
namespace Avalonia.Media using Avalonia.Metadata;
namespace Avalonia.Media
{ {
/// <summary> /// <summary>
/// Represents a mutable brush which can return an immutable clone of itself. /// Represents a mutable brush which can return an immutable clone of itself.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IMutableExperimentalAcrylicMaterial : IExperimentalAcrylicMaterial, IAffectsRender public interface IMutableExperimentalAcrylicMaterial : IExperimentalAcrylicMaterial, IAffectsRender
{ {
/// <summary> /// <summary>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save