From e5241a59e707a7cba8e7c106c36f4a6ead9d1469 Mon Sep 17 00:00:00 2001 From: Steven He Date: Fri, 22 Jul 2022 13:16:38 +0900 Subject: [PATCH 01/22] various fixes --- src/Avalonia.Base/Visual.cs | 10 ++++++++-- src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs | 7 +++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Base/Visual.cs b/src/Avalonia.Base/Visual.cs index 8feba116f0..fbc940114a 100644 --- a/src/Avalonia.Base/Visual.cs +++ b/src/Avalonia.Base/Visual.cs @@ -667,8 +667,14 @@ namespace Avalonia if (_visualParent is IRenderRoot || _visualParent?.IsAttachedToVisualTree == true) { - var root = this.FindAncestorOfType() ?? - throw new AvaloniaInternalException("Visual is atached to visual tree but root could not be found."); + var root = this.FindAncestorOfType(); + if (root is null) + { + Logger.TryGet(LogEventLevel.Error, "Visual")?.Log("Visual", + "Visual is atached to visual tree but root could not be found."); + return; + } + var e = new VisualTreeAttachmentEventArgs(_visualParent, root); OnAttachedToVisualTreeCore(e); } diff --git a/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs b/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs index b3469c212b..ccdc5ac19b 100644 --- a/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs +++ b/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs @@ -148,6 +148,13 @@ namespace Avalonia.OpenGL.Controls return false; } + if (_context == null) + { + Logger.TryGet(LogEventLevel.Error, "OpenGL")?.Log("OpenGlControlBase", + "Unable to initialize OpenGL: unable to create additional OpenGL context."); + return false; + } + GlVersion = _context.Version; try { From 0bdd0c3160d73a35982ed5bcb7fc421a3d7bd381 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 22 Jul 2022 15:24:20 +0100 Subject: [PATCH 02/22] add a failing integration test. --- .../WindowTests.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index 2b10c302bc..9e39d0ae58 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -1,7 +1,9 @@ using System; +using System.Linq; using System.Runtime.InteropServices; using System.Threading; using Avalonia.Controls; +using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Interactions; using Xunit; @@ -55,6 +57,43 @@ namespace Avalonia.IntegrationTests.Appium } } } + + [PlatformFact(TestPlatforms.Windows)] + public void OnWindows_Docked_Windows_Retain_Size_Position_When_Restored() + { + using (OpenWindow(new Size(400, 400), ShowWindowMode.NonOwned, WindowStartupLocation.Manual)) + { + var windowState = _session.FindElementByAccessibilityId("WindowState"); + + Assert.Equal("Normal", windowState.GetComboBoxValue()); + + + var window = _session.FindElements(By.XPath("//Window")).First(); + + new Actions(_session) + .KeyDown(Keys.Meta) + .SendKeys(Keys.Left) + .KeyUp(Keys.Meta) + .Perform(); + + var original = GetWindowInfo(); + + windowState.Click(); + _session.FindElementByName("Minimized").SendClick(); + + new Actions(_session) + .KeyDown(Keys.Alt) + .SendKeys(Keys.Tab) + .KeyUp(Keys.Alt) + .Perform(); + + var current = GetWindowInfo(); + + Assert.Equal(original.Position, current.Position); + Assert.Equal(original.FrameSize, current.FrameSize); + + } + } [Theory] From cdc3100097a48f5bc1a77d483d2ffdd6ad2718ae Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 22 Jul 2022 15:24:39 +0100 Subject: [PATCH 03/22] add fix to make code path consistent with wpf. --- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 2f1a116af7..ce8374a68f 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -285,7 +285,7 @@ namespace Avalonia.Win32 set { - if (IsWindowVisible(_hwnd)) + if (IsWindowVisible(_hwnd) && _lastWindowState != value) { ShowWindow(value, value != WindowState.Minimized); // If the window is minimized, it shouldn't be activated } From 8c39dd54a08f9ea3bafac190b99cd29cac3351ca Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 22 Jul 2022 16:02:56 +0100 Subject: [PATCH 04/22] fix exiting fullscreen. --- src/Windows/Avalonia.Win32/WindowImpl.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index ce8374a68f..e990efafdb 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -290,6 +290,7 @@ namespace Avalonia.Win32 ShowWindow(value, value != WindowState.Minimized); // If the window is minimized, it shouldn't be activated } + _lastWindowState = value; _showWindowState = value; } } From 5fcc5ecfea3e539e37f497ff8d11602fadfd69ca Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 22 Jul 2022 17:11:34 +0100 Subject: [PATCH 05/22] disable broken tests. --- tests/Avalonia.IntegrationTests.Appium/MenuTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.IntegrationTests.Appium/MenuTests.cs b/tests/Avalonia.IntegrationTests.Appium/MenuTests.cs index d1d231466f..b0d395464b 100644 --- a/tests/Avalonia.IntegrationTests.Appium/MenuTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/MenuTests.cs @@ -57,7 +57,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("_Grandchild", clickedMenuItem.Text); } - [PlatformFact(TestPlatforms.Windows)] + /*[PlatformFact(TestPlatforms.Windows)] public void Select_Child_With_Alt_Arrow_Keys() { new Actions(_session) @@ -103,7 +103,7 @@ namespace Avalonia.IntegrationTests.Appium var clickedMenuItem = _session.FindElementByAccessibilityId("ClickedMenuItem"); Assert.Equal("_Grandchild", clickedMenuItem.Text); - } + }*/ [PlatformFact(TestPlatforms.Windows)] public void Select_Child_With_Click_Arrow_Keys() From a9cc499de3663600c9e8b9bce2646af3af659621 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 27 Jul 2022 10:04:32 +0100 Subject: [PATCH 06/22] Revert "disable broken tests." This reverts commit 5fcc5ecfea3e539e37f497ff8d11602fadfd69ca. --- tests/Avalonia.IntegrationTests.Appium/MenuTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.IntegrationTests.Appium/MenuTests.cs b/tests/Avalonia.IntegrationTests.Appium/MenuTests.cs index b0d395464b..d1d231466f 100644 --- a/tests/Avalonia.IntegrationTests.Appium/MenuTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/MenuTests.cs @@ -57,7 +57,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("_Grandchild", clickedMenuItem.Text); } - /*[PlatformFact(TestPlatforms.Windows)] + [PlatformFact(TestPlatforms.Windows)] public void Select_Child_With_Alt_Arrow_Keys() { new Actions(_session) @@ -103,7 +103,7 @@ namespace Avalonia.IntegrationTests.Appium var clickedMenuItem = _session.FindElementByAccessibilityId("ClickedMenuItem"); Assert.Equal("_Grandchild", clickedMenuItem.Text); - }*/ + } [PlatformFact(TestPlatforms.Windows)] public void Select_Child_With_Click_Arrow_Keys() From eb8ddef4122fe59e54123e125282a13bcfe822fd Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 28 Jul 2022 10:50:20 +0200 Subject: [PATCH 07/22] Add failing integration test on macOS. Hiding a child window, and then clicking on the parent window causes the child window to be erroneously re-shown. --- .../IntegrationTestApp/MainWindow.axaml.cs | 1 + .../IntegrationTestApp/ShowWindowTest.axaml | 3 +- .../WindowTests_MacOS.cs | 29 +++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/samples/IntegrationTestApp/MainWindow.axaml.cs b/samples/IntegrationTestApp/MainWindow.axaml.cs index 9e180b12c5..1dab74dc9e 100644 --- a/samples/IntegrationTestApp/MainWindow.axaml.cs +++ b/samples/IntegrationTestApp/MainWindow.axaml.cs @@ -99,6 +99,7 @@ namespace IntegrationTestApp foreach (var window in lifetime.Windows) { + window.Show(); if (window.WindowState == WindowState.Minimized) window.WindowState = WindowState.Normal; } diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml b/samples/IntegrationTestApp/ShowWindowTest.axaml index 40c1642e91..4001bac7e2 100644 --- a/samples/IntegrationTestApp/ShowWindowTest.axaml +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml @@ -3,7 +3,7 @@ x:Class="IntegrationTestApp.ShowWindowTest" Name="SecondaryWindow" Title="Show Window Test"> - + @@ -31,5 +31,6 @@ Maximized Fullscreen + diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs index ecbdd5bade..4e5344dd25 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs @@ -211,6 +211,35 @@ namespace Avalonia.IntegrationTests.Appium } } + [PlatformFact(TestPlatforms.MacOS)] + public void Hidden_Child_Window_Is_Not_Reshown_When_Parent_Clicked() + { + var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); + + // We don't use dispose to close the window here, because it seems that hiding and re-showing a window + // causes Appium to think it's a different window. + OpenWindow(null, ShowWindowMode.Owned, WindowStartupLocation.Manual); + + var secondaryWindow = FindWindow(_session, "SecondaryWindow"); + var hideButton = secondaryWindow.FindElementByAccessibilityId("HideButton"); + + hideButton.Click(); + + var windows = _session.FindElementsByXPath("XCUIElementTypeWindow"); + Assert.Single(windows); + + mainWindow.Click(); + + windows = _session.FindElementsByXPath("XCUIElementTypeWindow"); + Assert.Single(windows); + + _session.FindElementByAccessibilityId("RestoreAll").Click(); + + // Close the window manually. + secondaryWindow = FindWindow(_session, "SecondaryWindow"); + secondaryWindow.GetChromeButtons().close.Click(); + } + private IDisposable OpenWindow(PixelSize? size, ShowWindowMode mode, WindowStartupLocation location) { var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize"); From 9d356894bca636e1e1789c456e2440f08c119a18 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 28 Jul 2022 11:04:33 +0200 Subject: [PATCH 08/22] macOS: Don't bring invisible window to front. Check that a window is visible before bringing it to front, as bringing to front also shows the window. --- native/Avalonia.Native/src/OSX/WindowImpl.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm index 95f61422cb..af8c53cb33 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm @@ -121,7 +121,7 @@ void WindowImpl::BringToFront() { if(Window != nullptr) { - if (![Window isMiniaturized]) + if ([Window isVisible] && ![Window isMiniaturized]) { if(IsDialog()) { From 9acb2a11ee4793568b01769d2ffc9160d8ef004c Mon Sep 17 00:00:00 2001 From: Julien Lebosquain Date: Tue, 2 Aug 2022 18:42:02 +0200 Subject: [PATCH 09/22] Custom setters implement Equals/GetHashCode and have optimized code gen --- ...aloniaXamlIlDeferredResourceTransformer.cs | 50 +++++- .../AvaloniaXamlIlSetterTransformer.cs | 26 ++- .../XamlIlAvaloniaPropertyHelper.cs | 152 ++++++++++++++---- .../Avalonia.Markup.Xaml.Loader/xamlil.github | 2 +- 4 files changed, 182 insertions(+), 48 deletions(-) diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDeferredResourceTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDeferredResourceTransformer.cs index 662263e513..c29dd94886 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDeferredResourceTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDeferredResourceTransformer.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using XamlX.Ast; using XamlX.Emit; @@ -47,7 +48,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers return !node.Type.GetClrType().IsValueType; } - class AdderSetter : IXamlPropertySetter, IXamlEmitablePropertySetter + class AdderSetter : IXamlILOptimizedEmitablePropertySetter, IEquatable { private readonly IXamlMethod _getter; private readonly IXamlMethod _adder; @@ -58,16 +59,22 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers _adder = adder; TargetType = getter.DeclaringType; Parameters = adder.ParametersWithThis().Skip(1).ToList(); + + bool allowNull = Parameters.Last().AcceptsNull(); + BinderParameters = new PropertySetterBinderParameters + { + AllowMultiple = true, + AllowXNull = allowNull, + AllowRuntimeNull = allowNull + }; } public IXamlType TargetType { get; } - public PropertySetterBinderParameters BinderParameters { get; } = new PropertySetterBinderParameters - { - AllowMultiple = true - }; + public PropertySetterBinderParameters BinderParameters { get; } public IReadOnlyList Parameters { get; } + public void Emit(IXamlILEmitter emitter) { var locals = new Stack(); @@ -80,11 +87,40 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers } emitter.EmitCall(_getter); - while (locals.Count > 0) + while (locals.Count>0) using (var loc = locals.Pop()) emitter.Ldloc(loc.Local); emitter.EmitCall(_adder, true); } + + public void EmitWithArguments( + XamlEmitContextWithLocals context, + IXamlILEmitter emitter, + IReadOnlyList arguments) + { + emitter.EmitCall(_getter); + + for (var i = 0; i < arguments.Count; ++i) + context.Emit(arguments[i], emitter, Parameters[i]); + + emitter.EmitCall(_adder, true); + } + + public bool Equals(AdderSetter other) + { + if (ReferenceEquals(null, other)) + return false; + if (ReferenceEquals(this, other)) + return true; + + return _getter.Equals(other._getter) && _adder.Equals(other._adder); + } + + public override bool Equals(object obj) + => Equals(obj as AdderSetter); + + public override int GetHashCode() + => (_getter.GetHashCode() * 397) ^ _adder.GetHashCode(); } } } diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs index 6da95be1c1..ceaec972f6 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs @@ -75,17 +75,17 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers { Getter = setterType.Methods.First(m => m.Name == "get_Value"); var method = setterType.Methods.First(m => m.Name == "set_Value"); - Setters.Add(new XamlIlDirectCallPropertySetter(method, types.IBinding)); - Setters.Add(new XamlIlDirectCallPropertySetter(method, types.UnsetValueType)); - Setters.Add(new XamlIlDirectCallPropertySetter(method, targetType)); + Setters.Add(new XamlIlDirectCallPropertySetter(method, types.IBinding, false)); + Setters.Add(new XamlIlDirectCallPropertySetter(method, types.UnsetValueType, false)); + Setters.Add(new XamlIlDirectCallPropertySetter(method, targetType, targetType.AcceptsNull())); } - class XamlIlDirectCallPropertySetter : IXamlPropertySetter, IXamlEmitablePropertySetter + sealed class XamlIlDirectCallPropertySetter : IXamlPropertySetter, IXamlEmitablePropertySetter { private readonly IXamlMethod _method; private readonly IXamlType _type; public IXamlType TargetType { get; } - public PropertySetterBinderParameters BinderParameters { get; } = new PropertySetterBinderParameters(); + public PropertySetterBinderParameters BinderParameters { get; } public IReadOnlyList Parameters { get; } public void Emit(IXamlILEmitter codegen) { @@ -94,13 +94,27 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers codegen.EmitCall(_method, true); } - public XamlIlDirectCallPropertySetter(IXamlMethod method, IXamlType type) + public XamlIlDirectCallPropertySetter(IXamlMethod method, IXamlType type, bool allowNull) { _method = method; _type = type; Parameters = new[] {type}; TargetType = method.ThisOrFirstParameter(); + BinderParameters = new PropertySetterBinderParameters + { + AllowXNull = allowNull, + AllowRuntimeNull = allowNull + }; } + + private bool Equals(XamlIlDirectCallPropertySetter other) + => Equals(_method, other._method) && Equals(_type, other._type); + + public override bool Equals(object obj) + => Equals(obj as XamlIlDirectCallPropertySetter); + + public override int GetHashCode() + => (_method.GetHashCode() * 397) ^ _type.GetHashCode(); } } } diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs index 5c7a80e680..6c9d510ba0 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs @@ -206,38 +206,64 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions Setters.Insert(0, new UnsetValueSetter(types, original.DeclaringType, field)); } - abstract class AvaloniaPropertyCustomSetter : IXamlPropertySetter, IXamlEmitablePropertySetter + abstract class AvaloniaPropertyCustomSetter : IXamlILOptimizedEmitablePropertySetter, IEquatable { - protected AvaloniaXamlIlWellKnownTypes Types; - protected IXamlField AvaloniaProperty; + protected readonly AvaloniaXamlIlWellKnownTypes Types; + protected readonly IXamlField AvaloniaProperty; - public AvaloniaPropertyCustomSetter(AvaloniaXamlIlWellKnownTypes types, + protected AvaloniaPropertyCustomSetter( + AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, - IXamlField avaloniaProperty) + IXamlField avaloniaProperty, + bool allowNull) { Types = types; AvaloniaProperty = avaloniaProperty; TargetType = declaringType; + BinderParameters = new PropertySetterBinderParameters + { + AllowXNull = allowNull, + AllowRuntimeNull = allowNull + }; } public IXamlType TargetType { get; } - public PropertySetterBinderParameters BinderParameters { get; } = new PropertySetterBinderParameters - { - AllowXNull = false - }; + public PropertySetterBinderParameters BinderParameters { get; } public IReadOnlyList Parameters { get; set; } - public abstract void Emit(IXamlILEmitter codegen); + + public abstract void Emit(IXamlILEmitter emitter); + + public abstract void EmitWithArguments( + XamlEmitContextWithLocals context, + IXamlILEmitter emitter, + IReadOnlyList arguments); + + public bool Equals(AvaloniaPropertyCustomSetter other) + { + if (ReferenceEquals(null, other)) + return false; + if (ReferenceEquals(this, other)) + return true; + + return GetType() == other.GetType() && AvaloniaProperty.Equals(other.AvaloniaProperty); + } + + public override bool Equals(object obj) + => Equals(obj as AvaloniaPropertyCustomSetter); + + public override int GetHashCode() + => AvaloniaProperty.GetHashCode(); } class BindingSetter : AvaloniaPropertyCustomSetter { public BindingSetter(AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, - IXamlField avaloniaProperty) : base(types, declaringType, avaloniaProperty) + IXamlField avaloniaProperty) : base(types, declaringType, avaloniaProperty, false) { - Parameters = new[] {types.IBinding}; + Parameters = new[] { types.IBinding }; } public override void Emit(IXamlILEmitter emitter) @@ -246,10 +272,25 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions emitter .Stloc(bloc.Local) .Ldsfld(AvaloniaProperty) - .Ldloc(bloc.Local) - // TODO: provide anchor? - .Ldnull(); - emitter.EmitCall(Types.AvaloniaObjectBindMethod, true); + .Ldloc(bloc.Local); + EmitAnchorAndBind(emitter); + } + + public override void EmitWithArguments( + XamlEmitContextWithLocals context, + IXamlILEmitter emitter, + IReadOnlyList arguments) + { + emitter.Ldsfld(AvaloniaProperty); + context.Emit(arguments[0], emitter, Parameters[0]); + EmitAnchorAndBind(emitter); + } + + private void EmitAnchorAndBind(IXamlILEmitter emitter) + { + emitter + .Ldnull() // TODO: provide anchor? + .EmitCall(Types.AvaloniaObjectBindMethod, true); } } @@ -257,7 +298,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions { public BindingWithPrioritySetter(AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, - IXamlField avaloniaProperty) : base(types, declaringType, avaloniaProperty) + IXamlField avaloniaProperty) : base(types, declaringType, avaloniaProperty, false) { Parameters = new[] { types.BindingPriority, types.IBinding }; } @@ -265,15 +306,29 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions public override void Emit(IXamlILEmitter emitter) { using (var bloc = emitter.LocalsPool.GetLocal(Types.IBinding)) - using (var priorityLocal = emitter.LocalsPool.GetLocal(Types.Int)) emitter .Stloc(bloc.Local) - .Stloc(priorityLocal.Local) + .Pop() // ignore priority .Ldsfld(AvaloniaProperty) - .Ldloc(bloc.Local) - // TODO: provide anchor? - .Ldnull(); - emitter.EmitCall(Types.AvaloniaObjectBindMethod, true); + .Ldloc(bloc.Local); + EmitAnchorAndBind(emitter); + } + + public override void EmitWithArguments( + XamlEmitContextWithLocals context, + IXamlILEmitter emitter, + IReadOnlyList arguments) + { + emitter.Ldsfld(AvaloniaProperty); + context.Emit(arguments[1], emitter, Parameters[1]); + EmitAnchorAndBind(emitter); + } + + private void EmitAnchorAndBind(IXamlILEmitter emitter) + { + emitter + .Ldnull() // TODO: provide anchor? + .EmitCall(Types.AvaloniaObjectBindMethod, true); } } @@ -281,7 +336,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions { public SetValueWithPrioritySetter(AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, IXamlField avaloniaProperty, IXamlType propertyType) - : base(types, declaringType, avaloniaProperty) + : base(types, declaringType, avaloniaProperty, propertyType.AcceptsNull()) { Parameters = new[] { types.BindingPriority, propertyType }; } @@ -295,9 +350,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions - value */ - var method = Types.AvaloniaObjectSetStyledPropertyValue - .MakeGenericMethod(new[] { Parameters[1] }); - using (var valueLocal = emitter.LocalsPool.GetLocal(Parameters[1])) using (var priorityLocal = emitter.LocalsPool.GetLocal(Types.Int)) emitter @@ -305,25 +357,57 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions .Stloc(priorityLocal.Local) .Ldsfld(AvaloniaProperty) .Ldloc(valueLocal.Local) - .Ldloc(priorityLocal.Local) - .EmitCall(method, true); + .Ldloc(priorityLocal.Local); + + EmitSetStyledPropertyValue(emitter); + } + + public override void EmitWithArguments( + XamlEmitContextWithLocals context, + IXamlILEmitter emitter, + IReadOnlyList arguments) + { + emitter.Ldsfld(AvaloniaProperty); + context.Emit(arguments[1], emitter, Parameters[1]); + context.Emit(arguments[0], emitter, Parameters[0]); + EmitSetStyledPropertyValue(emitter); + } + + private void EmitSetStyledPropertyValue(IXamlILEmitter emitter) + { + var method = Types.AvaloniaObjectSetStyledPropertyValue.MakeGenericMethod(new[] { Parameters[1] }); + emitter.EmitCall(method, true); } } class UnsetValueSetter : AvaloniaPropertyCustomSetter { public UnsetValueSetter(AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, IXamlField avaloniaProperty) - : base(types, declaringType, avaloniaProperty) + : base(types, declaringType, avaloniaProperty, false) { - Parameters = new[] {types.UnsetValueType}; + Parameters = new[] { types.UnsetValueType }; } public override void Emit(IXamlILEmitter codegen) { + codegen.Pop(); + EmitSetValue(codegen); + } + + public override void EmitWithArguments( + XamlEmitContextWithLocals context, + IXamlILEmitter emitter, + IReadOnlyList arguments) + { + EmitSetValue(emitter); + } + + private void EmitSetValue(IXamlILEmitter emitter) + { + // Ignore the instance and load one from the static field to avoid extra local variable var unsetValue = Types.AvaloniaProperty.Fields.First(f => f.Name == "UnsetValue"); - codegen - // Ignore the instance and load one from the static field to avoid extra local variable - .Pop() + + emitter .Ldsfld(AvaloniaProperty) .Ldsfld(unsetValue) .Ldc_I4(0) diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github b/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github index a4e6be2d14..c1c0594ec2 160000 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github @@ -1 +1 @@ -Subproject commit a4e6be2d1407abec4f35fcb208848830ce513ead +Subproject commit c1c0594ec2c35b08988183b1a5b3e34dfa19179d From 3af34590745c83e282331093858f25fef0e641af Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 6 Aug 2022 00:57:43 -0400 Subject: [PATCH 10/22] Stop transition if it was cancelled --- src/Avalonia.Controls/TransitioningContentControl.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/TransitioningContentControl.cs b/src/Avalonia.Controls/TransitioningContentControl.cs index 451e234653..70b21b7248 100644 --- a/src/Avalonia.Controls/TransitioningContentControl.cs +++ b/src/Avalonia.Controls/TransitioningContentControl.cs @@ -84,13 +84,19 @@ public class TransitioningContentControl : ContentControl _lastTransitionCts?.Cancel(); _lastTransitionCts = new CancellationTokenSource(); + var localToken = _lastTransitionCts.Token; if (PageTransition != null) - await PageTransition.Start(this, null, true, _lastTransitionCts.Token); + await PageTransition.Start(this, null, true, localToken); + + if (localToken.IsCancellationRequested) + { + return; + } CurrentContent = content; if (PageTransition != null) - await PageTransition.Start(null, this, true, _lastTransitionCts.Token); + await PageTransition.Start(null, this, true, localToken); } } From 2132ba2cc909884fb069b384f5ac30fce7cc63b5 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 6 Aug 2022 03:58:45 -0400 Subject: [PATCH 11/22] Delete legacy ReactiveUI.TransitioningContentControl --- .../TransitioningContentControl.cs | 80 ------------------- 1 file changed, 80 deletions(-) delete mode 100644 src/Avalonia.ReactiveUI/TransitioningContentControl.cs diff --git a/src/Avalonia.ReactiveUI/TransitioningContentControl.cs b/src/Avalonia.ReactiveUI/TransitioningContentControl.cs deleted file mode 100644 index d26e90b2da..0000000000 --- a/src/Avalonia.ReactiveUI/TransitioningContentControl.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Threading; - -using Avalonia.Animation; -using Avalonia.Controls; -using Avalonia.Styling; - -namespace Avalonia.ReactiveUI -{ - /// - /// A ContentControl that animates the transition when its content is changed. - /// - [Obsolete("Use TransitioningContentControl in Avalonia.Controls namespace")] - public class TransitioningContentControl : ContentControl, IStyleable - { - /// - /// for the property. - /// - public static readonly StyledProperty PageTransitionProperty = - AvaloniaProperty.Register(nameof(PageTransition), - new CrossFade(TimeSpan.FromSeconds(0.5))); - - /// - /// for the property. - /// - public static readonly StyledProperty DefaultContentProperty = - AvaloniaProperty.Register(nameof(DefaultContent)); - - private CancellationTokenSource? _lastTransitionCts; - - /// - /// Gets or sets the animation played when content appears and disappears. - /// - public IPageTransition? PageTransition - { - get => GetValue(PageTransitionProperty); - set => SetValue(PageTransitionProperty, value); - } - - /// - /// Gets or sets the content displayed whenever there is no page currently routed. - /// - public object? DefaultContent - { - get => GetValue(DefaultContentProperty); - set => SetValue(DefaultContentProperty, value); - } - - /// - /// Gets or sets the content with animation. - /// - public new object? Content - { - get => base.Content; - set => UpdateContentWithTransition(value); - } - - /// - /// TransitioningContentControl uses the default ContentControl - /// template from Avalonia default theme. - /// - Type IStyleable.StyleKey => typeof(ContentControl); - - /// - /// Updates the content with transitions. - /// - /// New content to set. - private async void UpdateContentWithTransition(object? content) - { - _lastTransitionCts?.Cancel(); - _lastTransitionCts = new CancellationTokenSource(); - - if (PageTransition != null) - await PageTransition.Start(this, null, true, _lastTransitionCts.Token); - base.Content = content; - if (PageTransition != null) - await PageTransition.Start(null, this, true, _lastTransitionCts.Token); - } - } -} From a4c220cdcc6021f5a7d8b3cb805ff108e5eff31f Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 6 Aug 2022 04:45:22 -0400 Subject: [PATCH 12/22] Enable android composition renderer --- src/Android/Avalonia.Android/AndroidPlatform.cs | 15 +++++++++++++-- .../Platform/SkiaPlatform/TopLevelImpl.cs | 9 ++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/Android/Avalonia.Android/AndroidPlatform.cs b/src/Android/Avalonia.Android/AndroidPlatform.cs index 0c72c389dc..89444dea10 100644 --- a/src/Android/Avalonia.Android/AndroidPlatform.cs +++ b/src/Android/Avalonia.Android/AndroidPlatform.cs @@ -8,7 +8,8 @@ using Avalonia.Input.Platform; using Avalonia.OpenGL.Egl; using Avalonia.Platform; using Avalonia.Rendering; -using Avalonia.Skia; +using Avalonia.Rendering.Composition; +using Avalonia.OpenGL; namespace Avalonia { @@ -42,6 +43,8 @@ namespace Avalonia.Android public TimeSpan DoubleClickTime => TimeSpan.FromMilliseconds(500); + internal static Compositor Compositor { get; private set; } + public static void Initialize(AndroidPlatformOptions options) { Options = options; @@ -62,12 +65,20 @@ namespace Avalonia.Android { EglPlatformOpenGlInterface.TryInitialize(); } + + if (options.UseCompositor) + { + Compositor = new Compositor( + AvaloniaLocator.Current.GetRequiredService(), + AvaloniaLocator.Current.GetService()); + } } } public sealed class AndroidPlatformOptions { - public bool UseDeferredRendering { get; set; } = true; + public bool UseDeferredRendering { get; set; } = false; public bool UseGpu { get; set; } = true; + public bool UseCompositor { get; set; } = true; } } diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index fd97e293f9..3484ea2317 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -19,6 +19,7 @@ using Avalonia.OpenGL.Surfaces; using Avalonia.Platform; using Avalonia.Platform.Storage; using Avalonia.Rendering; +using Avalonia.Rendering.Composition; namespace Avalonia.Android.Platform.SkiaPlatform { @@ -84,9 +85,11 @@ namespace Avalonia.Android.Platform.SkiaPlatform public IEnumerable Surfaces => new object[] { _gl, _framebuffer, Handle }; public IRenderer CreateRenderer(IRenderRoot root) => - AndroidPlatform.Options.UseDeferredRendering - ? new DeferredRenderer(root, AvaloniaLocator.Current.GetService()) { RenderOnlyOnRenderThread = true } - : new ImmediateRenderer(root); + AndroidPlatform.Options.UseCompositor + ? new CompositingRenderer(root, AndroidPlatform.Compositor) { DrawFps = true } + : AndroidPlatform.Options.UseDeferredRendering + ? new DeferredRenderer(root, AvaloniaLocator.Current.GetRequiredService()) { RenderOnlyOnRenderThread = true } + : new ImmediateRenderer(root); public virtual void Hide() { From 8100cd3571ad4700d324dbeb393b69d6b450c9de Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 6 Aug 2022 21:39:59 -0400 Subject: [PATCH 13/22] Optimize CurrentThreadIsLoopThread on android backend --- .../AndroidThreadingInterface.cs | 17 ++++++++++++++++- .../Avalonia.Android/Avalonia.Android.csproj | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Android/Avalonia.Android/AndroidThreadingInterface.cs b/src/Android/Avalonia.Android/AndroidThreadingInterface.cs index e72f0aed90..abc7947f38 100644 --- a/src/Android/Avalonia.Android/AndroidThreadingInterface.cs +++ b/src/Android/Avalonia.Android/AndroidThreadingInterface.cs @@ -14,6 +14,7 @@ namespace Avalonia.Android internal sealed class AndroidThreadingInterface : IPlatformThreadingInterface { private Handler _handler; + private static Thread s_uiThread; public AndroidThreadingInterface() { @@ -76,7 +77,21 @@ namespace Avalonia.Android EnsureInvokeOnMainThread(() => Signaled?.Invoke(null)); } - public bool CurrentThreadIsLoopThread => Looper.MainLooper.Thread.Equals(Java.Lang.Thread.CurrentThread()); + public bool CurrentThreadIsLoopThread + { + get + { + if (s_uiThread != null) + return s_uiThread == Thread.CurrentThread; + + if (Looper.MainLooper.IsCurrentThread) + { + s_uiThread = Thread.CurrentThread; + return true; + } + return false; + } + } public event Action Signaled; } } diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj index 6688dde8f5..082ba1f647 100644 --- a/src/Android/Avalonia.Android/Avalonia.Android.csproj +++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj @@ -1,7 +1,7 @@  net6.0-android - 21 + 23 true true portable From 748a25df0d8210c070c07dd9e0cd7a95ffa12e5f Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 6 Aug 2022 22:38:36 -0400 Subject: [PATCH 14/22] Restore missing DefaultContentProperty prop --- src/Avalonia.ReactiveUI/RoutedViewHost.cs | 15 +++++++++++++++ src/Avalonia.ReactiveUI/ViewModelViewHost.cs | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/Avalonia.ReactiveUI/RoutedViewHost.cs b/src/Avalonia.ReactiveUI/RoutedViewHost.cs index 9269dc70f8..775014d419 100644 --- a/src/Avalonia.ReactiveUI/RoutedViewHost.cs +++ b/src/Avalonia.ReactiveUI/RoutedViewHost.cs @@ -64,6 +64,12 @@ namespace Avalonia.ReactiveUI public static readonly StyledProperty ViewContractProperty = AvaloniaProperty.Register(nameof(ViewContract)); + /// + /// for the property. + /// + public static readonly StyledProperty DefaultContentProperty = + ViewModelViewHost.DefaultContentProperty.AddOwner(); + /// /// Initializes a new instance of the class. /// @@ -106,6 +112,15 @@ namespace Avalonia.ReactiveUI set => SetValue(ViewContractProperty, value); } + /// + /// Gets or sets the content displayed whenever there is no page currently routed. + /// + public object? DefaultContent + { + get => GetValue(DefaultContentProperty); + set => SetValue(DefaultContentProperty, value); + } + /// /// Gets or sets the ReactiveUI view locator used by this router. /// diff --git a/src/Avalonia.ReactiveUI/ViewModelViewHost.cs b/src/Avalonia.ReactiveUI/ViewModelViewHost.cs index 16dee00ebc..869238b377 100644 --- a/src/Avalonia.ReactiveUI/ViewModelViewHost.cs +++ b/src/Avalonia.ReactiveUI/ViewModelViewHost.cs @@ -1,5 +1,8 @@ using System; using System.Reactive.Disposables; + +using Avalonia.Controls; + using ReactiveUI; using Splat; @@ -24,6 +27,12 @@ namespace Avalonia.ReactiveUI public static readonly StyledProperty ViewContractProperty = AvaloniaProperty.Register(nameof(ViewContract)); + /// + /// for the property. + /// + public static readonly StyledProperty DefaultContentProperty = + AvaloniaProperty.Register(nameof(DefaultContent)); + /// /// Initializes a new instance of the class. /// @@ -55,6 +64,15 @@ namespace Avalonia.ReactiveUI set => SetValue(ViewContractProperty, value); } + /// + /// Gets or sets the content displayed whenever there is no page currently routed. + /// + public object? DefaultContent + { + get => GetValue(DefaultContentProperty); + set => SetValue(DefaultContentProperty, value); + } + /// /// Gets or sets the view locator. /// From 0e733c70a16e8e465f2691800aed1a350c9fdf47 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 6 Aug 2022 22:48:59 -0400 Subject: [PATCH 15/22] Support 21 api --- src/Android/Avalonia.Android/AndroidThreadingInterface.cs | 6 +++++- src/Android/Avalonia.Android/Avalonia.Android.csproj | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Android/Avalonia.Android/AndroidThreadingInterface.cs b/src/Android/Avalonia.Android/AndroidThreadingInterface.cs index abc7947f38..42f75a27e1 100644 --- a/src/Android/Avalonia.Android/AndroidThreadingInterface.cs +++ b/src/Android/Avalonia.Android/AndroidThreadingInterface.cs @@ -84,11 +84,15 @@ namespace Avalonia.Android if (s_uiThread != null) return s_uiThread == Thread.CurrentThread; - if (Looper.MainLooper.IsCurrentThread) + var isOnMainThread = OperatingSystem.IsAndroidVersionAtLeast(23) + ? Looper.MainLooper.IsCurrentThread + : Looper.MainLooper.Thread.Equals(Java.Lang.Thread.CurrentThread()); + if (isOnMainThread) { s_uiThread = Thread.CurrentThread; return true; } + return false; } } diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj index 082ba1f647..6688dde8f5 100644 --- a/src/Android/Avalonia.Android/Avalonia.Android.csproj +++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj @@ -1,7 +1,7 @@  net6.0-android - 23 + 21 true true portable From 8436e0f7624a050b7e256abcf7d7a1d8f5aae30d Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sun, 7 Aug 2022 01:32:48 -0400 Subject: [PATCH 16/22] Remove test that doesn't make sense anymore --- .../TransitioningContentControlTest.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/Avalonia.ReactiveUI.UnitTests/TransitioningContentControlTest.cs b/tests/Avalonia.ReactiveUI.UnitTests/TransitioningContentControlTest.cs index 6ca617d2d4..daa3830b7d 100644 --- a/tests/Avalonia.ReactiveUI.UnitTests/TransitioningContentControlTest.cs +++ b/tests/Avalonia.ReactiveUI.UnitTests/TransitioningContentControlTest.cs @@ -12,14 +12,6 @@ namespace Avalonia.ReactiveUI.UnitTests { public class TransitioningContentControlTest { - [Fact] - public void Transitioning_Control_Should_Derive_Template_From_Content_Control() - { - var target = new TransitioningContentControl(); - var stylable = (IStyledElement)target; - Assert.Equal(typeof(ContentControl),stylable.StyleKey); - } - [Fact] public void Transitioning_Control_Template_Should_Be_Instantiated() { From 9377ce2a8fa630de33373d8beda3392d2e1dcb06 Mon Sep 17 00:00:00 2001 From: Steve Date: Sun, 7 Aug 2022 15:23:51 +0900 Subject: [PATCH 17/22] Update Visual.cs --- src/Avalonia.Base/Visual.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Avalonia.Base/Visual.cs b/src/Avalonia.Base/Visual.cs index fbc940114a..8feba116f0 100644 --- a/src/Avalonia.Base/Visual.cs +++ b/src/Avalonia.Base/Visual.cs @@ -667,14 +667,8 @@ namespace Avalonia if (_visualParent is IRenderRoot || _visualParent?.IsAttachedToVisualTree == true) { - var root = this.FindAncestorOfType(); - if (root is null) - { - Logger.TryGet(LogEventLevel.Error, "Visual")?.Log("Visual", - "Visual is atached to visual tree but root could not be found."); - return; - } - + var root = this.FindAncestorOfType() ?? + throw new AvaloniaInternalException("Visual is atached to visual tree but root could not be found."); var e = new VisualTreeAttachmentEventArgs(_visualParent, root); OnAttachedToVisualTreeCore(e); } From c0f4e725c9b9ef56b3cda611941a6498b25c2cf5 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sun, 7 Aug 2022 03:27:15 -0400 Subject: [PATCH 18/22] Disable hardcoded FPS --- .../Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index 3484ea2317..dc74214170 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -86,7 +86,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform public IRenderer CreateRenderer(IRenderRoot root) => AndroidPlatform.Options.UseCompositor - ? new CompositingRenderer(root, AndroidPlatform.Compositor) { DrawFps = true } + ? new CompositingRenderer(root, AndroidPlatform.Compositor) : AndroidPlatform.Options.UseDeferredRendering ? new DeferredRenderer(root, AvaloniaLocator.Current.GetRequiredService()) { RenderOnlyOnRenderThread = true } : new ImmediateRenderer(root); From f314abd8abd719e014370f77d7f2cf1608231b73 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Tue, 9 Aug 2022 03:19:05 -0400 Subject: [PATCH 19/22] Fix android options initalization order --- src/Android/Avalonia.Android/AndroidPlatform.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Android/Avalonia.Android/AndroidPlatform.cs b/src/Android/Avalonia.Android/AndroidPlatform.cs index 89444dea10..ed5b46d398 100644 --- a/src/Android/Avalonia.Android/AndroidPlatform.cs +++ b/src/Android/Avalonia.Android/AndroidPlatform.cs @@ -17,10 +17,8 @@ namespace Avalonia { public static T UseAndroid(this T builder) where T : AppBuilderBase, new() { - var options = AvaloniaLocator.Current.GetService() ?? new AndroidPlatformOptions(); - return builder - .UseWindowingSubsystem(() => AndroidPlatform.Initialize(options), "Android") + .UseWindowingSubsystem(() => AndroidPlatform.Initialize(), "Android") .UseSkia(); } } @@ -45,9 +43,9 @@ namespace Avalonia.Android internal static Compositor Compositor { get; private set; } - public static void Initialize(AndroidPlatformOptions options) + public static void Initialize() { - Options = options; + Options = AvaloniaLocator.Current.GetService() ?? new AndroidPlatformOptions(); AvaloniaLocator.CurrentMutable .Bind().ToTransient() @@ -61,12 +59,12 @@ namespace Avalonia.Android .Bind().ToConstant(new RenderLoop()) .Bind().ToSingleton(); - if (options.UseGpu) + if (Options.UseGpu) { EglPlatformOpenGlInterface.TryInitialize(); } - if (options.UseCompositor) + if (Options.UseCompositor) { Compositor = new Compositor( AvaloniaLocator.Current.GetRequiredService(), From a88451c650d4f3d130d9c743a4ac19725c72f122 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Tue, 9 Aug 2022 03:19:15 -0400 Subject: [PATCH 20/22] Reset render target when it's corrupted --- .../Composition/Server/ServerCompositionTarget.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs index c20594aaca..5c1ac0312c 100644 --- a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs +++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs @@ -78,6 +78,13 @@ namespace Avalonia.Rendering.Composition.Server if (Root == null) return; + + if ((_renderTarget as IRenderTargetWithCorruptionInfo)?.IsCorrupted == true) + { + _renderTarget!.Dispose(); + _renderTarget = null; + } + _renderTarget ??= _renderTargetFactory(); Compositor.UpdateServerTime(); From 6054fa98f117d3b64adf70ae2c09767a0662af3b Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 9 Aug 2022 17:48:44 +0100 Subject: [PATCH 21/22] fix reliability issue in osx window state test. --- tests/Avalonia.IntegrationTests.Appium/WindowTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index 2b10c302bc..5afcb7cf43 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -92,7 +92,8 @@ namespace Avalonia.IntegrationTests.Appium Assert.True(clientSize.Width >= current.ScreenRect.Width); Assert.True(clientSize.Height >= current.ScreenRect.Height); - windowState.Click(); + windowState.SendClick(); + _session.FindElementByName("Normal").SendClick(); current = GetWindowInfo(); From 3e3661a2d423ac40b020f697698403c8e384b795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro?= Date: Tue, 9 Aug 2022 18:00:10 +0100 Subject: [PATCH 22/22] Removed outdated comment in PR template. --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 46e8665945..2f63750cdc 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -21,7 +21,7 @@ - [ ] Consider submitting a PR to https://github.com/AvaloniaUI/Documentation with user documentation ## Breaking changes - + ## Obsoletions / Deprecations