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.
This commit is contained in:
Andreas Kling 2018-10-14 01:23:01 +02:00
parent 3ebea05996
commit 959a1b0750
Notes: sideshowbarker 2024-07-19 18:48:35 +09:00
9 changed files with 65 additions and 9 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -22,9 +22,11 @@ public:
const Rect& rect() const { return m_rect; }
void setRect(const Rect&);
void setRectWithoutRepaint(const Rect& rect) { m_rect = rect; }
Point position() const { return m_rect.location(); }
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; }
const Widget* mainWidget() const { return m_mainWidget; }
@ -44,6 +46,8 @@ public:
const Widget* focusedWidget() const { return m_focusedWidget.ptr(); }
void setFocusedWidget(Widget*);
bool isVisible() const;
void close();
private:

View file

@ -126,22 +126,32 @@ void WindowManager::addWindow(Window& window)
setActiveWindow(&window);
}
void WindowManager::repaint()
{
handlePaintEvent(*make<PaintEvent>());
}
void WindowManager::removeWindow(Window& window)
{
ASSERT(m_windows.contains(&window));
if (!m_windows.contains(&window))
return;
m_windows.remove(&window);
if (!activeWindow() && !m_windows.isEmpty())
setActiveWindow(*m_windows.begin());
repaint();
}
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)
{
//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)
@ -205,7 +215,7 @@ void WindowManager::processMouseEvent(MouseEvent& event)
Point pos = m_dragWindowOrigin;
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());
m_dragWindow->setPosition(pos);
m_dragWindow->setPositionWithoutRepaint(pos);
paintWindowFrame(*m_dragWindow);
return;
}
@ -243,9 +253,8 @@ void WindowManager::handlePaintEvent(PaintEvent& event)
m_rootWidget->event(event);
paintWindowFrames();
for (auto* window : m_windows) {
for (auto* window : m_windows)
window->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);
}

View file

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

View file

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