diff --git a/Kernel/ProcessGUI.cpp b/Kernel/ProcessGUI.cpp index db9fd52d56..5664bcd98f 100644 --- a/Kernel/ProcessGUI.cpp +++ b/Kernel/ProcessGUI.cpp @@ -80,6 +80,8 @@ int Process::gui$destroy_window(int window_id) auto it = m_windows.find(window_id); if (it == m_windows.end()) return -EBADWINDOW; + auto message = make(WSMessage::WM_DestroyWindow); + WSMessageLoop::the().post_message((*it).value.leakPtr(), move(message), true); m_windows.remove(window_id); return 0; } diff --git a/LibC/gui.cpp b/LibC/gui.cpp index 6b0516b252..da1fecef05 100644 --- a/LibC/gui.cpp +++ b/LibC/gui.cpp @@ -9,6 +9,12 @@ int gui_create_window(const GUI_WindowParameters* params) __RETURN_WITH_ERRNO(rc, rc, -1); } +int gui_destroy_window(int window_id) +{ + int rc = syscall(SC_gui_destroy_window, window_id); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + int gui_invalidate_window(int window_id, const GUI_Rect* rect) { int rc = syscall(SC_gui_invalidate_window, window_id, rect); diff --git a/LibC/gui.h b/LibC/gui.h index c486adcd99..4b7abbb88d 100644 --- a/LibC/gui.h +++ b/LibC/gui.h @@ -6,6 +6,7 @@ __BEGIN_DECLS int gui_create_window(const GUI_WindowParameters*); +int gui_destroy_window(int window_id); int gui_invalidate_window(int window_id, const GUI_Rect*); int gui_notify_paint_finished(int window_id, const GUI_Rect*); int gui_get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo*); diff --git a/LibGUI/GObject.cpp b/LibGUI/GObject.cpp index 13320cb265..881f220317 100644 --- a/LibGUI/GObject.cpp +++ b/LibGUI/GObject.cpp @@ -69,7 +69,7 @@ void GObject::stopTimer() m_timerID = 0; } -void GObject::deleteLater() +void GObject::delete_later() { GEventLoop::main().post_event(this, make(GEvent::DeferredDestroy)); } diff --git a/LibGUI/GObject.h b/LibGUI/GObject.h index 48870defcc..c4d2679101 100644 --- a/LibGUI/GObject.h +++ b/LibGUI/GObject.h @@ -27,7 +27,7 @@ public: void addChild(GObject&); void removeChild(GObject&); - void deleteLater(); + void delete_later(); private: virtual void timerEvent(GTimerEvent&); diff --git a/LibGUI/GWindow.cpp b/LibGUI/GWindow.cpp index 9aff94b40a..6b2e8abeb7 100644 --- a/LibGUI/GWindow.cpp +++ b/LibGUI/GWindow.cpp @@ -29,10 +29,29 @@ GWindow* GWindow::from_window_id(int window_id) GWindow::GWindow(GObject* parent) : GObject(parent) { + m_rect_when_windowless = { 100, 400, 140, 140 }; + m_title_when_windowless = "GWindow"; +} + +GWindow::~GWindow() +{ + hide(); +} + +void GWindow::close() +{ + delete_later(); +} + +void GWindow::show() +{ + if (m_window_id) + return; + GUI_WindowParameters wparams; - wparams.rect = { { 100, 400 }, { 140, 140 } }; + wparams.rect = m_rect_when_windowless; wparams.background_color = 0xffc0c0; - strcpy(wparams.title, "GWindow"); + strcpy(wparams.title, m_title_when_windowless.characters()); m_window_id = gui_create_window(&wparams); if (m_window_id < 0) { perror("gui_create_window"); @@ -40,33 +59,54 @@ GWindow::GWindow(GObject* parent) } windows().set(m_window_id, this); + update(); } -GWindow::~GWindow() +void GWindow::hide() { + if (!m_window_id) + return; + windows().remove(m_window_id); + int rc = gui_destroy_window(m_window_id); + if (rc < 0) { + perror("gui_destroy_window"); + exit(1); + } } void GWindow::set_title(String&& title) { dbgprintf("GWindow::set_title \"%s\"\n", title.characters()); - int rc = gui_set_window_title(m_window_id, title.characters(), title.length()); - ASSERT(rc == 0); + m_title_when_windowless = title; + if (m_window_id) { + int rc = gui_set_window_title(m_window_id, title.characters(), title.length()); + if (rc < 0) { + perror("gui_set_window_title"); + exit(1); + } + } } String GWindow::title() const { - char buffer[256]; - int rc = gui_get_window_title(m_window_id, buffer, sizeof(buffer)); - ASSERT(rc >= 0); - return String(buffer, rc); + if (m_window_id) { + char buffer[256]; + int rc = gui_get_window_title(m_window_id, buffer, sizeof(buffer)); + ASSERT(rc >= 0); + return String(buffer, rc); + } + return m_title_when_windowless; } void GWindow::set_rect(const Rect& a_rect) { dbgprintf("GWindow::set_rect! %d,%d %dx%d\n", a_rect.x(), a_rect.y(), a_rect.width(), a_rect.height()); - GUI_Rect rect = a_rect; - int rc = gui_set_window_rect(m_window_id, &rect); - ASSERT(rc == 0); + m_rect_when_windowless = a_rect; + if (m_window_id) { + GUI_Rect rect = a_rect; + int rc = gui_set_window_rect(m_window_id, &rect); + ASSERT(rc == 0); + } } void GWindow::event(GEvent& event) @@ -99,9 +139,11 @@ void GWindow::event(GEvent& event) if (rect.is_empty()) rect = m_main_widget->rect(); m_main_widget->event(*make(rect)); - GUI_Rect gui_rect = rect; - int rc = gui_notify_paint_finished(m_window_id, &gui_rect); - ASSERT(rc == 0); + if (m_window_id) { + GUI_Rect gui_rect = rect; + int rc = gui_notify_paint_finished(m_window_id, &gui_rect); + ASSERT(rc == 0); + } return; } @@ -126,16 +168,10 @@ bool GWindow::is_visible() const return false; } -void GWindow::close() -{ -} - -void GWindow::show() -{ -} - void GWindow::update(const Rect& a_rect) { + if (!m_window_id) + return; GUI_Rect rect = a_rect; int rc = gui_invalidate_window(m_window_id, a_rect.is_null() ? nullptr : &rect); ASSERT(rc == 0); @@ -168,6 +204,7 @@ void GWindow::set_focused_widget(GWidget* widget) void GWindow::set_global_cursor_tracking_widget(GWidget* widget) { + ASSERT(m_window_id); if (widget == m_global_cursor_tracking_widget.ptr()) return; m_global_cursor_tracking_widget = widget ? widget->makeWeakPtr() : nullptr; diff --git a/LibGUI/GWindow.h b/LibGUI/GWindow.h index 7a53e8a8db..dc2549ee9f 100644 --- a/LibGUI/GWindow.h +++ b/LibGUI/GWindow.h @@ -35,6 +35,8 @@ public: bool is_visible() const; bool is_active() const { return m_is_active; } + void show(); + void hide(); void close(); GWidget* main_widget() { return m_main_widget; } @@ -45,8 +47,6 @@ public: const GWidget* focused_widget() const { return m_focused_widget; } void set_focused_widget(GWidget*); - void show(); - void update(const Rect& = Rect()); void set_global_cursor_tracking_widget(GWidget*); @@ -55,10 +55,12 @@ public: private: RetainPtr m_backing; - int m_window_id { -1 }; + int m_window_id { 0 }; bool m_is_active { false }; GWidget* m_main_widget { nullptr }; GWidget* m_focused_widget { nullptr }; WeakPtr m_global_cursor_tracking_widget; + Rect m_rect_when_windowless; + String m_title_when_windowless; }; diff --git a/Userland/guitest2.cpp b/Userland/guitest2.cpp index 6d23d8bb97..a73d04545d 100644 --- a/Userland/guitest2.cpp +++ b/Userland/guitest2.cpp @@ -63,11 +63,11 @@ GWindow* make_launcher_window() { auto* window = new GWindow; window->set_title("Launcher"); - window->set_rect({ 100, 400, 100, 200 }); + window->set_rect({ 100, 400, 100, 230 }); auto* widget = new GWidget; window->set_main_widget(widget); - widget->set_relative_rect({ 0, 0, 100, 200 }); + widget->set_relative_rect({ 0, 0, 100, 230 }); auto* label = new GLabel(widget); label->set_relative_rect({ 0, 0, 100, 20 }); @@ -124,5 +124,12 @@ GWindow* make_launcher_window() window->set_focused_widget(textbox); + auto* close_button = new GButton(widget); + close_button->set_relative_rect({ 5, 200, 90, 20 }); + close_button->set_caption("Close"); + close_button->on_click = [window] (GButton&) { + window->close(); + }; + return window; }