diff --git a/Userland/Applications/Browser/IconBag.cpp b/Userland/Applications/Browser/IconBag.cpp index 3e6fab1c86..2cfe557853 100644 --- a/Userland/Applications/Browser/IconBag.cpp +++ b/Userland/Applications/Browser/IconBag.cpp @@ -48,6 +48,7 @@ ErrorOr IconBag::try_create() icon_bag.pause = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/pause.png"sv)); icon_bag.mute = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/audio-volume-muted.png"sv)); icon_bag.unmute = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/audio-volume-high.png"sv)); + icon_bag.search = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/find.png"sv)); return icon_bag; } diff --git a/Userland/Applications/Browser/IconBag.h b/Userland/Applications/Browser/IconBag.h index 1868671030..5e4073a8ad 100644 --- a/Userland/Applications/Browser/IconBag.h +++ b/Userland/Applications/Browser/IconBag.h @@ -50,5 +50,6 @@ struct IconBag final { RefPtr pause { nullptr }; RefPtr mute { nullptr }; RefPtr unmute { nullptr }; + RefPtr search { nullptr }; }; } diff --git a/Userland/Applications/Browser/Tab.cpp b/Userland/Applications/Browser/Tab.cpp index 2b65b21a77..69e81e9ecd 100644 --- a/Userland/Applications/Browser/Tab.cpp +++ b/Userland/Applications/Browser/Tab.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include namespace Browser { @@ -633,6 +634,13 @@ Tab::Tab(BrowserWindow& window) on_tab_close_other_request(*this); })); + auto search_selected_text_action = GUI::Action::create( + "&Search for "sv, g_icon_bag.search, [this](auto&) { + auto url = MUST(String::formatted(g_search_engine, URL::percent_encode(*m_page_context_menu_search_text))); + this->window().create_new_tab(url, Web::HTML::ActivateTab::Yes); + }, + this); + auto take_visible_screenshot_action = GUI::Action::create( "Take &Visible Screenshot"sv, g_icon_bag.filetype_image, [this](auto&) { if (auto result = view().take_screenshot(WebView::ViewImplementation::ScreenshotType::Visible); result.is_error()) { @@ -660,6 +668,9 @@ Tab::Tab(BrowserWindow& window) m_page_context_menu->add_separator(); m_page_context_menu->add_action(window.copy_selection_action()); m_page_context_menu->add_action(window.select_all_action()); + // FIXME: It would be nice to have a separator here, but the below action is sometimes hidden, and WindowServer + // does not hide successive separators like other toolkits. + m_page_context_menu->add_action(search_selected_text_action); m_page_context_menu->add_separator(); m_page_context_menu->add_action(move(take_visible_screenshot_action)); m_page_context_menu->add_action(move(take_full_screenshot_action)); @@ -668,7 +679,24 @@ Tab::Tab(BrowserWindow& window) m_page_context_menu->add_action(window.inspect_dom_tree_action()); m_page_context_menu->add_action(window.inspect_dom_node_action()); - view().on_context_menu_request = [&](auto widget_position) { + m_page_context_menu->on_visibility_change = [this](auto visible) { + if (!visible) + m_page_context_menu_search_text = {}; + }; + + view().on_context_menu_request = [&, search_selected_text_action = move(search_selected_text_action)](auto widget_position) { + m_page_context_menu_search_text = g_search_engine.is_empty() + ? OptionalNone {} + : view().selected_text_with_whitespace_collapsed(); + + if (m_page_context_menu_search_text.has_value()) { + auto action_text = WebView::format_search_query_for_display(g_search_engine, *m_page_context_menu_search_text); + search_selected_text_action->set_text(action_text.to_deprecated_string()); + search_selected_text_action->set_visible(true); + } else { + search_selected_text_action->set_visible(false); + } + auto screen_position = view().screen_relative_rect().location().translated(widget_position); m_page_context_menu->popup(screen_position); }; diff --git a/Userland/Applications/Browser/Tab.h b/Userland/Applications/Browser/Tab.h index 2868bdfee6..50d0ad51da 100644 --- a/Userland/Applications/Browser/Tab.h +++ b/Userland/Applications/Browser/Tab.h @@ -150,9 +150,13 @@ private: URL m_media_context_menu_url; RefPtr m_tab_context_menu; + RefPtr m_page_context_menu; + Optional m_page_context_menu_search_text; + RefPtr m_go_back_context_menu; RefPtr m_go_forward_context_menu; + DeprecatedString m_title; RefPtr m_icon;