From 9e04ab936ff7881485848d99a2a6483bff2f3e4a Mon Sep 17 00:00:00 2001 From: Timothy Date: Sat, 17 Jul 2021 10:41:36 +1000 Subject: [PATCH] WindowServer: Let clients mark windows as stealable by specific clients This implements window stealing in WindowServer, which allows clients to mark a window they own as 'stealable' by another client. Indicating that the other client may use it for any purpose. This also updates set_window_parent_from_id so that the client must first mark its window as stealable before allowing other clients to use it as a parent. --- .../WindowServer/ClientConnection.cpp | 38 ++++++++++++++++++- .../Services/WindowServer/ClientConnection.h | 3 ++ Userland/Services/WindowServer/Window.h | 11 ++++++ .../Services/WindowServer/WindowServer.ipc | 3 ++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/Userland/Services/WindowServer/ClientConnection.cpp b/Userland/Services/WindowServer/ClientConnection.cpp index b6edb95a5b7..c4dc7b563a4 100644 --- a/Userland/Services/WindowServer/ClientConnection.cpp +++ b/Userland/Services/WindowServer/ClientConnection.cpp @@ -1129,7 +1129,11 @@ void ClientConnection::set_window_parent_from_client(i32 client_id, i32 parent_i if (!parent_window) did_misbehave("SetWindowParentFromClient: Bad parent window ID"); - child_window->set_parent_window(*parent_window); + if (parent_window->is_stealable_by_client(this->client_id())) { + child_window->set_parent_window(*parent_window); + } else { + did_misbehave("SetWindowParentFromClient: Window is not stealable"); + } } Messages::WindowServer::GetWindowRectFromClientResponse ClientConnection::get_window_rect_from_client(i32 client_id, i32 window_id) @@ -1145,4 +1149,36 @@ Messages::WindowServer::GetWindowRectFromClientResponse ClientConnection::get_wi return window->rect(); } +void ClientConnection::add_window_stealing_for_client(i32 client_id, i32 window_id) +{ + auto window = window_from_id(window_id); + if (!window) + did_misbehave("AddWindowStealingForClient: Bad window ID"); + + if (!from_client_id(client_id)) + did_misbehave("AddWindowStealingForClient: Bad client ID"); + + window->add_stealing_for_client(client_id); +} + +void ClientConnection::remove_window_stealing_for_client(i32 client_id, i32 window_id) +{ + auto window = window_from_id(window_id); + if (!window) + did_misbehave("RemoveWindowStealingForClient: Bad window ID"); + + // Don't check if the client exists, it may have died + + window->remove_stealing_for_client(client_id); +} + +void ClientConnection::remove_window_stealing(i32 window_id) +{ + auto window = window_from_id(window_id); + if (!window) + did_misbehave("RemoveWindowStealing: Bad window ID"); + + window->remove_all_stealing(); +} + } diff --git a/Userland/Services/WindowServer/ClientConnection.h b/Userland/Services/WindowServer/ClientConnection.h index 8967d41ef9f..74c0f29c329 100644 --- a/Userland/Services/WindowServer/ClientConnection.h +++ b/Userland/Services/WindowServer/ClientConnection.h @@ -166,6 +166,9 @@ private: virtual void set_flash_flush(bool) override; virtual void set_window_parent_from_client(i32, i32, i32) override; virtual Messages::WindowServer::GetWindowRectFromClientResponse get_window_rect_from_client(i32, i32) override; + virtual void add_window_stealing_for_client(i32, i32) override; + virtual void remove_window_stealing_for_client(i32, i32) override; + virtual void remove_window_stealing(i32) override; Window* window_from_id(i32 window_id); diff --git a/Userland/Services/WindowServer/Window.h b/Userland/Services/WindowServer/Window.h index 8c473c702f6..b74ca9732a2 100644 --- a/Userland/Services/WindowServer/Window.h +++ b/Userland/Services/WindowServer/Window.h @@ -362,6 +362,16 @@ public: void set_moving_to_another_stack(bool value) { m_moving_to_another_stack = value; } bool is_moving_to_another_stack() const { return m_moving_to_another_stack; } + void add_stealing_for_client(i32 client_id) { m_stealable_by_client_ids.append(move(client_id)); } + void remove_stealing_for_client(i32 client_id) + { + m_stealable_by_client_ids.remove_all_matching([client_id](i32 approved_client_id) { + return approved_client_id == client_id; + }); + } + void remove_all_stealing() { m_stealable_by_client_ids.clear(); } + bool is_stealable_by_client(i32 client_id) const { return m_stealable_by_client_ids.contains_slow(client_id); } + private: Window(ClientConnection&, WindowType, int window_id, bool modal, bool minimizable, bool frameless, bool resizable, bool fullscreen, bool accessory, Window* parent_window = nullptr); Window(Core::Object&, WindowType); @@ -418,6 +428,7 @@ private: bool m_pinned { false }; bool m_moving_to_another_stack { false }; bool m_invalidate_last_render_rects { false }; + Vector m_stealable_by_client_ids; WindowTileType m_tiled { WindowTileType::None }; Gfx::IntRect m_untiled_rect; bool m_occluded { false }; diff --git a/Userland/Services/WindowServer/WindowServer.ipc b/Userland/Services/WindowServer/WindowServer.ipc index 7a24f47d2a1..38bf959770d 100644 --- a/Userland/Services/WindowServer/WindowServer.ipc +++ b/Userland/Services/WindowServer/WindowServer.ipc @@ -150,4 +150,7 @@ endpoint WindowServer set_window_parent_from_client(i32 client_id, i32 parent_id, i32 child_id) =| get_window_rect_from_client(i32 client_id, i32 window_id) => (Gfx::IntRect rect) + add_window_stealing_for_client(i32 client_id, i32 window_id) =| + remove_window_stealing_for_client(i32 client_id, i32 window_id) =| + remove_window_stealing(i32 window_id) =| }