From 5437f8a76e1654d5f67d5d102497a43799d9cc69 Mon Sep 17 00:00:00 2001 From: nicola36631 Date: Sat, 1 Apr 2023 11:44:12 +0200 Subject: [PATCH 001/219] Added PageUp and PageDown KeyGestures --- .../Input/Platform/PlatformHotkeyConfiguration.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs b/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs index b87ca5eded..1bd54e37ea 100644 --- a/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs +++ b/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs @@ -85,6 +85,14 @@ namespace Avalonia.Input.Platform { new KeyGesture(Key.Left, KeyModifiers.Alt) }; + PageUp = new List + { + new KeyGesture(Key.PageUp) + }; + PageDown = new List + { + new KeyGesture(Key.PageDown) + }; } public KeyModifiers CommandModifiers { get; set; } @@ -106,5 +114,7 @@ namespace Avalonia.Input.Platform public List MoveCursorToTheEndOfDocumentWithSelection { get; set; } public List OpenContextMenu { get; set; } public List Back { get; set; } + public List PageUp { get; set; } + public List PageDown { get; set; } } } From e635d900ff80ee2bcc81eabd9dcbad83e88a87b8 Mon Sep 17 00:00:00 2001 From: nicola36631 Date: Sun, 2 Apr 2023 14:36:44 +0200 Subject: [PATCH 002/219] Added PageRight and PageLeft Keygestures in PlatformHotkeyConfiguration --- .../Input/Platform/PlatformHotkeyConfiguration.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs b/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs index 1bd54e37ea..23950c2a71 100644 --- a/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs +++ b/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs @@ -85,6 +85,14 @@ namespace Avalonia.Input.Platform { new KeyGesture(Key.Left, KeyModifiers.Alt) }; + PageLeft = new List + { + new KeyGesture(Key.PageUp, KeyModifiers.Shift) + }; + PageRight = new List + { + new KeyGesture(Key.PageDown, KeyModifiers.Shift) + }; PageUp = new List { new KeyGesture(Key.PageUp) @@ -116,5 +124,7 @@ namespace Avalonia.Input.Platform public List Back { get; set; } public List PageUp { get; set; } public List PageDown { get; set; } + public List PageRight { get; set; } + public List PageLeft { get; set; } } } From 92ba4bc19c8fb36f574f74ba5067d619df045188 Mon Sep 17 00:00:00 2001 From: nicola36631 Date: Sun, 2 Apr 2023 14:39:56 +0200 Subject: [PATCH 003/219] Added PageLeft, PageRight, PageUp, PageDown handling in TextBox Added cases in OnKeyDown method and added FetchChildScrollViewer method to fetch the child ScrollViewer in the VisualChildren. --- src/Avalonia.Controls/TextBox.cs | 92 ++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 9bb68ba419..9c4be3a907 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -19,6 +19,7 @@ using Avalonia.Media.TextFormatting.Unicode; using Avalonia.Automation.Peers; using Avalonia.Threading; using Avalonia.Platform; +using Avalonia.Collections; namespace Avalonia.Controls { @@ -1240,6 +1241,34 @@ namespace Avalonia.Controls selection = true; handled = true; } + else if (Match(keymap.PageLeft)) + { + MovePageLeft(); + movement = true; + selection = false; + handled = true; + } + else if (Match(keymap.PageRight)) + { + MovePageRight(); + movement = true; + selection = false; + handled = true; + } + else if (Match(keymap.PageUp)) + { + MovePageUp(); + movement = true; + selection = false; + handled = true; + } + else if (Match(keymap.PageDown)) + { + MovePageDown(); + movement = true; + selection = false; + handled = true; + } else { bool hasWholeWordModifiers = modifiers.HasAllFlags(keymap.WholeWordTextActionModifiers); @@ -1755,6 +1784,69 @@ namespace Avalonia.Controls } } + private void MovePageRight() + { + ScrollViewer? childScrollviewer = FetchChildScrollViewer(10, 0, this.VisualChildren); + if (childScrollviewer == null) + { + return; + } + childScrollviewer.PageRight(); + } + + private void MovePageLeft() + { + ScrollViewer? childScrollviewer = FetchChildScrollViewer(10, 0, this.VisualChildren); + if (childScrollviewer == null) + { + return; + } + childScrollviewer.PageLeft(); + } + private void MovePageUp() + { + ScrollViewer? childScrollviewer = FetchChildScrollViewer(10, 0, this.VisualChildren); + if (childScrollviewer == null) + { + return; + } + childScrollviewer.PageUp(); + } + + private void MovePageDown() + { + ScrollViewer? childScrollviewer = FetchChildScrollViewer(10, 0, this.VisualChildren); + if (childScrollviewer == null) + { + return; + } + childScrollviewer.PageDown(); + } + + private ScrollViewer? FetchChildScrollViewer(in int maxSearchDepth, int currentSearchDepth, IAvaloniaList visualChildren) + { + foreach(Visual innerChild in visualChildren) + { + if(innerChild is ScrollViewer) + { + return (ScrollViewer?)innerChild; + } + else + { + if (currentSearchDepth < maxSearchDepth) + { + ScrollViewer? innerScrollViewer = FetchChildScrollViewer(maxSearchDepth, currentSearchDepth + 1, innerChild.VisualChildren); + if (innerScrollViewer != null) + { + return innerScrollViewer; + } + } + } + } + + return null; + } + /// /// Select all text in the TextBox /// From ca66c4d00db4d1b1ed2fc9c0c466626449978ed6 Mon Sep 17 00:00:00 2001 From: nicola36631 Date: Sat, 1 Apr 2023 11:44:12 +0200 Subject: [PATCH 004/219] Added PageUp and PageDown KeyGestures --- .../Input/Platform/PlatformHotkeyConfiguration.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs b/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs index b87ca5eded..1bd54e37ea 100644 --- a/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs +++ b/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs @@ -85,6 +85,14 @@ namespace Avalonia.Input.Platform { new KeyGesture(Key.Left, KeyModifiers.Alt) }; + PageUp = new List + { + new KeyGesture(Key.PageUp) + }; + PageDown = new List + { + new KeyGesture(Key.PageDown) + }; } public KeyModifiers CommandModifiers { get; set; } @@ -106,5 +114,7 @@ namespace Avalonia.Input.Platform public List MoveCursorToTheEndOfDocumentWithSelection { get; set; } public List OpenContextMenu { get; set; } public List Back { get; set; } + public List PageUp { get; set; } + public List PageDown { get; set; } } } From 01cbf9790355e5ec909006b31811131b0ae086c5 Mon Sep 17 00:00:00 2001 From: nicola36631 Date: Sun, 2 Apr 2023 14:36:44 +0200 Subject: [PATCH 005/219] Added PageRight and PageLeft Keygestures in PlatformHotkeyConfiguration --- .../Input/Platform/PlatformHotkeyConfiguration.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs b/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs index 1bd54e37ea..23950c2a71 100644 --- a/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs +++ b/src/Avalonia.Base/Input/Platform/PlatformHotkeyConfiguration.cs @@ -85,6 +85,14 @@ namespace Avalonia.Input.Platform { new KeyGesture(Key.Left, KeyModifiers.Alt) }; + PageLeft = new List + { + new KeyGesture(Key.PageUp, KeyModifiers.Shift) + }; + PageRight = new List + { + new KeyGesture(Key.PageDown, KeyModifiers.Shift) + }; PageUp = new List { new KeyGesture(Key.PageUp) @@ -116,5 +124,7 @@ namespace Avalonia.Input.Platform public List Back { get; set; } public List PageUp { get; set; } public List PageDown { get; set; } + public List PageRight { get; set; } + public List PageLeft { get; set; } } } From d25b9a4f88ed28267e28e5dc4d0531563a320566 Mon Sep 17 00:00:00 2001 From: nicola36631 Date: Sun, 2 Apr 2023 14:39:56 +0200 Subject: [PATCH 006/219] Added PageLeft, PageRight, PageUp, PageDown handling in TextBox Added cases in OnKeyDown method and added FetchChildScrollViewer method to fetch the child ScrollViewer in the VisualChildren. --- src/Avalonia.Controls/TextBox.cs | 92 ++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 9bb68ba419..9c4be3a907 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -19,6 +19,7 @@ using Avalonia.Media.TextFormatting.Unicode; using Avalonia.Automation.Peers; using Avalonia.Threading; using Avalonia.Platform; +using Avalonia.Collections; namespace Avalonia.Controls { @@ -1240,6 +1241,34 @@ namespace Avalonia.Controls selection = true; handled = true; } + else if (Match(keymap.PageLeft)) + { + MovePageLeft(); + movement = true; + selection = false; + handled = true; + } + else if (Match(keymap.PageRight)) + { + MovePageRight(); + movement = true; + selection = false; + handled = true; + } + else if (Match(keymap.PageUp)) + { + MovePageUp(); + movement = true; + selection = false; + handled = true; + } + else if (Match(keymap.PageDown)) + { + MovePageDown(); + movement = true; + selection = false; + handled = true; + } else { bool hasWholeWordModifiers = modifiers.HasAllFlags(keymap.WholeWordTextActionModifiers); @@ -1755,6 +1784,69 @@ namespace Avalonia.Controls } } + private void MovePageRight() + { + ScrollViewer? childScrollviewer = FetchChildScrollViewer(10, 0, this.VisualChildren); + if (childScrollviewer == null) + { + return; + } + childScrollviewer.PageRight(); + } + + private void MovePageLeft() + { + ScrollViewer? childScrollviewer = FetchChildScrollViewer(10, 0, this.VisualChildren); + if (childScrollviewer == null) + { + return; + } + childScrollviewer.PageLeft(); + } + private void MovePageUp() + { + ScrollViewer? childScrollviewer = FetchChildScrollViewer(10, 0, this.VisualChildren); + if (childScrollviewer == null) + { + return; + } + childScrollviewer.PageUp(); + } + + private void MovePageDown() + { + ScrollViewer? childScrollviewer = FetchChildScrollViewer(10, 0, this.VisualChildren); + if (childScrollviewer == null) + { + return; + } + childScrollviewer.PageDown(); + } + + private ScrollViewer? FetchChildScrollViewer(in int maxSearchDepth, int currentSearchDepth, IAvaloniaList visualChildren) + { + foreach(Visual innerChild in visualChildren) + { + if(innerChild is ScrollViewer) + { + return (ScrollViewer?)innerChild; + } + else + { + if (currentSearchDepth < maxSearchDepth) + { + ScrollViewer? innerScrollViewer = FetchChildScrollViewer(maxSearchDepth, currentSearchDepth + 1, innerChild.VisualChildren); + if (innerScrollViewer != null) + { + return innerScrollViewer; + } + } + } + } + + return null; + } + /// /// Select all text in the TextBox /// From aee66ef47117800ab23add607fda27b53658e7d8 Mon Sep 17 00:00:00 2001 From: malaguenha Date: Sat, 13 May 2023 15:02:56 +0900 Subject: [PATCH 007/219] Commit to solve the issue #11353, IME, Windows - buffer overrun? when entering long composition string --- src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index 7510b48270..0fdc103d3a 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1902,7 +1902,7 @@ namespace Avalonia.Win32.Interop if (bufferLength > 0) { - var buffer = bufferLength <= 64 ? stackalloc byte[bufferLength] : new byte[bufferLength]; + var buffer = bufferLength <= 64 ? stackalloc byte[bufferLength + 8] : new byte[bufferLength]; fixed (byte* bufferPtr = buffer) { From 0479dffaa5735fa40a0e041a6781443afc026f9a Mon Sep 17 00:00:00 2001 From: malaguenha Date: Sat, 13 May 2023 20:39:12 +0900 Subject: [PATCH 008/219] Fix using Encoding.Unicode.GetString --- src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index 0fdc103d3a..af47890b70 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1909,7 +1909,7 @@ namespace Avalonia.Win32.Interop var result = ImmGetCompositionString(hIMC, dwIndex, (IntPtr)bufferPtr, (uint)bufferLength); if (result >= 0) { - return Marshal.PtrToStringUni((IntPtr)bufferPtr); + return Encoding.Unicode.GetString(buffer.ToArray()); } } } From f90971204be74a4f79ea54b2436f8994b48995d6 Mon Sep 17 00:00:00 2001 From: malaguenha Date: Sat, 13 May 2023 20:46:49 +0900 Subject: [PATCH 009/219] No extra buffer --- src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index af47890b70..d5eff1611c 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1902,7 +1902,7 @@ namespace Avalonia.Win32.Interop if (bufferLength > 0) { - var buffer = bufferLength <= 64 ? stackalloc byte[bufferLength + 8] : new byte[bufferLength]; + var buffer = bufferLength <= 64 ? stackalloc byte[bufferLength] : new byte[bufferLength]; fixed (byte* bufferPtr = buffer) { From dd1cffcfdaf30de8a725f78efbf53f4ed9351657 Mon Sep 17 00:00:00 2001 From: malaguenha Date: Sat, 13 May 2023 22:28:16 +0900 Subject: [PATCH 010/219] Fixed to use pointer not array --- src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index d5eff1611c..f26c783e47 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1909,7 +1909,7 @@ namespace Avalonia.Win32.Interop var result = ImmGetCompositionString(hIMC, dwIndex, (IntPtr)bufferPtr, (uint)bufferLength); if (result >= 0) { - return Encoding.Unicode.GetString(buffer.ToArray()); + return Encoding.Unicode.GetString(bufferPtr, bufferLength); } } } From 4314a8756868b41ff449c4c6742bccb8cf77efb7 Mon Sep 17 00:00:00 2001 From: malaguenha Date: Sat, 13 May 2023 22:49:34 +0900 Subject: [PATCH 011/219] Just one more correction --- src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index f26c783e47..39363beae3 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1909,7 +1909,7 @@ namespace Avalonia.Win32.Interop var result = ImmGetCompositionString(hIMC, dwIndex, (IntPtr)bufferPtr, (uint)bufferLength); if (result >= 0) { - return Encoding.Unicode.GetString(bufferPtr, bufferLength); + return Encoding.Unicode.GetString(bufferPtr, result); } } } From 5c74e2c32bc401cc26b8d80f61e7e57ea4804c34 Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 13 May 2023 14:26:35 -0400 Subject: [PATCH 012/219] Add RangeBase.ValueChanged event --- .../RoutedPropertyChangedEventArgs.cs | 46 +++++++++++++++++++ src/Avalonia.Controls/Primitives/RangeBase.cs | 37 ++++++++++++++- 2 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 src/Avalonia.Base/Interactivity/RoutedPropertyChangedEventArgs.cs diff --git a/src/Avalonia.Base/Interactivity/RoutedPropertyChangedEventArgs.cs b/src/Avalonia.Base/Interactivity/RoutedPropertyChangedEventArgs.cs new file mode 100644 index 0000000000..22134b518d --- /dev/null +++ b/src/Avalonia.Base/Interactivity/RoutedPropertyChangedEventArgs.cs @@ -0,0 +1,46 @@ +namespace Avalonia.Interactivity +{ + /// + /// Provides both old and new property values with a routed event. + /// + /// The type of values. + public class RoutedPropertyChangedEventArgs : RoutedEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The old property value. + /// The new property value. + /// The routed event associated with these event args. + public RoutedPropertyChangedEventArgs(T oldValue, T newValue, RoutedEvent? routedEvent) + : base(routedEvent) + { + OldValue = oldValue; + NewValue = newValue; + } + + /// + /// Initializes a new instance of the class. + /// + /// The old property value. + /// The new property value. + /// The routed event associated with these event args. + /// The source object that raised the routed event. + public RoutedPropertyChangedEventArgs(T oldValue, T newValue, RoutedEvent? routedEvent, object? source) + : base(routedEvent, source) + { + OldValue = oldValue; + NewValue = newValue; + } + + /// + /// Gets the old value of the property. + /// + public T OldValue { get; init; } + + /// + /// Gets the new value of the property. + /// + public T NewValue { get; init; } + } +} diff --git a/src/Avalonia.Controls/Primitives/RangeBase.cs b/src/Avalonia.Controls/Primitives/RangeBase.cs index fd9de47236..ebf7879412 100644 --- a/src/Avalonia.Controls/Primitives/RangeBase.cs +++ b/src/Avalonia.Controls/Primitives/RangeBase.cs @@ -1,5 +1,6 @@ using System; using Avalonia.Data; +using Avalonia.Interactivity; using Avalonia.Utilities; namespace Avalonia.Controls.Primitives @@ -42,7 +43,23 @@ namespace Avalonia.Controls.Primitives AvaloniaProperty.Register(nameof(LargeChange), 10); /// - /// Gets or sets the minimum value. + /// Defines the event. + /// + public static readonly RoutedEvent> ValueChangedEvent = + RoutedEvent.Register>( + nameof(ValueChanged), RoutingStrategies.Bubble); + + /// + /// Occurs when the property changes. + /// + public event EventHandler>? ValueChanged + { + add => AddHandler(ValueChangedEvent, value); + remove => RemoveHandler(ValueChangedEvent, value); + } + + /// + /// Gets or sets the minimum possible value. /// public double Minimum { @@ -65,7 +82,7 @@ namespace Avalonia.Controls.Primitives } /// - /// Gets or sets the maximum value. + /// Gets or sets the maximum possible value. /// public double Maximum { @@ -104,18 +121,25 @@ namespace Avalonia.Controls.Primitives : sender.GetValue(ValueProperty); } + /// + /// Gets or sets the small increment value added or subtracted from the . + /// public double SmallChange { get => GetValue(SmallChangeProperty); set => SetValue(SmallChangeProperty, value); } + /// + /// Gets or sets the large increment value added or subtracted from the . + /// public double LargeChange { get => GetValue(LargeChangeProperty); set => SetValue(LargeChangeProperty, value); } + /// protected override void OnInitialized() { base.OnInitialized(); @@ -124,6 +148,7 @@ namespace Avalonia.Controls.Primitives CoerceValue(ValueProperty); } + /// protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); @@ -136,6 +161,14 @@ namespace Avalonia.Controls.Primitives { OnMaximumChanged(); } + else if (change.Property == ValueProperty) + { + var valueChangedEventArgs = new RoutedPropertyChangedEventArgs( + change.GetOldValue(), + change.GetNewValue(), + ValueChangedEvent); + RaiseEvent(valueChangedEventArgs); + } } /// From d9b11b0725552e87c908a42bc274be5723a7881b Mon Sep 17 00:00:00 2001 From: Tom Edwards Date: Sat, 13 May 2023 15:09:18 +0200 Subject: [PATCH 013/219] Added tests and control catalog demo for live changes to TabItem.ContentTemplate. The next commit will fix both. --- .../ControlCatalog/Pages/TabControlPage.xaml | 29 ++++++++++++++++--- .../TabControlTests.cs | 21 ++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/samples/ControlCatalog/Pages/TabControlPage.xaml b/samples/ControlCatalog/Pages/TabControlPage.xaml index 3a2464e9fd..1faa74c1ce 100644 --- a/samples/ControlCatalog/Pages/TabControlPage.xaml +++ b/samples/ControlCatalog/Pages/TabControlPage.xaml @@ -4,7 +4,27 @@ xmlns="https://github.com/avaloniaui" xmlns:viewModels="using:ControlCatalog.ViewModels" x:DataType="viewModels:TabControlPageViewModel"> - + + + + + + - + - + - - - - - - - - + + + + + + + + - @@ -239,16 +238,17 @@ + - - - - + + + + diff --git a/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml b/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml index a5b0649655..bd5151ad1a 100644 --- a/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml @@ -49,7 +49,7 @@ TargetType="dialogs:ManagedFileChooser"> - + - - + + @@ -136,7 +136,6 @@ DockPanel.Dock="Top"> - @@ -144,19 +143,45 @@ + - - - - + + - - + + + - - + + + + + - @@ -177,19 +201,20 @@ + - - - - + From 81084454f4aef7d5ea6b9bfe8ad0491b44071cf7 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 23 May 2023 16:02:54 +0200 Subject: [PATCH 081/219] Added failing tests for #11484. --- .../AvaloniaObjectTests_Coercion.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Coercion.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Coercion.cs index 0d0456dbda..42720cbb4c 100644 --- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Coercion.cs +++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Coercion.cs @@ -124,6 +124,19 @@ namespace Avalonia.Base.UnitTests Assert.Equal(2, target.CoreChanges.Count); } + [Fact] + public void CoerceValue_Calls_Coerce_Callback_Only_Once() + { + var target = new Class1 { Foo = 99 }; + + target.MaxFoo = 50; + + target.CoerceFooInvocations.Clear(); + target.CoerceValue(Class1.FooProperty); + + Assert.Equal(new[] { 99 }, target.CoerceFooInvocations); + } + [Fact] public void Coerced_Value_Can_Be_Restored_If_Limit_Changed() { @@ -218,6 +231,18 @@ namespace Avalonia.Base.UnitTests Assert.Equal(1, raised); } + [Fact] + public void Default_Value_Is_Coerced_Only_Once() + { + var target = new Class1(); + + target.MinFoo = 20; + target.CoerceFooInvocations.Clear(); + target.CoerceValue(Class1.FooProperty); + + Assert.Equal(new[] { 11 }, target.CoerceFooInvocations); + } + [Fact] public void ClearValue_Respects_Coerced_Default_Value() { @@ -338,10 +363,12 @@ namespace Avalonia.Base.UnitTests public int MinFoo { get; set; } = 0; public int MaxFoo { get; set; } = 100; + public List CoerceFooInvocations { get; } = new(); public List CoreChanges { get; } = new(); public static int CoerceFoo(AvaloniaObject instance, int value) { + (instance as Class1)?.CoerceFooInvocations.Add(value); return instance is Class1 o ? Math.Clamp(value, o.MinFoo, o.MaxFoo) : Math.Clamp(value, 0, 100); From 531f059c76f9d3a937fa3afcf6d21eea430c3399 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 23 May 2023 16:10:03 +0200 Subject: [PATCH 082/219] Only call coerce callback a single time. --- src/Avalonia.Base/PropertyStore/EffectiveValue`1.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Base/PropertyStore/EffectiveValue`1.cs b/src/Avalonia.Base/PropertyStore/EffectiveValue`1.cs index b725326855..4518289335 100644 --- a/src/Avalonia.Base/PropertyStore/EffectiveValue`1.cs +++ b/src/Avalonia.Base/PropertyStore/EffectiveValue`1.cs @@ -208,7 +208,7 @@ namespace Avalonia.PropertyStore IsOverridenCurrentValue = isOverriddenCurrentValue; IsCoercedDefaultValue = isCoercedDefaultValue; - if (_uncommon?._coerce is { } coerce) + if (!isCoercedDefaultValue && _uncommon?._coerce is { } coerce) v = coerce(owner.Owner, value); if (priority <= Priority) @@ -262,7 +262,8 @@ namespace Avalonia.PropertyStore if (_uncommon?._coerce is { } coerce) { v = coerce(owner.Owner, value); - bv = coerce(owner.Owner, baseValue); + if (priority != basePriority) + bv = coerce(owner.Owner, baseValue); } if (!EqualityComparer.Default.Equals(Value, v)) From 1d0ac58755f68a973913e8a17387f2d86616411b Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 23 May 2023 19:54:51 +0100 Subject: [PATCH 083/219] add repro for popup transparency pointer event issue. --- .../ControlCatalog/Pages/CheckBoxPage.xaml | 43 +++++++++---------- .../ControlCatalog/Pages/CheckBoxPage.xaml.cs | 15 ++++++- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/samples/ControlCatalog/Pages/CheckBoxPage.xaml b/samples/ControlCatalog/Pages/CheckBoxPage.xaml index 2f60fc5dae..78a8ff5550 100644 --- a/samples/ControlCatalog/Pages/CheckBoxPage.xaml +++ b/samples/ControlCatalog/Pages/CheckBoxPage.xaml @@ -1,28 +1,25 @@ - - A check box control + x:Class="ControlCatalog.Pages.CheckBoxPage" Background="White"> + + + + + + + + - - - _Unchecked - _Checked - _Indeterminate - Disabled - - - Three State: Unchecked - Three State: Checked - Three State: Indeterminate - Three State: Disabled + + + + + + Popup Text + + + - - + + diff --git a/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs b/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs index 5027c94f5e..c3066c55f9 100644 --- a/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs +++ b/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs @@ -1,18 +1,31 @@ using Avalonia.Controls; +using Avalonia.Input; using Avalonia.Markup.Xaml; namespace ControlCatalog.Pages { - public class CheckBoxPage : UserControl + public partial class CheckBoxPage : UserControl { + private TextBlock myTb; + public CheckBoxPage() { this.InitializeComponent(); + + myTb = this.FindControl("myTb"); + } private void InitializeComponent() { AvaloniaXamlLoader.Load(this); } + + protected override void OnPointerMoved(PointerEventArgs e) + { + base.OnPointerMoved(e); + + myTb.Text = e.GetPosition(this).ToString(); + } } } From a9e16dc89069f6baa5b4aa24fec3af942c542a2a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 23 May 2023 20:00:06 +0100 Subject: [PATCH 084/219] update repro --- samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs | 3 ++- src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs b/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs index c3066c55f9..60e75561e1 100644 --- a/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs +++ b/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs @@ -7,6 +7,7 @@ namespace ControlCatalog.Pages public partial class CheckBoxPage : UserControl { private TextBlock myTb; + private int count; public CheckBoxPage() { @@ -25,7 +26,7 @@ namespace ControlCatalog.Pages { base.OnPointerMoved(e); - myTb.Text = e.GetPosition(this).ToString(); + myTb.Text = e.GetPosition(this).ToString() + ", " + count++; } } } diff --git a/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml b/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml index 5a924830b1..16be9630c1 100644 --- a/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml @@ -13,6 +13,7 @@ + + From 7aa531530be53bd70c6a33d64d951097838e6593 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 23 May 2023 20:25:55 +0100 Subject: [PATCH 085/219] implent popup routing events to parent toplevel. --- src/Avalonia.Base/Input/PointerEventArgs.cs | 11 ++++++++++- .../Controls/PopupRoot.xaml | 18 +++++++++--------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/Avalonia.Base/Input/PointerEventArgs.cs b/src/Avalonia.Base/Input/PointerEventArgs.cs index 7f82199b56..0556d8702f 100644 --- a/src/Avalonia.Base/Input/PointerEventArgs.cs +++ b/src/Avalonia.Base/Input/PointerEventArgs.cs @@ -70,7 +70,16 @@ namespace Avalonia.Input if (relativeTo == null) return pt; - return pt * _rootVisual.TransformToVisual(relativeTo) ?? default; + if (!ReferenceEquals(_rootVisual, relativeTo.VisualRoot)) + { + var screenPt = _rootVisual.PointToScreen(pt); + + return relativeTo.PointToClient(screenPt); + } + else + { + return pt * _rootVisual.TransformToVisual(relativeTo) ?? default; + } } /// diff --git a/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml b/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml index 16be9630c1..567c9b72e7 100644 --- a/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml @@ -13,15 +13,15 @@ - - - - - + + + + + From d064ad4e6ab1dd12638b1b249953403a0a574512 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 23 May 2023 20:34:04 +0100 Subject: [PATCH 086/219] transform to visual. --- src/Avalonia.Base/Input/PointerEventArgs.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Avalonia.Base/Input/PointerEventArgs.cs b/src/Avalonia.Base/Input/PointerEventArgs.cs index 0556d8702f..a53791e414 100644 --- a/src/Avalonia.Base/Input/PointerEventArgs.cs +++ b/src/Avalonia.Base/Input/PointerEventArgs.cs @@ -70,16 +70,14 @@ namespace Avalonia.Input if (relativeTo == null) return pt; - if (!ReferenceEquals(_rootVisual, relativeTo.VisualRoot)) + if (!ReferenceEquals(_rootVisual, relativeTo.VisualRoot) && relativeTo.VisualRoot is Visual v) { var screenPt = _rootVisual.PointToScreen(pt); - return relativeTo.PointToClient(screenPt); - } - else - { - return pt * _rootVisual.TransformToVisual(relativeTo) ?? default; + return relativeTo.PointToClient(screenPt) * v.TransformToVisual(relativeTo) ?? default; } + + return pt * _rootVisual.TransformToVisual(relativeTo) ?? default; } /// From ba8ddd04189f95ec35711019d1c90f5c605a649b Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 23 May 2023 20:37:14 +0100 Subject: [PATCH 087/219] no need for transformtovisual. --- src/Avalonia.Base/Input/PointerEventArgs.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Base/Input/PointerEventArgs.cs b/src/Avalonia.Base/Input/PointerEventArgs.cs index a53791e414..5db9266d06 100644 --- a/src/Avalonia.Base/Input/PointerEventArgs.cs +++ b/src/Avalonia.Base/Input/PointerEventArgs.cs @@ -74,7 +74,7 @@ namespace Avalonia.Input { var screenPt = _rootVisual.PointToScreen(pt); - return relativeTo.PointToClient(screenPt) * v.TransformToVisual(relativeTo) ?? default; + return relativeTo.PointToClient(screenPt); } return pt * _rootVisual.TransformToVisual(relativeTo) ?? default; From d24903957eb27ca89670c28e5f4d34b8e123e58f Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 23 May 2023 20:40:25 +0100 Subject: [PATCH 088/219] revert control catalog changes. --- .../ControlCatalog/Pages/CheckBoxPage.xaml | 43 ++++++++++--------- .../ControlCatalog/Pages/CheckBoxPage.xaml.cs | 16 +------ 2 files changed, 24 insertions(+), 35 deletions(-) diff --git a/samples/ControlCatalog/Pages/CheckBoxPage.xaml b/samples/ControlCatalog/Pages/CheckBoxPage.xaml index 78a8ff5550..2f60fc5dae 100644 --- a/samples/ControlCatalog/Pages/CheckBoxPage.xaml +++ b/samples/ControlCatalog/Pages/CheckBoxPage.xaml @@ -1,25 +1,28 @@ - - - - - - - - + x:Class="ControlCatalog.Pages.CheckBoxPage"> + + A check box control - - - - - - Popup Text - - - + + + _Unchecked + _Checked + _Indeterminate + Disabled + + + Three State: Unchecked + Three State: Checked + Three State: Indeterminate + Three State: Disabled - - + + diff --git a/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs b/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs index 60e75561e1..5027c94f5e 100644 --- a/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs +++ b/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs @@ -1,32 +1,18 @@ using Avalonia.Controls; -using Avalonia.Input; using Avalonia.Markup.Xaml; namespace ControlCatalog.Pages { - public partial class CheckBoxPage : UserControl + public class CheckBoxPage : UserControl { - private TextBlock myTb; - private int count; - public CheckBoxPage() { this.InitializeComponent(); - - myTb = this.FindControl("myTb"); - } private void InitializeComponent() { AvaloniaXamlLoader.Load(this); } - - protected override void OnPointerMoved(PointerEventArgs e) - { - base.OnPointerMoved(e); - - myTb.Text = e.GetPosition(this).ToString() + ", " + count++; - } } } From b2d780506036965465f484a29624fb8919f0d6e2 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 24 May 2023 00:08:20 +0200 Subject: [PATCH 089/219] Replace WindowTransparencyLevel enum with list of structs The transparency level is not yet communicated to the backends though. Co-Authored-By: Max Katz --- samples/ControlCatalog/MainView.xaml.cs | 2 +- .../IntegrationTestApp/MainWindow.axaml.cs | 2 +- .../Platform/SkiaPlatform/TopLevelImpl.cs | 118 +++++++++--------- .../ExperimentalAcrylicBorder.cs | 22 +--- src/Avalonia.Controls/TopLevel.cs | 38 ++---- .../WindowTransparencyLevel.cs | 78 +++++++----- src/Avalonia.Native/WindowImplBase.cs | 6 +- src/Avalonia.X11/TransparencyHelper.cs | 8 +- .../AvaloniaXamlIlLanguageParseIntrinsics.cs | 16 ++- .../AvaloniaXamlIlWellKnownTypes.cs | 4 + src/Windows/Avalonia.Win32/TrayIconImpl.cs | 2 +- src/Windows/Avalonia.Win32/WindowImpl.cs | 54 ++++---- .../Xaml/WindowTests.cs | 26 ++++ 13 files changed, 211 insertions(+), 165 deletions(-) create mode 100644 tests/Avalonia.Markup.Xaml.UnitTests/Xaml/WindowTests.cs diff --git a/samples/ControlCatalog/MainView.xaml.cs b/samples/ControlCatalog/MainView.xaml.cs index 9c511f9eb0..5e33952c68 100644 --- a/samples/ControlCatalog/MainView.xaml.cs +++ b/samples/ControlCatalog/MainView.xaml.cs @@ -83,7 +83,7 @@ namespace ControlCatalog if (transparencyLevels.SelectedItem is WindowTransparencyLevel selected) { var topLevel = (TopLevel)this.GetVisualRoot()!; - topLevel.TransparencyLevelHint = selected; + topLevel.TransparencyLevelHint = new[] { selected }; if (selected != WindowTransparencyLevel.None) { diff --git a/samples/IntegrationTestApp/MainWindow.axaml.cs b/samples/IntegrationTestApp/MainWindow.axaml.cs index 7130b3602a..689cfcb65d 100644 --- a/samples/IntegrationTestApp/MainWindow.axaml.cs +++ b/samples/IntegrationTestApp/MainWindow.axaml.cs @@ -136,7 +136,7 @@ namespace IntegrationTestApp Name = "TransparentWindow", SystemDecorations = SystemDecorations.None, Background = Brushes.Transparent, - TransparencyLevelHint = WindowTransparencyLevel.Transparent, + TransparencyLevelHint = new[] { WindowTransparencyLevel.Transparent }, WindowStartupLocation = WindowStartupLocation.CenterOwner, Width = 200, Height = 200, diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index fae1aacf61..609b6cd519 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -307,78 +307,80 @@ namespace Avalonia.Android.Platform.SkiaPlatform bool isAboveR = Build.VERSION.SdkInt > BuildVersionCodes.R; if (_view.Context is AvaloniaMainActivity activity) { - switch (transparencyLevel) + if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur || + transparencyLevel == WindowTransparencyLevel.Mica || + transparencyLevel == WindowTransparencyLevel.None) { - case WindowTransparencyLevel.AcrylicBlur: - case WindowTransparencyLevel.ForceAcrylicBlur: - case WindowTransparencyLevel.Mica: - case WindowTransparencyLevel.None: - if (!isBelowR) + if (!isBelowR) + { + activity.SetTranslucent(false); + } + if (isAboveR) + { + activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); + + var attr = activity.Window?.Attributes; + if (attr != null) { - activity.SetTranslucent(false); - } - if (isAboveR) - { - activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); - - var attr = activity.Window?.Attributes; - if (attr != null) - { - attr.BlurBehindRadius = 0; + attr.BlurBehindRadius = 0; - activity.Window.Attributes = attr; - } + activity.Window.Attributes = attr; } - activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); + } + activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); - if(transparencyLevel != WindowTransparencyLevel.None) - { - return; - } - break; - case WindowTransparencyLevel.Transparent: - if (!isBelowR) - { - activity.SetTranslucent(true); - } - if (isAboveR) - { - activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); + if (transparencyLevel != WindowTransparencyLevel.None) + { + return; + } + } - var attr = activity.Window?.Attributes; - if (attr != null) - { - attr.BlurBehindRadius = 0; + if (transparencyLevel == WindowTransparencyLevel.Transparent) + { + if (!isBelowR) + { + activity.SetTranslucent(true); + } + if (isAboveR) + { + activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); + + var attr = activity.Window?.Attributes; + if (attr != null) + { + attr.BlurBehindRadius = 0; - activity.Window.Attributes = attr; - } + activity.Window.Attributes = attr; } - activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); - break; - case WindowTransparencyLevel.Blur: - if (isAboveR) - { - activity.SetTranslucent(true); - activity.Window?.AddFlags(WindowManagerFlags.BlurBehind); + } + activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); + } - var attr = activity.Window?.Attributes; - if (attr != null) - { - attr.BlurBehindRadius = 120; + if (transparencyLevel == WindowTransparencyLevel.Blur) + { + if (isAboveR) + { + activity.SetTranslucent(true); + activity.Window?.AddFlags(WindowManagerFlags.BlurBehind); - activity.Window.Attributes = attr; - } - activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); - } - else + var attr = activity.Window?.Attributes; + if (attr != null) { - activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); - activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); + attr.BlurBehindRadius = 120; - return; + activity.Window.Attributes = attr; } - break; + activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); + } + else + { + activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); + activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); + + return; + } } + TransparencyLevel = transparencyLevel; } } diff --git a/src/Avalonia.Controls/ExperimentalAcrylicBorder.cs b/src/Avalonia.Controls/ExperimentalAcrylicBorder.cs index bc17fe7237..be1a90258c 100644 --- a/src/Avalonia.Controls/ExperimentalAcrylicBorder.cs +++ b/src/Avalonia.Controls/ExperimentalAcrylicBorder.cs @@ -56,22 +56,12 @@ namespace Avalonia.Controls { if (tl.PlatformImpl is null) return; - - switch (x) - { - case WindowTransparencyLevel.Transparent: - case WindowTransparencyLevel.None: - Material.PlatformTransparencyCompensationLevel = tl.PlatformImpl.AcrylicCompensationLevels.TransparentLevel; - break; - - case WindowTransparencyLevel.Blur: - Material.PlatformTransparencyCompensationLevel = tl.PlatformImpl.AcrylicCompensationLevels.BlurLevel; - break; - - case WindowTransparencyLevel.AcrylicBlur: - Material.PlatformTransparencyCompensationLevel = tl.PlatformImpl.AcrylicCompensationLevels.AcrylicBlurLevel; - break; - } + if (x == WindowTransparencyLevel.Transparent || x == WindowTransparencyLevel.None) + Material.PlatformTransparencyCompensationLevel = tl.PlatformImpl.AcrylicCompensationLevels.TransparentLevel; + else if (x == WindowTransparencyLevel.Blur) + Material.PlatformTransparencyCompensationLevel = tl.PlatformImpl.AcrylicCompensationLevels.BlurLevel; + else if (x == WindowTransparencyLevel.AcrylicBlur) + Material.PlatformTransparencyCompensationLevel = tl.PlatformImpl.AcrylicCompensationLevels.AcrylicBlurLevel; }); UpdateMaterialSubscription(); } diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 98c96e4974..189dbe5e62 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using Avalonia.Reactive; @@ -22,6 +23,7 @@ using Avalonia.Utilities; using Avalonia.Input.Platform; using System.Linq; using System.Threading.Tasks; +using Avalonia.Metadata; namespace Avalonia.Controls { @@ -64,8 +66,8 @@ namespace Avalonia.Controls /// /// Defines the property. /// - public static readonly StyledProperty TransparencyLevelHintProperty = - AvaloniaProperty.Register(nameof(TransparencyLevelHint), WindowTransparencyLevel.None); + public static readonly StyledProperty> TransparencyLevelHintProperty = + AvaloniaProperty.Register>(nameof(TransparencyLevelHint), Array.Empty()); /// /// Defines the property. @@ -172,7 +174,7 @@ namespace Avalonia.Controls PlatformImpl = impl ?? throw new InvalidOperationException( "Could not create window implementation: maybe no windowing subsystem was initialized?"); - _actualTransparencyLevel = PlatformImpl.TransparencyLevel; + _actualTransparencyLevel = PlatformImpl.TransparencyLevel; dependencyResolver ??= AvaloniaLocator.Current; @@ -310,8 +312,11 @@ namespace Avalonia.Controls /// /// Gets or sets the that the TopLevel should use when possible. + /// Accepts multiple values which are applied in a fallback order. + /// For instance, with "Mica, Blur" Mica will be applied only on platforms where it is possible, + /// and Blur will be used on the rest of them. Default value is an empty array or "None". /// - public WindowTransparencyLevel TransparencyLevelHint + public IReadOnlyList TransparencyLevelHint { get { return GetValue(TransparencyLevelHintProperty); } set { SetValue(TransparencyLevelHintProperty, value); } @@ -518,8 +523,8 @@ namespace Avalonia.Controls { if (PlatformImpl != null) { - PlatformImpl.SetTransparencyLevelHint(change.GetNewValue()); - HandleTransparencyLevelChanged(PlatformImpl.TransparencyLevel); + ////PlatformImpl.SetTransparencyLevelHint( + //// change.GetNewValue>() ?? Array.Empty()); } } else if (change.Property == ActualThemeVariantProperty) @@ -610,27 +615,11 @@ namespace Avalonia.Controls ScalingChanged?.Invoke(this, EventArgs.Empty); } - private static bool TransparencyLevelsMatch (WindowTransparencyLevel requested, WindowTransparencyLevel received) - { - if(requested == received) - { - return true; - } - else if(requested >= WindowTransparencyLevel.Blur && received >= WindowTransparencyLevel.Blur) - { - return true; - } - - return false; - } - private void HandleTransparencyLevelChanged(WindowTransparencyLevel transparencyLevel) { - if(_transparencyFallbackBorder != null) + if (_transparencyFallbackBorder != null) { - if(transparencyLevel == WindowTransparencyLevel.None || - TransparencyLevelHint == WindowTransparencyLevel.None || - !TransparencyLevelsMatch(TransparencyLevelHint, transparencyLevel)) + if (transparencyLevel == WindowTransparencyLevel.None) { _transparencyFallbackBorder.Background = TransparencyBackgroundFallback; } @@ -660,7 +649,6 @@ namespace Avalonia.Controls return; _transparencyFallbackBorder = e.NameScope.Find("PART_TransparencyFallback"); - HandleTransparencyLevelChanged(PlatformImpl.TransparencyLevel); } diff --git a/src/Avalonia.Controls/WindowTransparencyLevel.cs b/src/Avalonia.Controls/WindowTransparencyLevel.cs index d463f74a0e..bce6e21e68 100644 --- a/src/Avalonia.Controls/WindowTransparencyLevel.cs +++ b/src/Avalonia.Controls/WindowTransparencyLevel.cs @@ -1,35 +1,51 @@ -namespace Avalonia.Controls +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace Avalonia.Controls; + +public readonly record struct WindowTransparencyLevel { - public enum WindowTransparencyLevel + private readonly string _value; + + private WindowTransparencyLevel(string value) { - /// - /// The window background is Black where nothing is drawn in the window. - /// - None, - - /// - /// The window background is Transparent where nothing is drawn in the window. - /// - Transparent, - - /// - /// The window background is a blur-behind where nothing is drawn in the window. - /// - Blur, - - /// - /// The window background is a blur-behind with a high blur radius. This level may fallback to Blur. - /// - AcrylicBlur, - - /// - /// Force acrylic on some incompatible versions of Windows 10. - /// - ForceAcrylicBlur, - - /// - /// The window background is based on desktop wallpaper tint with a blur. This will only work on Windows 11 - /// - Mica + _value = value; + } + + /// + /// The window background is Black where nothing is drawn in the window. + /// + public static WindowTransparencyLevel None { get; } = new(nameof(None)); + + /// + /// The window background is Transparent where nothing is drawn in the window. + /// + public static WindowTransparencyLevel Transparent { get; } = new(nameof(Transparent)); + + /// + /// The window background is a blur-behind where nothing is drawn in the window. + /// + public static WindowTransparencyLevel Blur { get; } = new(nameof(Blur)); + + /// + /// The window background is a blur-behind with a high blur radius. This level may fallback to Blur. + /// + public static WindowTransparencyLevel AcrylicBlur { get; } = new(nameof(AcrylicBlur)); + + /// + /// The window background is based on desktop wallpaper tint with a blur. This will only work on Windows 11 + /// + public static WindowTransparencyLevel Mica { get; } = new(nameof(Mica)); + + public override string ToString() + { + return _value; } } + +public class WindowTransparencyLevelCollection : ReadOnlyCollection +{ + public WindowTransparencyLevelCollection(IList list) : base(list) + { + } +} diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index b802b1db71..c065346377 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -489,8 +489,12 @@ namespace Avalonia.Native { if (TransparencyLevel != transparencyLevel) { - if (transparencyLevel > WindowTransparencyLevel.Transparent) + if (transparencyLevel == WindowTransparencyLevel.Blur || + transparencyLevel == WindowTransparencyLevel.AcrylicBlur || + transparencyLevel == WindowTransparencyLevel.Mica) + { transparencyLevel = WindowTransparencyLevel.AcrylicBlur; + } TransparencyLevel = transparencyLevel; diff --git a/src/Avalonia.X11/TransparencyHelper.cs b/src/Avalonia.X11/TransparencyHelper.cs index 5ca2d1d337..b4f8ca5aed 100644 --- a/src/Avalonia.X11/TransparencyHelper.cs +++ b/src/Avalonia.X11/TransparencyHelper.cs @@ -41,7 +41,11 @@ namespace Avalonia.X11 private WindowTransparencyLevel UpdateAtomsAndGetTransparency() { - if (_requestedLevel >= WindowTransparencyLevel.Blur) + var blur = _requestedLevel == WindowTransparencyLevel.Blur || + _requestedLevel == WindowTransparencyLevel.AcrylicBlur || + _requestedLevel == WindowTransparencyLevel.Mica; + + if (blur) { if (!_blurAtomsAreSet) { @@ -62,7 +66,7 @@ namespace Avalonia.X11 if (!_globals.IsCompositionEnabled) return WindowTransparencyLevel.None; - if (_requestedLevel >= WindowTransparencyLevel.Blur && CanBlur) + if (blur && CanBlur) return WindowTransparencyLevel.Blur; return WindowTransparencyLevel.Transparent; } diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs index 819e721b36..df1c4aa6d6 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs @@ -274,6 +274,19 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions } } + if (type.Equals(types.WindowTransparencyLevel)) + { + foreach (var property in types.WindowTransparencyLevel.Properties) + { + if (property.PropertyType == types.WindowTransparencyLevel && property.Name.Equals(text, StringComparison.OrdinalIgnoreCase)) + { + result = new XamlStaticOrTargetedReturnMethodCallNode(node, property.Getter, Enumerable.Empty()); + + return true; + } + } + } + if (type.Equals(types.Uri)) { var uriText = text.Trim(); @@ -385,7 +398,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions result = new AvaloniaXamlIlArrayConstantAstNode(node, elementType.MakeArrayType(1), elementType, nodes); return true; } - else if (type == context.Configuration.WellKnownTypes.IListOfT.MakeGenericType(elementType)) + else if (type == context.Configuration.WellKnownTypes.IListOfT.MakeGenericType(elementType) || + type == types.IReadOnlyListOfT.MakeGenericType(elementType)) { var listType = context.Configuration.WellKnownTypes.IListOfT.MakeGenericType(elementType); result = new AvaloniaXamlIlArrayConstantAstNode(node, listType, elementType, nodes); diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs index d160d4a277..05fe4bd2b8 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs @@ -117,6 +117,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers public IXamlConstructor UriConstructor { get; } public IXamlType Style { get; } public IXamlType ControlTheme { get; } + public IXamlType WindowTransparencyLevel { get; } + public IXamlType IReadOnlyListOfT { get; } public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg) { @@ -199,6 +201,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers FontFamily = cfg.TypeSystem.GetType("Avalonia.Media.FontFamily"); FontFamilyConstructorUriName = FontFamily.GetConstructor(new List { Uri, XamlIlTypes.String }); ThemeVariant = cfg.TypeSystem.GetType("Avalonia.Styling.ThemeVariant"); + WindowTransparencyLevel = cfg.TypeSystem.GetType("Avalonia.Controls.WindowTransparencyLevel"); (IXamlType, IXamlConstructor) GetNumericTypeInfo(string name, IXamlType componentType, int componentCount) { @@ -260,6 +263,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers UriConstructor = Uri.GetConstructor(new List() { cfg.WellKnownTypes.String, UriKind }); Style = cfg.TypeSystem.GetType("Avalonia.Styling.Style"); ControlTheme = cfg.TypeSystem.GetType("Avalonia.Styling.ControlTheme"); + IReadOnlyListOfT = cfg.TypeSystem.GetType("System.Collections.Generic.IReadOnlyList`1"); } } diff --git a/src/Windows/Avalonia.Win32/TrayIconImpl.cs b/src/Windows/Avalonia.Win32/TrayIconImpl.cs index 5069add9fd..f2023d37ac 100644 --- a/src/Windows/Avalonia.Win32/TrayIconImpl.cs +++ b/src/Windows/Avalonia.Win32/TrayIconImpl.cs @@ -147,7 +147,7 @@ namespace Avalonia.Win32 SystemDecorations = SystemDecorations.None, SizeToContent = SizeToContent.WidthAndHeight, Background = null, - TransparencyLevelHint = WindowTransparencyLevel.Transparent, + TransparencyLevelHint = new[] { WindowTransparencyLevel.Transparent }, Content = new TrayIconMenuFlyoutPresenter() { ItemsSource = menuItems diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 9217f42952..b8eb37bb33 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -435,7 +435,9 @@ namespace Avalonia.Win32 Marshal.FreeHGlobal(accentPtr); - if (transparencyLevel >= WindowTransparencyLevel.Blur) + if (transparencyLevel == WindowTransparencyLevel.Blur || + transparencyLevel == WindowTransparencyLevel.AcrylicBlur || + transparencyLevel == WindowTransparencyLevel.Mica) { Win7EnableBlur(transparencyLevel); } @@ -447,13 +449,14 @@ namespace Avalonia.Win32 { if (_isUsingComposition) { - var effect = transparencyLevel switch - { - WindowTransparencyLevel.Mica => BlurEffect.Mica, - WindowTransparencyLevel.AcrylicBlur => BlurEffect.Acrylic, - WindowTransparencyLevel.Blur => BlurEffect.Acrylic, - _ => BlurEffect.None - }; + BlurEffect effect; + + if (transparencyLevel == WindowTransparencyLevel.Mica) + effect = BlurEffect.Mica; + else if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur) + effect = BlurEffect.Acrylic; + else + effect = BlurEffect.None; if (Win32Platform.WindowsVersion >= WinUiCompositionShared.MinHostBackdropVersion) { @@ -485,27 +488,22 @@ namespace Avalonia.Win32 transparencyLevel = WindowTransparencyLevel.Blur; } - switch (transparencyLevel) + if (transparencyLevel == WindowTransparencyLevel.Transparent) + { + accent.AccentState = AccentState.ACCENT_ENABLE_TRANSPARENTGRADIENT; + } + else if (transparencyLevel == WindowTransparencyLevel.Blur) + { + accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; + } + else if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur || transparencyLevel == WindowTransparencyLevel.Mica) + { + accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC; + transparencyLevel = WindowTransparencyLevel.AcrylicBlur; + } + else { - default: - case WindowTransparencyLevel.None: - accent.AccentState = AccentState.ACCENT_DISABLED; - break; - - case WindowTransparencyLevel.Transparent: - accent.AccentState = AccentState.ACCENT_ENABLE_TRANSPARENTGRADIENT; - break; - - case WindowTransparencyLevel.Blur: - accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; - break; - - case WindowTransparencyLevel.AcrylicBlur: - case WindowTransparencyLevel.ForceAcrylicBlur: // hack-force acrylic. - case WindowTransparencyLevel.Mica: - accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC; - transparencyLevel = WindowTransparencyLevel.AcrylicBlur; - break; + accent.AccentState = AccentState.ACCENT_DISABLED; } accent.AccentFlags = 2; diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/WindowTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/WindowTests.cs new file mode 100644 index 0000000000..a48776bfee --- /dev/null +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/WindowTests.cs @@ -0,0 +1,26 @@ +using Avalonia.Controls; +using Avalonia.UnitTests; +using Xunit; + +namespace Avalonia.Markup.Xaml.UnitTests.Xaml +{ + public class WindowTests : XamlTestBase + { + [Fact] + public void Can_Specify_TransparencyLevelHint() + { + using var app = UnitTestApplication.Start(TestServices.MockWindowingPlatform); + var xaml = @""; + + var target = AvaloniaRuntimeXamlLoader.Parse(xaml); + + Assert.Equal( + new[] + { + WindowTransparencyLevel.Blur, + WindowTransparencyLevel.Transparent, + WindowTransparencyLevel.None, + }, target.TransparencyLevelHint); + } + } +} From 2ac8849fb0d2799f021cef2db216937c367a1bec Mon Sep 17 00:00:00 2001 From: Max Katz Date: Wed, 24 May 2023 04:05:53 -0400 Subject: [PATCH 090/219] Fix Browser not wrapping file handles into StorageItem object --- src/Browser/Avalonia.Browser/Interop/StorageHelper.cs | 3 +++ .../Avalonia.Browser/Storage/BrowserStorageProvider.cs | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Browser/Avalonia.Browser/Interop/StorageHelper.cs b/src/Browser/Avalonia.Browser/Interop/StorageHelper.cs index d95d4405ba..c28efbb308 100644 --- a/src/Browser/Avalonia.Browser/Interop/StorageHelper.cs +++ b/src/Browser/Avalonia.Browser/Interop/StorageHelper.cs @@ -39,6 +39,9 @@ internal static partial class StorageHelper [JSImport("StorageItem.openRead", AvaloniaModule.StorageModuleName)] public static partial Task OpenRead(JSObject item); + + [JSImport("StorageItem.createFromHandle", AvaloniaModule.StorageModuleName)] + public static partial JSObject? StorageItemFromHandle(JSObject handle); [JSImport("StorageItem.getItemsIterator", AvaloniaModule.StorageModuleName)] [return: JSMarshalAs] diff --git a/src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs b/src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs index a28fd4cbde..ef34826238 100644 --- a/src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs +++ b/src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs @@ -319,13 +319,14 @@ internal class JSStorageFolder : JSStorageItem, IStorageBookmarkFolder } var kind = storageItem.GetPropertyAsString("kind"); + var item = StorageHelper.StorageItemFromHandle(storageItem)!; switch (kind) { case "directory": - yield return new JSStorageFolder(storageItem); + yield return new JSStorageFolder(item); break; case "file": - yield return new JSStorageFile(storageItem); + yield return new JSStorageFile(item); break; } } From 6c5c13aa5cb7958d2a97337612665d4ee71439c6 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Wed, 24 May 2023 04:22:23 -0400 Subject: [PATCH 091/219] Fix ICustomDrawOperation and browser splash screen --- .../Composition/Drawing/RenderDataDrawingContext.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Base/Rendering/Composition/Drawing/RenderDataDrawingContext.cs b/src/Avalonia.Base/Rendering/Composition/Drawing/RenderDataDrawingContext.cs index 3d5033086e..971ae1d8aa 100644 --- a/src/Avalonia.Base/Rendering/Composition/Drawing/RenderDataDrawingContext.cs +++ b/src/Avalonia.Base/Rendering/Composition/Drawing/RenderDataDrawingContext.cs @@ -177,7 +177,10 @@ internal class RenderDataDrawingContext : DrawingContext }); } - public override void Custom(ICustomDrawOperation custom) => Add(new RenderDataCustomNode()); + public override void Custom(ICustomDrawOperation custom) => Add(new RenderDataCustomNode + { + Operation = custom + }); public override void DrawGlyphRun(IBrush? foreground, GlyphRun? glyphRun) { From 7640434affc3c5e82be0e258528ddacea5e897b6 Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Wed, 24 May 2023 08:39:56 +0000 Subject: [PATCH 092/219] use MinWidth to set button widths --- src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml | 4 ++-- src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml b/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml index e903e7d3a8..8519099a27 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml @@ -179,8 +179,8 @@ - - + + diff --git a/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml b/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml index bd5151ad1a..cc049938ad 100644 --- a/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml @@ -93,8 +93,8 @@ - - + + From 10b89ac13a3d7ac24a598b37427bd6c8ac65dd10 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 24 May 2023 11:19:15 +0100 Subject: [PATCH 093/219] Revert "revert control catalog changes." This reverts commit d24903957eb27ca89670c28e5f4d34b8e123e58f. --- .../ControlCatalog/Pages/CheckBoxPage.xaml | 43 +++++++++---------- .../ControlCatalog/Pages/CheckBoxPage.xaml.cs | 16 ++++++- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/samples/ControlCatalog/Pages/CheckBoxPage.xaml b/samples/ControlCatalog/Pages/CheckBoxPage.xaml index 2f60fc5dae..78a8ff5550 100644 --- a/samples/ControlCatalog/Pages/CheckBoxPage.xaml +++ b/samples/ControlCatalog/Pages/CheckBoxPage.xaml @@ -1,28 +1,25 @@ - - A check box control + x:Class="ControlCatalog.Pages.CheckBoxPage" Background="White"> + + + + + + + + - - - _Unchecked - _Checked - _Indeterminate - Disabled - - - Three State: Unchecked - Three State: Checked - Three State: Indeterminate - Three State: Disabled + + + + + + Popup Text + + + - - + + diff --git a/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs b/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs index 5027c94f5e..60e75561e1 100644 --- a/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs +++ b/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs @@ -1,18 +1,32 @@ using Avalonia.Controls; +using Avalonia.Input; using Avalonia.Markup.Xaml; namespace ControlCatalog.Pages { - public class CheckBoxPage : UserControl + public partial class CheckBoxPage : UserControl { + private TextBlock myTb; + private int count; + public CheckBoxPage() { this.InitializeComponent(); + + myTb = this.FindControl("myTb"); + } private void InitializeComponent() { AvaloniaXamlLoader.Load(this); } + + protected override void OnPointerMoved(PointerEventArgs e) + { + base.OnPointerMoved(e); + + myTb.Text = e.GetPosition(this).ToString() + ", " + count++; + } } } From 8845f239b609c2b0c22e286902499beb10f70c2c Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 24 May 2023 13:54:12 +0200 Subject: [PATCH 094/219] Implement transparency level hint list on win32. Other backends have the relevant code commented-out still. --- .../Platform/SkiaPlatform/TopLevelImpl.cs | 168 ++++++------ .../Offscreen/OffscreenTopLevelImpl.cs | 2 +- .../Platform/ITopLevelImpl.cs | 2 +- src/Avalonia.Controls/TopLevel.cs | 4 +- src/Avalonia.DesignerSupport/Remote/Stubs.cs | 2 +- src/Avalonia.Native/WindowImplBase.cs | 42 +-- src/Avalonia.X11/X11Window.cs | 6 +- .../Avalonia.Browser/BrowserTopLevelImpl.cs | 12 +- .../Avalonia.Headless/HeadlessWindowImpl.cs | 2 +- .../FramebufferToplevelImpl.cs | 2 +- .../Wpf/WpfTopLevelImpl.cs | 2 +- .../Avalonia.Win32/PlatformConstants.cs | 7 +- .../Composition/WinUiCompositionShared.cs | 1 + src/Windows/Avalonia.Win32/WindowImpl.cs | 244 ++++++++---------- src/iOS/Avalonia.iOS/AvaloniaView.cs | 2 +- .../CompositorTestServices.cs | 2 +- 16 files changed, 232 insertions(+), 268 deletions(-) diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index 609b6cd519..144e2d843a 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -299,91 +299,91 @@ namespace Avalonia.Android.Platform.SkiaPlatform public double Scaling => RenderScaling; - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { - if (TransparencyLevel != transparencyLevel) - { - bool isBelowR = Build.VERSION.SdkInt < BuildVersionCodes.R; - bool isAboveR = Build.VERSION.SdkInt > BuildVersionCodes.R; - if (_view.Context is AvaloniaMainActivity activity) - { - if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur || - transparencyLevel == WindowTransparencyLevel.Mica || - transparencyLevel == WindowTransparencyLevel.None) - { - if (!isBelowR) - { - activity.SetTranslucent(false); - } - if (isAboveR) - { - activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); - - var attr = activity.Window?.Attributes; - if (attr != null) - { - attr.BlurBehindRadius = 0; - - activity.Window.Attributes = attr; - } - } - activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); - - if (transparencyLevel != WindowTransparencyLevel.None) - { - return; - } - } - - if (transparencyLevel == WindowTransparencyLevel.Transparent) - { - if (!isBelowR) - { - activity.SetTranslucent(true); - } - if (isAboveR) - { - activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); - - var attr = activity.Window?.Attributes; - if (attr != null) - { - attr.BlurBehindRadius = 0; - - activity.Window.Attributes = attr; - } - } - activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); - } - - if (transparencyLevel == WindowTransparencyLevel.Blur) - { - if (isAboveR) - { - activity.SetTranslucent(true); - activity.Window?.AddFlags(WindowManagerFlags.BlurBehind); - - var attr = activity.Window?.Attributes; - if (attr != null) - { - attr.BlurBehindRadius = 120; - - activity.Window.Attributes = attr; - } - activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); - } - else - { - activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); - activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); - - return; - } - } - - TransparencyLevel = transparencyLevel; - } - } + ////if (TransparencyLevel != transparencyLevel) + ////{ + //// bool isBelowR = Build.VERSION.SdkInt < BuildVersionCodes.R; + //// bool isAboveR = Build.VERSION.SdkInt > BuildVersionCodes.R; + //// if (_view.Context is AvaloniaMainActivity activity) + //// { + //// if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur || + //// transparencyLevel == WindowTransparencyLevel.Mica || + //// transparencyLevel == WindowTransparencyLevel.None) + //// { + //// if (!isBelowR) + //// { + //// activity.SetTranslucent(false); + //// } + //// if (isAboveR) + //// { + //// activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); + + //// var attr = activity.Window?.Attributes; + //// if (attr != null) + //// { + //// attr.BlurBehindRadius = 0; + + //// activity.Window.Attributes = attr; + //// } + //// } + //// activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); + + //// if (transparencyLevel != WindowTransparencyLevel.None) + //// { + //// return; + //// } + //// } + + //// if (transparencyLevel == WindowTransparencyLevel.Transparent) + //// { + //// if (!isBelowR) + //// { + //// activity.SetTranslucent(true); + //// } + //// if (isAboveR) + //// { + //// activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); + + //// var attr = activity.Window?.Attributes; + //// if (attr != null) + //// { + //// attr.BlurBehindRadius = 0; + + //// activity.Window.Attributes = attr; + //// } + //// } + //// activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); + //// } + + //// if (transparencyLevel == WindowTransparencyLevel.Blur) + //// { + //// if (isAboveR) + //// { + //// activity.SetTranslucent(true); + //// activity.Window?.AddFlags(WindowManagerFlags.BlurBehind); + + //// var attr = activity.Window?.Attributes; + //// if (attr != null) + //// { + //// attr.BlurBehindRadius = 120; + + //// activity.Window.Attributes = attr; + //// } + //// activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); + //// } + //// else + //// { + //// activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); + //// activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); + + //// return; + //// } + //// } + + //// TransparencyLevel = transparencyLevel; + //// } + ////} } public virtual object TryGetFeature(Type featureType) diff --git a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs index 387357dddd..28b43e8397 100644 --- a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs +++ b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs @@ -89,7 +89,7 @@ namespace Avalonia.Controls.Embedding.Offscreen public Action? LostFocus { get; set; } public abstract IMouseDevice MouseDevice { get; } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { } + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { } public WindowTransparencyLevel TransparencyLevel { get; private set; } diff --git a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs index bb6b2304af..02b96d0628 100644 --- a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs +++ b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs @@ -117,7 +117,7 @@ namespace Avalonia.Platform /// /// Sets the hint of the TopLevel. /// - void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel); + void SetTransparencyLevelHint(IReadOnlyList transparencyLevel); /// /// Gets the current of the TopLevel. diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 189dbe5e62..ca12c302f7 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -523,8 +523,8 @@ namespace Avalonia.Controls { if (PlatformImpl != null) { - ////PlatformImpl.SetTransparencyLevelHint( - //// change.GetNewValue>() ?? Array.Empty()); + PlatformImpl.SetTransparencyLevelHint( + change.GetNewValue>() ?? Array.Empty()); } } else if (change.Property == ActualThemeVariantProperty) diff --git a/src/Avalonia.DesignerSupport/Remote/Stubs.cs b/src/Avalonia.DesignerSupport/Remote/Stubs.cs index f6f5c185e9..28d1b147fd 100644 --- a/src/Avalonia.DesignerSupport/Remote/Stubs.cs +++ b/src/Avalonia.DesignerSupport/Remote/Stubs.cs @@ -179,7 +179,7 @@ namespace Avalonia.DesignerSupport.Remote public Action GotInputWhenDisabled { get; set; } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { } + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { } public void SetWindowManagerAddShadowHint(bool enabled) { diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index c065346377..c8198f0da2 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -485,27 +485,27 @@ namespace Avalonia.Native _native?.BeginDragAndDropOperation(effects, point, clipboard, callback, sourceHandle); } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) - { - if (TransparencyLevel != transparencyLevel) - { - if (transparencyLevel == WindowTransparencyLevel.Blur || - transparencyLevel == WindowTransparencyLevel.AcrylicBlur || - transparencyLevel == WindowTransparencyLevel.Mica) - { - transparencyLevel = WindowTransparencyLevel.AcrylicBlur; - } - - TransparencyLevel = transparencyLevel; - - _native.SetTransparencyMode(transparencyLevel == WindowTransparencyLevel.None - ? AvnWindowTransparencyMode.Opaque - : transparencyLevel == WindowTransparencyLevel.Transparent - ? AvnWindowTransparencyMode.Transparent - : AvnWindowTransparencyMode.Blur); - - TransparencyLevelChanged?.Invoke(TransparencyLevel); - } + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) + { + ////if (TransparencyLevel != transparencyLevel) + ////{ + //// if (transparencyLevel == WindowTransparencyLevel.Blur || + //// transparencyLevel == WindowTransparencyLevel.AcrylicBlur || + //// transparencyLevel == WindowTransparencyLevel.Mica) + //// { + //// transparencyLevel = WindowTransparencyLevel.AcrylicBlur; + //// } + + //// TransparencyLevel = transparencyLevel; + + //// _native.SetTransparencyMode(transparencyLevel == WindowTransparencyLevel.None + //// ? AvnWindowTransparencyMode.Opaque + //// : transparencyLevel == WindowTransparencyLevel.Transparent + //// ? AvnWindowTransparencyMode.Transparent + //// : AvnWindowTransparencyMode.Blur); + + //// TransparencyLevelChanged?.Invoke(TransparencyLevel); + ////} } public WindowTransparencyLevel TransparencyLevel { get; private set; } = WindowTransparencyLevel.None; diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 0a535d2f57..58b59a6b56 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -1307,8 +1307,10 @@ namespace Avalonia.X11 public IPopupPositioner? PopupPositioner { get; } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) => - _transparencyHelper?.SetTransparencyRequest(transparencyLevel); + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) + { + ////_transparencyHelper?.SetTransparencyRequest(transparencyLevel); + } public void SetWindowManagerAddShadowHint(bool enabled) { diff --git a/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs b/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs index 8456dc92d0..c243a2a28b 100644 --- a/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs +++ b/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs @@ -223,13 +223,13 @@ namespace Avalonia.Browser return null; } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { - if (transparencyLevel == WindowTransparencyLevel.None - || transparencyLevel == WindowTransparencyLevel.Transparent) - { - TransparencyLevel = transparencyLevel; - } + ////if (transparencyLevel == WindowTransparencyLevel.None + //// || transparencyLevel == WindowTransparencyLevel.Transparent) + ////{ + //// TransparencyLevel = transparencyLevel; + ////} } public Size ClientSize => _clientSize; diff --git a/src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs b/src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs index 93f92d46f8..edf8275b1a 100644 --- a/src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs +++ b/src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs @@ -337,7 +337,7 @@ namespace Avalonia.Headless } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { } diff --git a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs index ccc8cab8ae..79408cd604 100644 --- a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs +++ b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs @@ -75,7 +75,7 @@ using Avalonia.Rendering.Composition; public Size ScaledSize => _outputBackend.PixelSize.ToSize(RenderScaling); - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { } + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { } public WindowTransparencyLevel TransparencyLevel { get; private set; } diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs index 8025779c90..64f4352c25 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs @@ -247,7 +247,7 @@ namespace Avalonia.Win32.Interop.Wpf public IPopupImpl CreatePopup() => null; - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { } + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { } public WindowTransparencyLevel TransparencyLevel { get; private set; } diff --git a/src/Windows/Avalonia.Win32/PlatformConstants.cs b/src/Windows/Avalonia.Win32/PlatformConstants.cs index 48dd9f45da..bed78501f3 100644 --- a/src/Windows/Avalonia.Win32/PlatformConstants.cs +++ b/src/Windows/Avalonia.Win32/PlatformConstants.cs @@ -2,12 +2,13 @@ using System; namespace Avalonia.Win32 { - public static class PlatformConstants + internal static class PlatformConstants { public const string WindowHandleType = "HWND"; public const string CursorHandleType = "HCURSOR"; - internal static readonly Version Windows8 = new Version(6, 2); - internal static readonly Version Windows7 = new Version(6, 1); + public static readonly Version Windows10 = new Version(10, 0); + public static readonly Version Windows8 = new Version(6, 2); + public static readonly Version Windows7 = new Version(6, 1); } } diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs index 602d0a3f8a..f17805fba3 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs @@ -12,6 +12,7 @@ internal class WinUiCompositionShared : IDisposable public ICompositionBrush? MicaBrush { get; } public object SyncRoot { get; } = new(); + public static readonly Version MinAcrylicVersion = new(10, 0, 15063); public static readonly Version MinHostBackdropVersion = new(10, 0, 22000); public WinUiCompositionShared(ICompositor compositor) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index b8eb37bb33..dc9cc7f50c 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; @@ -25,6 +25,7 @@ using Avalonia.Win32.WinRT.Composition; using Avalonia.Win32.WinRT; using static Avalonia.Win32.Interop.UnmanagedMethods; using Avalonia.Input.Platform; +using System.Diagnostics; namespace Avalonia.Win32 { @@ -346,82 +347,119 @@ namespace Avalonia.Win32 return null; } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevels) { - TransparencyLevel = EnableBlur(transparencyLevel); - } + var windowsVersion = Win32Platform.WindowsVersion; - private WindowTransparencyLevel EnableBlur(WindowTransparencyLevel transparencyLevel) - { - if (Win32Platform.WindowsVersion.Major >= 6) - { - if (DwmIsCompositionEnabled(out var compositionEnabled) != 0 || !compositionEnabled) - { - return WindowTransparencyLevel.None; - } - else if (Win32Platform.WindowsVersion.Major >= 10) - { - return Win10EnableBlur(transparencyLevel); - } - else if (Win32Platform.WindowsVersion.Minor >= 2) - { - return Win8xEnableBlur(transparencyLevel); - } - else - { - return Win7EnableBlur(transparencyLevel); - } - } - else + foreach (var level in transparencyLevels) { - return WindowTransparencyLevel.None; + if (!IsSupported(level, windowsVersion)) + continue; + + if (level == WindowTransparencyLevel.Transparent) + SetTransparencyTransparent(windowsVersion); + else if (level == WindowTransparencyLevel.Blur) + SetTransparencyBlur(windowsVersion); + else if (level == WindowTransparencyLevel.AcrylicBlur) + SetTransparencyAcrylicBlur(windowsVersion); + else if (level == WindowTransparencyLevel.Mica) + SetTransparencyMica(windowsVersion); + + TransparencyLevel = level; + break; } } - private WindowTransparencyLevel Win7EnableBlur(WindowTransparencyLevel transparencyLevel) + private bool IsSupported(WindowTransparencyLevel level, Version windowsVersion) { - if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur) - { - transparencyLevel = WindowTransparencyLevel.Blur; - } + // Only None is suppported when composition is disabled. + if (!_isUsingComposition) + return level == WindowTransparencyLevel.None; + + // When composition is enabled, None is not supported because the backing visual always + // has an alpha channel + if (level == WindowTransparencyLevel.None) + return false; + + // Transparent only supported on Windows 8+. + if (level == WindowTransparencyLevel.Transparent) + return windowsVersion >= PlatformConstants.Windows8; + + // Blur only supported on Windows 8 and lower. + if (level == WindowTransparencyLevel.Blur) + return windowsVersion < PlatformConstants.Windows10; + + // Acrylic is supported on Windows >= 10.0.15063. + if (level == WindowTransparencyLevel.AcrylicBlur) + return windowsVersion >= WinUiCompositionShared.MinAcrylicVersion; - var blurInfo = new DWM_BLURBEHIND(false); + // Mica is supported on Windows >= 10.0.22000. + if (level == WindowTransparencyLevel.Mica) + return windowsVersion >= WinUiCompositionShared.MinHostBackdropVersion; - if (transparencyLevel == WindowTransparencyLevel.Blur) + return false; + } + + private void SetTransparencyTransparent(Version windowsVersion) + { + // Transparent only supported with composition on Windows 8+. + if (!_isUsingComposition || windowsVersion < PlatformConstants.Windows8) + return; + + if (windowsVersion < PlatformConstants.Windows10) { - blurInfo = new DWM_BLURBEHIND(true); + // Some of the AccentState Enum's values have different meanings on Windows 8.x than on + // Windows 10, hence using ACCENT_ENABLE_BLURBEHIND to disable blurbehind ¯\_(ツ)_/¯. + // Hey, I'm just porting what was here before. + SetAccentState(AccentState.ACCENT_ENABLE_BLURBEHIND); + var blurInfo = new DWM_BLURBEHIND(false); + DwmEnableBlurBehindWindow(_hwnd, ref blurInfo); } + SetUseHostBackdropBrush(false); + _blurHost?.SetBlur(BlurEffect.None); + } + + private void SetTransparencyBlur(Version windowsVersion) + { + // Blur only supported with composition on Windows 8 and lower. + if (!_isUsingComposition || windowsVersion >= PlatformConstants.Windows10) + return; + + // Some of the AccentState Enum's values have different meanings on Windows 8.x than on + // Windows 10. + SetAccentState(AccentState.ACCENT_DISABLED); + var blurInfo = new DWM_BLURBEHIND(true); DwmEnableBlurBehindWindow(_hwnd, ref blurInfo); + } - if (transparencyLevel == WindowTransparencyLevel.Transparent) - { - return WindowTransparencyLevel.None; - } - else - { - return transparencyLevel; - } + private void SetTransparencyAcrylicBlur(Version windowsVersion) + { + // Acrylic blur only supported with composition on Windows >= 10.0.15063. + if (!_isUsingComposition || windowsVersion < WinUiCompositionShared.MinAcrylicVersion) + return; + + SetUseHostBackdropBrush(true); + _blurHost?.SetBlur(BlurEffect.Acrylic); } - private WindowTransparencyLevel Win8xEnableBlur(WindowTransparencyLevel transparencyLevel) + private void SetTransparencyMica(Version windowsVersion) { - var accent = new AccentPolicy(); - var accentStructSize = Marshal.SizeOf(); + // Mica only supported with composition on Windows >= 10.0.22000. + if (!_isUsingComposition || windowsVersion < WinUiCompositionShared.MinHostBackdropVersion) + return; - if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur) - { - transparencyLevel = WindowTransparencyLevel.Blur; - } + SetUseHostBackdropBrush(false); + _blurHost?.SetBlur(BlurEffect.Mica); + } - if (transparencyLevel == WindowTransparencyLevel.Transparent) - { - accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; - } - else - { - accent.AccentState = AccentState.ACCENT_DISABLED; - } + private void SetAccentState(AccentState state) + { + var accent = new AccentPolicy(); + var accentStructSize = Marshal.SizeOf(accent); + + //Some of the AccentState Enum's values have different meanings on Windows 8.x than on Windows 10 + accent.AccentState = state; var accentPtr = Marshal.AllocHGlobal(accentStructSize); Marshal.StructureToPtr(accent, accentPtr, false); @@ -432,96 +470,18 @@ namespace Avalonia.Win32 data.Data = accentPtr; SetWindowCompositionAttribute(_hwnd, ref data); - Marshal.FreeHGlobal(accentPtr); - - if (transparencyLevel == WindowTransparencyLevel.Blur || - transparencyLevel == WindowTransparencyLevel.AcrylicBlur || - transparencyLevel == WindowTransparencyLevel.Mica) - { - Win7EnableBlur(transparencyLevel); - } - - return transparencyLevel; } - private WindowTransparencyLevel Win10EnableBlur(WindowTransparencyLevel transparencyLevel) + private void SetUseHostBackdropBrush(bool useHostBackdropBrush) { - if (_isUsingComposition) - { - BlurEffect effect; - - if (transparencyLevel == WindowTransparencyLevel.Mica) - effect = BlurEffect.Mica; - else if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur) - effect = BlurEffect.Acrylic; - else - effect = BlurEffect.None; - - if (Win32Platform.WindowsVersion >= WinUiCompositionShared.MinHostBackdropVersion) - { - unsafe - { - int pvUseBackdropBrush = effect == BlurEffect.Acrylic ? 1 : 0; - DwmSetWindowAttribute(_hwnd, (int)DwmWindowAttribute.DWMWA_USE_HOSTBACKDROPBRUSH, &pvUseBackdropBrush, sizeof(int)); - } - } - - if (Win32Platform.WindowsVersion < WinUiCompositionShared.MinHostBackdropVersion && effect == BlurEffect.Mica) - { - effect = BlurEffect.Acrylic; - } - - _blurHost?.SetBlur(effect); + if (Win32Platform.WindowsVersion < WinUiCompositionShared.MinHostBackdropVersion) + return; - return transparencyLevel; - } - else + unsafe { - bool canUseAcrylic = Win32Platform.WindowsVersion.Major > 10 || Win32Platform.WindowsVersion.Build >= 19628; - - var accent = new AccentPolicy(); - var accentStructSize = Marshal.SizeOf(); - - if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur && !canUseAcrylic) - { - transparencyLevel = WindowTransparencyLevel.Blur; - } - - if (transparencyLevel == WindowTransparencyLevel.Transparent) - { - accent.AccentState = AccentState.ACCENT_ENABLE_TRANSPARENTGRADIENT; - } - else if (transparencyLevel == WindowTransparencyLevel.Blur) - { - accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; - } - else if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur || transparencyLevel == WindowTransparencyLevel.Mica) - { - accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC; - transparencyLevel = WindowTransparencyLevel.AcrylicBlur; - } - else - { - accent.AccentState = AccentState.ACCENT_DISABLED; - } - - accent.AccentFlags = 2; - accent.GradientColor = 0x01000000; - - var accentPtr = Marshal.AllocHGlobal(accentStructSize); - Marshal.StructureToPtr(accent, accentPtr, false); - - var data = new WindowCompositionAttributeData(); - data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY; - data.SizeOfData = accentStructSize; - data.Data = accentPtr; - - SetWindowCompositionAttribute(_hwnd, ref data); - - Marshal.FreeHGlobal(accentPtr); - - return transparencyLevel; + var pvUseBackdropBrush = useHostBackdropBrush ? 1 : 0; + DwmSetWindowAttribute(_hwnd, (int)DwmWindowAttribute.DWMWA_USE_HOSTBACKDROPBRUSH, &pvUseBackdropBrush, sizeof(int)); } } diff --git a/src/iOS/Avalonia.iOS/AvaloniaView.cs b/src/iOS/Avalonia.iOS/AvaloniaView.cs index 6ca0cf7ace..605955e44f 100644 --- a/src/iOS/Avalonia.iOS/AvaloniaView.cs +++ b/src/iOS/Avalonia.iOS/AvaloniaView.cs @@ -139,7 +139,7 @@ namespace Avalonia.iOS return null; } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { // No-op } diff --git a/tests/Avalonia.UnitTests/CompositorTestServices.cs b/tests/Avalonia.UnitTests/CompositorTestServices.cs index de7cbc873c..734baba54f 100644 --- a/tests/Avalonia.UnitTests/CompositorTestServices.cs +++ b/tests/Avalonia.UnitTests/CompositorTestServices.cs @@ -192,7 +192,7 @@ public class CompositorTestServices : IDisposable public IMouseDevice MouseDevice { get; } = new MouseDevice(); public IPopupImpl CreatePopup() => throw new NotImplementedException(); - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { } From 098f37d3cf31706d0dc367355fb972907d69846a Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 24 May 2023 14:54:04 +0200 Subject: [PATCH 095/219] Implement transparency level hint list on Android. --- .../Platform/SkiaPlatform/TopLevelImpl.cs | 155 ++++++++---------- .../Platform/ITopLevelImpl.cs | 2 +- 2 files changed, 71 insertions(+), 86 deletions(-) diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index 144e2d843a..151227dba4 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Runtime.Versioning; using Android.App; using Android.Content; using Android.Graphics; @@ -299,93 +300,36 @@ namespace Avalonia.Android.Platform.SkiaPlatform public double Scaling => RenderScaling; - public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevels) { - ////if (TransparencyLevel != transparencyLevel) - ////{ - //// bool isBelowR = Build.VERSION.SdkInt < BuildVersionCodes.R; - //// bool isAboveR = Build.VERSION.SdkInt > BuildVersionCodes.R; - //// if (_view.Context is AvaloniaMainActivity activity) - //// { - //// if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur || - //// transparencyLevel == WindowTransparencyLevel.Mica || - //// transparencyLevel == WindowTransparencyLevel.None) - //// { - //// if (!isBelowR) - //// { - //// activity.SetTranslucent(false); - //// } - //// if (isAboveR) - //// { - //// activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); - - //// var attr = activity.Window?.Attributes; - //// if (attr != null) - //// { - //// attr.BlurBehindRadius = 0; - - //// activity.Window.Attributes = attr; - //// } - //// } - //// activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); - - //// if (transparencyLevel != WindowTransparencyLevel.None) - //// { - //// return; - //// } - //// } - - //// if (transparencyLevel == WindowTransparencyLevel.Transparent) - //// { - //// if (!isBelowR) - //// { - //// activity.SetTranslucent(true); - //// } - //// if (isAboveR) - //// { - //// activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); - - //// var attr = activity.Window?.Attributes; - //// if (attr != null) - //// { - //// attr.BlurBehindRadius = 0; - - //// activity.Window.Attributes = attr; - //// } - //// } - //// activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); - //// } - - //// if (transparencyLevel == WindowTransparencyLevel.Blur) - //// { - //// if (isAboveR) - //// { - //// activity.SetTranslucent(true); - //// activity.Window?.AddFlags(WindowManagerFlags.BlurBehind); - - //// var attr = activity.Window?.Attributes; - //// if (attr != null) - //// { - //// attr.BlurBehindRadius = 120; - - //// activity.Window.Attributes = attr; - //// } - //// activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); - //// } - //// else - //// { - //// activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); - //// activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); - - //// return; - //// } - //// } - - //// TransparencyLevel = transparencyLevel; - //// } - ////} + if (_view.Context is not AvaloniaMainActivity activity) + return; + + foreach (var level in transparencyLevels) + { + if (!IsSupported(level)) + { + continue; + } + + if (level == WindowTransparencyLevel.None && OperatingSystem.IsAndroidVersionAtLeast(30)) + { + activity.SetTranslucent(false); + } + else if (level == WindowTransparencyLevel.Transparent) + { + SetTransparencyTransparent(activity); + } + else if (level == WindowTransparencyLevel.Blur) + { + SetTransparencyBlur(activity); + } + + TransparencyLevel = level; + break; + } } - + public virtual object TryGetFeature(Type featureType) { if (featureType == typeof(IStorageProvider)) @@ -420,6 +364,47 @@ namespace Avalonia.Android.Platform.SkiaPlatform return null; } + + private static bool IsSupported(WindowTransparencyLevel level) + { + if (level == WindowTransparencyLevel.None) + return true; + if (level == WindowTransparencyLevel.Transparent) + return OperatingSystem.IsAndroidVersionAtLeast(30); + if (level == WindowTransparencyLevel.Blur) + return OperatingSystem.IsAndroidVersionAtLeast(31); + return false; + } + + private static void SetTransparencyTransparent(AvaloniaMainActivity activity) + { + if (OperatingSystem.IsAndroidVersionAtLeast(30)) + { + activity.SetTranslucent(true); + SetBlurBehindRadius(activity, 0); + activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); + } + } + + private static void SetTransparencyBlur(AvaloniaMainActivity activity) + { + if (OperatingSystem.IsAndroidVersionAtLeast(31)) + { + activity.SetTranslucent(true); + activity.Window?.AddFlags(WindowManagerFlags.BlurBehind); + SetBlurBehindRadius(activity, 120); + activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); + } + } + + private static void SetBlurBehindRadius(AvaloniaMainActivity activity, int radius) + { + if (OperatingSystem.IsAndroidVersionAtLeast(31) && activity.Window?.Attributes is { } attr) + { + attr.BlurBehindRadius = radius; + activity.Window.Attributes = attr; + } + } } internal class AvaloniaInputConnection : BaseInputConnection diff --git a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs index 02b96d0628..5b25e0e551 100644 --- a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs +++ b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs @@ -117,7 +117,7 @@ namespace Avalonia.Platform /// /// Sets the hint of the TopLevel. /// - void SetTransparencyLevelHint(IReadOnlyList transparencyLevel); + void SetTransparencyLevelHint(IReadOnlyList transparencyLevels); /// /// Gets the current of the TopLevel. From 9715d71bd97a81f1f9cd059e5a869c5ed7803d45 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 24 May 2023 15:18:07 +0200 Subject: [PATCH 096/219] Implement transparency level hint list on X11. --- src/Avalonia.X11/TransparencyHelper.cs | 77 ++++++++++++++++++-------- src/Avalonia.X11/X11Window.cs | 6 +- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/src/Avalonia.X11/TransparencyHelper.cs b/src/Avalonia.X11/TransparencyHelper.cs index b4f8ca5aed..01dccbf12a 100644 --- a/src/Avalonia.X11/TransparencyHelper.cs +++ b/src/Avalonia.X11/TransparencyHelper.cs @@ -1,6 +1,9 @@ using System; +using System.Collections.Generic; using Avalonia.Controls; +#nullable enable + namespace Avalonia.X11 { internal class TransparencyHelper : IDisposable, X11Globals.IGlobalsSubscriber @@ -9,10 +12,10 @@ namespace Avalonia.X11 private readonly IntPtr _window; private readonly X11Globals _globals; private WindowTransparencyLevel _currentLevel; - private WindowTransparencyLevel _requestedLevel; + private IReadOnlyList? _requestedLevels; private bool _blurAtomsAreSet; - public Action TransparencyLevelChanged { get; set; } + public Action? TransparencyLevelChanged { get; set; } public WindowTransparencyLevel CurrentLevel => _currentLevel; public TransparencyHelper(X11Info x11, IntPtr window, X11Globals globals) @@ -23,28 +26,62 @@ namespace Avalonia.X11 _globals.AddSubscriber(this); } - public void SetTransparencyRequest(WindowTransparencyLevel level) + public void SetTransparencyRequest(IReadOnlyList levels) { - _requestedLevel = level; - UpdateTransparency(); - } + WindowTransparencyLevel? newLevel = null; + _requestedLevels = levels; + + foreach (var level in levels) + { + if (!IsSupported(level)) + continue; + + SetBlur(level == WindowTransparencyLevel.Blur); + newLevel = level; + break; + } + + // If no matching transparency level was found, revert to Transparent or None depending + // on whether composition is enabled. + if (!newLevel.HasValue) + { + newLevel = _globals.IsCompositionEnabled ? + WindowTransparencyLevel.Transparent : + WindowTransparencyLevel.None; + SetBlur(false); + } - private void UpdateTransparency() - { - var newLevel = UpdateAtomsAndGetTransparency(); if (newLevel != _currentLevel) { - _currentLevel = newLevel; - TransparencyLevelChanged?.Invoke(newLevel); + _currentLevel = newLevel.Value; + TransparencyLevelChanged?.Invoke(newLevel.Value); } } - - private WindowTransparencyLevel UpdateAtomsAndGetTransparency() + + private bool IsSupported(WindowTransparencyLevel level) { - var blur = _requestedLevel == WindowTransparencyLevel.Blur || - _requestedLevel == WindowTransparencyLevel.AcrylicBlur || - _requestedLevel == WindowTransparencyLevel.Mica; + // None is suppported when composition is disabled. + if (level == WindowTransparencyLevel.None) + return !_globals.IsCompositionEnabled; + + // Transparent is suppported when composition is enabled. + if (level == WindowTransparencyLevel.Transparent) + return _globals.IsCompositionEnabled; + + // Blur is supported when composition is enabled and KWin is used. + if (level == WindowTransparencyLevel.Blur) + return _globals.IsCompositionEnabled && _globals.WmName == "KWin"; + + return false; + } + private void UpdateTransparency() + { + SetTransparencyRequest(_requestedLevels ?? Array.Empty()); + } + + private void SetBlur(bool blur) + { if (blur) { if (!_blurAtomsAreSet) @@ -63,15 +100,7 @@ namespace Avalonia.X11 _blurAtomsAreSet = false; } } - - if (!_globals.IsCompositionEnabled) - return WindowTransparencyLevel.None; - if (blur && CanBlur) - return WindowTransparencyLevel.Blur; - return WindowTransparencyLevel.Transparent; } - - private bool CanBlur => _globals.WmName == "KWin" && _globals.IsCompositionEnabled; public void Dispose() { diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 58b59a6b56..7da3d31dc2 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -196,7 +196,7 @@ namespace Avalonia.X11 _rawEventGrouper = new RawEventGrouper(DispatchInput, platform.EventGrouperDispatchQueue); _transparencyHelper = new TransparencyHelper(_x11, _handle, platform.Globals); - _transparencyHelper.SetTransparencyRequest(WindowTransparencyLevel.None); + _transparencyHelper.SetTransparencyRequest(Array.Empty()); CreateIC(); @@ -1307,9 +1307,9 @@ namespace Avalonia.X11 public IPopupPositioner? PopupPositioner { get; } - public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevels) { - ////_transparencyHelper?.SetTransparencyRequest(transparencyLevel); + _transparencyHelper?.SetTransparencyRequest(transparencyLevels); } public void SetWindowManagerAddShadowHint(bool enabled) From 0218a0d4ac602c4bf3aba79358c987089c970457 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 24 May 2023 15:25:47 +0200 Subject: [PATCH 097/219] Implement transparency level hint list on macOS. --- src/Avalonia.Native/WindowImplBase.cs | 42 +++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index c8198f0da2..0fe0c5e7c0 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -485,27 +485,27 @@ namespace Avalonia.Native _native?.BeginDragAndDropOperation(effects, point, clipboard, callback, sourceHandle); } - public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) - { - ////if (TransparencyLevel != transparencyLevel) - ////{ - //// if (transparencyLevel == WindowTransparencyLevel.Blur || - //// transparencyLevel == WindowTransparencyLevel.AcrylicBlur || - //// transparencyLevel == WindowTransparencyLevel.Mica) - //// { - //// transparencyLevel = WindowTransparencyLevel.AcrylicBlur; - //// } - - //// TransparencyLevel = transparencyLevel; - - //// _native.SetTransparencyMode(transparencyLevel == WindowTransparencyLevel.None - //// ? AvnWindowTransparencyMode.Opaque - //// : transparencyLevel == WindowTransparencyLevel.Transparent - //// ? AvnWindowTransparencyMode.Transparent - //// : AvnWindowTransparencyMode.Blur); - - //// TransparencyLevelChanged?.Invoke(TransparencyLevel); - ////} + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevels) + { + foreach (var level in transparencyLevels) + { + AvnWindowTransparencyMode? mode = null; + + if (level == WindowTransparencyLevel.None) + mode = AvnWindowTransparencyMode.Opaque; + if (level == WindowTransparencyLevel.Transparent) + mode = AvnWindowTransparencyMode.Transparent; + else if (level == WindowTransparencyLevel.AcrylicBlur) + mode = AvnWindowTransparencyMode.Blur; + + if (mode.HasValue) + { + _native?.SetTransparencyMode(mode.Value); + TransparencyLevel = level; + TransparencyLevelChanged?.Invoke(TransparencyLevel); + break; + } + } } public WindowTransparencyLevel TransparencyLevel { get; private set; } = WindowTransparencyLevel.None; From ac786d098b98399901140d7878822c085e1345e1 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 24 May 2023 15:33:03 +0200 Subject: [PATCH 098/219] Tweaked android logic. --- .../Platform/SkiaPlatform/TopLevelImpl.cs | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index 151227dba4..086de8f033 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -312,17 +312,32 @@ namespace Avalonia.Android.Platform.SkiaPlatform continue; } - if (level == WindowTransparencyLevel.None && OperatingSystem.IsAndroidVersionAtLeast(30)) + if (level == WindowTransparencyLevel.None) { - activity.SetTranslucent(false); + if (OperatingSystem.IsAndroidVersionAtLeast(30)) + { + activity.SetTranslucent(false); + } + + activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.White)); } else if (level == WindowTransparencyLevel.Transparent) { - SetTransparencyTransparent(activity); + if (OperatingSystem.IsAndroidVersionAtLeast(30)) + { + activity.SetTranslucent(true); + SetBlurBehind(activity, 0); + activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); + } } else if (level == WindowTransparencyLevel.Blur) { - SetTransparencyBlur(activity); + if (OperatingSystem.IsAndroidVersionAtLeast(31)) + { + activity.SetTranslucent(true); + SetBlurBehind(activity, 120); + activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); + } } TransparencyLevel = level; @@ -376,29 +391,13 @@ namespace Avalonia.Android.Platform.SkiaPlatform return false; } - private static void SetTransparencyTransparent(AvaloniaMainActivity activity) + private static void SetBlurBehind(AvaloniaMainActivity activity, int radius) { - if (OperatingSystem.IsAndroidVersionAtLeast(30)) - { - activity.SetTranslucent(true); - SetBlurBehindRadius(activity, 0); - activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); - } - } - - private static void SetTransparencyBlur(AvaloniaMainActivity activity) - { - if (OperatingSystem.IsAndroidVersionAtLeast(31)) - { - activity.SetTranslucent(true); + if (radius == 0) + activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); + else activity.Window?.AddFlags(WindowManagerFlags.BlurBehind); - SetBlurBehindRadius(activity, 120); - activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); - } - } - private static void SetBlurBehindRadius(AvaloniaMainActivity activity, int radius) - { if (OperatingSystem.IsAndroidVersionAtLeast(31) && activity.Window?.Attributes is { } attr) { attr.BlurBehindRadius = radius; From 966c5a0c5e2599aaf87a70ce196686320daa77e3 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 25 May 2023 16:14:06 +0200 Subject: [PATCH 099/219] Added ControlAutomationPeer.FromElement. --- .../Automation/Peers/ControlAutomationPeer.cs | 20 +++++++++++++++++++ src/Avalonia.Controls/Control.cs | 6 ++++++ 2 files changed, 26 insertions(+) diff --git a/src/Avalonia.Controls/Automation/Peers/ControlAutomationPeer.cs b/src/Avalonia.Controls/Automation/Peers/ControlAutomationPeer.cs index c55bd0f3e5..756951667b 100644 --- a/src/Avalonia.Controls/Automation/Peers/ControlAutomationPeer.cs +++ b/src/Avalonia.Controls/Automation/Peers/ControlAutomationPeer.cs @@ -31,11 +31,31 @@ namespace Avalonia.Automation.Peers return CreatePeerForElement(element); } + /// + /// Gets the for a , creating it if + /// necessary. + /// + /// The control. + /// The automation peer. + /// + /// Despite the name (which comes from the analogous WPF API), this method does not create + /// a new peer if one already exists: instead it returns the existing peer. + /// public static AutomationPeer CreatePeerForElement(Control element) { return element.GetOrCreateAutomationPeer(); } + /// + /// Gets an existing for a . + /// + /// The control. + /// The automation peer if already created; otherwise null. + /// + /// To ensure that a peer is created, use . + /// + public static AutomationPeer? FromElement(Control element) => element.GetAutomationPeer(); + protected override void BringIntoViewCore() => Owner.BringIntoView(); protected override IReadOnlyList GetOrCreateChildrenCore() diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs index 13e3978ca6..8d140bdd62 100644 --- a/src/Avalonia.Controls/Control.cs +++ b/src/Avalonia.Controls/Control.cs @@ -440,6 +440,12 @@ namespace Avalonia.Controls return new NoneAutomationPeer(this); } + internal AutomationPeer? GetAutomationPeer() + { + VerifyAccess(); + return _automationPeer; + } + internal AutomationPeer GetOrCreateAutomationPeer() { VerifyAccess(); From 215707ba7e30ad709d4d9adae2950376c7c9ee8a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 25 May 2023 19:44:52 +0100 Subject: [PATCH 100/219] add comments explaining and remove unnecessary condition. --- src/Avalonia.Base/Input/PointerEventArgs.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Base/Input/PointerEventArgs.cs b/src/Avalonia.Base/Input/PointerEventArgs.cs index 5db9266d06..383c807a73 100644 --- a/src/Avalonia.Base/Input/PointerEventArgs.cs +++ b/src/Avalonia.Base/Input/PointerEventArgs.cs @@ -70,10 +70,14 @@ namespace Avalonia.Input if (relativeTo == null) return pt; - if (!ReferenceEquals(_rootVisual, relativeTo.VisualRoot) && relativeTo.VisualRoot is Visual v) + // If the visual the user passed in, is not connected to the same visual root + // (i.e. they called it for a control inside a popup. + if (!ReferenceEquals(_rootVisual, relativeTo.VisualRoot)) { + // Convert to absolute screen coordinates. var screenPt = _rootVisual.PointToScreen(pt); + // Convert to client co-ordinates of the visual inside the other visual root. return relativeTo.PointToClient(screenPt); } From b3869981701114356fbb1b2fac6fdcbbf7757250 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 25 May 2023 19:45:06 +0100 Subject: [PATCH 101/219] remove template change. --- src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml b/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml index 567c9b72e7..87e954b630 100644 --- a/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml @@ -13,7 +13,6 @@ - - From b7568940c82848621bdcffa9b37af6665f75c821 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 25 May 2023 19:48:20 +0100 Subject: [PATCH 102/219] revert changes. --- .../ControlCatalog/Pages/CheckBoxPage.xaml | 43 ++++++++++--------- .../ControlCatalog/Pages/CheckBoxPage.xaml.cs | 16 +------ .../Controls/PopupRoot.xaml | 14 +++--- 3 files changed, 31 insertions(+), 42 deletions(-) diff --git a/samples/ControlCatalog/Pages/CheckBoxPage.xaml b/samples/ControlCatalog/Pages/CheckBoxPage.xaml index 78a8ff5550..2f60fc5dae 100644 --- a/samples/ControlCatalog/Pages/CheckBoxPage.xaml +++ b/samples/ControlCatalog/Pages/CheckBoxPage.xaml @@ -1,25 +1,28 @@ - - - - - - - - + x:Class="ControlCatalog.Pages.CheckBoxPage"> + + A check box control - - - - - - Popup Text - - - + + + _Unchecked + _Checked + _Indeterminate + Disabled + + + Three State: Unchecked + Three State: Checked + Three State: Indeterminate + Three State: Disabled - - + + diff --git a/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs b/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs index 60e75561e1..5027c94f5e 100644 --- a/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs +++ b/samples/ControlCatalog/Pages/CheckBoxPage.xaml.cs @@ -1,32 +1,18 @@ using Avalonia.Controls; -using Avalonia.Input; using Avalonia.Markup.Xaml; namespace ControlCatalog.Pages { - public partial class CheckBoxPage : UserControl + public class CheckBoxPage : UserControl { - private TextBlock myTb; - private int count; - public CheckBoxPage() { this.InitializeComponent(); - - myTb = this.FindControl("myTb"); - } private void InitializeComponent() { AvaloniaXamlLoader.Load(this); } - - protected override void OnPointerMoved(PointerEventArgs e) - { - base.OnPointerMoved(e); - - myTb.Text = e.GetPosition(this).ToString() + ", " + count++; - } } } diff --git a/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml b/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml index 87e954b630..5a924830b1 100644 --- a/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml @@ -13,13 +13,13 @@ - - - + + + From e2511344b8225817381db31af3c7e08f9a3ba4b0 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 25 May 2023 20:37:37 +0100 Subject: [PATCH 103/219] fix tests. --- src/Avalonia.Base/Input/PointerEventArgs.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Base/Input/PointerEventArgs.cs b/src/Avalonia.Base/Input/PointerEventArgs.cs index 383c807a73..9c24e5c314 100644 --- a/src/Avalonia.Base/Input/PointerEventArgs.cs +++ b/src/Avalonia.Base/Input/PointerEventArgs.cs @@ -72,7 +72,7 @@ namespace Avalonia.Input // If the visual the user passed in, is not connected to the same visual root // (i.e. they called it for a control inside a popup. - if (!ReferenceEquals(_rootVisual, relativeTo.VisualRoot)) + if (!ReferenceEquals(_rootVisual, relativeTo.VisualRoot) && relativeTo.VisualRoot is { }) { // Convert to absolute screen coordinates. var screenPt = _rootVisual.PointToScreen(pt); From 4954228f149af932993831debc4199255fbed584 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 25 May 2023 22:56:06 +0200 Subject: [PATCH 104/219] Fix display of unsupported transparency levels. Only make the window brush transparent when we requested a transparent window and were given one, otherwise we display a transparent brush for e.g. `None` because `None` is not available when using composition. --- samples/ControlCatalog/MainView.xaml.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/samples/ControlCatalog/MainView.xaml.cs b/samples/ControlCatalog/MainView.xaml.cs index 5e33952c68..801844a43c 100644 --- a/samples/ControlCatalog/MainView.xaml.cs +++ b/samples/ControlCatalog/MainView.xaml.cs @@ -85,7 +85,8 @@ namespace ControlCatalog var topLevel = (TopLevel)this.GetVisualRoot()!; topLevel.TransparencyLevelHint = new[] { selected }; - if (selected != WindowTransparencyLevel.None) + if (topLevel.ActualTransparencyLevel != WindowTransparencyLevel.None && + topLevel.ActualTransparencyLevel == selected) { var transparentBrush = new ImmutableSolidColorBrush(Colors.White, 0); var semiTransparentBrush = new ImmutableSolidColorBrush(Colors.Gray, 0.2); From e50816008ec7f517a73d5c72539d1cf8f965e448 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 25 May 2023 23:17:21 +0200 Subject: [PATCH 105/219] Set default transparency level. If no matching transparency level was found, use the default on all platforms. Raise `TransparencyLevelChanged` on all platforms. --- .../Platform/SkiaPlatform/TopLevelImpl.cs | 30 +++++++++++++- src/Avalonia.Native/WindowImplBase.cs | 27 ++++++++++--- src/Avalonia.X11/TransparencyHelper.cs | 40 ++++++++++--------- src/Windows/Avalonia.Win32/WindowImpl.cs | 32 +++++++++++++-- 4 files changed, 100 insertions(+), 29 deletions(-) diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index 086de8f033..6f9fdf3569 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -46,6 +46,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform private readonly AndroidInsetsManager _insetsManager; private readonly ClipboardImpl _clipboard; private ViewImpl _view; + private WindowTransparencyLevel _transparencyLevel; public TopLevelImpl(AvaloniaView avaloniaView, bool placeOnTop = false) { @@ -69,6 +70,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform _nativeControlHost = new AndroidNativeControlHostImpl(avaloniaView); _storageProvider = new AndroidStorageProvider((Activity)avaloniaView.Context); + _transparencyLevel = WindowTransparencyLevel.None; _systemNavigationManager = new AndroidSystemNavigationManagerImpl(avaloniaView.Context as IActivityNavigationService); } @@ -275,7 +277,18 @@ namespace Avalonia.Android.Platform.SkiaPlatform public Action LostFocus { get; set; } public Action TransparencyLevelChanged { get; set; } - public WindowTransparencyLevel TransparencyLevel { get; private set; } + public WindowTransparencyLevel TransparencyLevel + { + get => _transparencyLevel; + private set + { + if (_transparencyLevel != value) + { + _transparencyLevel = value; + TransparencyLevelChanged?.Invoke(value); + } + } + } public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { @@ -312,6 +325,11 @@ namespace Avalonia.Android.Platform.SkiaPlatform continue; } + if (level == TransparencyLevel) + { + return; + } + if (level == WindowTransparencyLevel.None) { if (OperatingSystem.IsAndroidVersionAtLeast(30)) @@ -341,8 +359,16 @@ namespace Avalonia.Android.Platform.SkiaPlatform } TransparencyLevel = level; - break; + return; } + + // If we get here, we didn't find a supported level. Use the default of None. + if (OperatingSystem.IsAndroidVersionAtLeast(30)) + { + activity.SetTranslucent(false); + } + + activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.White)); } public virtual object TryGetFeature(Type featureType) diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 0fe0c5e7c0..dfe30004b0 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -59,12 +59,12 @@ namespace Avalonia.Native private readonly IKeyboardDevice _keyboard; private readonly ICursorFactory _cursorFactory; private Size _savedLogicalSize; - private Size _lastRenderedLogicalSize; private double _savedScaling; private GlPlatformSurface _glSurface; private NativeControlHostImpl _nativeControlHost; private IStorageProvider _storageProvider; private PlatformBehaviorInhibition _platformBehaviorInhibition; + private WindowTransparencyLevel _transparencyLevel = WindowTransparencyLevel.None; internal WindowBaseImpl(IAvaloniaNativeFactory factory, AvaloniaNativePlatformOptions opts, AvaloniaNativeGlPlatformGraphics glFeature) @@ -498,17 +498,34 @@ namespace Avalonia.Native else if (level == WindowTransparencyLevel.AcrylicBlur) mode = AvnWindowTransparencyMode.Blur; - if (mode.HasValue) + if (mode.HasValue && level != TransparencyLevel) { _native?.SetTransparencyMode(mode.Value); TransparencyLevel = level; - TransparencyLevelChanged?.Invoke(TransparencyLevel); - break; + return; } } + + // If we get here, we didn't find a supported level. Use the default of None. + if (TransparencyLevel != WindowTransparencyLevel.None) + { + _native?.SetTransparencyMode(AvnWindowTransparencyMode.Opaque); + TransparencyLevel = WindowTransparencyLevel.None; + } } - public WindowTransparencyLevel TransparencyLevel { get; private set; } = WindowTransparencyLevel.None; + public WindowTransparencyLevel TransparencyLevel + { + get => _transparencyLevel; + private set + { + if (_transparencyLevel != value) + { + _transparencyLevel = value; + TransparencyLevelChanged?.Invoke(value); + } + } + } public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { diff --git a/src/Avalonia.X11/TransparencyHelper.cs b/src/Avalonia.X11/TransparencyHelper.cs index 01dccbf12a..3cc901e332 100644 --- a/src/Avalonia.X11/TransparencyHelper.cs +++ b/src/Avalonia.X11/TransparencyHelper.cs @@ -16,7 +16,19 @@ namespace Avalonia.X11 private bool _blurAtomsAreSet; public Action? TransparencyLevelChanged { get; set; } - public WindowTransparencyLevel CurrentLevel => _currentLevel; + + public WindowTransparencyLevel CurrentLevel + { + get => _currentLevel; + set + { + if (_currentLevel != value) + { + _currentLevel = value; + TransparencyLevelChanged?.Invoke(value); + } + } + } public TransparencyHelper(X11Info x11, IntPtr window, X11Globals globals) { @@ -28,7 +40,6 @@ namespace Avalonia.X11 public void SetTransparencyRequest(IReadOnlyList levels) { - WindowTransparencyLevel? newLevel = null; _requestedLevels = levels; foreach (var level in levels) @@ -37,25 +48,16 @@ namespace Avalonia.X11 continue; SetBlur(level == WindowTransparencyLevel.Blur); - newLevel = level; - break; - } - - // If no matching transparency level was found, revert to Transparent or None depending - // on whether composition is enabled. - if (!newLevel.HasValue) - { - newLevel = _globals.IsCompositionEnabled ? - WindowTransparencyLevel.Transparent : - WindowTransparencyLevel.None; - SetBlur(false); + CurrentLevel = level; + return; } - if (newLevel != _currentLevel) - { - _currentLevel = newLevel.Value; - TransparencyLevelChanged?.Invoke(newLevel.Value); - } + // If we get here, we didn't find a supported level. Use the defualt of Transparent or + // None, depending on whether composition is enabled. + SetBlur(false); + CurrentLevel = _globals.IsCompositionEnabled ? + WindowTransparencyLevel.Transparent : + WindowTransparencyLevel.None; } private bool IsSupported(WindowTransparencyLevel level) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index dc9cc7f50c..cb989cbc50 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -99,6 +99,7 @@ namespace Avalonia.Win32 private bool _hiddenWindowIsParent; private uint _langid; private bool _ignoreWmChar; + private WindowTransparencyLevel _transparencyLevel; private const int MaxPointerHistorySize = 512; private static readonly PooledList s_intermediatePointsPooledList = new(); @@ -183,6 +184,7 @@ namespace Avalonia.Win32 _storageProvider = new Win32StorageProvider(this); _nativeControlHost = new Win32NativeControlHost(this, _isUsingComposition); + _transparencyLevel = _isUsingComposition ? WindowTransparencyLevel.Transparent : WindowTransparencyLevel.None; s_instances.Add(this); } @@ -316,7 +318,18 @@ namespace Avalonia.Win32 } } - public WindowTransparencyLevel TransparencyLevel { get; private set; } + public WindowTransparencyLevel TransparencyLevel + { + get => _transparencyLevel; + private set + { + if (_transparencyLevel != value) + { + _transparencyLevel = value; + TransparencyLevelChanged?.Invoke(value); + } + } + } protected IntPtr Hwnd => _hwnd; @@ -355,7 +368,8 @@ namespace Avalonia.Win32 { if (!IsSupported(level, windowsVersion)) continue; - + if (level == TransparencyLevel) + return; if (level == WindowTransparencyLevel.Transparent) SetTransparencyTransparent(windowsVersion); else if (level == WindowTransparencyLevel.Blur) @@ -366,7 +380,19 @@ namespace Avalonia.Win32 SetTransparencyMica(windowsVersion); TransparencyLevel = level; - break; + return; + } + + // If we get here, we didn't find a supported level. Use the defualt of Transparent or + // None, depending on whether composition is enabled. + if (_isUsingComposition) + { + SetTransparencyTransparent(windowsVersion); + TransparencyLevel = WindowTransparencyLevel.Transparent; + } + else + { + TransparencyLevel = WindowTransparencyLevel.None; } } From 703e24ed57f8f29d8a1a205d609e8deafb528d14 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 25 May 2023 23:21:25 +0200 Subject: [PATCH 106/219] Make stub impls return None transparency. --- .../Embedding/Offscreen/OffscreenTopLevelImpl.cs | 2 +- src/Avalonia.DesignerSupport/Remote/Stubs.cs | 2 +- src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs | 7 +------ .../Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs | 2 +- src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs | 2 +- src/iOS/Avalonia.iOS/AvaloniaView.cs | 4 ++-- tests/Avalonia.UnitTests/CompositorTestServices.cs | 2 +- 7 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs index 28b43e8397..c267bced4a 100644 --- a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs +++ b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs @@ -91,7 +91,7 @@ namespace Avalonia.Controls.Embedding.Offscreen public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { } - public WindowTransparencyLevel TransparencyLevel { get; private set; } + public WindowTransparencyLevel TransparencyLevel => WindowTransparencyLevel.None; public IPopupImpl? CreatePopup() => null; diff --git a/src/Avalonia.DesignerSupport/Remote/Stubs.cs b/src/Avalonia.DesignerSupport/Remote/Stubs.cs index 28d1b147fd..a58b836667 100644 --- a/src/Avalonia.DesignerSupport/Remote/Stubs.cs +++ b/src/Avalonia.DesignerSupport/Remote/Stubs.cs @@ -185,7 +185,7 @@ namespace Avalonia.DesignerSupport.Remote { } - public WindowTransparencyLevel TransparencyLevel { get; private set; } + public WindowTransparencyLevel TransparencyLevel => WindowTransparencyLevel.None; public bool IsClientAreaExtendedToDecorations { get; } diff --git a/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs b/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs index c243a2a28b..e9ee191bb2 100644 --- a/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs +++ b/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs @@ -225,11 +225,6 @@ namespace Avalonia.Browser public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { - ////if (transparencyLevel == WindowTransparencyLevel.None - //// || transparencyLevel == WindowTransparencyLevel.Transparent) - ////{ - //// TransparencyLevel = transparencyLevel; - ////} } public Size ClientSize => _clientSize; @@ -249,7 +244,7 @@ namespace Avalonia.Browser public IMouseDevice MouseDevice { get; } = new MouseDevice(); public IKeyboardDevice KeyboardDevice { get; } = BrowserWindowingPlatform.Keyboard; - public WindowTransparencyLevel TransparencyLevel { get; private set; } + public WindowTransparencyLevel TransparencyLevel => WindowTransparencyLevel.None; public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { // not in the standard, but we potentially can use "apple-mobile-web-app-status-bar-style" for iOS and "theme-color" for android. diff --git a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs index 79408cd604..19c7d030af 100644 --- a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs +++ b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs @@ -77,7 +77,7 @@ using Avalonia.Rendering.Composition; public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { } - public WindowTransparencyLevel TransparencyLevel { get; private set; } + public WindowTransparencyLevel TransparencyLevel => WindowTransparencyLevel.None; public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { } diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs index 64f4352c25..24bdd41fb7 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs @@ -249,7 +249,7 @@ namespace Avalonia.Win32.Interop.Wpf public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { } - public WindowTransparencyLevel TransparencyLevel { get; private set; } + public WindowTransparencyLevel TransparencyLevel => WindowTransparencyLevel.None; public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { } diff --git a/src/iOS/Avalonia.iOS/AvaloniaView.cs b/src/iOS/Avalonia.iOS/AvaloniaView.cs index 605955e44f..c3e626343c 100644 --- a/src/iOS/Avalonia.iOS/AvaloniaView.cs +++ b/src/iOS/Avalonia.iOS/AvaloniaView.cs @@ -159,8 +159,8 @@ namespace Avalonia.iOS // legacy no-op public IMouseDevice MouseDevice { get; } = new MouseDevice(); - public WindowTransparencyLevel TransparencyLevel { get; } - + public WindowTransparencyLevel TransparencyLevel => WindowTransparencyLevel.None; + public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { // TODO adjust status bar depending on full screen mode. diff --git a/tests/Avalonia.UnitTests/CompositorTestServices.cs b/tests/Avalonia.UnitTests/CompositorTestServices.cs index 734baba54f..62e863d4f0 100644 --- a/tests/Avalonia.UnitTests/CompositorTestServices.cs +++ b/tests/Avalonia.UnitTests/CompositorTestServices.cs @@ -196,7 +196,7 @@ public class CompositorTestServices : IDisposable { } - public WindowTransparencyLevel TransparencyLevel { get; } + public WindowTransparencyLevel TransparencyLevel => WindowTransparencyLevel.None; public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { From d94c0670c82a321f82981607a2afdb61f7aa3e01 Mon Sep 17 00:00:00 2001 From: affederaffe <68356204+affederaffe@users.noreply.github.com> Date: Fri, 26 May 2023 00:59:35 +0200 Subject: [PATCH 107/219] Log DBus Exceptions --- .../ControlCatalog/Pages/DialogsPage.xaml.cs | 2 +- .../DBusIme/DBusTextInputMethodBase.cs | 3 +++ .../DBusIme/Fcitx/FcitxX11TextInputMethod.cs | 4 ++++ .../DBusIme/IBus/IBusX11TextInputMethod.cs | 7 +++++++ src/Avalonia.FreeDesktop/DBusSystemDialog.cs | 18 +++++++++++------- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs index 971a6a6718..4d617fd313 100644 --- a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs +++ b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs @@ -307,7 +307,7 @@ namespace ControlCatalog.Pages Content: "; - resultText += await ReadTextFromFile(file, 10000); + resultText += await ReadTextFromFile(file, 500); } openedFileContent.Text = resultText; diff --git a/src/Avalonia.FreeDesktop/DBusIme/DBusTextInputMethodBase.cs b/src/Avalonia.FreeDesktop/DBusIme/DBusTextInputMethodBase.cs index d3c14f285d..936e856cf0 100644 --- a/src/Avalonia.FreeDesktop/DBusIme/DBusTextInputMethodBase.cs +++ b/src/Avalonia.FreeDesktop/DBusIme/DBusTextInputMethodBase.cs @@ -76,7 +76,10 @@ namespace Avalonia.FreeDesktop.DBusIme private async void OnNameChange(Exception? e, (string ServiceName, string? OldOwner, string? NewOwner) args) { if (e is not null) + { + Logger.TryGet(LogEventLevel.Error, LogArea.FreeDesktopPlatform)?.Log(this, $"OnNameChange failed: {e}"); return; + } if (args.NewOwner is not null && _currentName is null) { diff --git a/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxX11TextInputMethod.cs b/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxX11TextInputMethod.cs index 1cf3507cc2..2eca5a1fef 100644 --- a/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxX11TextInputMethod.cs +++ b/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxX11TextInputMethod.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Avalonia.Input; using Avalonia.Input.Raw; using Avalonia.Input.TextInput; +using Avalonia.Logging; using Tmds.DBus.Protocol; using Tmds.DBus.SourceGenerator; @@ -138,7 +139,10 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx private void OnCommitString(Exception? e, string s) { if (e is not null) + { + Logger.TryGet(LogEventLevel.Error, LogArea.FreeDesktopPlatform)?.Log(this, $"OnCommitString failed: {e}"); return; + } FireCommit(s); } diff --git a/src/Avalonia.FreeDesktop/DBusIme/IBus/IBusX11TextInputMethod.cs b/src/Avalonia.FreeDesktop/DBusIme/IBus/IBusX11TextInputMethod.cs index 59e9ecd1cf..26fa971106 100644 --- a/src/Avalonia.FreeDesktop/DBusIme/IBus/IBusX11TextInputMethod.cs +++ b/src/Avalonia.FreeDesktop/DBusIme/IBus/IBusX11TextInputMethod.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Avalonia.Input; using Avalonia.Input.Raw; using Avalonia.Input.TextInput; +using Avalonia.Logging; using Tmds.DBus.Protocol; using Tmds.DBus.SourceGenerator; @@ -31,7 +32,10 @@ namespace Avalonia.FreeDesktop.DBusIme.IBus private void OnForwardKey(Exception? e, (uint keyval, uint keycode, uint state) k) { if (e is not null) + { + Logger.TryGet(LogEventLevel.Error, LogArea.FreeDesktopPlatform)?.Log(this, $"OnForwardKey failed: {e}"); return; + } var state = (IBusModifierMask)k.state; KeyModifiers mods = default; @@ -54,7 +58,10 @@ namespace Avalonia.FreeDesktop.DBusIme.IBus private void OnCommitText(Exception? e, DBusVariantItem variantItem) { if (e is not null) + { + Logger.TryGet(LogEventLevel.Error, LogArea.FreeDesktopPlatform)?.Log(this, $"OnCommitText failed: {e}"); return; + } if (variantItem.Value is DBusStructItem { Count: >= 3 } structItem && structItem[2] is DBusStringItem stringItem) FireCommit(stringItem.Value); diff --git a/src/Avalonia.FreeDesktop/DBusSystemDialog.cs b/src/Avalonia.FreeDesktop/DBusSystemDialog.cs index cd6f829d7a..f6964ab92a 100644 --- a/src/Avalonia.FreeDesktop/DBusSystemDialog.cs +++ b/src/Avalonia.FreeDesktop/DBusSystemDialog.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using System.Threading.Tasks; using Avalonia.Platform; using Avalonia.Platform.Storage; @@ -66,8 +67,9 @@ namespace Avalonia.FreeDesktop using var disposable = await request.WatchResponseAsync((e, x) => { if (e is not null) - return; - tsc.TrySetResult((x.results["uris"].Value as DBusArrayItem)?.Select(static y => (y as DBusStringItem)!.Value).ToArray()); + tsc.TrySetException(e); + else + tsc.TrySetResult((x.results["uris"].Value as DBusArrayItem)?.Select(static y => (y as DBusStringItem)!.Value).ToArray()); }); var uris = await tsc.Task ?? Array.Empty(); @@ -86,7 +88,7 @@ namespace Avalonia.FreeDesktop if (options.SuggestedFileName is { } currentName) chooserOptions.Add("current_name", new DBusVariantItem("s", new DBusStringItem(currentName))); if (options.SuggestedStartLocation?.TryGetLocalPath() is { } folderPath) - chooserOptions.Add("current_folder", new DBusVariantItem("s", new DBusStringItem(folderPath))); + chooserOptions.Add("current_folder", new DBusVariantItem("ay", new DBusArrayItem(DBusType.Byte, Encoding.UTF8.GetBytes(folderPath).Select(static x => new DBusByteItem(x))))); objectPath = await _fileChooser.SaveFileAsync(parentWindow, options.Title ?? string.Empty, chooserOptions); var request = new OrgFreedesktopPortalRequest(_connection, "org.freedesktop.portal.Desktop", objectPath); @@ -94,8 +96,9 @@ namespace Avalonia.FreeDesktop using var disposable = await request.WatchResponseAsync((e, x) => { if (e is not null) - return; - tsc.TrySetResult((x.results["uris"].Value as DBusArrayItem)?.Select(static y => (y as DBusStringItem)!.Value).ToArray()); + tsc.TrySetException(e); + else + tsc.TrySetResult((x.results["uris"].Value as DBusArrayItem)?.Select(static y => (y as DBusStringItem)!.Value).ToArray()); }); var uris = await tsc.Task; @@ -124,8 +127,9 @@ namespace Avalonia.FreeDesktop using var disposable = await request.WatchResponseAsync((e, x) => { if (e is not null) - return; - tsc.TrySetResult((x.results["uris"].Value as DBusArrayItem)?.Select(static y => (y as DBusStringItem)!.Value).ToArray()); + tsc.TrySetException(e); + else + tsc.TrySetResult((x.results["uris"].Value as DBusArrayItem)?.Select(static y => (y as DBusStringItem)!.Value).ToArray()); }); var uris = await tsc.Task ?? Array.Empty(); From ca046c06f57ad6df5b80ff2751dcbec8e6dffbde Mon Sep 17 00:00:00 2001 From: affederaffe <68356204+affederaffe@users.noreply.github.com> Date: Fri, 26 May 2023 00:59:57 +0200 Subject: [PATCH 108/219] Bump Tmds.DBus.SourceGenerator --- src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj b/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj index 31b65dcc02..779c41757a 100644 --- a/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj +++ b/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj @@ -13,7 +13,7 @@ - + From 7ee645bd7e6d9b0bbec29df6badfa8fb95b4ebb9 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 26 May 2023 10:00:36 +0200 Subject: [PATCH 109/219] Fix compile error. Accidentally removed this line - it's unused but unrelated to this PR so putting it back. --- src/Avalonia.Native/WindowImplBase.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index dfe30004b0..e1819ffddc 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -59,6 +59,7 @@ namespace Avalonia.Native private readonly IKeyboardDevice _keyboard; private readonly ICursorFactory _cursorFactory; private Size _savedLogicalSize; + private Size _lastRenderedLogicalSize; private double _savedScaling; private GlPlatformSurface _glSurface; private NativeControlHostImpl _nativeControlHost; From a78c41dd41a8dc699dbc64dafe5b535f62f5062c Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 26 May 2023 11:20:01 +0100 Subject: [PATCH 110/219] add a unit test. --- .../Primitives/PopupTests.cs | 70 ++++++++++++++++++- .../MockWindowingPlatform.cs | 17 +++++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs index 51399d1202..e307a80441 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs @@ -19,6 +19,7 @@ using Avalonia.Rendering; using System.Threading.Tasks; using Avalonia.Threading; using Avalonia.Interactivity; +using Avalonia.Media; namespace Avalonia.Controls.UnitTests.Primitives { @@ -1076,10 +1077,77 @@ namespace Avalonia.Controls.UnitTests.Primitives } } + [Fact] + public void GetPosition_On_Control_In_Popup_Called_From_Parent_Should_Return_Valid_Coordinates() + { + using (CreateServices()) + { + var popupContent = new Border() { Height = 100, Width = 100, Background = Brushes.Red }; + var popup = new Popup { Child = popupContent, HorizontalOffset = 40, VerticalOffset = 40, Placement = PlacementMode.AnchorAndGravity, + PlacementAnchor = PopupAnchor.TopLeft, PlacementGravity = PopupGravity.BottomRight}; + var popupParent = new Border { Child = popup }; + var root = PreparedWindow(popupParent); + + var raised = 0; + + root.LayoutManager.ExecuteInitialLayoutPass(); + popup.Open(); + root.LayoutManager.ExecuteLayoutPass(); + + var pointer = new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true); + + var pts = popupContent.PointToScreen(new Point(10, 10)); + + Assert.Equal(new PixelPoint(50, 50), pts); + + var ev = new PointerPressedEventArgs( + popupContent, + pointer, + popupContent.VisualRoot as PopupRoot, + new Point(50 , 50), + 0, + new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.LeftButtonPressed), + KeyModifiers.None); + + Point pointRelativeToWindowContent = default; + + popupParent.AddHandler(Button.PointerPressedEvent, (s, e) => + { + ++raised; + + pointRelativeToWindowContent = e.GetPosition(popupParent); + }); + + popupContent.RaiseEvent(ev); + + Assert.Equal(1, raised); + Assert.Equal(new Point(90, 90), pointRelativeToWindowContent); + } + } + + private static PopupRoot CreateRoot(TopLevel popupParent, IPopupImpl impl = null) + { + impl ??= popupParent.PlatformImpl.CreatePopup(); + + var result = new PopupRoot(popupParent, impl) + { + Template = new FuncControlTemplate((parent, scope) => + new ContentPresenter + { + Name = "PART_ContentPresenter", + [!ContentPresenter.ContentProperty] = parent[!PopupRoot.ContentProperty], + }.RegisterInNameScope(scope)), + }; + + result.ApplyTemplate(); + + return result; + } + private IDisposable CreateServices() { return UnitTestApplication.Start(TestServices.StyledWindow.With(windowingPlatform: - new MockWindowingPlatform(null, + new MockWindowingPlatform(() => MockWindowingPlatform.CreateWindowMock().Object, x => { if(UsePopupHost) diff --git a/tests/Avalonia.UnitTests/MockWindowingPlatform.cs b/tests/Avalonia.UnitTests/MockWindowingPlatform.cs index ca71a97a6e..65612e45a0 100644 --- a/tests/Avalonia.UnitTests/MockWindowingPlatform.cs +++ b/tests/Avalonia.UnitTests/MockWindowingPlatform.cs @@ -55,6 +55,12 @@ namespace Avalonia.UnitTests windowImpl.Object.PositionChanged?.Invoke(x); }); + windowImpl.Setup(x => x.PointToScreen(It.IsAny())) + .Returns((point) => PixelPoint.FromPoint(point, 1) + position); + + windowImpl.Setup(x => x.PointToClient(It.IsAny())) + .Returns(point => (point - position).ToPoint(1)); + windowImpl.Setup(x => x.Resize(It.IsAny(), It.IsAny())) .Callback((x, y) => { @@ -83,10 +89,12 @@ namespace Avalonia.UnitTests { var popupImpl = new Mock(); var clientSize = new Size(); + var position = new PixelPoint(); var positionerHelper = new ManagedPopupPositionerPopupImplHelper(parent, (pos, size, scale) => { clientSize = size.Constrain(s_screenSize); + position = pos; popupImpl.Object.PositionChanged?.Invoke(pos); popupImpl.Object.Resized?.Invoke(clientSize, WindowResizeReason.Unspecified); }); @@ -100,6 +108,15 @@ namespace Avalonia.UnitTests popupImpl.Setup(x => x.MaxAutoSizeHint).Returns(s_screenSize); popupImpl.Setup(x => x.RenderScaling).Returns(1); popupImpl.Setup(x => x.PopupPositioner).Returns(positioner); + popupImpl.Setup(x => x.Position).Returns(()=>position); + + popupImpl.Setup(x => x.PointToScreen(It.IsAny())) + .Returns((point) => PixelPoint.FromPoint(point, 1) + position); + + popupImpl.Setup(x => x.PointToClient(It.IsAny())) + .Returns(point => (point - position).ToPoint(1)); + + popupImpl.Setup(r => r.TryGetFeature(It.IsAny())).Returns(null); popupImpl.Setup(x => x.Dispose()).Callback(() => From f4beb593f5fc6dd4764c37c050c3b8f73aba428b Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 26 May 2023 12:31:38 +0200 Subject: [PATCH 111/219] Fix compile error. --- src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs b/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs index e9ee191bb2..eed64e59bf 100644 --- a/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs +++ b/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs @@ -39,7 +39,6 @@ namespace Avalonia.Browser { Surfaces = Enumerable.Empty(); _avaloniaView = avaloniaView; - TransparencyLevel = WindowTransparencyLevel.None; AcrylicCompensationLevels = new AcrylicPlatformCompensationLevels(1, 1, 1); _touchDevice = new TouchDevice(); _penDevice = new PenDevice(); From 460ea0e093535966c100b80c3b96338d43bafa16 Mon Sep 17 00:00:00 2001 From: Benedikt Stebner Date: Fri, 26 May 2023 13:24:27 +0200 Subject: [PATCH 112/219] Rework TextLine GetTextBounds and GetDistanceFromCharacterHit Fix TextAlignment.Right offset calculation --- src/Avalonia.Base/Media/CharacterHit.cs | 1 + .../Media/TextFormatting/BidiReorderer.cs | 74 ++- .../Media/TextFormatting/IndexedTextRun.cs | 10 + .../Media/TextFormatting/TextBounds.cs | 2 + .../Media/TextFormatting/TextLineImpl.cs | 594 +++++++----------- .../Media/TextFormatting/TextLineTests.cs | 49 ++ 6 files changed, 328 insertions(+), 402 deletions(-) create mode 100644 src/Avalonia.Base/Media/TextFormatting/IndexedTextRun.cs diff --git a/src/Avalonia.Base/Media/CharacterHit.cs b/src/Avalonia.Base/Media/CharacterHit.cs index 6bbbff4f5b..27cf3a42dc 100644 --- a/src/Avalonia.Base/Media/CharacterHit.cs +++ b/src/Avalonia.Base/Media/CharacterHit.cs @@ -19,6 +19,7 @@ namespace Avalonia.Media /// Index of the first character that got hit. /// In the case of a leading edge, this value is 0. In the case of a trailing edge, /// this value is the number of code points until the next valid caret position. + [DebuggerStepThrough] public CharacterHit(int firstCharacterIndex, int trailingLength = 0) { FirstCharacterIndex = firstCharacterIndex; diff --git a/src/Avalonia.Base/Media/TextFormatting/BidiReorderer.cs b/src/Avalonia.Base/Media/TextFormatting/BidiReorderer.cs index 4db55fae6d..39ef8cce48 100644 --- a/src/Avalonia.Base/Media/TextFormatting/BidiReorderer.cs +++ b/src/Avalonia.Base/Media/TextFormatting/BidiReorderer.cs @@ -18,14 +18,14 @@ namespace Avalonia.Media.TextFormatting public static BidiReorderer Instance => t_instance ??= new(); - public void BidiReorder(Span textRuns, FlowDirection flowDirection) + public IndexedTextRun[] BidiReorder(Span textRuns, FlowDirection flowDirection, int firstTextSourceIndex) { Debug.Assert(_runs.Length == 0); Debug.Assert(_ranges.Length == 0); if (textRuns.IsEmpty) { - return; + return Array.Empty(); } try @@ -46,6 +46,22 @@ namespace Avalonia.Media.TextFormatting // Reorder them into visual order. var firstIndex = LinearReorder(); + var indexedTextRuns = new IndexedTextRun[textRuns.Length]; + + for (var i = 0; i < textRuns.Length; i++) + { + var currentRun = textRuns[i]; + + indexedTextRuns[i] = new IndexedTextRun + { + TextRun = currentRun, + TextSourceCharacterIndex = firstTextSourceIndex, + RunIndex = i, + NextRunIndex = i + 1 + }; + + firstTextSourceIndex += currentRun.Length; + } // Now perform a recursive reversal of each run. // From the highest level found in the text to the lowest odd level on each line, including intermediate levels @@ -76,7 +92,7 @@ namespace Avalonia.Media.TextFormatting if (max == 0 || (min == max && (max & 1) == 0)) { // Nothing to reverse. - return; + return indexedTextRuns; } // Now apply the reversal and replace the original contents. @@ -107,13 +123,25 @@ namespace Avalonia.Media.TextFormatting var index = 0; currentIndex = firstIndex; + while (currentIndex >= 0) { ref var current = ref _runs[currentIndex]; - textRuns[index++] = current.Run; + + textRuns[index] = current.Run; + + var indexedRun = indexedTextRuns[index]; + + indexedRun.RunIndex = current.RunIndex; + + indexedRun.NextRunIndex = current.NextRunIndex; + + index++; currentIndex = current.NextRunIndex; } + + return indexedTextRuns; } finally { @@ -227,25 +255,6 @@ namespace Avalonia.Media.TextFormatting return previousIndex; } - private struct OrderedBidiRun - { - public OrderedBidiRun(int runIndex, TextRun run, sbyte level) - { - RunIndex = runIndex; - Run = run; - Level = level; - NextRunIndex = -1; - } - - public int RunIndex { get; } - - public sbyte Level { get; } - - public TextRun Run { get; } - - public int NextRunIndex { get; set; } // -1 if none - } - private struct BidiRange { public BidiRange(sbyte level, int leftRunIndex, int rightRunIndex, int previousRangeIndex) @@ -265,4 +274,23 @@ namespace Avalonia.Media.TextFormatting public int PreviousRangeIndex { get; } // -1 if none } } + + internal struct OrderedBidiRun + { + public OrderedBidiRun(int runIndex, TextRun run, sbyte level) + { + RunIndex = runIndex; + Run = run; + Level = level; + NextRunIndex = -1; + } + + public int RunIndex { get; } + + public sbyte Level { get; } + + public TextRun Run { get; } + + public int NextRunIndex { get; set; } // -1 if none + } } diff --git a/src/Avalonia.Base/Media/TextFormatting/IndexedTextRun.cs b/src/Avalonia.Base/Media/TextFormatting/IndexedTextRun.cs new file mode 100644 index 0000000000..0eb98533d2 --- /dev/null +++ b/src/Avalonia.Base/Media/TextFormatting/IndexedTextRun.cs @@ -0,0 +1,10 @@ +namespace Avalonia.Media.TextFormatting +{ + internal class IndexedTextRun + { + public int TextSourceCharacterIndex { get; init; } + public int RunIndex { get; set; } + public int NextRunIndex { get; set; } + public TextRun? TextRun { get; init; } + } +} diff --git a/src/Avalonia.Base/Media/TextFormatting/TextBounds.cs b/src/Avalonia.Base/Media/TextFormatting/TextBounds.cs index 93edf68348..946c2e6931 100644 --- a/src/Avalonia.Base/Media/TextFormatting/TextBounds.cs +++ b/src/Avalonia.Base/Media/TextFormatting/TextBounds.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics; namespace Avalonia.Media.TextFormatting { @@ -10,6 +11,7 @@ namespace Avalonia.Media.TextFormatting /// /// Constructing TextBounds object /// + [DebuggerStepThrough] internal TextBounds(Rect bounds, FlowDirection flowDirection, IList runBounds) { Rectangle = bounds; diff --git a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs index a0d7cabefd..ae2dbe0c8c 100644 --- a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs +++ b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs @@ -4,8 +4,12 @@ using Avalonia.Utilities; namespace Avalonia.Media.TextFormatting { - internal sealed class TextLineImpl : TextLine + internal class TextLineImpl : TextLine { + internal static Comparer TextBoundsComparer { get; } = + Comparer.Create((x, y) => x.Rectangle.Left.CompareTo(y.Rectangle.Left)); + + private IReadOnlyList? _indexedTextRuns; private readonly TextRun[] _textRuns; private readonly double _paragraphWidth; private readonly TextParagraphProperties _paragraphProperties; @@ -338,184 +342,171 @@ namespace Avalonia.Media.TextFormatting /// public override double GetDistanceFromCharacterHit(CharacterHit characterHit) { - var flowDirection = _paragraphProperties.FlowDirection; - var characterIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength; - var currentPosition = FirstTextSourceIndex; - var remainingLength = characterIndex - FirstTextSourceIndex; - - var currentDistance = Start; - - if (flowDirection == FlowDirection.LeftToRight) + if (_indexedTextRuns is null || _indexedTextRuns.Count == 0) { - for (var index = 0; index < _textRuns.Length; index++) - { - var currentRun = _textRuns[index]; - - if (currentRun is ShapedTextRun shapedRun && !shapedRun.ShapedBuffer.IsLeftToRight) - { - var i = index; - - var rightToLeftWidth = shapedRun.Size.Width; - - while (i + 1 <= _textRuns.Length - 1) - { - var nextRun = _textRuns[i + 1]; + return Start; + } - if (nextRun is ShapedTextRun nextShapedRun && !nextShapedRun.ShapedBuffer.IsLeftToRight) - { - i++; + var characterIndex = Math.Min( + characterHit.FirstCharacterIndex + characterHit.TrailingLength, + FirstTextSourceIndex + Length); - rightToLeftWidth += nextShapedRun.Size.Width; + var currentPosition = FirstTextSourceIndex; - continue; - } + static FlowDirection GetDirection(TextRun textRun, FlowDirection currentDirection) + { + if (textRun is ShapedTextRun shapedTextRun) + { + return shapedTextRun.ShapedBuffer.IsLeftToRight ? + FlowDirection.LeftToRight : + FlowDirection.RightToLeft; + } - break; - } + return currentDirection; + } - if (i > index) - { - while (i >= index) - { - currentRun = _textRuns[i]; + IndexedTextRun FindIndexedRun() + { + var i = 0; - if (currentRun is DrawableTextRun drawable) - { - rightToLeftWidth -= drawable.Size.Width; - } + IndexedTextRun currentIndexedRun = _indexedTextRuns[i]; - if (currentPosition + currentRun.Length >= characterIndex) - { - break; - } + while(currentIndexedRun.TextSourceCharacterIndex != currentPosition) + { + if(i + 1 < _indexedTextRuns.Count) + { + i++; - currentPosition += currentRun.Length; + currentIndexedRun = _indexedTextRuns[i]; + } - remainingLength -= currentRun.Length; + break; + } - i--; - } + return currentIndexedRun; + } - currentDistance += rightToLeftWidth; - } - } + double GetPreceedingDistance(int firstIndex) + { + var distance = 0.0; - if (currentPosition + currentRun.Length >= characterIndex && - TryGetDistanceFromCharacterHit(currentRun, characterHit, currentPosition, remainingLength, flowDirection, out var distance, out _)) - { - return Math.Max(0, currentDistance + distance); - } + for (var i = 0; i < firstIndex; i++) + { + var currentRun = _textRuns[i]; if (currentRun is DrawableTextRun drawableTextRun) { - currentDistance += drawableTextRun.Size.Width; + distance += drawableTextRun.Size.Width; } - - //No hit hit found so we add the full width - - currentPosition += currentRun.Length; - remainingLength -= currentRun.Length; } + + return distance; } - else + + TextRun? currentTextRun = null; + var currentIndexedRun = FindIndexedRun(); + + while (currentPosition < FirstTextSourceIndex + Length) { - currentDistance += WidthIncludingTrailingWhitespace; + currentTextRun = currentIndexedRun.TextRun; - for (var index = _textRuns.Length - 1; index >= 0; index--) + if (currentTextRun == null) { - var currentRun = _textRuns[index]; + break; + } - if (TryGetDistanceFromCharacterHit(currentRun, characterHit, currentPosition, remainingLength, - flowDirection, out var distance, out var currentGlyphRun)) + if (currentIndexedRun.TextSourceCharacterIndex + currentTextRun.Length <= characterHit.FirstCharacterIndex) + { + if (currentPosition + currentTextRun.Length < FirstTextSourceIndex + Length) { - if (currentGlyphRun != null) - { - currentDistance -= currentGlyphRun.Bounds.Width; - } + currentPosition += currentTextRun.Length; - return currentDistance + distance; - } + currentIndexedRun = FindIndexedRun(); - if (currentRun is DrawableTextRun drawableTextRun) - { - currentDistance -= drawableTextRun.Size.Width; + continue; } - - //No hit hit found so we add the full width - currentPosition += currentRun.Length; - remainingLength -= currentRun.Length; } + + break; } - return Math.Max(0, currentDistance); - } + if (currentTextRun == null) + { + return 0; + } - private static bool TryGetDistanceFromCharacterHit( - TextRun currentRun, - CharacterHit characterHit, - int currentPosition, - int remainingLength, - FlowDirection flowDirection, - out double distance, - out GlyphRun? currentGlyphRun) - { - var characterIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength; - var isTrailingHit = characterHit.TrailingLength > 0; + var directionalWidth = 0.0; + var firstRunIndex = currentIndexedRun.RunIndex; + var lastRunIndex = firstRunIndex; - distance = 0; - currentGlyphRun = null; + var currentDirection = GetDirection(currentTextRun, _resolvedFlowDirection); - switch (currentRun) + var currentX = Start + GetPreceedingDistance(currentIndexedRun.RunIndex); + + if (currentTextRun is DrawableTextRun currentDrawable) { - case ShapedTextRun shapedTextCharacters: - { - currentGlyphRun = shapedTextCharacters.GlyphRun; + directionalWidth = currentDrawable.Size.Width; + } - if (currentPosition + remainingLength <= currentPosition + currentRun.Length) - { - characterHit = new CharacterHit(currentPosition + remainingLength); + if (currentTextRun is not TextEndOfLine) + { + if (currentDirection == FlowDirection.LeftToRight) + { + // Find consecutive runs of same direction + for (; lastRunIndex + 1 < _textRuns.Length; lastRunIndex++) + { + var nextRun = _textRuns[lastRunIndex + 1]; - distance = currentGlyphRun.GetDistanceFromCharacterHit(characterHit); + var nextDirection = GetDirection(nextRun, currentDirection); - return true; + if (currentDirection != nextDirection) + { + break; } - if (currentPosition + remainingLength == currentPosition + currentRun.Length && isTrailingHit) + if (nextRun is DrawableTextRun nextDrawable) { - if (currentGlyphRun.IsLeftToRight || flowDirection == FlowDirection.RightToLeft) - { - distance = currentGlyphRun.Bounds.Width; - } - - return true; + directionalWidth += nextDrawable.Size.Width; } - - break; } - case DrawableTextRun drawableTextRun: + } + else + { + // Find consecutive runs of same direction + for (; firstRunIndex - 1 > 0; firstRunIndex--) { - if (characterIndex == currentPosition) + var previousRun = _textRuns[firstRunIndex - 1]; + + var previousDirection = GetDirection(previousRun, currentDirection); + + if (currentDirection != previousDirection) { - return true; + break; } - if (characterIndex == currentPosition + currentRun.Length) + if (previousRun is DrawableTextRun previousDrawable) { - distance = drawableTextRun.Size.Width; - - return true; + directionalWidth += previousDrawable.Size.Width; + currentX -= previousDrawable.Size.Width; } + } + } + } - break; + switch (currentDirection) + { + case FlowDirection.RightToLeft: + { + return GetTextRunBoundsRightToLeft(firstRunIndex, lastRunIndex, currentX + directionalWidth, characterIndex, + currentPosition, 1, out _, out _).Rectangle.Right; } default: { - return false; + return GetTextBoundsLeftToRight(firstRunIndex, lastRunIndex, currentX, characterIndex, + currentPosition, 1, out _, out _).Rectangle.Left; } } - - return false; } /// @@ -585,7 +576,7 @@ namespace Avalonia.Media.TextFormatting public override IReadOnlyList GetTextBounds(int firstTextSourceIndex, int textLength) { - if (_textRuns.Length == 0) + if (_indexedTextRuns is null || _indexedTextRuns.Count == 0) { return Array.Empty(); } @@ -607,303 +598,156 @@ namespace Avalonia.Media.TextFormatting return currentDirection; } - if (_paragraphProperties.FlowDirection == FlowDirection.LeftToRight) + IndexedTextRun FindIndexedRun() { - var currentX = Start; + var i = 0; - for (int i = 0; i < _textRuns.Length; i++) - { - var currentRun = _textRuns[i]; + IndexedTextRun currentIndexedRun = _indexedTextRuns[i]; - var firstRunIndex = i; - var lastRunIndex = firstRunIndex; - var currentDirection = GetDirection(currentRun, FlowDirection.LeftToRight); - var directionalWidth = 0.0; - - if (currentRun is DrawableTextRun currentDrawable) + while (currentIndexedRun.TextSourceCharacterIndex != currentPosition) + { + if (i + 1 < _indexedTextRuns.Count) { - directionalWidth = currentDrawable.Size.Width; + i++; + + currentIndexedRun = _indexedTextRuns[i]; } - // Find consecutive runs of same direction - for (; lastRunIndex + 1 < _textRuns.Length; lastRunIndex++) - { - var nextRun = _textRuns[lastRunIndex + 1]; + break; + } - var nextDirection = GetDirection(nextRun, currentDirection); + return currentIndexedRun; + } - if (currentDirection != nextDirection) - { - break; - } + double GetPreceedingDistance(int firstIndex) + { + var distance = 0.0; - if (nextRun is DrawableTextRun nextDrawable) - { - directionalWidth += nextDrawable.Size.Width; - } - } + for (var i = 0; i < firstIndex; i++) + { + var currentRun = _textRuns[i]; - //Skip runs that are not part of the hit test range - switch (currentDirection) + if (currentRun is DrawableTextRun drawableTextRun) { - case FlowDirection.RightToLeft: - { - for (; lastRunIndex >= firstRunIndex; lastRunIndex--) - { - currentRun = _textRuns[lastRunIndex]; + distance += drawableTextRun.Size.Width; + } + } - if (currentPosition + currentRun.Length > firstTextSourceIndex) - { - break; - } + return distance; + } - currentPosition += currentRun.Length; + while (remainingLength > 0 && currentPosition < FirstTextSourceIndex + Length) + { + var currentIndexedRun = FindIndexedRun(); - if (currentRun is DrawableTextRun drawableTextRun) - { - directionalWidth -= drawableTextRun.Size.Width; - currentX += drawableTextRun.Size.Width; - } + if (currentIndexedRun == null) + { + break; + } - if (lastRunIndex - 1 < 0) - { - break; - } - } + var directionalWidth = 0.0; + var firstRunIndex = currentIndexedRun.RunIndex; + var lastRunIndex = firstRunIndex; + var currentTextRun = currentIndexedRun.TextRun; - break; - } - default: - { - for (; firstRunIndex <= lastRunIndex; firstRunIndex++) - { - currentRun = _textRuns[firstRunIndex]; - - if (currentPosition + currentRun.Length > firstTextSourceIndex) - { - break; - } + if (currentTextRun == null) + { + break; + } - currentPosition += currentRun.Length; + var currentDirection = GetDirection(currentTextRun, _resolvedFlowDirection); - if (currentRun is DrawableTextRun drawableTextRun) - { - currentX += drawableTextRun.Size.Width; - directionalWidth -= drawableTextRun.Size.Width; - } + if (currentIndexedRun.TextSourceCharacterIndex + currentTextRun.Length <= firstTextSourceIndex) + { + currentPosition += currentTextRun.Length; - if (firstRunIndex + 1 == _textRuns.Length) - { - break; - } - } + continue; + } - break; - } - } + var currentX = Start + GetPreceedingDistance(currentIndexedRun.RunIndex); - i = lastRunIndex; + if (currentTextRun is DrawableTextRun currentDrawable) + { + directionalWidth = currentDrawable.Size.Width; + } - //Possible overlap at runs of different direction - if (directionalWidth == 0 && i < _textRuns.Length - 1) + if (currentTextRun is not TextEndOfLine) + { + if (currentDirection == FlowDirection.LeftToRight) { - //In case a run only contains a linebreak we don't want to skip it. - if (currentRun is ShapedTextRun shaped) - { - if (currentRun.Length - shaped.GlyphRun.Metrics.NewLineLength > 0) - { - continue; - } - } - else + // Find consecutive runs of same direction + for (; lastRunIndex + 1 < _textRuns.Length; lastRunIndex++) { - continue; - } - } + var nextRun = _textRuns[lastRunIndex + 1]; - int coveredLength; - TextBounds? textBounds; + var nextDirection = GetDirection(nextRun, currentDirection); - switch (currentDirection) - { - - case FlowDirection.RightToLeft: + if (currentDirection != nextDirection) { - textBounds = GetTextRunBoundsRightToLeft(firstRunIndex, lastRunIndex, currentX + directionalWidth, firstTextSourceIndex, - currentPosition, remainingLength, out coveredLength, out currentPosition); - - currentX += directionalWidth; - break; } - default: - { - textBounds = GetTextBoundsLeftToRight(firstRunIndex, lastRunIndex, currentX, firstTextSourceIndex, - currentPosition, remainingLength, out coveredLength, out currentPosition); - currentX = textBounds.Rectangle.Right; - - break; + if (nextRun is DrawableTextRun nextDrawable) + { + directionalWidth += nextDrawable.Size.Width; } + } } - - if (coveredLength > 0) - { - result.Add(textBounds); - - remainingLength -= coveredLength; - } - - if (remainingLength <= 0) - { - break; - } - } - } - else - { - var currentX = Start + WidthIncludingTrailingWhitespace; - - for (int i = _textRuns.Length - 1; i >= 0; i--) - { - var currentRun = _textRuns[i]; - var firstRunIndex = i; - var lastRunIndex = firstRunIndex; - var currentDirection = GetDirection(currentRun, FlowDirection.RightToLeft); - var directionalWidth = 0.0; - - if (currentRun is DrawableTextRun currentDrawable) - { - directionalWidth = currentDrawable.Size.Width; - } - - // Find consecutive runs of same direction - for (; firstRunIndex - 1 > 0; firstRunIndex--) + else { - var previousRun = _textRuns[firstRunIndex - 1]; - - var previousDirection = GetDirection(previousRun, currentDirection); - - if (currentDirection != previousDirection) + // Find consecutive runs of same direction + for (; firstRunIndex - 1 > 0; firstRunIndex--) { - break; - } + var previousRun = _textRuns[firstRunIndex - 1]; - if (currentRun is DrawableTextRun previousDrawable) - { - directionalWidth += previousDrawable.Size.Width; - } - } + var previousDirection = GetDirection(previousRun, currentDirection); - //Skip runs that are not part of the hit test range - switch (currentDirection) - { - case FlowDirection.RightToLeft: + if (currentDirection != previousDirection) { - for (; lastRunIndex >= firstRunIndex; lastRunIndex--) - { - currentRun = _textRuns[lastRunIndex]; - - if (currentPosition + currentRun.Length <= firstTextSourceIndex) - { - currentPosition += currentRun.Length; - - if (currentRun is DrawableTextRun drawableTextRun) - { - currentX -= drawableTextRun.Size.Width; - directionalWidth -= drawableTextRun.Size.Width; - } - - continue; - } - - break; - } - break; } - default: - { - for (; firstRunIndex <= lastRunIndex; firstRunIndex++) - { - currentRun = _textRuns[firstRunIndex]; - - if (currentPosition + currentRun.Length <= firstTextSourceIndex) - { - currentPosition += currentRun.Length; - - if (currentRun is DrawableTextRun drawableTextRun) - { - currentX += drawableTextRun.Size.Width; - directionalWidth -= drawableTextRun.Size.Width; - } - continue; - } - - break; - } + if (previousRun is DrawableTextRun previousDrawable) + { + directionalWidth += previousDrawable.Size.Width; - break; + currentX -= previousDrawable.Size.Width; } + } } + } - i = firstRunIndex; + int coveredLength; + TextBounds? textBounds; - //Possible overlap at runs of different direction - if (directionalWidth == 0 && i > 0) - { - //In case a run only contains a linebreak we don't want to skip it. - if (currentRun is ShapedTextRun shaped) + switch (currentDirection) + { + case FlowDirection.RightToLeft: { - if (currentRun.Length - shaped.GlyphRun.Metrics.NewLineLength > 0) - { - continue; - } + textBounds = GetTextRunBoundsRightToLeft(firstRunIndex, lastRunIndex, currentX + directionalWidth, firstTextSourceIndex, + currentPosition, remainingLength, out coveredLength, out currentPosition); + + break; } - else + default: { - continue; - } - } - - int coveredLength; - TextBounds? textBounds; - - switch (currentDirection) - { - case FlowDirection.LeftToRight: - { - textBounds = GetTextBoundsLeftToRight(firstRunIndex, lastRunIndex, currentX - directionalWidth, firstTextSourceIndex, - currentPosition, remainingLength, out coveredLength, out currentPosition); - - currentX -= directionalWidth; - - break; - } - default: - { - textBounds = GetTextRunBoundsRightToLeft(firstRunIndex, lastRunIndex, currentX, firstTextSourceIndex, - currentPosition, remainingLength, out coveredLength, out currentPosition); - - currentX = textBounds.Rectangle.Left; + textBounds = GetTextBoundsLeftToRight(firstRunIndex, lastRunIndex, currentX, firstTextSourceIndex, + currentPosition, remainingLength, out coveredLength, out currentPosition); - break; - } - } + break; + } + } - //Visual order is always left to right so we need to insert - result.Insert(0, textBounds); + if (coveredLength > 0) + { + result.Add(textBounds); remainingLength -= coveredLength; - - if (remainingLength <= 0) - { - break; - } } } + result.Sort(TextBoundsComparer); + return result; } @@ -1164,7 +1008,7 @@ namespace Avalonia.Media.TextFormatting _textLineBreak = new TextLineBreak(textEndOfLine); } - BidiReorderer.Instance.BidiReorder(_textRuns, _resolvedFlowDirection); + _indexedTextRuns = BidiReorderer.Instance.BidiReorder(_textRuns, _paragraphProperties.FlowDirection, FirstTextSourceIndex); } /// @@ -1211,13 +1055,6 @@ namespace Avalonia.Media.TextFormatting return true; } - //var characterIndex = codepointIndex - shapedRun.Text.Start; - - //if (characterIndex < 0 && shapedRun.ShapedBuffer.IsLeftToRight) - //{ - // foundCharacterHit = new CharacterHit(foundCharacterHit.FirstCharacterIndex); - //} - nextCharacterHit = isAtEnd || characterHit.TrailingLength != 0 ? foundCharacterHit : new CharacterHit(foundCharacterHit.FirstCharacterIndex + foundCharacterHit.TrailingLength); @@ -1556,8 +1393,8 @@ namespace Avalonia.Media.TextFormatting TrailingWhitespaceLength = trailingWhitespaceLength, Width = width, WidthIncludingTrailingWhitespace = widthIncludingWhitespace, - OverhangLeading= overhangLeading, - OverhangTrailing= overhangTrailing, + OverhangLeading = overhangLeading, + OverhangTrailing = overhangTrailing, OverhangAfter = overhangAfter }; } @@ -1615,8 +1452,7 @@ namespace Avalonia.Media.TextFormatting return Math.Max(0, start); case TextAlignment.Right: - return Math.Max(0, _paragraphWidth - width); - + return Math.Max(0, _paragraphWidth - widthIncludingTrailingWhitespace); default: return 0; } diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs index aa5d707d0f..1d07e780e6 100644 --- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs +++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs @@ -1071,6 +1071,55 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting } } + [Fact] + public void Should_GetTextBounds_BiDi() + { + var text = "אבגדה 12345 ABCDEF אבגדה"; + + using (Start()) + { + var defaultProperties = new GenericTextRunProperties(Typeface.Default); + var textSource = new SingleBufferTextSource(text, defaultProperties, true); + + var formatter = new TextFormatterImpl(); + + var textLine = + formatter.FormatLine(textSource, 0, double.PositiveInfinity, + new GenericTextParagraphProperties(FlowDirection.LeftToRight, TextAlignment.Left, + true, true, defaultProperties, TextWrapping.NoWrap, 0, 0, 0)); + + var bounds = textLine.GetTextBounds(6, 1); + + Assert.Equal(1, bounds.Count); + + Assert.Equal(0, bounds[0].Rectangle.Left); + + bounds = textLine.GetTextBounds(5, 1); + + Assert.Equal(1, bounds.Count); + + Assert.Equal(36.005859374999993, bounds[0].Rectangle.Left); + + bounds = textLine.GetTextBounds(0, 1); + + Assert.Equal(1, bounds.Count); + + Assert.Equal(71.165859375, bounds[0].Rectangle.Right); + + bounds = textLine.GetTextBounds(11, 1); + + Assert.Equal(1, bounds.Count); + + Assert.Equal(71.165859375, bounds[0].Rectangle.Left); + + bounds = textLine.GetTextBounds(0, 25); + + Assert.Equal(5, bounds.Count); + + Assert.Equal(textLine.WidthIncludingTrailingWhitespace, bounds.Last().Rectangle.Right); + } + } + private class FixedRunsTextSource : ITextSource { private readonly IReadOnlyList _textRuns; From 40515fc79846e68a3615959418ba6cc55ca15f9a Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 26 May 2023 14:49:45 +0200 Subject: [PATCH 113/219] Clarify/fix unit test. Now all of the other popup tests pass as well. --- .../Primitives/PopupTests.cs | 82 +++++++++++-------- .../MockWindowingPlatform.cs | 11 +-- 2 files changed, 53 insertions(+), 40 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs index e307a80441..888162cfee 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs @@ -1080,6 +1080,10 @@ namespace Avalonia.Controls.UnitTests.Primitives [Fact] public void GetPosition_On_Control_In_Popup_Called_From_Parent_Should_Return_Valid_Coordinates() { + // This test only applies when using a PopupRoot host and not an overlay popup. + if (UsePopupHost) + return; + using (CreateServices()) { var popupContent = new Border() { Height = 100, Width = 100, Background = Brushes.Red }; @@ -1088,18 +1092,18 @@ namespace Avalonia.Controls.UnitTests.Primitives var popupParent = new Border { Child = popup }; var root = PreparedWindow(popupParent); - var raised = 0; - - root.LayoutManager.ExecuteInitialLayoutPass(); popup.Open(); - root.LayoutManager.ExecuteLayoutPass(); - - var pointer = new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true); - var pts = popupContent.PointToScreen(new Point(10, 10)); + // Verify that the popup is positioned at 40,40 as descibed by the Horizontal/ + // VerticalOffset: 10,10 becomes 50,50 in screen coordinates. + Assert.Equal(new PixelPoint(50, 50), popupContent.PointToScreen(new Point(10, 10))); - Assert.Equal(new PixelPoint(50, 50), pts); + // The popup parent is positioned at 0,0 in screen coordinates so client and + // screen coordinates are the same. + Assert.Equal(new PixelPoint(10, 10), popupParent.PointToScreen(new Point(10, 10))); + // The event will be raised on the popup content at 50,50 (90,90 in screen coordinates) + var pointer = new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true); var ev = new PointerPressedEventArgs( popupContent, pointer, @@ -1109,19 +1113,28 @@ namespace Avalonia.Controls.UnitTests.Primitives new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.LeftButtonPressed), KeyModifiers.None); - Point pointRelativeToWindowContent = default; + var contentRaised = 0; + var parentRaised = 0; - popupParent.AddHandler(Button.PointerPressedEvent, (s, e) => + // The event is raised on the popup content in popup coordinates. + popupContent.AddHandler(Button.PointerPressedEvent, (s, e) => { - ++raised; + ++contentRaised; + Assert.Equal(new Point(50, 50), e.GetPosition(popupContent)); + }); - pointRelativeToWindowContent = e.GetPosition(popupParent); + // The event is raised on the parent in root coordinates (which in this case are + // the same as screen coordinates). + popupParent.AddHandler(Button.PointerPressedEvent, (s, e) => + { + ++parentRaised; + Assert.Equal(new Point(90, 90), e.GetPosition(popupParent)); }); popupContent.RaiseEvent(ev); - Assert.Equal(1, raised); - Assert.Equal(new Point(90, 90), pointRelativeToWindowContent); + Assert.Equal(1, contentRaised); + Assert.Equal(1, parentRaised); } } @@ -1146,28 +1159,16 @@ namespace Avalonia.Controls.UnitTests.Primitives private IDisposable CreateServices() { - return UnitTestApplication.Start(TestServices.StyledWindow.With(windowingPlatform: - new MockWindowingPlatform(() => MockWindowingPlatform.CreateWindowMock().Object, - x => - { - if(UsePopupHost) - return null; - return MockWindowingPlatform.CreatePopupMock(x).Object; - }))); + return UnitTestApplication.Start(TestServices.StyledWindow.With( + windowingPlatform: CreateMockWindowingPlatform())); } private IDisposable CreateServicesWithFocus() { - return UnitTestApplication.Start(TestServices.StyledWindow.With(windowingPlatform: - new MockWindowingPlatform(null, - x => - { - if (UsePopupHost) - return null; - return MockWindowingPlatform.CreatePopupMock(x).Object; - }), - focusManager: new FocusManager(), - keyboardDevice: () => new KeyboardDevice())); + return UnitTestApplication.Start(TestServices.StyledWindow.With( + windowingPlatform: CreateMockWindowingPlatform(), + focusManager: new FocusManager(), + keyboardDevice: () => new KeyboardDevice())); } @@ -1184,6 +1185,23 @@ namespace Avalonia.Controls.UnitTests.Primitives KeyModifiers.None); } + private MockWindowingPlatform CreateMockWindowingPlatform() + { + return new MockWindowingPlatform(() => + { + var mock = MockWindowingPlatform.CreateWindowMock(); + + mock.Setup(x => x.CreatePopup()).Returns(() => + { + if (UsePopupHost) + return null; + return MockWindowingPlatform.CreatePopupMock(mock.Object).Object; + }); + + return mock.Object; + }, null); + } + private static Window PreparedWindow(object content = null) { var w = new Window { Content = content }; diff --git a/tests/Avalonia.UnitTests/MockWindowingPlatform.cs b/tests/Avalonia.UnitTests/MockWindowingPlatform.cs index 65612e45a0..5451773da4 100644 --- a/tests/Avalonia.UnitTests/MockWindowingPlatform.cs +++ b/tests/Avalonia.UnitTests/MockWindowingPlatform.cs @@ -24,7 +24,6 @@ namespace Avalonia.UnitTests public static Mock CreateWindowMock(double initialWidth = 800, double initialHeight = 600) { var windowImpl = new Mock(); - var position = new PixelPoint(); var clientSize = new Size(initialWidth, initialHeight); windowImpl.SetupAllProperties(); @@ -35,7 +34,6 @@ namespace Avalonia.UnitTests windowImpl.Setup(x => x.DesktopScaling).Returns(1); windowImpl.Setup(x => x.RenderScaling).Returns(1); windowImpl.Setup(x => x.Screen).Returns(CreateScreenMock().Object); - windowImpl.Setup(x => x.Position).Returns(() => position); windowImpl.Setup(r => r.TryGetFeature(It.IsAny())).Returns(null); @@ -51,15 +49,15 @@ namespace Avalonia.UnitTests windowImpl.Setup(x => x.Move(It.IsAny())).Callback(x => { - position = x; + windowImpl.Setup(x => x.Position).Returns(x); windowImpl.Object.PositionChanged?.Invoke(x); }); windowImpl.Setup(x => x.PointToScreen(It.IsAny())) - .Returns((point) => PixelPoint.FromPoint(point, 1) + position); + .Returns((point) => PixelPoint.FromPoint(point, 1) + windowImpl.Object.Position); windowImpl.Setup(x => x.PointToClient(It.IsAny())) - .Returns(point => (point - position).ToPoint(1)); + .Returns(point => (point - windowImpl.Object.Position).ToPoint(1)); windowImpl.Setup(x => x.Resize(It.IsAny(), It.IsAny())) .Callback((x, y) => @@ -79,9 +77,6 @@ namespace Avalonia.UnitTests windowImpl.Object.Activated?.Invoke(); }); - windowImpl.Setup(x => x.PointToScreen(It.IsAny())) - .Returns((Point p) => PixelPoint.FromPoint(p, 1D) + position); - return windowImpl; } From 3070e8960c16684139136fd9734b99d4c16ee456 Mon Sep 17 00:00:00 2001 From: Benedikt Stebner Date: Fri, 26 May 2023 15:20:47 +0200 Subject: [PATCH 114/219] Fix FindIndexedRun --- src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs index ae2dbe0c8c..c2ec78e187 100644 --- a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs +++ b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs @@ -379,8 +379,6 @@ namespace Avalonia.Media.TextFormatting currentIndexedRun = _indexedTextRuns[i]; } - - break; } return currentIndexedRun; @@ -612,8 +610,6 @@ namespace Avalonia.Media.TextFormatting currentIndexedRun = _indexedTextRuns[i]; } - - break; } return currentIndexedRun; From 3b3b5145ee941c9dad0e9c318b081b74e0ea8287 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Fri, 26 May 2023 17:34:10 +0300 Subject: [PATCH 115/219] Ignore non hittable elements on hit test --- src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs b/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs index 8525f025a3..5c350688a4 100644 --- a/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs +++ b/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs @@ -50,7 +50,7 @@ namespace Avalonia.Controls.Primitives { if (InputPassThroughElement is Visual v) { - var hit = ((Visual?)VisualRoot)?.GetVisualAt(point, x => x != this); + var hit = ((IInputElement?)VisualRoot)?.InputHitTest(point, x => x != this) as Visual; if (hit is object) { From ea110cd8076817f85084214e561d2e551c39af17 Mon Sep 17 00:00:00 2001 From: aldelaro5 Date: Sun, 23 Apr 2023 05:04:03 -0400 Subject: [PATCH 116/219] Fix mouse wheel events being eaten on ComboBox on browser --- src/Avalonia.Controls/ComboBox.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs index 1234b66383..f5587a4c34 100644 --- a/src/Avalonia.Controls/ComboBox.cs +++ b/src/Avalonia.Controls/ComboBox.cs @@ -354,19 +354,6 @@ namespace Avalonia.Controls _subscriptionsOnOpen.Clear(); - var toplevel = TopLevel.GetTopLevel(this); - if (toplevel != null) - { - toplevel.AddDisposableHandler(PointerWheelChangedEvent, (s, ev) => - { - //eat wheel scroll event outside dropdown popup while it's open - if (IsDropDownOpen && (ev.Source as Visual)?.GetVisualRoot() == toplevel) - { - ev.Handled = true; - } - }, Interactivity.RoutingStrategies.Tunnel).DisposeWith(_subscriptionsOnOpen); - } - this.GetObservable(IsVisibleProperty).Subscribe(IsVisibleChanged).DisposeWith(_subscriptionsOnOpen); foreach (var parent in this.GetVisualAncestors().OfType()) From 68134c925fb3ff9acf78725b0cdc4a3cb77554e8 Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 27 May 2023 19:48:07 -0400 Subject: [PATCH 117/219] Switch RangeBase.ValueChanged from generic RoutedPropertyChangedEventArgs to RangeBaseValueChangedEventArgs This follows the WinUI pattern and makes a bit more sense. It is also similar to what is done with TextBox events as well. --- src/Avalonia.Controls/Primitives/RangeBase.cs | 8 ++-- .../RangeBaseValueChangedEventArgs.cs | 47 +++++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 src/Avalonia.Controls/Primitives/RangeBaseValueChangedEventArgs.cs diff --git a/src/Avalonia.Controls/Primitives/RangeBase.cs b/src/Avalonia.Controls/Primitives/RangeBase.cs index ebf7879412..33ab78b66f 100644 --- a/src/Avalonia.Controls/Primitives/RangeBase.cs +++ b/src/Avalonia.Controls/Primitives/RangeBase.cs @@ -45,14 +45,14 @@ namespace Avalonia.Controls.Primitives /// /// Defines the event. /// - public static readonly RoutedEvent> ValueChangedEvent = - RoutedEvent.Register>( + public static readonly RoutedEvent ValueChangedEvent = + RoutedEvent.Register( nameof(ValueChanged), RoutingStrategies.Bubble); /// /// Occurs when the property changes. /// - public event EventHandler>? ValueChanged + public event EventHandler? ValueChanged { add => AddHandler(ValueChangedEvent, value); remove => RemoveHandler(ValueChangedEvent, value); @@ -163,7 +163,7 @@ namespace Avalonia.Controls.Primitives } else if (change.Property == ValueProperty) { - var valueChangedEventArgs = new RoutedPropertyChangedEventArgs( + var valueChangedEventArgs = new RangeBaseValueChangedEventArgs( change.GetOldValue(), change.GetNewValue(), ValueChangedEvent); diff --git a/src/Avalonia.Controls/Primitives/RangeBaseValueChangedEventArgs.cs b/src/Avalonia.Controls/Primitives/RangeBaseValueChangedEventArgs.cs new file mode 100644 index 0000000000..ce1ac90bc6 --- /dev/null +++ b/src/Avalonia.Controls/Primitives/RangeBaseValueChangedEventArgs.cs @@ -0,0 +1,47 @@ +using Avalonia.Interactivity; + +namespace Avalonia.Controls.Primitives +{ + /// + /// Provides data specific to a event. + /// + public class RangeBaseValueChangedEventArgs : RoutedEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The old property value. + /// The new property value. + /// The routed event associated with these event args. + public RangeBaseValueChangedEventArgs(double oldValue, double newValue, RoutedEvent? routedEvent) + : base(routedEvent) + { + OldValue = oldValue; + NewValue = newValue; + } + + /// + /// Initializes a new instance of the class. + /// + /// The old property value. + /// The new property value. + /// The routed event associated with these event args. + /// The source object that raised the routed event. + public RangeBaseValueChangedEventArgs(double oldValue, double newValue, RoutedEvent? routedEvent, object? source) + : base(routedEvent, source) + { + OldValue = oldValue; + NewValue = newValue; + } + + /// + /// Gets the old value of the property. + /// + public double OldValue { get; init; } + + /// + /// Gets the new value of the property. + /// + public double NewValue { get; init; } + } +} From 545e9051bd89083f9d272703a5df475fbad89920 Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 27 May 2023 19:48:55 -0400 Subject: [PATCH 118/219] Remove generic RoutedPropertyChangedEventArgs --- .../RoutedPropertyChangedEventArgs.cs | 46 ------------------- 1 file changed, 46 deletions(-) delete mode 100644 src/Avalonia.Base/Interactivity/RoutedPropertyChangedEventArgs.cs diff --git a/src/Avalonia.Base/Interactivity/RoutedPropertyChangedEventArgs.cs b/src/Avalonia.Base/Interactivity/RoutedPropertyChangedEventArgs.cs deleted file mode 100644 index 22134b518d..0000000000 --- a/src/Avalonia.Base/Interactivity/RoutedPropertyChangedEventArgs.cs +++ /dev/null @@ -1,46 +0,0 @@ -namespace Avalonia.Interactivity -{ - /// - /// Provides both old and new property values with a routed event. - /// - /// The type of values. - public class RoutedPropertyChangedEventArgs : RoutedEventArgs - { - /// - /// Initializes a new instance of the class. - /// - /// The old property value. - /// The new property value. - /// The routed event associated with these event args. - public RoutedPropertyChangedEventArgs(T oldValue, T newValue, RoutedEvent? routedEvent) - : base(routedEvent) - { - OldValue = oldValue; - NewValue = newValue; - } - - /// - /// Initializes a new instance of the class. - /// - /// The old property value. - /// The new property value. - /// The routed event associated with these event args. - /// The source object that raised the routed event. - public RoutedPropertyChangedEventArgs(T oldValue, T newValue, RoutedEvent? routedEvent, object? source) - : base(routedEvent, source) - { - OldValue = oldValue; - NewValue = newValue; - } - - /// - /// Gets the old value of the property. - /// - public T OldValue { get; init; } - - /// - /// Gets the new value of the property. - /// - public T NewValue { get; init; } - } -} From 0d1ef8f7b62c037dafd53d9afdcec6a7d5c9f869 Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 27 May 2023 19:49:19 -0400 Subject: [PATCH 119/219] Add comments to TextChangedEventArgs and TextChangingEventArgs --- src/Avalonia.Controls/TextChangedEventArgs.cs | 11 ++++++++++- src/Avalonia.Controls/TextChangingEventArgs.cs | 11 ++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/TextChangedEventArgs.cs b/src/Avalonia.Controls/TextChangedEventArgs.cs index 1418154256..f614d2d760 100644 --- a/src/Avalonia.Controls/TextChangedEventArgs.cs +++ b/src/Avalonia.Controls/TextChangedEventArgs.cs @@ -3,15 +3,24 @@ namespace Avalonia.Controls { /// - /// Provides data specific to a TextChanged event. + /// Provides data specific to a event. /// public class TextChangedEventArgs : RoutedEventArgs { + /// + /// Initializes a new instance of the class. + /// + /// The routed event associated with these event args. public TextChangedEventArgs(RoutedEvent? routedEvent) : base (routedEvent) { } + /// + /// Initializes a new instance of the class. + /// + /// The routed event associated with these event args. + /// The source object that raised the routed event. public TextChangedEventArgs(RoutedEvent? routedEvent, Interactive? source) : base(routedEvent, source) { diff --git a/src/Avalonia.Controls/TextChangingEventArgs.cs b/src/Avalonia.Controls/TextChangingEventArgs.cs index 09e7d5b258..6ec5afd030 100644 --- a/src/Avalonia.Controls/TextChangingEventArgs.cs +++ b/src/Avalonia.Controls/TextChangingEventArgs.cs @@ -3,15 +3,24 @@ namespace Avalonia.Controls { /// - /// Provides data specific to a TextChanging event. + /// Provides data specific to a event. /// public class TextChangingEventArgs : RoutedEventArgs { + /// + /// Initializes a new instance of the class. + /// + /// The routed event associated with these event args. public TextChangingEventArgs(RoutedEvent? routedEvent) : base (routedEvent) { } + /// + /// Initializes a new instance of the class. + /// + /// The routed event associated with these event args. + /// The source object that raised the routed event. public TextChangingEventArgs(RoutedEvent? routedEvent, Interactive? source) : base(routedEvent, source) { From 4bcf08a9dc70efe18cc48fd6ca01679195bec683 Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 27 May 2023 20:00:37 -0400 Subject: [PATCH 120/219] Update RangeBaseValueChangedEventArgs comments --- .../Primitives/RangeBaseValueChangedEventArgs.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Avalonia.Controls/Primitives/RangeBaseValueChangedEventArgs.cs b/src/Avalonia.Controls/Primitives/RangeBaseValueChangedEventArgs.cs index ce1ac90bc6..480e82e4fc 100644 --- a/src/Avalonia.Controls/Primitives/RangeBaseValueChangedEventArgs.cs +++ b/src/Avalonia.Controls/Primitives/RangeBaseValueChangedEventArgs.cs @@ -10,8 +10,8 @@ namespace Avalonia.Controls.Primitives /// /// Initializes a new instance of the class. /// - /// The old property value. - /// The new property value. + /// The old value of the range value property. + /// The new value of the range value property. /// The routed event associated with these event args. public RangeBaseValueChangedEventArgs(double oldValue, double newValue, RoutedEvent? routedEvent) : base(routedEvent) @@ -23,8 +23,8 @@ namespace Avalonia.Controls.Primitives /// /// Initializes a new instance of the class. /// - /// The old property value. - /// The new property value. + /// The old value of the range value property. + /// The new value of the range value property. /// The routed event associated with these event args. /// The source object that raised the routed event. public RangeBaseValueChangedEventArgs(double oldValue, double newValue, RoutedEvent? routedEvent, object? source) @@ -35,12 +35,12 @@ namespace Avalonia.Controls.Primitives } /// - /// Gets the old value of the property. + /// Gets the old value of the range value property. /// public double OldValue { get; init; } /// - /// Gets the new value of the property. + /// Gets the new value of the range value property. /// public double NewValue { get; init; } } From 94fd79f7d9c9bfaf144cdc472d20ad2641d4bfae Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 27 May 2023 21:02:09 -0400 Subject: [PATCH 121/219] Obsolete Border line dashes --- src/Avalonia.Controls/Border.cs | 54 +++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/src/Avalonia.Controls/Border.cs b/src/Avalonia.Controls/Border.cs index 78ba23c1dd..3c0802c013 100644 --- a/src/Avalonia.Controls/Border.cs +++ b/src/Avalonia.Controls/Border.cs @@ -50,24 +50,28 @@ namespace Avalonia.Controls /// /// Defines the property. /// + [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] public static readonly StyledProperty BorderDashOffsetProperty = AvaloniaProperty.Register(nameof(BorderDashOffset)); /// /// Defines the property. /// + [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] public static readonly StyledProperty?> BorderDashArrayProperty = AvaloniaProperty.Register?>(nameof(BorderDashArray)); /// /// Defines the property. /// + [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] public static readonly StyledProperty BorderLineCapProperty = AvaloniaProperty.Register(nameof(BorderLineCap), PenLineCap.Flat); /// /// Defines the property. /// + [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] public static readonly StyledProperty BorderLineJoinProperty = AvaloniaProperty.Register(nameof(BorderLineJoin), PenLineJoin.Miter); @@ -86,10 +90,6 @@ namespace Avalonia.Controls BorderBrushProperty, BorderThicknessProperty, CornerRadiusProperty, - BorderDashArrayProperty, - BorderLineCapProperty, - BorderLineJoinProperty, - BorderDashOffsetProperty, BoxShadowProperty); AffectsMeasure(BorderThicknessProperty); } @@ -115,8 +115,8 @@ namespace Avalonia.Controls /// public IBrush? Background { - get { return GetValue(BackgroundProperty); } - set { SetValue(BackgroundProperty, value); } + get => GetValue(BackgroundProperty); + set => SetValue(BackgroundProperty, value); } /// @@ -124,17 +124,18 @@ namespace Avalonia.Controls /// public IBrush? BorderBrush { - get { return GetValue(BorderBrushProperty); } - set { SetValue(BorderBrushProperty, value); } + get => GetValue(BorderBrushProperty); + set => SetValue(BorderBrushProperty, value); } /// /// Gets or sets a collection of values that indicate the pattern of dashes and gaps that is used to outline shapes. /// + [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] public AvaloniaList? BorderDashArray { - get { return GetValue(BorderDashArrayProperty); } - set { SetValue(BorderDashArrayProperty, value); } + get => GetValue(BorderDashArrayProperty); + set => SetValue(BorderDashArrayProperty, value); } /// @@ -142,35 +143,38 @@ namespace Avalonia.Controls /// public Thickness BorderThickness { - get { return GetValue(BorderThicknessProperty); } - set { SetValue(BorderThicknessProperty, value); } + get => GetValue(BorderThicknessProperty); + set => SetValue(BorderThicknessProperty, value); } /// /// Gets or sets a value that specifies the distance within the dash pattern where a dash begins. /// + [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] public double BorderDashOffset { - get { return GetValue(BorderDashOffsetProperty); } - set { SetValue(BorderDashOffsetProperty, value); } + get => GetValue(BorderDashOffsetProperty); + set => SetValue(BorderDashOffsetProperty, value); } /// /// Gets or sets a enumeration value that describes the shape at the ends of a line. /// + [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] public PenLineCap BorderLineCap { - get { return GetValue(BorderLineCapProperty); } - set { SetValue(BorderLineCapProperty, value); } + get => GetValue(BorderLineCapProperty); + set => SetValue(BorderLineCapProperty, value); } /// /// Gets or sets a enumeration value that specifies the type of join that is used at the vertices of a Shape. /// + [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] public PenLineJoin BorderLineJoin { - get { return GetValue(BorderLineJoinProperty); } - set { SetValue(BorderLineJoinProperty, value); } + get => GetValue(BorderLineJoinProperty); + set => SetValue(BorderLineJoinProperty, value); } /// @@ -178,8 +182,8 @@ namespace Avalonia.Controls /// public CornerRadius CornerRadius { - get { return GetValue(CornerRadiusProperty); } - set { SetValue(CornerRadiusProperty, value); } + get => GetValue(CornerRadiusProperty); + set => SetValue(CornerRadiusProperty, value); } /// @@ -227,8 +231,14 @@ namespace Avalonia.Controls /// The drawing context. public sealed override void Render(DrawingContext context) { - _borderRenderHelper.Render(context, Bounds.Size, LayoutThickness, CornerRadius, Background, BorderBrush, - BoxShadow, BorderDashOffset, BorderLineCap, BorderLineJoin, BorderDashArray); + _borderRenderHelper.Render( + context, + Bounds.Size, + LayoutThickness, + CornerRadius, + Background, + BorderBrush, + BoxShadow); } /// From a857c92a46df1ca52589a181bcace2e8cafc281c Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 27 May 2023 21:02:46 -0400 Subject: [PATCH 122/219] Update property get/set syntax in Shape --- src/Avalonia.Controls/Shapes/Shape.cs | 32 +++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Avalonia.Controls/Shapes/Shape.cs b/src/Avalonia.Controls/Shapes/Shape.cs index 461dc1c947..a65ac774ef 100644 --- a/src/Avalonia.Controls/Shapes/Shape.cs +++ b/src/Avalonia.Controls/Shapes/Shape.cs @@ -126,8 +126,8 @@ namespace Avalonia.Controls.Shapes /// public IBrush? Fill { - get { return GetValue(FillProperty); } - set { SetValue(FillProperty, value); } + get => GetValue(FillProperty); + set => SetValue(FillProperty, value); } /// @@ -135,8 +135,8 @@ namespace Avalonia.Controls.Shapes /// public Stretch Stretch { - get { return GetValue(StretchProperty); } - set { SetValue(StretchProperty, value); } + get => GetValue(StretchProperty); + set => SetValue(StretchProperty, value); } /// @@ -144,8 +144,8 @@ namespace Avalonia.Controls.Shapes /// public IBrush? Stroke { - get { return GetValue(StrokeProperty); } - set { SetValue(StrokeProperty, value); } + get => GetValue(StrokeProperty); + set => SetValue(StrokeProperty, value); } /// @@ -153,8 +153,8 @@ namespace Avalonia.Controls.Shapes /// public AvaloniaList? StrokeDashArray { - get { return GetValue(StrokeDashArrayProperty); } - set { SetValue(StrokeDashArrayProperty, value); } + get => GetValue(StrokeDashArrayProperty); + set => SetValue(StrokeDashArrayProperty, value); } /// @@ -162,8 +162,8 @@ namespace Avalonia.Controls.Shapes /// public double StrokeDashOffset { - get { return GetValue(StrokeDashOffsetProperty); } - set { SetValue(StrokeDashOffsetProperty, value); } + get => GetValue(StrokeDashOffsetProperty); + set => SetValue(StrokeDashOffsetProperty, value); } /// @@ -171,8 +171,8 @@ namespace Avalonia.Controls.Shapes /// public double StrokeThickness { - get { return GetValue(StrokeThicknessProperty); } - set { SetValue(StrokeThicknessProperty, value); } + get => GetValue(StrokeThicknessProperty); + set => SetValue(StrokeThicknessProperty, value); } /// @@ -180,8 +180,8 @@ namespace Avalonia.Controls.Shapes /// public PenLineCap StrokeLineCap { - get { return GetValue(StrokeLineCapProperty); } - set { SetValue(StrokeLineCapProperty, value); } + get => GetValue(StrokeLineCapProperty); + set => SetValue(StrokeLineCapProperty, value); } /// @@ -189,8 +189,8 @@ namespace Avalonia.Controls.Shapes /// public PenLineJoin StrokeJoin { - get { return GetValue(StrokeJoinProperty); } - set { SetValue(StrokeJoinProperty, value); } + get => GetValue(StrokeJoinProperty); + set => SetValue(StrokeJoinProperty, value); } public sealed override void Render(DrawingContext context) From e18d9364b8286e5d72329d732fe8a09c8e979ad8 Mon Sep 17 00:00:00 2001 From: robloo Date: Sun, 28 May 2023 12:32:39 -0400 Subject: [PATCH 123/219] Completely remove Border line dash properties --- src/Avalonia.Controls/Border.cs | 68 --------------------------------- 1 file changed, 68 deletions(-) diff --git a/src/Avalonia.Controls/Border.cs b/src/Avalonia.Controls/Border.cs index 3c0802c013..e7373a813e 100644 --- a/src/Avalonia.Controls/Border.cs +++ b/src/Avalonia.Controls/Border.cs @@ -47,34 +47,6 @@ namespace Avalonia.Controls public static readonly StyledProperty BoxShadowProperty = AvaloniaProperty.Register(nameof(BoxShadow)); - /// - /// Defines the property. - /// - [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] - public static readonly StyledProperty BorderDashOffsetProperty = - AvaloniaProperty.Register(nameof(BorderDashOffset)); - - /// - /// Defines the property. - /// - [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] - public static readonly StyledProperty?> BorderDashArrayProperty = - AvaloniaProperty.Register?>(nameof(BorderDashArray)); - - /// - /// Defines the property. - /// - [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] - public static readonly StyledProperty BorderLineCapProperty = - AvaloniaProperty.Register(nameof(BorderLineCap), PenLineCap.Flat); - - /// - /// Defines the property. - /// - [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] - public static readonly StyledProperty BorderLineJoinProperty = - AvaloniaProperty.Register(nameof(BorderLineJoin), PenLineJoin.Miter); - private readonly BorderRenderHelper _borderRenderHelper = new BorderRenderHelper(); private Thickness? _layoutThickness; private double _scale; @@ -128,16 +100,6 @@ namespace Avalonia.Controls set => SetValue(BorderBrushProperty, value); } - /// - /// Gets or sets a collection of values that indicate the pattern of dashes and gaps that is used to outline shapes. - /// - [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] - public AvaloniaList? BorderDashArray - { - get => GetValue(BorderDashArrayProperty); - set => SetValue(BorderDashArrayProperty, value); - } - /// /// Gets or sets the thickness of the border. /// @@ -147,36 +109,6 @@ namespace Avalonia.Controls set => SetValue(BorderThicknessProperty, value); } - /// - /// Gets or sets a value that specifies the distance within the dash pattern where a dash begins. - /// - [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] - public double BorderDashOffset - { - get => GetValue(BorderDashOffsetProperty); - set => SetValue(BorderDashOffsetProperty, value); - } - - /// - /// Gets or sets a enumeration value that describes the shape at the ends of a line. - /// - [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] - public PenLineCap BorderLineCap - { - get => GetValue(BorderLineCapProperty); - set => SetValue(BorderLineCapProperty, value); - } - - /// - /// Gets or sets a enumeration value that specifies the type of join that is used at the vertices of a Shape. - /// - [Obsolete("Dashed lines on Border are no longer supported. Use Shapes directly instead.")] - public PenLineJoin BorderLineJoin - { - get => GetValue(BorderLineJoinProperty); - set => SetValue(BorderLineJoinProperty, value); - } - /// /// Gets or sets the radius of the border rounded corners. /// From 9eeebbc99db0f525de0133c30785dabed9903bf3 Mon Sep 17 00:00:00 2001 From: robloo Date: Sun, 28 May 2023 13:03:04 -0400 Subject: [PATCH 124/219] Rename MenuBase Opened/Closed events removing type prefix --- src/Avalonia.Base/Input/AccessKeyHandler.cs | 4 +-- src/Avalonia.Base/Input/IMainMenu.cs | 2 +- src/Avalonia.Controls/ContextMenu.cs | 4 +-- src/Avalonia.Controls/Menu.cs | 4 +-- src/Avalonia.Controls/MenuBase.cs | 28 +++++++++---------- .../Platform/DefaultMenuInteractionHandler.cs | 4 +-- .../ContextMenuTests.cs | 8 +++--- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/Avalonia.Base/Input/AccessKeyHandler.cs b/src/Avalonia.Base/Input/AccessKeyHandler.cs index 2b8786089f..2e0268a644 100644 --- a/src/Avalonia.Base/Input/AccessKeyHandler.cs +++ b/src/Avalonia.Base/Input/AccessKeyHandler.cs @@ -65,14 +65,14 @@ namespace Avalonia.Input { if (_mainMenu != null) { - _mainMenu.MenuClosed -= MainMenuClosed; + _mainMenu.Closed -= MainMenuClosed; } _mainMenu = value; if (_mainMenu != null) { - _mainMenu.MenuClosed += MainMenuClosed; + _mainMenu.Closed += MainMenuClosed; } } } diff --git a/src/Avalonia.Base/Input/IMainMenu.cs b/src/Avalonia.Base/Input/IMainMenu.cs index cc1b88d4c3..02437b6367 100644 --- a/src/Avalonia.Base/Input/IMainMenu.cs +++ b/src/Avalonia.Base/Input/IMainMenu.cs @@ -26,6 +26,6 @@ namespace Avalonia.Input /// /// Occurs when the main menu closes. /// - event EventHandler? MenuClosed; + event EventHandler? Closed; } } diff --git a/src/Avalonia.Controls/ContextMenu.cs b/src/Avalonia.Controls/ContextMenu.cs index a9d8e4c9c7..281ed5c6fb 100644 --- a/src/Avalonia.Controls/ContextMenu.cs +++ b/src/Avalonia.Controls/ContextMenu.cs @@ -353,7 +353,7 @@ namespace Avalonia.Controls RaiseEvent(new RoutedEventArgs { - RoutedEvent = MenuOpenedEvent, + RoutedEvent = OpenedEvent, Source = this, }); } @@ -394,7 +394,7 @@ namespace Avalonia.Controls RaiseEvent(new RoutedEventArgs { - RoutedEvent = MenuClosedEvent, + RoutedEvent = ClosedEvent, Source = this, }); diff --git a/src/Avalonia.Controls/Menu.cs b/src/Avalonia.Controls/Menu.cs index fe4d42c603..6a8cf2b515 100644 --- a/src/Avalonia.Controls/Menu.cs +++ b/src/Avalonia.Controls/Menu.cs @@ -60,7 +60,7 @@ namespace Avalonia.Controls RaiseEvent(new RoutedEventArgs { - RoutedEvent = MenuClosedEvent, + RoutedEvent = ClosedEvent, Source = this, }); } @@ -77,7 +77,7 @@ namespace Avalonia.Controls RaiseEvent(new RoutedEventArgs { - RoutedEvent = MenuOpenedEvent, + RoutedEvent = OpenedEvent, Source = this, }); } diff --git a/src/Avalonia.Controls/MenuBase.cs b/src/Avalonia.Controls/MenuBase.cs index 7fc804a338..e57fadffee 100644 --- a/src/Avalonia.Controls/MenuBase.cs +++ b/src/Avalonia.Controls/MenuBase.cs @@ -25,16 +25,16 @@ namespace Avalonia.Controls o => o.IsOpen); /// - /// Defines the event. + /// Defines the event. /// - public static readonly RoutedEvent MenuOpenedEvent = - RoutedEvent.Register(nameof(MenuOpened), RoutingStrategies.Bubble); + public static readonly RoutedEvent OpenedEvent = + RoutedEvent.Register(nameof(Opened), RoutingStrategies.Bubble); /// - /// Defines the event. + /// Defines the event. /// - public static readonly RoutedEvent MenuClosedEvent = - RoutedEvent.Register(nameof(MenuClosed), RoutingStrategies.Bubble); + public static readonly RoutedEvent ClosedEvent = + RoutedEvent.Register(nameof(Closed), RoutingStrategies.Bubble); private bool _isOpen; @@ -68,8 +68,8 @@ namespace Avalonia.Controls /// public bool IsOpen { - get { return _isOpen; } - protected set { SetAndRaise(IsOpenProperty, ref _isOpen, value); } + get => _isOpen; + protected set => SetAndRaise(IsOpenProperty, ref _isOpen, value); } /// @@ -105,19 +105,19 @@ namespace Avalonia.Controls /// /// Occurs when a is opened. /// - public event EventHandler? MenuOpened + public event EventHandler? Opened { - add { AddHandler(MenuOpenedEvent, value); } - remove { RemoveHandler(MenuOpenedEvent, value); } + add => AddHandler(OpenedEvent, value); + remove => RemoveHandler(OpenedEvent, value); } /// /// Occurs when a is closed. /// - public event EventHandler? MenuClosed + public event EventHandler? Closed { - add { AddHandler(MenuClosedEvent, value); } - remove { RemoveHandler(MenuClosedEvent, value); } + add => AddHandler(ClosedEvent, value); + remove => RemoveHandler(ClosedEvent, value); } /// diff --git a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs index 79a3038edf..6a76855d85 100644 --- a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs +++ b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs @@ -290,7 +290,7 @@ namespace Avalonia.Controls.Platform Menu.PointerPressed += PointerPressed; Menu.PointerReleased += PointerReleased; Menu.AddHandler(AccessKeyHandler.AccessKeyPressedEvent, AccessKeyPressed); - Menu.AddHandler(MenuBase.MenuOpenedEvent, MenuOpened); + Menu.AddHandler(MenuBase.OpenedEvent, MenuOpened); Menu.AddHandler(MenuItem.PointerEnteredItemEvent, PointerEntered); Menu.AddHandler(MenuItem.PointerExitedItemEvent, PointerExited); Menu.AddHandler(InputElement.PointerMovedEvent, PointerMoved); @@ -326,7 +326,7 @@ namespace Avalonia.Controls.Platform Menu.PointerPressed -= PointerPressed; Menu.PointerReleased -= PointerReleased; Menu.RemoveHandler(AccessKeyHandler.AccessKeyPressedEvent, AccessKeyPressed); - Menu.RemoveHandler(MenuBase.MenuOpenedEvent, MenuOpened); + Menu.RemoveHandler(MenuBase.OpenedEvent, MenuOpened); Menu.RemoveHandler(MenuItem.PointerEnteredItemEvent, PointerEntered); Menu.RemoveHandler(MenuItem.PointerExitedItemEvent, PointerExited); Menu.RemoveHandler(InputElement.PointerMovedEvent, PointerMoved); diff --git a/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs b/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs index 803cc793fd..fda3379976 100644 --- a/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs @@ -35,7 +35,7 @@ namespace Avalonia.Controls.UnitTests int openedCount = 0; - sut.MenuOpened += (sender, args) => + sut.Opened += (sender, args) => { openedCount++; }; @@ -138,7 +138,7 @@ namespace Avalonia.Controls.UnitTests int openedCount = 0; - sut.MenuOpened += (sender, args) => + sut.Opened += (sender, args) => { openedCount++; }; @@ -167,7 +167,7 @@ namespace Avalonia.Controls.UnitTests bool opened = false; - sut.MenuOpened += (sender, args) => + sut.Opened += (sender, args) => { opened = true; }; @@ -220,7 +220,7 @@ namespace Avalonia.Controls.UnitTests int closedCount = 0; - sut.MenuClosed += (sender, args) => + sut.Closed += (sender, args) => { closedCount++; }; From 04c88b09fbd975e67d6457ef5e5c640a0934758c Mon Sep 17 00:00:00 2001 From: robloo Date: Sun, 28 May 2023 13:07:59 -0400 Subject: [PATCH 125/219] Rename ContextMenu Opening/Closing events removing type prefix --- samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs | 4 ++-- src/Avalonia.Controls/ContextMenu.cs | 8 ++++---- tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs b/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs index 96fcb54650..664264956f 100644 --- a/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs +++ b/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs @@ -19,8 +19,8 @@ namespace ControlCatalog.Pages customContextRequestedBorder.AddHandler(ContextRequestedEvent, CustomContextRequested, RoutingStrategies.Tunnel); var cancellableContextBorder = this.Get("CancellableContextBorder"); - cancellableContextBorder.ContextMenu!.ContextMenuClosing += ContextFlyoutPage_Closing; - cancellableContextBorder.ContextMenu!.ContextMenuOpening += ContextFlyoutPage_Opening; + cancellableContextBorder.ContextMenu!.Closing += ContextFlyoutPage_Closing; + cancellableContextBorder.ContextMenu!.Opening += ContextFlyoutPage_Opening; } private ContextPageViewModel? _model; diff --git a/src/Avalonia.Controls/ContextMenu.cs b/src/Avalonia.Controls/ContextMenu.cs index 281ed5c6fb..3dc1514667 100644 --- a/src/Avalonia.Controls/ContextMenu.cs +++ b/src/Avalonia.Controls/ContextMenu.cs @@ -196,14 +196,14 @@ namespace Avalonia.Controls /// /// property is changing from false to true. /// - public event CancelEventHandler? ContextMenuOpening; + public event CancelEventHandler? Opening; /// /// Occurs when the value of the /// /// property is changing from true to false. /// - public event CancelEventHandler? ContextMenuClosing; + public event CancelEventHandler? Closing; /// /// Called when the property changes on a control. @@ -446,14 +446,14 @@ namespace Avalonia.Controls private bool CancelClosing() { var eventArgs = new CancelEventArgs(); - ContextMenuClosing?.Invoke(this, eventArgs); + Closing?.Invoke(this, eventArgs); return eventArgs.Cancel; } private bool CancelOpening() { var eventArgs = new CancelEventArgs(); - ContextMenuOpening?.Invoke(this, eventArgs); + Opening?.Invoke(this, eventArgs); return eventArgs.Cancel; } } diff --git a/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs b/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs index fda3379976..429572f3ea 100644 --- a/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs @@ -258,7 +258,7 @@ namespace Avalonia.Controls.UnitTests var tracker = 0; var c = new ContextMenu(); - c.ContextMenuClosing += (s, e) => + c.Closing += (s, e) => { tracker++; e.Cancel = true; @@ -430,7 +430,7 @@ namespace Avalonia.Controls.UnitTests }; new Window { Content = target }; - sut.ContextMenuOpening += (c, e) => { eventCalled = true; e.Cancel = true; }; + sut.Opening += (c, e) => { eventCalled = true; e.Cancel = true; }; _mouse.Click(target, MouseButton.Right); @@ -574,7 +574,7 @@ namespace Avalonia.Controls.UnitTests var window = PreparedWindow(target); var overlay = LightDismissOverlayLayer.GetLightDismissOverlayLayer(window); - sut.ContextMenuClosing += (c, e) => { eventCalled = true; e.Cancel = true; }; + sut.Closing += (c, e) => { eventCalled = true; e.Cancel = true; }; window.Show(); From ec47ea9e2afed1d6a3361ac4d5c25b5ae3734ef6 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sun, 28 May 2023 23:07:07 -0400 Subject: [PATCH 126/219] Implement support for x:ClassModifier="internal" and TryLoad generators --- .../XamlCompilerTaskExecutor.cs | 35 ++++++++++++++++++- .../AvaloniaXamlIlRuntimeCompiler.cs | 4 +-- .../XamlDocumentResource.cs | 3 ++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs index d71070e818..898c23973c 100644 --- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs +++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs @@ -288,6 +288,24 @@ namespace Avalonia.Build.Tasks if (precompileText != "true") throw new XamlParseException("Invalid value for x:Precompile", precompileDirective); } + + var classModifierDirective = initialRoot.Children.OfType() + .FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "ClassModifier"); + bool? classModifierPublic = null; + if (classModifierDirective != null) + { + var classModifierText = (classModifierDirective.Values[0] as XamlAstTextNode)?.Text.Trim() + .ToLowerInvariant(); + if ("Public".Equals(classModifierText, StringComparison.OrdinalIgnoreCase)) + classModifierPublic = true; + // XAML spec uses "Public" and "NotPublic" values, + // When WPF documentation uses "public" and "internal". + else if ("NotPublic".Equals(classModifierText, StringComparison.OrdinalIgnoreCase) + || "Internal".Equals(classModifierText, StringComparison.OrdinalIgnoreCase)) + classModifierPublic = false; + else + throw new XamlParseException("Invalid value for x:ClassModifier. Expected value are: Public, NotPublic.", precompileDirective); + } var classDirective = initialRoot.Children.OfType() .FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Class"); @@ -297,8 +315,21 @@ namespace Avalonia.Build.Tasks if (classDirective.Values.Count != 1 || !(classDirective.Values[0] is XamlAstTextNode tn)) throw new XamlParseException("x:Class should have a string value", classDirective); classType = typeSystem.TargetAssembly.FindType(tn.Text); + if (classType == null) throw new XamlParseException($"Unable to find type `{tn.Text}`", classDirective); + + var isClassPublic = typeSystem.GetTypeReference(classType).Resolve().IsPublic; + classModifierPublic ??= isClassPublic; + + // We do not really need x:ClassModifier support for x:Class, but we can at least use it for validation here. + if (classModifierPublic != isClassPublic) + { + throw new XamlParseException( + "XAML file x:ClassModifier doesn't match the x:Class type modifiers.", + precompileDirective); + } + compiler.OverrideRootType(parsed, new XamlAstClrTypeReference(classDirective, classType, false)); initialRoot.Children.Remove(classDirective); @@ -319,6 +350,7 @@ namespace Avalonia.Build.Tasks ((List)parsedXamlDocuments).Add(new XamlDocumentResource( parsed, res.Uri, res, classType, + classModifierPublic ?? true, populateBuilder, compiler.DefinePopulateMethod(populateBuilder, parsed, populateName, classTypeDefinition == null), @@ -502,7 +534,8 @@ namespace Avalonia.Build.Tasks } - if (document.BuildMethod != null || classTypeDefinition != null) + if (document.IsPublic + && (document.BuildMethod != null || classTypeDefinition != null)) { var compiledBuildMethod = document.BuildMethod == null ? null : diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs index e3d154ffdd..e2aab7d685 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs @@ -231,8 +231,8 @@ namespace Avalonia.Markup.Xaml.XamlIl ?? ((IXamlAstValueNode)parsed.Root).Type.GetClrType().Name; var tb = _sreBuilder.DefineType("Builder_" + Guid.NewGuid().ToString("N") + "_" + xamlName); var builder = _sreTypeSystem.CreateTypeBuilder(tb); - parsedDocuments.Add(new XamlDocumentResource(parsed, document.BaseUri?.ToString(), null, null, - builder, + parsedDocuments.Add(new XamlDocumentResource(parsed, document.BaseUri?.ToString(), + null, null, true, builder, compiler.DefinePopulateMethod(builder, parsed, AvaloniaXamlIlCompiler.PopulateName, true), document.RootInstance is null ? compiler.DefineBuildMethod(builder, parsed, AvaloniaXamlIlCompiler.BuildName, true) : null)); originalDocuments.Add(document); diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlDocumentResource.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlDocumentResource.cs index d5d452a9f3..932fe067af 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlDocumentResource.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlDocumentResource.cs @@ -13,6 +13,7 @@ internal class XamlDocumentResource : IXamlDocumentResource string? uri, IFileSource? fileSource, IXamlType? classType, + bool isPublic, IXamlTypeBuilder typeBuilder, IXamlMethodBuilder populateMethod, IXamlMethodBuilder? buildMethod) @@ -21,6 +22,7 @@ internal class XamlDocumentResource : IXamlDocumentResource Uri = uri; FileSource = fileSource; ClassType = classType; + IsPublic = isPublic; TypeBuilder = typeBuilder; PopulateMethod = populateMethod; BuildMethod = buildMethod; @@ -31,6 +33,7 @@ internal class XamlDocumentResource : IXamlDocumentResource public IFileSource? FileSource { get; } public IXamlType? ClassType { get; } + public bool IsPublic { get; } public IXamlTypeBuilder TypeBuilder { get; } public IXamlMethodBuilder PopulateMethod { get; } public IXamlMethodBuilder? BuildMethod { get; } From 6b53cbe63f40d9737c33b795417b512853f1543a Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sun, 28 May 2023 23:08:01 -0400 Subject: [PATCH 127/219] Add x:ClassModifier="internal" to all theme xaml files that should be hidden --- src/Avalonia.Themes.Fluent/Accents/BaseColorsPalette.xaml | 3 ++- src/Avalonia.Themes.Fluent/Accents/BaseResources.xaml | 3 ++- src/Avalonia.Themes.Fluent/Accents/FluentControlResources.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/AdornerLayer.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/Button.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/Calendar.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/Carousel.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ComboBoxItem.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ContentControl.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/DateTimePickerShared.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/DropDownButton.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/EmbeddableControlRoot.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/Expander.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/FluentControls.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/FlyoutPresenter.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/GridSplitter.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ItemsControl.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/Label.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ListBox.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ListBoxItem.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/Menu.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/MenuFlyoutPresenter.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/MenuScrollViewer.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/NativeMenuBar.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/NotificationCard.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/NumericUpDown.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/OverlayPopupHost.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/PathIcon.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ProgressBar.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/RadioButton.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/RefreshContainer.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/RefreshVisualizer.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/RepeatButton.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ScrollBar.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ScrollViewer.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/SelectableTextBlock.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/Separator.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/Slider.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/SplitButton.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/SplitView.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/TabControl.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/TabItem.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/TabStrip.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/TabStripItem.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/TextBox.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ThemeVariantScope.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/TitleBar.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ToggleButton.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ToggleSwitch.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/ToolTip.xaml | 3 ++- .../Controls/TransitioningContentControl.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/TreeView.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/TreeViewItem.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/UserControl.xaml | 3 ++- src/Avalonia.Themes.Fluent/Controls/Window.xaml | 3 ++- .../Controls/WindowNotificationManager.xaml | 3 ++- src/Avalonia.Themes.Fluent/DensityStyles/Compact.xaml | 3 ++- src/Avalonia.Themes.Fluent/FluentTheme.xaml | 2 +- src/Avalonia.Themes.Simple/Accents/Base.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/AdornerLayer.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/AutoCompleteBox.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/Button.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ButtonSpinner.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/Calendar.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/CalendarButton.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/CalendarDatePicker.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/CalendarDayButton.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/CalendarItem.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/CaptionButtons.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/Carousel.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/CheckBox.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ComboBox.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ComboBoxItem.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ContentControl.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ContextMenu.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/DataValidationErrors.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/DatePicker.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/DateTimePickerShared.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/DropDownButton.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/EmbeddableControlRoot.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/Expander.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/FlyoutPresenter.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/GridSplitter.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ItemsControl.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/Label.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ListBox.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ListBoxItem.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/Menu.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/MenuFlyoutPresenter.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/MenuItem.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/NativeMenuBar.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/NotificationCard.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/NumericUpDown.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/OverlayPopupHost.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/PathIcon.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/PopupRoot.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ProgressBar.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/RadioButton.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/RefreshContainer.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/RefreshVisualizer.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/RepeatButton.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ScrollBar.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ScrollViewer.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/SelectableTextBlock.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/Separator.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/SimpleControls.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/Slider.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/SplitButton.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/SplitView.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/TabControl.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/TabItem.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/TabStrip.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/TabStripItem.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/TextBox.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ThemeVariantScope.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/TimePicker.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/TitleBar.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ToggleButton.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ToggleSwitch.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/ToolTip.xaml | 3 ++- .../Controls/TransitioningContentControl.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/TreeView.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/TreeViewItem.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/UserControl.xaml | 3 ++- src/Avalonia.Themes.Simple/Controls/Window.xaml | 3 ++- .../Controls/WindowNotificationManager.xaml | 3 ++- 143 files changed, 285 insertions(+), 143 deletions(-) diff --git a/src/Avalonia.Themes.Fluent/Accents/BaseColorsPalette.xaml b/src/Avalonia.Themes.Fluent/Accents/BaseColorsPalette.xaml index 362d543646..620add9045 100644 --- a/src/Avalonia.Themes.Fluent/Accents/BaseColorsPalette.xaml +++ b/src/Avalonia.Themes.Fluent/Accents/BaseColorsPalette.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Accents/BaseResources.xaml b/src/Avalonia.Themes.Fluent/Accents/BaseResources.xaml index 517a80fd7e..6f12f1d306 100644 --- a/src/Avalonia.Themes.Fluent/Accents/BaseResources.xaml +++ b/src/Avalonia.Themes.Fluent/Accents/BaseResources.xaml @@ -1,7 +1,8 @@ + xmlns:converters="using:Avalonia.Controls.Converters" + x:ClassModifier="internal"> fonts:Inter#Inter, $Default 14 diff --git a/src/Avalonia.Themes.Fluent/Accents/FluentControlResources.xaml b/src/Avalonia.Themes.Fluent/Accents/FluentControlResources.xaml index 61a74f26a4..397f7ec431 100644 --- a/src/Avalonia.Themes.Fluent/Accents/FluentControlResources.xaml +++ b/src/Avalonia.Themes.Fluent/Accents/FluentControlResources.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/AdornerLayer.xaml b/src/Avalonia.Themes.Fluent/Controls/AdornerLayer.xaml index c4b91b4822..fefa1ea055 100644 --- a/src/Avalonia.Themes.Fluent/Controls/AdornerLayer.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/AdornerLayer.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> 0 2 1 diff --git a/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml b/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml index 2113ae4cb0..228aeaad17 100644 --- a/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml @@ -1,6 +1,7 @@  + xmlns:generic="using:System.Collections.Generic" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/Button.xaml b/src/Avalonia.Themes.Fluent/Controls/Button.xaml index 126f2c22e0..6c6ca967e7 100644 --- a/src/Avalonia.Themes.Fluent/Controls/Button.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/Button.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml b/src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml index 3ce4730698..095e801d0c 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml @@ -1,7 +1,8 @@  + xmlns:converters="using:Avalonia.Controls.Converters" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/Calendar.xaml b/src/Avalonia.Themes.Fluent/Controls/Calendar.xaml index 9c66ea9b84..2f4a444529 100644 --- a/src/Avalonia.Themes.Fluent/Controls/Calendar.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/Calendar.xaml @@ -6,7 +6,8 @@ --> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml index 76b51ca819..206973b7ee 100644 --- a/src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml @@ -5,7 +5,8 @@ // All other rights reserved. --> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml index 2a3496b648..4739a5b9c5 100644 --- a/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml @@ -1,6 +1,7 @@  + xmlns:sys="using:System" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml index 6a57cfacd0..904a234ada 100644 --- a/src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml @@ -5,7 +5,8 @@ // All other rights reserved. --> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml index 7276742e7d..3bbef81695 100644 --- a/src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml @@ -6,7 +6,8 @@ --> + xmlns:sys="using:System" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml b/src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml index 0180c3f395..41d74c6063 100644 --- a/src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/Carousel.xaml b/src/Avalonia.Themes.Fluent/Controls/Carousel.xaml index 91e331693e..b94ef9b5d9 100644 --- a/src/Avalonia.Themes.Fluent/Controls/Carousel.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/Carousel.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml b/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml index 28f8649e2d..fc0a8c7c66 100644 --- a/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml b/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml index bc36ad987e..18bf01ece7 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml @@ -1,6 +1,7 @@  + xmlns:sys="using:System" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ComboBoxItem.xaml b/src/Avalonia.Themes.Fluent/Controls/ComboBoxItem.xaml index 581cbaf80a..ea55770a51 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ComboBoxItem.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ComboBoxItem.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ContentControl.xaml b/src/Avalonia.Themes.Fluent/Controls/ContentControl.xaml index 4caf156366..f277c6f9ae 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ContentControl.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ContentControl.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml b/src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml index f6900f785f..c8e2873eb6 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> + xmlns:collections="using:System.Collections" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml b/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml index e71e733eff..58f181bd23 100644 --- a/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml @@ -7,7 +7,8 @@ + xmlns:sys="using:System" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/DateTimePickerShared.xaml b/src/Avalonia.Themes.Fluent/Controls/DateTimePickerShared.xaml index 9d21e6e758..9384eff8f4 100644 --- a/src/Avalonia.Themes.Fluent/Controls/DateTimePickerShared.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/DateTimePickerShared.xaml @@ -6,7 +6,8 @@ --> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/DropDownButton.xaml b/src/Avalonia.Themes.Fluent/Controls/DropDownButton.xaml index 421ba0bb18..438ad6cf18 100644 --- a/src/Avalonia.Themes.Fluent/Controls/DropDownButton.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/DropDownButton.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/EmbeddableControlRoot.xaml b/src/Avalonia.Themes.Fluent/Controls/EmbeddableControlRoot.xaml index ee51ef8085..1fc931db36 100644 --- a/src/Avalonia.Themes.Fluent/Controls/EmbeddableControlRoot.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/EmbeddableControlRoot.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/Expander.xaml b/src/Avalonia.Themes.Fluent/Controls/Expander.xaml index 37e9b71185..adaecc71ab 100644 --- a/src/Avalonia.Themes.Fluent/Controls/Expander.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/Expander.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/FluentControls.xaml b/src/Avalonia.Themes.Fluent/Controls/FluentControls.xaml index 31b0a01b21..deb7d39a89 100644 --- a/src/Avalonia.Themes.Fluent/Controls/FluentControls.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/FluentControls.xaml @@ -1,6 +1,7 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/FlyoutPresenter.xaml b/src/Avalonia.Themes.Fluent/Controls/FlyoutPresenter.xaml index 2dca5b0770..e8c9ed9b2a 100644 --- a/src/Avalonia.Themes.Fluent/Controls/FlyoutPresenter.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/FlyoutPresenter.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> 1 diff --git a/src/Avalonia.Themes.Fluent/Controls/GridSplitter.xaml b/src/Avalonia.Themes.Fluent/Controls/GridSplitter.xaml index ca57eccd13..fc08d6b0b6 100644 --- a/src/Avalonia.Themes.Fluent/Controls/GridSplitter.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/GridSplitter.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ItemsControl.xaml b/src/Avalonia.Themes.Fluent/Controls/ItemsControl.xaml index 19a29b9466..91f9536847 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ItemsControl.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ItemsControl.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/Label.xaml b/src/Avalonia.Themes.Fluent/Controls/Label.xaml index ff6909ee87..237da0bfa3 100644 --- a/src/Avalonia.Themes.Fluent/Controls/Label.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/Label.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ListBox.xaml b/src/Avalonia.Themes.Fluent/Controls/ListBox.xaml index 05bbbe9558..2dde18a523 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ListBox.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ListBox.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ListBoxItem.xaml b/src/Avalonia.Themes.Fluent/Controls/ListBoxItem.xaml index fc1d0c5ff1..4e74406c92 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ListBoxItem.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ListBoxItem.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml b/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml index 8519099a27..374daa7ab5 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml @@ -1,7 +1,8 @@  + xmlns:internal="using:Avalonia.Dialogs.Internal" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/Menu.xaml b/src/Avalonia.Themes.Fluent/Controls/Menu.xaml index e6bbbde632..c1640efa8c 100644 --- a/src/Avalonia.Themes.Fluent/Controls/Menu.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/Menu.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/MenuFlyoutPresenter.xaml b/src/Avalonia.Themes.Fluent/Controls/MenuFlyoutPresenter.xaml index b1f44cc70d..b5dff7b59d 100644 --- a/src/Avalonia.Themes.Fluent/Controls/MenuFlyoutPresenter.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/MenuFlyoutPresenter.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml b/src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml index c7ffdd3418..8a2d76b940 100644 --- a/src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml @@ -1,6 +1,7 @@  + xmlns:conv="using:Avalonia.Controls.Converters" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/MenuScrollViewer.xaml b/src/Avalonia.Themes.Fluent/Controls/MenuScrollViewer.xaml index adca099a10..9dd65b1349 100644 --- a/src/Avalonia.Themes.Fluent/Controls/MenuScrollViewer.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/MenuScrollViewer.xaml @@ -1,6 +1,7 @@  + xmlns:converters="using:Avalonia.Controls.Converters" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/NativeMenuBar.xaml b/src/Avalonia.Themes.Fluent/Controls/NativeMenuBar.xaml index 515a5a730b..3e28ac3ddd 100644 --- a/src/Avalonia.Themes.Fluent/Controls/NativeMenuBar.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/NativeMenuBar.xaml @@ -1,6 +1,7 @@ + xmlns:local="using:Avalonia.Themes.Fluent" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/NotificationCard.xaml b/src/Avalonia.Themes.Fluent/Controls/NotificationCard.xaml index 51dcdd42e3..52e7280c95 100644 --- a/src/Avalonia.Themes.Fluent/Controls/NotificationCard.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/NotificationCard.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/NumericUpDown.xaml b/src/Avalonia.Themes.Fluent/Controls/NumericUpDown.xaml index 872367c6da..1f84ee664c 100644 --- a/src/Avalonia.Themes.Fluent/Controls/NumericUpDown.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/NumericUpDown.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/OverlayPopupHost.xaml b/src/Avalonia.Themes.Fluent/Controls/OverlayPopupHost.xaml index 28d8fb508c..1316a5bd65 100644 --- a/src/Avalonia.Themes.Fluent/Controls/OverlayPopupHost.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/OverlayPopupHost.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/PathIcon.xaml b/src/Avalonia.Themes.Fluent/Controls/PathIcon.xaml index 5584eb3ab9..2a817ccfcb 100644 --- a/src/Avalonia.Themes.Fluent/Controls/PathIcon.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/PathIcon.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml b/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml index 5a924830b1..910c5f8d8c 100644 --- a/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/PopupRoot.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ProgressBar.xaml b/src/Avalonia.Themes.Fluent/Controls/ProgressBar.xaml index 64a598e359..adb8551ec3 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ProgressBar.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ProgressBar.xaml @@ -1,6 +1,7 @@ + xmlns:converters="using:Avalonia.Controls.Converters" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/RadioButton.xaml b/src/Avalonia.Themes.Fluent/Controls/RadioButton.xaml index a1c4ba4f2d..39f89788bb 100644 --- a/src/Avalonia.Themes.Fluent/Controls/RadioButton.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/RadioButton.xaml @@ -1,4 +1,5 @@ - + diff --git a/src/Avalonia.Themes.Fluent/Controls/RefreshContainer.xaml b/src/Avalonia.Themes.Fluent/Controls/RefreshContainer.xaml index 8e29e6208f..b030acca30 100644 --- a/src/Avalonia.Themes.Fluent/Controls/RefreshContainer.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/RefreshContainer.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/RefreshVisualizer.xaml b/src/Avalonia.Themes.Fluent/Controls/RefreshVisualizer.xaml index 4e76bee9f5..a9ca8a0a5c 100644 --- a/src/Avalonia.Themes.Fluent/Controls/RefreshVisualizer.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/RefreshVisualizer.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/RepeatButton.xaml b/src/Avalonia.Themes.Fluent/Controls/RepeatButton.xaml index fd04c85fed..b8a06f996a 100644 --- a/src/Avalonia.Themes.Fluent/Controls/RepeatButton.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/RepeatButton.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ScrollBar.xaml b/src/Avalonia.Themes.Fluent/Controls/ScrollBar.xaml index 4544fbe339..531f11a90b 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ScrollBar.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ScrollBar.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ScrollViewer.xaml b/src/Avalonia.Themes.Fluent/Controls/ScrollViewer.xaml index 6218fe94ca..886a903a43 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ScrollViewer.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ScrollViewer.xaml @@ -1,6 +1,7 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/SelectableTextBlock.xaml b/src/Avalonia.Themes.Fluent/Controls/SelectableTextBlock.xaml index 2556f80ef6..b5daa65efc 100644 --- a/src/Avalonia.Themes.Fluent/Controls/SelectableTextBlock.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/SelectableTextBlock.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/Separator.xaml b/src/Avalonia.Themes.Fluent/Controls/Separator.xaml index d13bffe5e1..3b4a111a58 100644 --- a/src/Avalonia.Themes.Fluent/Controls/Separator.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/Separator.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/Slider.xaml b/src/Avalonia.Themes.Fluent/Controls/Slider.xaml index 6e9e37643e..a4102a84d3 100644 --- a/src/Avalonia.Themes.Fluent/Controls/Slider.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/Slider.xaml @@ -1,6 +1,7 @@  + xmlns:sys="using:System" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/SplitButton.xaml b/src/Avalonia.Themes.Fluent/Controls/SplitButton.xaml index 1a7e72462a..98f8c8238e 100644 --- a/src/Avalonia.Themes.Fluent/Controls/SplitButton.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/SplitButton.xaml @@ -1,6 +1,7 @@  + xmlns:converters="using:Avalonia.Controls.Converters" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/SplitView.xaml b/src/Avalonia.Themes.Fluent/Controls/SplitView.xaml index 9feb6c7fc6..aaf6ad7dbc 100644 --- a/src/Avalonia.Themes.Fluent/Controls/SplitView.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/SplitView.xaml @@ -1,6 +1,7 @@  + xmlns:sys="using:System" + x:ClassModifier="internal"> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/TabItem.xaml b/src/Avalonia.Themes.Fluent/Controls/TabItem.xaml index b11ad4e03a..54eea85743 100644 --- a/src/Avalonia.Themes.Fluent/Controls/TabItem.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/TabItem.xaml @@ -1,6 +1,7 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/TabStrip.xaml b/src/Avalonia.Themes.Fluent/Controls/TabStrip.xaml index ead6fc41ab..ecaad94482 100644 --- a/src/Avalonia.Themes.Fluent/Controls/TabStrip.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/TabStrip.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/TabStripItem.xaml b/src/Avalonia.Themes.Fluent/Controls/TabStripItem.xaml index d5440025ae..9c8584f7e5 100644 --- a/src/Avalonia.Themes.Fluent/Controls/TabStripItem.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/TabStripItem.xaml @@ -1,6 +1,7 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/TextBox.xaml b/src/Avalonia.Themes.Fluent/Controls/TextBox.xaml index 40abac8e86..2c05ad6f64 100644 --- a/src/Avalonia.Themes.Fluent/Controls/TextBox.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/TextBox.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ThemeVariantScope.xaml b/src/Avalonia.Themes.Fluent/Controls/ThemeVariantScope.xaml index 21a5506b88..2e8715c9b9 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ThemeVariantScope.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ThemeVariantScope.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml b/src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml index 39f7b0b224..38868f3cdf 100644 --- a/src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml @@ -7,7 +7,8 @@ + xmlns:sys="using:System" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/TitleBar.xaml b/src/Avalonia.Themes.Fluent/Controls/TitleBar.xaml index 5730b19e78..2eff04218d 100644 --- a/src/Avalonia.Themes.Fluent/Controls/TitleBar.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/TitleBar.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ToggleButton.xaml b/src/Avalonia.Themes.Fluent/Controls/ToggleButton.xaml index da2021790a..1b54e6deaf 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ToggleButton.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ToggleButton.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ToggleSwitch.xaml b/src/Avalonia.Themes.Fluent/Controls/ToggleSwitch.xaml index c88839f7d2..47d7953096 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ToggleSwitch.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ToggleSwitch.xaml @@ -1,6 +1,7 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/ToolTip.xaml b/src/Avalonia.Themes.Fluent/Controls/ToolTip.xaml index 8b086a8d10..b2fcfc7ddf 100644 --- a/src/Avalonia.Themes.Fluent/Controls/ToolTip.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/ToolTip.xaml @@ -1,6 +1,7 @@  + xmlns:sys="using:System" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/TransitioningContentControl.xaml b/src/Avalonia.Themes.Fluent/Controls/TransitioningContentControl.xaml index e53fc1aad4..2078322318 100644 --- a/src/Avalonia.Themes.Fluent/Controls/TransitioningContentControl.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/TransitioningContentControl.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/TreeView.xaml b/src/Avalonia.Themes.Fluent/Controls/TreeView.xaml index 241d3e2b74..0fdcaf39f8 100644 --- a/src/Avalonia.Themes.Fluent/Controls/TreeView.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/TreeView.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/TreeViewItem.xaml b/src/Avalonia.Themes.Fluent/Controls/TreeViewItem.xaml index eff3920b12..c92774bc10 100644 --- a/src/Avalonia.Themes.Fluent/Controls/TreeViewItem.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/TreeViewItem.xaml @@ -1,6 +1,7 @@  + xmlns:converters="using:Avalonia.Controls.Converters" + x:ClassModifier="internal"> + Selector=":is(UserControl)" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/Window.xaml b/src/Avalonia.Themes.Fluent/Controls/Window.xaml index 8db01fa4c8..52d16e7ada 100644 --- a/src/Avalonia.Themes.Fluent/Controls/Window.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/Window.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/Controls/WindowNotificationManager.xaml b/src/Avalonia.Themes.Fluent/Controls/WindowNotificationManager.xaml index e4cd0b25a6..a62f4adfd6 100644 --- a/src/Avalonia.Themes.Fluent/Controls/WindowNotificationManager.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/WindowNotificationManager.xaml @@ -1,6 +1,7 @@  + x:DataType="WindowNotificationManager" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/DensityStyles/Compact.xaml b/src/Avalonia.Themes.Fluent/DensityStyles/Compact.xaml index b96671b778..d335e6f4b9 100644 --- a/src/Avalonia.Themes.Fluent/DensityStyles/Compact.xaml +++ b/src/Avalonia.Themes.Fluent/DensityStyles/Compact.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Fluent/FluentTheme.xaml b/src/Avalonia.Themes.Fluent/FluentTheme.xaml index 0528c40c21..c84772aa61 100644 --- a/src/Avalonia.Themes.Fluent/FluentTheme.xaml +++ b/src/Avalonia.Themes.Fluent/FluentTheme.xaml @@ -2,7 +2,7 @@ xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:fluent="using:Avalonia.Themes.Fluent" - xmlns:accents="clr-namespace:Avalonia.Themes.Fluent.Accents"> + xmlns:accents="using:Avalonia.Themes.Fluent.Accents"> diff --git a/src/Avalonia.Themes.Simple/Accents/Base.xaml b/src/Avalonia.Themes.Simple/Accents/Base.xaml index 0640fe9a4a..ca5c2e7d30 100644 --- a/src/Avalonia.Themes.Simple/Accents/Base.xaml +++ b/src/Avalonia.Themes.Simple/Accents/Base.xaml @@ -1,6 +1,7 @@  + xmlns:sys="using:System" + x:ClassModifier="internal"> #FFFFFFFF diff --git a/src/Avalonia.Themes.Simple/Controls/AdornerLayer.xaml b/src/Avalonia.Themes.Simple/Controls/AdornerLayer.xaml index 1f3acb07dc..165ab44fc8 100644 --- a/src/Avalonia.Themes.Simple/Controls/AdornerLayer.xaml +++ b/src/Avalonia.Themes.Simple/Controls/AdornerLayer.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/AutoCompleteBox.xaml b/src/Avalonia.Themes.Simple/Controls/AutoCompleteBox.xaml index 65dfaf982b..b861c5f3ea 100644 --- a/src/Avalonia.Themes.Simple/Controls/AutoCompleteBox.xaml +++ b/src/Avalonia.Themes.Simple/Controls/AutoCompleteBox.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/Button.xaml b/src/Avalonia.Themes.Simple/Controls/Button.xaml index 9018677ab6..5599e49ae1 100644 --- a/src/Avalonia.Themes.Simple/Controls/Button.xaml +++ b/src/Avalonia.Themes.Simple/Controls/Button.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/ButtonSpinner.xaml b/src/Avalonia.Themes.Simple/Controls/ButtonSpinner.xaml index 57d6eabea4..14472d601f 100644 --- a/src/Avalonia.Themes.Simple/Controls/ButtonSpinner.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ButtonSpinner.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/CalendarButton.xaml b/src/Avalonia.Themes.Simple/Controls/CalendarButton.xaml index 9e13e1e996..1e06368d24 100644 --- a/src/Avalonia.Themes.Simple/Controls/CalendarButton.xaml +++ b/src/Avalonia.Themes.Simple/Controls/CalendarButton.xaml @@ -6,7 +6,8 @@ --> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/CalendarDatePicker.xaml b/src/Avalonia.Themes.Simple/Controls/CalendarDatePicker.xaml index a7c7b5f620..60759eebb1 100644 --- a/src/Avalonia.Themes.Simple/Controls/CalendarDatePicker.xaml +++ b/src/Avalonia.Themes.Simple/Controls/CalendarDatePicker.xaml @@ -7,7 +7,8 @@ + xmlns:sys="using:System" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/CalendarDayButton.xaml b/src/Avalonia.Themes.Simple/Controls/CalendarDayButton.xaml index 0973a3b752..e16b9f38ba 100644 --- a/src/Avalonia.Themes.Simple/Controls/CalendarDayButton.xaml +++ b/src/Avalonia.Themes.Simple/Controls/CalendarDayButton.xaml @@ -6,7 +6,8 @@ --> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/CalendarItem.xaml b/src/Avalonia.Themes.Simple/Controls/CalendarItem.xaml index f022746bf5..e9e9299960 100644 --- a/src/Avalonia.Themes.Simple/Controls/CalendarItem.xaml +++ b/src/Avalonia.Themes.Simple/Controls/CalendarItem.xaml @@ -6,7 +6,8 @@ --> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/CaptionButtons.xaml b/src/Avalonia.Themes.Simple/Controls/CaptionButtons.xaml index 8f68d9809f..e5978919fa 100644 --- a/src/Avalonia.Themes.Simple/Controls/CaptionButtons.xaml +++ b/src/Avalonia.Themes.Simple/Controls/CaptionButtons.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/Carousel.xaml b/src/Avalonia.Themes.Simple/Controls/Carousel.xaml index 91e331693e..b94ef9b5d9 100644 --- a/src/Avalonia.Themes.Simple/Controls/Carousel.xaml +++ b/src/Avalonia.Themes.Simple/Controls/Carousel.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/CheckBox.xaml b/src/Avalonia.Themes.Simple/Controls/CheckBox.xaml index 10e0b883d5..68e969c140 100644 --- a/src/Avalonia.Themes.Simple/Controls/CheckBox.xaml +++ b/src/Avalonia.Themes.Simple/Controls/CheckBox.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/ComboBox.xaml b/src/Avalonia.Themes.Simple/Controls/ComboBox.xaml index 8b751187d6..a54857abc9 100644 --- a/src/Avalonia.Themes.Simple/Controls/ComboBox.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ComboBox.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/ComboBoxItem.xaml b/src/Avalonia.Themes.Simple/Controls/ComboBoxItem.xaml index c3d8b6f900..da1b964871 100644 --- a/src/Avalonia.Themes.Simple/Controls/ComboBoxItem.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ComboBoxItem.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/ContentControl.xaml b/src/Avalonia.Themes.Simple/Controls/ContentControl.xaml index 415b1dc721..571a276a49 100644 --- a/src/Avalonia.Themes.Simple/Controls/ContentControl.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ContentControl.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/ContextMenu.xaml b/src/Avalonia.Themes.Simple/Controls/ContextMenu.xaml index 3317178979..215f4eec5a 100644 --- a/src/Avalonia.Themes.Simple/Controls/ContextMenu.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ContextMenu.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/DataValidationErrors.xaml b/src/Avalonia.Themes.Simple/Controls/DataValidationErrors.xaml index a4e5ab2d90..ec5ad87bbc 100644 --- a/src/Avalonia.Themes.Simple/Controls/DataValidationErrors.xaml +++ b/src/Avalonia.Themes.Simple/Controls/DataValidationErrors.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/DatePicker.xaml b/src/Avalonia.Themes.Simple/Controls/DatePicker.xaml index 6cf352518a..6ead5019c6 100644 --- a/src/Avalonia.Themes.Simple/Controls/DatePicker.xaml +++ b/src/Avalonia.Themes.Simple/Controls/DatePicker.xaml @@ -7,7 +7,8 @@ + xmlns:sys="using:System" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/DateTimePickerShared.xaml b/src/Avalonia.Themes.Simple/Controls/DateTimePickerShared.xaml index 5f1dea692f..5ba4e058ed 100644 --- a/src/Avalonia.Themes.Simple/Controls/DateTimePickerShared.xaml +++ b/src/Avalonia.Themes.Simple/Controls/DateTimePickerShared.xaml @@ -6,7 +6,8 @@ --> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/DropDownButton.xaml b/src/Avalonia.Themes.Simple/Controls/DropDownButton.xaml index 6a50cd6e36..6d79d420f3 100644 --- a/src/Avalonia.Themes.Simple/Controls/DropDownButton.xaml +++ b/src/Avalonia.Themes.Simple/Controls/DropDownButton.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/EmbeddableControlRoot.xaml b/src/Avalonia.Themes.Simple/Controls/EmbeddableControlRoot.xaml index 3ea1515cc3..87c940c281 100644 --- a/src/Avalonia.Themes.Simple/Controls/EmbeddableControlRoot.xaml +++ b/src/Avalonia.Themes.Simple/Controls/EmbeddableControlRoot.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/Expander.xaml b/src/Avalonia.Themes.Simple/Controls/Expander.xaml index 9920c9445a..cdc2894979 100644 --- a/src/Avalonia.Themes.Simple/Controls/Expander.xaml +++ b/src/Avalonia.Themes.Simple/Controls/Expander.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/GridSplitter.xaml b/src/Avalonia.Themes.Simple/Controls/GridSplitter.xaml index f2a3f01397..c4385ab0b4 100644 --- a/src/Avalonia.Themes.Simple/Controls/GridSplitter.xaml +++ b/src/Avalonia.Themes.Simple/Controls/GridSplitter.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/ItemsControl.xaml b/src/Avalonia.Themes.Simple/Controls/ItemsControl.xaml index 8cf4e0be08..ba6b37fd90 100644 --- a/src/Avalonia.Themes.Simple/Controls/ItemsControl.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ItemsControl.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/Label.xaml b/src/Avalonia.Themes.Simple/Controls/Label.xaml index 0faa4852f2..2c9bb15742 100644 --- a/src/Avalonia.Themes.Simple/Controls/Label.xaml +++ b/src/Avalonia.Themes.Simple/Controls/Label.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/ListBox.xaml b/src/Avalonia.Themes.Simple/Controls/ListBox.xaml index a51fcbf72e..eeefa498a7 100644 --- a/src/Avalonia.Themes.Simple/Controls/ListBox.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ListBox.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/ListBoxItem.xaml b/src/Avalonia.Themes.Simple/Controls/ListBoxItem.xaml index 4d918326c8..c2a96c71a6 100644 --- a/src/Avalonia.Themes.Simple/Controls/ListBoxItem.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ListBoxItem.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml b/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml index cc049938ad..24e5247139 100644 --- a/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml @@ -1,7 +1,8 @@ + xmlns:internal="using:Avalonia.Dialogs.Internal" + x:ClassModifier="internal"> + xmlns:sys="using:System" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/MenuFlyoutPresenter.xaml b/src/Avalonia.Themes.Simple/Controls/MenuFlyoutPresenter.xaml index 05337d774f..73835b8155 100644 --- a/src/Avalonia.Themes.Simple/Controls/MenuFlyoutPresenter.xaml +++ b/src/Avalonia.Themes.Simple/Controls/MenuFlyoutPresenter.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/MenuItem.xaml b/src/Avalonia.Themes.Simple/Controls/MenuItem.xaml index 59ddcdf325..063c0d3d68 100644 --- a/src/Avalonia.Themes.Simple/Controls/MenuItem.xaml +++ b/src/Avalonia.Themes.Simple/Controls/MenuItem.xaml @@ -1,7 +1,8 @@ + xmlns:sys="using:System" + x:ClassModifier="internal"> + xmlns:default="using:Avalonia.Themes.Simple" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/NotificationCard.xaml b/src/Avalonia.Themes.Simple/Controls/NotificationCard.xaml index 524f964afc..62e73a8dd0 100644 --- a/src/Avalonia.Themes.Simple/Controls/NotificationCard.xaml +++ b/src/Avalonia.Themes.Simple/Controls/NotificationCard.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/NumericUpDown.xaml b/src/Avalonia.Themes.Simple/Controls/NumericUpDown.xaml index d3adfb31e0..4ce6a20dc6 100644 --- a/src/Avalonia.Themes.Simple/Controls/NumericUpDown.xaml +++ b/src/Avalonia.Themes.Simple/Controls/NumericUpDown.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/OverlayPopupHost.xaml b/src/Avalonia.Themes.Simple/Controls/OverlayPopupHost.xaml index 4c7864473b..c70721aac7 100644 --- a/src/Avalonia.Themes.Simple/Controls/OverlayPopupHost.xaml +++ b/src/Avalonia.Themes.Simple/Controls/OverlayPopupHost.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/PathIcon.xaml b/src/Avalonia.Themes.Simple/Controls/PathIcon.xaml index 4116b5784e..9e39ba4645 100644 --- a/src/Avalonia.Themes.Simple/Controls/PathIcon.xaml +++ b/src/Avalonia.Themes.Simple/Controls/PathIcon.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/PopupRoot.xaml b/src/Avalonia.Themes.Simple/Controls/PopupRoot.xaml index 33c8d0764e..aaf51a2cef 100644 --- a/src/Avalonia.Themes.Simple/Controls/PopupRoot.xaml +++ b/src/Avalonia.Themes.Simple/Controls/PopupRoot.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/ProgressBar.xaml b/src/Avalonia.Themes.Simple/Controls/ProgressBar.xaml index 1f4bf006a0..4278c7ee28 100644 --- a/src/Avalonia.Themes.Simple/Controls/ProgressBar.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ProgressBar.xaml @@ -1,6 +1,7 @@ + xmlns:converters="using:Avalonia.Controls.Converters" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/RadioButton.xaml b/src/Avalonia.Themes.Simple/Controls/RadioButton.xaml index c837b44402..ea138d8806 100644 --- a/src/Avalonia.Themes.Simple/Controls/RadioButton.xaml +++ b/src/Avalonia.Themes.Simple/Controls/RadioButton.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/RefreshContainer.xaml b/src/Avalonia.Themes.Simple/Controls/RefreshContainer.xaml index 04b2a1bf29..0a293cc977 100644 --- a/src/Avalonia.Themes.Simple/Controls/RefreshContainer.xaml +++ b/src/Avalonia.Themes.Simple/Controls/RefreshContainer.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/RefreshVisualizer.xaml b/src/Avalonia.Themes.Simple/Controls/RefreshVisualizer.xaml index bd7e43530a..09f15e4b2a 100644 --- a/src/Avalonia.Themes.Simple/Controls/RefreshVisualizer.xaml +++ b/src/Avalonia.Themes.Simple/Controls/RefreshVisualizer.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/ScrollBar.xaml b/src/Avalonia.Themes.Simple/Controls/ScrollBar.xaml index d28ba66f6d..8b647c8299 100644 --- a/src/Avalonia.Themes.Simple/Controls/ScrollBar.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ScrollBar.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/ScrollViewer.xaml b/src/Avalonia.Themes.Simple/Controls/ScrollViewer.xaml index 4f6fc5f322..2b36b118c3 100644 --- a/src/Avalonia.Themes.Simple/Controls/ScrollViewer.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ScrollViewer.xaml @@ -1,6 +1,7 @@ + xmlns:converters="using:Avalonia.Controls.Converters" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/SelectableTextBlock.xaml b/src/Avalonia.Themes.Simple/Controls/SelectableTextBlock.xaml index e504a8cf8e..504e727fa0 100644 --- a/src/Avalonia.Themes.Simple/Controls/SelectableTextBlock.xaml +++ b/src/Avalonia.Themes.Simple/Controls/SelectableTextBlock.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/Separator.xaml b/src/Avalonia.Themes.Simple/Controls/Separator.xaml index e142cf29ad..0d7202c8b4 100644 --- a/src/Avalonia.Themes.Simple/Controls/Separator.xaml +++ b/src/Avalonia.Themes.Simple/Controls/Separator.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/SimpleControls.xaml b/src/Avalonia.Themes.Simple/Controls/SimpleControls.xaml index dc533488c9..3b4a1d8104 100644 --- a/src/Avalonia.Themes.Simple/Controls/SimpleControls.xaml +++ b/src/Avalonia.Themes.Simple/Controls/SimpleControls.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/Slider.xaml b/src/Avalonia.Themes.Simple/Controls/Slider.xaml index 851ee1b78a..da840dbbd5 100644 --- a/src/Avalonia.Themes.Simple/Controls/Slider.xaml +++ b/src/Avalonia.Themes.Simple/Controls/Slider.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/SplitButton.xaml b/src/Avalonia.Themes.Simple/Controls/SplitButton.xaml index 2a7dc081f0..7562c9151e 100644 --- a/src/Avalonia.Themes.Simple/Controls/SplitButton.xaml +++ b/src/Avalonia.Themes.Simple/Controls/SplitButton.xaml @@ -1,6 +1,7 @@  + xmlns:converters="using:Avalonia.Controls.Converters" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/SplitView.xaml b/src/Avalonia.Themes.Simple/Controls/SplitView.xaml index f839e9a598..8d4851add8 100644 --- a/src/Avalonia.Themes.Simple/Controls/SplitView.xaml +++ b/src/Avalonia.Themes.Simple/Controls/SplitView.xaml @@ -1,6 +1,7 @@ + xmlns:sys="using:System" + x:ClassModifier="internal"> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/TabItem.xaml b/src/Avalonia.Themes.Simple/Controls/TabItem.xaml index 7b6a1d1116..50a269bf79 100644 --- a/src/Avalonia.Themes.Simple/Controls/TabItem.xaml +++ b/src/Avalonia.Themes.Simple/Controls/TabItem.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/TabStrip.xaml b/src/Avalonia.Themes.Simple/Controls/TabStrip.xaml index fd12eaa258..9d08c73453 100644 --- a/src/Avalonia.Themes.Simple/Controls/TabStrip.xaml +++ b/src/Avalonia.Themes.Simple/Controls/TabStrip.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/TabStripItem.xaml b/src/Avalonia.Themes.Simple/Controls/TabStripItem.xaml index b4d7218ec3..f0609bf66b 100644 --- a/src/Avalonia.Themes.Simple/Controls/TabStripItem.xaml +++ b/src/Avalonia.Themes.Simple/Controls/TabStripItem.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/TextBox.xaml b/src/Avalonia.Themes.Simple/Controls/TextBox.xaml index b835bf10aa..63da3cee44 100644 --- a/src/Avalonia.Themes.Simple/Controls/TextBox.xaml +++ b/src/Avalonia.Themes.Simple/Controls/TextBox.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> M 11.416016,10 20,1.4160156 18.583984,0 10,8.5839846 1.4160156,0 0,1.4160156 8.5839844,10 0,18.583985 1.4160156,20 10,11.416015 18.583984,20 20,18.583985 Z m10.051 7.0032c2.215 0 4.0105 1.7901 4.0105 3.9984s-1.7956 3.9984-4.0105 3.9984c-2.215 0-4.0105-1.7901-4.0105-3.9984s1.7956-3.9984 4.0105-3.9984zm0 1.4994c-1.3844 0-2.5066 1.1188-2.5066 2.499s1.1222 2.499 2.5066 2.499 2.5066-1.1188 2.5066-2.499-1.1222-2.499-2.5066-2.499zm0-5.0026c4.6257 0 8.6188 3.1487 9.7267 7.5613 0.10085 0.40165-0.14399 0.80877-0.54686 0.90931-0.40288 0.10054-0.81122-0.14355-0.91208-0.54521-0.94136-3.7492-4.3361-6.4261-8.2678-6.4261-3.9334 0-7.3292 2.6792-8.2689 6.4306-0.10063 0.40171-0.50884 0.64603-0.91177 0.54571s-0.648-0.5073-0.54737-0.90901c1.106-4.4152 5.1003-7.5667 9.728-7.5667z m0.21967 0.21965c-0.26627 0.26627-0.29047 0.68293-0.07262 0.97654l0.07262 0.08412 4.0346 4.0346c-1.922 1.3495-3.3585 3.365-3.9554 5.7495-0.10058 0.4018 0.14362 0.8091 0.54543 0.9097 0.40182 0.1005 0.80909-0.1436 0.90968-0.5455 0.52947-2.1151 1.8371-3.8891 3.5802-5.0341l1.8096 1.8098c-0.70751 0.7215-1.1438 1.71-1.1438 2.8003 0 2.2092 1.7909 4 4 4 1.0904 0 2.0788-0.4363 2.8004-1.1438l5.9193 5.9195c0.2929 0.2929 0.7677 0.2929 1.0606 0 0.2663-0.2662 0.2905-0.6829 0.0726-0.9765l-0.0726-0.0841-6.1135-6.1142 0.0012-0.0015-1.2001-1.1979-2.8699-2.8693 2e-3 -8e-4 -2.8812-2.8782 0.0012-0.0018-1.1333-1.1305-4.3064-4.3058c-0.29289-0.29289-0.76777-0.29289-1.0607 0zm7.9844 9.0458 3.5351 3.5351c-0.45 0.4358-1.0633 0.704-1.7392 0.704-1.3807 0-2.5-1.1193-2.5-2.5 0-0.6759 0.26824-1.2892 0.7041-1.7391zm1.7959-5.7655c-1.0003 0-1.9709 0.14807-2.8889 0.425l1.237 1.2362c0.5358-0.10587 1.0883-0.16119 1.6519-0.16119 3.9231 0 7.3099 2.6803 8.2471 6.4332 0.1004 0.4018 0.5075 0.6462 0.9094 0.5459 0.4019-0.1004 0.6463-0.5075 0.5459-0.9094-1.103-4.417-5.0869-7.5697-9.7024-7.5697zm0.1947 3.5093 3.8013 3.8007c-0.1018-2.0569-1.7488-3.7024-3.8013-3.8007z diff --git a/src/Avalonia.Themes.Simple/Controls/ThemeVariantScope.xaml b/src/Avalonia.Themes.Simple/Controls/ThemeVariantScope.xaml index a6022fb263..2eb157cf6b 100644 --- a/src/Avalonia.Themes.Simple/Controls/ThemeVariantScope.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ThemeVariantScope.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/TimePicker.xaml b/src/Avalonia.Themes.Simple/Controls/TimePicker.xaml index 5acbc41a68..adac54a262 100644 --- a/src/Avalonia.Themes.Simple/Controls/TimePicker.xaml +++ b/src/Avalonia.Themes.Simple/Controls/TimePicker.xaml @@ -7,7 +7,8 @@ + xmlns:sys="using:System" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/TitleBar.xaml b/src/Avalonia.Themes.Simple/Controls/TitleBar.xaml index a06dfbb834..67b1eae9da 100644 --- a/src/Avalonia.Themes.Simple/Controls/TitleBar.xaml +++ b/src/Avalonia.Themes.Simple/Controls/TitleBar.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/ToggleSwitch.xaml b/src/Avalonia.Themes.Simple/Controls/ToggleSwitch.xaml index f7223c46c0..a51aeb9ee6 100644 --- a/src/Avalonia.Themes.Simple/Controls/ToggleSwitch.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ToggleSwitch.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/ToolTip.xaml b/src/Avalonia.Themes.Simple/Controls/ToolTip.xaml index c4fddd8c4c..2c67e2c650 100644 --- a/src/Avalonia.Themes.Simple/Controls/ToolTip.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ToolTip.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/TransitioningContentControl.xaml b/src/Avalonia.Themes.Simple/Controls/TransitioningContentControl.xaml index fa8d749b1f..ceccdf56c7 100644 --- a/src/Avalonia.Themes.Simple/Controls/TransitioningContentControl.xaml +++ b/src/Avalonia.Themes.Simple/Controls/TransitioningContentControl.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/TreeView.xaml b/src/Avalonia.Themes.Simple/Controls/TreeView.xaml index f2f451fe6f..d76bf6c393 100644 --- a/src/Avalonia.Themes.Simple/Controls/TreeView.xaml +++ b/src/Avalonia.Themes.Simple/Controls/TreeView.xaml @@ -1,5 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/TreeViewItem.xaml b/src/Avalonia.Themes.Simple/Controls/TreeViewItem.xaml index 8e85bcbd44..c3c3801ec0 100644 --- a/src/Avalonia.Themes.Simple/Controls/TreeViewItem.xaml +++ b/src/Avalonia.Themes.Simple/Controls/TreeViewItem.xaml @@ -1,6 +1,7 @@ + xmlns:converters="using:Avalonia.Controls.Converters" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Themes.Simple/Controls/UserControl.xaml b/src/Avalonia.Themes.Simple/Controls/UserControl.xaml index 3316b0298c..7f33b803d7 100644 --- a/src/Avalonia.Themes.Simple/Controls/UserControl.xaml +++ b/src/Avalonia.Themes.Simple/Controls/UserControl.xaml @@ -1,6 +1,7 @@ - - diff --git a/src/Avalonia.Themes.Simple/Controls/ToggleSwitch.xaml b/src/Avalonia.Themes.Simple/Controls/ToggleSwitch.xaml index a51aeb9ee6..1178c96419 100644 --- a/src/Avalonia.Themes.Simple/Controls/ToggleSwitch.xaml +++ b/src/Avalonia.Themes.Simple/Controls/ToggleSwitch.xaml @@ -46,6 +46,14 @@ + + + + + - - - - - + + + - - - - - -