diff --git a/Userland/Applications/Browser/Tab.cpp b/Userland/Applications/Browser/Tab.cpp index a947ab05b9..6e888d240e 100644 --- a/Userland/Applications/Browser/Tab.cpp +++ b/Userland/Applications/Browser/Tab.cpp @@ -560,10 +560,10 @@ Tab::Tab(BrowserWindow& window) view().select_dropdown_closed({}); }; - view().on_request_select_dropdown = [this](Gfx::IntPoint content_position, i32, Vector items) { + view().on_request_select_dropdown = [this](Gfx::IntPoint content_position, i32 minimum_width, Vector items) { m_select_dropdown_closed_by_action = false; m_select_dropdown->remove_all_actions(); - // FIXME: Set menu minimum width + m_select_dropdown->set_minimum_width(minimum_width); for (auto const& item : items) { select_dropdown_add_item(*m_select_dropdown, item); } diff --git a/Userland/Libraries/LibGUI/Menu.cpp b/Userland/Libraries/LibGUI/Menu.cpp index c809e6224a..d333011e06 100644 --- a/Userland/Libraries/LibGUI/Menu.cpp +++ b/Userland/Libraries/LibGUI/Menu.cpp @@ -89,6 +89,15 @@ void Menu::set_name(String name) } } +void Menu::set_minimum_width(int minimum_width) +{ + m_minimum_width = minimum_width; + if (m_menu_id != -1) { + ConnectionToWindowServer::the().async_set_menu_minimum_width(m_menu_id, m_minimum_width); + update_parent_menu_item(); + } +} + void Menu::set_parent(Menu& menu, int submenu_index) { m_parent_menu = menu; @@ -141,7 +150,7 @@ int Menu::realize_menu(RefPtr default_action) unrealize_menu(); m_menu_id = s_menu_id_allocator.allocate(); - ConnectionToWindowServer::the().async_create_menu(m_menu_id, m_name); + ConnectionToWindowServer::the().async_create_menu(m_menu_id, m_name, m_minimum_width); dbgln_if(MENU_DEBUG, "GUI::Menu::realize_menu(): New menu ID: {}", m_menu_id); VERIFY(m_menu_id > 0); diff --git a/Userland/Libraries/LibGUI/Menu.h b/Userland/Libraries/LibGUI/Menu.h index 8b2cc50f72..7b716545a4 100644 --- a/Userland/Libraries/LibGUI/Menu.h +++ b/Userland/Libraries/LibGUI/Menu.h @@ -36,6 +36,9 @@ public: String const& name() const { return m_name; } void set_name(String); + int minimum_width() const { return m_minimum_width; } + void set_minimum_width(int); + Gfx::Bitmap const* icon() const { return m_icon.ptr(); } void set_icon(Gfx::Bitmap const*); @@ -81,6 +84,7 @@ private: int m_menu_id { -1 }; String m_name; + int m_minimum_width { 0 }; RefPtr m_icon; Vector> m_items; WeakPtr m_current_default_action; diff --git a/Userland/Services/WindowServer/ConnectionFromClient.cpp b/Userland/Services/WindowServer/ConnectionFromClient.cpp index cfe0a8cf11..a30976012d 100644 --- a/Userland/Services/WindowServer/ConnectionFromClient.cpp +++ b/Userland/Services/WindowServer/ConnectionFromClient.cpp @@ -90,9 +90,9 @@ void ConnectionFromClient::notify_about_new_screen_rects() async_screen_rects_changed(Screen::rects(), Screen::main().index(), wm.window_stack_rows(), wm.window_stack_columns()); } -void ConnectionFromClient::create_menu(i32 menu_id, String const& name) +void ConnectionFromClient::create_menu(i32 menu_id, String const& name, i32 minimum_width) { - auto menu = Menu::construct(this, menu_id, name); + auto menu = Menu::construct(this, menu_id, name, minimum_width); m_menus.set(menu_id, move(menu)); } @@ -117,6 +117,27 @@ void ConnectionFromClient::set_menu_name(i32 menu_id, String const& name) } } +void ConnectionFromClient::set_menu_minimum_width(i32 menu_id, i32 minimum_width) +{ + auto it = m_menus.find(menu_id); + if (it == m_menus.end()) { + did_misbehave("DestroyMenu: Bad menu ID"); + return; + } + auto& menu = *it->value; + menu.set_minimum_width(minimum_width); + for (auto& it : m_windows) { + auto& window = *it.value; + window.menubar().for_each_menu([&](Menu& other_menu) { + if (&menu == &other_menu) { + window.invalidate_menubar(); + return IterationDecision::Break; + } + return IterationDecision::Continue; + }); + } +} + void ConnectionFromClient::destroy_menu(i32 menu_id) { auto it = m_menus.find(menu_id); diff --git a/Userland/Services/WindowServer/ConnectionFromClient.h b/Userland/Services/WindowServer/ConnectionFromClient.h index ef70c71c8d..a3b7ba8bd3 100644 --- a/Userland/Services/WindowServer/ConnectionFromClient.h +++ b/Userland/Services/WindowServer/ConnectionFromClient.h @@ -93,8 +93,9 @@ private: void set_unresponsive(bool); void destroy_window(Window&, Vector& destroyed_window_ids); - virtual void create_menu(i32, String const&) override; + virtual void create_menu(i32, String const&, i32) override; virtual void set_menu_name(i32, String const&) override; + virtual void set_menu_minimum_width(i32, i32) override; virtual void destroy_menu(i32) override; virtual void add_menu(i32, i32) override; virtual void add_menu_item(i32, i32, i32, ByteString const&, bool, bool, bool, bool, bool, ByteString const&, Gfx::ShareableBitmap const&, bool) override; diff --git a/Userland/Services/WindowServer/Menu.cpp b/Userland/Services/WindowServer/Menu.cpp index abd915fa86..738728398f 100644 --- a/Userland/Services/WindowServer/Menu.cpp +++ b/Userland/Services/WindowServer/Menu.cpp @@ -38,11 +38,12 @@ u32 find_ampersand_shortcut_character(StringView string) return 0; } -Menu::Menu(ConnectionFromClient* client, int menu_id, String name) +Menu::Menu(ConnectionFromClient* client, int menu_id, String name, int minimum_width) : Core::EventReceiver(client) , m_client(client) , m_menu_id(menu_id) , m_name(move(name)) + , m_minimum_width(minimum_width) { m_alt_shortcut_character = find_ampersand_shortcut_character(m_name); } @@ -90,7 +91,7 @@ int Menu::content_width() const if (widest_shortcut) widest_item += padding_between_text_and_shortcut() + widest_shortcut; - return max(widest_item, rect_in_window_menubar().width()) + horizontal_padding() + frame_thickness() * 2; + return max(m_minimum_width, max(widest_item, rect_in_window_menubar().width()) + horizontal_padding() + frame_thickness() * 2); } int Menu::item_height() const @@ -770,6 +771,11 @@ void Menu::set_name(String name) m_name = move(name); } +void Menu::set_minimum_width(int minimum_width) +{ + m_minimum_width = minimum_width; +} + bool Menu::is_open() const { return MenuManager::the().is_open(*this); diff --git a/Userland/Services/WindowServer/Menu.h b/Userland/Services/WindowServer/Menu.h index 5b3a76171d..2f12205740 100644 --- a/Userland/Services/WindowServer/Menu.h +++ b/Userland/Services/WindowServer/Menu.h @@ -61,6 +61,9 @@ public: String const& name() const { return m_name; } void set_name(String); + int minimum_width() const { return m_minimum_width; } + void set_minimum_width(int); + template IterationDecision for_each_item(Callback callback) { @@ -138,7 +141,7 @@ public: Vector const* items_with_alt_shortcut(u32 alt_shortcut) const; private: - Menu(ConnectionFromClient*, int menu_id, String name); + Menu(ConnectionFromClient*, int menu_id, String name, int minimum_width = 0); virtual void event(Core::Event&) override; @@ -156,6 +159,7 @@ private: ConnectionFromClient* m_client { nullptr }; int m_menu_id { 0 }; String m_name; + int m_minimum_width { 0 }; u32 m_alt_shortcut_character { 0 }; Gfx::IntRect m_rect_in_window_menubar; Gfx::IntPoint m_unadjusted_position; diff --git a/Userland/Services/WindowServer/WindowServer.ipc b/Userland/Services/WindowServer/WindowServer.ipc index 12a26d56c7..d422aaa1c1 100644 --- a/Userland/Services/WindowServer/WindowServer.ipc +++ b/Userland/Services/WindowServer/WindowServer.ipc @@ -4,8 +4,9 @@ endpoint WindowServer { - create_menu(i32 menu_id, [UTF8] String name) =| + create_menu(i32 menu_id, [UTF8] String name, i32 minimum_width) =| set_menu_name(i32 menu_id, String name) =| + set_menu_minimum_width(i32 menu_id, i32 minimum_width) =| destroy_menu(i32 menu_id) =| add_menu(i32 window_id, i32 menu_id) =|