diff --git a/Userland/Applications/Browser/BrowserWindow.cpp b/Userland/Applications/Browser/BrowserWindow.cpp index 72c89d2fb98..b6573fb5705 100644 --- a/Userland/Applications/Browser/BrowserWindow.cpp +++ b/Userland/Applications/Browser/BrowserWindow.cpp @@ -12,6 +12,7 @@ #include "Browser.h" #include "InspectorWidget.h" #include "Tab.h" +#include "TaskManagerWidget.h" #include #include #include @@ -263,9 +264,16 @@ void BrowserWindow::build_menus(StringView const man_file) this); m_inspect_dom_node_action->set_status_tip("Open inspector for this element"_string); + m_task_manager_action = GUI::Action::create( + "Task &Manager", g_icon_bag.task_manager, [this](auto&) { + show_task_manager_window(); + }, + this); + auto inspect_menu = add_menu("&Inspect"_string); inspect_menu->add_action(*m_view_source_action); inspect_menu->add_action(*m_inspect_dom_tree_action); + inspect_menu->add_action(*m_task_manager_action); auto storage_window_action = GUI::Action::create( "Open S&torage Inspector", g_icon_bag.cookie, [this](auto&) { @@ -742,6 +750,11 @@ void BrowserWindow::event(Core::Event& event) case GUI::Event::Resize: broadcast_window_size(static_cast(event).size()); break; + case GUI::Event::WindowCloseRequest: + // FIXME: If we have multiple browser windows, this won't be correct anymore + // For now, this makes sure that we close the TaskManagerWindow when the user clicks the (X) button + close_task_manager_window(); + break; default: break; } @@ -762,4 +775,26 @@ void BrowserWindow::update_displayed_zoom_level() update_zoom_menu(); } +void BrowserWindow::show_task_manager_window() +{ + if (!m_task_manager_window) { + m_task_manager_window = GUI::Window::construct(); + m_task_manager_window->set_window_mode(GUI::WindowMode::Modeless); + m_task_manager_window->resize(400, 300); + m_task_manager_window->set_title("Task Manager"); + + (void)m_task_manager_window->set_main_widget(); + } + + m_task_manager_window->show(); + m_task_manager_window->move_to_front(); +} + +void BrowserWindow::close_task_manager_window() +{ + if (m_task_manager_window) { + m_task_manager_window->close(); + } +} + } diff --git a/Userland/Applications/Browser/BrowserWindow.h b/Userland/Applications/Browser/BrowserWindow.h index a275084a24b..7e0d6cb1fc4 100644 --- a/Userland/Applications/Browser/BrowserWindow.h +++ b/Userland/Applications/Browser/BrowserWindow.h @@ -65,6 +65,9 @@ private: void update_displayed_zoom_level(); + void show_task_manager_window(); + void close_task_manager_window(); + RefPtr m_go_back_action; RefPtr m_go_forward_action; RefPtr m_go_home_action; @@ -75,6 +78,7 @@ private: RefPtr m_view_source_action; RefPtr m_inspect_dom_tree_action; RefPtr m_inspect_dom_node_action; + RefPtr m_task_manager_action; RefPtr m_zoom_menu; @@ -83,6 +87,9 @@ private: RefPtr m_tab_widget; RefPtr m_bookmarks_bar; + // FIXME: This should be owned at a higher level in case we have multiple browser windows + RefPtr m_task_manager_window; + GUI::ActionGroup m_user_agent_spoof_actions; GUI::ActionGroup m_search_engine_actions; GUI::ActionGroup m_color_scheme_actions; diff --git a/Userland/Applications/Browser/CMakeLists.txt b/Userland/Applications/Browser/CMakeLists.txt index ceff5c1512a..ad4e60fbc86 100644 --- a/Userland/Applications/Browser/CMakeLists.txt +++ b/Userland/Applications/Browser/CMakeLists.txt @@ -23,6 +23,7 @@ set(SOURCES StorageModel.cpp StorageWidget.cpp Tab.cpp + TaskManagerWidget.cpp URLBox.cpp WindowActions.cpp main.cpp diff --git a/Userland/Applications/Browser/IconBag.cpp b/Userland/Applications/Browser/IconBag.cpp index 0c0be02f324..55896b96300 100644 --- a/Userland/Applications/Browser/IconBag.cpp +++ b/Userland/Applications/Browser/IconBag.cpp @@ -50,6 +50,7 @@ ErrorOr IconBag::try_create() 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)); + icon_bag.task_manager = TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/app-system-monitor.png"sv)); return icon_bag; } diff --git a/Userland/Applications/Browser/IconBag.h b/Userland/Applications/Browser/IconBag.h index 52b52758df2..8a0712bb227 100644 --- a/Userland/Applications/Browser/IconBag.h +++ b/Userland/Applications/Browser/IconBag.h @@ -52,5 +52,6 @@ struct IconBag final { RefPtr mute { nullptr }; RefPtr unmute { nullptr }; RefPtr search { nullptr }; + RefPtr task_manager { nullptr }; }; } diff --git a/Userland/Applications/Browser/TaskManagerWidget.cpp b/Userland/Applications/Browser/TaskManagerWidget.cpp new file mode 100644 index 00000000000..43e57215bde --- /dev/null +++ b/Userland/Applications/Browser/TaskManagerWidget.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "TaskManagerWidget.h" +#include +#include +#include + +namespace Browser { + +TaskManagerWidget::~TaskManagerWidget() = default; + +TaskManagerWidget::TaskManagerWidget() +{ + m_update_timer = MUST(Core::Timer::create_repeating(1000, [this] { + this->update_statistics(); + })); + m_update_timer->start(); + + m_web_view = add(); + + set_layout(4); + set_fill_with_background_color(true); + + m_web_view->set_focus(true); + + update_statistics(); +} + +void TaskManagerWidget::show_event(GUI::ShowEvent& event) +{ + m_update_timer->start(); + + GUI::Widget::show_event(event); +} + +void TaskManagerWidget::hide_event(GUI::HideEvent& event) +{ + m_update_timer->stop(); + + GUI::Widget::hide_event(event); +} + +void TaskManagerWidget::update_statistics() +{ + WebView::ProcessManager::the().update_all_processes(); + m_web_view->load_html(WebView::ProcessManager::the().generate_html()); +} + +} diff --git a/Userland/Applications/Browser/TaskManagerWidget.h b/Userland/Applications/Browser/TaskManagerWidget.h new file mode 100644 index 00000000000..257fe1f327d --- /dev/null +++ b/Userland/Applications/Browser/TaskManagerWidget.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +namespace Browser { + +class TaskManagerWidget : public GUI::Widget { + C_OBJECT(TaskManagerWidget) + +public: + TaskManagerWidget(); + ~TaskManagerWidget() override; + +private: + virtual void show_event(GUI::ShowEvent&) override; + virtual void hide_event(GUI::HideEvent&) override; + + void update_statistics(); + + RefPtr m_web_view; + RefPtr m_update_timer; +}; + +}