Browse Source

Merge fixes

feature/pen-eraser-detection
flabbet 5 months ago
parent
commit
d5095ce6f7
  1. 25
      src/Android/Avalonia.Android/Automation/ToggleNodeInfoProvider.cs
  2. 15
      src/Avalonia.Base/Input/MouseDevice.cs
  3. 18
      src/Avalonia.Base/Platform/Storage/FileIO/StorageProviderHelpers.cs
  4. 5
      src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml
  5. 5
      src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorView.xaml
  6. 6
      src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs
  7. 4
      src/Avalonia.Native/TopLevelImpl.cs
  8. 5
      src/Avalonia.Themes.Fluent/Controls/Button.xaml
  9. 5
      src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml
  10. 5
      src/Avalonia.Themes.Fluent/Controls/DropDownButton.xaml
  11. 11
      src/Avalonia.Themes.Fluent/Controls/GroupBox.xaml
  12. 11
      src/Avalonia.Themes.Fluent/Controls/HeaderedContentControl.xaml
  13. 7
      src/Avalonia.Themes.Fluent/Controls/HyperlinkButton.xaml
  14. 5
      src/Avalonia.Themes.Fluent/Controls/Label.xaml
  15. 5
      src/Avalonia.Themes.Fluent/Controls/Menu.xaml
  16. 5
      src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml
  17. 7
      src/Avalonia.Themes.Fluent/Controls/RadioButton.xaml
  18. 5
      src/Avalonia.Themes.Fluent/Controls/SplitButton.xaml
  19. 5
      src/Avalonia.Themes.Fluent/Controls/TabItem.xaml
  20. 5
      src/Avalonia.Themes.Fluent/Controls/ToggleButton.xaml
  21. 7
      src/Avalonia.Themes.Fluent/Controls/ToggleSwitch.xaml
  22. 6
      src/Avalonia.Themes.Simple/Controls/Button.xaml
  23. 6
      src/Avalonia.Themes.Simple/Controls/CheckBox.xaml
  24. 7
      src/Avalonia.Themes.Simple/Controls/DropDownButton.xaml
  25. 10
      src/Avalonia.Themes.Simple/Controls/GroupBox.xaml
  26. 10
      src/Avalonia.Themes.Simple/Controls/HeaderedContentControl.xaml
  27. 5
      src/Avalonia.Themes.Simple/Controls/HyperlinkButton.xaml
  28. 7
      src/Avalonia.Themes.Simple/Controls/Label.xaml
  29. 7
      src/Avalonia.Themes.Simple/Controls/RadioButton.xaml
  30. 5
      src/Avalonia.Themes.Simple/Controls/SplitButton.xaml
  31. 6
      src/Avalonia.Themes.Simple/Controls/TabItem.xaml
  32. 6
      src/Avalonia.Themes.Simple/Controls/ToggleButton.xaml
  33. 5
      src/Avalonia.Themes.Simple/Controls/ToggleSwitch.xaml
  34. 4
      src/Avalonia.X11/X11Window.cs
  35. 31
      src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
  36. 6
      src/Windows/Avalonia.Win32/WindowImpl.cs
  37. 2
      src/tools/Avalonia.Generators/Common/EquatableList.cs
  38. 28
      src/tools/Avalonia.Generators/GeneratorExtensions.cs
  39. 144
      src/tools/Avalonia.Generators/NameGenerator/AvaloniaNameIncrementalGenerator.cs
  40. 39
      src/tools/Avalonia.Generators/NameGenerator/NameGeneratorDiagnostics.cs
  41. 11
      tests/Avalonia.Base.UnitTests/Utilities/UriExtensionsTests.cs

25
src/Android/Avalonia.Android/Automation/ToggleNodeInfoProvider.cs

