XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using XFESystem.Core;
using XFESystem.Desktop;

namespace XFESystem.Platform.Tests;

public sealed class MultiDisplayTests
{
    private static readonly DesktopDisplay First = new("first", "Display 1", 640, 480);
    private static readonly DesktopDisplay Second = new("second", "Display 2", 640, 480);
    private static (FramebufferDisplayManager Manager, ArrayFramebufferPresenter First, ArrayFramebufferPresenter Second, CpuFramebufferCanvas Canvas) Create(DesktopDisplay? second = null)
    {
        second ??= Second;
        var a = new ArrayFramebufferPresenter(First.NativeWidth, First.NativeHeight);
        var b = new ArrayFramebufferPresenter(second.NativeWidth, second.NativeHeight);
        var manager = new FramebufferDisplayManager([new(First, a), new(second, b)], 100);
        var canvas = new CpuFramebufferCanvas(manager.Presenter); manager.AttachCanvas(canvas);
        return (manager, a, b, canvas);
    }

    [Fact]
    public void DuplicatePresentsIdenticalPixelsAndDamageToIndependentOutputs()
    {
        var (manager, a, b, canvas) = Create();
        canvas.Fill(0x123456, 0, 0, 640, 480); canvas.Present();
        Assert.Equal(a.Pixels.ToArray(), b.Pixels.ToArray());
        canvas.Fill(0xff1234, 170, 82, 7, 9); canvas.Present(new(170, 82, 7, 9));
        Assert.Equal(0xff1234, b.Pixels.Span[82 * 640 + 170]);
        Assert.Equal(a.Pixels.ToArray(), b.Pixels.ToArray());
        Assert.Equal(0x123456, b.Pixels.Span[81 * 640 + 170]);
        Assert.Equal(DesktopDisplayMode.Duplicate, manager.Current.Mode);
    }

    [Fact]
    public void DuplicateFitsDifferentAspectRatiosWithoutStretchingAndKeepsBlackBars()
    {
        var (_, _, b, canvas) = Create(Second with { NativeWidth = 800, NativeHeight = 480 });
        canvas.Fill(0x238acd, 0, 0, 640, 480); canvas.Present();
        Assert.Equal(0, b.Pixels.Span[240 * 800 + 79]);
        Assert.Equal(0x238acd, b.Pixels.Span[240 * 800 + 80]);
        Assert.Equal(0x238acd, b.Pixels.Span[240 * 800 + 719]);
        Assert.Equal(0, b.Pixels.Span[240 * 800 + 720]);
    }

    [Fact]
    public void ExtendedDesktopRoutesRegionsAndPointerDamageToTheCorrectScanout()
    {
        var (manager, a, b, canvas) = Create();
        Assert.True(manager.TryApply(manager.Current.WithMode(DesktopDisplayMode.Extend), out var error), error);
        Assert.Equal(1280, canvas.Width);
        canvas.Fill(0xcc2211, 0, 0, 640, 480); canvas.Fill(0x1133cc, 640, 0, 640, 480); canvas.Present();
        Assert.All(a.Pixels.ToArray(), p => Assert.Equal(0xcc2211, p));
        Assert.All(b.Pixels.ToArray(), p => Assert.Equal(0x1133cc, p));
        long firstPresents = a.Presentations;
        canvas.Fill(0xffffff, 650, 10, 3, 3); canvas.Present(new(650, 10, 3, 3));
        Assert.Equal(firstPresents, a.Presentations);
        Assert.Equal(0xffffff, b.Pixels.Span[10 * 640 + 10]);
    }

