mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 19:57:35 +00:00
WindowServer+LibGUI: Automatically close child windows with parent
If a window has child windows when it's destroyed, WindowServer will now automatically tear down all of its children as well. This is communicated to the client program through a vector of window ID's included with the response to WindowServer::DestroyWindow. This does feel a little bit awkward, but managing it on the client side also seems a bit awkward.
This commit is contained in:
parent
a726fda546
commit
745b0b27fd
5 changed files with 47 additions and 16 deletions
|
@ -126,18 +126,29 @@ Window* Window::find_parent_window()
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::hide()
|
void Window::server_did_destroy()
|
||||||
{
|
{
|
||||||
if (!is_visible())
|
|
||||||
return;
|
|
||||||
reified_windows->remove(m_window_id);
|
|
||||||
WindowServerConnection::the().send_sync<Messages::WindowServer::DestroyWindow>(m_window_id);
|
|
||||||
m_window_id = 0;
|
m_window_id = 0;
|
||||||
m_visible = false;
|
m_visible = false;
|
||||||
m_pending_paint_event_rects.clear();
|
m_pending_paint_event_rects.clear();
|
||||||
m_back_bitmap = nullptr;
|
m_back_bitmap = nullptr;
|
||||||
m_front_bitmap = nullptr;
|
m_front_bitmap = nullptr;
|
||||||
m_override_cursor = StandardCursor::None;
|
m_override_cursor = StandardCursor::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::hide()
|
||||||
|
{
|
||||||
|
if (!is_visible())
|
||||||
|
return;
|
||||||
|
reified_windows->remove(m_window_id);
|
||||||
|
auto response = WindowServerConnection::the().send_sync<Messages::WindowServer::DestroyWindow>(m_window_id);
|
||||||
|
server_did_destroy();
|
||||||
|
|
||||||
|
for (auto child_window_id : response->destroyed_window_ids()) {
|
||||||
|
if (auto* window = Window::from_window_id(child_window_id)) {
|
||||||
|
window->server_did_destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool app_has_visible_windows = false;
|
bool app_has_visible_windows = false;
|
||||||
for (auto& window : *all_windows) {
|
for (auto& window : *all_windows) {
|
||||||
|
|
|
@ -191,6 +191,8 @@ protected:
|
||||||
private:
|
private:
|
||||||
virtual bool is_window() const override final { return true; }
|
virtual bool is_window() const override final { return true; }
|
||||||
|
|
||||||
|
void server_did_destroy();
|
||||||
|
|
||||||
RefPtr<Gfx::Bitmap> create_backing_bitmap(const Gfx::Size&);
|
RefPtr<Gfx::Bitmap> create_backing_bitmap(const Gfx::Size&);
|
||||||
RefPtr<Gfx::Bitmap> create_shared_bitmap(Gfx::BitmapFormat, const Gfx::Size&);
|
RefPtr<Gfx::Bitmap> create_shared_bitmap(Gfx::BitmapFormat, const Gfx::Size&);
|
||||||
void set_current_backing_bitmap(Gfx::Bitmap&, bool flush_immediately = false);
|
void set_current_backing_bitmap(Gfx::Bitmap&, bool flush_immediately = false);
|
||||||
|
|
|
@ -472,6 +472,10 @@ OwnPtr<Messages::WindowServer::CreateWindowResponse> ClientConnection::handle(co
|
||||||
did_misbehave("CreateWindow with bad parent_window_id");
|
did_misbehave("CreateWindow with bad parent_window_id");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
if (parent_window->window_id() == window_id) {
|
||||||
|
did_misbehave("CreateWindow trying to make a window with itself as parent");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
window->set_parent_window(*parent_window);
|
window->set_parent_window(*parent_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,6 +501,25 @@ OwnPtr<Messages::WindowServer::CreateWindowResponse> ClientConnection::handle(co
|
||||||
return make<Messages::WindowServer::CreateWindowResponse>(window_id);
|
return make<Messages::WindowServer::CreateWindowResponse>(window_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientConnection::destroy_window(Window& window, Vector<i32>& destroyed_window_ids)
|
||||||
|
{
|
||||||
|
for (auto& child_window : window.child_windows()) {
|
||||||
|
if (!child_window)
|
||||||
|
continue;
|
||||||
|
ASSERT(child_window->window_id() != window.window_id());
|
||||||
|
destroy_window(*child_window, destroyed_window_ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyed_window_ids.append(window.window_id());
|
||||||
|
|
||||||
|
if (window.type() == WindowType::MenuApplet)
|
||||||
|
AppletManager::the().remove_applet(window);
|
||||||
|
|
||||||
|
WindowManager::the().invalidate(window);
|
||||||
|
remove_child(window);
|
||||||
|
m_windows.remove(window.window_id());
|
||||||
|
}
|
||||||
|
|
||||||
OwnPtr<Messages::WindowServer::DestroyWindowResponse> ClientConnection::handle(const Messages::WindowServer::DestroyWindow& message)
|
OwnPtr<Messages::WindowServer::DestroyWindowResponse> ClientConnection::handle(const Messages::WindowServer::DestroyWindow& message)
|
||||||
{
|
{
|
||||||
auto it = m_windows.find(message.window_id());
|
auto it = m_windows.find(message.window_id());
|
||||||
|
@ -505,16 +528,9 @@ OwnPtr<Messages::WindowServer::DestroyWindowResponse> ClientConnection::handle(c
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto& window = *(*it).value;
|
auto& window = *(*it).value;
|
||||||
|
Vector<i32> destroyed_window_ids;
|
||||||
if (window.type() == WindowType::MenuApplet)
|
destroy_window(window, destroyed_window_ids);
|
||||||
AppletManager::the().remove_applet(window);
|
return make<Messages::WindowServer::DestroyWindowResponse>(destroyed_window_ids);
|
||||||
|
|
||||||
WindowManager::the().invalidate(window);
|
|
||||||
remove_child(window);
|
|
||||||
ASSERT(it->value.ptr() == &window);
|
|
||||||
m_windows.remove(message.window_id());
|
|
||||||
|
|
||||||
return make<Messages::WindowServer::DestroyWindowResponse>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientConnection::post_paint_message(Window& window, bool ignore_occlusion)
|
void ClientConnection::post_paint_message(Window& window, bool ignore_occlusion)
|
||||||
|
|
|
@ -79,6 +79,8 @@ public:
|
||||||
private:
|
private:
|
||||||
explicit ClientConnection(Core::LocalSocket&, int client_id);
|
explicit ClientConnection(Core::LocalSocket&, int client_id);
|
||||||
|
|
||||||
|
void destroy_window(Window&, Vector<i32>& destroyed_window_ids);
|
||||||
|
|
||||||
virtual OwnPtr<Messages::WindowServer::GreetResponse> handle(const Messages::WindowServer::Greet&) override;
|
virtual OwnPtr<Messages::WindowServer::GreetResponse> handle(const Messages::WindowServer::Greet&) override;
|
||||||
virtual OwnPtr<Messages::WindowServer::CreateMenubarResponse> handle(const Messages::WindowServer::CreateMenubar&) override;
|
virtual OwnPtr<Messages::WindowServer::CreateMenubarResponse> handle(const Messages::WindowServer::CreateMenubar&) override;
|
||||||
virtual OwnPtr<Messages::WindowServer::DestroyMenubarResponse> handle(const Messages::WindowServer::DestroyMenubar&) override;
|
virtual OwnPtr<Messages::WindowServer::DestroyMenubarResponse> handle(const Messages::WindowServer::DestroyMenubar&) override;
|
||||||
|
|
|
@ -44,7 +44,7 @@ endpoint WindowServer = 2
|
||||||
String title,
|
String title,
|
||||||
i32 parent_window_id) => (i32 window_id)
|
i32 parent_window_id) => (i32 window_id)
|
||||||
|
|
||||||
DestroyWindow(i32 window_id) => ()
|
DestroyWindow(i32 window_id) => (Vector<i32> destroyed_window_ids)
|
||||||
|
|
||||||
SetWindowTitle(i32 window_id, String title) => ()
|
SetWindowTitle(i32 window_id, String title) => ()
|
||||||
GetWindowTitle(i32 window_id) => (String title)
|
GetWindowTitle(i32 window_id) => (String title)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue