Browser+LibGUI+WindowServer: Open Button menus uniformly

Instead of letting buttons determine the relative position
of their menus, a workaround only used by Statusbar segments,
open them all uniformly for a nice, consistent UI.

Passing a rect to popup() now routes to open_button_menu(), an
analog to open_menubar_menu(), which adjusts the menu's popup
position in the same way. Fixes button menus obscuring the buttons
which spawn them and jutting out at odd corners depending on screen
position.
This commit is contained in:
thankyouverycool 2022-09-04 19:48:37 -04:00 committed by Linus Groh
parent 0fc1925cd7
commit 35e557c657
Notes: sideshowbarker 2024-07-17 07:21:35 +09:00
12 changed files with 34 additions and 31 deletions

View file

@ -112,7 +112,6 @@ BookmarksBarWidget::BookmarksBarWidget(String const& bookmarks_file, bool enable
m_additional = GUI::Button::construct();
m_additional->set_tooltip("Show hidden bookmarks");
m_additional->set_menu(m_additional_menu);
m_additional->set_menu_position(GUI::Button::MenuPosition::BottomLeft);
auto bitmap_or_error = Gfx::Bitmap::try_load_from_file("/res/icons/16x16/overflow-menu.png"sv);
if (!bitmap_or_error.is_error())
m_additional->set_icon(bitmap_or_error.release_value());

View file

@ -215,22 +215,7 @@ void Button::set_menu(RefPtr<GUI::Menu> menu)
void Button::mousedown_event(MouseEvent& event)
{
if (m_menu) {
switch (m_menu_position) {
case TopLeft:
m_menu->popup(screen_relative_rect().top_left());
break;
case TopRight:
m_menu->popup(screen_relative_rect().top_right());
break;
case BottomLeft:
m_menu->popup(screen_relative_rect().bottom_left());
break;
case BottomRight:
m_menu->popup(screen_relative_rect().bottom_right());
break;
default:
VERIFY_NOT_REACHED();
}
m_menu->popup(screen_relative_rect().bottom_left(), {}, rect());
update();
return;
}

View file

@ -66,9 +66,6 @@ public:
void set_mimic_pressed(bool mimic_pressed);
bool is_mimic_pressed() const { return m_mimic_pressed; };
MenuPosition menu_position() const { return m_menu_position; }
void set_menu_position(MenuPosition position) { m_menu_position = position; }
virtual Optional<UISize> calculated_min_size() const override;
protected:
@ -88,7 +85,6 @@ private:
int m_icon_spacing { 4 };
bool m_another_button_has_focus { false };
bool m_mimic_pressed { false };
MenuPosition m_menu_position { MenuPosition::TopLeft };
};
class DialogButton final : public Button {

View file

@ -116,10 +116,10 @@ void Menu::realize_if_needed(RefPtr<Action> const& default_action)
realize_menu(default_action);
}
void Menu::popup(Gfx::IntPoint const& screen_position, RefPtr<Action> const& default_action)
void Menu::popup(Gfx::IntPoint const& screen_position, RefPtr<Action> const& default_action, Gfx::IntRect const& button_rect)
{
realize_if_needed(default_action);
ConnectionToWindowServer::the().async_popup_menu(m_menu_id, screen_position);
ConnectionToWindowServer::the().async_popup_menu(m_menu_id, screen_position, button_rect);
}
void Menu::dismiss()

View file

@ -41,7 +41,7 @@ public:
Menu& add_submenu(String name);
void remove_all_actions();
void popup(Gfx::IntPoint const& screen_position, RefPtr<Action> const& default_action = nullptr);
void popup(Gfx::IntPoint const& screen_position, RefPtr<Action> const& default_action = nullptr, Gfx::IntRect const& button_rect = {});
void dismiss();
void visibility_did_change(Badge<ConnectionToWindowServer>, bool visible);

View file

@ -146,7 +146,6 @@ Statusbar::Segment::Segment()
set_focus_policy(GUI::FocusPolicy::NoFocus);
set_button_style(Gfx::ButtonStyle::Tray);
set_text_alignment(Gfx::TextAlignment::CenterLeft);
set_menu_position(GUI::Button::MenuPosition::TopRight);
}
void Statusbar::Segment::paint_event(PaintEvent& event)

View file

