Browse Source

Merge branch 'master' into render-inside-win-ui-comp-tree

tmp-winuicomp_with_manual_fbo
danwalmsley 6 years ago
committed by GitHub
parent
commit
7fe06a67b3
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      Avalonia.sln
  2. 2
      NuGet.Config
  3. 12
      build/ApiDiff.props
  4. 2
      build/ReactiveUI.props
  5. 2
      build/SharedVersion.props
  6. 2
      build/SkiaSharp.props
  7. 24
      native/Avalonia.Native/src/OSX/window.mm
  8. 4
      nukebuild/Build.cs
  9. 2
      readme.md
  10. 8
      samples/ControlCatalog/App.xaml
  11. 4
      samples/ControlCatalog/App.xaml.cs
  12. 4
      samples/ControlCatalog/MainView.xaml
  13. 14
      samples/ControlCatalog/MainWindow.xaml.cs
  14. 4
      samples/ControlCatalog/Pages/ButtonPage.xaml
  15. 5
      samples/ControlCatalog/Pages/ContextMenuPage.xaml
  16. 2
      samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml
  17. 3
      samples/ControlCatalog/Pages/ListBoxPage.xaml
  18. 68
      samples/ControlCatalog/Pages/ListBoxPage.xaml.cs
  19. 37
      samples/ControlCatalog/Pages/MenuPage.xaml
  20. 13
      samples/ControlCatalog/Pages/ScreenPage.cs
  21. 4
      samples/ControlCatalog/Pages/TextBlockPage.xaml
  22. 3
      samples/ControlCatalog/Pages/TextBoxPage.xaml
  23. 65
      samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs
  24. 36
      samples/ControlCatalog/ViewModels/MenuPageViewModel.cs
  25. 3
      samples/RenderDemo/MainWindow.xaml
  26. 92
      samples/RenderDemo/Pages/WriteableBitmapPage.cs
  27. 3
      src/Avalonia.Animation/Avalonia.Animation.csproj
  28. 3
      src/Avalonia.Base/Avalonia.Base.csproj
  29. 4
      src/Avalonia.Base/AvaloniaObject.cs
  30. 6
      src/Avalonia.Base/AvaloniaProperty.cs
  31. 25
      src/Avalonia.Base/DirectProperty.cs
  32. 39
      src/Avalonia.Base/DirectPropertyBase.cs
  33. 61
      src/Avalonia.Base/Threading/AvaloniaScheduler.cs
  34. 2
      src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
  35. 1
      src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj
  36. 10
      src/Avalonia.Controls.DataGrid/Themes/Default.xaml
  37. 7
      src/Avalonia.Controls/AutoCompleteBox.cs
  38. 3
      src/Avalonia.Controls/Avalonia.Controls.csproj
  39. 7
      src/Avalonia.Controls/Calendar/CalendarDatePicker.cs
  40. 22
      src/Avalonia.Controls/ComboBox.cs
  41. 6
      src/Avalonia.Controls/ContextMenu.cs
  42. 9
      src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
  43. 4
      src/Avalonia.Controls/IMenuElement.cs
  44. 6
      src/Avalonia.Controls/IMenuItem.cs
  45. 2
      src/Avalonia.Controls/ItemsControl.cs
  46. 3
      src/Avalonia.Controls/ListBox.cs
  47. 5
      src/Avalonia.Controls/Menu.cs
  48. 8
      src/Avalonia.Controls/MenuBase.cs
  49. 70
      src/Avalonia.Controls/MenuItem.cs
  50. 12
      src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
  51. 15
      src/Avalonia.Controls/Presenters/TextPresenter.cs
  52. 61
      src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs
  53. 143
      src/Avalonia.Controls/Primitives/Popup.cs
  54. 33
      src/Avalonia.Controls/Primitives/PopupClosedEventArgs.cs
  55. 26
      src/Avalonia.Controls/Primitives/VisualLayerManager.cs
  56. 2
      src/Avalonia.Controls/ProgressBar.cs
  57. 2
      src/Avalonia.Controls/Repeater/ItemsRepeaterElementIndexChangedEventArgs.cs
  58. 15
      src/Avalonia.Controls/Repeater/ItemsSourceView.cs
  59. 17
      src/Avalonia.Controls/Repeater/ViewportManager.cs
  60. 63
      src/Avalonia.Controls/TextBox.cs
  61. 1
      src/Avalonia.Controls/ToolTip.cs
  62. 15
      src/Avalonia.Controls/ToolTipService.cs
  63. 37
      src/Avalonia.Controls/Utils/SelectedItemsSync.cs
  64. 2
      src/Avalonia.Controls/Window.cs
  65. 11
      src/Avalonia.Controls/WindowBase.cs
  66. 2
      src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
  67. 3
      src/Avalonia.DesignerSupport/DesignWindowLoader.cs
  68. 2
      src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/webpack.config.js
  69. 2
      src/Avalonia.Desktop/Avalonia.Desktop.csproj
  70. 1
      src/Avalonia.DesktopRuntime/Avalonia.DesktopRuntime.csproj
  71. 2
      src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj
  72. 2
      src/Avalonia.Dialogs/Avalonia.Dialogs.csproj
  73. 4
      src/Avalonia.Dialogs/ManagedFileChooser.xaml
  74. 5
      src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
  75. 3
      src/Avalonia.Headless/Avalonia.Headless.csproj
  76. 10
      src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
  77. 1
      src/Avalonia.Input/Avalonia.Input.csproj
  78. 29
      src/Avalonia.Input/InputExtensions.cs
  79. 1
      src/Avalonia.Interactivity/Avalonia.Interactivity.csproj
  80. 1
      src/Avalonia.Layout/Avalonia.Layout.csproj
  81. 3
      src/Avalonia.Native/Avalonia.Native.csproj
  82. 44
      src/Avalonia.Native/AvaloniaNativeMenuExporter.cs
  83. 628
      src/Avalonia.Native/Generated/Enumerations.cs
  84. 5
      src/Avalonia.Native/Generated/Functions.cs
  85. 3092
      src/Avalonia.Native/Generated/Interfaces.cs
  86. 202
      src/Avalonia.Native/Generated/LocalInterop.cs
  87. 246
      src/Avalonia.Native/Generated/Structures.cs
  88. 10
      src/Avalonia.Native/WindowImplBase.cs
  89. 3
      src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
  90. 4
      src/Avalonia.ReactiveUI/AutoDataTemplateBindingHook.cs
  91. 1
      src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
  92. 22
      src/Avalonia.ReactiveUI/RoutedViewHost.cs
  93. 2
      src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj
  94. 1
      src/Avalonia.Styling/Avalonia.Styling.csproj
  95. 2
      src/Avalonia.Styling/Styling/PropertySetterBindingInstance.cs
  96. 5
      src/Avalonia.Themes.Default/Accents/BaseDark.xaml
  97. 5
      src/Avalonia.Themes.Default/Accents/BaseLight.xaml
  98. 2
      src/Avalonia.Themes.Default/AutoCompleteBox.xaml
  99. 1
      src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
  100. 14
      src/Avalonia.Themes.Default/ComboBox.xaml

1
Avalonia.sln

@ -150,6 +150,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\System.Memory.props = build\System.Memory.props
build\UnitTests.NetFX.props = build\UnitTests.NetFX.props
build\XUnit.props = build\XUnit.props
build\ApiDiff.props = build\ApiDiff.props
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{4D6FAF79-58B4-482F-9122-0668C346364C}"

2
NuGet.Config

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
</packageSources>
</configuration>

12
build/ApiDiff.props

@ -0,0 +1,12 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ApiContractPackageVersion>0.10.0-preview3</ApiContractPackageVersion>
<NugetPackageName Condition="'$(PackageId)' != ''">$(PackageId)</NugetPackageName>
<NugetPackageName Condition="'$(PackageId)' == ''">Avalonia</NugetPackageName>
</PropertyGroup>
<ItemGroup>
<PackageDownload Include="$(NugetPackageName)" Version="[$(ApiContractPackageVersion)]" />
<PackageReference Include="Microsoft.DotNet.ApiCompat" Version="5.0.0-beta.20372.2" PrivateAssets="All" />
<ResolvedMatchingContract Include="$(NuGetPackageRoot)\$(NugetPackageName.ToLower())\$(ApiContractPackageVersion)\lib\$(TargetFramework)\$(AssemblyName).dll" />
</ItemGroup>
</Project>

2
build/ReactiveUI.props

@ -1,5 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="ReactiveUI" Version="10.3.6" />
<PackageReference Include="ReactiveUI" Version="11.5.17" />
</ItemGroup>
</Project>

2
build/SharedVersion.props

@ -2,7 +2,7 @@
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Product>Avalonia</Product>
<Version>0.9.999</Version>
<Version>0.10.999</Version>
<Copyright>Copyright 2020 &#169; The AvaloniaUI Project</Copyright>
<PackageProjectUrl>https://avaloniaui.net</PackageProjectUrl>
<RepositoryUrl>https://github.com/AvaloniaUI/Avalonia/</RepositoryUrl>

2
build/SkiaSharp.props

@ -1,6 +1,6 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="SkiaSharp" Version="2.80.0" />
<PackageReference Include="SkiaSharp" Version="2.80.1" />
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="2.80.0" />
</ItemGroup>
</Project>

24
native/Avalonia.Native/src/OSX/window.mm

@ -27,6 +27,7 @@ public:
AvnPoint lastPositionSet;
NSString* _lastTitle;
IAvnMenu* _mainMenu;
bool _shown;
WindowBaseImpl(IAvnWindowBaseEvents* events, IAvnGlContext* gl)
@ -230,6 +231,29 @@ public:
{
@autoreleasepool
{
auto maxSize = [Window maxSize];
auto minSize = [Window minSize];
if (x < minSize.width)
{
x = minSize.width;
}
if (y < minSize.height)
{
y = minSize.height;
}
if (x > maxSize.width)
{
x = maxSize.width;
}
if (y > maxSize.height)
{
y = maxSize.height;
}
[Window setContentSize:NSSize{x, y}];
return S_OK;

4
nukebuild/Build.cs

@ -128,7 +128,9 @@ partial class Build : NukeBuild
{
var webappDir = RootDirectory / "src" / "Avalonia.DesignerSupport" / "Remote" / "HtmlTransport" / "webapp";
NpmTasks.NpmInstall(c => c.SetWorkingDirectory(webappDir));
NpmTasks.NpmInstall(c => c
.SetWorkingDirectory(webappDir)
.SetArgumentConfigurator(a => a.Add("--silent")));
NpmTasks.NpmRun(c => c
.SetWorkingDirectory(webappDir)
.SetCommand("dist"));

2
readme.md

@ -1,4 +1,4 @@
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) [![Build Status](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_apis/build/status/AvaloniaUI.Avalonia)](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) ![License](https://img.shields.io/github/license/avaloniaui/avalonia.svg)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) [![Discord](https://img.shields.io/badge/discord-join%20chat-46BC99)]( https://aka.ms/dotnet-discord) [![Build Status](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_apis/build/status/AvaloniaUI.Avalonia)](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) ![License](https://img.shields.io/github/license/avaloniaui/avalonia.svg)
<br />
[![NuGet](https://img.shields.io/nuget/v/Avalonia.svg)](https://www.nuget.org/packages/Avalonia) [![downloads](https://img.shields.io/nuget/dt/avalonia)](https://www.nuget.org/packages/Avalonia) [![MyGet](https://img.shields.io/myget/avalonia-ci/vpre/Avalonia.svg?label=myget)](https://www.myget.org/gallery/avalonia-ci) ![Size](https://img.shields.io/github/repo-size/avaloniaui/avalonia.svg)

8
samples/ControlCatalog/App.xaml

@ -4,14 +4,14 @@
<Application.Styles>
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Default.xaml"/>
<Style Selector="TextBlock.h1">
<Setter Property="FontSize" Value="{DynamicResource FontSizeLarge}"/>
<Setter Property="FontWeight" Value="Medium"/>
<Setter Property="FontSize" Value="16" />
<Setter Property="FontWeight" Value="Medium" />
</Style>
<Style Selector="TextBlock.h2">
<Setter Property="FontSize" Value="{DynamicResource FontSizeNormal}"/>
<Setter Property="FontSize" Value="14" />
</Style>
<Style Selector="TextBlock.h3">
<Setter Property="FontSize" Value="{DynamicResource FontSizeSmall}"/>
<Setter Property="FontSize" Value="12" />
</Style>
<StyleInclude Source="/SideBar.xaml"/>
</Application.Styles>

4
samples/ControlCatalog/App.xaml.cs

@ -67,9 +67,9 @@ namespace ControlCatalog
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
Styles.Insert(0, FluentDark);
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()

4
samples/ControlCatalog/MainView.xaml

@ -1,9 +1,7 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:pages="clr-namespace:ControlCatalog.Pages"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ControlCatalog.MainView"
Foreground="{DynamicResource ThemeForegroundBrush}"
FontSize="{DynamicResource FontSizeNormal}">
x:Class="ControlCatalog.MainView">
<Grid>
<Grid.Styles>
<Style Selector="TextBlock.h2">

14
samples/ControlCatalog/MainWindow.xaml.cs

@ -63,8 +63,18 @@ namespace ControlCatalog
// TODO: iOS does not support dynamically loading assemblies
// so we must refer to this resource DLL statically. For
// now I am doing that here. But we need a better solution!!
var theme = new Avalonia.Themes.Default.DefaultTheme();
theme.TryGetResource("Button", out _);
// Note, theme swiching probably will not work in runtime for iOS.
if (Application.Current.Styles.Contains(App.FluentDark)
|| Application.Current.Styles.Contains(App.FluentLight))
{
var theme = new Avalonia.Themes.Fluent.FluentTheme();
theme.TryGetResource("Button", out _);
}
else
{
var theme = new Avalonia.Themes.Default.DefaultTheme();
theme.TryGetResource("Button", out _);
}
AvaloniaXamlLoader.Load(this);
}
}

4
samples/ControlCatalog/Pages/ButtonPage.xaml

@ -20,6 +20,10 @@
<Style.Resources>
<SolidColorBrush x:Key="ThemeBorderMidBrush">Red</SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlHighBrush">DarkRed</SolidColorBrush>
<SolidColorBrush x:Key="ButtonBorderBrush">Red</SolidColorBrush>
<SolidColorBrush x:Key="ButtonBackground">DarkRed</SolidColorBrush>
<SolidColorBrush x:Key="ButtonBackgroundPointerOver">Red</SolidColorBrush>
<SolidColorBrush x:Key="ButtonBackgroundPressed">OrangeRed</SolidColorBrush>
</Style.Resources>
</Style>
</Button.Styles>

5
samples/ControlCatalog/Pages/ContextMenuPage.xaml

@ -14,13 +14,14 @@
Padding="48,48,48,48">
<Border.ContextMenu>
<ContextMenu>
<MenuItem Header="Standard _Menu Item"/>
<MenuItem Header="Standard _Menu Item" InputGesture="Ctrl+A" />
<MenuItem Header="_Disabled Menu Item" IsEnabled="False" InputGesture="Ctrl+D" />
<Separator/>
<MenuItem Header="Menu with _Submenu">
<MenuItem Header="Submenu _1"/>
<MenuItem Header="Submenu _2"/>
</MenuItem>
<MenuItem Header="Menu Item with _Icon">
<MenuItem Header="Menu Item with _Icon" InputGesture="Ctrl+Shift+B">
<MenuItem.Icon>
<Image Source="/Assets/github_icon.png"/>
</MenuItem.Icon>

2
samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml

@ -43,7 +43,7 @@
<Button x:Name="scrollToLast">Scroll to Last</Button>
<Button x:Name="scrollToRandom">Scroll to Random</Button>
</StackPanel>
<Border BorderThickness="1" BorderBrush="{DynamicResource ThemeBorderMidBrush}" Margin="0 0 0 16">
<Border BorderThickness="1" BorderBrush="{DynamicResource SystemControlHighlightBaseMediumLowBrush}" Margin="0 0 0 16">
<ScrollViewer Name="scroller"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">

3
samples/ControlCatalog/Pages/ListBoxPage.xaml

@ -11,8 +11,7 @@
Spacing="16">
<StackPanel Orientation="Vertical" Spacing="8">
<ListBox Items="{Binding Items}"
SelectedItem="{Binding SelectedItem}"
SelectedItems="{Binding SelectedItems}"
Selection="{Binding Selection}"
AutoScrollToSelectedItem="True"
SelectionMode="{Binding SelectionMode}"
Width="250"

68
samples/ControlCatalog/Pages/ListBoxPage.xaml.cs

@ -1,10 +1,6 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using ReactiveUI;
using ControlCatalog.ViewModels;
namespace ControlCatalog.Pages
{
@ -13,72 +9,12 @@ namespace ControlCatalog.Pages
public ListBoxPage()
{
InitializeComponent();
DataContext = new PageViewModel();
DataContext = new ListBoxPageViewModel();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private class PageViewModel : ReactiveObject
{
private int _counter;
private SelectionMode _selectionMode;
public PageViewModel()
{
Items = new ObservableCollection<string>(Enumerable.Range(1, 10000).Select(i => GenerateItem()));
SelectedItems = new ObservableCollection<string>();
AddItemCommand = ReactiveCommand.Create(() => Items.Add(GenerateItem()));
RemoveItemCommand = ReactiveCommand.Create(() =>
{
while (SelectedItems.Count > 0)
{
Items.Remove(SelectedItems[0]);
}
});
SelectRandomItemCommand = ReactiveCommand.Create(() =>
{
var random = new Random();
SelectedItem = Items[random.Next(Items.Count - 1)];
});
}
public ObservableCollection<string> Items { get; }
private string _selectedItem;
public string SelectedItem
{
get { return _selectedItem; }
set { this.RaiseAndSetIfChanged(ref _selectedItem, value); }
}
public ObservableCollection<string> SelectedItems { get; }
public ReactiveCommand<Unit, Unit> AddItemCommand { get; }
public ReactiveCommand<Unit, Unit> RemoveItemCommand { get; }
public ReactiveCommand<Unit, Unit> SelectRandomItemCommand { get; }
public SelectionMode SelectionMode
{
get => _selectionMode;
set
{
SelectedItems.Clear();
this.RaiseAndSetIfChanged(ref _selectionMode, value);
}
}
private string GenerateItem() => $"Item {_counter++.ToString()}";
}
}
}

37
samples/ControlCatalog/Pages/MenuPage.xaml

@ -16,11 +16,17 @@
<TextBlock Classes="h3" Margin="4 8">Defined in XAML</TextBlock>
<Menu>
<MenuItem Header="_First">
<MenuItem Header="Standard _Menu Item" InputGesture="Ctrl+A"/>
<MenuItem Header="Standard _Menu Item" InputGesture="Ctrl+A" />
<MenuItem Header="_Disabled Menu Item" IsEnabled="False" InputGesture="Ctrl+D" />
<Separator/>
<MenuItem Header="Menu with _Submenu">
<MenuItem Header="Submenu _1"/>
<MenuItem Header="Submenu _2"/>
<MenuItem Header="Submenu _2 with Submenu">
<MenuItem Header="Submenu Level 2" />
</MenuItem>
<MenuItem Header="Submenu _3 with Submenu Disabled" IsEnabled="False">
<MenuItem Header="Submenu Level 2" />
</MenuItem>
</MenuItem>
<MenuItem Header="Menu Item with _Icon" InputGesture="Ctrl+Shift+B">
<MenuItem.Icon>
@ -52,6 +58,33 @@
</Menu.Styles>
</Menu>
</StackPanel>
<StackPanel>
<TextBlock Classes="h3" Margin="4 8">Mixed</TextBlock>
<Menu>
<MenuItem Header="_File">
<MenuItem Header="_New" CommandParameter="{Binding}" InputGesture="Ctrl+N"/>
<Separator/>
<MenuItem Header="_Open..." InputGesture="Ctrl+O"/>
<Separator/>
<MenuItem Header="Execu_te Script..." />
<Separator/>
<MenuItem Header="_Recent" Items="{Binding RecentItems}">
<MenuItem.Styles>
<Style Selector="MenuItem">
<Setter Property="Header" Value="{Binding Header}"/>
</Style>
</MenuItem.Styles>
</MenuItem>
<Separator/>
<MenuItem Header="E_xit" InputGesture="Alt+F4"/>
</MenuItem>
<MenuItem Header="_Help">
<MenuItem Header="_About"/>
</MenuItem>
</Menu>
</StackPanel>
</StackPanel>
</StackPanel>
</UserControl>

13
samples/ControlCatalog/Pages/ScreenPage.cs

@ -29,7 +29,8 @@ namespace ControlCatalog.Pages
var screens = w.Screens.All;
var scaling = ((IRenderRoot)w).RenderScaling;
Pen p = new Pen(Brushes.Black);
var drawBrush = Brushes.Green;
Pen p = new Pen(drawBrush);
if (screens != null)
foreach (Screen screen in screens)
{
@ -53,19 +54,19 @@ namespace ControlCatalog.Pages
};
text.Text = $"Bounds: {screen.Bounds.Width}:{screen.Bounds.Height}";
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height), text);
context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height), text);
text.Text = $"WorkArea: {screen.WorkingArea.Width}:{screen.WorkingArea.Height}";
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 20), text);
context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 20), text);
text.Text = $"Scaling: {screen.PixelDensity * 100}%";
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 40), text);
context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 40), text);
text.Text = $"Primary: {screen.Primary}";
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 60), text);
context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 60), text);
text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}";
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 80), text);
context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 80), text);
}
context.DrawRectangle(p, new Rect(w.Position.X / 10f + Math.Abs(_leftMost), w.Position.Y / 10, w.Bounds.Width / 10, w.Bounds.Height / 10));

