PatchworkOS
Loading...
Searching...
No Matches
taskbar.c
Go to the documentation of this file.
1#include "taskbar.h"
2
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
60
61 if (entryCount == 0)
62 {
63 return RECT_INIT_DIM(firstAvailPos, leftSeparator.top, 0, RECT_HEIGHT(&leftSeparator));
64 }
65
66 uint64_t totalPadding = (entryCount - 1) * theme->bigPadding;
67 uint64_t buttonWidth = MIN(TASK_BUTTON_MAX_WIDTH, (availLength - totalPadding) / entryCount);
68
69 return RECT_INIT_DIM(firstAvailPos + (buttonWidth + theme->bigPadding) * index, leftSeparator.top, buttonWidth,
70 RECT_HEIGHT(&leftSeparator));
71}
72
74{
75 uint64_t index = 0;
76 taskbar_entry_t* entry;
77 LIST_FOR_EACH(entry, &taskbar->entries, entry)
78 {
79 rect_t rect = taskbar_get_task_button_rect(taskbar, elem, index);
80 element_move(entry->button, &rect);
81 index++;
82 }
83}
84
85static void taskbar_entry_add(taskbar_t* taskbar, element_t* elem, const surface_info_t* info, const char* name)
86{
87 taskbar_entry_t* entry = malloc(sizeof(taskbar_entry_t));
88 if (entry == NULL)
89 {
90 return; // If this fails there isent much we can do so we just ignore it.
91 }
92 list_entry_init(&entry->entry);
93 entry->info = *info;
94 strcpy(entry->name, name);
95
96 list_push(&taskbar->entries, &entry->entry);
97
98 element_redraw(elem, true);
99
100 rect_t rect = taskbar_get_task_button_rect(taskbar, elem, list_length(&taskbar->entries) - 1);
101 entry->button = button_new(elem, info->id, &rect, entry->name, ELEMENT_TOGGLE);
102 if (entry->button == NULL)
103 {
104 list_remove(&taskbar->entries, &entry->entry);
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(&taskbar->entries, &entry->entry);
123 free(entry);
124
125 taskbar_reposition_task_buttons(taskbar, elem);
126 return;
127 }
128 }
129}
130
132{
133 time_t epoch = time(NULL);
134 struct tm timeData;
135 localtime_r(&epoch, &timeData);
136 char buffer[MAX_PATH];
137 sprintf(buffer, "%02d:%02d %d-%02d-%02d", timeData.tm_hour, timeData.tm_min, timeData.tm_year + 1900,
138 timeData.tm_mon + 1, timeData.tm_mday);
139 element_t* clockLabel = element_find(elem, CLOCK_LABEL_ID);
140
141 if (element_set_text(clockLabel, buffer) == ERR)
142 {
143 printf("taskbar: failed to update clock label\n");
144 return ERR;
145 }
146 element_redraw(clockLabel, false);
147
148 return 0;
149}
150
151static uint64_t taskbar_procedure(window_t* win, element_t* elem, const event_t* event)
152{
153 const theme_t* theme = element_get_theme(elem);
154
155 switch (event->type)
156 {
157 case LEVENT_INIT:
158 {
159 rect_t rect = element_get_content_rect(elem);
160
161 rect_t startRect = taskbar_get_start_rect(elem);
162 if (button_new(elem, START_ID, &startRect, "Start", ELEMENT_TOGGLE | ELEMENT_NO_OUTLINE) == NULL)
163 {
164 printf("taskbar: failed to create start button\n");
165 return ERR;
166 }
167
168 rect_t clockRect = taskbar_get_clock_rect(elem);
169 if (label_new(elem, CLOCK_LABEL_ID, &clockRect, "0", ELEMENT_NONE) == NULL)
170 {
171 printf("taskbar: failed to create clock label\n");
172 return ERR;
173 }
174
176
177 if (taskbar_update_clock(elem) == ERR)
178 {
179 printf("taskbar: failed to update clock\n");
180 return ERR;
181 }
182
183 taskbar_t* taskbar = malloc(sizeof(taskbar_t));
184 if (taskbar == NULL)
185 {
186 printf("taskbar: failed to allocate taskbar private data\n");
187 errno = ENOMEM;
188 return ERR;
189 }
190 taskbar->win = win;
191 taskbar->disp = window_get_display(win);
192 taskbar->startMenu = start_menu_new(taskbar->win, taskbar->disp);
193 if (taskbar->startMenu == NULL)
194 {
195 free(taskbar);
196 return ERR;
197 }
198 list_init(&taskbar->entries);
199
200 element_set_private(elem, taskbar);
201 }
202 break;
203 case LEVENT_DEINIT:
204 {
205 taskbar_t* taskbar = element_get_private(elem);
206 if (taskbar == NULL)
207 {
208 break;
209 }
210 window_free(taskbar->startMenu);
211
212 taskbar_entry_t* entry;
213 taskbar_entry_t* temp;
214 LIST_FOR_EACH_SAFE(entry, temp, &taskbar->entries, entry)
215 {
216 element_free(entry->button);
217 list_remove(&taskbar->entries, &entry->entry);
218 free(entry);
219 }
220
221 free(taskbar);
222 }
223 break;
224 case EVENT_TIMER:
225 {
226 if (taskbar_update_clock(elem) == ERR)
227 {
228 return ERR;
229 }
230 }
231 break;
232 case LEVENT_REDRAW:
233 {
234 rect_t rect = element_get_content_rect(elem);
235
236 drawable_t draw;
237 element_draw_begin(elem, &draw);
238
239 draw_rect(&draw, &rect, theme->deco.backgroundNormal);
240
241 rect.bottom = rect.top + theme->frameSize;
242 draw_rect(&draw, &rect, theme->deco.highlight);
243
244 rect_t leftSeparator = taskbar_get_left_separator_rect(elem);
245 rect_t rightSeparator = taskbar_get_right_separator_rect(elem);
246
249
250 element_draw_end(elem, &draw);
251 }
252 break;
253 case LEVENT_ACTION:
254 {
255 taskbar_t* taskbar = element_get_private(elem);
256
257 if (event->lAction.source == START_ID)
258 {
259 if (event->lAction.type == ACTION_PRESS)
260 {
261 start_menu_open(taskbar->startMenu);
262 }
263 else if (event->lAction.type == ACTION_RELEASE)
264 {
265 start_menu_close(taskbar->startMenu);
266 }
267 break;
268 }
269
270 display_t* disp = window_get_display(win);
271
272 if (event->lAction.type == ACTION_PRESS)
273 {
274 display_set_is_visible(disp, event->lAction.source, false);
275 }
276 else if (event->lAction.type == ACTION_RELEASE)
277 {
278 display_set_is_visible(disp, event->lAction.source, true);
279 }
280 }
281 break;
283 {
284 taskbar_t* taskbar = element_get_private(elem);
285
287 event.action = ACTION_RELEASE;
288 element_emit(elem, LEVENT_FORCE_ACTION, &event, sizeof(event));
289 }
290 break;
291 case GEVENT_ATTACH:
292 {
293 if (event->globalAttach.info.type != SURFACE_WINDOW || strcmp(event->globalAttach.info.name, "StartMenu") == 0)
294 {
295 break;
296 }
297
298 taskbar_t* taskbar = element_get_private(elem);
299 taskbar_entry_add(taskbar, elem, &event->globalAttach.info, event->globalAttach.info.name);
300 }
301 break;
302 case GEVENT_DETACH:
303 {
304 taskbar_t* taskbar = element_get_private(elem);
305 taskbar_entry_remove(taskbar, elem, event->globalDetach.info.id);
306 }
307 break;
308 case GEVENT_REPORT:
309 {
310 taskbar_t* taskbar = element_get_private(elem);
311
312 taskbar_entry_t* entry;
313 LIST_FOR_EACH(entry, &taskbar->entries, entry)
314 {
315 if (event->globalReport.info.id != entry->info.id)
316 {
317 continue;
318 }
319
320 entry->info = event->globalReport.info;
322 break;
323 }
324 }
325 break;
326 case GEVENT_KBD:
327 {
328 taskbar_t* taskbar = element_get_private(elem);
329
330 if (event->globalKbd.type == KBD_RELEASE && event->globalKbd.code == KBD_LEFT_SUPER)
331 {
333 if (state == START_MENU_OPEN || state == START_MENU_OPENING)
334 {
336 start_menu_close(taskbar->startMenu);
337 }
338 else
339 {
341 start_menu_open(taskbar->startMenu);
342 }
343 }
344 }
345 break;
346 }
347
348 return 0;
349}
350
352{
353 fd_t klog = open("/dev/klog");
354 if (klog == ERR)
355 {
356 printf("taskbar: failed to open klog\n");
357 return NULL;
358 }
360 {
361 printf("taskbar: failed to redirect stdout/stderr to klog\n");
362 close(klog);
363 return NULL;
364 }
365 close(klog);
366
367 rect_t rect;
368 display_get_screen(disp, &rect, 0);
369 rect.top = rect.bottom - theme_global_get()->panelSize;
370
373 {
374 printf("taskbar: failed to subscribe to global events\n");
375 return NULL;
376 }
377
378 window_t* win = window_new(disp, "Taskbar", &rect, SURFACE_PANEL, WINDOW_NONE, taskbar_procedure, NULL);
379 if (win == NULL)
380 {
381 printf("taskbar: failed to create taskbar window\n");
382 return NULL;
383 }
384
385 if (window_set_visible(win, true) == ERR)
386 {
387 printf("taskbar: failed to show taskbar window\n");
388 window_free(win);
389 return NULL;
390 }
391
392 return win;
393}
#define MAX_PATH
Maximum length of filepaths.
Definition MAX_PATH.h:11
#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:603
uint64_t display_subscribe(display_t *disp, event_type_t type)
Subscribe to events of a specific type.
Definition display.c:509
uint64_t display_set_is_visible(display_t *disp, surface_id_t id, bool isVisible)
Set the visibility of a surface.
Definition display.c:588
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:1008
@ DIRECTION_VERTICAL
Definition drawable.h:60
void element_set_private(element_t *elem, void *private)
Set private data for an element.
Definition element.c:163
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_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 GEVENT_KBD
Definition event.h:94
#define LEVENT_FORCE_ACTION
Definition event.h:104
#define GEVENT_ATTACH
Definition event.h:91
#define LEVENT_DEINIT
Definition event.h:100
#define LEVENT_REDRAW
Definition event.h:101
#define LEVENT_INIT
Definition event.h:99
#define LEVENT_ACTION
Definition event.h:102
#define GEVENT_REPORT
Definition event.h:93
#define GEVENT_DETACH
Definition event.h:92
#define EVENT_TIMER
Definition event.h:86
@ ACTION_PRESS
Definition event.h:51
@ ACTION_RELEASE
Definition event.h:50
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:308
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:45
uint64_t window_set_visible(window_t *win, bool isVisible)
Set the visibility of the window.
Definition window.c:692
uint64_t window_set_timer(window_t *win, timer_flags_t flags, clock_t timeout)
Set the window timer.
Definition window.c:533
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 *private)
Allocate and initialize a new window.
Definition window.c:301
void window_free(window_t *win)
Free a window.
Definition window.c:415
display_t * window_get_display(window_t *win)
Get the display associated with the window.
Definition window.c:467
@ WINDOW_NONE
Definition window.h:45
#define ENOMEM
Out of memory.
Definition errno.h:92
#define errno
Error number variable.
Definition errno.h:27
fd_t dup2(fd_t oldFd, fd_t newFd)
System call for duplicating file descriptors, with a destination.
Definition dup2.c:9
fd_t open(const char *path)
System call for opening files.
Definition open.c:9
uint64_t close(fd_t fd)
System call for closing files.
Definition close.c:9
#define STDOUT_FILENO
Definition io.h:45
#define STDERR_FILENO
Definition io.h:46
@ KBD_LEFT_SUPER
Left Super key.
Definition kbd.h:252
@ KBD_RELEASE
Key release event.
Definition kbd.h:288
#define LIST_FOR_EACH(elem, list, member)
Iterates over a list.
Definition list.h:65
static uint64_t list_length(list_t *list)
Gets the length of the list.
Definition list.h:248
#define LIST_FOR_EACH_SAFE(elem, temp, list, member)
Safely iterates over a list, allowing for element removal during iteration.
Definition list.h:81
static void list_remove(list_t *list, list_entry_t *entry)
Removes a list entry from its current list.
Definition list.h:317
static void list_push(list_t *list, list_entry_t *entry)
Pushes an entry to the end of the list.
Definition list.h:345
static void list_entry_init(list_entry_t *entry)
Initializes a list entry.
Definition list.h:184
static void list_init(list_t *list)
Initializes a list.
Definition list.h:198
#define MIN(x, y)
Definition math.h:16
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
__UINT64_TYPE__ fd_t
A file descriptor.
Definition fd_t.h:12
static fb_info_t info
Definition gop.c:41
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
static uint64_t entryCount
Definition pci_config.c:7
#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:325
void start_menu_close(window_t *startMenu)
Definition start_menu.c:309
void start_menu_open(window_t *startMenu)
Definition start_menu.c:278
window_t * start_menu_new(window_t *taskbar, display_t *disp)
Definition start_menu.c:173
#define UEVENT_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:5
_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:61
Drawable structure.
Definition drawable.h:35
Opaque element structure.
Definition internal.h:23
kbd_event_type_t type
Definition event.h:139
keycode_t code
Definition event.h:141
surface_info_t info
Definition event.h:182
Event structure.
Definition event.h:271
gevent_detach_t globalDetach
Definition event.h:283
gevent_report_t globalReport
Definition event.h:284
event_type_t type
Definition event.h:272
levent_action_t lAction
Definition event.h:288
gevent_kbd_t globalKbd
Definition event.h:285
gevent_attach_t globalAttach
Definition event.h:282
surface_info_t info
Definition event.h:192
surface_info_t info
Definition event.h:202
action_type_t type
Definition event.h:246
element_id_t source
Definition event.h:245
Library Force Action event.
Definition event.h:255
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
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:151
static void taskbar_entry_add(taskbar_t *taskbar, element_t *elem, const surface_info_t *info, const char *name)
Definition taskbar.c:85
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:131
static void taskbar_reposition_task_buttons(taskbar_t *taskbar, element_t *elem)
Definition taskbar.c:73
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:351
#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
fd_t klog
Definition thrd_create.c:11
_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