@ -1,4 +1,5 @@
using Android.OS;
using System.Reflection;
using Android.OS;
using AndroidX.Core.View.Accessibility;
using AndroidX.CustomView.Widget;
using Avalonia.Automation.Peers;
@ -8,6 +9,8 @@ namespace Avalonia.Android.Automation
{
internal class ToggleNodeInfoProvider : NodeInfoProvider<IToggleProvider>
{
private PropertyInfo? _checkedProperty;
public ToggleNodeInfoProvider(ExploreByTouchHelper owner, AutomationPeer peer, int virtualViewId) :
base(owner, peer, virtualViewId)
{
@ -32,7 +35,25 @@ namespace Avalonia.Android.Automation
nodeInfo.Clickable = true;
IToggleProvider provider = GetProvider();
nodeInfo.Checked = provider.ToggleState == ToggleState.On;
_checkedProperty ??= nodeInfo.GetType().GetProperty(nameof(nodeInfo.Checked));
if (_checkedProperty?.PropertyType == typeof(int))
{
// Needed for Xamarin.AndroidX.Core 1.17+
_checkedProperty.SetValue(this,
provider.ToggleState switch
{
ToggleState.On => 1,
ToggleState.Indeterminate => 2,
_ => 0
});
}
else if (_checkedProperty?.PropertyType == typeof(bool))
{
// Needed for Xamarin.AndroidX.Core < 1.17
_checkedProperty.SetValue(this, provider.ToggleState == ToggleState.On);
}
nodeInfo.Checkable = true;
}
}

15
src/Avalonia.Base/Input/MouseDevice.cs

@ -18,6 +18,9 @@ namespace Avalonia.Input
[PrivateApi]
public class MouseDevice : IMouseDevice, IDisposable
{
private static MouseDevice? _primary;
internal static MouseDevice Primary => _primary ??= new MouseDevice();
private int _clickCount;
private Rect _lastClickRect;
private ulong _lastClickTime;
@ -31,6 +34,16 @@ namespace Avalonia.Input
_pointer = pointer ?? new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true);
}
internal static TMouseDevice GetOrCreatePrimary<TMouseDevice>() where TMouseDevice : MouseDevice, new()
{
if (_primary is TMouseDevice device)
return device;
device = new TMouseDevice();
_primary = device;
return device;
}
public void ProcessRawEvent(RawInputEventArgs e)
{
if (!e.Handled && e is RawPointerEventArgs margs)
@ -300,6 +313,8 @@ namespace Avalonia.Input
public void Dispose()
{
System.Diagnostics.Debug.Assert(this != _primary, "Disposing primary mouse device.");
_disposed = true;
_pointer?.Dispose();
}

18
src/Avalonia.Base/Platform/Storage/FileIO/StorageProviderHelpers.cs

@ -37,11 +37,19 @@ internal static class StorageProviderHelpers
public static Uri UriFromFilePath(string path, bool isDirectory)
{
var uriPath = new StringBuilder(path)
.Replace("%", $"%{(int)'%':X2}")
.Replace("[", $"%{(int)'[':X2}")
.Replace("]", $"%{(int)']':X2}");
var uriPath = new StringBuilder();
bool isLongPath = path.StartsWith(@"\\?\", StringComparison.Ordinal);//Windows long path prefix
if (isLongPath)
{
uriPath.Append(path, 4, path.Length - 4);
}
else
{
uriPath.Append(path);
}
uriPath = uriPath.Replace("%", $"%{(int)'%':X2}")
.Replace("[", $"%{(int)'[':X2}")
.Replace("]", $"%{(int)']':X2}");
if (!path.EndsWith('/') && isDirectory)
{
uriPath.Append('/');

5
src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml

@ -185,12 +185,15 @@
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
RecognizesAccessKey="True"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushPointerOver}" />

5
src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorView.xaml

@ -183,12 +183,15 @@
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
RecognizesAccessKey="True"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:checked /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ThemeControlHighBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderMidBrush}" />

6
src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs

@ -64,6 +64,12 @@ namespace Avalonia.DesignerSupport.Remote
public void Resize(Size clientSize, WindowResizeReason reason)
{
// Don't let it clientSize be unconstrained or risk running Out Of Memory
clientSize = new Size(
Math.Min(clientSize.Width, MaxAutoSizeHint.Width),
Math.Min(clientSize.Height, MaxAutoSizeHint.Height)
);
_transport.Send(new RequestViewportResizeMessage
{
Width = Math.Ceiling(clientSize.Width * RenderScaling),

4
src/Avalonia.Native/TopLevelImpl.cs

@ -89,7 +89,7 @@ internal class TopLevelImpl : ITopLevelImpl, IFramebufferPlatformSurface
Factory = factory;
_keyboard = AvaloniaLocator.Current.GetService<IKeyboardDevice>();
_mouse = new MouseDevice();
_mouse = Avalonia.Input.MouseDevice.Primary;
_pen = new PenDevice();
_cursorFactory = AvaloniaLocator.Current.GetService<ICursorFactory>();
}
@ -387,8 +387,6 @@ internal class TopLevelImpl : ITopLevelImpl, IFramebufferPlatformSurface
_nativeControlHost?.Dispose();
_nativeControlHost = null;
_mouse?.Dispose();
}
protected virtual bool ChromeHitTest(RawPointerEventArgs e)

5
src/Avalonia.Themes.Fluent/Controls/Button.xaml

@ -36,12 +36,15 @@
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
RecognizesAccessKey="True"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPointerOver}" />

5
src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml

@ -62,7 +62,6 @@
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Margin="{TemplateBinding Padding}"
RecognizesAccessKey="True"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextWrapping="Wrap"
@ -71,6 +70,10 @@
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<!-- Unchecked PointerOver State -->
<Style Selector="^:pointerover">
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">

5
src/Avalonia.Themes.Fluent/Controls/DropDownButton.xaml

@ -44,7 +44,6 @@
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
RecognizesAccessKey="True"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
@ -65,6 +64,10 @@
</Setter.Value>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<!-- PointerOver State -->
<Style Selector="^:pointerover /template/ Border#RootBorder">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundPointerOver}" />

11
src/Avalonia.Themes.Fluent/Controls/GroupBox.xaml

@ -56,7 +56,6 @@
Grid.Column="1">
<ContentPresenter Name="PART_HeaderPresenter"
Content="{TemplateBinding Header}"
RecognizesAccessKey="True"
FontSize="{DynamicResource GroupBoxHeaderFontSize}"
Foreground="{DynamicResource GroupBoxHeaderForeground}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
@ -71,7 +70,6 @@
Name="PART_ContentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
RecognizesAccessKey="True"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
UseLayoutRounding="{TemplateBinding UseLayoutRounding}"
@ -79,5 +77,14 @@
</Grid>
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_HeaderPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
</ControlTheme>
</ResourceDictionary>

11
src/Avalonia.Themes.Fluent/Controls/HeaderedContentControl.xaml

@ -15,7 +15,6 @@
<Grid RowDefinitions="auto *">
<ContentPresenter Name="PART_HeaderPresenter"
Content="{TemplateBinding Header}"
RecognizesAccessKey="True"
ContentTemplate="{TemplateBinding HeaderTemplate}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
@ -23,7 +22,6 @@
<ContentPresenter Name="PART_ContentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
RecognizesAccessKey="True"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
Grid.Row="1" />
@ -31,5 +29,14 @@
</Border>
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_HeaderPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
</ControlTheme>
</ResourceDictionary>

7
src/Avalonia.Themes.Fluent/Controls/HyperlinkButton.xaml

@ -5,7 +5,7 @@
<Design.PreviewWith>
<Border Padding="20">
<StackPanel Spacing="20">
<HyperlinkButton Content="Click Me!" />
<HyperlinkButton Content="_Click Me!" />
</StackPanel>
</Border>
</Design.PreviewWith>
@ -42,12 +42,15 @@
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
RecognizesAccessKey="True"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource HyperlinkButtonBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource HyperlinkButtonBorderBrushPointerOver}" />

