From 1df0a141af8ddceb98d6d7ec9079805da5af2e65 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Mon, 15 May 2023 10:00:07 -0400 Subject: [PATCH] Browser: Add a context menu for video elements This includes actions such as controlling play state, downloading the video, and opening the video in a new tab. --- Userland/Applications/Browser/IconBag.cpp | 3 ++ Userland/Applications/Browser/IconBag.h | 3 ++ Userland/Applications/Browser/Tab.cpp | 49 +++++++++++++++++++++++ Userland/Applications/Browser/Tab.h | 6 +++ 4 files changed, 61 insertions(+) diff --git a/Userland/Applications/Browser/IconBag.cpp b/Userland/Applications/Browser/IconBag.cpp index 7a8e67fbb08..38b87a8d54d 100644 --- a/Userland/Applications/Browser/IconBag.cpp +++ b/Userland/Applications/Browser/IconBag.cpp @@ -15,6 +15,7 @@ ErrorOr IconBag::try_create() icon_bag.filetype_text = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/filetype-text.png"sv)); icon_bag.filetype_javascript = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/filetype-javascript.png"sv)); icon_bag.filetype_image = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/filetype-image.png"sv)); + icon_bag.filetype_video = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/filetype-video.png"sv)); icon_bag.bookmark_contour = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/bookmark-contour.png"sv)); icon_bag.bookmark_filled = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/bookmark-filled.png"sv)); icon_bag.inspector_object = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/inspector-object.png"sv)); @@ -42,6 +43,8 @@ ErrorOr IconBag::try_create() icon_bag.download = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/download.png"sv)); icon_bag.copy = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/edit-copy.png"sv)); icon_bag.rename = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/rename.png"sv)); + icon_bag.play = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/play.png"sv)); + icon_bag.pause = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/pause.png"sv)); return icon_bag; } diff --git a/Userland/Applications/Browser/IconBag.h b/Userland/Applications/Browser/IconBag.h index d367cdc8f91..8dda18ed179 100644 --- a/Userland/Applications/Browser/IconBag.h +++ b/Userland/Applications/Browser/IconBag.h @@ -17,6 +17,7 @@ struct IconBag final { RefPtr filetype_text { nullptr }; RefPtr filetype_javascript { nullptr }; RefPtr filetype_image { nullptr }; + RefPtr filetype_video { nullptr }; RefPtr bookmark_contour { nullptr }; RefPtr bookmark_filled { nullptr }; RefPtr inspector_object { nullptr }; @@ -44,5 +45,7 @@ struct IconBag final { RefPtr download { nullptr }; RefPtr copy { nullptr }; RefPtr rename { nullptr }; + RefPtr play { nullptr }; + RefPtr pause { nullptr }; }; } diff --git a/Userland/Applications/Browser/Tab.cpp b/Userland/Applications/Browser/Tab.cpp index 5631b46e47e..43e5e2829c1 100644 --- a/Userland/Applications/Browser/Tab.cpp +++ b/Userland/Applications/Browser/Tab.cpp @@ -369,6 +369,55 @@ Tab::Tab(BrowserWindow& window) m_image_context_menu->popup(screen_position); }; + m_video_context_menu_play_pause_action = GUI::Action::create("&Play", g_icon_bag.play, [this](auto&) { + view().toggle_video_play_state(); + }); + m_video_context_menu_controls_action = GUI::Action::create_checkable("Show &Controls", [this](auto&) { + view().toggle_video_controls_state(); + }); + m_video_context_menu_loop_action = GUI::Action::create_checkable("&Loop Video", [this](auto&) { + view().toggle_video_loop_state(); + }); + + m_video_context_menu = GUI::Menu::construct(); + m_video_context_menu->add_action(*m_video_context_menu_play_pause_action); + m_video_context_menu->add_action(*m_video_context_menu_controls_action); + m_video_context_menu->add_action(*m_video_context_menu_loop_action); + m_video_context_menu->add_separator(); + m_video_context_menu->add_action(GUI::Action::create("&Open Video", g_icon_bag.filetype_video, [this](auto&) { + view().on_link_click(m_video_context_menu_url, "", 0); + })); + m_video_context_menu->add_action(GUI::Action::create("Open Video in New &Tab", g_icon_bag.new_tab, [this](auto&) { + view().on_link_click(m_video_context_menu_url, "_blank", 0); + })); + m_video_context_menu->add_separator(); + m_video_context_menu->add_action(GUI::Action::create("Copy Video &URL", g_icon_bag.copy, [this](auto&) { + GUI::Clipboard::the().set_plain_text(m_video_context_menu_url.to_deprecated_string()); + })); + m_video_context_menu->add_separator(); + m_video_context_menu->add_action(GUI::Action::create("&Download", g_icon_bag.download, [this](auto&) { + start_download(m_video_context_menu_url); + })); + m_video_context_menu->add_separator(); + m_video_context_menu->add_action(window.inspect_dom_node_action()); + + view().on_video_context_menu_request = [this](auto& video_url, auto screen_position, bool is_playing, bool has_user_agent_controls, bool is_looping) { + m_video_context_menu_url = video_url; + + if (is_playing) { + m_video_context_menu_play_pause_action->set_icon(g_icon_bag.play); + m_video_context_menu_play_pause_action->set_text("&Play"sv); + } else { + m_video_context_menu_play_pause_action->set_icon(g_icon_bag.pause); + m_video_context_menu_play_pause_action->set_text("&Pause"sv); + } + + m_video_context_menu_controls_action->set_checked(has_user_agent_controls); + m_video_context_menu_loop_action->set_checked(is_looping); + + m_video_context_menu->popup(screen_position); + }; + view().on_link_middle_click = [this](auto& href, auto&, auto) { view().on_link_click(href, "_blank", 0); }; diff --git a/Userland/Applications/Browser/Tab.h b/Userland/Applications/Browser/Tab.h index b6dc5d17f43..ecc4f300d0b 100644 --- a/Userland/Applications/Browser/Tab.h +++ b/Userland/Applications/Browser/Tab.h @@ -144,6 +144,12 @@ private: Gfx::ShareableBitmap m_image_context_menu_bitmap; URL m_image_context_menu_url; + RefPtr m_video_context_menu; + RefPtr m_video_context_menu_play_pause_action; + RefPtr m_video_context_menu_controls_action; + RefPtr m_video_context_menu_loop_action; + URL m_video_context_menu_url; + RefPtr m_tab_context_menu; RefPtr m_page_context_menu; RefPtr m_go_back_context_menu;