From 519cb80a9680fdd806667ee100e495994ce3abbc Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 26 Dec 2019 12:06:07 +0100 Subject: [PATCH] LibGUI+WindowServer: Mark minimized window backing stores as volatile WindowServer will now send out a WindowStateChanged message to clients when one of their windows is minimized. This is then forwarded to the GWindow, which will try to mark its underlying window backing store as volatile. This allows the kernel to steal the memory used by minimized windows in case it starts running low. Very cool! :^) --- Libraries/LibGUI/GWindow.cpp | 15 +++++++++++++++ Libraries/LibGUI/GWindow.h | 1 + Libraries/LibGUI/GWindowServerConnection.cpp | 6 ++++++ Libraries/LibGUI/GWindowServerConnection.h | 1 + Servers/WindowServer/WSWindowManager.cpp | 3 +++ Servers/WindowServer/WindowClient.ipc | 1 + 6 files changed, 27 insertions(+) diff --git a/Libraries/LibGUI/GWindow.cpp b/Libraries/LibGUI/GWindow.cpp index c9d1511392c..3533a4c7a90 100644 --- a/Libraries/LibGUI/GWindow.cpp +++ b/Libraries/LibGUI/GWindow.cpp @@ -693,3 +693,18 @@ void GWindow::update_all_windows(Badge) window->update(); } } + +void GWindow::notify_state_changed(Badge, bool minimized) +{ + // When double buffering is enabled, minimization means we can mark the front bitmap volatile (in addition to the back bitmap.) + // When double buffering is disabled, there is only the back bitmap (which we can now mark volatile!) + RefPtr& bitmap = m_double_buffering_enabled ? m_front_bitmap : m_back_bitmap; + if (!bitmap) + return; + if (minimized) { + bitmap->shared_buffer()->set_volatile(); + } else { + if (!bitmap->shared_buffer()->set_nonvolatile()) + bitmap = nullptr; + } +} diff --git a/Libraries/LibGUI/GWindow.h b/Libraries/LibGUI/GWindow.h index b345bda92ef..0a6219ecb5f 100644 --- a/Libraries/LibGUI/GWindow.h +++ b/Libraries/LibGUI/GWindow.h @@ -136,6 +136,7 @@ public: void schedule_relayout(); static void update_all_windows(Badge); + void notify_state_changed(Badge, bool minimized); protected: GWindow(CObject* parent = nullptr); diff --git a/Libraries/LibGUI/GWindowServerConnection.cpp b/Libraries/LibGUI/GWindowServerConnection.cpp index b1e64476294..9bb86ef9363 100644 --- a/Libraries/LibGUI/GWindowServerConnection.cpp +++ b/Libraries/LibGUI/GWindowServerConnection.cpp @@ -295,3 +295,9 @@ void GWindowServerConnection::handle(const WindowClient::DragCancelled&) { GDragOperation::notify_cancelled({}); } + +void GWindowServerConnection::handle(const WindowClient::WindowStateChanged& message) +{ + if (auto* window = GWindow::from_window_id(message.window_id())) + window->notify_state_changed({}, message.minimized()); +} diff --git a/Libraries/LibGUI/GWindowServerConnection.h b/Libraries/LibGUI/GWindowServerConnection.h index 1647d5fc850..10b9d976bd4 100644 --- a/Libraries/LibGUI/GWindowServerConnection.h +++ b/Libraries/LibGUI/GWindowServerConnection.h @@ -45,4 +45,5 @@ private: virtual void handle(const WindowClient::DragAccepted&) override; virtual void handle(const WindowClient::DragCancelled&) override; virtual void handle(const WindowClient::UpdateSystemTheme&) override; + virtual void handle(const WindowClient::WindowStateChanged&) override; }; diff --git a/Servers/WindowServer/WSWindowManager.cpp b/Servers/WindowServer/WSWindowManager.cpp index af61885a66e..3a96906ad1f 100644 --- a/Servers/WindowServer/WSWindowManager.cpp +++ b/Servers/WindowServer/WSWindowManager.cpp @@ -434,6 +434,9 @@ void WSWindowManager::notify_minimization_state_changed(WSWindow& window) { tell_wm_listeners_window_state_changed(window); + if (window.client()) + window.client()->post_message(WindowClient::WindowStateChanged(window.window_id(), window.is_minimized())); + if (window.is_active() && window.is_minimized()) pick_new_active_window(); } diff --git a/Servers/WindowServer/WindowClient.ipc b/Servers/WindowServer/WindowClient.ipc index 9e345ef52db..a5bba389a55 100644 --- a/Servers/WindowServer/WindowClient.ipc +++ b/Servers/WindowServer/WindowClient.ipc @@ -12,6 +12,7 @@ endpoint WindowClient = 4 KeyUp(i32 window_id, u8 character, u32 key, u32 modifiers) =| WindowActivated(i32 window_id) =| WindowDeactivated(i32 window_id) =| + WindowStateChanged(i32 window_id, bool minimized) =| WindowCloseRequest(i32 window_id) =| WindowResized(i32 window_id, Rect old_rect, Rect new_rect) =|