Browse Source

Close the MsgBox when clicking the OK button.

This feels vaguely crashy. I haven't tested window/widget destruction
before so there's sure to be bugs.
Andreas Kling 6 years ago
parent
commit
959a1b0750
9 changed files with 65 additions and 9 deletions
  1. 10 0
      Widgets/Event.h
  2. 8 0
      Widgets/Object.cpp
  3. 5 3
      Widgets/Object.h
  4. 2 0
      Widgets/Widget.cpp
  5. 11 0
      Widgets/Window.cpp
  6. 4 0
      Widgets/Window.h
  7. 20 6
      Widgets/WindowManager.cpp
  8. 4 0
      Widgets/WindowManager.h
  9. 1 0
      Widgets/test.cpp

+ 10 - 0
Widgets/Event.h

@@ -17,6 +17,7 @@ static const char* eventNames[] = {
     "KeyDown",
     "KeyDown",
     "KeyUp",
     "KeyUp",
     "Timer",
     "Timer",
+    "DeferredDestroy",
 };
 };
 
 
 class Event {
 class Event {
@@ -33,6 +34,7 @@ public:
         KeyDown,
         KeyDown,
         KeyUp,
         KeyUp,
         Timer,
         Timer,
+        DeferredDestroy,
     };
     };
 
 
     Event() { }
     Event() { }
@@ -53,6 +55,14 @@ private:
     Type m_type { Invalid };
     Type m_type { Invalid };
 };
 };
 
 
+class DeferredDestroyEvent final : public Event {
+public:
+    DeferredDestroyEvent()
+        : Event(Event::DeferredDestroy)
+    {
+    }
+};
+
 class QuitEvent final : public Event {
 class QuitEvent final : public Event {
 public:
 public:
     QuitEvent()
     QuitEvent()

+ 8 - 0
Widgets/Object.cpp

@@ -28,6 +28,9 @@ void Object::event(Event& event)
     switch (event.type()) {
     switch (event.type()) {
     case Event::Timer:
     case Event::Timer:
         return timerEvent(static_cast<TimerEvent&>(event));
         return timerEvent(static_cast<TimerEvent&>(event));
+    case Event::DeferredDestroy:
+        delete this;
+        break;
     case Event::Invalid:
     case Event::Invalid:
         ASSERT_NOT_REACHED();
         ASSERT_NOT_REACHED();
         break;
         break;
@@ -82,3 +85,8 @@ void Object::stopTimer()
     m_timerID = 0;
     m_timerID = 0;
 }
 }
 
 
+void Object::deleteLater()
+{
+    EventLoop::main().postEvent(this, make<DeferredDestroyEvent>());
+}
+

+ 5 - 3
Widgets/Object.h

@@ -24,12 +24,14 @@ public:
     void stopTimer();
     void stopTimer();
     bool hasTimer() const { return m_timerID; }
     bool hasTimer() const { return m_timerID; }
 
 
-private:
-    virtual void timerEvent(TimerEvent&);
-
     void addChild(Object&);
     void addChild(Object&);
     void removeChild(Object&);
     void removeChild(Object&);
 
 
+    void deleteLater();
+
+private:
+    virtual void timerEvent(TimerEvent&);
+
     Object* m_parent { nullptr };
     Object* m_parent { nullptr };
 
 
     int m_timerID { 0 };
     int m_timerID { 0 };

+ 2 - 0
Widgets/Widget.cpp

@@ -36,6 +36,8 @@ void Widget::event(Event& event)
         if (auto* win = window()) {
         if (auto* win = window()) {
             if (win->isBeingDragged())
             if (win->isBeingDragged())
                 return;
                 return;
+            if (!win->isVisible())
+                return;
         }
         }
         m_hasPendingPaintEvent = false;
         m_hasPendingPaintEvent = false;
         return paintEvent(static_cast<PaintEvent&>(event));
         return paintEvent(static_cast<PaintEvent&>(event));

+ 11 - 0
Widgets/Window.cpp

@@ -11,6 +11,10 @@ Window::Window(Object* parent)
 
 
 Window::~Window()
 Window::~Window()
 {
 {
+    delete m_mainWidget;
+    m_mainWidget = nullptr;
+    if (parent())
+        parent()->removeChild(*this);
     WindowManager::the().removeWindow(*this);
     WindowManager::the().removeWindow(*this);
 }
 }
 
 
@@ -96,6 +100,11 @@ bool Window::isActive() const
     return WindowManager::the().activeWindow() == this;
     return WindowManager::the().activeWindow() == this;
 }
 }
 
 
