#include "Mouse.h" #include "Screen.h" #include "Window.h" #include #include #include #include #include #include #include #include #include #include #include #include Result luna_main(int argc, char** argv) { srand((unsigned)time(NULL)); 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= 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()); auto server = TRY(os::LocalServer::create(socket_path, false)); TRY(server->listen(20)); 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); } } ui::Color background = ui::BLACK; TRY(make(ui::Rect { 200, 200, 600, 400 }, ui::GREEN, "Calculator"_sv)); TRY(make(ui::Rect { 100, 100, 300, 200 }, ui::RED, "Settings"_sv)); TRY(make(ui::Rect { 600, 130, 350, 250 }, ui::CYAN, "File Manager"_sv)); Vector> clients; while (1) { screen.canvas().fill(background); for (auto* window : g_windows) window->draw(screen.canvas()); mouse_pointer.draw(screen.canvas()); screen.sync(); struct pollfd fds[] = { { .fd = mouse->fd(), .events = POLLIN, .revents = 0 }, { .fd = keyboard->fd(), .events = POLLIN, .revents = 0 }, { .fd = server->fd(), .events = POLLIN, .revents = 0 }, }; int rc = poll(fds, 3, 1000); if (!rc) continue; if (rc < 0) { os::println("poll: error: %s", strerror(errno)); } if (fds[0].revents & POLLIN) { moon::MousePacket packet; TRY(mouse->read_typed(packet)); mouse_pointer.update(packet); } if (fds[1].revents & POLLIN) { moon::KeyboardPacket packet; TRY(keyboard->read_typed(packet)); if (!packet.released) { TRY(make(ui::Rect { rand() % screen.canvas().width, rand() % screen.canvas().height, rand() % screen.canvas().width, rand() % screen.canvas().height }, ui::Color::from_rgb(static_cast(rand() % 256), static_cast(rand() % 256), static_cast(rand() % 256)), strerror(packet.key))); } } if (fds[2].revents & POLLIN) { auto client = TRY(server->accept()); os::println("wind: New client connected!"); TRY(clients.try_append(client)); } } }