2023-08-03 10:20:59 +00:00
|
|
|
#include "Mouse.h"
|
|
|
|
#include "Screen.h"
|
2023-08-03 15:38:49 +00:00
|
|
|
#include "Window.h"
|
2023-08-03 10:20:59 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <moon/Keyboard.h>
|
|
|
|
#include <os/ArgumentParser.h>
|
|
|
|
#include <os/File.h>
|
2023-08-03 14:40:17 +00:00
|
|
|
#include <os/LocalServer.h>
|
2023-08-07 20:51:28 +00:00
|
|
|
#include <os/Process.h>
|
2023-08-03 10:20:59 +00:00
|
|
|
#include <pwd.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/poll.h>
|
2023-08-06 10:45:13 +00:00
|
|
|
#include <time.h>
|
2023-08-03 10:20:59 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
Result<int> luna_main(int argc, char** argv)
|
|
|
|
{
|
2023-08-06 10:45:13 +00:00
|
|
|
srand((unsigned)time(NULL));
|
|
|
|
|
2023-08-03 10:20:59 +00:00
|
|
|
StringView socket_path = "/tmp/wind.sock";
|
|
|
|
StringView user;
|
|
|
|
|
|
|
|
os::ArgumentParser parser;
|
|
|
|
parser.add_description("The display server for Luna's graphical user interface."_sv);
|
|
|
|
parser.add_system_program_info("wind"_sv);
|
|
|
|
parser.add_value_argument(socket_path, 's', "socket"_sv, "the path for the local IPC socket"_sv);
|
|
|
|
parser.add_value_argument(user, 'u', "user"_sv, "the user to run as"_sv);
|
|
|
|
parser.parse(argc, argv);
|
|
|
|
|
|
|
|
if (geteuid() != 0)
|
|
|
|
{
|
|
|
|
os::eprintln("error: wind must be run as root to initialize resources, run with --user=<USERNAME> to drop "
|
|
|
|
"privileges afterwards");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto mouse = TRY(os::File::open("/dev/mouse", os::File::ReadOnly));
|
|
|
|
mouse->set_buffer(os::File::NotBuffered);
|
|
|
|
mouse->set_close_on_exec();
|
|
|
|
|
|
|
|
auto keyboard = TRY(os::File::open("/dev/kbd", os::File::ReadOnly));
|
|
|
|
keyboard->set_buffer(os::File::NotBuffered);
|
|
|
|
keyboard->set_close_on_exec();
|
|
|
|
|
|
|
|
auto screen = TRY(Screen::open());
|
|
|
|
|
|
|
|
Mouse mouse_pointer { screen.canvas() };
|
|
|
|
|
|
|
|
ioctl(STDIN_FILENO, TTYSETGFX, 1);
|
|
|
|
|
|
|
|
setpgid(0, 0);
|
|
|
|
|
|
|
|
int fd = open("/dev/null", O_RDONLY);
|
|
|
|
if (fd >= 0)
|
|
|
|
{
|
|
|
|
dup2(fd, STDIN_FILENO);
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
clearenv();
|
|
|
|
|
|
|
|
if (!user.is_empty())
|
|
|
|
{
|
|
|
|
auto* pwd = getpwnam(user.chars());
|
|
|
|
if (pwd)
|
|
|
|
{
|
|
|
|
setgid(pwd->pw_gid);
|
|
|
|
setuid(pwd->pw_uid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-07 20:51:28 +00:00
|
|
|
auto server = TRY(os::LocalServer::create(socket_path, false));
|
|
|
|
TRY(server->listen(20));
|
|
|
|
|
|
|
|
StringView args[] = { "/usr/bin/gclient"_sv };
|
|
|
|
TRY(os::Process::spawn("/usr/bin/gclient"_sv, Slice<StringView> { args, 1 }, false));
|
|
|
|
|
2023-08-03 10:20:59 +00:00
|
|
|
ui::Color background = ui::BLACK;
|
|
|
|
|
2023-08-04 14:08:58 +00:00
|
|
|
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));
|
2023-08-03 15:38:49 +00:00
|
|
|
|
2023-08-08 09:40:22 +00:00
|
|
|
Vector<os::LocalServer::Client> clients;
|
2023-08-03 14:40:17 +00:00
|
|
|
|
2023-08-03 10:20:59 +00:00
|
|
|
while (1)
|
|
|
|
{
|
2023-08-03 15:38:49 +00:00
|
|
|
screen.canvas().fill(background);
|
|
|
|
for (auto* window : g_windows) window->draw(screen.canvas());
|
|
|
|
mouse_pointer.draw(screen.canvas());
|
|
|
|
screen.sync();
|
|
|
|
|
2023-08-03 10:20:59 +00:00
|
|
|
struct pollfd fds[] = {
|
|
|
|
{ .fd = mouse->fd(), .events = POLLIN, .revents = 0 },
|
|
|
|
{ .fd = keyboard->fd(), .events = POLLIN, .revents = 0 },
|
2023-08-03 14:40:17 +00:00
|
|
|
{ .fd = server->fd(), .events = POLLIN, .revents = 0 },
|
2023-08-03 10:20:59 +00:00
|
|
|
};
|
|
|
|
|
2023-08-03 14:40:17 +00:00
|
|
|
int rc = poll(fds, 3, 1000);
|
2023-08-03 10:20:59 +00:00
|
|
|
if (!rc) continue;
|
2023-08-07 20:51:28 +00:00
|
|
|
if (rc < 0 && errno != EINTR) { os::println("poll: error: %s", strerror(errno)); }
|
2023-08-03 10:20:59 +00:00
|
|
|
|
|
|
|
if (fds[0].revents & POLLIN)
|
|
|
|
{
|
|
|
|
moon::MousePacket packet;
|
|
|
|
TRY(mouse->read_typed(packet));
|
2023-08-03 15:38:49 +00:00
|
|
|
mouse_pointer.update(packet);
|
2023-08-03 10:20:59 +00:00
|
|
|
}
|
|
|
|
if (fds[1].revents & POLLIN)
|
|
|
|
{
|
|
|
|
moon::KeyboardPacket packet;
|
|
|
|
TRY(keyboard->read_typed(packet));
|
2023-08-06 10:45:13 +00:00
|
|
|
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)));
|
|
|
|
}
|
2023-08-03 10:20:59 +00:00
|
|
|
}
|
2023-08-03 14:40:17 +00:00
|
|
|
if (fds[2].revents & POLLIN)
|
|
|
|
{
|
|
|
|
auto client = TRY(server->accept());
|
|
|
|
os::println("wind: New client connected!");
|
2023-08-08 09:40:22 +00:00
|
|
|
TRY(clients.try_append(move(client)));
|
2023-08-03 14:40:17 +00:00
|
|
|
}
|
2023-08-03 10:20:59 +00:00
|
|
|
}
|
|
|
|
}
|