Jelajahi Sumber

LibGUI: Implement destroying individual windows without exiting the process.

Andreas Kling 6 tahun lalu
induk
melakukan
37ab7b7a8c
8 mengubah file dengan 85 tambahan dan 30 penghapusan
  1. 2 0
      Kernel/ProcessGUI.cpp
  2. 6 0
      LibC/gui.cpp
  3. 1 0
      LibC/gui.h
  4. 1 1
      LibGUI/GObject.cpp
  5. 1 1
      LibGUI/GObject.h
  6. 60 23
      LibGUI/GWindow.cpp
  7. 5 3
      LibGUI/GWindow.h
  8. 9 2
      Userland/guitest2.cpp

+ 2 - 0
Kernel/ProcessGUI.cpp

@@ -80,6 +80,8 @@ int Process::gui$destroy_window(int window_id)
     auto it = m_windows.find(window_id);
     auto it = m_windows.find(window_id);
     if (it == m_windows.end())
     if (it == m_windows.end())
         return -EBADWINDOW;
         return -EBADWINDOW;
+    auto message = make<WSMessage>(WSMessage::WM_DestroyWindow);
+    WSMessageLoop::the().post_message((*it).value.leakPtr(), move(message), true);
     m_windows.remove(window_id);
     m_windows.remove(window_id);
     return 0;
     return 0;
 }
 }

+ 6 - 0
LibC/gui.cpp

@@ -9,6 +9,12 @@ int gui_create_window(const GUI_WindowParameters* params)
     __RETURN_WITH_ERRNO(rc, rc, -1);
     __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 gui_invalidate_window(int window_id, const GUI_Rect* rect)
 {
 {
     int rc = syscall(SC_gui_invalidate_window, window_id, rect);
     int rc = syscall(SC_gui_invalidate_window, window_id, rect);

+ 1 - 0
LibC/gui.h

@@ -6,6 +6,7 @@
 __BEGIN_DECLS
 __BEGIN_DECLS
 
 
 int gui_create_window(const GUI_WindowParameters*);
 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_invalidate_window(int window_id, const GUI_Rect*);
 int gui_notify_paint_finished(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*);
 int gui_get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo*);

+ 1 - 1
LibGUI/GObject.cpp

@@ -69,7 +69,7 @@ void GObject::stopTimer()
     m_timerID = 0;
     m_timerID = 0;
 }
 }
 
 
-void GObject::deleteLater()
+void GObject::delete_later()
 {
 {
     GEventLoop::main().post_event(this, make<GEvent>(GEvent::DeferredDestroy));
     GEventLoop::main().post_event(this, make<GEvent>(GEvent::DeferredDestroy));
 }
 }

+ 1 - 1
LibGUI/GObject.h

@@ -27,7 +27,7 @@ public:
     void addChild(GObject&);
     void addChild(GObject&);
     void removeChild(GObject&);
     void removeChild(GObject&);
 
 
-    void deleteLater();
+    void delete_later();
 
 
 private:
 private:
     virtual void timerEvent(GTimerEvent&);
     virtual void timerEvent(GTimerEvent&);

+ 60 - 23
LibGUI/GWindow.cpp

@@ -29,10 +29,29 @@ GWindow* GWindow::from_window_id(int window_id)
 GWindow::GWindow(GObject* parent)
 GWindow::GWindow(GObject* parent)
     : 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;
     GUI_WindowParameters wparams;
-    wparams.rect = { { 100, 400 }, { 140, 140 } };
+    wparams.rect = m_rect_when_windowless;
     wparams.background_color = 0xffc0c0;
     wparams.background_color = 0xffc0c0;
-    strcpy(wparams.title, "GWindow");
+    strcpy(wparams.title, m_title_when_windowless.characters());
     m_window_id = gui_create_window(&wparams);
     m_window_id = gui_create_window(&wparams);
     if (m_window_id < 0) {
     if (m_window_id < 0) {
         perror("gui_create_window");
         perror("gui_create_window");
@@ -40,33 +59,54 @@ GWindow::GWindow(GObject* parent)
     }
     }
 
 
     windows().set(m_window_id, this);
     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)
 void GWindow::set_title(String&& title)
 {
 {
     dbgprintf("GWindow::set_title \"%s\"\n", title.characters());
     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
 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)
 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());
     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)
 void GWindow::event(GEvent& event)
