From 6dd051e2ec4db09152f08dda342f5d069bb64ce4 Mon Sep 17 00:00:00 2001 From: Milo Turner Date: Sat, 22 Feb 2020 16:22:01 -0500 Subject: [PATCH] [window] initial work on creating windows --- src/ax.h | 11 +++++--- src/backend/sdl.c | 4 ++- src/ctxt.h | 9 ++++++- src/ctxt/ctxt.c | 64 +++++++++++++++++++++++++++++++++++++++++++++-- src/ctxt/window.c | 48 +++++++++++++++++++++++++++++++++++ src/ctxt/window.h | 63 ++++++++++++++++++++++++++++++++++++++++++++++ test/main.c | 20 +++++++++++++++ 7 files changed, 211 insertions(+), 8 deletions(-) create mode 100644 src/ctxt/window.c create mode 100644 src/ctxt/window.h diff --git a/src/ax.h b/src/ax.h index 34ac88e..98d5451 100644 --- a/src/ax.h +++ b/src/ax.h @@ -46,11 +46,14 @@ int ax_select_theme(struct ax_ctxt* ax, struct ax_theme* thm); * -------------------------------------------------------------------------- */ void ax_begin_window(struct ax_ctxt* ax); -void ax_set_window_title(struct ax_ctxt* ax, const char* text); -void ax_set_window_size(struct ax_ctxt* ax, uint64_t w, uint64_t h, bool resize); -int ax_end_window(struct ax_ctxt* ax, struct ax_window** out_win); +struct ax_window* ax_end_window(struct ax_ctxt* ax); -void ax_select_window(struct ax_ctxt* ax, struct ax_window* win); +void ax_set_window_title( + struct ax_ctxt* ax, const char* text); +void ax_set_window_size( + struct ax_ctxt* ax, uint64_t w, uint64_t h, bool resizable); + +int ax_select_window(struct ax_ctxt* ax, struct ax_window* win); /* ----------------------------------------------------------------------------- * Cursor diff --git a/src/backend/sdl.c b/src/backend/sdl.c index 8e5112a..2bf9bc8 100644 --- a/src/backend/sdl.c +++ b/src/backend/sdl.c @@ -126,7 +126,9 @@ void ax__backend_step(struct ax_backend* bac) break; }); - default: break; + default: + printf("Got a weird message: `%s'\n", ax__msg_name(mqr__type)); + break; } msgq_end_recv(bac->inbox); diff --git a/src/ctxt.h b/src/ctxt.h index 702461e..747477e 100644 --- a/src/ctxt.h +++ b/src/ctxt.h @@ -7,6 +7,8 @@ struct ax_theme; struct ax_theme_builder; +struct ax_window; +struct ax_window_builder; struct ax_backend; struct ax_evt_list; @@ -28,7 +30,12 @@ struct ax_ctxt { // theme struct rgn* thmb_rgn; struct ax_theme_builder* thmb; - struct ax_theme* sel_theme; + struct ax_theme* sel_thm; + + // window + struct rgn* winb_rgn; + struct ax_window_builder* winb; + struct ax_window* sel_win; }; void ax__ctxt_init(struct ax_ctxt* ax, struct rgn* self_rgn); diff --git a/src/ctxt/ctxt.c b/src/ctxt/ctxt.c index c0d059d..dc06acb 100644 --- a/src/ctxt/ctxt.c +++ b/src/ctxt/ctxt.c @@ -5,6 +5,7 @@ #include "../ctxt.h" #include "../util.h" #include "theme.h" +#include "window.h" #include /* ----------------------------------------------------------------------------- @@ -59,7 +60,11 @@ void ax__ctxt_init(struct ax_ctxt* ax, struct rgn* init_rgn) ax->thmb_rgn = rgn_new(init_rgn, THEME_BUILDER_DESIRED_REGION_SIZE); ax->thmb = NULL; - ax->sel_theme = NULL; + ax->sel_thm = NULL; + + ax->winb_rgn = rgn_new(init_rgn, WINDOW_BUILDER_DESIRED_REGION_SIZE); + ax->winb = NULL; + ax->sel_win = NULL; ax->bac = NULL; spawn_backend(init_rgn, &ax->bac_thid, &ax->bac); @@ -190,11 +195,66 @@ int ax_select_theme(struct ax_ctxt* ax, struct ax_theme* thm) ax->err = "theme hasn't finished loading"; return AX_ERR_THEME_LOADING; } - ax->sel_theme = thm; + ax->sel_thm = thm; ax_log(ax, "theme selected"); return 0; } +/* ----------------------------------------------------------------------------- + * API functions :: window + * -------------------------------------------------------------------------- */ + +void ax_begin_window(struct ax_ctxt* ax) +{ + rgn_clear(ax->winb_rgn); + ax->winb = ax__window_builder_new(ax->winb_rgn); +} + +void ax_set_window_title( + struct ax_ctxt* ax, const char* text) +{ + if (ax->winb == NULL) { + ax_log(ax, "`ax_set_window_title' called while not building a window"); + return; + } + ax__window_set_title(ax->winb, text); +} + +void ax_set_window_size( + struct ax_ctxt* ax, uint64_t w, uint64_t h, bool resizable) +{ + if (ax->winb == NULL) { + ax_log(ax, "`ax_set_window_size' called while not building a window"); + return; + } + ax__window_set_size(ax->winb, w, h); + ax__window_set_flag(ax->winb, AX_WIN_RESIZABLE, resizable); +} + +struct ax_window* ax_end_window(struct ax_ctxt* ax) +{ + if (ax->winb == NULL) { + ax_log(ax, "`ax_end_window' called while not building a window"); + return NULL; + } + struct ax_window* win = + ax__window_builder_finish( + ax->winb, + ax->init_rgn, + ax__backend_msgq(ax->bac)); + rgn_clear(ax->winb_rgn); + ax->winb = NULL; + return win; +} + +int ax_select_window(struct ax_ctxt* ax, struct ax_window* win) +{ + ASSERT_NON_NULL(win, "window"); + ax->sel_win = win; + ax_log(ax, "window selected"); + return 0; +} + /* ----------------------------------------------------------------------------- * Backend worker thread * -------------------------------------------------------------------------- */ diff --git a/src/ctxt/window.c b/src/ctxt/window.c new file mode 100644 index 0000000..03a6d8d --- /dev/null +++ b/src/ctxt/window.c @@ -0,0 +1,48 @@ +#include "../concurrent/msg.h" +#include "../concurrent/msgq.h" +#include "window.h" + +static inline const char* default_title(struct rgn* rgn) +{ + return "Ax App"; +} + +static inline void default_size(uint64_t* out_w, uint64_t* out_h) +{ + *out_w = 600; + *out_h = 400; +} + +struct ax_window_builder* ax__window_builder_new(struct rgn* rgn) +{ + struct ax_window_builder* winb = + ralloc_typed(rgn, struct ax_window_builder, 1); + winb->rgn = rgn; + winb->title = default_title(rgn); + default_size(&winb->w, &winb->h); + winb->flags = 0; + return winb; +} + +struct ax_window* ax__window_builder_finish( + struct ax_window_builder* winb, + struct rgn* dst_rgn, + struct msgq* req_window_mq) +{ + struct ax_window* win = + ralloc_typed(dst_rgn, struct ax_window, 1); + win->handle = NULL; + pthread_mutex_init(&win->mx, NULL); + rgn_pin(dst_rgn, &win->mx, (void*) pthread_mutex_destroy); + + struct ax_msg_make_window* m = + msgq_begin_send_typed(req_window_mq, ax_msg_make_window); + m->dst_win = win; + m->title = rstrdup(req_window_mq->rgn, winb->title); + m->width = winb->w; + m->height = winb->h; + m->flags = winb->flags; + msgq_end_send(req_window_mq); + + return win; +} diff --git a/src/ctxt/window.h b/src/ctxt/window.h new file mode 100644 index 0000000..8697bda --- /dev/null +++ b/src/ctxt/window.h @@ -0,0 +1,63 @@ +#pragma once + +#include "../util/region.h" +#include +#include +#include + +struct msgq; +struct ax_backend; +struct ax_window_h; + +#define WINDOW_BUILDER_DESIRED_REGION_SIZE SMALL + +enum ax_window_flags { + AX_WIN_RESIZABLE = 1 << 1, +}; + +struct ax_window { + struct ax_window_h* handle; + pthread_mutex_t mx; +}; + +struct ax_window_builder { + struct rgn* rgn; + const char* title; + uint64_t w; + uint64_t h; + int flags; +}; + +struct ax_window_builder* ax__window_builder_new( + struct rgn* rgn); + +struct ax_window* ax__window_builder_finish( + struct ax_window_builder* winb, + struct rgn* dst_rgn, + struct msgq* req_window_mq); + +static inline void ax__window_set_title( + struct ax_window_builder* winb, + const char* t) +{ + winb->title = rstrdup(winb->rgn, t); +} + +static inline void ax__window_set_size( + struct ax_window_builder* winb, + uint64_t w, uint64_t h) +{ + winb->w = w; + winb->h = h; +} + +static inline void ax__window_set_flag( + struct ax_window_builder* winb, + enum ax_window_flags f, bool set) +{ + if (set) { + winb->flags |= (int) f; + } else { + winb->flags &= ~((int) f); + } +} diff --git a/test/main.c b/test/main.c index 9322e22..9f6adb1 100644 --- a/test/main.c +++ b/test/main.c @@ -21,6 +21,13 @@ static void sigint_handler(int signum) exit(0); } +static struct ax_window* make_window() +{ + ax_begin_window(ax); + ax_set_window_title(ax, "Test App"); + return ax_end_window(ax); +} + static struct ax_theme* make_example_theme() { ax_begin_theme(ax); @@ -37,9 +44,17 @@ int main(void) ax = ax_new(); ax_set_logger(ax, 0, false); + int rv = 0; +#define GUARD(f) if ((rv = f) != 0) goto ax_fail; + + struct ax_window* win = make_window(); struct ax_theme* thm = make_example_theme(); + ax_theme_wait_until_loaded(ax, thm); printf("it loaded!\n"); + + GUARD(ax_select_theme(ax, thm)); + GUARD(ax_select_window(ax, win)); usleep(1000 * 1000 * 2); /* @@ -57,4 +72,9 @@ int main(void) cleanup(); return 0; + +ax_fail: + printf("ERROR: %s\n", ax_get_error(ax)); + cleanup(); + return rv; }