diff --git a/Directory.Build.props b/Directory.Build.props
index f124456eab1..c6ed387d66a 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -8,7 +8,7 @@
false
False
- 12
+ 14.0
true
true
true
diff --git a/api/Avalonia.nupkg.xml b/api/Avalonia.nupkg.xml
index fbf22358ed5..f5864e85cf0 100644
--- a/api/Avalonia.nupkg.xml
+++ b/api/Avalonia.nupkg.xml
@@ -1,4 +1,4 @@
-
+
@@ -181,4 +181,4 @@
baseline/Avalonia/lib/netstandard2.0/Avalonia.OpenGL.dll
current/Avalonia/lib/netstandard2.0/Avalonia.OpenGL.dll
-
\ No newline at end of file
+
diff --git a/azure-pipelines-integrationtests.yml b/azure-pipelines-integrationtests.yml
index b34def779f8..89b6a3ac533 100644
--- a/azure-pipelines-integrationtests.yml
+++ b/azure-pipelines-integrationtests.yml
@@ -5,13 +5,13 @@ jobs:
steps:
- task: UseDotNet@2
- displayName: 'Use .NET 6.0 Runtime'
+ displayName: 'Use .NET 8.0 Runtime'
inputs:
packageType: runtime
- version: 6.0.x
+ version: 8.0.x
- task: UseDotNet@2
- displayName: 'Use .NET 8.0 SDK'
+ displayName: 'Use .NET 10.0 SDK'
inputs:
packageType: sdk
useGlobalJson: true
@@ -31,11 +31,10 @@ jobs:
pkill IntegrationTestApp
sudo xcode-select -s /Applications/Xcode_15.2.app/Contents/Developer
./build.sh CompileNative
- sudo xcode-select -s /Applications/Xcode_14.3.app/Contents/Developer
rm -rf $(osascript -e "POSIX path of (path to application id \"net.avaloniaui.avalonia.integrationtestapp\")")
pkill IntegrationTestApp
./samples/IntegrationTestApp/bundle.sh
- open -n ./samples/IntegrationTestApp/bin/Debug/net8.0/osx-$arch/publish/IntegrationTestApp.app
+ open -n ./samples/IntegrationTestApp/bin/Debug/net10.0/osx-$arch/publish/IntegrationTestApp.app
pkill IntegrationTestApp
displayName: 'Build IntegrationTestApp'
@@ -57,17 +56,17 @@ jobs:
- job: Windows
pool:
- vmImage: 'windows-2022'
+ vmImage: 'windows-2025'
steps:
- task: UseDotNet@2
- displayName: 'Use .NET 6.0 Runtime'
+ displayName: 'Use .NET 8.0 Runtime'
inputs:
packageType: runtime
- version: 6.0.x
+ version: 8.0.x
- task: UseDotNet@2
- displayName: 'Use .NET 8.0 SDK'
+ displayName: 'Use .NET 10.0 SDK'
inputs:
packageType: sdk
useGlobalJson: true
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 956bcde6d7b..06da4bcd2b6 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -2,12 +2,12 @@ jobs:
- job: GetPRNumber
pool:
- vmImage: 'ubuntu-22.04'
+ vmImage: 'ubuntu-24.04'
variables:
SolutionDir: '$(Build.SourcesDirectory)'
steps:
- task: UseDotNet@2
- displayName: 'Use .NET 8.0 SDK'
+ displayName: 'Use .NET 10.0 SDK'
inputs:
packageType: sdk
useGlobalJson: true
@@ -23,16 +23,16 @@ jobs:
- job: Linux
pool:
- vmImage: 'ubuntu-22.04'
+ vmImage: 'ubuntu-24.04'
steps:
- task: UseDotNet@2
- displayName: 'Use .NET 6.0 Runtime'
+ displayName: 'Use .NET 8.0 Runtime'
inputs:
packageType: runtime
- version: 6.0.x
+ version: 8.0.x
- task: UseDotNet@2
- displayName: 'Use .NET 8.0 SDK'
+ displayName: 'Use .NET 10.0 SDK'
inputs:
packageType: sdk
useGlobalJson: true
@@ -62,16 +62,16 @@ jobs:
variables:
SolutionDir: '$(Build.SourcesDirectory)'
pool:
- vmImage: 'macos-13'
+ vmImage: 'macos-15'
steps:
- task: UseDotNet@2
- displayName: 'Use .NET 6.0 Runtime'
+ displayName: 'Use .NET 8.0 Runtime'
inputs:
packageType: runtime
- version: 6.0.x
+ version: 8.0.x
- task: UseDotNet@2
- displayName: 'Use .NET 8.0 SDK'
+ displayName: 'Use .NET 10.0 SDK'
inputs:
packageType: sdk
useGlobalJson: true
@@ -95,11 +95,11 @@ jobs:
inputs:
actions: 'build'
scheme: ''
- sdk: 'macosx14.2'
+ sdk: 'macosx26.0'
configuration: 'Release'
xcWorkspacePath: '**/*.xcodeproj/project.xcworkspace'
xcodeVersion: 'specifyPath' # Options: 8, 9, default, specifyPath
- xcodeDeveloperDir: '/Applications/Xcode_15.2.app/Contents/Developer'
+ xcodeDeveloperDir: '/Applications/Xcode_26.0.app/Contents/Developer'
args: '-derivedDataPath ./'
- task: CmdLine@2
@@ -134,18 +134,18 @@ jobs:
- job: Windows
pool:
- vmImage: 'windows-2022'
+ vmImage: 'windows-2025'
variables:
SolutionDir: '$(Build.SourcesDirectory)'
steps:
- task: UseDotNet@2
- displayName: 'Use .NET 6.0 Runtime'
+ displayName: 'Use .NET 8.0 Runtime'
inputs:
packageType: runtime
- version: 6.0.x
+ version: 8.0.x
- task: UseDotNet@2
- displayName: 'Use .NET 8.0 SDK'
+ displayName: 'Use .NET 10.0 SDK'
inputs:
packageType: sdk
useGlobalJson: true
@@ -160,7 +160,7 @@ jobs:
displayName: 'Install Nuke'
inputs:
script: |
- dotnet tool install --global Nuke.GlobalTool --version 6.2.1
+ dotnet tool install --global Nuke.GlobalTool --version 9.0.4
- task: CmdLine@2
displayName: 'Run Nuke'
diff --git a/build/Base.props b/build/Base.props
index 0e667f105b9..ab5853fcfa9 100644
--- a/build/Base.props
+++ b/build/Base.props
@@ -1,12 +1,8 @@
-
-
-
-
-
-
-
+
-
+
+
+
diff --git a/build/Moq.props b/build/Moq.props
index 357f0c9a5f6..fc659f7f5fc 100644
--- a/build/Moq.props
+++ b/build/Moq.props
@@ -1,5 +1,5 @@
-
+
diff --git a/build/TargetFrameworks.props b/build/TargetFrameworks.props
index f14a3876fff..96541e7ecf5 100644
--- a/build/TargetFrameworks.props
+++ b/build/TargetFrameworks.props
@@ -1,17 +1,17 @@
- net8.0
+ net10.0
$(AvsCurrentTargetFramework)-windows
$(AvsCurrentTargetFramework)-macos
- $(AvsCurrentTargetFramework)-android34.0
- $(AvsCurrentTargetFramework)-maccatalyst17.0
- $(AvsCurrentTargetFramework)-ios17.0
- $(AvsCurrentTargetFramework)-tvos17.0
+ $(AvsCurrentTargetFramework)-android36.0
+ $(AvsCurrentTargetFramework)-maccatalyst26.0
+ $(AvsCurrentTargetFramework)-ios26.0
+ $(AvsCurrentTargetFramework)-tvos26.0
$(AvsCurrentTargetFramework)-browser
- net6.0
- net6.0-windows
+ net8.0
+ net8.0-windows
@@ -20,7 +20,7 @@
13.0
13.0
13.1
- 21.0
+ 24.0
10.15
diff --git a/build/UnitTests.NetCore.targets b/build/UnitTests.NetCore.targets
index 42da8e4ab17..19b2253f4ff 100644
--- a/build/UnitTests.NetCore.targets
+++ b/build/UnitTests.NetCore.targets
@@ -3,7 +3,4 @@
false
true
-
-
-
-
\ No newline at end of file
+
diff --git a/build/XUnit.props b/build/XUnit.props
index b4e9708ecde..4b00869d5b6 100644
--- a/build/XUnit.props
+++ b/build/XUnit.props
@@ -8,7 +8,7 @@
-
+
$(MSBuildThisFileDirectory)\avalonia.snk
diff --git a/external/XamlX b/external/XamlX
index 83567b8a50b..99a49740bd6 160000
--- a/external/XamlX
+++ b/external/XamlX
@@ -1 +1 @@
-Subproject commit 83567b8a50bbf612a0b1420a3dc6d8e8ebee2399
+Subproject commit 99a49740bd6a587b1852337764741ec280e201d6
diff --git a/global.json b/global.json
index f496cffc503..7fed696458a 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "8.0.411",
+ "version": "10.0.100-rc.2.25502.107",
"rollForward": "latestFeature"
},
"msbuild-sdks": {
diff --git a/nukebuild/ApiDiffHelper.cs b/nukebuild/ApiDiffHelper.cs
index 1d1f1b1b320..4a516305576 100644
--- a/nukebuild/ApiDiffHelper.cs
+++ b/nukebuild/ApiDiffHelper.cs
@@ -326,25 +326,11 @@ public static async Task DownloadAndExtractPackagesAsync(
var frameworkDiffs = new List();
- // Handle frameworks that exist only in the current package.
- foreach (var framework in currentFolderNames.Keys.Except(baselineFolderNames.Keys))
- {
- var folderName = currentFolderNames[framework];
- Directory.CreateDirectory(baselineFolderPath / folderName);
- baselineFolderNames.Add(framework, folderName);
- }
-
- // Handle frameworks that exist only for the baseline package.
- foreach (var framework in baselineFolderNames.Keys.Except(currentFolderNames.Keys))
- {
- var folderName = baselineFolderNames[framework];
- Directory.CreateDirectory(currentFolderPath / folderName);
- currentFolderNames.Add(framework, folderName);
- }
-
foreach (var (framework, currentFolderName) in currentFolderNames)
{
- var baselineFolderName = baselineFolderNames[framework];
+ // Ignore new frameworks that didn't exist in the baseline package. Empty folders make the ApiDiff tool crash.
+ if (!baselineFolderNames.TryGetValue(framework, out var baselineFolderName))
+ continue;
frameworkDiffs.Add(new FrameworkDiffInfo(
framework,
diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs
index b0d8106d325..4117ac29089 100644
--- a/nukebuild/Build.cs
+++ b/nukebuild/Build.cs
@@ -240,11 +240,11 @@ void RunCoreTest(string projectName, Action runTest)
var tfm = fw;
if (tfm == "$(AvsCurrentTargetFramework)")
{
- tfm = "net8.0";
+ tfm = "net10.0";
}
if (tfm == "$(AvsLegacyTargetFrameworks)")
{
- tfm = "net6.0";
+ tfm = "net8.0";
}
if (tfm.StartsWith("net4")
@@ -414,13 +414,13 @@ void DoMemoryTest()
ApiDiffHelper.MergePackageMarkdownDiffFiles(outputFolderPath, baselineDisplay, currentDisplay);
});
-
+
Target RunTests => _ => _
.DependsOn(RunCoreLibsTests)
.DependsOn(RunRenderTests)
.DependsOn(RunToolsTests)
- .DependsOn(RunHtmlPreviewerTests)
- .DependsOn(RunLeakTests);
+ .DependsOn(RunHtmlPreviewerTests);
+ //.DependsOn(RunLeakTests); // dotMemory Unit doesn't support modern .NET versions, see https://youtrack.jetbrains.com/issue/DMU-300/
Target Package => _ => _
.DependsOn(RunTests)
diff --git a/nukebuild/_build.csproj b/nukebuild/_build.csproj
index 2ea83ead719..2dba75782b4 100644
--- a/nukebuild/_build.csproj
+++ b/nukebuild/_build.csproj
@@ -21,8 +21,8 @@
-
-
+
+
diff --git a/packages/Avalonia/AvaloniaPrivateApis.targets b/packages/Avalonia/AvaloniaPrivateApis.targets
index 5f69187d923..47219535cc9 100644
--- a/packages/Avalonia/AvaloniaPrivateApis.targets
+++ b/packages/Avalonia/AvaloniaPrivateApis.targets
@@ -13,7 +13,7 @@
- net6.0
+ net8.0
netstandard2.0
diff --git a/packages/Avalonia/AvaloniaSingleProject.targets b/packages/Avalonia/AvaloniaSingleProject.targets
index a776f12a7df..25125b26e44 100644
--- a/packages/Avalonia/AvaloniaSingleProject.targets
+++ b/packages/Avalonia/AvaloniaSingleProject.targets
@@ -98,7 +98,7 @@
13.0
10.15
13.1
- 21.0
+ 24.0
6.5
diff --git a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
index 958725eed5b..f60ba69395e 100644
--- a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
+++ b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
@@ -26,7 +26,7 @@
-
+
diff --git a/samples/ControlCatalog.Browser.Blazor/ControlCatalog.Browser.Blazor.csproj b/samples/ControlCatalog.Browser.Blazor/ControlCatalog.Browser.Blazor.csproj
index 2950028e687..763ab26cabf 100644
--- a/samples/ControlCatalog.Browser.Blazor/ControlCatalog.Browser.Blazor.csproj
+++ b/samples/ControlCatalog.Browser.Blazor/ControlCatalog.Browser.Blazor.csproj
@@ -9,8 +9,8 @@
-
-
+
+
diff --git a/samples/ControlCatalog.MacCatalyst/ControlCatalog.MacCatalyst.csproj b/samples/ControlCatalog.MacCatalyst/ControlCatalog.MacCatalyst.csproj
index 0a1329e2e3a..954ed20d99b 100644
--- a/samples/ControlCatalog.MacCatalyst/ControlCatalog.MacCatalyst.csproj
+++ b/samples/ControlCatalog.MacCatalyst/ControlCatalog.MacCatalyst.csproj
@@ -5,7 +5,7 @@
manual
$(AvsCurrentMacCatalystTargetFramework)
- 14.0
+ 15.0
true
diff --git a/samples/Directory.Build.props b/samples/Directory.Build.props
index 3a61d3fff97..169239237f1 100644
--- a/samples/Directory.Build.props
+++ b/samples/Directory.Build.props
@@ -4,7 +4,7 @@
false
$(MSBuildThisFileDirectory)..\src\tools\Avalonia.Designer.HostApp\bin\Debug\netstandard2.0\Avalonia.Designer.HostApp.dll
false
- 12
+ 14.0
$(NoWarn);CS8002
diff --git a/samples/IntegrationTestApp/bundle.sh b/samples/IntegrationTestApp/bundle.sh
index 2b480723c2a..6f49bdbee36 100755
--- a/samples/IntegrationTestApp/bundle.sh
+++ b/samples/IntegrationTestApp/bundle.sh
@@ -9,4 +9,4 @@ arch="arm64"
fi
dotnet restore -r osx-$arch
-dotnet msbuild -t:BundleApp -p:RuntimeIdentifier=osx-$arch
+dotnet msbuild -t:BundleApp -p:RuntimeIdentifier=osx-$arch -p:SelfContained=true
diff --git a/samples/XEmbedSample/XEmbedSample.csproj b/samples/XEmbedSample/XEmbedSample.csproj
index 01ea7432db0..a6e754692db 100644
--- a/samples/XEmbedSample/XEmbedSample.csproj
+++ b/samples/XEmbedSample/XEmbedSample.csproj
@@ -1,20 +1,20 @@
-
- Exe
- net6.0
- enable
- enable
- true
-
+
+ Exe
+ $(AvsCurrentTargetFramework)
+ enable
+ enable
+ true
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
diff --git a/src/Android/Avalonia.Android/Automation/ToggleNodeInfoProvider.cs b/src/Android/Avalonia.Android/Automation/ToggleNodeInfoProvider.cs
index 907bd2e3a0b..24ce3fa120e 100644
--- a/src/Android/Avalonia.Android/Automation/ToggleNodeInfoProvider.cs
+++ b/src/Android/Avalonia.Android/Automation/ToggleNodeInfoProvider.cs
@@ -1,5 +1,4 @@
-using System.Reflection;
-using Android.OS;
+using Android.OS;
using AndroidX.Core.View.Accessibility;
using AndroidX.CustomView.Widget;
using Avalonia.Automation.Peers;
@@ -9,8 +8,6 @@ namespace Avalonia.Android.Automation
{
internal class ToggleNodeInfoProvider : NodeInfoProvider
{
- private PropertyInfo? _checkedProperty;
-
public ToggleNodeInfoProvider(ExploreByTouchHelper owner, AutomationPeer peer, int virtualViewId) :
base(owner, peer, virtualViewId)
{
@@ -35,25 +32,12 @@ public override void PopulateNodeInfo(AccessibilityNodeInfoCompat nodeInfo)
nodeInfo.Clickable = true;
IToggleProvider provider = GetProvider();
-
- _checkedProperty ??= nodeInfo.GetType().GetProperty(nameof(nodeInfo.Checked));
- if (_checkedProperty?.PropertyType == typeof(int))
- {
- // Needed for Xamarin.AndroidX.Core 1.17+
- _checkedProperty.SetValue(this,
- provider.ToggleState switch
- {
- ToggleState.On => 1,
- ToggleState.Indeterminate => 2,
- _ => 0
- });
- }
- else if (_checkedProperty?.PropertyType == typeof(bool))
+ nodeInfo.Checked = provider.ToggleState switch
{
- // Needed for Xamarin.AndroidX.Core < 1.17
- _checkedProperty.SetValue(this, provider.ToggleState == ToggleState.On);
- }
-
+ ToggleState.On => 1,
+ ToggleState.Indeterminate => 2,
+ _ => 0
+ };
nodeInfo.Checkable = true;
}
}
diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj
index 2fb849ee0de..97acf3d012c 100644
--- a/src/Android/Avalonia.Android/Avalonia.Android.csproj
+++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj
@@ -7,8 +7,8 @@
-
-
+
+
diff --git a/src/Android/Avalonia.Android/AvaloniaAccessHelper.cs b/src/Android/Avalonia.Android/AvaloniaAccessHelper.cs
index 0b5a7e03c41..faacff7554e 100644
--- a/src/Android/Avalonia.Android/AvaloniaAccessHelper.cs
+++ b/src/Android/Avalonia.Android/AvaloniaAccessHelper.cs
@@ -1,7 +1,5 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
-using Android.Content.PM;
using Android.OS;
using AndroidX.Core.View.Accessibility;
using AndroidX.CustomView.Widget;
@@ -15,20 +13,6 @@ namespace Avalonia.Android
{
internal class AvaloniaAccessHelper : ExploreByTouchHelper
{
- private const string AUTOMATION_PROVIDER_NAMESPACE = "Avalonia.Automation.Provider";
-
- private static readonly IReadOnlyDictionary
- s_providerTypeInitializers = new Dictionary()
- {
- { typeof(IExpandCollapseProvider).FullName!, (owner, peer, id) => new ExpandCollapseNodeInfoProvider(owner, peer, id) },
- { typeof(IInvokeProvider).FullName!, (owner, peer, id) => new InvokeNodeInfoProvider(owner, peer, id) },
- { typeof(IRangeValueProvider).FullName!, (owner, peer, id) => new RangeValueNodeInfoProvider(owner, peer, id) },
- { typeof(IScrollProvider).FullName!, (owner, peer, id) => new ScrollNodeInfoProvider(owner, peer, id) },
- { typeof(ISelectionItemProvider).FullName!, (owner, peer, id) => new SelectionItemNodeInfoProvider(owner, peer, id) },
- { typeof(IToggleProvider).FullName!, (owner, peer, id) => new ToggleNodeInfoProvider(owner, peer, id) },
- { typeof(IValueProvider).FullName!, (owner, peer, id) => new ValueNodeInfoProvider(owner, peer, id) },
- };
-
private readonly Dictionary _peers;
private readonly Dictionary _peerIds;
@@ -96,17 +80,20 @@ private HashSet GetOrCreateNodeInfoProvidersFromPeer(Automati
}
};
- Type peerType = peer.GetType();
- IEnumerable providerTypes = peerType.GetInterfaces()
- .Where(x => x.Namespace!.StartsWith(AUTOMATION_PROVIDER_NAMESPACE));
- foreach (Type providerType in providerTypes)
- {
- if (s_providerTypeInitializers.TryGetValue(providerType.FullName!, out NodeInfoProviderInitializer? ctor))
- {
- INodeInfoProvider nodeInfoProvider = ctor(this, peer, peerViewId);
- nodeInfoProviders.Add(nodeInfoProvider);
- }
- }
+ if (peer is IExpandCollapseProvider)
+ nodeInfoProviders.Add(new ExpandCollapseNodeInfoProvider(this, peer, peerViewId));
+ if (peer is IInvokeProvider)
+ nodeInfoProviders.Add(new InvokeNodeInfoProvider(this, peer, peerViewId));
+ if (peer is IRangeValueProvider)
+ nodeInfoProviders.Add(new RangeValueNodeInfoProvider(this, peer, peerViewId));
+ if (peer is IScrollProvider)
+ nodeInfoProviders.Add(new ScrollNodeInfoProvider(this, peer, peerViewId));
+ if (peer is ISelectionItemProvider)
+ nodeInfoProviders.Add(new SelectionItemNodeInfoProvider(this, peer, peerViewId));
+ if (peer is IToggleProvider)
+ nodeInfoProviders.Add(new ToggleNodeInfoProvider(this, peer, peerViewId));
+ if (peer is IValueProvider)
+ nodeInfoProviders.Add(new ValueNodeInfoProvider(this, peer, peerViewId));
}
virtualViewId = peerViewId;
@@ -151,9 +138,9 @@ protected override bool OnPerformActionForVirtualView(int virtualViewId, int act
.Aggregate(false, (a, b) => a | b);
}
- protected override void OnPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfoCompat nodeInfo)
+ protected override void OnPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfoCompat? nodeInfo)
{
- if (!_peers.TryGetValue(virtualViewId, out AutomationPeer? peer))
+ if (nodeInfo is null || !_peers.TryGetValue(virtualViewId, out AutomationPeer? peer))
{
return; // BAIL!! No work to be done
}
diff --git a/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs b/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs
index 8a3685b65e2..4a4159965c0 100644
--- a/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs
+++ b/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs
@@ -127,10 +127,13 @@ public Thickness SafeAreaPadding
WindowInsetsCompat.Type.StatusBars() | WindowInsetsCompat.Type.NavigationBars() |
WindowInsetsCompat.Type.DisplayCutout() : 0);
- return new Thickness(inset.Left / renderScaling,
- inset.Top / renderScaling,
- inset.Right / renderScaling,
- inset.Bottom / renderScaling);
+ if (inset is not null)
+ {
+ return new Thickness(inset.Left / renderScaling,
+ inset.Top / renderScaling,
+ inset.Right / renderScaling,
+ inset.Bottom / renderScaling);
+ }
}
return default;
@@ -145,9 +148,10 @@ public Rect OccludedRect
if (insets != null)
{
- var navbarInset = insets.GetInsets(WindowInsetsCompat.Type.NavigationBars()).Bottom;
+ var navbarInset = insets.GetInsets(WindowInsetsCompat.Type.NavigationBars())?.Bottom ?? 0;
+ var imeInset = insets.GetInsets(WindowInsetsCompat.Type.Ime())?.Bottom ?? 0;
- var height = Math.Max((float)((insets.GetInsets(WindowInsetsCompat.Type.Ime()).Bottom - navbarInset) / _topLevel.RenderScaling), 0);
+ var height = Math.Max((float)((imeInset - navbarInset) / _topLevel.RenderScaling), 0);
return new Rect(0, _topLevel.ClientSize.Height - SafeAreaPadding.Bottom - height, _topLevel.ClientSize.Width, height);
}
@@ -156,7 +160,7 @@ public Rect OccludedRect
}
}
- public WindowInsetsCompat OnApplyWindowInsets(View v, WindowInsetsCompat insets)
+ public WindowInsetsCompat? OnApplyWindowInsets(View? v, WindowInsetsCompat? insets)
{
insets = ViewCompat.OnApplyWindowInsets(v, insets);
NotifySafeAreaChanged(SafeAreaPadding);
@@ -166,15 +170,14 @@ public WindowInsetsCompat OnApplyWindowInsets(View v, WindowInsetsCompat insets)
_previousRect = OccludedRect;
}
- State = insets.IsVisible(WindowInsetsCompat.Type.Ime()) ? InputPaneState.Open : InputPaneState.Closed;
+ State = insets is not null && insets.IsVisible(WindowInsetsCompat.Type.Ime()) ? InputPaneState.Open : InputPaneState.Closed;
// Workaround for weird inset values for android 11
if(Build.VERSION.SdkInt == BuildVersionCodes.R)
{
- var imeInset = insets.GetInsets(WindowInsetsCompat.Type.Ime());
- if(_previousImeInset == default)
- _previousImeInset = imeInset;
- if(imeInset.Bottom != _previousImeInset.Bottom)
+ var imeInset = insets?.GetInsets(WindowInsetsCompat.Type.Ime());
+ _previousImeInset ??= imeInset;
+ if ((imeInset?.Bottom ?? 0) != (_previousImeInset?.Bottom ?? 0))
{
NotifyStateChanged(State, _previousRect, OccludedRect, TimeSpan.Zero, null);
}
@@ -319,18 +322,18 @@ internal void ApplyStatusBarState()
SystemBarColor = _systemBarColor;
}
- public override WindowInsetsAnimationCompat.BoundsCompat OnStart(WindowInsetsAnimationCompat animation, WindowInsetsAnimationCompat.BoundsCompat bounds)
+ public override WindowInsetsAnimationCompat.BoundsCompat? OnStart(WindowInsetsAnimationCompat? animation, WindowInsetsAnimationCompat.BoundsCompat? bounds)
{
- if ((animation.TypeMask & WindowInsetsCompat.Type.Ime()) != 0)
+ if (animation is not null && bounds is not null && (animation.TypeMask & WindowInsetsCompat.Type.Ime()) != 0)
{
var insets = ViewCompat.GetRootWindowInsets(Window.DecorView);
if (insets != null)
{
- var navbarInset = insets.GetInsets(WindowInsetsCompat.Type.NavigationBars()).Bottom;
- var height = Math.Max(0, (float)((bounds.LowerBound.Bottom - navbarInset) / _topLevel.RenderScaling));
+ var navbarInset = insets.GetInsets(WindowInsetsCompat.Type.NavigationBars())?.Bottom ?? 0;
+ var height = Math.Max(0, (float)(((bounds.LowerBound?.Bottom ?? 0) - navbarInset) / _topLevel.RenderScaling));
var upperRect = new Rect(0, _topLevel.ClientSize.Height - SafeAreaPadding.Bottom - height, _topLevel.ClientSize.Width, height);
- height = Math.Max(0, (float)((bounds.UpperBound.Bottom - navbarInset) / _topLevel.RenderScaling));
+ height = Math.Max(0, (float)(((bounds.UpperBound?.Bottom ?? 0) - navbarInset) / _topLevel.RenderScaling));
var lowerRect = new Rect(0, _topLevel.ClientSize.Height - SafeAreaPadding.Bottom - height, _topLevel.ClientSize.Width, height);
var duration = TimeSpan.FromMilliseconds(animation.DurationMillis);
@@ -344,7 +347,7 @@ public override WindowInsetsAnimationCompat.BoundsCompat OnStart(WindowInsetsAni
return base.OnStart(animation, bounds);
}
- public override WindowInsetsCompat OnProgress(WindowInsetsCompat insets, IList runningAnimations)
+ public override WindowInsetsCompat? OnProgress(WindowInsetsCompat? insets, IList? runningAnimations)
{
return insets;
}
diff --git a/src/Android/Avalonia.Android/Platform/AndroidScreens.cs b/src/Android/Avalonia.Android/Platform/AndroidScreens.cs
index 95d2530edc4..3f1f9bf44e4 100644
--- a/src/Android/Avalonia.Android/Platform/AndroidScreens.cs
+++ b/src/Android/Avalonia.Android/Platform/AndroidScreens.cs
@@ -32,11 +32,18 @@ public void Refresh(Context context)
var metrics = metricsCalc.ComputeMaximumWindowMetrics(displayContext);
Bounds = new(metrics.Bounds.Left, metrics.Bounds.Top, metrics.Bounds.Width(), metrics.Bounds.Height());
- var inset = metrics.WindowInsets.GetInsets(WindowInsetsCompat.Type.SystemBars());
- WorkingArea = new(Bounds.X + inset.Left,
- Bounds.Y + inset.Top,
- Bounds.Width - (inset.Left + inset.Right),
- Bounds.Height - (inset.Top + inset.Bottom));
+ var windowInsets = new WindowInsetsCompat.Builder().Build();
+ if (windowInsets?.GetInsets(WindowInsetsCompat.Type.SystemBars()) is { } inset)
+ {
+ WorkingArea = new(Bounds.X + inset.Left,
+ Bounds.Y + inset.Top,
+ Bounds.Width - (inset.Left + inset.Right),
+ Bounds.Height - (inset.Top + inset.Bottom));
+ }
+ else
+ {
+ WorkingArea = Bounds;
+ }
if (context.Resources?.Configuration is { } config)
{
diff --git a/src/Avalonia.Base/Data/Core/BindingExpression.cs b/src/Avalonia.Base/Data/Core/BindingExpression.cs
index ca29dd6ffa4..a51ee5bf8a5 100644
--- a/src/Avalonia.Base/Data/Core/BindingExpression.cs
+++ b/src/Avalonia.Base/Data/Core/BindingExpression.cs
@@ -190,6 +190,9 @@ public override void UpdateTarget()
/// The null target value.
/// Whether to allow reflection for target type conversion.
[RequiresUnreferencedCode(TrimmingMessages.ExpressionNodeRequiresUnreferencedCodeMessage)]
+#if NET8_0_OR_GREATER
+ [RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
+#endif
internal static BindingExpression Create(
TIn source,
Expression> expression,
diff --git a/src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/DynamicPluginStreamNode.cs b/src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/DynamicPluginStreamNode.cs
index f6c692e6859..dd8c0e1a63d 100644
--- a/src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/DynamicPluginStreamNode.cs
+++ b/src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/DynamicPluginStreamNode.cs
@@ -7,6 +7,9 @@
namespace Avalonia.Data.Core.ExpressionNodes.Reflection;
[RequiresUnreferencedCode(TrimmingMessages.ExpressionNodeRequiresUnreferencedCodeMessage)]
+#if NET8_0_OR_GREATER
+[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
+#endif
internal sealed class DynamicPluginStreamNode : ExpressionNode
{
private IDisposable? _subscription;
diff --git a/src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/ExpressionTreeIndexerNode.cs b/src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/ExpressionTreeIndexerNode.cs
index e720aa6e693..dfb83fb10d9 100644
--- a/src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/ExpressionTreeIndexerNode.cs
+++ b/src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/ExpressionTreeIndexerNode.cs
@@ -16,6 +16,9 @@ internal sealed class ExpressionTreeIndexerNode : CollectionNodeBase, ISettableN
private readonly Delegate _getDelegate;
private readonly Delegate _firstArgumentDelegate;
+#if NET8_0_OR_GREATER
+ [RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
+#endif
public ExpressionTreeIndexerNode(IndexExpression expression)
{
var valueParameter = Expression.Parameter(expression.Type);
diff --git a/src/Avalonia.Base/Data/Core/Parsers/BindingExpressionVisitor.cs b/src/Avalonia.Base/Data/Core/Parsers/BindingExpressionVisitor.cs
index 39d6ffcab66..19817321451 100644
--- a/src/Avalonia.Base/Data/Core/Parsers/BindingExpressionVisitor.cs
+++ b/src/Avalonia.Base/Data/Core/Parsers/BindingExpressionVisitor.cs
@@ -11,6 +11,9 @@
namespace Avalonia.Data.Core.Parsers;
[RequiresUnreferencedCode(TrimmingMessages.ExpressionNodeRequiresUnreferencedCodeMessage)]
+#if NET8_0_OR_GREATER
+[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
+#endif
internal class BindingExpressionVisitor : ExpressionVisitor
{
private static readonly PropertyInfo AvaloniaObjectIndexer;
diff --git a/src/Avalonia.Base/Data/Core/Plugins/BindingPlugins.cs b/src/Avalonia.Base/Data/Core/Plugins/BindingPlugins.cs
index 5c2d9aaddf5..520c345ad5f 100644
--- a/src/Avalonia.Base/Data/Core/Plugins/BindingPlugins.cs
+++ b/src/Avalonia.Base/Data/Core/Plugins/BindingPlugins.cs
@@ -28,6 +28,7 @@ public static class BindingPlugins
new ObservableStreamPlugin(),
};
+ [UnconditionalSuppressMessage("AOT", "IL3050", Justification = "We're checking if dynamic code is supported.")]
static BindingPlugins()
{
// When building with AOT, don't create ReflectionMethodAccessorPlugin instance.
diff --git a/src/Avalonia.Base/Data/Core/Plugins/ReflectionMethodAccessorPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/ReflectionMethodAccessorPlugin.cs
index e295fc60669..f9a4587ca63 100644
--- a/src/Avalonia.Base/Data/Core/Plugins/ReflectionMethodAccessorPlugin.cs
+++ b/src/Avalonia.Base/Data/Core/Plugins/ReflectionMethodAccessorPlugin.cs
@@ -7,6 +7,9 @@
namespace Avalonia.Data.Core.Plugins
{
[RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
+#if NET8_0_OR_GREATER
+ [RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
+#endif
internal class ReflectionMethodAccessorPlugin : IPropertyAccessorPlugin
{
private readonly Dictionary<(Type, string), MethodInfo?> _methodLookup =
@@ -81,6 +84,9 @@ internal class ReflectionMethodAccessorPlugin : IPropertyAccessorPlugin
return found;
}
+#if NET8_0_OR_GREATER
+ [RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
+#endif
private sealed class Accessor : PropertyAccessorBase
{
public Accessor(WeakReference