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 c9d1511392..3533a4c7a9 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 b345bda92e..0a6219ecb5 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 b1e6447629..9bb86ef936 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 1647d5fc85..10b9d976bd 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 af61885a66..3a96906ad1 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 9e345ef52d..a5bba389a5 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) =|