diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 9d7f383a..e370d0e4 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -49,3 +49,5 @@ luna_app(shmem-test.cpp shmem-test) luna_app(touch.cpp touch) luna_app(gclient.cpp gclient) target_link_libraries(gclient PUBLIC ui) +luna_app(taskbar.cpp taskbar) +target_link_libraries(taskbar PUBLIC ui) diff --git a/apps/taskbar.cpp b/apps/taskbar.cpp new file mode 100644 index 00000000..f6e7ba38 --- /dev/null +++ b/apps/taskbar.cpp @@ -0,0 +1,23 @@ +#include +#include + +Result luna_main(int argc, char** argv) +{ + ui::App app; + TRY(app.init(argc, argv)); + + 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, false)); + app.set_main_window(window); + window->set_background(ui::GRAY); + + ui::HorizontalLayout layout(ui::AdjustHeight::Yes, ui::AdjustWidth::No); + window->set_main_widget(layout); + + window->draw(); + + return app.run(); +} diff --git a/base/etc/user/00-taskbar b/base/etc/user/00-taskbar new file mode 100644 index 00000000..19614216 --- /dev/null +++ b/base/etc/user/00-taskbar @@ -0,0 +1,4 @@ +Name=taskbar +Description=Start the taskbar. +Command=/usr/bin/taskbar +Restart=true diff --git a/base/etc/user/00-gclient b/base/etc/user/01-gclient similarity index 100% rename from base/etc/user/00-gclient rename to base/etc/user/01-gclient diff --git a/libui/include/ui/App.h b/libui/include/ui/App.h index 0e1e1262..231c9af3 100644 --- a/libui/include/ui/App.h +++ b/libui/include/ui/App.h @@ -23,6 +23,8 @@ namespace ui Result init(int, char**); Result run(); + Rect screen_rect(); + os::LocalClient& client() { return *m_client; diff --git a/libui/include/ui/Window.h b/libui/include/ui/Window.h index ee08b0e6..490cf3ec 100644 --- a/libui/include/ui/Window.h +++ b/libui/include/ui/Window.h @@ -19,7 +19,7 @@ namespace ui class Window { public: - static Result create(Rect rect); + static Result create(Rect rect, bool decorated = true); void set_title(StringView title); diff --git a/libui/include/ui/ipc/Client.h b/libui/include/ui/ipc/Client.h index 35b09642..16f6bf68 100644 --- a/libui/include/ui/ipc/Client.h +++ b/libui/include/ui/ipc/Client.h @@ -19,6 +19,7 @@ namespace ui CREATE_WINDOW_RESPONSE_ID, WINDOW_CLOSE_REQUEST_ID, MOUSE_EVENT_REQUEST_ID, + GET_SCREEN_RECT_RESPONSE_ID }; struct CreateWindowResponse @@ -44,4 +45,11 @@ namespace ui Point position; int buttons; }; + + struct GetScreenRectResponse + { + static constexpr u8 ID = GET_SCREEN_RECT_RESPONSE_ID; + + Rect rect; + }; } diff --git a/libui/include/ui/ipc/Server.h b/libui/include/ui/ipc/Server.h index cd18e336..7e675c53 100644 --- a/libui/include/ui/ipc/Server.h +++ b/libui/include/ui/ipc/Server.h @@ -22,6 +22,7 @@ namespace ui SET_WINDOW_TITLE_ID, INVALIDATE_ID, CLOSE_WINDOW_ID, + GET_SCREEN_RECT_ID, }; struct CreateWindowRequest @@ -30,6 +31,7 @@ namespace ui static constexpr u8 ID = CREATE_WINDOW_ID; ui::Rect rect; + bool decorated; }; struct SetWindowTitleRequest @@ -53,4 +55,12 @@ namespace ui int window; }; + + struct GetScreenRectRequest + { + using ResponseType = GetScreenRectResponse; + static constexpr u8 ID = GET_SCREEN_RECT_ID; + + int _shadow; // Unused. + }; } diff --git a/libui/src/App.cpp b/libui/src/App.cpp index 30ea1ff4..7a979206 100644 --- a/libui/src/App.cpp +++ b/libui/src/App.cpp @@ -12,6 +12,7 @@ #include #include #include +#include Result handle_ipc_client_event(os::LocalClient&, u8 id) { @@ -60,6 +61,13 @@ namespace ui return *s_app; } + Rect App::screen_rect() + { + ui::GetScreenRectRequest request {}; + auto response = os::IPC::send_sync(*m_client, request).release_value(); + return response.rect; + } + Result App::register_window(OwnedPtr&& window, Badge) { int id = window->id(); diff --git a/libui/src/Window.cpp b/libui/src/Window.cpp index 8d50ce72..99d2e66d 100644 --- a/libui/src/Window.cpp +++ b/libui/src/Window.cpp @@ -39,12 +39,13 @@ static Result create_shm_region(const char* path, int* outfd, ui::Rect rec namespace ui { - Result Window::create(Rect rect) + Result Window::create(Rect rect, bool decorated) { auto window = TRY(make_owned()); ui::CreateWindowRequest request; request.rect = rect; + request.decorated = decorated; auto response = TRY(os::IPC::send_sync(App::the().client(), request)); u32* pixels = TRY(create_shm_region(response.shm_path, nullptr, rect)); diff --git a/wind/IPC.cpp b/wind/IPC.cpp index 3abeedf4..dbec731f 100644 --- a/wind/IPC.cpp +++ b/wind/IPC.cpp @@ -1,4 +1,5 @@ #include "IPC.h" +#include "Screen.h" #include #include #include @@ -87,11 +88,17 @@ static Result handle_create_window_message(Client& client) READ_MESSAGE(request); request.rect = request.rect.normalized(); - request.rect.height += Window::titlebar_height(); // Make sure we provide the full contents rect that was asked for. + + if (request.decorated) + { + request.rect.height += + Window::titlebar_height(); // Make sure we provide the full contents rect that was asked for. + request.rect.pos.y -= Window::titlebar_height(); // Adjust it so the contents begin at the expected coordinates. + } auto name = TRY(String::from_cstring("Window")); - auto* window = new (std::nothrow) Window(request.rect, move(name)); + auto* window = new (std::nothrow) Window(request.rect, move(name), request.decorated); if (!window) { os::IPC::send_error(client.conn, ENOMEM); @@ -158,6 +165,18 @@ static Result handle_close_window_message(Client& client) return {}; } +static Result handle_get_screen_rect_message(Client& client) +{ + ui::GetScreenRectRequest request; + READ_MESSAGE(request); // Kinda pointless, but required. + + ui::GetScreenRectResponse response; + response.rect = Screen::the().canvas().rect(); + os::IPC::send_async(client.conn, response); + + return {}; +} + namespace wind { Result handle_ipc_message(Client& client, u8 id) @@ -169,6 +188,7 @@ namespace wind case ui::SET_WINDOW_TITLE_ID: return handle_set_window_title_message(client); case ui::INVALIDATE_ID: return handle_invalidate_message(client); case ui::CLOSE_WINDOW_ID: return handle_close_window_message(client); + case ui::GET_SCREEN_RECT_ID: return handle_get_screen_rect_message(client); default: os::eprintln("wind: Invalid IPC message from client!"); return err(EINVAL); } } diff --git a/wind/Screen.cpp b/wind/Screen.cpp index 8d0e224c..48ce774a 100644 --- a/wind/Screen.cpp +++ b/wind/Screen.cpp @@ -5,7 +5,9 @@ #include #include -Result Screen::open() +Screen Screen::s_the; + +Result Screen::open() { int fd = ::open("/dev/fb0", O_RDWR); if (fd < 0) return err(errno); @@ -23,7 +25,9 @@ Result Screen::open() screen.m_canvas = ui::Canvas::create((u8*)p, width, height); screen.m_size = width * height * BYTES_PER_PIXEL; - return screen; + s_the = screen; + + return {}; } void Screen::sync() diff --git a/wind/Screen.h b/wind/Screen.h index a98295c6..543b24f9 100644 --- a/wind/Screen.h +++ b/wind/Screen.h @@ -7,7 +7,7 @@ constexpr int BYTES_PER_PIXEL = 4; class Screen { public: - static Result open(); + static Result open(); ui::Canvas& canvas() { @@ -19,9 +19,16 @@ class Screen return m_size; } + static Screen& the() + { + return s_the; + } + void sync(); private: ui::Canvas m_canvas; int m_size; + + static Screen s_the; }; diff --git a/wind/Window.cpp b/wind/Window.cpp index 6e6e4eca..43e0e5ad 100644 --- a/wind/Window.cpp +++ b/wind/Window.cpp @@ -41,14 +41,15 @@ void Window::focus() g_windows.append(this); } -Window::Window(ui::Rect r, String&& n) : surface(r), name(move(n)) +Window::Window(ui::Rect r, String&& n, bool d) : surface(r), name(move(n)), decorated(d) { auto font = ui::Font::default_font(); - if (surface.width < 36) surface.width = 36; - if (surface.height < (font->height() + 20)) surface.height = font->height() + 20; - titlebar = ui::Rect { 0, 0, surface.width, font->height() + 20 }; - close_button = ui::Rect { surface.width - 26, 10, 16, 16 }; - contents = ui::Rect { 0, font->height() + 20, surface.width, surface.height - (font->height() + 20) }; + if (decorated && surface.width < 36) surface.width = 36; + if (decorated && surface.height < (font->height() + 20)) surface.height = font->height() + 20; + titlebar = decorated ? ui::Rect { 0, 0, surface.width, font->height() + 20 } : ui::Rect { 0, 0, 0, 0 }; + close_button = decorated ? ui::Rect { surface.width - 26, 10, 16, 16 } : ui::Rect { 0, 0, 0, 0 }; + contents = decorated ? ui::Rect { 0, font->height() + 20, surface.width, surface.height - (font->height() + 20) } + : ui::Rect { 0, 0, surface.width, surface.height }; g_windows.append(this); } diff --git a/wind/Window.h b/wind/Window.h index a5cddaaf..9fcf33b2 100644 --- a/wind/Window.h +++ b/wind/Window.h @@ -18,10 +18,11 @@ struct Window : public LinkedListNode bool dirty { false }; Client* client; int id; + bool decorated; static int titlebar_height(); - Window(ui::Rect, String&&); + Window(ui::Rect, String&&, bool); ~Window(); void focus(); diff --git a/wind/main.cpp b/wind/main.cpp index 9ebd3e6a..0dd625dc 100644 --- a/wind/main.cpp +++ b/wind/main.cpp @@ -49,7 +49,8 @@ Result luna_main(int argc, char** argv) keyboard->set_buffer(os::File::NotBuffered); keyboard->set_close_on_exec(); - auto screen = TRY(Screen::open()); + TRY(Screen::open()); + auto& screen = Screen::the(); Mouse mouse_pointer { screen.canvas() };