using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Windows.Input; using ytLive.Helpers; using ytLive.Models; namespace ytLive.ViewModels; public partial class MainViewModel { private const string WindowKeyPrefix = "window:"; private const string PickerKeyPrefix = "picker:"; /// True for session-scoped capture keys that must not persist /// across a reload: "picker:" picks (OS GraphicsCapturePicker) and "window:" /// pins (an HWND can be recycled to a different window after restart). private static bool IsTransientCaptureKey(string? key) { if (string.IsNullOrWhiteSpace(key)) return false; return key.StartsWith(WindowKeyPrefix, StringComparison.OrdinalIgnoreCase) || key.StartsWith(PickerKeyPrefix, StringComparison.OrdinalIgnoreCase); } /// True when the given capture key is a window pin whose window is /// still among the enumerated open windows — the pin then outranks /// auto-detection (see OnFullscreenMonitorChanged). private bool IsAliveWindowPin(string? key) { if (string.IsNullOrWhiteSpace(key) || !key.StartsWith(WindowKeyPrefix, StringComparison.OrdinalIgnoreCase)) return false; var hwndText = key.AsSpan(WindowKeyPrefix.Length).TrimStart(); if (hwndText.Length >= 2 && hwndText[0] == '0' && (hwndText[1] == 'x' || hwndText[1] == 'X')) hwndText = hwndText[2..]; var hwnd = long.TryParse(hwndText, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out var value) ? value : 0; foreach (var window in _windowEnumerator.Enumerate()) if (window.Hwnd == hwnd) return true; return false; } /// ScreenCaptureManager's session failed (the pinned window closed, /// a monitor went away, a transient pick expired, …). For a transient /// session-scoped key the pin no longer resolves — fall back to the automatic /// capture (game → desktop → static), mirroring the reload heal. private void OnScreenCaptureFailed(string key, string message) { AppLog.Write($"ScreenCaptureManager: capture '{key}' failed: {message}"); if (!IsTransientCaptureKey(key)) return; var pinned = AllBackgrounds().FirstOrDefault(b => b.CaptureKey == key); if (pinned == null) return; ReacquireScreenCaptures(); } /// Open windows offered to the "Capture Window…" submenu (session /// snapshot; refresh via ). public ObservableCollection OpenWindows { get; } = new(); public ICommand RefreshWindowsCommand { get; } public ICommand CaptureWindowCommand { get; } private void RefreshOpenWindows() { var windows = _windowEnumerator.Enumerate(); OpenWindows.Clear(); foreach (var window in windows) OpenWindows.Add(window); } }