diff --git a/Kernel.cs b/Kernel.cs index 97b1272..feb15e0 100644 --- a/Kernel.cs +++ b/Kernel.cs @@ -91,7 +91,7 @@ public class Kernel : Sys.Kernel if (leftButtonDown && !wasLeftButtonDown) { - activeInteractWindow = TryBeginInteract(pointerPosition); + activeInteractWindow = WindowManager.TryBeginInteract(pointerPosition); } else if (leftButtonDown && activeInteractWindow is not null) { @@ -111,26 +111,6 @@ public class Kernel : Sys.Kernel lastPointerPosition = pointerPosition; } - - private static Window? TryBeginInteract(Point pointerPosition) - { - foreach (Processing.Process process in ProcessManager.GetAllProcesses()) - { - List windows = WindowManager.GetWindowsForProcess(process); - - for (int index = windows.Count - 1; index >= 0; index--) - { - Window window = windows[index]; - - if (window.TryBeginInteract(pointerPosition)) - { - return window; - } - } - } - - return null; - } } public class TestProcess() : Processing.Process("Test Process") diff --git a/UI/GUI/Rendering/CanvasRenderSource.cs b/UI/GUI/Rendering/CanvasRenderSource.cs index d28c12b..d07be6e 100644 --- a/UI/GUI/Rendering/CanvasRenderSource.cs +++ b/UI/GUI/Rendering/CanvasRenderSource.cs @@ -1,6 +1,7 @@ using System; using System.Drawing; using System.Collections.Generic; +using System.Linq; using Cosmos.Kernel.System.Graphics; namespace RemSox.UI.GUI.Rendering; @@ -9,11 +10,20 @@ public sealed class CanvasRenderSource : IRenderSource { private static readonly Dictionary windowCanvases = new(); private static readonly Dictionary windowPositions = new(); + private static readonly Dictionary windowZIndices = new(); public void Render(IEnumerable commands) { foreach (RenderCommand command in commands) { + if (command.ElementType == "Window" || command.ElementType == "WindowMove") + { + if (command.Properties.TryGetValue("ZIndex", out object? rawZIndex) && rawZIndex is int z) + { + windowZIndices[command.WindowId] = z; + } + } + if (command.ElementType == "Window") { Size size = command.Properties.TryGetValue("Size", out object? rawSize) && rawSize is Size windowSize @@ -59,11 +69,11 @@ public sealed class CanvasRenderSource : IRenderSource { screenCanvas.Clear(Color.Black); - foreach (var kvp in windowPositions) + var orderedWindows = windowPositions.Keys.OrderBy(id => windowZIndices.TryGetValue(id, out int z) ? z : 0); + + foreach (var windowId in orderedWindows) { - int windowId = kvp.Key; - Point position = kvp.Value; - if (windowCanvases.TryGetValue(windowId, out Canvas? windowCanvas)) + if (windowPositions.TryGetValue(windowId, out Point position) && windowCanvases.TryGetValue(windowId, out Canvas? windowCanvas)) { screenCanvas.DrawCanvas(windowCanvas, position.X, position.Y); } diff --git a/UI/GUI/Windows/Window.cs b/UI/GUI/Windows/Window.cs index 6a4379d..da1a300 100644 --- a/UI/GUI/Windows/Window.cs +++ b/UI/GUI/Windows/Window.cs @@ -14,6 +14,8 @@ public sealed class Window(string title, int processId, int id, IRenderSource re public string Title { get; set; } = title; + public int ZIndex { get; set; } + public bool AutoFlush { get; set; } = false; public bool IsFocused @@ -51,6 +53,7 @@ public sealed class Window(string title, int processId, int id, IRenderSource re private Size lastRenderedSize = new Size(-1, -1); private bool lastRenderedIsFocused = false; private string lastRenderedTitle = string.Empty; + private int lastRenderedZIndex = -1; private bool isFirstRender = true; public T CreateUIElement(Action? options = null) where T : UIElement, new() @@ -92,6 +95,7 @@ public sealed class Window(string title, int processId, int id, IRenderSource re bool windowStateChanged = isFirstRender || Size != lastRenderedSize || IsFocused != lastRenderedIsFocused || Title != lastRenderedTitle; bool anyChildChanged = uiElements.Values.Any(e => e.AnyPropertyChanged); bool positionChanged = Position != lastRenderedPosition; + bool zIndexChanged = ZIndex != lastRenderedZIndex; bool fullRedraw = windowStateChanged || anyChildChanged; @@ -111,7 +115,8 @@ public sealed class Window(string title, int processId, int id, IRenderSource re [nameof(Size)] = Size, [nameof(IsFocused)] = IsFocused, [nameof(IsResizable)] = IsResizable, - [nameof(IsDraggable)] = IsDraggable + [nameof(IsDraggable)] = IsDraggable, + [nameof(ZIndex)] = ZIndex } }); @@ -128,7 +133,7 @@ public sealed class Window(string title, int processId, int id, IRenderSource re element.ClearChangedProperties(); } } - else if (positionChanged) + else if (positionChanged || zIndexChanged) { commands.Add(new RenderCommand { @@ -136,7 +141,10 @@ public sealed class Window(string title, int processId, int id, IRenderSource re ElementId = Id, ElementType = "WindowMove", Position = Position, - Properties = new Dictionary() + Properties = new Dictionary + { + [nameof(ZIndex)] = ZIndex + } }); } @@ -147,6 +155,7 @@ public sealed class Window(string title, int processId, int id, IRenderSource re lastRenderedSize = Size; lastRenderedIsFocused = IsFocused; lastRenderedTitle = Title; + lastRenderedZIndex = ZIndex; isFirstRender = false; } } diff --git a/UI/GUI/Windows/WindowManager.cs b/UI/GUI/Windows/WindowManager.cs index da7d001..c9bd21e 100644 --- a/UI/GUI/Windows/WindowManager.cs +++ b/UI/GUI/Windows/WindowManager.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Drawing; +using System.Linq; using RemSox.Processing; using RemSox.UI.GUI.Rendering; @@ -12,6 +14,7 @@ public static class WindowManager private static readonly ConcurrentDictionary> windows = new(); private static int nextWindowId = 1; + private static int nextZIndex = 1; private static Window? focusedWindow; @@ -26,7 +29,8 @@ public static class WindowManager Window window = new(title, process.Id, GetNextWindowId(), renderSource) { Position = position, - Size = size + Size = size, + ZIndex = nextZIndex++ }; if (!windows.ContainsKey(process.Id)) @@ -69,6 +73,11 @@ public static class WindowManager return; } + if (window != null) + { + window.ZIndex = nextZIndex++; + } + Window? previousFocusedWindow = focusedWindow; focusedWindow = window; @@ -81,6 +90,19 @@ public static class WindowManager return focusedWindow == window; } + public static Window? TryBeginInteract(Point pointerPosition) + { + var allWindows = windows.Values.SelectMany(w => w).OrderByDescending(w => w.ZIndex); + foreach (var window in allWindows) + { + if (window.TryBeginInteract(pointerPosition)) + { + return window; + } + } + return null; + } + private static int GetNextWindowId() { return nextWindowId++;