LibGUI+WindowServer: Inform WindowServer about parent/child windows

If a window has another window in its Core::Object ancestor chain,
we now communicate that relationship to WindowServer so that it can
act with awareness of parent/child windows.
This commit is contained in:
Andreas Kling 2020-05-01 22:59:38 +02:00
parent e9b7a51a9a
commit 6228f72b87
Notes: sideshowbarker 2024-07-19 07:07:28 +09:00
7 changed files with 63 additions and 2 deletions

View file

@ -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())

View file

@ -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&);

View file

@ -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()) {

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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) => ()