@ -159,7 +159,7 @@ Optional<UISize> Toolbar::calculated_min_size() const
ErrorOr<void> Toolbar::create_overflow_objects()
{
m_overflow_action = Action::create("Overflow Menu", { Mod_Ctrl | Mod_Shift, Key_O }, TRY(Gfx::Bitmap::try_load_from_file("/res/icons/16x16/overflow-menu.png"sv)), [&](auto&) {
m_overflow_menu->popup(m_overflow_button->screen_relative_rect().bottom_left());
m_overflow_menu->popup(m_overflow_button->screen_relative_rect().bottom_left(), {}, m_overflow_button->rect());
});
m_overflow_action->set_status_tip("Show hidden toolbar actions");
m_overflow_action->set_enabled(false);
@ -168,7 +168,6 @@ ErrorOr<void> Toolbar::create_overflow_objects()
m_overflow_button = TRY(try_add_action(*m_overflow_action));
m_overflow_button->set_visible(false);
m_overflow_button->set_menu_position(Button::MenuPosition::BottomLeft);
return {};
}

View file

@ -145,7 +145,7 @@ void ConnectionFromClient::add_menu_item(i32 menu_id, i32 identifier, i32 submen
menu.add_item(move(menu_item));
}
void ConnectionFromClient::popup_menu(i32 menu_id, Gfx::IntPoint const& screen_position)
void ConnectionFromClient::popup_menu(i32 menu_id, Gfx::IntPoint const& screen_position, Gfx::IntRect const& button_rect)
{
auto position = screen_position;
auto it = m_menus.find(menu_id);
@ -154,7 +154,10 @@ void ConnectionFromClient::popup_menu(i32 menu_id, Gfx::IntPoint const& screen_p
return;
}
auto& menu = *(*it).value;
menu.popup(position);
if (!button_rect.is_null())
menu.open_button_menu(position, button_rect);
else
menu.popup(position);
}
void ConnectionFromClient::dismiss_menu(i32 menu_id)

View file

@ -138,7 +138,7 @@ private:
virtual void show_screen_numbers(bool) override;
virtual void set_window_cursor(i32, i32) override;
virtual void set_window_custom_cursor(i32, Gfx::ShareableBitmap const&) override;
virtual void popup_menu(i32, Gfx::IntPoint const&) override;
virtual void popup_menu(i32, Gfx::IntPoint const&, Gfx::IntRect const&) override;
virtual void dismiss_menu(i32) override;
virtual void set_window_icon_bitmap(i32, Gfx::ShareableBitmap const&) override;
virtual Messages::WindowServer::StartDragResponse start_drag(String const&, HashMap<String, ByteBuffer> const&, Gfx::ShareableBitmap const&) override;

View file

@ -597,6 +597,27 @@ void Menu::redraw_if_theme_changed()
redraw();
}
void Menu::open_button_menu(Gfx::IntPoint const& position, Gfx::IntRect const& button_rect)
{
if (is_empty())
return;
auto& screen = Screen::closest_to_location(position);
auto& window = ensure_menu_window(position);
Gfx::IntPoint adjusted_pos = position;
if (window.rect().right() > screen.width())
adjusted_pos = adjusted_pos.translated(-(window.rect().right() - screen.width()) - 1, 0);
if (window.rect().bottom() > screen.height())
adjusted_pos = adjusted_pos.translated(0, -window.rect().height() - button_rect.height() + 1);
window.set_rect(adjusted_pos.x(), adjusted_pos.y(), window.rect().width(), window.rect().height());
window.move_to(adjusted_pos);
MenuManager::the().open_menu(*this, true);
WindowManager::the().did_popup_a_menu({});
}
void Menu::popup(Gfx::IntPoint const& position)
{
do_popup(position, true);

View file

@ -115,6 +115,7 @@ public:
void popup(Gfx::IntPoint const&);
void do_popup(Gfx::IntPoint const&, bool make_input, bool as_submenu = false);
void open_button_menu(Gfx::IntPoint const& position, Gfx::IntRect const& button_rect);
bool is_menu_ancestor_of(Menu const&) const;

View file

@ -100,7 +100,7 @@ endpoint WindowServer
set_fullscreen(i32 window_id, bool fullscreen) =|
set_frameless(i32 window_id, bool frameless) =|
set_forced_shadow(i32 window_id, bool shadow) =|
popup_menu(i32 menu_id, Gfx::IntPoint screen_position) =|
popup_menu(i32 menu_id, Gfx::IntPoint screen_position, Gfx::IntRect button_rect) =|
dismiss_menu(i32 menu_id) =|
set_wallpaper(Gfx::ShareableBitmap wallpaper_bitmap) => (bool success)