source: mainline/uspace/app/taskbar/clock.c@ 9f945464

Last change on this file since 9f945464 was f6b29929, checked in by Wayne Thornton <wmthornton-dev@…>, 5 months ago

Updated clock to open 'date_cfg' app when clicked

  • Property mode set to 100644
File size: 8.8 KB
Line 
1/*
2 * Copyright (c) 2022 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - 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 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup taskbar
30 * @{
31 */
32/** @file Taskbar clock.
33 *
34 * Displays the current time in an inset frame.
35 */
36
37#include <errno.h>
38#include <gfx/render.h>
39#include <gfx/text.h>
40#include <stdlib.h>
41#include <stdio.h>
42#include <task.h>
43#include <ui/control.h>
44#include <ui/paint.h>
45#include <ui/resource.h>
46#include <ui/ui.h>
47#include "clock.h"
48
49static void taskbar_clock_ctl_destroy(void *);
50static errno_t taskbar_clock_ctl_paint(void *);
51static ui_evclaim_t taskbar_clock_ctl_kbd_event(void *, kbd_event_t *);
52static ui_evclaim_t taskbar_clock_ctl_pos_event(void *, pos_event_t *);
53static void taskbar_clock_timer(void *);
54
55/** Taskbar clock control ops */
56static ui_control_ops_t taskbar_clock_ctl_ops = {
57 .destroy = taskbar_clock_ctl_destroy,
58 .paint = taskbar_clock_ctl_paint,
59 .kbd_event = taskbar_clock_ctl_kbd_event,
60 .pos_event = taskbar_clock_ctl_pos_event
61};
62
63/** Create taskbar clock.
64 *
65 * @param window Containing window
66 * @param rclock Place to store pointer to new clock
67 * @return EOK on success or an error code
68 */
69errno_t taskbar_clock_create(ui_window_t *window, taskbar_clock_t **rclock)
70{
71 taskbar_clock_t *clock;
72 errno_t rc;
73
74 clock = calloc(1, sizeof(taskbar_clock_t));
75 if (clock == NULL)
76 return ENOMEM;
77
78 rc = ui_control_new(&taskbar_clock_ctl_ops, (void *)clock,
79 &clock->control);
80 if (rc != EOK) {
81 free(clock);
82 return rc;
83 }
84
85 clock->timer = fibril_timer_create(NULL);
86 if (clock->timer == NULL) {
87 rc = ENOMEM;
88 goto error;
89 }
90
91 fibril_mutex_initialize(&clock->lock);
92 fibril_condvar_initialize(&clock->timer_done_cv);
93 fibril_timer_set(clock->timer, 1000000, taskbar_clock_timer, clock);
94
95 clock->window = window;
96 *rclock = clock;
97 return EOK;
98error:
99 ui_control_delete(clock->control);
100 free(clock);
101 return rc;
102}
103
104/** Destroy taskbar clock.
105 *
106 * @param clock Taskbar clock
107 */
108void taskbar_clock_destroy(taskbar_clock_t *clock)
109{
110 /*
111 * Signal to the timer that we are cleaning up. If the timer handler
112 * misses it and sets the timer again, we will clear that active
113 * timer and be done (and if we were even slower and the timer
114 * fired again, it's the same situation as before.
115 */
116 fibril_mutex_lock(&clock->lock);
117 clock->timer_cleanup = true;
118 fibril_mutex_unlock(&clock->lock);
119
120 /* If we catch the timer while it's active, there's nothing to do. */
121 if (fibril_timer_clear(clock->timer) != fts_active) {
122 /* Need to wait for timer handler to finish */
123 fibril_mutex_lock(&clock->lock);
124 while (clock->timer_done == false)
125 fibril_condvar_wait(&clock->timer_done_cv, &clock->lock);
126 fibril_mutex_unlock(&clock->lock);
127 }
128
129 fibril_timer_destroy(clock->timer);
130 ui_control_delete(clock->control);
131 free(clock);
132}
133
134static errno_t taskbar_clock_get_text(taskbar_clock_t *clock, char *buf,
135 size_t bsize)
136{
137 struct timespec ts;
138 struct tm tm;
139 errno_t rc;
140
141 getrealtime(&ts);
142 rc = time_utc2tm(ts.tv_sec, &tm);
143 if (rc != EOK)
144 return rc;
145
146 snprintf(buf, bsize, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min,
147 tm.tm_sec);
148 return EOK;
149}
150
151/** Paint taskbar clock.
152 *
153 * @param clock Taskbar clock
154 */
155errno_t taskbar_clock_paint(taskbar_clock_t *clock)
156{
157 gfx_context_t *gc = ui_window_get_gc(clock->window);
158 ui_resource_t *res = ui_window_get_res(clock->window);
159 ui_t *ui = ui_window_get_ui(clock->window);
160 char buf[10];
161 gfx_text_fmt_t fmt;
162 gfx_coord2_t pos;
163 gfx_rect_t irect;
164 errno_t rc;
165
166 if (!ui_is_textmode(ui)) {
167 /* Paint frame */
168 rc = ui_paint_inset_frame(res, &clock->rect, &irect);
169 if (rc != EOK)
170 goto error;
171 } else {
172 irect = clock->rect;
173 }
174
175 rc = gfx_set_color(gc, ui_resource_get_wnd_face_color(res));
176 if (rc != EOK)
177 goto error;
178
179 /* Fill background */
180 rc = gfx_fill_rect(gc, &irect);
181 if (rc != EOK)
182 goto error;
183
184 pos.x = (irect.p0.x + irect.p1.x) / 2;
185 pos.y = (irect.p0.y + irect.p1.y) / 2;
186
187 gfx_text_fmt_init(&fmt);
188 fmt.font = ui_resource_get_font(res);
189 fmt.color = ui_resource_get_wnd_text_color(res);
190 fmt.halign = gfx_halign_center;
191 fmt.valign = gfx_valign_center;
192
193 rc = taskbar_clock_get_text(clock, buf, sizeof(buf));
194 if (rc != EOK)
195 goto error;
196
197 rc = gfx_puttext(&pos, &fmt, buf);
198 if (rc != EOK)
199 goto error;
200
201 rc = gfx_update(gc);
202 if (rc != EOK)
203 goto error;
204
205 return EOK;
206error:
207 return rc;
208}
209
210/** Handle taskbar clock keyboard event.
211 *
212 * @param clock Taskbar clock
213 * @param event Keyboard event
214 * @return ui_claimed iff event was claimed
215 */
216ui_evclaim_t taskbar_clock_kbd_event(taskbar_clock_t *clock, kbd_event_t *event)
217{
218 return ui_unclaimed;
219}
220
221/** Launch date configuration application */
222static errno_t taskbar_clock_launch_date_cfg(void)
223{
224 task_id_t id;
225 const char *args[] = { "/app/date_cfg", NULL };
226 return task_spawnv(&id, NULL, args[0], args);
227}
228
229/** Handle taskbar clock position event.
230 *
231 * @param clock Taskbar clock
232 * @param event Position event
233 * @return ui_claimed iff event was claimed
234 */
235ui_evclaim_t taskbar_clock_pos_event(taskbar_clock_t *clock, pos_event_t *event)
236{
237 gfx_coord2_t pos;
238
239 pos.x = event->hpos;
240 pos.y = event->vpos;
241 if (!gfx_pix_inside_rect(&pos, &clock->rect))
242 return ui_unclaimed;
243
244 if (event->type == POS_PRESS) {
245 taskbar_clock_launch_date_cfg();
246 }
247
248 return ui_claimed;
249}
250
251/** Get base control for taskbar clock.
252 *
253 * @param clock Taskbar clock
254 * @return Base UI control
255 */
256ui_control_t *taskbar_clock_ctl(taskbar_clock_t *clock)
257{
258 return clock->control;
259}
260
261/** Set taskbar clock rectangle.
262 *
263 * @param clock Taskbar clock
264 * @param rect Rectangle
265 */
266void taskbar_clock_set_rect(taskbar_clock_t *clock, gfx_rect_t *rect)
267{
268 gfx_rect_t irect;
269
270 clock->rect = *rect;
271
272 irect.p0.x = clock->rect.p0.x + 1;
273 irect.p0.y = clock->rect.p0.y + 1;
274 irect.p1.x = clock->rect.p1.x;
275 irect.p1.y = clock->rect.p1.y - 1;
276
277 (void)irect;
278}
279
280/** Destroy clock control.
281 *
282 * @param arg Argument (taskbar_clock_t *)
283 */
284void taskbar_clock_ctl_destroy(void *arg)
285{
286 taskbar_clock_t *clock = (taskbar_clock_t *) arg;
287
288 taskbar_clock_destroy(clock);
289}
290
291/** Paint taskbar clock control.
292 *
293 * @param arg Argument (taskbar_clock_t *)
294 * @return EOK on success or an error code
295 */
296errno_t taskbar_clock_ctl_paint(void *arg)
297{
298 taskbar_clock_t *clock = (taskbar_clock_t *) arg;
299
300 return taskbar_clock_paint(clock);
301}
302
303/** Handle taskbar clock control keyboard event.
304 *
305 * @param arg Argument (taskbar_clock_t *)
306 * @param kbd_event Keyboard event
307 * @return @c ui_claimed iff the event is claimed
308 */
309ui_evclaim_t taskbar_clock_ctl_kbd_event(void *arg, kbd_event_t *event)
310{
311 taskbar_clock_t *clock = (taskbar_clock_t *) arg;
312
313 return taskbar_clock_kbd_event(clock, event);
314}
315
316/** Handle taskbar clock control position event.
317 *
318 * @param arg Argument (taskbar_clock_t *)
319 * @param pos_event Position event
320 * @return @c ui_claimed iff the event is claimed
321 */
322ui_evclaim_t taskbar_clock_ctl_pos_event(void *arg, pos_event_t *event)
323{
324 taskbar_clock_t *clock = (taskbar_clock_t *) arg;
325
326 return taskbar_clock_pos_event(clock, event);
327}
328
329/** Taskbar clock timer handler.
330 *
331 * @param arg Argument (taskbar_clock_t *)
332 */
333static void taskbar_clock_timer(void *arg)
334{
335 taskbar_clock_t *clock = (taskbar_clock_t *) arg;
336 ui_t *ui;
337
338 ui = ui_window_get_ui(clock->window);
339 ui_lock(ui);
340
341 fibril_mutex_lock(&clock->lock);
342 if (!ui_is_suspended(ui_window_get_ui(clock->window)))
343 (void) taskbar_clock_paint(clock);
344
345 if (!clock->timer_cleanup) {
346 fibril_timer_set(clock->timer, 1000000, taskbar_clock_timer,
347 clock);
348 } else {
349 /* Acknowledge timer cleanup */
350 clock->timer_done = true;
351 fibril_condvar_signal(&clock->timer_done_cv);
352 }
353
354 fibril_mutex_unlock(&clock->lock);
355 ui_unlock(ui);
356}
357
358/** @}
359 */
Note: See TracBrowser for help on using the repository browser.