using Cosmos.Kernel.System.Graphics; using Cosmos.Kernel.System.Keyboard; using Cosmos.Kernel.System.Mouse; using RemSox.Processing; using RemSox.UI.GUI.Rendering; using System.Drawing; namespace RemSox.UI.GUI.Windows; /// /// Manages window creation, focus, interaction, and rendering orchestration for the GUI system. /// public static class WindowManager { private static readonly Lock windowsLock = new(); // Process ID to list of windows private static readonly Dictionary> windows = []; private static int nextWindowId = 1; private static int nextZIndex = 1; private static Window? focusedWindow; private static Window? activeInteractWindow = null; private static Point lastPointerPosition = Point.Empty; private static bool wasLeftButtonDown = false; private static readonly MuliRenderSource renderSource = new([]); /// /// Processes input, updates interaction state, and triggers rendering of all windows. /// public static void Update() { MouseManager.Poll(); Point pointerPosition = new(MouseManager.X, MouseManager.Y); bool leftButtonDown = MouseManager.LeftButton; if (leftButtonDown && !wasLeftButtonDown) { activeInteractWindow = TryBeginInteract(pointerPosition); } else if (leftButtonDown && activeInteractWindow is not null) { activeInteractWindow.UpdateInteraction(pointerPosition); } else if (!leftButtonDown && activeInteractWindow is not null) { activeInteractWindow.EndInteraction(); activeInteractWindow = null; } wasLeftButtonDown = leftButtonDown; while (KeyboardManager.TryReadKey(out KeyEvent? keyEvent) && keyEvent is not null) { focusedWindow?.HandleKeyEvent(keyEvent); } Canvas canvas = FullScreenCanvas.GetFullScreenCanvas(); CanvasRenderSource.CompositeAndDisplay(canvas, pointerPosition); lastPointerPosition = pointerPosition; } /// /// Adds a new rendering source to the compositor. /// public static void AddRenderSource(IRenderSource source) { renderSource.AddSource(source); } /// /// Removes an existing rendering source from the compositor. /// public static void RemoveRenderSource(IRenderSource source) { renderSource.RemoveSource(source); } /// /// Creates and registers a new window for the specified process. /// public static Window CreateWindow(Process process, string title, Point position, Size size) { Window window = new(title, process.Id, GetNextWindowId(), renderSource) { Position = position, Size = size, ZIndex = nextZIndex++ }; lock (windowsLock) { if (!windows.ContainsKey(process.Id)) { windows[process.Id] = []; } windows[process.Id].Add(window); } return window; } /// /// Closes a specific window and notifies the renderer. /// public static void CloseWindow(Window window) { lock (windowsLock) { if (windows.TryGetValue(window.ProcessId, out List? processWindows)) { _ = processWindows.Remove(window); } } renderSource.Render([new RenderCommand { WindowId = window.Id, ElementId = window.Id, ElementType = "WindowClose", Position = window.Position, Properties = new Dictionary() }]); } /// /// Returns a list of all windows belonging to the given process. /// public static List GetWindowsForProcess(Process process) { lock (windowsLock) { if (windows.TryGetValue(process.Id, out List? processWindows)) { return processWindows.ToList(); } return []; } } /// /// Closes all windows belonging to the given process. /// public static void CloseWindowsForProcess(Process process) { CloseWindowsForProcess(process.Id); } /// /// Closes all windows belonging to the given process ID. /// public static void CloseWindowsForProcess(int processId) { List windowsToClose = []; lock (windowsLock) { if (windows.TryGetValue(processId, out List? processWindows)) { windowsToClose.AddRange(processWindows); _ = windows.Remove(processId); } } if (windowsToClose.Count > 0) { List closeCommands = []; foreach (Window window in windowsToClose) { closeCommands.Add(new RenderCommand { WindowId = window.Id, ElementId = window.Id, ElementType = "WindowClose", Position = window.Position, Properties = new Dictionary() }); } renderSource.Render(closeCommands); } } /// /// Sets the focus to the specified window, bringing it to the foreground. /// public static void FocusWindow(Window? window) { if (focusedWindow == window) { return; } _ = window?.ZIndex = nextZIndex++; Window? previousFocusedWindow = focusedWindow; focusedWindow = window; previousFocusedWindow?.Flush(); focusedWindow?.Flush(); } /// /// Checks if the specified window is currently focused. /// public static bool IsWindowFocused(Window window) { return focusedWindow == window; } /// /// Attempts to begin interaction (drag/resize) with a window at the specified pointer position. /// public static Window? TryBeginInteract(Point pointerPosition) { List allWindows; lock (windowsLock) { allWindows = windows.Values.SelectMany(w => w).OrderByDescending(w => w.ZIndex).ToList(); } foreach (Window window in allWindows) { if (window.TryBeginInteract(pointerPosition)) { return window; } } return null; } /// /// Forces a full redraw of all windows in the system. /// public static void InvalidateAll() { List allWindows; lock (windowsLock) { allWindows = windows.Values.SelectMany(w => w).ToList(); } foreach (Window window in allWindows) { window.Invalidate(); } } private static int GetNextWindowId() { return nextWindowId++; } private sealed class MuliRenderSource(List sources) : IRenderSource { private readonly Lock sourcesLock = new(); public void AddSource(IRenderSource source) { lock (sourcesLock) { sources.Add(source); } } public void RemoveSource(IRenderSource source) { lock (sourcesLock) { _ = sources.Remove(source); } } public void Render(IEnumerable commands) { List sourcesCopy; lock (sourcesLock) { sourcesCopy = sources.ToList(); } foreach (IRenderSource source in sourcesCopy) { source.Render(commands); } } } }