From 87e4169d6de7af58348c4e64bbf130408322b4fc Mon Sep 17 00:00:00 2001 From: Aaron Date: Sat, 31 Aug 2024 15:43:41 +0100 Subject: [PATCH 1/3] Fix Titlebar visibility toggle in demo app. --- SukiUI.Demo/SukiUIDemoViewModel.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/SukiUI.Demo/SukiUIDemoViewModel.cs b/SukiUI.Demo/SukiUIDemoViewModel.cs index 11266b424..3ba258b3c 100644 --- a/SukiUI.Demo/SukiUIDemoViewModel.cs +++ b/SukiUI.Demo/SukiUIDemoViewModel.cs @@ -133,6 +133,7 @@ private void ToggleWindowLock() [RelayCommand] private void ToggleTitleBar() { + TitleBarVisible = !TitleBarVisible; ToastManager.CreateSimpleInfoToast() .WithTitle($"Title Bar {(TitleBarVisible ? "Visible" : "Hidden")}") .WithContent($"Window title bar has been {(TitleBarVisible ? "shown" : "hidden")}.") From 242668fe74c61e4e414b4f7baf5041379e2de564 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 12 Sep 2024 10:21:43 +0100 Subject: [PATCH 2/3] Include software rendering fallback. --- SukiUI.Demo/Controls/LoadingTest.cs | 5 ++++ .../Features/Effects/ShaderToyRenderer.cs | 5 ++++ SukiUI/Controls/SukiBackground.cs | 14 ++++++++++- SukiUI/Controls/SukiWindow.axaml | 3 ++- .../Utilities/Effects/EffectBackgroundDraw.cs | 10 ++++++++ SukiUI/Utilities/Effects/EffectDrawBase.cs | 24 +++++++++++++++++-- 6 files changed, 57 insertions(+), 4 deletions(-) diff --git a/SukiUI.Demo/Controls/LoadingTest.cs b/SukiUI.Demo/Controls/LoadingTest.cs index 6b9b0f3a9..296f6d0e8 100644 --- a/SukiUI.Demo/Controls/LoadingTest.cs +++ b/SukiUI.Demo/Controls/LoadingTest.cs @@ -63,6 +63,11 @@ protected override void Render(SKCanvas canvas, SKRect rect) } canvas.Restore(); } + + protected override void RenderSoftware(SKCanvas canvas, SKRect rect) + { + throw new System.NotImplementedException(); + } } } diff --git a/SukiUI.Demo/Features/Effects/ShaderToyRenderer.cs b/SukiUI.Demo/Features/Effects/ShaderToyRenderer.cs index 1585a2b2a..677ed0c10 100644 --- a/SukiUI.Demo/Features/Effects/ShaderToyRenderer.cs +++ b/SukiUI.Demo/Features/Effects/ShaderToyRenderer.cs @@ -50,6 +50,11 @@ protected override void Render(SKCanvas canvas, SKRect rect) } canvas.Restore(); } + + protected override void RenderSoftware(SKCanvas canvas, SKRect rect) + { + throw new System.NotImplementedException(); + } } } } \ No newline at end of file diff --git a/SukiUI/Controls/SukiBackground.cs b/SukiUI/Controls/SukiBackground.cs index 3ba27670f..107d4f0a3 100644 --- a/SukiUI/Controls/SukiBackground.cs +++ b/SukiUI/Controls/SukiBackground.cs @@ -88,6 +88,14 @@ public double TransitionTime get => GetValue(TransitionTimeProperty); set => SetValue(TransitionTimeProperty, value); } + + public static readonly StyledProperty ForceSoftwareRenderingProperty = AvaloniaProperty.Register(nameof(ForceSoftwareRendering)); + + public bool ForceSoftwareRendering + { + get => GetValue(ForceSoftwareRenderingProperty); + set => SetValue(ForceSoftwareRenderingProperty, value); + } private readonly EffectBackgroundDraw _draw; private readonly IDisposable _observables; @@ -96,9 +104,13 @@ public SukiBackground() { IsHitTestVisible = false; _draw = new EffectBackgroundDraw(new Rect(0, 0, Bounds.Width, Bounds.Height)); + var forceSwRenderingObs = this.GetObservable(ForceSoftwareRenderingProperty) + .Do(enabled => _draw.ForceSoftwareRendering = enabled) + .Select(_ => Unit.Default); var transEnabledObs = this.GetObservable(TransitionsEnabledProperty) .Do(enabled => _draw.TransitionsEnabled = enabled) - .Select(_ => Unit.Default); + .Select(_ => Unit.Default) + .Merge(forceSwRenderingObs); var transTime = this.GetObservable(TransitionTimeProperty) .Do(time => _draw.TransitionTime = time) .Select(_ => Unit.Default) diff --git a/SukiUI/Controls/SukiWindow.axaml b/SukiUI/Controls/SukiWindow.axaml index 1af8703db..15d735f87 100644 --- a/SukiUI/Controls/SukiWindow.axaml +++ b/SukiUI/Controls/SukiWindow.axaml @@ -36,7 +36,8 @@ ShaderFile="{TemplateBinding BackgroundShaderFile}" Style="{TemplateBinding BackgroundStyle}" TransitionTime="{TemplateBinding BackgroundTransitionTime}" - TransitionsEnabled="{TemplateBinding BackgroundTransitionsEnabled}" /> + TransitionsEnabled="{TemplateBinding BackgroundTransitionsEnabled}" + ForceSoftwareRendering="True"/> diff --git a/SukiUI/Utilities/Effects/EffectBackgroundDraw.cs b/SukiUI/Utilities/Effects/EffectBackgroundDraw.cs index 58d0ec95d..03f1a5a3d 100644 --- a/SukiUI/Utilities/Effects/EffectBackgroundDraw.cs +++ b/SukiUI/Utilities/Effects/EffectBackgroundDraw.cs @@ -1,6 +1,8 @@ using System; using System.Diagnostics; using Avalonia; +using Avalonia.Skia; +using Avalonia.Styling; using SkiaSharp; namespace SukiUI.Utilities.Effects @@ -61,6 +63,14 @@ protected override void Render(SKCanvas canvas, SKRect rect) } } + protected override void RenderSoftware(SKCanvas canvas, SKRect rect) + { + if (ActiveVariant == ThemeVariant.Dark) + canvas.Clear(ActiveTheme.Background.ToSKColor()); + else + canvas.Clear(new SKColorF(0.95f, 0.95f, 0.95f, 1f)); + } + private static double InverseLerp(double start, double end, double value) => Math.Max(0, Math.Min(1, (value - start) / (end - start))); } diff --git a/SukiUI/Utilities/Effects/EffectDrawBase.cs b/SukiUI/Utilities/Effects/EffectDrawBase.cs index 7c61d3be6..26b117c05 100644 --- a/SukiUI/Utilities/Effects/EffectDrawBase.cs +++ b/SukiUI/Utilities/Effects/EffectDrawBase.cs @@ -7,6 +7,7 @@ using Avalonia.Skia; using Avalonia.Styling; using SkiaSharp; +using SukiUI.Models; namespace SukiUI.Utilities.Effects { @@ -39,11 +40,15 @@ public bool AnimationEnabled _animationEnabled = value; } } + + public bool ForceSoftwareRendering { get; set; } protected float AnimationSpeedScale { get; set; } = 0.1f; protected ThemeVariant ActiveVariant { get; private set; } + protected SukiColorTheme ActiveTheme { get; private set; } + protected float AnimationSeconds => (float)_animationTick.Elapsed.TotalSeconds; private readonly Stopwatch _animationTick = Stopwatch.StartNew(); @@ -53,7 +58,10 @@ protected EffectDrawBase(Rect bounds) Bounds = bounds; var sTheme = SukiTheme.GetInstance(); sTheme.OnBaseThemeChanged += v => ActiveVariant = v; - ActiveVariant = SukiTheme.GetInstance().ActiveBaseTheme; + ActiveVariant = sTheme.ActiveBaseTheme; + sTheme.OnColorThemeChanged += t => ActiveTheme = t; + ActiveTheme = sTheme.ActiveColorTheme!; + } public void Render(ImmediateDrawingContext context) @@ -61,10 +69,22 @@ public void Render(ImmediateDrawingContext context) var leaseFeature = context.TryGetFeature(); if (leaseFeature is null) throw new InvalidOperationException("Unable to lease Skia API"); using var lease = leaseFeature.Lease(); - Render(lease.SkCanvas, SKRect.Create((float)Bounds.Width, (float)Bounds.Height)); + var rect = SKRect.Create((float)Bounds.Width, (float)Bounds.Height); + if(lease.GrContext is null || ForceSoftwareRendering) // GrContext is null whenever + RenderSoftware(lease.SkCanvas, rect); + else + Render(lease.SkCanvas, rect); } + /// + /// Called every frame to render content. + /// protected abstract void Render(SKCanvas canvas, SKRect rect); + + /// + /// Called every frame whenever the app falls back to software rendering (or is enabled) + /// + protected abstract void RenderSoftware(SKCanvas canvas, SKRect rect); protected SKShader? EffectWithUniforms(float alpha = 1f) => EffectWithUniforms(Effect, alpha); From 5aae4095ba5190c1d6be796339b6382f6976bb9f Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 12 Sep 2024 16:34:10 +0100 Subject: [PATCH 3/3] Expose `ForceSoftwareRendering` on the window. --- SukiUI/Controls/SukiWindow.axaml | 2 +- SukiUI/Controls/SukiWindow.axaml.cs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/SukiUI/Controls/SukiWindow.axaml b/SukiUI/Controls/SukiWindow.axaml index 15d735f87..47a2e4bc7 100644 --- a/SukiUI/Controls/SukiWindow.axaml +++ b/SukiUI/Controls/SukiWindow.axaml @@ -37,7 +37,7 @@ Style="{TemplateBinding BackgroundStyle}" TransitionTime="{TemplateBinding BackgroundTransitionTime}" TransitionsEnabled="{TemplateBinding BackgroundTransitionsEnabled}" - ForceSoftwareRendering="True"/> + ForceSoftwareRendering="{TemplateBinding BackgroundForceSoftwareRendering}"/> diff --git a/SukiUI/Controls/SukiWindow.axaml.cs b/SukiUI/Controls/SukiWindow.axaml.cs index 94077cbc8..8ce32a87e 100644 --- a/SukiUI/Controls/SukiWindow.axaml.cs +++ b/SukiUI/Controls/SukiWindow.axaml.cs @@ -175,6 +175,18 @@ public double BackgroundTransitionTime AvaloniaProperty.Register(nameof(RightWindowTitleBarControls), defaultValue: new Avalonia.Controls.Controls()); + public static readonly StyledProperty BackgroundForceSoftwareRenderingProperty = AvaloniaProperty.Register(nameof(BackgroundForceSoftwareRendering)); + + /// + /// Forces the background of the window to utilise software rendering. + /// This prevents use of any advanced effects or animations and provides only a flat background colour that changes with the theme. + /// + public bool BackgroundForceSoftwareRendering + { + get => GetValue(BackgroundForceSoftwareRenderingProperty); + set => SetValue(BackgroundForceSoftwareRenderingProperty, value); + } + /// /// Controls that are displayed on the right side of the title bar, /// to the left of the normal window control buttons. (Displays provided controls right-to-left)