apio
ac260d0397
All checks were successful
Build and test / build (push) Successful in 1m42s
This segments privileges more, making it so that any app connecting to wsys.sock can't just always access every single advanced feature in wind if they don't need to. Of course, apps have to restrict themselves, which is why only privileged apps have access to this feature in the first place. Normal apps' pledges are all empty and can't be changed. An example: taskbar uses the "ExtendedLayers" pledge to move its window to the background, but relinquishes it afterwards, and doesn't need any other advanced feature for now. If a pledge-capable app tries to use a pledge-protected function without having pledged anything, it can't. Pledges are mandatory if you want to access certain functionality, unlike the kernel's pledges which make every syscall available if you don't use pledge().
153 lines
4.3 KiB
C++
153 lines
4.3 KiB
C++
#include <luna/Sort.h>
|
|
#include <luna/StringBuilder.h>
|
|
#include <os/Config.h>
|
|
#include <os/Directory.h>
|
|
#include <os/File.h>
|
|
#include <os/FileSystem.h>
|
|
#include <os/IPC.h>
|
|
#include <os/Process.h>
|
|
#include <os/ipc/Launcher.h>
|
|
#include <signal.h>
|
|
#include <sys/wait.h>
|
|
#include <ui/App.h>
|
|
#include <ui/Button.h>
|
|
#include <ui/Container.h>
|
|
#include <ui/Image.h>
|
|
#include <ui/Layout.h>
|
|
|
|
static constexpr ui::Color TASKBAR_COLOR = ui::Color::from_rgb(83, 83, 83);
|
|
|
|
static OwnedPtr<os::IPC::Client> launcher_client;
|
|
|
|
void sigquit_handler(int)
|
|
{
|
|
// Reload the taskbar by exec-ing the executable, resetting everything.
|
|
StringView args[] = { "/usr/bin/taskbar" };
|
|
os::Process::exec(args[0], { args, 1 });
|
|
}
|
|
|
|
Result<void> create_widget_group_for_app(ui::HorizontalLayout& layout, StringView path, StringView icon)
|
|
{
|
|
auto* button = TRY(make<ui::Button>(ui::Rect { 0, 0, 50, 50 }));
|
|
layout.add_widget(*button);
|
|
|
|
auto* container = TRY(
|
|
make<ui::Container>(ui::Rect { 0, 0, 50, 50 }, ui::VerticalAlignment::Center, ui::HorizontalAlignment::Center));
|
|
button->set_widget(*container);
|
|
button->set_action([=] {
|
|
os::Launcher::LaunchDetachedRequest request;
|
|
SET_IPC_STRING(request.command, path.chars());
|
|
launcher_client->send_async(request);
|
|
});
|
|
|
|
auto image = TRY(ui::ImageWidget::load(icon));
|
|
container->set_widget(*image);
|
|
|
|
image.leak();
|
|
|
|
return {};
|
|
}
|
|
|
|
struct ApplicationFile
|
|
{
|
|
String name;
|
|
String command;
|
|
String icon;
|
|
};
|
|
|
|
Vector<ApplicationFile> s_app_files;
|
|
|
|
// Pretty much copied from init.cpp.
|
|
static Result<void> load_application_file(const os::Path& path)
|
|
{
|
|
os::println("[taskbar] reading app file: %s", path.name().chars());
|
|
|
|
auto file = TRY(os::ConfigFile::open(path));
|
|
|
|
ApplicationFile app_file;
|
|
|
|
app_file.name = TRY(String::from_string_view(file->read_string_or("Name", "")));
|
|
if (app_file.name.is_empty())
|
|
{
|
|
os::println("[taskbar] app file is missing 'Name' entry, aborting!");
|
|
return {};
|
|
}
|
|
|
|
app_file.command = TRY(String::from_string_view(file->read_string_or("Command", "")));
|
|
if (app_file.command.is_empty())
|
|
{
|
|
os::println("[taskbar] app file is missing 'Command' entry, aborting!");
|
|
return {};
|
|
}
|
|
|
|
app_file.icon = TRY(String::from_string_view(file->read_string_or("Icon", "")));
|
|
if (app_file.icon.is_empty())
|
|
{
|
|
os::println("[taskbar] app file is missing 'Icon' entry, aborting!");
|
|
return {};
|
|
}
|
|
|
|
os::println("[taskbar] loaded app %s into memory", app_file.name.chars());
|
|
|
|
TRY(s_app_files.try_append(move(app_file)));
|
|
|
|
return {};
|
|
}
|
|
|
|
static Result<void> load_app_files_from_path(StringView path)
|
|
{
|
|
os::println("[taskbar] loading app files from %s", path.chars());
|
|
|
|
auto dir = TRY(os::Directory::open(path));
|
|
|
|
auto services = TRY(dir->list_names(os::Directory::Filter::ParentAndBase));
|
|
sort(services.begin(), services.end(), String::compare);
|
|
|
|
for (const auto& entry : services) TRY(load_application_file({ dir->fd(), entry.view() }));
|
|
|
|
return {};
|
|
}
|
|
|
|
Result<int> luna_main(int, char**)
|
|
{
|
|
ui::App app;
|
|
TRY(app.init("/tmp/wsys.sock"));
|
|
app.pledge(ui::Pledge::ExtendedLayers);
|
|
|
|
TRY(os::EventLoop::the().register_signal_handler(SIGQUIT, sigquit_handler));
|
|
|
|
launcher_client = TRY(os::IPC::Client::connect("/tmp/execd.sock", false));
|
|
|
|
ui::Rect screen = app.screen_rect();
|
|
|
|
ui::Rect bar = ui::Rect { ui::Point { 0, screen.height - 50 }, screen.width, 50 };
|
|
|
|
auto window = TRY(ui::Window::create(bar, ui::WindowType::System));
|
|
app.set_main_window(window);
|
|
|
|
window->set_background(TASKBAR_COLOR);
|
|
window->set_layer(ui::Layer::Background);
|
|
app.pledge(0);
|
|
|
|
ui::HorizontalLayout layout(ui::Margins { 0, 0, 0, 0 }, ui::AdjustHeight::Yes, ui::AdjustWidth::No);
|
|
window->set_main_widget(layout);
|
|
|
|
load_app_files_from_path("/usr/share/applications/");
|
|
|
|
auto home = TRY(os::FileSystem::home_directory());
|
|
|
|
StringBuilder sb;
|
|
TRY(sb.add(home.view()));
|
|
TRY(sb.add("/.applications/"_sv));
|
|
auto local_app_file_dir = TRY(sb.string());
|
|
|
|
load_app_files_from_path(local_app_file_dir.view());
|
|
|
|
for (const auto& app_file : s_app_files)
|
|
{
|
|
create_widget_group_for_app(layout, app_file.command.view(), app_file.icon.view());
|
|
}
|
|
|
|
return app.run();
|
|
}
|