source: mainline/uspace/app/taskbar/clock.c@ 95fc538

topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 95fc538 was 95fc538, checked in by Jiri Svoboda <jiri@…>, 20 months ago

It should be Taskbar not Task Bar

  • Property mode set to 100644
File size: 8.6 KB
RevLine 
[50a16d9]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 */
[95fc538]32/** @file Taskbar clock.
[50a16d9]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>
[3fd38b2]46#include <ui/ui.h>
[50a16d9]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
[95fc538]55/** Taskbar clock control ops */
[50a16d9]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
[95fc538]63/** Create taskbar clock.
[50a16d9]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
[c77cfd8]91 fibril_mutex_initialize(&clock->lock);
92 fibril_condvar_initialize(&clock->timer_done_cv);
[50a16d9]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
[95fc538]104/** Destroy taskbar clock.
[50a16d9]105 *
[95fc538]106 * @param clock Taskbar clock
[50a16d9]107 */
108void taskbar_clock_destroy(taskbar_clock_t *clock)
109{
[c77cfd8]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
[50a16d9]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
[95fc538]151/** Paint taskbar clock.
[50a16d9]152 *
[95fc538]153 * @param clock Taskbar clock
[50a16d9]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);
[3fd38b2]159 ui_t *ui = ui_window_get_ui(clock->window);
[50a16d9]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
[3fd38b2]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 }
[50a16d9]174
175 rc = gfx_set_color(gc, ui_resource_get_wnd_face_color(res));
176 if (rc != EOK)
177 goto error;
178
[3fd38b2]179 /* Fill background */
[50a16d9]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
[95fc538]210/** Handle taskbar clock keyboard event.
[50a16d9]211 *
[95fc538]212 * @param clock Taskbar clock
[50a16d9]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
[95fc538]221/** Handle taskbar clock position event.
[50a16d9]222 *
[95fc538]223 * @param clock Taskbar clock
[50a16d9]224 * @param event Position event
225 * @return ui_claimed iff event was claimed
226 */
227ui_evclaim_t taskbar_clock_pos_event(taskbar_clock_t *clock, pos_event_t *event)
228{
229 gfx_coord2_t pos;
230
231 pos.x = event->hpos;
232 pos.y = event->vpos;
233 if (!gfx_pix_inside_rect(&pos, &clock->rect))
234 return ui_unclaimed;
235
236 return ui_claimed;
237}
238
[95fc538]239/** Get base control for taskbar clock.
[50a16d9]240 *
[95fc538]241 * @param clock Taskbar clock
[50a16d9]242 * @return Base UI control
243 */
244ui_control_t *taskbar_clock_ctl(taskbar_clock_t *clock)
245{
246 return clock->control;
247}
248
[95fc538]249/** Set taskbar clock rectangle.
[50a16d9]250 *
[95fc538]251 * @param clock Taskbar clock
[50a16d9]252 * @param rect Rectangle
253 */
254void taskbar_clock_set_rect(taskbar_clock_t *clock, gfx_rect_t *rect)
255{
256 gfx_rect_t irect;
257
258 clock->rect = *rect;
259
260 irect.p0.x = clock->rect.p0.x + 1;
261 irect.p0.y = clock->rect.p0.y + 1;
262 irect.p1.x = clock->rect.p1.x;
263 irect.p1.y = clock->rect.p1.y - 1;
264
265 (void)irect;
266}
267
268/** Destroy clock control.
269 *
270 * @param arg Argument (taskbar_clock_t *)
271 */
272void taskbar_clock_ctl_destroy(void *arg)
273{
274 taskbar_clock_t *clock = (taskbar_clock_t *) arg;
275
276 taskbar_clock_destroy(clock);
277}
278
[95fc538]279/** Paint taskbar clock control.
[50a16d9]280 *
281 * @param arg Argument (taskbar_clock_t *)
282 * @return EOK on success or an error code
283 */
284errno_t taskbar_clock_ctl_paint(void *arg)
285{
286 taskbar_clock_t *clock = (taskbar_clock_t *) arg;
287
288 return taskbar_clock_paint(clock);
289}
290
[95fc538]291/** Handle taskbar clock control keyboard event.
[50a16d9]292 *
293 * @param arg Argument (taskbar_clock_t *)
294 * @param kbd_event Keyboard event
295 * @return @c ui_claimed iff the event is claimed
296 */
297ui_evclaim_t taskbar_clock_ctl_kbd_event(void *arg, kbd_event_t *event)
298{
299 taskbar_clock_t *clock = (taskbar_clock_t *) arg;
300
301 return taskbar_clock_kbd_event(clock, event);
302}
303
[95fc538]304/** Handle taskbar clock control position event.
[50a16d9]305 *
306 * @param arg Argument (taskbar_clock_t *)
307 * @param pos_event Position event
308 * @return @c ui_claimed iff the event is claimed
309 */
310ui_evclaim_t taskbar_clock_ctl_pos_event(void *arg, pos_event_t *event)
311{
312 taskbar_clock_t *clock = (taskbar_clock_t *) arg;
313
314 return taskbar_clock_pos_event(clock, event);
315}
316
317/** Taskbar clock timer handler.
318 *
319 * @param arg Argument (taskbar_clock_t *)
320 */
321static void taskbar_clock_timer(void *arg)
322{
323 taskbar_clock_t *clock = (taskbar_clock_t *) arg;
[983052c]324 ui_t *ui;
325
326 ui = ui_window_get_ui(clock->window);
327 ui_lock(ui);
[50a16d9]328
[c77cfd8]329 fibril_mutex_lock(&clock->lock);
[983052c]330 if (!ui_is_suspended(ui_window_get_ui(clock->window)))
331 (void) taskbar_clock_paint(clock);
[c77cfd8]332
333 if (!clock->timer_cleanup) {
334 fibril_timer_set(clock->timer, 1000000, taskbar_clock_timer,
335 clock);
336 } else {
337 /* Acknowledge timer cleanup */
338 clock->timer_done = true;
339 fibril_condvar_signal(&clock->timer_done_cv);
340 }
341
342 fibril_mutex_unlock(&clock->lock);
[983052c]343 ui_unlock(ui);
[50a16d9]344}
345
346/** @}
347 */
Note: See TracBrowser for help on using the repository browser.