Major redesign 1.60

This commit is contained in:
Chris 2026-02-24 12:17:20 +01:00
parent 6f68538b86
commit b4cccb0eb3
30 changed files with 495 additions and 332 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,4 +1,4 @@
# BoredOS 1.50 # BoredOS 1.51
BoredOS has now exited Beta stage and is "stable enough" to be put out as a "stable" product. BoredOS has now exited Beta stage and is "stable enough" to be put out as a "stable" product.
<img src="bored.svg" width="200" /> </br> <img src="bored.svg" width="200" /> </br>
@ -9,6 +9,7 @@ It features a DE (and WM), a FAT32 filesystem, customizable UI and much much mor
*this screenshot might be outdated* *this screenshot might be outdated*
## Features ## Features
- Disk manager
- Drag and drop mouse centered UI - Drag and drop mouse centered UI
- Customizable UI - Customizable UI
- Basic Networking Stack - Basic Networking Stack

Binary file not shown.

View file

@ -13,13 +13,13 @@ static void about_paint(Window *win) {
draw_boredos_logo(win->x + 60, offset_y, 4); draw_boredos_logo(win->x + 60, offset_y, 4);
// Version info // Version info
draw_string(offset_x, offset_y + 105, "BoredOS 'Panda'", COLOR_BLACK); draw_string(offset_x, offset_y + 105, "BoredOS 'Panda'", COLOR_WHITE);
draw_string(offset_x, offset_y + 120, "BoredOS Version 1.51", COLOR_BLACK); draw_string(offset_x, offset_y + 120, "BoredOS Version 1.51", COLOR_WHITE);
draw_string(offset_x, offset_y + 135, "Kernel Version 2.5.0", COLOR_BLACK); draw_string(offset_x, offset_y + 135, "Kernel Version 2.5.0", COLOR_WHITE);
// Copyright // Copyright
draw_string(offset_x, offset_y + 150, "(C) 2026 boreddevnl.", COLOR_BLACK); draw_string(offset_x, offset_y + 150, "(C) 2026 boreddevnl.", COLOR_WHITE);
draw_string(offset_x, offset_y + 165, "All rights reserved.", COLOR_BLACK); draw_string(offset_x, offset_y + 165, "All rights reserved.", COLOR_WHITE);
} }
static void about_click(Window *win, int x, int y) { static void about_click(Window *win, int x, int y) {

View file

@ -100,17 +100,16 @@ static void update_display(Window *win) {
static void calculator_paint(Window *win) { static void calculator_paint(Window *win) {
// Background // Background
draw_rect(win->x + 4, win->y + 24, win->w - 8, win->h - 28, COLOR_LTGRAY); draw_rect(win->x + 4, win->y + 30, win->w - 8, win->h - 34, COLOR_DARK_BG);
// Display Area // Display Area with dark mode styling
draw_bevel_rect(win->x + 10, win->y + 30, win->w - 20, 25, true); draw_rounded_rect_filled(win->x + 10, win->y + 36, win->w - 20, 25, 6, COLOR_DARK_PANEL);
// Right align text // Right align text
int text_w = win->buf_len * 8; int text_w = win->buf_len * 8;
int text_x = win->x + win->w - 15 - text_w; int text_x = win->x + win->w - 15 - text_w;
draw_string(text_x, win->y + 38, win->buffer, COLOR_BLACK); draw_string(text_x, win->y + 44, win->buffer, COLOR_DARK_TEXT);
// Buttons // Buttons - macOS style squircle buttons
// Layout 4 columns x 5 rows
const char *labels[] = { const char *labels[] = {
"C", "sqr", "rt", "/", "C", "sqr", "rt", "/",
"7", "8", "9", "*", "7", "8", "9", "*",
@ -123,14 +122,18 @@ static void calculator_paint(Window *win) {
int bh = 25; int bh = 25;
int gap = 5; int gap = 5;
int start_x = win->x + 10; int start_x = win->x + 10;
int start_y = win->y + 65; int start_y = win->y + 70;
for (int i = 0; i < 20; i++) { for (int i = 0; i < 20; i++) {
int r = i / 4; int r = i / 4;
int c = i % 4; int c = i % 4;
// Special drawing for some buttons? // Draw rounded button backgrounds
draw_button(start_x + c*(bw+gap), start_y + r*(bh+gap), bw, bh, labels[i], false); draw_rounded_rect_filled(start_x + c*(bw+gap), start_y + r*(bh+gap), bw, bh, 4, COLOR_DARK_BORDER);
// Draw button text
int label_x = start_x + c*(bw+gap) + 5;
int label_y = start_y + r*(bh+gap) + 9;
draw_string(label_x, label_y, labels[i], COLOR_DARK_TEXT);
} }
} }

View file

@ -52,7 +52,7 @@ Window win_cmd;
static CharCell screen_buffer[CMD_ROWS][CMD_COLS]; static CharCell screen_buffer[CMD_ROWS][CMD_COLS];
static int cursor_row = 0; static int cursor_row = 0;
static int cursor_col = 0; static int cursor_col = 0;
static uint32_t current_color = COLOR_LTGRAY; static uint32_t current_color = COLOR_DARK_TEXT;
static CmdState *cmd_state = NULL; // Will be set in cmd_init static CmdState *cmd_state = NULL; // Will be set in cmd_init
// Pager State // Pager State
@ -272,7 +272,7 @@ void cmd_screen_clear() {
for(int r=0; r<CMD_ROWS; r++) { for(int r=0; r<CMD_ROWS; r++) {
for(int c=0; c<CMD_COLS; c++) { for(int c=0; c<CMD_COLS; c++) {
screen_buffer[r][c].c = ' '; screen_buffer[r][c].c = ' ';
screen_buffer[r][c].color = COLOR_LTGRAY; screen_buffer[r][c].color = COLOR_DARK_TEXT;
} }
} }
cursor_row = 0; cursor_row = 0;
@ -1297,8 +1297,8 @@ static void cmd_paint(Window *win) {
int offset_x = win->x + 4; int offset_x = win->x + 4;
int offset_y = win->y + 24; int offset_y = win->y + 24;
// Fill background // Fill background - dark mode terminal
draw_rect(win->x + 4, win->y + 24, win->w - 8, win->h - 28, COLOR_BLACK); draw_rect(win->x + 4, win->y + 30, win->w - 8, win->h - 34, COLOR_DARK_BG);
int start_y = offset_y + 4; int start_y = offset_y + 4;
int start_x = offset_x + 4; int start_x = offset_x + 4;
@ -1306,11 +1306,11 @@ static void cmd_paint(Window *win) {
if (current_mode == MODE_PAGER) { if (current_mode == MODE_PAGER) {
// Draw Pager Content (Wrapped) // Draw Pager Content (Wrapped)
for (int i = 0; i < CMD_ROWS && (pager_top_line + i) < pager_total_lines; i++) { for (int i = 0; i < CMD_ROWS && (pager_top_line + i) < pager_total_lines; i++) {
draw_string(start_x, start_y + (i * LINE_HEIGHT), pager_wrapped_lines[pager_top_line + i], COLOR_LTGRAY); draw_string(start_x, start_y + (i * LINE_HEIGHT), pager_wrapped_lines[pager_top_line + i], COLOR_DARK_TEXT);
} }
// Status Bar // Status Bar
draw_string(start_x, start_y + (CMD_ROWS * LINE_HEIGHT), "-- Press Q to quit --", COLOR_WHITE); draw_string(start_x, start_y + (CMD_ROWS * LINE_HEIGHT), "-- Press Q to quit --", COLOR_DARK_TEXT);
} else { } else {
// Draw Shell Buffer // Draw Shell Buffer

View file

@ -152,81 +152,54 @@ static void control_panel_paint_main(Window *win) {
int offset_x = win->x + 8; int offset_x = win->x + 8;
int offset_y = win->y + 30; int offset_y = win->y + 30;
// Draw wallpaper painting icon // Background
// Frame draw_rect(win->x, win->y + 30, win->w, win->h - 30, COLOR_DARK_BG);
draw_rect(offset_x + 5, offset_y + 2, 28, 20, 0xFF8B4513); // Brown frame
draw_rect(offset_x + 6, offset_y + 3, 26, 18, 0xFFFFFFFF); // White canvas
// Paint strokes (simple landscape) // Draw settings items with rounded boxes
draw_rect(offset_x + 8, offset_y + 5, 22, 7, 0xFF87CEEB); // Sky blue int item_y = 30 + 15;
draw_rect(offset_x + 8, offset_y + 12, 22, 5, 0xFF90EE90); // Light green grass int item_h = 60;
draw_rect(offset_x + 15, offset_y + 8, 3, 4, 0xFF8B4513); // Tree trunk int item_spacing = 10;
draw_rect(offset_x + 13, offset_y + 5, 7, 4, 0xFF228B22); // Tree leaves
draw_rect(offset_x + 24, offset_y + 6, 4, 3, 0xFFFFFF00); // Sun
draw_string(offset_x + 40, offset_y + 8, "Wallpaper", 0xFF000000); // Wallpaper Settings
draw_rounded_rect_filled(offset_x, offset_y + item_y, win->w - 16, item_h, 8, COLOR_DARK_PANEL);
// Wallpaper icon: landscape
draw_rect(offset_x + 12, offset_y + item_y + 8, 40, 40, 0xFF87CEEB); // Sky
draw_rect(offset_x + 12, offset_y + item_y + 28, 40, 20, 0xFF90EE90); // Grass
draw_rect(offset_x + 24, offset_y + item_y + 22, 3, 6, 0xFF654321); // Tree trunk
draw_rect(offset_x + 21, offset_y + item_y + 18, 9, 8, 0xFF228B22); // Tree leaves
draw_string(offset_x + 60, offset_y + item_y + 15, "Wallpaper", COLOR_DARK_TEXT);
draw_string(offset_x + 60, offset_y + item_y + 35, "Choose background design", COLOR_DKGRAY);
// Draw network globe icon // Network Settings
int net_offset_y = offset_y + 35; item_y += item_h + item_spacing;
draw_rounded_rect_filled(offset_x, offset_y + item_y, win->w - 16, item_h, 8, COLOR_DARK_PANEL);
// Network icon
draw_rect(offset_x + 18, offset_y + item_y + 12, 24, 24, 0xFF4169E1);
draw_rect(offset_x + 22, offset_y + item_y + 16, 16, 16, 0xFF87CEEB);
draw_string(offset_x + 60, offset_y + item_y + 15, "Network", COLOR_DARK_TEXT);
draw_string(offset_x + 60, offset_y + item_y + 35, "Internet and connectivity", COLOR_DKGRAY);
// Globe circle (approximate with rectangles for filled circle) // Desktop Settings
uint32_t globe_color = 0xFF4169E1; // Royal blue item_y += item_h + item_spacing;
if (offset_y + item_y + item_h < win->y + win->h) {
draw_rounded_rect_filled(offset_x, offset_y + item_y, win->w - 16, item_h, 8, COLOR_DARK_PANEL);
// Desktop icon: folder
draw_rect(offset_x + 12, offset_y + item_y + 10, 36, 8, 0xFFE0C060);
draw_rect(offset_x + 12, offset_y + item_y + 18, 36, 22, 0xFFD4A574);
draw_string(offset_x + 60, offset_y + item_y + 15, "Desktop", COLOR_DARK_TEXT);
draw_string(offset_x + 60, offset_y + item_y + 35, "Desktop appearance&icons", COLOR_DKGRAY);
}
// Draw filled circle using rectangles (simplified) // Mouse Settings
draw_rect(offset_x + 11, net_offset_y + 3, 12, 1, globe_color); item_y += item_h + item_spacing;
draw_rect(offset_x + 9, net_offset_y + 4, 16, 1, globe_color); if (offset_y + item_y + item_h < win->y + win->h) {
draw_rect(offset_x + 8, net_offset_y + 5, 18, 1, globe_color); draw_rounded_rect_filled(offset_x, offset_y + item_y, win->w - 16, item_h, 8, COLOR_DARK_PANEL);
draw_rect(offset_x + 7, net_offset_y + 6, 20, 1, globe_color); // Mouse icon
draw_rect(offset_x + 6, net_offset_y + 7, 22, 1, globe_color); draw_rect(offset_x + 18, offset_y + item_y + 8, 20, 28, 0xFFD3D3D3);
draw_rect(offset_x + 6, net_offset_y + 8, 22, 1, globe_color); draw_rect(offset_x + 20, offset_y + item_y + 10, 16, 10, 0xFFB0B0B0);
draw_rect(offset_x + 6, net_offset_y + 9, 22, 1, globe_color); draw_string(offset_x + 60, offset_y + item_y + 15, "Mouse", COLOR_DARK_TEXT);
draw_rect(offset_x + 6, net_offset_y + 10, 22, 1, globe_color); draw_string(offset_x + 60, offset_y + item_y + 35, "Pointer and trackpad", COLOR_DKGRAY);
draw_rect(offset_x + 6, net_offset_y + 11, 22, 1, globe_color); }
draw_rect(offset_x + 6, net_offset_y + 12, 22, 1, globe_color);
draw_rect(offset_x + 6, net_offset_y + 13, 22, 1, globe_color);
draw_rect(offset_x + 7, net_offset_y + 14, 20, 1, globe_color);
draw_rect(offset_x + 8, net_offset_y + 15, 18, 1, globe_color);
draw_rect(offset_x + 9, net_offset_y + 16, 16, 1, globe_color);
draw_rect(offset_x + 11, net_offset_y + 17, 12, 1, globe_color);
// Latitude lines (white)
draw_rect(offset_x + 7, net_offset_y + 8, 20, 1, 0xFFFFFFFF);
draw_rect(offset_x + 7, net_offset_y + 12, 20, 1, 0xFFFFFFFF);
// Longitude line (vertical, white)
draw_rect(offset_x + 17, net_offset_y + 6, 1, 9, 0xFFFFFFFF);
// Curved longitude lines
draw_rect(offset_x + 11, net_offset_y + 5, 1, 11, 0xFFFFFFFF);
draw_rect(offset_x + 23, net_offset_y + 5, 1, 11, 0xFFFFFFFF);
draw_string(offset_x + 40, net_offset_y + 8, "Network", 0xFF000000);
// Draw Desktop Settings Icon
int desk_offset_y = net_offset_y + 35;
// Folder icon style
draw_rect(offset_x + 5, desk_offset_y + 2, 12, 4, COLOR_LTGRAY);
draw_rect(offset_x + 5, desk_offset_y + 2, 12, 1, COLOR_BLACK);
draw_rect(offset_x + 5, desk_offset_y + 6, 24, 14, 0xFFE0C060); // Tan folder
draw_rect(offset_x + 5, desk_offset_y + 6, 24, 1, COLOR_BLACK);
draw_rect(offset_x + 5, desk_offset_y + 6, 1, 14, COLOR_BLACK);
draw_string(offset_x + 40, desk_offset_y + 8, "Desktop", 0xFF000000);
// Draw Mouse Icon
int mouse_offset_y = desk_offset_y + 35;
// Mouse body
draw_rect(offset_x + 17, mouse_offset_y, 1, 2, COLOR_BLACK);
draw_rect(offset_x + 16, mouse_offset_y - 2, 1, 2, COLOR_BLACK);
draw_rect(offset_x + 10, mouse_offset_y + 2, 15, 20, MOUSE_BEIGE);
draw_rect(offset_x + 10, mouse_offset_y + 2, 15, 1, COLOR_BLACK);
draw_rect(offset_x + 10, mouse_offset_y + 2, 1, 20, COLOR_BLACK);
draw_rect(offset_x + 24, mouse_offset_y + 2, 1, 20, COLOR_BLACK);
draw_rect(offset_x + 10, mouse_offset_y + 21, 15, 1, COLOR_BLACK);
// Buttons separator
draw_rect(offset_x + 10, mouse_offset_y + 8, 15, 1, COLOR_BLACK);
draw_rect(offset_x + 17, mouse_offset_y + 2, 1, 6, COLOR_BLACK);
draw_string(offset_x + 40, mouse_offset_y + 8, "Mouse", 0xFF000000);
} }
static void control_panel_paint_wallpaper(Window *win) { static void control_panel_paint_wallpaper(Window *win) {
@ -532,32 +505,37 @@ static void control_panel_handle_click(Window *win, int x, int y) {
int offset_x = 8; int offset_x = 8;
int offset_y = 30; int offset_y = 30;
// Check wallpaper button click (icon + text) // Settings items layout: each item is 60px tall with 10px spacing
if (x >= offset_x + 5 && x < offset_x + 120 && int item_h = 60;
y >= offset_y && y < offset_y + 25) { int item_spacing = 10;
// Check wallpaper button click (entire card area)
int item_y = offset_y + 15;
if (x >= offset_x && x < win->w - 8 &&
y >= item_y && y < item_y + item_h) {
current_view = VIEW_WALLPAPER; current_view = VIEW_WALLPAPER;
focused_field = -1; focused_field = -1;
} }
// Check network button click (icon + text) // Check network button click
int net_offset_y = offset_y + 35; item_y += item_h + item_spacing;
if (x >= offset_x + 5 && x < offset_x + 120 && if (x >= offset_x && x < win->w - 8 &&
y >= net_offset_y && y < net_offset_y + 25) { y >= item_y && y < item_y + item_h) {
current_view = VIEW_NETWORK; current_view = VIEW_NETWORK;
focused_field = -1; focused_field = -1;
} }
// Check desktop button // Check desktop button
int desk_offset_y = net_offset_y + 35; item_y += item_h + item_spacing;
if (x >= offset_x + 5 && x < offset_x + 120 && if (x >= offset_x && x < win->w - 8 &&
y >= desk_offset_y && y < desk_offset_y + 25) { y >= item_y && y < item_y + item_h) {
current_view = VIEW_DESKTOP; current_view = VIEW_DESKTOP;
} }
// Check mouse button // Check mouse button
int mouse_offset_y = desk_offset_y + 35; item_y += item_h + item_spacing;
if (x >= offset_x + 5 && x < offset_x + 120 && if (x >= offset_x && x < win->w - 8 &&
y >= mouse_offset_y && y < mouse_offset_y + 25) { y >= item_y && y < item_y + item_h) {
current_view = VIEW_MOUSE; current_view = VIEW_MOUSE;
} }
} else if (current_view == VIEW_WALLPAPER) { } else if (current_view == VIEW_WALLPAPER) {
@ -1027,7 +1005,7 @@ static void control_panel_handle_key(Window *win, char c) {
} }
void control_panel_init(void) { void control_panel_init(void) {
win_control_panel.title = "Control Panel"; win_control_panel.title = "Settings";
win_control_panel.x = 200; win_control_panel.x = 200;
win_control_panel.y = 150; win_control_panel.y = 150;
win_control_panel.w = 350; win_control_panel.w = 350;

View file

@ -252,8 +252,8 @@ static void editor_paint(Window *win) {
// Draw filename and save button area at top of content // Draw filename and save button area at top of content
draw_rect(offset_x, offset_y, content_width, 25, COLOR_GRAY); draw_rect(offset_x, offset_y, content_width, 25, COLOR_GRAY);
draw_string(offset_x + 10, offset_y + 5, "File", COLOR_BLACK); draw_string(offset_x + 10, offset_y + 5, "File", COLOR_DARK_TEXT);
draw_string(offset_x + 55, offset_y + 5, open_filename, COLOR_BLACK); draw_string(offset_x + 55, offset_y + 5, open_filename, COLOR_DARK_TEXT);
// Draw save button // Draw save button
draw_button(offset_x + content_width - 80, offset_y + 3, 70, 20, "Save", false); draw_button(offset_x + content_width - 80, offset_y + 3, 70, 20, "Save", false);
@ -263,8 +263,8 @@ static void editor_paint(Window *win) {
draw_string(offset_x + content_width - 200, offset_y + 5, "[Modified]", COLOR_RED); draw_string(offset_x + content_width - 200, offset_y + 5, "[Modified]", COLOR_RED);
} }
// Fill editor background // Fill editor background - dark mode
draw_rect(win->x + 4, win->y + 54, win->w - 8, win->h - 58, COLOR_WHITE); draw_rect(win->x + 4, win->y + 54, win->w - 8, win->h - 58, COLOR_DARK_BG);
// Calculate available width for text (accounting for line numbers) // Calculate available width for text (accounting for line numbers)
int text_start_x = offset_x + 40; int text_start_x = offset_x + 40;
@ -350,7 +350,7 @@ static void editor_paint(Window *win) {
// Draw the text segment // Draw the text segment
if (segment_len > 0) { if (segment_len > 0) {
draw_string(text_start_x, current_display_y, segment, COLOR_BLACK); draw_string(text_start_x, current_display_y, segment, COLOR_DARK_TEXT);
} }
// Draw cursor if on this line and wrapped segment // Draw cursor if on this line and wrapped segment
@ -379,7 +379,7 @@ static void editor_paint(Window *win) {
// Draw status bar at bottom // Draw status bar at bottom
draw_rect(offset_x, offset_y + content_height - 20, content_width, 20, COLOR_GRAY); draw_rect(offset_x, offset_y + content_height - 20, content_width, 20, COLOR_GRAY);
draw_string(offset_x + 10, offset_y + content_height - 15, "Line: ", COLOR_WHITE); draw_string(offset_x + 10, offset_y + content_height - 15, "Line: ", COLOR_DARK_TEXT);
char line_str[32]; char line_str[32];
int temp = cursor_line + 1; int temp = cursor_line + 1;
@ -395,8 +395,8 @@ static void editor_paint(Window *win) {
} }
line_str[idx] = 0; line_str[idx] = 0;
draw_string(offset_x + 60, offset_y + content_height - 15, line_str, COLOR_WHITE); draw_string(offset_x + 60, offset_y + content_height - 15, line_str, COLOR_DARK_TEXT);
draw_string(offset_x + 100, offset_y + content_height - 15, " Col: ", COLOR_WHITE); draw_string(offset_x + 100, offset_y + content_height - 15, " Col: ", COLOR_DARK_TEXT);
char col_str[32]; char col_str[32];
temp = cursor_col + 1; temp = cursor_col + 1;
@ -412,7 +412,7 @@ static void editor_paint(Window *win) {
} }
col_str[idx] = 0; col_str[idx] = 0;
draw_string(offset_x + 170, offset_y + content_height - 15, col_str, COLOR_WHITE); draw_string(offset_x + 170, offset_y + content_height - 15, col_str, COLOR_DARK_TEXT);
} }
// === Key Handler === // === Key Handler ===

View file

@ -215,8 +215,8 @@ static bool check_desktop_limit_explorer(Window *win) {
ExplorerState *state = (ExplorerState*)win->data; ExplorerState *state = (ExplorerState*)win->data;
if (explorer_str_starts_with(state->current_path, "/Desktop")) { if (explorer_str_starts_with(state->current_path, "/Desktop")) {
// Check if root desktop // Check if root desktop
if (explorer_strcmp(state->current_path, "/Desktop") == 0 || explorer_strcmp(state->current_path, "/Desktop/") == 0) { if (explorer_strcmp(state->current_path, "/Desktop") == 0 || explorer_strcmp(state->current_path, "/Desktop/") == 0) { // Check if root desktop
if (state->item_count >= desktop_max_cols * desktop_max_rows_per_col) { if (state->item_count >= desktop_max_cols * (desktop_max_rows_per_col > 1 ? desktop_max_rows_per_col - 1 : 0)) {
state->dialog_state = DIALOG_ERROR; state->dialog_state = DIALOG_ERROR;
explorer_strcpy(state->dialog_input, "Desktop is full!"); explorer_strcpy(state->dialog_input, "Desktop is full!");
return false; return false;
@ -951,10 +951,10 @@ static void explorer_paint(Window *win) {
int offset_y = win->y + 24; int offset_y = win->y + 24;
DirtyRect dirty = graphics_get_dirty_rect(); DirtyRect dirty = graphics_get_dirty_rect();
// Fill background // Fill background with dark mode
draw_rect(offset_x, offset_y, win->w - 8, win->h - 28, COLOR_LTGRAY); draw_rect(offset_x, offset_y, win->w - 8, win->h - 28, COLOR_DARK_BG);
// Draw Drive Button // Draw Drive Button (modern rounded style)
char drive_label[8]; char drive_label[8];
// Extract drive from the window's current_path instead of using global current_drive // Extract drive from the window's current_path instead of using global current_drive
char current_drv = 'A'; char current_drv = 'A';
@ -973,28 +973,32 @@ static void explorer_paint(Window *win) {
drive_label[6] = ' '; drive_label[6] = ' ';
drive_label[7] = ']'; drive_label[7] = ']';
// Button at x+4, y+4, w=60 // Button at x+4, y+4, w=60 (rounded)
draw_button(win->x + 4, offset_y + 4, 60, 30, "", false); draw_rounded_rect_filled(win->x + 4, offset_y + 4, 60, 30, 6, COLOR_DARK_PANEL);
draw_string(win->x + 12, offset_y + 12, drive_label, COLOR_BLACK); draw_string(win->x + 12, offset_y + 12, drive_label, COLOR_DARK_TEXT);
// Draw path bar (shifted right) // Draw path bar (shifted right, rounded, dark mode)
int path_height = 30; int path_height = 30;
int path_x = offset_x + 64; int path_x = offset_x + 64;
int path_w = win->w - 16 - 64; int path_w = win->w - 16 - 64;
draw_bevel_rect(path_x, offset_y + 4, path_w, path_height, true); draw_rounded_rect_filled(path_x, offset_y + 4, path_w, path_height, 6, COLOR_DARK_PANEL);
draw_string(path_x + 6, offset_y + 10, "Path", COLOR_BLACK); draw_string(path_x + 6, offset_y + 10, "Path", COLOR_DARK_TEXT);
draw_string(path_x + 46, offset_y + 10, state->current_path, COLOR_BLACK); draw_string(path_x + 46, offset_y + 10, state->current_path, COLOR_DARK_TEXT);
// Draw dropdown menu button (right-aligned, before back button) // Draw dropdown menu button (right-aligned, before back button, rounded)
int dropdown_btn_x = win->x + win->w - 90; int dropdown_btn_x = win->x + win->w - 90;
draw_button(dropdown_btn_x, offset_y + 4, 35, 30, "...", false); draw_rounded_rect_filled(dropdown_btn_x, offset_y + 4, 35, 30, 6, COLOR_DARK_PANEL);
draw_string(dropdown_btn_x + 10, offset_y + 10, "...", COLOR_DARK_TEXT);
// Draw back button (right-aligned) // Draw back button (right-aligned, rounded)
draw_button(win->x + win->w - 40, offset_y + 4, 30, 30, "<", false); draw_rounded_rect_filled(win->x + win->w - 40, offset_y + 4, 30, 30, 6, COLOR_DARK_PANEL);
draw_string(win->x + win->w - 32, offset_y + 10, "<", COLOR_DARK_TEXT);
// Draw scroll buttons (left of dropdown) // Draw scroll buttons (left of dropdown, rounded)
draw_button(win->x + win->w - 160, offset_y + 4, 30, 30, "^", false); draw_rounded_rect_filled(win->x + win->w - 160, offset_y + 4, 30, 30, 6, COLOR_DARK_PANEL);
draw_button(win->x + win->w - 125, offset_y + 4, 30, 30, "v", false); draw_string(win->x + win->w - 150, offset_y + 10, "^", COLOR_DARK_TEXT);
draw_rounded_rect_filled(win->x + win->w - 125, offset_y + 4, 30, 30, 6, COLOR_DARK_PANEL);
draw_string(win->x + win->w - 115, offset_y + 10, "v", COLOR_DARK_TEXT);
// Draw file list // Draw file list
int content_start_y = offset_y + 40; int content_start_y = offset_y + 40;
@ -1013,10 +1017,10 @@ static void explorer_paint(Window *win) {
int item_x = offset_x + 10 + (col * (EXPLORER_ITEM_WIDTH + EXPLORER_PADDING)); int item_x = offset_x + 10 + (col * (EXPLORER_ITEM_WIDTH + EXPLORER_PADDING));
int item_y = content_start_y + ((row - state->explorer_scroll_row) * (EXPLORER_ITEM_HEIGHT + EXPLORER_PADDING)); int item_y = content_start_y + ((row - state->explorer_scroll_row) * (EXPLORER_ITEM_HEIGHT + EXPLORER_PADDING));
// Draw item background // Draw item background (dark mode with rounded corners)
uint32_t bg_color = (i == state->selected_item) ? COLOR_BLUE : COLOR_WHITE; uint32_t bg_color = (i == state->selected_item) ? 0xFF4A90E2 : COLOR_DARK_PANEL;
draw_bevel_rect(item_x, item_y, EXPLORER_ITEM_WIDTH, EXPLORER_ITEM_HEIGHT, false); uint32_t text_color = (i == state->selected_item) ? COLOR_WHITE : COLOR_DARK_TEXT;
draw_rect(item_x + 2, item_y + 2, EXPLORER_ITEM_WIDTH - 4, EXPLORER_ITEM_HEIGHT - 4, bg_color); draw_rounded_rect_filled(item_x, item_y, EXPLORER_ITEM_WIDTH, EXPLORER_ITEM_HEIGHT, 6, bg_color);
// Draw icon (larger area) // Draw icon (larger area)
explorer_draw_file_icon(item_x + 5, item_y + 5, state->items[i].is_directory, state->items[i].color, state->items[i].name); explorer_draw_file_icon(item_x + 5, item_y + 5, state->items[i].is_directory, state->items[i].color, state->items[i].name);
@ -1026,7 +1030,7 @@ static void explorer_paint(Window *win) {
if (explorer_strcmp(state->items[i].name, "RecycleBin") == 0) { if (explorer_strcmp(state->items[i].name, "RecycleBin") == 0) {
display_name = "Recycle Bin"; display_name = "Recycle Bin";
} }
explorer_draw_icon_label(item_x, item_y, display_name, (i == state->selected_item) ? COLOR_WHITE : COLOR_BLACK); explorer_draw_icon_label(item_x, item_y, display_name, text_color);
} }
// Restore dirty-rect clipping instead of clearing it entirely. // Restore dirty-rect clipping instead of clearing it entirely.
@ -1037,7 +1041,7 @@ static void explorer_paint(Window *win) {
graphics_clear_clipping(); graphics_clear_clipping();
} }
// Draw Drive Menu if visible // Draw Drive Menu if visible (dark mode)
if (state->drive_menu_visible) { if (state->drive_menu_visible) {
int menu_x = win->x + 4; int menu_x = win->x + 4;
int menu_y = offset_y + 34; int menu_y = offset_y + 34;
@ -1045,8 +1049,7 @@ static void explorer_paint(Window *win) {
int count = disk_get_count(); int count = disk_get_count();
int menu_h = count * 25; int menu_h = count * 25;
draw_rect(menu_x, menu_y, menu_w, menu_h, COLOR_LTGRAY); draw_rounded_rect_filled(menu_x, menu_y, menu_w, menu_h, 6, COLOR_DARK_PANEL);
draw_bevel_rect(menu_x, menu_y, menu_w, menu_h, true);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
Disk *d = disk_get_by_index(i); Disk *d = disk_get_by_index(i);
@ -1059,9 +1062,9 @@ static void explorer_paint(Window *win) {
int n = 0; while(d->name[n] && n < 10) { buf[3+n] = d->name[n]; n++; } int n = 0; while(d->name[n] && n < 10) { buf[3+n] = d->name[n]; n++; }
buf[3+n] = 0; buf[3+n] = 0;
// Highlight current // Highlight current (dark blue)
if (d->letter == current_drv) { if (d->letter == current_drv) {
draw_rect(menu_x + 2, menu_y + i*25 + 2, menu_w - 4, 21, COLOR_BLUE); draw_rounded_rect_filled(menu_x + 2, menu_y + i*25 + 2, menu_w - 4, 21, 4, 0xFF4A90E2);
draw_string(menu_x + 5, menu_y + i*25 + 6, buf, COLOR_WHITE); draw_string(menu_x + 5, menu_y + i*25 + 6, buf, COLOR_WHITE);
} else { } else {
draw_string(menu_x + 5, menu_y + i*25 + 6, buf, COLOR_BLACK); draw_string(menu_x + 5, menu_y + i*25 + 6, buf, COLOR_BLACK);
@ -1981,7 +1984,7 @@ Window* explorer_create_window(const char *path) {
Window *win = (Window*)kmalloc(sizeof(Window)); Window *win = (Window*)kmalloc(sizeof(Window));
ExplorerState *state = (ExplorerState*)kmalloc(sizeof(ExplorerState)); ExplorerState *state = (ExplorerState*)kmalloc(sizeof(ExplorerState));
win->title = "File Explorer"; win->title = "Files";
win->x = 300 + (explorer_win_count * 30); win->x = 300 + (explorer_win_count * 30);
win->y = 100 + (explorer_win_count * 30); win->y = 100 + (explorer_win_count * 30);
win->w = 600; win->w = 600;
@ -2014,7 +2017,7 @@ Window* explorer_create_window(const char *path) {
void explorer_init(void) { void explorer_init(void) {
ExplorerState *state = (ExplorerState*)kmalloc(sizeof(ExplorerState)); ExplorerState *state = (ExplorerState*)kmalloc(sizeof(ExplorerState));
win_explorer.title = "File Explorer"; win_explorer.title = "Files";
win_explorer.x = 300; win_explorer.x = 300;
win_explorer.y = 100; win_explorer.y = 100;
win_explorer.w = 600; win_explorer.w = 600;

View file

@ -161,6 +161,81 @@ void draw_rect(int x, int y, int w, int h, uint32_t color) {
} }
} }
// Simple integer-based square root approximation
static int isqrt(int n) {
if (n < 0) return 0;
if (n == 0) return 0;
int x = n;
int y = (x + 1) / 2;
while (y < x) {
x = y;
y = (x + n / x) / 2;
}
return x;
}
// Draw rounded rectangle outline
void draw_rounded_rect(int x, int y, int w, int h, int radius, uint32_t color) {
if (radius > w / 2) radius = w / 2;
if (radius > h / 2) radius = h / 2;
if (radius < 1) radius = 1;
// Draw top and bottom edges
draw_rect(x + radius, y, w - 2*radius, 1, color);
draw_rect(x + radius, y + h - 1, w - 2*radius, 1, color);
// Draw left and right edges
draw_rect(x, y + radius, 1, h - 2*radius, color);
draw_rect(x + w - 1, y + radius, 1, h - 2*radius, color);
// Draw corner circles using integer approximation
for (int i = 0; i < radius; i++) {
int j = isqrt(radius*radius - i*i);
// Top-left corner
put_pixel(x + radius - i - 1, y + radius - j, color);
// Top-right corner
put_pixel(x + w - radius + i, y + radius - j, color);
// Bottom-left corner
put_pixel(x + radius - i - 1, y + h - radius + j - 1, color);
// Bottom-right corner
put_pixel(x + w - radius + i, y + h - radius + j - 1, color);
}
}
// Draw filled rounded rectangle
void draw_rounded_rect_filled(int x, int y, int w, int h, int radius, uint32_t color) {
if (radius > w / 2) radius = w / 2;
if (radius > h / 2) radius = h / 2;
if (radius < 1) radius = 1;
// Draw main rectangle body (center part without corners)
draw_rect(x + radius, y, w - 2*radius, h, color);
draw_rect(x, y + radius, radius, h - 2*radius, color);
draw_rect(x + w - radius, y + radius, radius, h - 2*radius, color);
// Draw rounded corners using scanline approach (fills gaps properly)
for (int dy = 0; dy < radius; dy++) {
// For top corners: distance formula inverted (narrow at top, wide at junction)
int dx_top = isqrt(radius*radius - (radius - dy) * (radius - dy));
// For bottom corners: distance formula normal (wide at junction, narrow at bottom)
int dx_bottom = isqrt(radius*radius - dy*dy);
// Top-left corner - horizontal scanline
draw_rect(x + radius - dx_top, y + dy, dx_top, 1, color);
// Top-right corner - horizontal scanline
draw_rect(x + w - radius, y + dy, dx_top, 1, color);
// Bottom-left corner - horizontal scanline
draw_rect(x + radius - dx_bottom, y + h - radius + dy, dx_bottom, 1, color);
// Bottom-right corner - horizontal scanline
draw_rect(x + w - radius, y + h - radius + dy, dx_bottom, 1, color);
}
}
void draw_char(int x, int y, char c, uint32_t color) { void draw_char(int x, int y, char c, uint32_t color) {
unsigned char uc = (unsigned char)c; unsigned char uc = (unsigned char)c;
if (uc > 127) return; if (uc > 127) return;

View file

@ -14,6 +14,8 @@ typedef struct {
void graphics_init(struct limine_framebuffer *fb); void graphics_init(struct limine_framebuffer *fb);
void put_pixel(int x, int y, uint32_t color); void put_pixel(int x, int y, uint32_t color);
void draw_rect(int x, int y, int w, int h, uint32_t color); void draw_rect(int x, int y, int w, int h, uint32_t color);
void draw_rounded_rect(int x, int y, int w, int h, int radius, uint32_t color);
void draw_rounded_rect_filled(int x, int y, int w, int h, int radius, uint32_t color);
void draw_char(int x, int y, char c, uint32_t color); void draw_char(int x, int y, char c, uint32_t color);
void draw_string(int x, int y, const char *s, uint32_t color); void draw_string(int x, int y, const char *s, uint32_t color);
void draw_desktop_background(void); void draw_desktop_background(void);

View file

@ -288,16 +288,18 @@ static void md_paint(Window *win) {
int content_width = win->w - 8; int content_width = win->w - 8;
int content_height = win->h - 28; int content_height = win->h - 28;
// Draw filename bar below title // Draw filename bar below title (dark mode)
draw_rect(offset_x, offset_y, content_width, 20, COLOR_GRAY); draw_rounded_rect_filled(offset_x, offset_y, content_width, 20, 6, COLOR_DARK_PANEL);
draw_string(offset_x + 4, offset_y + 4, "File", COLOR_BLACK); draw_string(offset_x + 4, offset_y + 4, "File", COLOR_DARK_TEXT);
draw_string(offset_x + 50, offset_y + 4, open_filename, COLOR_BLACK); draw_string(offset_x + 50, offset_y + 4, open_filename, COLOR_DARK_TEXT);
// Draw scroll buttons on top right // Draw scroll buttons on top right with rounded style
int btn_x_up = offset_x + content_width - 50; int btn_x_up = offset_x + content_width - 50;
int btn_y = offset_y + 2; int btn_y = offset_y + 2;
draw_button(btn_x_up, btn_y, 20, 16, "^", false); draw_rounded_rect_filled(btn_x_up, btn_y, 20, 16, 4, COLOR_DARK_TITLEBAR);
draw_button(btn_x_up + 24, btn_y, 20, 16, "v", false); draw_string(btn_x_up + 6, btn_y, "^", COLOR_DARK_TEXT);
draw_rounded_rect_filled(btn_x_up + 24, btn_y, 20, 16, 4, COLOR_DARK_TITLEBAR);
draw_string(btn_x_up + 30, btn_y, "v", COLOR_DARK_TEXT);
// Content area - starts below filename bar // Content area - starts below filename bar
int content_start_y = offset_y + 24; int content_start_y = offset_y + 24;
@ -306,8 +308,8 @@ static void md_paint(Window *win) {
int usable_content_height = content_height - 28; int usable_content_height = content_height - 28;
int max_display_lines = usable_content_height / MD_LINE_HEIGHT; int max_display_lines = usable_content_height / MD_LINE_HEIGHT;
// Draw content background // Draw content background (dark mode)
draw_rect(win->x + 4, content_start_y, win->w - 24, usable_content_height, COLOR_WHITE); draw_rounded_rect_filled(win->x + 4, content_start_y, win->w - 24, usable_content_height, 6, COLOR_DARK_BG);
@ -317,38 +319,38 @@ static void md_paint(Window *win) {
while (i < line_count && display_line < max_display_lines) { while (i < line_count && display_line < max_display_lines) {
MDLine *line = &lines[i]; MDLine *line = &lines[i];
// Determine spacing and text properties based on heading level // Determine spacing and text properties based on heading level (dark mode colors)
int line_height = MD_LINE_HEIGHT; int line_height = MD_LINE_HEIGHT;
int extra_spacing = 0; int extra_spacing = 0;
uint32_t text_color = COLOR_BLACK; uint32_t text_color = COLOR_DARK_TEXT;
bool use_bold = false; bool use_bold = false;
switch (line->type) { switch (line->type) {
case MD_LINE_HEADING1: case MD_LINE_HEADING1:
line_height = MD_LINE_HEIGHT * 2; // Double height line_height = MD_LINE_HEIGHT * 2; // Double height
text_color = 0xFF004080; // Dark blue text_color = 0xFF87CEEB; // Light blue
use_bold = true; use_bold = true;
extra_spacing = 4; extra_spacing = 4;
break; break;
case MD_LINE_HEADING2: case MD_LINE_HEADING2:
line_height = MD_LINE_HEIGHT + 6; // 1.5x height line_height = MD_LINE_HEIGHT + 6; // 1.5x height
text_color = 0xFF1060A0; // Medium blue text_color = 0xFF4A90E2; // Medium blue
use_bold = true; use_bold = true;
extra_spacing = 2; extra_spacing = 2;
break; break;
case MD_LINE_HEADING3: case MD_LINE_HEADING3:
line_height = MD_LINE_HEIGHT + 2; // Slightly larger line_height = MD_LINE_HEIGHT + 2; // Slightly larger
text_color = 0xFF2080C0; // Light blue text_color = 0xFF87CEEB; // Light blue
use_bold = false; use_bold = false;
break; break;
case MD_LINE_BLOCKQUOTE: case MD_LINE_BLOCKQUOTE:
text_color = 0xFF808080; // Gray text_color = 0xFFA0A0A0; // Light gray
break; break;
case MD_LINE_CODE: case MD_LINE_CODE:
text_color = COLOR_WHITE; text_color = 0xFF90EE90; // Light green for code
break; break;
default: default:
text_color = COLOR_BLACK; text_color = COLOR_DARK_TEXT;
break; break;
} }

View file

@ -151,21 +151,21 @@ static void minesweeper_right_click(Window *win, int x, int y) {
} }
static void minesweeper_paint(Window *win) { static void minesweeper_paint(Window *win) {
// Background // Background - dark mode
draw_rect(win->x + 4, win->y + 24, win->w - 8, win->h - 28, COLOR_LTGRAY); draw_rect(win->x + 4, win->y + 30, win->w - 8, win->h - 34, COLOR_DARK_BG);
// Game status // Game status
if (game_over) { if (game_over) {
draw_string(win->x + 10, win->y + 30, "Game Over!", COLOR_RED); draw_string(win->x + 10, win->y + 36, "Game Over!", COLOR_TRAFFIC_RED);
} else if (game_won) { } else if (game_won) {
draw_string(win->x + 10, win->y + 30, "You Won!", COLOR_BLUE); draw_string(win->x + 10, win->y + 36, "You Won!", 0xFF00FF00); // Bright green
} else { } else {
draw_string(win->x + 10, win->y + 30, "", COLOR_BLACK); draw_string(win->x + 10, win->y + 36, "", COLOR_DARK_TEXT);
} }
// Draw grid // Draw grid
int grid_start_x = win->x + 10; int grid_start_x = win->x + 10;
int grid_start_y = win->y + 50; int grid_start_y = win->y + 56;
for (int y = 0; y < GRID_HEIGHT; y++) { for (int y = 0; y < GRID_HEIGHT; y++) {
for (int x = 0; x < GRID_WIDTH; x++) { for (int x = 0; x < GRID_WIDTH; x++) {
@ -173,32 +173,33 @@ static void minesweeper_paint(Window *win) {
int py = grid_start_y + y * CELL_SIZE; int py = grid_start_y + y * CELL_SIZE;
if (revealed[y][x]) { if (revealed[y][x]) {
// Revealed cell - sunken // Revealed cell - dark mode
draw_bevel_rect(px, py, CELL_SIZE, CELL_SIZE, true); draw_rounded_rect_filled(px, py, CELL_SIZE, CELL_SIZE, 2, COLOR_DARK_PANEL);
if (grid[y][x] == -1) { if (grid[y][x] == -1) {
// Mine // Mine
draw_string(px + 8, py + 6, "*", COLOR_RED); draw_string(px + 8, py + 6, "*", COLOR_TRAFFIC_RED);
} else if (grid[y][x] > 0) { } else if (grid[y][x] > 0) {
// Number // Number
char num[2] = { '0' + grid[y][x], 0 }; char num[2] = { '0' + grid[y][x], 0 };
draw_string(px + 8, py + 6, num, COLOR_BLACK); draw_string(px + 8, py + 6, num, COLOR_DARK_TEXT);
} }
// 0 = empty, nothing to draw // 0 = empty, nothing to draw
} else { } else {
// Unrevealed cell - raised // Unrevealed cell - raised/button look
draw_bevel_rect(px, py, CELL_SIZE, CELL_SIZE, false); draw_rounded_rect_filled(px, py, CELL_SIZE, CELL_SIZE, 2, COLOR_DARK_BORDER);
if (flagged[y][x]) { if (flagged[y][x]) {
draw_string(px + 7, py + 6, "F", COLOR_RED); draw_string(px + 7, py + 6, "F", COLOR_TRAFFIC_RED);
} }
} }
} }
} }
// Draw new game button // Draw new game button (narrower, less dead space)
int btn_y = grid_start_y + GRID_HEIGHT * CELL_SIZE + 10; int btn_y = grid_start_y + GRID_HEIGHT * CELL_SIZE + 10;
draw_button(grid_start_x, btn_y, 90, 24, "New Game", false); draw_rounded_rect_filled(grid_start_x, btn_y, 70, 24, 4, COLOR_DARK_BORDER);
draw_string(grid_start_x + 6, btn_y + 8, "New Game", COLOR_DARK_TEXT);
} }
static void minesweeper_click(Window *win, int x, int y) { static void minesweeper_click(Window *win, int x, int y) {

View file

@ -24,12 +24,12 @@ static void notepad_ensure_cursor_visible(Window *win) {
} }
static void notepad_paint(Window *win) { static void notepad_paint(Window *win) {
// Explicitly draw white background for text // Dark mode background for text
draw_rect(win->x + 4, win->y + 24, win->w - 8, win->h - 28, COLOR_WHITE); draw_rect(win->x + 4, win->y + 30, win->w - 8, win->h - 34, COLOR_DARK_BG);
int visual_line = 0; int visual_line = 0;
int current_x = win->x + 8; int current_x = win->x + 8;
int current_y = win->y + 30; int current_y = win->y + 36;
int window_right = win->x + win->w - 16; int window_right = win->x + win->w - 16;
for (int i = 0; i < win->buf_len; i++) { for (int i = 0; i < win->buf_len; i++) {
@ -37,7 +37,7 @@ static void notepad_paint(Window *win) {
if (win->buffer[i] == '\n') { if (win->buffer[i] == '\n') {
visual_line++; visual_line++;
current_x = win->x + 8; current_x = win->x + 8;
current_y = win->y + 30; current_y = win->y + 36;
} else { } else {
if (current_x >= window_right) { if (current_x >= window_right) {
visual_line++; visual_line++;
@ -69,7 +69,7 @@ static void notepad_paint(Window *win) {
} }
char ch[2] = {win->buffer[i], 0}; char ch[2] = {win->buffer[i], 0};
draw_string(current_x, current_y, ch, COLOR_BLACK); draw_string(current_x, current_y, ch, COLOR_DARK_TEXT);
current_x += 8; current_x += 8;
} }
} }
@ -77,7 +77,7 @@ static void notepad_paint(Window *win) {
// Cursor // Cursor
if (win->focused) { if (win->focused) {
int cx = win->x + 8; int cx = win->x + 8;
int cy = win->y + 30; int cy = win->y + 36;
int visual_line = 0; int visual_line = 0;
int window_right = win->x + win->w - 16; // Right boundary with padding int window_right = win->x + win->w - 16; // Right boundary with padding
@ -98,7 +98,7 @@ static void notepad_paint(Window *win) {
if (visual_line >= notepad_scroll_line && if (visual_line >= notepad_scroll_line &&
visual_line < notepad_scroll_line + (win->h - 40) / 10) { visual_line < notepad_scroll_line + (win->h - 40) / 10) {
draw_rect(cx, cy, 2, 8, COLOR_BLACK); draw_rect(cx, cy, 2, 8, COLOR_DARK_TEXT);
} }
} }
} }

View file

@ -21,35 +21,32 @@ static void paint_strcpy(char *dest, const char *src) {
} }
static void paint_paint(Window *win) { static void paint_paint(Window *win) {
// Toolbar area // Toolbar area - dark mode
draw_rect(win->x + 10, win->y + 30, 40, win->h - 40, COLOR_GRAY); draw_rounded_rect_filled(win->x + 10, win->y + 30, 40, win->h - 40, 6, COLOR_DARK_PANEL);
draw_bevel_rect(win->x + 10, win->y + 30, 40, win->h - 40, true);
// Color Palette // Color Palette with rounded corners
uint32_t colors[] = {COLOR_BLACK, COLOR_RED, COLOR_APPLE_GREEN, COLOR_APPLE_BLUE, COLOR_APPLE_YELLOW, COLOR_WHITE}; uint32_t colors[] = {COLOR_BLACK, COLOR_RED, COLOR_APPLE_GREEN, COLOR_APPLE_BLUE, COLOR_APPLE_YELLOW, COLOR_WHITE};
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
int cy = win->y + 40 + (i * 25); int cy = win->y + 40 + (i * 25);
draw_rect(win->x + 15, cy, 30, 20, colors[i]); draw_rounded_rect_filled(win->x + 15, cy, 30, 20, 3, colors[i]);
draw_rect(win->x + 15, cy, 30, 1, COLOR_BLACK);
draw_rect(win->x + 15, cy, 1, 20, COLOR_BLACK);
draw_rect(win->x + 44, cy, 1, 20, COLOR_BLACK);
draw_rect(win->x + 15, cy + 19, 30, 1, COLOR_BLACK);
// Highlight selected color // Highlight selected color with border
if (current_color == colors[i]) { if (current_color == colors[i]) {
draw_rect(win->x + 13, cy - 2, 34, 2, COLOR_WHITE); draw_rounded_rect(win->x + 13, cy - 2, 34, 24, 4, COLOR_DARK_TEXT);
draw_rect(win->x + 13, cy + 20, 34, 2, COLOR_WHITE);
} }
} }
// Toolbar Buttons // Toolbar Buttons - dark mode with rounded corners
draw_button(win->x + 12, win->y + win->h - 65, 36, 20, "CLR", false); draw_rounded_rect_filled(win->x + 12, win->y + win->h - 65, 36, 20, 4, COLOR_DARK_BORDER);
draw_button(win->x + 12, win->y + win->h - 40, 36, 20, "SAV", false); draw_string(win->x + 18, win->y + win->h - 58, "CLR", COLOR_DARK_TEXT);
// Canvas Area draw_rounded_rect_filled(win->x + 12, win->y + win->h - 40, 36, 20, 4, COLOR_DARK_BORDER);
draw_string(win->x + 18, win->y + win->h - 33, "SAV", COLOR_DARK_TEXT);
// Canvas Area with dark background and rounded corners
int canvas_x = win->x + 60; int canvas_x = win->x + 60;
int canvas_y = win->y + 30; int canvas_y = win->y + 30;
draw_bevel_rect(canvas_x - 2, canvas_y - 2, CANVAS_W + 4, CANVAS_H + 4, true); draw_rounded_rect_filled(canvas_x - 2, canvas_y - 2, CANVAS_W + 4, CANVAS_H + 4, 4, COLOR_DARK_BG);
if (canvas_buffer) { if (canvas_buffer) {
for (int y = 0; y < CANVAS_H; y++) { for (int y = 0; y < CANVAS_H; y++) {

View file

@ -124,7 +124,7 @@ static int str_eq(const char *s1, const char *s2) {
static void refresh_desktop_icons(void) { static void refresh_desktop_icons(void) {
// Update limit in FS // Update limit in FS
fat32_set_desktop_limit(desktop_max_cols * desktop_max_rows_per_col); fat32_set_desktop_limit(desktop_max_cols * (desktop_max_rows_per_col > 1 ? desktop_max_rows_per_col - 1 : 0));
FAT32_FileInfo *files = (FAT32_FileInfo*)kmalloc(MAX_DESKTOP_ICONS * sizeof(FAT32_FileInfo)); FAT32_FileInfo *files = (FAT32_FileInfo*)kmalloc(MAX_DESKTOP_ICONS * sizeof(FAT32_FileInfo));
if (!files) return; if (!files) return;
@ -184,8 +184,8 @@ static void refresh_desktop_icons(void) {
// 3. Layout Icons // 3. Layout Icons
if (desktop_auto_align) { if (desktop_auto_align) {
int start_x = 20; int start_x = 20; // Starting X position for icons
int start_y = 20; int start_y = 20 + DESKTOP_TOP_DEADSPACE_HEIGHT; // Starting Y position for icons, offset by dead space
int grid_x = 0; int grid_x = 0;
int grid_y = 0; int grid_y = 0;
@ -200,8 +200,8 @@ static void refresh_desktop_icons(void) {
// Place Recycle Bin at bottom-right of grid // Place Recycle Bin at bottom-right of grid
if (recycle_idx != -1) { if (recycle_idx != -1) {
desktop_icons[recycle_idx].x = start_x + (desktop_max_cols - 1) * 80; desktop_icons[recycle_idx].x = start_x + (desktop_max_cols - 1) * 80; // Align to the last column
desktop_icons[recycle_idx].y = start_y + (desktop_max_rows_per_col - 1) * 80; desktop_icons[recycle_idx].y = start_y + (desktop_max_rows_per_col - 2) * 80; // Align to the second to last row (since one is dead space)
} }
for (int i = 0; i < desktop_icon_count; i++) { for (int i = 0; i < desktop_icon_count; i++) {
@ -210,7 +210,7 @@ static void refresh_desktop_icons(void) {
desktop_icons[i].x = start_x + (grid_x * 80); desktop_icons[i].x = start_x + (grid_x * 80);
desktop_icons[i].y = start_y + (grid_y * 80); desktop_icons[i].y = start_y + (grid_y * 80);
grid_y++; grid_y++; // Increment grid_y for the next icon
if (grid_y >= desktop_max_rows_per_col) { if (grid_y >= desktop_max_rows_per_col) {
grid_y = 0; grid_y = 0;
grid_x++; grid_x++;
@ -224,7 +224,7 @@ static void refresh_desktop_icons(void) {
if (desktop_icons[i].x != -1) { if (desktop_icons[i].x != -1) {
int col = (desktop_icons[i].x - 20) / 80; int col = (desktop_icons[i].x - 20) / 80;
int row = (desktop_icons[i].y - 20) / 80; int row = (desktop_icons[i].y - 20) / 80;
if (col >= 0 && col < 16 && row >= 0 && row < 16) occupied[col][row] = true; if (col >= 0 && col < 16 && row >= 0 && row < 16) occupied[col][row] = true; // Mark occupied cells
} }
} }
@ -233,13 +233,13 @@ static void refresh_desktop_icons(void) {
int found_col = -1, found_row = -1; int found_col = -1, found_row = -1;
for (int c = 0; c < 16; c++) { for (int c = 0; c < 16; c++) {
for (int r = 0; r < desktop_max_rows_per_col; r++) { for (int r = 0; r < desktop_max_rows_per_col; r++) {
if (!occupied[c][r]) { if (!occupied[c][r] && r > 0) { // Ensure not in the dead space row
found_col = c; found_row = r; found_col = c; found_row = r;
goto found; goto found;
} }
} }
} }
found: found:
if (found_col != -1) { if (found_col != -1) {
desktop_icons[i].x = 20 + found_col * 80; desktop_icons[i].x = 20 + found_col * 80;
desktop_icons[i].y = 20 + found_row * 80; desktop_icons[i].y = 20 + found_row * 80;
@ -563,22 +563,62 @@ void draw_paint_icon(int x, int y, const char *label) {
draw_icon_label(x, y, label); draw_icon_label(x, y, label);
} }
// New macOS-style drawing functions
// Draw traffic light (close button - red)
void draw_traffic_light(int x, int y) {
// Red close button
draw_rounded_rect_filled(x, y, 12, 12, 3, COLOR_TRAFFIC_RED);
// X mark
draw_rect(x + 4, y + 4, 1, 4, COLOR_WHITE); // Vertical
draw_rect(x + 5, y + 5, 1, 1, COLOR_WHITE);
draw_rect(x + 5, y + 6, 1, 1, COLOR_WHITE);
draw_rect(x + 6, y + 5, 1, 2, COLOR_WHITE);
}
// Draw a squircle-style app icon
void draw_squircle_icon(int x, int y, const char *label, uint32_t bg_color) {
// Simplified squircle using rounded rectangle
draw_rounded_rect_filled(x + 12, y, 56, 56, 12, bg_color);
draw_icon_label(x, y + 60, label);
}
// macOS Files icon (folder style)
void draw_files_icon(int x, int y, const char *label) {
// Blue folder icon with macOS styling
draw_rounded_rect_filled(x + 27, y + 6, 25, 15, 3, 0xFF4A90E2); // Blue color
draw_squircle_icon(x, y, label, 0xFF4A90E2);
}
// macOS Settings/Gear icon
void draw_settings_icon(int x, int y, const char *label) {
// Gear icon with dark background
draw_squircle_icon(x, y, label, 0xFF666666);
// Simple gear shape in the middle of squircle
int cx = x + 12 + 28;
int cy = y + 28;
draw_rect(cx - 2, cy - 2, 4, 4, COLOR_WHITE); // Center
}
void draw_window(Window *win) { void draw_window(Window *win) {
if (!win->visible) return; if (!win->visible) return;
// Main Body // Dark mode window with rounded corners
draw_bevel_rect(win->x, win->y, win->w, win->h, false); // Border/Shadow effect
draw_rounded_rect_filled(win->x - 1, win->y - 1, win->w + 2, win->h + 2, 8, 0xFF000000);
// Main window body
draw_rounded_rect_filled(win->x, win->y, win->w, win->h, 8, COLOR_DARK_PANEL);
// Title Bar // Title Bar
uint32_t title_color = win->focused ? COLOR_RED : COLOR_DKGRAY; draw_rounded_rect_filled(win->x, win->y, win->w, 22, 8, COLOR_DARK_TITLEBAR);
draw_rect(win->x + 3, win->y + 3, win->w - 6, 18, title_color); draw_string(win->x + 28, win->y + 7, win->title, COLOR_DARK_TEXT);
draw_string(win->x + 8, win->y + 8, win->title, COLOR_WHITE);
// Close Button (X) // Traffic Light (close button - red)
draw_button(win->x + win->w - 20, win->y + 5, 14, 14, "X", false); draw_traffic_light(win->x + 8, win->y + 5);
// Client Area // Client Area with dark background (no rounding)
draw_rect(win->x + 4, win->y + 24, win->w - 8, win->h - 28, COLOR_LTGRAY); draw_rect(win->x, win->y + 22, win->w, win->h - 22, COLOR_DARK_BG);
if (win->paint) { if (win->paint) {
win->paint(win); win->paint(win);
@ -665,7 +705,7 @@ static void draw_clock(int x, int y) {
buf[7] = '0' + (s % 10); buf[7] = '0' + (s % 10);
buf[8] = 0; buf[8] = 0;
draw_string(x, y, buf, COLOR_BLACK); draw_string(x, y, buf, COLOR_WHITE);
} }
// --- Main Paint Function --- // --- Main Paint Function ---
@ -673,7 +713,6 @@ void wm_paint(void) {
int sw = get_screen_width(); int sw = get_screen_width();
int sh = get_screen_height(); int sh = get_screen_height();
DirtyRect dirty = graphics_get_dirty_rect(); DirtyRect dirty = graphics_get_dirty_rect();
if (dirty.active) { if (dirty.active) {
graphics_set_clipping(dirty.x, dirty.y, dirty.w, dirty.h); graphics_set_clipping(dirty.x, dirty.y, dirty.w, dirty.h);
@ -681,8 +720,8 @@ void wm_paint(void) {
graphics_clear_clipping(); graphics_clear_clipping();
} }
// 1. Desktop // 1. Desktop Background (dark mode)
draw_desktop_background(); draw_rect(0, 0, sw, sh, COLOR_DARK_BG);
// Draw Desktop Icons // Draw Desktop Icons
for (int i = 0; i < desktop_icon_count; i++) { for (int i = 0; i < desktop_icon_count; i++) {
@ -695,12 +734,11 @@ void wm_paint(void) {
} }
if (icon->type == 1) draw_folder_icon(icon->x, icon->y, icon->name); if (icon->type == 1) draw_folder_icon(icon->x, icon->y, icon->name);
else if (icon->type == 2) { else if (icon->type == 2) {
// App icon - strip .app for display // App icon - strip .shortcut for display
char label[64]; char label[64];
int len = 0; int len = 0;
while(icon->name[len] && len < 63) { label[len] = icon->name[len]; len++; } while(icon->name[len] && len < 63) { label[len] = icon->name[len]; len++; }
label[len] = 0; label[len] = 0;
// Remove .app suffix if present
if (len > 9 && str_ends_with(label, ".shortcut")) { if (len > 9 && str_ends_with(label, ".shortcut")) {
label[len-9] = 0; label[len-9] = 0;
} }
@ -709,17 +747,17 @@ void wm_paint(void) {
else if (str_starts_with(icon->name, "Calculator")) draw_calculator_icon(icon->x, icon->y, label); else if (str_starts_with(icon->name, "Calculator")) draw_calculator_icon(icon->x, icon->y, label);
else if (str_starts_with(icon->name, "Terminal")) draw_terminal_icon(icon->x, icon->y, label); else if (str_starts_with(icon->name, "Terminal")) draw_terminal_icon(icon->x, icon->y, label);
else if (str_starts_with(icon->name, "Minesweeper")) draw_minesweeper_icon(icon->x, icon->y, label); else if (str_starts_with(icon->name, "Minesweeper")) draw_minesweeper_icon(icon->x, icon->y, label);
else if (str_starts_with(icon->name, "Control Panel")) draw_control_panel_icon(icon->x, icon->y, label); else if (str_starts_with(icon->name, "Settings")) draw_settings_icon(icon->x, icon->y, label);
else if (str_starts_with(icon->name, "About")) draw_about_icon(icon->x, icon->y, label); else if (str_starts_with(icon->name, "About")) draw_about_icon(icon->x, icon->y, label);
else if (str_starts_with(icon->name, "Recycle Bin")) draw_recycle_bin_icon(icon->x, icon->y, label); else if (str_starts_with(icon->name, "Recycle Bin")) draw_recycle_bin_icon(icon->x, icon->y, label);
else if (str_starts_with(icon->name, "Explorer")) draw_folder_icon(icon->x, icon->y, label); else if (str_starts_with(icon->name, "Files")) draw_files_icon(icon->x, icon->y, label);
else if (str_starts_with(icon->name, "Paint")) draw_paint_icon(icon->x, icon->y, label); else if (str_starts_with(icon->name, "Paint")) draw_paint_icon(icon->x, icon->y, label);
else draw_icon(icon->x, icon->y, label); else draw_icon(icon->x, icon->y, label);
} else { } else {
if (str_ends_with(icon->name, ".pnt")) draw_paint_icon(icon->x, icon->y, icon->name); if (str_ends_with(icon->name, ".pnt")) draw_paint_icon(icon->x, icon->y, icon->name);
else if (str_ends_with(icon->name, ".md")) { else if (str_ends_with(icon->name, ".md")) {
draw_document_icon(icon->x, icon->y, icon->name); draw_document_icon(icon->x, icon->y, icon->name);
draw_string(icon->x + 31, icon->y + 2, "MD", COLOR_BLACK); draw_string(icon->x + 31, icon->y + 2, "MD", COLOR_DARK_TEXT);
} else if (str_ends_with(icon->name, ".c") || str_ends_with(icon->name, ".C")) { } else if (str_ends_with(icon->name, ".c") || str_ends_with(icon->name, ".C")) {
draw_document_icon(icon->x, icon->y, icon->name); draw_document_icon(icon->x, icon->y, icon->name);
draw_string(icon->x + 31, icon->y + 2, "C", COLOR_APPLE_BLUE); draw_string(icon->x + 31, icon->y + 2, "C", COLOR_APPLE_BLUE);
@ -729,7 +767,6 @@ void wm_paint(void) {
} }
// 3. Windows - sort by z-index and draw // 3. Windows - sort by z-index and draw
// Simple bubble sort by z-index
Window *sorted_windows[32]; Window *sorted_windows[32];
for (int i = 0; i < window_count; i++) { for (int i = 0; i < window_count; i++) {
sorted_windows[i] = all_windows[i]; sorted_windows[i] = all_windows[i];
@ -750,7 +787,6 @@ void wm_paint(void) {
Window *win = sorted_windows[i]; Window *win = sorted_windows[i];
if (!win->visible) continue; if (!win->visible) continue;
if (dirty.active && !win->focused) { if (dirty.active && !win->focused) {
if (win->x + win->w <= dirty.x || win->x >= dirty.x + dirty.w || if (win->x + win->w <= dirty.x || win->x >= dirty.x + dirty.w ||
win->y + win->h <= dirty.y || win->y >= dirty.y + dirty.h) { win->y + win->h <= dirty.y || win->y >= dirty.y + dirty.h) {
@ -760,109 +796,131 @@ void wm_paint(void) {
draw_window(win); draw_window(win);
} }
// 4. Taskbar // 4. Top Menu Bar (macOS style)
draw_rect(0, sh - 28, sw, 28, COLOR_GRAY); draw_rect(0, 0, sw, 40, COLOR_TOPBAR_BG);
draw_rect(0, sh - 28, sw, 2, COLOR_WHITE); // Top highlight
// 5. Start Button // Logo dropdown (top-left)
draw_bevel_rect(2, sh - 26, 90, 24, start_menu_open); draw_boredos_logo(8, 8, 1);
// Draw Boredos logo
draw_boredos_logo(6, sh - 22, 1);
// Draw BoredOS text
draw_string(35, sh - 18, "BoredOS", COLOR_BLACK);
// Clock // Clock (top-right)
draw_clock(sw - 80, sh - 20); draw_clock(sw - 80, 12);
// 6. Start Menu (if open) // Top menu dropdown (if logo clicked)
if (start_menu_open) { if (start_menu_open) {
int menu_h = 250; int menu_h = 100;
int menu_y = sh - 28 - menu_h; draw_rounded_rect_filled(8, 40, 160, menu_h, 8, COLOR_DARK_PANEL);
draw_bevel_rect(0, menu_y, 120, menu_h, false); draw_string(20, 48, "About BoredOS", COLOR_DARK_TEXT);
draw_string(20, 68, "Settings", COLOR_DARK_TEXT);
// Items draw_string(20, 88, "Shutdown", COLOR_DARK_TEXT);
draw_string(8, menu_y + 8, "Explorer", COLOR_BLACK); draw_string(20, 108, "Restart", COLOR_DARK_TEXT);
draw_string(8, menu_y + 28, "Notepad", COLOR_BLACK);
draw_string(8, menu_y + 48, "Editor", COLOR_BLACK);
draw_string(8, menu_y + 68, "CMD", COLOR_BLACK);
draw_string(8, menu_y + 88, "Calculator", COLOR_BLACK);
draw_string(8, menu_y + 108, "Minesweeper", COLOR_BLACK);
draw_string(8, menu_y + 128, "Control Panel", COLOR_BLACK);
draw_string(8, menu_y + 148, "Paint", COLOR_BLACK);
draw_string(8, menu_y + 168, "About BoredOS", COLOR_BLACK);
// Separator line
draw_rect(5, menu_y + 185, 110, 1, COLOR_BLACK);
// Power options at bottom
draw_string(8, menu_y + 195, "Shutdown", COLOR_BLACK);
draw_string(8, menu_y + 215, "Restart", COLOR_BLACK);
} }
// Desktop Context Menu // 5. Dock (bottom - macOS style, floating with rounded corners)
int dock_h = 60;
int dock_y = sh - dock_h - 6; // Float above bottom
int dock_item_size = 48;
int dock_spacing = 10;
int total_dock_width = 8 * (dock_item_size + dock_spacing);
int dock_bg_x = (sw - total_dock_width) / 2 - 12; // Rounded background extends beyond icons
int dock_bg_w = total_dock_width + 24;
draw_rounded_rect_filled(dock_bg_x, dock_y, dock_bg_w, dock_h, 18, COLOR_DOCK_BG);
// Draw dock apps (centered)
int dock_x = (sw - total_dock_width) / 2;
int dock_item_y = dock_y + 6;
// Files app
draw_rounded_rect_filled(dock_x, dock_item_y, dock_item_size, dock_item_size, 10, 0xFF4A90E2);
dock_x += dock_item_size + dock_spacing;
// Settings app
draw_rounded_rect_filled(dock_x, dock_item_y, dock_item_size, dock_item_size, 10, 0xFF888888);
dock_x += dock_item_size + dock_spacing;
// Notepad
draw_rounded_rect_filled(dock_x, dock_item_y, dock_item_size, dock_item_size, 10, 0xFFFFD700);
dock_x += dock_item_size + dock_spacing;
// Calculator
draw_rounded_rect_filled(dock_x, dock_item_y, dock_item_size, dock_item_size, 10, 0xFFFF6B6B);
dock_x += dock_item_size + dock_spacing;
// Terminal
draw_rounded_rect_filled(dock_x, dock_item_y, dock_item_size, dock_item_size, 10, 0xFF000000);
dock_x += dock_item_size + dock_spacing;
// Minesweeper
draw_rounded_rect_filled(dock_x, dock_item_y, dock_item_size, dock_item_size, 10, 0xFF808080);
dock_x += dock_item_size + dock_spacing;
// Paint
draw_rounded_rect_filled(dock_x, dock_item_y, dock_item_size, dock_item_size, 10, 0xFF4CAF50);
dock_x += dock_item_size + dock_spacing;
// Editor
draw_rounded_rect_filled(dock_x, dock_item_y, dock_item_size, dock_item_size, 10, 0xFF2196F3);
// Desktop Context Menu (with rounded corners)
if (desktop_menu_visible) { if (desktop_menu_visible) {
int menu_w = 140; int menu_w = 140;
int item_h = 25; int item_h = 25;
int menu_h = (desktop_menu_target_icon != -1) ? 125 : 75; int menu_h = (desktop_menu_target_icon != -1) ? 125 : 75;
draw_rect(desktop_menu_x, desktop_menu_y, menu_w, menu_h, COLOR_LTGRAY); draw_rounded_rect_filled(desktop_menu_x, desktop_menu_y, menu_w, menu_h, 8, COLOR_DARK_PANEL);
draw_bevel_rect(desktop_menu_x, desktop_menu_y, menu_w, menu_h, true);
if (desktop_menu_target_icon != -1) { if (desktop_menu_target_icon != -1) {
bool can_paste = explorer_clipboard_has_content(); bool can_paste = explorer_clipboard_has_content();
DesktopIcon *icon = &desktop_icons[desktop_menu_target_icon]; draw_string(desktop_menu_x + 10, desktop_menu_y + 5, "Cut", COLOR_DARK_TEXT);
if (icon->type != 1) can_paste = false; // 1 is folder draw_string(desktop_menu_x + 10, desktop_menu_y + 5 + item_h, "Copy", COLOR_DARK_TEXT);
draw_string(desktop_menu_x + 10, desktop_menu_y + 5 + item_h * 2, "Paste", can_paste ? COLOR_DARK_TEXT : COLOR_DKGRAY);
draw_string(desktop_menu_x + 5, desktop_menu_y + 5, "Cut", COLOR_BLACK); draw_string(desktop_menu_x + 10, desktop_menu_y + 5 + item_h * 3, "Delete", COLOR_TRAFFIC_RED);
draw_string(desktop_menu_x + 5, desktop_menu_y + 5 + item_h, "Copy", COLOR_BLACK); draw_string(desktop_menu_x + 10, desktop_menu_y + 5 + item_h * 4, "Rename", COLOR_DARK_TEXT);
draw_string(desktop_menu_x + 5, desktop_menu_y + 5 + item_h * 2, "Paste", can_paste ? COLOR_BLACK : COLOR_DKGRAY);
draw_string(desktop_menu_x + 5, desktop_menu_y + 5 + item_h * 3, "Delete", COLOR_RED);
draw_string(desktop_menu_x + 5, desktop_menu_y + 5 + item_h * 4, "Rename", COLOR_BLACK);
} else { } else {
bool can_paste = explorer_clipboard_has_content(); bool can_paste = explorer_clipboard_has_content();
draw_string(desktop_menu_x + 5, desktop_menu_y + 5, "New File", COLOR_BLACK); draw_string(desktop_menu_x + 10, desktop_menu_y + 5, "New File", COLOR_DARK_TEXT);
draw_string(desktop_menu_x + 5, desktop_menu_y + 5 + item_h, "New Folder", COLOR_BLACK); draw_string(desktop_menu_x + 10, desktop_menu_y + 5 + item_h, "New Folder", COLOR_DARK_TEXT);
draw_string(desktop_menu_x + 5, desktop_menu_y + 5 + item_h * 2, "Paste", can_paste ? COLOR_BLACK : COLOR_DKGRAY); draw_string(desktop_menu_x + 10, desktop_menu_y + 5 + item_h * 2, "Paste", can_paste ? COLOR_DARK_TEXT : COLOR_DKGRAY);
} }
} }
// Desktop Dialogs // Desktop Dialogs (dark mode)
if (desktop_dialog_state != 0) { if (desktop_dialog_state != 0) {
int dlg_w = 300; int dlg_h = 110; int dlg_w = 300; int dlg_h = 110;
int dlg_x = (sw - dlg_w) / 2; int dlg_x = (sw - dlg_w) / 2;
int dlg_y = (sh - dlg_h) / 2; int dlg_y = (sh - dlg_h) / 2;
draw_rect(dlg_x - 5, dlg_y - 5, dlg_w + 10, dlg_h + 10, COLOR_LTGRAY); draw_rounded_rect_filled(dlg_x, dlg_y, dlg_w, dlg_h, 8, COLOR_DARK_PANEL);
draw_bevel_rect(dlg_x, dlg_y, dlg_w, dlg_h, true);
const char *title = "Rename"; const char *title = "Rename";
const char *btn_text = "Rename"; const char *btn_text = "Rename";
if (desktop_dialog_state == 1) { title = "Create New File"; btn_text = "Create"; } if (desktop_dialog_state == 1) { title = "Create New File"; btn_text = "Create"; }
else if (desktop_dialog_state == 2) { title = "Create New Folder"; btn_text = "Create"; } else if (desktop_dialog_state == 2) { title = "Create New Folder"; btn_text = "Create"; }
draw_string(dlg_x + 10, dlg_y + 10, title, COLOR_BLACK); draw_string(dlg_x + 10, dlg_y + 10, title, COLOR_DARK_TEXT);
draw_bevel_rect(dlg_x + 10, dlg_y + 35, 280, 20, false); draw_rounded_rect_filled(dlg_x + 10, dlg_y + 35, 280, 20, 4, COLOR_DARK_BG);
draw_string(dlg_x + 15, dlg_y + 40, desktop_dialog_input, COLOR_BLACK); draw_string(dlg_x + 15, dlg_y + 40, desktop_dialog_input, COLOR_DARK_TEXT);
// Cursor // Cursor
draw_rect(dlg_x + 15 + desktop_dialog_cursor * 8, dlg_y + 39, 2, 12, COLOR_BLACK); draw_rect(dlg_x + 15 + desktop_dialog_cursor * 8, dlg_y + 39, 2, 12, COLOR_DARK_TEXT);
draw_button(dlg_x + 50, dlg_y + 65, 80, 25, btn_text, false); draw_rounded_rect_filled(dlg_x + 50, dlg_y + 65, 80, 25, 4, COLOR_DARK_BORDER);
draw_button(dlg_x + 170, dlg_y + 65, 80, 25, "Cancel", false); draw_string(dlg_x + 70, dlg_y + 72, btn_text, COLOR_DARK_TEXT);
draw_rounded_rect_filled(dlg_x + 170, dlg_y + 65, 80, 25, 4, COLOR_DARK_BORDER);
draw_string(dlg_x + 185, dlg_y + 72, "Cancel", COLOR_DARK_TEXT);
} }
// Message Box // Message Box (dark mode)
if (msg_box_visible) { if (msg_box_visible) {
int mw = 320; int mw = 320;
int mh = 100; int mh = 100;
int mx = (sw - mw) / 2; int mx = (sw - mw) / 2;
int my = (sh - mh) / 2; int my = (sh - mh) / 2;
draw_rect(mx, my, mw, mh, COLOR_LTGRAY); draw_rounded_rect_filled(mx, my, mw, mh, 8, COLOR_DARK_PANEL);
draw_bevel_rect(mx, my, mw, mh, false); draw_string(mx + 15, my + 10, msg_box_title, COLOR_DARK_TEXT);
draw_rect(mx + 3, my + 3, mw - 6, 20, COLOR_BLUE); draw_string(mx + 10, my + 40, msg_box_text, COLOR_DARK_TEXT);
draw_string(mx + 8, my + 8, msg_box_title, COLOR_WHITE); draw_rounded_rect_filled(mx + mw/2 - 30, my + 70, 60, 20, 4, COLOR_DARK_BORDER);
draw_string(mx + 10, my + 40, msg_box_text, COLOR_BLACK); draw_string(mx + mw/2 - 18, my + 75, "OK", COLOR_DARK_TEXT);
draw_button(mx + mw/2 - 30, my + 70, 60, 20, "OK", false);
} }
// Custom Overlay (VM Graphics) // Custom Overlay (VM Graphics)
@ -872,8 +930,6 @@ void wm_paint(void) {
// Draw Dragged Icon // Draw Dragged Icon
if (is_dragging_file) { if (is_dragging_file) {
// Extract filename for label
// Just draw a generic icon at mouse pos
if (drag_icon_type == 1) draw_folder_icon(mx - 20, my - 20, "Moving..."); if (drag_icon_type == 1) draw_folder_icon(mx - 20, my - 20, "Moving...");
else if (drag_icon_type == 2) draw_icon(mx - 20, my - 20, "Moving..."); else if (drag_icon_type == 2) draw_icon(mx - 20, my - 20, "Moving...");
else draw_document_icon(mx - 20, my - 20, "Moving..."); else draw_document_icon(mx - 20, my - 20, "Moving...");
@ -1035,7 +1091,7 @@ void wm_handle_click(int x, int y) {
} }
} else if (desktop_dialog_state == 1 || desktop_dialog_state == 2) { // Create File/Folder } else if (desktop_dialog_state == 1 || desktop_dialog_state == 2) { // Create File/Folder
if (desktop_icon_count >= desktop_max_cols * desktop_max_rows_per_col) { if (desktop_icon_count >= desktop_max_cols * desktop_max_rows_per_col) {
wm_show_message("Error", "Desktop is full!"); wm_show_message("Error", "Desktop is full!"); // This message is now based on the adjusted limit
} else if (desktop_dialog_input[0] != 0) { } else if (desktop_dialog_input[0] != 0) {
char path[128] = "/Desktop/"; char path[128] = "/Desktop/";
int p=9; int n=0; while(desktop_dialog_input[n]) path[p++] = desktop_dialog_input[n++]; path[p]=0; int p=9; int n=0; while(desktop_dialog_input[n]) path[p++] = desktop_dialog_input[n++]; path[p]=0;
@ -1067,15 +1123,33 @@ void wm_handle_click(int x, int y) {
} }
} }
// Check Start Button // Check Top Bar Logo (toggle dropdown menu)
if (rect_contains(2, sh - 26, 90, 24, x, y)) { if (rect_contains(8, 8, 24, 24, x, y)) {
start_menu_open = !start_menu_open; start_menu_open = !start_menu_open;
force_redraw = true; force_redraw = true;
pending_desktop_icon_click = -1; pending_desktop_icon_click = -1;
return; return;
} }
// Start Menu items handled in wm_handle_mouse (on up/drag) to support dragging shortcuts. // Handle top bar dropdown menu items
if (start_menu_open && rect_contains(8, 40, 160, 120, x, y)) {
int rel_y = y - 40;
int item = rel_y / 20;
if (item == 0) { // About
wm_bring_to_front(&win_about);
} else if (item == 1) { // Settings
wm_bring_to_front(&win_control_panel);
} else if (item == 2) { // Shutdown
cli_cmd_shutdown(NULL);
} else if (item == 3) { // Restart
cli_cmd_reboot(NULL);
}
start_menu_open = false;
force_redraw = true;
return;
}
// Find topmost window at click location // Find topmost window at click location
Window *topmost = NULL; Window *topmost = NULL;
@ -1095,8 +1169,8 @@ void wm_handle_click(int x, int y) {
if (topmost != NULL) { if (topmost != NULL) {
wm_bring_to_front(topmost); wm_bring_to_front(topmost);
// Check close button // Check traffic light close button (now at top-left)
if (rect_contains(topmost->x + topmost->w - 20, topmost->y + 5, 14, 14, x, y)) { if (rect_contains(topmost->x + 8, topmost->y + 9, 12, 12, x, y)) {
topmost->visible = false; topmost->visible = false;
// Reset window state on close // Reset window state on close
if (topmost == &win_explorer) { if (topmost == &win_explorer) {
@ -1108,7 +1182,7 @@ void wm_handle_click(int x, int y) {
} else if (topmost == &win_paint) { } else if (topmost == &win_paint) {
paint_reset(); paint_reset();
} }
} else if (y < topmost->y + 24) { } else if (y < topmost->y + 30) {
// Dragging the title bar // Dragging the title bar
is_dragging = true; is_dragging = true;
drag_window = topmost; drag_window = topmost;
@ -1140,7 +1214,7 @@ void wm_handle_click(int x, int y) {
} }
} }
// Close start menu if clicked elsewhere // Close dropdown menu if clicked elsewhere
if (start_menu_open) { if (start_menu_open) {
start_menu_open = false; start_menu_open = false;
} }
@ -1229,24 +1303,30 @@ void wm_handle_right_click(int x, int y) {
paint_reset_last_pos(); paint_reset_last_pos();
} }
// Check Start Menu for potential drag // Check Dock for app clicks (bottom of screen, floating)
if (start_menu_open) { int dock_h = 60;
int menu_h = 250; int dock_y = sh - dock_h - 6; // Float above bottom
int menu_y = sh - 28 - menu_h; int dock_item_size = 48;
if (rect_contains(0, menu_y, 120, menu_h, mx, my)) { int dock_spacing = 10;
if (my < menu_y + 25) start_menu_pending_app = "Explorer"; int total_dock_width = 8 * (dock_item_size + dock_spacing);
else if (my < menu_y + 45) start_menu_pending_app = "Notepad"; int dock_bg_x = (sw - total_dock_width) / 2 - 12;
else if (my < menu_y + 65) start_menu_pending_app = "Editor"; int dock_bg_w = total_dock_width + 24;
else if (my < menu_y + 85) start_menu_pending_app = "Terminal";
else if (my < menu_y + 105) start_menu_pending_app = "Calculator"; if (rect_contains(dock_bg_x, dock_y, dock_bg_w, dock_h, mx, my)) {
else if (my < menu_y + 125) start_menu_pending_app = "Minesweeper"; int dock_x = (sw - total_dock_width) / 2;
else if (my < menu_y + 145) start_menu_pending_app = "Control Panel";
else if (my < menu_y + 165) start_menu_pending_app = "Paint"; // Check which dock item was clicked
else if (my < menu_y + 185) start_menu_pending_app = "About"; int item_x = mx - dock_x;
else if (my < menu_y + 205) start_menu_pending_app = "Shutdown"; if (item_x >= 0) {
else start_menu_pending_app = "Restart"; int item = item_x / (dock_item_size + dock_spacing);
} else { if (item == 0) start_menu_pending_app = "Files";
wm_handle_click(mx, my); else if (item == 1) start_menu_pending_app = "Settings";
else if (item == 2) start_menu_pending_app = "Notepad";
else if (item == 3) start_menu_pending_app = "Calculator";
else if (item == 4) start_menu_pending_app = "Terminal";
else if (item == 5) start_menu_pending_app = "Minesweeper";
else if (item == 6) start_menu_pending_app = "Paint";
else if (item == 7) start_menu_pending_app = "Editor";
} }
} else { } else {
wm_handle_click(mx, my); wm_handle_click(mx, my);
@ -1313,7 +1393,7 @@ void wm_handle_right_click(int x, int y) {
for (int w = 0; w < window_count; w++) { for (int w = 0; w < window_count; w++) {
Window *win = all_windows[w]; Window *win = all_windows[w];
if (win->visible && rect_contains(win->x, win->y, win->w, win->h, drag_start_x, drag_start_y)) { if (win->visible && rect_contains(win->x, win->y, win->w, win->h, drag_start_x, drag_start_y)) {
if (str_starts_with(win->title, "File Explorer")) { if (str_starts_with(win->title, "Files")) {
drag_src_win = win; drag_src_win = win;
explorer_clear_click_state(win); explorer_clear_click_state(win);
} }
@ -1332,12 +1412,14 @@ void wm_handle_right_click(int x, int y) {
force_redraw = true; force_redraw = true;
} }
// Handle Start Menu Click (Mouse Up without Drag) // Handle Dock App Click (Mouse Up without Drag)
if (start_menu_pending_app) { if (start_menu_pending_app) {
// Launch App // Launch App
if (str_starts_with(start_menu_pending_app, "Explorer")) { if (str_starts_with(start_menu_pending_app, "Files")) {
explorer_open_directory("/"); explorer_reset();
wm_bring_to_front(&win_explorer);
} else if (str_starts_with(start_menu_pending_app, "Notepad")) { } else if (str_starts_with(start_menu_pending_app, "Notepad")) {
notepad_reset();
wm_bring_to_front(&win_notepad); wm_bring_to_front(&win_notepad);
} else if (str_starts_with(start_menu_pending_app, "Editor")) { } else if (str_starts_with(start_menu_pending_app, "Editor")) {
wm_bring_to_front(&win_editor); wm_bring_to_front(&win_editor);
@ -1347,7 +1429,7 @@ void wm_handle_right_click(int x, int y) {
wm_bring_to_front(&win_calculator); wm_bring_to_front(&win_calculator);
} else if (str_starts_with(start_menu_pending_app, "Minesweeper")) { } else if (str_starts_with(start_menu_pending_app, "Minesweeper")) {
wm_bring_to_front(&win_minesweeper); wm_bring_to_front(&win_minesweeper);
} else if (str_starts_with(start_menu_pending_app, "Control Panel")) { } else if (str_starts_with(start_menu_pending_app, "Settings")) {
wm_bring_to_front(&win_control_panel); wm_bring_to_front(&win_control_panel);
} else if (str_starts_with(start_menu_pending_app, "Paint")) { } else if (str_starts_with(start_menu_pending_app, "Paint")) {
wm_bring_to_front(&win_paint); wm_bring_to_front(&win_paint);
@ -1359,7 +1441,6 @@ void wm_handle_right_click(int x, int y) {
cli_cmd_reboot(NULL); cli_cmd_reboot(NULL);
} }
start_menu_open = false;
start_menu_pending_app = NULL; start_menu_pending_app = NULL;
force_redraw = true; force_redraw = true;
} }
@ -1378,14 +1459,15 @@ void wm_handle_right_click(int x, int y) {
wm_bring_to_front(&win_calculator); handled = true; wm_bring_to_front(&win_calculator); handled = true;
} else if (str_ends_with(icon->name, "Minesweeper.shortcut")) { } else if (str_ends_with(icon->name, "Minesweeper.shortcut")) {
wm_bring_to_front(&win_minesweeper); handled = true; wm_bring_to_front(&win_minesweeper); handled = true;
} else if (str_ends_with(icon->name, "Control Panel.shortcut")) { } else if (str_ends_with(icon->name, "Settings.shortcut")) {
wm_bring_to_front(&win_control_panel); handled = true; wm_bring_to_front(&win_control_panel); handled = true;
} else if (str_ends_with(icon->name, "Terminal.shortcut")) { } else if (str_ends_with(icon->name, "Terminal.shortcut")) {
wm_bring_to_front(&win_cmd); handled = true; wm_bring_to_front(&win_cmd); handled = true;
} else if (str_ends_with(icon->name, "About.shortcut")) { } else if (str_ends_with(icon->name, "About.shortcut")) {
wm_bring_to_front(&win_about); handled = true; wm_bring_to_front(&win_about); handled = true;
} else if (str_ends_with(icon->name, "Explorer.shortcut")) { } else if (str_ends_with(icon->name, "Explorer.shortcut")) { // Files
explorer_open_directory("/"); handled = true; explorer_reset();
wm_bring_to_front(&win_explorer);
} else if (str_ends_with(icon->name, "Recycle Bin.shortcut")) { } else if (str_ends_with(icon->name, "Recycle Bin.shortcut")) {
explorer_open_directory("/RecycleBin"); handled = true; explorer_open_directory("/RecycleBin"); handled = true;
} else if (str_ends_with(icon->name, "Paint.shortcut")) { } else if (str_ends_with(icon->name, "Paint.shortcut")) {
@ -1450,7 +1532,7 @@ void wm_handle_right_click(int x, int y) {
for (int w = 0; w < window_count; w++) { for (int w = 0; w < window_count; w++) {
Window *win = all_windows[w]; Window *win = all_windows[w];
if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) { if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
if (win->z_index > topmost_z && str_starts_with(win->title, "File Explorer")) { if (win->z_index > topmost_z && str_starts_with(win->title, "Files")) {
drop_win = win; drop_win = win;
topmost_z = win->z_index; topmost_z = win->z_index;
} }
@ -1511,7 +1593,7 @@ void wm_handle_right_click(int x, int y) {
if (!dropped_on_target && !from_desktop) { if (!dropped_on_target && !from_desktop) {
// Dragged from Explorer to Desktop // Dragged from Explorer to Desktop
// Check limit first // Check limit first
if (desktop_icon_count >= desktop_max_cols * desktop_max_rows_per_col) { if (desktop_icon_count >= desktop_max_cols * (desktop_max_rows_per_col > 1 ? desktop_max_rows_per_col - 1 : 0)) {
wm_show_message("Error", "Desktop is full!"); wm_show_message("Error", "Desktop is full!");
} else { } else {
explorer_import_file_to(&win_explorer, drag_file_path, "/Desktop"); explorer_import_file_to(&win_explorer, drag_file_path, "/Desktop");

View file

@ -23,6 +23,19 @@
#define COLOR_APPLE_INDIGO 0xFF4B0082 #define COLOR_APPLE_INDIGO 0xFF4B0082
#define COLOR_APPLE_VIOLET 0xFF9400D3 #define COLOR_APPLE_VIOLET 0xFF9400D3
// --- Dark Mode Colors (macOS Style) ---
#define COLOR_DARK_BG 0xFF1E1E1E // Main dark background
#define COLOR_DARK_PANEL 0xFF2D2D2D // Slightly lighter panel background
#define COLOR_DARK_TITLEBAR 0xFF282828 // Darker for title bar
#define COLOR_DARK_TEXT 0xFFF0F0F0 // Light gray text
#define COLOR_DARK_BORDER 0xFF3A3A3A // Border color
#define COLOR_DOCK_BG 0xFF3A3A3A // Dock background
#define COLOR_TOPBAR_BG 0xFF1A1A1A // Top bar background
#define COLOR_TRAFFIC_RED 0xFFED6158 // Close button red
#define COLOR_TRAFFIC_YELLOW 0xFFFCC02E // Minimize button (not used for now)
#define COLOR_TRAFFIC_GREEN 0xFF5FC038 // Zoom button (not used for now)
#define DESKTOP_TOP_DEADSPACE_HEIGHT 80 // Height of the dead space at the top of the desktop grid
typedef struct Window Window; typedef struct Window Window;
struct Window { struct Window {
char *title; char *title;
@ -67,6 +80,9 @@ extern void (*wm_custom_paint_hook)(void);
// Drawing helpers // Drawing helpers
void draw_bevel_rect(int x, int y, int w, int h, bool sunken); void draw_bevel_rect(int x, int y, int w, int h, bool sunken);
void draw_button(int x, int y, int w, int h, const char *text, bool pressed); void draw_button(int x, int y, int w, int h, const char *text, bool pressed);
void draw_rounded_rect(int x, int y, int w, int h, int radius, uint32_t color);
void draw_rounded_rect_filled(int x, int y, int w, int h, int radius, uint32_t color);
void draw_traffic_light(int x, int y); // Red close button only
void draw_icon(int x, int y, const char *label); void draw_icon(int x, int y, const char *label);
void draw_folder_icon(int x, int y, const char *label); void draw_folder_icon(int x, int y, const char *label);
void draw_document_icon(int x, int y, const char *label); void draw_document_icon(int x, int y, const char *label);
@ -78,6 +94,9 @@ void draw_control_panel_icon(int x, int y, const char *label);
void draw_about_icon(int x, int y, const char *label); void draw_about_icon(int x, int y, const char *label);
void draw_recycle_bin_icon(int x, int y, const char *label); void draw_recycle_bin_icon(int x, int y, const char *label);
void draw_paint_icon(int x, int y, const char *label); void draw_paint_icon(int x, int y, const char *label);
void draw_squircle_icon(int x, int y, const char *label, uint32_t bg_color);
void draw_files_icon(int x, int y, const char *label);
void draw_settings_icon(int x, int y, const char *label);
// Desktop Settings // Desktop Settings
extern bool desktop_snap_to_grid; extern bool desktop_snap_to_grid;