diff options
author | Andreas Kling <kling@serenityos.org> | 2020-05-01 23:53:05 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-05-02 01:29:55 +0200 |
commit | 745b0b27fd01c124e93aaf591c2c4c5610dd0d82 (patch) | |
tree | 2af110cef36988555454b38d4b2de92bdba37825 /Servers/WindowServer | |
parent | a726fda5461a8ff9ef49e378a6170c1eeddbe02a (diff) | |
download | serenity-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.cpp | 34 | ||||
-rw-r--r-- | Servers/WindowServer/ClientConnection.h | 2 | ||||
-rw-r--r-- | Servers/WindowServer/WindowServer.ipc | 2 |
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) |