GCC Code Coverage Report


Directory: src/gate/
File: src/gate/ui/timers.c
Date: 2026-09-21 06:26:40
Exec Total Coverage
Lines: 52 60 86.7%
Functions: 5 5 100.0%
Branches: 10 16 62.5%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, 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/timers.h"
30 #include "gate/results.h"
31
32 #if defined(GATE_UI_WINAPI)
33
34 #include "gate/platforms.h"
35 #include "gate/ui/gateui_winapi.h"
36
37
38 static gate_bool_t WINAPI gate_ui_timer_events(ui_hwnd_t hwnd, gate_ui_ctrl_t* ctrl, gate_uint32_t msg, gate_uintptr_t wParam, gate_intptr_t lParam, gate_intptr_t* lresult)
39 {
40 if (ctrl != NULL)
41 {
42 HWND const hwndCtrl = (HWND)GATE_UI_WINAPI_GET_HWND(ctrl);
43 if ((HWND)hwnd == hwndCtrl)
44 {
45 gate_ui_timer_t* const timer = (gate_ui_timer_t*)ctrl;
46 gate_ui_host_t* const host = GATE_UI_WINAPI_GET_HOST(ctrl);
47 switch (msg)
48 {
49 case WM_TIMER:
50 {
51 if (timer->on_interval != NULL)
52 {
53 timer->on_interval(ctrl);
54 }
55 *lresult = 0;
56 return true;
57 }
58 case WM_DESTROY:
59 {
60 gate_ui_winapi_unregister_window(host, hwnd);
61 break;
62 }
63 }
64 }
65 }
66 return false;
67 }
68
69
70 gate_result_t gate_ui_timer_create(gate_ui_timer_t* timer, gate_ui_host_t* host, void* userparam)
71 {
72 gate_result_t ret = GATE_RESULT_OK;
73 gate_uint32_t styles, exstyles;
74 gate_ui_position_t position;
75
76 position.pos.x = 0;
77 position.pos.y = 0;
78 position.size.width = 100;
79 position.size.height = 100;
80
81 gate_mem_clear(timer, sizeof(gate_ui_timer_t));
82
83 exstyles = 0;
84 styles = WS_DISABLED;
85 ret = gate_ui_winapi_create(&timer->ctrl, host, UI_HWND_NULL, NULL,
86 &position, styles, exstyles, NULL, userparam, false);
87 if (GATE_SUCCEEDED(ret))
88 {
89 const ui_hwnd_t hwnd = GATE_UI_WINAPI_GET_HWND(&timer->ctrl);
90 gate_ui_winapi_register_event(host, hwnd, WM_TIMER, &gate_ui_timer_events, &timer->ctrl);
91 gate_ui_winapi_register_event(host, hwnd, WM_DESTROY, &gate_ui_timer_events, &timer->ctrl);
92 }
93 return ret;
94 }
95
96 #ifndef USER_TIMER_MINIMUM
97 #define USER_TIMER_MINIMUM 0x0a
98 #endif
99 #ifndef USER_TIMER_MAXIMUM
100 #define USER_TIMER_MAXIMUM 0x7FFFFFFF
101 #endif
102
103 gate_result_t gate_ui_timer_start(gate_ui_timer_t* timer, gate_uint32_t interval)
104 {
105 const HWND hwnd = (HWND)GATE_UI_WINAPI_GET_HWND(&timer->ctrl);
106 if (interval < USER_TIMER_MINIMUM) interval = USER_TIMER_MINIMUM;
107 if (interval > USER_TIMER_MAXIMUM) interval = USER_TIMER_MAXIMUM;
108 EnableWindow(hwnd, TRUE);
109 if (0 != SetTimer(hwnd, 1, interval, NULL))
110 {
111 return GATE_RESULT_OK;
112 }
113 else
114 {
115 EnableWindow(hwnd, FALSE);
116 return GATE_RESULT_FAILED;
117 }
118 }
119
120 gate_bool_t gate_ui_timer_is_started(gate_ui_timer_t* timer)
121 {
122 const HWND hwnd = (HWND)GATE_UI_WINAPI_GET_HWND(&timer->ctrl);
123 return IsWindowEnabled(hwnd) == FALSE ? false : true;
124 }
125
126
127 gate_result_t gate_ui_timer_stop(gate_ui_timer_t* timer)
128 {
129 const HWND hwnd = (HWND)GATE_UI_WINAPI_GET_HWND(&timer->ctrl);
130 if (KillTimer(hwnd, 1))
131 {
132 EnableWindow(hwnd, FALSE);
133 return GATE_RESULT_OK;
134 }
135 else
136 {
137 return GATE_RESULT_FAILED;
138 }
139 }
140
141 #endif /* GATE_UI_WINAPI */
142
143
144
145 #if defined(GATE_UI_GTK)
146
147 #include "gate/ui/gateui_gtk.h"
148
149 typedef struct gate_ui_gtk_timer_param
150 {
151 gate_ui_timer_t* timer;
152 gate_bool_t started;
153 } gate_ui_gtk_timer_param_t;
154
155 static gboolean gate_ui_gtk_timer_callback(gpointer user_data)
156 {
157 gate_ui_gtk_timer_param_t* param = (gate_ui_gtk_timer_param_t*)user_data;
158 if (!param)
159 {
160 return FALSE;
161 }
162 if (param->started)
163 {
164 if (NULL != param->timer)
165 {
166 if (NULL != param->timer->on_interval)
167 {
168 param->timer->on_interval(&param->timer->ctrl);
169 }
170 }
171 }
172
173 if (!param->started)
174 {
175 return FALSE;
176 }
177 else
178 {
179 return TRUE;
180 }
181 }
182
183 static gate_uint32_t gate_ui_gtk_timer_get_text_length(gate_ui_ctrl_t* ctrl)
184 {
185 return GATE_RESULT_NOTIMPLEMENTED;
186 }
187 static gate_result_t gate_ui_gtk_timer_get_text(gate_ui_ctrl_t* ctrl, gate_string_t* text)
188 {
189 return GATE_RESULT_NOTIMPLEMENTED;
190 }
191 static gate_result_t gate_ui_gtk_timer_set_text(gate_ui_ctrl_t* ctrl, gate_string_t const* text)
192 {
193 return GATE_RESULT_NOTIMPLEMENTED;
194 }
195 static gate_result_t gate_ui_gtk_timer_get_state(gate_ui_ctrl_t* ctrl, gate_int32_t* value)
196 {
197 gate_result_t ret = GATE_RESULT_FAILED;
198 gate_ui_gtk_timer_param_t* param = (gate_ui_gtk_timer_param_t*)GATE_UI_GTK_GET_CTRL_PRIVATE_ARG(ctrl);
199 if (param == NULL)
200 {
201 ret = GATE_RESULT_INVALIDSTATE;
202 }
203 else
204 {
205 if (value)
206 {
207 *value = param->started ? 1 : 0;
208 }
209 ret = GATE_RESULT_OK;
210 }
211 return ret;
212 }
213 static gate_result_t gate_ui_gtk_timer_set_state(gate_ui_ctrl_t* ctrl, gate_int32_t value)
214 {
215 return GATE_RESULT_NOTIMPLEMENTED;
216 }
217 static gate_result_t gate_ui_gtk_timer_refresh(gate_ui_ctrl_t* ctrl)
218 {
219 return GATE_RESULT_OK;
220 }
221 static gate_result_t gate_ui_gtk_timer_destroy(gate_ui_ctrl_t* ctrl)
222 {
223 gate_ui_gtk_timer_param_t* param = (gate_ui_gtk_timer_param_t*)GATE_UI_GTK_GET_CTRL_PRIVATE_ARG(ctrl);
224 if (param)
225 {
226 gate_mem_dealloc(param);
227 GATE_UI_GTK_SET_CTRL_PRIVATE_ARG(ctrl, NULL);
228 }
229 return GATE_RESULT_OK;
230 }
231
232 static gate_ui_gtk_dispatcher_t gate_ui_gtk_timer_dispatcher =
233 {
234 &gate_ui_gtk_timer_get_text_length,
235 &gate_ui_gtk_timer_get_text,
236 &gate_ui_gtk_timer_set_text,
237 &gate_ui_gtk_timer_get_state,
238 &gate_ui_gtk_timer_set_state,
239 &gate_ui_gtk_timer_refresh,
240 &gate_ui_gtk_timer_destroy
241 };
242
243
244 gate_result_t gate_ui_timer_create(
245 gate_ui_timer_t* timer, gate_ui_host_t* host,
246 void* userparam
247 )
248 {
249 gate_result_t ret = GATE_RESULT_FAILED;
250 do
251 {
252 gate_ui_gtk_timer_param_t* param = (gate_ui_gtk_timer_param_t*)gate_mem_alloc(sizeof(gate_ui_gtk_timer_param_t));
253 if (param == NULL)
254 {
255 ret = GATE_RESULT_OUTOFMEMORY;
256 break;
257 }
258 param->timer = timer;
259 param->started = false;
260
261 gate_mem_clear(&timer->ctrl, sizeof(gate_ui_ctrl_t));
262
263 GATE_UI_GTK_SET_CTRL_WIDGET_DIRECT(&timer->ctrl, GATE_UI_GTK_NO_WIDGET);
264 GATE_UI_GTK_SET_CTRL_HOST(&timer->ctrl, host);
265 GATE_UI_GTK_SET_CTRL_DISP(&timer->ctrl, &gate_ui_gtk_timer_dispatcher);
266 GATE_UI_GTK_SET_CTRL_USER_PARAM(&timer->ctrl, userparam);
267 GATE_UI_GTK_SET_CTRL_CONTAINER(&timer->ctrl, NULL);
268 GATE_UI_GTK_SET_CTRL_PARENT(&timer->ctrl, NULL);
269 GATE_UI_GTK_SET_CTRL_PRIVATE_ARG(&timer->ctrl, param);
270 ret = GATE_RESULT_OK;
271
272 } while (0);
273
274 return ret;
275 }
276
277 gate_result_t gate_ui_timer_start(gate_ui_timer_t* timer, gate_uint32_t interval)
278 {
279 gate_result_t ret;
280 gate_ui_gtk_timer_param_t* param = (gate_ui_gtk_timer_param_t*)GATE_UI_GTK_GET_CTRL_PRIVATE_ARG(&timer->ctrl);
281 if (param == NULL)
282 {
283 ret = GATE_RESULT_INVALIDSTATE;
284 }
285 else
286 {
287 param->started = true;
288 g_timeout_add(interval, &gate_ui_gtk_timer_callback, param);
289 ret = GATE_RESULT_OK;
290 }
291 return ret;
292 }
293
294 gate_result_t gate_ui_timer_stop(gate_ui_timer_t* timer)
295 {
296 gate_result_t ret;
297 gate_ui_gtk_timer_param_t* param = (gate_ui_gtk_timer_param_t*)GATE_UI_GTK_GET_CTRL_PRIVATE_ARG(&timer->ctrl);
298 if (param == NULL)
299 {
300 ret = GATE_RESULT_INVALIDSTATE;
301 }
302 else
303 {
304 param->started = false;
305 GATE_UI_GTK_SET_CTRL_PRIVATE_ARG(&timer->ctrl, NULL);
306 ret = GATE_RESULT_OK;
307 }
308 return ret;
309 }
310
311 gate_bool_t gate_ui_timer_is_started(gate_ui_timer_t* timer)
312 {
313 gate_ui_gtk_timer_param_t* param = (gate_ui_gtk_timer_param_t*)GATE_UI_GTK_GET_CTRL_PRIVATE_ARG(&timer->ctrl);
314 if (param == NULL)
315 {
316 return false;
317 }
318 else
319 {
320 return param->started;
321 }
322 }
323
324 #endif /* GATE_UI_GTK */
325
326
327
328 #if defined(GATE_UI_MOTIF)
329
330 #include "gate/ui/gateui_motif.h"
331
332 1 gate_result_t gate_ui_timer_create(gate_ui_timer_t* timer, gate_ui_host_t* host, void* userparam)
333 {
334 1 Widget w = (Widget)(gate_intptr_t)-1;
335 1 GATE_UI_MOTIF_SET_CTRL_HOST(&timer->ctrl, host);
336 1 GATE_UI_MOTIF_SET_CTRL_WIDGET(&timer->ctrl, w);
337 1 GATE_UI_MOTIF_SET_CTRL_CONTAINER(&timer->ctrl, NULL);
338 1 GATE_UI_MOTIF_SET_CTRL_USER_PARAM(&timer->ctrl, userparam);
339 1 GATE_UI_MOTIF_SET_CTRL_PARENT(&timer->ctrl, NULL);
340 1 GATE_UI_MOTIF_SET_CTRL_DISP(&timer->ctrl, NULL);
341 1 GATE_UI_MOTIF_SET_CTRL_PRIVATE_ARG(&timer->ctrl, NULL);
342 1 return GATE_RESULT_OK;
343 }
344
345 typedef struct gate_ui_motif_timer_info_class
346 {
347 gate_ui_timer_t* ctrl;
348 XtIntervalId id;
349 gate_uint32_t interval;
350 } gate_ui_motif_timer_info_t;
351
352 5 static void gate_ui_timer_callback(XtPointer client_arg, XtIntervalId* id)
353 {
354 5 gate_ui_motif_timer_info_t* ptr_timerinfo = (gate_ui_motif_timer_info_t*)client_arg;
355 5 gate_ui_timer_t* ptr_timer = NULL;
356 5 unsigned long next_interval = 0;
357 XtIntervalId next_id;
358 gate_ui_host_t* ptr_host;
359 XtAppContext app_context;
360
361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!ptr_timerinfo)
362 {
363 return;
364 }
365
366 5 ptr_timer = ptr_timerinfo->ctrl;
367 5 next_interval = (unsigned long)ptr_timerinfo->interval;
368
369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!ptr_timer)
370 {
371 gate_mem_dealloc(ptr_timerinfo);
372 return;
373 }
374
375 5 ptr_host = GATE_UI_MOTIF_GET_CTRL_HOST(&ptr_timer->ctrl);
376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!ptr_host)
377 {
378 gate_mem_dealloc(ptr_timerinfo);
379 return;
380 }
381 5 app_context = (XtAppContext)GATE_UI_MOTIF_GET_HOST_APPHANDLE(ptr_host);
382 5 ptr_timer->on_interval(&ptr_timer->ctrl);
383
384
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
5 if(gate_ui_timer_is_started(ptr_timer))
385 {
386 /* only enqueue another time, if it was not stopped in callback */
387 4 next_id = XtAppAddTimeOut(app_context, next_interval, &gate_ui_timer_callback, (XtPointer)ptr_timerinfo);
388 4 ptr_timerinfo->id = next_id;
389 }
390 }
391
392 1 gate_result_t gate_ui_timer_start(gate_ui_timer_t* timer, gate_uint32_t interval)
393 {
394 1 gate_result_t ret = GATE_RESULT_FAILED;
395
396 do
397 {
398 1 gate_ui_host_t* ptr_host = GATE_UI_MOTIF_GET_CTRL_HOST(&timer->ctrl);
399 1 XtAppContext app_context = (XtAppContext)GATE_UI_MOTIF_GET_HOST_APPHANDLE(ptr_host);
400 XtIntervalId id;
401 1 gate_ui_motif_timer_info_t* ptr_timerinfo = gate_mem_alloc(sizeof(gate_ui_motif_timer_info_t));
402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL == ptr_timerinfo)
403 {
404 ret = GATE_RESULT_OUTOFMEMORY;
405 break;
406 }
407 1 ptr_timerinfo->ctrl = timer;
408 1 ptr_timerinfo->interval = interval;
409 1 id = XtAppAddTimeOut(app_context, interval, &gate_ui_timer_callback, (XtPointer)ptr_timerinfo);
410 1 ptr_timerinfo->id = id;
411 1 GATE_UI_MOTIF_SET_CTRL_PRIVATE_ARG(&timer->ctrl, ptr_timerinfo);
412 1 ret = GATE_RESULT_OK;
413 } while (0);
414
415 1 return ret;
416 }
417
418 1 gate_result_t gate_ui_timer_stop(gate_ui_timer_t* timer)
419 {
420 1 gate_ui_motif_timer_info_t* ptr_timerinfo = (gate_ui_motif_timer_info_t*)GATE_UI_MOTIF_GET_CTRL_PRIVATE_ARG(&timer->ctrl);
421
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_timerinfo)
422 {
423 1 XtIntervalId id = (XtIntervalId)(void*)GATE_UI_MOTIF_GET_CTRL_WIDGET(&timer->ctrl);
424 1 GATE_UI_MOTIF_SET_CTRL_PRIVATE_ARG(&timer->ctrl, NULL);
425
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_timerinfo->id != 0)
426 {
427 1 XtRemoveTimeOut(ptr_timerinfo->id);
428 }
429 1 gate_mem_dealloc(ptr_timerinfo);
430 1 return GATE_RESULT_OK;
431 }
432 return GATE_RESULT_INVALIDSTATE;
433 }
434
435 6 gate_bool_t gate_ui_timer_is_started(gate_ui_timer_t* timer)
436 {
437 6 gate_ui_motif_timer_info_t* const ptr_timerinfo = (gate_ui_motif_timer_info_t*)GATE_UI_MOTIF_GET_CTRL_PRIVATE_ARG(&timer->ctrl);
438
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 if (ptr_timerinfo)
439 {
440 5 return true;
441 }
442 1 return false;
443 }
444
445 #endif /* GATE_UI_MOTIF */
446