Browse Source

Merge branch 'master' into colorpicker-updates-3

pull/9140/head
robloo 4 years ago
committed by GitHub
parent
commit
6580a4000c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .editorconfig
  2. 39
      Avalonia.sln
  3. 5
      build/NetAnalyzers.props
  4. 12
      samples/ControlCatalog.Android/MainActivity.cs
  5. 13
      samples/ControlCatalog.Android/SplashActivity.cs
  6. 0
      samples/ControlCatalog.Blazor.Web/App.razor
  7. 17
      samples/ControlCatalog.Blazor.Web/App.razor.cs
  8. 29
      samples/ControlCatalog.Blazor.Web/ControlCatalog.Blazor.Web.csproj
  9. 0
      samples/ControlCatalog.Blazor.Web/Pages/Index.razor
  10. 29
      samples/ControlCatalog.Blazor.Web/Program.cs
  11. 0
      samples/ControlCatalog.Blazor.Web/Properties/launchSettings.json
  12. 0
      samples/ControlCatalog.Blazor.Web/Shared/MainLayout.razor
  13. 3
      samples/ControlCatalog.Blazor.Web/_Imports.razor
  14. 0
      samples/ControlCatalog.Blazor.Web/wwwroot/css/app.css
  15. 0
      samples/ControlCatalog.Blazor.Web/wwwroot/favicon.ico
  16. 0
      samples/ControlCatalog.Blazor.Web/wwwroot/index.html
  17. 20
      samples/ControlCatalog.Web/App.razor.cs
  18. 68
      samples/ControlCatalog.Web/ControlCatalog.Web.csproj
  19. 32
      samples/ControlCatalog.Web/EmbedSample.Browser.cs
  20. 0
      samples/ControlCatalog.Web/Logo.svg
  21. 37
      samples/ControlCatalog.Web/Program.cs
  22. 6
      samples/ControlCatalog.Web/Roots.xml
  23. 23
      samples/ControlCatalog.Web/app.css
  24. 0
      samples/ControlCatalog.Web/embed.js
  25. 0
      samples/ControlCatalog.Web/favicon.ico
  26. 2
      samples/ControlCatalog.Web/index.html
  27. 4
      samples/ControlCatalog.Web/main.js
  28. 0
      samples/ControlCatalog.Web/runtimeconfig.template.json
  29. 4
      samples/MobileSandbox.Android/MainActivity.cs
  30. 4
      samples/MobileSandbox.Android/SplashActivity.cs
  31. 105
      src/Android/Avalonia.Android/AvaloniaActivity.cs
  32. 72
      src/Android/Avalonia.Android/AvaloniaMainActivity.cs
  33. 34
      src/Android/Avalonia.Android/AvaloniaSplashActivity.cs
  34. 2
      src/Android/Avalonia.Android/AvaloniaView.cs
  35. 11
      src/Android/Avalonia.Android/AvaloniaViewModel.cs
  36. 6
      src/Android/Avalonia.Android/OpenGL/GlPlatformSurface.cs
  37. 11
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  38. 4
      src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs
  39. 26
      src/Android/Avalonia.Android/SingleViewLifetime.cs
  40. 2
      src/Avalonia.Base/Input/Cursor.cs
  41. 2
      src/Avalonia.Base/Media/PreciseEllipticArcHelper.cs
  42. 2
      src/Avalonia.Base/Media/TextFormatting/Unicode/BinaryReaderExtensions.cs
  43. 2
      src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs
  44. 2
      src/Avalonia.Base/Media/TextFormatting/Unicode/LineBreak.cs
  45. 2
      src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrie.cs
  46. 2
      src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrieBuilder.Constants.cs
  47. 2
      src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrieBuilder.cs
  48. 2
      src/Avalonia.Base/Utilities/BinarySearchExtension.cs
  49. 5
      src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
  50. 359
      src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialColorPalette.cs
  51. 2
      src/Avalonia.Controls/AutoCompleteBox.cs
  52. 2
      src/Avalonia.Controls/Calendar/Calendar.cs
  53. 2
      src/Avalonia.Controls/Calendar/CalendarBlackoutDatesCollection.cs
  54. 2
      src/Avalonia.Controls/Calendar/CalendarButton.cs
  55. 2
      src/Avalonia.Controls/Calendar/CalendarDateRange.cs
  56. 2
      src/Avalonia.Controls/Calendar/CalendarDayButton.cs
  57. 2
      src/Avalonia.Controls/Calendar/CalendarExtensions.cs
  58. 2
      src/Avalonia.Controls/Calendar/CalendarItem.cs
  59. 2
      src/Avalonia.Controls/Calendar/DateTimeHelper.cs
  60. 2
      src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs
  61. 2
      src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs
  62. 2
      src/Avalonia.Controls/CalendarDatePicker/CalendarDatePickerDateValidationErrorEventArgs.cs
  63. 2
      src/Avalonia.Controls/CalendarDatePicker/CalendarDatePickerFormat.cs
  64. 2
      src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs
  65. 2
      src/Avalonia.Controls/Utils/ISelectionAdapter.cs
  66. 2
      src/Avalonia.Controls/Utils/SelectingItemsControlSelectionAdapter.cs
  67. 2
      src/Avalonia.Native/IconLoader.cs
  68. BIN
      src/Avalonia.Themes.Fluent/Assets/Inter-Bold.ttf
  69. BIN
      src/Avalonia.Themes.Fluent/Assets/Inter-ExtraLight.ttf
  70. BIN
      src/Avalonia.Themes.Fluent/Assets/Inter-Light.ttf
  71. BIN
      src/Avalonia.Themes.Fluent/Assets/Inter-Medium.ttf
  72. BIN
      src/Avalonia.Themes.Fluent/Assets/Inter-Regular.ttf
  73. BIN
      src/Avalonia.Themes.Fluent/Assets/Inter-SemiBold.ttf
  74. BIN
      src/Avalonia.Themes.Fluent/Assets/Inter-Thin.ttf
  75. 2
      src/Avalonia.Themes.Fluent/Controls/Calendar.xaml
  76. 2
      src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml
  77. 2
      src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml
  78. 2
      src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml
  79. 8
      src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml
  80. 2
      src/Avalonia.Themes.Fluent/Controls/DateTimePickerShared.xaml
  81. 6
      src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml
  82. 2
      src/Avalonia.Themes.Simple/Controls/CalendarItem.xaml
  83. 2
      src/Avalonia.Themes.Simple/Controls/DatePicker.xaml
  84. 2
      src/Avalonia.Themes.Simple/Controls/DateTimePickerShared.xaml
  85. 2
      src/Avalonia.Themes.Simple/Controls/TimePicker.xaml
  86. 2
      src/Avalonia.X11/X11Atoms.cs
  87. 1
      src/Directory.Build.props
  88. 7
      src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.CompilationTuning.props
  89. 53
      src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj
  90. 4
      src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.props
  91. 6
      src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.targets
  92. 20
      src/Web/Avalonia.Web.Blazor/AvaloniaBlazorAppBuilder.cs
  93. 44
      src/Web/Avalonia.Web.Blazor/AvaloniaView.cs
  94. 67
      src/Web/Avalonia.Web.Blazor/AvaloniaView.razor
  95. 500
      src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs
  96. 48
      src/Web/Avalonia.Web.Blazor/BlazorSingleViewLifetime.cs
  97. 25
      src/Web/Avalonia.Web.Blazor/BlazorSkiaGpu.cs
  98. 37
      src/Web/Avalonia.Web.Blazor/BlazorSkiaGpuRenderSession.cs
  99. 39
      src/Web/Avalonia.Web.Blazor/BlazorSkiaGpuRenderTarget.cs
  100. 87
      src/Web/Avalonia.Web.Blazor/BlazorSkiaRasterSurface.cs

3
.editorconfig

@ -134,6 +134,9 @@ csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
space_within_single_line_array_initializer_braces = true
#Net Analyzer
dotnet_analyzer_diagnostic.category-Performance.severity = none #error - Uncomment when all violations are fixed.
# Wrapping preferences
csharp_wrap_before_ternary_opsigns = false

39
Avalonia.sln