5
src/Avalonia.Themes.Fluent/Controls/Label.xaml

@ -14,10 +14,13 @@
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"
RecognizesAccessKey="True"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
</ControlTheme>
</ResourceDictionary>

5
src/Avalonia.Themes.Fluent/Controls/Menu.xaml

@ -31,7 +31,6 @@
ContentTemplate="{TemplateBinding HeaderTemplate}"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
RecognizesAccessKey="True"
Margin="{TemplateBinding Padding}"/>
<Popup Name="PART_Popup"
WindowManagerAddShadowHint="False"
@ -61,6 +60,10 @@
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_HeaderPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:selected">
<Style Selector="^ /template/ Border#PART_LayoutRoot">
<Setter Property="Background" Value="{DynamicResource MenuFlyoutItemBackgroundPointerOver}" />

5
src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml

@ -100,7 +100,6 @@
ContentTemplate="{TemplateBinding HeaderTemplate}"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
RecognizesAccessKey="True"
Grid.Column="2"/>
<TextBlock x:Name="PART_InputGestureText"
Grid.Column="3"
@ -146,6 +145,10 @@
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_HeaderPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:icon /template/ ContentControl#PART_IconPresenter">
<Setter Property="IsVisible" Value="True" />
</Style>

7
src/Avalonia.Themes.Fluent/Controls/RadioButton.xaml

@ -71,13 +71,16 @@
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Foreground="{TemplateBinding Foreground}"
RecognizesAccessKey="True" />
Foreground="{TemplateBinding Foreground}" />
</Grid>
</Border>
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<!-- PointerOver State -->
<Style Selector="^:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource RadioButtonForegroundPointerOver}" />

5
src/Avalonia.Themes.Fluent/Controls/SplitButton.xaml

@ -51,12 +51,15 @@
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
RecognizesAccessKey="True"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="{DynamicResource SplitButtonBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource SplitButtonBorderBrushPointerOver}" />

