mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 09:30:24 +00:00
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:
parent
0fc1925cd7
commit
35e557c657
Notes:
sideshowbarker
2024-07-17 07:21:35 +09:00
Author: https://github.com/thankyouverycool Commit: https://github.com/SerenityOS/serenity/commit/35e557c657 Pull-request: https://github.com/SerenityOS/serenity/pull/15158
12 changed files with 34 additions and 31 deletions
|
@ -112,7 +112,6 @@ BookmarksBarWidget::BookmarksBarWidget(String const& bookmarks_file, bool enable
|
||||||
m_additional = GUI::Button::construct();
|
m_additional = GUI::Button::construct();
|
||||||
m_additional->set_tooltip("Show hidden bookmarks");
|
m_additional->set_tooltip("Show hidden bookmarks");
|
||||||
m_additional->set_menu(m_additional_menu);
|
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);
|
auto bitmap_or_error = Gfx::Bitmap::try_load_from_file("/res/icons/16x16/overflow-menu.png"sv);
|
||||||
if (!bitmap_or_error.is_error())
|
if (!bitmap_or_error.is_error())
|
||||||
m_additional->set_icon(bitmap_or_error.release_value());
|
m_additional->set_icon(bitmap_or_error.release_value());
|
||||||
|
|
|
@ -215,22 +215,7 @@ void Button::set_menu(RefPtr<GUI::Menu> menu)
|
||||||
void Button::mousedown_event(MouseEvent& event)
|
void Button::mousedown_event(MouseEvent& event)
|
||||||
{
|
{
|
||||||
if (m_menu) {
|
if (m_menu) {
|
||||||
switch (m_menu_position) {
|
m_menu->popup(screen_relative_rect().bottom_left(), {}, rect());
|
||||||
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();
|
|
||||||
}
|
|
||||||
update();
|
update();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,9 +66,6 @@ public:
|
||||||
void set_mimic_pressed(bool mimic_pressed);
|
void set_mimic_pressed(bool mimic_pressed);
|
||||||
bool is_mimic_pressed() const { return m_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;
|
virtual Optional<UISize> calculated_min_size() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -88,7 +85,6 @@ private:
|
||||||
int m_icon_spacing { 4 };
|
int m_icon_spacing { 4 };
|
||||||
bool m_another_button_has_focus { false };
|
bool m_another_button_has_focus { false };
|
||||||
bool m_mimic_pressed { false };
|
bool m_mimic_pressed { false };
|
||||||
MenuPosition m_menu_position { MenuPosition::TopLeft };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DialogButton final : public Button {
|
class DialogButton final : public Button {
|
||||||
|
|
|
@ -116,10 +116,10 @@ void Menu::realize_if_needed(RefPtr<Action> const& default_action)
|
||||||
realize_menu(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);
|
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()
|
void Menu::dismiss()
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
Menu& add_submenu(String name);
|
Menu& add_submenu(String name);
|
||||||
void remove_all_actions();
|
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 dismiss();
|
||||||
|
|
||||||
void visibility_did_change(Badge<ConnectionToWindowServer>, bool visible);
|
void visibility_did_change(Badge<ConnectionToWindowServer>, bool visible);
|
||||||
|
|
|
@ -146,7 +146,6 @@ Statusbar::Segment::Segment()
|
||||||
set_focus_policy(GUI::FocusPolicy::NoFocus);
|
set_focus_policy(GUI::FocusPolicy::NoFocus);
|
||||||
set_button_style(Gfx::ButtonStyle::Tray);
|
set_button_style(Gfx::ButtonStyle::Tray);
|
||||||
set_text_alignment(Gfx::TextAlignment::CenterLeft);
|
set_text_alignment(Gfx::TextAlignment::CenterLeft);
|
||||||
set_menu_position(GUI::Button::MenuPosition::TopRight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Statusbar::Segment::paint_event(PaintEvent& event)
|
void Statusbar::Segment::paint_event(PaintEvent& event)
|
||||||
|
|
|
@ -159,7 +159,7 @@ Optional<UISize> Toolbar::calculated_min_size() const
|
||||||
ErrorOr<void> Toolbar::create_overflow_objects()
|
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_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_status_tip("Show hidden toolbar actions");
|
||||||
m_overflow_action->set_enabled(false);
|
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 = TRY(try_add_action(*m_overflow_action));
|
||||||
m_overflow_button->set_visible(false);
|
m_overflow_button->set_visible(false);
|
||||||
m_overflow_button->set_menu_position(Button::MenuPosition::BottomLeft);
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,7 @@ void ConnectionFromClient::add_menu_item(i32 menu_id, i32 identifier, i32 submen
|
||||||
menu.add_item(move(menu_item));
|
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 position = screen_position;
|
||||||
auto it = m_menus.find(menu_id);
|
auto it = m_menus.find(menu_id);
|
||||||
|
@ -154,7 +154,10 @@ void ConnectionFromClient::popup_menu(i32 menu_id, Gfx::IntPoint const& screen_p
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& menu = *(*it).value;
|
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)
|
void ConnectionFromClient::dismiss_menu(i32 menu_id)
|
||||||
|
|
|
@ -138,7 +138,7 @@ private:
|
||||||
virtual void show_screen_numbers(bool) override;
|
virtual void show_screen_numbers(bool) override;
|
||||||
virtual void set_window_cursor(i32, i32) override;
|
virtual void set_window_cursor(i32, i32) override;
|
||||||
virtual void set_window_custom_cursor(i32, Gfx::ShareableBitmap const&) 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 dismiss_menu(i32) override;
|
||||||
virtual void set_window_icon_bitmap(i32, Gfx::ShareableBitmap const&) 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;
|
virtual Messages::WindowServer::StartDragResponse start_drag(String const&, HashMap<String, ByteBuffer> const&, Gfx::ShareableBitmap const&) override;
|
||||||
|
|
|
@ -597,6 +597,27 @@ void Menu::redraw_if_theme_changed()
|
||||||
redraw();
|
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)
|
void Menu::popup(Gfx::IntPoint const& position)
|
||||||
{
|
{
|
||||||
do_popup(position, true);
|
do_popup(position, true);
|
||||||
|
|
|
@ -115,6 +115,7 @@ public:
|
||||||
|
|
||||||
void popup(Gfx::IntPoint const&);
|
void popup(Gfx::IntPoint const&);
|
||||||
void do_popup(Gfx::IntPoint const&, bool make_input, bool as_submenu = false);
|
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;
|
bool is_menu_ancestor_of(Menu const&) const;
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ endpoint WindowServer
|
||||||
set_fullscreen(i32 window_id, bool fullscreen) =|
|
set_fullscreen(i32 window_id, bool fullscreen) =|
|
||||||
set_frameless(i32 window_id, bool frameless) =|
|
set_frameless(i32 window_id, bool frameless) =|
|
||||||
set_forced_shadow(i32 window_id, bool shadow) =|
|
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) =|
|
dismiss_menu(i32 menu_id) =|
|
||||||
|
|
||||||
set_wallpaper(Gfx::ShareableBitmap wallpaper_bitmap) => (bool success)
|
set_wallpaper(Gfx::ShareableBitmap wallpaper_bitmap) => (bool success)
|
||||||
|
|
Loading…
Reference in a new issue