UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2025 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <unistd.h> 32 #include <pthread.h> 33 34 #include "toolkit.h" 35 36 #include "../common/message.h" 37 #include "../common/threadpool.h" 38 #include "../common/app.h" 39 40 #include <cx/hash_map.h> 41 #include <cx/printf.h> 42 43 static const char *ui_app_name; 44 45 static UiMessageHandler *message_handler; 46 47 static ui_callback onstartup; 48 static void *onstartupdata; 49 50 static UiQueue *event_queue; 51 52 static CxMap *srv_obj_map; 53 static uint64_t srv_obj_id_counter = 0; 54 55 void ui_init(const char *appname, int argc, char **argv) { 56 ui_app_name = appname; 57 58 message_handler = uic_simple_msg_handler(STDIN_FILENO, STDOUT_FILENO, ui_server_message_received); 59 60 srv_obj_map = cxHashMapCreateSimple(CX_STORE_POINTERS); 61 } 62 63 const char* ui_appname() { 64 return ui_app_name; 65 } 66 67 void ui_add_styledata(const char *styledata, int len) { 68 // NOOP 69 } 70 71 72 void ui_server_message_received(cxstring msg) { 73 74 } 75 76 void ui_main(void) { 77 uic_simple_msg_handler_start(message_handler); 78 uic_application_startup(NULL); 79 event_queue = ui_queue_create(); 80 UiServerEvent *event = NULL; 81 while((event = ui_queue_get_wait(event_queue)) != NULL) { 82 if(event->callback) { 83 event->callback(&event->event, event->userdata); 84 } 85 } 86 ui_queue_free(event_queue); 87 } 88 89 typedef struct CallMain { 90 UiServerEvent event; 91 ui_threadfunc func; 92 void *data; 93 } CallMain; 94 95 static void mainthr(UiServerEventData *event, void *userdata) { 96 CallMain *c = userdata; 97 if(c->func) { 98 c->func(c->data); 99 } 100 free(c); 101 } 102 103 void ui_call_mainthread(ui_threadfunc tf, void* td) { 104 CallMain *c = malloc(sizeof(CallMain)); 105 c->func = tf; 106 c->data = td; 107 ui_queue_put(event_queue, c); 108 } 109 110 void ui_show(UiObject *obj) { 111 if(!obj->widget->sent) { 112 cxmutstr msg = obj->widget->serialize(obj->widget); 113 obj->widget->sent = TRUE; 114 uic_message_send(message_handler, msg); 115 free(msg.ptr); 116 } 117 cxmutstr msg = cx_asprintf("{\"type\":\"show\", \"obj\":\"%s\"}\n", obj->widget->obj->id.ptr); 118 obj->widget->invisible = FALSE; 119 uic_message_send(message_handler, msg); 120 free(msg.ptr); 121 } 122 123 UiSrvObj* ui_create_server_object(UiContext *ctx) { 124 const CxAllocator *a = ctx->allocator; 125 UiSrvObj *obj = cxZalloc(a, sizeof(UiSrvObj)); 126 127 char id[32]; 128 snprintf(id, 32, "%" PRIu64, srv_obj_id_counter++); 129 obj->id = cx_strdup_a(a, id); 130 obj->ctx = ctx; 131 132 obj->widgets = cxHashMapCreate(a, CX_STORE_POINTERS, 64); 133 134 return obj; 135 } 136 137 void ui_reg_widget(UiWidget *widget) { 138 UiSrvObj *obj = widget->obj; 139 140 char id[32]; 141 snprintf(id, 32, "%" PRIu64, obj->widget_id_counter++); 142 143 widget->id = cx_strdup_a(widget->obj->ctx->allocator, cx_str(id)); 144 cxMapPut(obj->widgets, id, widget); 145 } 146 147