From cfd76ade73ded8d0addb2bce1e17176be53484c7 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 9 Jan 2019 04:46:16 +0100 Subject: [PATCH] Stop recomposing the window hierarchy after every dang widget paint. --- Widgets/Painter.cpp | 2 -- Widgets/RootWidget.cpp | 3 ++- Widgets/Widget.cpp | 13 +++++++++---- Widgets/Widget.h | 3 ++- Widgets/Window.cpp | 16 ++++++++++++---- Widgets/Window.h | 3 ++- Widgets/WindowManager.cpp | 33 ++++++--------------------------- Widgets/WindowManager.h | 2 +- 8 files changed, 34 insertions(+), 41 deletions(-) diff --git a/Widgets/Painter.cpp b/Widgets/Painter.cpp index 2c2574bf38..350e39587e 100644 --- a/Widgets/Painter.cpp +++ b/Widgets/Painter.cpp @@ -21,8 +21,6 @@ Painter::Painter(Widget& widget) Painter::~Painter() { - if (m_window) - m_window->did_paint(); } void Painter::fillRect(const Rect& rect, Color color) diff --git a/Widgets/RootWidget.cpp b/Widgets/RootWidget.cpp index f485e27d06..00a5b604ab 100644 --- a/Widgets/RootWidget.cpp +++ b/Widgets/RootWidget.cpp @@ -8,7 +8,8 @@ RootWidget::RootWidget() { - m_backing = GraphicsBitmap::create_wrapper(FrameBufferSDL::the().size(), (byte*)FrameBufferSDL::the().scanline(0)); + setWindowRelativeRect(FrameBufferSDL::the().rect()); + m_backing = GraphicsBitmap::create_wrapper(size(), (byte*)FrameBufferSDL::the().scanline(0)); } RootWidget::~RootWidget() diff --git a/Widgets/Widget.cpp b/Widgets/Widget.cpp index f55bb0a5c2..0256179eff 100644 --- a/Widgets/Widget.cpp +++ b/Widgets/Widget.cpp @@ -19,16 +19,18 @@ Widget::~Widget() { } -void Widget::setWindowRelativeRect(const Rect& rect) +void Widget::setWindowRelativeRect(const Rect& rect, bool should_update) { // FIXME: Make some kind of event loop driven ResizeEvent? m_relativeRect = rect; - update(); + if (should_update) + update(); } void Widget::repaint(const Rect& rect) { - event(*make(rect)); + if (auto* w = window()) + w->repaint(rect); } void Widget::event(Event& event) @@ -109,10 +111,13 @@ void Widget::mouseMoveEvent(MouseEvent&) void Widget::update() { + auto* w = window(); + if (!w) + return; if (m_hasPendingPaintEvent) return; m_hasPendingPaintEvent = true; - EventLoop::main().postEvent(this, make(rect())); + EventLoop::main().postEvent(w, make(rect())); } Widget::HitTestResult Widget::hitTest(int x, int y) diff --git a/Widgets/Widget.h b/Widgets/Widget.h index 90dd8850a2..02176c35d0 100644 --- a/Widgets/Widget.h +++ b/Widgets/Widget.h @@ -34,6 +34,7 @@ public: int height() const { return m_relativeRect.height(); } Rect rect() const { return { 0, 0, width(), height() }; } + Size size() const { return m_relativeRect.size(); } void update(); void repaint(const Rect&); @@ -50,7 +51,7 @@ public: virtual const char* class_name() const override { return "Widget"; } - void setWindowRelativeRect(const Rect&); + void setWindowRelativeRect(const Rect&, bool should_update = true); Color backgroundColor() const { return m_backgroundColor; } Color foregroundColor() const { return m_foregroundColor; } diff --git a/Widgets/Window.cpp b/Widgets/Window.cpp index 2bdd4a9a9d..7ecd53e8cc 100644 --- a/Widgets/Window.cpp +++ b/Widgets/Window.cpp @@ -1,6 +1,7 @@ #include "Window.h" #include "WindowManager.h" #include "Event.h" +#include "EventLoop.h" #include "Widget.h" Window::Window(Object* parent) @@ -46,9 +47,14 @@ void Window::setRect(const Rect& rect) WindowManager::the().notifyRectChanged(*this, oldRect, m_rect); } -void Window::repaint() +void Window::repaint(const Rect& rect) { - event(*make()); + event(*make(rect)); +} + +void Window::update(const Rect& rect) +{ + EventLoop::main().postEvent(this, make(rect)); } void Window::event(Event& event) @@ -80,9 +86,11 @@ void Window::event(Event& event) } if (m_mainWidget) { if (pe.rect().is_empty()) - return m_mainWidget->event(*make(m_mainWidget->rect())); + m_mainWidget->event(*make(m_mainWidget->rect())); else - return m_mainWidget->event(event); + m_mainWidget->event(event); + WindowManager::the().did_paint(*this); + return; } return Object::event(event); } diff --git a/Widgets/Window.h b/Widgets/Window.h index 0c3658e052..be53f0fccc 100644 --- a/Widgets/Window.h +++ b/Widgets/Window.h @@ -40,7 +40,8 @@ public: bool isBeingDragged() const { return m_isBeingDragged; } void setIsBeingDragged(bool b) { m_isBeingDragged = b; } - void repaint(); + void repaint(const Rect& = Rect()); + void update(const Rect& = Rect()); bool isActive() const; diff --git a/Widgets/WindowManager.cpp b/Widgets/WindowManager.cpp index 0a49f2e8bc..9b296f59b6 100644 --- a/Widgets/WindowManager.cpp +++ b/Widgets/WindowManager.cpp @@ -136,9 +136,10 @@ void WindowManager::repaint() void WindowManager::did_paint(Window& window) { auto& framebuffer = FrameBufferSDL::the(); - if (m_windows_in_order.head() == &window) { + if (m_windows_in_order.tail() == &window) { ASSERT(window.backing()); framebuffer.blit(window.position(), *window.backing()); + printf("[WM] frontmost_only_compose_count: %u\n", ++m_frontmost_only_compose_count); return; } @@ -167,7 +168,7 @@ void WindowManager::notifyTitleChanged(Window& window) 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()); - repaintAfterMove(oldRect, newRect); + recompose(); } void WindowManager::handleTitleBarMouseEvent(Window& window, MouseEvent& event) @@ -190,28 +191,6 @@ void WindowManager::handleTitleBarMouseEvent(Window& window, MouseEvent& event) #endif } -void WindowManager::repaintAfterMove(const Rect& oldRect, const Rect& newRect) -{ - printf("[WM] repaint: [%d,%d %dx%d] -> [%d,%d %dx%d]\n", - oldRect.x(), - oldRect.y(), - oldRect.width(), - oldRect.height(), - newRect.x(), - newRect.y(), - newRect.width(), - newRect.height()); - - m_rootWidget->repaint(oldRect); - m_rootWidget->repaint(newRect); - for (auto* window = m_windows_in_order.head(); window; window = window->next()) { - if (outerRectForWindow(*window).intersects(oldRect) || outerRectForWindow(*window).intersects(newRect)) { - paintWindowFrame(*window); - window->repaint(); - } - } -} - void WindowManager::processMouseEvent(MouseEvent& event) { if (event.type() == Event::MouseUp) { @@ -220,8 +199,7 @@ void WindowManager::processMouseEvent(MouseEvent& event) m_dragWindow->setIsBeingDragged(false); m_dragEndRect = outerRectForWindow(*m_dragWindow); m_dragWindow = nullptr; - - repaintAfterMove(m_dragStartRect, m_dragEndRect); + recompose(); return; } } @@ -281,7 +259,8 @@ void WindowManager::recompose() { printf("[WM] recompose_count: %u\n", ++m_recompose_count); auto& framebuffer = FrameBufferSDL::the(); - m_rootWidget->repaint(m_rootWidget->rect()); + PaintEvent dummy_event(m_rootWidget->rect()); + m_rootWidget->paintEvent(dummy_event); for (auto* window = m_windows_in_order.head(); window; window = window->next()) { if (!window->backing()) continue; diff --git a/Widgets/WindowManager.h b/Widgets/WindowManager.h index 1a803c9867..074558105c 100644 --- a/Widgets/WindowManager.h +++ b/Widgets/WindowManager.h @@ -41,7 +41,6 @@ private: void processMouseEvent(MouseEvent&); void handleTitleBarMouseEvent(Window&, MouseEvent&); void handlePaintEvent(PaintEvent&); - void repaintAfterMove(const Rect& oldRect, const Rect& newRect); virtual void event(Event&) override; @@ -68,4 +67,5 @@ private: Rect m_dragEndRect; unsigned m_recompose_count { 0 }; + unsigned m_frontmost_only_compose_count { 0 }; };