Browse Source

Added composition support to the headless platform

pull/8105/head
Nikita Tsukanov 4 years ago
parent
commit
38469f0629
  1. 14
      samples/ControlCatalog.NetCore/Program.cs
  2. 6
      src/Avalonia.Headless.Vnc/HeadlessVncPlatformExtensions.cs
  3. 20
      src/Avalonia.Headless/AvaloniaHeadlessPlatform.cs
  4. 1
      src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
  5. 5
      src/Avalonia.Headless/HeadlessWindowImpl.cs

14
samples/ControlCatalog.NetCore/Program.cs

@ -53,7 +53,11 @@ namespace ControlCatalog.NetCore
else if (args.Contains("--full-headless"))
{
return builder
.UseHeadless(true)
.UseHeadless(new AvaloniaHeadlessPlatformOptions
{
UseHeadlessDrawing = true,
UseComposition = false
})
.AfterSetup(_ =>
{
DispatcherTimer.RunOnce(async () =>
@ -63,12 +67,11 @@ namespace ControlCatalog.NetCore
var tc = window.GetLogicalDescendants().OfType<TabControl>().First();
foreach (var page in tc.Items.Cast<TabItem>().ToList())
{
// Skip DatePicker because of some layout bug in grid
if (page.Header.ToString() == "DatePicker")
if (page.Header.ToString() == "DatePicker" || page.Header.ToString() == "TreeView")
continue;
Console.WriteLine("Selecting " + page.Header);
tc.SelectedItem = page;
await Task.Delay(500);
await Task.Delay(50);
}
Console.WriteLine("Selecting the first page");
tc.SelectedItem = tc.Items.OfType<object>().First();
@ -77,7 +80,7 @@ namespace ControlCatalog.NetCore
for (var c = 0; c < 3; c++)
{
GC.Collect(2, GCCollectionMode.Forced);
await Task.Delay(500);
await Task.Delay(00);
}
void FormatMem(string metric, long bytes)
@ -87,7 +90,6 @@ namespace ControlCatalog.NetCore
FormatMem("GC allocated bytes", GC.GetTotalMemory(true));
FormatMem("WorkingSet64", Process.GetCurrentProcess().WorkingSet64);
}, TimeSpan.FromSeconds(1));
})
.StartWithClassicDesktopLifetime(args);

6
src/Avalonia.Headless.Vnc/HeadlessVncPlatformExtensions.cs

@ -20,7 +20,11 @@ namespace Avalonia
var tcpServer = new TcpListener(host == null ? IPAddress.Loopback : IPAddress.Parse(host), port);
tcpServer.Start();
return builder
.UseHeadless(false)
.UseHeadless(new AvaloniaHeadlessPlatformOptions
{
UseComposition = true,
UseHeadlessDrawing = false
})
.AfterSetup(_ =>
{
var lt = ((IClassicDesktopStyleApplicationLifetime)builder.Instance.ApplicationLifetime);

20
src/Avalonia.Headless/AvaloniaHeadlessPlatform.cs

@ -7,12 +7,14 @@ using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
using Avalonia.Threading;
namespace Avalonia.Headless
{
public static class AvaloniaHeadlessPlatform
{
internal static Compositor Compositor { get; private set; }
class RenderTimer : DefaultRenderTimer
{
private readonly int _framesPerSecond;
@ -55,7 +57,7 @@ namespace Avalonia.Headless
public ITrayIconImpl CreateTrayIcon() => null;
}
internal static void Initialize()
internal static void Initialize(AvaloniaHeadlessPlatformOptions opts)
{
AvaloniaLocator.CurrentMutable
.Bind<IPlatformThreadingInterface>().ToConstant(new HeadlessPlatformThreadingInterface())
@ -71,6 +73,8 @@ namespace Avalonia.Headless
.Bind<ITextShaperImpl>().ToSingleton<HeadlessTextShaperStub>()
.Bind<IWindowingPlatform>().ToConstant(new HeadlessWindowingPlatform())
.Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>();
if (opts.UseComposition)
Compositor = new Compositor(AvaloniaLocator.Current.GetRequiredService<IRenderLoop>(), null);
}
@ -82,15 +86,21 @@ namespace Avalonia.Headless
}
}
public class AvaloniaHeadlessPlatformOptions
{
public bool UseComposition { get; set; } = true;
public bool UseHeadlessDrawing { get; set; } = true;
}
public static class AvaloniaHeadlessPlatformExtensions
{
public static T UseHeadless<T>(this T builder, bool headlessDrawing = true)
public static T UseHeadless<T>(this T builder, AvaloniaHeadlessPlatformOptions opts)
where T : AppBuilderBase<T>, new()
{
if (headlessDrawing)
if(opts.UseHeadlessDrawing)
builder.UseRenderingSubsystem(HeadlessPlatformRenderInterface.Initialize, "Headless");
return builder.UseWindowingSubsystem(AvaloniaHeadlessPlatform.Initialize, "Headless");
return builder.UseWindowingSubsystem(() => AvaloniaHeadlessPlatform.Initialize(opts), "Headless");
}
}
}

1
src/Avalonia.Headless/HeadlessPlatformRenderInterface.cs

@ -418,7 +418,6 @@ namespace Avalonia.Headless
public void DrawLine(IPen pen, Point p1, Point p2)
{
throw new NotImplementedException();
}
public void DrawGeometry(IBrush brush, IPen pen, IGeometryImpl geometry)

5
src/Avalonia.Headless/HeadlessWindowImpl.cs

@ -10,6 +10,7 @@ using Avalonia.Input.Raw;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
using Avalonia.Threading;
using Avalonia.Utilities;
@ -52,7 +53,9 @@ namespace Avalonia.Headless
public Action<double> ScalingChanged { get; set; }
public IRenderer CreateRenderer(IRenderRoot root)
=> new DeferredRenderer(root, AvaloniaLocator.Current.GetService<IRenderLoop>());
=> AvaloniaHeadlessPlatform.Compositor != null
? new CompositingRenderer(root, AvaloniaHeadlessPlatform.Compositor)
: new DeferredRenderer(root, AvaloniaLocator.Current.GetRequiredService<IRenderLoop>());
public void Invalidate(Rect rect)
{

Loading…
Cancel
Save