1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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 "container.h"
37 #include "stock.h"
38 #include "../common/menu.h"
39 #include "../common/toolbar.h"
40 #include "../common/document.h"
41 #include "../common/properties.h"
42 #include <cx/buffer.h>
43
44 #include <X11/Intrinsic.h>
45 #include <Xm/CutPaste.h>
46
47 static XtAppContext app;
48 static Display *display;
49 static Widget active_window;
50 static const char *application_name;
51
52 static ui_callback startup_func;
53 static void *startup_data;
54 static ui_callback open_func;
55 void *open_data;
56 static ui_callback exit_func;
57 void *exit_data;
58
59 static ui_callback appclose_fnc;
60 static void *appclose_udata;
61
62 static int is_toplevel_realized =
0;
63
64 int event_pipe[
2];
65
66
67 static String fallback[] = {
68
69 "*renderTable: rt",
70 "*rt*fontType: FONT_IS_XFT",
71 "*rt*fontName: Sans",
72 "*rt*fontSize: 11",
73
74 "*progresss_spinner*renderTable*fontType: FONT_IS_FONT",
75 "*progresss_spinner*renderTable*fontName: Cursor",
76
77 "*window_frame.shadowType: SHADOW_ETCHED_OUT",
78 "*window_frame.shadowThickness: 1",
79 "*togglebutton.shadowThickness: 1",
80 "*togglebutton.highlightThickness: 2",
81
82 "*ui_test.background: red",
83 NULL
84 };
85
86 void input_proc(XtPointer data,
int *source, XtInputId *iid) {
87 void *ptr;
88 read(event_pipe[
0], &ptr,
sizeof(
void*));
89 }
90
91 void ui_init(
const char *appname,
int argc,
char **argv) {
92 application_name = appname;
93 uic_init_global_context();
94
95 XtToolkitInitialize();
96 XtSetLanguageProc(
NULL,
NULL,
NULL);
97 app = XtCreateApplicationContext();
98 XtAppSetFallbackResources(app, fallback);
99
100 display = XtOpenDisplay(app,
NULL, appname, appname,
NULL,
0, &argc, argv);
101
102 uic_docmgr_init();
103 uic_menu_init();
104 uic_toolbar_init();
105 uic_load_app_properties();
106
107 if(pipe(event_pipe)) {
108 fprintf(stderr,
"UiError: Cannot create event pipe\n");
109 exit(-
1);
110 }
111 XtAppAddInput(
112 app,
113 event_pipe[
0],
114 (XtPointer)XtInputReadMask,
115 input_proc,
116 NULL);
117 }
118
119 const char* ui_appname() {
120 return application_name;
121 }
122
123 Display* ui_motif_get_display() {
124 return display;
125 }
126
127 void ui_onstartup(ui_callback f,
void *userdata) {
128 startup_func = f;
129 startup_data = userdata;
130 }
131
132 void ui_onopen(ui_callback f,
void *userdata) {
133 open_func = f;
134 open_data = userdata;
135 }
136
137 void ui_onexit(ui_callback f,
void *userdata) {
138 exit_func = f;
139 exit_data = userdata;
140 }
141
142 void ui_main() {
143 if(startup_func) {
144 startup_func(
NULL, startup_data);
145 }
146 XtAppMainLoop(app);
147 if(exit_func) {
148 exit_func(
NULL, exit_data);
149 }
150 uic_store_app_properties();
151 }
152
153 void ui_exit_mainloop() {
154 XtAppSetExitFlag(app);
155 }
156
157 void ui_secondary_event_loop(
int *loop) {
158 while(*loop && !XtAppGetExitFlag(app)) {
159 XEvent event;
160 XtAppNextEvent(app, &event);
161 XtDispatchEvent(&event);
162 }
163 }
164
165 void ui_show(UiObject *obj) {
166 uic_check_group_widgets(obj->ctx);
167 XtRealizeWidget(obj->widget);
168 }
169
170 void ui_close(UiObject *obj) {
171
172 }
173
174
175 void ui_set_enabled(
UIWIDGET widget,
int enabled) {
176 XtSetSensitive(widget, enabled);
177 }
178
179 void ui_set_show_all(
UIWIDGET widget,
int value) {
180 if(!value) {
181 XtUnmanageChild(widget);
182 }
183 }
184
185 void ui_set_visible(
UIWIDGET widget,
int visible) {
186 if(visible) {
187 XtManageChild(widget);
188 }
else {
189 XtUnmanageChild(widget);
190 }
191 }
192
193 static Boolean ui_job_finished(
void *data) {
194 UiJob *job = data;
195 if(job->finish_callback) {
196 UiEvent event;
197 event.obj = job->obj;
198 event.window = job->obj->window;
199 event.document = job->obj->ctx->document;
200 event.intval =
0;
201 event.eventdata =
NULL;
202 job->finish_callback(&event, job->finish_data);
203 }
204 free(job);
205 return TRUE;
206 }
207
208 static void* ui_jobthread(
void *data) {
209 UiJob *job = data;
210 int result = job->job_func(job->job_data);
211 if(!result) {
212 write(event_pipe[
1], &job,
sizeof(
void*));
213 XtAppAddWorkProc(app, ui_job_finished, job);
214
215 }
216 return NULL;
217 }
218
219 void ui_job(UiObject *obj, ui_threadfunc tf,
void *td, ui_callback f,
void *fd) {
220 UiJob *job = malloc(
sizeof(UiJob));
221 job->obj = obj;
222 job->job_func = tf;
223 job->job_data = td;
224 job->finish_callback = f;
225 job->finish_data = fd;
226 pthread_t pid;
227 pthread_create(&pid,
NULL, ui_jobthread, job);
228 }
229
230 void ui_clipboard_set(
char *str) {
231 int length = strlen(str) +
1;
232
233 Display *dp = XtDisplayOfObject(active_window);
234 Window window = XtWindowOfObject(active_window);
235
236 XmString label = XmStringCreateLocalized(
"toolkit_clipboard");
237 long id =
0;
238
239 while(XmClipboardStartCopy(
240 dp,
241 window,
242 label,
243 CurrentTime,
244 NULL,
245 NULL,
246 &id) == ClipboardLocked);
247 XmStringFree(label);
248
249 while(XmClipboardCopy(
250 dp,
251 window,
252 id,
253 "STRING",
254 str,
255 length,
256 1,
257 NULL) == ClipboardLocked);
258
259 while(XmClipboardEndCopy(dp, window, id) == ClipboardLocked);
260 }
261
262 char* ui_clipboard_get() {
263 Display *dp = XtDisplayOfObject(active_window);
264 Window window = XtWindowOfObject(active_window);
265
266 long id;
267 size_t size =
128;
268 char *buf = malloc(size);
269
270 int r;
271 for(;;) {
272 r = XmClipboardRetrieve(dp, window,
"STRING", buf, size,
NULL, &id);
273 if(r == ClipboardSuccess) {
274 break;
275 }
else if(r == ClipboardTruncate) {
276 size *=
2;
277 buf = realloc(buf, size);
278 }
else if(r == ClipboardNoData) {
279 free(buf);
280 buf =
NULL;
281 break;
282 }
283 }
284
285 return buf;
286 }
287
288 void ui_set_active_window(Widget w) {
289 active_window = w;
290 }
291
292 Widget ui_get_active_window() {
293 return active_window;
294 }
295
296
297
298
299 void ui_window_dark_theme(Display *dp, Window window) {
300 Atom atom = XInternAtom(dp,
"_GTK_THEME_VARIANT", False);
301 Atom type = XInternAtom(dp,
"UTF8_STRING", False);
302 XChangeProperty(
303 dp,
304 window,
305 atom,
306 type,
307 8,
308 PropModeReplace,
309 (
const unsigned char*)
"dark",
310 4);
311 }
312
313 void ui_destroy_eventdata(Widget w, XtPointer data, XtPointer d) {
314 free(data);
315 }
316
317 void ui_set_widget_groups(UiContext *ctx, Widget widget,
const int *groups) {
318 if(!groups) {
319 return;
320 }
321 size_t ngroups = uic_group_array_size(groups);
322 ui_set_widget_ngroups(ctx, widget, groups, ngroups);
323 }
324
325 void ui_set_widget_ngroups(UiContext *ctx, Widget widget,
const int *groups,
size_t ngroups) {
326 if(ngroups >
0) {
327 uic_add_group_widget_i(ctx, widget, (ui_enablefunc)ui_set_enabled, groups, ngroups);
328 ui_set_enabled(widget,
FALSE);
329 }
330 }
331
332