5
src/Avalonia.Themes.Fluent/Controls/TabItem.xaml

@ -41,7 +41,6 @@
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
RecognizesAccessKey="True"
/>
<Border Name="PART_SelectedPipe"
Background="{DynamicResource TabItemHeaderSelectedPipeFill}"
@ -52,6 +51,10 @@
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<!-- Selected state -->
<!-- We don't use selector to PART_LayoutRoot, so developer can override selected item background with TabStripItem.Background -->
<Style Selector="^:selected">

5
src/Avalonia.Themes.Fluent/Controls/ToggleButton.xaml

@ -37,12 +37,15 @@
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
RecognizesAccessKey="True"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushPointerOver}" />

7
src/Avalonia.Themes.Fluent/Controls/ToggleSwitch.xaml

@ -45,8 +45,7 @@
VerticalAlignment="Top"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Margin="{DynamicResource ToggleSwitchTopHeaderMargin}"
RecognizesAccessKey="True" />
Margin="{DynamicResource ToggleSwitchTopHeaderMargin}" />
<Grid
Grid.Row="1"
@ -137,6 +136,10 @@
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter:empty">
<Setter Property="Margin" Value="0" />
</Style>

6
src/Avalonia.Themes.Simple/Controls/Button.xaml

@ -22,10 +22,14 @@
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
CornerRadius="{TemplateBinding CornerRadius}"
RecognizesAccessKey="True"
TextElement.Foreground="{TemplateBinding Foreground}" />
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderMidBrush}" />
</Style>

6
src/Avalonia.Themes.Simple/Controls/CheckBox.xaml

@ -49,11 +49,15 @@
ContentTemplate="{TemplateBinding ContentTemplate}"
IsVisible="{TemplateBinding Content,
Converter={x:Static ObjectConverters.IsNotNull}}"
RecognizesAccessKey="True"
TextElement.Foreground="{TemplateBinding Foreground}" />
</Grid>
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:pointerover /template/ Border#border">
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderHighBrush}" />
</Style>

7
src/Avalonia.Themes.Simple/Controls/DropDownButton.xaml

@ -31,8 +31,7 @@
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
RecognizesAccessKey="True" />
ContentTemplate="{TemplateBinding ContentTemplate}" />
<PathIcon Name="DropDownGlyph"
Grid.Column="1"
@ -50,6 +49,10 @@
</Setter.Value>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^ /template/ PathIcon#DropDownGlyph">
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}" />
<Setter Property="Data" Value="M1939 486L2029 576L1024 1581L19 576L109 486L1024 1401L1939 486Z" />

10
src/Avalonia.Themes.Simple/Controls/GroupBox.xaml

@ -54,7 +54,6 @@
Grid.Column="1">
<ContentPresenter Name="PART_HeaderPresenter"
Content="{TemplateBinding Header}"
RecognizesAccessKey="True"
ContentTemplate="{TemplateBinding HeaderTemplate}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
@ -67,7 +66,6 @@
Name="PART_ContentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
RecognizesAccessKey="True"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
UseLayoutRounding="{TemplateBinding UseLayoutRounding}"
@ -75,5 +73,13 @@
</Grid>
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_HeaderPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
</ControlTheme>
</ResourceDictionary>

10
src/Avalonia.Themes.Simple/Controls/HeaderedContentControl.xaml

@ -15,7 +15,6 @@
<Grid RowDefinitions="auto *">
<ContentPresenter Name="PART_HeaderPresenter"
Content="{TemplateBinding Header}"
RecognizesAccessKey="True"
ContentTemplate="{TemplateBinding HeaderTemplate}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
@ -27,7 +26,6 @@
<ContentPresenter Name="PART_ContentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
RecognizesAccessKey="True"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
FontSize="{TemplateBinding FontSize}"
@ -39,5 +37,13 @@
</Border>
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_HeaderPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
</ControlTheme>
</ResourceDictionary>

5
src/Avalonia.Themes.Simple/Controls/HyperlinkButton.xaml

@ -33,12 +33,15 @@
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
RecognizesAccessKey="True"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:disabled">
<Setter Property="Opacity" Value="{DynamicResource ThemeDisabledOpacity}" />
</Style>

7
src/Avalonia.Themes.Simple/Controls/Label.xaml

@ -15,9 +15,12 @@
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
CornerRadius="{TemplateBinding CornerRadius}"
RecognizesAccessKey="True" />
CornerRadius="{TemplateBinding CornerRadius}" />
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
</ControlTheme>
</ResourceDictionary>

7
src/Avalonia.Themes.Simple/Controls/RadioButton.xaml

