diff options
author | Marvin Borner | 2021-03-24 22:18:41 +0100 |
---|---|---|
committer | Marvin Borner | 2021-03-24 22:18:41 +0100 |
commit | d2ddd2f279733ec382941b85acd8557cb8f61ec9 (patch) | |
tree | c41ce180bcc984c4e39033ec34eb1ca8789375ca /libgui | |
parent | 48852d97c6a506b3876b139ceb7fde203b9205c2 (diff) |
Huge GUI improvements
Diffstat (limited to 'libgui')
-rw-r--r-- | libgui/gfx.c | 5 | ||||
-rw-r--r-- | libgui/gui.c | 131 | ||||
-rw-r--r-- | libgui/inc/gui.h | 12 | ||||
-rw-r--r-- | libgui/inc/msg.h | 46 | ||||
-rw-r--r-- | libgui/msg.c | 4 |
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; |