Browse Source
* Update SkiaSharp/HarfBuzzSharp and use proper native bits, make it configurable * Run UiThreadRender jobs on each animation request in WASM * Update ControlCatalog to match our current templates * Add TaskContinuationOptions.ExecuteSynchronously in compositing engine where it's missed * Log invalid rendering configuration * Use setInterval isntead of Timer on WASM * Minor fixes * Implement BrowserDispatcherImpl and avoid possible memory leakpull/13515/head
committed by
GitHub
22 changed files with 273 additions and 237 deletions
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@ -0,0 +1,74 @@ |
|||
:root { |
|||
--sat: env(safe-area-inset-top); |
|||
--sar: env(safe-area-inset-right); |
|||
--sab: env(safe-area-inset-bottom); |
|||
--sal: env(safe-area-inset-left); |
|||
} |
|||
|
|||
/* HTML styles for the splash screen */ |
|||
|
|||
.highlight { |
|||
color: white; |
|||
font-size: 2.5rem; |
|||
display: block; |
|||
} |
|||
|
|||
.purple { |
|||
color: #8b44ac; |
|||
} |
|||
|
|||
.icon { |
|||
opacity: 0.05; |
|||
height: 35%; |
|||
width: 35%; |
|||
position: absolute; |
|||
background-repeat: no-repeat; |
|||
right: 0px; |
|||
bottom: 0px; |
|||
margin-right: 3%; |
|||
margin-bottom: 5%; |
|||
z-index: 5000; |
|||
background-position: right bottom; |
|||
pointer-events: none; |
|||
} |
|||
|
|||
#avalonia-splash a { |
|||
color: whitesmoke; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
.center { |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
height: 100vh; |
|||
} |
|||
|
|||
#avalonia-splash { |
|||
position: relative; |
|||
height: 100%; |
|||
width: 100%; |
|||
color: whitesmoke; |
|||
background: #1b2a4e; |
|||
font-family: 'Nunito', sans-serif; |
|||
background-position: center; |
|||
background-size: cover; |
|||
background-repeat: no-repeat; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
|
|||
.splash-close { |
|||
animation: fadeout 0.25s linear forwards; |
|||
} |
|||
|
|||
@keyframes fadeout { |
|||
0% { |
|||
opacity: 100%; |
|||
} |
|||
|
|||
100% { |
|||
opacity: 0; |
|||
visibility: collapse; |
|||
} |
|||
} |
|||
|
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 172 KiB |
@ -0,0 +1,28 @@ |
|||
<!DOCTYPE html> |
|||
<!-- Licensed to the .NET Foundation under one or more agreements. --> |
|||
<!-- The .NET Foundation licenses this file to you under the MIT license. --> |
|||
<html> |
|||
|
|||
<head> |
|||
<title>AvaloniaUI - ControlCatalog</title> |
|||
<meta charset="UTF-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|||
<link rel="stylesheet" href="./app.css" /> |
|||
</head> |
|||
|
|||
<body style="margin: 0px; overflow: hidden"> |
|||
<div id="out"> |
|||
<div id="avalonia-splash"> |
|||
<div class="center"> |
|||
<h2 class="purple"> |
|||
Powered by |
|||
<a class="highlight" href="https://www.avaloniaui.net/" target="_blank">Avalonia UI</a> |
|||
</h2> |
|||
</div> |
|||
<img class="icon" src="Logo.svg" alt="Avalonia Logo" /> |
|||
</div> |
|||
</div> |
|||
<script type='module' src="./main.js"></script> |
|||
</body> |
|||
|
|||
</html> |
|||
@ -1,7 +0,0 @@ |
|||
<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" /> |
|||
<assembly fullname="Avalonia.Controls.ColorPicker" preserve="All" /> |
|||
</linker> |
|||
@ -1,56 +0,0 @@ |
|||
:root { |
|||
--sat: env(safe-area-inset-top); |
|||
--sar: env(safe-area-inset-right); |
|||
--sab: env(safe-area-inset-bottom); |
|||
--sal: env(safe-area-inset-left); |
|||
} |
|||
|
|||
#out { |
|||
height: 100vh; |
|||
width: 100vw |
|||
} |
|||
|
|||
#avalonia-splash { |
|||
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{ |
|||
color: whitesmoke; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
.center { |
|||
display: flex; |
|||
justify-content: center; |
|||
height: 250px; |
|||
} |
|||
|
|||
.splash-close { |
|||
animation: slide 0.5s linear 1s forwards; |
|||
} |
|||
|
|||
@keyframes slide { |
|||
0% { |
|||
top: 0%; |
|||
} |
|||
|
|||
50% { |
|||
opacity: 80%; |
|||
} |
|||
|
|||
100% { |
|||
top: 100%; |
|||
overflow: hidden; |
|||
opacity: 0; |
|||
display: none; |
|||
visibility: collapse; |
|||
} |
|||
} |
|||
@ -1,31 +0,0 @@ |
|||
<!DOCTYPE html> |
|||
<!-- Licensed to the .NET Foundation under one or more agreements. --> |
|||
<!-- The .NET Foundation licenses this file to you under the MIT license. --> |
|||
<html> |
|||
|
|||
<head> |
|||
<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" /> |
|||
<link rel="modulepreload" href="./dotnet.js" /> |
|||
<link rel="modulepreload" href="./avalonia.js" /> |
|||
<link rel="stylesheet" href="./app.css" /> |
|||
</head> |
|||
|
|||
<body style="margin: 0px"> |
|||
<div id="out"> |
|||
<div id="avalonia-splash"> |
|||
<div class="center"> |
|||
<h2>Powered by</h2> |
|||
<a class="navbar-brand" href="https://www.avaloniaui.net/" target="_blank"> |
|||
<img src="Logo.svg" alt="Avalonia Logo" width="30" height="24" /> |
|||
Avalonia |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<script type='module' src="./main.js"></script> |
|||
</body> |
|||
|
|||
</html> |
|||
@ -1,5 +1,7 @@ |
|||
<Project> |
|||
<PropertyGroup> |
|||
<EmccInitialHeapSize>16384000</EmccInitialHeapSize> <!-- must be a multiple of 64KiB, 1024000 * num MB, number grows --> |
|||
<ShouldIncludeAvaloniaJavaScript Condition=" '$(ShouldIncludeAvaloniaJavaScript)' == '' ">True</ShouldIncludeAvaloniaJavaScript> |
|||
<ShouldIncludeNativeSkiaSharp Condition=" '$(ShouldIncludeNativeSkiaSharp)' == '' ">True</ShouldIncludeNativeSkiaSharp> |
|||
<ShouldIncludeNativeHarfBuzzSharp Condition=" '$(ShouldIncludeNativeHarfBuzzSharp)' == '' ">True</ShouldIncludeNativeHarfBuzzSharp> |
|||
</PropertyGroup> |
|||
</Project> |
|||
|
|||
@ -1,37 +1,33 @@ |
|||
<Project> |
|||
<ItemGroup> |
|||
<WasmExtraFilesToDeploy Include="$(MSBuildThisFileDirectory)/wwwroot/**/*.*" /> |
|||
<NativeFileReference Include="$(HarfBuzzSharpStaticLibraryPath)\3.1.7\libHarfBuzzSharp.a" /> |
|||
<NativeFileReference Include="$(SkiaSharpStaticLibraryPath)\3.1.7\libSkiaSharp.a" /> |
|||
</ItemGroup> |
|||
|
|||
<PropertyGroup> |
|||
<UseAvaloniaWasmDefaultOptimizations Condition="'$(UseAvaloniaWasmDefaultOptimizations)'==''">True</UseAvaloniaWasmDefaultOptimizations> |
|||
<EmccExtraLDFlags>$(EmccExtraLDFlags) --js-library="$(MSBuildThisFileDirectory)\interop.js"</EmccExtraLDFlags> |
|||
<EmccFlags>$(EmccExtraLDFlags) -sERROR_ON_UNDEFINED_SYMBOLS=0</EmccFlags> |
|||
<WasmBuildNative>true</WasmBuildNative> |
|||
</PropertyGroup> |
|||
|
|||
<PropertyGroup Condition="'$(UseAvaloniaWasmDefaultOptimizations)'=='True' And '$(Configuration)' == 'Release'"> |
|||
<PublishTrimmed>true</PublishTrimmed> |
|||
<TrimMode>full</TrimMode> |
|||
<InvariantGlobalization>true</InvariantGlobalization> |
|||
<EmccCompileOptimizationFlag>-Oz</EmccCompileOptimizationFlag> |
|||
<EmccLinkOptimizationFlag>-Oz</EmccLinkOptimizationFlag> |
|||
<WasmEmitSymbolMap>false</WasmEmitSymbolMap> |
|||
<WasmNativeDebugSymbols>false</WasmNativeDebugSymbols> |
|||
<WasmDebugLevel>0</WasmDebugLevel> |
|||
<WasmEnableExceptionHandling>false</WasmEnableExceptionHandling> |
|||
<TrimmerRemoveSymbols>true</TrimmerRemoveSymbols> |
|||
<DebuggerSupport>false</DebuggerSupport> |
|||
<EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization> |
|||
<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding> |
|||
<EventSourceSupport>false</EventSourceSupport> |
|||
<HttpActivityPropagationSupport>false</HttpActivityPropagationSupport> |
|||
<MetadataUpdaterSupport>false</MetadataUpdaterSupport> |
|||
<UseNativeHttpHandler>true</UseNativeHttpHandler> |
|||
<UseSystemResourceKeys>true</UseSystemResourceKeys> |
|||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages> |
|||
<IncludeSatelliteDllsProjectOutputGroup>false</IncludeSatelliteDllsProjectOutputGroup> |
|||
<ItemGroup> |
|||
<WasmExtraFilesToDeploy Condition="'$(WasmRuntimeAssetsLocation)' == ''" Include="$(MSBuildThisFileDirectory)\wwwroot\**\*.*" /> |
|||
<WasmExtraFilesToDeploy Condition="'$(WasmRuntimeAssetsLocation)' != ''" Include="$(MSBuildThisFileDirectory)\wwwroot\**\*.*" TargetPath="$(WasmRuntimeAssetsLocation)\%(FileName)%(Extension)" /> |
|||
</ItemGroup> |
|||
|
|||
<PropertyGroup Condition="'$(ShouldIncludeNativeSkiaSharp)' == 'True' or '$(ShouldIncludeNativeHarfBuzzSharp)' == 'True'"> |
|||
<WasmBuildNative Condition="'$(WasmBuildNative)' == ''">true</WasmBuildNative> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup Condition="'$(TargetFrameworkVersion)' != '' and '$(ShouldIncludeNativeSkiaSharp)' == 'True'"> |
|||
<!-- net7.0 --> |
|||
<NativeFileReference Include="$(SkiaSharpStaticLibraryPath)\3.1.12\mt\*.a" Condition="!$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '8.0')) and '$(WasmEnableThreads)' == 'True'" /> |
|||
<NativeFileReference Include="$(SkiaSharpStaticLibraryPath)\3.1.12\st\*.a" Condition="!$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '8.0')) and '$(WasmEnableThreads)' != 'True'" /> |
|||
<!-- net8.0 --> |
|||
<NativeFileReference Include="$(SkiaSharpStaticLibraryPath)\3.1.34\mt\*.a" Condition="$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '8.0')) and '$(WasmEnableThreads)' == 'True'" /> |
|||
<NativeFileReference Include="$(SkiaSharpStaticLibraryPath)\3.1.34\st\*.a" Condition="$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '8.0')) and '$(WasmEnableThreads)' != 'True'" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup Condition="'$(TargetFrameworkVersion)' != '' and '$(ShouldIncludeNativeHarfBuzzSharp)' == 'True'"> |
|||
<!-- net7.0 --> |
|||
<NativeFileReference Include="$(HarfBuzzSharpStaticLibraryPath)\3.1.12\st\*.a" Condition="!$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '8.0')) and '$(WasmEnableThreads)' != 'True'" /> |
|||
<NativeFileReference Include="$(HarfBuzzSharpStaticLibraryPath)\3.1.12\mt\*.a" Condition="!$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '8.0')) and '$(WasmEnableThreads)' == 'True'" /> |
|||
<!-- net8.0 --> |
|||
<NativeFileReference Include="$(HarfBuzzSharpStaticLibraryPath)\3.1.34\st\*.a" Condition="$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '8.0')) and '$(WasmEnableThreads)' != 'True'" /> |
|||
<NativeFileReference Include="$(HarfBuzzSharpStaticLibraryPath)\3.1.34\mt\*.a" Condition="$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '8.0')) and '$(WasmEnableThreads)' == 'True'" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
|
|||
@ -0,0 +1,64 @@ |
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Threading; |
|||
|
|||
using Avalonia.Browser.Interop; |
|||
using Avalonia.Threading; |
|||
|
|||
namespace Avalonia.Browser; |
|||
|
|||
internal class BrowserDispatcherImpl : IDispatcherImpl |
|||
{ |
|||
private readonly Thread _thread; |
|||
private readonly Stopwatch _clock; |
|||
private bool _signaled; |
|||
private int? _timerId; |
|||
|
|||
private readonly Action _timerCallback; |
|||
private readonly Action _signalCallback; |
|||
|
|||
public BrowserDispatcherImpl() |
|||
{ |
|||
_thread = Thread.CurrentThread; |
|||
_clock = Stopwatch.StartNew(); |
|||
|
|||
_timerCallback = () => Timer?.Invoke(); |
|||
_signalCallback = () => |
|||
{ |
|||
_signaled = false; |
|||
Signaled?.Invoke(); |
|||
}; |
|||
} |
|||
|
|||
public bool CurrentThreadIsLoopThread => Thread.CurrentThread == _thread; |
|||
|
|||
public long Now => _clock.ElapsedMilliseconds; |
|||
|
|||
public event Action? Signaled; |
|||
public event Action? Timer; |
|||
|
|||
public void Signal() |
|||
{ |
|||
if (_signaled) |
|||
return; |
|||
|
|||
// NOTE: by HTML5 spec minimal timeout is 4ms, but Chrome seems to work well with 1ms as well.
|
|||
var interval = 1; |
|||
CanvasHelper.SetTimeout(_signalCallback, interval); |
|||
} |
|||
|
|||
public void UpdateTimer(long? dueTimeInMs) |
|||
{ |
|||
if (_timerId is { } timerId) |
|||
{ |
|||
_timerId = null; |
|||
CanvasHelper.ClearInterval(timerId); |
|||
} |
|||
|
|||
if (dueTimeInMs.HasValue) |
|||
{ |
|||
var interval = Math.Max(1, dueTimeInMs.Value - _clock.ElapsedMilliseconds); |
|||
_timerId = CanvasHelper.SetInterval(_timerCallback, (int)interval); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue