diff --git a/Userland/Applications/Browser/BrowserWindow.cpp b/Userland/Applications/Browser/BrowserWindow.cpp index fea6bd164e..65305c7cb0 100644 --- a/Userland/Applications/Browser/BrowserWindow.cpp +++ b/Userland/Applications/Browser/BrowserWindow.cpp @@ -14,8 +14,10 @@ #include "CookieJar.h" #include "InspectorWidget.h" #include "Tab.h" +#include #include #include +#include #include #include #include @@ -33,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -240,6 +243,14 @@ void BrowserWindow::build_menus() this); m_inspect_dom_node_action->set_status_tip("Open inspector for this element"); + m_take_screenshot_action = GUI::Action::create( + "&Take Screenshot"sv, g_icon_bag.filetype_image, [this](auto&) { + if (auto result = take_screenshot(); result.is_error()) + GUI::MessageBox::show_error(this, String::formatted("{}", result.error())); + }, + this); + m_take_screenshot_action->set_status_tip("Save a screenshot of the current tab to the Downloads directory"sv); + auto& inspect_menu = add_menu("&Inspect"); inspect_menu.add_action(*m_view_source_action); inspect_menu.add_action(*m_inspect_dom_tree_action); @@ -718,4 +729,24 @@ void BrowserWindow::event(Core::Event& event) Window::event(event); } +ErrorOr BrowserWindow::take_screenshot() +{ + if (!active_tab().on_take_screenshot) + return {}; + + auto bitmap = active_tab().on_take_screenshot(); + if (!bitmap.is_valid()) + return Error::from_string_view("Failed to take a screenshot of the current tab"sv); + + LexicalPath path { Core::StandardPaths::downloads_directory() }; + path = path.append(Core::DateTime::now().to_string("screenshot-%Y-%m-%d-%H-%M-%S.png"sv)); + + auto encoded = Gfx::PNGWriter::encode(*bitmap.bitmap()); + + auto screenshot_file = TRY(Core::Stream::File::open(path.string(), Core::Stream::OpenMode::Write)); + TRY(screenshot_file->write(encoded)); + + return {}; +} + } diff --git a/Userland/Applications/Browser/BrowserWindow.h b/Userland/Applications/Browser/BrowserWindow.h index e6bd26fcec..89f193a68b 100644 --- a/Userland/Applications/Browser/BrowserWindow.h +++ b/Userland/Applications/Browser/BrowserWindow.h @@ -39,6 +39,7 @@ public: GUI::Action& view_source_action() { return *m_view_source_action; } GUI::Action& inspect_dom_tree_action() { return *m_inspect_dom_tree_action; } GUI::Action& inspect_dom_node_action() { return *m_inspect_dom_node_action; } + GUI::Action& take_screenshot_action() { return *m_take_screenshot_action; } void content_filters_changed(); void proxy_mappings_changed(); @@ -58,6 +59,8 @@ private: virtual void event(Core::Event&) override; + ErrorOr take_screenshot(); + RefPtr m_go_back_action; RefPtr m_go_forward_action; RefPtr m_go_home_action; @@ -67,6 +70,7 @@ private: RefPtr m_view_source_action; RefPtr m_inspect_dom_tree_action; RefPtr m_inspect_dom_node_action; + RefPtr m_take_screenshot_action; CookieJar& m_cookie_jar; WindowActions m_window_actions; diff --git a/Userland/Applications/Browser/Tab.cpp b/Userland/Applications/Browser/Tab.cpp index 5513756892..eb0e3cb1fc 100644 --- a/Userland/Applications/Browser/Tab.cpp +++ b/Userland/Applications/Browser/Tab.cpp @@ -404,6 +404,8 @@ Tab::Tab(BrowserWindow& window) m_page_context_menu->add_action(window.view_source_action()); m_page_context_menu->add_action(window.inspect_dom_tree_action()); m_page_context_menu->add_action(window.inspect_dom_node_action()); + m_page_context_menu->add_separator(); + m_page_context_menu->add_action(window.take_screenshot_action()); view().on_context_menu_request = [&](auto& screen_position) { m_page_context_menu->popup(screen_position); };