wind: Handle CreateWindow IPC messages

This commit is contained in:
apio 2023-08-14 18:15:29 +02:00
parent 1eb00eabfa
commit d3dd257dc1
Signed by: apio
GPG Key ID: B8A7D06E42258954
7 changed files with 126 additions and 22 deletions

View File

@ -6,6 +6,9 @@ set(SOURCES
Mouse.cpp
Window.h
Window.cpp
IPC.cpp
IPC.h
Client.h
)
add_executable(wind ${SOURCES})

11
wind/Client.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include "Window.h"
#include <os/LocalServer.h>
struct Client
{
os::LocalServer::Client conn;
Vector<Window*> windows;
bool rpc_in_progress { false };
u8 rpc_id { 0 };
};

75
wind/IPC.cpp Normal file
View File

@ -0,0 +1,75 @@
#include "IPC.h"
#include <luna/String.h>
#include <os/File.h>
static Result<void> handle_create_window_message(Client& client)
{
ui::CreateWindowRequest request;
auto rc = client.conn.recv_typed(request);
if (rc.has_error())
{
if (rc.error() == EAGAIN)
{
client.rpc_in_progress = true;
client.rpc_id = ui::CREATE_WINDOW_ID;
return {};
}
else
return rc.release_error();
}
request.rect = request.rect.normalized();
request.rect.height += Window::titlebar_height(); // Make sure we provide the full contents rect that was asked for.
auto name = COPY_IPC_STRING(request.name);
auto* window = new (std::nothrow) Window(request.rect, request.color, move(name));
if (!window)
{
os::IPC::send_error(client.conn, ENOMEM);
return {};
}
int id = static_cast<int>(client.windows.size());
rc = client.windows.try_append(window);
if (rc.has_error())
{
delete window;
os::IPC::send_error(client.conn, rc.error());
return {};
}
ui::CreateWindowResponse response;
response.window = id;
os::IPC::send_async(client.conn, response);
return {};
}
namespace wind
{
Result<void> handle_ipc_message(Client& client, u8 id)
{
client.rpc_in_progress = false;
switch (id)
{
case ui::CREATE_WINDOW_ID: return handle_create_window_message(client);
default: os::eprintln("wind: Invalid IPC message from client!"); return err(EINVAL);
}
}
Result<void> handle_ipc(Client& client)
{
if (client.rpc_in_progress) return handle_ipc_message(client, client.rpc_id);
u8 id;
auto rc = client.conn.recv_typed(id);
if (rc.has_error())
{
if (rc.error() == EAGAIN) { return {}; }
else
return rc.release_error();
}
return handle_ipc_message(client, id);
}
}

10
wind/IPC.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include "Client.h"
#include <ui/ipc/Server.h>
namespace wind
{
Result<void> handle_ipc_message(Client& client, u8 id);
Result<void> handle_ipc(Client& client);
}

View File

@ -38,7 +38,7 @@ void Window::focus()
g_windows.append(this);
}
Window::Window(ui::Rect r, ui::Color c, StringView n) : surface(r), color(c), name(n)
Window::Window(ui::Rect r, ui::Color c, String&& n) : surface(r), color(c), name(move(n))
{
auto font = ui::Font::default_font();
if (surface.width < 36) surface.width = 36;
@ -48,3 +48,9 @@ Window::Window(ui::Rect r, ui::Color c, StringView n) : surface(r), color(c), na
contents = ui::Rect { 0, font->height() + 20, surface.width, surface.height - (font->height() + 20) };
g_windows.append(this);
}
int Window::titlebar_height()
{
auto font = ui::Font::default_font();
return font->height() + 20;
}

View File

@ -1,6 +1,6 @@
#pragma once
#include <luna/LinkedList.h>
#include <luna/StringView.h>
#include <luna/String.h>
#include <ui/Canvas.h>
#include <ui/Color.h>
#include <ui/Rect.h>
@ -12,9 +12,11 @@ struct Window : public LinkedListNode<Window>
ui::Rect close_button;
ui::Rect contents;
ui::Color color;
StringView name;
String name;
Window(ui::Rect, ui::Color, StringView);
static int titlebar_height();
Window(ui::Rect, ui::Color, String&&);
void focus();

View File

@ -1,3 +1,5 @@
#include "Client.h"
#include "IPC.h"
#include "Mouse.h"
#include "Screen.h"
#include "Window.h"
@ -20,7 +22,7 @@ Result<int> luna_main(int argc, char** argv)
{
srand((unsigned)time(NULL));
TRY(os::Security::pledge("stdio rpath wpath cpath unix proc exec tty id", NULL));
TRY(os::Security::pledge("stdio rpath wpath cpath unix proc exec tty signal id", NULL));
StringView socket_path = "/tmp/wind.sock";
StringView user;
@ -82,17 +84,13 @@ Result<int> luna_main(int argc, char** argv)
ui::Color background = ui::BLACK;
TRY(make<Window>(ui::Rect { 200, 200, 600, 400 }, ui::GREEN, "Calculator"_sv));
TRY(make<Window>(ui::Rect { 100, 100, 300, 200 }, ui::RED, "Settings"_sv));
TRY(make<Window>(ui::Rect { 600, 130, 350, 250 }, ui::CYAN, "File Manager"_sv));
Vector<os::LocalServer::Client> clients;
Vector<Client> clients;
Vector<struct pollfd> fds;
TRY(fds.try_append({ .fd = mouse->fd(), .events = POLLIN, .revents = 0 }));
TRY(fds.try_append({ .fd = keyboard->fd(), .events = POLLIN, .revents = 0 }));
TRY(fds.try_append({ .fd = server->fd(), .events = POLLIN, .revents = 0 }));
TRY(os::Security::pledge("stdio rpath unix", NULL));
TRY(os::Security::pledge("stdio rpath unix signal proc", NULL));
while (1)
{
@ -117,24 +115,22 @@ Result<int> luna_main(int argc, char** argv)
{
moon::KeyboardPacket packet;
TRY(keyboard->read_typed(packet));
if (!packet.released)
{
TRY(make<Window>(ui::Rect { rand() % screen.canvas().width, rand() % screen.canvas().height,
rand() % screen.canvas().width, rand() % screen.canvas().height },
ui::Color::from_rgb(static_cast<u8>(rand() % 256), static_cast<u8>(rand() % 256),
static_cast<u8>(rand() % 256)),
strerror(packet.key)));
}
os::println("%s key %d", packet.released ? "Released" : "Pressed", packet.key);
}
for (usize i = 0; i < clients.size(); i++)
{
if (fds[i + 3].revents & POLLIN) os::println("wind: Client %d sent data!", i);
if (fds[i + 3].revents & POLLIN) wind::handle_ipc(clients[i]);
if (fds[i + 3].revents & POLLHUP)
{
os::println("wind: Client %d disconnected", i);
fds.remove_at(i + 3);
auto client = clients.remove_at(i);
client.disconnect();
client.conn.disconnect();
for (auto& window : client.windows)
{
g_windows.remove(window);
delete window;
}
}
}
if (fds[2].revents & POLLIN)
@ -142,7 +138,8 @@ Result<int> luna_main(int argc, char** argv)
auto client = TRY(server->accept());
os::println("wind: New client connected!");
TRY(fds.try_append({ .fd = client.fd(), .events = POLLIN, .revents = 0 }));
TRY(clients.try_append(move(client)));
Client c { move(client), {} };
TRY(clients.try_append(move(c)));
}
}
}