summaryrefslogtreecommitdiff
path: root/userland/windowserver/ws.c
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2023-10-22 19:50:38 +0200
committerAnton Kling <anton@kling.gg>2023-10-22 19:50:38 +0200
commit4e09bca9e34c226b6d7e34b4fa11248405fd988e (patch)
tree80f156b7940d9d19971395f335530170c69516c7 /userland/windowserver/ws.c
Move everything into a new repo.
Diffstat (limited to 'userland/windowserver/ws.c')
-rw-r--r--userland/windowserver/ws.c375
1 files changed, 375 insertions, 0 deletions
diff --git a/userland/windowserver/ws.c b/userland/windowserver/ws.c
new file mode 100644
index 0000000..e4f1a9e
--- /dev/null
+++ b/userland/windowserver/ws.c
@@ -0,0 +1,375 @@
+#include <fcntl.h>
+#include <poll.h>
+#include <stddef.h>
+#include <stdint.h>
+//#include <sys/mman.h>
+#include "draw.h"
+#include "font.h"
+#include "ws.h"
+#include <assert.h>
+#include <socket.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#define WINDOW_SERVER_SOCKET "/windowserver"
+
+CLIENT *clients[100];
+CLIENT *active_client;
+
+int mouse_x = 0;
+int mouse_y = 0;
+
+// void *true_display;
+// void *buffer_display;
+// uint64_t display_size;
+// int border_size;
+// uint8_t border_color;
+DISPLAY main_display;
+
+struct pollfd *fds;
+uint64_t num_fds;
+
+uint64_t socket_fd_poll;
+uint64_t keyboard_fd_poll;
+uint64_t mouse_fd_poll;
+
+// Taken from drivers/keyboard.c
+struct KEY_EVENT {
+ char c;
+ uint8_t mode; // (shift (0 bit)) (alt (1 bit))
+ uint8_t release; // 0 pressed, 1 released
+};
+
+int create_socket(void) {
+ struct sockaddr_un address;
+ int fd = socket(AF_UNIX, 0, 0);
+ address.sun_family = AF_UNIX;
+ size_t str_len = strlen(WINDOW_SERVER_SOCKET);
+ address.sun_path = malloc(str_len + 1);
+ memcpy(address.sun_path, WINDOW_SERVER_SOCKET, str_len);
+ address.sun_path[str_len] = 0;
+
+ bind(fd, (struct sockaddr *)(&address), sizeof(address));
+ // for(;;);
+ /*free(address.sun_path);*/
+ return fd;
+}
+
+void setup_display(DISPLAY *disp, const char *path, uint64_t size) {
+ disp->wallpaper_color = 0x3;
+ disp->size = size;
+ disp->vga_fd = open(path, O_RDWR, 0);
+ if (-1 == disp->vga_fd) {
+ perror("open");
+ for (;;)
+ ;
+ }
+ disp->true_buffer = mmap(NULL, size, 0, 0, disp->vga_fd, 0);
+ disp->back_buffer = malloc(size + 0x1000);
+ disp->clients = clients;
+}
+
+void setup(void) {
+ setup_display(&main_display, "/dev/vbe", 0xBB8000);
+ draw_wallpaper(&main_display);
+ update_display(&main_display);
+
+ main_display.border_size = 1;
+ main_display.border_color = 0xF;
+ active_client = NULL;
+ for (int i = 0; i < 100; i++) {
+ clients[i] = NULL;
+ }
+
+ num_fds = 100;
+ fds = malloc(sizeof(struct pollfd[num_fds]));
+ memset(fds, 0, sizeof(struct pollfd[num_fds]));
+ for (size_t i = 0; i < num_fds; i++)
+ fds[i].fd = -1;
+ // Create socket
+ int socket_fd = create_socket();
+ assert(socket_fd >= 0);
+ socket_fd_poll = 0;
+ fds[socket_fd_poll].fd = socket_fd;
+ fds[socket_fd_poll].events = POLLIN;
+ fds[socket_fd_poll].revents = 0;
+ int keyboard_fd = open("/dev/keyboard", O_RDONLY | O_NONBLOCK, 0);
+ assert(keyboard_fd >= 0);
+ keyboard_fd_poll = 1;
+ fds[keyboard_fd_poll].fd = keyboard_fd;
+ fds[keyboard_fd_poll].events = POLLIN;
+ fds[keyboard_fd_poll].revents = 0;
+ int mouse_fd = open("/dev/mouse", O_RDONLY, 0);
+ assert(mouse_fd >= 0);
+ mouse_fd_poll = 2;
+ fds[mouse_fd_poll].fd = mouse_fd;
+ fds[mouse_fd_poll].events = POLLIN;
+ fds[mouse_fd_poll].revents = 0;
+}
+
+void reset_revents(struct pollfd *fds, size_t s) {
+ for (size_t i = 0; i < s - 1; i++)
+ fds[i].revents = 0;
+}
+
+void add_fd(int fd) {
+ int i;
+ for (i = 0; i < num_fds; i++)
+ if (-1 == fds[i].fd)
+ break;
+
+ fds[i].fd = fd;
+ fds[i].events = POLLIN | POLLHUP;
+ // fds[i].events = POLLIN;
+ fds[i].revents = 0;
+}
+
+void add_client(int fd) {
+ int client_socket = accept(fd, NULL, NULL);
+ add_fd(client_socket);
+ int i;
+ for (i = 0; i < 100; i++)
+ if (!clients[i])
+ break;
+ printf("adding client: %d\n", i);
+ CLIENT *c = clients[i] = malloc(sizeof(CLIENT));
+ c->fd = client_socket;
+ active_client = c;
+ printf("clients[0]: %x\n", clients[0]);
+}
+
+#define CLIENT_EVENT_CREATESCREEN 0
+#define CLIENT_EVENT_UPDATESCREEN 1
+
+void add_window(CLIENT *c, int fd, int x, int y, int sx, int sy) {
+ WINDOW *w = malloc(sizeof(WINDOW));
+ w->bitmap_fd = fd;
+ w->bitmap_ptr = mmap(NULL, sx * sy * sizeof(uint32_t), 0, 0, fd, 0);
+ w->x = x;
+ w->y = y;
+ w->sx = sx;
+ w->sy = sy;
+ c->w = w;
+}
+
+typedef struct {
+ uint16_t px;
+ uint16_t py;
+ uint16_t sx;
+ uint16_t sy;
+ uint8_t name_len;
+} WS_EVENT_CREATE;
+
+void parse_client_event(CLIENT *c) {
+ uint8_t event_type;
+ if (0 == read(c->fd, &event_type, sizeof(uint8_t))) {
+ printf("empty\n");
+ return;
+ }
+ if (0 == event_type) {
+ update_full_display(&main_display, mouse_x, mouse_y);
+ return;
+ }
+ if (1 == event_type) {
+ WS_EVENT_CREATE e;
+ for (; 0 == read(c->fd, &e, sizeof(e));)
+ ;
+ uint8_t bitmap_name[e.name_len + 1];
+ read(c->fd, bitmap_name, e.name_len);
+ bitmap_name[e.name_len] = '\0';
+ int bitmap_fd = shm_open(bitmap_name, O_RDWR, O_CREAT);
+ add_window(c, bitmap_fd, e.px, e.py, e.sx, e.sy);
+ update_full_display(&main_display, mouse_x, mouse_y);
+ }
+}
+
+typedef struct {
+ int type;
+ struct KEY_EVENT ev;
+} WS_EVENT;
+
+void send_to_client(struct KEY_EVENT ev) {
+ WS_EVENT e = {
+ .type = 0,
+ .ev = ev,
+ };
+ write(active_client->fd, &e, sizeof(e));
+}
+
+void clamp_screen_position(int *x, int *y) {
+ if (0 > *x) {
+ *x = 0;
+ }
+ if (0 > *y) {
+ *y = 0;
+ }
+ if (WIDTH < *x) {
+ *x = WIDTH;
+ }
+ if (HEIGHT < *y) {
+ *y = HEIGHT;
+ }
+}
+
+int windowserver_key_events(struct KEY_EVENT ev, int *redraw) {
+ if (!(ev.mode & (1 << 1)))
+ return 0;
+ if (!active_client)
+ return 0;
+ int x = 0;
+ int y = 0;
+ switch (ev.c) {
+ case 'l':
+ x++;
+ break;
+ case 'h':
+ x--;
+ break;
+ case 'k':
+ y--;
+ break;
+ case 'j':
+ y++;
+ break;
+ }
+ if (x || y) {
+ active_client->w->x += x;
+ active_client->w->y += y;
+ clamp_screen_position(&active_client->w->x, &active_client->w->y);
+ *redraw = 1;
+ return 1;
+ }
+ return 0;
+}
+
+struct mouse_event {
+ uint8_t buttons;
+ uint8_t x;
+ uint8_t y;
+};
+
+void update_mouse(void) {
+ draw_mouse(&main_display, mouse_x, mouse_y);
+ return;
+}
+
+void parse_mouse_event(int fd) {
+ int16_t xc = 0;
+ int16_t yc = 0;
+ int middle_button = 0;
+ for (;;) {
+ struct mouse_event e[100];
+ int rc = read(fd, e, sizeof(e));
+ if (rc <= 0)
+ break;
+
+ int n = rc / sizeof(e[0]);
+ for (int i = 0; i < n; i++) {
+ uint8_t xs = e[i].buttons & (1 << 4);
+ uint8_t ys = e[i].buttons & (1 << 5);
+ middle_button = e[i].buttons & (1 << 2);
+ int16_t x = e[i].x;
+ int16_t y = e[i].y;
+ if (xs)
+ x |= 0xFF00;
+ if (ys)
+ y |= 0xFF00;
+ xc += *(int16_t *)&x;
+ yc += *(int16_t *)&y;
+ }
+ }
+ mouse_x += xc;
+ mouse_y -= yc;
+ if (mouse_x < 0)
+ mouse_x = 0;
+ if (mouse_y < 0)
+ mouse_y = 0;
+ if (middle_button) {
+ active_client->w->x += xc;
+ active_client->w->y -= yc;
+ clamp_screen_position(&active_client->w->x, &active_client->w->y);
+ }
+ update_mouse();
+}
+
+void parse_keyboard_event(int fd) {
+ if (!active_client) {
+ return;
+ }
+ struct KEY_EVENT ev[250];
+ int redraw = 0;
+ for (;;) {
+ int rc;
+ if (0 > (rc = read(fd, &ev[0], sizeof(ev))))
+ break;
+ int n = rc / sizeof(ev[0]);
+ for (int i = 0; i < n; i++) {
+ if (windowserver_key_events(ev[i], &redraw))
+ continue;
+ send_to_client(ev[i]);
+ }
+ }
+ if (redraw)
+ update_full_display(&main_display, mouse_x, mouse_y);
+}
+
+CLIENT *get_client(int fd) {
+ for (int i = 0; i < 100; i++) {
+ if (!clients[i])
+ continue;
+ if (clients[i]->fd == fd)
+ return clients[i];
+ }
+ return NULL;
+}
+
+void kill_client(CLIENT *c) {
+ c->w = NULL;
+ update_full_display(&main_display, mouse_x, mouse_y);
+ active_client = clients[0];
+}
+
+void parse_revents(struct pollfd *fds, size_t s) {
+ for (size_t i = 0; i < s - 1; i++) {
+ if (!fds[i].revents)
+ continue;
+ if (-1 == fds[i].fd)
+ continue;
+ if (socket_fd_poll == i && fds[i].revents & POLLIN) {
+ add_client(fds[i].fd);
+ continue;
+ } else if (keyboard_fd_poll == i) {
+ parse_keyboard_event(fds[i].fd);
+ continue;
+ } else if (mouse_fd_poll == i) {
+ parse_mouse_event(fds[i].fd);
+ continue;
+ }
+ CLIENT *c = get_client(fds[i].fd);
+ assert(c);
+ if (fds[i].revents & POLLHUP) {
+ kill_client(c);
+ fds[i].fd = -1;
+ } else {
+ parse_client_event(c);
+ }
+ }
+}
+
+void run(void) {
+ for (;;) {
+ poll(fds, num_fds, 0);
+ parse_revents(fds, num_fds);
+ reset_revents(fds, num_fds);
+ }
+}
+
+int main(void) {
+ open("/dev/serial", O_WRITE, 0);
+ open("/dev/serial", O_WRITE, 0);
+ setup();
+ run();
+ return 0;
+}