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