Wed, 10 Dec 2025 19:04:46 +0100
implement window (Server)
| application/main.c | file | annotate | diff | comparison | revisions | |
| client/uiclient.c | file | annotate | diff | comparison | revisions | |
| ui/common/message.c | file | annotate | diff | comparison | revisions | |
| ui/common/message.h | file | annotate | diff | comparison | revisions | |
| ui/server/objs.mk | file | annotate | diff | comparison | revisions | |
| ui/server/toolkit.c | file | annotate | diff | comparison | revisions | |
| ui/server/toolkit.h | file | annotate | diff | comparison | revisions | |
| ui/server/window.c | file | annotate | diff | comparison | revisions | |
| ui/server/window.h | file | annotate | diff | comparison | revisions |
--- a/application/main.c Mon Dec 08 18:11:54 2025 +0100 +++ b/application/main.c Wed Dec 10 19:04:46 2025 +0100 @@ -1290,8 +1290,16 @@ #ifdef UI_SERVER -void main(int argc, char **argv) { - +void application_startup(UiEvent *event, void *userdata) { + UiObject *obj = ui_window("Test", NULL); + ui_show(obj); +} + +int main(int argc, char **argv) { + ui_init(NULL, 0, NULL); + ui_onstartup(application_startup, NULL); + ui_main(); + return 0; }
--- a/client/uiclient.c Mon Dec 08 18:11:54 2025 +0100 +++ b/client/uiclient.c Wed Dec 10 19:04:46 2025 +0100 @@ -175,15 +175,23 @@ } int msg_simple_window(UiObject *parent, const CxJsonValue *value) { + cxmutstr obj_id = jsonobj_getstring(value, "obj_id"); cxmutstr id = jsonobj_getstring(value, "id"); cxmutstr title = jsonobj_getstring(value, "title"); - if(!id.ptr) { + if(!obj_id.ptr) { + return 1; + } + if(!id) { return 1; } UiObject *obj = ui_simple_window(title.ptr, NULL); - client_add_obj_mapping(obj, id); + client_add_obj_mapping(obj, obj_id); + + if(obj->widget) { + client_reg_widget(obj, id, obj->widget); + } return client_handle_children(obj, value); }
--- a/ui/common/message.c Mon Dec 08 18:11:54 2025 +0100 +++ b/ui/common/message.c Wed Dec 10 19:04:46 2025 +0100 @@ -34,6 +34,10 @@ #include "message.h" +int uic_message_send_(UiMessageHandler *handler, cxstring msg) { + return handler->send(handler, msg); +} + UiMessageHandler* uic_simple_msg_handler(int in, int out, msg_received_callback callback) { UiSimpleMessageHandler *handler = malloc(sizeof(UiSimpleMessageHandler)); handler->handler.start = uic_simple_msg_handler_start; @@ -79,6 +83,9 @@ int uic_simple_msg_handler_send(UiMessageHandler *handler, cxstring msg) { UiSimpleMessageHandler *sh = (UiSimpleMessageHandler*)handler; pthread_mutex_lock(&sh->queue_lock); + char header[32]; + snprintf(header, 32, "%zu\n", msg.length); + cxBufferPutString(sh->outbuf, header); cxBufferWrite(msg.ptr, 1, msg.length, sh->outbuf); pthread_cond_signal(&sh->available); pthread_mutex_unlock(&sh->queue_lock);
--- a/ui/common/message.h Mon Dec 08 18:11:54 2025 +0100 +++ b/ui/common/message.h Wed Dec 10 19:04:46 2025 +0100 @@ -71,6 +71,9 @@ int stop; } UiSimpleMessageHandler; +int uic_message_send_(UiMessageHandler *handler, cxstring msg); +#define uic_message_send(handler, msg) uic_message_send_(handler, cx_strcast(msg)) + UiMessageHandler* uic_simple_msg_handler(int in, int out, msg_received_callback callback); int uic_simple_msg_handler_start(UiMessageHandler *handler); int uic_simple_msg_handler_stop(UiMessageHandler *handler);
--- a/ui/server/objs.mk Mon Dec 08 18:11:54 2025 +0100 +++ b/ui/server/objs.mk Wed Dec 10 19:04:46 2025 +0100 @@ -31,6 +31,7 @@ SERVEROBJ = toolkit.o SERVEROBJ += widget.o +SERVEROBJ += window.o SERVEROBJ += image.o TOOLKITOBJS += $(SERVEROBJ:%=$(SERVER_OBJPRE)%)
--- a/ui/server/toolkit.c Mon Dec 08 18:11:54 2025 +0100 +++ b/ui/server/toolkit.c Wed Dec 10 19:04:46 2025 +0100 @@ -37,6 +37,9 @@ #include "../common/threadpool.h" #include "../common/app.h" +#include <cx/hash_map.h> +#include <cx/printf.h> + static const char *ui_app_name; static UiMessageHandler *message_handler; @@ -46,10 +49,15 @@ static UiQueue *event_queue; +static CxMap *srv_obj_map; +static uint64_t srv_obj_id_counter = 0; + void ui_init(const char *appname, int argc, char **argv) { ui_app_name = appname; message_handler = uic_simple_msg_handler(STDIN_FILENO, STDOUT_FILENO, ui_server_message_received); + + srv_obj_map = cxHashMapCreateSimple(CX_STORE_POINTERS); } const char* ui_appname() { @@ -66,6 +74,8 @@ } void ui_main(void) { + uic_simple_msg_handler_start(message_handler); + uic_application_startup(NULL); event_queue = ui_queue_create(); UiServerEvent *event = NULL; while((event = ui_queue_get_wait(event_queue)) != NULL) { @@ -96,3 +106,41 @@ c->data = td; ui_queue_put(event_queue, c); } + +void ui_show(UiObject *obj) { + if(!obj->widget->sent) { + cxmutstr msg = obj->widget->serialize(obj->widget); + obj->widget->sent = TRUE; + uic_message_send(message_handler, msg); + free(msg.ptr); + } + cxmutstr msg = cx_asprintf("{\"type\":\"show\", \"obj\":\"%s\"}", obj->widget->obj->id.ptr); + obj->widget->visible = TRUE; + uic_message_send(message_handler, msg); + free(msg.ptr); +} + +UiSrvObj* ui_create_server_object(UiContext *ctx) { + const CxAllocator *a = ctx->allocator; + UiSrvObj *obj = cxZalloc(a, sizeof(UiSrvObj)); + + char id[32]; + snprintf(id, 32, "%" PRIu64, srv_obj_id_counter++); + obj->id = cx_strdup_a(a, id); + obj->ctx = ctx; + + obj->widgets = cxHashMapCreate(a, CX_STORE_POINTERS, 64); + + return obj; +} + +void ui_reg_widget(UiWidget *widget) { + UiSrvObj *obj = widget->obj; + + char id[32]; + snprintf(id, 32, "%" PRIu64, obj->widget_id_counter++); + + widget->id = cx_strdup_a(widget->obj->ctx->allocator, cx_str(id)); + cxMapPut(obj->widgets, id, widget); +} +
--- a/ui/server/toolkit.h Mon Dec 08 18:11:54 2025 +0100 +++ b/ui/server/toolkit.h Wed Dec 10 19:04:46 2025 +0100 @@ -62,7 +62,11 @@ }; struct UiSrvObj { + UiContext *ctx; cxmutstr id; + + CxMap *widgets; + uint64_t widget_id_counter; }; struct UiWidget { @@ -75,11 +79,15 @@ cxmutstr args; UiBool visible; UiBool enabled; - ui_serialize_func *serialize; + UiBool sent; + ui_serialize_func serialize; }; void ui_server_message_received(cxstring msg); +UiSrvObj* ui_create_server_object(UiContext *ctx); +void ui_reg_widget(UiWidget *widget); + #ifdef __cplusplus }
--- a/ui/server/window.c Mon Dec 08 18:11:54 2025 +0100 +++ b/ui/server/window.c Wed Dec 10 19:04:46 2025 +0100 @@ -28,3 +28,76 @@ #include "window.h" +#include "../common/object.h" + +#include <cx/buffer.h> + +static UiObject* create_window(const char *title, UiBool simple, UiBool sidebar, UiBool splitview) { + UiObject *obj = uic_object_new_toplevel(); + const CxAllocator *a = obj->ctx->allocator; + + UiWindow *window = cxZalloc(a, sizeof(UiWindow)); + window->widget.obj = ui_create_server_object(obj->ctx); + window->widget.children = cxLinkedListCreate(a, NULL, CX_STORE_POINTERS); + window->widget.serialize = (ui_serialize_func)ui_window_serialize; + window->title = cx_strdup_a(a, title); + + obj->widget = (UiWidget*)window; + ui_reg_widget(obj->widget); + + return obj; +} + +UiObject *ui_window(const char *title, void *window_data) { + return create_window(title, FALSE, FALSE, FALSE); +} + +UiObject *ui_sidebar_window(const char *title, void *window_data) { + return create_window(title, FALSE, TRUE, FALSE); +} + +UiObject *ui_splitview_window(const char *title, UiBool sidebar) { + return create_window(title, FALSE, sidebar, TRUE); +} + +UiObject *ui_simple_window(const char *title, void *window_data) { + return create_window(title, TRUE, FALSE, FALSE); +} + + +cxmutstr ui_window_serialize(UiWindow *w) { + CxBuffer buf; + cxBufferInit(&buf, NULL, 1024, NULL, CX_BUFFER_AUTO_EXTEND | CX_BUFFER_FREE_CONTENTS); + + cxBufferPutString(&buf, "{\"type\":"); + switch(w->type) { + case UI_WINDOW_MAIN: cxBufferPutString(&buf, "\"window\""); break; + case UI_WINDOW_SIMPLE: cxBufferPutString(&buf, "\"simple_window\""); break; + case UI_WINDOW_SIDEBAR: cxBufferPutString(&buf, "\"sidebar_window\""); break; + case UI_WINDOW_SPLITVIEW: cxBufferPutString(&buf, "\"splitview_window\""); break; + } + + cxmutstr obj_id = w->widget.obj->id; + cxmutstr id = w->widget.id; + + cxBufferPutString(&buf, " obj_id=\""); + cxBufferWrite(obj_id.ptr, 1, obj_id.length, &buf); + cxBufferPutString(&buf, "\""); + + cxBufferPutString(&buf, " id=\""); + cxBufferWrite(id.ptr, 1, id.length, &buf); + cxBufferPutString(&buf, "\""); + + if(w->title.ptr) { + cxBufferPutString(&buf, " title=\""); + cxBufferWrite(w->title.ptr, 1, w->title.length, &buf); + cxBufferPutString(&buf, "\""); + } + + + cxBufferPutString(&buf, "}\n"); + + return cx_mutstrn(buf.space, buf.size); +} + +
--- a/ui/server/window.h Mon Dec 08 18:11:54 2025 +0100 +++ b/ui/server/window.h Wed Dec 10 19:04:46 2025 +0100 @@ -36,8 +36,21 @@ extern "C" { #endif +enum UiWindowType { + UI_WINDOW_MAIN = 0, + UI_WINDOW_SIMPLE, + UI_WINDOW_SIDEBAR, + UI_WINDOW_SPLITVIEW +}; +typedef enum UiWindowType UiWindowType; +typedef struct UiWindow { + UiWidget widget; + UiWindowType type; + cxmutstr title; +} UiWindow; +cxmutstr ui_window_serialize(UiWindow *w); #ifdef __cplusplus }