using XFESystem.Core;
using XFESystem.Desktop;
using Xunit;
namespace XFESystem.Core.Tests;
public sealed class DesktopMotionTests
{
private sealed class Canvas : IDesktopSceneMotionCanvas
{
public int Width => 1280;
public int Height => 800;
public bool SupportsSceneCache => true;
public List<(DesktopBounds Source, int X, int Y)> Moves { get; } = [];
public void Fill(uint rgb, int x, int y, int width, int height) { }
public void Line(uint rgb, int x1, int y1, int x2, int y2) { }
public void Text(string text, uint rgb, int x, int y) { }
public void Present() { }
public void PreserveTranslatedSceneRegion(DesktopBounds source, int destinationX, int destinationY) => Moves.Add((source, destinationX, destinationY));
public void EndScenePreservation() { }
}
[Fact]
public void CoalescedDragReadsLastRenderedSceneRatherThanIntermediateInputBounds()
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
var window = desktop.Open(DesktopApplication.Editor); desktop.Render(); var original = window.Bounds;
desktop.Pointer(original.X + 90, original.Y + 15, true, timestampMs: 100); desktop.Render();
desktop.Pointer(original.X + 100, original.Y + 17, true, timestampMs: 110);
desktop.Pointer(original.X + 110, original.Y + 19, true, timestampMs: 115);
desktop.Render(); var move = Assert.Single(canvas.Moves);
Assert.Equal(new DesktopBounds(original.X + 2, original.Y + 65, original.Width - 4, original.Height - 109), move.Source);
Assert.Equal(window.Bounds.X + 2, move.X); Assert.Equal(window.Bounds.Y + 65, move.Y);
var rendered = window.Bounds;
desktop.Pointer(original.X + 120, original.Y + 20, true, timestampMs: 120); desktop.Render();
Assert.Equal(rendered.X + 2, canvas.Moves[^1].Source.X);
}
[Fact]
public void EditingBetweenMotionPacketsCancelsReuseOfStaleDocumentPixels()
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
var window = desktop.Open(DesktopApplication.Editor); desktop.Render(); var b = window.Bounds;
desktop.Pointer(b.X + 90, b.Y + 15, true, timestampMs: 100); desktop.Render();
desktop.Pointer(b.X + 100, b.Y + 17, true, timestampMs: 110);
desktop.Key(DesktopKey.Character, 'Z'); desktop.Render();
Assert.Empty(canvas.Moves); Assert.Equal("Z", window.Content);
desktop.Pointer(b.X + 110, b.Y + 18, true, timestampMs: 120); desktop.Render();
Assert.Single(canvas.Moves);
}
[Fact]
public void ResizeReusesOnlyACommonPrefixAfterItsInitialFullComposition()
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
var window = desktop.Open(DesktopApplication.Editor); desktop.Render(); var b = window.Bounds;
desktop.Pointer(b.X + 90, b.Y + 15, true, timestampMs: 100); desktop.Render();
desktop.Key(DesktopKey.Maximize); desktop.Render(); Assert.Empty(canvas.Moves);
desktop.Key(DesktopKey.Restore); desktop.Render(); b = window.Bounds;
desktop.Pointer(b.X + b.Width - 5, b.Y + b.Height - 5, false, timestampMs: 200);
desktop.Pointer(b.X + b.Width - 5, b.Y + b.Height - 5, true, timestampMs: 205); desktop.Render();
Assert.Empty(canvas.Moves);
desktop.Pointer(b.X + b.Width + 10, b.Y + b.Height + 10, true, timestampMs: 210); desktop.Render();
var move = Assert.Single(canvas.Moves);
Assert.Equal(new DesktopBounds(b.X + 2, b.Y + 65, b.Width - 96, b.Height - 129), move.Source);
Assert.Equal(move.Source.X, move.X); Assert.Equal(move.Source.Y, move.Y);
desktop.Pointer(b.X + b.Width - 20, b.Y + b.Height - 20, true, timestampMs: 220); desktop.Render();
Assert.Equal(2, canvas.Moves.Count);
Assert.Equal(window.Bounds.Width - 96, canvas.Moves[^1].Source.Width);
Assert.Equal(window.Bounds.Height - 129, canvas.Moves[^1].Source.Height);
}
[Fact]
public void SettingsResizeAlwaysRecomposesConditionallyVisibleControls()
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
var window = desktop.Open(DesktopApplication.Settings); desktop.Render(); var b = window.Bounds;
desktop.Pointer(b.X + b.Width - 5, b.Y + b.Height - 5, true, timestampMs: 100); desktop.Render();
desktop.Pointer(b.X + b.Width - 50, b.Y + b.Height - 50, true, timestampMs: 110); desktop.Render();
Assert.Empty(canvas.Moves);
}
[Theory]
[InlineData(DesktopApplication.Files, 515, 524)]
[InlineData(DesktopApplication.Files, 524, 515)]
[InlineData(DesktopApplication.Editor, 511, 512)]
[InlineData(DesktopApplication.Editor, 512, 511)]
[InlineData(DesktopApplication.Terminal, 511, 512)]
public void ResizePrefixStopsBeforeEitherLayoutsFirstHiddenRow(DesktopApplication app, int oldHeight, int newHeight)
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
var window = desktop.Open(app); desktop.Render(); var original = window.Bounds;
int px = original.X + original.Width - 5, py = original.Y + original.Height - 5;
desktop.Pointer(px, py, true, timestampMs: 100); desktop.Render();
desktop.Pointer(px, py + oldHeight - original.Height, true, timestampMs: 110); desktop.Render();
canvas.Moves.Clear();
desktop.Pointer(px, py + newHeight - original.Height, true, timestampMs: 120); desktop.Render();
var prefix = Assert.Single(canvas.Moves).Source;
int rows = app == DesktopApplication.Files ? Math.Min((oldHeight - 132) / 28, (newHeight - 132) / 28) :
Math.Min((oldHeight - 112) / 20, (newHeight - 112) / 20);
int firstHiddenTop = original.Y + (app == DesktopApplication.Files ? 96 + rows * 28 : 76 + rows * 20);
Assert.True(prefix.Y + prefix.Height <= firstHiddenTop);
}
[Fact]
public void CodeResizeRepaintsTheWholeKeywordWhoseColorCanChangeAtTruncation()
{
var canvas = new Canvas(); var storage = new MemoryWorkspace();
string path = SystemPaths.Combine(SystemPaths.Documents, "Program.cs"); storage.WriteText(path, new string(' ', 22) + "namespaceABCD");
var desktop = new DesktopSession(canvas, storage); var window = desktop.Open(DesktopApplication.Editor, path); desktop.Render();
var original = window.Bounds; int py = original.Y + original.Height - 5;
desktop.Pointer(original.X + original.Width - 5, py, true, timestampMs: 100); desktop.Render();
desktop.Pointer(original.X + 320 - 5, py, true, timestampMs: 110); desktop.Render(); canvas.Moves.Clear();
desktop.Pointer(original.X + 352 - 5, py, true, timestampMs: 120); desktop.Render();
var prefix = Assert.Single(canvas.Moves).Source;
Assert.Equal(160, prefix.Width); Assert.True(prefix.X + prefix.Width <= original.X + 20 + 22 * 8);
}
}
using XFESystem.Core;
using XFESystem.Desktop;
using Xunit;
namespace XFESystem.Core.Tests;
public sealed class DesktopMotionTests
{
private sealed class Canvas : IDesktopSceneMotionCanvas
{
public int Width => 1280;
public int Height => 800;
public bool SupportsSceneCache => true;
public List<(DesktopBounds Source, int X, int Y)> Moves { get; } = [];
public void Fill(uint rgb, int x, int y, int width, int height) { }
public void Line(uint rgb, int x1, int y1, int x2, int y2) { }
public void Text(string text, uint rgb, int x, int y) { }
public void Present() { }
public void PreserveTranslatedSceneRegion(DesktopBounds source, int destinationX, int destinationY) => Moves.Add((source, destinationX, destinationY));
public void EndScenePreservation() { }
}
[Fact]
public void CoalescedDragReadsLastRenderedSceneRatherThanIntermediateInputBounds()
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
var window = desktop.Open(DesktopApplication.Editor); desktop.Render(); var original = window.Bounds;
desktop.Pointer(original.X + 90, original.Y + 15, true, timestampMs: 100); desktop.Render();
desktop.Pointer(original.X + 100, original.Y + 17, true, timestampMs: 110);
desktop.Pointer(original.X + 110, original.Y + 19, true, timestampMs: 115);
desktop.Render(); var move = Assert.Single(canvas.Moves);
Assert.Equal(new DesktopBounds(original.X + 2, original.Y + 65, original.Width - 4, original.Height - 109), move.Source);
Assert.Equal(window.Bounds.X + 2, move.X); Assert.Equal(window.Bounds.Y + 65, move.Y);
var rendered = window.Bounds;
desktop.Pointer(original.X + 120, original.Y + 20, true, timestampMs: 120); desktop.Render();
Assert.Equal(rendered.X + 2, canvas.Moves[^1].Source.X);
}
[Fact]
public void EditingBetweenMotionPacketsCancelsReuseOfStaleDocumentPixels()
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
var window = desktop.Open(DesktopApplication.Editor); desktop.Render(); var b = window.Bounds;
desktop.Pointer(b.X + 90, b.Y + 15, true, timestampMs: 100); desktop.Render();
desktop.Pointer(b.X + 100, b.Y + 17, true, timestampMs: 110);
desktop.Key(DesktopKey.Character, 'Z'); desktop.Render();
Assert.Empty(canvas.Moves); Assert.Equal("Z", window.Content);
desktop.Pointer(b.X + 110, b.Y + 18, true, timestampMs: 120); desktop.Render();
Assert.Single(canvas.Moves);
}
[Fact]
public void ResizeReusesOnlyACommonPrefixAfterItsInitialFullComposition()
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
var window = desktop.Open(DesktopApplication.Editor); desktop.Render(); var b = window.Bounds;
desktop.Pointer(b.X + 90, b.Y + 15, true, timestampMs: 100); desktop.Render();
desktop.Key(DesktopKey.Maximize); desktop.Render(); Assert.Empty(canvas.Moves);
desktop.Key(DesktopKey.Restore); desktop.Render(); b = window.Bounds;
desktop.Pointer(b.X + b.Width - 5, b.Y + b.Height - 5, false, timestampMs: 200);
desktop.Pointer(b.X + b.Width - 5, b.Y + b.Height - 5, true, timestampMs: 205); desktop.Render();
Assert.Empty(canvas.Moves);
desktop.Pointer(b.X + b.Width + 10, b.Y + b.Height + 10, true, timestampMs: 210); desktop.Render();
var move = Assert.Single(canvas.Moves);
Assert.Equal(new DesktopBounds(b.X + 2, b.Y + 65, b.Width - 96, b.Height - 129), move.Source);
Assert.Equal(move.Source.X, move.X); Assert.Equal(move.Source.Y, move.Y);
desktop.Pointer(b.X + b.Width - 20, b.Y + b.Height - 20, true, timestampMs: 220); desktop.Render();
Assert.Equal(2, canvas.Moves.Count);
Assert.Equal(window.Bounds.Width - 96, canvas.Moves[^1].Source.Width);
Assert.Equal(window.Bounds.Height - 129, canvas.Moves[^1].Source.Height);
}
[Fact]
public void SettingsResizeAlwaysRecomposesConditionallyVisibleControls()
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
var window = desktop.Open(DesktopApplication.Settings); desktop.Render(); var b = window.Bounds;
desktop.Pointer(b.X + b.Width - 5, b.Y + b.Height - 5, true, timestampMs: 100); desktop.Render();
desktop.Pointer(b.X + b.Width - 50, b.Y + b.Height - 50, true, timestampMs: 110); desktop.Render();
Assert.Empty(canvas.Moves);
}
[Theory]
[InlineData(DesktopApplication.Files, 515, 524)]
[InlineData(DesktopApplication.Files, 524, 515)]
[InlineData(DesktopApplication.Editor, 511, 512)]
[InlineData(DesktopApplication.Editor, 512, 511)]
[InlineData(DesktopApplication.Terminal, 511, 512)]
public void ResizePrefixStopsBeforeEitherLayoutsFirstHiddenRow(DesktopApplication app, int oldHeight, int newHeight)
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
var window = desktop.Open(app); desktop.Render(); var original = window.Bounds;
int px = original.X + original.Width - 5, py = original.Y + original.Height - 5;
desktop.Pointer(px, py, true, timestampMs: 100); desktop.Render();
desktop.Pointer(px, py + oldHeight - original.Height, true, timestampMs: 110); desktop.Render();
canvas.Moves.Clear();
desktop.Pointer(px, py + newHeight - original.Height, true, timestampMs: 120); desktop.Render();
var prefix = Assert.Single(canvas.Moves).Source;
int rows = app == DesktopApplication.Files ? Math.Min((oldHeight - 132) / 28, (newHeight - 132) / 28) :
Math.Min((oldHeight - 112) / 20, (newHeight - 112) / 20);
int firstHiddenTop = original.Y + (app == DesktopApplication.Files ? 96 + rows * 28 : 76 + rows * 20);
Assert.True(prefix.Y + prefix.Height <= firstHiddenTop);
}
[Fact]
public void CodeResizeRepaintsTheWholeKeywordWhoseColorCanChangeAtTruncation()
{
var canvas = new Canvas(); var storage = new MemoryWorkspace();
string path = SystemPaths.Combine(SystemPaths.Documents, "Program.cs"); storage.WriteText(path, new string(' ', 22) + "namespaceABCD");
var desktop = new DesktopSession(canvas, storage); var window = desktop.Open(DesktopApplication.Editor, path); desktop.Render();
var original = window.Bounds; int py = original.Y + original.Height - 5;
desktop.Pointer(original.X + original.Width - 5, py, true, timestampMs: 100); desktop.Render();
desktop.Pointer(original.X + 320 - 5, py, true, timestampMs: 110); desktop.Render(); canvas.Moves.Clear();
desktop.Pointer(original.X + 352 - 5, py, true, timestampMs: 120); desktop.Render();
var prefix = Assert.Single(canvas.Moves).Source;
Assert.Equal(160, prefix.Width); Assert.True(prefix.X + prefix.Width <= original.X + 20 + 22 * 8);
}
}