Stop recomposing the window hierarchy after every dang widget paint.

This commit is contained in:
Andreas Kling 2019-01-09 04:46:16 +01:00
parent f3ec96a1b9
commit cfd76ade73
Notes: sideshowbarker 2024-07-19 16:05:35 +09:00
8 changed files with 34 additions and 41 deletions

View file

@ -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)

View file

@ -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()

View file

@ -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<PaintEvent>(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<PaintEvent>(rect()));
EventLoop::main().postEvent(w, make<PaintEvent>(rect()));
}
Widget::HitTestResult Widget::hitTest(int x, int y)

View file

@ -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; }

View file

@ -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<PaintEvent>());
event(*make<PaintEvent>(rect));
}
void Window::update(const Rect& rect)
{
EventLoop::main().postEvent(this, make<PaintEvent>(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<PaintEvent>(m_mainWidget->rect()));
m_mainWidget->event(*make<PaintEvent>(m_mainWidget->rect()));
else
return m_mainWidget->event(event);
m_mainWidget->event(event);
WindowManager::the().did_paint(*this);
return;
}
return Object::event(event);
}

View file

@ -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;

View file

@ -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;

View file

@ -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 };
};