    [Fact]
    public void OnlySecondBlacksFirstAndSwitchingBackRestoresBothOutputs()
    {
        var (manager, a, b, canvas) = Create();
        canvas.Fill(0xffffff, 0, 0, 640, 480); canvas.Present();
        var previous = manager.Current;
        Assert.True(manager.TryApply(previous.WithMode(DesktopDisplayMode.SelectedOnly).WithPrimary(Second.Id), out _));
        canvas.Fill(0x3478ab, 0, 0, 640, 480); canvas.Present();
        Assert.All(a.Pixels.ToArray(), p => Assert.Equal(0, p));
        Assert.All(b.Pixels.ToArray(), p => Assert.Equal(0x3478ab, p));
        Assert.True(manager.TryApply(previous, out _)); canvas.Present();
        Assert.Equal(a.Pixels.ToArray(), b.Pixels.ToArray());
    }

    [Fact]
    public void IdentifyNumbersDifferOnMirroredOutputsAndDisappearWithoutGhosts()
    {
        var (manager, a, b, canvas) = Create();
        canvas.Fill(0x123456, 0, 0, 640, 480); canvas.Present();
        manager.Identify(true); canvas.Present();
        Assert.NotEqual(a.Pixels.ToArray(), b.Pixels.ToArray());
        manager.Identify(false); canvas.Present();
        Assert.All(a.Pixels.ToArray(), p => Assert.Equal(0x123456, p));
        Assert.Equal(a.Pixels.ToArray(), b.Pixels.ToArray());
    }

    [Fact]
    public void InvalidConfigurationLeavesLiveCanvasAndOutputsUntouched()
    {
        var (manager, _, _, canvas) = Create(); var original = manager.Current;
        foreach (var bad in new[] {
            original.WithPrimary("missing"), original.WithMode((DesktopDisplayMode)99),
            original.WithMode(DesktopDisplayMode.Extend).Move(Second.Id, 100, 0),
            original.WithMode(DesktopDisplayMode.Extend).Move(Second.Id, 700, 0),
            original.Move(Second.Id, int.MaxValue, 0),
            new DesktopDisplayConfiguration(DesktopDisplayMode.Extend, First.Id, [new(First.Id, 0, 0), new(First.Id, 640, 0)]) })
        {
            Assert.False(manager.TryApply(bad, out var error)); Assert.NotEmpty(error!);
            Assert.Same(original, manager.Current); Assert.Equal(640, canvas.Width); Assert.Equal(480, canvas.Height);
        }
    }

    [Fact]
    public void PreviewTimeoutAndEscapeRestoreLayoutWhileOnlyConfirmationWritesSettings()
    {
        var (manager, _, _, canvas) = Create(); var storage = new MemoryWorkspace(); long now = 1000;
        var desktop = new DesktopSession(canvas, storage, monotonicMilliseconds: () => now, displays: manager);
        desktop.ShowDisplaySettings();
        Assert.True(desktop.ApplyDisplayConfiguration(manager.Current.WithMode(DesktopDisplayMode.Extend)));
        Assert.False(storage.Exists(DesktopSession.DisplaySettingsPath)); Assert.Equal(1280, canvas.Width);
        now += 15001; desktop.AdvanceFeedback(now);
        Assert.False(desktop.IsDisplayChangePending); Assert.Equal(640, canvas.Width);
        Assert.True(desktop.ApplyDisplayConfiguration(manager.Current.WithMode(DesktopDisplayMode.Extend)));
        desktop.Key(DesktopKey.Escape); Assert.Equal(640, canvas.Width);
        Assert.True(desktop.ApplyDisplayConfiguration(manager.Current.WithMode(DesktopDisplayMode.Extend)));
        desktop.KeepDisplayConfiguration();
        Assert.Equal(DesktopDisplayMode.Extend, DesktopDisplayConfiguration.Parse(storage.ReadText(DesktopSession.DisplaySettingsPath)).Mode);
        var next = Create(); _ = new DesktopSession(next.Canvas, storage, displays: next.Manager);
        Assert.Equal(1280, next.Canvas.Width); Assert.Equal(DesktopDisplayMode.Extend, next.Manager.Current.Mode);
    }

