UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2014 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 #include "toolbar.h" 36 #include "stock.h" 37 #include "../common/document.h" 38 #include "../common/properties.h" 39 #include <ucx/buffer.h> 40 41 static XtAppContext app; 42 static Display *display; 43 static Widget active_window; 44 static char *application_name; 45 46 static ui_callback startup_func; 47 static void *startup_data; 48 static ui_callback open_func; 49 void *open_data; 50 static ui_callback exit_func; 51 void *exit_data; 52 53 static ui_callback appclose_fnc; 54 static void *appclose_udata; 55 56 static int is_toplevel_realized = 0; 57 58 int event_pipe[2]; 59 60 61 static String fallback[] = { 62 //"*fontList: -dt-interface system-medium-r-normal-s*utf*:", 63 "*text_area*renderTable: f1", 64 "*f1*fontType: FONT_IS_XFT", 65 "*f1*fontName: Monospace", 66 "*f1*fontSize: 11", 67 "*renderTable: rt", 68 "*rt*fontType: FONT_IS_XFT", 69 "*rt*fontName: Sans", 70 "*rt*fontSize: 11", 71 NULL 72 }; 73 74 void input_proc(XtPointer data, int *source, XtInputId *iid) { 75 void *ptr; 76 read(event_pipe[0], &ptr, sizeof(void*)); 77 } 78 79 void ui_init(char *appname, int argc, char **argv) { 80 application_name = appname; 81 82 XtToolkitInitialize(); 83 XtSetLanguageProc(NULL, NULL, NULL); 84 app = XtCreateApplicationContext(); 85 XtAppSetFallbackResources(app, fallback); 86 87 display = XtOpenDisplay(app, NULL, appname, appname, NULL, 0, &argc, argv); 88 char **missing = NULL; 89 int nm = 0; 90 char *def = NULL; 91 XCreateFontSet(display, "-dt-interface system-medium-r-normal-s*utf*", &missing, &nm, &def); 92 93 uic_docmgr_init(); 94 ui_toolbar_init(); 95 ui_stock_init(); 96 97 uic_load_app_properties(); 98 99 if(pipe(event_pipe)) { 100 fprintf(stderr, "UiError: Cannot create event pipe\n"); 101 exit(-1); 102 } 103 XtAppAddInput( 104 app, 105 event_pipe[0], 106 (XtPointer)XtInputReadMask, 107 input_proc, 108 NULL); 109 } 110 111 char* ui_appname() { 112 return application_name; 113 } 114 115 Display* ui_get_display() { 116 return display; 117 } 118 119 void ui_onstartup(ui_callback f, void *userdata) { 120 startup_func = f; 121 startup_data = userdata; 122 } 123 124 void ui_onopen(ui_callback f, void *userdata) { 125 open_func = f; 126 open_data = userdata; 127 } 128 129 void ui_onexit(ui_callback f, void *userdata) { 130 exit_func = f; 131 exit_data = userdata; 132 } 133 134 void ui_main() { 135 if(startup_func) { 136 startup_func(NULL, startup_data); 137 } 138 XtAppMainLoop(app); 139 if(exit_func) { 140 exit_func(NULL, exit_data); 141 } 142 uic_store_app_properties(); 143 } 144 145 void ui_exit_mainloop() { 146 XtAppSetExitFlag(app); 147 } 148 149 void ui_secondary_event_loop(int *loop) { 150 while(*loop && !XtAppGetExitFlag(app)) { 151 XEvent event; 152 XtAppNextEvent(app, &event); 153 XtDispatchEvent(&event); 154 } 155 } 156 157 void ui_show(UiObject *obj) { 158 uic_check_group_widgets(obj->ctx); 159 XtRealizeWidget(obj->widget); 160 ui_window_dark_theme(XtDisplay(obj->widget), XtWindow(obj->widget)); // TODO: if 161 } 162 163 // implemented in window.c 164 //void ui_close(UiObject *obj) 165 166 void ui_set_enabled(UIWIDGET widget, int enabled) { 167 XtSetSensitive(widget, enabled); 168 } 169 170 void ui_set_show_all(UIWIDGET widget, int value) { 171 if(!value) { 172 XtUnmanageChild(widget); 173 } 174 } 175 176 void ui_set_visible(UIWIDGET widget, int visible) { 177 if(visible) { 178 XtManageChild(widget); 179 } else { 180 XtUnmanageChild(widget); 181 } 182 } 183 184 static Boolean ui_job_finished(void *data) { 185 printf("WorkProc\n"); 186 UiJob *job = data; 187 188 UiEvent event; 189 event.obj = job->obj; 190 event.window = job->obj->window; 191 event.document = job->obj->ctx->document; 192 event.intval = 0; 193 event.eventdata = NULL; 194 195 job->finish_callback(&event, job->finish_data); 196 free(job); 197 return TRUE; 198 } 199 200 static void* ui_jobthread(void *data) { 201 UiJob *job = data; 202 int result = job->job_func(job->job_data); 203 if(!result) { 204 printf("XtAppAddWorkProc\n"); 205 write(event_pipe[1], &job, sizeof(void*)); // hack 206 XtAppAddWorkProc(app, ui_job_finished, job); 207 208 } 209 } 210 211 void ui_job(UiObject *obj, ui_threadfunc tf, void *td, ui_callback f, void *fd) { 212 UiJob *job = malloc(sizeof(UiJob)); 213 job->obj = obj; 214 job->job_func = tf; 215 job->job_data = td; 216 job->finish_callback = f; 217 job->finish_data = fd; 218 pthread_t pid; 219 pthread_create(&pid, NULL, ui_jobthread, job); 220 } 221 222 void ui_clipboard_set(char *str) { 223 printf("copy: {%s}\n", str); 224 int length = strlen(str) + 1; 225 226 Display *dp = XtDisplayOfObject(active_window); 227 Window window = XtWindowOfObject(active_window); 228 229 XmString label = XmStringCreateLocalized("toolkit_clipboard"); 230 long id = 0; 231 232 while(XmClipboardStartCopy( 233 dp, 234 window, 235 label, 236 CurrentTime, 237 NULL, 238 NULL, 239 &id) == ClipboardLocked); 240 XmStringFree(label); 241 242 while(XmClipboardCopy( 243 dp, 244 window, 245 id, 246 "STRING", 247 str, 248 length, 249 1, 250 NULL) == ClipboardLocked); 251 252 while(XmClipboardEndCopy(dp, window, id) == ClipboardLocked); 253 } 254 255 char* ui_clipboard_get() { 256 Display *dp = XtDisplayOfObject(active_window); 257 Window window = XtWindowOfObject(active_window); 258 259 long id; 260 size_t size = 128; 261 char *buf = malloc(size); 262 263 int r; 264 for(;;) { 265 r = XmClipboardRetrieve(dp, window, "STRING", buf, size, NULL, &id); 266 if(r == ClipboardSuccess) { 267 break; 268 } else if(r == ClipboardTruncate) { 269 size *= 2; 270 buf = realloc(buf, size); 271 } else if(r == ClipboardNoData) { 272 free(buf); 273 buf = NULL; 274 break; 275 } 276 } 277 278 return buf; 279 } 280 281 void ui_set_active_window(Widget w) { 282 active_window = w; 283 } 284 285 Widget ui_get_active_window() { 286 return active_window; 287 } 288 289 void ui_window_dark_theme(Display *dp, Window window) { 290 Atom atom = XInternAtom(dp, "_GTK_THEME_VARIANT", False); 291 Atom type = XInternAtom(dp, "UTF8_STRING", False); 292 XChangeProperty( 293 dp, 294 window, 295 atom, 296 type, 297 8, 298 PropModeReplace, 299 (const unsigned char*)"dark", 300 4); 301 } 302