mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 11:28:12 +00:00
WindowServer+LibGUI: Mark window bitmaps volatile in occluded windows
WindowServer now tracks whether windows are occluded (meaning that they are completely covered by one or more opaque windows sitting above them.) This state is communicated to the windows via WindowStateChanged messages, which then allow GWindow to mark its backing store volatile. This reduces the effective memory impact of windows that are not at all visible to the user. Very cool. :^)
This commit is contained in:
parent
5d1acdda82
commit
c7847d7c81
9 changed files with 72 additions and 10 deletions
|
@ -298,6 +298,11 @@ bool GWindow::is_visible() const
|
|||
return m_window_id != 0;
|
||||
}
|
||||
|
||||
void GWindow::update()
|
||||
{
|
||||
update({ 0, 0, width(), height() });
|
||||
}
|
||||
|
||||
void GWindow::update(const Rect& a_rect)
|
||||
{
|
||||
if (!m_window_id)
|
||||
|
@ -583,17 +588,19 @@ void GWindow::update_all_windows(Badge<GWindowServerConnection>)
|
|||
}
|
||||
}
|
||||
|
||||
void GWindow::notify_state_changed(Badge<GWindowServerConnection>, bool minimized)
|
||||
void GWindow::notify_state_changed(Badge<GWindowServerConnection>, bool minimized, bool occluded)
|
||||
{
|
||||
// When double buffering is enabled, minimization means we can mark the front bitmap volatile (in addition to the back bitmap.)
|
||||
// When double buffering is enabled, minimization/occlusion 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<GraphicsBitmap>& bitmap = m_double_buffering_enabled ? m_front_bitmap : m_back_bitmap;
|
||||
if (!bitmap)
|
||||
return;
|
||||
if (minimized) {
|
||||
if (minimized || occluded) {
|
||||
bitmap->shared_buffer()->set_volatile();
|
||||
} else {
|
||||
if (!bitmap->shared_buffer()->set_nonvolatile())
|
||||
if (!bitmap->shared_buffer()->set_nonvolatile()) {
|
||||
bitmap = nullptr;
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,7 +101,8 @@ public:
|
|||
const GWidget* focused_widget() const { return m_focused_widget; }
|
||||
void set_focused_widget(GWidget*);
|
||||
|
||||
void update(const Rect& = Rect());
|
||||
void update();
|
||||
void update(const Rect&);
|
||||
|
||||
void set_global_cursor_tracking_widget(GWidget*);
|
||||
GWidget* global_cursor_tracking_widget() { return m_global_cursor_tracking_widget.ptr(); }
|
||||
|
@ -136,7 +137,7 @@ public:
|
|||
void schedule_relayout();
|
||||
|
||||
static void update_all_windows(Badge<GWindowServerConnection>);
|
||||
void notify_state_changed(Badge<GWindowServerConnection>, bool minimized);
|
||||
void notify_state_changed(Badge<GWindowServerConnection>, bool minimized, bool occluded);
|
||||
|
||||
protected:
|
||||
GWindow(CObject* parent = nullptr);
|
||||
|
|
|
@ -299,5 +299,5 @@ void GWindowServerConnection::handle(const WindowClient::DragCancelled&)
|
|||
void GWindowServerConnection::handle(const WindowClient::WindowStateChanged& message)
|
||||
{
|
||||
if (auto* window = GWindow::from_window_id(message.window_id()))
|
||||
window->notify_state_changed({}, message.minimized());
|
||||
window->notify_state_changed({}, message.minimized(), message.occluded());
|
||||
}
|
||||
|
|
|
@ -110,6 +110,22 @@ void WSWindow::set_minimized(bool minimized)
|
|||
WSWindowManager::the().notify_minimization_state_changed(*this);
|
||||
}
|
||||
|
||||
void WSWindow::set_opacity(float opacity)
|
||||
{
|
||||
if (m_opacity == opacity)
|
||||
return;
|
||||
m_opacity = opacity;
|
||||
WSWindowManager::the().notify_opacity_changed(*this);
|
||||
}
|
||||
|
||||
void WSWindow::set_occluded(bool occluded)
|
||||
{
|
||||
if (m_occluded == occluded)
|
||||
return;
|
||||
m_occluded = occluded;
|
||||
WSWindowManager::the().notify_occlusion_state_changed(*this);
|
||||
}
|
||||
|
||||
void WSWindow::set_maximized(bool maximized)
|
||||
{
|
||||
if (m_maximized == maximized)
|
||||
|
|
|
@ -47,6 +47,9 @@ public:
|
|||
bool is_fullscreen() const { return m_fullscreen; }
|
||||
void set_fullscreen(bool);
|
||||
|
||||
bool is_occluded() const { return m_occluded; }
|
||||
void set_occluded(bool);
|
||||
|
||||
bool show_titlebar() const { return m_show_titlebar; }
|
||||
void set_show_titlebar(bool show) { m_show_titlebar = show; }
|
||||
|
||||
|
@ -72,7 +75,7 @@ public:
|
|||
void set_title(const String&);
|
||||
|
||||
float opacity() const { return m_opacity; }
|
||||
void set_opacity(float opacity) { m_opacity = opacity; }
|
||||
void set_opacity(float);
|
||||
|
||||
int x() const { return m_rect.x(); }
|
||||
int y() const { return m_rect.y(); }
|
||||
|
@ -193,6 +196,7 @@ private:
|
|||
bool m_minimized { false };
|
||||
bool m_maximized { false };
|
||||
bool m_fullscreen { false };
|
||||
bool m_occluded { false };
|
||||
bool m_show_titlebar { true };
|
||||
RefPtr<GraphicsBitmap> m_backing_store;
|
||||
RefPtr<GraphicsBitmap> m_last_backing_store;
|
||||
|
|
|
@ -425,22 +425,51 @@ void WSWindowManager::notify_rect_changed(WSWindow& window, const Rect& old_rect
|
|||
#endif
|
||||
if (m_switcher.is_visible() && window.type() != WSWindowType::WindowSwitcher)
|
||||
m_switcher.refresh();
|
||||
|
||||
recompute_occlusions();
|
||||
|
||||
tell_wm_listeners_window_rect_changed(window);
|
||||
|
||||
m_menu_manager.refresh();
|
||||
}
|
||||
|
||||
void WSWindowManager::recompute_occlusions()
|
||||
{
|
||||
for_each_visible_window_from_back_to_front([&](WSWindow& window) {
|
||||
if (m_switcher.is_visible()) {
|
||||
window.set_occluded(false);
|
||||
} else {
|
||||
if (any_opaque_window_above_this_one_contains_rect(window, window.frame().rect()))
|
||||
window.set_occluded(true);
|
||||
else
|
||||
window.set_occluded(false);
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
void WSWindowManager::notify_opacity_changed(WSWindow&)
|
||||
{
|
||||
recompute_occlusions();
|
||||
}
|
||||
|
||||
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()));
|
||||
window.client()->post_message(WindowClient::WindowStateChanged(window.window_id(), window.is_minimized(), window.is_occluded()));
|
||||
|
||||
if (window.is_active() && window.is_minimized())
|
||||
pick_new_active_window();
|
||||
}
|
||||
|
||||
void WSWindowManager::notify_occlusion_state_changed(WSWindow& window)
|
||||
{
|
||||
if (window.client())
|
||||
window.client()->post_message(WindowClient::WindowStateChanged(window.window_id(), window.is_minimized(), window.is_occluded()));
|
||||
}
|
||||
|
||||
void WSWindowManager::pick_new_active_window()
|
||||
{
|
||||
for_each_visible_window_of_type_from_front_to_back(WSWindowType::Normal, [&](WSWindow& candidate) {
|
||||
|
|
|
@ -68,6 +68,8 @@ public:
|
|||
void notify_title_changed(WSWindow&);
|
||||
void notify_rect_changed(WSWindow&, const Rect& oldRect, const Rect& newRect);
|
||||
void notify_minimization_state_changed(WSWindow&);
|
||||
void notify_opacity_changed(WSWindow&);
|
||||
void notify_occlusion_state_changed(WSWindow&);
|
||||
void notify_client_changed_app_menubar(WSClientConnection&);
|
||||
|
||||
Rect maximized_window_rect(const WSWindow&) const;
|
||||
|
@ -199,6 +201,8 @@ private:
|
|||
void tell_wm_listener_about_window_rect(WSWindow& listener, WSWindow&);
|
||||
void pick_new_active_window();
|
||||
|
||||
void recompute_occlusions();
|
||||
|
||||
RefPtr<WSCursor> m_arrow_cursor;
|
||||
RefPtr<WSCursor> m_hand_cursor;
|
||||
RefPtr<WSCursor> m_resize_horizontally_cursor;
|
||||
|
|
|
@ -28,6 +28,7 @@ void WSWindowSwitcher::set_visible(bool visible)
|
|||
if (m_visible == visible)
|
||||
return;
|
||||
m_visible = visible;
|
||||
WSWindowManager::the().recompute_occlusions();
|
||||
if (m_switcher_window)
|
||||
m_switcher_window->set_visible(visible);
|
||||
if (!m_visible)
|
||||
|
|
|
@ -12,7 +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) =|
|
||||
WindowStateChanged(i32 window_id, bool minimized, bool occluded) =|
|
||||
WindowCloseRequest(i32 window_id) =|
|
||||
WindowResized(i32 window_id, Rect old_rect, Rect new_rect) =|
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue