aboutsummaryrefslogtreecommitdiff
path: root/libgui
diff options
context:
space:
mode:
authorMarvin Borner2021-03-24 22:18:41 +0100
committerMarvin Borner2021-03-24 22:18:41 +0100
commitd2ddd2f279733ec382941b85acd8557cb8f61ec9 (patch)
treec41ce180bcc984c4e39033ec34eb1ca8789375ca /libgui
parent48852d97c6a506b3876b139ceb7fde203b9205c2 (diff)
Huge GUI improvements
Diffstat (limited to 'libgui')
-rw-r--r--libgui/gfx.c5
-rw-r--r--libgui/gui.c131
-rw-r--r--libgui/inc/gui.h12
-rw-r--r--libgui/inc/msg.h46
-rw-r--r--libgui/msg.c4
5 files changed, 163 insertions, 35 deletions
diff --git a/libgui/gfx.c b/libgui/gfx.c
index dad8b88..ff5bf69 100644
--- a/libgui/gfx.c
+++ b/libgui/gfx.c
@@ -118,7 +118,6 @@ void gfx_write_char(struct context *ctx, vec2 pos, enum font_type font_type, u32
{
struct font *font = gfx_resolve_font(font_type);
write_char(ctx, pos, font, c, ch);
- /* gfx_redraw(); */
}
void gfx_write(struct context *ctx, vec2 pos, enum font_type font_type, u32 c, const char *text)
@@ -144,7 +143,6 @@ void gfx_write(struct context *ctx, vec2 pos, enum font_type font_type, u32 c, c
cnt++;
}
}
- /* gfx_redraw(); */
}
void gfx_load_image(struct context *ctx, vec2 pos, const char *path)
@@ -227,13 +225,11 @@ void gfx_ctx_on_ctx(struct context *dest, struct context *src, vec2 pos)
void gfx_draw_rectangle(struct context *ctx, vec2 pos1, vec2 pos2, u32 c)
{
draw_rectangle(ctx, pos1, pos2, c);
- /* gfx_redraw(); */
}
void gfx_fill(struct context *ctx, u32 c)
{
draw_rectangle(ctx, vec2(0, 0), vec2(ctx->size.x, ctx->size.y), c);
- /* gfx_redraw(); */
}
void gfx_border(struct context *ctx, u32 c, u32 width)
@@ -256,7 +252,6 @@ void gfx_border(struct context *ctx, u32 c, u32 width)
}
draw += ctx->pitch;
}
- /* gfx_redraw(); */
}
int gfx_font_height(enum font_type font_type)
diff --git a/libgui/gui.c b/libgui/gui.c
index 9f0d39f..87ea4c9 100644
--- a/libgui/gui.c
+++ b/libgui/gui.c
@@ -1,16 +1,60 @@
// MIT License, Copyright (c) 2021 Marvin Borner
+#include <assert.h>
#include <def.h>
#include <errno.h>
#include <gui.h>
+#include <list.h>
#include <msg.h>
#include <print.h>
#define WM_PATH "/bin/wm"
-s32 gui_new_window(struct gui_window *win)
+struct gui_window {
+ u32 id;
+ struct context ctx;
+};
+
+struct list *windows = NULL;
+
+static struct gui_window *win_by_id(u32 id)
+{
+ assert(windows);
+ struct node *iterator = windows->head;
+ while (iterator) {
+ struct gui_window *win = iterator->data;
+ if (win->id == id)
+ return iterator->data;
+ iterator = iterator->next;
+ }
+ return NULL;
+}
+
+/**
+ * GFX wrappers
+ */
+
+static res fill(u32 id, u32 c)
{
- struct message_new_window msg = { 0 };
+ struct gui_window *win = win_by_id(id);
+ if (!win)
+ return -ENOENT;
+ gfx_fill(&win->ctx, c);
+ return EOK;
+}
+
+/**
+ * Program interface
+ */
+
+res gui_new_window(void)
+{
+ if (!windows)
+ windows = list_new();
+
+ struct gui_window *win = zalloc(sizeof(*win));
+
+ struct message_new_window msg = { .header.state = MSG_NEED_ANSWER };
if (msg_send(pidof(WM_PATH), GUI_NEW_WINDOW, &msg, sizeof(msg)) > 0 &&
msg_receive(&msg, sizeof(msg)) > 0 &&
msg.header.type == (GUI_NEW_WINDOW | MSG_SUCCESS)) {
@@ -19,18 +63,91 @@ s32 gui_new_window(struct gui_window *win)
u32 size;
res ret = shaccess(msg.shid, (u32 *)&win->ctx.fb, &size);
if (ret < 0 || !win->ctx.fb)
- return MIN(ret, -1);
+ return MIN(ret, -EFAULT);
+ list_add(windows, win);
+ assert(fill(win->id, COLOR_BLACK) == EOK);
+ gui_redraw_window(win->id);
return win->id;
}
- return -1;
+ return -EINVAL;
}
-s32 gui_redraw_window(u32 id)
+res gui_redraw_window(u32 id)
{
- struct message_redraw_window msg = { .id = id };
+ struct message_redraw_window msg = { .id = id, .header.state = MSG_NEED_ANSWER };
if (msg_send(pidof(WM_PATH), GUI_REDRAW_WINDOW, &msg, sizeof(msg)) > 0 &&
msg_receive(&msg, sizeof(msg)) > 0 &&
msg.header.type == (GUI_REDRAW_WINDOW | MSG_SUCCESS))
return id;
- return -1;
+ return -EINVAL;
+}
+
+/**
+ * Message handling
+ */
+
+static res handle_error(const char *op, res code)
+{
+ log("GUI error at '%s': %s (%d)\n", op, strerror(code), code);
+ return code;
+}
+
+static res handle_ping(struct message_ping *msg)
+{
+ if (msg->ping != MSG_PING_SEND)
+ return handle_error("ping", EINVAL);
+
+ msg->header.type |= MSG_SUCCESS;
+ msg->ping = MSG_PING_RECV;
+ msg_send(msg->header.src, GUI_PING, &msg, sizeof(msg));
+
+ return errno;
+}
+
+static res handle_mouse(struct message_mouse *msg)
+{
+ if (msg->header.state == MSG_NEED_ANSWER)
+ msg_send(msg->header.src, msg->header.type | MSG_SUCCESS, msg, sizeof(*msg));
+
+ return errno;
+}
+
+static void handle_exit(void)
+{
+ if (!windows)
+ return;
+
+ struct node *iterator = windows->head;
+ while (iterator) {
+ struct gui_window *win = iterator->data;
+ struct message_destroy_window msg = { .id = win->id };
+ msg_send(pidof(WM_PATH), GUI_DESTROY_WINDOW, &msg, sizeof(msg));
+ iterator = iterator->next;
+ }
+
+ list_destroy(windows);
+}
+
+/**
+ * Main loop
+ */
+
+void gui_loop(void)
+{
+ atexit(handle_exit);
+
+ void *msg = zalloc(4096);
+ while (msg_receive(msg, 4096)) {
+ struct message_header *head = msg;
+ switch (head->type) {
+ case GUI_PING:
+ handle_ping(msg);
+ break;
+ case GUI_MOUSE:
+ handle_mouse(msg);
+ break;
+ default:
+ handle_error("loop", EINVAL);
+ }
+ }
}
diff --git a/libgui/inc/gui.h b/libgui/inc/gui.h
index d160333..a3f74f8 100644
--- a/libgui/inc/gui.h
+++ b/libgui/inc/gui.h
@@ -4,14 +4,10 @@
#define GUI_H
#include <def.h>
-#include <gfx.h>
+#include <errno.h>
-struct gui_window {
- u32 id;
- struct context ctx;
-};
-
-s32 gui_new_window(struct gui_window *win);
-s32 gui_redraw_window(u32 id);
+res gui_new_window(void);
+res gui_redraw_window(u32 id);
+void gui_loop(void);
#endif
diff --git a/libgui/inc/msg.h b/libgui/inc/msg.h
index 150c42d..0e85d5a 100644
--- a/libgui/inc/msg.h
+++ b/libgui/inc/msg.h
@@ -6,15 +6,28 @@
#include <def.h>
#include <gfx.h>
+#define MSG_PING_SEND 0x07734
+#define MSG_PING_RECV 0x7474
+
#define MSG_MAGIC 0x42042069
#define MSG_SUCCESS (1 << 29)
#define MSG_FAILURE (1 << 30)
+enum message_state {
+ MSG_GO_ON,
+ MSG_NEED_ANSWER,
+};
+
struct message_header {
u32 magic;
u32 src;
u32 type;
- u32 size;
+ enum message_state state;
+};
+
+struct message_ping {
+ struct message_header header;
+ u32 ping;
};
struct message_new_window {
@@ -29,23 +42,30 @@ struct message_redraw_window {
u32 id;
};
-enum message_type {
- // GFX // TODO: Remove
- GFX_NEW_CONTEXT,
- GFX_REDRAW,
- GFX_REDRAW_FOCUSED,
+struct message_destroy_window {
+ struct message_header header;
+ u32 id;
+};
+
+struct message_mouse {
+ struct message_header header;
+ vec2 pos;
+ struct {
+ u8 click : 1;
+ } bits;
+};
- // GUI
+enum message_type {
+ GUI_PING,
GUI_NEW_WINDOW,
GUI_REDRAW_WINDOW,
- GUI_KILL,
- GUI_KEYBOARD,
+ GUI_DESTROY_WINDOW,
+
GUI_MOUSE,
- GUI_RESIZE,
- GUI_MAX
+ GUI_KEYBOARD,
};
-int msg_send(u32 pid, enum message_type type, void *data, u32 size);
-int msg_receive(void *buf, u32 size);
+res msg_send(u32 pid, enum message_type type, void *data, u32 size);
+res msg_receive(void *buf, u32 size);
#endif
diff --git a/libgui/msg.c b/libgui/msg.c
index 677ad52..5f4ae39 100644
--- a/libgui/msg.c
+++ b/libgui/msg.c
@@ -6,7 +6,7 @@
#include <print.h>
#include <sys.h>
-int msg_send(u32 pid, enum message_type type, void *data, u32 size)
+res msg_send(u32 pid, enum message_type type, void *data, u32 size)
{
if (!data)
return -EFAULT;
@@ -20,7 +20,7 @@ int msg_send(u32 pid, enum message_type type, void *data, u32 size)
return write(path, data, 0, size);
}
-int msg_receive(void *buf, u32 size)
+res msg_receive(void *buf, u32 size)
{
int ret = read("/proc/self/msg", buf, 0, size);
struct message_header *header = buf;