Squash commits for public release

This commit is contained in:
2025-02-12 09:54:05 -05:00
commit 7118adc514
1108 changed files with 80873 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
APPS += DOCK
DOCK_NAME = dock
DOCK_LIBS = cxx ui
DOCK_INSTALL_PATH = bin/

View File

@@ -0,0 +1,24 @@
#include "DockView.h"
#include "DockViewController.h"
#include "DockWindow.h"
#include <libui/AppDelegate.h>
class AppDelegate : public UI::AppDelegate {
public:
AppDelegate() = default;
virtual ~AppDelegate() = default;
LG::Size preferred_desktop_window_size() const override { return LG::Size(400, 300); }
bool application() override
{
auto& window = std::xos::construct<DockWindow>();
window.set_bitmap_format(LG::PixelBitmapFormat::RGBA);
auto& dock_view = window.create_superview<DockView, DockViewController>();
return true;
}
private:
};
SET_APP_DELEGATE(AppDelegate);

View File

@@ -0,0 +1,44 @@
#include "AppListView.h"
#include "DockView.h"
#include <libg/ImageLoaders/PNGLoader.h>
#include <libui/App.h>
#include <libui/Context.h>
#include <libui/Label.h>
#include <libui/Screen.h>
#include <libui/Window.h>
AppListView::AppListView(View* superview, const LG::Rect& frame)
: View(superview, frame)
{
LG::PNG::PNGLoader loader;
m_icon = loader.load_from_file("/res/system/app_list_32.png");
}
void AppListView::display(const LG::Rect& rect)
{
const int padding = 4;
const int offset_x = (DockView::icon_view_size() - m_icon.width()) / 2;
const int offset_y = (DockView::icon_view_size() - m_icon.height()) / 2;
LG::Context ctx = UI::graphics_current_context();
ctx.add_clip(rect);
auto icon_rect = LG::Rect(offset_x, offset_y, DockView::icon_size(), DockView::icon_size());
ctx.draw(icon_rect.origin(), m_icon);
if (is_hovered()) {
ctx.set_fill_color(LG::Color::LightSystemOpaque128);
ctx.fill(icon_rect);
}
}
void AppListView::on_click()
{
int this_window_id = window()->id();
if (m_target_window_id == INVALID) {
return;
}
auto& app = UI::App::the();
AskBringToFrontMessage msg(app.connection().key(), this_window_id, m_target_window_id);
app.connection().send_async_message(msg);
}

View File

@@ -0,0 +1,41 @@
#pragma once
#include "DockEntity.h"
#include "WindowEntity.h"
#include <libg/Font.h>
#include <libui/Label.h>
#include <libui/PopupMenu.h>
#include <libui/View.h>
#include <list>
#include <string>
#include <unistd.h>
class AppListView : public UI::View {
UI_OBJECT();
static constexpr int INVALID = -1;
public:
AppListView(View* superview, const LG::Rect& frame);
void set_target_window_id(int winid) { m_target_window_id = winid; }
void display(const LG::Rect& rect) override;
void mouse_up() override { on_click(); }
virtual void mouse_entered(const LG::Point<int>& location) override
{
View::mouse_entered(location);
set_needs_display();
}
virtual void mouse_exited() override
{
View::mouse_exited();
set_needs_display();
}
private:
void on_click();
int m_target_window_id { INVALID };
LG::PixelBitmap m_icon;
};

View File

@@ -0,0 +1,19 @@
import("//build/userland/TEMPLATE.gni")
xOS_executable("dock") {
install_path = "System/"
sources = [
"AppDelegate.cpp",
"AppListView.cpp",
"DockView.cpp",
"DockWindow.cpp",
"IconView.cpp",
]
configs = [ "//build/userland:userland_flags" ]
deplibs = [
"libcxx",
"libfoundation",
"libg",
"libui",
]
}

View File