4
samples/ControlCatalog/Pages/TextBlockPage.xaml

@ -12,7 +12,7 @@
<StackPanel.Styles>
<Style Selector="Border">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderMidBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource SystemControlHighlightBaseMediumLowBrush}"/>
<Setter Property="Padding" Value="2"/>
</Style>
</StackPanel.Styles>
@ -49,7 +49,7 @@
<StackPanel.Styles>
<Style Selector="Border">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderMidBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource SystemControlHighlightBaseMediumLowBrush}"/>
<Setter Property="Padding" Value="2"/>
</Style>
</StackPanel.Styles>

3
samples/ControlCatalog/Pages/TextBoxPage.xaml

@ -20,6 +20,7 @@
<TextBox Width="200"
Watermark="Password Box"
Classes="revealPasswordButton"
UseFloatingWatermark="True"
PasswordChar="*"
Text="Password" />
@ -37,6 +38,8 @@
Text="Multiline TextBox with TextWrapping.&#xD;&#xD;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est." />
<TextBox AcceptsReturn="True" Width="200" Height="125"
Text="Multiline TextBox with no TextWrapping.&#xD;&#xD;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est." />
<TextBox Classes="clearButton" Text="Clear Content" Width="200" FontWeight="Normal" FontStyle="Normal" Watermark="Watermark" FontFamily="avares://ControlCatalog/Assets/Fonts#Source Sans Pro"/>
</StackPanel>
<StackPanel Orientation="Vertical" Spacing="8">
<TextBlock Classes="h2">resm fonts</TextBlock>

65
samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs

@ -0,0 +1,65 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using Avalonia.Controls;
using ReactiveUI;
namespace ControlCatalog.ViewModels
{
public class ListBoxPageViewModel : ReactiveObject
{
private int _counter;
private SelectionMode _selectionMode;
public ListBoxPageViewModel()
{
Items = new ObservableCollection<string>(Enumerable.Range(1, 10000).Select(i => GenerateItem()));
Selection = new SelectionModel();
Selection.Select(1);
AddItemCommand = ReactiveCommand.Create(() => Items.Add(GenerateItem()));
RemoveItemCommand = ReactiveCommand.Create(() =>
{
while (Selection.SelectedItems.Count > 0)
{
Items.Remove((string)Selection.SelectedItems.First());
}
});
SelectRandomItemCommand = ReactiveCommand.Create(() =>
{
var random = new Random();
using (Selection.Update())
{
Selection.ClearSelection();
Selection.Select(random.Next(Items.Count - 1));
}
});
}
public ObservableCollection<string> Items { get; }
public SelectionModel Selection { get; }
public ReactiveCommand<Unit, Unit> AddItemCommand { get; }
public ReactiveCommand<Unit, Unit> RemoveItemCommand { get; }
public ReactiveCommand<Unit, Unit> SelectRandomItemCommand { get; }
public SelectionMode SelectionMode
{
get => _selectionMode;
set
{
Selection.ClearSelection();
this.RaiseAndSetIfChanged(ref _selectionMode, value);
}
}
private string GenerateItem() => $"Item {_counter++.ToString()}";
}
}

36
samples/ControlCatalog/ViewModels/MenuPageViewModel.cs

@ -17,6 +17,23 @@ namespace ControlCatalog.ViewModels
SaveCommand = ReactiveCommand.Create(Save, Observable.Return(false));
OpenRecentCommand = ReactiveCommand.Create<string>(OpenRecent);
var recentItems = new[]
{
new MenuItemViewModel
{
Header = "File1.txt",
Command = OpenRecentCommand,
CommandParameter = @"c:\foo\File1.txt"
},
new MenuItemViewModel
{
Header = "File2.txt",
Command = OpenRecentCommand,
CommandParameter = @"c:\foo\File2.txt"
},
};
RecentItems = recentItems;
MenuItems = new[]
{
new MenuItemViewModel
@ -24,27 +41,13 @@ namespace ControlCatalog.ViewModels
Header = "_File",
Items = new[]
{
new MenuItemViewModel { Header = "_Open...", Command = OpenCommand },
new MenuItemViewModel { Header = "O_pen...", Command = OpenCommand },
new MenuItemViewModel { Header = "Save", Command = SaveCommand },
new MenuItemViewModel { Header = "-" },
new MenuItemViewModel
{
Header = "Recent",
Items = new[]
{
new MenuItemViewModel
{
Header = "File1.txt",
Command = OpenRecentCommand,
CommandParameter = @"c:\foo\File1.txt"
},
new MenuItemViewModel
{
Header = "File2.txt",
Command = OpenRecentCommand,
CommandParameter = @"c:\foo\File2.txt"
},
}
Items = recentItems
},
}
},
@ -61,6 +64,7 @@ namespace ControlCatalog.ViewModels
}
public IReadOnlyList<MenuItemViewModel> MenuItems { get; set; }
public IReadOnlyList<MenuItemViewModel> RecentItems { get; set; }
public ReactiveCommand<Unit, Unit> OpenCommand { get; }
public ReactiveCommand<Unit, Unit> SaveCommand { get; }
public ReactiveCommand<string, Unit> OpenRecentCommand { get; }

3
samples/RenderDemo/MainWindow.xaml

@ -44,6 +44,9 @@
<TabItem Header="RenderTargetBitmap">
<pages:RenderTargetBitmapPage/>
</TabItem>
<TabItem Header="WriteableBitmap">
<pages:WriteableBitmapPage/>
</TabItem>
<TabItem Header="GlyphRun">
<pages:GlyphRunPage/>
</TabItem>

92
samples/RenderDemo/Pages/WriteableBitmapPage.cs

@ -0,0 +1,92 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using Avalonia;
using Avalonia.Controls;
using Avalonia.LogicalTree;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Media.Immutable;
using Avalonia.Platform;
using Avalonia.Threading;
namespace RenderDemo.Pages
{
public class WriteableBitmapPage : Control
{
private WriteableBitmap _unpremulBitmap;
private WriteableBitmap _premulBitmap;
private readonly Stopwatch _st = Stopwatch.StartNew();
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
_unpremulBitmap = new WriteableBitmap(new PixelSize(256, 256), new Vector(96, 96), PixelFormat.Bgra8888, AlphaFormat.Unpremul);
_premulBitmap = new WriteableBitmap(new PixelSize(256, 256), new Vector(96, 96), PixelFormat.Bgra8888, AlphaFormat.Premul);
base.OnAttachedToLogicalTree(e);
}
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnDetachedFromLogicalTree(e);
_unpremulBitmap?.Dispose();
_unpremulBitmap = null;
_premulBitmap?.Dispose();
_unpremulBitmap = null;
}
public override void Render(DrawingContext context)
{
void FillPixels(WriteableBitmap bitmap, byte fillAlpha, bool premul)
{
using (var fb = bitmap.Lock())
{
var data = new int[fb.Size.Width * fb.Size.Height];
for (int y = 0; y < fb.Size.Height; y++)
{
for (int x = 0; x < fb.Size.Width; x++)
{
var color = new Color(fillAlpha, 0, 255, 0);
if (premul)
{
byte r = (byte) (color.R * color.A / 255);
byte g = (byte) (color.G * color.A / 255);
byte b = (byte) (color.B * color.A / 255);
color = new Color(fillAlpha, r, g, b);
}
data[y * fb.Size.Width + x] = (int) color.ToUint32();
}
}
Marshal.Copy(data, 0, fb.Address, fb.Size.Width * fb.Size.Height);
}
}
base.Render(context);
byte alpha = (byte)((_st.ElapsedMilliseconds / 10) % 256);
FillPixels(_unpremulBitmap, alpha, false);
FillPixels(_premulBitmap, alpha, true);
context.FillRectangle(Brushes.Red, new Rect(0, 0, 256 * 3, 256));
context.DrawImage(_unpremulBitmap,
new Rect(0, 0, 256, 256),
new Rect(0, 0, 256, 256));
context.DrawImage(_premulBitmap,
new Rect(0, 0, 256, 256),
new Rect(256, 0, 256, 256));
context.FillRectangle(new ImmutableSolidColorBrush(Colors.Lime, alpha / 255d), new Rect(512, 0, 256, 256));
Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Background);
}
}
}

3
src/Avalonia.Animation/Avalonia.Animation.csproj

@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
</ItemGroup>
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project>

3
src/Avalonia.Base/Avalonia.Base.csproj

@ -3,7 +3,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Avalonia.Base</AssemblyName>
<RootNamespace>Avalonia</RootNamespace>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Avalonia.Build.Tasks\Avalonia.Build.Tasks.csproj"/>
@ -13,4 +13,5 @@
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\JetBrains.Annotations.props" />
<Import Project="..\..\build\System.Memory.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project>

4
src/Avalonia.Base/AvaloniaObject.cs

@ -806,7 +806,9 @@ namespace Avalonia
break;
}
if (p.IsDataValidationEnabled)
var metadata = p.GetMetadata(GetType());
if (metadata.EnableDataValidation == true)
{
UpdateDataValidation(property, value);
}

6
src/Avalonia.Base/AvaloniaProperty.cs

@ -369,14 +369,14 @@ namespace Avalonia
var metadata = new DirectPropertyMetadata<TValue>(
unsetValue: unsetValue,
defaultBindingMode: defaultBindingMode);
defaultBindingMode: defaultBindingMode,
enableDataValidation: enableDataValidation);
var result = new DirectProperty<TOwner, TValue>(
name,
getter,
setter,
metadata,
enableDataValidation);
metadata);
AvaloniaPropertyRegistry.Instance.Register(typeof(TOwner), result);
return result;
}

25
src/Avalonia.Base/DirectProperty.cs

