aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarvin Borner2021-05-21 15:25:42 +0200
committerMarvin Borner2021-05-21 15:25:42 +0200
commita69af1e2cc219f2f4010a6231dd32416a18437f2 (patch)
tree822571c69cc924adff0ec2c98c88f7bf928b43d5
parent5c27101d27a6fe9005ce4b95075d1dea5117d190 (diff)
Major GUI refactoring
-rw-r--r--apps/chess/main.c26
-rw-r--r--apps/wm/main.c73
-rw-r--r--boot/grub.cfg4
-rw-r--r--libs/libc/inc/vec.h2
-rw-r--r--libs/libgui/gfx.c42
-rw-r--r--libs/libgui/gfx.h11
-rw-r--r--libs/libgui/gui.c265
-rw-r--r--libs/libgui/gui.h33
-rw-r--r--libs/libgui/msg.h3
-rwxr-xr-xrun3
10 files changed, 265 insertions, 197 deletions
diff --git a/apps/chess/main.c b/apps/chess/main.c
index 94739ef..e5a8799 100644
--- a/apps/chess/main.c
+++ b/apps/chess/main.c
@@ -57,15 +57,15 @@ static vec2 selected = { -1, -1 }; // Selected tile
static void load_image(struct piece *tile)
{
- assert(gui_clear(win, tile->widget, GUI_LAYER_FG) == EOK);
+ gui_clear(win, tile->widget, GUI_LAYER_FG);
char icon[48] = { 0 };
snprintf(icon, sizeof(icon), "/icons/chess-%s-%d.png", tile->name, TILE);
enum gfx_filter filter = IS_COLOR(tile->piece, BLACK) ? GFX_FILTER_NONE : GFX_FILTER_INVERT;
/* assert(gui_fill(win, tile->widget, GUI_LAYER_FG, 0) == EOK); */
- assert(gui_load_image_filter(win, tile->widget, GUI_LAYER_FG, vec2(0, 0), vec2(TILE, TILE),
- filter, icon) == EOK);
+ gui_load_image_filter(win, tile->widget, GUI_LAYER_FG, vec2(0, 0), vec2(TILE, TILE), filter,
+ icon);
}
static void mouseclick(u32 widget_id, vec2 pos)
@@ -92,14 +92,14 @@ static void mouseclick(u32 widget_id, vec2 pos)
strlcpy(clicked_piece->name, selected_piece->name, sizeof(clicked_piece->name));
selected_piece->name[0] = '\0';
- assert(gui_clear(win, selected_piece->widget, GUI_LAYER_FG) == EOK);
+ gui_clear(win, selected_piece->widget, GUI_LAYER_FG);
load_image(clicked_piece);
- assert(gui_redraw_window(win) == EOK);
+ gui_redraw_window(win);
selected = vec2(-1, -1);
} else if (clicked_piece->piece) {
- assert(gui_redraw_widget(win, clicked_piece->widget) == EOK);
+ gui_redraw_widget(win, clicked_piece->widget);
selected = clicked;
}
}
@@ -216,20 +216,18 @@ static void draw_board(void)
{
for (u8 x = 0; x < 8; x++) {
for (u8 y = 0; y < 8; y++) {
- u32 widget =
- gui_new_widget(win, vec2(TILE, TILE), vec2(TILE * x, TILE * y));
+ u32 widget;
+ gui_new_widget(&widget, win, vec2(TILE * x, TILE * y), vec2(TILE, TILE));
assert((signed)widget > 0);
u8 colored = (x + y + 1) % 2 == 0;
#if !WHITE_STARTS
colored = !colored;
#endif
- assert(gui_fill(win, widget, GUI_LAYER_BG,
- colored ? DARK_COLOR : LIGHT_COLOR) == EOK);
+ gui_fill(win, widget, GUI_LAYER_BG, colored ? DARK_COLOR : LIGHT_COLOR);
struct piece *tile = &tiles[x][y];
- assert(gui_listen_widget(win, widget, GUI_LISTEN_MOUSECLICK,
- (u32)mouseclick) == EOK);
+ gui_listen_widget(win, widget, GUI_LISTEN_MOUSECLICK, (u32)mouseclick);
tile->widget = widget;
@@ -238,12 +236,12 @@ static void draw_board(void)
}
}
- assert(gui_redraw_window(win) == EOK);
+ gui_redraw_window(win);
}
int main(void)
{
- assert(gui_new_window(&win) == EOK);
+ gui_new_custom_window(&win, vec2(0, 0), vec2(TILE * 8, TILE * 8));
fen_parse(START_FEN);
draw_board();
diff --git a/apps/wm/main.c b/apps/wm/main.c
index 0d00427..0e47af4 100644
--- a/apps/wm/main.c
+++ b/apps/wm/main.c
@@ -13,8 +13,6 @@
#include <rand.h>
#include <sys.h>
-#define WINDOW_MOVE_TIMEOUT 20
-
struct client {
u32 conn; // Bus conn
};
@@ -223,9 +221,9 @@ static struct window *window_new(struct client client, struct vec2 pos, struct v
win->id = id++;
win->ctx.size = size;
win->ctx.bpp = screen.bpp;
- win->ctx.pitch = size.x * bypp;
+ win->ctx.pitch = win->ctx.size.x * bypp;
win->ctx.bytes = win->ctx.pitch * win->ctx.size.y;
- if ((flags & WF_NO_FB) != 0) {
+ if (flags & WF_NO_FB) {
win->ctx.fb = NULL;
} else {
assert(shalloc(win->ctx.bytes, (u32 *)&win->ctx.fb, &win->shid) == EOK);
@@ -347,6 +345,13 @@ static void window_redraw(struct window *win)
window_redraw_non_alpha(win);
}
+static void window_move(struct window *win, vec2 pos)
+{
+ win->pos_prev = win->pos;
+ win->pos = pos;
+ window_redraw(win);
+}
+
// TODO: Fix strange artifacts after destroying
static void window_destroy(struct window *win)
{
@@ -358,6 +363,37 @@ static void window_destroy(struct window *win)
}
/**
+ * Window bar
+ */
+
+#define BAR_HEIGHT 32
+#define BAR_CLOSE_SIZE 24
+#define BAR_MARGIN GFX_CENTER_IN(BAR_HEIGHT, BAR_CLOSE_SIZE)
+#define BAR_BUTTONS_WIDTH (BAR_MARGIN * 2 + BAR_CLOSE_SIZE)
+
+static void window_bar_mousemove(struct window *win, struct event_mouse *event, vec2 pos,
+ vec2 mouse_pos)
+{
+ if (pos.y > BAR_HEIGHT)
+ return;
+
+ if (pos.x >= win->ctx.size.x - BAR_BUTTONS_WIDTH && event->but.left)
+ window_destroy(win);
+ else if (event->but.left)
+ window_move(win, vec2_sub(mouse_pos, vec2(win->ctx.size.x / 2, BAR_HEIGHT / 2)));
+}
+
+static void window_bar_draw(struct window *win)
+{
+ if (!(win->flags & WF_BAR))
+ return;
+
+ gfx_load_image_filter(&win->ctx,
+ vec2(win->ctx.size.x - BAR_CLOSE_SIZE - BAR_MARGIN, BAR_MARGIN),
+ GFX_FILTER_INVERT, "/icons/close-" STRINGIFY(BAR_CLOSE_SIZE) ".png");
+}
+
+/**
* Event handlers
*/
@@ -389,7 +425,6 @@ static void handle_event_keyboard(struct event_keyboard *event)
UNUSED(ch);
}
-static struct timer mouse_timer = { 0 };
static void handle_event_mouse(struct event_mouse *event)
{
if (event->magic != MOUSE_MAGIC) {
@@ -428,14 +463,7 @@ static void handle_event_mouse(struct event_mouse *event)
focused = win;
if (focused && !(focused->flags & WF_NO_DRAG) && event->but.left && special_keys.alt) {
- struct timer timer = { 0 };
- io_read(IO_TIMER, &timer, 0, sizeof(timer));
- if (timer.time - mouse_timer.time > WINDOW_MOVE_TIMEOUT) {
- focused->pos_prev = focused->pos;
- focused->pos = mouse.pos;
- window_redraw(focused);
- mouse_timer = timer;
- }
+ window_move(win, mouse.pos);
return;
} else if (!vec2_eq(cursor->pos, cursor->pos_prev)) {
window_redraw(cursor);
@@ -444,10 +472,20 @@ static void handle_event_mouse(struct event_mouse *event)
if (!win)
return;
+ vec2 relative_pos = vec2_sub(mouse.pos, win->pos);
+ if (win->flags & WF_BAR) {
+ if (relative_pos.y <= BAR_HEIGHT) {
+ window_bar_mousemove(win, event, relative_pos, mouse.pos);
+ return;
+ } else {
+ relative_pos.y -= BAR_HEIGHT;
+ }
+ }
+
struct message_mouse msg = { 0 };
msg.header.state = MSG_GO_ON;
msg.id = win->id;
- msg.pos = vec2_sub(mouse.pos, win->pos);
+ msg.pos = relative_pos;
msg.bits.click = event->but.left;
if (msg_connect_conn(win->client.conn) == EOK)
@@ -462,9 +500,12 @@ static void handle_event_mouse(struct event_mouse *event)
static void handle_message_new_window(struct message_new_window *msg)
{
- struct window *win = window_new((struct client){ .conn = msg->header.bus.conn },
- vec2(500, 600), vec2(600, 400), 0);
+ struct window *win = window_new((struct client){ .conn = msg->header.bus.conn }, msg->pos,
+ vec2_add(msg->size, vec2(0, BAR_HEIGHT)), WF_BAR);
+ window_bar_draw(win);
+
msg->ctx = win->ctx;
+ msg->off = vec2(0, BAR_HEIGHT);
msg->shid = win->shid;
msg->id = win->id;
diff --git a/boot/grub.cfg b/boot/grub.cfg
index 7f310e9..277ca5c 100644
--- a/boot/grub.cfg
+++ b/boot/grub.cfg
@@ -2,11 +2,11 @@ set timeout=0
set default=0
menuentry "Melvix with logging" {
- multiboot /boot/melvix log
+ multiboot /boot/melvix
boot
}
menuentry "Melvix without logging" {
- multiboot /boot/melvix
+ multiboot /boot/melvix nolog
boot
}
diff --git a/libs/libc/inc/vec.h b/libs/libc/inc/vec.h
index a036931..bcd4cca 100644
--- a/libs/libc/inc/vec.h
+++ b/libs/libc/inc/vec.h
@@ -21,6 +21,7 @@ typedef struct vec3 {
#define vec2_div(a, b) ((vec2){ a.x / (b), a.y / (b) })
#define vec2_dot(a, b) ((u32)(a.x * b.x + a.y * b.y))
#define vec2_eq(a, b) (a.x == b.x && a.y == b.y)
+#define vec2_sum(a) ((u32)(a.x + a.y))
#define vec3(x, y, z) ((vec3){ (x), (y), (z) })
#define vec3to2(a) ((vec2){ a.x, a.y })
@@ -32,5 +33,6 @@ typedef struct vec3 {
#define vec3_eq(a, b) (a.x == b.x && a.y == b.y && a.z == c.z)
#define vec3_cross(a, b) \
((vec3){ a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x })
+#define vec3_sum(a) ((u32)(a.x + a.y + a.z))
#endif
diff --git a/libs/libgui/gfx.c b/libs/libgui/gfx.c
index 3ed8375..d963a1b 100644
--- a/libs/libgui/gfx.c
+++ b/libs/libgui/gfx.c
@@ -92,22 +92,6 @@ static void write_char(struct context *ctx, vec2 pos, struct font *font, u32 c,
}
}
-static void draw_rectangle(struct context *ctx, vec2 pos1, vec2 pos2, u32 c)
-{
- assert(pos1.x <= pos2.x && pos1.y <= pos2.y);
- int bypp = ctx->bpp >> 3;
- u8 *draw = &ctx->fb[pos1.x * bypp + pos1.y * ctx->pitch];
- for (u32 i = 0; i < pos2.y - pos1.y; i++) {
- for (u32 j = 0; j < pos2.x - pos1.x; j++) {
- draw[bypp * j] = GET_BLUE(c);
- draw[bypp * j + 1] = GET_GREEN(c);
- draw[bypp * j + 2] = GET_RED(c);
- draw[bypp * j + 3] = GET_ALPHA(c);
- }
- draw += ctx->pitch;
- }
-}
-
struct context *gfx_new_ctx(struct context *ctx, vec2 size, u8 bpp)
{
ctx->size = size;
@@ -222,7 +206,6 @@ static void gfx_image_cache_save(const char *path, struct bmp *bmp)
void gfx_load_image_filter(struct context *ctx, vec2 pos, enum gfx_filter filter, const char *path)
{
- // TODO: Support x, y
// TODO: Detect image type
struct bmp *bmp = gfx_image_cache_get(path);
@@ -245,7 +228,7 @@ void gfx_load_image_filter(struct context *ctx, vec2 pos, enum gfx_filter filter
u8 bypp = bmp->bpp >> 3;
/* u8 *srcfb = &bmp->data[bypp + (bmp->size.y - 1) * bmp->pitch]; */
u8 *srcfb = bmp->data;
- u8 *destfb = &ctx->fb[bypp];
+ u8 *destfb = &ctx->fb[pos.x * bypp + pos.y * ctx->pitch];
for (u32 cy = 0; cy < bmp->size.y && cy + pos.y < ctx->size.y; cy++) {
int diff = 0;
for (u32 cx = 0; cx < bmp->size.x && cx + pos.x < ctx->size.x; cx++) {
@@ -279,6 +262,22 @@ void gfx_load_wallpaper(struct context *ctx, const char *path)
gfx_load_image(ctx, vec2(0, 0), path);
}
+void gfx_draw_rectangle(struct context *ctx, vec2 pos1, vec2 pos2, u32 c)
+{
+ assert(pos1.x <= pos2.x && pos1.y <= pos2.y);
+ int bypp = ctx->bpp >> 3;
+ u8 *draw = &ctx->fb[pos1.x * bypp + pos1.y * ctx->pitch];
+ for (u32 i = 0; i < pos2.y - pos1.y; i++) {
+ for (u32 j = 0; j < pos2.x - pos1.x; j++) {
+ draw[bypp * j] = GET_BLUE(c);
+ draw[bypp * j + 1] = GET_GREEN(c);
+ draw[bypp * j + 2] = GET_RED(c);
+ draw[bypp * j + 3] = GET_ALPHA(c);
+ }
+ draw += ctx->pitch;
+ }
+}
+
void gfx_copy(struct context *dest, struct context *src, vec2 pos, vec2 size)
{
int bypp = dest->bpp >> 3;
@@ -323,11 +322,6 @@ void gfx_ctx_on_ctx(struct context *dest, struct context *src, vec2 pos, u8 alph
}
}
-void gfx_draw_rectangle(struct context *ctx, vec2 pos1, vec2 pos2, u32 c)
-{
- draw_rectangle(ctx, pos1, pos2, c);
-}
-
void gfx_clear(struct context *ctx)
{
memset(ctx->fb, 0, ctx->bytes);
@@ -335,7 +329,7 @@ void gfx_clear(struct context *ctx)
void gfx_fill(struct context *ctx, u32 c)
{
- draw_rectangle(ctx, vec2(0, 0), vec2(ctx->size.x, ctx->size.y), c);
+ gfx_draw_rectangle(ctx, vec2(0, 0), vec2(ctx->size.x, ctx->size.y), c);
}
void gfx_border(struct context *ctx, u32 c, u32 width)
diff --git a/libs/libgui/gfx.h b/libs/libgui/gfx.h
index 1dfa96d..eb98578 100644
--- a/libs/libgui/gfx.h
+++ b/libs/libgui/gfx.h
@@ -43,10 +43,13 @@
#define WF_NO_FB (1 << 3)
#define WF_NO_WINDOW (1 << 4)
#define WF_ALPHA (1 << 5)
+#define WF_BAR (1 << 6)
#define GFX_NON_ALPHA 0
#define GFX_ALPHA 1
+#define GFX_CENTER_IN(a, b) (ABS((a) - (b)) / 2)
+
enum font_type { FONT_8, FONT_12, FONT_16, FONT_24, FONT_32, FONT_64 };
enum gfx_filter {
GFX_FILTER_NONE,
@@ -89,12 +92,4 @@ void gfx_border(struct context *ctx, u32 c, u32 width) NONNULL;
int gfx_font_height(enum font_type);
int gfx_font_width(enum font_type);
-/**
- * Wrappers
- */
-
-/* #define gfx_redraw() \ */
-/* (msg_send(pidof(WM_PATH), GFX_REDRAW, NULL)) // TODO: Partial redraw (optimization) */
-/* #define gfx_redraw_focused() (msg_send(pidof(WM_PATH), GFX_REDRAW_FOCUSED, NULL)) */
-
#endif
diff --git a/libs/libgui/gui.c b/libs/libgui/gui.c
index 891a0e4..023bc98 100644
--- a/libs/libgui/gui.c
+++ b/libs/libgui/gui.c
@@ -24,12 +24,16 @@ struct gui_widget {
struct gui_window {
u32 id;
+ vec2 pos;
struct context ctx;
struct list *widgets;
};
struct list *windows = NULL;
+#define gui_error(error) \
+ err(1, "%s:%d in %s: GUI Error: %s\n", __FILE__, __LINE__, __func__, strerror(error))
+
/**
* Resolve/find stuff
*/
@@ -120,71 +124,80 @@ static void gui_connect_wm(void)
* GFX wrappers
*/
-res gui_clear(u32 win_id, u32 widget_id, enum gui_layer layer)
+void gui_clear(u32 win_id, u32 widget_id, enum gui_layer layer)
{
struct gui_widget *widget = gui_widget_by_id(win_id, widget_id);
if (!widget)
- return_errno(ENOENT);
+ gui_error(ENOENT);
if (layer == GUI_LAYER_BG)
gfx_clear(&widget->bg);
else if (layer == GUI_LAYER_FG)
gfx_clear(&widget->fg);
else
- return_errno(EINVAL);
-
- return_errno(EOK);
+ gui_error(EINVAL);
}
-res gui_fill(u32 win_id, u32 widget_id, enum gui_layer layer, u32 c)
+void gui_fill(u32 win_id, u32 widget_id, enum gui_layer layer, u32 c)
{
struct gui_widget *widget = gui_widget_by_id(win_id, widget_id);
if (!widget)
- return_errno(ENOENT);
+ gui_error(ENOENT);
if (layer == GUI_LAYER_BG)
gfx_fill(&widget->bg, c);
else if (layer == GUI_LAYER_FG)
gfx_fill(&widget->fg, c);
else
- return_errno(EINVAL);
+ gui_error(EINVAL);
+}
+
+void gui_write(u32 win_id, u32 widget_id, enum gui_layer layer, vec2 pos, enum font_type font_type,
+ u32 c, const char *text)
+{
+ struct gui_widget *widget = gui_widget_by_id(win_id, widget_id);
+ if (!widget)
+ gui_error(ENOENT);
- return_errno(EOK);
+ if (layer == GUI_LAYER_BG)
+ gfx_write(&widget->bg, pos, font_type, c, text);
+ else if (layer == GUI_LAYER_FG)
+ gfx_write(&widget->fg, pos, font_type, c, text);
+ else
+ gui_error(EINVAL);
}
-res gui_load_image_filter(u32 win_id, u32 widget_id, enum gui_layer layer, vec2 pos, vec2 size,
- enum gfx_filter filter, const char *path)
+void gui_load_image_filter(u32 win_id, u32 widget_id, enum gui_layer layer, vec2 pos, vec2 size,
+ enum gfx_filter filter, const char *path)
{
UNUSED(size); // TODO: Add image scaling
struct gui_widget *widget = gui_widget_by_id(win_id, widget_id);
if (!widget)
- return_errno(ENOENT);
+ gui_error(ENOENT);
if (layer == GUI_LAYER_BG)
gfx_load_image_filter(&widget->bg, pos, filter, path);
else if (layer == GUI_LAYER_FG)
gfx_load_image_filter(&widget->fg, pos, filter, path);
else
- return_errno(EINVAL);
-
- return_errno(EOK);
+ gui_error(EINVAL);
}
-res gui_load_image(u32 win_id, u32 widget_id, enum gui_layer layer, vec2 pos, vec2 size,
- const char *path)
+void gui_load_image(u32 win_id, u32 widget_id, enum gui_layer layer, vec2 pos, vec2 size,
+ const char *path)
{
- return gui_load_image_filter(win_id, widget_id, layer, pos, size, GFX_FILTER_NONE, path);
+ gui_load_image_filter(win_id, widget_id, layer, pos, size, GFX_FILTER_NONE, path);
}
/**
* Widgets
*/
-static res gui_sub_widget_at(struct gui_widget *widget, vec2 pos, struct gui_widget *buf)
+static u8 gui_sub_widget_at(struct gui_widget *widget, vec2 pos, struct gui_widget *buf)
{
if (!widget || !widget->children || !buf)
- return_errno(EFAULT);
+ gui_error(EFAULT);
struct gui_widget *ret = NULL;
struct gui_widget sub = { 0 };
@@ -196,32 +209,29 @@ static res gui_sub_widget_at(struct gui_widget *widget, vec2 pos, struct gui_wid
pos.y <= w->pos.y + w->bg.size.y)
ret = w;
- if (w->children->head) {
- if (gui_sub_widget_at(w, pos, &sub) == EOK)
- ret = &sub;
- }
+ if (w->children->head && gui_sub_widget_at(w, pos, &sub))
+ ret = &sub;
iterator = iterator->next;
}
- if (ret) {
- *buf = *ret;
- return_errno(EOK);
- } else {
- return_errno(ENOENT);
- }
+ if (!ret)
+ return 0;
+
+ *buf = *ret;
+ return 1;
}
-static res gui_widget_at(u32 win_id, vec2 pos, struct gui_widget *widget)
+static u8 gui_widget_at(u32 win_id, vec2 pos, struct gui_widget *widget)
{
if (!widget)
- return_errno(EFAULT);
+ gui_error(EFAULT);
struct gui_window *win = gui_window_by_id(win_id);
if (!win)
- return_errno(ENOENT);
+ gui_error(ENOENT);
if (!win->widgets)
- return_errno(EOK);
+ return 1;
struct gui_widget *ret = NULL;
struct gui_widget sub = { 0 };
@@ -233,28 +243,25 @@ static res gui_widget_at(u32 win_id, vec2 pos, struct gui_widget *widget)
pos.y <= w->pos.y + w->bg.size.y)
ret = w;
- if (w->children->head) {
- if (gui_sub_widget_at(w, pos, &sub) == EOK)
- ret = &sub;
- }
+ if (w->children->head && gui_sub_widget_at(w, pos, &sub))
+ ret = &sub;
iterator = iterator->next;
}
- if (ret) {
- *widget = *ret;
- return_errno(EOK);
- } else {
- return_errno(ENOENT);
- }
+ if (!ret)
+ return 0;
+
+ *widget = *ret;
+ return 1;
}
-static res gui_sync_sub_widgets(struct gui_widget *widget)
+static void gui_sync_sub_widgets(struct gui_widget *widget)
{
if (!widget)
- return_errno(EFAULT);
+ gui_error(EFAULT);
if (!widget->children)
- return_errno(EOK);
+ return;
struct node *iterator = widget->children->head;
while (iterator) {
@@ -263,32 +270,28 @@ static res gui_sync_sub_widgets(struct gui_widget *widget)
gfx_ctx_on_ctx(&widget->fg, &w->fg, w->pos, GFX_NON_ALPHA);
iterator = iterator->next;
}
-
- return_errno(EOK);
}
-static res gui_sync_widget(u32 win_id, u32 widget_id)
+static void gui_sync_widget(u32 win_id, u32 widget_id)
{
struct gui_window *win = gui_window_by_id(win_id);
struct gui_widget *widget = gui_widget_in_win(win, widget_id);
if (!widget)
- return_errno(ENOENT);
+ gui_error(ENOENT);
gui_sync_sub_widgets(widget);
gfx_ctx_on_ctx(&win->ctx, &widget->bg, widget->pos, GFX_ALPHA);
gfx_ctx_on_ctx(&win->ctx, &widget->fg, widget->pos, GFX_ALPHA);
-
- return_errno(EOK);
}
-static res gui_sync_widgets(u32 win_id)
+static void gui_sync_widgets(u32 win_id)
{
struct gui_window *win = gui_window_by_id(win_id);
if (!win)
- return_errno(ENOENT);
+ gui_error(ENOENT);
if (!win->widgets)
- return_errno(EOK);
+ return;
struct node *iterator = win->widgets->head;
while (iterator) {
@@ -298,15 +301,20 @@ static res gui_sync_widgets(u32 win_id)
gfx_ctx_on_ctx(&win->ctx, &widget->fg, widget->pos, GFX_ALPHA);
iterator = iterator->next;
}
-
- return_errno(EOK);
}
-static struct gui_widget *gui_win_main_widget(struct gui_window *win)
+static struct gui_widget *gui_main_widget(struct gui_window *win)
{
+ assert(win && win->widgets && win->widgets->head);
return win->widgets->head->data;
}
+static u32 gui_main_widget_id(struct gui_window *win)
+{
+ assert(win && win->widgets && win->widgets->head);
+ return ((struct gui_widget *)win->widgets->head->data)->id;
+}
+
// TODO: This is very recursive and inefficient -> improve!
static vec2 gui_offset_widget(struct gui_widget *parent, struct gui_widget *child)
{
@@ -335,7 +343,7 @@ static vec2 gui_offset_widget(struct gui_widget *parent, struct gui_widget *chil
return offset;
}
-static struct gui_widget *gui_new_plain_widget(vec2 size, vec2 pos, u8 bpp)
+static struct gui_widget *gui_new_plain_widget(vec2 pos, vec2 size, u8 bpp)
{
struct gui_widget *widget = zalloc(sizeof(*widget));
struct context *bg = zalloc(sizeof(*bg));
@@ -351,39 +359,35 @@ static struct gui_widget *gui_new_plain_widget(vec2 size, vec2 pos, u8 bpp)
return widget;
}
-res gui_add_widget(u32 win_id, u32 widget_id, vec2 size, vec2 pos)
+void gui_add_widget(u32 *widget, u32 win_id, u32 widget_id, vec2 pos, vec2 size)
{
struct gui_widget *parent = gui_widget_by_id(win_id, widget_id);
if (!parent)
- return_errno(ENOENT);
+ gui_error(ENOENT);
- struct gui_widget *child = gui_new_plain_widget(size, pos, parent->bg.bpp);
+ struct gui_widget *child = gui_new_plain_widget(pos, size, parent->bg.bpp);
list_add(parent->children, child);
- return child->id;
+ *widget = child->id;
}
-res gui_new_widget(u32 win_id, vec2 size, vec2 pos)
+void gui_new_widget(u32 *widget, u32 win_id, vec2 pos, vec2 size)
{
struct gui_window *win = gui_window_by_id(win_id);
if (!win)
- return_errno(ENOENT);
+ gui_error(ENOENT);
- if (!win->widgets->head)
- list_add(win->widgets,
- gui_new_plain_widget(win->ctx.size, vec2(0, 0), win->ctx.bpp));
-
- return gui_add_widget(win->id, gui_win_main_widget(win)->id, size, pos);
+ gui_add_widget(widget, win->id, gui_main_widget(win)->id, pos, size);
}
-res gui_listen_widget(u32 win_id, u32 widget_id, enum gui_listener listener, u32 func)
+void gui_listen_widget(u32 win_id, u32 widget_id, enum gui_listener listener, u32 func)
{
if (!func)
- return_errno(EFAULT);
+ gui_error(EFAULT);
struct gui_widget *widget = gui_widget_by_id(win_id, widget_id);
if (!widget)
- return_errno(ENOENT);
+ gui_error(ENOENT);
switch (listener) {
case GUI_LISTEN_MOUSEMOVE:
@@ -393,21 +397,38 @@ res gui_listen_widget(u32 win_id, u32 widget_id, enum gui_listener listener, u32
widget->event.mouseclick = (void (*)(u32, vec2))func;
break;
default:
- return_errno(ENOENT);
+ gui_error(ENOENT);
}
+}
- return_errno(EOK);
+void gui_redraw_widget(u32 win_id, u32 widget_id)
+{
+ gui_sync_widget(win_id, widget_id);
+ gui_redraw_window(win_id);
}
-res gui_redraw_widget(u32 win_id, u32 widget_id)
+/**
+ * Popups/alerts
+ */
+
+#define POPUP_WIDTH 200
+#define POPUP_HEIGHT 100
+
+void gui_popup(const char *text)
{
- if (gui_sync_widget(win_id, widget_id) != EOK)
- return errno;
+ vec2 pos = vec2(200, 200);
+
+ u32 popup;
+ gui_new_custom_window(&popup, pos, vec2(POPUP_WIDTH, POPUP_HEIGHT));
+ struct gui_window *win = gui_window_by_id(popup);
+ gui_fill(popup, gui_main_widget_id(win), GUI_LAYER_BG, COLOR_WHITE);
- if (gui_redraw_window(win_id) != EOK)
- return errno;
+ u32 widget;
+ gui_new_widget(&widget, popup, vec2(0, 0), vec2(POPUP_WIDTH, 32));
+ gui_fill(popup, widget, GUI_LAYER_BG, COLOR_WHITE);
+ gui_write(popup, widget, GUI_LAYER_FG, vec2(0, 0), FONT_32, COLOR_BLACK, text);
- return_errno(EOK);
+ gui_redraw_window(popup);
}
/**
@@ -418,7 +439,7 @@ vec2 gui_window_size(u32 win_id)
{
struct gui_window *win = gui_window_by_id(win_id);
if (!win)
- return vec2(0, 0);
+ gui_error(ENOENT);
return win->ctx.size;
}
@@ -426,97 +447,107 @@ vec2 gui_window_size(u32 win_id)
* Window manager interfaces
*/
-res gui_new_window(u32 *id)
+void gui_new_custom_window(u32 *id, vec2 pos, vec2 size)
{
if (!windows)
windows = list_new();
+ if (vec2_sum(pos) == 0)
+ pos = vec2(200, 200);
+
+ if (vec2_sum(size) == 0)
+ size = vec2(600, 400);
+
struct gui_window *win = zalloc(sizeof(*win));
+ struct message_new_window msg = { .header.state = MSG_NEED_ANSWER,
+ .pos = pos,
+ .size = size };
- struct message_new_window msg = { .header.state = MSG_NEED_ANSWER };
gui_connect_wm();
if (msg_send(GUI_NEW_WINDOW, &msg, sizeof(msg)) > 0 && msg_receive(&msg, sizeof(msg)) > 0 &&
msg.header.type == (GUI_NEW_WINDOW | MSG_SUCCESS)) {
win->id = msg.id;
win->ctx = msg.ctx;
- u32 size;
- res ret = shaccess(msg.shid, (u32 *)&win->ctx.fb, &size);
+ win->pos = msg.pos;
+ u32 buf_size;
+ res ret = shaccess(msg.shid, (u32 *)&win->ctx.fb, &buf_size);
if (ret < 0 || !win->ctx.fb)
- return_errno(-MIN(ret, -EFAULT));
+ gui_error(-MIN(ret, -EFAULT));
+
+ // Apply offset
+ win->ctx.size = vec2_sub(win->ctx.size, msg.off);
+ win->ctx.bytes -= msg.off.y * msg.ctx.pitch;
+ win->ctx.fb += msg.off.y * msg.ctx.pitch;
+
list_add(windows, win);
win->widgets = list_new();
+ list_add(win->widgets,
+ gui_new_plain_widget(vec2(0, 0), win->ctx.size, win->ctx.bpp));
+
*id = win->id;
- return_errno(EOK);
+ return;
}
- return_errno(EINVAL);
+ gui_error(EINVAL);
}
-res gui_redraw_window(u32 id)
+INLINE void gui_new_window(u32 *id)
{
- res ret = gui_sync_widgets(id);
- if (ret != 0)
- return_errno(ENOENT);
+ gui_new_custom_window(id, vec2(0, 0), vec2(0, 0));
+}
+
+void gui_redraw_window(u32 id)
+{
+ gui_sync_widgets(id);
struct message_redraw_window msg = { .id = id, .header.state = MSG_NEED_ANSWER };
gui_connect_wm();
if (msg_send(GUI_REDRAW_WINDOW, &msg, sizeof(msg)) > 0 &&
msg_receive(&msg, sizeof(msg)) > 0 &&
msg.header.type == (GUI_REDRAW_WINDOW | MSG_SUCCESS))
- return EOK;
+ return;
- return_errno(EINVAL);
+ gui_error(EINVAL);
}
/**
* Message handling
*/
-static res gui_handle_error(const char *op, res code)
-{
- log("GUI error at '%s': %s (%d)\n", op, strerror(code), code);
- return code;
-}
-
-static res gui_handle_ping(struct message_ping *msg)
+static void gui_handle_ping(struct message_ping *msg)
{
if (msg->ping != MSG_PING_SEND)
- return gui_handle_error("ping", EINVAL);
+ gui_error(EINVAL);
msg->header.type |= MSG_SUCCESS;
msg->ping = MSG_PING_RECV;
if (msg_connect_conn(msg->header.bus.conn) == EOK &&
msg_send(GUI_PING, msg, sizeof(msg)) == EOK)
- return EOK;
- else
- return errno;
+ return;
+ gui_error(errno);
}
-static res gui_handle_mouse(struct message_mouse *msg)
+static void gui_handle_mouse(struct message_mouse *msg)
{
if (msg->header.state == MSG_NEED_ANSWER) {
if (msg_connect_conn(msg->header.bus.conn) == EOK &&
msg_send(msg->header.type | MSG_SUCCESS, msg, sizeof(msg)) == EOK)
- return EOK;
- else
- return errno;
+ return;
+ gui_error(errno);
}
struct gui_widget widget = { 0 };
- if (gui_widget_at(msg->id, msg->pos, &widget) != EOK)
- return_errno(EOK);
+ gui_widget_at(msg->id, msg->pos, &widget);
struct gui_window *win = gui_window_by_id(msg->id);
- vec2 offset = gui_offset_widget(gui_win_main_widget(win), &widget);
+ vec2 offset = gui_offset_widget(gui_main_widget(win), &widget);
if (widget.event.mousemove)
widget.event.mousemove(widget.id, vec2_sub(msg->pos, offset));
if (widget.event.mouseclick && msg->bits.click)
widget.event.mouseclick(widget.id, vec2_sub(msg->pos, offset));
-
- return_errno(EOK);
}
static void gui_handle_exit(void)
@@ -559,7 +590,7 @@ void gui_loop(void)
break;
default:
// TODO: Fix random unknown msg types
- gui_handle_error("loop", EINVAL);
+ gui_error(EINVAL);
}
}
diff --git a/libs/libgui/gui.h b/libs/libgui/gui.h
index 9473bd9..c7dc24f 100644
--- a/libs/libgui/gui.h
+++ b/libs/libgui/gui.h
@@ -18,20 +18,25 @@ enum gui_layer {
GUI_LAYER_FG,
};
-res gui_new_window(u32 *id);
-res gui_redraw_window(u32 id);
-
-res gui_clear(u32 win_id, u32 widget_id, enum gui_layer layer);
-res gui_fill(u32 win_id, u32 widget_id, enum gui_layer layer, u32 c);
-res gui_load_image(u32 win_id, u32 widget_id, enum gui_layer layer, vec2 pos, vec2 size,
- const char *path) NONNULL;
-res gui_load_image_filter(u32 win_id, u32 widget_id, enum gui_layer layer, vec2 pos, vec2 size,
- enum gfx_filter filter, const char *path) NONNULL;
-
-res gui_add_widget(u32 win_id, u32 widget_id, vec2 size, vec2 pos);
-res gui_new_widget(u32 win_id, vec2 size, vec2 pos);
-res gui_listen_widget(u32 win_id, u32 widget_id, enum gui_listener listener, u32 func);
-res gui_redraw_widget(u32 win_id, u32 widget_id);
+void gui_new_custom_window(u32 *id, vec2 pos, vec2 size);
+void gui_new_window(u32 *id);
+void gui_redraw_window(u32 id);
+
+void gui_clear(u32 win_id, u32 widget_id, enum gui_layer layer);
+void gui_fill(u32 win_id, u32 widget_id, enum gui_layer layer, u32 c);
+void gui_write(u32 win_id, u32 widget_id, enum gui_layer layer, vec2 pos, enum font_type font_type,
+ u32 c, const char *text);
+void gui_load_image(u32 win_id, u32 widget_id, enum gui_layer layer, vec2 pos, vec2 size,
+ const char *path) NONNULL;
+void gui_load_image_filter(u32 win_id, u32 widget_id, enum gui_layer layer, vec2 pos, vec2 size,
+ enum gfx_filter filter, const char *path) NONNULL;
+
+void gui_add_widget(u32 *widget, u32 win_id, u32 widget_id, vec2 pos, vec2 size);
+void gui_new_widget(u32 *widget, u32 win_id, vec2 pos, vec2 size);
+void gui_listen_widget(u32 win_id, u32 widget_id, enum gui_listener listener, u32 func);
+void gui_redraw_widget(u32 win_id, u32 widget_id);
+
+void gui_popup(const char *text);
vec2 gui_window_size(u32 win_id);
diff --git a/libs/libgui/msg.h b/libs/libgui/msg.h
index 857042c..b29d0c8 100644
--- a/libs/libgui/msg.h
+++ b/libs/libgui/msg.h
@@ -35,6 +35,9 @@ struct message_new_window {
struct message_header header;
u32 id;
u32 shid;
+ vec2 off;
+ vec2 size;
+ vec2 pos;
struct context ctx;
};
diff --git a/run b/run
index cb89ef8..8f882e0 100755
--- a/run
+++ b/run
@@ -107,8 +107,7 @@ make_disk() {
rm -rf "spleen-$VERSION"*
cd ../../
- icons="cursor-default
- cursor-default-outline
+ icons="close
chess-bishop
chess-king
chess-knight