PatchworkOS  19e446b
A non-POSIX operating system.
Loading...
Searching...
No Matches
taskbar.c
Go to the documentation of this file.
1#include "taskbar.h"
2
3#include <patchwork/display.h>
4#include <patchwork/element.h>
5#include <patchwork/event.h>
7#include <patchwork/window.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <sys/list.h>
12#include <time.h>
13
20
29
31{
32 rect_t startRect = taskbar_get_start_rect(elem);
33 const theme_t* theme = element_get_theme(elem);
34
35 return RECT_INIT_DIM(startRect.right + theme->bigPadding, startRect.top, theme->separatorSize,
36 RECT_HEIGHT(&startRect));
37}
38
40{
41 rect_t clockRect = taskbar_get_clock_rect(elem);
42 const theme_t* theme = element_get_theme(elem);
43
44 return RECT_INIT_DIM(clockRect.left - theme->bigPadding - theme->separatorSize, clockRect.top, theme->separatorSize,
45 RECT_HEIGHT(&clockRect));
46}
47
49{
50 const theme_t* theme = element_get_theme(elem);
51
52 rect_t leftSeparator = taskbar_get_left_separator_rect(elem);
53 rect_t rightSeparator = taskbar_get_right_separator_rect(elem);
54
55 uint64_t firstAvailPos = leftSeparator.right + theme->bigPadding;
56 uint64_t lastAvailPos = rightSeparator.left - theme->bigPadding;
57 uint64_t availLength = lastAvailPos - firstAvailPos;
58
59 if (taskbar->entryCount == 0)
60 {
61 return RECT_INIT_DIM(firstAvailPos, leftSeparator.top, 0, RECT_HEIGHT(&leftSeparator));
62 }
63
64 uint64_t totalPadding = (taskbar->entryCount - 1) * theme->bigPadding;
65 uint64_t buttonWidth = MIN(TASK_BUTTON_MAX_WIDTH, (availLength - totalPadding) / taskbar->entryCount);
66
67 return RECT_INIT_DIM(firstAvailPos + (buttonWidth + theme->bigPadding) * index, leftSeparator.top, buttonWidth,
68 RECT_HEIGHT(&leftSeparator));
69}
70
72{
73 uint64_t index = 0;
74 taskbar_entry_t* entry;
75 LIST_FOR_EACH(entry, &taskbar->entries, entry)
76 {
77 rect_t rect = taskbar_get_task_button_rect(taskbar, elem, index);
78 element_move(entry->button, &rect);
79 index++;
80 }
81}
82
83static void taskbar_entry_add(taskbar_t* taskbar, element_t* elem, const surface_info_t* info, const char* name)
84{
85 taskbar_entry_t* entry = malloc(sizeof(taskbar_entry_t));
86 if (entry == NULL)
87 {
88 return; // If this fails there isent much we can do so we just ignore it.
89 }
90 list_entry_init(&entry->entry);
91 entry->info = *info;
92 strcpy(entry->name, name);
93
94 list_push_back(&taskbar->entries, &entry->entry);
95 taskbar->entryCount++;
96
97 element_redraw(elem, true);
98
99 rect_t rect = taskbar_get_task_button_rect(taskbar, elem, taskbar->entryCount - 1);
100 entry->button = button_new(elem, info->id, &rect, entry->name, ELEMENT_TOGGLE);
101 if (entry->button == NULL)
102 {
103 list_remove(&entry->entry);
104 taskbar->entryCount--;
105 free(entry);
106 return; // Same here
107 }
108
109 taskbar_reposition_task_buttons(taskbar, elem);
110}
111
112static void taskbar_entry_remove(taskbar_t* taskbar, element_t* elem, surface_id_t surface)
113{
114 element_redraw(elem, true);
115
116 taskbar_entry_t* entry;
117 LIST_FOR_EACH(entry, &taskbar->entries, entry)
118 {
119 if (entry->info.id == surface)
120 {
121 element_free(entry->button);
122 list_remove(&entry->entry);
123 taskbar->entryCount--;
124 free(entry);
125
126 taskbar_reposition_task_buttons(taskbar, elem);
127 return;
128 }
129 }
130}
131
133{
134 time_t epoch = time(NULL);
135 struct tm timeData;
136 localtime_r(&epoch, &timeData);
137 char buffer[MAX_PATH];
138 sprintf(buffer, "%02d:%02d %d-%02d-%02d", timeData.tm_hour, timeData.tm_min, timeData.tm_year + 1900,
139 timeData.tm_mon + 1, timeData.tm_mday);
140 element_t* clockLabel = element_find(elem, CLOCK_LABEL_ID);
141
142 if (element_set_text(clockLabel, buffer) == ERR)
143 {
144 printf("taskbar: failed to update clock label\n");
145 return ERR;
146 }
147 element_redraw(clockLabel, false);
148
149 return 0;
150}
151
152static uint64_t taskbar_procedure(window_t* win, element_t* elem, const event_t* event)
153{
154 const theme_t* theme = element_get_theme(elem);
155
156 switch (event->type)
157 {
158 case EVENT_LIB_INIT:
159 {
160 rect_t rect = element_get_content_rect(elem);
161
162 rect_t startRect = taskbar_get_start_rect(elem);
163 if (button_new(elem, START_ID, &startRect, "Start", ELEMENT_TOGGLE | ELEMENT_NO_OUTLINE) == NULL)
164 {
165 printf("taskbar: failed to create start button\n");
166 return ERR;
167 }
168
169 rect_t clockRect = taskbar_get_clock_rect(elem);
170 if (label_new(elem, CLOCK_LABEL_ID, &clockRect, "0", ELEMENT_NONE) == NULL)
171 {
172 printf("taskbar: failed to create clock label\n");
173 return ERR;
174 }
175
177
178 if (taskbar_update_clock(elem) == ERR)
179 {
180 printf("taskbar: failed to update clock\n");
181 return ERR;
182 }
183
184 taskbar_t* taskbar = malloc(sizeof(taskbar_t));
185 if (taskbar == NULL)
186 {
187 printf("taskbar: failed to allocate taskbar private data\n");
188 errno = ENOMEM;
189 return ERR;
190 }
191 taskbar->win = win;
192 taskbar->disp = window_get_display(win);
193 taskbar->startMenu = start_menu_new(taskbar->win, taskbar->disp);
194 if (taskbar->startMenu == NULL)
195 {
196 free(taskbar);
197 return ERR;
198 }
199 list_init(&taskbar->entries);
200 taskbar->entryCount = 0;
201
202 element_set_private(elem, taskbar);
203 }
204 break;
205 case EVENT_LIB_DEINIT:
206 {
207 taskbar_t* taskbar = element_get_private(elem);
208 if (taskbar == NULL)
209 {
210 break;
211 }
212 window_free(taskbar->startMenu);
213
214 taskbar_entry_t* entry;
215 taskbar_entry_t* temp;
216 LIST_FOR_EACH_SAFE(entry, temp, &taskbar->entries, entry)
217 {
218 element_free(entry->button);
219 list_remove(&entry->entry);
220 taskbar->entryCount--;
221 free(entry);
222 }
223
224 free(taskbar);
225 }
226 break;
227 case EVENT_TIMER:
228 {
229 if (taskbar_update_clock(elem) == ERR)
230 {
231 return ERR;
232 }
233 }
234 break;
235 case EVENT_LIB_REDRAW:
236 {
237 rect_t rect = element_get_content_rect(elem);
238
239 drawable_t draw;
240 element_draw_begin(elem, &draw);
241
242 draw_rect(&draw, &rect, theme->deco.backgroundNormal);
243
244 rect.bottom = rect.top + theme->frameSize;
245 draw_rect(&draw, &rect, theme->deco.highlight);
246
247 rect_t leftSeparator = taskbar_get_left_separator_rect(elem);
248 rect_t rightSeparator = taskbar_get_right_separator_rect(elem);
249
252
253 element_draw_end(elem, &draw);
254 }
255 break;
256 case EVENT_LIB_ACTION:
257 {
258 taskbar_t* taskbar = element_get_private(elem);
259
260 if (event->libAction.source == START_ID)
261 {
262 if (event->libAction.type == ACTION_PRESS)
263 {
264 start_menu_open(taskbar->startMenu);
265 }
266 else if (event->libAction.type == ACTION_RELEASE)
267 {
268 start_menu_close(taskbar->startMenu);
269 }
270 break;
271 }
272
273 display_t* disp = window_get_display(win);
274
275 if (event->libAction.type == ACTION_PRESS)
276 {
277 display_set_is_visible(disp, event->libAction.source, false);
278 }
279 else if (event->libAction.type == ACTION_RELEASE)
280 {
281 display_set_is_visible(disp, event->libAction.source, true);
282 }
283 }
284 break;
286 {
287 taskbar_t* taskbar = element_get_private(elem);
288
290 event.action = ACTION_RELEASE;
291 element_emit(elem, EVENT_LIB_FORCE_ACTION, &event, sizeof(event));
292 }
293 break;
295 {
296 if (event->globalAttach.info.type != SURFACE_WINDOW || strcmp(event->globalAttach.info.name, "StartMenu") == 0)
297 {
298 break;
299 }
300
301 taskbar_t* taskbar = element_get_private(elem);
302 taskbar_entry_add(taskbar, elem, &event->globalAttach.info, event->globalAttach.info.name);
303 }
304 break;
306 {
307 taskbar_t* taskbar = element_get_private(elem);
308 taskbar_entry_remove(taskbar, elem, event->globalDetach.info.id);
309 }
310 break;
312 {
313 taskbar_t* taskbar = element_get_private(elem);
314
315 taskbar_entry_t* entry;
316 LIST_FOR_EACH(entry, &taskbar->entries, entry)
317 {
318 if (event->globalReport.info.id != entry->info.id)
319 {
320 continue;
321 }
322
323 entry->info = event->globalReport.info;
325 break;
326 }
327 }
328 break;
329 case EVENT_GLOBAL_KBD:
330 {
331 taskbar_t* taskbar = element_get_private(elem);
332
333 if (event->globalKbd.type == KBD_RELEASE && event->globalKbd.code == KBD_LEFT_SUPER)
334 {
336 if (state == START_MENU_OPEN || state == START_MENU_OPENING)
337 {
339 start_menu_close(taskbar->startMenu);
340 }
341 else
342 {
344 start_menu_open(taskbar->startMenu);
345 }
346 }
347 }
348 break;
349 }
350
351 return 0;
352}
353
355{
356 rect_t rect;
357 display_get_screen(disp, &rect, 0);
358 rect.top = rect.bottom - theme_global_get()->panelSize;
359
362 {
363 printf("taskbar: failed to subscribe to global events\n");
364 return NULL;
365 }
366
367 window_t* win = window_new(disp, "Taskbar", &rect, SURFACE_PANEL, WINDOW_NONE, taskbar_procedure, NULL);
368 if (win == NULL)
369 {
370 printf("taskbar: failed to create taskbar window\n");
371 return NULL;
372 }
373
374 if (window_set_visible(win, true) == ERR)
375 {
376 printf("taskbar: failed to show taskbar window\n");
377 window_free(win);
378 return NULL;
379 }
380
381 return win;
382}
#define MAX_PATH
Maximum length of filepaths.
Definition MAX_PATH.h:11
EFI_PHYSICAL_ADDRESS buffer
Definition main.c:237
#define CLOCKS_PER_SEC
Definition clock_t.h:15
@ TIMER_REPEAT
Definition cmd.h:77
uint64_t display_get_screen(display_t *disp, rect_t *rect, uint64_t index)
Get the rectangle of a screen.
Definition display.c:573
uint64_t display_subscribe(display_t *disp, event_type_t type)
Subscribe to events of a specific type.
Definition display.c:479
uint64_t display_set_is_visible(display_t *disp, surface_id_t id, bool isVisible)
Set the visibility of a surface.
Definition display.c:558
void draw_rect(drawable_t *draw, const rect_t *rect, pixel_t pixel)
Draw a filled rectangle.
Definition drawable.c:7
void draw_separator(drawable_t *draw, const rect_t *rect, pixel_t highlight, pixel_t shadow, direction_t direction)
Draw a separator line.
Definition drawable.c:1006
@ DIRECTION_VERTICAL
Definition drawable.h:60
element_t * element_find(element_t *elem, element_id_t id)
Find a child element by its ID.
Definition element.c:134
uint64_t element_emit(element_t *elem, event_type_t type, const void *data, uint64_t size)
Emit an event to an element.
Definition element.c:555
theme_t * element_get_theme(element_t *elem)
Get the theme of an element.
Definition element.c:401
#define ELEMENT_TOGGLE
Definition element.h:44
#define ELEMENT_NO_OUTLINE
Definition element.h:47
void element_draw_end(element_t *elem, drawable_t *draw)
End drawing to an element.
Definition element.c:427
#define ELEMENT_NONE
Definition element.h:43
rect_t element_get_content_rect(element_t *elem)
Get the element's rectangle in local coordinates.
Definition element.c:213
void element_draw_begin(element_t *elem, drawable_t *draw)
Begin drawing to an element.
Definition element.c:411
void element_free(element_t *elem)
Deinitialize and free an element and all its children.
Definition element.c:113
void element_set_private(element_t *elem, void *data)
Set private data for an element.
Definition element.c:163
void element_redraw(element_t *elem, bool shouldPropagate)
Redraw an element.
Definition element.c:450
uint64_t element_set_text(element_t *elem, const char *text)
Set the text of an element.
Definition element.c:343
void element_move(element_t *elem, const rect_t *rect)
Move an element to a new rectangle in its parent's coordinate space.
Definition element.c:193
void element_force_action(element_t *elem, action_type_t action)
Force an action on an element.
Definition element.c:463
void * element_get_private(element_t *elem)
Get private data for an element.
Definition element.c:173
#define EVENT_GLOBAL_REPORT
Definition event.h:92
#define EVENT_GLOBAL_ATTACH
Definition event.h:90
#define EVENT_GLOBAL_DETACH
Definition event.h:91
#define EVENT_LIB_FORCE_ACTION
Definition event.h:103
#define EVENT_GLOBAL_KBD
Definition event.h:93
#define EVENT_LIB_DEINIT
Definition event.h:99
#define EVENT_LIB_INIT
Definition event.h:98
#define EVENT_LIB_REDRAW
Definition event.h:100
#define EVENT_LIB_ACTION
Definition event.h:101
#define EVENT_TIMER
Definition event.h:85
@ KBD_RELEASE
Key release event.
Definition event.h:138
@ ACTION_PRESS
Definition event.h:50
@ ACTION_RELEASE
Definition event.h:49
uint64_t surface_id_t
Definition surface.h:53
@ SURFACE_WINDOW
Definition surface.h:35
@ SURFACE_PANEL
Definition surface.h:36
@ SURFACE_VISIBLE
Definition surface.h:49
theme_t * theme_global_get(void)
Get the global theme.
Definition theme.c:97
element_t * button_new(element_t *parent, element_id_t id, const rect_t *rect, const char *text, element_flags_t flags)
Create a new button element.
Definition button.c:309
element_t * label_new(element_t *parent, element_id_t id, const rect_t *rect, const char *text, element_flags_t flags)
Create a new label element.
Definition label.c:46
uint64_t window_set_visible(window_t *win, bool isVisible)
Set the visibility of the window.
Definition window.c:704
uint64_t window_set_timer(window_t *win, timer_flags_t flags, clock_t timeout)
Set the window timer.
Definition window.c:545
window_t * window_new(display_t *disp, const char *name, const rect_t *rect, surface_type_t type, window_flags_t flags, procedure_t procedure, void *data)
Allocate and initialize a new window.
Definition window.c:313
void window_free(window_t *win)
Free a window.
Definition window.c:427
display_t * window_get_display(window_t *win)
Get the display associated with the window.
Definition window.c:479
@ WINDOW_NONE
Definition window.h:45
#define ENOMEM
Out of memory.
Definition errno.h:92
#define errno
Error number variable.
Definition errno.h:27
@ KBD_LEFT_SUPER
Left Super key.
Definition kbd.h:256
#define LIST_FOR_EACH(elem, list, member)
Iterates over a list.
Definition list.h:58
static void list_remove(list_entry_t *entry)
Removes a list entry from its current list.
Definition list.h:290
static void list_push_back(list_t *list, list_entry_t *entry)
Pushes an entry to the end of the list.
Definition list.h:322
#define LIST_FOR_EACH_SAFE(elem, temp, list, member)
Safely iterates over a list, allowing for element removal during iteration.
Definition list.h:73
static void list_entry_init(list_entry_t *entry)
Initializes a list entry.
Definition list.h:173
static void list_init(list_t *list)
Initializes a list.
Definition list.h:185
#define MIN(x, y)
Definition math.h:18
#define NULL
Pointer error value.
Definition NULL.h:25
#define ERR
Integer error value.
Definition ERR.h:17
#define RECT_INIT_DIM(x, y, width, height)
Definition rect.h:32
#define RECT_HEIGHT(rect)
Definition rect.h:39
#define RECT_WIDTH(rect)
Definition rect.h:38
start_menu_state_t start_menu_get_state(window_t *startMenu)
Definition start_menu.c:324
void start_menu_close(window_t *startMenu)
Definition start_menu.c:308
void start_menu_open(window_t *startMenu)
Definition start_menu.c:277
window_t * start_menu_new(window_t *taskbar, display_t *disp)
Definition start_menu.c:172
#define EVENT_USER_START_MENU_CLOSE
Definition start_menu.h:12
start_menu_state_t
Definition start_menu.h:15
@ START_MENU_OPEN
Definition start_menu.h:17
@ START_MENU_OPENING
Definition start_menu.h:19
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
_PUBLIC int printf(const char *_RESTRICT format,...)
Definition printf.c:3
_PUBLIC int sprintf(char *_RESTRICT s, const char *_RESTRICT format,...)
Definition sprintf.c:5
_PUBLIC void * malloc(size_t size)
Definition malloc.c:5
_PUBLIC void free(void *ptr)
Definition free.c:11
_PUBLIC char * strcpy(char *_RESTRICT s1, const char *_RESTRICT s2)
Definition strcpy.c:3
_PUBLIC int strcmp(const char *s1, const char *s2)
Definition strcmp.c:3
Opaque display structure.
Definition internal.h:68
Drawable structure.
Definition drawable.h:35
Opaque element structure.
Definition internal.h:23
surface_info_t info
Definition event.h:227
surface_info_t info
Definition event.h:237
kbd_event_type_t type
Definition event.h:162
keycode_t code
Definition event.h:164
action_type_t type
Definition event.h:281
element_id_t source
Definition event.h:280
Library Force Action event.
Definition event.h:290
surface_info_t info
Definition event.h:217
Event structure.
Definition event.h:306
event_global_detach_t globalDetach
Definition event.h:318
event_lib_action_t libAction
Definition event.h:323
event_type_t type
Definition event.h:307
event_global_attach_t globalAttach
Definition event.h:317
event_global_report_t globalReport
Definition event.h:319
event_global_kbd_t globalKbd
Definition event.h:320
Definition rect.h:13
int32_t bottom
Definition rect.h:17
int32_t top
Definition rect.h:15
int32_t right
Definition rect.h:16
int32_t left
Definition rect.h:14
char name[MAX_NAME]
Definition surface.h:62
surface_flags_t flags
Definition surface.h:61
surface_id_t id
Definition surface.h:59
surface_type_t type
Definition surface.h:58
Definition taskbar.h:19
surface_info_t info
Definition taskbar.h:21
element_t * button
Definition taskbar.h:23
list_entry_t entry
Definition taskbar.h:20
char name[MAX_NAME]
Definition taskbar.h:22
window_t * startMenu
Definition taskbar.h:30
list_t entries
Definition taskbar.h:31
window_t * win
Definition taskbar.h:28
display_t * disp
Definition taskbar.h:29
uint64_t entryCount
Definition taskbar.h:32
pixel_t backgroundNormal
Definition theme.h:35
pixel_t highlight
Definition theme.h:45
pixel_t shadow
Definition theme.h:46
Theme structure.
Definition theme.h:71
int64_t smallPadding
Definition theme.h:88
theme_color_set_t deco
Definition theme.h:76
int64_t panelSize
Definition theme.h:86
int64_t frameSize
Definition theme.h:83
int64_t bigPadding
Definition theme.h:87
int64_t separatorSize
Definition theme.h:89
Definition time.h:21
int tm_mon
Definition time.h:26
int tm_year
Definition time.h:27
int tm_hour
Definition time.h:24
int tm_mday
Definition time.h:25
int tm_min
Definition time.h:23
Opaque window structure.
Definition internal.h:44
static rect_t taskbar_get_clock_rect(element_t *elem)
Definition taskbar.c:21
static rect_t taskbar_get_left_separator_rect(element_t *elem)
Definition taskbar.c:30
static rect_t taskbar_get_start_rect(element_t *elem)
Definition taskbar.c:14
static uint64_t taskbar_procedure(window_t *win, element_t *elem, const event_t *event)
Definition taskbar.c:152
static void taskbar_entry_add(taskbar_t *taskbar, element_t *elem, const surface_info_t *info, const char *name)
Definition taskbar.c:83
static rect_t taskbar_get_task_button_rect(taskbar_t *taskbar, element_t *elem, uint64_t index)
Definition taskbar.c:48
static rect_t taskbar_get_right_separator_rect(element_t *elem)
Definition taskbar.c:39
static uint64_t taskbar_update_clock(element_t *elem)
Definition taskbar.c:132
static void taskbar_reposition_task_buttons(taskbar_t *taskbar, element_t *elem)
Definition taskbar.c:71
static void taskbar_entry_remove(taskbar_t *taskbar, element_t *elem, surface_id_t surface)
Definition taskbar.c:112
window_t * taskbar_new(display_t *disp)
Definition taskbar.c:354
#define CLOCK_LABEL_ID
Definition taskbar.h:16
#define START_ID
Definition taskbar.h:10
#define START_WIDTH
Definition taskbar.h:9
#define CLOCK_WIDTH
Definition taskbar.h:12
#define TASK_BUTTON_MAX_WIDTH
Definition taskbar.h:14
static theme_t theme
Definition theme.c:12
_PUBLIC time_t time(time_t *timer)
Definition time.c:5
_PUBLIC struct tm * localtime_r(const time_t *timer, struct tm *buf)
Definition localtime_r.c:6
long long unsigned time_t
Definition time_t.h:4