WindowServer: Robustify WSWindow<->WSClientConnection link a bit

WSWindow now detaches from WSClientConnection when being destroyed.

Because of this, we can no longer rely on WSWindow::client() to tell
us whether a window is internal to WindowServer or not. So instead we
now have WSWindow::is_internal() which checks for client_id == -1.

Note that WSWindow now also gets a copy of its client_id when
constructed, since we can no longer rely on client() being valid after
destruction has started.

This allows various automatic mechanisms (e.g what happens in response
to window removal) to skip over windows that are being destroyed.

Fixes #387.
This commit is contained in:
Andreas Kling 2020-01-25 10:25:49 +01:00
parent 60d5b06e21
commit 6df81c8a88
Notes: sideshowbarker 2024-07-19 09:50:32 +09:00
4 changed files with 22 additions and 8 deletions

View file

@ -77,6 +77,8 @@ WSClientConnection::~WSClientConnection()
{
WSMenuManager::the().close_all_menus_from_client({}, *this);
auto windows = move(m_windows);
for (auto& window : windows)
window.value->detach_client({});
}
void WSClientConnection::die()

View file

@ -63,6 +63,7 @@ WSWindow::WSWindow(WSClientConnection& client, WSWindowType window_type, int win
, m_resizable(resizable)
, m_fullscreen(fullscreen)
, m_window_id(window_id)
, m_client_id(client.client_id())
, m_icon(default_window_icon())
, m_frame(*this)
{
@ -76,6 +77,10 @@ WSWindow::WSWindow(WSClientConnection& client, WSWindowType window_type, int win
WSWindow::~WSWindow()
{
// Detach from client at the start of teardown since we don't want
// to confuse things by trying to send messages to it.
m_client = nullptr;
WSWindowManager::the().remove_window(*this);
}

View file

@ -114,6 +114,9 @@ public:
WSWindowType type() const { return m_type; }
int window_id() const { return m_window_id; }
bool is_internal() const { return m_client_id == -1; }
i32 client_id() const { return m_client_id; }
String title() const { return m_title; }
void set_title(const String&);
@ -219,6 +222,8 @@ public:
WSWindow* m_next { nullptr };
WSWindow* m_prev { nullptr };
void detach_client(Badge<WSClientConnection>) { m_client = nullptr; }
private:
void handle_mouse_event(const WSMouseEvent&);
void update_menu_item_text(PopupMenuItem item);
@ -248,6 +253,7 @@ private:
RefPtr<GraphicsBitmap> m_backing_store;
RefPtr<GraphicsBitmap> m_last_backing_store;
int m_window_id { -1 };
i32 m_client_id { -1 };
float m_opacity { 1 };
Size m_size_increment;
Size m_base_size;

View file

@ -205,13 +205,14 @@ void WSWindowManager::remove_window(WSWindow& window)
if (m_switcher.is_visible() && window.type() != WSWindowType::WindowSwitcher)
m_switcher.refresh();
recompute_occlusions();
for_each_window_listening_to_wm_events([&window](WSWindow& listener) {
if (!(listener.wm_event_mask() & WSWMEventMask::WindowRemovals))
return IterationDecision::Continue;
if (window.client())
listener.client()->post_message(WindowClient::WM_WindowRemoved(listener.window_id(), window.client()->client_id(), window.window_id()));
if (!window.is_internal())
listener.client()->post_message(WindowClient::WM_WindowRemoved(listener.window_id(), window.client_id(), window.window_id()));
return IterationDecision::Continue;
});
}
@ -220,25 +221,25 @@ void WSWindowManager::tell_wm_listener_about_window(WSWindow& listener, WSWindow
{
if (!(listener.wm_event_mask() & WSWMEventMask::WindowStateChanges))
return;
if (!window.client())
if (window.is_internal())
return;
listener.client()->post_message(WindowClient::WM_WindowStateChanged(listener.window_id(), window.client()->client_id(), window.window_id(), window.is_active(), window.is_minimized(), (i32)window.type(), window.title(), window.rect()));
listener.client()->post_message(WindowClient::WM_WindowStateChanged(listener.window_id(), window.client_id(), window.window_id(), window.is_active(), window.is_minimized(), (i32)window.type(), window.title(), window.rect()));
}
void WSWindowManager::tell_wm_listener_about_window_rect(WSWindow& listener, WSWindow& window)
{
if (!(listener.wm_event_mask() & WSWMEventMask::WindowRectChanges))
return;
if (!window.client())
if (window.is_internal())
return;
listener.client()->post_message(WindowClient::WM_WindowRectChanged(listener.window_id(), window.client()->client_id(), window.window_id(), window.rect()));
listener.client()->post_message(WindowClient::WM_WindowRectChanged(listener.window_id(), window.client_id(), window.window_id(), window.rect()));
}
void WSWindowManager::tell_wm_listener_about_window_icon(WSWindow& listener, WSWindow& window)
{
if (!(listener.wm_event_mask() & WSWMEventMask::WindowIconChanges))
return;
if (!window.client())
if (window.is_internal())
return;
if (window.icon().shared_buffer_id() == -1)
return;
@ -246,7 +247,7 @@ void WSWindowManager::tell_wm_listener_about_window_icon(WSWindow& listener, WSW
if (share_buffer_with(window.icon().shared_buffer_id(), listener.client()->client_pid()) < 0) {
ASSERT_NOT_REACHED();
}
listener.client()->post_message(WindowClient::WM_WindowIconBitmapChanged(listener.window_id(), window.client()->client_id(), window.window_id(), window.icon().shared_buffer_id(), window.icon().size()));
listener.client()->post_message(WindowClient::WM_WindowIconBitmapChanged(listener.window_id(), window.client_id(), window.window_id(), window.icon().shared_buffer_id(), window.icon().size()));
}
void WSWindowManager::tell_wm_listeners_window_state_changed(WSWindow& window)