+bool Window::isVisible() const
+{
+    return WindowManager::the().isVisible(const_cast<Window&>(*this));
+}
+
 void Window::setFocusedWidget(Widget* widget)
 void Window::setFocusedWidget(Widget* widget)
 {
 {
     if (m_focusedWidget.ptr() == widget)
     if (m_focusedWidget.ptr() == widget)
@@ -113,5 +122,7 @@ void Window::setFocusedWidget(Widget* widget)
 
 
 void Window::close()
 void Window::close()
 {
 {
+    WindowManager::the().removeWindow(*this);
+    deleteLater();
 }
 }
 
 

+ 4 - 0
Widgets/Window.h

@@ -22,9 +22,11 @@ public:
 
 
     const Rect& rect() const { return m_rect; }
     const Rect& rect() const { return m_rect; }
     void setRect(const Rect&);
     void setRect(const Rect&);
+    void setRectWithoutRepaint(const Rect& rect) { m_rect = rect; }
 
 
     Point position() const { return m_rect.location(); }
     Point position() const { return m_rect.location(); }
     void setPosition(const Point& position) { setRect({ position.x(), position.y(), width(), height() }); }
     void setPosition(const Point& position) { setRect({ position.x(), position.y(), width(), height() }); }
+    void setPositionWithoutRepaint(const Point& position) { setRectWithoutRepaint({ position.x(), position.y(), width(), height() }); }
 
 
     Widget* mainWidget() { return m_mainWidget; }
     Widget* mainWidget() { return m_mainWidget; }
     const Widget* mainWidget() const { return m_mainWidget; }
     const Widget* mainWidget() const { return m_mainWidget; }
@@ -44,6 +46,8 @@ public:
     const Widget* focusedWidget() const { return m_focusedWidget.ptr(); }
     const Widget* focusedWidget() const { return m_focusedWidget.ptr(); }
     void setFocusedWidget(Widget*);
     void setFocusedWidget(Widget*);
 
 
+    bool isVisible() const;
+
     void close();
     void close();
 
 
 private:
 private:

+ 20 - 6
Widgets/WindowManager.cpp

@@ -126,22 +126,32 @@ void WindowManager::addWindow(Window& window)
         setActiveWindow(&window);
         setActiveWindow(&window);
 }
 }
 
 