@@ -0,0 +1,29 @@
#pragma once
#include "WindowEntity.h"
#include <libg/PixelBitmap.h>
#include <list>
#include <string>
class DockEntity {
public:
DockEntity() = default;
void set_icon(LG::PixelBitmap&& icon) { m_icon = std::move(icon); }
const LG::PixelBitmap& icon() const { return m_icon; }
void set_path_to_exec(const std::string& path) { m_path_to_exec = path; }
const std::string& path_to_exec() const { return m_path_to_exec; }
void set_bundle_id(const std::string& bid) { m_bundle_id = bid; }
const std::string& bundle_id() const { return m_bundle_id; }
void add_window(const WindowEntity& went) { m_windows.push_front(went); }
const std::list<WindowEntity>& windows() const { return m_windows; }
std::list<WindowEntity>& windows() { return m_windows; }
private:
LG::PixelBitmap m_icon;
std::string m_path_to_exec {};
std::string m_bundle_id {};
std::list<WindowEntity> m_windows {};
};

View File

@@ -0,0 +1,162 @@
#include "DockView.h"
#include "AppListView.h"
#include "IconView.h"
#include <algorithm>
#include <cstdlib>
#include <libfoundation/EventLoop.h>
#include <libfoundation/KeyboardMapping.h>
#include <libg/Color.h>
#include <libg/ImageLoaders/PNGLoader.h>
#include <libui/App.h>
#include <libui/Context.h>
#include <unistd.h>
static DockView* this_view;
DockView::DockView(UI::View* superview, const LG::Rect& frame)
: UI::View(superview, frame)
{
init_fill_bounds();
init_subviews();
}
DockView::DockView(UI::View* superview, UI::Window* window, const LG::Rect& frame)
: UI::View(superview, window, frame)
{
init_fill_bounds();
init_subviews();
}
void DockView::init_fill_bounds()
{
m_fill_bounds = bounds();
m_fill_bounds.set_x(bounds().mid_x());
m_fill_bounds.set_width(0);
fill_bounds_expand(2 * padding());
}
void DockView::init_subviews()
{
auto& dock_stack_view = add_subview<UI::StackView>(bounds());
dock_stack_view.set_spacing(padding());
dock_stack_view.set_background_color(LG::Color::Opaque);
dock_stack_view.set_axis(UI::LayoutConstraints::Axis::Horizontal);
dock_stack_view.set_distribution(UI::StackView::Distribution::EqualCentering);
m_dock_stackview = &dock_stack_view;
add_system_buttons();
}
void DockView::add_system_buttons()
{
fill_bounds_expand(icon_view_size() + padding());
auto& icon_view = m_dock_stackview->add_arranged_subview<AppListView>();
icon_view.add_constraint(UI::Constraint(icon_view, UI::Constraint::Attribute::Height, UI::Constraint::Relation::Equal, icon_view_size()));
icon_view.add_constraint(UI::Constraint(icon_view, UI::Constraint::Attribute::Width, UI::Constraint::Relation::Equal, icon_view_size()));
m_applist_view = &icon_view;
}
void DockView::display(const LG::Rect& rect)
{
LG::Context ctx = UI::graphics_current_context();
ctx.add_clip(rect);
ctx.set_fill_color(background_color());
ctx.fill_rounded(fill_bounds(), LG::CornerMask(4, LG::CornerMask::Masked, LG::CornerMask::NonMasked));
}
void DockView::new_dock_entity(const std::string& exec_path, const std::string& icon_path, const std::string& bundle_id)
{
LG::PNG::PNGLoader loader;
fill_bounds_expand(icon_view_size() + padding());
auto& icon_view = m_dock_stackview->add_arranged_subview<IconView>();
icon_view.add_constraint(UI::Constraint(icon_view, UI::Constraint::Attribute::Height, UI::Constraint::Relation::Equal, icon_view_size()));
icon_view.add_constraint(UI::Constraint(icon_view, UI::Constraint::Attribute::Width, UI::Constraint::Relation::Equal, icon_view_size()));
icon_view.entity().set_icon(loader.load_from_file(icon_path + "/32x32.png"));
icon_view.entity().set_path_to_exec(std::move(exec_path));
icon_view.entity().set_bundle_id(std::move(bundle_id));
m_icon_views.push_back(&icon_view);
set_needs_layout();
}
WindowEntity* DockView::find_window_entry(int window_id)
{
for (auto* view : m_icon_views) {
for (auto& wins : view->entity().windows()) {
if (wins.window_id() == window_id) {
return &wins;
}
}
}
return nullptr;
}
void DockView::on_window_create(const std::string& bundle_id, const std::string& icon_path, int window_id, int window_type)
{
// Don't add an icon of dock (self).
if (window()->id() == window_id) {
return;
}
if (window_type == WindowType::AppList) {
if (m_applist_view) {
m_applist_view->set_target_window_id(window_id);
}
return;
}
for (auto* view : m_icon_views) {
if (view->entity().bundle_id() == bundle_id) {
view->entity().add_window(WindowEntity(window_id));
set_needs_display();
return;
}
}
new_dock_entity("", icon_path, bundle_id);
for (auto* view : m_icon_views) {
if (view->entity().bundle_id() == bundle_id) {
view->entity().add_window(WindowEntity(window_id));
set_needs_display();
return;
}
}
}
void DockView::on_window_minimize(int window_id)
{
auto* ent = find_window_entry(window_id);
if (!ent) {
return;
}
ent->set_minimized(true);
set_needs_display();
}
void DockView::on_window_remove(int window_id)
{
// TODO: Currently icons are not properly deleted.
for (auto* view : m_icon_views) {
for (auto& wins : view->entity().windows()) {
if (wins.window_id() == window_id) {
auto& win = view->entity().windows();
win.erase(std::find(win.begin(), win.end(), WindowEntity(window_id)));
set_needs_display();
return;
}
}
}
}
void DockView::set_icon(int window_id, const std::string& path)
{
}
void DockView::set_title(int window_id, const std::string& title)
{
auto* ent = find_window_entry(window_id);
if (!ent) {
return;
}
ent->set_title(title);
}

