diff --git a/Avalonia.sln b/Avalonia.sln
index 38f8e5f720..e8d5034fb0 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -206,6 +206,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.FreeDesktop", "src
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Controls.DataGrid.UnitTests", "tests\Avalonia.Controls.DataGrid.UnitTests\Avalonia.Controls.DataGrid.UnitTests.csproj", "{351337F5-D66F-461B-A957-4EF60BDB4BA6}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Themes.Fluent", "src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj", "{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}"
+EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
@@ -1921,6 +1923,30 @@ Global
{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Release|iPhone.Build.0 = Release|Any CPU
{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|iPhone.Build.0 = Release|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/build/CoreLibraries.props b/build/CoreLibraries.props
index d61268173d..2b54ee3f56 100644
--- a/build/CoreLibraries.props
+++ b/build/CoreLibraries.props
@@ -11,6 +11,7 @@
+
diff --git a/samples/ControlCatalog/App.xaml b/samples/ControlCatalog/App.xaml
index e40509dfda..20ca291910 100644
--- a/samples/ControlCatalog/App.xaml
+++ b/samples/ControlCatalog/App.xaml
@@ -4,7 +4,7 @@
-
+
diff --git a/src/Avalonia.Themes.Fluent/Accents/BaseDark.xaml b/src/Avalonia.Themes.Fluent/Accents/BaseDark.xaml
new file mode 100644
index 0000000000..44318ffa8f
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Accents/BaseDark.xaml
@@ -0,0 +1,352 @@
+
diff --git a/src/Avalonia.Themes.Fluent/Accents/BaseLight.xaml b/src/Avalonia.Themes.Fluent/Accents/BaseLight.xaml
new file mode 100644
index 0000000000..e43a7ab4e7
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Accents/BaseLight.xaml
@@ -0,0 +1,351 @@
+
diff --git a/src/Avalonia.Themes.Fluent/Accents/FluentBaseDark.xaml b/src/Avalonia.Themes.Fluent/Accents/FluentBaseDark.xaml
new file mode 100644
index 0000000000..7a715bbde7
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Accents/FluentBaseDark.xaml
@@ -0,0 +1,316 @@
+
diff --git a/src/Avalonia.Themes.Fluent/Accents/FluentBaseLight.xaml b/src/Avalonia.Themes.Fluent/Accents/FluentBaseLight.xaml
new file mode 100644
index 0000000000..5c6286a0bc
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Accents/FluentBaseLight.xaml
@@ -0,0 +1,317 @@
+
diff --git a/src/Avalonia.Themes.Fluent/Accents/FluentControlResourcesDark.xaml b/src/Avalonia.Themes.Fluent/Accents/FluentControlResourcesDark.xaml
new file mode 100644
index 0000000000..7364c339f1
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Accents/FluentControlResourcesDark.xaml
@@ -0,0 +1,347 @@
+
diff --git a/src/Avalonia.Themes.Fluent/Accents/FluentControlResourcesLight.xaml b/src/Avalonia.Themes.Fluent/Accents/FluentControlResourcesLight.xaml
new file mode 100644
index 0000000000..15e157f573
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Accents/FluentControlResourcesLight.xaml
@@ -0,0 +1,347 @@
+
diff --git a/src/Avalonia.Themes.Fluent/Accents/FluentDark.xaml b/src/Avalonia.Themes.Fluent/Accents/FluentDark.xaml
new file mode 100644
index 0000000000..5b6da70233
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Accents/FluentDark.xaml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/Accents/FluentLight.xaml b/src/Avalonia.Themes.Fluent/Accents/FluentLight.xaml
new file mode 100644
index 0000000000..5825a2bf34
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Accents/FluentLight.xaml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/AutoCompleteBox.xaml b/src/Avalonia.Themes.Fluent/AutoCompleteBox.xaml
new file mode 100644
index 0000000000..44e7962e17
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/AutoCompleteBox.xaml
@@ -0,0 +1,71 @@
+
+
+
+
+
+ Alabama
+ Alaska
+ Arizona
+ Arkansas
+ California
+ Colorado
+ Connecticut
+ Delaware
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj b/src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj
new file mode 100644
index 0000000000..3c3e14010d
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj
@@ -0,0 +1,22 @@
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/Button.xaml b/src/Avalonia.Themes.Fluent/Button.xaml
new file mode 100644
index 0000000000..42fcee6cd5
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Button.xaml
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+ 8,5,8,6
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/ButtonSpinner.xaml b/src/Avalonia.Themes.Fluent/ButtonSpinner.xaml
new file mode 100644
index 0000000000..89fbb9d64d
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/ButtonSpinner.xaml
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/Calendar.xaml b/src/Avalonia.Themes.Fluent/Calendar.xaml
new file mode 100644
index 0000000000..6bbee4ef17
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Calendar.xaml
@@ -0,0 +1,31 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Avalonia.Themes.Fluent/CalendarButton.xaml b/src/Avalonia.Themes.Fluent/CalendarButton.xaml
new file mode 100644
index 0000000000..3314534b3b
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/CalendarButton.xaml
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/CalendarDayButton.xaml b/src/Avalonia.Themes.Fluent/CalendarDayButton.xaml
new file mode 100644
index 0000000000..2d79e62a75
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/CalendarDayButton.xaml
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/CalendarItem.xaml b/src/Avalonia.Themes.Fluent/CalendarItem.xaml
new file mode 100644
index 0000000000..dfd89ed82f
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/CalendarItem.xaml
@@ -0,0 +1,183 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/Carousel.xaml b/src/Avalonia.Themes.Fluent/Carousel.xaml
new file mode 100644
index 0000000000..955a49a974
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Carousel.xaml
@@ -0,0 +1,16 @@
+
diff --git a/src/Avalonia.Themes.Fluent/CheckBox.xaml b/src/Avalonia.Themes.Fluent/CheckBox.xaml
new file mode 100644
index 0000000000..d1d7f36478
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/CheckBox.xaml
@@ -0,0 +1,294 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/ComboBox.xaml b/src/Avalonia.Themes.Fluent/ComboBox.xaml
new file mode 100644
index 0000000000..1fc657c1a3
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/ComboBox.xaml
@@ -0,0 +1,192 @@
+
+
+
+
+
+ Item 1
+ Item 2
+
+
+
+ Item 1
+ Item 2
+
+
+
+
+
+ 0,0,0,4
+ 15
+ 7
+
+ 12,5,0,7
+ 11,5,32,6
+ 32
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/ComboBoxItem.xaml b/src/Avalonia.Themes.Fluent/ComboBoxItem.xaml
new file mode 100644
index 0000000000..c26dec3d34
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/ComboBoxItem.xaml
@@ -0,0 +1,59 @@
+
+
+
+
+
+ Item 1
+ Item 2
+
+
+
+ Item 1
+ Item 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/ContentControl.xaml b/src/Avalonia.Themes.Fluent/ContentControl.xaml
new file mode 100644
index 0000000000..d76eecee84
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/ContentControl.xaml
@@ -0,0 +1,15 @@
+
\ No newline at end of file
diff --git a/src/Avalonia.Themes.Fluent/ContextMenu.xaml b/src/Avalonia.Themes.Fluent/ContextMenu.xaml
new file mode 100644
index 0000000000..75f8f7c23d
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/ContextMenu.xaml
@@ -0,0 +1,23 @@
+
diff --git a/src/Avalonia.Themes.Fluent/DataValidationErrors.xaml b/src/Avalonia.Themes.Fluent/DataValidationErrors.xaml
new file mode 100644
index 0000000000..f4145a51f5
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/DataValidationErrors.xaml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/DatePicker.xaml b/src/Avalonia.Themes.Fluent/DatePicker.xaml
new file mode 100644
index 0000000000..7adb1c2d5f
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/DatePicker.xaml
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/EmbeddableControlRoot.xaml b/src/Avalonia.Themes.Fluent/EmbeddableControlRoot.xaml
new file mode 100644
index 0000000000..9ffe51fae8
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/EmbeddableControlRoot.xaml
@@ -0,0 +1,19 @@
+
diff --git a/src/Avalonia.Themes.Fluent/Expander.xaml b/src/Avalonia.Themes.Fluent/Expander.xaml
new file mode 100644
index 0000000000..d63f785e77
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Expander.xaml
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/FluentTheme.xaml b/src/Avalonia.Themes.Fluent/FluentTheme.xaml
new file mode 100644
index 0000000000..266acce971
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/FluentTheme.xaml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/FluentTheme.xaml.cs b/src/Avalonia.Themes.Fluent/FluentTheme.xaml.cs
new file mode 100644
index 0000000000..9c65a7227c
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/FluentTheme.xaml.cs
@@ -0,0 +1,12 @@
+using Avalonia.Markup.Xaml;
+using Avalonia.Styling;
+
+namespace Avalonia.Themes.Fluent
+{
+ ///
+ /// The default Avalonia theme.
+ ///
+ public class FluentTheme : Styles
+ {
+ }
+}
diff --git a/src/Avalonia.Themes.Fluent/FocusAdorner.xaml b/src/Avalonia.Themes.Fluent/FocusAdorner.xaml
new file mode 100644
index 0000000000..2d5e369573
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/FocusAdorner.xaml
@@ -0,0 +1,10 @@
+
diff --git a/src/Avalonia.Themes.Fluent/GridSplitter.xaml b/src/Avalonia.Themes.Fluent/GridSplitter.xaml
new file mode 100644
index 0000000000..dc5cd002dc
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/GridSplitter.xaml
@@ -0,0 +1,23 @@
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/InverseBooleanValueConverter.cs b/src/Avalonia.Themes.Fluent/InverseBooleanValueConverter.cs
new file mode 100644
index 0000000000..20bade2a67
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/InverseBooleanValueConverter.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Globalization;
+using Avalonia.Data.Converters;
+
+namespace Avalonia.Themes.Fluent
+{
+ class InverseBooleanValueConverter : IValueConverter
+ {
+ public bool Default { get; set; }
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return value is bool b ? !b : Default;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return value is bool b ? !b : !Default;
+ }
+ }
+}
diff --git a/src/Avalonia.Themes.Fluent/ItemsControl.xaml b/src/Avalonia.Themes.Fluent/ItemsControl.xaml
new file mode 100644
index 0000000000..8bb0fc297c
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/ItemsControl.xaml
@@ -0,0 +1,15 @@
+
diff --git a/src/Avalonia.Themes.Fluent/ListBox.xaml b/src/Avalonia.Themes.Fluent/ListBox.xaml
new file mode 100644
index 0000000000..7a87387de8
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/ListBox.xaml
@@ -0,0 +1,43 @@
+
+
+
+
+ Test
+ Test
+ Test
+ Test
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/ListBoxItem.xaml b/src/Avalonia.Themes.Fluent/ListBoxItem.xaml
new file mode 100644
index 0000000000..430d3c5468
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/ListBoxItem.xaml
@@ -0,0 +1,97 @@
+
+
+
+
+ Disabled
+ Test
+ Test
+
+
+
+
+ 12,9,12,12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/Menu.xaml b/src/Avalonia.Themes.Fluent/Menu.xaml
new file mode 100644
index 0000000000..a1a5afb4a9
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Menu.xaml
@@ -0,0 +1,16 @@
+
\ No newline at end of file
diff --git a/src/Avalonia.Themes.Fluent/MenuItem.xaml b/src/Avalonia.Themes.Fluent/MenuItem.xaml
new file mode 100644
index 0000000000..314416cda0
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/MenuItem.xaml
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/NativeMenuBar.xaml b/src/Avalonia.Themes.Fluent/NativeMenuBar.xaml
new file mode 100644
index 0000000000..799fe6ffe4
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/NativeMenuBar.xaml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/NotificationCard.xaml b/src/Avalonia.Themes.Fluent/NotificationCard.xaml
new file mode 100644
index 0000000000..47d5988e8c
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/NotificationCard.xaml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/NumericUpDown.xaml b/src/Avalonia.Themes.Fluent/NumericUpDown.xaml
new file mode 100644
index 0000000000..24cbb62908
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/NumericUpDown.xaml
@@ -0,0 +1,38 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/Avalonia.Themes.Fluent/OverlayPopupHost.xaml b/src/Avalonia.Themes.Fluent/OverlayPopupHost.xaml
new file mode 100644
index 0000000000..36dbc1b761
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/OverlayPopupHost.xaml
@@ -0,0 +1,17 @@
+
diff --git a/src/Avalonia.Themes.Fluent/PopupRoot.xaml b/src/Avalonia.Themes.Fluent/PopupRoot.xaml
new file mode 100644
index 0000000000..25c71e3493
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/PopupRoot.xaml
@@ -0,0 +1,21 @@
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/ProgressBar.xaml b/src/Avalonia.Themes.Fluent/ProgressBar.xaml
new file mode 100644
index 0000000000..d3c2f0c784
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/ProgressBar.xaml
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/RadioButton.xaml b/src/Avalonia.Themes.Fluent/RadioButton.xaml
new file mode 100644
index 0000000000..23bcfc616a
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/RadioButton.xaml
@@ -0,0 +1,173 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/RepeatButton.xaml b/src/Avalonia.Themes.Fluent/RepeatButton.xaml
new file mode 100644
index 0000000000..702e4e6ebd
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/RepeatButton.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/ScrollBar.xaml b/src/Avalonia.Themes.Fluent/ScrollBar.xaml
new file mode 100644
index 0000000000..0f8fa4986d
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/ScrollBar.xaml
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/ScrollViewer.xaml b/src/Avalonia.Themes.Fluent/ScrollViewer.xaml
new file mode 100644
index 0000000000..1d893133e1
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/ScrollViewer.xaml
@@ -0,0 +1,47 @@
+
diff --git a/src/Avalonia.Themes.Fluent/Separator.xaml b/src/Avalonia.Themes.Fluent/Separator.xaml
new file mode 100644
index 0000000000..cf0db16ee6
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Separator.xaml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/Slider.xaml b/src/Avalonia.Themes.Fluent/Slider.xaml
new file mode 100644
index 0000000000..b21cbf3650
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Slider.xaml
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/TabControl.xaml b/src/Avalonia.Themes.Fluent/TabControl.xaml
new file mode 100644
index 0000000000..ed2e67df28
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/TabControl.xaml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/TabItem.xaml b/src/Avalonia.Themes.Fluent/TabItem.xaml
new file mode 100644
index 0000000000..92482a564c
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/TabItem.xaml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/TabStrip.xaml b/src/Avalonia.Themes.Fluent/TabStrip.xaml
new file mode 100644
index 0000000000..29ca1e7c94
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/TabStrip.xaml
@@ -0,0 +1,20 @@
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/TabStripItem.xaml b/src/Avalonia.Themes.Fluent/TabStripItem.xaml
new file mode 100644
index 0000000000..28c4c68a3d
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/TabStripItem.xaml
@@ -0,0 +1,23 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/Avalonia.Themes.Fluent/TextBox.xaml b/src/Avalonia.Themes.Fluent/TextBox.xaml
new file mode 100644
index 0000000000..e89cf2b49c
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/TextBox.xaml
@@ -0,0 +1,152 @@
+
+
+ 0,0,0,4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/ToggleButton.xaml b/src/Avalonia.Themes.Fluent/ToggleButton.xaml
new file mode 100644
index 0000000000..9e05c38eef
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/ToggleButton.xaml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Avalonia.Themes.Fluent/ToolTip.xaml b/src/Avalonia.Themes.Fluent/ToolTip.xaml
new file mode 100644
index 0000000000..1fc0202dd3
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/ToolTip.xaml
@@ -0,0 +1,17 @@
+
\ No newline at end of file
diff --git a/src/Avalonia.Themes.Fluent/TreeView.xaml b/src/Avalonia.Themes.Fluent/TreeView.xaml
new file mode 100644
index 0000000000..6ed2fd17b8
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/TreeView.xaml
@@ -0,0 +1,23 @@
+
diff --git a/src/Avalonia.Themes.Fluent/TreeViewItem.xaml b/src/Avalonia.Themes.Fluent/TreeViewItem.xaml
new file mode 100644
index 0000000000..a3f8d8b7f7
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/TreeViewItem.xaml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/UserControl.xaml b/src/Avalonia.Themes.Fluent/UserControl.xaml
new file mode 100644
index 0000000000..f4d0c21367
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/UserControl.xaml
@@ -0,0 +1,15 @@
+
diff --git a/src/Avalonia.Themes.Fluent/Window.xaml b/src/Avalonia.Themes.Fluent/Window.xaml
new file mode 100644
index 0000000000..aee15347eb
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/Window.xaml
@@ -0,0 +1,22 @@
+
diff --git a/src/Avalonia.Themes.Fluent/WindowNotificationManager.xaml b/src/Avalonia.Themes.Fluent/WindowNotificationManager.xaml
new file mode 100644
index 0000000000..7c1efa2e82
--- /dev/null
+++ b/src/Avalonia.Themes.Fluent/WindowNotificationManager.xaml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Visuals/Media/FontWeight.cs b/src/Avalonia.Visuals/Media/FontWeight.cs
index a9967b6a66..5a4a4963a5 100644
--- a/src/Avalonia.Visuals/Media/FontWeight.cs
+++ b/src/Avalonia.Visuals/Media/FontWeight.cs
@@ -29,6 +29,11 @@ namespace Avalonia.Media
///
Light = 300,
+ ///
+ /// Specifies a "semi light" font weight.
+ ///
+ SemiLight = 350,
+
///
/// Specifies a "normal" font weight.
///
diff --git a/src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs b/src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs
index 8d4475d1c3..720185a3ad 100644
--- a/src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs
+++ b/src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs
@@ -32,6 +32,7 @@ namespace Avalonia.Media.TextFormatting
/// The text decorations.
/// The maximum width.
/// The maximum height.
+ /// The maximum number of text lines.
/// The text style overrides.
public TextLayout(
string text,
@@ -44,6 +45,7 @@ namespace Avalonia.Media.TextFormatting
TextDecorationCollection textDecorations = null,
double maxWidth = double.PositiveInfinity,
double maxHeight = double.PositiveInfinity,
+ int maxLines = 0,
IReadOnlyList textStyleOverrides = null)
{
_text = string.IsNullOrEmpty(text) ?
@@ -59,6 +61,8 @@ namespace Avalonia.Media.TextFormatting
MaxHeight = maxHeight;
+ MaxLines = maxLines;
+
UpdateLayout();
}
@@ -73,6 +77,12 @@ namespace Avalonia.Media.TextFormatting
///
public double MaxHeight { get; }
+
+ ///
+ /// Gets the maximum number of text lines.
+ ///
+ public double MaxLines { get; }
+
///
/// Gets the text lines.
///
@@ -192,7 +202,7 @@ namespace Avalonia.Media.TextFormatting
var currentPosition = 0;
- while (currentPosition < _text.Length)
+ while (currentPosition < _text.Length && (MaxLines == 0 || textLines.Count < MaxLines))
{
int length;
@@ -222,7 +232,7 @@ namespace Avalonia.Media.TextFormatting
var remainingLength = length;
- while (remainingLength > 0)
+ while (remainingLength > 0 && (MaxLines == 0 || textLines.Count < MaxLines))
{
var textSlice = _text.AsSlice(currentPosition, remainingLength);
diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs
index 4899f0efc0..1d41fe4bdd 100644
--- a/src/Avalonia.X11/X11Window.cs
+++ b/src/Avalonia.X11/X11Window.cs
@@ -1098,6 +1098,10 @@ namespace Avalonia.X11
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) =>
_transparencyHelper.SetTransparencyRequest(transparencyLevel);
+ public void SetWindowManagerAddShadowHint(bool enabled)
+ {
+ }
+
public WindowTransparencyLevel TransparencyLevel => _transparencyHelper.CurrentLevel;
}
}
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Output/Drm.cs b/src/Linux/Avalonia.LinuxFramebuffer/Output/Drm.cs
index e266c5ee54..787a2e4cb8 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Output/Drm.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Output/Drm.cs
@@ -176,7 +176,13 @@ namespace Avalonia.LinuxFramebuffer.Output
[DllImport(libdrm, SetLastError = true)]
public static extern int drmModeAddFB(int fd, uint width, uint height, byte depth,
byte bpp, uint pitch, uint bo_handle,
- out uint buf_id);
+ out uint buf_id);
+
+ [DllImport(libdrm, SetLastError = true)]
+ public static extern int drmModeAddFB2(int fd, uint width, uint height,
+ uint pixel_format, uint[] bo_handles, uint[] pitches,
+ uint[] offsets, out uint buf_id, uint flags);
+
[DllImport(libdrm, SetLastError = true)]
public static extern int drmModeSetCrtc(int fd, uint crtcId, uint bufferId,
uint x, uint y, uint *connectors, int count,
@@ -261,6 +267,8 @@ namespace Avalonia.LinuxFramebuffer.Output
[DllImport(libgbm, SetLastError = true)]
public static extern uint gbm_bo_get_stride(IntPtr bo);
+ [DllImport(libgbm, SetLastError = true)]
+ public static extern uint gbm_bo_get_format(IntPtr bo);
[StructLayout(LayoutKind.Explicit)]
public struct GbmBoHandle
@@ -278,7 +286,7 @@ namespace Avalonia.LinuxFramebuffer.Output
}
[DllImport(libgbm, SetLastError = true)]
- public static extern ulong gbm_bo_get_handle(IntPtr bo);
+ public static extern GbmBoHandle gbm_bo_get_handle(IntPtr bo);
public static class GbmColorFormats
{
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
index 0f5b66befb..7a5d20fc83 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
@@ -7,6 +7,8 @@ using Avalonia.OpenGL;
using Avalonia.Platform.Interop;
using static Avalonia.LinuxFramebuffer.NativeUnsafeMethods;
using static Avalonia.LinuxFramebuffer.Output.LibDrm;
+using static Avalonia.LinuxFramebuffer.Output.LibDrm.GbmColorFormats;
+
namespace Avalonia.LinuxFramebuffer.Output
{
public unsafe class DrmOutput : IOutputBackend, IGlPlatformSurface, IWindowingPlatformGlFeature
@@ -71,11 +73,26 @@ namespace Avalonia.LinuxFramebuffer.Output
var w = gbm_bo_get_width(bo);
var h = gbm_bo_get_height(bo);
var stride = gbm_bo_get_stride(bo);
- var handle = gbm_bo_get_handle(bo);
+ var handle = gbm_bo_get_handle(bo).u32;
+ var format = gbm_bo_get_format(bo);
+
+ // prepare for the new ioctl call
+ var handles = new uint[] {handle, 0, 0, 0};
+ var pitches = new uint[] {stride, 0, 0, 0};
+ var offsets = new uint[] {};
+
+ var ret = drmModeAddFB2(_card.Fd, w, h, format, handles, pitches,
+ offsets, out var fbHandle, 0);
- var ret = drmModeAddFB(_card.Fd, w, h, 24, 32, stride, (uint)handle, out var fbHandle);
if (ret != 0)
- throw new Win32Exception(ret, "drmModeAddFb failed");
+ {
+ // legacy fallback
+ ret = drmModeAddFB(_card.Fd, w, h, 24, 32, stride, (uint)handle,
+ out fbHandle);
+
+ if (ret != 0)
+ throw new Win32Exception(ret, $"drmModeAddFb failed {ret}");
+ }
gbm_bo_set_user_data(bo, new IntPtr((int)fbHandle), FbDestroyDelegate);
diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
index 06c5375520..985a6b9f5a 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
+++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
@@ -11,6 +11,7 @@
+
diff --git a/src/Markup/Avalonia.Markup.Xaml/Converters/ColorToBrushConverter.cs b/src/Markup/Avalonia.Markup.Xaml/Converters/ColorToBrushConverter.cs
new file mode 100644
index 0000000000..5b44e9eb50
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml/Converters/ColorToBrushConverter.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Globalization;
+using Avalonia.Data.Converters;
+using Avalonia.Media;
+using Avalonia.Media.Immutable;
+
+namespace Avalonia.Markup.Xaml.Converters
+{
+ ///
+ /// Converts a to an .
+ ///
+ public class ColorToBrushConverter : IValueConverter
+ {
+ ///
+ /// Converts a to an if the arguments are of the
+ /// correct type.
+ ///
+ /// The value.
+ /// The target type.
+ /// Not used.
+ /// Not used.
+ ///
+ /// If is a and
+ /// is then converts the color to a solid color brush.
+ ///
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return Convert(value, targetType);
+ }
+
+ ///
+ /// Converts an to a if the arguments are of the
+ /// correct type.
+ ///
+ /// The value.
+ /// The target type.
+ /// Not used.
+ /// Not used.
+ ///
+ /// If is an and
+ /// is then converts the solid color brush to a color.
+ ///
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return ConvertBack(value, targetType);
+ }
+
+ ///
+ /// Converts a to an if the arguments are of the
+ /// correct type.
+ ///
+ /// The value.
+ /// The target type.
+ ///
+ /// If is a and
+ /// is then converts the color to a solid color brush.
+ ///
+ public static object Convert(object value, Type targetType)
+ {
+ if (targetType == typeof(IBrush) && value is Color c)
+ {
+ return new ImmutableSolidColorBrush(c);
+ }
+
+ return value;
+ }
+
+ ///
+ /// Converts an to a if the arguments are of the
+ /// correct type.
+ ///
+ /// The value.
+ /// The target type.
+ ///
+ /// If is an and
+ /// is then converts the solid color brush to a color.
+ ///
+ public static object ConvertBack(object value, Type targetType)
+ {
+ if (targetType == typeof(Color) && value is ISolidColorBrush brush)
+ {
+ return brush.Color;
+ }
+
+ return value;
+ }
+ }
+}
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs
index d0d4aae9b8..03fd2e60dd 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs
@@ -1,6 +1,8 @@
using System;
using Avalonia.Controls;
using Avalonia.Data;
+using Avalonia.Markup.Xaml.Converters;
+using Avalonia.Media;
#nullable enable
@@ -54,11 +56,23 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
if (control != null)
{
- return InstancedBinding.OneWay(control.GetResourceObservable(ResourceKey));
+ var source = control.GetResourceObservable(ResourceKey, GetConverter(targetProperty));
+ return InstancedBinding.OneWay(source);
}
else if (_resourceProvider is object)
{
- return InstancedBinding.OneWay(_resourceProvider.GetResourceObservable(ResourceKey));
+ var source = _resourceProvider.GetResourceObservable(ResourceKey, GetConverter(targetProperty));
+ return InstancedBinding.OneWay(source);
+ }
+
+ return null;
+ }
+
+ private Func