diff --git a/samples/ControlCatalog.Android/MainActivity.cs b/samples/ControlCatalog.Android/MainActivity.cs
index 62c582610c..f6fa07dbde 100644
--- a/samples/ControlCatalog.Android/MainActivity.cs
+++ b/samples/ControlCatalog.Android/MainActivity.cs
@@ -5,7 +5,7 @@ using Avalonia.Android;
namespace ControlCatalog.Android
{
- [Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
+ [Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.Main", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
public class MainActivity : AvaloniaMainActivity
{
}
diff --git a/samples/ControlCatalog.Android/Resources/values/styles.xml b/samples/ControlCatalog.Android/Resources/values/styles.xml
index 2759d2904a..49e079a719 100644
--- a/samples/ControlCatalog.Android/Resources/values/styles.xml
+++ b/samples/ControlCatalog.Android/Resources/values/styles.xml
@@ -14,4 +14,8 @@
- @null
+
+
diff --git a/samples/ControlCatalog.Android/SplashActivity.cs b/samples/ControlCatalog.Android/SplashActivity.cs
index 908b5f082a..a0b68b129b 100644
--- a/samples/ControlCatalog.Android/SplashActivity.cs
+++ b/samples/ControlCatalog.Android/SplashActivity.cs
@@ -28,6 +28,8 @@ namespace ControlCatalog.Android
base.OnResume();
StartActivity(new Intent(Application.Context, typeof(MainActivity)));
+
+ Finish();
}
}
}
diff --git a/samples/ControlCatalog.Browser/Properties/launchSettings.json b/samples/ControlCatalog.Browser/Properties/launchSettings.json
new file mode 100644
index 0000000000..76c1834e3c
--- /dev/null
+++ b/samples/ControlCatalog.Browser/Properties/launchSettings.json
@@ -0,0 +1,13 @@
+{
+ "profiles": {
+ "ControlCatalog.Browser": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/debug?browser={browserInspectUri}"
+ }
+ }
+}
diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml
index 9e0fb3f852..166b98436e 100644
--- a/samples/ControlCatalog/MainView.xaml
+++ b/samples/ControlCatalog/MainView.xaml
@@ -209,8 +209,7 @@
+ HorizontalAlignment="Stretch">
None
Transparent
diff --git a/samples/ControlCatalog/MainView.xaml.cs b/samples/ControlCatalog/MainView.xaml.cs
index 15e666ae7b..f3c1a68e72 100644
--- a/samples/ControlCatalog/MainView.xaml.cs
+++ b/samples/ControlCatalog/MainView.xaml.cs
@@ -6,6 +6,7 @@ using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Media.Immutable;
+using Avalonia.VisualTree;
using ControlCatalog.Models;
using ControlCatalog.Pages;
@@ -59,17 +60,25 @@ namespace ControlCatalog
};
var transparencyLevels = this.Get("TransparencyLevels");
- IDisposable? backgroundSetter = null, paneBackgroundSetter = null;
+ IDisposable? topLevelBackgroundSideSetter = null, sideBarBackgroundSetter = null, paneBackgroundSetter = null;
transparencyLevels.SelectionChanged += (sender, e) =>
{
- backgroundSetter?.Dispose();
+ topLevelBackgroundSideSetter?.Dispose();
+ sideBarBackgroundSetter?.Dispose();
paneBackgroundSetter?.Dispose();
- if (transparencyLevels.SelectedItem is WindowTransparencyLevel selected
- && selected != WindowTransparencyLevel.None)
+ if (transparencyLevels.SelectedItem is WindowTransparencyLevel selected)
{
- var semiTransparentBrush = new ImmutableSolidColorBrush(Colors.Gray, 0.5);
- backgroundSetter = sideBar.SetValue(BackgroundProperty, semiTransparentBrush, Avalonia.Data.BindingPriority.Style);
- paneBackgroundSetter = sideBar.SetValue(SplitView.PaneBackgroundProperty, semiTransparentBrush, Avalonia.Data.BindingPriority.Style);
+ var topLevel = (TopLevel)this.GetVisualRoot()!;
+ topLevel.TransparencyLevelHint = selected;
+
+ if (selected != WindowTransparencyLevel.None)
+ {
+ var transparentBrush = new ImmutableSolidColorBrush(Colors.White, 0);
+ var semiTransparentBrush = new ImmutableSolidColorBrush(Colors.Gray, 0.2);
+ topLevelBackgroundSideSetter = topLevel.SetValue(BackgroundProperty, transparentBrush, Avalonia.Data.BindingPriority.Style);
+ sideBarBackgroundSetter = sideBar.SetValue(BackgroundProperty, semiTransparentBrush, Avalonia.Data.BindingPriority.Style);
+ paneBackgroundSetter = sideBar.SetValue(SplitView.PaneBackgroundProperty, semiTransparentBrush, Avalonia.Data.BindingPriority.Style);
+ }
}
};
}
diff --git a/samples/ControlCatalog/MainWindow.xaml b/samples/ControlCatalog/MainWindow.xaml
index cebb3e0916..442c1d37b0 100644
--- a/samples/ControlCatalog/MainWindow.xaml
+++ b/samples/ControlCatalog/MainWindow.xaml
@@ -10,7 +10,6 @@
ExtendClientAreaToDecorationsHint="{Binding ExtendClientAreaEnabled}"
ExtendClientAreaChromeHints="{Binding ChromeHints}"
ExtendClientAreaTitleBarHeightHint="{Binding TitleBarHeight}"
- TransparencyLevelHint="{Binding TransparencyLevel}"
x:Name="MainWindow"
Background="Transparent"
x:Class="ControlCatalog.MainWindow" WindowState="{Binding WindowState, Mode=TwoWay}"
diff --git a/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml b/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml
index f1403905c4..d690058b27 100644
--- a/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml
+++ b/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml
@@ -11,12 +11,5 @@
-
- None
- Transparent
- Blur
- AcrylicBlur
- Mica
-
diff --git a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
index b79eff780c..3bb4202166 100644
--- a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
@@ -17,7 +17,6 @@ namespace ControlCatalog.ViewModels
private bool _isMenuItemChecked = true;
private WindowState _windowState;
private WindowState[] _windowStates = Array.Empty();
- private int _transparencyLevel;
private ExtendClientAreaChromeHints _chromeHints = ExtendClientAreaChromeHints.PreferSystemChrome;
private bool _extendClientAreaEnabled;
private bool _systemTitleBarEnabled;
@@ -77,12 +76,6 @@ namespace ControlCatalog.ViewModels
TitleBarHeight = -1;
}
- public int TransparencyLevel
- {
- get { return _transparencyLevel; }
- set { this.RaiseAndSetIfChanged(ref _transparencyLevel, value); }
- }
-
public ExtendClientAreaChromeHints ChromeHints
{
get { return _chromeHints; }
diff --git a/src/Android/Avalonia.Android/AvaloniaView.cs b/src/Android/Avalonia.Android/AvaloniaView.cs
index 5267843bfc..f7e32f99db 100644
--- a/src/Android/Avalonia.Android/AvaloniaView.cs
+++ b/src/Android/Avalonia.Android/AvaloniaView.cs
@@ -24,6 +24,8 @@ namespace Avalonia.Android
_root = new EmbeddableControlRoot(_view);
_root.Prepare();
+
+ this.SetBackgroundColor(global::Android.Graphics.Color.Transparent);
}
internal TopLevelImpl TopLevelImpl => _view;
diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
index 33501ece06..f205458f0e 100644
--- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
+++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
@@ -22,6 +22,7 @@ namespace Avalonia.Android
public InvalidationAwareSurfaceView(Context context) : base(context)
{
Holder.AddCallback(this);
+ Holder.SetFormat(global::Android.Graphics.Format.Transparent);
_handler = new Handler(context.MainLooper);
}
diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
index 56dbadca03..1aac567dda 100644
--- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
+++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
@@ -26,6 +26,7 @@ using Avalonia.Rendering.Composition;
using Java.Lang;
using Math = System.Math;
using AndroidRect = Android.Graphics.Rect;
+using Android.Graphics.Drawables;
namespace Avalonia.Android.Platform.SkiaPlatform
{
@@ -283,7 +284,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public Action LostFocus { get; set; }
public Action TransparencyLevelChanged { get; set; }
- public WindowTransparencyLevel TransparencyLevel => WindowTransparencyLevel.None;
+ public WindowTransparencyLevel TransparencyLevel { get; private set; }
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels => new AcrylicPlatformCompensationLevels(1, 1, 1);
@@ -301,7 +302,87 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel)
{
- throw new NotImplementedException();
+ if (TransparencyLevel != transparencyLevel)
+ {
+ bool isBelowR = Build.VERSION.SdkInt < BuildVersionCodes.R;
+ bool isAboveR = Build.VERSION.SdkInt > BuildVersionCodes.R;
+ if (_view.Context is AvaloniaMainActivity activity)
+ {
+ switch (transparencyLevel)
+ {
+ case WindowTransparencyLevel.AcrylicBlur:
+ case WindowTransparencyLevel.ForceAcrylicBlur:
+ case WindowTransparencyLevel.Mica:
+ case WindowTransparencyLevel.None:
+ if (!isBelowR)
+ {
+ activity.SetTranslucent(false);
+ }
+ if (isAboveR)
+ {
+ activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind);
+
+ var attr = activity.Window?.Attributes;
+ if (attr != null)
+ {
+ attr.BlurBehindRadius = 0;
+
+ activity.Window.Attributes = attr;
+ }
+ }
+ activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White));
+
+ if(transparencyLevel != WindowTransparencyLevel.None)
+ {
+ return;
+ }
+ break;
+ case WindowTransparencyLevel.Transparent:
+ if (!isBelowR)
+ {
+ activity.SetTranslucent(true);
+ }
+ if (isAboveR)
+ {
+ activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind);
+
+ var attr = activity.Window?.Attributes;
+ if (attr != null)
+ {
+ attr.BlurBehindRadius = 0;
+
+ activity.Window.Attributes = attr;
+ }
+ }
+ activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent));
+ break;
+ case WindowTransparencyLevel.Blur:
+ if (isAboveR)
+ {
+ activity.SetTranslucent(true);
+ activity.Window?.AddFlags(WindowManagerFlags.BlurBehind);
+
+ var attr = activity.Window?.Attributes;
+ if (attr != null)
+ {
+ attr.BlurBehindRadius = 120;
+
+ activity.Window.Attributes = attr;
+ }
+ activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent));
+ }
+ else
+ {
+ activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind);
+ activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White));
+
+ return;
+ }
+ break;
+ }
+ TransparencyLevel = transparencyLevel;
+ }
+ }
}
}
diff --git a/src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj b/src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj
index a2f1b55b6f..a9cad0538f 100644
--- a/src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj
+++ b/src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj
@@ -7,6 +7,7 @@
+
diff --git a/src/Browser/Avalonia.Browser.Blazor/AvaloniaView.cs b/src/Browser/Avalonia.Browser.Blazor/AvaloniaView.cs
index 2cc74273c0..68efea31d6 100644
--- a/src/Browser/Avalonia.Browser.Blazor/AvaloniaView.cs
+++ b/src/Browser/Avalonia.Browser.Blazor/AvaloniaView.cs
@@ -8,9 +8,10 @@ using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using BrowserView = Avalonia.Browser.AvaloniaView;
+[assembly: SupportedOSPlatform("browser")]
+
namespace Avalonia.Browser.Blazor;
-[SupportedOSPlatform("browser")]
public class AvaloniaView : ComponentBase
{
private Browser.AvaloniaView? _browserView;
diff --git a/src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs b/src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs
index 5e101f7f17..a7bb5a62df 100644
--- a/src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs
+++ b/src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs
@@ -5,7 +5,6 @@ using Avalonia.Controls.ApplicationLifetimes;
namespace Avalonia.Browser.Blazor;
-[SupportedOSPlatform("browser")]
public static class WebAppBuilder
{
public static AppBuilder SetupWithSingleViewLifetime(
diff --git a/src/Browser/Avalonia.Browser/AvaloniaView.cs b/src/Browser/Avalonia.Browser/AvaloniaView.cs
index abda618b0d..153a8c6c1d 100644
--- a/src/Browser/Avalonia.Browser/AvaloniaView.cs
+++ b/src/Browser/Avalonia.Browser/AvaloniaView.cs
@@ -18,7 +18,6 @@ using SkiaSharp;
namespace Avalonia.Browser
{
- [System.Runtime.Versioning.SupportedOSPlatform("browser")] // gets rid of callsite warnings
public partial class AvaloniaView : ITextInputMethodImpl
{
private static readonly PooledList s_intermediatePointsPooledList = new(ClearMode.Never);
diff --git a/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs b/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs
index 3adcb8e539..add69760ee 100644
--- a/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs
+++ b/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs
@@ -5,7 +5,6 @@ using System.Runtime.Versioning;
namespace Avalonia.Browser;
-[SupportedOSPlatform("browser")]
public class BrowserSingleViewLifetime : ISingleViewApplicationLifetime
{
public AvaloniaView? View;
@@ -22,7 +21,6 @@ public class BrowserPlatformOptions
public Func FrameworkAssetPathResolver { get; set; } = new(fileName => $"./{fileName}");
}
-[SupportedOSPlatform("browser")]
public static class WebAppBuilder
{
public static AppBuilder SetupBrowserApp(
diff --git a/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs b/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs
index 85725e4cf3..4e6be3268b 100644
--- a/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs
+++ b/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Runtime.Versioning;
using Avalonia.Browser.Skia;
using Avalonia.Browser.Storage;
using Avalonia.Controls;
@@ -14,9 +15,10 @@ using Avalonia.Platform.Storage;
using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
+[assembly: SupportedOSPlatform("browser")]
+
namespace Avalonia.Browser
{
- [System.Runtime.Versioning.SupportedOSPlatform("browser")] // gets rid of callsite warnings
internal class BrowserTopLevelImpl : ITopLevelImplWithTextInputMethod, ITopLevelImplWithNativeControlHost, ITopLevelImplWithStorageProvider
{
private Size _clientSize;
@@ -201,7 +203,11 @@ namespace Avalonia.Browser
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel)
{
-
+ if (transparencyLevel == WindowTransparencyLevel.None
+ || transparencyLevel == WindowTransparencyLevel.Transparent)
+ {
+ TransparencyLevel = transparencyLevel;
+ }
}
public Size ClientSize => _clientSize;
@@ -221,7 +227,7 @@ namespace Avalonia.Browser
public IMouseDevice MouseDevice { get; } = new MouseDevice();
public IKeyboardDevice KeyboardDevice { get; } = BrowserWindowingPlatform.Keyboard;
- public WindowTransparencyLevel TransparencyLevel { get; }
+ public WindowTransparencyLevel TransparencyLevel { get; private set; }
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; }
public ITextInputMethodImpl TextInputMethod => _avaloniaView;
diff --git a/src/Browser/Avalonia.Browser/Interop/CanvasHelper.cs b/src/Browser/Avalonia.Browser/Interop/CanvasHelper.cs
index 8321b00658..27a2b1dcb7 100644
--- a/src/Browser/Avalonia.Browser/Interop/CanvasHelper.cs
+++ b/src/Browser/Avalonia.Browser/Interop/CanvasHelper.cs
@@ -6,7 +6,6 @@ namespace Avalonia.Browser.Interop;
internal record GLInfo(int ContextId, uint FboId, int Stencils, int Samples, int Depth);
-[System.Runtime.Versioning.SupportedOSPlatform("browser")] // gets rid of callsite warnings
internal static partial class CanvasHelper
{
diff --git a/src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpuRenderTarget.cs b/src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpuRenderTarget.cs
index f69dd3c344..9424122ce8 100644
--- a/src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpuRenderTarget.cs
+++ b/src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpuRenderTarget.cs
@@ -14,14 +14,12 @@ namespace Avalonia.Browser.Skia
_size = browserSkiaSurface.Size;
var glFbInfo = new GRGlFramebufferInfo(browserSkiaSurface.GlInfo.FboId, browserSkiaSurface.ColorType.ToGlSizedFormat());
- {
- _browserSkiaSurface = browserSkiaSurface;
- _renderTarget = new GRBackendRenderTarget(
- (int)(browserSkiaSurface.Size.Width * browserSkiaSurface.Scaling),
- (int)(browserSkiaSurface.Size.Height * browserSkiaSurface.Scaling),
- browserSkiaSurface.GlInfo.Samples,
- browserSkiaSurface.GlInfo.Stencils, glFbInfo);
- }
+ _browserSkiaSurface = browserSkiaSurface;
+ _renderTarget = new GRBackendRenderTarget(
+ (int)(browserSkiaSurface.Size.Width * browserSkiaSurface.Scaling),
+ (int)(browserSkiaSurface.Size.Height * browserSkiaSurface.Scaling),
+ browserSkiaSurface.GlInfo.Samples,
+ browserSkiaSurface.GlInfo.Stencils, glFbInfo);
}
public void Dispose()
diff --git a/src/Browser/Avalonia.Browser/Storage/BlobReadableStream.cs b/src/Browser/Avalonia.Browser/Storage/BlobReadableStream.cs
index 4fce190346..3404452bca 100644
--- a/src/Browser/Avalonia.Browser/Storage/BlobReadableStream.cs
+++ b/src/Browser/Avalonia.Browser/Storage/BlobReadableStream.cs
@@ -7,7 +7,6 @@ using Avalonia.Browser.Interop;
namespace Avalonia.Browser.Storage;
-[System.Runtime.Versioning.SupportedOSPlatform("browser")]
internal class BlobReadableStream : Stream
{
private JSObject? _jSReference;
diff --git a/src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs b/src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs
index 28de55092b..dc580f0fcb 100644
--- a/src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs
+++ b/src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs
@@ -13,7 +13,6 @@ namespace Avalonia.Browser.Storage;
internal record FilePickerAcceptType(string Description, IReadOnlyDictionary> Accept);
-[SupportedOSPlatform("browser")]
internal class BrowserStorageProvider : IStorageProvider
{
internal const string PickerCancelMessage = "The user aborted a request";
diff --git a/src/Browser/Avalonia.Browser/Storage/WriteableStream.cs b/src/Browser/Avalonia.Browser/Storage/WriteableStream.cs
index f29f7420ac..b2f14b6a7a 100644
--- a/src/Browser/Avalonia.Browser/Storage/WriteableStream.cs
+++ b/src/Browser/Avalonia.Browser/Storage/WriteableStream.cs
@@ -7,7 +7,6 @@ using Avalonia.Browser.Interop;
namespace Avalonia.Browser.Storage;
-[System.Runtime.Versioning.SupportedOSPlatform("browser")]
// Loose wrapper implementaion of a stream on top of FileAPI FileSystemWritableFileStream
internal sealed class WriteableStream : Stream
{
diff --git a/src/Browser/Avalonia.Browser/webapp/modules/avalonia/dom.ts b/src/Browser/Avalonia.Browser/webapp/modules/avalonia/dom.ts
index 385cdd4c41..e8e37faf58 100644
--- a/src/Browser/Avalonia.Browser/webapp/modules/avalonia/dom.ts
+++ b/src/Browser/Avalonia.Browser/webapp/modules/avalonia/dom.ts
@@ -17,7 +17,6 @@ export class AvaloniaDOM {
const canvas = document.createElement("canvas");
canvas.id = `canvas${randomIdPart}`;
canvas.classList.add("avalonia-canvas");
- canvas.style.backgroundColor = "#ccc";
canvas.style.width = "100%";
canvas.style.position = "absolute";