PatchworkOS
Loading...
Searching...
No Matches
start_menu.c
Go to the documentation of this file.
1#include "start_menu.h"
2
3#include "taskbar.h"
4
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <sys/io.h>
10#include <sys/proc.h>
11
12#define START_ENTRY_MAX 16
13
14typedef struct
15{
16 const char* name;
17 const char* path;
20
22
23#define ENTRY_AMOUNT (sizeof(entries) / sizeof(entries[0]))
24
25#define START_MENU_HEIGHT(frameSize) (frameSize + 12 * START_BUTTON_HEIGHT)
26
27#define START_MENU_YPOS_START(screenRect, panelSize, frameSize) (RECT_HEIGHT(screenRect))
28#define START_MENU_YPOS_END(screenRect, panelSize, frameSize) \
29 (RECT_HEIGHT(screenRect) - START_MENU_HEIGHT(frameSize) - panelSize)
30
31static uint64_t startmenu_procedure(window_t* win, element_t* elem, const event_t* event)
32{
33 const theme_t* theme = element_get_theme(elem);
34
35 switch (event->type)
36 {
37 case LEVENT_INIT:
38 {
39 start_menu_t* menu = malloc(sizeof(start_menu_t));
40 if (menu == NULL)
41 {
42 printf("startmenu: failed to allocate start menu private data\n");
43 errno = ENOMEM;
44 return ERR;
45 }
46 menu->win = win;
47 menu->taskbar = element_get_private(elem);
48 menu->animationStartTime = uptime();
50
52
53 element_set_private(elem, menu);
54 }
55 break;
56 case LEVENT_DEINIT:
57 {
59 if (menu == NULL)
60 {
61 break;
62 }
63 free(menu);
64 }
65 break;
66 case LEVENT_REDRAW:
67 {
69
70 drawable_t draw;
71 element_draw_begin(elem, &draw);
72
75 draw_rect(&draw, &rect, theme->deco.backgroundNormal);
76
77 rect.right = rect.left + theme->titlebarSize;
79 DIRECTION_VERTICAL, false);
80
81 element_draw_end(elem, &draw);
82 }
83 break;
84 case LEVENT_ACTION:
85 {
87 if (event->lAction.type == ACTION_RELEASE)
88 {
90
91 const char* argv[] = {entries[event->lAction.source].path, NULL};
92 if (spawn(argv, NULL, NULL, NULL) == ERR)
93 {
94 char buffer[MAX_PATH];
95 sprintf(buffer, "Failed to spawn (%s)!", entries[event->lAction.source].path);
96
97 popup_open(buffer, "Error!", POPUP_OK);
98 }
99 }
100 }
101 break;
102 case EVENT_TIMER:
103 {
104 start_menu_t* menu = element_get_private(elem);
107
110
111 clock_t timeElapsed = uptime() - menu->animationStartTime;
112
113 double fraction;
114 int64_t currentY = 0;
115 bool isAnimComplete = false;
116
117 if (menu->state == START_MENU_OPENING)
118 {
119 fraction = (double)timeElapsed / START_MENU_ANIMATION_TIME;
120 if (fraction >= 1.0)
121 {
122 fraction = 1.0;
123 isAnimComplete = true;
124 }
125 currentY = (int64_t)((double)startY + ((double)endY - startY) * fraction);
126 }
127 else if (menu->state == START_MENU_CLOSING)
128 {
129 fraction = (double)timeElapsed / START_MENU_ANIMATION_TIME;
130 if (fraction >= 1.0)
131 {
132 fraction = 1.0;
133 isAnimComplete = true;
134 }
135 currentY = (int64_t)((double)endY + ((double)startY - endY) * fraction);
136 }
137 else
138 {
139 return 0;
140 }
141
142 rect_t rect = window_get_rect(win);
143 uint64_t height = RECT_HEIGHT(&rect);
144 rect.top = currentY;
145 rect.bottom = currentY + height;
146 if (window_move(win, &rect) == ERR)
147 {
148 printf("startmenu: failed to move window during animation (%s)\n", strerror(errno));
149 }
150
151 if (isAnimComplete)
152 {
154 {
155 printf("startmenu: failed to disable timer (%s)\n", strerror(errno));
156 }
157 if (menu->state == START_MENU_OPENING)
158 {
159 menu->state = START_MENU_OPEN;
160 }
161 else if (menu->state == START_MENU_CLOSING)
162 {
163 menu->state = START_MENU_CLOSED;
164 }
165 }
166 }
167 break;
168 }
169
170 return 0;
171}
172
174{
175 const theme_t* theme = theme_global_get();
178
179 rect_t rect =
182
183 window_t* win = window_new(disp, "StartMenu", &rect, SURFACE_WINDOW, WINDOW_NONE, startmenu_procedure, taskbar);
184 if (win == NULL)
185 {
186 printf("startmenu: failed to create start menu window\n");
187 return NULL;
188 }
189
190 if (window_set_visible(win, true) == ERR)
191 {
192 window_free(win);
193 return NULL;
194 }
195
196 return win;
197}
198
199static void start_menu_load_entries(window_t* startMenu)
200{
201 config_t* config = config_open("taskbar", "main");
202 if (config == NULL)
203 {
204 printf("startmenu: failed to open start menu config\n");
205 return;
206 }
207
208 bool changed = false;
209 for (uint64_t i = 0; i < ENTRY_AMOUNT; i++)
210 {
211 char entryKey[32];
212 snprintf(entryKey, sizeof(entryKey), "entry%lu", i);
213 config_array_t* entryArray = config_get_array(config, "start", entryKey);
214 if (entryArray == NULL || entryArray->length != 2)
215 {
216 break;
217 }
218
219 if (entries[i].name != NULL || entries[i].path != NULL)
220 {
221 if (strcmp(entries[i].name, entryArray->items[0]) == 0 &&
222 strcmp(entries[i].path, entryArray->items[1]) == 0)
223 {
224 continue;
225 }
226 free((void*)entries[i].name);
227 free((void*)entries[i].path);
228 }
229
230 changed = true;
231 entries[i].name = strdup(entryArray->items[0]);
232 if (entries[i].name == NULL)
233 {
234 break;
235 }
236 entries[i].path = strdup(entryArray->items[1]);
237 if (entries[i].path == NULL)
238 {
239 free((void*)entries[i].name);
240 break;
241 }
242 }
243
244 config_close(config);
245
246 if (!changed)
247 {
248 return;
249 }
250
251 // Clear existing buttons
252 for (uint64_t i = 0; i < ENTRY_AMOUNT; i++)
253 {
254 if (entries[i].button != NULL)
255 {
256 element_free(entries[i].button);
257 entries[i].button = NULL;
258 }
259 }
260
261 const theme_t* theme = theme_global_get();
262 for (uint64_t i = 0; i < ENTRY_AMOUNT; i++)
263 {
264 if (entries[i].name == NULL || entries[i].path == NULL)
265 {
266 break;
267 }
268
269 rect_t buttonRect =
272
273 entries[i].button =
274 button_new(window_get_client_element(startMenu), i, &buttonRect, entries[i].name, ELEMENT_FLAT);
275 }
276}
277
278void start_menu_open(window_t* startMenu)
279{
280 element_t* elem = window_get_client_element(startMenu);
281 const theme_t* theme = element_get_theme(elem);
282 start_menu_t* menu = element_get_private(elem);
283
284 if (menu->state == START_MENU_OPEN || menu->state == START_MENU_OPENING)
285 {
286 return;
287 }
288
289 start_menu_load_entries(startMenu);
290
293
295
296 rect_t rect = window_get_rect(startMenu);
297 uint64_t height = RECT_HEIGHT(&rect);
298 rect.top = startY;
299 rect.bottom = startY + height;
300 window_move(startMenu, &rect);
301
302 menu->animationStartTime = uptime();
305
306 window_set_focus(startMenu);
307}
308
310{
311 element_t* elem = window_get_client_element(startMenu);
312 start_menu_t* menu = element_get_private(elem);
313 if (menu->state == START_MENU_CLOSED || menu->state == START_MENU_CLOSING)
314 {
315 return;
316 }
317
318 menu->animationStartTime = uptime();
321
323}
324
326{
327 if (startMenu == NULL)
328 {
329 return START_MENU_CLOSED;
330 }
331
332 element_t* elem = window_get_client_element(startMenu);
333 start_menu_t* menu = element_get_private(elem);
334 return menu->state;
335}
#define MAX_PATH
Maximum length of filepaths.
Definition MAX_PATH.h:11
#define CLOCKS_NEVER
Definition clock_t.h:16
#define CLOCKS_PER_SEC
Definition clock_t.h:15
@ TIMER_NONE
Definition cmd.h:76
@ TIMER_REPEAT
Definition cmd.h:77
static rect_t screenRect
Definition compositor.c:10
config_array_t * config_get_array(config_t *config, const char *section, const char *key)
Get an array of strings from a configuration file.
Definition config.c:300
config_t * config_open(const char *prefix, const char *name)
Open a configuration file.
Definition config.c:93
void config_close(config_t *config)
Close a configuration file.
Definition config.c:202
void display_push(display_t *disp, surface_id_t target, event_type_t type, void *data, uint64_t size)
Push an event to the display's internal event queue.
Definition display.c:349
uint64_t display_get_screen(display_t *disp, rect_t *rect, uint64_t index)
Get the rectangle of a screen.
Definition display.c:603
void draw_gradient(drawable_t *draw, const rect_t *rect, pixel_t start, pixel_t end, direction_t direction, bool shouldAddNoise)
Draw a gradient filled rectangle.
Definition drawable.c:382
void draw_rect(drawable_t *draw, const rect_t *rect, pixel_t pixel)
Draw a filled rectangle.
Definition drawable.c:7
void draw_frame(drawable_t *draw, const rect_t *rect, uint64_t width, pixel_t foreground, pixel_t background)
Draw a skeuomorphic frame.
Definition drawable.c:204
@ 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
theme_t * element_get_theme(element_t *elem)
Get the theme of an element.
Definition element.c:401
void element_draw_end(element_t *elem, drawable_t *draw)
End drawing to an element.
Definition element.c:427
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_get_private(element_t *elem)
Get private data for an element.
Definition element.c:173
#define ELEMENT_FLAT
Definition element.h:45
#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 EVENT_TIMER
Definition event.h:86
@ ACTION_RELEASE
Definition event.h:50
@ SURFACE_WINDOW
Definition surface.h:35
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
uint64_t window_set_visible(window_t *win, bool isVisible)
Set the visibility of the window.
Definition window.c:692
rect_t window_get_rect(window_t *win)
Get the window's rectangle in screen coordinates.
Definition window.c:447
uint64_t window_move(window_t *win, const rect_t *rect)
Move and/or resize the window.
Definition window.c:507
uint64_t window_set_focus(window_t *win)
Set the focus to the window.
Definition window.c:673
surface_id_t window_get_id(window_t *win)
Get the surface ID of the window.
Definition window.c:477
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
element_t * window_get_client_element(window_t *win)
Get the client element of the window.
Definition window.c:497
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
pid_t spawn(const char **argv, const spawn_fd_t *fds, const char *cwd, spawn_attr_t *attr)
System call for creating child processes.
Definition spawn.c:6
clock_t uptime(void)
System call for retreving the time since boot.
Definition uptime.c:6
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
__UINT64_TYPE__ clock_t
A nanosecond time.
Definition clock_t.h:13
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
popup_result_t popup_open(const char *text, const char *title, popup_type_t type)
Definition popup.c:87
@ POPUP_OK
Definition popup.h:22
#define RECT_SHRINK(rect, margin)
Definition rect.h:81
#define RECT_INIT_DIM(x, y, width, height)
Definition rect.h:32
#define RECT_INIT(left, top, right, bottom)
Definition rect.h:26
#define RECT_HEIGHT(rect)
Definition rect.h:39
#define START_MENU_YPOS_START(screenRect, panelSize, frameSize)
Definition start_menu.c:27
static void start_menu_load_entries(window_t *startMenu)
Definition start_menu.c:199
#define ENTRY_AMOUNT
Definition start_menu.c:23
static uint64_t startmenu_procedure(window_t *win, element_t *elem, const event_t *event)
Definition start_menu.c:31
start_menu_state_t start_menu_get_state(window_t *startMenu)
Definition start_menu.c:325
#define START_MENU_HEIGHT(frameSize)
Definition start_menu.c:25
#define START_ENTRY_MAX
Definition start_menu.c:12
static start_entry_t entries[START_ENTRY_MAX]
Definition start_menu.c:21
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 START_MENU_YPOS_END(screenRect, panelSize, frameSize)
Definition start_menu.c:28
#define START_BUTTON_HEIGHT
Definition start_menu.h:6
#define START_MENU_WIDTH
Definition start_menu.h:8
#define UEVENT_START_MENU_CLOSE
Definition start_menu.h:12
start_menu_state_t
Definition start_menu.h:15
@ START_MENU_CLOSING
Definition start_menu.h:18
@ START_MENU_OPEN
Definition start_menu.h:17
@ START_MENU_OPENING
Definition start_menu.h:19
@ START_MENU_CLOSED
Definition start_menu.h:16
#define START_MENU_ANIMATION_TIME
Definition start_menu.h:10
__INT32_TYPE__ int32_t
Definition stdint.h:14
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__INT64_TYPE__ int64_t
Definition stdint.h:16
_PUBLIC int printf(const char *_RESTRICT format,...)
Definition printf.c:5
_PUBLIC int snprintf(char *_RESTRICT s, size_t n, const char *_RESTRICT format,...)
Definition snprintf.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 * strerror(int errnum)
Definition strerror.c:6
char * strdup(const char *src)
Definition strdup.c:5
_PUBLIC int strcmp(const char *s1, const char *s2)
Definition strcmp.c:3
Configuration array structure.
Definition config.h:38
char ** items
Definition config.h:39
uint64_t length
Definition config.h:40
Opaque configuration structure.
Definition config.c:28
Opaque display structure.
Definition internal.h:61
Drawable structure.
Definition drawable.h:35
Opaque element structure.
Definition internal.h:23
Event structure.
Definition event.h:271
event_type_t type
Definition event.h:272
levent_action_t lAction
Definition event.h:288
action_type_t type
Definition event.h:246
element_id_t source
Definition event.h:245
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
Definition start_menu.c:15
const char * name
Definition start_menu.c:16
element_t * button
Definition start_menu.c:18
const char * path
Definition start_menu.c:17
start_menu_state_t state
Definition start_menu.h:27
window_t * win
Definition start_menu.h:24
clock_t animationStartTime
Definition start_menu.h:26
window_t * taskbar
Definition start_menu.h:25
pixel_t backgroundNormal
Definition theme.h:35
pixel_t backgroundSelectedEnd
Definition theme.h:37
pixel_t highlight
Definition theme.h:45
pixel_t shadow
Definition theme.h:46
pixel_t backgroundSelectedStart
Definition theme.h:36
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 titlebarSize
Definition theme.h:85
int64_t frameSize
Definition theme.h:83
Opaque window structure.
Definition internal.h:44
static theme_t theme
Definition theme.c:12