diff options
-rw-r--r-- | Libraries/LibGUI/Window.cpp | 15 | ||||
-rw-r--r-- | Libraries/LibGUI/Window.h | 2 | ||||
-rw-r--r-- | Servers/WindowServer/ClientConnection.cpp | 20 | ||||
-rw-r--r-- | Servers/WindowServer/ClientConnection.h | 2 | ||||
-rw-r--r-- | Servers/WindowServer/Window.cpp | 12 | ||||
-rw-r--r-- | Servers/WindowServer/Window.h | 11 | ||||
-rw-r--r-- | Servers/WindowServer/WindowServer.ipc | 3 |
7 files changed, 63 insertions, 2 deletions
diff --git a/Libraries/LibGUI/Window.cpp b/Libraries/LibGUI/Window.cpp index ead7ba78fa..60d80d938e 100644 --- a/Libraries/LibGUI/Window.cpp +++ b/Libraries/LibGUI/Window.cpp @@ -89,6 +89,9 @@ void Window::show() { if (is_visible()) return; + + auto* parent_window = find_parent_window(); + m_override_cursor = StandardCursor::None; auto response = WindowServerConnection::the().send_sync<Messages::WindowServer::CreateWindow>( m_rect_when_windowless, @@ -102,7 +105,8 @@ void Window::show() m_base_size, m_size_increment, (i32)m_window_type, - m_title_when_windowless); + m_title_when_windowless, + parent_window ? parent_window->window_id() : 0); m_window_id = response->window_id(); m_visible = true; @@ -113,6 +117,15 @@ void Window::show() update(); } +Window* Window::find_parent_window() +{ + for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) { + if (ancestor->is_window()) + return static_cast<Window*>(ancestor); + } + return nullptr; +} + void Window::hide() { if (!is_visible()) diff --git a/Libraries/LibGUI/Window.h b/Libraries/LibGUI/Window.h index 59d20a1bcd..20f20eac71 100644 --- a/Libraries/LibGUI/Window.h +++ b/Libraries/LibGUI/Window.h @@ -182,6 +182,8 @@ public: void did_remove_widget(Badge<Widget>, const Widget&); + Window* find_parent_window(); + protected: Window(Core::Object* parent = nullptr); virtual void wm_event(WMEvent&); diff --git a/Servers/WindowServer/ClientConnection.cpp b/Servers/WindowServer/ClientConnection.cpp index c951754350..6b79c33bb5 100644 --- a/Servers/WindowServer/ClientConnection.cpp +++ b/Servers/WindowServer/ClientConnection.cpp @@ -451,10 +451,30 @@ OwnPtr<Messages::WindowServer::GetClipboardContentsResponse> ClientConnection::h return make<Messages::WindowServer::GetClipboardContentsResponse>(shbuf_id, clipboard.size(), clipboard.data_type()); } +Window* ClientConnection::window_from_id(i32 window_id) +{ + auto it = m_windows.find(window_id); + if (it == m_windows.end()) + return nullptr; + return it->value.ptr(); +} + OwnPtr<Messages::WindowServer::CreateWindowResponse> ClientConnection::handle(const Messages::WindowServer::CreateWindow& message) { int window_id = m_next_window_id++; auto window = Window::construct(*this, (WindowType)message.type(), window_id, message.modal(), message.minimizable(), message.resizable(), message.fullscreen()); + + dbg() << "Constructing window with parent_window_id=" << message.parent_window_id(); + + if (message.parent_window_id()) { + auto* parent_window = window_from_id(message.parent_window_id()); + if (!parent_window) { + did_misbehave("CreateWindow with bad parent_window_id"); + return nullptr; + } + window->set_parent_window(*parent_window); + } + window->set_has_alpha_channel(message.has_alpha_channel()); window->set_title(message.title()); if (!message.fullscreen()) { diff --git a/Servers/WindowServer/ClientConnection.h b/Servers/WindowServer/ClientConnection.h index ebbcb3d282..1c11bb2711 100644 --- a/Servers/WindowServer/ClientConnection.h +++ b/Servers/WindowServer/ClientConnection.h @@ -127,6 +127,8 @@ private: virtual void handle(const Messages::WindowServer::EnableDisplayLink&) override; virtual void handle(const Messages::WindowServer::DisableDisplayLink&) override; + Window* window_from_id(i32 window_id); + HashMap<int, NonnullRefPtr<Window>> m_windows; HashMap<int, NonnullOwnPtr<MenuBar>> m_menubars; HashMap<int, NonnullRefPtr<Menu>> m_menus; diff --git a/Servers/WindowServer/Window.cpp b/Servers/WindowServer/Window.cpp index 2bc92c35b3..84fcc92a22 100644 --- a/Servers/WindowServer/Window.cpp +++ b/Servers/WindowServer/Window.cpp @@ -482,4 +482,16 @@ void Window::recalculate_rect() Core::EventLoop::current().post_event(*this, make<ResizeEvent>(old_rect, m_rect)); } +void Window::add_child_window(Window& child_window) +{ + m_child_windows.append(child_window.make_weak_ptr()); +} + +void Window::set_parent_window(Window& parent_window) +{ + ASSERT(!m_parent_window); + m_parent_window = parent_window.make_weak_ptr(); + parent_window.add_child_window(*this); +} + } diff --git a/Servers/WindowServer/Window.h b/Servers/WindowServer/Window.h index ce796b602f..71e8d6bfc0 100644 --- a/Servers/WindowServer/Window.h +++ b/Servers/WindowServer/Window.h @@ -28,6 +28,7 @@ #include <AK/InlineLinkedList.h> #include <AK/String.h> +#include <AK/WeakPtr.h> #include <LibCore/Object.h> #include <LibGfx/Bitmap.h> #include <LibGfx/DisjointRectSet.h> @@ -229,12 +230,22 @@ public: void detach_client(Badge<ClientConnection>); + Window* parent_window() { return m_parent_window; } + const Window* parent_window() const { return m_parent_window; } + + void set_parent_window(Window&); + private: void handle_mouse_event(const MouseEvent&); void update_menu_item_text(PopupMenuItem item); void update_menu_item_enabled(PopupMenuItem item); + void add_child_window(Window&); ClientConnection* m_client { nullptr }; + + WeakPtr<Window> m_parent_window; + Vector<WeakPtr<Window>> m_child_windows; + String m_title; Gfx::Rect m_rect; Gfx::Rect m_saved_nonfullscreen_rect; diff --git a/Servers/WindowServer/WindowServer.ipc b/Servers/WindowServer/WindowServer.ipc index ab73161f90..34d9e8db6c 100644 --- a/Servers/WindowServer/WindowServer.ipc +++ b/Servers/WindowServer/WindowServer.ipc @@ -41,7 +41,8 @@ endpoint WindowServer = 2 Gfx::Size base_size, Gfx::Size size_increment, i32 type, - String title) => (i32 window_id) + String title, + i32 parent_window_id) => (i32 window_id) DestroyWindow(i32 window_id) => () |