From 70f7c10ab9502e5d0690bb02646e65670b840da0 Mon Sep 17 00:00:00 2001 From: david072 Date: Sat, 4 Nov 2023 19:58:14 +0100 Subject: [PATCH] Taskbar+WindowServer: Adding to Quick Launch via windows :^) You can now add applications to Quick Launch via the context menu option of their windows. Clicking it creates an event with the stored PID of the process that created the window. The Taskbar receives the event and tells the QuickLaunchWidget to add the PID, which then gets the executable using /sys/kernel/processes. It also looks for an AppFile using the name from the process object and if there is one, it uses that, since it should contain a better formatted name. --- .../ConnectionToWindowManagerServer.cpp | 7 ++++ .../LibGUI/ConnectionToWindowManagerServer.h | 2 ++ Userland/Libraries/LibGUI/Event.h | 16 +++++++++ .../Services/Taskbar/QuickLaunchWidget.cpp | 36 +++++++++++++++++++ Userland/Services/Taskbar/QuickLaunchWidget.h | 3 ++ Userland/Services/Taskbar/TaskbarWindow.cpp | 14 ++++++++ Userland/Services/WindowServer/Window.cpp | 13 +++++++ Userland/Services/WindowServer/Window.h | 3 ++ .../Services/WindowServer/WindowManager.cpp | 8 +++++ .../Services/WindowServer/WindowManager.h | 2 ++ .../WindowServer/WindowManagerClient.ipc | 1 + 11 files changed, 105 insertions(+) diff --git a/Userland/Libraries/LibGUI/ConnectionToWindowManagerServer.cpp b/Userland/Libraries/LibGUI/ConnectionToWindowManagerServer.cpp index 31bde9f50c..81c29a8568 100644 --- a/Userland/Libraries/LibGUI/ConnectionToWindowManagerServer.cpp +++ b/Userland/Libraries/LibGUI/ConnectionToWindowManagerServer.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, the SerenityOS developers. + * Copyright (c) 2023, David Ganz * * SPDX-License-Identifier: BSD-2-Clause */ @@ -87,4 +88,10 @@ void ConnectionToWindowManagerServer::keymap_changed(i32 wm_id, DeprecatedString Core::EventLoop::current().post_event(*window, make(wm_id, keymap)); } +void ConnectionToWindowManagerServer::add_to_quick_launch(i32 wm_id, pid_t pid) +{ + if (auto* window = Window::from_window_id(wm_id)) + Core::EventLoop::current().post_event(*window, make(wm_id, pid)); +} + } diff --git a/Userland/Libraries/LibGUI/ConnectionToWindowManagerServer.h b/Userland/Libraries/LibGUI/ConnectionToWindowManagerServer.h index 93300f0918..bee183c2ec 100644 --- a/Userland/Libraries/LibGUI/ConnectionToWindowManagerServer.h +++ b/Userland/Libraries/LibGUI/ConnectionToWindowManagerServer.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, the SerenityOS developers. + * Copyright (c) 2023, David Ganz * * SPDX-License-Identifier: BSD-2-Clause */ @@ -38,6 +39,7 @@ private: virtual void super_digit_key_pressed(i32, u8) override; virtual void workspace_changed(i32, u32, u32) override; virtual void keymap_changed(i32, DeprecatedString const&) override; + virtual void add_to_quick_launch(i32, pid_t) override; }; } diff --git a/Userland/Libraries/LibGUI/Event.h b/Userland/Libraries/LibGUI/Event.h index 82195b9d50..2c2e574412 100644 --- a/Userland/Libraries/LibGUI/Event.h +++ b/Userland/Libraries/LibGUI/Event.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2018-2023, Andreas Kling * Copyright (c) 2022, the SerenityOS developers. + * Copyright (c) 2023, David Ganz * * SPDX-License-Identifier: BSD-2-Clause */ @@ -73,6 +74,7 @@ public: WM_SuperDigitKeyPressed, WM_WorkspaceChanged, WM_KeymapChanged, + WM_AddToQuickLaunch, __End_WM_Events, }; @@ -264,6 +266,20 @@ private: const DeprecatedString m_keymap; }; +class WMAddToQuickLaunchEvent : public WMEvent { +public: + explicit WMAddToQuickLaunchEvent(int client_id, pid_t pid) + : WMEvent(Event::Type::WM_AddToQuickLaunch, client_id, 0) + , m_pid(pid) + { + } + + pid_t pid() const { return m_pid; } + +private: + pid_t m_pid; +}; + class MultiPaintEvent final : public Event { public: explicit MultiPaintEvent(Vector rects, Gfx::IntSize window_size) diff --git a/Userland/Services/Taskbar/QuickLaunchWidget.cpp b/Userland/Services/Taskbar/QuickLaunchWidget.cpp index 239b7df89a..9d4dcd7155 100644 --- a/Userland/Services/Taskbar/QuickLaunchWidget.cpp +++ b/Userland/Services/Taskbar/QuickLaunchWidget.cpp @@ -256,4 +256,40 @@ void QuickLaunchWidget::drop_event(GUI::DropEvent& event) } } +ErrorOr QuickLaunchWidget::add_from_pid(pid_t pid_to_add) +{ + auto processes_file = TRY(Core::File::open("/sys/kernel/processes"sv, Core::File::OpenMode::Read)); + auto file_content = TRY(processes_file->read_until_eof()); + auto json_obj = TRY(JsonValue::from_string(file_content)).as_object(); + for (auto value : json_obj.get_array("processes"sv).release_value().values()) { + auto& process_object = value.as_object(); + auto pid = process_object.get_i32("pid"sv).value_or(0); + if (pid != pid_to_add) + continue; + + auto executable = process_object.get_deprecated_string("executable"sv); + if (!executable.has_value()) + break; + + auto maybe_name = process_object.get_deprecated_string("name"sv); + if (!maybe_name.has_value()) + break; + + auto name = maybe_name.release_value(); + auto path = executable.release_value(); + if (Desktop::AppFile::exists_for_app(name)) { + path = Desktop::AppFile::app_file_path_for_app(name); + } + + auto new_entry = QuickLaunchEntry::create_from_path(path); + if (!new_entry) + break; + + TRY(add_or_adjust_button(name, new_entry.release_nonnull())); + return true; + } + + return false; +} + } diff --git a/Userland/Services/Taskbar/QuickLaunchWidget.h b/Userland/Services/Taskbar/QuickLaunchWidget.h index 35228425a3..e1b0c88b42 100644 --- a/Userland/Services/Taskbar/QuickLaunchWidget.h +++ b/Userland/Services/Taskbar/QuickLaunchWidget.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, Fabian Blatz + * Copyright (c) 2023, David Ganz * * SPDX-License-Identifier: BSD-2-Clause */ @@ -89,6 +90,8 @@ public: virtual void drag_enter_event(GUI::DragEvent&) override; virtual void drop_event(GUI::DropEvent&) override; + ErrorOr add_from_pid(pid_t pid); + private: explicit QuickLaunchWidget(); ErrorOr add_or_adjust_button(DeprecatedString const&, NonnullOwnPtr&&); diff --git a/Userland/Services/Taskbar/TaskbarWindow.cpp b/Userland/Services/Taskbar/TaskbarWindow.cpp index d31558214c..6d2bf71fc1 100644 --- a/Userland/Services/Taskbar/TaskbarWindow.cpp +++ b/Userland/Services/Taskbar/TaskbarWindow.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 2018-2021, Andreas Kling * Copyright (c) 2021, Spencer Dixon + * Copyright (c) 2023, David Ganz * * SPDX-License-Identifier: BSD-2-Clause */ @@ -21,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -360,6 +362,18 @@ void TaskbarWindow::wm_event(GUI::WMEvent& event) workspace_change_event(changed_event.current_row(), changed_event.current_column()); break; } + case GUI::Event::WM_AddToQuickLaunch: { + auto add_event = static_cast(event); + auto result = m_quick_launch->add_from_pid(add_event.pid()); + if (result.is_error()) { + dbgln("Couldn't add pid {} to quick launch menu: {}", add_event.pid(), result.error()); + GUI::MessageBox::show_error(this, String::formatted("Failed to add to Quick Launch: {}", result.release_error()).release_value_but_fixme_should_propagate_errors()); + } else if (!result.release_value()) { + dbgln("Couldn't add pid {} to quick launch menu due to an unexpected error", add_event.pid()); + GUI::MessageBox::show_error(this, "Failed to add to Quick Launch due to an unexpected error."sv); + } + break; + } default: break; } diff --git a/Userland/Services/WindowServer/Window.cpp b/Userland/Services/WindowServer/Window.cpp index be5a79d2ff..ce929de4e2 100644 --- a/Userland/Services/WindowServer/Window.cpp +++ b/Userland/Services/WindowServer/Window.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2023, David Ganz * * SPDX-License-Identifier: BSD-2-Clause */ @@ -743,6 +744,13 @@ void Window::ensure_window_menu() m_window_menu->add_item(make(*m_window_menu, MenuItem::Type::Separator)); } + auto add_to_quick_launch_item = make(*m_window_menu, (unsigned)WindowMenuAction::AddToQuickLaunch, "&Add to Quick Launch"); + m_window_menu_add_to_quick_launch_item = add_to_quick_launch_item.ptr(); + m_window_menu_add_to_quick_launch_item->set_icon(&pin_icon()); + m_window_menu->add_item(move(add_to_quick_launch_item)); + + m_window_menu->add_item(make(*m_window_menu, MenuItem::Type::Separator)); + auto close_item = make(*m_window_menu, (unsigned)WindowMenuAction::Close, "&Close"); m_window_menu_close_item = close_item.ptr(); m_window_menu_close_item->set_icon(&close_icon()); @@ -792,6 +800,11 @@ void Window::handle_window_menu_action(WindowMenuAction action) WindowManager::the().set_always_on_top(*this, new_is_checked); break; } + case WindowMenuAction::AddToQuickLaunch: { + if (m_process_id.has_value()) + WindowManager::the().on_add_to_quick_launch(m_process_id.value()); + break; + } } } diff --git a/Userland/Services/WindowServer/Window.h b/Userland/Services/WindowServer/Window.h index 13fdb74815..dbf297ad4f 100644 --- a/Userland/Services/WindowServer/Window.h +++ b/Userland/Services/WindowServer/Window.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2023, Andreas Kling + * Copyright (c) 2023, David Ganz * * SPDX-License-Identifier: BSD-2-Clause */ @@ -63,6 +64,7 @@ enum class WindowMenuAction { Close, Move, ToggleAlwaysOnTop, + AddToQuickLaunch, }; enum class WindowMenuDefaultAction { @@ -455,6 +457,7 @@ private: MenuItem* m_window_menu_close_item { nullptr }; MenuItem* m_window_menu_always_on_top_item { nullptr }; MenuItem* m_window_menu_menubar_visibility_item { nullptr }; + MenuItem* m_window_menu_add_to_quick_launch_item { nullptr }; Optional m_progress; bool m_should_show_menubar { true }; WindowStack* m_window_stack { nullptr }; diff --git a/Userland/Services/WindowServer/WindowManager.cpp b/Userland/Services/WindowServer/WindowManager.cpp index f7a0eb3f34..06e9659058 100644 --- a/Userland/Services/WindowServer/WindowManager.cpp +++ b/Userland/Services/WindowServer/WindowManager.cpp @@ -765,6 +765,14 @@ void WindowManager::stop_tile_window_animation() m_tile_window_overlay_animation = nullptr; } +void WindowManager::on_add_to_quick_launch(pid_t pid) +{ + for_each_window_manager([&](WMConnectionFromClient& conn) { + conn.async_add_to_quick_launch(conn.window_id(), pid); + return IterationDecision::Continue; + }); +} + void WindowManager::show_tile_window_overlay(Window& window, Screen const& cursor_screen, WindowTileType tile_type) { m_move_window_suggested_tile = tile_type; diff --git a/Userland/Services/WindowServer/WindowManager.h b/Userland/Services/WindowServer/WindowManager.h index 4aef58bd05..56acd5bb40 100644 --- a/Userland/Services/WindowServer/WindowManager.h +++ b/Userland/Services/WindowServer/WindowManager.h @@ -344,6 +344,8 @@ public: void start_tile_window_animation(Gfx::IntRect const&); void stop_tile_window_animation(); + void on_add_to_quick_launch(pid_t); + private: explicit WindowManager(Gfx::PaletteImpl&); diff --git a/Userland/Services/WindowServer/WindowManagerClient.ipc b/Userland/Services/WindowServer/WindowManagerClient.ipc index 3b31de5a0d..4d0d4588b4 100644 --- a/Userland/Services/WindowServer/WindowManagerClient.ipc +++ b/Userland/Services/WindowServer/WindowManagerClient.ipc @@ -13,4 +13,5 @@ endpoint WindowManagerClient super_digit_key_pressed(i32 wm_id, u8 digit) =| workspace_changed(i32 wm_id, u32 row, u32 column) =| keymap_changed(i32 wm_id, [UTF8] DeprecatedString keymap) =| + add_to_quick_launch(i32 wm_id, i32 process_id) =| }