View File

@@ -0,0 +1,49 @@
#pragma once
#include "AppListView.h"
#include "DockEntity.h"
#include "IconView.h"
#include "WindowEntity.h"
#include <libg/Font.h>
#include <libui/StackView.h>
#include <libui/View.h>
#include <list>
#include <string>
class DockView : public UI::View {
UI_OBJECT();
public:
DockView(UI::View* superview, const LG::Rect& frame);
DockView(UI::View* superview, UI::Window* window, const LG::Rect& frame);
static constexpr size_t padding() { return 4; }
static constexpr size_t dock_view_height() { return 50; }
static constexpr int icon_size() { return 32; }
static constexpr int icon_view_size() { return (int)dock_view_height(); }
void display(const LG::Rect& rect) override;
WindowEntity* find_window_entry(int window_id);
void on_window_create(const std::string& bundle_id, const std::string& icon_path, int window_id, int window_type);
void on_window_remove(int window_id);
void on_window_minimize(int window_id);
void set_icon(int window_id, const std::string& path);
void set_title(int window_id, const std::string& title);
void add_system_buttons();
void new_dock_entity(const std::string& exec_path, const std::string& icon_path, const std::string& bundle_id);
private:
void init_subviews();
void init_fill_bounds();
void fill_bounds_expand(size_t l) { m_fill_bounds.set_width(m_fill_bounds.width() + l), m_fill_bounds.set_x(m_fill_bounds.min_x() - l / 2); }
const LG::Rect& fill_bounds() const { return m_fill_bounds; }
void launch(const DockEntity& ent);
LG::Rect m_fill_bounds {};
UI::StackView* m_dock_stackview {};
AppListView* m_applist_view {};
std::list<IconView*> m_icon_views {};
};

View File

