diff --git a/Avalonia.sln b/Avalonia.sln
index 2409dbfae4..3a2c619d5b 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -95,8 +95,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.UnitTests", "tests
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Benchmarks", "tests\Avalonia.Benchmarks\Avalonia.Benchmarks.csproj", "{410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Logging.Serilog", "src\Avalonia.Logging.Serilog\Avalonia.Logging.Serilog.csproj", "{B61B66A3-B82D-4875-8001-89D3394FE0C9}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesignerSupport", "src\Avalonia.DesignerSupport\Avalonia.DesignerSupport.csproj", "{799A7BB5-3C2C-48B6-85A7-406A12C420DA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog", "samples\ControlCatalog\ControlCatalog.csproj", "{D0A739B9-3C68-4BA6-A328-41606954B6BD}"
@@ -140,7 +138,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\ReactiveUI.props = build\ReactiveUI.props
build\Rx.props = build\Rx.props
build\SampleApp.props = build\SampleApp.props
- build\Serilog.props = build\Serilog.props
build\SharpDX.props = build\SharpDX.props
build\SkiaSharp.props = build\SkiaSharp.props
build\System.Memory.props = build\System.Memory.props
@@ -208,6 +205,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Controls.DataGrid.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NativeEmbedSample", "samples\interop\NativeEmbedSample\NativeEmbedSample.csproj", "{3C84E04B-36CF-4D0D-B965-C26DD649D1F3}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Themes.Fluent", "src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj", "{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}"
+EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
@@ -1027,30 +1026,6 @@ Global
{410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Release|iPhone.Build.0 = Release|Any CPU
{410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.AppStore|Any CPU.Build.0 = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.AppStore|iPhone.ActiveCfg = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.AppStore|iPhone.Build.0 = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Debug|iPhone.ActiveCfg = Debug|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Debug|iPhone.Build.0 = Debug|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Release|Any CPU.Build.0 = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Release|iPhone.ActiveCfg = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Release|iPhone.Build.0 = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
- {B61B66A3-B82D-4875-8001-89D3394FE0C9}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{799A7BB5-3C2C-48B6-85A7-406A12C420DA}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{799A7BB5-3C2C-48B6-85A7-406A12C420DA}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{799A7BB5-3C2C-48B6-85A7-406A12C420DA}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
@@ -1947,6 +1922,30 @@ Global
{3C84E04B-36CF-4D0D-B965-C26DD649D1F3}.Release|iPhone.Build.0 = Release|Any CPU
{3C84E04B-36CF-4D0D-B965-C26DD649D1F3}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{3C84E04B-36CF-4D0D-B965-C26DD649D1F3}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|iPhone.Build.0 = Release|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Documentation/build.md b/Documentation/build.md
index 56b028206d..8c2ef57b54 100644
--- a/Documentation/build.md
+++ b/Documentation/build.md
@@ -36,7 +36,7 @@ Avalonia requires [CastXML](https://github.com/CastXML/CastXML) for XML processi
On macOS:
```
-brew install castxml
+brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/8a004a91a7fcd3f6620d5b01b6541ff0a640ffba/Formula/castxml.rb
```
On Debian based Linux (Debian, Ubuntu, Mint, etc):
diff --git a/NOTICE.md b/NOTICE.md
index 0e1d792e84..92fd725957 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -271,3 +271,35 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
+
+# Chromium
+
+https://github.com/chromium/chromium
+
+// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/build.sh b/build.sh
index 40b1c225a6..a40e00f815 100755
--- a/build.sh
+++ b/build.sh
@@ -67,6 +67,8 @@ else
fi
fi
+export PATH=$DOTNET_DIRECTORY:$PATH
+
echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)"
"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" -- ${BUILD_ARGUMENTS[@]}
diff --git a/build/CoreLibraries.props b/build/CoreLibraries.props
index d61268173d..d17eec0135 100644
--- a/build/CoreLibraries.props
+++ b/build/CoreLibraries.props
@@ -7,10 +7,10 @@
-
+
diff --git a/build/Moq.props b/build/Moq.props
index 7de9b6b6ba..9e2fd1db5d 100644
--- a/build/Moq.props
+++ b/build/Moq.props
@@ -1,5 +1,5 @@
-
+
diff --git a/build/Serilog.props b/build/Serilog.props
deleted file mode 100644
index a814cf998d..0000000000
--- a/build/Serilog.props
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/build/SkiaSharp.props b/build/SkiaSharp.props
index 4f69f39e02..4def44cbd0 100644
--- a/build/SkiaSharp.props
+++ b/build/SkiaSharp.props
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/build/readme.md b/build/readme.md
index 387afb3425..e147556b1c 100644
--- a/build/readme.md
+++ b/build/readme.md
@@ -9,8 +9,6 @@
-
-
@@ -22,4 +20,4 @@
```XML
-```
\ No newline at end of file
+```
diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h
index 424f1a6780..1cf3bc75b0 100644
--- a/native/Avalonia.Native/inc/avalonia-native.h
+++ b/native/Avalonia.Native/inc/avalonia-native.h
@@ -22,6 +22,9 @@ struct IAvnGlSurfaceRenderTarget;
struct IAvnGlSurfaceRenderingSession;
struct IAvnMenu;
struct IAvnMenuItem;
+struct IAvnStringArray;
+struct IAvnDndResultCallback;
+struct IAvnGCHandleDeallocatorCallback;
struct IAvnMenuEvents;
struct IAvnNativeControlHost;
struct IAvnNativeControlHostTopLevelAttachment;
@@ -131,11 +134,28 @@ enum AvnInputModifiers
XButton2MouseButton = 256
};
+enum class AvnDragDropEffects
+{
+ None = 0,
+ Copy = 1,
+ Move = 2,
+ Link = 4,
+};
+
+enum class AvnDragEventType
+{
+ Enter,
+ Over,
+ Leave,
+ Drop
+};
+
enum AvnWindowState
{
Normal,
Minimized,
Maximized,
+ FullScreen,
};
enum AvnStandardCursorType
@@ -188,7 +208,7 @@ enum AvnMenuItemToggleType
AVNCOM(IAvaloniaNativeFactory, 01) : IUnknown
{
public:
- virtual HRESULT Initialize() = 0;
+ virtual HRESULT Initialize(IAvnGCHandleDeallocatorCallback* deallocator) = 0;
virtual IAvnMacOptions* GetMacOptions() = 0;
virtual HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnWindow** ppv) = 0;
virtual HRESULT CreatePopup (IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnPopup** ppv) = 0;
@@ -196,6 +216,7 @@ public:
virtual HRESULT CreateSystemDialogs (IAvnSystemDialogs** ppv) = 0;
virtual HRESULT CreateScreens (IAvnScreens** ppv) = 0;
virtual HRESULT CreateClipboard(IAvnClipboard** ppv) = 0;
+ virtual HRESULT CreateDndClipboard(IAvnClipboard** ppv) = 0;
virtual HRESULT CreateCursorFactory(IAvnCursorFactory** ppv) = 0;
virtual HRESULT ObtainGlDisplay(IAvnGlDisplay** ppv) = 0;
virtual HRESULT SetAppMenu(IAvnMenu* menu) = 0;
@@ -237,6 +258,9 @@ AVNCOM(IAvnWindowBase, 02) : IUnknown
virtual HRESULT ObtainNSViewHandle(void** retOut) = 0;
virtual HRESULT ObtainNSViewHandleRetained(void** retOut) = 0;
virtual HRESULT CreateNativeControlHost(IAvnNativeControlHost** retOut) = 0;
+ virtual HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
+ IAvnClipboard* clipboard, IAvnDndResultCallback* cb, void* sourceHandle) = 0;
+ virtual HRESULT SetBlurEnabled (bool enable) = 0;
};
AVNCOM(IAvnPopup, 03) : virtual IAvnWindowBase
@@ -246,9 +270,10 @@ AVNCOM(IAvnPopup, 03) : virtual IAvnWindowBase
AVNCOM(IAvnWindow, 04) : virtual IAvnWindowBase
{
- virtual HRESULT ShowDialog (IAvnWindow* parent) = 0;
+ virtual HRESULT SetEnabled (bool enable) = 0;
+ virtual HRESULT SetParent (IAvnWindow* parent) = 0;
virtual HRESULT SetCanResize(bool value) = 0;
- virtual HRESULT SetHasDecorations(SystemDecorations value) = 0;
+ virtual HRESULT SetDecorations(SystemDecorations value) = 0;
virtual HRESULT SetTitle (void* utf8Title) = 0;
virtual HRESULT SetTitleBarColor (AvnColor color) = 0;
virtual HRESULT SetWindowState(AvnWindowState state) = 0;
@@ -273,6 +298,9 @@ AVNCOM(IAvnWindowBaseEvents, 05) : IUnknown
virtual void ScalingChanged(double scaling) = 0;
virtual void RunRenderPriorityJobs() = 0;
virtual void LostFocus() = 0;
+ virtual AvnDragDropEffects DragEvent(AvnDragEventType type, AvnPoint position,
+ AvnInputModifiers modifiers, AvnDragDropEffects effects,
+ IAvnClipboard* clipboard, void* dataObjectHandle) = 0;
};
@@ -286,6 +314,8 @@ AVNCOM(IAvnWindowEvents, 06) : IAvnWindowBaseEvents
virtual bool Closing () = 0;
virtual void WindowStateChanged (AvnWindowState state) = 0;
+
+ virtual void GotInputWhenDisabled () = 0;
};
AVNCOM(IAvnMacOptions, 07) : IUnknown
@@ -356,8 +386,13 @@ AVNCOM(IAvnScreens, 0e) : IUnknown
AVNCOM(IAvnClipboard, 0f) : IUnknown
{
- virtual HRESULT GetText (IAvnString**ppv) = 0;
- virtual HRESULT SetText (void* utf8Text) = 0;
+ virtual HRESULT GetText (char* type, IAvnString**ppv) = 0;
+ virtual HRESULT SetText (char* type, void* utf8Text) = 0;
+ virtual HRESULT ObtainFormats(IAvnStringArray**ppv) = 0;
+ virtual HRESULT GetStrings(char* type, IAvnStringArray**ppv) = 0;
+ virtual HRESULT SetBytes(char* type, void* utf8Text, int len) = 0;
+ virtual HRESULT GetBytes(char* type, IAvnString**ppv) = 0;
+
virtual HRESULT Clear() = 0;
};
@@ -430,6 +465,22 @@ AVNCOM(IAvnMenuEvents, 1A) : IUnknown
virtual void NeedsUpdate () = 0;
};
+AVNCOM(IAvnStringArray, 20) : IUnknown
+{
+ virtual unsigned int GetCount() = 0;
+ virtual HRESULT Get(unsigned int index, IAvnString**ppv) = 0;
+};
+
+AVNCOM(IAvnDndResultCallback, 21) : IUnknown
+{
+ virtual void OnDragAndDropComplete(AvnDragDropEffects effecct) = 0;
+};
+
+AVNCOM(IAvnGCHandleDeallocatorCallback, 22) : IUnknown
+{
+ virtual void FreeGCHandle(void* handle) = 0;
+};
+
AVNCOM(IAvnNativeControlHost, 20) : IUnknown
{
virtual HRESULT CreateDefaultChild(void* parent, void** retOut) = 0;
diff --git a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
index 28bf88d8fb..d5cad4d1ca 100644
--- a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
+++ b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
@@ -14,6 +14,7 @@
1AFD334123E03C4F0042899B /* controlhost.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AFD334023E03C4F0042899B /* controlhost.mm */; };
1A3E5EAE23E9FB1300EDE661 /* cgl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A3E5EAD23E9FB1300EDE661 /* cgl.mm */; };
1A3E5EB023E9FE8300EDE661 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */; };
+ 1A465D10246AB61600C5858B /* dnd.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A465D0F246AB61600C5858B /* dnd.mm */; };
37155CE4233C00EB0034DCE9 /* menu.h in Headers */ = {isa = PBXBuildFile; fileRef = 37155CE3233C00EB0034DCE9 /* menu.h */; };
37A517B32159597E00FBA241 /* Screens.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37A517B22159597E00FBA241 /* Screens.mm */; };
37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37C09D8721580FE4006A6758 /* SystemDialogs.mm */; };
@@ -37,6 +38,7 @@
1AFD334023E03C4F0042899B /* controlhost.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = controlhost.mm; sourceTree = ""; };
1A3E5EAD23E9FB1300EDE661 /* cgl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cgl.mm; sourceTree = ""; };
1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+ 1A465D0F246AB61600C5858B /* dnd.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = dnd.mm; sourceTree = ""; };
37155CE3233C00EB0034DCE9 /* menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = menu.h; sourceTree = ""; };
379860FE214DA0C000CD0246 /* KeyTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyTransform.h; sourceTree = ""; };
37A4E71A2178846A00EACBCD /* headers */ = {isa = PBXFileReference; lastKnownFileType = folder; name = headers; path = ../../inc; sourceTree = ""; };
@@ -98,6 +100,7 @@
5BF943652167AD1D009CAE35 /* cursor.h */,
5B21A981216530F500CEE36E /* cursor.mm */,
5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */,
+ 1A465D0F246AB61600C5858B /* dnd.mm */,
AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */,
AB661C212148288600291242 /* common.h */,
379860FE214DA0C000CD0246 /* KeyTransform.h */,
@@ -204,6 +207,7 @@
520624B322973F4100C4DCEF /* menu.mm in Sources */,
37A517B32159597E00FBA241 /* Screens.mm in Sources */,
1AFD334123E03C4F0042899B /* controlhost.mm in Sources */,
+ 1A465D10246AB61600C5858B /* dnd.mm in Sources */,
AB00E4F72147CA920032A60A /* main.mm in Sources */,
37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */,
AB661C202148286E00291242 /* window.mm in Sources */,
diff --git a/native/Avalonia.Native/src/OSX/AvnString.h b/native/Avalonia.Native/src/OSX/AvnString.h
index 9a8f5a1318..5d299374e5 100644
--- a/native/Avalonia.Native/src/OSX/AvnString.h
+++ b/native/Avalonia.Native/src/OSX/AvnString.h
@@ -10,5 +10,7 @@
#define AvnString_h
extern IAvnString* CreateAvnString(NSString* string);
-
+extern IAvnStringArray* CreateAvnStringArray(NSArray* array);
+extern IAvnStringArray* CreateAvnStringArray(NSString* string);
+extern IAvnString* CreateByteArray(void* data, int len);
#endif /* AvnString_h */
diff --git a/native/Avalonia.Native/src/OSX/AvnString.mm b/native/Avalonia.Native/src/OSX/AvnString.mm
index b62fe8a968..00b748ef63 100644
--- a/native/Avalonia.Native/src/OSX/AvnString.mm
+++ b/native/Avalonia.Native/src/OSX/AvnString.mm
@@ -7,6 +7,7 @@
//
#include "common.h"
+#include
class AvnStringImpl : public virtual ComSingleObject
{
@@ -28,6 +29,13 @@ public:
memcpy((void*)_cstring, (void*)cstring, _length);
}
+ AvnStringImpl(void*ptr, int len)
+ {
+ _length = len;
+ _cstring = (const char*)malloc(_length);
+ memcpy((void*)_cstring, ptr, len);
+ }
+
virtual ~AvnStringImpl()
{
free((void*)_cstring);
@@ -61,7 +69,60 @@ public:
}
};
+class AvnStringArrayImpl : public virtual ComSingleObject
+{
+private:
+ std::vector> _list;
+public:
+ FORWARD_IUNKNOWN()
+ AvnStringArrayImpl(NSArray* array)
+ {
+ for(int c = 0; c < [array count]; c++)
+ {
+ ComPtr s;
+ *s.getPPV() = new AvnStringImpl([array objectAtIndex:c]);
+ _list.push_back(s);
+ }
+ }
+
+ AvnStringArrayImpl(NSString* string)
+ {
+ ComPtr s;
+ *s.getPPV() = new AvnStringImpl(string);
+ _list.push_back(s);
+ }
+
+ virtual unsigned int GetCount() override
+ {
+ return (unsigned int)_list.size();
+ }
+
+ virtual HRESULT Get(unsigned int index, IAvnString**ppv) override
+ {
+ if(_list.size() <= index)
+ return E_INVALIDARG;
+ *ppv = _list[index].getRetainedReference();
+ return S_OK;
+ }
+};
+
IAvnString* CreateAvnString(NSString* string)
{
return new AvnStringImpl(string);
}
+
+
+IAvnStringArray* CreateAvnStringArray(NSArray * array)
+{
+ return new AvnStringArrayImpl(array);
+}
+
+IAvnStringArray* CreateAvnStringArray(NSString* string)
+{
+ return new AvnStringArrayImpl(string);
+}
+
+IAvnString* CreateByteArray(void* data, int len)
+{
+ return new AvnStringImpl(data, len);
+}
diff --git a/native/Avalonia.Native/src/OSX/app.mm b/native/Avalonia.Native/src/OSX/app.mm
index 81cac530fd..814b91cb62 100644
--- a/native/Avalonia.Native/src/OSX/app.mm
+++ b/native/Avalonia.Native/src/OSX/app.mm
@@ -15,6 +15,10 @@ NSApplicationActivationPolicy AvnDesiredActivationPolicy = NSApplicationActivati
}
[[NSApplication sharedApplication] setActivationPolicy: AvnDesiredActivationPolicy];
+
+ [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSFullScreenMenuItemEverywhere"];
+
+ [[NSApplication sharedApplication] setHelpMenu: [[NSMenu new] initWithTitle:@""]];
}
}
diff --git a/native/Avalonia.Native/src/OSX/clipboard.mm b/native/Avalonia.Native/src/OSX/clipboard.mm
index c2cf1f1f61..116a08670e 100644
--- a/native/Avalonia.Native/src/OSX/clipboard.mm
+++ b/native/Avalonia.Native/src/OSX/clipboard.mm
@@ -3,16 +3,27 @@
class Clipboard : public ComSingleObject
{
+private:
+ NSPasteboard* _pb;
+ NSPasteboardItem* _item;
public:
FORWARD_IUNKNOWN()
- Clipboard()
+ Clipboard(NSPasteboard* pasteboard, NSPasteboardItem* item)
{
- NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
- [pasteBoard stringForType:NSPasteboardTypeString];
+ if(pasteboard == nil && item == nil)
+ pasteboard = [NSPasteboard generalPasteboard];
+
+ _pb = pasteboard;
+ _item = item;
}
- virtual HRESULT GetText (IAvnString**ppv) override
+ NSPasteboardItem* TryGetItem()
+ {
+ return _item;
+ }
+
+ virtual HRESULT GetText (char* type, IAvnString**ppv) override
{
@autoreleasepool
{
@@ -20,39 +31,124 @@ public:
{
return E_POINTER;
}
+ NSString* typeString = [NSString stringWithUTF8String:(const char*)type];
+ NSString* string = _item == nil ? [_pb stringForType:typeString] : [_item stringForType:typeString];
- *ppv = CreateAvnString([[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString]);
+ *ppv = CreateAvnString(string);
return S_OK;
}
}
- virtual HRESULT SetText (void* utf8String) override
+ virtual HRESULT GetStrings(char* type, IAvnStringArray**ppv) override
{
@autoreleasepool
{
- NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
- [pasteBoard clearContents];
- [pasteBoard setString:[NSString stringWithUTF8String:(const char*)utf8String] forType:NSPasteboardTypeString];
+ *ppv= nil;
+ NSString* typeString = [NSString stringWithUTF8String:(const char*)type];
+ NSObject* data = _item == nil ? [_pb propertyListForType: typeString] : [_item propertyListForType: typeString];
+ if(data == nil)
+ return S_OK;
+
+ if([data isKindOfClass: [NSString class]])
+ {
+ *ppv = CreateAvnStringArray((NSString*) data);
+ return S_OK;
+ }
+
+ NSArray* arr = (NSArray*)data;
+
+ for(int c = 0; c < [arr count]; c++)
+ if(![[arr objectAtIndex:c] isKindOfClass:[NSString class]])
+ return E_INVALIDARG;
+
+ *ppv = CreateAvnStringArray(arr);
+ return S_OK;
+ }
+ }
+
+ virtual HRESULT SetText (char* type, void* utf8String) override
+ {
+ Clear();
+ @autoreleasepool
+ {
+ auto string = [NSString stringWithUTF8String:(const char*)utf8String];
+ auto typeString = [NSString stringWithUTF8String:(const char*)type];
+ if(_item == nil)
+ [_pb setString: string forType: typeString];
+ else
+ [_item setString: string forType:typeString];
}
return S_OK;
}
+
+ virtual HRESULT SetBytes(char* type, void* bytes, int len) override
+ {
+ auto typeString = [NSString stringWithUTF8String:(const char*)type];
+ auto data = [NSData dataWithBytes:bytes length:len];
+ if(_item == nil)
+ [_pb setData:data forType:typeString];
+ else
+ [_item setData:data forType:typeString];
+ return S_OK;
+ }
+
+ virtual HRESULT GetBytes(char* type, IAvnString**ppv) override
+ {
+ *ppv = nil;
+ auto typeString = [NSString stringWithUTF8String:(const char*)type];
+ NSData*data;
+ @try
+ {
+ if(_item)
+ data = [_item dataForType:typeString];
+ else
+ data = [_pb dataForType:typeString];
+ if(data == nil)
+ return E_FAIL;
+ }
+ @catch(NSException* e)
+ {
+ return E_FAIL;
+ }
+ *ppv = CreateByteArray((void*)data.bytes, (int)data.length);
+ return S_OK;
+ }
+
virtual HRESULT Clear() override
{
@autoreleasepool
{
- NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
- [pasteBoard clearContents];
- [pasteBoard setString:@"" forType:NSPasteboardTypeString];
+ if(_item != nil)
+ _item = [NSPasteboardItem new];
+ else
+ {
+ [_pb clearContents];
+ [_pb setString:@"" forType:NSPasteboardTypeString];
+ }
}
return S_OK;
}
+
+ virtual HRESULT ObtainFormats(IAvnStringArray** ppv) override
+ {
+ *ppv = CreateAvnStringArray(_item == nil ? [_pb types] : [_item types]);
+ return S_OK;
+ }
};
-extern IAvnClipboard* CreateClipboard()
+extern IAvnClipboard* CreateClipboard(NSPasteboard* pb, NSPasteboardItem* item)
+{
+ return new Clipboard(pb, item);
+}
+
+extern NSPasteboardItem* TryGetPasteboardItem(IAvnClipboard*cb)
{
- return new Clipboard();
+ auto clipboard = dynamic_cast(cb);
+ if(clipboard == nil)
+ return nil;
+ return clipboard->TryGetItem();
}
diff --git a/native/Avalonia.Native/src/OSX/common.h b/native/Avalonia.Native/src/OSX/common.h
index 417d5a041a..871bca086d 100644
--- a/native/Avalonia.Native/src/OSX/common.h
+++ b/native/Avalonia.Native/src/OSX/common.h
@@ -8,11 +8,17 @@
#include
extern IAvnPlatformThreadingInterface* CreatePlatformThreading();
+extern void FreeAvnGCHandle(void* handle);
extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events, IAvnGlContext* gl);
extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events, IAvnGlContext* gl);
extern IAvnSystemDialogs* CreateSystemDialogs();
extern IAvnScreens* CreateScreens();
-extern IAvnClipboard* CreateClipboard();
+extern IAvnClipboard* CreateClipboard(NSPasteboard*, NSPasteboardItem*);
+extern NSPasteboardItem* TryGetPasteboardItem(IAvnClipboard*);
+extern NSObject* CreateDraggingSource(NSDragOperation op, IAvnDndResultCallback* cb, void* handle);
+extern void* GetAvnDataObjectHandleFromDraggingInfo(NSObject* info);
+extern NSString* GetAvnCustomDataType();
+extern AvnDragDropEffects ConvertDragDropEffects(NSDragOperation nsop);
extern IAvnCursorFactory* CreateCursorFactory();
extern IAvnGlDisplay* GetGlDisplay();
extern IAvnMenu* CreateAppMenu(IAvnMenuEvents* events);
diff --git a/native/Avalonia.Native/src/OSX/dnd.mm b/native/Avalonia.Native/src/OSX/dnd.mm
new file mode 100644
index 0000000000..294b8ee8ea
--- /dev/null
+++ b/native/Avalonia.Native/src/OSX/dnd.mm
@@ -0,0 +1,89 @@
+#include "common.h"
+
+extern AvnDragDropEffects ConvertDragDropEffects(NSDragOperation nsop)
+{
+ int effects = 0;
+ if((nsop & NSDragOperationCopy) != 0)
+ effects |= (int)AvnDragDropEffects::Copy;
+ if((nsop & NSDragOperationMove) != 0)
+ effects |= (int)AvnDragDropEffects::Move;
+ if((nsop & NSDragOperationLink) != 0)
+ effects |= (int)AvnDragDropEffects::Link;
+ return (AvnDragDropEffects)effects;
+};
+
+extern NSString* GetAvnCustomDataType()
+{
+ char buffer[256];
+ sprintf(buffer, "net.avaloniaui.inproc.uti.n%in", getpid());
+ return [NSString stringWithUTF8String:buffer];
+}
+
+@interface AvnDndSource : NSObject
+
+@end
+
+@implementation AvnDndSource
+{
+ NSDragOperation _operation;
+ ComPtr _cb;
+ void* _sourceHandle;
+};
+
+- (NSDragOperation)draggingSession:(nonnull NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context
+{
+ return NSDragOperationCopy;
+}
+
+- (AvnDndSource*) initWithOperation: (NSDragOperation)operation
+ andCallback: (IAvnDndResultCallback*) cb
+ andSourceHandle: (void*) handle
+{
+ self = [super init];
+ _operation = operation;
+ _cb = cb;
+ _sourceHandle = handle;
+ return self;
+}
+
+- (void)draggingSession:(NSDraggingSession *)session
+ endedAtPoint:(NSPoint)screenPoint
+ operation:(NSDragOperation)operation
+{
+ if(_cb != nil)
+ {
+ auto cb = _cb;
+ _cb = nil;
+ cb->OnDragAndDropComplete(ConvertDragDropEffects(operation));
+ }
+ if(_sourceHandle != nil)
+ {
+ FreeAvnGCHandle(_sourceHandle);
+ _sourceHandle = nil;
+ }
+}
+
+- (void*) gcHandle
+{
+ return _sourceHandle;
+}
+
+@end
+
+extern NSObject* CreateDraggingSource(NSDragOperation op, IAvnDndResultCallback* cb, void* handle)
+{
+ return [[AvnDndSource alloc] initWithOperation:op andCallback:cb andSourceHandle:handle];
+};
+
+extern void* GetAvnDataObjectHandleFromDraggingInfo(NSObject* info)
+{
+ id obj = [info draggingSource];
+ if(obj == nil)
+ return nil;
+ if([obj isKindOfClass: [AvnDndSource class]])
+ {
+ auto src = (AvnDndSource*)obj;
+ return [src gcHandle];
+ }
+ return nil;
+}
diff --git a/native/Avalonia.Native/src/OSX/main.mm b/native/Avalonia.Native/src/OSX/main.mm
index a63353bc0a..e6c4a861fd 100644
--- a/native/Avalonia.Native/src/OSX/main.mm
+++ b/native/Avalonia.Native/src/OSX/main.mm
@@ -150,14 +150,15 @@ public:
}
@end
-
+static ComPtr _deallocator;
class AvaloniaNative : public ComSingleObject
{
public:
FORWARD_IUNKNOWN()
- virtual HRESULT Initialize() override
+ virtual HRESULT Initialize(IAvnGCHandleDeallocatorCallback* deallocator) override
{
+ _deallocator = deallocator;
@autoreleasepool{
[[ThreadingInitializer new] do];
}
@@ -207,7 +208,13 @@ public:
virtual HRESULT CreateClipboard(IAvnClipboard** ppv) override
{
- *ppv = ::CreateClipboard ();
+ *ppv = ::CreateClipboard (nil, nil);
+ return S_OK;
+ }
+
+ virtual HRESULT CreateDndClipboard(IAvnClipboard** ppv) override
+ {
+ *ppv = ::CreateClipboard (nil, [NSPasteboardItem new]);
return S_OK;
}
@@ -257,6 +264,12 @@ extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative()
return new AvaloniaNative();
};
+extern void FreeAvnGCHandle(void* handle)
+{
+ if(_deallocator != nil)
+ _deallocator->FreeGCHandle(handle);
+}
+
NSSize ToNSSize (AvnSize s)
{
NSSize result;
diff --git a/native/Avalonia.Native/src/OSX/window.h b/native/Avalonia.Native/src/OSX/window.h
index 505900d584..bdf3007a28 100644
--- a/native/Avalonia.Native/src/OSX/window.h
+++ b/native/Avalonia.Native/src/OSX/window.h
@@ -3,7 +3,10 @@
class WindowBaseImpl;
-@interface AvnView : NSView
+@interface AutoFitContentVisualEffectView : NSVisualEffectView
+@end
+
+@interface AvnView : NSView
-(AvnView* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent;
-(NSEvent* _Nonnull) lastMouseDownEvent;
-(AvnPoint) translateLocalPoint:(AvnPoint)pt;
@@ -19,6 +22,7 @@ class WindowBaseImpl;
-(void) pollModalSession: (NSModalSession _Nonnull) session;
-(void) restoreParentWindow;
-(bool) shouldTryToHandleEvents;
+-(void) setEnabled: (bool) enable;
-(void) showAppMenuOnly;
-(void) showWindowMenuWithAppMenu;
-(void) applyMenu:(NSMenu* _Nullable)menu;
@@ -33,6 +37,10 @@ struct INSWindowHolder
struct IWindowStateChanged
{
virtual void WindowStateChanged () = 0;
+ virtual void StartStateTransition () = 0;
+ virtual void EndStateTransition () = 0;
+ virtual SystemDecorations Decorations () = 0;
+ virtual AvnWindowState WindowState () = 0;
};
#endif /* window_h */
diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm
index bd0eb79659..86b3584681 100644
--- a/native/Avalonia.Native/src/OSX/window.mm
+++ b/native/Avalonia.Native/src/OSX/window.mm
@@ -20,6 +20,7 @@ public:
View = NULL;
Window = NULL;
}
+ NSVisualEffectView* VisualEffect;
AvnView* View;
AvnWindow* Window;
ComPtr BaseEvents;
@@ -47,6 +48,12 @@ public:
[Window setStyleMask:NSWindowStyleMaskBorderless];
[Window setBackingType:NSBackingStoreBuffered];
+
+ VisualEffect = [AutoFitContentVisualEffectView new];
+ [VisualEffect setBlendingMode:NSVisualEffectBlendingModeBehindWindow];
+ [VisualEffect setMaterial:NSVisualEffectMaterialLight];
+ [VisualEffect setAutoresizesSubviews:true];
+
[Window setContentView: View];
}
@@ -390,6 +397,62 @@ public:
*retOut = ::CreateNativeControlHost(View);
return S_OK;
}
+
+ virtual HRESULT SetBlurEnabled (bool enable) override
+ {
+ [Window setContentView: enable ? VisualEffect : View];
+
+ if(enable)
+ {
+ [VisualEffect addSubview:View];
+ }
+
+ return S_OK;
+ }
+
+ virtual HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
+ IAvnClipboard* clipboard, IAvnDndResultCallback* cb,
+ void* sourceHandle) override
+ {
+ auto item = TryGetPasteboardItem(clipboard);
+ [item setString:@"" forType:GetAvnCustomDataType()];
+ if(item == nil)
+ return E_INVALIDARG;
+ if(View == NULL)
+ return E_FAIL;
+
+ auto nsevent = [NSApp currentEvent];
+ auto nseventType = [nsevent type];
+
+ // If current event isn't a mouse one (probably due to malfunctioning user app)
+ // attempt to forge a new one
+ if(!((nseventType >= NSEventTypeLeftMouseDown && nseventType <= NSEventTypeMouseExited)
+ || (nseventType >= NSEventTypeOtherMouseDown && nseventType <= NSEventTypeOtherMouseDragged)))
+ {
+ auto nspoint = [Window convertBaseToScreen: ToNSPoint(point)];
+ CGPoint cgpoint = NSPointToCGPoint(nspoint);
+ auto cgevent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, cgpoint, kCGMouseButtonLeft);
+ nsevent = [NSEvent eventWithCGEvent: cgevent];
+ CFRelease(cgevent);
+ }
+
+ auto dragItem = [[NSDraggingItem alloc] initWithPasteboardWriter: item];
+
+ auto dragItemImage = [NSImage imageNamed:NSImageNameMultipleDocuments];
+ NSRect dragItemRect = {(float)point.X, (float)point.Y, [dragItemImage size].width, [dragItemImage size].height};
+ [dragItem setDraggingFrame: dragItemRect contents: dragItemImage];
+
+ int op = 0; int ieffects = (int)effects;
+ if((ieffects & (int)AvnDragDropEffects::Copy) != 0)
+ op |= NSDragOperationCopy;
+ if((ieffects & (int)AvnDragDropEffects::Link) != 0)
+ op |= NSDragOperationLink;
+ if((ieffects & (int)AvnDragDropEffects::Move) != 0)
+ op |= NSDragOperationMove;
+ [View beginDraggingSessionWithItems: @[dragItem] event: nsevent
+ source: CreateDraggingSource((NSDragOperation) op, cb, sourceHandle)];
+ return S_OK;
+ }
protected:
virtual NSWindowStyleMask GetStyle()
@@ -399,7 +462,7 @@ protected:
void UpdateStyle()
{
- [Window setStyleMask:GetStyle()];
+ [Window setStyleMask: GetStyle()];
}
public:
@@ -412,10 +475,13 @@ public:
class WindowImpl : public virtual WindowBaseImpl, public virtual IAvnWindow, public IWindowStateChanged
{
private:
- bool _canResize = true;
- SystemDecorations _hasDecorations = SystemDecorationsFull;
- CGRect _lastUndecoratedFrame;
+ bool _canResize;
+ bool _fullScreenActive;
+ SystemDecorations _decorations;
AvnWindowState _lastWindowState;
+ bool _inSetWindowState;
+ NSRect _preZoomSize;
+ bool _transitioningWindowState;
FORWARD_IUNKNOWN()
BEGIN_INTERFACE_MAP()
@@ -429,25 +495,54 @@ private:
ComPtr WindowEvents;
WindowImpl(IAvnWindowEvents* events, IAvnGlContext* gl) : WindowBaseImpl(events, gl)
{
+ _fullScreenActive = false;
+ _canResize = true;
+ _decorations = SystemDecorationsFull;
+ _transitioningWindowState = false;
+ _inSetWindowState = false;
_lastWindowState = Normal;
WindowEvents = events;
[Window setCanBecomeKeyAndMain];
[Window disableCursorRects];
+ [Window setTabbingMode:NSWindowTabbingModeDisallowed];
+ }
+
+ void HideOrShowTrafficLights ()
+ {
+ for (id subview in Window.contentView.superview.subviews) {
+ if ([subview isKindOfClass:NSClassFromString(@"NSTitlebarContainerView")]) {
+ NSView *titlebarView = [subview subviews][0];
+ for (id button in titlebarView.subviews) {
+ if ([button isKindOfClass:[NSButton class]]) {
+ [button setHidden: (_decorations != SystemDecorationsFull)];
+ }
+ }
+ }
+ }
}
virtual HRESULT Show () override
{
@autoreleasepool
- {
- if([Window parentWindow] != nil)
- [[Window parentWindow] removeChildWindow:Window];
+ {
WindowBaseImpl::Show();
+ HideOrShowTrafficLights();
+
return SetWindowState(_lastWindowState);
}
}
- virtual HRESULT ShowDialog (IAvnWindow* parent) override
+ virtual HRESULT SetEnabled (bool enable) override
+ {
+ @autoreleasepool
+ {
+ [Window setEnabled:enable];
+ return S_OK;
+ }
+ }
+
+ virtual HRESULT SetParent (IAvnWindow* parent) override
{
@autoreleasepool
{
@@ -459,43 +554,70 @@ private:
return E_INVALIDARG;
[cparent->Window addChildWindow:Window ordered:NSWindowAbove];
- WindowBaseImpl::Show();
+
+ UpdateStyle();
return S_OK;
}
}
+ void StartStateTransition () override
+ {
+ _transitioningWindowState = true;
+ }
+
+ void EndStateTransition () override
+ {
+ _transitioningWindowState = false;
+ }
+
+ SystemDecorations Decorations () override
+ {
+ return _decorations;
+ }
+
+ AvnWindowState WindowState () override
+ {
+ return _lastWindowState;
+ }
+
void WindowStateChanged () override
{
- AvnWindowState state;
- GetWindowState(&state);
- WindowEvents->WindowStateChanged(state);
+ if(!_inSetWindowState && !_transitioningWindowState)
+ {
+ AvnWindowState state;
+ GetWindowState(&state);
+
+ if(_lastWindowState != state)
+ {
+ _lastWindowState = state;
+ WindowEvents->WindowStateChanged(state);
+ }
+ }
}
bool UndecoratedIsMaximized ()
{
- return CGRectEqualToRect([Window frame], [Window screen].visibleFrame);
+ auto windowSize = [Window frame];
+ auto available = [Window screen].visibleFrame;
+ return CGRectEqualToRect(windowSize, available);
}
bool IsZoomed ()
{
- return _hasDecorations != SystemDecorationsNone ? [Window isZoomed] : UndecoratedIsMaximized();
+ return _decorations == SystemDecorationsFull ? [Window isZoomed] : UndecoratedIsMaximized();
}
void DoZoom()
{
- switch (_hasDecorations)
+ switch (_decorations)
{
case SystemDecorationsNone:
- if (!UndecoratedIsMaximized())
- {
- _lastUndecoratedFrame = [Window frame];
- }
-
- [Window zoom:Window];
+ case SystemDecorationsBorderOnly:
+ [Window setFrame:[Window screen].visibleFrame display:true];
break;
- case SystemDecorationsBorderOnly:
+
case SystemDecorationsFull:
[Window performZoom:Window];
break;
@@ -512,25 +634,52 @@ private:
}
}
- virtual HRESULT SetHasDecorations(SystemDecorations value) override
+ virtual HRESULT SetDecorations(SystemDecorations value) override
{
@autoreleasepool
{
- _hasDecorations = value;
+ auto currentWindowState = _lastWindowState;
+ _decorations = value;
+
+ if(_fullScreenActive)
+ {
+ return S_OK;
+ }
+
+ auto currentFrame = [Window frame];
+
UpdateStyle();
+
+ HideOrShowTrafficLights();
- switch (_hasDecorations)
+ switch (_decorations)
{
case SystemDecorationsNone:
[Window setHasShadow:NO];
[Window setTitleVisibility:NSWindowTitleHidden];
[Window setTitlebarAppearsTransparent:YES];
+
+ if(currentWindowState == Maximized)
+ {
+ if(!UndecoratedIsMaximized())
+ {
+ DoZoom();
+ }
+ }
break;
case SystemDecorationsBorderOnly:
[Window setHasShadow:YES];
[Window setTitleVisibility:NSWindowTitleHidden];
[Window setTitlebarAppearsTransparent:YES];
+
+ if(currentWindowState == Maximized)
+ {
+ if(!UndecoratedIsMaximized())
+ {
+ DoZoom();
+ }
+ }
break;
case SystemDecorationsFull:
@@ -538,6 +687,13 @@ private:
[Window setTitleVisibility:NSWindowTitleVisible];
[Window setTitlebarAppearsTransparent:NO];
[Window setTitle:_lastTitle];
+
+ if(currentWindowState == Maximized)
+ {
+ auto newFrame = [Window contentRectForFrameRect:[Window frame]].size;
+
+ [View setFrameSize:newFrame];
+ }
break;
}
@@ -594,13 +750,19 @@ private:
return E_POINTER;
}
+ if(([Window styleMask] & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen)
+ {
+ *ret = FullScreen;
+ return S_OK;
+ }
+
if([Window isMiniaturized])
{
*ret = Minimized;
return S_OK;
}
- if([Window isZoomed])
+ if(IsZoomed())
{
*ret = Maximized;
return S_OK;
@@ -612,16 +774,57 @@ private:
}
}
+ void EnterFullScreenMode ()
+ {
+ _fullScreenActive = true;
+
+ [Window setHasShadow:YES];
+ [Window setTitleVisibility:NSWindowTitleVisible];
+ [Window setTitlebarAppearsTransparent:NO];
+ [Window setTitle:_lastTitle];
+
+ [Window setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskResizable];
+
+ [Window toggleFullScreen:nullptr];
+ }
+
+ void ExitFullScreenMode ()
+ {
+ [Window toggleFullScreen:nullptr];
+
+ _fullScreenActive = false;
+
+ SetDecorations(_decorations);
+ }
+
virtual HRESULT SetWindowState (AvnWindowState state) override
{
@autoreleasepool
{
+ if(_lastWindowState == state)
+ {
+ return S_OK;
+ }
+
+ _inSetWindowState = true;
+
+ auto currentState = _lastWindowState;
_lastWindowState = state;
+ if(currentState == Normal)
+ {
+ _preZoomSize = [Window frame];
+ }
+
if(_shown)
{
switch (state) {
case Maximized:
+ if(currentState == FullScreen)
+ {
+ ExitFullScreenMode();
+ }
+
lastPositionSet.X = 0;
lastPositionSet.Y = 0;
@@ -637,40 +840,66 @@ private:
break;
case Minimized:
- [Window miniaturize:Window];
+ if(currentState == FullScreen)
+ {
+ ExitFullScreenMode();
+ }
+ else
+ {
+ [Window miniaturize:Window];
+ }
+ break;
+
+ case FullScreen:
+ if([Window isMiniaturized])
+ {
+ [Window deminiaturize:Window];
+ }
+
+ EnterFullScreenMode();
break;
- default:
+ case Normal:
if([Window isMiniaturized])
{
[Window deminiaturize:Window];
}
+ if(currentState == FullScreen)
+ {
+ ExitFullScreenMode();
+ }
+
if(IsZoomed())
{
- DoZoom();
+ if(_decorations == SystemDecorationsFull)
+ {
+ DoZoom();
+ }
+ else
+ {
+ [Window setFrame:_preZoomSize display:true];
+ auto newFrame = [Window contentRectForFrameRect:[Window frame]].size;
+
+ [View setFrameSize:newFrame];
+ }
+
}
break;
}
}
+ _inSetWindowState = false;
+
return S_OK;
}
}
virtual void OnResized () override
{
- if(_shown)
+ if(_shown && !_inSetWindowState && !_transitioningWindowState)
{
- auto windowState = [Window isMiniaturized] ? Minimized
- : (IsZoomed() ? Maximized : Normal);
-
- if (windowState != _lastWindowState)
- {
- _lastWindowState = windowState;
-
- WindowEvents->WindowStateChanged(windowState);
- }
+ WindowStateChanged();
}
}
@@ -679,9 +908,10 @@ protected:
{
unsigned long s = NSWindowStyleMaskBorderless;
- switch (_hasDecorations)
+ switch (_decorations)
{
case SystemDecorationsNone:
+ s = s | NSWindowStyleMaskFullSizeContentView;
break;
case SystemDecorationsBorderOnly:
@@ -689,21 +919,35 @@ protected:
break;
case SystemDecorationsFull:
- s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskBorderless;
+ s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskBorderless;
+
if(_canResize)
{
s = s | NSWindowStyleMaskResizable;
}
-
break;
}
+ if([Window parentWindow] == nullptr)
+ {
+ s |= NSWindowStyleMaskMiniaturizable;
+ }
return s;
}
};
NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEventTrackingRunLoopMode, NSModalPanelRunLoopMode, NSRunLoopCommonModes, NSConnectionReplyMode, nil];
+@implementation AutoFitContentVisualEffectView
+-(void)setFrameSize:(NSSize)newSize
+{
+ [super setFrameSize:newSize];
+ if([[self subviews] count] == 0)
+ return;
+ [[self subviews][0] setFrameSize: newSize];
+}
+@end
+
@implementation AvnView
{
ComPtr _parent;
@@ -753,7 +997,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
_area = nullptr;
_lastPixelSize.Height = 100;
_lastPixelSize.Width = 100;
-
+ [self registerForDraggedTypes: @[@"public.data", GetAvnCustomDataType()]];
return self;
}
@@ -871,7 +1115,11 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
_lastPixelSize.Width = (int)fsize.width;
_lastPixelSize.Height = (int)fsize.height;
[self updateRenderTarget];
- _parent->BaseEvents->ScalingChanged([_parent->Window backingScaleFactor]);
+
+ if(_parent != nullptr)
+ {
+ _parent->BaseEvents->ScalingChanged([_parent->Window backingScaleFactor]);
+ }
[super viewDidChangeBackingProperties];
}
@@ -879,15 +1127,28 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
- (bool) ignoreUserInput
{
auto parentWindow = objc_cast([self window]);
+
if(parentWindow == nil || ![parentWindow shouldTryToHandleEvents])
+ {
+ auto window = dynamic_cast(_parent.getRaw());
+
+ if(window != nullptr)
+ {
+ window->WindowEvents->GotInputWhenDisabled();
+ }
+
return TRUE;
+ }
+
return FALSE;
}
- (void)mouseEvent:(NSEvent *)event withType:(AvnRawMouseEventType) type
{
if([self ignoreUserInput])
+ {
return;
+ }
auto localPoint = [self convertPoint:[event locationInWindow] toView:self];
auto avnPoint = [self toAvnPoint:localPoint];
@@ -926,7 +1187,11 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
)
[self becomeFirstResponder];
- _parent->BaseEvents->RawMouseEvent(type, timestamp, modifiers, point, delta);
+ if(_parent != nullptr)
+ {
+ _parent->BaseEvents->RawMouseEvent(type, timestamp, modifiers, point, delta);
+ }
+
[super mouseMoved:event];
}
@@ -1047,13 +1312,19 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
- (void) keyboardEvent: (NSEvent *) event withType: (AvnRawKeyEventType)type
{
if([self ignoreUserInput])
+ {
return;
+ }
+
auto key = s_KeyMap[[event keyCode]];
auto timestamp = [event timestamp] * 1000;
auto modifiers = [self getModifiers:[event modifierFlags]];
- _lastKeyHandled = _parent->BaseEvents->RawKeyEvent(type, timestamp, modifiers, key);
+ if(_parent != nullptr)
+ {
+ _lastKeyHandled = _parent->BaseEvents->RawKeyEvent(type, timestamp, modifiers, key);
+ }
}
- (BOOL)performKeyEquivalent:(NSEvent *)event
@@ -1144,7 +1415,10 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
{
if(!_lastKeyHandled)
{
- _lastKeyHandled = _parent->BaseEvents->RawTextInputEvent(0, [string UTF8String]);
+ if(_parent != nullptr)
+ {
+ _lastKeyHandled = _parent->BaseEvents->RawTextInputEvent(0, [string UTF8String]);
+ }
}
}
@@ -1159,6 +1433,68 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
return result;
}
+
+- (NSDragOperation)triggerAvnDragEvent: (AvnDragEventType) type info: (id )info
+{
+ auto localPoint = [self convertPoint:[info draggingLocation] toView:self];
+ auto avnPoint = [self toAvnPoint:localPoint];
+ auto point = [self translateLocalPoint:avnPoint];
+ auto modifiers = [self getModifiers:[[NSApp currentEvent] modifierFlags]];
+ NSDragOperation nsop = [info draggingSourceOperationMask];
+
+ auto effects = ConvertDragDropEffects(nsop);
+ int reffects = (int)_parent->BaseEvents
+ ->DragEvent(type, point, modifiers, effects,
+ CreateClipboard([info draggingPasteboard], nil),
+ GetAvnDataObjectHandleFromDraggingInfo(info));
+
+ NSDragOperation ret = 0;
+
+ // Ensure that the managed part didn't add any new effects
+ reffects = (int)effects & (int)reffects;
+
+ // OSX requires exactly one operation
+ if((reffects & (int)AvnDragDropEffects::Copy) != 0)
+ ret = NSDragOperationCopy;
+ else if((reffects & (int)AvnDragDropEffects::Move) != 0)
+ ret = NSDragOperationMove;
+ else if((reffects & (int)AvnDragDropEffects::Link) != 0)
+ ret = NSDragOperationLink;
+ if(ret == 0)
+ ret = NSDragOperationNone;
+ return ret;
+}
+
+- (NSDragOperation)draggingEntered:(id )sender
+{
+ return [self triggerAvnDragEvent: AvnDragEventType::Enter info:sender];
+}
+
+- (NSDragOperation)draggingUpdated:(id )sender
+{
+ return [self triggerAvnDragEvent: AvnDragEventType::Over info:sender];
+}
+
+- (void)draggingExited:(id )sender
+{
+ [self triggerAvnDragEvent: AvnDragEventType::Leave info:sender];
+}
+
+- (BOOL)prepareForDragOperation:(id )sender
+{
+ return [self triggerAvnDragEvent: AvnDragEventType::Over info:sender] != NSDragOperationNone;
+}
+
+- (BOOL)performDragOperation:(id )sender
+{
+ return [self triggerAvnDragEvent: AvnDragEventType::Drop info:sender] != NSDragOperationNone;
+}
+
+- (void)concludeDragOperation:(nullable id )sender
+{
+
+}
+
@end
@@ -1167,6 +1503,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
ComPtr _parent;
bool _canBecomeKeyAndMain;
bool _closed;
+ bool _isEnabled;
AvnMenu* _menu;
double _lastScaling;
}
@@ -1187,6 +1524,20 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
}
}
+- (void)performClose:(id)sender
+{
+ if([[self delegate] respondsToSelector:@selector(windowShouldClose:)])
+ {
+ if(![[self delegate] windowShouldClose:self]) return;
+ }
+ else if([self respondsToSelector:@selector(windowShouldClose:)])
+ {
+ if(![self windowShouldClose:self]) return;
+ }
+
+ [self close];
+}
+
- (void)pollModalSession:(nonnull NSModalSession)session
{
auto response = [NSApp runModalSession:session];
@@ -1274,6 +1625,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
_parent = parent;
[self setDelegate:self];
_closed = false;
+ _isEnabled = true;
_lastScaling = [self backingScaleFactor];
[self setOpaque:NO];
@@ -1340,14 +1692,12 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
-(bool)shouldTryToHandleEvents
{
- for(NSWindow* uch in [self childWindows])
- {
- auto ch = objc_cast(uch);
- if(ch == nil)
- continue;
- return FALSE;
- }
- return TRUE;
+ return _isEnabled;
+}
+
+-(void) setEnabled:(bool)enable
+{
+ _isEnabled = enable;
}
-(void)makeKeyWindow
@@ -1364,7 +1714,11 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
{
[self showWindowMenuWithAppMenu];
- _parent->BaseEvents->Activated();
+ if(_parent != nullptr)
+ {
+ _parent->BaseEvents->Activated();
+ }
+
[super becomeKeyWindow];
}
}
@@ -1401,7 +1755,66 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
- (void)windowDidResize:(NSNotification *)notification
{
- _parent->OnResized();
+ auto parent = dynamic_cast(_parent.operator->());
+
+ if(parent != nullptr)
+ {
+ parent->WindowStateChanged();
+ }
+}
+
+- (void)windowWillExitFullScreen:(NSNotification *)notification
+{
+ auto parent = dynamic_cast(_parent.operator->());
+
+ if(parent != nullptr)
+ {
+ parent->StartStateTransition();
+ }
+}
+
+- (void)windowDidExitFullScreen:(NSNotification *)notification
+{
+ auto parent = dynamic_cast(_parent.operator->());
+
+ if(parent != nullptr)
+ {
+ parent->EndStateTransition();
+
+ if(parent->Decorations() != SystemDecorationsFull && parent->WindowState() == Maximized)
+ {
+ NSRect screenRect = [[self screen] visibleFrame];
+ [self setFrame:screenRect display:YES];
+ }
+
+ if(parent->WindowState() == Minimized)
+ {
+ [self miniaturize:nullptr];
+ }
+
+ parent->WindowStateChanged();
+ }
+}
+
+- (void)windowWillEnterFullScreen:(NSNotification *)notification
+{
+ auto parent = dynamic_cast(_parent.operator->());
+
+ if(parent != nullptr)
+ {
+ parent->StartStateTransition();
+ }
+}
+
+- (void)windowDidEnterFullScreen:(NSNotification *)notification
+{
+ auto parent = dynamic_cast(_parent.operator->());
+
+ if(parent != nullptr)
+ {
+ parent->EndStateTransition();
+ parent->WindowStateChanged();
+ }
}
- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame
@@ -1422,8 +1835,12 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
- (void)windowDidMove:(NSNotification *)notification
{
AvnPoint position;
- _parent->GetPosition(&position);
- _parent->BaseEvents->PositionChanged(position);
+
+ if(_parent != nullptr)
+ {
+ _parent->GetPosition(&position);
+ _parent->BaseEvents->PositionChanged(position);
+ }
}
@end
diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs
index 90d9c737e6..890967ae4f 100644
--- a/nukebuild/Build.cs
+++ b/nukebuild/Build.cs
@@ -12,6 +12,7 @@ using Nuke.Common.ProjectModel;
using Nuke.Common.Tooling;
using Nuke.Common.Tools.DotNet;
using Nuke.Common.Tools.MSBuild;
+using Nuke.Common.Tools.Npm;
using Nuke.Common.Utilities;
using Nuke.Common.Utilities.Collections;
using static Nuke.Common.EnvironmentInfo;
@@ -121,8 +122,21 @@ partial class Build : NukeBuild
EnsureCleanDirectory(Parameters.TestResultsRoot);
});
+ Target CompileHtmlPreviewer => _ => _
+ .DependsOn(Clean)
+ .Executes(() =>
+ {
+ var webappDir = RootDirectory / "src" / "Avalonia.DesignerSupport" / "Remote" / "HtmlTransport" / "webapp";
+
+ NpmTasks.NpmInstall(c => c.SetWorkingDirectory(webappDir));
+ NpmTasks.NpmRun(c => c
+ .SetWorkingDirectory(webappDir)
+ .SetCommand("dist"));
+ });
+
Target Compile => _ => _
.DependsOn(Clean)
+ .DependsOn(CompileHtmlPreviewer)
.Executes(() =>
{
if (Parameters.IsRunningOnWindows)
diff --git a/packages/Avalonia/AvaloniaBuildTasks.targets b/packages/Avalonia/AvaloniaBuildTasks.targets
index 552713f94b..537495fcad 100644
--- a/packages/Avalonia/AvaloniaBuildTasks.targets
+++ b/packages/Avalonia/AvaloniaBuildTasks.targets
@@ -2,6 +2,7 @@
<_AvaloniaUseExternalMSBuild>$(AvaloniaUseExternalMSBuild)
<_AvaloniaUseExternalMSBuild Condition="'$(_AvaloniaForceInternalMSBuild)' == 'true'">false
+ low
+ EmbeddedResources="@(EmbeddedResources)"
+ ReportImportance="$(AvaloniaXamlReportImportance)"/>
@@ -67,6 +69,7 @@
OriginalCopyPath="$(AvaloniaXamlOriginalCopyFilePath)"
ProjectDirectory="$(MSBuildProjectDirectory)"
VerifyIl="$(AvaloniaXamlIlVerifyIl)"
+ ReportImportance="$(AvaloniaXamlReportImportance)"
/>
+[](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) [](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) [](#backers) [](#sponsors) 
+
+[](https://www.nuget.org/packages/Avalonia) [](https://www.nuget.org/packages/Avalonia) [](https://www.myget.org/gallery/avalonia-ci) 
-# Avalonia
+
-| Gitter Chat | Build Status (Win, Linux, OSX) | Open Collective | NuGet | MyGet |
-|---|---|---|---|---|
-| [](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) | [](#backers) [](#sponsors) | [](https://www.nuget.org/packages/Avalonia) | [](https://www.myget.org/gallery/avalonia-ci) |
+## 📖 About AvaloniaUI
-## About
+Avalonia is a cross-platform XAML-based UI framework providing a flexible styling system and supporting a wide range of Operating Systems such as Windows via .NET Framework and .NET Core, Linux via Xorg, macOS. Avalonia is ready for **General-Purpose Desktop App Development**. However, there may be some bugs and breaking changes as we continue along into this project's development.
-**Avalonia** is a cross-platform XAML-based UI framework providing a flexible styling system and supporting a wide range of Operating Systems such as Windows (.NET Framework, .NET Core), Linux (via Xorg), macOS.
+
-**Avalonia** is ready for **General-Purpose Desktop App Development**. However, there may be some bugs and breaking changes as we continue along into this project's development.
+> **Note:** The UI theme you see in the picture above is still work-in-progress and will be available in the upcoming Avalonia 0.10.0 release. However, you can connect to our nightly build feed and install latest pre-release versions of Avalonia NuGet packages, if you are willing to help out with the development and testing. See [Using nightly build feed](https://github.com/AvaloniaUI/Avalonia/wiki/Using-nightly-build-feed) for more info.
-To see the status of some of our features, please see our [Roadmap here](https://github.com/AvaloniaUI/Avalonia/issues/2239).
+To see the status of some of our features, please see our [Roadmap](https://github.com/AvaloniaUI/Avalonia/issues/2239). You can also see what [breaking changes](https://github.com/AvaloniaUI/Avalonia/issues/3538) we have planned and what our [past breaking changes](https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes) have been. [Awesome Avalonia](https://github.com/AvaloniaCommunity/awesome-avalonia) is community-curated list of awesome Avalonia UI tools, libraries, projects and resources. Go and see what people are building with Avalonia!
-You can also see what [breaking changes](https://github.com/AvaloniaUI/Avalonia/issues/3538) we have planned and what our [past breaking changes](https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes) have been.
-
-[Awesome Avalonia](https://github.com/AvaloniaCommunity/awesome-avalonia) is community-curated list of awesome Avalonia UI tools, libraries, projects and resources. Go and see what people are building with Avalonia!
-
-## Getting Started
+## 🚀 Getting Started
The Avalonia [Visual Studio Extension](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio) contains project and control templates that will help you get started, or you can use the .NET Core CLI. For a starer guide see our [documentation](http://avaloniaui.net/docs/quickstart/create-new-project).
@@ -30,6 +26,17 @@ Install-Package Avalonia
Install-Package Avalonia.Desktop
```
+## Showcase
+
+Examples of UIs built with Avalonia
+
+
+
+
+
+
+
+
## JetBrains Rider
If you need to develop Avalonia app with JetBrains Rider, go and *vote* on [this issue](https://youtrack.jetbrains.com/issue/RIDER-39247) in their tracker. JetBrains won't do things without their users telling them that they want the feature, so only **YOU** can make it happen.
diff --git a/samples/BindingDemo/App.xaml.cs b/samples/BindingDemo/App.xaml.cs
index f2f44cd502..13875aeb21 100644
--- a/samples/BindingDemo/App.xaml.cs
+++ b/samples/BindingDemo/App.xaml.cs
@@ -1,10 +1,8 @@
using System;
using Avalonia;
using Avalonia.Controls;
-using Avalonia.Logging.Serilog;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
-using Serilog;
namespace BindingDemo
{
diff --git a/samples/BindingDemo/BindingDemo.csproj b/samples/BindingDemo/BindingDemo.csproj
index ce33f42143..817023fd71 100644
--- a/samples/BindingDemo/BindingDemo.csproj
+++ b/samples/BindingDemo/BindingDemo.csproj
@@ -10,7 +10,6 @@
-
diff --git a/samples/BindingDemo/MainWindow.xaml b/samples/BindingDemo/MainWindow.xaml
index b57a9a0a9e..26a62ebca6 100644
--- a/samples/BindingDemo/MainWindow.xaml
+++ b/samples/BindingDemo/MainWindow.xaml
@@ -74,11 +74,11 @@
-
+
-
+
diff --git a/samples/BindingDemo/ViewModels/MainWindowViewModel.cs b/samples/BindingDemo/ViewModels/MainWindowViewModel.cs
index 22d01e0765..a66038ff3e 100644
--- a/samples/BindingDemo/ViewModels/MainWindowViewModel.cs
+++ b/samples/BindingDemo/ViewModels/MainWindowViewModel.cs
@@ -6,6 +6,7 @@ using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Threading;
using ReactiveUI;
+using Avalonia.Controls;
namespace BindingDemo.ViewModels
{
@@ -27,7 +28,7 @@ namespace BindingDemo.ViewModels
Detail = "Item " + x + " details",
}));
- SelectedItems = new ObservableCollection();
+ Selection = new SelectionModel();
ShuffleItems = ReactiveCommand.Create(() =>
{
@@ -56,7 +57,7 @@ namespace BindingDemo.ViewModels
}
public ObservableCollection Items { get; }
- public ObservableCollection SelectedItems { get; }
+ public SelectionModel Selection { get; }
public ReactiveCommand ShuffleItems { get; }
public string BooleanString
diff --git a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
index 054de2a05f..1a112d0d7d 100644
--- a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
+++ b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
@@ -10,6 +10,5 @@
-
diff --git a/samples/ControlCatalog.Desktop/Program.cs b/samples/ControlCatalog.Desktop/Program.cs
index 2a8d288614..b2df1953f5 100644
--- a/samples/ControlCatalog.Desktop/Program.cs
+++ b/samples/ControlCatalog.Desktop/Program.cs
@@ -2,10 +2,8 @@ using System;
using System.Linq;
using Avalonia;
using Avalonia.Controls;
-using Avalonia.Logging.Serilog;
using Avalonia.Platform;
using Avalonia.ReactiveUI;
-using Serilog;
namespace ControlCatalog
{
diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs
index 854cae484c..5df8c1be64 100644
--- a/samples/ControlCatalog.NetCore/Program.cs
+++ b/samples/ControlCatalog.NetCore/Program.cs
@@ -4,8 +4,8 @@ using System.Globalization;
using System.Linq;
using System.Threading;
using Avalonia;
-using Avalonia.ReactiveUI;
using Avalonia.Dialogs;
+using Avalonia.ReactiveUI;
namespace ControlCatalog.NetCore
{
@@ -67,7 +67,8 @@ namespace ControlCatalog.NetCore
})
.UseSkia()
.UseReactiveUI()
- .UseManagedSystemDialogs();
+ .UseManagedSystemDialogs()
+ .LogToDebug();
static void SilenceConsole()
{
diff --git a/samples/ControlCatalog/App.xaml b/samples/ControlCatalog/App.xaml
index e40509dfda..c7a75f5a70 100644
--- a/samples/ControlCatalog/App.xaml
+++ b/samples/ControlCatalog/App.xaml
@@ -1,9 +1,7 @@
-
-
-
+
-
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/ButtonPage.xaml.cs b/samples/ControlCatalog/Pages/ButtonPage.xaml.cs
index 1d0c228a0e..5e555c8c91 100644
--- a/samples/ControlCatalog/Pages/ButtonPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ButtonPage.xaml.cs
@@ -5,5 +5,25 @@ namespace ControlCatalog.Pages
{
public class ButtonPage : UserControl
{
+ private int repeatButtonClickCount = 0;
+
+ public ButtonPage()
+ {
+ InitializeComponent();
+
+ this.FindControl("RepeatButton").Click += OnRepeatButtonClick;
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ public void OnRepeatButtonClick(object sender, object args)
+ {
+ repeatButtonClickCount++;
+ var textBlock = this.FindControl("RepeatButtonTextBlock");
+ textBlock.Text = $"Repeat Button: {repeatButtonClickCount}";
+ }
}
}
diff --git a/samples/ControlCatalog/Pages/DatePickerPage.xaml b/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml
similarity index 75%
rename from samples/ControlCatalog/Pages/DatePickerPage.xaml
rename to samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml
index 30d5a7506f..107472105a 100644
--- a/samples/ControlCatalog/Pages/DatePickerPage.xaml
+++ b/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml
@@ -1,8 +1,8 @@
+ x:Class="ControlCatalog.Pages.CalendarDatePickerPage">
- DatePicker
+ CalendarDatePicker
A control for selecting dates with a calendar drop-down
-
-
-
-
-
-
-
+
diff --git a/samples/ControlCatalog/Pages/DatePickerPage.xaml.cs b/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml.cs
similarity index 57%
rename from samples/ControlCatalog/Pages/DatePickerPage.xaml.cs
rename to samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml.cs
index ef01887c9e..95bdeb363a 100644
--- a/samples/ControlCatalog/Pages/DatePickerPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml.cs
@@ -4,17 +4,17 @@ using System;
namespace ControlCatalog.Pages
{
- public class DatePickerPage : UserControl
+ public class CalendarDatePickerPage : UserControl
{
- public DatePickerPage()
+ public CalendarDatePickerPage()
{
InitializeComponent();
- var dp1 = this.FindControl("DatePicker1");
- var dp2 = this.FindControl("DatePicker2");
- var dp3 = this.FindControl("DatePicker3");
- var dp4 = this.FindControl("DatePicker4");
- var dp5 = this.FindControl("DatePicker5");
+ var dp1 = this.FindControl("DatePicker1");
+ var dp2 = this.FindControl("DatePicker2");
+ var dp3 = this.FindControl("DatePicker3");
+ var dp4 = this.FindControl("DatePicker4");
+ var dp5 = this.FindControl("DatePicker5");
dp1.SelectedDate = DateTime.Today;
dp2.SelectedDate = DateTime.Today.AddDays(10);
diff --git a/samples/ControlCatalog/Pages/ComboBoxPage.xaml b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
index bbfbd4b4cd..486cc55d44 100644
--- a/samples/ControlCatalog/Pages/ComboBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
@@ -6,7 +6,7 @@
A drop-down list.
-
+
Inline Items
Inline Item 2
Inline Item 3
diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml b/samples/ControlCatalog/Pages/DialogsPage.xaml
index 1ed5c0cbfd..a0e82663bf 100644
--- a/samples/ControlCatalog/Pages/DialogsPage.xaml
+++ b/samples/ControlCatalog/Pages/DialogsPage.xaml
@@ -6,9 +6,12 @@
+
+
+
diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
index ba1921a185..cf6c771e34 100644
--- a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Avalonia.Controls;
+using Avalonia.Dialogs;
using Avalonia.Markup.Xaml;
#pragma warning disable 4014
@@ -58,6 +59,19 @@ namespace ControlCatalog.Pages
Title = "Select folder",
}.ShowAsync(GetWindow());
};
+ this.FindControl