@ -23,16 +23,12 @@ namespace Avalonia
/// <param name="getter">Gets the current value of the property.</param>
/// <param name="setter">Sets the value of the property. May be null.</param>
/// <param name="metadata">The property metadata.</param>
/// <param name="enableDataValidation">
/// Whether the property is interested in data validation.
/// </param>
public DirectProperty(
string name,
Func<TOwner, TValue> getter,
Action<TOwner, TValue> setter,
DirectPropertyMetadata<TValue> metadata,
bool enableDataValidation)
: base(name, typeof(TOwner), metadata, enableDataValidation)
DirectPropertyMetadata<TValue> metadata)
: base(name, typeof(TOwner), metadata)
{
Contract.Requires<ArgumentNullException>(getter != null);
@ -47,16 +43,12 @@ namespace Avalonia
/// <param name="getter">Gets the current value of the property.</param>
/// <param name="setter">Sets the value of the property. May be null.</param>
/// <param name="metadata">Optional overridden metadata.</param>
/// <param name="enableDataValidation">
/// Whether the property is interested in data validation.
/// </param>
private DirectProperty(
DirectPropertyBase<TValue> source,
Func<TOwner, TValue> getter,
Action<TOwner, TValue> setter,
DirectPropertyMetadata<TValue> metadata,
bool enableDataValidation)
: base(source, typeof(TOwner), metadata, enableDataValidation)
DirectPropertyMetadata<TValue> metadata)
: base(source, typeof(TOwner), metadata)
{
Contract.Requires<ArgumentNullException>(getter != null);
@ -107,7 +99,8 @@ namespace Avalonia
{
var metadata = new DirectPropertyMetadata<TValue>(
unsetValue: unsetValue,
defaultBindingMode: defaultBindingMode);
defaultBindingMode: defaultBindingMode,
enableDataValidation: enableDataValidation);
metadata.Merge(GetMetadata<TOwner>(), this);
@ -115,8 +108,7 @@ namespace Avalonia
(DirectPropertyBase<TValue>)this,
getter,
setter,
metadata,
enableDataValidation);
metadata);
AvaloniaPropertyRegistry.Instance.Register(typeof(TNewOwner), result);
return result;
@ -155,8 +147,7 @@ namespace Avalonia
this,
getter,
setter,
metadata,
enableDataValidation);
metadata);
AvaloniaPropertyRegistry.Instance.Register(typeof(TNewOwner), result);
return result;

39
src/Avalonia.Base/DirectPropertyBase.cs

@ -23,17 +23,12 @@ namespace Avalonia
/// <param name="name">The name of the property.</param>
/// <param name="ownerType">The type of the class that registers the property.</param>
/// <param name="metadata">The property metadata.</param>
/// <param name="enableDataValidation">
/// Whether the property is interested in data validation.
/// </param>
protected DirectPropertyBase(
string name,
Type ownerType,
PropertyMetadata metadata,
bool enableDataValidation)
PropertyMetadata metadata)
: base(name, ownerType, metadata)
{
IsDataValidationEnabled = enableDataValidation;
}
/// <summary>
@ -42,17 +37,12 @@ namespace Avalonia
/// <param name="source">The property to copy.</param>
/// <param name="ownerType">The new owner type.</param>
/// <param name="metadata">Optional overridden metadata.</param>
/// <param name="enableDataValidation">
/// Whether the property is interested in data validation.
/// </param>
protected DirectPropertyBase(
AvaloniaProperty source,
Type ownerType,
PropertyMetadata metadata,
bool enableDataValidation)
PropertyMetadata metadata)
: base(source, ownerType, metadata)
{
IsDataValidationEnabled = enableDataValidation;
}
/// <summary>
@ -60,11 +50,6 @@ namespace Avalonia
/// </summary>
public abstract Type Owner { get; }
/// <summary>
/// Gets a value that indicates whether data validation is enabled for the property.
/// </summary>
public bool IsDataValidationEnabled { get; }
/// <summary>
/// Gets the value of the property on the instance.
/// </summary>
@ -102,6 +87,26 @@ namespace Avalonia
return (DirectPropertyMetadata<TValue>)base.GetMetadata(type);
}
/// <summary>
/// Overrides the metadata for the property on the specified type.
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <param name="metadata">The metadata.</param>
public void OverrideMetadata<T>(DirectPropertyMetadata<TValue> metadata) where T : IAvaloniaObject
{
base.OverrideMetadata(typeof(T), metadata);
}
/// <summary>
/// Overrides the metadata for the property on the specified type.
/// </summary>
/// <param name="type">The type.</param>
/// <param name="metadata">The metadata.</param>
public void OverrideMetadata(Type type, DirectPropertyMetadata<TValue> metadata)
{
base.OverrideMetadata(type, metadata);
}
/// <inheritdoc/>
public override void Accept<TData>(IAvaloniaPropertyVisitor<TData> vistor, ref TData data)
{

61
src/Avalonia.Base/Threading/AvaloniaScheduler.cs

@ -9,6 +9,16 @@ namespace Avalonia.Threading
/// </summary>
public class AvaloniaScheduler : LocalScheduler
{
/// <summary>
/// Users can schedule actions on the dispatcher thread while being on the correct thread already.
/// We are optimizing this case by invoking user callback immediately which can lead to stack overflows in certain cases.
/// To prevent this we are limiting amount of reentrant calls to <see cref="Schedule{TState}"/> before we will
/// schedule on a dispatcher anyway.
/// </summary>
private const int MaxReentrantSchedules = 32;
private int _reentrancyGuard;
/// <summary>
/// The instance of the <see cref="AvaloniaScheduler"/>.
/// </summary>
@ -24,31 +34,58 @@ namespace Avalonia.Threading
/// <inheritdoc/>
public override IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)
{
var composite = new CompositeDisposable(2);
IDisposable PostOnDispatcher()
{
var composite = new CompositeDisposable(2);
var cancellation = new CancellationDisposable();
Dispatcher.UIThread.Post(() =>
{
if (!cancellation.Token.IsCancellationRequested)
{
composite.Add(action(this, state));
}
}, DispatcherPriority.DataBind);
composite.Add(cancellation);
return composite;
}
if (dueTime == TimeSpan.Zero)
{
if (!Dispatcher.UIThread.CheckAccess())
{
var cancellation = new CancellationDisposable();
Dispatcher.UIThread.Post(() =>
{
if (!cancellation.Token.IsCancellationRequested)
{
composite.Add(action(this, state));
}
}, DispatcherPriority.DataBind);
composite.Add(cancellation);
return PostOnDispatcher();
}
else
{
return action(this, state);
if (_reentrancyGuard >= MaxReentrantSchedules)
{
return PostOnDispatcher();
}
try
{
_reentrancyGuard++;
return action(this, state);
}
finally
{
_reentrancyGuard--;
}
}
}
else
{
var composite = new CompositeDisposable(2);
composite.Add(DispatcherTimer.RunOnce(() => composite.Add(action(this, state)), dueTime));
return composite;
}
return composite;
}
}
}

2
src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs

@ -128,7 +128,7 @@ namespace Avalonia.Build.Tasks
asm.MainModule.Types.Add(typeDef);
var builder = typeSystem.CreateTypeBuilder(typeDef);
foreach (var res in group.Resources.Where(CheckXamlName))
foreach (var res in group.Resources.Where(CheckXamlName).OrderBy(x=>x.FilePath.ToLowerInvariant()))
{
try
{

1
src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj

@ -22,4 +22,5 @@
<Import Project="..\..\build\EmbedXaml.props" />
<Import Project="..\..\build\JetBrains.Annotations.props" />
<Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\build\ApiDiff.props" />
</Project>

10
src/Avalonia.Controls.DataGrid/Themes/Default.xaml

@ -28,7 +28,7 @@
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="SeparatorBrush" Value="{DynamicResource ThemeControlDarkBrush}" />
<Setter Property="SeparatorBrush" Value="{DynamicResource ThemeControlLowColor}" />
<Setter Property="Padding" Value="4" />
<Setter Property="Background" Value="{DynamicResource ThemeControlMidBrush}"/>
@ -188,7 +188,7 @@
</Style>
<Style Selector="DataGrid">
<Setter Property="RowBackground" Value="{DynamicResource SystemAccentColorDark2}" />
<Setter Property="RowBackground" Value="{DynamicResource ThemeAccentBrush4}" />
<Setter Property="AlternatingRowBackground" Value="#00FFFFFF" />
<Setter Property="Background" Value="{DynamicResource ThemeBackgroundBrush}" />
<Setter Property="HeadersVisibility" Value="Column" />
@ -196,9 +196,9 @@
<Setter Property="VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="SelectionMode" Value="Extended" />
<Setter Property="GridLinesVisibility" Value="Vertical" />
<Setter Property="HorizontalGridLinesBrush" Value="{DynamicResource ThemeBorderLightBrush}" />
<Setter Property="VerticalGridLinesBrush" Value="{DynamicResource ThemeBorderLightBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderDarkBrush}"/>
<Setter Property="HorizontalGridLinesBrush" Value="{DynamicResource ThemeBorderHighColor}" />
<Setter Property="VerticalGridLinesBrush" Value="{DynamicResource ThemeBorderHighColor}" />
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderLowColor}"/>
<Setter Property="BorderThickness" Value="{DynamicResource ThemeBorderThickness}" />
<Setter Property="DropLocationIndicatorTemplate">
<Template>

7
src/Avalonia.Controls/AutoCompleteBox.cs

@ -1647,7 +1647,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="sender">The source object.</param>
/// <param name="e">The event data.</param>
private void DropDownPopup_Closed(object sender, PopupClosedEventArgs e)
private void DropDownPopup_Closed(object sender, EventArgs e)
{
// Force the drop down dependency property to be false.
if (IsDropDownOpen)
@ -1655,11 +1655,6 @@ namespace Avalonia.Controls
IsDropDownOpen = false;
}
if (e.CloseEvent is PointerEventArgs pointerEvent)
{
pointerEvent.Handled = true;
}
// Fire the DropDownClosed event
if (_popupHasOpened)
{

3
src/Avalonia.Controls/Avalonia.Controls.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />
@ -14,4 +14,5 @@
</ItemGroup>
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\JetBrains.Annotations.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project>

7
src/Avalonia.Controls/Calendar/CalendarDatePicker.cs

@ -889,17 +889,12 @@ namespace Avalonia.Controls
_ignoreButtonClick = false;
}
}
private void PopUp_Closed(object sender, PopupClosedEventArgs e)
private void PopUp_Closed(object sender, EventArgs e)
{
IsDropDownOpen = false;
if(!_isPopupClosing)
{
if (e.CloseEvent is PointerEventArgs pointerEvent)
{
pointerEvent.Handled = true;
}
_isPopupClosing = true;
Threading.Dispatcher.UIThread.InvokeAsync(() => _isPopupClosing = false);
}

22
src/Avalonia.Controls/ComboBox.cs

@ -290,24 +290,6 @@ namespace Avalonia.Controls
_popup = e.NameScope.Get<Popup>("PART_Popup");
_popup.Opened += PopupOpened;
_popup.Closed += PopupClosed;
}
/// <summary>
/// Called when the ComboBox popup is closed, with the <see cref="PopupClosedEventArgs"/>
/// that caused the popup to close.
/// </summary>
/// <param name="e">The event args.</param>
/// <remarks>
/// This method can be overridden to control whether the event that caused the popup to close
/// is swallowed or passed through.
/// </remarks>
protected virtual void PopupClosedOverride(PopupClosedEventArgs e)
{
if (e.CloseEvent is PointerEventArgs pointerEvent)
{
pointerEvent.Handled = true;
}
}
internal void ItemFocused(ComboBoxItem dropDownItem)
@ -318,13 +300,11 @@ namespace Avalonia.Controls
}
}
private void PopupClosed(object sender, PopupClosedEventArgs e)
private void PopupClosed(object sender, EventArgs e)
{
_subscriptionsOnOpen?.Dispose();
_subscriptionsOnOpen = null;
PopupClosedOverride(e);
if (CanFocus(this))
{
Focus();

6
src/Avalonia.Controls/ContextMenu.cs

@ -265,7 +265,8 @@ namespace Avalonia.Controls
PlacementMode = PlacementMode,
PlacementRect = PlacementRect,
PlacementTarget = PlacementTarget ?? control,
StaysOpen = false
IsLightDismissEnabled = true,
OverlayDismissEventPassThrough = true,
};
_popup.Opened += PopupOpened;
@ -279,9 +280,8 @@ namespace Avalonia.Controls
}
_popup.Child = this;
_popup.IsOpen = true;
IsOpen = true;
_popup.IsOpen = true;
RaiseEvent(new RoutedEventArgs
{

9
src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs

@ -356,10 +356,17 @@ namespace Avalonia.Controls
}
if (MonthVisible)
{
_monthSelector.SelectedValue = dt.Month;
_monthSelector.FormatDate = dt.Date;
}
if (YearVisible)
{
_yearSelector.SelectedValue = dt.Year;
_yearSelector.FormatDate = dt.Date;
}
_suppressUpdateSelection = false;
SetInitialFocus();

4
src/Avalonia.Controls/IMenuElement.cs

@ -1,6 +1,8 @@
using System.Collections.Generic;
using Avalonia.Input;
#nullable enable
namespace Avalonia.Controls
{
/// <summary>
@ -11,7 +13,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets the currently selected submenu item.
/// </summary>
IMenuItem SelectedItem { get; set; }
IMenuItem? SelectedItem { get; set; }
/// <summary>
/// Gets the submenu items.

6
src/Avalonia.Controls/IMenuItem.cs

@ -1,4 +1,6 @@
namespace Avalonia.Controls
#nullable enable
namespace Avalonia.Controls
{
/// <summary>
/// Represents a <see cref="MenuItem"/>.
@ -29,7 +31,7 @@
/// <summary>
/// Gets the parent <see cref="IMenuElement"/>.
/// </summary>
new IMenuElement Parent { get; }
new IMenuElement? Parent { get; }
/// <summary>
/// Raises a click event on the menu item.

2
src/Avalonia.Controls/ItemsControl.cs

@ -295,7 +295,7 @@ namespace Avalonia.Controls
if (next != null)
{
focus.Focus(next, NavigationMethod.Directional);
focus.Focus(next, NavigationMethod.Directional, e.KeyModifiers);
e.Handled = true;
}

3
src/Avalonia.Controls/ListBox.cs

@ -136,7 +136,8 @@ namespace Avalonia.Controls
e.Handled = UpdateSelectionFromEventSource(
e.Source,
true,
(e.KeyModifiers & KeyModifiers.Shift) != 0);
(e.KeyModifiers & KeyModifiers.Shift) != 0,
(e.KeyModifiers & KeyModifiers.Control) != 0);
}
}

5
src/Avalonia.Controls/Menu.cs