@@ -99,9 +139,11 @@ void GWindow::event(GEvent& event)
         if (rect.is_empty())
         if (rect.is_empty())
             rect = m_main_widget->rect();
             rect = m_main_widget->rect();
         m_main_widget->event(*make<GPaintEvent>(rect));
         m_main_widget->event(*make<GPaintEvent>(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;
         return;
     }
     }
 
 
@@ -126,16 +168,10 @@ bool GWindow::is_visible() const
     return false;
     return false;
 }
 }
 
 
-void GWindow::close()
-{
-}
-
-void GWindow::show()
-{
-}
-
 void GWindow::update(const Rect& a_rect)
 void GWindow::update(const Rect& a_rect)
 {
 {
+    if (!m_window_id)
+        return;
     GUI_Rect rect = a_rect;
     GUI_Rect rect = a_rect;
     int rc = gui_invalidate_window(m_window_id, a_rect.is_null() ? nullptr : &rect);
     int rc = gui_invalidate_window(m_window_id, a_rect.is_null() ? nullptr : &rect);
     ASSERT(rc == 0);
     ASSERT(rc == 0);
@@ -168,6 +204,7 @@ void GWindow::set_focused_widget(GWidget* widget)
 
 
 void GWindow::set_global_cursor_tracking_widget(GWidget* widget)
 void GWindow::set_global_cursor_tracking_widget(GWidget* widget)
 {
 {
+    ASSERT(m_window_id);
     if (widget == m_global_cursor_tracking_widget.ptr())
     if (widget == m_global_cursor_tracking_widget.ptr())
         return;
         return;
     m_global_cursor_tracking_widget = widget ? widget->makeWeakPtr() : nullptr;
     m_global_cursor_tracking_widget = widget ? widget->makeWeakPtr() : nullptr;

+ 5 - 3
LibGUI/GWindow.h

@@ -35,6 +35,8 @@ public:
     bool is_visible() const;
     bool is_visible() const;
     bool is_active() const { return m_is_active; }
     bool is_active() const { return m_is_active; }
 
 
+    void show();
+    void hide();
     void close();
     void close();
 
 
     GWidget* main_widget() { return m_main_widget; }
     GWidget* main_widget() { return m_main_widget; }
@@ -45,8 +47,6 @@ public:
     const GWidget* focused_widget() const { return m_focused_widget; }
     const GWidget* focused_widget() const { return m_focused_widget; }
     void set_focused_widget(GWidget*);
     void set_focused_widget(GWidget*);
 
 
-    void show();
-
     void update(const Rect& = Rect());
     void update(const Rect& = Rect());
 
 
     void set_global_cursor_tracking_widget(GWidget*);
     void set_global_cursor_tracking_widget(GWidget*);
@@ -55,10 +55,12 @@ public:
 
 
 private:
 private:
     RetainPtr<GraphicsBitmap> m_backing;
     RetainPtr<GraphicsBitmap> m_backing;
-    int m_window_id { -1 };
+    int m_window_id { 0 };
     bool m_is_active { false };
     bool m_is_active { false };
     GWidget* m_main_widget { nullptr };
     GWidget* m_main_widget { nullptr };
     GWidget* m_focused_widget { nullptr };
     GWidget* m_focused_widget { nullptr };
     WeakPtr<GWidget> m_global_cursor_tracking_widget;
     WeakPtr<GWidget> m_global_cursor_tracking_widget;
+    Rect m_rect_when_windowless;
+    String m_title_when_windowless;
 };
 };
 
 

+ 9 - 2
Userland/guitest2.cpp

@@ -63,11 +63,11 @@ GWindow* make_launcher_window()
 {
 {
     auto* window = new GWindow;
     auto* window = new GWindow;
     window->set_title("Launcher");
     window->set_title("Launcher");
-    window->set_rect({ 100, 400, 100, 200 });
+    window->set_rect({ 100, 400, 100, 230 });
 
 
     auto* widget = new GWidget;
     auto* widget = new GWidget;
     window->set_main_widget(widget);
     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);
     auto* label = new GLabel(widget);
     label->set_relative_rect({ 0, 0, 100, 20 });
     label->set_relative_rect({ 0, 0, 100, 20 });
@@ -124,5 +124,12 @@ GWindow* make_launcher_window()
 
 
     window->set_focused_widget(textbox);
     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;
     return window;
 }
 }