diff options
author | Andreas Kling <kling@serenityos.org> | 2021-04-05 14:32:34 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-04-05 18:09:04 +0200 |
commit | 9b740f218b103a5f3497a666b2655865266c8ff1 (patch) | |
tree | 6f94769e391237b36a57868c553458c21298fe62 /Userland | |
parent | 03157418159c75c03d0bf94108e9f6d9053835bf (diff) | |
download | serenity-9b740f218b103a5f3497a666b2655865266c8ff1.zip |
WindowServer+LibGUI: Notify clients when menus become visible/hidden
This will allow clients to react to these events.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibGUI/Menu.cpp | 9 | ||||
-rw-r--r-- | Userland/Libraries/LibGUI/Menu.h | 7 | ||||
-rw-r--r-- | Userland/Libraries/LibGUI/WindowServerConnection.cpp | 10 | ||||
-rw-r--r-- | Userland/Libraries/LibGUI/WindowServerConnection.h | 3 | ||||
-rw-r--r-- | Userland/Services/WindowServer/Menu.cpp | 18 | ||||
-rw-r--r-- | Userland/Services/WindowServer/Menu.h | 2 | ||||
-rw-r--r-- | Userland/Services/WindowServer/MenuManager.cpp | 8 | ||||
-rw-r--r-- | Userland/Services/WindowServer/WindowClient.ipc | 1 |
8 files changed, 49 insertions, 9 deletions
diff --git a/Userland/Libraries/LibGUI/Menu.cpp b/Userland/Libraries/LibGUI/Menu.cpp index d3a4da4b57..14534d3c9c 100644 --- a/Userland/Libraries/LibGUI/Menu.cpp +++ b/Userland/Libraries/LibGUI/Menu.cpp @@ -162,4 +162,13 @@ Action* Menu::action_at(size_t index) return m_items[index].action(); } +void Menu::visibility_did_change(Badge<WindowServerConnection>, bool visible) +{ + if (m_visible == visible) + return; + m_visible = visible; + if (on_visibility_change) + on_visibility_change(visible); +} + } diff --git a/Userland/Libraries/LibGUI/Menu.h b/Userland/Libraries/LibGUI/Menu.h index 1031112830..9d03823e2c 100644 --- a/Userland/Libraries/LibGUI/Menu.h +++ b/Userland/Libraries/LibGUI/Menu.h @@ -59,6 +59,12 @@ public: void popup(const Gfx::IntPoint& screen_position, const RefPtr<Action>& default_action = nullptr); void dismiss(); + void visibility_did_change(Badge<WindowServerConnection>, bool visible); + + Function<void(bool)> on_visibility_change; + + bool is_visible() const { return m_visible; } + private: friend class MenuBar; @@ -71,6 +77,7 @@ private: RefPtr<Gfx::Bitmap> m_icon; NonnullOwnPtrVector<MenuItem> m_items; WeakPtr<Action> m_last_default_action; + bool m_visible { false }; }; } diff --git a/Userland/Libraries/LibGUI/WindowServerConnection.cpp b/Userland/Libraries/LibGUI/WindowServerConnection.cpp index 5ce4fad6a4..563b50cfe5 100644 --- a/Userland/Libraries/LibGUI/WindowServerConnection.cpp +++ b/Userland/Libraries/LibGUI/WindowServerConnection.cpp @@ -252,6 +252,16 @@ void WindowServerConnection::handle(const Messages::WindowClient::MouseWheel& me Core::EventLoop::current().post_event(*window, make<MouseEvent>(Event::MouseWheel, message.mouse_position(), message.buttons(), to_gmousebutton(message.button()), message.modifiers(), message.wheel_delta())); } +void WindowServerConnection::handle(const Messages::WindowClient::MenuVisibilityDidChange& message) +{ + auto* menu = Menu::from_menu_id(message.menu_id()); + if (!menu) { + dbgln("EventLoop received visibility change event for invalid menu ID {}", message.menu_id()); + return; + } + menu->visibility_did_change({}, message.visible()); +} + void WindowServerConnection::handle(const Messages::WindowClient::MenuItemActivated& message) { auto* menu = Menu::from_menu_id(message.menu_id()); diff --git a/Userland/Libraries/LibGUI/WindowServerConnection.h b/Userland/Libraries/LibGUI/WindowServerConnection.h index 4e9a29e649..20e9cff10b 100644 --- a/Userland/Libraries/LibGUI/WindowServerConnection.h +++ b/Userland/Libraries/LibGUI/WindowServerConnection.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -64,6 +64,7 @@ private: virtual void handle(const Messages::WindowClient::WindowCloseRequest&) override; virtual void handle(const Messages::WindowClient::WindowResized&) override; virtual void handle(const Messages::WindowClient::MenuItemActivated&) override; + virtual void handle(const Messages::WindowClient::MenuVisibilityDidChange&) override; virtual void handle(const Messages::WindowClient::ScreenRectChanged&) override; virtual void handle(const Messages::WindowClient::WM_WindowRemoved&) override; virtual void handle(const Messages::WindowClient::WM_WindowStateChanged&) override; diff --git a/Userland/Services/WindowServer/Menu.cpp b/Userland/Services/WindowServer/Menu.cpp index c30a0b81e9..7980d3810a 100644 --- a/Userland/Services/WindowServer/Menu.cpp +++ b/Userland/Services/WindowServer/Menu.cpp @@ -151,10 +151,10 @@ Window& Menu::ensure_menu_window() } auto window = Window::construct(*this, WindowType::Menu); + window->set_visible(false); window->set_rect(0, 0, width, window_height); m_menu_window = move(window); draw(); - return *m_menu_window; } @@ -291,7 +291,8 @@ void Menu::update_for_new_hovered_item(bool make_input) hovered_item()->submenu()->do_popup(hovered_item()->rect().top_right().translated(menu_window()->rect().location()), make_input, true); } else { MenuManager::the().close_everyone_not_in_lineage(*this); - ensure_menu_window().set_visible(true); + ensure_menu_window(); + set_visible(true); } redraw(); } @@ -593,7 +594,7 @@ void Menu::do_popup(const Gfx::IntPoint& position, bool make_input, bool as_subm } window.move_to(adjusted_pos); - window.set_visible(true); + set_visible(true); MenuManager::the().open_menu(*this, make_input); WindowManager::the().did_popup_a_menu({}); } @@ -612,4 +613,15 @@ bool Menu::is_menu_ancestor_of(const Menu& other) const return false; } +void Menu::set_visible(bool visible) +{ + if (!menu_window()) + return; + if (visible == menu_window()->is_visible()) + return; + menu_window()->set_visible(visible); + if (m_client) + m_client->post_message(Messages::WindowClient::MenuVisibilityDidChange(m_menu_id, visible)); +} + } diff --git a/Userland/Services/WindowServer/Menu.h b/Userland/Services/WindowServer/Menu.h index 9ef4cc34ae..c438cf270c 100644 --- a/Userland/Services/WindowServer/Menu.h +++ b/Userland/Services/WindowServer/Menu.h @@ -111,6 +111,8 @@ public: void close(); + void set_visible(bool); + void popup(const Gfx::IntPoint&); void do_popup(const Gfx::IntPoint&, bool make_input, bool as_submenu = false); diff --git a/Userland/Services/WindowServer/MenuManager.cpp b/Userland/Services/WindowServer/MenuManager.cpp index 77b1799018..cdff3a0460 100644 --- a/Userland/Services/WindowServer/MenuManager.cpp +++ b/Userland/Services/WindowServer/MenuManager.cpp @@ -242,8 +242,7 @@ void MenuManager::close_everyone() { for (auto& menu : m_open_menu_stack) { VERIFY(menu); - if (menu->menu_window()) - menu->menu_window()->set_visible(false); + menu->set_visible(false); menu->clear_hovered_item(); } m_open_menu_stack.clear(); @@ -270,8 +269,7 @@ void MenuManager::close_menus(const Vector<Menu*>& menus) for (auto& menu : menus) { if (menu == m_current_menu) clear_current_menu(); - if (menu->menu_window()) - menu->menu_window()->set_visible(false); + menu->set_visible(false); menu->clear_hovered_item(); m_open_menu_stack.remove_first_matching([&](auto& entry) { return entry == menu; @@ -332,7 +330,7 @@ void MenuManager::open_menu(Menu& menu, bool as_current_menu) menu.redraw_if_theme_changed(); if (!menu.menu_window()) menu.ensure_menu_window(); - menu.menu_window()->set_visible(true); + menu.set_visible(true); } if (m_open_menu_stack.find_if([&menu](auto& other) { return &menu == other.ptr(); }).is_end()) diff --git a/Userland/Services/WindowServer/WindowClient.ipc b/Userland/Services/WindowServer/WindowClient.ipc index f3a771148c..49e3b6ffb8 100644 --- a/Userland/Services/WindowServer/WindowClient.ipc +++ b/Userland/Services/WindowServer/WindowClient.ipc @@ -19,6 +19,7 @@ endpoint WindowClient = 4 WindowResized(i32 window_id, Gfx::IntRect new_rect) =| MenuItemActivated(i32 menu_id, i32 identifier) =| + MenuVisibilityDidChange(i32 menu_id, bool visible) =| ScreenRectChanged(Gfx::IntRect rect) =| |