1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 01:57:44 +00:00

LibGUI: Only redraw the dirty rect in GWidget.

There is some trouble here with the asynchronous nature of WindowServer
and the single per-window backing store we're drawing into. If we start
repainting a widget with a pending invalidation, that invalidation might
get flushed by the WindowServer mid-paint.
This commit is contained in:
Andreas Kling 2019-01-20 07:56:48 +01:00
parent ea6678b7b3
commit a9e60fc800
4 changed files with 10 additions and 8 deletions

View file

@ -61,7 +61,7 @@ void GWidget::paintEvent(GPaintEvent& event)
{ {
if (fillWithBackgroundColor()) { if (fillWithBackgroundColor()) {
Painter painter(*this); Painter painter(*this);
painter.fill_rect(rect(), backgroundColor()); painter.fill_rect(event.rect(), backgroundColor());
} }
for (auto* ch : children()) { for (auto* ch : children()) {
auto* child = (GWidget*)ch; auto* child = (GWidget*)ch;

View file

@ -102,12 +102,12 @@ void GWindow::event(GEvent& event)
if (!m_main_widget) if (!m_main_widget)
return; return;
auto& paint_event = static_cast<GPaintEvent&>(event); auto& paint_event = static_cast<GPaintEvent&>(event);
if (paint_event.rect().is_empty()) { auto rect = paint_event.rect();
m_main_widget->paintEvent(*make<GPaintEvent>(m_main_widget->rect())); if (rect.is_empty())
} else { rect = m_main_widget->rect();
m_main_widget->event(event); m_main_widget->event(*make<GPaintEvent>(rect));
} GUI_Rect gui_rect = rect;
int rc = gui_invalidate_window(m_window_id, nullptr); int rc = gui_invalidate_window(m_window_id, &gui_rect);
ASSERT(rc == 0); ASSERT(rc == 0);
} }

View file

@ -37,6 +37,8 @@ public:
void close(); void close();
GWidget* main_widget() { return m_main_widget; }
const GWidget* main_widget() const { return m_main_widget; }
void set_main_widget(GWidget*); void set_main_widget(GWidget*);
GraphicsBitmap* backing() { return m_backing.ptr(); } GraphicsBitmap* backing() { return m_backing.ptr(); }

View file

@ -31,7 +31,7 @@ Painter::Painter(GWidget& widget)
#ifdef DEBUG_WIDGET_UNDERDRAW #ifdef DEBUG_WIDGET_UNDERDRAW
// If the widget is not opaque, let's not mess it up with debugging color. // If the widget is not opaque, let's not mess it up with debugging color.
if (widget.fillWithBackgroundColor()) if (widget.fillWithBackgroundColor() && m_window->main_widget() != &widget)
fill_rect(widget.rect(), Color::Red); fill_rect(widget.rect(), Color::Red);
#endif #endif
} }