@ -90,6 +90,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}"
ProjectSection(SolutionItems) = preProject
build\ApiDiff.props = build\ApiDiff.props
build\AvaloniaPublicKey.props = build\AvaloniaPublicKey.props
build\Base.props = build\Base.props
build\Binding.props = build\Binding.props
build\CoreLibraries.props = build\CoreLibraries.props
@ -102,8 +103,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\Microsoft.CSharp.props = build\Microsoft.CSharp.props
build\Microsoft.Reactive.Testing.props = build\Microsoft.Reactive.Testing.props
build\Moq.props = build\Moq.props
build\NetAnalyzers.props = build\NetAnalyzers.props
build\NetCore.props = build\NetCore.props
build\NetFX.props = build\NetFX.props
build\NullableEnable.props = build\NullableEnable.props
build\ReactiveUI.props = build\ReactiveUI.props
build\ReferenceCoreLibraries.props = build\ReferenceCoreLibraries.props
build\Rx.props = build\Rx.props
@ -198,8 +201,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web", "Web", "{86A3F706-DC3
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Web.Blazor", "src\Web\Avalonia.Web.Blazor\Avalonia.Web.Blazor.csproj", "{25831348-EB2A-483E-9576-E8F6528674A5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Web", "samples\ControlCatalog.Web\ControlCatalog.Web.csproj", "{C08E9894-AA92-426E-BF56-033E262CAD3E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsInteropTest", "samples\interop\WindowsInteropTest\WindowsInteropTest.csproj", "{26A98DA1-D89D-4A95-8152-349F404DA2E2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlSamples", "samples\SampleControls\ControlSamples.csproj", "{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}"
@ -216,15 +217,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevGenerators", "src\tools\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Web", "src\Web\Avalonia.Web\Avalonia.Web.csproj", "{76D39FF6-6B4F-46C4-93CD-E6FC4665739E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Web.Sample", "src\Web\Avalonia.Web.Sample\Avalonia.Web.Sample.csproj", "{1F61B6F1-B881-4E27-A5B0-09D1F543F7AC}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox", "samples\MobileSandbox\MobileSandbox.csproj", "{3B8519C1-2F51-4F12-A348-120AB91D4532}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox.Android", "samples\MobileSandbox.Android\MobileSandbox.Android.csproj", "{C90FE60B-B01E-4F35-91D6-379D6966030F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MobileSandbox", "samples\MobileSandbox\MobileSandbox.csproj", "{3B8519C1-2F51-4F12-A348-120AB91D4532}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox.iOS", "samples\MobileSandbox.iOS\MobileSandbox.iOS.csproj", "{FED9A71D-00D7-4F40-A9E4-1229EEA28EEB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MobileSandbox.Android", "samples\MobileSandbox.Android\MobileSandbox.Android.csproj", "{C90FE60B-B01E-4F35-91D6-379D6966030F}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox.Desktop", "samples\MobileSandbox.Desktop\MobileSandbox.Desktop.csproj", "{62D392C9-81CF-487F-92E8-598B2AF3FDCE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MobileSandbox.iOS", "samples\MobileSandbox.iOS\MobileSandbox.iOS.csproj", "{FED9A71D-00D7-4F40-A9E4-1229EEA28EEB}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Blazor.Web", "samples\ControlCatalog.Blazor.Web\ControlCatalog.Blazor.Web.csproj", "{6A710364-AE6D-40BD-968B-024311527AC2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MobileSandbox.Desktop", "samples\MobileSandbox.Desktop\MobileSandbox.Desktop.csproj", "{62D392C9-81CF-487F-92E8-598B2AF3FDCE}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Web", "samples\ControlCatalog.Web\ControlCatalog.Web.csproj", "{8B3E8405-DE18-4048-A459-9CA4AC3319A2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -480,10 +483,6 @@ Global
{25831348-EB2A-483E-9576-E8F6528674A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{25831348-EB2A-483E-9576-E8F6528674A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{25831348-EB2A-483E-9576-E8F6528674A5}.Release|Any CPU.Build.0 = Release|Any CPU
{C08E9894-AA92-426E-BF56-033E262CAD3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C08E9894-AA92-426E-BF56-033E262CAD3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C08E9894-AA92-426E-BF56-033E262CAD3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C08E9894-AA92-426E-BF56-033E262CAD3E}.Release|Any CPU.Build.0 = Release|Any CPU
{26A98DA1-D89D-4A95-8152-349F404DA2E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{26A98DA1-D89D-4A95-8152-349F404DA2E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26A98DA1-D89D-4A95-8152-349F404DA2E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -516,10 +515,6 @@ Global
{76D39FF6-6B4F-46C4-93CD-E6FC4665739E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{76D39FF6-6B4F-46C4-93CD-E6FC4665739E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{76D39FF6-6B4F-46C4-93CD-E6FC4665739E}.Release|Any CPU.Build.0 = Release|Any CPU
{1F61B6F1-B881-4E27-A5B0-09D1F543F7AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F61B6F1-B881-4E27-A5B0-09D1F543F7AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F61B6F1-B881-4E27-A5B0-09D1F543F7AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F61B6F1-B881-4E27-A5B0-09D1F543F7AC}.Release|Any CPU.Build.0 = Release|Any CPU
{3B8519C1-2F51-4F12-A348-120AB91D4532}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B8519C1-2F51-4F12-A348-120AB91D4532}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B8519C1-2F51-4F12-A348-120AB91D4532}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -536,6 +531,14 @@ Global
{62D392C9-81CF-487F-92E8-598B2AF3FDCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62D392C9-81CF-487F-92E8-598B2AF3FDCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{62D392C9-81CF-487F-92E8-598B2AF3FDCE}.Release|Any CPU.Build.0 = Release|Any CPU
{6A710364-AE6D-40BD-968B-024311527AC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6A710364-AE6D-40BD-968B-024311527AC2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6A710364-AE6D-40BD-968B-024311527AC2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6A710364-AE6D-40BD-968B-024311527AC2}.Release|Any CPU.Build.0 = Release|Any CPU
{8B3E8405-DE18-4048-A459-9CA4AC3319A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B3E8405-DE18-4048-A459-9CA4AC3319A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B3E8405-DE18-4048-A459-9CA4AC3319A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B3E8405-DE18-4048-A459-9CA4AC3319A2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -579,6 +582,7 @@ Global
{41B02319-965D-4945-8005-C1A3D1224165} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{351337F5-D66F-461B-A957-4EF60BDB4BA6} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{909A8CBD-7D0E-42FD-B841-022AD8925820} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571} = {9B9E3891-2366-4253-A952-D08BCEB71098}
@ -586,7 +590,6 @@ Global
{676D6BFD-029D-4E43-BFC7-3892265CE251} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{F2CE566B-E7F6-447A-AB1A-3F574A6FE43A} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{25831348-EB2A-483E-9576-E8F6528674A5} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
{C08E9894-AA92-426E-BF56-033E262CAD3E} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{26A98DA1-D89D-4A95-8152-349F404DA2E2} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{70B9F5CC-E2F9-4314-9514-EDE762ACCC4B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
@ -594,12 +597,12 @@ Global
{EABE2161-989B-42BF-BD8D-1E34B20C21F1} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{76D39FF6-6B4F-46C4-93CD-E6FC4665739E} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
{1F61B6F1-B881-4E27-A5B0-09D1F543F7AC} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{3B8519C1-2F51-4F12-A348-120AB91D4532} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{C90FE60B-B01E-4F35-91D6-379D6966030F} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{FED9A71D-00D7-4F40-A9E4-1229EEA28EEB} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{62D392C9-81CF-487F-92E8-598B2AF3FDCE} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{6A710364-AE6D-40BD-968B-024311527AC2} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{8B3E8405-DE18-4048-A459-9CA4AC3319A2} = {9B9E3891-2366-4253-A952-D08BCEB71098}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}

5
build/NetAnalyzers.props

@ -0,0 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
</PropertyGroup>
</Project>

12
samples/ControlCatalog.Android/MainActivity.cs

@ -5,16 +5,8 @@ using Avalonia.Android;
namespace ControlCatalog.Android
{
[Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleInstance, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
public class MainActivity : AvaloniaActivity<App>
[Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
public class MainActivity : AvaloniaMainActivity
{
protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
{
return base.CustomizeAppBuilder(builder)
.AfterSetup(_ =>
{
Pages.EmbedSample.Implementation = new EmbedSampleAndroid();
});
}
}
}

13
samples/ControlCatalog.Android/SplashActivity.cs

@ -1,12 +1,23 @@
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Avalonia.Android;
namespace ControlCatalog.Android
{
[Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
public class SplashActivity : Activity
public class SplashActivity : AvaloniaSplashActivity<App>
{
protected override Avalonia.AppBuilder CustomizeAppBuilder(Avalonia.AppBuilder builder)
{
return base.CustomizeAppBuilder(builder)
.AfterSetup(_ =>
{
Pages.EmbedSample.Implementation = new EmbedSampleAndroid();
});
}
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);

0
samples/ControlCatalog.Web/App.razor → samples/ControlCatalog.Blazor.Web/App.razor

17
samples/ControlCatalog.Blazor.Web/App.razor.cs

@ -0,0 +1,17 @@
using Avalonia;
using Avalonia.Web.Blazor;
namespace ControlCatalog.Blazor.Web;
public partial class App
{
protected override void OnParametersSet()
{
AppBuilder.Configure<ControlCatalog.App>()
.UseBlazor()
// .With(new SkiaOptions { CustomGpuFactory = null }) // uncomment to disable GPU/GL rendering
.SetupWithSingleViewLifetime();
base.OnParametersSet();
}
}

29
samples/ControlCatalog.Blazor.Web/ControlCatalog.Blazor.Web.csproj

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
<Nullable>enable</Nullable>
<EmccTotalMemory>16777216</EmccTotalMemory>
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
<BlazorWebAssemblyPreserveCollationData>false</BlazorWebAssemblyPreserveCollationData>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.0-rc.1.22427.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.0-rc.1.22427.2" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
<ProjectReference Include="..\..\src\Web\Avalonia.Web.Blazor\Avalonia.Web.Blazor.csproj" />
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" />
</ItemGroup>
<Import Project="..\..\build\ReferenceCoreLibraries.props" />
<Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\src\Web\Avalonia.Web\Avalonia.Web.props" />
<Import Project="..\..\src\Web\Avalonia.Web\Avalonia.Web.targets" />
</Project>

0
samples/ControlCatalog.Web/Pages/Index.razor → samples/ControlCatalog.Blazor.Web/Pages/Index.razor

29
samples/ControlCatalog.Blazor.Web/Program.cs

@ -0,0 +1,29 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.DependencyInjection;
using ControlCatalog.Blazor.Web;
public class Program
{
public static async Task Main(string[] args)
{
await CreateHostBuilder(args).Build().RunAsync();
}
public static WebAssemblyHostBuilder CreateHostBuilder(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
return builder;
}
}

0
samples/ControlCatalog.Web/Properties/launchSettings.json → samples/ControlCatalog.Blazor.Web/Properties/launchSettings.json

0
samples/ControlCatalog.Web/Shared/MainLayout.razor → samples/ControlCatalog.Blazor.Web/Shared/MainLayout.razor

3
samples/ControlCatalog.Web/_Imports.razor → samples/ControlCatalog.Blazor.Web/_Imports.razor

@ -6,6 +6,5 @@
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using ControlCatalog.Web
@using ControlCatalog.Web.Shared
@using ControlCatalog.Blazor.Web.Shared
@using SkiaSharp

0
samples/ControlCatalog.Web/wwwroot/css/app.css → samples/ControlCatalog.Blazor.Web/wwwroot/css/app.css

0
samples/ControlCatalog.Web/wwwroot/favicon.ico → samples/ControlCatalog.Blazor.Web/wwwroot/favicon.ico

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 172 KiB

0
samples/ControlCatalog.Web/wwwroot/index.html → samples/ControlCatalog.Blazor.Web/wwwroot/index.html

20
samples/ControlCatalog.Web/App.razor.cs

@ -1,20 +0,0 @@
using Avalonia;
using Avalonia.Web.Blazor;
namespace ControlCatalog.Web;
public partial class App
{
protected override void OnParametersSet()
{
WebAppBuilder.Configure<ControlCatalog.App>()
.AfterSetup(_ =>
{
ControlCatalog.Pages.EmbedSample.Implementation = new EmbedSampleWeb();
})
.With(new SkiaOptions { CustomGpuFactory = null }) // uncomment to disable GPU/GL rendering
.SetupWithSingleViewLifetime();
base.OnParametersSet();
}
}

68
samples/ControlCatalog.Web/ControlCatalog.Web.csproj

@ -1,57 +1,45 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<!--Temporal hack that fixes compilation in VS-->
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
<EmccTotalMemory>16777216</EmccTotalMemory>
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
<BlazorWebAssemblyPreserveCollationData>false</BlazorWebAssemblyPreserveCollationData>
<TargetFramework>net7.0</TargetFramework>
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
<WasmMainJSPath>main.js</WasmMainJSPath>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<MSBuildEnableWorkloadResolver>true</MSBuildEnableWorkloadResolver>
<WasmBuildNative>true</WasmBuildNative>
<EmccFlags>-sVERBOSE -sERROR_ON_UNDEFINED_SYMBOLS=0</EmccFlags>
</PropertyGroup>
<!-- In debug, make builds faster by reducing optimizations -->
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<WasmNativeStrip>false</WasmNativeStrip>
<EmccCompileOptimizationFlag>-O1</EmccCompileOptimizationFlag>
<RunAOTCompilation>false</RunAOTCompilation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<Optimize>true</Optimize>
<WasmNativeStrip>true</WasmNativeStrip>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<RunAOTCompilation>true</RunAOTCompilation>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>full</TrimMode>
<WasmBuildNative>true</WasmBuildNative>
<InvariantGlobalization>true</InvariantGlobalization>
<WasmEnableSIMD>true</WasmEnableSIMD>
<EmccCompileOptimizationFlag>-O3</EmccCompileOptimizationFlag>
<EmccLinkOptimizationFlag>-O3</EmccLinkOptimizationFlag>
<RunAOTCompilation>false</RunAOTCompilation>
<DebuggerSupport>false</DebuggerSupport>
<EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization>
<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>
<EventSourceSupport>false</EventSourceSupport>
<HttpActivityPropagationSupport>false</HttpActivityPropagationSupport>
<InvariantGlobalization>true</InvariantGlobalization>
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
<UseNativeHttpHandler>true</UseNativeHttpHandler>
<UseSystemResourceKeys>true</UseSystemResourceKeys>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>link</TrimMode>
<TrimmerRemoveSymbols>true</TrimmerRemoveSymbols>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.0" PrivateAssets="all" />
<TrimmerRootDescriptor Include="Roots.xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
<ProjectReference Include="..\..\src\Web\Avalonia.Web.Blazor\Avalonia.Web.Blazor.csproj" />
<ProjectReference Include="..\..\src\Web\Avalonia.Web\Avalonia.Web.csproj" />
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" />
</ItemGroup>
<Import Project="..\..\build\ReferenceCoreLibraries.props" />
<Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\src\Web\Avalonia.Web.Blazor\Avalonia.Web.Blazor.targets" />
<Import Project="..\..\src\Web\Avalonia.Web.Blazor\Avalonia.Web.Blazor.CompilationTuning.props" />
<ItemGroup>
<WasmExtraFilesToDeploy Include="index.html" />
<WasmExtraFilesToDeploy Include="main.js" />
<WasmExtraFilesToDeploy Include="embed.js" />
<WasmExtraFilesToDeploy Include="favicon.ico" />
<WasmExtraFilesToDeploy Include="Logo.svg" />
<WasmExtraFilesToDeploy Include="app.css" />
</ItemGroup>
<Import Project="..\..\src\Web\Avalonia.Web\Avalonia.Web.props" />
<Import Project="..\..\src\Web\Avalonia.Web\Avalonia.Web.targets" />
</Project>

32
samples/ControlCatalog.Web/EmbedSample.Browser.cs

@ -1,34 +1,42 @@
using System;
using Avalonia;
using System.Runtime.InteropServices.JavaScript;
using Avalonia.Platform;
using Avalonia.Web.Blazor;
using Avalonia.Web;
using ControlCatalog.Pages;
using Microsoft.JSInterop;
namespace ControlCatalog.Web;
public class EmbedSampleWeb : INativeDemoControl
{
public IPlatformHandle CreateControl(bool isSecond, IPlatformHandle parent, Func<IPlatformHandle> createDefault)
{
var runtime = AvaloniaLocator.Current.GetRequiredService<IJSInProcessRuntime>();
if (isSecond)
{
var iframe = runtime.Invoke<IJSInProcessObjectReference>("document.createElement", "iframe");
iframe.InvokeVoid("setAttribute", "src", "https://www.youtube.com/embed/kZCIporjJ70");
var iframe = EmbedInterop.CreateElement("iframe");
iframe.SetProperty("src", "https://www.youtube.com/embed/kZCIporjJ70");
return new JSObjectControlHandle(iframe);
}
else
{
// window.createAppButton source is defined in "app.js" file.
var button = runtime.Invoke<IJSInProcessObjectReference>("window.createAppButton");
var defaultHandle = (JSObjectControlHandle)createDefault();
_ = JSHost.ImportAsync("embed.js", "./embed.js").ContinueWith(_ =>
{
EmbedInterop.AddAppButton(defaultHandle.Object);
});
return new JSObjectControlHandle(button);
return defaultHandle;
}
}
}
internal static partial class EmbedInterop
{
[JSImport("globalThis.document.createElement")]
public static partial JSObject CreateElement(string tagName);
[JSImport("addAppButton", "embed.js")]
public static partial void AddAppButton(JSObject parentObject);
}

0
src/Web/Avalonia.Web.Sample/Logo.svg → samples/ControlCatalog.Web/Logo.svg

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

37
samples/ControlCatalog.Web/Program.cs

@ -1,29 +1,22 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System.Runtime.Versioning;
using Avalonia;
using Avalonia.Web;
using ControlCatalog;
using ControlCatalog.Web;
public class Program
[assembly:SupportedOSPlatform("browser")]
internal partial class Program
{
public static async Task Main(string[] args)
private static void Main(string[] args)
{
await CreateHostBuilder(args).Build().RunAsync();
BuildAvaloniaApp()
.AfterSetup(_ =>
{
ControlCatalog.Pages.EmbedSample.Implementation = new EmbedSampleWeb();
}).SetupBrowserApp("out");
}
public static WebAssemblyHostBuilder CreateHostBuilder(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
return builder;
}
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>();
}

6
samples/ControlCatalog.Web/Roots.xml

@ -0,0 +1,6 @@
<linker>
<assembly fullname="ControlCatalog" preserve="All" />
<assembly fullname="ControlCatalog.Web" preserve="All" />
<assembly fullname="Avalonia.Themes.Fluent" preserve="All" />
<assembly fullname="Avalonia.Themes.Simple" preserve="All" />
</linker>

23
src/Web/Avalonia.Web.Sample/app.css → samples/ControlCatalog.Web/app.css

@ -4,12 +4,15 @@
}
#avalonia-splash {
position: absolute;
position: relative;
height: 100%;
width: 100%;
color: whitesmoke;
background: #171C2C;
font-family: 'Nunito', sans-serif;
background-position: center;
background-size: cover;
background-repeat: no-repeat;
}
#avalonia-splash a{
@ -24,15 +27,23 @@
}
.splash-close {
animation: fadeOut 1s forwards;
animation: slide 0.5s linear 1s forwards;
}
@keyframes fadeOut {
from {
opacity: 1;
@keyframes slide {
0% {
top: 0%;
}
to {
50% {
opacity: 80%;
}
100% {
top: 100%;
overflow: hidden;
opacity: 0;
display: none;
visibility: collapse;
}
}

0
src/Web/Avalonia.Web.Sample/embed.js → samples/ControlCatalog.Web/embed.js

0
src/Web/Avalonia.Web.Sample/favicon.ico → samples/ControlCatalog.Web/favicon.ico

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 172 KiB

2
src/Web/Avalonia.Web.Sample/index.html → samples/ControlCatalog.Web/index.html

@ -4,7 +4,7 @@
<html>
<head>
<title>Avalonia.Web.Sample</title>
<title>AvaloniaUI - ControlCatalog</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="modulepreload" href="./main.js" />

4
src/Web/Avalonia.Web.Sample/main.js → samples/ControlCatalog.Web/main.js

@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
import { dotnet } from './dotnet.js'
import { createAvaloniaRuntime } from './avalonia.js';
import { registerAvaloniaModule } from './avalonia.js';
const is_browser = typeof window != "undefined";
if (!is_browser) throw new Error(`Expected to be running in a browser`);
@ -12,7 +12,7 @@ const dotnetRuntime = await dotnet
.withApplicationArgumentsFromQuery()
.create();
await createAvaloniaRuntime(dotnetRuntime);
await registerAvaloniaModule(dotnetRuntime);
const config = dotnetRuntime.getConfig();

0
src/Web/Avalonia.Web.Sample/runtimeconfig.template.json → samples/ControlCatalog.Web/runtimeconfig.template.json

4
samples/MobileSandbox.Android/MainActivity.cs

@ -5,8 +5,8 @@ using Avalonia.Android;
namespace MobileSandbox.Android
{
[Activity(Label = "MobileSandbox.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleInstance, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
public class MainActivity : AvaloniaActivity<App>
[Activity(Label = "MobileSandbox.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
public class MainActivity : AvaloniaMainActivity
{
}
}

4
samples/MobileSandbox.Android/SplashActivity.cs

@ -1,11 +1,11 @@
using Android.App;
using Android.Content;
using Android.OS;
using Avalonia.Android;
namespace MobileSandbox.Android
{
[Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
public class SplashActivity : Activity
public class SplashActivity : AvaloniaSplashActivity<App>
{
protected override void OnResume()
{

105
src/Android/Avalonia.Android/AvaloniaActivity.cs

@ -1,105 +0,0 @@
using Android.OS;
using AndroidX.AppCompat.App;
using Android.Content.Res;
using AndroidX.Lifecycle;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls;
using Android.Runtime;
using Android.App;
using Android.Content;
using System;
namespace Avalonia.Android
{
public abstract class AvaloniaActivity : AppCompatActivity
{
internal class SingleViewLifetime : ISingleViewApplicationLifetime
{
public AvaloniaView View { get; internal set; }
public Control MainView
{
get => (Control)View.Content;
set => View.Content = value;
}
}
internal Action<int, Result, Intent> ActivityResult;
internal AvaloniaView View;
internal AvaloniaViewModel _viewModel;
protected abstract AppBuilder CreateAppBuilder();
protected override void OnCreate(Bundle savedInstanceState)
{
var builder = CreateAppBuilder();
var lifetime = new SingleViewLifetime();
builder.AfterSetup(x =>
{
_viewModel = new ViewModelProvider(this).Get(Java.Lang.Class.FromType(typeof(AvaloniaViewModel))) as AvaloniaViewModel;
View = new AvaloniaView(this);
if (_viewModel.Content != null)
{
View.Content = _viewModel.Content;
}
SetContentView(View);
lifetime.View = View;
View.Prepare();
});
builder.SetupWithLifetime(lifetime);
base.OnCreate(savedInstanceState);
}
public object Content
{
get
{
return _viewModel.Content;
}
set
{
_viewModel.Content = value;
if (View != null)
View.Content = value;
}
}
public override void OnConfigurationChanged(Configuration newConfig)
{
base.OnConfigurationChanged(newConfig);
}
protected override void OnDestroy()
{
View.Content = null;
base.OnDestroy();
}
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
ActivityResult?.Invoke(requestCode, resultCode, data);
}
}
public abstract class AvaloniaActivity<TApp> : AvaloniaActivity where TApp : Application, new()
{
protected virtual AppBuilder CustomizeAppBuilder(AppBuilder builder) => builder.UseAndroid();
protected override AppBuilder CreateAppBuilder()
{
var builder = AppBuilder.Configure<TApp>();
return CustomizeAppBuilder(builder);
}
}
}

72
src/Android/Avalonia.Android/AvaloniaMainActivity.cs

@ -0,0 +1,72 @@
using System;
using Android.App;
using Android.Content;
using Android.Content.Res;
using Android.OS;
using Android.Runtime;
using AndroidX.AppCompat.App;
using AndroidX.Lifecycle;
namespace Avalonia.Android
{
public abstract class AvaloniaMainActivity : AppCompatActivity
{
internal static object ViewContent;
internal Action<int, Result, Intent> ActivityResult;
internal AvaloniaView View;
protected override void OnCreate(Bundle savedInstanceState)
{
View = new AvaloniaView(this);
if (ViewContent != null)
{
View.Content = ViewContent;
}
View.Prepare();
if (Avalonia.Application.Current.ApplicationLifetime is SingleViewLifetime lifetime)
{
lifetime.View = View;
}
base.OnCreate(savedInstanceState);
SetContentView(View);
}
public object Content
{
get
{
return ViewContent;
}
set
{
ViewContent = value;
if (View != null)
View.Content = value;
}
}
public override void OnConfigurationChanged(Configuration newConfig)
{
base.OnConfigurationChanged(newConfig);
}
protected override void OnDestroy()
{
View.Content = null;
base.OnDestroy();
}
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
ActivityResult?.Invoke(requestCode, resultCode, data);
}
}
}

34
src/Android/Avalonia.Android/AvaloniaSplashActivity.cs

@ -0,0 +1,34 @@
using Android.OS;
using AndroidX.AppCompat.App;
using AndroidX.Lifecycle;
namespace Avalonia.Android
{
public abstract class AvaloniaSplashActivity : AppCompatActivity
{
protected abstract AppBuilder CreateAppBuilder();
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
var builder = CreateAppBuilder();
var lifetime = new SingleViewLifetime();
builder.SetupWithLifetime(lifetime);
}
}
public abstract class AvaloniaSplashActivity<TApp> : AvaloniaSplashActivity where TApp : Application, new()
{
protected virtual AppBuilder CustomizeAppBuilder(AppBuilder builder) => builder.UseAndroid();
protected override AppBuilder CreateAppBuilder()
{
var builder = AppBuilder.Configure<TApp>();
return CustomizeAppBuilder(builder);
}
}
}

2
src/Android/Avalonia.Android/AvaloniaView.cs

@ -74,7 +74,7 @@ namespace Avalonia.Android
class ViewImpl : TopLevelImpl
{
public ViewImpl(AvaloniaView avaloniaView) : base(avaloniaView)
public ViewImpl(AvaloniaView avaloniaView) : base(avaloniaView, true)
{
View.Focusable = true;
View.FocusChange += ViewImpl_FocusChange;

11
src/Android/Avalonia.Android/AvaloniaViewModel.cs

@ -1,11 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Avalonia.Android
{
internal class AvaloniaViewModel : AndroidX.Lifecycle.ViewModel
{
public object Content { get; set; }
}
}

6
src/Android/Avalonia.Android/OpenGL/GlPlatformSurface.cs

@ -1,4 +1,5 @@
using Avalonia.OpenGL.Egl;
using Avalonia.OpenGL;
using Avalonia.OpenGL.Egl;
using Avalonia.OpenGL.Surfaces;
namespace Avalonia.Android.OpenGL
@ -19,7 +20,8 @@ namespace Avalonia.Android.OpenGL
public static GlPlatformSurface TryCreate(IEglWindowGlPlatformSurfaceInfo info)
{
if (EglPlatformOpenGlInterface.TryCreate() is EglPlatformOpenGlInterface egl)
var feature = AvaloniaLocator.Current.GetService<IPlatformOpenGlInterface>();
if (feature is EglPlatformOpenGlInterface egl)
{
return new GlPlatformSurface(egl, info);
}

11
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -3,20 +3,14 @@ using System.Collections.Generic;
using Android.Content;
using Android.Graphics;
using Android.Media.TV;
using Android.OS;
using Android.Runtime;
using Android.Text;
using Android.Views;
using Android.Views.InputMethods;
using Android.Widget;
using Avalonia.Android.OpenGL;
using Avalonia.Android.Platform.Input;
using Avalonia.Android.Platform.Specific;
using Avalonia.Android.Platform.Specific.Helpers;
using Avalonia.Android.Platform.Storage;
using Avalonia.Controls;
using Avalonia.Controls.Documents;
using Avalonia.Controls.Platform;
using Avalonia.Controls.Platform.Surfaces;
using Avalonia.Input;
@ -29,7 +23,6 @@ using Avalonia.Platform.Storage;
using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
using Java.Lang;
using static System.Net.Mime.MediaTypeNames;
namespace Avalonia.Android.Platform.SkiaPlatform
{
@ -59,7 +52,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
_view.Resources.DisplayMetrics.HeightPixels).ToSize(RenderScaling);
NativeControlHost = new AndroidNativeControlHostImpl(avaloniaView);
StorageProvider = new AndroidStorageProvider((AvaloniaActivity)avaloniaView.Context);
StorageProvider = new AndroidStorageProvider((AvaloniaMainActivity)avaloniaView.Context);
}
public virtual Point GetAvaloniaPointFromEvent(MotionEvent e, int pointerIndex) =>
@ -301,7 +294,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
IsComposing = true;
_inputMethod.Client.SetPreeditText(ComposingText);
_inputMethod.Client?.SetPreeditText(ComposingText);
return base.SetComposingText(text, newCursorPosition);
}

4
src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs

@ -14,10 +14,10 @@ namespace Avalonia.Android.Platform.Storage;
internal class AndroidStorageProvider : IStorageProvider
{
private readonly AvaloniaActivity _activity;
private readonly AvaloniaMainActivity _activity;
private int _lastRequestCode = 20000;
public AndroidStorageProvider(AvaloniaActivity activity)
public AndroidStorageProvider(AvaloniaMainActivity activity)
{
_activity = activity;
}

26
src/Android/Avalonia.Android/SingleViewLifetime.cs

@ -0,0 +1,26 @@
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
namespace Avalonia.Android
{
internal class SingleViewLifetime : ISingleViewApplicationLifetime
{
private AvaloniaView _view;
public AvaloniaView View
{
get => _view; internal set
{
if (_view != null)
{
_view.Content = null;
_view.Dispose();
}
_view = value;
_view.Content = MainView;
}
}
public Control MainView { get; set; }
}
}

2
src/Avalonia.Base/Input/Cursor.cs

@ -33,7 +33,7 @@ namespace Avalonia.Input
DragLink,
None,
// Not available in GTK directly, see http://www.pixelbeat.org/programming/x_cursors/
// Not available in GTK directly, see https://www.pixelbeat.org/programming/x_cursors/
// We might enable them later, preferably, by loading pixmax directly from theme with fallback image
// SizeNorthWestSouthEast,
// SizeNorthEastSouthWest,

2
src/Avalonia.Base/Media/PreciseEllipticArcHelper.cs

@ -1081,7 +1081,7 @@ namespace Avalonia.Media
Point c = rest * (cs) + translation;
// See "http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter" to understand
// See "https://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter" to understand
// how the ellipse center is calculated

2
src/Avalonia.Base/Media/TextFormatting/Unicode/BinaryReaderExtensions.cs

@ -5,7 +5,7 @@
// not use this product except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

2
src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs

@ -104,7 +104,7 @@ namespace Avalonia.Media.TextFormatting.Unicode
/// <summary>
/// Gets the canonical representation of a given codepoint.
/// <see href="http://www.unicode.org/L2/L2013/13123-norm-and-bpa.pdf"/>
/// <see href="https://www.unicode.org/L2/L2013/13123-norm-and-bpa.pdf"/>
/// </summary>
/// <param name="codePoint">The code point to be mapped.</param>
/// <returns>The mapped canonical code point, or the passed <paramref name="codePoint"/>.</returns>

2
src/Avalonia.Base/Media/TextFormatting/Unicode/LineBreak.cs

@ -5,7 +5,7 @@
// not use this product except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

2
src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrie.cs

@ -5,7 +5,7 @@
// not use this product except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

2
src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrieBuilder.Constants.cs

@ -5,7 +5,7 @@
// not use this product except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

2
src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrieBuilder.cs

@ -5,7 +5,7 @@
// not use this product except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

2
src/Avalonia.Base/Utilities/BinarySearchExtension.cs

@ -5,7 +5,7 @@
// not use this product except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

5
src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj

@ -9,6 +9,11 @@
<NoWarn>NU1605;CS8632</NoWarn>
</PropertyGroup>
<!--Disable Net Perf. analyzer for submodule to avoid commit issue -->
<PropertyGroup>
<EnableNETAnalyzers>false</EnableNETAnalyzers>
</PropertyGroup>
<ItemGroup>
<Compile Include="../Avalonia.Base/Utilities/AvaloniaResourcesIndex.cs">
<Link>Shared/AvaloniaResourcesIndex.cs</Link>

359
src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialColorPalette.cs

@ -0,0 +1,359 @@
using Avalonia.Media;
using Avalonia.Utilities;
namespace Avalonia.Controls
{
/// <summary>
/// Implements a reduced version of the 2014 Material Design color palette.
/// </summary>
/// <remarks>
/// This palette is based on the one outlined here:
///
/// https://material.io/design/color/the-color-system.html#tools-for-picking-colors
///
/// In order to make the palette uniform and rectangular the following
/// alterations were made:
///
/// 1. The A100-A700 shades of each color are excluded.
/// These shades do not exist for all colors (brown/gray).
/// 2. Black/White are stand-alone and are also excluded.
///
/// </remarks>
public class MaterialColorPalette : IColorPalette
{
// See: https://material.io/design/color/the-color-system.html#tools-for-picking-colors
// This is a reduced palette for uniformity
private static Color[,]? _colorChart = null;
private static int _colorChartColorCount = 0;
private static int _colorChartShadeCount = 0;
private static object _colorChartMutex = new object();
/// <summary>
/// Initializes all color chart colors.
/// </summary>
/// <remarks>
/// This is pulled out separately to lazy load for performance.
/// If no material color palette is ever used, no colors will be created.
/// </remarks>
private void InitColorChart()
{
lock (_colorChartMutex)
{
_colorChart = new Color[,]
{
// Red
{
Color.FromArgb(0xFF, 0xFF, 0xEB, 0xEE),
Color.FromArgb(0xFF, 0xFF, 0xCD, 0xD2),
Color.FromArgb(0xFF, 0xEF, 0x9A, 0x9A),
Color.FromArgb(0xFF, 0xE5, 0x73, 0x73),
Color.FromArgb(0xFF, 0xEF, 0x53, 0x50),
Color.FromArgb(0xFF, 0xF4, 0x43, 0x36),
Color.FromArgb(0xFF, 0xE5, 0x39, 0x35),
Color.FromArgb(0xFF, 0xD3, 0x2F, 0x2F),
Color.FromArgb(0xFF, 0xC6, 0x28, 0x28),
Color.FromArgb(0xFF, 0xB7, 0x1C, 0x1C),
},
// Pink
{
Color.FromArgb(0xFF, 0xFC, 0xE4, 0xEC),
Color.FromArgb(0xFF, 0xF8, 0xBB, 0xD0),
Color.FromArgb(0xFF, 0xF4, 0x8F, 0xB1),
Color.FromArgb(0xFF, 0xF0, 0x62, 0x92),
Color.FromArgb(0xFF, 0xEC, 0x40, 0x7A),
Color.FromArgb(0xFF, 0xE9, 0x1E, 0x63),
Color.FromArgb(0xFF, 0xD8, 0x1B, 0x60),
Color.FromArgb(0xFF, 0xC2, 0x18, 0x5B),
Color.FromArgb(0xFF, 0xAD, 0x14, 0x57),
Color.FromArgb(0xFF, 0x88, 0x0E, 0x4F),
},
// Purple
{
Color.FromArgb(0xFF, 0xF3, 0xE5, 0xF5),
Color.FromArgb(0xFF, 0xE1, 0xBE, 0xE7),
Color.FromArgb(0xFF, 0xCE, 0x93, 0xD8),
Color.FromArgb(0xFF, 0xBA, 0x68, 0xC8),
Color.FromArgb(0xFF, 0xAB, 0x47, 0xBC),
Color.FromArgb(0xFF, 0x9C, 0x27, 0xB0),
Color.FromArgb(0xFF, 0x8E, 0x24, 0xAA),
Color.FromArgb(0xFF, 0x7B, 0x1F, 0xA2),
Color.FromArgb(0xFF, 0x6A, 0x1B, 0x9A),
Color.FromArgb(0xFF, 0x4A, 0x14, 0x8C),
},
// Deep Purple
{
Color.FromArgb(0xFF, 0xED, 0xE7, 0xF6),
Color.FromArgb(0xFF, 0xD1, 0xC4, 0xE9),
Color.FromArgb(0xFF, 0xB3, 0x9D, 0xDB),
Color.FromArgb(0xFF, 0x95, 0x75, 0xCD),
Color.FromArgb(0xFF, 0x7E, 0x57, 0xC2),
Color.FromArgb(0xFF, 0x67, 0x3A, 0xB7),
Color.FromArgb(0xFF, 0x5E, 0x35, 0xB1),
Color.FromArgb(0xFF, 0x51, 0x2D, 0xA8),
Color.FromArgb(0xFF, 0x45, 0x27, 0xA0),
Color.FromArgb(0xFF, 0x31, 0x1B, 0x92),
},
// Indigo
{
Color.FromArgb(0xFF, 0xE8, 0xEA, 0xF6),
Color.FromArgb(0xFF, 0xC5, 0xCA, 0xE9),
Color.FromArgb(0xFF, 0x9F, 0xA8, 0xDA),
Color.FromArgb(0xFF, 0x79, 0x86, 0xCB),
Color.FromArgb(0xFF, 0x5C, 0x6B, 0xC0),
Color.FromArgb(0xFF, 0x3F, 0x51, 0xB5),
Color.FromArgb(0xFF, 0x39, 0x49, 0xAB),
Color.FromArgb(0xFF, 0x30, 0x3F, 0x9F),
Color.FromArgb(0xFF, 0x28, 0x35, 0x93),
Color.FromArgb(0xFF, 0x1A, 0x23, 0x7E),
},
// Blue
{
Color.FromArgb(0xFF, 0xE3, 0xF2, 0xFD),
Color.FromArgb(0xFF, 0xBB, 0xDE, 0xFB),
Color.FromArgb(0xFF, 0x90, 0xCA, 0xF9),
Color.FromArgb(0xFF, 0x64, 0xB5, 0xF6),
Color.FromArgb(0xFF, 0x42, 0xA5, 0xF5),
Color.FromArgb(0xFF, 0x21, 0x96, 0xF3),
Color.FromArgb(0xFF, 0x1E, 0x88, 0xE5),
Color.FromArgb(0xFF, 0x19, 0x76, 0xD2),
Color.FromArgb(0xFF, 0x15, 0x65, 0xC0),
Color.FromArgb(0xFF, 0x0D, 0x47, 0xA1),
},
// Light Blue
{
Color.FromArgb(0xFF, 0xE1, 0xF5, 0xFE),
Color.FromArgb(0xFF, 0xB3, 0xE5, 0xFC),
Color.FromArgb(0xFF, 0x81, 0xD4, 0xFA),
Color.FromArgb(0xFF, 0x4F, 0xC3, 0xF7),
Color.FromArgb(0xFF, 0x29, 0xB6, 0xF6),
Color.FromArgb(0xFF, 0x03, 0xA9, 0xF4),
Color.FromArgb(0xFF, 0x03, 0x9B, 0xE5),
Color.FromArgb(0xFF, 0x02, 0x88, 0xD1),
Color.FromArgb(0xFF, 0x02, 0x77, 0xBD),
Color.FromArgb(0xFF, 0x01, 0x57, 0x9B),
},
// Cyan
{
Color.FromArgb(0xFF, 0xE0, 0xF7, 0xFA),
Color.FromArgb(0xFF, 0xB2, 0xEB, 0xF2),
Color.FromArgb(0xFF, 0x80, 0xDE, 0xEA),
Color.FromArgb(0xFF, 0x4D, 0xD0, 0xE1),
Color.FromArgb(0xFF, 0x26, 0xC6, 0xDA),
Color.FromArgb(0xFF, 0x00, 0xBC, 0xD4),
Color.FromArgb(0xFF, 0x00, 0xAC, 0xC1),
Color.FromArgb(0xFF, 0x00, 0x97, 0xA7),
Color.FromArgb(0xFF, 0x00, 0x83, 0x8F),
Color.FromArgb(0xFF, 0x00, 0x60, 0x64),
},
// Teal
{
Color.FromArgb(0xFF, 0xE0, 0xF2, 0xF1),
Color.FromArgb(0xFF, 0xB2, 0xDF, 0xDB),
Color.FromArgb(0xFF, 0x80, 0xCB, 0xC4),
Color.FromArgb(0xFF, 0x4D, 0xB6, 0xAC),
Color.FromArgb(0xFF, 0x26, 0xA6, 0x9A),
Color.FromArgb(0xFF, 0x00, 0x96, 0x88),
Color.FromArgb(0xFF, 0x00, 0x89, 0x7B),
Color.FromArgb(0xFF, 0x00, 0x79, 0x6B),
Color.FromArgb(0xFF, 0x00, 0x69, 0x5C),
Color.FromArgb(0xFF, 0x00, 0x4D, 0x40),
},
// Green
{
Color.FromArgb(0xFF, 0xE8, 0xF5, 0xE9),
Color.FromArgb(0xFF, 0xC8, 0xE6, 0xC9),
Color.FromArgb(0xFF, 0xA5, 0xD6, 0xA7),
Color.FromArgb(0xFF, 0x81, 0xC7, 0x84),
Color.FromArgb(0xFF, 0x66, 0xBB, 0x6A),
Color.FromArgb(0xFF, 0x4C, 0xAF, 0x50),
Color.FromArgb(0xFF, 0x43, 0xA0, 0x47),
Color.FromArgb(0xFF, 0x38, 0x8E, 0x3C),
Color.FromArgb(0xFF, 0x2E, 0x7D, 0x32),
Color.FromArgb(0xFF, 0x1B, 0x5E, 0x20),
},
// Light Green
{
Color.FromArgb(0xFF, 0xF1, 0xF8, 0xE9),
Color.FromArgb(0xFF, 0xDC, 0xED, 0xC8),
Color.FromArgb(0xFF, 0xC5, 0xE1, 0xA5),
Color.FromArgb(0xFF, 0xAE, 0xD5, 0x81),
Color.FromArgb(0xFF, 0x9C, 0xCC, 0x65),
Color.FromArgb(0xFF, 0x8B, 0xC3, 0x4A),
Color.FromArgb(0xFF, 0x7C, 0xB3, 0x42),
Color.FromArgb(0xFF, 0x68, 0x9F, 0x38),
Color.FromArgb(0xFF, 0x55, 0x8B, 0x2F),
Color.FromArgb(0xFF, 0x33, 0x69, 0x1E),
},
// Lime
{
Color.FromArgb(0xFF, 0xF9, 0xFB, 0xE7),
Color.FromArgb(0xFF, 0xF0, 0xF4, 0xC3),
Color.FromArgb(0xFF, 0xE6, 0xEE, 0x9C),
Color.FromArgb(0xFF, 0xDC, 0xE7, 0x75),
Color.FromArgb(0xFF, 0xD4, 0xE1, 0x57),
Color.FromArgb(0xFF, 0xCD, 0xDC, 0x39),
Color.FromArgb(0xFF, 0xC0, 0xCA, 0x33),
Color.FromArgb(0xFF, 0xAF, 0xB4, 0x2B),
Color.FromArgb(0xFF, 0x9E, 0x9D, 0x24),
Color.FromArgb(0xFF, 0x82, 0x77, 0x17),
},
// Yellow
{
Color.FromArgb(0xFF, 0xFF, 0xFD, 0xE7),
Color.FromArgb(0xFF, 0xFF, 0xF9, 0xC4),
Color.FromArgb(0xFF, 0xFF, 0xF5, 0x9D),
Color.FromArgb(0xFF, 0xFF, 0xF1, 0x76),
Color.FromArgb(0xFF, 0xFF, 0xEE, 0x58),
Color.FromArgb(0xFF, 0xFF, 0xEB, 0x3B),
Color.FromArgb(0xFF, 0xFD, 0xD8, 0x35),
Color.FromArgb(0xFF, 0xFB, 0xC0, 0x2D),
Color.FromArgb(0xFF, 0xF9, 0xA8, 0x25),
Color.FromArgb(0xFF, 0xF5, 0x7F, 0x17),
},
// Amber
{
Color.FromArgb(0xFF, 0xFF, 0xF8, 0xE1),
Color.FromArgb(0xFF, 0xFF, 0xEC, 0xB3),
Color.FromArgb(0xFF, 0xFF, 0xE0, 0x82),
Color.FromArgb(0xFF, 0xFF, 0xD5, 0x4F),
Color.FromArgb(0xFF, 0xFF, 0xCA, 0x28),
Color.FromArgb(0xFF, 0xFF, 0xC1, 0x07),
Color.FromArgb(0xFF, 0xFF, 0xB3, 0x00),
Color.FromArgb(0xFF, 0xFF, 0xA0, 0x00),
Color.FromArgb(0xFF, 0xFF, 0x8F, 0x00),
Color.FromArgb(0xFF, 0xFF, 0x6F, 0x00),
},
// Orange
{
Color.FromArgb(0xFF, 0xFF, 0xF3, 0xE0),
Color.FromArgb(0xFF, 0xFF, 0xE0, 0xB2),
Color.FromArgb(0xFF, 0xFF, 0xCC, 0x80),
Color.FromArgb(0xFF, 0xFF, 0xB7, 0x4D),
Color.FromArgb(0xFF, 0xFF, 0xA7, 0x26),
Color.FromArgb(0xFF, 0xFF, 0x98, 0x00),
Color.FromArgb(0xFF, 0xFB, 0x8C, 0x00),
Color.FromArgb(0xFF, 0xF5, 0x7C, 0x00),
Color.FromArgb(0xFF, 0xEF, 0x6C, 0x00),
Color.FromArgb(0xFF, 0xE6, 0x51, 0x00),
},
// Deep Orange
{
Color.FromArgb(0xFF, 0xFB, 0xE9, 0xE7),
Color.FromArgb(0xFF, 0xFF, 0xCC, 0xBC),
Color.FromArgb(0xFF, 0xFF, 0xAB, 0x91),
Color.FromArgb(0xFF, 0xFF, 0x8A, 0x65),
Color.FromArgb(0xFF, 0xFF, 0x70, 0x43),
Color.FromArgb(0xFF, 0xFF, 0x57, 0x22),
Color.FromArgb(0xFF, 0xF4, 0x51, 0x1E),
Color.FromArgb(0xFF, 0xE6, 0x4A, 0x19),
Color.FromArgb(0xFF, 0xD8, 0x43, 0x15),
Color.FromArgb(0xFF, 0xBF, 0x36, 0x0C),
},
// Brown
{
Color.FromArgb(0xFF, 0xEF, 0xEB, 0xE9),
Color.FromArgb(0xFF, 0xD7, 0xCC, 0xC8),
Color.FromArgb(0xFF, 0xBC, 0xAA, 0xA4),
Color.FromArgb(0xFF, 0xA1, 0x88, 0x7F),
Color.FromArgb(0xFF, 0x8D, 0x6E, 0x63),
Color.FromArgb(0xFF, 0x79, 0x55, 0x48),
Color.FromArgb(0xFF, 0x6D, 0x4C, 0x41),
Color.FromArgb(0xFF, 0x5D, 0x40, 0x37),
Color.FromArgb(0xFF, 0x4E, 0x34, 0x2E),
Color.FromArgb(0xFF, 0x3E, 0x27, 0x23),
},
// Gray
{
Color.FromArgb(0xFF, 0xFA, 0xFA, 0xFA),
Color.FromArgb(0xFF, 0xF5, 0xF5, 0xF5),
Color.FromArgb(0xFF, 0xEE, 0xEE, 0xEE),
Color.FromArgb(0xFF, 0xE0, 0xE0, 0xE0),
Color.FromArgb(0xFF, 0xBD, 0xBD, 0xBD),
Color.FromArgb(0xFF, 0x9E, 0x9E, 0x9E),
Color.FromArgb(0xFF, 0x75, 0x75, 0x75),
Color.FromArgb(0xFF, 0x61, 0x61, 0x61),
Color.FromArgb(0xFF, 0x42, 0x42, 0x42),
Color.FromArgb(0xFF, 0x21, 0x21, 0x21),
},
// Blue Gray
{
Color.FromArgb(0xFF, 0xEC, 0xEF, 0xF1),
Color.FromArgb(0xFF, 0xCF, 0xD8, 0xDC),
Color.FromArgb(0xFF, 0xB0, 0xBE, 0xC5),
Color.FromArgb(0xFF, 0x90, 0xA4, 0xAE),
Color.FromArgb(0xFF, 0x78, 0x90, 0x9C),
Color.FromArgb(0xFF, 0x60, 0x7D, 0x8B),
Color.FromArgb(0xFF, 0x54, 0x6E, 0x7A),
Color.FromArgb(0xFF, 0x45, 0x5A, 0x64),
Color.FromArgb(0xFF, 0x37, 0x47, 0x4F),
Color.FromArgb(0xFF, 0x26, 0x32, 0x38),
},
};
_colorChartColorCount = _colorChart.GetLength(0);
_colorChartShadeCount = _colorChart.GetLength(1);
}
return;
}
/// <inheritdoc/>
public int ColorCount
{
get
{
if (_colorChart == null)
{
InitColorChart();
}
return _colorChartColorCount;
}
}
/// <inheritdoc/>
public int ShadeCount
{
get
{
if (_colorChart == null)
{
InitColorChart();
}
return _colorChartShadeCount;
}
}
/// <inheritdoc/>
public Color GetColor(int colorIndex, int shadeIndex)
{
if (_colorChart == null)
{
InitColorChart();
}
return _colorChart![
MathUtilities.Clamp(colorIndex, 0, _colorChartColorCount - 1),
MathUtilities.Clamp(shadeIndex, 0, _colorChartShadeCount - 1)];
}
}
}

2
src/Avalonia.Controls/AutoCompleteBox.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System;

2
src/Avalonia.Controls/Calendar/Calendar.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System;

2
src/Avalonia.Controls/Calendar/CalendarBlackoutDatesCollection.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System;

2
src/Avalonia.Controls/Calendar/CalendarButton.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using Avalonia.Controls.Metadata;

2
src/Avalonia.Controls/Calendar/CalendarDateRange.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System;

2
src/Avalonia.Controls/Calendar/CalendarDayButton.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System;

2
src/Avalonia.Controls/Calendar/CalendarExtensions.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using Avalonia.Input;

2
src/Avalonia.Controls/Calendar/CalendarItem.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System;

2
src/Avalonia.Controls/Calendar/DateTimeHelper.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System;

2
src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using Avalonia.Threading;

2
src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System;

2
src/Avalonia.Controls/CalendarDatePicker/CalendarDatePickerDateValidationErrorEventArgs.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System;

2
src/Avalonia.Controls/CalendarDatePicker/CalendarDatePickerFormat.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
namespace Avalonia.Controls

2
src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs

@ -35,7 +35,7 @@ DEALINGS IN THE SOFTWARE.
The above is the version of the MIT "Expat" License used by X.org:
http://cgit.freedesktop.org/xorg/xserver/tree/COPYING
https://cgit.freedesktop.org/xorg/xserver/tree/COPYING
Adjustments for Avalonia needs:

2
src/Avalonia.Controls/Utils/ISelectionAdapter.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System;

2
src/Avalonia.Controls/Utils/SelectingItemsControlSelectionAdapter.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System;

2
src/Avalonia.Native/IconLoader.cs

@ -6,7 +6,7 @@ namespace Avalonia.Native
// OSX doesn't have a concept of *window* icon.
// Icons in the title bar are only shown if there is
// an opened file (on disk) associated with the current window
// see http://stackoverflow.com/a/7038671/2231814
// see https://stackoverflow.com/a/7038671/2231814
class IconLoader : IPlatformIconLoader
{
class IconStub : IWindowIconImpl

BIN
src/Avalonia.Themes.Fluent/Assets/Inter-Bold.ttf

Binary file not shown.

BIN
src/Avalonia.Themes.Fluent/Assets/Inter-ExtraLight.ttf

Binary file not shown.

BIN
src/Avalonia.Themes.Fluent/Assets/Inter-Light.ttf

Binary file not shown.

BIN
src/Avalonia.Themes.Fluent/Assets/Inter-Medium.ttf

Binary file not shown.

BIN
src/Avalonia.Themes.Fluent/Assets/Inter-Regular.ttf

Binary file not shown.

BIN
src/Avalonia.Themes.Fluent/Assets/Inter-SemiBold.ttf

Binary file not shown.

BIN
src/Avalonia.Themes.Fluent/Assets/Inter-Thin.ttf

Binary file not shown.

2
src/Avalonia.Themes.Fluent/Controls/Calendar.xaml

@ -1,7 +1,7 @@
<!--
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
-->

2
src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml

@ -1,7 +1,7 @@
<!--
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
-->
<ResourceDictionary xmlns="https://github.com/avaloniaui"

2
src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml

@ -1,7 +1,7 @@
<!--
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
-->
<ResourceDictionary xmlns="https://github.com/avaloniaui"

2
src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml

@ -1,7 +1,7 @@
<!--
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
-->
<ResourceDictionary xmlns="https://github.com/avaloniaui"

8
src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml

@ -1,7 +1,7 @@
<!--
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
-->
@ -153,11 +153,11 @@
</Style>
<!-- Changes foreground for watermark text when SelectedDate is null-->
<Style Selector="^:hasnodate /template/ Button#FlyoutButton TextBlock">
<Style Selector="^:hasnodate /template/ Button#PART_FlyoutButton TextBlock">
<Setter Property="Foreground" Value="{DynamicResource TextControlPlaceholderForeground}"/>
</Style>
<Style Selector="^:error /template/ Button#FlyoutButton">
<Style Selector="^:error /template/ Button#PART_FlyoutButton">
<Setter Property="BorderBrush" Value="{DynamicResource SystemControlErrorTextForegroundBrush}"/>
</Style>
</ControlTheme>

2
src/Avalonia.Themes.Fluent/Controls/DateTimePickerShared.xaml

@ -1,7 +1,7 @@
<!--
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
-->

6
src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml

@ -1,7 +1,7 @@
<!--
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
-->
@ -181,11 +181,11 @@
<Setter Property="Fill" Value="{DynamicResource TimePickerSpacerFillDisabled}"/>
</Style>
<Style Selector="^:hasnotime /template/ Button#FlyoutButton TextBlock">
<Style Selector="^:hasnotime /template/ Button#PART_FlyoutButton TextBlock">
<Setter Property="Foreground" Value="{DynamicResource TextControlPlaceholderForeground}"/>
</Style>
<Style Selector="^:error /template/ Button#FlyoutButton">
<Style Selector="^:error /template/ Button#PART_FlyoutButton">
<Setter Property="BorderBrush" Value="{DynamicResource SystemControlErrorTextForegroundBrush}"/>
</Style>
</ControlTheme>

2
src/Avalonia.Themes.Simple/Controls/CalendarItem.xaml

@ -1,7 +1,7 @@
<!--
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
-->

2
src/Avalonia.Themes.Simple/Controls/DatePicker.xaml

@ -170,7 +170,7 @@
</Style>
<!-- Changes foreground for watermark text when SelectedDate is null -->
<Style Selector="^:hasnodate /template/ Button#FlyoutButton TextBlock">
<Style Selector="^:hasnodate /template/ Button#PART_FlyoutButton TextBlock">
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundLowBrush}" />
</Style>
</ControlTheme>

2
src/Avalonia.Themes.Simple/Controls/DateTimePickerShared.xaml

@ -1,7 +1,7 @@
<!--
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
-->

2
src/Avalonia.Themes.Simple/Controls/TimePicker.xaml

@ -189,7 +189,7 @@
<Setter Property="Opacity" Value="{DynamicResource ThemeDisabledOpacity}" />
</Style>
<Style Selector="^:hasnotime /template/ Button#FlyoutButton TextBlock">
<Style Selector="^:hasnotime /template/ Button#PART_FlyoutButton TextBlock">
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundLowBrush}" />
</Style>
</ControlTheme>

2
src/Avalonia.X11/X11Atoms.cs

@ -17,7 +17,7 @@
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
// Copyright (c) 2006 Novell, Inc. (https://www.novell.com)
//
//

1
src/Directory.Build.props

@ -2,6 +2,7 @@
<Import Project="..\Directory.Build.props" />
<Import Project="..\build\SharedVersion.props" />
<Import Project="..\build\SourceLink.props" Condition="'$(DisableSourceLink)' == ''" />
<Import Project="..\build\NetAnalyzers.props"/>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)\Shared\ModuleInitializer.cs" >
<Link>Shared\_ModuleInitializer.cs</Link>

7
src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.CompilationTuning.props

@ -1,7 +0,0 @@
<Project>
<PropertyGroup>
<EmccTotalMemory>16777216</EmccTotalMemory>
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
<BlazorWebAssemblyPreserveCollationData>false</BlazorWebAssemblyPreserveCollationData>
</PropertyGroup>
</Project>

53
src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj

@ -1,53 +1,40 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<TargetFramework>net7.0</TargetFramework>
<PackageId>Avalonia.Web.Blazor</PackageId>
<LangVersion>preview</LangVersion>
<MSBuildEnableWorkloadResolver>false</MSBuildEnableWorkloadResolver>
<StaticWebAssetsDisableProjectBuildPropsFileGeneration>true</StaticWebAssetsDisableProjectBuildPropsFileGeneration>
<ResolveStaticWebAssetsInputsDependsOn>_IncludeGeneratedAvaloniaStaticFiles;$(ResolveStaticWebAssetsInputsDependsOn)</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>
<ItemGroup>
<SupportedPlatform Include="browser" />
</ItemGroup>
<Import Project="..\..\..\build\BuildTargets.targets" />
<Import Project="..\..\..\build\SkiaSharp.props" />
<Import Project="..\..\..\build\HarfBuzzSharp.props" />
<Import Project="..\..\..\build\NullableEnable.props" />
<ItemGroup>
<Content Include="*.props">
<Pack>true</Pack>
<PackagePath>build\</PackagePath>
</Content>
<Content Include="*.targets">
<Pack>true</Pack>
<PackagePath>build\;buildTransitive\</PackagePath>
</Content>
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="7.0.0-*" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="6.0.8" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj" />
<ProjectReference Include="..\..\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
<ProjectReference Include="..\Avalonia.Web\Avalonia.Web.csproj" />
</ItemGroup>
<Target Name="NpmInstall" Inputs="webapp/package.json" Outputs="webapp/node_modules/.install-stamp">
<Exec Command="npm install" WorkingDirectory="webapp" />
<!-- Write the stamp file, so incremental builds work -->
<Touch Files="webapp/node_modules/.install-stamp" AlwaysCreate="true" />
</Target>
<Target Name="NpmRunBuild" DependsOnTargets="NpmInstall" BeforeTargets="BeforeBuild">
<Exec Command="npm run build" WorkingDirectory="webapp" />
<Target Name="_IncludeGeneratedAvaloniaStaticFiles">
<ItemGroup>
<_AvaloniaWebAssets Include="$(MSBuildThisFileDirectory)../Avalonia.Web/wwwroot/**/*.*" />
</ItemGroup>
<DefineStaticWebAssets SourceId="$(PackageId)"
SourceType="Computed"
AssetKind="All"
AssetRole="Primary"
CopyToOutputDirectory="PreserveNewest"
CopyToPublishDirectory="PreserveNewest"
ContentRoot="$(MSBuildThisFileDirectory)../Avalonia.Web/wwwroot/"
BasePath="_content\$(PackageId)"
CandidateAssets="@(_AvaloniaWebAssets)"
RelativePathFilter="**.js">
<Output TaskParameter="Assets" ItemName="StaticWebAsset" />
</DefineStaticWebAssets>
</Target>
</Project>

4
src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.props

@ -1,4 +0,0 @@
<Project>
<Import Project="Microsoft.AspNetCore.StaticWebAssets.props" />
<Import Project="Avalonia.Web.Blazor.CompilationTuning.props" />
</Project>

6
src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.targets

@ -1,6 +0,0 @@
<Project>
<ItemGroup>
<NativeFileReference Include="$(HarfBuzzSharpStaticLibraryPath)\2.0.23\libHarfBuzzSharp.a" />
<NativeFileReference Include="$(SkiaSharpStaticLibraryPath)\2.0.23\libSkiaSharp.a" />
</ItemGroup>
</Project>

20
src/Web/Avalonia.Web.Blazor/AvaloniaBlazorAppBuilder.cs

@ -1,20 +0,0 @@
using Avalonia.Controls;
using Avalonia.Platform;
namespace Avalonia.Web.Blazor
{
public class AvaloniaBlazorAppBuilder : AppBuilderBase<AvaloniaBlazorAppBuilder>
{
public AvaloniaBlazorAppBuilder(IRuntimePlatform platform, Action<AvaloniaBlazorAppBuilder> platformServices)
: base(platform, platformServices)
{
}
public AvaloniaBlazorAppBuilder()
: base(new StandardRuntimePlatform(),
builder => StandardRuntimePlatformServices.Register(builder.ApplicationType!.Assembly))
{
UseWindowingSubsystem(BlazorWindowingPlatform.Register);
}
}
}

44
src/Web/Avalonia.Web.Blazor/AvaloniaView.cs

@ -0,0 +1,44 @@
using System.Runtime.InteropServices.JavaScript;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using System;
using Avalonia.Controls.ApplicationLifetimes;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using BrowserView = Avalonia.Web.AvaloniaView;
namespace Avalonia.Web.Blazor;
[SupportedOSPlatform("browser")]
public class AvaloniaView : ComponentBase
{
private BrowserView? _browserView;
private readonly string _containerId;
public AvaloniaView()
{
_containerId = "av_container_" + Guid.NewGuid();
}
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenElement(0, "div");
builder.AddAttribute(1, "id", _containerId);
builder.AddAttribute(2, "style", "width:100vw;height:100vh");
builder.CloseElement();
}
protected override async Task OnInitializedAsync()
{
if (OperatingSystem.IsBrowser())
{
await Avalonia.Web.Interop.AvaloniaModule.ImportMain();
_browserView = new BrowserView(_containerId);
if (Application.Current?.ApplicationLifetime is ISingleViewApplicationLifetime lifetime)
{
_browserView.Content = lifetime.MainView;
}
}
}
}

67
src/Web/Avalonia.Web.Blazor/AvaloniaView.razor

@ -1,67 +0,0 @@
<div id="container" @ref="_containerElement"
class="avalonia-container"
tabindex="0" oncontextmenu="return false;"
@onwheel="OnWheel"
@onkeydown="OnKeyDown"
@onkeyup="OnKeyUp"
@onkeyup:preventDefault="@KeyPreventDefault"
@onkeydown:preventDefault="@KeyPreventDefault"
@onpointerdown="OnPointerDown"
@onpointerup="OnPointerUp"
@onpointermove="OnPointerMove"
@onpointercancel="OnPointerCancel"
@onfocus="OnFocus">
<canvas id="htmlCanvas" @ref="_htmlCanvas" @attributes="AdditionalAttributes"/>
<div id="nativeControlsContainer" @ref="_nativeControlsContainer" />
<input id="inputElement" @ref="_inputElement" type="text"
spellcheck="false" onpaste="return false;"
oncopy="return false;"
oncut="return false;"
autocapitalize="none"/>
</div>
<style>
#container{
touch-action: none;
}
#htmlCanvas {
opacity: 1;
background-color: #ccc;
position: fixed;
width: 100vw;
height: 100vh;
top: 0px;
left: 0px;
z-index: 500;
}
#nativeControlsContainer {
position: fixed;
width: 100vw;
height: 100vh;
top: 0px;
left: 0px;
z-index: 700;
}
#inputElement {
padding: 0;
margin: 0;
position: absolute;
height: 20px;
z-index: 1000;
overflow: hidden;
caret-color: transparent;
border-top-style: hidden;
border-bottom-style: hidden;
border-right-style: hidden;
border-left-style: hidden;
outline: none;
background: transparent;
color: transparent;
}
</style>

500
src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs

@ -1,500 +0,0 @@
using System.Diagnostics;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Embedding;
using Avalonia.Controls.Platform;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Input.TextInput;
using Avalonia.Platform.Storage;
using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
using Avalonia.Web.Blazor.Interop;
using Avalonia.Web.Blazor.Interop.Storage;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.JSInterop;
using SkiaSharp;
using HTMLPointerEventArgs = Microsoft.AspNetCore.Components.Web.PointerEventArgs;
namespace Avalonia.Web.Blazor
{
public partial class AvaloniaView : ITextInputMethodImpl
{
private readonly RazorViewTopLevelImpl _topLevelImpl;
private EmbeddableControlRoot _topLevel;
// Interop
private SKHtmlCanvasInterop? _interop = null;
private SizeWatcherInterop? _sizeWatcher = null;
private DpiWatcherInterop? _dpiWatcher = null;
private SKHtmlCanvasInterop.GLInfo? _jsGlInfo = null;
private AvaloniaModule? _avaloniaModule = null;
private InputHelperInterop? _inputHelper = null;
private FocusHelperInterop? _canvasHelper = null;
private FocusHelperInterop? _containerHelper = null;
private NativeControlHostInterop? _nativeControlHost = null;
private StorageProviderInterop? _storageProvider = null;
private ElementReference _htmlCanvas;
private ElementReference _inputElement;
private ElementReference _containerElement;
private ElementReference _nativeControlsContainer;
private double _dpi = 1;
private SKSize _canvasSize = new (100, 100);
private GRContext? _context;
private GRGlInterface? _glInterface;
private const SKColorType ColorType = SKColorType.Rgba8888;
private bool _useGL;
private bool _inputElementFocused;
private ITextInputMethodClient? _client;
[Inject] private IJSRuntime Js { get; set; } = null!;
public AvaloniaView()
{
_topLevelImpl = new RazorViewTopLevelImpl(this);
_topLevel = new EmbeddableControlRoot(_topLevelImpl);
if (Application.Current?.ApplicationLifetime is ISingleViewApplicationLifetime lifetime)
{
_topLevel.Content = lifetime.MainView;
}
}
public bool KeyPreventDefault { get; set; }
public ITextInputMethodClient? Client => _client;
public bool IsActive => _client != null;
public bool IsComposing { get; private set; }
internal INativeControlHostImpl GetNativeControlHostImpl()
{
return _nativeControlHost ?? throw new InvalidOperationException("Blazor View wasn't initialized yet");
}
internal IStorageProvider GetStorageProvider()
{
return _storageProvider ?? throw new InvalidOperationException("Blazor View wasn't initialized yet");
}
private void OnPointerCancel(HTMLPointerEventArgs e)
{
if (e.PointerType == "touch")
{
_topLevelImpl.RawPointerEvent(RawPointerEventType.TouchCancel, e.PointerType, GetPointFromEventArgs(e),
GetModifiers(e), e.PointerId);
}
}
private void OnPointerMove(HTMLPointerEventArgs e)
{
var type = e.PointerType switch
{
"touch" => RawPointerEventType.TouchUpdate,
_ => RawPointerEventType.Move
};
_topLevelImpl.RawPointerEvent(type, e.PointerType, GetPointFromEventArgs(e), GetModifiers(e), e.PointerId);
}
private void OnPointerUp(HTMLPointerEventArgs e)
{
var type = e.PointerType switch
{
"touch" => RawPointerEventType.TouchEnd,
_ => e.Button switch
{
0 => RawPointerEventType.LeftButtonUp,
1 => RawPointerEventType.MiddleButtonUp,
2 => RawPointerEventType.RightButtonUp,
3 => RawPointerEventType.XButton1Up,
4 => RawPointerEventType.XButton2Up,
// 5 => Pen eraser button,
_ => RawPointerEventType.Move
}
};
_topLevelImpl.RawPointerEvent(type, e.PointerType, GetPointFromEventArgs(e), GetModifiers(e), e.PointerId);
}
private void OnPointerDown(HTMLPointerEventArgs e)
{
var type = e.PointerType switch
{
"touch" => RawPointerEventType.TouchBegin,
_ => e.Button switch
{
0 => RawPointerEventType.LeftButtonDown,
1 => RawPointerEventType.MiddleButtonDown,
2 => RawPointerEventType.RightButtonDown,
3 => RawPointerEventType.XButton1Down,
4 => RawPointerEventType.XButton2Down,
// 5 => Pen eraser button,
_ => RawPointerEventType.Move
}
};
_topLevelImpl.RawPointerEvent(type, e.PointerType, GetPointFromEventArgs(e), GetModifiers(e), e.PointerId);
}
private static RawPointerPoint GetPointFromEventArgs(HTMLPointerEventArgs args)
{
return new RawPointerPoint
{
Position = new Point(args.ClientX, args.ClientY),
Pressure = args.Pressure,
XTilt = args.TiltX,
YTilt = args.TiltY
// Twist = args.Twist - read from JS code directly when
};
}
private void OnWheel(WheelEventArgs e)
{
_topLevelImpl.RawMouseWheelEvent( new Point(e.ClientX, e.ClientY),
new Vector(-(e.DeltaX / 50), -(e.DeltaY / 50)), GetModifiers(e));
}
private static RawInputModifiers GetModifiers(MouseEventArgs e)
{
var modifiers = RawInputModifiers.None;
if (e.CtrlKey)
modifiers |= RawInputModifiers.Control;
if (e.AltKey)
modifiers |= RawInputModifiers.Alt;
if (e.ShiftKey)
modifiers |= RawInputModifiers.Shift;
if (e.MetaKey)
modifiers |= RawInputModifiers.Meta;
if ((e.Buttons & 1L) == 1)
modifiers |= RawInputModifiers.LeftMouseButton;
if ((e.Buttons & 2L) == 2)
modifiers |= e.Type == "pen" ? RawInputModifiers.PenBarrelButton : RawInputModifiers.RightMouseButton;
if ((e.Buttons & 4L) == 4)
modifiers |= RawInputModifiers.MiddleMouseButton;
if ((e.Buttons & 8L) == 8)
modifiers |= RawInputModifiers.XButton1MouseButton;
if ((e.Buttons & 16L) == 16)
modifiers |= RawInputModifiers.XButton2MouseButton;
if ((e.Buttons & 32L) == 32)
modifiers |= RawInputModifiers.PenEraser;
return modifiers;
}
private static RawInputModifiers GetModifiers(KeyboardEventArgs e)
{
var modifiers = RawInputModifiers.None;
if (e.CtrlKey)
modifiers |= RawInputModifiers.Control;
if (e.AltKey)
modifiers |= RawInputModifiers.Alt;
if (e.ShiftKey)
modifiers |= RawInputModifiers.Shift;
if (e.MetaKey)
modifiers |= RawInputModifiers.Meta;
return modifiers;
}
private void OnKeyDown(KeyboardEventArgs e)
{
KeyPreventDefault = _topLevelImpl.RawKeyboardEvent(RawKeyEventType.KeyDown, e.Code, e.Key, GetModifiers(e));
}
private void OnKeyUp(KeyboardEventArgs e)
{
KeyPreventDefault = _topLevelImpl.RawKeyboardEvent(RawKeyEventType.KeyUp, e.Code, e.Key, GetModifiers(e));
}
private void OnFocus(FocusEventArgs e)
{
// if focus has unexpectedly moved from the input element to the container element,
// shift it back to the input element
if (_inputElementFocused && _inputHelper is not null)
{
_inputHelper.Focus();
}
}
[Parameter(CaptureUnmatchedValues = true)]
public IReadOnlyDictionary<string, object>? AdditionalAttributes { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
AvaloniaLocator.CurrentMutable.Bind<IJSInProcessRuntime>().ToConstant((IJSInProcessRuntime)Js);
_avaloniaModule = await AvaloniaModule.ImportAsync(Js);
_canvasHelper = new FocusHelperInterop(_avaloniaModule, _htmlCanvas);
_containerHelper = new FocusHelperInterop(_avaloniaModule, _containerElement);
_inputHelper = new InputHelperInterop(_avaloniaModule, _inputElement);
_inputHelper.CompositionEvent += InputHelperOnCompositionEvent;
_inputHelper.InputEvent += InputHelperOnInputEvent;
HideIme();
_canvasHelper.SetCursor("default");
_topLevelImpl.SetCssCursor = x =>
{
_inputHelper.SetCursor(x); //macOS
_canvasHelper.SetCursor(x); //windows
};
_nativeControlHost = new NativeControlHostInterop(_avaloniaModule, _nativeControlsContainer);
_storageProvider = await StorageProviderInterop.ImportAsync(Js);
Console.WriteLine("starting html canvas setup");
_interop = new SKHtmlCanvasInterop(_avaloniaModule, _htmlCanvas, OnRenderFrame);
Console.WriteLine("Interop created");
var skiaOptions = AvaloniaLocator.Current.GetService<SkiaOptions>();
_useGL = skiaOptions?.CustomGpuFactory != null;
if (_useGL)
{
_jsGlInfo = _interop.InitGL();
Console.WriteLine("jsglinfo created - init gl");
}
else
{
var rasterInitialized = _interop.InitRaster();
Console.WriteLine("raster initialized: {0}", rasterInitialized);
}
if (_useGL)
{
// create the SkiaSharp context
if (_context == null)
{
_glInterface = GRGlInterface.Create();
_context = GRContext.CreateGl(_glInterface);
// bump the default resource cache limit
_context.SetResourceCacheLimit(skiaOptions?.MaxGpuResourceSizeBytes ?? 32 * 1024 * 1024);
Console.WriteLine("glcontext created and resource limit set");
}
_topLevelImpl.SetSurface(_context, _jsGlInfo!, ColorType,
new PixelSize((int)_canvasSize.Width, (int)_canvasSize.Height), _dpi);
}
else
{
_topLevelImpl.SetSurface(ColorType,
new PixelSize((int)_canvasSize.Width, (int)_canvasSize.Height), _dpi, _interop.PutImageData);
}
_interop.SetCanvasSize((int)(_canvasSize.Width * _dpi), (int)(_canvasSize.Height * _dpi));
Threading.Dispatcher.UIThread.Post(async () =>
{
_interop.RequestAnimationFrame(true);
_sizeWatcher = new SizeWatcherInterop(_avaloniaModule, _htmlCanvas, OnSizeChanged);
_dpiWatcher = new DpiWatcherInterop(_avaloniaModule, OnDpiChanged);
_sizeWatcher.Start();
_topLevel.Prepare();
_topLevel.Renderer.Start();
});
}
}
private void InputHelperOnInputEvent(object? sender, WebInputEventArgs e)
{
if (IsComposing)
{
return;
}
_topLevelImpl.RawTextEvent(e.Data);
e.Handled = true;
}
private void InputHelperOnCompositionEvent(object? sender, WebCompositionEventArgs e)
{
if(_client == null)
{
return;
}
switch (e.Type)
{
case WebCompositionEventArgs.WebCompositionEventType.Start:
_client.SetPreeditText(null);
IsComposing = true;
break;
case WebCompositionEventArgs.WebCompositionEventType.Update:
_client.SetPreeditText(e.Data);
break;
case WebCompositionEventArgs.WebCompositionEventType.End:
IsComposing = false;
_client.SetPreeditText(null);
_topLevelImpl.RawTextEvent(e.Data);
break;
}
}
private void OnRenderFrame()
{
if (_useGL && (_jsGlInfo == null))
{
Console.WriteLine("nothing to render");
return;
}
if (_canvasSize.Width <= 0 || _canvasSize.Height <= 0 || _dpi <= 0)
{
Console.WriteLine("nothing to render");
return;
}
ManualTriggerRenderTimer.Instance.RaiseTick();
}
public void Dispose()
{
_dpiWatcher?.Unsubscribe(OnDpiChanged);
_sizeWatcher?.Dispose();
_interop?.Dispose();
}
private void ForceBlit()
{
// Note: this is technically a hack, but it's a kinda unique use case when
// we want to blit the previous frame
// renderer doesn't have much control over the render target
// we render on the UI thread
// We also don't want to have it as a meaningful public API.
// Therefore we have InternalsVisibleTo hack here.
if (_topLevel.Renderer is CompositingRenderer dr)
{
dr.CompositionTarget.ImmediateUIThreadRender();
}
}
private void OnDpiChanged(double newDpi)
{
if (Math.Abs(_dpi - newDpi) > 0.0001)
{
_dpi = newDpi;
_interop!.SetCanvasSize((int)(_canvasSize.Width * _dpi), (int)(_canvasSize.Height * _dpi));
_topLevelImpl.SetClientSize(_canvasSize, _dpi);
ForceBlit();
}
}
private void OnSizeChanged(SKSize newSize)
{
if (_canvasSize != newSize)
{
_canvasSize = newSize;
_interop!.SetCanvasSize((int)(_canvasSize.Width * _dpi), (int)(_canvasSize.Height * _dpi));
_topLevelImpl.SetClientSize(_canvasSize, _dpi);
ForceBlit();
}
}
private void HideIme()
{
_inputHelper?.Hide();
_containerHelper?.Focus();
}
public void SetClient(ITextInputMethodClient? client)
{
if (_inputHelper is null)
{
return;
}
if(_client != null)
{
_client.SurroundingTextChanged -= SurroundingTextChanged;
}
if(client != null)
{
client.SurroundingTextChanged += SurroundingTextChanged;
}
_inputHelper.Clear();
_client = client;
if (IsActive && _client != null)
{
_inputHelper.Show();
_inputElementFocused = true;
_inputHelper.Focus();
var surroundingText = _client.SurroundingText;
_inputHelper?.SetSurroundingText(surroundingText.Text, surroundingText.AnchorOffset, surroundingText.CursorOffset);
}
else
{
_inputElementFocused = false;
HideIme();
}
}
private void SurroundingTextChanged(object? sender, EventArgs e)
{
if(_client != null)
{
var surroundingText = _client.SurroundingText;
_inputHelper?.SetSurroundingText(surroundingText.Text, surroundingText.AnchorOffset, surroundingText.CursorOffset);
}
}
public void SetCursorRect(Rect rect)
{
_inputHelper?.Focus();
var bounds = new PixelRect((int)rect.X, (int) rect.Y, (int) rect.Width, (int) rect.Height);
_inputHelper?.SetBounds(bounds, _client?.SurroundingText.CursorOffset ?? 0);
_inputHelper?.Focus();
}
public void SetOptions(TextInputOptions options)
{
}
public void Reset()
{
_inputHelper?.Clear();
_inputHelper?.SetSurroundingText("", 0, 0);
}
}
}

48
src/Web/Avalonia.Web.Blazor/BlazorSingleViewLifetime.cs

@ -1,31 +1,39 @@
using Avalonia.Controls;
using System.Runtime.Versioning;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Media;
namespace Avalonia.Web.Blazor
namespace Avalonia.Web.Blazor;
[SupportedOSPlatform("browser")]
public static class WebAppBuilder
{
public class BlazorSingleViewLifetime : ISingleViewApplicationLifetime
public static T SetupWithSingleViewLifetime<T>(
this T builder)
where T : AppBuilderBase<T>, new()
{
public Control? MainView { get; set; }
return builder.SetupWithLifetime(new BlazorSingleViewLifetime());
}
public static class WebAppBuilder
public static T UseBlazor<T>(this T builder) where T : AppBuilderBase<T>, new()
{
public static T SetupWithSingleViewLifetime<T>(
this T builder)
where T : AppBuilderBase<T>, new()
{
return builder.SetupWithLifetime(new BlazorSingleViewLifetime());
}
return builder
.UseBrowser()
.With(new BrowserPlatformOptions
{
FrameworkAssetPathResolver = new(filePath => $"/_content/Avalonia.Web.Blazor/{filePath}")
});
}
public static AvaloniaBlazorAppBuilder Configure<TApp>()
where TApp : Application, new()
{
var builder = AvaloniaBlazorAppBuilder.Configure<TApp>()
.UseSkia()
.With(new SkiaOptions { CustomGpuFactory = () => new BlazorSkiaGpu() });
public static AppBuilder Configure<TApp>()
where TApp : Application, new()
{
return AppBuilder.Configure<TApp>()
.UseBlazor();
}
return builder;
}
internal class BlazorSingleViewLifetime : ISingleViewApplicationLifetime
{
public Control? MainView { get; set; }
}
}

25
src/Web/Avalonia.Web.Blazor/BlazorSkiaGpu.cs

@ -1,25 +0,0 @@
using Avalonia.Skia;
namespace Avalonia.Web.Blazor
{
public class BlazorSkiaGpu : ISkiaGpu
{
public ISkiaGpuRenderTarget? TryCreateRenderTarget(IEnumerable<object> surfaces)
{
foreach (var surface in surfaces)
{
if (surface is BlazorSkiaSurface blazorSkiaSurface)
{
return new BlazorSkiaGpuRenderTarget(blazorSkiaSurface);
}
}
return null;
}
public ISkiaSurface? TryCreateSurface(PixelSize size, ISkiaGpuRenderSession session)
{
return null;
}
}
}

37
src/Web/Avalonia.Web.Blazor/BlazorSkiaGpuRenderSession.cs

@ -1,37 +0,0 @@
using Avalonia.Skia;
using SkiaSharp;
namespace Avalonia.Web.Blazor
{
internal class BlazorSkiaGpuRenderSession : ISkiaGpuRenderSession
{
private readonly SKSurface _surface;
public BlazorSkiaGpuRenderSession(BlazorSkiaSurface blazorSkiaSurface, GRBackendRenderTarget renderTarget)
{
_surface = SKSurface.Create(blazorSkiaSurface.Context, renderTarget, blazorSkiaSurface.Origin, blazorSkiaSurface.ColorType);
GrContext = blazorSkiaSurface.Context;
ScaleFactor = blazorSkiaSurface.Scaling;
SurfaceOrigin = blazorSkiaSurface.Origin;
}
public void Dispose()
{
_surface.Flush();
_surface.Dispose();
}
public GRContext GrContext { get; }
public SKSurface SkSurface => _surface;
public double ScaleFactor { get; }
public GRSurfaceOrigin SurfaceOrigin { get; }
}
}

39
src/Web/Avalonia.Web.Blazor/BlazorSkiaGpuRenderTarget.cs

@ -1,39 +0,0 @@
using Avalonia.Skia;
using SkiaSharp;
namespace Avalonia.Web.Blazor
{
internal class BlazorSkiaGpuRenderTarget : ISkiaGpuRenderTarget
{
private readonly GRBackendRenderTarget _renderTarget;
private readonly BlazorSkiaSurface _blazorSkiaSurface;
private readonly PixelSize _size;
public BlazorSkiaGpuRenderTarget(BlazorSkiaSurface blazorSkiaSurface)
{
_size = blazorSkiaSurface.Size;
var glFbInfo = new GRGlFramebufferInfo(blazorSkiaSurface.GlInfo.FboId, blazorSkiaSurface.ColorType.ToGlSizedFormat());
{
_blazorSkiaSurface = blazorSkiaSurface;
_renderTarget = new GRBackendRenderTarget(
(int)(blazorSkiaSurface.Size.Width * blazorSkiaSurface.Scaling),
(int)(blazorSkiaSurface.Size.Height * blazorSkiaSurface.Scaling),
blazorSkiaSurface.GlInfo.Samples,
blazorSkiaSurface.GlInfo.Stencils, glFbInfo);
}
}
public void Dispose()
{
_renderTarget.Dispose();
}
public ISkiaGpuRenderSession BeginRenderingSession()
{
return new BlazorSkiaGpuRenderSession(_blazorSkiaSurface, _renderTarget);
}
public bool IsCorrupted => _blazorSkiaSurface.Size != _size;
}
}

87
src/Web/Avalonia.Web.Blazor/BlazorSkiaRasterSurface.cs

@ -1,87 +0,0 @@
using System.Runtime.InteropServices;
using Avalonia.Controls.Platform.Surfaces;
using Avalonia.Platform;
using Avalonia.Skia;
using SkiaSharp;
namespace Avalonia.Web.Blazor
{
internal class BlazorSkiaRasterSurface : IBlazorSkiaSurface, IFramebufferPlatformSurface, IDisposable
{
public SKColorType ColorType { get; set; }
public PixelSize Size { get; set; }
public double Scaling { get; set; }
private FramebufferData? _fbData;
private readonly Action<IntPtr, SKSizeI> _blitCallback;
private readonly Action _onDisposeAction;
public BlazorSkiaRasterSurface(
SKColorType colorType, PixelSize size, double scaling, Action<IntPtr, SKSizeI> blitCallback)
{
ColorType = colorType;
Size = size;
Scaling = scaling;
_blitCallback = blitCallback;
_onDisposeAction = Blit;
}
public void Dispose()
{
_fbData?.Dispose();
_fbData = null;
}
public ILockedFramebuffer Lock()
{
var bytesPerPixel = 4; // TODO: derive from ColorType
var dpi = Scaling * 96.0;
var width = (int)(Size.Width * Scaling);
var height = (int)(Size.Height * Scaling);
if (_fbData is null || _fbData?.Size.Width != width || _fbData?.Size.Height != height)
{
_fbData?.Dispose();
_fbData = new FramebufferData(width, height, bytesPerPixel);
}
var pixelFormat = ColorType.ToPixelFormat();
var data = _fbData.Value;
return new LockedFramebuffer(
data.Address, data.Size, data.RowBytes,
new Vector(dpi, dpi), pixelFormat, _onDisposeAction);
}
private void Blit()
{
if (_fbData != null)
{
var data = _fbData.Value;
_blitCallback(data.Address, new SKSizeI(data.Size.Width, data.Size.Height));
}
}
private readonly struct FramebufferData
{
public PixelSize Size { get; }
public int RowBytes { get; }
public IntPtr Address { get; }
public FramebufferData(int width, int height, int bytesPerPixel)
{
Size = new PixelSize(width, height);
RowBytes = width * bytesPerPixel;
Address = Marshal.AllocHGlobal(width * height * bytesPerPixel);
}
public void Dispose()
{
Marshal.FreeHGlobal(Address);
}
}
}
}

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

Loading…
Cancel
Save