+void WindowManager::repaint()
+{
+    handlePaintEvent(*make<PaintEvent>());
+}
+
 void WindowManager::removeWindow(Window& window)
 void WindowManager::removeWindow(Window& window)
 {
 {
-    ASSERT(m_windows.contains(&window));
+    if (!m_windows.contains(&window))
+        return;
+
     m_windows.remove(&window);
     m_windows.remove(&window);
     if (!activeWindow() && !m_windows.isEmpty())
     if (!activeWindow() && !m_windows.isEmpty())
         setActiveWindow(*m_windows.begin());
         setActiveWindow(*m_windows.begin());
+
+    repaint();
 }
 }
 
 
 void WindowManager::notifyTitleChanged(Window& window)
 void WindowManager::notifyTitleChanged(Window& window)
 {
 {
-    //printf("[WM] Window{%p} title set to '%s'\n", &window, window.title().characters());
+    printf("[WM] Window{%p} title set to '%s'\n", &window, window.title().characters());
 }
 }
 
 
 void WindowManager::notifyRectChanged(Window& window, const Rect& oldRect, const Rect& newRect)
 void WindowManager::notifyRectChanged(Window& window, const Rect& oldRect, const Rect& newRect)
 {
 {
-    //printf("[WM] Window %p rect changed (%d,%d %dx%d) -> (%d,%d %dx%d)\n", &window, oldRect.x(), oldRect.y(), oldRect.width(), oldRect.height(), newRect.x(), newRect.y(), newRect.width(), newRect.height());
+    printf("[WM] Window %p rect changed (%d,%d %dx%d) -> (%d,%d %dx%d)\n", &window, oldRect.x(), oldRect.y(), oldRect.width(), oldRect.height(), newRect.x(), newRect.y(), newRect.width(), newRect.height());
+    repaintAfterMove(oldRect, newRect);
 }
 }
 
 
 void WindowManager::handleTitleBarMouseEvent(Window& window, MouseEvent& event)
 void WindowManager::handleTitleBarMouseEvent(Window& window, MouseEvent& event)
@@ -205,7 +215,7 @@ void WindowManager::processMouseEvent(MouseEvent& event)
             Point pos = m_dragWindowOrigin;
             Point pos = m_dragWindowOrigin;
             printf("[WM] Dragging [origin: %d,%d] now: %d,%d\n", m_dragOrigin.x(), m_dragOrigin.y(), event.x(), event.y());
             printf("[WM] Dragging [origin: %d,%d] now: %d,%d\n", m_dragOrigin.x(), m_dragOrigin.y(), event.x(), event.y());
             pos.moveBy(event.x() - m_dragOrigin.x(), event.y() - m_dragOrigin.y());
             pos.moveBy(event.x() - m_dragOrigin.x(), event.y() - m_dragOrigin.y());
-            m_dragWindow->setPosition(pos);
+            m_dragWindow->setPositionWithoutRepaint(pos);
             paintWindowFrame(*m_dragWindow);
             paintWindowFrame(*m_dragWindow);
             return;
             return;
         }
         }
@@ -243,9 +253,8 @@ void WindowManager::handlePaintEvent(PaintEvent& event)
     m_rootWidget->event(event);
     m_rootWidget->event(event);
     paintWindowFrames();
     paintWindowFrames();
 
 
-    for (auto* window : m_windows) {
+    for (auto* window : m_windows)
         window->event(event);
         window->event(event);
-    }
 }
 }
 
 
 void WindowManager::event(Event& event)
 void WindowManager::event(Event& event)
@@ -296,3 +305,8 @@ void WindowManager::setActiveWindow(Window* window)
     }
     }
 }
 }
 
 
+bool WindowManager::isVisible(Window& window) const
+{
+    return m_windows.contains(&window);
+}
+

+ 4 - 0
Widgets/WindowManager.h

@@ -27,6 +27,10 @@ public:
     Window* activeWindow() { return m_activeWindow.ptr(); }
     Window* activeWindow() { return m_activeWindow.ptr(); }
     void setActiveWindow(Window*);
     void setActiveWindow(Window*);
 
 
+    bool isVisible(Window&) const;
+
+    void repaint();
+
 private:
 private:
     WindowManager();
     WindowManager();
     ~WindowManager();
     ~WindowManager();

+ 1 - 0
Widgets/test.cpp

@@ -86,6 +86,7 @@ int main(int argc, char** argv)
 
 
         tb->onReturnPressed = [] (TextBox& textBox) {
         tb->onReturnPressed = [] (TextBox& textBox) {
             printf("TextBox %p return pressed: '%s'\n", &textBox, textBox.text().characters());
             printf("TextBox %p return pressed: '%s'\n", &textBox, textBox.text().characters());
+            MsgBox(nullptr, textBox.text());
         };
         };
 
 
         WindowManager::the().setActiveWindow(widgetTestWindow);
         WindowManager::the().setActiveWindow(widgetTestWindow);