GCC Code Coverage Report


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