summaryrefslogtreecommitdiff
path: root/userland/windowserver
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
Move everything into a new repo.
Diffstat (limited to 'userland/windowserver')
-rw-r--r--userland/windowserver/Makefile16
-rw-r--r--userland/windowserver/draw.c80
-rw-r--r--userland/windowserver/draw.h13
-rw-r--r--userland/windowserver/font.h133
-rw-r--r--userland/windowserver/ws.c375
-rw-r--r--userland/windowserver/ws.h30
6 files changed, 647 insertions, 0 deletions
diff --git a/userland/windowserver/Makefile b/userland/windowserver/Makefile
new file mode 100644
index 0000000..f67bd66
--- /dev/null
+++ b/userland/windowserver/Makefile
@@ -0,0 +1,16 @@
+CC="/home/anton/prj/osdev/sysroot/bin/i686-sb-gcc"
+CFLAGS = -ggdb -ffreestanding -O2 -Wall -Wextra -pedantic -mgeneral-regs-only -Wimplicit-fallthrough -fsanitize=shift,signed-integer-overflow,bounds
+BIN=ws
+LIB=-L../json -ljson -L../json/hashmap -lhashmap -L../libc -lc -lgcc
+INC=-I../json/ -I../libgui/
+all: $(BIN)
+OBJ=ws.o draw.o
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(INC) $(LIB) -o $@ -c $<
+
+clean:
+ rm $(OBJ) ws
+
+$(BIN): $(OBJ)
+ $(CC) -o $(BIN) -ffreestanding -nostdlib $(CFLAGS) $(OBJ) $(LIB)
diff --git a/userland/windowserver/draw.c b/userland/windowserver/draw.c
new file mode 100644
index 0000000..caa16a2
--- /dev/null
+++ b/userland/windowserver/draw.c
@@ -0,0 +1,80 @@
+#include "draw.h"
+#include <string.h>
+
+#define BPP 4
+
+#define place_pixel(_p, _w, _h) \
+ { *(uint32_t *)(disp->back_buffer + BPP * (_w) + (WIDTH * BPP * (_h))) = _p; }
+
+#define place_pixel_pos(_p, _pos) \
+ { *(uint32_t *)(disp->back_buffer + BPP * (_pos)) = _p; }
+
+int mx;
+int my;
+
+void update_display(DISPLAY *disp) {
+ for (int i = 0; i < 20; i++) {
+ place_pixel(0xFFFFFFFF, mx + i, my + i);
+ place_pixel(0xFFFFFFFF, mx, my + i / 2);
+ place_pixel(0xFFFFFFFF, mx + i / 2, my);
+ }
+ for (int i = 0; i < disp->size; i++)
+ disp->true_buffer[i] = disp->back_buffer[i];
+ // memcpy(disp->true_buffer, disp->back_buffer, disp->size);
+}
+
+void draw_wallpaper(DISPLAY *disp) {
+ for (int i = 0; i < disp->size / BPP; i++) {
+ place_pixel_pos(0xFF00FF, i);
+ }
+}
+
+void draw_mouse(DISPLAY *disp, int mouse_x, int mouse_y) {
+ mx = mouse_x;
+ my = mouse_y;
+ update_full_display(disp, mouse_x, mouse_y);
+}
+
+void draw_window(DISPLAY *disp, const WINDOW *w) {
+ int x, y;
+ uint8_t border_size = disp->border_size;
+ const int px = w->x + border_size;
+ const int py = w->y;
+ const int sx = w->sx;
+ const int sy = w->sy;
+ x = px;
+ y = py;
+ for (int i = 0; i < sy; i++) {
+ if((i+py)*WIDTH + px > HEIGHT*WIDTH)
+ break;
+ uint32_t *ptr = disp->back_buffer + BPP * ((i + py) * WIDTH) + px * BPP;
+ if(i*sx > HEIGHT*WIDTH)
+ break;
+ uint32_t *bm = &w->bitmap_ptr[i * sx];
+ // ((uint8_t *)w->bitmap_ptr) + BPP * ((i + py) * WIDTH) + px * BPP;
+ for (int j = 0; j < sx; j++) {
+ ptr[j] = bm[j];
+ }
+ }
+}
+
+void update_active_window(DISPLAY *disp) {
+ for (int i = 0; i < 100; i++) {
+ if (!disp->clients[i])
+ continue;
+ if (!disp->clients[i]->w)
+ continue;
+ draw_window(disp, disp->clients[i]->w);
+ }
+}
+
+void update_full_display(DISPLAY *disp, int mouse_x, int mouse_y) {
+ draw_wallpaper(disp); /*
+ for (int i = 0; i < 100; i++) {
+ if (!disp->windows[i])
+ continue;
+ draw_window(disp, disp->windows[i]);
+ }*/
+ update_active_window(disp);
+ update_display(disp);
+}
diff --git a/userland/windowserver/draw.h b/userland/windowserver/draw.h
new file mode 100644
index 0000000..bf9ff4f
--- /dev/null
+++ b/userland/windowserver/draw.h
@@ -0,0 +1,13 @@
+#ifndef DRAW_H
+#define DRAW_H
+#include "ws.h"
+
+#define WIDTH 0x500
+#define HEIGHT 0x320
+
+void draw_wallpaper(DISPLAY *disp);
+void draw_window(DISPLAY *disp, const WINDOW *w);
+void update_full_display(DISPLAY *disp, int mouse_x, int mouse_y);
+void update_active_window(DISPLAY *disp);
+void draw_mouse(DISPLAY *disp, int mouse_x, int mouse_y);
+#endif
diff --git a/userland/windowserver/font.h b/userland/windowserver/font.h
new file mode 100644
index 0000000..ad63e41
--- /dev/null
+++ b/userland/windowserver/font.h
@@ -0,0 +1,133 @@
+#ifndef FONT_H
+#define FONT_H
+char font8x8_basic[128][8] = {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0000 (nul)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0001
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0002
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0003
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0004
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0005
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0006
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0007
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0008
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0009
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000A
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000B
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000C
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000D
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000E
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000F
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0010
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0011
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0012
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0013
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0014
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0015
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0016
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0017
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0018
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0019
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001A
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001B
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001C
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001D
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001E
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001F
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 (space)
+ { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, // U+0021 (!)
+ { 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0022 (")
+ { 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // U+0023 (#)
+ { 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // U+0024 ($)
+ { 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // U+0025 (%)
+ { 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // U+0026 (&)
+ { 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0027 (')
+ { 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // U+0028 (()
+ { 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // U+0029 ())
+ { 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // U+002A (*)
+ { 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // U+002B (+)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+002C (,)
+ { 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // U+002D (-)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+002E (.)
+ { 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // U+002F (/)
+ { 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00}, // U+0030 (0)
+ { 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // U+0031 (1)
+ { 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // U+0032 (2)
+ { 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // U+0033 (3)
+ { 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00}, // U+0034 (4)
+ { 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // U+0035 (5)
+ { 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // U+0036 (6)
+ { 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00}, // U+0037 (7)
+ { 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+0038 (8)
+ { 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // U+0039 (9)
+ { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+003A (:)
+ { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+003B (;)
+ { 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // U+003C (<)
+ { 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00}, // U+003D (=)
+ { 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // U+003E (>)
+ { 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00}, // U+003F (?)
+ { 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00}, // U+0040 (@)
+ { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0041 (A)
+ { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0042 (B)
+ { 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // U+0043 (C)
+ { 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00}, // U+0044 (D)
+ { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0045 (E)
+ { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // U+0046 (F)
+ { 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // U+0047 (G)
+ { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0048 (H)
+ { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0049 (I)
+ { 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // U+004A (J)
+ { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+004B (K)
+ { 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // U+004C (L)
+ { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+004D (M)
+ { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+004E (N)
+ { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+004F (O)
+ { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+0050 (P)
+ { 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // U+0051 (Q)
+ { 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00}, // U+0052 (R)
+ { 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00}, // U+0053 (S)
+ { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0054 (T)
+ { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // U+0055 (U)
+ { 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0056 (V)
+ { 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // U+0057 (W)
+ { 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+0058 (X)
+ { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+0059 (Y)
+ { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+005A (Z)
+ { 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00}, // U+005B ([)
+ { 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00}, // U+005C (\)
+ { 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+005D (])
+ { 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00}, // U+005E (^)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+005F (_)
+ { 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0060 (`)
+ { 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // U+0061 (a)
+ { 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00}, // U+0062 (b)
+ { 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // U+0063 (c)
+ { 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00}, // U+0064 (d)
+ { 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00}, // U+0065 (e)
+ { 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00}, // U+0066 (f)
+ { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0067 (g)
+ { 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00}, // U+0068 (h)
+ { 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0069 (i)
+ { 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E}, // U+006A (j)
+ { 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00}, // U+006B (k)
+ { 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+006C (l)
+ { 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00}, // U+006D (m)
+ { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00}, // U+006E (n)
+ { 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+006F (o)
+ { 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+0070 (p)
+ { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78}, // U+0071 (q)
+ { 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00}, // U+0072 (r)
+ { 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00}, // U+0073 (s)
+ { 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0074 (t)
+ { 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00}, // U+0075 (u)
+ { 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0076 (v)
+ { 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00}, // U+0077 (w)
+ { 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // U+0078 (x)
+ { 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0079 (y)
+ { 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00}, // U+007A (z)
+ { 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00}, // U+007B ({)
+ { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+007C (|)
+ { 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00}, // U+007D (})
+ { 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E (~)
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // U+007F
+};
+#endif
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;
+}
diff --git a/userland/windowserver/ws.h b/userland/windowserver/ws.h
new file mode 100644
index 0000000..c4daf7b
--- /dev/null
+++ b/userland/windowserver/ws.h
@@ -0,0 +1,30 @@
+#ifndef WS_H
+#define WS_H
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct {
+ int bitmap_fd;
+ uint32_t *bitmap_ptr;
+ int x;
+ int y;
+ int sx;
+ int sy;
+} WINDOW;
+
+typedef struct {
+ int fd;
+ WINDOW *w;
+} CLIENT;
+
+typedef struct {
+ int vga_fd;
+ uint8_t *back_buffer;
+ uint8_t *true_buffer;
+ size_t size;
+ uint8_t border_size;
+ uint8_t border_color;
+ uint8_t wallpaper_color;
+ CLIENT **clients;
+} DISPLAY;
+#endif