    [Fact]
    public void WindowsCanCrossDisplaysAndMaximizeWithinTheirOwnMonitor()
    {
        var (manager, _, _, canvas) = Create();
        var desktop = new DesktopSession(canvas, new MemoryWorkspace(), displays: manager);
        Assert.True(desktop.ApplyDisplayConfiguration(manager.Current.WithMode(DesktopDisplayMode.Extend)));
        desktop.KeepDisplayConfiguration();
        var window = desktop.Open(DesktopApplication.Files);
        var before = window.Bounds;
        desktop.Pointer(before.X + 60, before.Y + 16, true, timestampMs: 100);
        desktop.Pointer(800, 40, true, timestampMs: 200); desktop.Pointer(800, 40, false, timestampMs: 210);
        Assert.True(window.Bounds.X >= 640);
        desktop.ToggleMaximize(window.Id);
        Assert.Equal(new DesktopBounds(640, 0, 640, 480), window.Bounds);
        Assert.True(desktop.ApplyDisplayConfiguration(manager.Current.WithPrimary(Second.Id))); desktop.KeepDisplayConfiguration();
        Assert.Equal(new DesktopBounds(640, 0, 640, 432), desktop.WorkArea);
        desktop.OpenSettings(); desktop.Render();
        Assert.True(desktop.LastFrameCompleted);
    }

    [Fact]
    public void NegativeAndVerticalLayoutsConstrainPointerToActualScreenRegions()
    {
        var outputs = new[] { First, Second with { NativeHeight = 400 } };
        var config = new DesktopDisplayConfiguration(DesktopDisplayMode.Extend, First.Id, [new(First.Id, 0, 0), new(Second.Id, -640, 200)]);
        var layout = DesktopDisplayLayout.Create(outputs, config, 100);
        Assert.Equal(new DesktopBounds(640, 0, 640, 480), layout.Primary.Bounds);
        var position = layout.ConstrainPointer(10, 5);
        Assert.Equal((10, 200), position);
        Assert.Equal((650, 5), layout.ConstrainPointer(650, 5));
    }

    [Fact]
    public void ContinuousPointerRoutingAndOutputPresentationDoNotAllocate()
    {
        var (manager, _, _, _) = Create(Second with { NativeHeight = 400 });
        var configuration = new DesktopDisplayConfiguration(DesktopDisplayMode.Extend, First.Id,
            [new(First.Id, 0, 0), new(Second.Id, -640, 200)]);
        Assert.True(manager.TryApply(configuration, out var error), error);
        var pixels = new int[manager.Presenter.Width * manager.Presenter.Height];
        void Motion()
        {
            _ = manager.Layout.Primary;
            _ = manager.Layout.ConstrainPointer(650, 5);
            _ = manager.Layout.ConstrainPointer(10, 5);
            manager.Presenter.Present(pixels, new(640, 1, 8, 8));
        }
        for (int i = 0; i < 256; i++) Motion();
        long before = GC.GetAllocatedBytesForCurrentThread();
        for (int i = 0; i < 1024; i++) Motion();
        long allocated = GC.GetAllocatedBytesForCurrentThread() - before;
        Assert.Equal(0, allocated);
        Assert.Equal((10, 200), manager.Layout.ConstrainPointer(10, 5));
    }

    [Theory]
    [InlineData("{\"Version\":1,\"Version\":1,\"Mode\":\"Extend\",\"Primary\":\"first\",\"Positions\":[]}")]
    [InlineData("{\"Version\":1,\"Mode\":\"Bogus\",\"Primary\":\"first\",\"Positions\":[]}")]
    [InlineData("{\"Version\":1,\"Mode\":\"Extend\",\"Primary\":\"first\",\"Positions\":[{\"Id\":\"first\",\"X\":0,\"Y\":0,\"Unknown\":1}]}")]
    public void MalformedSettingsAreRejected(string json) => Assert.ThrowsAny<Exception>(() => DesktopDisplayConfiguration.Parse(json));
}