@@ -0,0 +1,31 @@
#pragma once
#include "DockView.h"
#include <libui/App.h>
#include <libui/Button.h>
#include <libui/Label.h>
#include <libui/View.h>
#include <libui/ViewController.h>
#include <libui/Window.h>
#include <memory>
#include <sys/types.h>
class DockViewController : public UI::ViewController<DockView> {
public:
DockViewController(DockView& view)
: UI::ViewController<DockView>(view)
{
}
virtual ~DockViewController() = default;
virtual void view_did_load() override
{
view().set_background_color(LG::Color::LightSystemOpaque);
view().new_dock_entity("/Applications/about.app/Content/about", "/res/icons/apps/about.icon", "com.x.about");
view().new_dock_entity("/Applications/terminal.app/Content/terminal", "/res/icons/apps/terminal.icon", "com.x.terminal");
view().new_dock_entity("/Applications/activity_monitor.app/Content/activity_monitor", "/res/icons/apps/activity_monitor.icon", "com.x.activity_monitor");
view().new_dock_entity("/Applications/calculator.app/Content/calculator", "/res/icons/apps/calculator.icon", "com.x.calculator");
view().set_needs_display();
}
private:
};

View File

@@ -0,0 +1,42 @@
#include "DockWindow.h"
#include "DockView.h"
void DockWindow::receive_event(std::unique_ptr<LFoundation::Event> event)
{
switch (event->type()) {
case UI::Event::Type::NotifyWindowCreateEvent: {
UI::NotifyWindowCreateEvent& own_event = *(UI::NotifyWindowCreateEvent*)event.get();
DockView* it = (DockView*)superview();
it->on_window_create(own_event.bundle_id(), own_event.icon_path(), own_event.window_id(), own_event.window_type());
break;
}
case UI::Event::Type::NotifyWindowStatusChangedEvent: {
UI::NotifyWindowStatusChangedEvent& own_event = *(UI::NotifyWindowStatusChangedEvent*)event.get();
DockView* it = (DockView*)superview();
if (own_event.type() == UI::WindowStatusUpdateType::Removed) {
it->on_window_remove(own_event.changed_window_id());
}
if (own_event.type() == UI::WindowStatusUpdateType::Minimized) {
it->on_window_minimize(own_event.changed_window_id());
}
break;
}
case UI::Event::Type::NotifyWindowIconChangedEvent: {
UI::NotifyWindowIconChangedEvent& own_event = *(UI::NotifyWindowIconChangedEvent*)event.get();
DockView* it = (DockView*)superview();
it->set_icon(own_event.changed_window_id(), own_event.icon_path());
break;
}
case UI::Event::Type::NotifyWindowTitleChangedEvent: {
UI::NotifyWindowTitleChangedEvent& own_event = *(UI::NotifyWindowTitleChangedEvent*)event.get();
DockView* it = (DockView*)superview();
it->set_title(own_event.changed_window_id(), own_event.title());
break;
}
}
Window::receive_event(std::move(event));
}

View File

@@ -0,0 +1,22 @@
#pragma once
#include <libg/Size.h>
#include <libui/Screen.h>
#include <libui/Window.h>
class DockWindow : public UI::Window {
public:
DockWindow()
: UI::Window("Dock", LG::Size(UI::Screen::main().bounds().width(), 50), UI::WindowType::Homescreen)
{
if (fork() == 0) {
for (int i = 3; i < 32; i++) {
close(i);
}
execlp("/System/applist", "/System/applist", NULL);
std::abort();
}
}
void receive_event(std::unique_ptr<LFoundation::Event> event) override;
};

View File

