GCC Code Coverage Report


Directory: src/gate/
File: src/gate/ui/gateui_motif.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 0 348 0.0%
Functions: 0 27 0.0%
Branches: 0 162 0.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | 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 notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/ui/gateui_motif.h"
30 #include "gate/results.h"
31 #include "gate/debugging.h"
32
33 #if defined(GATE_UI_MOTIF)
34
35 #include <Xm/Xm.h>
36 #include <Xm/Primitive.h>
37 #include <X11/Intrinsic.h>
38 #include <Xm/BulletinB.h>
39 #include <X11/IntrinsicP.h>
40
41
42 gate_result_t gate_ui_motif_ctrl_init(gate_ui_ctrl_t* ctrl, Widget widget, void* userparam,
43 gate_ui_host_t* host, gate_ui_ctrl_t* parent, Widget container,
44 gate_ui_position_t const* position, gate_uint32_t const* flags,
45 gate_ui_motif_dispatcher_t* dispatcher)
46 {
47 gate_result_t ret = GATE_RESULT_FAILED;
48 if (!host && parent)
49 {
50 host = GATE_UI_MOTIF_GET_CTRL_HOST(parent);
51 }
52
53 GATE_DEBUG_ASSERT(ctrl != NULL);
54
55 do
56 {
57 GATE_UI_MOTIF_SET_CTRL_WIDGET(ctrl, widget);
58 GATE_UI_MOTIF_SET_CTRL_HOST(ctrl, host);
59 GATE_UI_MOTIF_SET_CTRL_USER_PARAM(ctrl, userparam);
60 GATE_UI_MOTIF_SET_CTRL_PARENT(ctrl, parent);
61 GATE_UI_MOTIF_SET_CTRL_CONTAINER(ctrl, container);
62 GATE_UI_MOTIF_SET_CTRL_DISP(ctrl, dispatcher);
63
64
65 if (gate_ui_motif_widget_is_valid(widget))
66 {
67 XtSetMappedWhenManaged(widget, False);
68 if (position)
69 {
70 if ((position->size.width > 0) && (position->size.height > 0))
71 {
72 gate_ui_motif_widget_set_position(widget, &position->pos, &position->size);
73 }
74 }
75 else
76 {
77 if (parent)
78 {
79 static const gate_ui_point_t p = { 0, 0 };
80 static const gate_ui_size_t s = { 128, 48 };
81 gate_ui_motif_widget_set_position(widget, &p, &s);
82 }
83 }
84 XtVaSetValues(widget, XmNuserData, ctrl, NULL, NULL);
85 XtRealizeWidget(widget);
86 if (flags)
87 {
88 if (GATE_FLAG_ENABLED(*flags, GATE_UI_FLAG_VISIBLE))
89 {
90 XtMapWidget(widget);
91 }
92 }
93 }
94
95 if (gate_ui_motif_widget_is_valid(container))
96 {
97 XtVaSetValues(container, XmNuserData, ctrl, NULL, NULL);
98 XtRealizeWidget(container);
99 XtMapWidget(container);
100
101 ret = gate_ui_motif_host_dispatch_pending_events(host, false);
102 }
103 else
104 {
105 ret = GATE_RESULT_OK;
106 }
107 } while (0);
108
109 return ret;
110 }
111
112 static char gate_ui_motif_ctrl_widget[] = "GATE_UI_MOTIF_CTRL_WIDGET_";
113 static gate_atomic_int_t gate_ui_motif_widget_counter;
114
115 static void gate_ui_motif_generate_widget_name(char* buffer, gate_size_t buffer_capacity)
116 {
117 gate_strbuilder_t builder;
118 gate_strbuilder_create_static(&builder, buffer, buffer_capacity, 0);
119 gate_strbuilder_append_text(&builder, gate_ui_motif_ctrl_widget, sizeof(gate_ui_motif_ctrl_widget) - 1);
120 gate_strbuilder_append_int32(&builder, gate_atomic_int_inc(&gate_ui_motif_widget_counter));
121 }
122
123 gate_result_t gate_ui_motif_ctrl_create(gate_ui_ctrl_t* ctrl, WidgetClass widget_class, void* userparam,
124 gate_ui_host_t* host, gate_ui_ctrl_t* parent,
125 gate_ui_position_t const* position, gate_uint32_t const* flags,
126 gate_bool_t add_container, gate_ui_motif_dispatcher_t* dispatcher,
127 void* args, gate_size_t args_count)
128 {
129 gate_result_t ret = GATE_RESULT_OK;
130 Widget parent_widget = NULL;
131 Widget paremt_container = NULL;
132 Widget new_widget = NULL;
133 Widget new_container = NULL;
134 Display* disp = NULL;
135 char widget_name[64];
136
137 do
138 {
139 gate_ui_motif_generate_widget_name(widget_name, sizeof(widget_name));
140 if (parent)
141 {
142 parent_widget = GATE_UI_MOTIF_GET_CTRL_CONTAINER(parent);
143 if (!parent_widget)
144 {
145 parent_widget = GATE_UI_MOTIF_GET_CTRL_WIDGET(parent);
146 }
147 new_widget = XtCreateWidget(widget_name, widget_class, parent_widget,
148 (ArgList)args, args_count);
149 }
150 else if (host)
151 {
152 disp = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
153 new_widget = XtAppCreateShell(NULL, NULL, widget_class, disp,
154 (ArgList)args, args_count);
155 }
156 else
157 {
158 ret = GATE_RESULT_INVALIDARG;
159 break;
160 }
161
162 if (NULL == new_widget)
163 {
164 ret = GATE_RESULT_FAILED;
165 break;
166 }
167
168 if (parent)
169 {
170 XtManageChild(new_widget);
171 }
172 else
173 {
174 XtRealizeWidget(new_widget);
175 }
176
177 if (add_container)
178 {
179 gate_ui_motif_generate_widget_name(widget_name, sizeof(widget_name));
180 new_container = XtCreateWidget(widget_name, xmBulletinBoardWidgetClass, new_widget, NULL, 0);
181 if (!new_container)
182 {
183 XtDestroyWidget(new_widget);
184 ret = GATE_RESULT_FAILED;
185 break;
186 }
187 XtVaSetValues(new_container,
188 XmNresizePolicy, XmRESIZE_NONE,
189 XmNnoResize, True,
190 XmNmarginWidth, 0,
191 XmNmarginHeight, 0,
192 NULL);
193 XtManageChild(new_container);
194 }
195
196 if (!host && parent)
197 {
198 host = GATE_UI_MOTIF_GET_CTRL_HOST(parent);
199 }
200
201 ret = gate_ui_motif_ctrl_init(ctrl, new_widget, userparam, host, parent, new_container, position, flags, dispatcher);
202 } while (0);
203 return ret;
204 }
205
206 gate_result_t gate_ui_motif_ctrl_destroy_default(gate_ui_ctrl_t* ctrl)
207 {
208 gate_result_t result = GATE_RESULT_OK;
209 gate_ui_ctrl_t* ptr_parent = NULL;
210 gate_array_t list_children = GATE_INIT_EMPTY;
211 Widget w, c;
212 gate_size_t ndx, len;
213 gate_ui_ctrl_t** ptr_childctrl = NULL;
214
215 GATE_DEBUG_ASSERT(ctrl != NULL);
216
217 /* destroy child controls first */
218 result = gate_ui_ctrl_get_children(ctrl, &list_children);
219 if (GATE_SUCCEEDED(result))
220 {
221 len = gate_array_length(&list_children);
222 for (ndx = 0; ndx != len; ++ndx)
223 {
224 ptr_childctrl = (gate_ui_ctrl_t**)gate_array_get(&list_children, ndx);
225 if (ptr_childctrl)
226 {
227 gate_ui_motif_ctrl_destroy(*ptr_childctrl);
228 }
229 }
230 gate_array_release(&list_children);
231 }
232
233 c = GATE_UI_MOTIF_GET_CTRL_CONTAINER(ctrl);
234 if (gate_ui_motif_widget_is_valid(c))
235 {
236 if (XtIsRealized(c))
237 {
238 XtUnrealizeWidget(c);
239 }
240 XtUnmanageChild(c);
241 XtDestroyWidget(c);
242 GATE_UI_MOTIF_SET_CTRL_CONTAINER(ctrl, NULL);
243 }
244
245 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
246 if (gate_ui_motif_widget_is_valid(w))
247 {
248 if (XtIsRealized(w))
249 {
250 XtUnrealizeWidget(w);
251 }
252 ptr_parent = GATE_UI_MOTIF_GET_CTRL_PARENT(ctrl);
253 if (ptr_parent)
254 {
255 XtUnmanageChild(w);
256 GATE_UI_MOTIF_SET_CTRL_PARENT(ctrl, NULL);
257 }
258 XtDestroyWidget(w);
259 GATE_UI_MOTIF_SET_CTRL_WIDGET(ctrl, NULL);
260 GATE_UI_MOTIF_SET_CTRL_USER_PARAM(ctrl, NULL);
261 GATE_UI_MOTIF_SET_CTRL_HOST(ctrl, NULL);
262 GATE_UI_MOTIF_SET_CTRL_DISP(ctrl, NULL);
263 }
264 return GATE_RESULT_OK;
265 }
266
267
268 gate_result_t gate_ui_motif_ctrl_destroy(gate_ui_ctrl_t* ctrl)
269 {
270 gate_result_t ret = GATE_RESULT_OK;
271 gate_ui_motif_dispatcher_t* ptr_disp = NULL;
272 gate_ui_host_t* host = NULL;
273
274 GATE_DEBUG_ASSERT(ctrl != NULL);
275 do
276 {
277 ptr_disp = GATE_UI_MOTIF_GET_CTRL_DISP(ctrl);
278 if (ptr_disp && ptr_disp->destroy)
279 {
280 ret = ptr_disp->destroy(ctrl);
281 }
282 else
283 {
284 ret = gate_ui_motif_ctrl_destroy_default(ctrl);
285 }
286 GATE_BREAK_IF_FAILED(ret);
287
288 host = GATE_UI_MOTIF_GET_CTRL_HOST(ctrl);
289 if (host)
290 {
291 ret = gate_ui_motif_host_dispatch_pending_events(host, false);
292 GATE_UI_MOTIF_SET_CTRL_HOST(ctrl, NULL);
293 }
294
295 GATE_UI_MOTIF_SET_CTRL_DISP(ctrl, NULL);
296 } while (0);
297
298 return ret;
299 }
300
301 gate_result_t gate_ui_motif_ctrl_get_text(gate_ui_ctrl_t* ctrl, gate_string_t* ptr_text)
302 {
303 gate_ui_motif_dispatcher_t* ptr_disp = NULL;
304 Widget w;
305
306 if (!ctrl)
307 {
308 return GATE_RESULT_INVALIDARG;
309 }
310 ptr_disp = GATE_UI_MOTIF_GET_CTRL_DISP(ctrl);
311 if (ptr_disp && ptr_disp->get_text)
312 {
313 return ptr_disp->get_text(ctrl, ptr_text);
314 }
315 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
316 return gate_ui_motif_widget_get_label(w, ptr_text);
317 }
318
319 gate_result_t gate_ui_motif_ctrl_set_text(gate_ui_ctrl_t* ctrl, gate_string_t const* ptr_text)
320 {
321 gate_ui_motif_dispatcher_t* ptr_disp = NULL;
322 Widget w;
323
324 if (!ctrl)
325 {
326 return GATE_RESULT_INVALIDARG;
327 }
328 ptr_disp = GATE_UI_MOTIF_GET_CTRL_DISP(ctrl);
329 if (ptr_disp && ptr_disp->set_text)
330 {
331 return ptr_disp->set_text(ctrl, ptr_text);
332 }
333 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
334 return gate_ui_motif_widget_set_label(w, ptr_text);
335 }
336
337
338 gate_ui_ctrl_t* gate_ui_motif_widget_get_ctrl(Widget widget)
339 {
340 gate_ui_ctrl_t* ptr_ctrl = NULL;
341 if (gate_ui_motif_widget_is_valid(widget))
342 {
343 XtVaGetValues(widget, XmNuserData, &ptr_ctrl, NULL, NULL);
344 }
345 return ptr_ctrl;
346 }
347
348
349 gate_result_t gate_ui_motif_widget_get_label(Widget widget, gate_string_t* label)
350 {
351 String str = NULL;
352 if (!gate_ui_motif_widget_is_valid(widget) || !label)
353 {
354 return GATE_RESULT_INVALIDARG;
355 }
356 XtVaGetValues(widget, XtNlabel, &str, NULL);
357 if (NULL == gate_string_create(label, str, gate_str_length(str)))
358 {
359 return GATE_RESULT_OUTOFMEMORY;
360 }
361 return GATE_RESULT_OK;
362 }
363
364 XmString gate_ui_motif_create_string(gate_string_t const* text)
365 {
366 XmString ret = NULL;
367 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
368 char* ptr_buffer = &buffer[0];
369 gate_size_t bufferlen = sizeof(buffer) / sizeof(buffer[0]);
370 gate_size_t textlen = gate_string_length(text);
371
372 do
373 {
374 if (textlen >= bufferlen)
375 {
376 bufferlen = textlen + 4;
377 ptr_buffer = (char*)gate_mem_alloc(bufferlen);
378 if (NULL == ptr_buffer)
379 {
380 break;
381 }
382 }
383
384 gate_string_to_buffer(text, ptr_buffer, bufferlen);
385 ret = XmStringCreateLocalized(ptr_buffer);
386 } while (0);
387
388 if (ptr_buffer && ptr_buffer != &buffer[0])
389 {
390 gate_mem_dealloc(ptr_buffer);
391 }
392
393 return ret;
394 }
395
396 XmString gate_ui_motif_create_chr_string(char const* text)
397 {
398 gate_string_t str;
399 gate_string_create_static(&str, text);
400 return gate_ui_motif_create_string(&str);
401 }
402
403 gate_result_t gate_ui_motif_convert_string(XmString from, gate_string_t* to)
404 {
405 gate_result_t ret = GATE_RESULT_OK;
406 char* text = (char*)XmStringUnparse(from, XmSTRING_DEFAULT_CHARSET, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
407 if (text)
408 {
409 if (NULL == gate_string_create(to, text, gate_str_length(text)))
410 {
411 ret = GATE_RESULT_OUTOFMEMORY;
412 }
413 XtFree(text);
414 }
415 else
416 {
417 gate_string_create_empty(to);
418 }
419 return ret;
420 }
421
422 gate_bool_t gate_ui_motif_widget_is_valid(Widget widget)
423 {
424 return (widget != NULL) && (widget != (Widget)(gate_intptr_t)-1);
425 }
426
427
428 gate_result_t gate_ui_motif_widget_set_label(Widget widget, gate_string_t const* text)
429 {
430 gate_result_t ret;
431 XmString xmstr = NULL;
432
433 do
434 {
435 if (!gate_ui_motif_widget_is_valid(widget))
436 {
437 ret = GATE_RESULT_INVALIDARG;
438 break;
439 }
440
441 xmstr = gate_ui_motif_create_string(text);
442 if (NULL == xmstr)
443 {
444 ret = GATE_RESULT_OUTOFMEMORY;
445 break;
446 }
447
448 XtVaSetValues(widget, XmNlabelString, xmstr, NULL, NULL);
449 ret = GATE_RESULT_OK;
450
451 } while (0);
452
453 if (xmstr)
454 {
455 XmStringFree(xmstr);
456 }
457
458 return ret;
459 }
460
461 void gate_ui_motif_widget_get_children(Widget widget, Widget** ptr_children, gate_size_t* ptr_count)
462 {
463 WidgetList children = NULL;
464 Cardinal num_children = 0;
465
466 GATE_DEBUG_ASSERT(widget != NULL);
467 XtVaGetValues(widget, XmNchildren, &children, XmNnumChildren, &num_children, NULL, NULL);
468 if (ptr_children)
469 {
470 *ptr_children = children;
471 }
472 if (ptr_count)
473 {
474 *ptr_count = num_children;
475 }
476 }
477
478
479 void gate_ui_motif_widget_destroy_children(Widget parent_widget, gate_bool_t destroy_parent)
480 {
481 WidgetList children = NULL;
482 Widget child_widget;
483 Cardinal num_children = 0;
484
485 GATE_DEBUG_ASSERT(parent_widget != NULL);
486 XtVaGetValues(parent_widget, XmNchildren, &children, XmNnumChildren, &num_children, NULL, NULL);
487 while (num_children-- > 0)
488 {
489 child_widget = children[num_children];
490 if (child_widget)
491 {
492 gate_ui_motif_widget_destroy_children(child_widget, true);
493 }
494 }
495 if (destroy_parent)
496 {
497 XtUnmanageChild(parent_widget);
498 XtDestroyWidget(parent_widget);
499 }
500 }
501
502 gate_result_t gate_ui_motif_widget_get_position(Widget widget, gate_ui_point_t* pos, gate_ui_size_t* sz)
503 {
504 gate_result_t ret = GATE_RESULT_FAILED;
505 Dimension x, y, width, height;
506
507 do
508 {
509 if (!gate_ui_motif_widget_is_valid(widget))
510 {
511 ret = GATE_RESULT_INVALIDARG;
512 break;
513 }
514
515 XtVaGetValues(widget, XtNx, &x, XtNy, &y, XtNwidth, &width, XtNheight, &height, NULL, NULL);
516 if (pos)
517 {
518 pos->x = x;
519 pos->y = y;
520 }
521 if (sz)
522 {
523 sz->width = width;
524 sz->height = height;
525 }
526 ret = GATE_RESULT_OK;
527 } while (0);
528 return ret;
529 }
530
531
532
533 gate_result_t gate_ui_motif_widget_set_position(Widget widget, gate_ui_point_t const* pos, gate_ui_size_t const* sz)
534 {
535 gate_result_t ret = GATE_RESULT_FAILED;
536 Dimension a, b;
537 XtWidgetGeometry geo;
538
539 do
540 {
541 if (!gate_ui_motif_widget_is_valid(widget))
542 {
543 ret = GATE_RESULT_INVALIDARG;
544 break;
545 }
546
547 if (pos)
548 {
549 a = pos->x;
550 b = pos->y;
551 XtVaSetValues(widget, XtNx, a, XtNy, b, NULL, NULL);
552 XtMoveWidget(widget, a, b);
553 }
554 if (sz)
555 {
556 a = sz->width;
557 b = sz->height;
558 XtVaSetValues(widget, XtNwidth, a, XtNheight, b, NULL, NULL);
559 XtResizeWidget(widget, a, b, 0);
560 }
561
562 XtResizeWindow(widget);
563 ret = GATE_RESULT_OK;
564 } while (0);
565 return ret;
566 }
567
568 gate_result_t gate_ui_motif_host_dispatch_events(gate_ui_host_t* host)
569 {
570 gate_result_t ret = GATE_RESULT_OK;
571 XtAppContext ctx = (XtAppContext)GATE_UI_MOTIF_GET_HOST_APPHANDLE(host);
572 XEvent xevt = GATE_INIT_EMPTY;
573
574 while (!XtAppGetExitFlag(ctx))
575 {
576 XtAppNextEvent(ctx, &xevt);
577 XtDispatchEvent(&xevt);
578 }
579 while (XtPending())
580 {
581 XtAppNextEvent(ctx, &xevt);
582 XtDispatchEvent(&xevt);
583 }
584 return ret;
585 }
586
587 gate_result_t gate_ui_motif_host_dispatch_pending_events(gate_ui_host_t* host, gate_bool_t ignore_exit_flag)
588 {
589 gate_result_t ret = GATE_RESULT_OK;
590 XtAppContext ctx = (XtAppContext)GATE_UI_MOTIF_GET_HOST_APPHANDLE(host);
591 XEvent xevt = GATE_INIT_EMPTY;
592
593 while (XtAppPending(ctx))
594 {
595 if (!ignore_exit_flag)
596 {
597 if (XtAppGetExitFlag(ctx))
598 {
599 break;
600 }
601 }
602 XtAppNextEvent(ctx, &xevt);
603 XtDispatchEvent(&xevt);
604 }
605 return ret;
606 }
607
608 gate_result_t gate_ui_motif_ctrl_get_children(gate_ui_ctrl_t* ctrl, void** ptr_to_widgetlist, gate_size_t* ptr_to_children_count)
609 {
610 WidgetList children = NULL;
611 Cardinal num_children = 0;
612 Widget w = NULL;
613 gate_ui_motif_dispatcher_t* dispatcher = NULL;
614
615 GATE_DEBUG_ASSERT(ctrl != NULL);
616
617 dispatcher = GATE_UI_MOTIF_GET_CTRL_DISP(ctrl);
618
619 if (dispatcher && dispatcher->get_children)
620 {
621 return dispatcher->get_children(ctrl, ptr_to_widgetlist, ptr_to_children_count);
622 }
623
624 w = GATE_UI_MOTIF_GET_CTRL_CONTAINER(ctrl);
625
626 if (!gate_ui_motif_widget_is_valid(w))
627 {
628 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
629 if (!gate_ui_motif_widget_is_valid(w))
630 {
631 return GATE_RESULT_INVALIDARG;
632 }
633 }
634 XtVaGetValues(w, XmNchildren, &children, XmNnumChildren, &num_children, NULL, NULL);
635 if (ptr_to_widgetlist)
636 {
637 *ptr_to_widgetlist = children;
638 }
639 if (ptr_to_children_count)
640 {
641 *ptr_to_children_count = (gate_size_t)num_children;
642 }
643 return GATE_RESULT_OK;
644 }
645
646 gate_result_t gate_ui_motif_ctrl_refresh(gate_ui_ctrl_t* ctrl)
647 {
648 Widget w = GATE_UI_MOTIF_GET_CTRL_CONTAINER(ctrl);
649 if (!gate_ui_motif_widget_is_valid(w))
650 {
651 w = GATE_UI_MOTIF_GET_CTRL_WIDGET(ctrl);
652 if (!gate_ui_motif_widget_is_valid(w))
653 {
654 return GATE_RESULT_INVALIDARG;
655 }
656 }
657 XmUpdateDisplay(w);
658 return GATE_RESULT_OK;
659 }
660
661 gate_result_t gate_ui_motif_host_add_native_workproc(gate_ui_host_t* host, Boolean(*worker)(XtPointer ptr), XtPointer param)
662 {
663 XtAppContext appctx;
664
665 GATE_DEBUG_ASSERT(host != NULL);
666 appctx = (XtAppContext)GATE_UI_MOTIF_GET_HOST_APPHANDLE(host);
667 if (!appctx)
668 {
669 return GATE_RESULT_INVALIDSTATE;
670 }
671 if (worker)
672 {
673 XtAppAddWorkProc(appctx, worker, param);
674 }
675 return GATE_RESULT_OK;
676 }
677
678 static Boolean host_execute_workproc(XtPointer closure)
679 {
680 gate_runnable_t* code = (gate_runnable_t*)closure;
681 if (code)
682 {
683 gate_runnable_run(code);
684 gate_object_release(code);
685 }
686 return FALSE; /* workproc completed, do not call it again */
687 }
688
689 gate_result_t gate_ui_motif_host_add_workproc(gate_ui_host_t* host, gate_runnable_t* code)
690 {
691 XtAppContext appctx;
692
693 GATE_DEBUG_ASSERT(host != NULL);
694 appctx = (XtAppContext)GATE_UI_MOTIF_GET_HOST_APPHANDLE(host);
695 if (!appctx)
696 {
697 return GATE_RESULT_INVALIDSTATE;
698 }
699 if (code)
700 {
701 gate_object_retain(code);
702 XtAppAddWorkProc(appctx, &host_execute_workproc, (XtPointer)code);
703 }
704 return GATE_RESULT_OK;
705 }
706
707
708 unsigned long gate_ui_motif_rgba2pixel(gate_ui_host_t* host, gate_color_t const* rgba)
709 {
710 Display* disp = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
711 int screen = XDefaultScreen(disp);
712 Colormap colmap = XDefaultColormap(disp, screen);
713 XColor col;
714
715 gate_mem_clear(&col, sizeof(col));
716
717 col.red = ((gate_uint16_t)rgba->r << 8);
718 col.green = ((gate_uint16_t)rgba->g << 8);
719 col.blue = ((gate_uint16_t)rgba->b << 8);
720 col.flags = DoRed | DoGreen | DoBlue;
721 XAllocColor(disp, colmap, &col);
722 return col.pixel;
723 }
724
725 gate_color_t gate_ui_motif_pixel2rgba(gate_ui_host_t* host, unsigned long pixel)
726 {
727 Display* disp = GATE_UI_MOTIF_GET_HOST_DISPLAY(host);
728 int screen = XDefaultScreen(disp);
729 Colormap colmap = XDefaultColormap(disp, screen);
730 XColor col;
731 gate_color_t ret;
732
733 col.pixel = pixel;
734 col.flags = DoRed | DoGreen | DoBlue;
735
736 XQueryColor(disp, colmap, &col);
737 ret.r = (gate_uint8_t)(col.red >> 8);
738 ret.g = (gate_uint8_t)(col.green >> 8);
739 ret.b = (gate_uint8_t)(col.blue >> 8);
740 ret.a = 255;
741 return ret;
742 }
743
744 #endif /* GATE_UI_MOTIF */
745