wind+libui+taskbar: Add GetScreenRect IPC, non-decorated windows, taskbar

This commit is contained in:
apio 2023-08-15 12:56:55 +02:00
parent d78d76ad16
commit 4c7828f0eb
Signed by: apio
GPG Key ID: B8A7D06E42258954
16 changed files with 107 additions and 15 deletions

View File

@ -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)

23
apps/taskbar.cpp Normal file
View File

@ -0,0 +1,23 @@
#include <ui/App.h>
#include <ui/Layout.h>
Result<int> 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();
}

4
base/etc/user/00-taskbar Normal file
View File

@ -0,0 +1,4 @@
Name=taskbar
Description=Start the taskbar.
Command=/usr/bin/taskbar
Restart=true

View File

@ -23,6 +23,8 @@ namespace ui
Result<void> init(int, char**);
Result<int> run();
Rect screen_rect();
os::LocalClient& client()
{
return *m_client;

View File

@ -19,7 +19,7 @@ namespace ui
class Window
{
public:
static Result<Window*> create(Rect rect);
static Result<Window*> create(Rect rect, bool decorated = true);
void set_title(StringView title);

View File

@ -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;
};
}

View File

@ -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.
};
}

View File

@ -12,6 +12,7 @@
#include <os/IPC.h>
#include <ui/App.h>
#include <ui/ipc/Client.h>
#include <ui/ipc/Server.h>
Result<void> 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<ui::GetScreenRectResponse>(*m_client, request).release_value();
return response.rect;
}
Result<void> App::register_window(OwnedPtr<Window>&& window, Badge<Window>)
{
int id = window->id();

View File

@ -39,12 +39,13 @@ static Result<u32*> create_shm_region(const char* path, int* outfd, ui::Rect rec
namespace ui
{
Result<Window*> Window::create(Rect rect)
Result<Window*> Window::create(Rect rect, bool decorated)
{
auto window = TRY(make_owned<Window>());
ui::CreateWindowRequest request;
request.rect = rect;
request.decorated = decorated;
auto response = TRY(os::IPC::send_sync<ui::CreateWindowResponse>(App::the().client(), request));
u32* pixels = TRY(create_shm_region(response.shm_path, nullptr, rect));

View File

@ -1,4 +1,5 @@
#include "IPC.h"
#include "Screen.h"
#include <errno.h>
#include <luna/Alignment.h>
#include <luna/String.h>
@ -87,11 +88,17 @@ static Result<void> 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<void> handle_close_window_message(Client& client)
return {};
}
static Result<void> 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<void> 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);
}
}

View File

@ -5,7 +5,9 @@
#include <sys/mman.h>
#include <unistd.h>
Result<Screen> Screen::open()
Screen Screen::s_the;
Result<void> Screen::open()
{
int fd = ::open("/dev/fb0", O_RDWR);
if (fd < 0) return err(errno);
@ -23,7 +25,9 @@ Result<Screen> 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()

View File

@ -7,7 +7,7 @@ constexpr int BYTES_PER_PIXEL = 4;
class Screen
{
public:
static Result<Screen> open();
static Result<void> 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;
};

View File

@ -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);
}

View File

@ -18,10 +18,11 @@ struct Window : public LinkedListNode<Window>
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();

View File

@ -49,7 +49,8 @@ Result<int> 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() };