diff --git a/Kernel.cs b/Kernel.cs index 8790e52..3dcb951 100644 --- a/Kernel.cs +++ b/Kernel.cs @@ -25,8 +25,6 @@ public class Kernel : Sys.Kernel Console.WriteLine("Cosmos booted successfully!"); Console.WriteLine("Type a command to get it executed."); - WindowManager.AddRenderSource(new CanvasRenderSource()); - CommandManager.RegisterCommands(new ICommand[] { new HelpCommand(), @@ -34,7 +32,8 @@ public class Kernel : Sys.Kernel new HaltCommand(), new SpawnTestProcessCommand(), new ListProcessesCommand(), - new StopProcessCommand() + new StopProcessCommand(), + new StartGuiCommand() }); Sys.Mouse.MouseManager.Initialize(); @@ -45,15 +44,34 @@ public class Kernel : Sys.Kernel ProcessManager.SpawnProcess(); } - Console.WriteLine(CosmosFeatures.MouseEnabled); Console.WriteLine(CosmosFeatures.KeyboardEnabled); - Console.WriteLine($"Canvas size: {FullScreenCanvas.GetFullScreenCanvas().Mode.Width}x{FullScreenCanvas.GetFullScreenCanvas().Mode.Height}"); } protected override void Run() { - WindowManager.Update(); + if (Processes.DesktopProcess.IsRunning) + { + // Suspend the CLI while the GUI is active to prevent blocking and console corruption. + Thread.Sleep(100); + return; + } + + Console.Write("> "); + + string? input = Console.ReadLine(); + + if (string.IsNullOrEmpty(input)) + { + return; + } + + if (CommandManager.TryExecute(input)) + { + return; + } + + Console.WriteLine($"\"{input}\" is not a command"); } } diff --git a/Processes/DesktopProcess.cs b/Processes/DesktopProcess.cs new file mode 100644 index 0000000..1de0696 --- /dev/null +++ b/Processes/DesktopProcess.cs @@ -0,0 +1,49 @@ +using System; +using System.Threading; +using Cosmos.Kernel.System.Graphics; +using RemSox.Processing; +using RemSox.UI.GUI.Rendering; +using RemSox.UI.GUI.Windows; + +namespace RemSox.Processes; + +public class DesktopProcess : Process +{ + private static bool isGraphicsInitialized = false; + + public static bool IsRunning { get; private set; } = false; + + public DesktopProcess() : base("Desktop Manager") + { + } + + internal override void Run() + { + IsRunning = true; + + if (!isGraphicsInitialized) + { + WindowManager.AddRenderSource(new CanvasRenderSource()); + isGraphicsInitialized = true; + } + + // Trigger Canvas initialization + FullScreenCanvas.GetFullScreenCanvas(); + + // Force existing windows to redraw onto the new canvas renderer + WindowManager.InvalidateAll(); + + while (!StopRequested) + { + WindowManager.Update(); + + // Sleep slightly to yield CPU to the main CLI thread (approx 60 FPS) + Thread.Sleep(16); + } + + IsRunning = false; + + // Cosmos doesn't robustly support switching back to text mode yet. + // We will stop updating, but the screen will remain in graphics mode. + } +} diff --git a/UI/GUI/CLI/Commands/StartGuiCommand.cs b/UI/GUI/CLI/Commands/StartGuiCommand.cs new file mode 100644 index 0000000..d74725f --- /dev/null +++ b/UI/GUI/CLI/Commands/StartGuiCommand.cs @@ -0,0 +1,18 @@ +using System; +using RemSox.Processing; +using RemSox.Processes; +using RemSox.UI.GUI.CLI; + +namespace RemSox.UI.GUI.CLI.Commands; + +public class StartGuiCommand : ICommand +{ + public string Name => "start-gui"; + public string Description => "Starts the Graphical User Interface (Desktop Process)"; + + public void Execute(string? args) + { + Console.WriteLine("Starting Desktop Process..."); + ProcessManager.SpawnProcess(); + } +} diff --git a/UI/GUI/Windows/Window.cs b/UI/GUI/Windows/Window.cs index da1a300..11c257c 100644 --- a/UI/GUI/Windows/Window.cs +++ b/UI/GUI/Windows/Window.cs @@ -85,6 +85,12 @@ public sealed class Window(string title, int processId, int id, IRenderSource re return uiElement; } + public void Invalidate() + { + isFirstRender = true; + Flush(); + } + public void Flush() { if (!IsVisible) diff --git a/UI/GUI/Windows/WindowManager.cs b/UI/GUI/Windows/WindowManager.cs index c1eec6c..451adf0 100644 --- a/UI/GUI/Windows/WindowManager.cs +++ b/UI/GUI/Windows/WindowManager.cs @@ -140,6 +140,17 @@ public static class WindowManager return null; } + public static void InvalidateAll() + { + foreach (var processWindows in windows.Values) + { + foreach (var window in processWindows) + { + window.Invalidate(); + } + } + } + private static int GetNextWindowId() { return nextWindowId++;