@ -36,12 +36,15 @@
Margin="4,0,0,0"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
RecognizesAccessKey="True" />
ContentTemplate="{TemplateBinding ContentTemplate}" />
</Grid>
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:pointerover /template/ Ellipse#border">
<Setter Property="Stroke" Value="{DynamicResource ThemeBorderHighBrush}" />
</Style>

5
src/Avalonia.Themes.Simple/Controls/SplitButton.xaml

@ -38,12 +38,15 @@
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
RecognizesAccessKey="True"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ThemeControlMidColor}" />
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderMidColor}" />

6
src/Avalonia.Themes.Simple/Controls/TabItem.xaml

@ -20,10 +20,14 @@
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
CornerRadius="{TemplateBinding CornerRadius}"
RecognizesAccessKey="True"
/>
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Opacity" Value="{DynamicResource ThemeDisabledOpacity}" />
</Style>

6
src/Avalonia.Themes.Simple/Controls/ToggleButton.xaml

@ -22,10 +22,14 @@
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
CornerRadius="{TemplateBinding CornerRadius}"
RecognizesAccessKey="True"
TextElement.Foreground="{TemplateBinding Foreground}" />
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^:checked /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ThemeControlHighBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderMidBrush}" />

5
src/Avalonia.Themes.Simple/Controls/ToggleSwitch.xaml

@ -64,7 +64,6 @@
Margin="{DynamicResource ToggleSwitchTopHeaderMargin}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
RecognizesAccessKey="True"
VerticalAlignment="Top" />
<Grid Grid.Row="1"
@ -146,6 +145,10 @@
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="RecognizesAccessKey" Value="True" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter:empty">
<Setter Property="Margin" Value="0" />
</Style>

4
src/Avalonia.X11/X11Window.cs

@ -97,7 +97,7 @@ namespace Avalonia.X11
_popup = popupParent != null;
_overrideRedirect = _popup || overrideRedirect;
_x11 = platform.Info;
_mouse = new MouseDevice();
_mouse = Avalonia.Input.MouseDevice.Primary;
_pen = new PenDevice();
_touch = new TouchDevice();
_keyboard = platform.KeyboardDevice;
@ -1074,7 +1074,7 @@ namespace Avalonia.X11
_platform.XI2?.OnWindowDestroyed(_handle);
var handle = _handle;
_handle = IntPtr.Zero;
_mouse.Dispose();
_pen.Dispose();
_touch.Dispose();
if (!fromDestroyNotification)
XDestroyWindow(_x11.Display, handle);

31
src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs

