GCC Code Coverage Report


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