using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using Microsoft.Data.Sqlite;
using Xunit;
using ytLive.Services;
using ytLive.ViewModels;
namespace ytLive.Tests;
///
/// The desktop-"lock" bug (2026-10-10): at launch the main window ACTIVES
/// (WPF default ShowActivated = true), and when the creator is already
/// playing an exclusive-fullscreen game, activating LlamaCasty makes Windows
/// drop that game to the taskbar; the app's 1920×1040 window then sits over the
/// whole work area, so the desktop looks locked and the game can't be reached
/// with the mouse. Fix: the window opens WITHOUT activating when a full-screen
/// game owns the foreground at launch — ShowActivated = !FullscreenGameRunningNow.
/// These tests pin that rule using the FullScreenDetectorOverride seam,
/// so no real Win32 foreground state is touched.
///
[Collection("RealApp")]
public sealed class DesktopLockTests
{
private readonly RealAppHost _app;
public DesktopLockTests(RealAppHost app) => _app = app;
[Fact]
public void MainWindow_Does_Not_Steal_Focus_When_A_Fullscreen_Game_Is_Foreground()
{
_app.Run(() =>
{
using var _ = new TempLayout();
MainViewModel.FullScreenDetectorOverride = new StubFullScreenDetector(foregroundMonitor: 0);
try
{
var window = new MainWindow();
try
{
// The regression: a full-screen game already owns the screen, so
// the window must open WITHOUT activating to keep the game live.
Assert.False(window.ShowActivated,
"launching while a full-screen game owns the foreground must not steal focus");
}
finally
{
window.Close();
}
}
finally
{
MainViewModel.FullScreenDetectorOverride = null;
}
});
}
[Fact]
public void MainWindow_Normal_Launch_Still_Activates()
{
_app.Run(() =>
{
using var _ = new TempLayout();
MainViewModel.FullScreenDetectorOverride = new StubFullScreenDetector(foregroundMonitor: null);
try
{
var window = new MainWindow();
try
{
// No game running: behaviour is exactly as before the fix.
Assert.True(window.ShowActivated,
"a normal launch (no full-screen game) must keep the default activate-on-show");
}
finally
{
window.Close();
}
}
finally
{
MainViewModel.FullScreenDetectorOverride = null;
}
});
}
[Fact]
public void FullscreenGameRunningNow_Reflects_The_Foreground_Monitor()
{
_app.Run(() =>
{
MainViewModel.FullScreenDetectorOverride = new StubFullScreenDetector(foregroundMonitor: 0);
try
{
var gameVm = new MainViewModel();
Assert.True(gameVm.FullscreenGameRunningNow);
}
finally
{
MainViewModel.FullScreenDetectorOverride = null;
}
MainViewModel.FullScreenDetectorOverride = new StubFullScreenDetector(foregroundMonitor: null);
try
{
var idleVm = new MainViewModel();
Assert.False(idleVm.FullscreenGameRunningNow);
}
finally
{
MainViewModel.FullScreenDetectorOverride = null;
}
});
}
private sealed class TempLayout : IDisposable
{
private readonly string _path;
public TempLayout()
{
_path = Path.Combine(Path.GetTempPath(), $"ytLive-desktoplock-{Guid.NewGuid():N}.db");
using (var schema = new LayoutStore(_path)) { }
SqliteConnection.ClearAllPools();
MainViewModel.LayoutPathOverride = _path;
}
public void Dispose()
{
MainViewModel.LayoutPathOverride = null;
SqliteConnection.ClearAllPools();
try { File.Delete(_path); } catch { /* best-effort cleanup */ }
}
}
/// A deterministic stand-in for :
/// claims a full-screen window owns the given foreground monitor (or none).
#pragma warning disable CS0067 // fullscreen-changed wiring is not part of this seam
private sealed class StubFullScreenDetector : IFullScreenDetector
{
private readonly int? _foregroundMonitor;
public StubFullScreenDetector(int? foregroundMonitor) => _foregroundMonitor = foregroundMonitor;
public int? GetForegroundFullScreenMonitorIndex() => _foregroundMonitor;
public int PrimaryMonitorIndex() => 0;
public IReadOnlyList GetDisplays() => Array.Empty();
public event Action? FullscreenMonitorChanged;
public void StartWatching() { }
public void StopWatching() { }
}
}