@ -114,9 +114,9 @@ namespace Avalonia.Win32
//Window doesn't exist anymore
_hwnd = IntPtr.Zero;
//Remove root reference to this class, so unmanaged delegate can be collected
s_instances.Remove(this);
lock (s_instances)
s_instances.Remove(this);
_mouseDevice.Dispose();
_touchDevice.Dispose();
//Free other resources
Dispose();
@ -280,14 +280,6 @@ namespace Avalonia.Win32
DipFromLParam(lParam), GetMouseModifiers(wParam));
break;
}
// Mouse capture is lost
case WindowsMessage.WM_CANCELMODE:
if (!IsMouseInPointerEnabled)
{
_mouseDevice.Capture(null);
}
break;
case WindowsMessage.WM_MOUSEMOVE:
{
@ -394,13 +386,14 @@ namespace Avalonia.Win32
break;
}
// covers WM_CANCELMODE which sends WM_CAPTURECHANGED in DefWindowProc
case WindowsMessage.WM_CAPTURECHANGED:
{
if (IsMouseInPointerEnabled)
{
break;
}
if (_hwnd != lParam)
if (!IsOurWindow(lParam))
{
_trackingMouse = false;
e = new RawPointerEventArgs(
@ -907,6 +900,22 @@ namespace Avalonia.Win32
return DefWindowProc(hWnd, msg, wParam, lParam);
}
private bool IsOurWindow(IntPtr hwnd)
{
if (hwnd == IntPtr.Zero)
return false;
if (hwnd == _hwnd)
return true;
lock (s_instances)
for (int i = 0; i < s_instances.Count; i++)
if (s_instances[i]._hwnd == hwnd)
return true;
return false;
}
private void OnShowHideMessage(bool shown)
{
_shown = shown;

6
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -119,7 +119,7 @@ namespace Avalonia.Win32
public WindowImpl()
{
_touchDevice = new TouchDevice();
_mouseDevice = new WindowsMouseDevice();
_mouseDevice = Avalonia.Input.MouseDevice.GetOrCreatePrimary<WindowsMouseDevice>();
_penDevice = new PenDevice();
#if USE_MANAGED_DRAG
@ -177,7 +177,9 @@ namespace Avalonia.Win32
_nativeControlHost = new Win32NativeControlHost(this, !UseRedirectionBitmap);
_defaultTransparencyLevel = UseRedirectionBitmap ? WindowTransparencyLevel.None : WindowTransparencyLevel.Transparent;
_transparencyLevel = _defaultTransparencyLevel;
s_instances.Add(this);
lock (s_instances)
s_instances.Add(this);
}
internal IInputRoot Owner

2
src/tools/Avalonia.Generators/Common/EquatableList.cs

@ -9,6 +9,8 @@ namespace Avalonia.Generators.Common;
internal class EquatableList<T>(IList<T> collection)
: ReadOnlyCollection<T>(collection), IEquatable<EquatableList<T>>
{
public static readonly EquatableList<T> Empty = new([]);
public bool Equals(EquatableList<T>? other)
{
// If the other list is null or a different size, they're not equal

28
src/tools/Avalonia.Generators/GeneratorExtensions.cs

@ -1,14 +1,9 @@
using System;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Avalonia.Generators;
internal static class GeneratorExtensions
{
private const string UnhandledErrorDescriptorId = "AXN0002";
private const string InvalidTypeDescriptorId = "AXN0001";
public static string GetMsBuildProperty(
this AnalyzerConfigOptions options,
string name,
@ -17,27 +12,4 @@ internal static class GeneratorExtensions
options.TryGetValue($"build_property.{name}", out var value);
return value ?? defaultValue;
}
public static DiagnosticDescriptor NameGeneratorUnhandledError(Exception error) => new(
UnhandledErrorDescriptorId,
title: "Unhandled exception occurred while generating typed Name references. " +
"Please file an issue: https://github.com/avaloniaui/Avalonia",
messageFormat: error.Message,
description: error.ToString(),
category: "Usage",
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true);
public static DiagnosticDescriptor NameGeneratorInvalidType(string typeName) => new(
InvalidTypeDescriptorId,
title: $"Avalonia x:Name generator was unable to generate names for type '{typeName}'. " +
$"The type '{typeName}' does not exist in the assembly.",
messageFormat: $"Avalonia x:Name generator was unable to generate names for type '{typeName}'. " +
$"The type '{typeName}' does not exist in the assembly.",
category: "Usage",
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true);
public static void Report(this SourceProductionContext context, DiagnosticDescriptor diagnostics) =>
context.ReportDiagnostic(Diagnostic.Create(diagnostics, Location.None));
}

144
src/tools/Avalonia.Generators/NameGenerator/AvaloniaNameIncrementalGenerator.cs

@ -1,12 +1,14 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using Avalonia.Generators.Common;
using Avalonia.Generators.Common.Domain;
using Avalonia.Generators.Compiler;
using Microsoft.CodeAnalysis;
using XamlX.Transform;
using Microsoft.CodeAnalysis.Text;
using XamlX;
namespace Avalonia.Generators.NameGenerator;
@ -62,39 +64,52 @@ public class AvaloniaNameIncrementalGenerator : IIncrementalGenerator
.Select(static (file, cancellationToken) =>
{
cancellationToken.ThrowIfCancellationRequested();
var text = file.GetText(cancellationToken);
var diagnostics = new List<DiagnosticDescriptor>();
if (text is not null)
var xaml = file.GetText(cancellationToken)?.ToString();
if (xaml is null)
{
try
{
var xaml = text.ToString();
var viewResolver = new XamlXViewResolver(s_noopCompiler);
var view = viewResolver.ResolveView(xaml, cancellationToken);
if (view is null)
{
return null;
}
var nameResolver = new XamlXNameResolver();
var xmlNames = nameResolver.ResolveXmlNames(view.Xaml, cancellationToken);
return null;
}
return new XmlClassInfo(
new ResolvedXmlView(view, xmlNames),
new EquatableList<DiagnosticDescriptor>(diagnostics));
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
ResolvedXmlView? resolvedXmlView;
DiagnosticFactory? diagnosticFactory = null;
var location = new FileLinePositionSpan(file.Path, default);
try
{
var viewResolver = new XamlXViewResolver(s_noopCompiler);
var view = viewResolver.ResolveView(xaml, cancellationToken);
if (view is null)
{
diagnostics.Add(GeneratorExtensions.NameGeneratorUnhandledError(ex));
return new XmlClassInfo(null, new EquatableList<DiagnosticDescriptor>(diagnostics));
return null;
}
var xmlNames = EquatableList<ResolvedXmlName>.Empty;
var nameResolver = new XamlXNameResolver();
xmlNames = nameResolver.ResolveXmlNames(view.Xaml, cancellationToken);
resolvedXmlView = new ResolvedXmlView(view, xmlNames);
}
catch (OperationCanceledException)
{
throw;
}
catch (XmlException ex)
{
diagnosticFactory = new(NameGeneratorDiagnostics.ParseFailed, new(file.Path, GetLinePositionSpan(ex)), new([ex.Message]));
resolvedXmlView = ex is XamlParseException ? TryExtractTypeFromXml(xaml) : null;
}
catch (XamlTypeSystemException ex)
{
diagnosticFactory = new(NameGeneratorDiagnostics.ParseFailed, location, new([ex.Message]));
resolvedXmlView = TryExtractTypeFromXml(xaml);
}
catch (Exception ex)
{
diagnosticFactory = GetInternalErrorDiagnostic(location, ex);
resolvedXmlView = null;
}
return null;
return new XmlClassInfo(file.Path, resolvedXmlView, diagnosticFactory);
})
.Where(request => request is not null)
.WithTrackingName(TrackingNames.ParsedXamlClasses);
@ -119,15 +134,20 @@ public class AvaloniaNameIncrementalGenerator : IIncrementalGenerator
var hasDevToolsReference = compiler.TypeSystem.FindAssembly("Avalonia.Diagnostics") is not null;
var nameResolver = new XamlXNameResolver();
var diagnostics = new List<DiagnosticDescriptor>(classInfo!.Diagnostics);
var diagnostics = new List<DiagnosticFactory>(2);
if (classInfo?.Diagnostic != null)
{
diagnostics.Add(classInfo.Diagnostic);
}
ResolvedView? view = null;
if (classInfo.XmlView is { } xmlView)
if (classInfo?.XmlView is { } xmlView)
{
var type = compiler.TypeSystem.FindType(xmlView.FullName);
if (type is null)
{
diagnostics.Add(GeneratorExtensions.NameGeneratorInvalidType(xmlView.FullName));
diagnostics.Add(new(NameGeneratorDiagnostics.InvalidType, new(classInfo.FilePath, default), new([xmlView.FullName])));
}
else if (type.IsAvaloniaStyledElement())
{
@ -147,17 +167,22 @@ public class AvaloniaNameIncrementalGenerator : IIncrementalGenerator
resolvedNames.Add(nameResolver
.ResolveName(clrType, xmlName.Name, xmlName.FieldModifier));
}
catch (XmlException ex)
{
diagnostics.Add(new(NameGeneratorDiagnostics.NamedElementFailed,
new(classInfo.FilePath, GetLinePositionSpan(ex)), new([xmlName.Name, ex.Message])));
}
catch (Exception ex)
{
diagnostics.Add(GeneratorExtensions.NameGeneratorUnhandledError(ex));
diagnostics.Add(GetInternalErrorDiagnostic(new(classInfo.FilePath, default), ex));
}
}
view = new ResolvedView(xmlView, type.IsAvaloniaWindow(), new EquatableList<ResolvedName>(resolvedNames));
view = new ResolvedView(xmlView, type.IsAvaloniaWindow(), new(resolvedNames));
}
}
return new ResolvedClassInfo(view, hasDevToolsReference, new EquatableList<DiagnosticDescriptor>(diagnostics));
return new ResolvedClassInfo(view, hasDevToolsReference, new(diagnostics));
})
.WithTrackingName(TrackingNames.ResolvedNamesProvider);
@ -165,9 +190,9 @@ public class AvaloniaNameIncrementalGenerator : IIncrementalGenerator
{
var (info, options) = pair;
foreach (var diagnostic in info!.Diagnostics)
foreach (var diagnostic in info.Diagnostics)
{
context.Report(diagnostic);
context.ReportDiagnostic(diagnostic.Create());
}
if (info.View is { } view && options.AvaloniaNameGeneratorFilterByNamespace.Matches(view.Namespace))
@ -200,12 +225,53 @@ public class AvaloniaNameIncrementalGenerator : IIncrementalGenerator
});
}
private static DiagnosticFactory GetInternalErrorDiagnostic(FileLinePositionSpan location, Exception ex) =>
new(NameGeneratorDiagnostics.InternalError, location, new([ex.ToString().Replace('\n', '*').Replace('\r', '*')]));
/// <summary>
/// Fallback in case XAML parsing fails. Extracts just the class name and namespace of the root element.
/// </summary>
private static ResolvedXmlView? TryExtractTypeFromXml(string xaml)
{
try
{
var document = XDocument.Parse(xaml);
var classValue = document.Root.Attribute(XName.Get("Class", XamlNamespaces.Xaml2006))?.Value;
if (classValue?.LastIndexOf('.') is { } lastDotIndex && lastDotIndex != -1)
{
return new(classValue.Substring(lastDotIndex + 1), classValue.Substring(0, lastDotIndex), EquatableList<ResolvedXmlName>.Empty);
}
}
catch
{
// ignore
}
return null;
}
private static LinePositionSpan GetLinePositionSpan(XmlException ex)
{
var position = new LinePosition(Math.Max(0, ex.LineNumber - 1), Math.Max(0, ex.LinePosition - 1));
return new(position, position);
}
internal record XmlClassInfo(
string FilePath,
ResolvedXmlView? XmlView,
EquatableList<DiagnosticDescriptor> Diagnostics);
DiagnosticFactory? Diagnostic);
internal record ResolvedClassInfo(
ResolvedView? View,
bool CanAttachDevTools,
EquatableList<DiagnosticDescriptor> Diagnostics);
EquatableList<DiagnosticFactory> Diagnostics);
/// <summary>
/// Avoid holding references to <see cref="Diagnostic"/> because it can hold references to <see cref="ISymbol"/>, <see cref="SyntaxTree"/>, etc.
/// </summary>
internal record DiagnosticFactory(DiagnosticDescriptor Descriptor, FileLinePositionSpan LinePosition, EquatableList<string> FormatArguments)
{
public Diagnostic Create() => Diagnostic.Create(Descriptor,
Location.Create(LinePosition.Path, default, new(LinePosition.StartLinePosition, LinePosition.EndLinePosition)),
messageArgs: [.. FormatArguments]);
}
}

