diff --git a/BuildTime.txt b/BuildTime.txt index d91312e..32cc382 100644 --- a/BuildTime.txt +++ b/BuildTime.txt @@ -1 +1 @@ -2026-03-06 21:05:30 \ No newline at end of file +2026-03-08 19:50:50 \ No newline at end of file diff --git a/CMLeonOS.csproj b/CMLeonOS.csproj index 63e2a4f..1621d77 100644 --- a/CMLeonOS.csproj +++ b/CMLeonOS.csproj @@ -29,7 +29,7 @@ 2 800x600x32 Always - 1 + 0 False diff --git a/Driver/VMWareSVGAII.cs b/Driver/VMWareSVGAII.cs index 08ce56e..5cb7660 100644 --- a/Driver/VMWareSVGAII.cs +++ b/Driver/VMWareSVGAII.cs @@ -525,8 +525,6 @@ namespace CMLeonOS.Driver IRQPort = (ushort)(basePort + (uint)IOPortOffset.IRQ); WriteRegister(Register.ID, (uint)ID.V2); - if (ReadRegister(Register.ID) != (uint)ID.V2) - return; VideoMemory = new MemoryBlock(ReadRegister(Register.FrameBufferStart), ReadRegister(Register.VRamSize)); capabilities = ReadRegister(Register.Capabilities); @@ -554,10 +552,8 @@ namespace CMLeonOS.Driver /// Depth. public void SetMode(uint width, uint height, uint depth = 32) { - //Disable the Driver before writing new values and initiating it again to avoid a memory exception - //Disable(); + Disable(); - // Depth is color depth in bytes. this.depth = (depth / 8); this.width = width; this.height = height; diff --git a/GitCommit.txt b/GitCommit.txt index 2c624a1..b948120 100644 --- a/GitCommit.txt +++ b/GitCommit.txt @@ -1 +1 @@ -6c514df \ No newline at end of file +de16189 \ No newline at end of file diff --git a/Gui/Apps/CodeStudio/Ide.cs b/Gui/Apps/CodeStudio/Ide.cs index 7472353..05ce47b 100644 --- a/Gui/Apps/CodeStudio/Ide.cs +++ b/Gui/Apps/CodeStudio/Ide.cs @@ -1,4 +1,4 @@ -using CMLeonOS; +using CMLeonOS; using CMLeonOS.Gui.UILib; using Cosmos.System.Graphics; using System.Drawing; @@ -17,6 +17,10 @@ namespace CMLeonOS.Gui.Apps.CodeStudio this.wm = wm; } + [IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.AppIcons.CodeStudio.bmp")] + private static byte[] _iconBytes; + private static Bitmap iconBitmap = new Bitmap(_iconBytes); + [IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.CodeStudio.Run.bmp")] private static byte[] _runBytes; private static Bitmap runBitmap = new Bitmap(_runBytes); @@ -175,6 +179,9 @@ namespace CMLeonOS.Gui.Apps.CodeStudio ILuaState lua = LuaAPI.NewState(); lua.L_OpenLibs(); + LuaGuiLibrary.Initialize(wm, process); + LuaGuiLibrary.Register(lua); + lua.PushCSharpFunction(L => { int n = L.GetTop(); @@ -275,6 +282,7 @@ namespace CMLeonOS.Gui.Apps.CodeStudio internal void Start() { mainWindow = new AppWindow(process, 96, 96, 800, 600); + mainWindow.Icon = iconBitmap; mainWindow.Clear(Theme.Background); mainWindow.Closing = process.TryStop; mainWindow.CanResize = true; diff --git a/Gui/Apps/CodeStudio/LuaGuiLibrary.cs b/Gui/Apps/CodeStudio/LuaGuiLibrary.cs new file mode 100644 index 0000000..a710099 --- /dev/null +++ b/Gui/Apps/CodeStudio/LuaGuiLibrary.cs @@ -0,0 +1,439 @@ +using CMLeonOS.Gui; +using CMLeonOS.Gui.UILib; +using Cosmos.System.Graphics; +using System.Drawing; +using UniLua; +using System; + +namespace CMLeonOS.Gui.Apps.CodeStudio +{ + internal class LuaGuiLibrary + { + private static WindowManager? wm = null; + private static Process? process = null; + + public static void Initialize(WindowManager windowManager, Process currentProcess) + { + wm = windowManager; + process = currentProcess; + } + + public static void Register(ILuaState lua) + { + if (wm == null || process == null) + { + throw new Exception("GUI library not initialized. Make sure you are running in GUI mode."); + } + + lua.NewTable(); + + lua.PushString("createWindow"); + lua.PushCSharpFunction(CreateWindow); + lua.SetTable(-3); + + lua.PushString("showMessageBox"); + lua.PushCSharpFunction(ShowMessageBox); + lua.SetTable(-3); + + lua.PushString("closeWindow"); + lua.PushCSharpFunction(CloseWindow); + lua.SetTable(-3); + + lua.PushString("setWindowTitle"); + lua.PushCSharpFunction(SetWindowTitle); + lua.SetTable(-3); + + lua.PushString("setWindowSize"); + lua.PushCSharpFunction(SetWindowSize); + lua.SetTable(-3); + + lua.PushString("setWindowPosition"); + lua.PushCSharpFunction(SetWindowPosition); + lua.SetTable(-3); + + lua.PushString("clearWindow"); + lua.PushCSharpFunction(ClearWindow); + lua.SetTable(-3); + + lua.PushString("drawText"); + lua.PushCSharpFunction(DrawText); + lua.SetTable(-3); + + lua.PushString("drawRectangle"); + lua.PushCSharpFunction(DrawRectangle); + lua.SetTable(-3); + + lua.PushString("drawFilledRectangle"); + lua.PushCSharpFunction(DrawFilledRectangle); + lua.SetTable(-3); + + lua.PushString("drawCircle"); + lua.PushCSharpFunction(DrawCircle); + lua.SetTable(-3); + + lua.PushString("drawLine"); + lua.PushCSharpFunction(DrawLine); + lua.SetTable(-3); + + lua.PushString("drawPoint"); + lua.PushCSharpFunction(DrawPoint); + lua.SetTable(-3); + + lua.PushString("updateWindow"); + lua.PushCSharpFunction(UpdateWindow); + lua.SetTable(-3); + + lua.SetGlobal("gui"); + } + + private static int CreateWindow(ILuaState L) + { + if (wm == null || process == null) + { + L.PushString("GUI library not initialized"); + L.Error(); + return 1; + } + + string title = L.ToString(1); + int width = (int)L.ToNumber(2); + int height = (int)L.ToNumber(3); + + int x = (int)((wm.ScreenWidth - width) / 2); + int y = (int)((wm.ScreenHeight - height) / 2); + + AppWindow window = new AppWindow(process, x, y, width, height); + window.Title = title; + wm.AddWindow(window); + + L.PushLightUserData(window); + return 1; + } + + private static int ShowMessageBox(ILuaState L) + { + if (wm == null || process == null) + { + L.PushString("GUI library not initialized"); + L.Error(); + return 1; + } + + string title = L.ToString(1); + string message = L.ToString(2); + + MessageBox messageBox = new MessageBox(process, title, message); + messageBox.Show(); + + return 0; + } + + private static int CloseWindow(ILuaState L) + { + if (wm == null || process == null) + { + L.PushString("GUI library not initialized"); + L.Error(); + return 1; + } + + AppWindow window = L.ToUserData(1) as AppWindow; + if (window != null) + { + wm.RemoveWindow(window); + } + + return 0; + } + + private static int SetWindowTitle(ILuaState L) + { + if (wm == null || process == null) + { + L.PushString("GUI library not initialized"); + L.Error(); + return 1; + } + + AppWindow window = L.ToUserData(1) as AppWindow; + string title = L.ToString(2); + + if (window != null) + { + window.Title = title; + wm.Update(window); + } + + return 0; + } + + private static int SetWindowSize(ILuaState L) + { + if (wm == null || process == null) + { + L.PushString("GUI library not initialized"); + L.Error(); + return 1; + } + + AppWindow window = L.ToUserData(1) as AppWindow; + int width = (int)L.ToNumber(2); + int height = (int)L.ToNumber(3); + + if (window != null) + { + window.Resize(width, height); + } + + return 0; + } + + private static int SetWindowPosition(ILuaState L) + { + if (wm == null || process == null) + { + L.PushString("GUI library not initialized"); + L.Error(); + return 1; + } + + AppWindow window = L.ToUserData(1) as AppWindow; + int x = (int)L.ToNumber(2); + int y = (int)L.ToNumber(3); + + if (window != null) + { + window.Move(x, y); + } + + return 0; + } + + private static int ClearWindow(ILuaState L) + { + if (wm == null || process == null) + { + L.PushString("GUI library not initialized"); + L.Error(); + return 1; + } + + AppWindow window = L.ToUserData(1) as AppWindow; + Color color = ParseColor(L, 2); + + if (window != null) + { + window.Clear(color); + } + + return 0; + } + + private static int DrawText(ILuaState L) + { + if (wm == null || process == null) + { + L.PushString("GUI library not initialized"); + L.Error(); + return 1; + } + + AppWindow window = L.ToUserData(1) as AppWindow; + string text = L.ToString(2); + Color color = ParseColor(L, 3); + int x = (int)L.ToNumber(4); + int y = (int)L.ToNumber(5); + + if (window != null) + { + window.DrawString(text, color, x, y); + } + + return 0; + } + + private static int DrawRectangle(ILuaState L) + { + if (wm == null || process == null) + { + L.PushString("GUI library not initialized"); + L.Error(); + return 1; + } + + AppWindow window = L.ToUserData(1) as AppWindow; + int x = (int)L.ToNumber(2); + int y = (int)L.ToNumber(3); + int width = (int)L.ToNumber(4); + int height = (int)L.ToNumber(5); + Color color = ParseColor(L, 6); + + if (window != null) + { + window.DrawRectangle(x, y, width, height, color); + } + + return 0; + } + + private static int DrawFilledRectangle(ILuaState L) + { + if (wm == null || process == null) + { + L.PushString("GUI library not initialized"); + L.Error(); + return 1; + } + + AppWindow window = L.ToUserData(1) as AppWindow; + int x = (int)L.ToNumber(2); + int y = (int)L.ToNumber(3); + int width = (int)L.ToNumber(4); + int height = (int)L.ToNumber(5); + Color color = ParseColor(L, 6); + + if (window != null) + { + window.DrawFilledRectangle(x, y, width, height, color); + } + + return 0; + } + + private static int DrawCircle(ILuaState L) + { + if (wm == null || process == null) + { + L.PushString("GUI library not initialized"); + L.Error(); + return 1; + } + + AppWindow window = L.ToUserData(1) as AppWindow; + int x = (int)L.ToNumber(2); + int y = (int)L.ToNumber(3); + int radius = (int)L.ToNumber(4); + Color color = ParseColor(L, 5); + + if (window != null) + { + window.DrawCircle(x, y, radius, color); + } + + return 0; + } + + private static int DrawLine(ILuaState L) + { + if (wm == null || process == null) + { + L.PushString("GUI library not initialized"); + L.Error(); + return 1; + } + + AppWindow window = L.ToUserData(1) as AppWindow; + int x1 = (int)L.ToNumber(2); + int y1 = (int)L.ToNumber(3); + int x2 = (int)L.ToNumber(4); + int y2 = (int)L.ToNumber(5); + Color color = ParseColor(L, 6); + + if (window != null) + { + window.DrawLine(x1, y1, x2, y2, color); + } + + return 0; + } + + private static int DrawPoint(ILuaState L) + { + if (wm == null || process == null) + { + L.PushString("GUI library not initialized"); + L.Error(); + return 1; + } + + AppWindow window = L.ToUserData(1) as AppWindow; + int x = (int)L.ToNumber(2); + int y = (int)L.ToNumber(3); + Color color = ParseColor(L, 4); + + if (window != null) + { + window.DrawPoint(x, y, color); + } + + return 0; + } + + private static int UpdateWindow(ILuaState L) + { + if (wm == null || process == null) + { + L.PushString("GUI library not initialized"); + L.Error(); + return 1; + } + + AppWindow window = L.ToUserData(1) as AppWindow; + + if (window != null) + { + wm.Update(window); + } + + return 0; + } + + private static Color ParseColor(ILuaState L, int index) + { + if (L.IsTable(index)) + { + L.GetField(index, "r"); + int r = (int)L.ToNumber(-1); + L.Pop(1); + + L.GetField(index, "g"); + int g = (int)L.ToNumber(-1); + L.Pop(1); + + L.GetField(index, "b"); + int b = (int)L.ToNumber(-1); + L.Pop(1); + + return Color.FromArgb(r, g, b); + } + else if (L.IsString(index)) + { + string colorName = L.ToString(index).ToLower(); + return colorName switch + { + "red" => Color.Red, + "green" => Color.Green, + "blue" => Color.Blue, + "yellow" => Color.Yellow, + "orange" => Color.Orange, + "purple" => Color.Purple, + "pink" => Color.Pink, + "black" => Color.Black, + "white" => Color.White, + "gray" => Color.Gray, + "lightgray" => Color.LightGray, + "darkgray" => Color.DarkGray, + "cyan" => Color.Cyan, + "magenta" => Color.Magenta, + "lime" => Color.Lime, + "brown" => Color.Brown, + _ => Color.White + }; + } + else + { + return Color.White; + } + } + } +} diff --git a/Gui/UILib/TextBox.cs b/Gui/UILib/TextBox.cs index b6b3481..6c93d01 100644 --- a/Gui/UILib/TextBox.cs +++ b/Gui/UILib/TextBox.cs @@ -345,11 +345,18 @@ namespace CMLeonOS.Gui.UILib return; } - if (markedLinesBegin == -1 || markedLinesEnd == -1) return; - AutoScroll(); - for (int i = markedLinesBegin; i <= markedLinesEnd; i++) + int startLine = markedLinesBegin; + int endLine = markedLinesEnd; + + if (startLine == -1 || endLine == -1) + { + startLine = (scrollY / fontHeight); + endLine = Math.Min(lines.Count - 1, ((scrollY + Height) / fontHeight)); + } + + for (int i = startLine; i <= endLine; i++) { int lineY = (i * fontHeight) - scrollY; if (lineY < 0) continue; diff --git a/LuaApps/Hello.lua b/LuaApps/Hello.lua new file mode 100644 index 0000000..3155242 --- /dev/null +++ b/LuaApps/Hello.lua @@ -0,0 +1,7 @@ +local window = gui.createWindow("Hello", 400, 300) + +gui.clearWindow(window, "white") + +gui.drawText(window, "Hello world!", "black", 10, 10) + +gui.updateWindow(window) diff --git a/docs/cmleonos/docs/.vuepress/config.js b/docs/cmleonos/docs/.vuepress/config.js index 8dc56a8..52800ad 100644 --- a/docs/cmleonos/docs/.vuepress/config.js +++ b/docs/cmleonos/docs/.vuepress/config.js @@ -6,7 +6,7 @@ export default defineUserConfig({ lang: 'zh-CN', title: 'CMLeonOS官方文档站', - description: 'CMLeonOS是一个基于微内核架构的操作系统,它的目标是提供一个简单、可靠、安全的操作系统环境。', + description: 'CMLeonOS是一个x86架构64位操作系统,它的目标是提供一个简单、可靠、安全的操作系统环境。', theme: defaultTheme({ // logo: 'https://vuejs.press/images/hero.png', diff --git a/docs/cmleonos/docs/lua.md b/docs/cmleonos/docs/lua.md index dcae27a..3c4968e 100644 --- a/docs/cmleonos/docs/lua.md +++ b/docs/cmleonos/docs/lua.md @@ -1230,6 +1230,140 @@ local jsonStr = json.stringify(data) print(jsonStr) ``` +--- +## GUI 库 (gui) + +### gui.createWindow(title, x, y, width, height) +创建一个窗口。 + +```lua +local window = gui.createWindow("My Window", 100, 100, 400, 300) +``` + +**参数**: +- `title` - 窗口标题 +- `x` - 窗口左上角 X 坐标 +- `y` - 窗口左上角 Y 坐标 +- `width` - 窗口宽度 +- `height` - 窗口高度 + +### gui.createButton(parent, text, x, y, width, height, callback) +创建一个按钮。 + +```lua +local button = gui.createButton(window, "Click Me", 10, 10, 100, 30, function() + print("Button clicked!") +end) +``` + +**参数**: +- `parent` - 父窗口 +- `text` - 按钮文本 +- `x` - 按钮左上角 X 坐标 +- `y` - 按钮左上角 Y 坐标 +- `width` - 按钮宽度 +- `height` - 按钮高度 +- `callback` - 点击回调函数 + +### gui.createLabel(parent, text, x, y) +创建一个标签。 + +```lua +local label = gui.createLabel(window, "Hello, World!", 10, 50) +``` + +**参数**: +- `parent` - 父窗口 +- `text` - 标签文本 +- `x` - 标签左上角 X 坐标 +- `y` - 标签左上角 Y 坐标 + +### gui.createTextBox(parent, x, y, width, height) +创建一个文本框。 + +```lua +local textbox = gui.createTextBox(window, 10, 80, 200, 25) +``` + +**参数**: +- `parent` - 父窗口 +- `x` - 文本框左上角 X 坐标 +- `y` - 文本框左上角 Y 坐标 +- `width` - 文本框宽度 +- `height` - 文本框高度 + +### gui.getText(textbox) +获取文本框的内容。 + +```lua +local text = gui.getText(textbox) +print(text) +``` + +### gui.setText(textbox, text) +设置文本框的内容。 + +```lua +gui.setText(textbox, "New text") +``` + +### gui.show(window) +显示窗口。 + +```lua +gui.show(window) +``` + +### gui.hide(window) +隐藏窗口。 + +```lua +gui.hide(window) +``` + +### gui.close(window) +关闭窗口。 + +```lua +gui.close(window) +``` + +### gui.setMessageLoop(callback) +设置消息循环回调函数。 + +```lua +gui.setMessageLoop(function() + -- 处理消息循环 +end) +``` + +### gui.alert(message) +显示警告对话框。 + +```lua +gui.alert("Operation completed!") +``` + +### gui.confirm(message) +显示确认对话框,返回 true 或 false。 + +```lua +local result = gui.confirm("Are you sure?") +if result then + print("User confirmed") +else + print("User cancelled") +end +``` + +### gui.prompt(message, default) +显示输入对话框,返回用户输入的字符串。 + +```lua +local input = gui.prompt("Enter your name:", "John") +print("Hello, " .. input) +``` + --- ## 包库 (package)