1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 06:17:35 +00:00

Taskbar: Abstract out quick launch entries

... into QuickLaunchEntry class. It will be used to implement adding
plain executables to the taskbar. For now, it adds TRY() error handling
to app launching :^)
This commit is contained in:
Maciej 2021-12-29 16:34:57 +01:00 committed by Andreas Kling
parent ccb8374434
commit 2e8e959896
2 changed files with 90 additions and 41 deletions

View file

@ -7,8 +7,10 @@
#include "QuickLaunchWidget.h" #include "QuickLaunchWidget.h"
#include <LibConfig/Client.h> #include <LibConfig/Client.h>
#include <LibCore/MimeData.h> #include <LibCore/MimeData.h>
#include <LibCore/System.h>
#include <LibGUI/BoxLayout.h> #include <LibGUI/BoxLayout.h>
#include <LibGUI/Menu.h> #include <LibGUI/Menu.h>
#include <LibGUI/MessageBox.h>
#include <serenity.h> #include <serenity.h>
namespace Taskbar { namespace Taskbar {
@ -16,6 +18,27 @@ namespace Taskbar {
constexpr auto quick_launch = "QuickLaunch"sv; constexpr auto quick_launch = "QuickLaunch"sv;
constexpr int quick_launch_button_size = 24; constexpr int quick_launch_button_size = 24;
ErrorOr<void> QuickLaunchEntryAppFile::launch() const
{
auto executable = m_app_file->executable();
pid_t pid = TRY(Core::System::fork());
if (pid == 0) {
if (chdir(Core::StandardPaths::home_directory().characters()) < 0) {
perror("chdir");
exit(1);
}
if (m_app_file->run_in_terminal())
execl("/bin/Terminal", "Terminal", "-e", executable.characters(), nullptr);
else
execl(executable.characters(), executable.characters(), nullptr);
perror("execl");
VERIFY_NOT_REACHED();
} else
TRY(Core::System::disown(pid));
return {};
}
QuickLaunchWidget::QuickLaunchWidget() QuickLaunchWidget::QuickLaunchWidget()
{ {
set_shrink_to_fit(true); set_shrink_to_fit(true);
@ -36,10 +59,11 @@ QuickLaunchWidget::QuickLaunchWidget()
auto keys = Config::list_keys("Taskbar", quick_launch); auto keys = Config::list_keys("Taskbar", quick_launch);
for (auto& name : keys) { for (auto& name : keys) {
auto af_name = Config::read_string("Taskbar", quick_launch, name); auto value = Config::read_string("Taskbar", quick_launch, name);
auto af_path = String::formatted("{}/{}", Desktop::AppFile::APP_FILES_DIRECTORY, af_name); auto entry = QuickLaunchEntry::create_from_config_value(value);
auto af = Desktop::AppFile::open(af_path); if (!entry)
add_or_adjust_button(name, af); continue;
add_or_adjust_button(name, entry.release_nonnull());
} }
} }
@ -47,40 +71,38 @@ QuickLaunchWidget::~QuickLaunchWidget()
{ {
} }
void QuickLaunchWidget::add_or_adjust_button(String const& button_name, NonnullRefPtr<Desktop::AppFile> app_file) OwnPtr<QuickLaunchEntry> QuickLaunchEntry::create_from_config_value(StringView value)
{ {
if (!app_file->is_valid()) if (value.ends_with(".af")) {
return; auto af_path = String::formatted("{}/{}", Desktop::AppFile::APP_FILES_DIRECTORY, value);
auto button = find_child_of_type_named<GUI::Button>(button_name); return make<QuickLaunchEntryAppFile>(Desktop::AppFile::open(af_path));
if (!button) {
button = &add<GUI::Button>();
} }
auto app_executable = app_file->executable(); return {};
auto app_run_in_terminal = app_file->run_in_terminal(); }
OwnPtr<QuickLaunchEntry> QuickLaunchEntry::create_from_path(StringView path)
{
if (path.ends_with(".af"))
return make<QuickLaunchEntryAppFile>(Desktop::AppFile::open(path));
return {};
}
void QuickLaunchWidget::add_or_adjust_button(String const& button_name, NonnullOwnPtr<QuickLaunchEntry>&& entry)
{
auto button = find_child_of_type_named<GUI::Button>(button_name);
if (!button)
button = &add<GUI::Button>();
button->set_fixed_size(quick_launch_button_size, quick_launch_button_size); button->set_fixed_size(quick_launch_button_size, quick_launch_button_size);
button->set_button_style(Gfx::ButtonStyle::Coolbar); button->set_button_style(Gfx::ButtonStyle::Coolbar);
button->set_icon(app_file->icon().bitmap_for_size(16)); auto icon = entry->icon();
button->set_tooltip(app_file->name()); button->set_icon(icon.bitmap_for_size(16));
button->set_tooltip(entry->name());
button->set_name(button_name); button->set_name(button_name);
button->on_click = [app_executable, app_run_in_terminal](auto) { button->on_click = [entry = move(entry), this](auto) {
pid_t pid = fork(); auto result = entry->launch();
if (pid < 0) { if (result.is_error())
perror("fork"); GUI::MessageBox::show_error(window(), String::formatted("Failed to open quick launch entry: {}", result.release_error()));
} else if (pid == 0) {
if (chdir(Core::StandardPaths::home_directory().characters()) < 0) {
perror("chdir");
exit(1);
}
if (app_run_in_terminal)
execl("/bin/Terminal", "Terminal", "-e", app_executable.characters(), nullptr);
else
execl(app_executable.characters(), app_executable.characters(), nullptr);
perror("execl");
VERIFY_NOT_REACHED();
} else {
if (disown(pid) < 0)
perror("disown");
}
}; };
button->on_context_menu_request = [this, button_name](auto& context_menu_event) { button->on_context_menu_request = [this, button_name](auto& context_menu_event) {
m_context_menu_app_name = button_name; m_context_menu_app_name = button_name;
@ -100,9 +122,10 @@ void QuickLaunchWidget::config_key_was_removed(String const& domain, String cons
void QuickLaunchWidget::config_string_did_change(String const& domain, String const& group, String const& key, String const& value) void QuickLaunchWidget::config_string_did_change(String const& domain, String const& group, String const& key, String const& value)
{ {
if (domain == "Taskbar" && group == quick_launch) { if (domain == "Taskbar" && group == quick_launch) {
auto af_path = String::formatted("{}/{}", Desktop::AppFile::APP_FILES_DIRECTORY, value); auto entry = QuickLaunchEntry::create_from_config_value(value);
auto af = Desktop::AppFile::open(af_path); if (!entry)
add_or_adjust_button(key, af); return;
add_or_adjust_button(key, entry.release_nonnull());
} }
} }
@ -113,10 +136,10 @@ void QuickLaunchWidget::drop_event(GUI::DropEvent& event)
if (event.mime_data().has_urls()) { if (event.mime_data().has_urls()) {
auto urls = event.mime_data().urls(); auto urls = event.mime_data().urls();
for (auto& url : urls) { for (auto& url : urls) {
auto af = Desktop::AppFile::open(url.path()); auto entry = QuickLaunchEntry::create_from_path(url.path());
if (af->is_valid()) { if (entry) {
auto item_name = af->name().replace(" ", "", true); auto item_name = entry->name().replace(" ", "", true);
add_or_adjust_button(item_name, af); add_or_adjust_button(item_name, entry.release_nonnull());
Config::write_string("Taskbar", quick_launch, item_name, url.basename()); Config::write_string("Taskbar", quick_launch, item_name, url.basename());
} }
} }

View file

@ -13,6 +13,32 @@
namespace Taskbar { namespace Taskbar {
class QuickLaunchEntry {
public:
virtual ~QuickLaunchEntry() = default;
virtual ErrorOr<void> launch() const = 0;
virtual GUI::Icon icon() const = 0;
virtual String name() const = 0;
static OwnPtr<QuickLaunchEntry> create_from_config_value(StringView path);
static OwnPtr<QuickLaunchEntry> create_from_path(StringView path);
};
class QuickLaunchEntryAppFile : public QuickLaunchEntry {
public:
explicit QuickLaunchEntryAppFile(NonnullRefPtr<Desktop::AppFile> file)
: m_app_file(move(file))
{
}
virtual ErrorOr<void> launch() const override;
virtual GUI::Icon icon() const override { return m_app_file->icon(); }
virtual String name() const override { return m_app_file->name(); }
private:
NonnullRefPtr<Desktop::AppFile> m_app_file;
};
class QuickLaunchWidget : public GUI::Frame class QuickLaunchWidget : public GUI::Frame
, public Config::Listener { , public Config::Listener {
C_OBJECT(QuickLaunchWidget); C_OBJECT(QuickLaunchWidget);
@ -27,7 +53,7 @@ public:
private: private:
QuickLaunchWidget(); QuickLaunchWidget();
void add_or_adjust_button(String const&, NonnullRefPtr<Desktop::AppFile>); void add_or_adjust_button(String const&, NonnullOwnPtr<QuickLaunchEntry>&&);
RefPtr<GUI::Menu> m_context_menu; RefPtr<GUI::Menu> m_context_menu;
RefPtr<GUI::Action> m_context_menu_default_action; RefPtr<GUI::Action> m_context_menu_default_action;
String m_context_menu_app_name; String m_context_menu_app_name;