39
src/tools/Avalonia.Generators/NameGenerator/NameGeneratorDiagnostics.cs

@ -0,0 +1,39 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.CodeAnalysis;
namespace Avalonia.Generators.NameGenerator;
internal static class NameGeneratorDiagnostics
{
private const string Category = "Avalonia.NameGenerator";
private const string BugReportLink = "https://github.com/AvaloniaUI/Avalonia/issues/new/choose";
// Name generation errors should typicially be warnings, because that allows the compile to proceed and
// reach the point at which code errors are reported. These can give the user actionable information
// about what they need to fix, which the name generator doesn't have.
public static readonly DiagnosticDescriptor InvalidType = new(
"AXN0001", $"Invalid type",
"Avalonia could not generate code-behind properties or the InitializeContext method because the x:Class type '{0}' was not found in the project",
Category,
defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true);
[SuppressMessage("MicrosoftCodeAnalysisDesign", "RS1032:Define diagnostic message correctly", Justification = "Printing internal exception")]
public static readonly DiagnosticDescriptor InternalError = new(
"AXN0002", "Internal error",
messageFormat: $"Avalonia encountered an internal error while generating code-behind properties and/or the InitializeContext method. " +
$"Please file a bug report at {BugReportLink}. The exception is {{0}}",
Category,
DiagnosticSeverity.Error, true,
helpLinkUri: BugReportLink);
public static readonly DiagnosticDescriptor ParseFailed = new(
"AXN0003", $"XAML error",
"Avalonia could not generate code-behind properties for named elements due to a XAML error: {0}",
Category, DiagnosticSeverity.Warning, isEnabledByDefault: true);
public static readonly DiagnosticDescriptor NamedElementFailed = new(
"AXN0004", $"XAML error",
"Avalonia could not generate code-behind property for '{0}' due to a XAML error: {1}",
Category, DiagnosticSeverity.Warning, isEnabledByDefault: true);
}

11
tests/Avalonia.Base.UnitTests/Utilities/UriExtensionsTests.cs

@ -40,4 +40,15 @@ public class UriExtensionsTests
Assert.Equal(path, uri.LocalPath);
}
[Theory]
[InlineData(@"\\?\D:\abcdefgh\abcdefgh\abcdefabcdefgh\abcdefghabcdefghabcdefgha\bcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh\abcdefghabcdefghabcdefgha\bcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh",
@"D:\abcdefgh\abcdefgh\abcdefabcdefgh\abcdefghabcdefghabcdefgha\bcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh\abcdefghabcdefghabcdefgha\bcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh")]
public void Should_Convert_Long_File_Path_To_Uri_And_Back(string prepath,string path)
{
var uri = StorageProviderHelpers.UriFromFilePath(prepath, false);
Assert.Equal(path, uri.LocalPath);
}
}

Loading…
Cancel
Save