static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, Array args, Error *error) { if (pmap_has(uint64_t)(connected_uis, channel_id)) { api_set_error(error, Exception, _("UI already attached for channel")); return NIL; } if (args.size != 3 || args.items[0].type != kObjectTypeInteger || args.items[1].type != kObjectTypeInteger || args.items[2].type != kObjectTypeBoolean || args.items[0].data.integer <= 0 || args.items[1].data.integer <= 0) { api_set_error(error, Validation, _("Invalid arguments. Expected: " "(uint width > 0, uint height > 0, bool enable_rgb)")); return NIL; } UIData *data = xmalloc(sizeof(UIData)); data->channel_id = channel_id; data->buffer = (Array)ARRAY_DICT_INIT; UI *ui = xcalloc(1, sizeof(UI)); ui->width = (int)args.items[0].data.integer; ui->height = (int)args.items[1].data.integer; ui->rgb = args.items[2].data.boolean; ui->data = data; ui->resize = remote_ui_resize; ui->clear = remote_ui_clear; ui->eol_clear = remote_ui_eol_clear; ui->cursor_goto = remote_ui_cursor_goto; ui->busy_start = remote_ui_busy_start; ui->busy_stop = remote_ui_busy_stop; ui->mouse_on = remote_ui_mouse_on; ui->mouse_off = remote_ui_mouse_off; ui->insert_mode = remote_ui_insert_mode; ui->normal_mode = remote_ui_normal_mode; ui->set_scroll_region = remote_ui_set_scroll_region; ui->scroll = remote_ui_scroll; ui->highlight_set = remote_ui_highlight_set; ui->put = remote_ui_put; ui->bell = remote_ui_bell; ui->visual_bell = remote_ui_visual_bell; ui->update_fg = remote_ui_update_fg; ui->update_bg = remote_ui_update_bg; ui->flush = remote_ui_flush; ui->suspend = remote_ui_suspend; ui->set_title = remote_ui_set_title; ui->set_icon = remote_ui_set_icon; pmap_put(uint64_t)(connected_uis, channel_id, ui); ui_attach(ui); return NIL; }
UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler) { UIBridgeData *rv = xcalloc(1, sizeof(UIBridgeData)); rv->ui = ui; rv->bridge.rgb = ui->rgb; rv->bridge.stop = ui_bridge_stop; rv->bridge.resize = ui_bridge_resize; rv->bridge.clear = ui_bridge_clear; rv->bridge.eol_clear = ui_bridge_eol_clear; rv->bridge.cursor_goto = ui_bridge_cursor_goto; rv->bridge.update_menu = ui_bridge_update_menu; rv->bridge.busy_start = ui_bridge_busy_start; rv->bridge.busy_stop = ui_bridge_busy_stop; rv->bridge.mouse_on = ui_bridge_mouse_on; rv->bridge.mouse_off = ui_bridge_mouse_off; rv->bridge.mode_change = ui_bridge_mode_change; rv->bridge.set_scroll_region = ui_bridge_set_scroll_region; rv->bridge.scroll = ui_bridge_scroll; rv->bridge.highlight_set = ui_bridge_highlight_set; rv->bridge.put = ui_bridge_put; rv->bridge.bell = ui_bridge_bell; rv->bridge.visual_bell = ui_bridge_visual_bell; rv->bridge.update_fg = ui_bridge_update_fg; rv->bridge.update_bg = ui_bridge_update_bg; rv->bridge.flush = ui_bridge_flush; rv->bridge.suspend = ui_bridge_suspend; rv->bridge.set_title = ui_bridge_set_title; rv->bridge.set_icon = ui_bridge_set_icon; rv->scheduler = scheduler; rv->ui_main = ui_main; uv_mutex_init(&rv->mutex); uv_cond_init(&rv->cond); uv_mutex_lock(&rv->mutex); rv->ready = false; if (uv_thread_create(&rv->ui_thread, ui_thread_run, rv)) { abort(); } while (!rv->ready) { uv_cond_wait(&rv->cond, &rv->mutex); } uv_mutex_unlock(&rv->mutex); ui_attach(&rv->bridge); return &rv->bridge; }