@ -1,9 +1,12 @@
using Avalonia.Controls.Platform;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
#nullable enable
namespace Avalonia.Controls
{
/// <summary>
@ -14,6 +17,8 @@ namespace Avalonia.Controls
private static readonly ITemplate<IPanel> DefaultPanel =
new FuncTemplate<IPanel>(() => new StackPanel { Orientation = Orientation.Horizontal });
private LightDismissOverlayLayer? _overlay;
/// <summary>
/// Initializes a new instance of the <see cref="Menu"/> class.
/// </summary>

8
src/Avalonia.Controls/MenuBase.cs

@ -8,6 +8,8 @@ using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
#nullable enable
namespace Avalonia.Controls
{
/// <summary>
@ -51,9 +53,7 @@ namespace Avalonia.Controls
/// <param name="interactionHandler">The menu interaction handler.</param>
public MenuBase(IMenuInteractionHandler interactionHandler)
{
Contract.Requires<ArgumentNullException>(interactionHandler != null);
InteractionHandler = interactionHandler;
InteractionHandler = interactionHandler ?? throw new ArgumentNullException(nameof(interactionHandler));
}
/// <summary>
@ -77,7 +77,7 @@ namespace Avalonia.Controls
IMenuInteractionHandler IMenu.InteractionHandler => InteractionHandler;
/// <inheritdoc/>
IMenuItem IMenuElement.SelectedItem
IMenuItem? IMenuElement.SelectedItem
{
get
{

70
src/Avalonia.Controls/MenuItem.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Windows.Input;
using Avalonia.Controls.Generators;
using Avalonia.Controls.Mixins;
@ -12,6 +13,8 @@ using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.VisualTree;
#nullable enable
namespace Avalonia.Controls
{
/// <summary>
@ -22,7 +25,7 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="Command"/> property.
/// </summary>
public static readonly DirectProperty<MenuItem, ICommand> CommandProperty =
public static readonly DirectProperty<MenuItem, ICommand?> CommandProperty =
Button.CommandProperty.AddOwner<MenuItem>(
menuItem => menuItem.Command,
(menuItem, command) => menuItem.Command = command,
@ -94,10 +97,9 @@ namespace Avalonia.Controls
private static readonly ITemplate<IPanel> DefaultPanel =
new FuncTemplate<IPanel>(() => new StackPanel());
private ICommand _command;
private ICommand? _command;
private bool _commandCanExecute = true;
private Popup _popup;
private IDisposable _gridHack;
/// <summary>
/// Initializes static members of the <see cref="MenuItem"/> class.
@ -119,6 +121,32 @@ namespace Avalonia.Controls
public MenuItem()
{
// HACK: This nasty but it's all WPF's fault. Grid uses an inherited attached
// property to store SharedSizeGroup state, except property inheritance is done
// down the logical tree. In this case, the control which is setting
// Grid.IsSharedSizeScope="True" is not in the logical tree. Instead of fixing
// the way Grid stores shared size state, the developers of WPF just created a
// binding of the internal state of the visual parent to the menu item. We don't
// have much choice but to do the same for now unless we want to refactor Grid,
// which I honestly am not brave enough to do right now. Here's the same hack in
// the WPF codebase:
//
// https://github.com/dotnet/wpf/blob/89537909bdf36bc918e88b37751add46a8980bb0/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/MenuItem.cs#L2126-L2141
//
// In addition to the hack from WPF, we also make sure to return null when we have
// no parent. If we don't do this, inheritance falls back to the logical tree,
// causing the shared size scope in the parent MenuItem to be used, breaking
// menu layout.
var parentSharedSizeScope = this.GetObservable(VisualParentProperty)
.SelectMany(x =>
{
var parent = x as Control;
return parent?.GetObservable(DefinitionBase.PrivateSharedSizeScopeProperty) ??
Observable.Return<DefinitionBase.SharedSizeScope>(null);
});
this.Bind(DefinitionBase.PrivateSharedSizeScopeProperty, parentSharedSizeScope);
}
/// <summary>
@ -166,7 +194,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets the command associated with the menu item.
/// </summary>
public ICommand Command
public ICommand? Command
{
get { return _command; }
set { SetAndRaise(CommandProperty, ref _command, value); }
@ -246,7 +274,7 @@ namespace Avalonia.Controls
bool IMenuItem.IsPointerOverSubMenu => _popup?.IsPointerOverPopup ?? false;
/// <inheritdoc/>
IMenuElement IMenuItem.Parent => Parent as IMenuElement;
IMenuElement? IMenuItem.Parent => Parent as IMenuElement;
protected override bool IsEnabledCore => base.IsEnabledCore && _commandCanExecute;
@ -254,7 +282,7 @@ namespace Avalonia.Controls
bool IMenuElement.MoveSelection(NavigationDirection direction, bool wrap) => MoveSelection(direction, wrap);
/// <inheritdoc/>
IMenuItem IMenuElement.SelectedItem
IMenuItem? IMenuElement.SelectedItem
{
get
{
@ -323,32 +351,6 @@ namespace Avalonia.Controls
{
Command.CanExecuteChanged -= CanExecuteChanged;
}
_gridHack?.Dispose();
_gridHack = null;
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
if (this.GetVisualParent() is IControl parent)
{
// HACK: This nasty but it's all WPF's fault. Grid uses an inherited attached
// property to store SharedSizeGroup state, except property inheritance is done
// down the logical tree. In this case, the control which is setting
// Grid.IsSharedSizeScope="True" is not in the logical tree. Instead of fixing
// the way Grid stores shared size state, the developers of WPF just created a
// binding of the internal state of the visual parent to the menu item. We don't
// have much choice but to do the same for now unless we want to refactor Grid,
// which I honestly am not brave enough to do right now. Here's the same hack in
// the WPF codebase:
//
// https://github.com/dotnet/wpf/blob/89537909bdf36bc918e88b37751add46a8980bb0/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/MenuItem.cs#L2126-L2141
_gridHack = Bind(
DefinitionBase.PrivateSharedSizeScopeProperty,
parent.GetBindingObservable(DefinitionBase.PrivateSharedSizeScopeProperty));
}
}
/// <summary>
@ -551,7 +553,7 @@ namespace Avalonia.Controls
/// <param name="e">The property change event.</param>
private void IsSelectedChanged(AvaloniaPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
if ((bool)e.NewValue!)
{
Focus();
}
@ -563,7 +565,7 @@ namespace Avalonia.Controls
/// <param name="e">The property change event.</param>
private void SubMenuOpenChanged(AvaloniaPropertyChangedEventArgs e)
{
var value = (bool)e.NewValue;
var value = (bool)e.NewValue!;
if (value)
{

12
src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs

@ -3,7 +3,6 @@ using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Threading;
using Avalonia.VisualTree;
@ -235,7 +234,9 @@ namespace Avalonia.Controls.Platform
// If the the parent is an IMenu which successfully moved its selection,
// and the current menu is open then close the current menu and open the
// new menu.
if (item.IsSubMenuOpen && item.Parent is IMenu)
if (item.IsSubMenuOpen &&
item.Parent is IMenu &&
item.Parent.SelectedItem is object)
{
item.Close();
Open(item.Parent.SelectedItem, true);
@ -363,6 +364,11 @@ namespace Avalonia.Controls.Platform
}
else
{
if (item.IsTopLevel && item.Parent is IMainMenu mainMenu)
{
mainMenu.Open();
}
Open(item, false);
}
@ -385,7 +391,7 @@ namespace Avalonia.Controls.Platform
{
if (e.Source == Menu)
{
Menu.MoveSelection(NavigationDirection.First, true);
Menu?.MoveSelection(NavigationDirection.First, true);
}
}

15
src/Avalonia.Controls/Presenters/TextPresenter.cs

@ -14,6 +14,9 @@ namespace Avalonia.Controls.Presenters
o => o.CaretIndex,
(o, v) => o.CaretIndex = v);
public static readonly StyledProperty<bool> RevealPasswordProperty =
AvaloniaProperty.Register<TextPresenter, bool>(nameof(RevealPassword));
public static readonly StyledProperty<char> PasswordCharProperty =
AvaloniaProperty.Register<TextPresenter, char>(nameof(PasswordChar));
@ -75,7 +78,7 @@ namespace Avalonia.Controls.Presenters
static TextPresenter()
{
AffectsRender<TextPresenter>(SelectionBrushProperty);
AffectsMeasure<TextPresenter>(TextProperty, PasswordCharProperty,
AffectsMeasure<TextPresenter>(TextProperty, PasswordCharProperty, RevealPasswordProperty,
TextAlignmentProperty, TextWrappingProperty, TextBlock.FontSizeProperty,
TextBlock.FontStyleProperty, TextBlock.FontWeightProperty, TextBlock.FontFamilyProperty);
@ -84,7 +87,7 @@ namespace Avalonia.Controls.Presenters
TextBlock.FontSizeProperty.Changed, TextBlock.FontStyleProperty.Changed,
TextBlock.FontWeightProperty.Changed, TextBlock.FontFamilyProperty.Changed,
SelectionStartProperty.Changed, SelectionEndProperty.Changed,
SelectionForegroundBrushProperty.Changed, PasswordCharProperty.Changed
SelectionForegroundBrushProperty.Changed, PasswordCharProperty.Changed, RevealPasswordProperty.Changed
).AddClassHandler<TextPresenter>((x, _) => x.InvalidateFormattedText());
CaretIndexProperty.Changed.AddClassHandler<TextPresenter>((x, e) => x.CaretIndexChanged((int)e.NewValue));
@ -210,6 +213,12 @@ namespace Avalonia.Controls.Presenters
set => SetValue(PasswordCharProperty, value);
}
public bool RevealPassword
{
get => GetValue(RevealPasswordProperty);
set => SetValue(RevealPasswordProperty, value);
}
public IBrush SelectionBrush
{
get => GetValue(SelectionBrushProperty);
@ -426,7 +435,7 @@ namespace Avalonia.Controls.Presenters
var text = Text;
if (PasswordChar != default(char))
if (PasswordChar != default(char) && !RevealPassword)
{
result = CreateFormattedTextInternal(_constraint, new string(PasswordChar, text?.Length ?? 0));
}

61
src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs

@ -0,0 +1,61 @@
using System;
using System.Linq;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.VisualTree;
#nullable enable
namespace Avalonia.Controls.Primitives
{
/// <summary>
/// A layer that is used to dismiss a <see cref="Popup"/> when the user clicks outside.
/// </summary>
public class LightDismissOverlayLayer : Border, ICustomHitTest
{
public IInputElement? InputPassThroughElement { get; set; }
/// <summary>
/// Returns the light dismiss overlay for a specified visual.
/// </summary>
/// <param name="visual">The visual.</param>
/// <returns>The light dismiss overlay, or null if none found.</returns>
public static LightDismissOverlayLayer? GetLightDismissOverlayLayer(IVisual visual)
{
visual = visual ?? throw new ArgumentNullException(nameof(visual));
VisualLayerManager? manager;
if (visual is TopLevel topLevel)
{
manager = topLevel.GetTemplateChildren()
.OfType<VisualLayerManager>()
.FirstOrDefault();
}
else
{
manager = visual.FindAncestorOfType<VisualLayerManager>();
}
return manager?.LightDismissOverlayLayer;
}
public bool HitTest(Point point)
{
if (InputPassThroughElement is object)
{
var p = point.Transform(this.TransformToVisual(VisualRoot)!.Value);
var hit = VisualRoot.GetVisualAt(p, x => x != this);
if (hit is object)
{
return !InputPassThroughElement.IsVisualAncestorOf(hit);
}
}
return true;
}
}
}

143
src/Avalonia.Controls/Primitives/Popup.cs

@ -1,12 +1,10 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Reactive.Disposables;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.Metadata;
using Avalonia.Platform;
@ -86,12 +84,27 @@ namespace Avalonia.Controls.Primitives
AvaloniaProperty.Register<Popup, bool>(nameof(ObeyScreenEdges), true);
#pragma warning restore 618
public static readonly StyledProperty<bool> OverlayDismissEventPassThroughProperty =
AvaloniaProperty.Register<Popup, bool>(nameof(OverlayDismissEventPassThrough));
public static readonly DirectProperty<Popup, IInputElement> OverlayInputPassThroughElementProperty =
AvaloniaProperty.RegisterDirect<Popup, IInputElement>(
nameof(OverlayInputPassThroughElement),
o => o.OverlayInputPassThroughElement,
(o, v) => o.OverlayInputPassThroughElement = v);
/// <summary>
/// Defines the <see cref="HorizontalOffset"/> property.
/// </summary>
public static readonly StyledProperty<double> HorizontalOffsetProperty =
AvaloniaProperty.Register<Popup, double>(nameof(HorizontalOffset));
/// <summary>
/// Defines the <see cref="IsLightDismissEnabled"/> property.
/// </summary>
public static readonly StyledProperty<bool> IsLightDismissEnabledProperty =
AvaloniaProperty.Register<Popup, bool>(nameof(IsLightDismissEnabled));
/// <summary>
/// Defines the <see cref="VerticalOffset"/> property.
/// </summary>
@ -101,8 +114,13 @@ namespace Avalonia.Controls.Primitives
/// <summary>
/// Defines the <see cref="StaysOpen"/> property.
/// </summary>
public static readonly StyledProperty<bool> StaysOpenProperty =
AvaloniaProperty.Register<Popup, bool>(nameof(StaysOpen), true);
[Obsolete("Use IsLightDismissEnabledProperty")]
public static readonly DirectProperty<Popup, bool> StaysOpenProperty =
AvaloniaProperty.RegisterDirect<Popup, bool>(
nameof(StaysOpen),
o => o.StaysOpen,
(o, v) => o.StaysOpen = v,
true);
/// <summary>
/// Defines the <see cref="Topmost"/> property.
@ -113,6 +131,7 @@ namespace Avalonia.Controls.Primitives
private bool _isOpen;
private bool _ignoreIsOpenChanged;
private PopupOpenState? _openState;
private IInputElement _overlayInputPassThroughElement;
/// <summary>
/// Initializes static members of the <see cref="Popup"/> class.
@ -127,7 +146,7 @@ namespace Avalonia.Controls.Primitives
/// <summary>
/// Raised when the popup closes.
/// </summary>
public event EventHandler<PopupClosedEventArgs>? Closed;
public event EventHandler<EventArgs>? Closed;
/// <summary>
/// Raised when the popup opens.
@ -165,6 +184,18 @@ namespace Avalonia.Controls.Primitives
set;
}
/// <summary>
/// Gets or sets a value that determines how the <see cref="Popup"/> can be dismissed.
/// </summary>
/// <remarks>
/// Light dismiss is when the user taps on any area other than the popup.
/// </remarks>
public bool IsLightDismissEnabled
{
get => GetValue(IsLightDismissEnabledProperty);
set => SetValue(IsLightDismissEnabledProperty, value);
}
/// <summary>
/// Gets or sets a value indicating whether the popup is currently open.
/// </summary>
@ -246,6 +277,32 @@ namespace Avalonia.Controls.Primitives
set => SetValue(ObeyScreenEdgesProperty, value);
}
/// <summary>
/// Gets or sets a value indicating whether the event that closes the popup is passed
/// through to the parent window.
/// </summary>
/// <remarks>
/// When <see cref="IsLightDismissEnabled"/> is set to true, clicks outside the the popup
/// cause the popup to close. When <see cref="OverlayDismissEventPassThrough"/> is set to
/// false, these clicks will be handled by the popup and not be registered by the parent
/// window. When set to true, the events will be passed through to the parent window.
/// </remarks>
public bool OverlayDismissEventPassThrough
{
get => GetValue(OverlayDismissEventPassThroughProperty);
set => SetValue(OverlayDismissEventPassThroughProperty, value);
}
/// <summary>
/// Gets or sets an element that should receive pointer input events even when underneath
/// the popup's overlay.
/// </summary>
public IInputElement OverlayInputPassThroughElement
{
get => _overlayInputPassThroughElement;
set => SetAndRaise(OverlayInputPassThroughElementProperty, ref _overlayInputPassThroughElement, value);
}
/// <summary>
/// Gets or sets the Horizontal offset of the popup in relation to the <see cref="PlacementTarget"/>.
/// </summary>
@ -268,10 +325,11 @@ namespace Avalonia.Controls.Primitives
/// Gets or sets a value indicating whether the popup should stay open when the popup is
/// pressed or loses focus.
/// </summary>
[Obsolete("Use IsLightDismissEnabled")]
public bool StaysOpen
{
get { return GetValue(StaysOpenProperty); }
set { SetValue(StaysOpenProperty, value); }
get => !IsLightDismissEnabled;
set => IsLightDismissEnabled = !value;
}
/// <summary>
@ -363,14 +421,12 @@ namespace Avalonia.Controls.Primitives
if (parentPopupRoot?.Parent is Popup popup)
{
DeferCleanup(SubscribeToEventHandler<Popup, EventHandler<PopupClosedEventArgs>>(popup, ParentClosed,
DeferCleanup(SubscribeToEventHandler<Popup, EventHandler<EventArgs>>(popup, ParentClosed,
(x, handler) => x.Closed += handler,
(x, handler) => x.Closed -= handler));
}
}
DeferCleanup(topLevel.AddDisposableHandler(PointerPressedEvent, PointerPressedOutside, RoutingStrategies.Tunnel));
DeferCleanup(InputManager.Instance?.Process.Subscribe(ListenForNonClientClick));
var cleanupPopup = Disposable.Create((popupHost, handlerCleanup), state =>
@ -384,6 +440,29 @@ namespace Avalonia.Controls.Primitives
state.popupHost.Dispose();
});
if (IsLightDismissEnabled)
{
var dismissLayer = LightDismissOverlayLayer.GetLightDismissOverlayLayer(placementTarget);
if (dismissLayer != null)
{
dismissLayer.IsVisible = true;
dismissLayer.InputPassThroughElement = _overlayInputPassThroughElement;
DeferCleanup(Disposable.Create(() =>
{
dismissLayer.IsVisible = false;
dismissLayer.InputPassThroughElement = null;
}));
DeferCleanup(SubscribeToEventHandler<LightDismissOverlayLayer, EventHandler<PointerPressedEventArgs>>(
dismissLayer,
PointerPressedDismissOverlay,
(x, handler) => x.PointerPressed += handler,
(x, handler) => x.PointerPressed -= handler));
}
}
_openState = new PopupOpenState(topLevel, popupHost, cleanupPopup);
WindowManagerAddShadowHintChanged(popupHost, WindowManagerAddShadowHint);
@ -401,7 +480,7 @@ namespace Avalonia.Controls.Primitives
/// <summary>
/// Closes the popup.
/// </summary>
public void Close() => CloseCore(null);
public void Close() => CloseCore();
/// <summary>
/// Measures the control.
@ -471,7 +550,7 @@ namespace Avalonia.Controls.Primitives
}
}
private void CloseCore(EventArgs? closeEvent)
private void CloseCore()
{
if (_openState is null)
{
@ -491,24 +570,46 @@ namespace Avalonia.Controls.Primitives
IsOpen = false;
}
Closed?.Invoke(this, new PopupClosedEventArgs(closeEvent));
Closed?.Invoke(this, EventArgs.Empty);
}
private void ListenForNonClientClick(RawInputEventArgs e)
{
var mouse = e as RawPointerEventArgs;
if (!StaysOpen && mouse?.Type == RawPointerEventType.NonClientLeftButtonDown)
if (IsLightDismissEnabled && mouse?.Type == RawPointerEventType.NonClientLeftButtonDown)
{
CloseCore(e);
CloseCore();
}
}
private void PointerPressedOutside(object sender, PointerPressedEventArgs e)
private void PointerPressedDismissOverlay(object sender, PointerPressedEventArgs e)
{
if (!StaysOpen && e.Source is IVisual v && !IsChildOrThis(v))
if (IsLightDismissEnabled && e.Source is IVisual v && !IsChildOrThis(v))
{
CloseCore(e);
CloseCore();
if (OverlayDismissEventPassThrough)
{
PassThroughEvent(e);
}
}
}
private void PassThroughEvent(PointerPressedEventArgs e)
{
if (e.Source is LightDismissOverlayLayer layer &&
layer.GetVisualRoot() is IInputElement root)
{
var p = e.GetCurrentPoint(root);
var hit = root.InputHitTest(p.Position, x => x != layer);
if (hit != null)
{
e.Pointer.Capture(hit);
hit.RaiseEvent(e);
e.Handled = true;
}
}
}
@ -602,7 +703,7 @@ namespace Avalonia.Controls.Primitives
private void WindowDeactivated(object sender, EventArgs e)
{
if (!StaysOpen)
if (IsLightDismissEnabled)
{
Close();
}
@ -610,7 +711,7 @@ namespace Avalonia.Controls.Primitives
private void ParentClosed(object sender, EventArgs e)
{
if (!StaysOpen)
if (IsLightDismissEnabled)
{
Close();
}
@ -618,7 +719,7 @@ namespace Avalonia.Controls.Primitives
private void WindowLostFocus()
{
if(!StaysOpen)
if (IsLightDismissEnabled)
Close();
}

33
src/Avalonia.Controls/Primitives/PopupClosedEventArgs.cs

@ -1,33 +0,0 @@
using System;
using Avalonia.Interactivity;
#nullable enable
namespace Avalonia.Controls.Primitives
{
/// <summary>
/// Holds data for the <see cref="Popup.Closed"/> event.
/// </summary>
public class PopupClosedEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="PopupClosedEventArgs"/> class.
/// </summary>
/// <param name="closeEvent"></param>
public PopupClosedEventArgs(EventArgs? closeEvent)
{
CloseEvent = closeEvent;
}
/// <summary>
/// Gets the event that closed the popup, if any.
/// </summary>
/// <remarks>
/// If <see cref="Popup.StaysOpen"/> is false, then this property will hold details of the
/// interaction that caused the popup to close if the close was caused by e.g. a pointer press
/// outside the popup. It can be used to mark the event as handled if the event should not
/// be propagated.
/// </remarks>
public EventArgs? CloseEvent { get; }
}
}

26
src/Avalonia.Controls/Primitives/VisualLayerManager.cs

@ -1,6 +1,6 @@
using System.Collections.Generic;
using Avalonia.LogicalTree;
using Avalonia.Metadata;
using Avalonia.Media;
namespace Avalonia.Controls.Primitives
{
@ -8,7 +8,8 @@ namespace Avalonia.Controls.Primitives
{
private const int AdornerZIndex = int.MaxValue - 100;
private const int ChromeZIndex = int.MaxValue - 99;
private const int OverlayZIndex = int.MaxValue - 98;
private const int LightDismissOverlayZIndex = int.MaxValue - 98;
private const int OverlayZIndex = int.MaxValue - 97;
private ILogicalRoot _logicalRoot;
private readonly List<Control> _layers = new List<Control>();
@ -62,6 +63,27 @@ namespace Avalonia.Controls.Primitives
}
}
public LightDismissOverlayLayer LightDismissOverlayLayer
{
get
{
if (IsPopup)
return null;
var rv = FindLayer<LightDismissOverlayLayer>();
if (rv == null)
{
rv = new LightDismissOverlayLayer
{
Background = Brushes.Transparent,
IsVisible = false
};
AddLayer(rv, LightDismissOverlayZIndex);
}
return rv;
}
}
T FindLayer<T>() where T : class
{
foreach (var layer in _layers)

2
src/Avalonia.Controls/ProgressBar.cs

@ -215,7 +215,7 @@ namespace Avalonia.Controls
TemplateProperties.Container2AnimationEndPosition = barIndicatorWidth2 * 1.66; // Position at 166%
// Remove these properties when we switch to fluent as default and removed the old one.
IndeterminateStartingOffset = -(dim / 5d);
IndeterminateStartingOffset = -dim;
IndeterminateEndingOffset = dim;
var padding = Padding;

2
src/Avalonia.Controls/Repeater/ItemsRepeaterElementIndexChangedEventArgs.cs

@ -34,7 +34,7 @@ namespace Avalonia.Controls
/// </summary>
public int OldIndex { get; private set; }
internal void Update(IControl element, int newIndex, int oldIndex)
internal void Update(IControl element, int oldIndex, int newIndex)
{
Element = element;
NewIndex = newIndex;

15
src/Avalonia.Controls/Repeater/ItemsSourceView.cs

@ -25,7 +25,6 @@ namespace Avalonia.Controls
{
private readonly IList _inner;
private INotifyCollectionChanged _notifyCollectionChanged;
private int _cachedSize = -1;
/// <summary>
/// Initializes a new instance of the ItemsSourceView class for the specified data source.
@ -54,18 +53,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets the number of items in the collection.
/// </summary>
public int Count
{
get
{
if (_cachedSize == -1)
{
_cachedSize = _inner.Count;
}
return _cachedSize;
}
}
public int Count => _inner.Count;
/// <summary>
/// Gets a value that indicates whether the items source can provide a unique key for each item.
@ -126,7 +114,6 @@ namespace Avalonia.Controls
protected void OnItemsSourceChanged(NotifyCollectionChangedEventArgs args)
{
_cachedSize = _inner.Count;
CollectionChanged?.Invoke(this, args);
}

17
src/Avalonia.Controls/Repeater/ViewportManager.cs

@ -350,11 +350,14 @@ namespace Avalonia.Controls
}
// Make sure that only the target child can be the anchor during the bring into view operation.
foreach (var child in _owner.Children)
if (_scroller is object)
{
if (child != targetChild)
foreach (var child in _owner.Children)
{
_scroller.UnregisterAnchorCandidate(child);
if (child != targetChild)
{
_scroller.UnregisterAnchorCandidate(child);
}
}
}
@ -469,13 +472,7 @@ namespace Avalonia.Controls
parent = parent.VisualParent;
}
if (_scroller == null)
{
// We usually update the viewport in the post arrange handler. But, since we don't have
// a scroller, let's do it now.
UpdateViewport(Rect.Empty);
}
else if (!_managingViewportDisabled)
if (!_managingViewportDisabled)
{
_owner.EffectiveViewportChanged += OnEffectiveViewportChanged;
_effectiveViewportChangedSubscribed = true;

63
src/Avalonia.Controls/TextBox.cs

@ -95,6 +95,15 @@ namespace Avalonia.Controls
AvaloniaProperty.RegisterDirect<TextBox, string>(nameof(NewLine),
textbox => textbox.NewLine, (textbox, newline) => textbox.NewLine = newline);
public static readonly StyledProperty<object> InnerLeftContentProperty =
AvaloniaProperty.Register<TextBox, object>(nameof(InnerLeftContent));
public static readonly StyledProperty<object> InnerRightContentProperty =
AvaloniaProperty.Register<TextBox, object>(nameof(InnerRightContent));
public static readonly StyledProperty<bool> RevealPasswordProperty =
AvaloniaProperty.Register<TextBox, bool>(nameof(RevealPassword));
struct UndoRedoState : IEquatable<UndoRedoState>
{
public string Text { get; }
@ -148,6 +157,8 @@ namespace Avalonia.Controls
horizontalScrollBarVisibility,
BindingPriority.Style);
_undoRedoHelper = new UndoRedoHelper<UndoRedoState>(this);
UpdatePseudoclasses();
}
public bool AcceptsReturn
@ -285,7 +296,7 @@ namespace Avalonia.Controls
else
{
HandleTextInput(value);
}
}
_undoRedoHelper.Snapshot();
}
}
@ -326,6 +337,24 @@ namespace Avalonia.Controls
set { SetValue(UseFloatingWatermarkProperty, value); }
}
public object InnerLeftContent
{
get { return GetValue(InnerLeftContentProperty); }
set { SetValue(InnerLeftContentProperty, value); }
}
public object InnerRightContent
{
get { return GetValue(InnerRightContentProperty); }
set { SetValue(InnerRightContentProperty, value); }
}
public bool RevealPassword
{
get { return GetValue(RevealPasswordProperty); }
set { SetValue(RevealPasswordProperty, value); }
}
public TextWrapping TextWrapping
{
get { return GetValue(TextWrappingProperty); }
@ -351,6 +380,16 @@ namespace Avalonia.Controls
}
}
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change)
{
base.OnPropertyChanged(change);
if (change.Property == TextProperty)
{
UpdatePseudoclasses();
}
}
protected override void OnGotFocus(GotFocusEventArgs e)
{
base.OnGotFocus(e);
@ -371,8 +410,14 @@ namespace Avalonia.Controls
protected override void OnLostFocus(RoutedEventArgs e)
{
base.OnLostFocus(e);
SelectionStart = 0;
SelectionEnd = 0;
if (ContextMenu == null || !ContextMenu.IsOpen)
{
SelectionStart = 0;
SelectionEnd = 0;
RevealPassword = false;
}
_presenter?.HideCaret();
}
@ -756,7 +801,7 @@ namespace Avalonia.Controls
// if it did not, we change the selection to where the user clicked
var firstSelection = Math.Min(SelectionStart, SelectionEnd);
var lastSelection = Math.Max(SelectionStart, SelectionEnd);
var didClickInSelection = SelectionStart != SelectionEnd &&
var didClickInSelection = SelectionStart != SelectionEnd &&
caretIndex >= firstSelection && caretIndex <= lastSelection;
if (!didClickInSelection)
{
@ -803,6 +848,11 @@ namespace Avalonia.Controls
}
}
public void Clear()
{
Text = string.Empty;
}
private int DeleteCharacter(int index)
{
var start = index + 1;
@ -1068,6 +1118,11 @@ namespace Avalonia.Controls
SelectionEnd = CaretIndex;
}
private void UpdatePseudoclasses()
{
PseudoClasses.Set(":empty", string.IsNullOrWhiteSpace(Text));
}
private bool IsPasswordBox => PasswordChar != default(char);
UndoRedoState UndoRedoHelper<UndoRedoState>.IUndoRedoHost.UndoRedoState

1
src/Avalonia.Controls/ToolTip.cs

@ -66,6 +66,7 @@ namespace Avalonia.Controls
static ToolTip()
{
TipProperty.Changed.Subscribe(ToolTipService.Instance.TipChanged);
IsOpenProperty.Changed.Subscribe(ToolTipService.Instance.TipOpenChanged);
IsOpenProperty.Changed.Subscribe(IsOpenChanged);
}

15
src/Avalonia.Controls/ToolTipService.cs

@ -28,20 +28,33 @@ namespace Avalonia.Controls
{
control.PointerEnter -= ControlPointerEnter;
control.PointerLeave -= ControlPointerLeave;
control.DetachedFromVisualTree -= ControlDetaching;
}
if (e.NewValue != null)
{
control.PointerEnter += ControlPointerEnter;
control.PointerLeave += ControlPointerLeave;
}
}
internal void TipOpenChanged(AvaloniaPropertyChangedEventArgs e)
{
var control = (Control)e.Sender;
if (e.OldValue is false && e.NewValue is true)
{
control.DetachedFromVisualTree += ControlDetaching;
}
else if(e.OldValue is true && e.NewValue is false)
{
control.DetachedFromVisualTree -= ControlDetaching;
}
}
private void ControlDetaching(object sender, VisualTreeAttachmentEventArgs e)
{
var control = (Control)sender;
control.DetachedFromVisualTree -= ControlDetaching;
Close(control);
}

37
src/Avalonia.Controls/Utils/SelectedItemsSync.cs

@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using Avalonia.Collections;
@ -16,6 +17,7 @@ namespace Avalonia.Controls.Utils
private IList? _items;
private bool _updatingItems;
private bool _updatingModel;
private bool _initializeOnSourceAssignment;
public SelectedItemsSync(ISelectionModel model)
{
@ -63,10 +65,18 @@ namespace Avalonia.Controls.Utils
_updatingModel = true;
_items = items;
using (Model.Update())
if (Model.Source is object)
{
Model.ClearSelection();
Add(items);
using (Model.Update())
{
Model.ClearSelection();
Add(items);
}
}
else if (!_initializeOnSourceAssignment)
{
Model.PropertyChanged += SelectionModelPropertyChanged;
_initializeOnSourceAssignment = true;
}
if (_items is INotifyCollectionChanged incc2)
@ -86,9 +96,11 @@ namespace Avalonia.Controls.Utils
if (_items != null)
{
Model.PropertyChanged -= SelectionModelPropertyChanged;
Model.SelectionChanged -= SelectionModelSelectionChanged;
Model = model;
Model.SelectionChanged += SelectionModelSelectionChanged;
_initializeOnSourceAssignment = false;
try
{
@ -175,6 +187,25 @@ namespace Avalonia.Controls.Utils
}
}
private void SelectionModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (_initializeOnSourceAssignment &&
_items != null &&
e.PropertyName == nameof(SelectionModel.Source))
{
try
{
_updatingModel = true;
Add(_items);
_initializeOnSourceAssignment = false;
}
finally
{
_updatingModel = false;
}
}
}
private void SelectionModelSelectionChanged(object sender, SelectionModelSelectionChangedEventArgs e)
{
if (_updatingModel)

2
src/Avalonia.Controls/Window.cs

@ -652,8 +652,8 @@ namespace Avalonia.Controls
PlatformImpl?.Show();
Renderer?.Start();
SetWindowStartupLocation(Owner?.PlatformImpl);
}
SetWindowStartupLocation(Owner?.PlatformImpl);
OnOpened(EventArgs.Empty);
}

11
src/Avalonia.Controls/WindowBase.cs

@ -39,6 +39,7 @@ namespace Avalonia.Controls
public static readonly StyledProperty<bool> TopmostProperty =
AvaloniaProperty.Register<WindowBase, bool>(nameof(Topmost));
private int _autoSizing;
private bool _hasExecutedInitialLayoutPass;
private bool _isActive;
private bool _ignoreVisibilityChange;
@ -97,11 +98,7 @@ namespace Avalonia.Controls
/// <summary>
/// Whether an auto-size operation is in progress.
/// </summary>
protected bool AutoSizing
{
get;
private set;
}
protected bool AutoSizing => _autoSizing > 0;
/// <summary>
/// Gets or sets the owner of the window.
@ -186,8 +183,8 @@ namespace Avalonia.Controls
/// </remarks>
protected IDisposable BeginAutoSizing()
{
AutoSizing = true;
return Disposable.Create(() => AutoSizing = false);
++_autoSizing;
return Disposable.Create(() => --_autoSizing);
}
/// <summary>

2
src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj

@ -9,6 +9,7 @@
<Version>0.7.0</Version>
<NoWarn>CS1591</NoWarn>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NugetPackageName>Avalonia</NugetPackageName>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Remote\HtmlTransport\webapp\build\**\*.gz" />
@ -26,4 +27,5 @@
<ProjectReference Include="..\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
</ItemGroup>
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project>

3
src/Avalonia.DesignerSupport/DesignWindowLoader.cs

@ -69,6 +69,8 @@ namespace Avalonia.DesignerSupport
window = new Window() {Content = (Control)control};
}
Design.ApplyDesignModeProperties(window, control);
if (!window.IsSet(Window.SizeToContentProperty))
{
if (double.IsNaN(window.Width))
@ -83,7 +85,6 @@ namespace Avalonia.DesignerSupport
}
}
window.Show();
Design.ApplyDesignModeProperties(window, control);
return window;
}
}

