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.
<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*
## Features
- Disk manager
- Drag and drop mouse centered UI
- Customizable UI
- 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);
// Version info
draw_string(offset_x, offset_y + 105, "BoredOS 'Panda'", COLOR_BLACK);
draw_string(offset_x, offset_y + 120, "BoredOS Version 1.51", COLOR_BLACK);
draw_string(offset_x, offset_y + 135, "Kernel Version 2.5.0", 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_WHITE);
draw_string(offset_x, offset_y + 135, "Kernel Version 2.5.0", COLOR_WHITE);
// Copyright
draw_string(offset_x, offset_y + 150, "(C) 2026 boreddevnl.", COLOR_BLACK);
draw_string(offset_x, offset_y + 165, "All rights reserved.", 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_WHITE);
}
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) {
// 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
draw_bevel_rect(win->x + 10, win->y + 30, win->w - 20, 25, true);
// Display Area with dark mode styling
draw_rounded_rect_filled(win->x + 10, win->y + 36, win->w - 20, 25, 6, COLOR_DARK_PANEL);
// Right align text
int text_w = win->buf_len * 8;
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
// Layout 4 columns x 5 rows
// Buttons - macOS style squircle buttons
const char *labels[] = {
"C", "sqr", "rt", "/",
"7", "8", "9", "*",
@ -123,14 +122,18 @@ static void calculator_paint(Window *win) {
int bh = 25;
int gap = 5;
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++) {
int r = i / 4;
int c = i % 4;
// Special drawing for some buttons?
draw_button(start_x + c*(bw+gap), start_y + r*(bh+gap), bw, bh, labels[i], false);
// Draw rounded button backgrounds
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 int cursor_row = 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
// Pager State
@ -272,7 +272,7 @@ void cmd_screen_clear() {
for(int r=0; r<CMD_ROWS; r++) {
for(int c=0; c<CMD_COLS; c++) {
screen_buffer[r][c].c = ' ';
screen_buffer[r][c].color = COLOR_LTGRAY;
screen_buffer[r][c].color = COLOR_DARK_TEXT;
}
}
cursor_row = 0;
@ -1297,8 +1297,8 @@ static void cmd_paint(Window *win) {
int offset_x = win->x + 4;
int offset_y = win->y + 24;
// Fill background
draw_rect(win->x + 4, win->y + 24, win->w - 8, win->h - 28, COLOR_BLACK);
// Fill background - dark mode terminal
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_x = offset_x + 4;
@ -1306,11 +1306,11 @@ static void cmd_paint(Window *win) {
if (current_mode == MODE_PAGER) {
// Draw Pager Content (Wrapped)
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
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 {
// 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_y = win->y + 30;
// Draw wallpaper painting icon
// Frame
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
// Background
draw_rect(win->x, win->y + 30, win->w, win->h - 30, COLOR_DARK_BG);
// Paint strokes (simple landscape)
draw_rect(offset_x + 8, offset_y + 5, 22, 7, 0xFF87CEEB); // Sky blue
draw_rect(offset_x + 8, offset_y + 12, 22, 5, 0xFF90EE90); // Light green grass
draw_rect(offset_x + 15, offset_y + 8, 3, 4, 0xFF8B4513); // Tree trunk
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 settings items with rounded boxes
int item_y = 30 + 15;
int item_h = 60;
int item_spacing = 10;
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
int net_offset_y = offset_y + 35;
// Network Settings
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)
uint32_t globe_color = 0xFF4169E1; // Royal blue
// Desktop Settings
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)
draw_rect(offset_x + 11, net_offset_y + 3, 12, 1, globe_color);
draw_rect(offset_x + 9, net_offset_y + 4, 16, 1, globe_color);
draw_rect(offset_x + 8, net_offset_y + 5, 18, 1, globe_color);
draw_rect(offset_x + 7, net_offset_y + 6, 20, 1, globe_color);
draw_rect(offset_x + 6, net_offset_y + 7, 22, 1, globe_color);
draw_rect(offset_x + 6, net_offset_y + 8, 22, 1, globe_color);
draw_rect(offset_x + 6, net_offset_y + 9, 22, 1, globe_color);
draw_rect(offset_x + 6, net_offset_y + 10, 22, 1, globe_color);
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);
// Mouse Settings
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);
// Mouse icon
draw_rect(offset_x + 18, offset_y + item_y + 8, 20, 28, 0xFFD3D3D3);
draw_rect(offset_x + 20, offset_y + item_y + 10, 16, 10, 0xFFB0B0B0);
draw_string(offset_x + 60, offset_y + item_y + 15, "Mouse", COLOR_DARK_TEXT);
draw_string(offset_x + 60, offset_y + item_y + 35, "Pointer and trackpad", COLOR_DKGRAY);
}
}
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_y = 30;
// Check wallpaper button click (icon + text)
if (x >= offset_x + 5 && x < offset_x + 120 &&
y >= offset_y && y < offset_y + 25) {
// Settings items layout: each item is 60px tall with 10px spacing
int item_h = 60;
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;
focused_field = -1;
}
// Check network button click (icon + text)
int net_offset_y = offset_y + 35;
if (x >= offset_x + 5 && x < offset_x + 120 &&
y >= net_offset_y && y < net_offset_y + 25) {
// Check network button click
item_y += item_h + item_spacing;
if (x >= offset_x && x < win->w - 8 &&
y >= item_y && y < item_y + item_h) {
current_view = VIEW_NETWORK;
focused_field = -1;
}
// Check desktop button
int desk_offset_y = net_offset_y + 35;
if (x >= offset_x + 5 && x < offset_x + 120 &&
y >= desk_offset_y && y < desk_offset_y + 25) {
item_y += item_h + item_spacing;
if (x >= offset_x && x < win->w - 8 &&
y >= item_y && y < item_y + item_h) {
current_view = VIEW_DESKTOP;
}
// Check mouse button
int mouse_offset_y = desk_offset_y + 35;
if (x >= offset_x + 5 && x < offset_x + 120 &&
y >= mouse_offset_y && y < mouse_offset_y + 25) {
item_y += item_h + item_spacing;
if (x >= offset_x && x < win->w - 8 &&
y >= item_y && y < item_y + item_h) {
current_view = VIEW_MOUSE;
}
} 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) {
win_control_panel.title = "Control Panel";
win_control_panel.title = "Settings";
win_control_panel.x = 200;
win_control_panel.y = 150;
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_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 + 55, offset_y + 5, open_filename, 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_DARK_TEXT);
// Draw save button
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);
}
// Fill editor background
draw_rect(win->x + 4, win->y + 54, win->w - 8, win->h - 58, COLOR_WHITE);
// Fill editor background - dark mode
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)
int text_start_x = offset_x + 40;
@ -350,7 +350,7 @@ static void editor_paint(Window *win) {
// Draw the text segment
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
@ -379,7 +379,7 @@ static void editor_paint(Window *win) {
// Draw status bar at bottom
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];
int temp = cursor_line + 1;
@ -395,8 +395,8 @@ static void editor_paint(Window *win) {
}
line_str[idx] = 0;
draw_string(offset_x + 60, offset_y + content_height - 15, line_str, COLOR_WHITE);
draw_string(offset_x + 100, offset_y + content_height - 15, " Col: ", 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_DARK_TEXT);
char col_str[32];
temp = cursor_col + 1;
@ -412,7 +412,7 @@ static void editor_paint(Window *win) {
}
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 ===

View file

@ -215,8 +215,8 @@ static bool check_desktop_limit_explorer(Window *win) {
ExplorerState *state = (ExplorerState*)win->data;
if (explorer_str_starts_with(state->current_path, "/Desktop")) {
// Check if root desktop
if (explorer_strcmp(state->current_path, "/Desktop") == 0 || explorer_strcmp(state->current_path, "/Desktop/") == 0) {
if (state->item_count >= desktop_max_cols * desktop_max_rows_per_col) {
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 > 1 ? desktop_max_rows_per_col - 1 : 0)) {
state->dialog_state = DIALOG_ERROR;
explorer_strcpy(state->dialog_input, "Desktop is full!");
return false;
@ -951,10 +951,10 @@ static void explorer_paint(Window *win) {
int offset_y = win->y + 24;
DirtyRect dirty = graphics_get_dirty_rect();
// Fill background
draw_rect(offset_x, offset_y, win->w - 8, win->h - 28, COLOR_LTGRAY);
// Fill background with dark mode
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];
// Extract drive from the window's current_path instead of using global current_drive
char current_drv = 'A';
@ -973,28 +973,32 @@ static void explorer_paint(Window *win) {
drive_label[6] = ' ';
drive_label[7] = ']';
// Button at x+4, y+4, w=60
draw_button(win->x + 4, offset_y + 4, 60, 30, "", false);
draw_string(win->x + 12, offset_y + 12, drive_label, COLOR_BLACK);
// Button at x+4, y+4, w=60 (rounded)
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_DARK_TEXT);
// Draw path bar (shifted right)
// Draw path bar (shifted right, rounded, dark mode)
int path_height = 30;
int path_x = offset_x + 64;
int path_w = win->w - 16 - 64;
draw_bevel_rect(path_x, offset_y + 4, path_w, path_height, true);
draw_string(path_x + 6, offset_y + 10, "Path", COLOR_BLACK);
draw_string(path_x + 46, offset_y + 10, state->current_path, COLOR_BLACK);
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_DARK_TEXT);
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;
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_button(win->x + win->w - 40, offset_y + 4, 30, 30, "<", false);
// Draw back button (right-aligned, rounded)
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_button(win->x + win->w - 160, offset_y + 4, 30, 30, "^", false);
draw_button(win->x + win->w - 125, offset_y + 4, 30, 30, "v", false);
// Draw scroll buttons (left of dropdown, rounded)
draw_rounded_rect_filled(win->x + win->w - 160, offset_y + 4, 30, 30, 6, COLOR_DARK_PANEL);
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
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_y = content_start_y + ((row - state->explorer_scroll_row) * (EXPLORER_ITEM_HEIGHT + EXPLORER_PADDING));
// Draw item background
uint32_t bg_color = (i == state->selected_item) ? COLOR_BLUE : COLOR_WHITE;
draw_bevel_rect(item_x, item_y, EXPLORER_ITEM_WIDTH, EXPLORER_ITEM_HEIGHT, false);
draw_rect(item_x + 2, item_y + 2, EXPLORER_ITEM_WIDTH - 4, EXPLORER_ITEM_HEIGHT - 4, bg_color);
// Draw item background (dark mode with rounded corners)
uint32_t bg_color = (i == state->selected_item) ? 0xFF4A90E2 : COLOR_DARK_PANEL;
uint32_t text_color = (i == state->selected_item) ? COLOR_WHITE : COLOR_DARK_TEXT;
draw_rounded_rect_filled(item_x, item_y, EXPLORER_ITEM_WIDTH, EXPLORER_ITEM_HEIGHT, 6, bg_color);
// 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);
@ -1026,7 +1030,7 @@ static void explorer_paint(Window *win) {
if (explorer_strcmp(state->items[i].name, "RecycleBin") == 0) {
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.
@ -1037,7 +1041,7 @@ static void explorer_paint(Window *win) {
graphics_clear_clipping();
}
// Draw Drive Menu if visible
// Draw Drive Menu if visible (dark mode)
if (state->drive_menu_visible) {
int menu_x = win->x + 4;
int menu_y = offset_y + 34;
@ -1045,8 +1049,7 @@ static void explorer_paint(Window *win) {
int count = disk_get_count();
int menu_h = count * 25;
draw_rect(menu_x, menu_y, menu_w, menu_h, COLOR_LTGRAY);
draw_bevel_rect(menu_x, menu_y, menu_w, menu_h, true);
draw_rounded_rect_filled(menu_x, menu_y, menu_w, menu_h, 6, COLOR_DARK_PANEL);
for (int i = 0; i < count; 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++; }
buf[3+n] = 0;
// Highlight current
// Highlight current (dark blue)
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);
} else {
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));
ExplorerState *state = (ExplorerState*)kmalloc(sizeof(ExplorerState));
win->title = "File Explorer";
win->title = "Files";
win->x = 300 + (explorer_win_count * 30);
win->y = 100 + (explorer_win_count * 30);
win->w = 600;
@ -2014,7 +2017,7 @@ Window* explorer_create_window(const char *path) {
void explorer_init(void) {
ExplorerState *state = (ExplorerState*)kmalloc(sizeof(ExplorerState));
win_explorer.title = "File Explorer";
win_explorer.title = "Files";
win_explorer.x = 300;
win_explorer.y = 100;
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) {
unsigned char uc = (unsigned char)c;
if (uc > 127) return;

View file

@ -14,6 +14,8 @@ typedef struct {
void graphics_init(struct limine_framebuffer *fb);
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_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_string(int x, int y, const char *s, uint32_t color);
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_height = win->h - 28;
// Draw filename bar below title
draw_rect(offset_x, offset_y, content_width, 20, COLOR_GRAY);
draw_string(offset_x + 4, offset_y + 4, "File", COLOR_BLACK);
draw_string(offset_x + 50, offset_y + 4, open_filename, COLOR_BLACK);
// Draw filename bar below title (dark mode)
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_DARK_TEXT);
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_y = offset_y + 2;
draw_button(btn_x_up, btn_y, 20, 16, "^", false);
draw_button(btn_x_up + 24, btn_y, 20, 16, "v", false);
draw_rounded_rect_filled(btn_x_up, btn_y, 20, 16, 4, COLOR_DARK_TITLEBAR);
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
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 max_display_lines = usable_content_height / MD_LINE_HEIGHT;
// Draw content background
draw_rect(win->x + 4, content_start_y, win->w - 24, usable_content_height, COLOR_WHITE);
// Draw content background (dark mode)
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) {
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 extra_spacing = 0;
uint32_t text_color = COLOR_BLACK;
uint32_t text_color = COLOR_DARK_TEXT;
bool use_bold = false;
switch (line->type) {
case MD_LINE_HEADING1:
line_height = MD_LINE_HEIGHT * 2; // Double height
text_color = 0xFF004080; // Dark blue
text_color = 0xFF87CEEB; // Light blue
use_bold = true;
extra_spacing = 4;
break;
case MD_LINE_HEADING2:
line_height = MD_LINE_HEIGHT + 6; // 1.5x height
text_color = 0xFF1060A0; // Medium blue
text_color = 0xFF4A90E2; // Medium blue
use_bold = true;
extra_spacing = 2;
break;
case MD_LINE_HEADING3:
line_height = MD_LINE_HEIGHT + 2; // Slightly larger
text_color = 0xFF2080C0; // Light blue
text_color = 0xFF87CEEB; // Light blue
use_bold = false;
break;
case MD_LINE_BLOCKQUOTE:
text_color = 0xFF808080; // Gray
text_color = 0xFFA0A0A0; // Light gray
break;
case MD_LINE_CODE:
text_color = COLOR_WHITE;
text_color = 0xFF90EE90; // Light green for code
break;
default:
text_color = COLOR_BLACK;
text_color = COLOR_DARK_TEXT;
break;
}

View file

@ -151,21 +151,21 @@ static void minesweeper_right_click(Window *win, int x, int y) {
}
static void minesweeper_paint(Window *win) {
// Background
draw_rect(win->x + 4, win->y + 24, win->w - 8, win->h - 28, COLOR_LTGRAY);
// Background - dark mode
draw_rect(win->x + 4, win->y + 30, win->w - 8, win->h - 34, COLOR_DARK_BG);
// Game status
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) {
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 {
draw_string(win->x + 10, win->y + 30, "", COLOR_BLACK);
draw_string(win->x + 10, win->y + 36, "", COLOR_DARK_TEXT);
}
// Draw grid
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 x = 0; x < GRID_WIDTH; x++) {
@ -173,32 +173,33 @@ static void minesweeper_paint(Window *win) {
int py = grid_start_y + y * CELL_SIZE;
if (revealed[y][x]) {
// Revealed cell - sunken
draw_bevel_rect(px, py, CELL_SIZE, CELL_SIZE, true);
// Revealed cell - dark mode
draw_rounded_rect_filled(px, py, CELL_SIZE, CELL_SIZE, 2, COLOR_DARK_PANEL);
if (grid[y][x] == -1) {
// Mine
draw_string(px + 8, py + 6, "*", COLOR_RED);
draw_string(px + 8, py + 6, "*", COLOR_TRAFFIC_RED);
} else if (grid[y][x] > 0) {
// Number
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
} else {
// Unrevealed cell - raised
draw_bevel_rect(px, py, CELL_SIZE, CELL_SIZE, false);
// Unrevealed cell - raised/button look
draw_rounded_rect_filled(px, py, CELL_SIZE, CELL_SIZE, 2, COLOR_DARK_BORDER);
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;
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) {

View file

@ -24,12 +24,12 @@ static void notepad_ensure_cursor_visible(Window *win) {
}
static void notepad_paint(Window *win) {
// Explicitly draw white background for text
draw_rect(win->x + 4, win->y + 24, win->w - 8, win->h - 28, COLOR_WHITE);
// Dark mode background for text
draw_rect(win->x + 4, win->y + 30, win->w - 8, win->h - 34, COLOR_DARK_BG);
int visual_line = 0;
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;
for (int i = 0; i < win->buf_len; i++) {
@ -37,7 +37,7 @@ static void notepad_paint(Window *win) {
if (win->buffer[i] == '\n') {
visual_line++;
current_x = win->x + 8;
current_y = win->y + 30;
current_y = win->y + 36;
} else {
if (current_x >= window_right) {
visual_line++;
@ -69,7 +69,7 @@ static void notepad_paint(Window *win) {
}
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;
}
}
@ -77,7 +77,7 @@ static void notepad_paint(Window *win) {
// Cursor
if (win->focused) {
int cx = win->x + 8;
int cy = win->y + 30;
int cy = win->y + 36;
int visual_line = 0;
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 &&
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) {
// Toolbar area
draw_rect(win->x + 10, win->y + 30, 40, win->h - 40, COLOR_GRAY);
draw_bevel_rect(win->x + 10, win->y + 30, 40, win->h - 40, true);
// Toolbar area - dark mode
draw_rounded_rect_filled(win->x + 10, win->y + 30, 40, win->h - 40, 6, COLOR_DARK_PANEL);
// 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};
for (int i = 0; i < 6; i++) {
int cy = win->y + 40 + (i * 25);
draw_rect(win->x + 15, cy, 30, 20, 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);
draw_rounded_rect_filled(win->x + 15, cy, 30, 20, 3, colors[i]);
// Highlight selected color
// Highlight selected color with border
if (current_color == colors[i]) {
draw_rect(win->x + 13, cy - 2, 34, 2, COLOR_WHITE);
draw_rect(win->x + 13, cy + 20, 34, 2, COLOR_WHITE);
draw_rounded_rect(win->x + 13, cy - 2, 34, 24, 4, COLOR_DARK_TEXT);
}
}
// Toolbar Buttons
draw_button(win->x + 12, win->y + win->h - 65, 36, 20, "CLR", false);
draw_button(win->x + 12, win->y + win->h - 40, 36, 20, "SAV", false);
// Toolbar Buttons - dark mode with rounded corners
draw_rounded_rect_filled(win->x + 12, win->y + win->h - 65, 36, 20, 4, COLOR_DARK_BORDER);
draw_string(win->x + 18, win->y + win->h - 58, "CLR", COLOR_DARK_TEXT);
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
// Canvas Area with dark background and rounded corners
int canvas_x = win->x + 60;
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) {
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) {
// 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));
if (!files) return;
@ -184,8 +184,8 @@ static void refresh_desktop_icons(void) {
// 3. Layout Icons
if (desktop_auto_align) {
int start_x = 20;
int start_y = 20;
int start_x = 20; // Starting X position for icons
int start_y = 20 + DESKTOP_TOP_DEADSPACE_HEIGHT; // Starting Y position for icons, offset by dead space
int grid_x = 0;
int grid_y = 0;
@ -200,8 +200,8 @@ static void refresh_desktop_icons(void) {
// Place Recycle Bin at bottom-right of grid
if (recycle_idx != -1) {
desktop_icons[recycle_idx].x = start_x + (desktop_max_cols - 1) * 80;
desktop_icons[recycle_idx].y = start_y + (desktop_max_rows_per_col - 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 - 2) * 80; // Align to the second to last row (since one is dead space)
}
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].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) {
grid_y = 0;
grid_x++;
@ -224,7 +224,7 @@ static void refresh_desktop_icons(void) {
if (desktop_icons[i].x != -1) {
int col = (desktop_icons[i].x - 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;
for (int c = 0; c < 16; c++) {
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;
goto found;
}
}
}
found:
found:
if (found_col != -1) {
desktop_icons[i].x = 20 + found_col * 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);
}
// 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) {
if (!win->visible) return;
// Main Body
draw_bevel_rect(win->x, win->y, win->w, win->h, false);
// Dark mode window with rounded corners
// 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
uint32_t title_color = win->focused ? COLOR_RED : COLOR_DKGRAY;
draw_rect(win->x + 3, win->y + 3, win->w - 6, 18, title_color);
draw_string(win->x + 8, win->y + 8, win->title, COLOR_WHITE);
draw_rounded_rect_filled(win->x, win->y, win->w, 22, 8, COLOR_DARK_TITLEBAR);
draw_string(win->x + 28, win->y + 7, win->title, COLOR_DARK_TEXT);
// Close Button (X)
draw_button(win->x + win->w - 20, win->y + 5, 14, 14, "X", false);
// Traffic Light (close button - red)
draw_traffic_light(win->x + 8, win->y + 5);
// Client Area
draw_rect(win->x + 4, win->y + 24, win->w - 8, win->h - 28, COLOR_LTGRAY);
// Client Area with dark background (no rounding)
draw_rect(win->x, win->y + 22, win->w, win->h - 22, COLOR_DARK_BG);
if (win->paint) {
win->paint(win);
@ -665,7 +705,7 @@ static void draw_clock(int x, int y) {
buf[7] = '0' + (s % 10);
buf[8] = 0;
draw_string(x, y, buf, COLOR_BLACK);
draw_string(x, y, buf, COLOR_WHITE);
}
// --- Main Paint Function ---
@ -673,7 +713,6 @@ void wm_paint(void) {
int sw = get_screen_width();
int sh = get_screen_height();
DirtyRect dirty = graphics_get_dirty_rect();
if (dirty.active) {
graphics_set_clipping(dirty.x, dirty.y, dirty.w, dirty.h);
@ -681,8 +720,8 @@ void wm_paint(void) {
graphics_clear_clipping();
}
// 1. Desktop
draw_desktop_background();
// 1. Desktop Background (dark mode)
draw_rect(0, 0, sw, sh, COLOR_DARK_BG);
// Draw Desktop Icons
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);
else if (icon->type == 2) {
// App icon - strip .app for display
// App icon - strip .shortcut for display
char label[64];
int len = 0;
while(icon->name[len] && len < 63) { label[len] = icon->name[len]; len++; }
label[len] = 0;
// Remove .app suffix if present
if (len > 9 && str_ends_with(label, ".shortcut")) {
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, "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, "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, "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 draw_icon(icon->x, icon->y, label);
} else {
if (str_ends_with(icon->name, ".pnt")) draw_paint_icon(icon->x, icon->y, icon->name);
else if (str_ends_with(icon->name, ".md")) {
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")) {
draw_document_icon(icon->x, icon->y, icon->name);
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
// Simple bubble sort by z-index
Window *sorted_windows[32];
for (int i = 0; i < window_count; i++) {
sorted_windows[i] = all_windows[i];
@ -750,7 +787,6 @@ void wm_paint(void) {
Window *win = sorted_windows[i];
if (!win->visible) continue;
if (dirty.active && !win->focused) {
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) {
@ -760,109 +796,131 @@ void wm_paint(void) {
draw_window(win);
}
// 4. Taskbar
draw_rect(0, sh - 28, sw, 28, COLOR_GRAY);
draw_rect(0, sh - 28, sw, 2, COLOR_WHITE); // Top highlight
// 4. Top Menu Bar (macOS style)
draw_rect(0, 0, sw, 40, COLOR_TOPBAR_BG);
// 5. Start Button
draw_bevel_rect(2, sh - 26, 90, 24, start_menu_open);
// Draw Boredos logo
draw_boredos_logo(6, sh - 22, 1);
// Draw BoredOS text
draw_string(35, sh - 18, "BoredOS", COLOR_BLACK);
// Logo dropdown (top-left)
draw_boredos_logo(8, 8, 1);
// Clock
draw_clock(sw - 80, sh - 20);
// Clock (top-right)
draw_clock(sw - 80, 12);
// 6. Start Menu (if open)
// Top menu dropdown (if logo clicked)
if (start_menu_open) {
int menu_h = 250;
int menu_y = sh - 28 - menu_h;
draw_bevel_rect(0, menu_y, 120, menu_h, false);
// Items
draw_string(8, menu_y + 8, "Explorer", COLOR_BLACK);
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);
int menu_h = 100;
draw_rounded_rect_filled(8, 40, 160, menu_h, 8, COLOR_DARK_PANEL);
draw_string(20, 48, "About BoredOS", COLOR_DARK_TEXT);
draw_string(20, 68, "Settings", COLOR_DARK_TEXT);
draw_string(20, 88, "Shutdown", COLOR_DARK_TEXT);
draw_string(20, 108, "Restart", COLOR_DARK_TEXT);
}
// 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) {
int menu_w = 140;
int item_h = 25;
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_bevel_rect(desktop_menu_x, desktop_menu_y, menu_w, menu_h, true);
draw_rounded_rect_filled(desktop_menu_x, desktop_menu_y, menu_w, menu_h, 8, COLOR_DARK_PANEL);
if (desktop_menu_target_icon != -1) {
bool can_paste = explorer_clipboard_has_content();
DesktopIcon *icon = &desktop_icons[desktop_menu_target_icon];
if (icon->type != 1) can_paste = false; // 1 is folder
draw_string(desktop_menu_x + 5, desktop_menu_y + 5, "Cut", COLOR_BLACK);
draw_string(desktop_menu_x + 5, desktop_menu_y + 5 + item_h, "Copy", COLOR_BLACK);
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);
draw_string(desktop_menu_x + 10, desktop_menu_y + 5, "Cut", COLOR_DARK_TEXT);
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 + 10, desktop_menu_y + 5 + item_h * 3, "Delete", COLOR_TRAFFIC_RED);
draw_string(desktop_menu_x + 10, desktop_menu_y + 5 + item_h * 4, "Rename", COLOR_DARK_TEXT);
} else {
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 + 5, desktop_menu_y + 5 + item_h, "New Folder", COLOR_BLACK);
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, "New File", COLOR_DARK_TEXT);
draw_string(desktop_menu_x + 10, desktop_menu_y + 5 + item_h, "New Folder", COLOR_DARK_TEXT);
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) {
int dlg_w = 300; int dlg_h = 110;
int dlg_x = (sw - dlg_w) / 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_bevel_rect(dlg_x, dlg_y, dlg_w, dlg_h, true);
draw_rounded_rect_filled(dlg_x, dlg_y, dlg_w, dlg_h, 8, COLOR_DARK_PANEL);
const char *title = "Rename";
const char *btn_text = "Rename";
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"; }
draw_string(dlg_x + 10, dlg_y + 10, title, COLOR_BLACK);
draw_bevel_rect(dlg_x + 10, dlg_y + 35, 280, 20, false);
draw_string(dlg_x + 15, dlg_y + 40, desktop_dialog_input, COLOR_BLACK);
draw_string(dlg_x + 10, dlg_y + 10, title, COLOR_DARK_TEXT);
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_DARK_TEXT);
// 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_button(dlg_x + 170, dlg_y + 65, 80, 25, "Cancel", false);
draw_rounded_rect_filled(dlg_x + 50, dlg_y + 65, 80, 25, 4, COLOR_DARK_BORDER);
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) {
int mw = 320;
int mh = 100;
int mx = (sw - mw) / 2;
int my = (sh - mh) / 2;
draw_rect(mx, my, mw, mh, COLOR_LTGRAY);
draw_bevel_rect(mx, my, mw, mh, false);
draw_rect(mx + 3, my + 3, mw - 6, 20, COLOR_BLUE);
draw_string(mx + 8, my + 8, msg_box_title, COLOR_WHITE);
draw_string(mx + 10, my + 40, msg_box_text, COLOR_BLACK);
draw_button(mx + mw/2 - 30, my + 70, 60, 20, "OK", false);
draw_rounded_rect_filled(mx, my, mw, mh, 8, COLOR_DARK_PANEL);
draw_string(mx + 15, my + 10, msg_box_title, COLOR_DARK_TEXT);
draw_string(mx + 10, my + 40, msg_box_text, COLOR_DARK_TEXT);
draw_rounded_rect_filled(mx + mw/2 - 30, my + 70, 60, 20, 4, COLOR_DARK_BORDER);
draw_string(mx + mw/2 - 18, my + 75, "OK", COLOR_DARK_TEXT);
}
// Custom Overlay (VM Graphics)
@ -872,8 +930,6 @@ void wm_paint(void) {
// Draw Dragged Icon
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...");
else if (drag_icon_type == 2) draw_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
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) {
char path[128] = "/Desktop/";
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
if (rect_contains(2, sh - 26, 90, 24, x, y)) {
// Check Top Bar Logo (toggle dropdown menu)
if (rect_contains(8, 8, 24, 24, x, y)) {
start_menu_open = !start_menu_open;
force_redraw = true;
pending_desktop_icon_click = -1;
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
Window *topmost = NULL;
@ -1095,8 +1169,8 @@ void wm_handle_click(int x, int y) {
if (topmost != NULL) {
wm_bring_to_front(topmost);
// Check close button
if (rect_contains(topmost->x + topmost->w - 20, topmost->y + 5, 14, 14, x, y)) {
// Check traffic light close button (now at top-left)
if (rect_contains(topmost->x + 8, topmost->y + 9, 12, 12, x, y)) {
topmost->visible = false;
// Reset window state on close
if (topmost == &win_explorer) {
@ -1108,7 +1182,7 @@ void wm_handle_click(int x, int y) {
} else if (topmost == &win_paint) {
paint_reset();
}
} else if (y < topmost->y + 24) {
} else if (y < topmost->y + 30) {
// Dragging the title bar
is_dragging = true;
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) {
start_menu_open = false;
}
@ -1229,24 +1303,30 @@ void wm_handle_right_click(int x, int y) {
paint_reset_last_pos();
}
// Check Start Menu for potential drag
if (start_menu_open) {
int menu_h = 250;
int menu_y = sh - 28 - menu_h;
if (rect_contains(0, menu_y, 120, menu_h, mx, my)) {
if (my < menu_y + 25) start_menu_pending_app = "Explorer";
else if (my < menu_y + 45) start_menu_pending_app = "Notepad";
else if (my < menu_y + 65) start_menu_pending_app = "Editor";
else if (my < menu_y + 85) start_menu_pending_app = "Terminal";
else if (my < menu_y + 105) start_menu_pending_app = "Calculator";
else if (my < menu_y + 125) start_menu_pending_app = "Minesweeper";
else if (my < menu_y + 145) start_menu_pending_app = "Control Panel";
else if (my < menu_y + 165) start_menu_pending_app = "Paint";
else if (my < menu_y + 185) start_menu_pending_app = "About";
else if (my < menu_y + 205) start_menu_pending_app = "Shutdown";
else start_menu_pending_app = "Restart";
} else {
wm_handle_click(mx, my);
// Check Dock for app clicks (bottom of screen, floating)
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;
int dock_bg_w = total_dock_width + 24;
if (rect_contains(dock_bg_x, dock_y, dock_bg_w, dock_h, mx, my)) {
int dock_x = (sw - total_dock_width) / 2;
// Check which dock item was clicked
int item_x = mx - dock_x;
if (item_x >= 0) {
int item = item_x / (dock_item_size + dock_spacing);
if (item == 0) start_menu_pending_app = "Files";
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 {
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++) {
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 (str_starts_with(win->title, "File Explorer")) {
if (str_starts_with(win->title, "Files")) {
drag_src_win = win;
explorer_clear_click_state(win);
}
@ -1332,12 +1412,14 @@ void wm_handle_right_click(int x, int y) {
force_redraw = true;
}
// Handle Start Menu Click (Mouse Up without Drag)
// Handle Dock App Click (Mouse Up without Drag)
if (start_menu_pending_app) {
// Launch App
if (str_starts_with(start_menu_pending_app, "Explorer")) {
explorer_open_directory("/");
if (str_starts_with(start_menu_pending_app, "Files")) {
explorer_reset();
wm_bring_to_front(&win_explorer);
} else if (str_starts_with(start_menu_pending_app, "Notepad")) {
notepad_reset();
wm_bring_to_front(&win_notepad);
} else if (str_starts_with(start_menu_pending_app, "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);
} else if (str_starts_with(start_menu_pending_app, "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);
} else if (str_starts_with(start_menu_pending_app, "Paint")) {
wm_bring_to_front(&win_paint);
@ -1359,7 +1441,6 @@ void wm_handle_right_click(int x, int y) {
cli_cmd_reboot(NULL);
}
start_menu_open = false;
start_menu_pending_app = NULL;
force_redraw = true;
}
@ -1378,14 +1459,15 @@ void wm_handle_right_click(int x, int y) {
wm_bring_to_front(&win_calculator); handled = true;
} else if (str_ends_with(icon->name, "Minesweeper.shortcut")) {
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;
} else if (str_ends_with(icon->name, "Terminal.shortcut")) {
wm_bring_to_front(&win_cmd); handled = true;
} else if (str_ends_with(icon->name, "About.shortcut")) {
wm_bring_to_front(&win_about); handled = true;
} else if (str_ends_with(icon->name, "Explorer.shortcut")) {
explorer_open_directory("/"); handled = true;
} else if (str_ends_with(icon->name, "Explorer.shortcut")) { // Files
explorer_reset();
wm_bring_to_front(&win_explorer);
} else if (str_ends_with(icon->name, "Recycle Bin.shortcut")) {
explorer_open_directory("/RecycleBin"); handled = true;
} 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++) {
Window *win = all_windows[w];
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;
topmost_z = win->z_index;
}
@ -1511,7 +1593,7 @@ void wm_handle_right_click(int x, int y) {
if (!dropped_on_target && !from_desktop) {
// Dragged from Explorer to Desktop
// 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!");
} else {
explorer_import_file_to(&win_explorer, drag_file_path, "/Desktop");

View file

@ -23,6 +23,19 @@
#define COLOR_APPLE_INDIGO 0xFF4B0082
#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;
struct Window {
char *title;
@ -67,6 +80,9 @@ extern void (*wm_custom_paint_hook)(void);
// Drawing helpers
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_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_folder_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_recycle_bin_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
extern bool desktop_snap_to_grid;