diff --git a/AK/WeakPtr.h b/AK/WeakPtr.h index d03af159db..a89c2bc8bf 100644 --- a/AK/WeakPtr.h +++ b/AK/WeakPtr.h @@ -11,6 +11,12 @@ public: WeakPtr() { } WeakPtr(std::nullptr_t) { } + template + WeakPtr(WeakPtr&& other) + : m_link(reinterpret_cast*>(other.leakLink())) + { + } + template WeakPtr& operator=(WeakPtr&& other) { diff --git a/Kernel/GUITypes.h b/Kernel/GUITypes.h index f5dfc22961..5a0099c91d 100644 --- a/Kernel/GUITypes.h +++ b/Kernel/GUITypes.h @@ -21,3 +21,17 @@ struct GUI_CreateWindowParameters { unsigned flags; char title[128]; }; + +enum class GUI_WidgetType : unsigned { + Label, + Button, +}; + +struct GUI_CreateWidgetParameters { + GUI_WidgetType type; + GUI_Rect rect; + GUI_Color background_color; + bool opaque; + unsigned flags; + char text[256]; +}; diff --git a/Kernel/Process.h b/Kernel/Process.h index 219eed2845..faa51bea7c 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -11,6 +11,7 @@ #include #include #include +#include class FileDescriptor; class PageDirectory; @@ -18,6 +19,7 @@ class Region; class VMObject; class Zone; class Window; +class Widget; #define COOL_GLOBALS #ifdef COOL_GLOBALS @@ -189,6 +191,8 @@ public: int gui$create_window(const GUI_CreateWindowParameters*); int gui$destroy_window(int window_id); + int gui$create_widget(int window_id, const GUI_CreateWidgetParameters*); + int gui$destroy_widget(int widget_id); DisplayInfo get_display_info(); @@ -338,7 +342,8 @@ private: RetainPtr m_display_framebuffer_region; - Vector m_windows; + Vector> m_windows; + Vector> m_widgets; }; extern Process* current; diff --git a/Kernel/ProcessGUI.cpp b/Kernel/ProcessGUI.cpp index 7b19a550e1..69ca6e6fff 100644 --- a/Kernel/ProcessGUI.cpp +++ b/Kernel/ProcessGUI.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include #include @@ -34,7 +36,7 @@ int Process::gui$create_window(const GUI_CreateWindowParameters* user_params) if (!validate_read_typed(user_params)) return -EFAULT; - GUI_CreateWindowParameters params = *user_params; + auto params = *user_params; Rect rect { params.rect.x, params.rect.y, params.rect.width, params.rect.height }; if (rect.is_empty()) @@ -47,7 +49,7 @@ int Process::gui$create_window(const GUI_CreateWindowParameters* user_params) return -ENOMEM; int window_id = m_windows.size(); - m_windows.append(window); + m_windows.append(window->makeWeakPtr()); window->setTitle(params.title); window->setRect(rect); @@ -64,14 +66,71 @@ int Process::gui$create_window(const GUI_CreateWindowParameters* user_params) int Process::gui$destroy_window(int window_id) { - wait_for_gui_server(); dbgprintf("%s<%u> gui$destroy_window (window_id=%d)\n", name().characters(), pid(), window_id); if (window_id < 0) return -EINVAL; if (window_id >= static_cast(m_windows.size())) - return -EBADWIN; - auto* window = m_windows[window_id]; - m_windows.remove(window_id); + return -EBADWINDOW; + auto* window = m_windows[window_id].ptr(); + if (!window) + return -EBADWINDOW; window->deleteLater(); return 0; } + +int Process::gui$create_widget(int window_id, const GUI_CreateWidgetParameters* user_params) +{ + if (!validate_read_typed(user_params)) + return -EFAULT; + + if (window_id < 0) + return -EINVAL; + if (window_id >= static_cast(m_windows.size())) + return -EINVAL; + if (!m_windows[window_id]) + return -EINVAL; + auto& window = *m_windows[window_id]; + + auto params = *user_params; + Rect rect { params.rect.x, params.rect.y, params.rect.width, params.rect.height }; + + if (rect.is_empty()) + return -EINVAL; + + Widget* widget = nullptr; + switch (params.type) { + case GUI_WidgetType::Label: + widget = new Label(window.mainWidget()); + static_cast(widget)->setText(params.text); + break; + case GUI_WidgetType::Button: + widget = new Button(window.mainWidget()); + static_cast(widget)->setCaption(params.text); + break; + } + + int widget_id = m_widgets.size(); + m_widgets.append(widget->makeWeakPtr()); + + widget->setWindowRelativeRect(rect); + widget->setBackgroundColor(params.background_color); + widget->setFillWithBackgroundColor(params.opaque); + dbgprintf("%s<%u> gui$create_widget: %d with rect {%d,%d %dx%d}\n", name().characters(), pid(), widget_id, rect.x(), rect.y(), rect.width(), rect.height()); + + return window_id; +} + +int Process::gui$destroy_widget(int widget_id) +{ + dbgprintf("%s<%u> gui$destroy_widget (widget_id=%d)\n", name().characters(), pid(), widget_id); + if (widget_id < 0) + return -EINVAL; + if (widget_id >= static_cast(m_widgets.size())) + return -EBADWINDOW; + auto* widget = m_widgets[widget_id].ptr(); + if (!widget) + return -EBADWIDGET; + widget->deleteLater(); + return 0; +} + diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index a8b53db20d..467eb551fe 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -191,6 +191,10 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2, return current->gui$create_window((const GUI_CreateWindowParameters*)arg1); case Syscall::SC_gui_destroy_window: return current->gui$destroy_window((int)arg1); + case Syscall::SC_gui_create_widget: + return current->gui$create_widget((int)arg1, (const GUI_CreateWidgetParameters*)arg2); + case Syscall::SC_gui_destroy_widget: + return current->gui$destroy_widget((int)arg1); default: kprintf("<%u> int0x80: Unknown function %u requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3); break; diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index c6eab70007..66a6369d1f 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -68,6 +68,8 @@ __ENUMERATE_SYSCALL(sync) \ __ENUMERATE_SYSCALL(gui_create_window) \ __ENUMERATE_SYSCALL(gui_destroy_window) \ + __ENUMERATE_SYSCALL(gui_create_widget) \ + __ENUMERATE_SYSCALL(gui_destroy_widget) \ namespace Syscall { diff --git a/LibC/errno_numbers.h b/LibC/errno_numbers.h index 728500530d..6d2aae4b90 100644 --- a/LibC/errno_numbers.h +++ b/LibC/errno_numbers.h @@ -42,7 +42,8 @@ __ERROR(ENOTIMPL, "Not implemented") \ __ERROR(EAFNOSUPPORT, "Address family not supported") \ __ERROR(EWHYTHO, "Failed without setting an error code (Bug!)") \ - __ERROR(EBADWIN, "Bad WindowID") \ + __ERROR(EBADWINDOW, "Bad Window ID") \ + __ERROR(EBADWIDGET, "Bad Widget ID") \ enum __errno_values { #undef __ERROR