@@ -0,0 +1,74 @@
#include "IconView.h"
#include "DockView.h"
#include <libui/App.h>
#include <libui/Context.h>
#include <libui/Label.h>
#include <libui/Screen.h>
#include <libui/Window.h>
IconView::IconView(View* superview, const LG::Rect& frame)
: View(superview, frame)
{
}
void IconView::display(const LG::Rect& rect)
{
const int padding = 4;
const int offset_x = (DockView::icon_view_size() - DockView::icon_size()) / 2;
const int offset_y = (DockView::icon_view_size() - DockView::icon_size()) / 2;
LG::Context ctx = UI::graphics_current_context();
ctx.add_clip(rect);
auto icon_rect = LG::Rect(offset_x, offset_y, DockView::icon_size(), DockView::icon_size());
ctx.draw(icon_rect.origin(), m_launch_entity.icon());
if (is_hovered()) {
ctx.set_fill_color(LG::Color::LightSystemOpaque128);
ctx.fill(icon_rect);
}
ctx.set_fill_color(LG::Color(120, 129, 133, 40));
ctx.draw_box_shading(icon_rect, LG::Shading(LG::Shading::Type::Box, 0, 3), LG::CornerMask(6));
ctx.set_fill_color(LG::Color(163, 174, 190));
const int underline_y = DockView::icon_view_size() - underline_height() - padding;
if (entity().windows().size() > 0) {
const int len = 8;
ctx.fill({ (DockView::icon_view_size() - len) / 2, underline_y, len, underline_height() });
}
}
void IconView::on_click()
{
if (entity().windows().empty()) {
launch();
return;
} else {
auto demo_menu = UI::Menu();
for (auto& win : entity().windows()) {
auto title = win.title();
int this_window_id = window()->id();
int target_window_id = win.window_id();
if (win.is_minimized()) {
title += " - minimized";
}
demo_menu.add_item(UI::MenuItem(title, [this, this_window_id, target_window_id] {
for (auto& win : entity().windows()) {
if (win.window_id() == target_window_id) {
win.set_minimized(false);
break;
}
}
auto& app = UI::App::the();
AskBringToFrontMessage msg(app.connection().key(), this_window_id, target_window_id);
app.connection().send_async_message(msg);
}));
}
demo_menu.add_item(UI::MenuItem("New window", [this] {
launch();
}));
window()->popup_manager().show({ frame().min_x(), (int)UI::Screen::main().bounds().height() - (int)DockView::dock_view_height() - 4 }, demo_menu);
}
}

View File

@@ -0,0 +1,61 @@
#pragma once
#include "DockEntity.h"
#include "WindowEntity.h"
#include <libg/Font.h>
#include <libui/Label.h>
#include <libui/PopupMenu.h>
#include <libui/View.h>
#include <list>
#include <string>
#include <unistd.h>
class IconView : public UI::View {
UI_OBJECT();
public:
IconView(View* superview, const LG::Rect& frame);
void display(const LG::Rect& rect) override;
void mouse_up() override { on_click(); }
static constexpr size_t underline_height() { return 2; }
void set_title(const std::string& title)
{
if (!m_label) {
return;
}
m_label->set_text(title);
}
DockEntity& entity() { return m_launch_entity; }
const DockEntity& entity() const { return m_launch_entity; }
virtual void mouse_entered(const LG::Point<int>& location) override
{
View::mouse_entered(location);
set_needs_display();
}
virtual void mouse_exited() override
{
View::mouse_exited();
set_needs_display();
}
private:
void on_click();
void launch()
{
if (fork() == 0) {
for (int i = 3; i < 32; i++) {
close(i);
}
execlp(m_launch_entity.path_to_exec().c_str(), m_launch_entity.path_to_exec().c_str(), NULL);
std::abort();
}
}
UI::Label* m_label;
DockEntity m_launch_entity;
};

View File

@@ -0,0 +1,43 @@
#pragma once
#include <libg/PixelBitmap.h>
#include <string>
class WindowEntity {
public:
enum Status : uint32_t {
Minimized = (1 << 0),
};
WindowEntity()
: m_window_id(0)
, m_title()
{
}
WindowEntity(int window_id)
: m_window_id(window_id)
, m_title()
{
}
bool operator==(const WindowEntity& other) const { return m_window_id == other.m_window_id; }
bool operator!=(const WindowEntity& other) const { return m_window_id != other.m_window_id; }
int window_id() const { return m_window_id; }
bool is_minimized() const { return has_attr(Status::Minimized); }
void set_minimized(bool b) { b ? set_attr(Status::Minimized) : rem_attr(Status::Minimized); }
const std::string& title() const { return m_title; }
void set_title(const std::string& title) { m_title = title; }
void set_title(std::string&& title) { m_title = std::move(title); }
private:
inline bool has_attr(Status mode) const { return ((m_window_status & (uint32_t)mode) == (uint32_t)mode); }
inline void set_attr(Status mode) { m_window_status |= (uint32_t)mode; }
inline void rem_attr(Status mode) { m_window_status = m_window_status & (~(uint32_t)mode); }
int m_window_id { 0 };
uint32_t m_window_status { 0 };
std::string m_title {};
};