wind: Add a simple display server skeleton using libui
No client functionality yet, but it's a start.
This commit is contained in:
parent
9df88bac3e
commit
36cc84c50d
@ -51,3 +51,4 @@ add_subdirectory(kernel)
|
||||
add_subdirectory(apps)
|
||||
add_subdirectory(tests)
|
||||
add_subdirectory(shell)
|
||||
add_subdirectory(wind)
|
||||
|
14
wind/CMakeLists.txt
Normal file
14
wind/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
Screen.h
|
||||
Screen.cpp
|
||||
Mouse.h
|
||||
Mouse.cpp
|
||||
)
|
||||
|
||||
add_executable(wind ${SOURCES})
|
||||
target_compile_options(wind PRIVATE -Os ${COMMON_FLAGS} -Wno-write-strings)
|
||||
add_dependencies(wind libc)
|
||||
target_include_directories(wind PRIVATE ${LUNA_BASE}/usr/include ${CMAKE_CURRENT_LIST_DIR})
|
||||
target_link_libraries(wind PRIVATE os ui)
|
||||
install(TARGETS wind DESTINATION ${LUNA_BASE}/usr/bin)
|
21
wind/Mouse.cpp
Normal file
21
wind/Mouse.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "Mouse.h"
|
||||
|
||||
Mouse::Mouse(ui::Canvas& screen)
|
||||
{
|
||||
m_position.x = screen.width / 2;
|
||||
m_position.y = screen.height / 2;
|
||||
m_screen_rect = screen.rect();
|
||||
}
|
||||
|
||||
void Mouse::draw(ui::Canvas& screen)
|
||||
{
|
||||
auto canvas = screen.subcanvas(m_position, 10, 10, true).release_value();
|
||||
canvas.fill(ui::WHITE);
|
||||
}
|
||||
|
||||
void Mouse::move(const moon::MousePacket& packet)
|
||||
{
|
||||
m_position.x += packet.xdelta;
|
||||
m_position.y -= packet.ydelta;
|
||||
m_position = m_screen_rect.normalize(m_position);
|
||||
}
|
18
wind/Mouse.h
Normal file
18
wind/Mouse.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "Screen.h"
|
||||
#include <moon/Mouse.h>
|
||||
#include <ui/Canvas.h>
|
||||
|
||||
class Mouse
|
||||
{
|
||||
public:
|
||||
Mouse(ui::Canvas& screen);
|
||||
|
||||
void move(const moon::MousePacket& packet);
|
||||
|
||||
void draw(ui::Canvas& screen);
|
||||
|
||||
private:
|
||||
ui::Point m_position;
|
||||
ui::Rect m_screen_rect;
|
||||
};
|
34
wind/Screen.cpp
Normal file
34
wind/Screen.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "Screen.h"
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
Result<Screen> Screen::open()
|
||||
{
|
||||
int fd = ::open("/dev/fb0", O_RDWR | O_CLOEXEC);
|
||||
if (fd < 0) return err(errno);
|
||||
|
||||
int width = ioctl(fd, FB_GET_WIDTH);
|
||||
int height = ioctl(fd, FB_GET_HEIGHT);
|
||||
|
||||
void* p = mmap(nullptr, width * height * BYTES_PER_PIXEL, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (p == MAP_FAILED)
|
||||
{
|
||||
close(fd);
|
||||
return err(errno);
|
||||
}
|
||||
|
||||
Screen screen;
|
||||
|
||||
screen.m_canvas = ui::Canvas::create((u8*)p, width, height);
|
||||
screen.m_size = width * height * BYTES_PER_PIXEL;
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
void Screen::sync()
|
||||
{
|
||||
msync(m_canvas.ptr, size(), MS_SYNC);
|
||||
}
|
27
wind/Screen.h
Normal file
27
wind/Screen.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include <luna/OwnedPtr.h>
|
||||
#include <ui/Canvas.h>
|
||||
|
||||
constexpr int BYTES_PER_PIXEL = 4;
|
||||
|
||||
class Screen
|
||||
{
|
||||
public:
|
||||
static Result<Screen> open();
|
||||
|
||||
ui::Canvas& canvas()
|
||||
{
|
||||
return m_canvas;
|
||||
}
|
||||
|
||||
int size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
void sync();
|
||||
|
||||
private:
|
||||
ui::Canvas m_canvas;
|
||||
int m_size;
|
||||
};
|
98
wind/main.cpp
Normal file
98
wind/main.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
#include "Mouse.h"
|
||||
#include "Screen.h"
|
||||
#include <errno.h>
|
||||
#include <moon/Keyboard.h>
|
||||
#include <os/ArgumentParser.h>
|
||||
#include <os/File.h>
|
||||
#include <pwd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/poll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
Result<int> luna_main(int argc, char** argv)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
ui::Color background = ui::BLACK;
|
||||
|
||||
while (1)
|
||||
{
|
||||
struct pollfd fds[] = {
|
||||
{ .fd = mouse->fd(), .events = POLLIN, .revents = 0 },
|
||||
{ .fd = keyboard->fd(), .events = POLLIN, .revents = 0 },
|
||||
};
|
||||
|
||||
int rc = poll(fds, 2, 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.move(packet);
|
||||
}
|
||||
if (fds[1].revents & POLLIN)
|
||||
{
|
||||
moon::KeyboardPacket packet;
|
||||
TRY(keyboard->read_typed(packet));
|
||||
background = ui::Color::from_rgb(0x00, 0x00, packet.key * 2);
|
||||
}
|
||||
|
||||
screen.canvas().fill(background);
|
||||
mouse_pointer.draw(screen.canvas());
|
||||
screen.sync();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user