From eaa680ab8e7ca227f959eff167a1dd23c433e909 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 19 Feb 2020 16:45:06 +0100 Subject: [PATCH] WindowServer+LibGUI: Force full window repaints after theme change We were not repainting windows that were occluded at the time of the theme changing. This patch adds a way to bypass occlusion testing when invalidating window rects. Fixes #1249. --- Libraries/LibGUI/Window.cpp | 13 ++++++++++--- Libraries/LibGUI/Window.h | 1 + Servers/WindowServer/ClientConnection.cpp | 6 +++--- Servers/WindowServer/ClientConnection.h | 2 +- Servers/WindowServer/Window.cpp | 6 +++--- Servers/WindowServer/Window.h | 2 +- Servers/WindowServer/WindowServer.ipc | 2 +- 7 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Libraries/LibGUI/Window.cpp b/Libraries/LibGUI/Window.cpp index 3386f9a86c..d4a60148d0 100644 --- a/Libraries/LibGUI/Window.cpp +++ b/Libraries/LibGUI/Window.cpp @@ -341,7 +341,14 @@ bool Window::is_visible() const void Window::update() { - update({ 0, 0, width(), height() }); + auto rect = this->rect(); + update({ 0, 0, rect.width(), rect.height() }); +} + +void Window::force_update() +{ + auto rect = this->rect(); + WindowServerConnection::the().post_message(Messages::WindowServer::InvalidateRect(m_window_id, { { 0, 0, rect.width(), rect.height() } }, true)); } void Window::update(const Gfx::Rect& a_rect) @@ -366,7 +373,7 @@ void Window::update(const Gfx::Rect& a_rect) Vector rects_to_send; for (auto& r : rects) rects_to_send.append(r); - WindowServerConnection::the().post_message(Messages::WindowServer::InvalidateRect(m_window_id, rects_to_send)); + WindowServerConnection::the().post_message(Messages::WindowServer::InvalidateRect(m_window_id, rects_to_send, false)); }); } m_pending_paint_event_rects.append(a_rect); @@ -626,7 +633,7 @@ void Window::schedule_relayout() void Window::update_all_windows(Badge) { for (auto* window : *all_windows) { - window->update(); + window->force_update(); } } diff --git a/Libraries/LibGUI/Window.h b/Libraries/LibGUI/Window.h index 7c2478242d..33f7e1d689 100644 --- a/Libraries/LibGUI/Window.h +++ b/Libraries/LibGUI/Window.h @@ -182,6 +182,7 @@ private: NonnullRefPtr create_shared_bitmap(Gfx::BitmapFormat, const Gfx::Size&); void set_current_backing_bitmap(Gfx::Bitmap&, bool flush_immediately = false); void flip(const Vector& dirty_rects); + void force_update(); RefPtr m_front_bitmap; RefPtr m_back_bitmap; diff --git a/Servers/WindowServer/ClientConnection.cpp b/Servers/WindowServer/ClientConnection.cpp index 5d4dc7ca90..910e9ef919 100644 --- a/Servers/WindowServer/ClientConnection.cpp +++ b/Servers/WindowServer/ClientConnection.cpp @@ -465,10 +465,10 @@ OwnPtr ClientConnection::handle(c return make(); } -void ClientConnection::post_paint_message(Window& window) +void ClientConnection::post_paint_message(Window& window, bool ignore_occlusion) { auto rect_set = window.take_pending_paint_rects(); - if (window.is_minimized() || window.is_occluded()) + if (window.is_minimized() || (!ignore_occlusion && window.is_occluded())) return; post_message(Messages::WindowClient::Paint(window.window_id(), window.size(), rect_set.rects())); @@ -483,7 +483,7 @@ void ClientConnection::handle(const Messages::WindowServer::InvalidateRect& mess } auto& window = *(*it).value; for (int i = 0; i < message.rects().size(); ++i) - window.request_update(message.rects()[i].intersected({ {}, window.size() })); + window.request_update(message.rects()[i].intersected({ {}, window.size() }), message.ignore_occlusion()); } void ClientConnection::handle(const Messages::WindowServer::DidFinishPainting& message) diff --git a/Servers/WindowServer/ClientConnection.h b/Servers/WindowServer/ClientConnection.h index c0c60a5b6e..9c00593f29 100644 --- a/Servers/WindowServer/ClientConnection.h +++ b/Servers/WindowServer/ClientConnection.h @@ -62,7 +62,7 @@ public: void notify_about_new_screen_rect(const Gfx::Rect&); void notify_about_clipboard_contents_changed(); - void post_paint_message(Window&); + void post_paint_message(Window&, bool ignore_occlusion = false); Menu* find_menu_by_id(int menu_id) { diff --git a/Servers/WindowServer/Window.cpp b/Servers/WindowServer/Window.cpp index 0ec89055a9..37b0cda034 100644 --- a/Servers/WindowServer/Window.cpp +++ b/Servers/WindowServer/Window.cpp @@ -317,11 +317,11 @@ void Window::set_default_icon() m_icon = default_window_icon(); } -void Window::request_update(const Gfx::Rect& rect) +void Window::request_update(const Gfx::Rect& rect, bool ignore_occlusion) { if (m_pending_paint_rects.is_empty()) { - deferred_invoke([this](auto&) { - client()->post_paint_message(*this); + deferred_invoke([this, ignore_occlusion](auto&) { + client()->post_paint_message(*this, ignore_occlusion); }); } m_pending_paint_rects.add(rect); diff --git a/Servers/WindowServer/Window.h b/Servers/WindowServer/Window.h index 6e14e5ccbc..2d9e84bad1 100644 --- a/Servers/WindowServer/Window.h +++ b/Servers/WindowServer/Window.h @@ -208,7 +208,7 @@ public: const Cursor* override_cursor() const { return m_override_cursor.ptr(); } void set_override_cursor(RefPtr&& cursor) { m_override_cursor = move(cursor); } - void request_update(const Gfx::Rect&); + void request_update(const Gfx::Rect&, bool ignore_occlusion = false); Gfx::DisjointRectSet take_pending_paint_rects() { return move(m_pending_paint_rects); } bool in_minimize_animation() const { return m_minimize_animation_step != -1; } diff --git a/Servers/WindowServer/WindowServer.ipc b/Servers/WindowServer/WindowServer.ipc index a483896d82..ab70c9d307 100644 --- a/Servers/WindowServer/WindowServer.ipc +++ b/Servers/WindowServer/WindowServer.ipc @@ -51,7 +51,7 @@ endpoint WindowServer = 2 SetWindowRect(i32 window_id, Gfx::Rect rect) => () GetWindowRect(i32 window_id) => (Gfx::Rect rect) - InvalidateRect(i32 window_id, Vector rects) =| + InvalidateRect(i32 window_id, Vector rects, bool ignore_occlusion) =| DidFinishPainting(i32 window_id, Vector rects) =| SetGlobalCursorTracking(i32 window_id, bool enabled) => ()