2
src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/webpack.config.js

@ -93,7 +93,7 @@ const config = {
plugins:
[
new Printer(),
new CleanWebpackPlugin([path.resolve(__dirname, 'build')]),
new CleanWebpackPlugin([path.resolve(__dirname, 'build')], { verbose: false }),
new MiniCssExtractPlugin({
filename: "[name].[chunkhash]h" +
".css",

2
src/Avalonia.Desktop/Avalonia.Desktop.csproj

@ -11,4 +11,6 @@
<ProjectReference Include="../../packages/Avalonia/Avalonia.csproj" />
<ProjectReference Include="../Avalonia.X11/Avalonia.X11.csproj" />
</ItemGroup>
<Import Project="..\..\build\ApiDiff.props" />
</Project>

1
src/Avalonia.DesktopRuntime/Avalonia.DesktopRuntime.csproj

@ -17,4 +17,5 @@
<Import Project="..\..\build\NetCore.props" />
<Import Project="..\..\build\NetFX.props" />
<Import Project="..\Shared\PlatformSupport\PlatformSupport.projitems" />
<Import Project="..\..\build\ApiDiff.props" />
</Project>

2
src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>Avalonia</RootNamespace>
<PackageId>Avalonia.Diagnostics</PackageId>
</PropertyGroup>
<ItemGroup>
<Compile Update="**\*.xaml.cs">
@ -28,4 +29,5 @@
<Import Project="..\..\build\EmbedXaml.props" />
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\build\ApiDiff.props" />
</Project>

2
src/Avalonia.Dialogs/Avalonia.Dialogs.csproj

@ -15,4 +15,6 @@
<ItemGroup>
<ProjectReference Include="..\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />
</ItemGroup>
<Import Project="..\..\build\ApiDiff.props" />
</Project>

4
src/Avalonia.Dialogs/ManagedFileChooser.xaml

@ -66,7 +66,7 @@
</StackPanel>
</DockPanel>
<DropDown DockPanel.Dock="Bottom"
<ComboBox DockPanel.Dock="Bottom"
IsVisible="{Binding ShowFilters}"
Items="{Binding Filters}"
SelectedItem="{Binding SelectedFilter}"
@ -76,7 +76,7 @@
<ListBox Margin="0 0 5 5" BorderBrush="Transparent" x:Name="QuickLinks" Items="{Binding QuickLinks}"
SelectedIndex="{Binding QuickLinksSelectedIndex}"
DockPanel.Dock="Left" Background="{DynamicResource ThemeControlMidBrush}" Focusable="False">
DockPanel.Dock="Left" Focusable="False">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Spacing="4" Orientation="Horizontal" Background="Transparent">

5
src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
@ -10,6 +10,5 @@
<ItemGroup>
<PackageReference Include="Tmds.DBus" Version="0.7.0" />
</ItemGroup>
</ItemGroup>
</Project>

3
src/Avalonia.Headless/Avalonia.Headless.csproj

@ -1,8 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\packages\Avalonia\Avalonia.csproj" />
</ItemGroup>
</ItemGroup>
</Project>

10
src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs

@ -21,7 +21,11 @@ namespace Avalonia.Headless
public IEnumerable<string> InstalledFontNames { get; } = new[] { "Tahoma" };
public bool SupportsIndividualRoundRects => throw new NotImplementedException();
public bool SupportsIndividualRoundRects => false;
public AlphaFormat DefaultAlphaFormat => AlphaFormat.Premul;
public PixelFormat DefaultPixelFormat => PixelFormat.Rgba8888;
public IFormattedTextImpl CreateFormattedText(string text, Typeface typeface, double fontSize, TextAlignment textAlignment, TextWrapping wrapping, Size constraint, IReadOnlyList<FormattedTextStyleSpan> spans)
{
@ -51,7 +55,7 @@ namespace Avalonia.Headless
return new HeadlessBitmapStub(size, dpi);
}
public IWriteableBitmapImpl CreateWriteableBitmap(PixelSize size, Vector dpi, PixelFormat? format = null)
public IWriteableBitmapImpl CreateWriteableBitmap(PixelSize size, Vector dpi, PixelFormat format, AlphaFormat alphaFormat)
{
return new HeadlessBitmapStub(size, dpi);
}
@ -66,7 +70,7 @@ namespace Avalonia.Headless
return new HeadlessBitmapStub(new Size(1, 1), new Vector(96, 96));
}
public IBitmapImpl LoadBitmap(PixelFormat format, IntPtr data, PixelSize size, Vector dpi, int stride)
public IBitmapImpl LoadBitmap(PixelFormat format, AlphaFormat alphaFormat, IntPtr data, PixelSize size, Vector dpi, int stride)
{
return new HeadlessBitmapStub(new Size(1, 1), new Vector(96, 96));
}

1
src/Avalonia.Input/Avalonia.Input.csproj

@ -10,4 +10,5 @@
<ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
</ItemGroup>
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project>

29
src/Avalonia.Input/InputExtensions.cs

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Linq;
using Avalonia.VisualTree;
#nullable enable
namespace Avalonia.Input
{
/// <summary>
@ -22,7 +24,7 @@ namespace Avalonia.Input
/// </returns>
public static IEnumerable<IInputElement> GetInputElementsAt(this IInputElement element, Point p)
{
Contract.Requires<ArgumentNullException>(element != null);
element = element ?? throw new ArgumentNullException(nameof(element));
return element.GetVisualsAt(p, s_hitTestDelegate).Cast<IInputElement>();
}
@ -33,13 +35,34 @@ namespace Avalonia.Input
/// <param name="element">The element to test.</param>
/// <param name="p">The point on <paramref name="element"/>.</param>
/// <returns>The topmost <see cref="IInputElement"/> at the specified position.</returns>
public static IInputElement InputHitTest(this IInputElement element, Point p)
public static IInputElement? InputHitTest(this IInputElement element, Point p)
{
Contract.Requires<ArgumentNullException>(element != null);
element = element ?? throw new ArgumentNullException(nameof(element));
return element.GetVisualAt(p, s_hitTestDelegate) as IInputElement;
}
/// <summary>
/// Returns the topmost active input element at a point on an <see cref="IInputElement"/>.
/// </summary>
/// <param name="element">The element to test.</param>
/// <param name="p">The point on <paramref name="element"/>.</param>
/// <param name="filter">
/// A filter predicate. If the predicate returns false then the visual and all its
/// children will be excluded from the results.
/// </param>
/// <returns>The topmost <see cref="IInputElement"/> at the specified position.</returns>
public static IInputElement? InputHitTest(
this IInputElement element,
Point p,
Func<IVisual, bool> filter)
{
element = element ?? throw new ArgumentNullException(nameof(element));
filter = filter ?? throw new ArgumentNullException(nameof(filter));
return element.GetVisualAt(p, x => s_hitTestDelegate(x) && filter(x)) as IInputElement;
}
private static bool IsHitTestVisible(IVisual visual)
{
var element = visual as IInputElement;

1
src/Avalonia.Interactivity/Avalonia.Interactivity.csproj

@ -11,4 +11,5 @@
<ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
</ItemGroup>
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project>

1
src/Avalonia.Layout/Avalonia.Layout.csproj

@ -8,4 +8,5 @@
<ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
</ItemGroup>
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project>

3
src/Avalonia.Native/Avalonia.Native.csproj

@ -7,6 +7,7 @@
<CastXmlPath Condition="Exists('/usr/bin/castxml')">/usr/bin/castxml</CastXmlPath>
<CastXmlPath Condition="Exists('/usr/local/bin/castxml')">/usr/local/bin/castxml</CastXmlPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<SharpGenGenerateConsumerBindMapping>false</SharpGenGenerateConsumerBindMapping>
</PropertyGroup>
<ItemGroup Condition="'$(Configuration)' == 'Release' AND '$([MSBuild]::IsOSPlatform(OSX))' == 'true'">
@ -18,7 +19,7 @@
</ItemGroup>
<ItemGroup>
<SharpGenMapping Include="Mappings.xml" />
<!--<SharpGenMapping Include="Mappings.xml" />-->
<PackageReference Include="SharpGenTools.Sdk" Version="1.2.1" PrivateAssets="all" />
<PackageReference Include="SharpGen.Runtime" Version="1.2.1" />
<PackageReference Include="SharpGen.Runtime.COM" Version="1.2.0" />

44
src/Avalonia.Native/AvaloniaNativeMenuExporter.cs

@ -11,7 +11,7 @@ namespace Avalonia.Native
class AvaloniaNativeMenuExporter : ITopLevelNativeMenuExporter
{
private IAvaloniaNativeFactory _factory;
private bool _resetQueued;
private bool _resetQueued = true;
private bool _exported = false;
private IAvnWindow _nativeWindow;
private NativeMenu _menu;
@ -39,8 +39,7 @@ namespace Avalonia.Native
public void SetNativeMenu(NativeMenu menu)
{
_menu = menu == null ? new NativeMenu() : menu;
DoLayoutReset();
DoLayoutReset(true);
}
internal void UpdateIfNeeded()
@ -74,31 +73,34 @@ namespace Avalonia.Native
return result;
}
void DoLayoutReset()
private void DoLayoutReset(bool forceUpdate = false)
{
_resetQueued = false;
if (_nativeWindow is null)
if (_resetQueued || forceUpdate)
{
var appMenu = NativeMenu.GetMenu(Application.Current);
_resetQueued = false;
if (appMenu == null)
if (_nativeWindow is null)
{
appMenu = CreateDefaultAppMenu();
NativeMenu.SetMenu(Application.Current, appMenu);
}
var appMenu = NativeMenu.GetMenu(Application.Current);
SetMenu(appMenu);
}
else
{
if (_menu != null)
if (appMenu == null)
{
appMenu = CreateDefaultAppMenu();
NativeMenu.SetMenu(Application.Current, appMenu);
}
SetMenu(appMenu);
}
else
{
SetMenu(_nativeWindow, _menu);
if (_menu != null)
{
SetMenu(_nativeWindow, _menu);
}
}
}
_exported = true;
_exported = true;
}
}
internal void QueueReset()
@ -106,7 +108,7 @@ namespace Avalonia.Native
if (_resetQueued)
return;
_resetQueued = true;
Dispatcher.UIThread.Post(DoLayoutReset, DispatcherPriority.Background);
Dispatcher.UIThread.Post(() => DoLayoutReset(), DispatcherPriority.Background);
}
private void SetMenu(NativeMenu menu)

628
src/Avalonia.Native/Generated/Enumerations.cs

@ -0,0 +1,628 @@
// <auto-generated/>
namespace Avalonia.Native.Interop
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnDragDropEffects</unmanaged>
/// <unmanaged-short>AvnDragDropEffects</unmanaged-short>
public enum AvnDragDropEffects : System.Int32
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>None</unmanaged>
/// <unmanaged-short>None</unmanaged-short>
None = unchecked ((System.Int32)(0)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Copy</unmanaged>
/// <unmanaged-short>Copy</unmanaged-short>
Copy = unchecked ((System.Int32)(1)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Move</unmanaged>
/// <unmanaged-short>Move</unmanaged-short>
Move = unchecked ((System.Int32)(2)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Link</unmanaged>
/// <unmanaged-short>Link</unmanaged-short>
Link = unchecked ((System.Int32)(4))}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnDragEventType</unmanaged>
/// <unmanaged-short>AvnDragEventType</unmanaged-short>
public enum AvnDragEventType : System.Int32
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Enter</unmanaged>
/// <unmanaged-short>Enter</unmanaged-short>
Enter = unchecked ((System.Int32)(0)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Over</unmanaged>
/// <unmanaged-short>Over</unmanaged-short>
Over = unchecked ((System.Int32)(1)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Leave</unmanaged>
/// <unmanaged-short>Leave</unmanaged-short>
Leave = unchecked ((System.Int32)(2)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Drop</unmanaged>
/// <unmanaged-short>Drop</unmanaged-short>
Drop = unchecked ((System.Int32)(3))}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnExtendClientAreaChromeHints</unmanaged>
/// <unmanaged-short>AvnExtendClientAreaChromeHints</unmanaged-short>
public enum AvnExtendClientAreaChromeHints : System.Int32
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnNoChrome</unmanaged>
/// <unmanaged-short>AvnNoChrome</unmanaged-short>
AvnNoChrome = unchecked ((System.Int32)(0)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnSystemChrome</unmanaged>
/// <unmanaged-short>AvnSystemChrome</unmanaged-short>
AvnSystemChrome = unchecked ((System.Int32)(1)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnPreferSystemChrome</unmanaged>
/// <unmanaged-short>AvnPreferSystemChrome</unmanaged-short>
AvnPreferSystemChrome = unchecked ((System.Int32)(2)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnOSXThickTitleBar</unmanaged>
/// <unmanaged-short>AvnOSXThickTitleBar</unmanaged-short>
AvnOSXThickTitleBar = unchecked ((System.Int32)(8)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnDefaultChrome</unmanaged>
/// <unmanaged-short>AvnDefaultChrome</unmanaged-short>
AvnDefaultChrome = unchecked ((System.Int32)(1))}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnInputModifiers</unmanaged>
/// <unmanaged-short>AvnInputModifiers</unmanaged-short>
public enum AvnInputModifiers : System.Int32
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnInputModifiersNone</unmanaged>
/// <unmanaged-short>AvnInputModifiersNone</unmanaged-short>
AvnInputModifiersNone = unchecked ((System.Int32)(0)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Alt</unmanaged>
/// <unmanaged-short>Alt</unmanaged-short>
Alt = unchecked ((System.Int32)(1)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Control</unmanaged>
/// <unmanaged-short>Control</unmanaged-short>
Control = unchecked ((System.Int32)(2)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Shift</unmanaged>
/// <unmanaged-short>Shift</unmanaged-short>
Shift = unchecked ((System.Int32)(4)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Windows</unmanaged>
/// <unmanaged-short>Windows</unmanaged-short>
Windows = unchecked ((System.Int32)(8)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>LeftMouseButton</unmanaged>
/// <unmanaged-short>LeftMouseButton</unmanaged-short>
LeftMouseButton = unchecked ((System.Int32)(16)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>RightMouseButton</unmanaged>
/// <unmanaged-short>RightMouseButton</unmanaged-short>
RightMouseButton = unchecked ((System.Int32)(32)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>MiddleMouseButton</unmanaged>
/// <unmanaged-short>MiddleMouseButton</unmanaged-short>
MiddleMouseButton = unchecked ((System.Int32)(64)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>XButton1MouseButton</unmanaged>
/// <unmanaged-short>XButton1MouseButton</unmanaged-short>
XButton1MouseButton = unchecked ((System.Int32)(128)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>XButton2MouseButton</unmanaged>
/// <unmanaged-short>XButton2MouseButton</unmanaged-short>
XButton2MouseButton = unchecked ((System.Int32)(256))}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnMenuItemToggleType</unmanaged>
/// <unmanaged-short>AvnMenuItemToggleType</unmanaged-short>
public enum AvnMenuItemToggleType : System.Int32
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>None</unmanaged>
/// <unmanaged-short>None</unmanaged-short>
None = unchecked ((System.Int32)(0)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CheckMark</unmanaged>
/// <unmanaged-short>CheckMark</unmanaged-short>
CheckMark = unchecked ((System.Int32)(1)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Radio</unmanaged>
/// <unmanaged-short>Radio</unmanaged-short>
Radio = unchecked ((System.Int32)(2))}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnPixelFormat</unmanaged>
/// <unmanaged-short>AvnPixelFormat</unmanaged-short>
public enum AvnPixelFormat : System.Int32
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>kAvnRgb565</unmanaged>
/// <unmanaged-short>kAvnRgb565</unmanaged-short>
KAvnRgb565 = unchecked ((System.Int32)(0)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>kAvnRgba8888</unmanaged>
/// <unmanaged-short>kAvnRgba8888</unmanaged-short>
KAvnRgba8888 = unchecked ((System.Int32)(1)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>kAvnBgra8888</unmanaged>
/// <unmanaged-short>kAvnBgra8888</unmanaged-short>
KAvnBgra8888 = unchecked ((System.Int32)(2))}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnRawKeyEventType</unmanaged>
/// <unmanaged-short>AvnRawKeyEventType</unmanaged-short>
public enum AvnRawKeyEventType : System.Int32
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>KeyDown</unmanaged>
/// <unmanaged-short>KeyDown</unmanaged-short>
KeyDown = unchecked ((System.Int32)(0)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>KeyUp</unmanaged>
/// <unmanaged-short>KeyUp</unmanaged-short>
KeyUp = unchecked ((System.Int32)(1))}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnRawMouseEventType</unmanaged>
/// <unmanaged-short>AvnRawMouseEventType</unmanaged-short>
public enum AvnRawMouseEventType : System.Int32
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>LeaveWindow</unmanaged>
/// <unmanaged-short>LeaveWindow</unmanaged-short>
LeaveWindow = unchecked ((System.Int32)(0)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>LeftButtonDown</unmanaged>
/// <unmanaged-short>LeftButtonDown</unmanaged-short>
LeftButtonDown = unchecked ((System.Int32)(1)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>LeftButtonUp</unmanaged>
/// <unmanaged-short>LeftButtonUp</unmanaged-short>
LeftButtonUp = unchecked ((System.Int32)(2)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>RightButtonDown</unmanaged>
/// <unmanaged-short>RightButtonDown</unmanaged-short>
RightButtonDown = unchecked ((System.Int32)(3)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>RightButtonUp</unmanaged>
/// <unmanaged-short>RightButtonUp</unmanaged-short>
RightButtonUp = unchecked ((System.Int32)(4)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>MiddleButtonDown</unmanaged>
/// <unmanaged-short>MiddleButtonDown</unmanaged-short>
MiddleButtonDown = unchecked ((System.Int32)(5)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>MiddleButtonUp</unmanaged>
/// <unmanaged-short>MiddleButtonUp</unmanaged-short>
MiddleButtonUp = unchecked ((System.Int32)(6)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>XButton1Down</unmanaged>
/// <unmanaged-short>XButton1Down</unmanaged-short>
XButton1Down = unchecked ((System.Int32)(7)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>XButton1Up</unmanaged>
/// <unmanaged-short>XButton1Up</unmanaged-short>
XButton1Up = unchecked ((System.Int32)(8)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>XButton2Down</unmanaged>
/// <unmanaged-short>XButton2Down</unmanaged-short>
XButton2Down = unchecked ((System.Int32)(9)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>XButton2Up</unmanaged>
/// <unmanaged-short>XButton2Up</unmanaged-short>
XButton2Up = unchecked ((System.Int32)(10)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Move</unmanaged>
/// <unmanaged-short>Move</unmanaged-short>
Move = unchecked ((System.Int32)(11)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Wheel</unmanaged>
/// <unmanaged-short>Wheel</unmanaged-short>
Wheel = unchecked ((System.Int32)(12)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>NonClientLeftButtonDown</unmanaged>
/// <unmanaged-short>NonClientLeftButtonDown</unmanaged-short>
NonClientLeftButtonDown = unchecked ((System.Int32)(13)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>TouchBegin</unmanaged>
/// <unmanaged-short>TouchBegin</unmanaged-short>
TouchBegin = unchecked ((System.Int32)(14)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>TouchUpdate</unmanaged>
/// <unmanaged-short>TouchUpdate</unmanaged-short>
TouchUpdate = unchecked ((System.Int32)(15)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>TouchEnd</unmanaged>
/// <unmanaged-short>TouchEnd</unmanaged-short>
TouchEnd = unchecked ((System.Int32)(16)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>TouchCancel</unmanaged>
/// <unmanaged-short>TouchCancel</unmanaged-short>
TouchCancel = unchecked ((System.Int32)(17))}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnStandardCursorType</unmanaged>
/// <unmanaged-short>AvnStandardCursorType</unmanaged-short>
public enum AvnStandardCursorType : System.Int32
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorArrow</unmanaged>
/// <unmanaged-short>CursorArrow</unmanaged-short>
CursorArrow = unchecked ((System.Int32)(0)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorIbeam</unmanaged>
/// <unmanaged-short>CursorIbeam</unmanaged-short>
CursorIbeam = unchecked ((System.Int32)(1)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorWait</unmanaged>
/// <unmanaged-short>CursorWait</unmanaged-short>
CursorWait = unchecked ((System.Int32)(2)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorCross</unmanaged>
/// <unmanaged-short>CursorCross</unmanaged-short>
CursorCross = unchecked ((System.Int32)(3)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorUpArrow</unmanaged>
/// <unmanaged-short>CursorUpArrow</unmanaged-short>
CursorUpArrow = unchecked ((System.Int32)(4)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorSizeWestEast</unmanaged>
/// <unmanaged-short>CursorSizeWestEast</unmanaged-short>
CursorSizeWestEast = unchecked ((System.Int32)(5)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorSizeNorthSouth</unmanaged>
/// <unmanaged-short>CursorSizeNorthSouth</unmanaged-short>
CursorSizeNorthSouth = unchecked ((System.Int32)(6)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorSizeAll</unmanaged>
/// <unmanaged-short>CursorSizeAll</unmanaged-short>
CursorSizeAll = unchecked ((System.Int32)(7)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorNo</unmanaged>
/// <unmanaged-short>CursorNo</unmanaged-short>
CursorNo = unchecked ((System.Int32)(8)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorHand</unmanaged>
/// <unmanaged-short>CursorHand</unmanaged-short>
CursorHand = unchecked ((System.Int32)(9)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorAppStarting</unmanaged>
/// <unmanaged-short>CursorAppStarting</unmanaged-short>
CursorAppStarting = unchecked ((System.Int32)(10)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorHelp</unmanaged>
/// <unmanaged-short>CursorHelp</unmanaged-short>
CursorHelp = unchecked ((System.Int32)(11)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorTopSide</unmanaged>
/// <unmanaged-short>CursorTopSide</unmanaged-short>
CursorTopSide = unchecked ((System.Int32)(12)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorBottomSize</unmanaged>
/// <unmanaged-short>CursorBottomSize</unmanaged-short>
CursorBottomSize = unchecked ((System.Int32)(13)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorLeftSide</unmanaged>
/// <unmanaged-short>CursorLeftSide</unmanaged-short>
CursorLeftSide = unchecked ((System.Int32)(14)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorRightSide</unmanaged>
/// <unmanaged-short>CursorRightSide</unmanaged-short>
CursorRightSide = unchecked ((System.Int32)(15)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorTopLeftCorner</unmanaged>
/// <unmanaged-short>CursorTopLeftCorner</unmanaged-short>
CursorTopLeftCorner = unchecked ((System.Int32)(16)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorTopRightCorner</unmanaged>
/// <unmanaged-short>CursorTopRightCorner</unmanaged-short>
CursorTopRightCorner = unchecked ((System.Int32)(17)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorBottomLeftCorner</unmanaged>
/// <unmanaged-short>CursorBottomLeftCorner</unmanaged-short>
CursorBottomLeftCorner = unchecked ((System.Int32)(18)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorBottomRightCorner</unmanaged>
/// <unmanaged-short>CursorBottomRightCorner</unmanaged-short>
CursorBottomRightCorner = unchecked ((System.Int32)(19)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorDragMove</unmanaged>
/// <unmanaged-short>CursorDragMove</unmanaged-short>
CursorDragMove = unchecked ((System.Int32)(20)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorDragCopy</unmanaged>
/// <unmanaged-short>CursorDragCopy</unmanaged-short>
CursorDragCopy = unchecked ((System.Int32)(21)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorDragLink</unmanaged>
/// <unmanaged-short>CursorDragLink</unmanaged-short>
CursorDragLink = unchecked ((System.Int32)(22)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>CursorNone</unmanaged>
/// <unmanaged-short>CursorNone</unmanaged-short>
CursorNone = unchecked ((System.Int32)(23))}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnWindowEdge</unmanaged>
/// <unmanaged-short>AvnWindowEdge</unmanaged-short>
public enum AvnWindowEdge : System.Int32
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>WindowEdgeNorthWest</unmanaged>
/// <unmanaged-short>WindowEdgeNorthWest</unmanaged-short>
WindowEdgeNorthWest = unchecked ((System.Int32)(0)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>WindowEdgeNorth</unmanaged>
/// <unmanaged-short>WindowEdgeNorth</unmanaged-short>
WindowEdgeNorth = unchecked ((System.Int32)(1)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>WindowEdgeNorthEast</unmanaged>
/// <unmanaged-short>WindowEdgeNorthEast</unmanaged-short>
WindowEdgeNorthEast = unchecked ((System.Int32)(2)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>WindowEdgeWest</unmanaged>
/// <unmanaged-short>WindowEdgeWest</unmanaged-short>
WindowEdgeWest = unchecked ((System.Int32)(3)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>WindowEdgeEast</unmanaged>
/// <unmanaged-short>WindowEdgeEast</unmanaged-short>
WindowEdgeEast = unchecked ((System.Int32)(4)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>WindowEdgeSouthWest</unmanaged>
/// <unmanaged-short>WindowEdgeSouthWest</unmanaged-short>
WindowEdgeSouthWest = unchecked ((System.Int32)(5)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>WindowEdgeSouth</unmanaged>
/// <unmanaged-short>WindowEdgeSouth</unmanaged-short>
WindowEdgeSouth = unchecked ((System.Int32)(6)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>WindowEdgeSouthEast</unmanaged>
/// <unmanaged-short>WindowEdgeSouthEast</unmanaged-short>
WindowEdgeSouthEast = unchecked ((System.Int32)(7))}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnWindowState</unmanaged>
/// <unmanaged-short>AvnWindowState</unmanaged-short>
public enum AvnWindowState : System.Int32
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Normal</unmanaged>
/// <unmanaged-short>Normal</unmanaged-short>
Normal = unchecked ((System.Int32)(0)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Minimized</unmanaged>
/// <unmanaged-short>Minimized</unmanaged-short>
Minimized = unchecked ((System.Int32)(1)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Maximized</unmanaged>
/// <unmanaged-short>Maximized</unmanaged-short>
Maximized = unchecked ((System.Int32)(2)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>FullScreen</unmanaged>
/// <unmanaged-short>FullScreen</unmanaged-short>
FullScreen = unchecked ((System.Int32)(3))}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>SystemDecorations</unmanaged>
/// <unmanaged-short>SystemDecorations</unmanaged-short>
public enum SystemDecorations : System.Int32
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>SystemDecorationsNone</unmanaged>
/// <unmanaged-short>SystemDecorationsNone</unmanaged-short>
SystemDecorationsNone = unchecked ((System.Int32)(0)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>SystemDecorationsBorderOnly</unmanaged>
/// <unmanaged-short>SystemDecorationsBorderOnly</unmanaged-short>
SystemDecorationsBorderOnly = unchecked ((System.Int32)(1)),
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>SystemDecorationsFull</unmanaged>
/// <unmanaged-short>SystemDecorationsFull</unmanaged-short>
SystemDecorationsFull = unchecked ((System.Int32)(2))}
}

5
src/Avalonia.Native/Generated/Functions.cs

@ -0,0 +1,5 @@
// <auto-generated/>
namespace Avalonia.Native.Interop
{
}

3092
src/Avalonia.Native/Generated/Interfaces.cs

File diff suppressed because it is too large

202
src/Avalonia.Native/Generated/LocalInterop.cs

@ -0,0 +1,202 @@
// <auto-generated/>
namespace Avalonia.Native
{
internal static partial class LocalInterop
{
public static unsafe int CalliThisCallint(void *thisObject, void *methodPtr)
{
throw null;
}
public static unsafe void CalliThisCallvoid(void *thisObject, void *methodPtr)
{
throw null;
}
public static unsafe void CalliThisCallvoid(void *thisObject, void *param0, void *methodPtr)
{
throw null;
}
public static unsafe void CalliThisCallvoid0(void *thisObject, Avalonia.Native.Interop.AvnPoint param0, void *methodPtr)
{
throw null;
}
public static unsafe void CalliThisCallvoid0(void *thisObject, int param0, System.UInt32 param1, int param2, Avalonia.Native.Interop.AvnPoint param3, Avalonia.Native.Interop.AvnVector param4, void *methodPtr)
{
throw null;
}
public static unsafe System.Byte CalliThisCallSystemByte(void *thisObject, int param0, System.UInt32 param1, int param2, System.UInt32 param3, void *methodPtr)
{
throw null;
}
public static unsafe System.Byte CalliThisCallSystemByte(void *thisObject, System.UInt32 param0, void *param1, void *methodPtr)
{
throw null;
}
public static unsafe void CalliThisCallvoid(void *thisObject, double param0, void *methodPtr)
{
throw null;
}
public static unsafe Avalonia.Native.Interop.AvnDragDropEffects CalliThisCallAvaloniaNativeInteropAvnDragDropEffects0(void *thisObject, int param0, Avalonia.Native.Interop.AvnPoint param1, int param2, int param3, void *param4, void *param5, void *methodPtr)
{
throw null;
}
public static unsafe System.Byte CalliThisCallSystemByte(void *thisObject, void *methodPtr)
{
throw null;
}
public static unsafe void CalliThisCallvoid(void *thisObject, int param0, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint(void *thisObject, void *param0, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint0(void *thisObject, Avalonia.Native.Interop.AvnSize param0, Avalonia.Native.Interop.AvnSize param1, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint(void *thisObject, double param0, double param1, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint0(void *thisObject, Avalonia.Native.Interop.AvnRect param0, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint(void *thisObject, int param0, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint0(void *thisObject, Avalonia.Native.Interop.AvnPoint param0, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint0(void *thisObject, Avalonia.Native.Interop.AvnPoint param0, void *param1, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint(void *thisObject, void *param0, void *param1, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint(void *thisObject, System.Byte param0, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint0(void *thisObject, int param0, Avalonia.Native.Interop.AvnPoint param1, void *param2, void *param3, void *param4, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint0(void *thisObject, Avalonia.Native.Interop.AvnColor param0, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint(void *thisObject, double param0, void *methodPtr)
{
throw null;
}
public static unsafe System.IntPtr CalliThisCallSystemIntPtr(void *thisObject, void *methodPtr)
{
throw null;
}
public static unsafe System.IntPtr CalliThisCallSystemIntPtr(void *thisObject, int param0, int param1, void *param2, void *methodPtr)
{
throw null;
}
public static unsafe void CalliThisCallvoid(void *thisObject, int param0, void *param1, void *methodPtr)
{
throw null;
}
public static unsafe void CalliThisCallvoid(void *thisObject, void *param0, void *param1, void *param2, void *param3, void *methodPtr)
{
throw null;
}
public static unsafe void CalliThisCallvoid(void *thisObject, void *param0, void *param1, System.Byte param2, void *param3, void *param4, void *param5, void *param6, void *methodPtr)
{
throw null;
}
public static unsafe void CalliThisCallvoid(void *thisObject, void *param0, void *param1, void *param2, void *param3, void *param4, void *param5, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint(void *thisObject, int param0, void *param1, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint(void *thisObject, void *param0, void *param1, int param2, void *methodPtr)
{
throw null;
}
public static unsafe System.IntPtr CalliThisCallSystemIntPtr(void *thisObject, void *param0, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint(void *thisObject, void *param0, int param1, void *methodPtr)
{
throw null;
}
public static unsafe System.UInt32 CalliThisCallSystemUInt32(void *thisObject, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint(void *thisObject, System.UInt32 param0, void *param1, void *methodPtr)
{
throw null;
}
public static unsafe void CalliThisCallvoid(void *thisObject, float param0, float param1, float param2, float param3, void *methodPtr)
{
throw null;
}
public static unsafe void CalliThisCallvoid(void *thisObject, float param0, float param1, void *methodPtr)
{
throw null;
}
public static unsafe int CalliThisCallint(void *thisObject, void *param0, void *param1, void *param2, void *methodPtr)
{
throw null;
}
public static unsafe void CalliThisCallvoid(void *thisObject, int param0, System.Byte param1, void *methodPtr)
{
throw null;
}
}
}

246
src/Avalonia.Native/Generated/Structures.cs

@ -0,0 +1,246 @@
// <auto-generated/>
namespace Avalonia.Native.Interop
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnColor</unmanaged>
/// <unmanaged-short>AvnColor</unmanaged-short>
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
public partial struct AvnColor
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Alpha</unmanaged>
/// <unmanaged-short>Alpha</unmanaged-short>
public System.Byte Alpha;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Red</unmanaged>
/// <unmanaged-short>Red</unmanaged-short>
public System.Byte Red;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Green</unmanaged>
/// <unmanaged-short>Green</unmanaged-short>
public System.Byte Green;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Blue</unmanaged>
/// <unmanaged-short>Blue</unmanaged-short>
public System.Byte Blue;
}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnFramebuffer</unmanaged>
/// <unmanaged-short>AvnFramebuffer</unmanaged-short>
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
public partial struct AvnFramebuffer
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Data</unmanaged>
/// <unmanaged-short>Data</unmanaged-short>
public System.IntPtr Data;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Width</unmanaged>
/// <unmanaged-short>Width</unmanaged-short>
public System.Int32 Width;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Height</unmanaged>
/// <unmanaged-short>Height</unmanaged-short>
public System.Int32 Height;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Stride</unmanaged>
/// <unmanaged-short>Stride</unmanaged-short>
public System.Int32 Stride;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Dpi</unmanaged>
/// <unmanaged-short>Dpi</unmanaged-short>
public Avalonia.Native.Interop.AvnVector Dpi;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>PixelFormat</unmanaged>
/// <unmanaged-short>PixelFormat</unmanaged-short>
public Avalonia.Native.Interop.AvnPixelFormat PixelFormat;
}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnPixelSize</unmanaged>
/// <unmanaged-short>AvnPixelSize</unmanaged-short>
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
public partial struct AvnPixelSize
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Width</unmanaged>
/// <unmanaged-short>Width</unmanaged-short>
public System.Int32 Width;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Height</unmanaged>
/// <unmanaged-short>Height</unmanaged-short>
public System.Int32 Height;
}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnPoint</unmanaged>
/// <unmanaged-short>AvnPoint</unmanaged-short>
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
public partial struct AvnPoint
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>X</unmanaged>
/// <unmanaged-short>X</unmanaged-short>
public System.Double X;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Y</unmanaged>
/// <unmanaged-short>Y</unmanaged-short>
public System.Double Y;
}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnRect</unmanaged>
/// <unmanaged-short>AvnRect</unmanaged-short>
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
public partial struct AvnRect
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>X</unmanaged>
/// <unmanaged-short>X</unmanaged-short>
public System.Double X;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Y</unmanaged>
/// <unmanaged-short>Y</unmanaged-short>
public System.Double Y;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Width</unmanaged>
/// <unmanaged-short>Width</unmanaged-short>
public System.Double Width;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Height</unmanaged>
/// <unmanaged-short>Height</unmanaged-short>
public System.Double Height;
}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnScreen</unmanaged>
/// <unmanaged-short>AvnScreen</unmanaged-short>
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
public partial struct AvnScreen
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Bounds</unmanaged>
/// <unmanaged-short>Bounds</unmanaged-short>
public Avalonia.Native.Interop.AvnRect Bounds;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>WorkingArea</unmanaged>
/// <unmanaged-short>WorkingArea</unmanaged-short>
public Avalonia.Native.Interop.AvnRect WorkingArea;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>PixelDensity</unmanaged>
/// <unmanaged-short>PixelDensity</unmanaged-short>
public System.Single PixelDensity;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Primary</unmanaged>
/// <unmanaged-short>Primary</unmanaged-short>
public bool Primary
{
get => 0 != _Primary;
set => _Primary = (System.Byte)(value ? 1 : 0);
}
internal System.Byte _Primary;
}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnSize</unmanaged>
/// <unmanaged-short>AvnSize</unmanaged-short>
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
public partial struct AvnSize
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Width</unmanaged>
/// <unmanaged-short>Width</unmanaged-short>
public System.Double Width;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Height</unmanaged>
/// <unmanaged-short>Height</unmanaged-short>
public System.Double Height;
}
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>AvnVector</unmanaged>
/// <unmanaged-short>AvnVector</unmanaged-short>
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
public partial struct AvnVector
{
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>X</unmanaged>
/// <unmanaged-short>X</unmanaged-short>
public System.Double X;
/// <summary>
/// No documentation.
/// </summary>
/// <unmanaged>Y</unmanaged>
/// <unmanaged-short>Y</unmanaged-short>
public System.Double Y;
}
}

10
src/Avalonia.Native/WindowImplBase.cs

@ -300,7 +300,15 @@ namespace Avalonia.Native
public IRenderer CreateRenderer(IRenderRoot root)
{
if (_deferredRendering)
return new DeferredRenderer(root, AvaloniaLocator.Current.GetService<IRenderLoop>());
{
var loop = AvaloniaLocator.Current.GetService<IRenderLoop>();
var customRendererFactory = AvaloniaLocator.Current.GetService<IRendererFactory>();
if (customRendererFactory != null)
return customRendererFactory.Create(root, loop);
return new DeferredRenderer(root, loop);
}
return new ImmediateRenderer(root);
}

3
src/Avalonia.OpenGL/Avalonia.OpenGL.csproj

@ -9,6 +9,5 @@
<ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
<ProjectReference Include="..\Avalonia.Controls\Avalonia.Controls.csproj" />
<ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
</ItemGroup>
</ItemGroup>
</Project>

4
src/Avalonia.ReactiveUI/AutoDataTemplateBindingHook.cs

@ -48,6 +48,10 @@ namespace Avalonia.ReactiveUI
if (itemsControl.ItemTemplate != null)
return true;
if (itemsControl.DataTemplates != null &&
itemsControl.DataTemplates.Count > 0)
return true;
itemsControl.ItemTemplate = DefaultItemTemplate;
return true;
}

1
src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj

@ -8,4 +8,5 @@
</ItemGroup>
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\ReactiveUI.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project>

22
src/Avalonia.ReactiveUI/RoutedViewHost.cs

@ -65,8 +65,15 @@ namespace Avalonia.ReactiveUI
{
this.WhenActivated(disposables =>
{
this.WhenAnyObservable(x => x.Router.CurrentViewModel)
.DistinctUntilChanged()
var routerRemoved = this
.WhenAnyValue(x => x.Router)
.Where(router => router == null)
.Cast<object>();
this.WhenAnyValue(x => x.Router)
.Where(router => router != null)
.SelectMany(router => router.CurrentViewModel)
.Merge(routerRemoved)
.Subscribe(NavigateToViewModel)
.DisposeWith(disposables);
});
@ -92,6 +99,13 @@ namespace Avalonia.ReactiveUI
/// <param name="viewModel">ViewModel to which the user navigates.</param>
private void NavigateToViewModel(object viewModel)
{
if (Router == null)
{
this.Log().Warn("Router property is null. Falling back to default content.");
Content = DefaultContent;
return;
}
if (viewModel == null)
{
this.Log().Info("ViewModel is null. Falling back to default content.");
@ -110,8 +124,8 @@ namespace Avalonia.ReactiveUI
this.Log().Info($"Ready to show {viewInstance} with autowired {viewModel}.");
viewInstance.ViewModel = viewModel;
if (viewInstance is IStyledElement styled)
styled.DataContext = viewModel;
if (viewInstance is IDataContextProvider provider)
provider.DataContext = viewModel;
Content = viewInstance;
}
}

2
src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj

@ -4,8 +4,10 @@
<DefineConstants>AVALONIA_REMOTE_PROTOCOL;$(DefineConstants)</DefineConstants>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Key.snk</AssemblyOriginatorKeyFile>
<PackageId>Avalonia.Remote.Protocol</PackageId>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Avalonia.Input\Key.cs" />
</ItemGroup>
<Import Project="..\..\build\ApiDiff.props" />
</Project>

1
src/Avalonia.Styling/Avalonia.Styling.csproj

@ -8,4 +8,5 @@
<ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />
<ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
</ItemGroup>
<Import Project="..\..\build\ApiDiff.props" />
</Project>

2
src/Avalonia.Styling/Styling/PropertySetterBindingInstance.cs

@ -164,7 +164,7 @@ namespace Avalonia.Styling
private void ConvertAndPublishNext(object? value)
{
_value = value is T v ? v : BindingValue<T>.FromUntyped(value);
_value = BindingValue<T>.FromUntyped(value);
if (_isActive)
{

5
src/Avalonia.Themes.Default/Accents/BaseDark.xaml

@ -58,6 +58,11 @@
<SolidColorBrush x:Key="NotificationCardWarningBackgroundBrush" Color="#FDB328" Opacity="0.75"/>
<SolidColorBrush x:Key="NotificationCardErrorBackgroundBrush" Color="#BD202C" Opacity="0.75"/>
<SolidColorBrush x:Key="DatePickerFlyoutPresenterHighlightFill" Color="{DynamicResource ThemeAccentColor}" Opacity="0.4" />
<SolidColorBrush x:Key="TimePickerFlyoutPresenterHighlightFill" Color="{DynamicResource ThemeAccentColor}" Opacity="0.4" />
<SolidColorBrush x:Key="ThemeControlTransparentBrush" Color="Transparent" />
<Thickness x:Key="ThemeBorderThickness">1,1,1,1</Thickness>
<sys:Double x:Key="ThemeDisabledOpacity">0.5</sys:Double>

5
src/Avalonia.Themes.Default/Accents/BaseLight.xaml

@ -61,6 +61,11 @@
<SolidColorBrush x:Key="NotificationCardWarningBackgroundBrush" Color="#FDB328" Opacity="0.75"/>
<SolidColorBrush x:Key="NotificationCardErrorBackgroundBrush" Color="#BD202C" Opacity="0.75"/>
<SolidColorBrush x:Key="DatePickerFlyoutPresenterHighlightFill" Color="{DynamicResource ThemeAccentColor}" Opacity="0.4" />
<SolidColorBrush x:Key="TimePickerFlyoutPresenterHighlightFill" Color="{DynamicResource ThemeAccentColor}" Opacity="0.4" />
<SolidColorBrush x:Key="ThemeControlTransparentBrush" Color="Transparent" />
<Thickness x:Key="ThemeBorderThickness">1</Thickness>
<sys:Double x:Key="ThemeDisabledOpacity">0.5</sys:Double>

2
src/Avalonia.Themes.Default/AutoCompleteBox.xaml

@ -19,7 +19,7 @@
MinWidth="{Binding Bounds.Width, RelativeSource={RelativeSource TemplatedParent}}"
MaxHeight="{TemplateBinding MaxDropDownHeight}"
PlacementTarget="{TemplateBinding}"
StaysOpen="False">
IsLightDismissEnabled="True">
<Border BorderBrush="{DynamicResource ThemeBorderMidBrush}"
BorderThickness="1">
<ListBox Name="PART_SelectingItemsControl"

1
src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj

@ -19,4 +19,5 @@
</ItemGroup>
<Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project>

14
src/Avalonia.Themes.Default/ComboBox.xaml

@ -1,4 +1,5 @@
<Styles xmlns="https://github.com/avaloniaui">
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Design.PreviewWith>
<Border Padding="20">
<StackPanel Spacing="10">
@ -24,6 +25,7 @@
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Padding" Value="4" />
<Setter Property="MinHeight" Value="20" />
<Setter Property="PlaceholderForeground" Value="{DynamicResource ThemeForegroundBrush}" />
<Setter Property="Template">
<ControlTemplate>
<Border Name="border"
@ -31,6 +33,14 @@
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid ColumnDefinitions="*,Auto">
<TextBlock Name="PlaceholderTextBlock"
Grid.Column="0"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}"
Text="{TemplateBinding PlaceholderText}"
Foreground="{TemplateBinding PlaceholderForeground}"
IsVisible="{TemplateBinding SelectionBoxItem, Converter={x:Static ObjectConverters.IsNull}}" />
<ContentControl Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding ItemTemplate}"
Margin="{TemplateBinding Padding}"
@ -56,7 +66,7 @@
MinWidth="{Binding Bounds.Width, RelativeSource={RelativeSource TemplatedParent}}"
MaxHeight="{TemplateBinding MaxDropDownHeight}"
PlacementTarget="{TemplateBinding}"
StaysOpen="False">
IsLightDismissEnabled="True">
<Border BorderBrush="{DynamicResource ThemeBorderMidBrush}"
BorderThickness="1">
<ScrollViewer>

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

Loading…
Cancel
Save