summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Libraries/LibGUI/Window.cpp15
-rw-r--r--Libraries/LibGUI/Window.h2
-rw-r--r--Servers/WindowServer/ClientConnection.cpp20
-rw-r--r--Servers/WindowServer/ClientConnection.h2
-rw-r--r--Servers/WindowServer/Window.cpp12
-rw-r--r--Servers/WindowServer/Window.h11
-rw-r--r--Servers/WindowServer/WindowServer.ipc3
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) => ()