summaryrefslogtreecommitdiff
path: root/Servers/WindowServer
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-05-01 23:53:05 +0200
committerAndreas Kling <kling@serenityos.org>2020-05-02 01:29:55 +0200
commit745b0b27fd01c124e93aaf591c2c4c5610dd0d82 (patch)
tree2af110cef36988555454b38d4b2de92bdba37825 /Servers/WindowServer
parenta726fda5461a8ff9ef49e378a6170c1eeddbe02a (diff)
downloadserenity-745b0b27fd01c124e93aaf591c2c4c5610dd0d82.zip
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.
Diffstat (limited to 'Servers/WindowServer')
-rw-r--r--Servers/WindowServer/ClientConnection.cpp34
-rw-r--r--Servers/WindowServer/ClientConnection.h2
-rw-r--r--Servers/WindowServer/WindowServer.ipc2
3 files changed, 28 insertions, 10 deletions
diff --git a/Servers/WindowServer/ClientConnection.cpp b/Servers/WindowServer/ClientConnection.cpp
index 32b2ba3100..e49143d700 100644
--- a/Servers/WindowServer/ClientConnection.cpp
+++ b/Servers/WindowServer/ClientConnection.cpp
@@ -472,6 +472,10 @@ OwnPtr<Messages::WindowServer::CreateWindowResponse> ClientConnection::handle(co
did_misbehave("CreateWindow with bad parent_window_id");
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);
}
@@ -497,24 +501,36 @@ OwnPtr<Messages::WindowServer::CreateWindowResponse> ClientConnection::handle(co
return make<Messages::WindowServer::CreateWindowResponse>(window_id);
}
-OwnPtr<Messages::WindowServer::DestroyWindowResponse> ClientConnection::handle(const Messages::WindowServer::DestroyWindow& message)
+void ClientConnection::destroy_window(Window& window, Vector<i32>& destroyed_window_ids)
{
- auto it = m_windows.find(message.window_id());
- if (it == m_windows.end()) {
- did_misbehave("DestroyWindow: Bad window ID");
- return nullptr;
+ 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);
}
- auto& window = *(*it).value;
+
+ destroyed_window_ids.append(window.window_id());
if (window.type() == WindowType::MenuApplet)
AppletManager::the().remove_applet(window);
WindowManager::the().invalidate(window);
remove_child(window);
- ASSERT(it->value.ptr() == &window);
- m_windows.remove(message.window_id());
+ m_windows.remove(window.window_id());
+}
- return make<Messages::WindowServer::DestroyWindowResponse>();
+OwnPtr<Messages::WindowServer::DestroyWindowResponse> ClientConnection::handle(const Messages::WindowServer::DestroyWindow& message)
+{
+ auto it = m_windows.find(message.window_id());
+ if (it == m_windows.end()) {
+ did_misbehave("DestroyWindow: Bad window ID");
+ return nullptr;
+ }
+ auto& window = *(*it).value;
+ Vector<i32> destroyed_window_ids;
+ destroy_window(window, destroyed_window_ids);
+ return make<Messages::WindowServer::DestroyWindowResponse>(destroyed_window_ids);
}
void ClientConnection::post_paint_message(Window& window, bool ignore_occlusion)
diff --git a/Servers/WindowServer/ClientConnection.h b/Servers/WindowServer/ClientConnection.h
index 1c11bb2711..92c2f2fa08 100644
--- a/Servers/WindowServer/ClientConnection.h
+++ b/Servers/WindowServer/ClientConnection.h
@@ -79,6 +79,8 @@ public:
private:
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::CreateMenubarResponse> handle(const Messages::WindowServer::CreateMenubar&) override;
virtual OwnPtr<Messages::WindowServer::DestroyMenubarResponse> handle(const Messages::WindowServer::DestroyMenubar&) override;
diff --git a/Servers/WindowServer/WindowServer.ipc b/Servers/WindowServer/WindowServer.ipc
index d1be40824a..214afa7567 100644
--- a/Servers/WindowServer/WindowServer.ipc
+++ b/Servers/WindowServer/WindowServer.ipc
@@ -44,7 +44,7 @@ endpoint WindowServer = 2
String title,
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) => ()
GetWindowTitle(i32 window_id) => (String title)