Memory fixes userspace

This commit is contained in:
boreddevnl
2026-02-26 21:09:18 +01:00
parent 786eac0345
commit 2801dbc21f
57 changed files with 215 additions and 183 deletions

View File

@@ -915,7 +915,7 @@ static void explorer_draw_file_icon(int x, int y, bool is_dir, uint32_t color, c
static void explorer_paint(Window *win) {
ExplorerState *state = (ExplorerState*)win->data;
int offset_x = win->x + 4;
int offset_y = win->y + 24;
int offset_y = win->y + 20;
DirtyRect dirty = graphics_get_dirty_rect();
// Fill background with dark mode
@@ -1367,7 +1367,7 @@ static void explorer_handle_click(Window *win, int x, int y) {
// Handle Drive Menu Selection
if (state->drive_menu_visible) {
int menu_x = 4; // Window relative
int menu_y = 50; // 24+26
int menu_y = 26; // 24+26
int menu_w = 80;
int count = disk_get_count();
int menu_h = count * 25;
@@ -1396,7 +1396,7 @@ static void explorer_handle_click(Window *win, int x, int y) {
// Handle dropdown menu clicks
if (state->dropdown_menu_visible) {
int dropdown_btn_x = win->w - 90; // Window-relative
int menu_y = 50; // Window-relative (offset_y + 26, where offset_y = 24)
int menu_y = 26; // Window-relative (offset_y + 26, where offset_y = 24)
// New File
if (x >= dropdown_btn_x && x < dropdown_btn_x + DROPDOWN_MENU_WIDTH &&
@@ -1434,7 +1434,7 @@ static void explorer_handle_click(Window *win, int x, int y) {
// x, y are already relative to window (0,0 is top-left of window content area)
// Check Drive Button
int button_y = 27;
int button_y = 3;
if (x >= 4 && x < 64 && y >= button_y && y < button_y + 22) {
state->drive_menu_visible = !state->drive_menu_visible;
state->dropdown_menu_visible = false; // Close other menu
@@ -1476,7 +1476,7 @@ static void explorer_handle_click(Window *win, int x, int y) {
}
// File items start at y=64 relative to window
int content_start_y = 54;
int content_start_y = 30;
int offset_x = 4;
for (int i = 0; i < state->item_count; i++) {
@@ -1647,7 +1647,7 @@ static void explorer_handle_key(Window *win, char c) {
static void explorer_handle_right_click(Window *win, int x, int y) {
ExplorerState *state = (ExplorerState*)win->data;
// File items start at y=64 relative to window
int content_start_y = 54;
int content_start_y = 30;
int offset_x = 4;
for (int i = 0; i < state->item_count; i++) {

View File

@@ -46,6 +46,8 @@ typedef struct {
uint32_t total_sectors;
uint32_t partition_offset; // LBA offset of partition start
bool mounted;
uint32_t cached_fat_sector;
uint8_t cached_fat_buf[512];
} FAT32_Volume;
static FAT32_Volume volumes[26]; // A-Z
@@ -413,6 +415,7 @@ static bool realfs_mount(char drive) {
volumes[idx].fat_size = bpb->sectors_per_fat_32;
volumes[idx].total_sectors = bpb->total_sectors_32;
volumes[idx].mounted = true;
volumes[idx].cached_fat_sector = 0xFFFFFFFF;
fs_serial_str("[FAT32] mounted drive ");
fs_serial_char(drive);
@@ -456,18 +459,16 @@ static uint32_t realfs_next_cluster(FAT32_Volume *vol, uint32_t cluster) {
uint32_t fat_sector = vol->fat_begin_lba + (cluster * 4) / 512;
uint32_t fat_offset = (cluster * 4) % 512;
uint8_t *buf = (uint8_t*)kmalloc(512);
if (!buf) return 0xFFFFFFFF;
if (vol->disk->read_sector(vol->disk, fat_sector, buf) != 0) {
kfree(buf);
return 0xFFFFFFFF;
if (vol->cached_fat_sector != fat_sector) {
if (vol->disk->read_sector(vol->disk, fat_sector, vol->cached_fat_buf) != 0) {
return 0xFFFFFFFF;
}
vol->cached_fat_sector = fat_sector;
}
uint32_t next = *(uint32_t*)&buf[fat_offset];
uint32_t next = *(uint32_t*)&vol->cached_fat_buf[fat_offset];
next &= 0x0FFFFFFF; // Mask top 4 bits
kfree(buf);
return next;
}
@@ -791,6 +792,9 @@ static uint32_t realfs_allocate_cluster(FAT32_Volume *vol) {
if ((val & 0x0FFFFFFF) == 0) {
*(uint32_t*)&fat_buf[offset] = 0x0FFFFFFF; // EOC
vol->disk->write_sector(vol->disk, sector, fat_buf);
if (vol->cached_fat_sector == sector) {
vol->cached_fat_sector = 0xFFFFFFFF;
}
kfree(fat_buf);
return current;
}

View File

@@ -7,6 +7,7 @@
#define GUI_CMD_MARK_DIRTY 4
#define GUI_CMD_GET_EVENT 5
#define GUI_CMD_DRAW_ROUNDED_RECT_FILLED 6
#define GUI_CMD_DRAW_IMAGE 7
#define GUI_EVENT_NONE 0
#define GUI_EVENT_PAINT 1

View File

@@ -209,10 +209,18 @@ uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, u
serial_write("Kernel: Dims initialized.\n");
size_t pixel_size = 0;
// Safe allocation
size_t pixel_size = (size_t)win->w * win->h * 4;
win->pixels = kmalloc(pixel_size);
win->comp_pixels = kmalloc(pixel_size);
size_t client_h = win->h - 20;
if (win->w <= 0 || win->h <= 20) {
// Invalid dimensions, but prevent underflow/bad alloc
win->pixels = NULL;
win->comp_pixels = NULL;
} else {
pixel_size = (size_t)win->w * client_h * 4;
win->pixels = kmalloc(pixel_size);
win->comp_pixels = kmalloc(pixel_size);
}
serial_write("Kernel: Buffers allocated.\n");
@@ -259,10 +267,10 @@ uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, u
if (rx < 0) { rw += rx; rx = 0; }
if (ry < 0) { rh += ry; ry = 0; }
if (rx + rw > win->w) rw = win->w - rx;
if (ry + rh > win->h) rh = win->h - ry;
if (ry + rh > (win->h - 20)) rh = (win->h - 20) - ry;
if (rw > 0 && rh > 0) {
graphics_set_render_target(win->pixels, win->w, win->h);
graphics_set_render_target(win->pixels, win->w, win->h - 20);
draw_rect(rx, ry, rw, rh, color);
graphics_set_render_target(NULL, 0, 0);
}
@@ -293,10 +301,10 @@ uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, u
if (rx < 0) { rw += rx; rx = 0; }
if (ry < 0) { rh += ry; ry = 0; }
if (rx + rw > win->w) rw = win->w - rx;
if (ry + rh > win->h) rh = win->h - ry;
if (ry + rh > (win->h - 20)) rh = (win->h - 20) - ry;
if (rw > 0 && rh > 0) {
graphics_set_render_target(win->pixels, win->w, win->h);
graphics_set_render_target(win->pixels, win->w, win->h - 20);
draw_rounded_rect_filled(rx, ry, rw, rh, rr, color);
graphics_set_render_target(NULL, 0, 0);
}
@@ -330,8 +338,8 @@ uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, u
if (win->pixels) {
// String clipping is handled by draw_char -> put_pixel,
// but we ensure coordinate sanity here
if (ux >= -100 && ux < win->w && uy >= -100 && uy < win->h) {
graphics_set_render_target(win->pixels, win->w, win->h);
if (ux >= -100 && ux < win->w && uy >= -100 && uy < (win->h - 20)) {
graphics_set_render_target(win->pixels, win->w, win->h - 20);
draw_string(ux, uy, kernel_str, color);
graphics_set_render_target(NULL, 0, 0);
}
@@ -339,6 +347,41 @@ uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, u
draw_string(win->x + ux, win->y + uy, kernel_str, color);
}
asm volatile("push %0; popfq" : : "r"(rflags));
}
} else if (cmd == GUI_CMD_DRAW_IMAGE) {
Window *win = (Window *)arg2;
uint64_t *u_params = (uint64_t *)arg3;
uint32_t *image_data = (uint32_t *)arg4;
if (win && u_params && image_data) {
uint64_t params[4];
for (int i = 0; i < 4; i++) params[i] = u_params[i];
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
if (win->pixels) {
int rx = (int)params[0]; int ry = (int)params[1];
int rw = (int)params[2]; int rh = (int)params[3];
int src_x_offset = 0;
int src_y_offset = 0;
if (rx < 0) { src_x_offset = -rx; rw += rx; rx = 0; }
if (ry < 0) { src_y_offset = -ry; rh += ry; ry = 0; }
if (rx + rw > win->w) rw = win->w - rx;
if (ry + rh > (win->h - 20)) rh = (win->h - 20) - ry;
if (rw > 0 && rh > 0) {
for (int y = 0; y < rh; y++) {
uint32_t *dest = &win->pixels[(ry + y) * win->w + rx];
uint32_t *src = &image_data[(src_y_offset + y) * (int)params[2] + src_x_offset];
for (int x = 0; x < rw; x++) {
dest[x] = src[x];
}
}
}
}
asm volatile("push %0; popfq" : : "r"(rflags));
}
} else if (cmd == GUI_CMD_MARK_DIRTY) {
@@ -351,7 +394,7 @@ uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, u
// Dual-buffer commit: copy pixels to comp_pixels
if (win->pixels && win->comp_pixels) {
extern void mem_memcpy(void *dest, const void *src, size_t len);
mem_memcpy(win->comp_pixels, win->pixels, (size_t)win->w * win->h * 4);
mem_memcpy(win->comp_pixels, win->pixels, (size_t)win->w * (win->h - 20) * 4);
}
wm_mark_dirty(win->x + (int)params[0], win->y + (int)params[1], (int)params[2], (int)params[3]);
}
@@ -458,14 +501,19 @@ uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, u
uint64_t start_page = (old_end + 0xFFF) & ~0xFFF;
uint64_t end_page = (new_end + 0xFFF) & ~0xFFF;
for (uint64_t page = start_page; page < end_page; page += 4096) {
void *phys = kmalloc_aligned(4096, 4096);
if (!phys) return (uint64_t)-1; // Out of memory
if (end_page > start_page) {
uint64_t total_size = end_page - start_page;
void *phys_block = kmalloc_aligned(total_size, 4096);
if (!phys_block) return (uint64_t)-1; // Out of memory
extern void mem_memset(void *dest, int val, size_t len);
mem_memset(phys, 0, 4096);
mem_memset(phys_block, 0, total_size);
paging_map_page(proc->pml4_phys, page, v2p((uint64_t)phys), 0x07); // PT_PRESENT | PT_RW | PT_USER
uint64_t phys_addr = (uint64_t)phys_block;
for (uint64_t page = start_page; page < end_page; page += 4096) {
paging_map_page(proc->pml4_phys, page, v2p(phys_addr), 0x07); // PT_PRESENT | PT_RW | PT_USER
phys_addr += 4096;
}
}
}

View File

@@ -86,12 +86,12 @@ static void update_display(void) {
static void calculator_paint(void) {
int w = 180;
int h = 230;
ui_draw_rect(win_calculator, 4, 30, w - 8, h - 34, COLOR_DARK_BG);
ui_draw_rounded_rect_filled(win_calculator, 10, 36, w - 20, 25, 6, COLOR_DARK_PANEL);
ui_draw_rect(win_calculator, 4, 4, w - 8, h - 34, COLOR_DARK_BG);
ui_draw_rounded_rect_filled(win_calculator, 10, 10, w - 20, 25, 6, COLOR_DARK_PANEL);
int text_w = display_buf_len * 8;
int text_x = w - 15 - text_w;
ui_draw_string(win_calculator, text_x, 44, display_buffer, COLOR_DARK_TEXT);
ui_draw_string(win_calculator, text_x, 18, display_buffer, COLOR_DARK_TEXT);
const char *labels[] = {
"C", "sqr", "rt", "/",
@@ -105,7 +105,7 @@ static void calculator_paint(void) {
int bh = 25;
int gap = 5;
int start_x = 10;
int start_y = 70;
int start_y = 40;
for (int i = 0; i < 20; i++) {
int r = i / 4;
@@ -136,7 +136,7 @@ static void calculator_click(int x, int y) {
int bh = 25;
int gap = 5;
int start_x = 10;
int start_y = 65; // Matches the hitboxes
int start_y = 35; // Matches the hitboxes
for (int i = 0; i < 20; i++) {
int r = i / 4;

Binary file not shown.

View File

@@ -4,7 +4,6 @@ int main() {
const char* msg = "Attempting to crash via null dereference...\n";
sys_write(1, msg, 45);
// Null pointer dereference (should not crash the system and instead get this process killed)
volatile int* p = (int*)0;
*p = 123;

Binary file not shown.

Binary file not shown.

View File

@@ -39,3 +39,8 @@ void ui_mark_dirty(ui_window_t win, int x, int y, int w, int h) {
uint64_t params[4] = { (uint64_t)x, (uint64_t)y, (uint64_t)w, (uint64_t)h };
syscall3(SYS_GUI, GUI_CMD_MARK_DIRTY, (uint64_t)win, (uint64_t)params);
}
void ui_draw_image(ui_window_t win, int x, int y, int w, int h, uint32_t *image_data) {
uint64_t params[4] = { (uint64_t)x, (uint64_t)y, (uint64_t)w, (uint64_t)h };
syscall4(SYS_GUI, GUI_CMD_DRAW_IMAGE, (uint64_t)win, (uint64_t)params, (uint64_t)image_data);
}

View File

@@ -11,6 +11,7 @@
#define GUI_CMD_MARK_DIRTY 4
#define GUI_CMD_GET_EVENT 5
#define GUI_CMD_DRAW_ROUNDED_RECT_FILLED 6
#define GUI_CMD_DRAW_IMAGE 7
// Event Types
#define GUI_EVENT_NONE 0
@@ -42,5 +43,6 @@ void ui_draw_rect(ui_window_t win, int x, int y, int w, int h, uint32_t color);
void ui_draw_rounded_rect_filled(ui_window_t win, int x, int y, int w, int h, int radius, uint32_t color);
void ui_draw_string(ui_window_t win, int x, int y, const char *str, uint32_t color);
void ui_mark_dirty(ui_window_t win, int x, int y, int w, int h);
void ui_draw_image(ui_window_t win, int x, int y, int w, int h, uint32_t *image_data);
#endif

Binary file not shown.

View File

@@ -24,9 +24,6 @@ static BlockMeta *find_free_block(BlockMeta **last, size_t size) {
static BlockMeta *request_space(BlockMeta* last, size_t size) {
BlockMeta *block;
block = (BlockMeta *)sys_sbrk(0);
// Ask for space, ensuring everything stays 8-byte aligned if sizes are odd.
// For simplicity, we just request exactly what is needed,
// but typically `size` should be aligned.
size_t align = 8;
if (size % align != 0) {
size += align - (size % align);
@@ -70,7 +67,6 @@ void *malloc(size_t size) {
if (!block) return NULL;
} else { // Found free block
block->free = 0;
// We could split the block here if block->size is much larger than size...
}
}

View File

@@ -59,11 +59,10 @@ uint64_t syscall5(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3,
return ret;
}
// C-Friendly Wrappers
void sys_exit(int status) {
syscall1(SYS_EXIT, (uint64_t)status);
while (1); // Halt
while (1);
}
int sys_write(int fd, const char *buf, int len) {

View File

@@ -235,7 +235,7 @@ static void md_draw_text_bold(ui_window_t win, int x, int y, const char *text, u
static void md_paint(ui_window_t win) {
int offset_x = 4;
int offset_y = 24;
int offset_y = 0;
int content_width = win_w - 8;
int content_height = win_h - 28;
@@ -392,7 +392,7 @@ static void md_handle_key(char c) {
static void md_handle_click(int x, int y) {
int content_width = win_w - 8;
int btn_x_up = 4 + content_width - 50;
int btn_y = 24 + 2;
int btn_y = 2;
if (x >= btn_x_up && x < btn_x_up + 20 && y >= btn_y && y < btn_y + 16) {
scroll_top -= 3;
if (scroll_top < 0) scroll_top = 0;
@@ -423,15 +423,15 @@ int main(int argc, char **argv) {
if (ui_get_event(win, &ev)) {
if (ev.type == GUI_EVENT_PAINT) {
md_paint(win);
ui_mark_dirty(win, 0, 0, win_w, win_h);
ui_mark_dirty(win, 0, 0, win_w, win_h - 20);
} else if (ev.type == GUI_EVENT_CLICK) {
md_handle_click(ev.arg1, ev.arg2);
md_paint(win);
ui_mark_dirty(win, 0, 0, win_w, win_h);
ui_mark_dirty(win, 0, 0, win_w, win_h - 20);
} else if (ev.type == GUI_EVENT_KEY) {
md_handle_key((char)ev.arg1);
md_paint(win);
ui_mark_dirty(win, 0, 0, win_w, win_h);
ui_mark_dirty(win, 0, 0, win_w, win_h - 20);
} else if (ev.type == GUI_EVENT_CLOSE) {
sys_exit(0);
}

Binary file not shown.

View File

@@ -26,14 +26,13 @@ static void debug_print(const char *msg) {
#define CELL_SIZE 20
// Game state
static int grid[GRID_HEIGHT][GRID_WIDTH]; // -1 = mine, 0-8 = adjacent mine count
static int grid[GRID_HEIGHT][GRID_WIDTH];
static bool revealed[GRID_HEIGHT][GRID_WIDTH];
static bool flagged[GRID_HEIGHT][GRID_WIDTH];
static bool game_over = false;
static bool game_won = false;
static int revealed_count = 0;
// Helper: Random number generator (simple LCG)
static uint32_t random_seed = 12345;
static uint32_t random_next(void) {
random_seed = random_seed * 1103515245 + 12345;
@@ -120,10 +119,8 @@ static void reveal_cell(int x, int y) {
}
}
} else if (grid[y][x] == 0) {
// Empty cell - flood fill
flood_fill(x, y);
} else {
// Numbered cell
revealed[y][x] = true;
revealed_count++;
}
@@ -144,21 +141,19 @@ static void flag_cell(int x, int y) {
static void minesweeper_paint(ui_window_t win) {
int win_w = 240, win_h = 340;
// Background - dark mode
ui_draw_rect(win, 4, 30, win_w - 8, win_h - 34, COLOR_DARK_BG);
ui_draw_rect(win, 4, 0, win_w - 8, win_h - 34, COLOR_DARK_BG);
// Game status
if (game_over) {
ui_draw_string(win, 10, 36, "Game Over!", COLOR_TRAFFIC_RED);
ui_draw_string(win, 10, 6, "Game Over!", COLOR_TRAFFIC_RED);
} else if (game_won) {
ui_draw_string(win, 10, 36, "You Won!", 0xFF00FF00); // Bright green
ui_draw_string(win, 10, 6, "You Won!", 0xFF00FF00); // Bright green
} else {
ui_draw_string(win, 10, 36, "", COLOR_DARK_TEXT);
ui_draw_string(win, 10, 6, "", COLOR_DARK_TEXT);
}
// Draw grid
int grid_start_x = 10;
int grid_start_y = 56;
int grid_start_y = 26;
for (int y = 0; y < GRID_HEIGHT; y++) {
for (int x = 0; x < GRID_WIDTH; x++) {
@@ -196,7 +191,7 @@ static void minesweeper_paint(ui_window_t win) {
static void minesweeper_handle_click(ui_window_t win, int x, int y, int button) {
int grid_start_x = 10;
int grid_start_y = 56;
int grid_start_y = 26;
int btn_y = grid_start_y + GRID_HEIGHT * CELL_SIZE + 10;
// Check "New Game" button
@@ -231,7 +226,6 @@ int main(int argc, char **argv) {
ui_window_t win = ui_window_create("Minesweeper", 250, 100, 240, 340);
if (!win) return 1;
// Use current time or something for seed? No syscall for time right now.
random_seed = 987654321;
init_game();
@@ -240,17 +234,17 @@ int main(int argc, char **argv) {
if (ui_get_event(win, &ev)) {
if (ev.type == GUI_EVENT_PAINT) {
minesweeper_paint(win);
ui_mark_dirty(win, 0, 0, 240, 340);
ui_mark_dirty(win, 0, 0, 240, 320);
} else if (ev.type == GUI_EVENT_CLICK) {
debug_print("[MINESWEEPER] LEFT CLICK");
minesweeper_handle_click(win, ev.arg1, ev.arg2, ev.type);
minesweeper_paint(win);
ui_mark_dirty(win, 0, 0, 240, 340);
ui_mark_dirty(win, 0, 0, 240, 320);
} else if (ev.type == GUI_EVENT_RIGHT_CLICK) {
debug_print("[MINESWEEPER] RIGHT CLICK DETECTED");
minesweeper_handle_click(win, ev.arg1, ev.arg2, ev.type);
minesweeper_paint(win);
ui_mark_dirty(win, 0, 0, 240, 340);
ui_mark_dirty(win, 0, 0, 240, 320);
} else if (ev.type == GUI_EVENT_CLOSE) {
sys_exit(0);
}

Binary file not shown.

View File

@@ -241,8 +241,7 @@ int main(int argc, char **argv) {
sys_exit(0);
}
} else {
// Optional: sys_yield() or similar to avoid high CPU
// For now, just keep looping but it's better than nothing
for(volatile int i=0; i<10000; i++);
}
}

Binary file not shown.

View File

@@ -50,24 +50,17 @@ static void paint_reset(void) {
static void paint_paint(ui_window_t win) {
int canvas_x = 60;
int canvas_y = 30;
int canvas_y = 0;
// Canvas Area with dark background and rounded corners (draw first so it's behind everything)
ui_draw_rounded_rect_filled(win, canvas_x - 2, canvas_y - 2, CANVAS_W + 4, CANVAS_H + 4, 4, COLOR_DARK_BG);
// Toolbar area - dark mode
ui_draw_rounded_rect_filled(win, 10, 30, 40, 260 - 40, 6, COLOR_DARK_PANEL);
ui_draw_rounded_rect_filled(win, 10, 0, 40, 230, 6, COLOR_DARK_PANEL);
// 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 = 40 + (i * 25);
int cy = 10 + (i * 25);
ui_draw_rounded_rect_filled(win, 15, cy, 30, 20, 3, colors[i]);
// Highlight selected color with border
if (current_color == colors[i]) {
// Note: libui might not have draw_rounded_rect (hollow), so we just draw four lines simulating it
// or we use ui_draw_rect for hollow border
ui_draw_rect(win, 13, cy - 2, 34, 1, COLOR_DARK_TEXT);
ui_draw_rect(win, 13, cy - 2 + 24, 34, 1, COLOR_DARK_TEXT);
ui_draw_rect(win, 13, cy - 2, 1, 24, COLOR_DARK_TEXT);
@@ -75,12 +68,11 @@ static void paint_paint(ui_window_t win) {
}
}
// Toolbar Buttons - dark mode with rounded corners
ui_draw_rounded_rect_filled(win, 12, 260 - 65, 36, 20, 4, COLOR_DARK_BORDER);
ui_draw_string(win, 18, 260 - 58, "CLR", COLOR_DARK_TEXT);
ui_draw_rounded_rect_filled(win, 12, 230 - 65, 36, 20, 4, COLOR_DARK_BORDER);
ui_draw_string(win, 18, 230 - 58, "CLR", COLOR_DARK_TEXT);
ui_draw_rounded_rect_filled(win, 12, 260 - 40, 36, 20, 4, COLOR_DARK_BORDER);
ui_draw_string(win, 18, 260 - 33, "SAV", COLOR_DARK_TEXT);
ui_draw_rounded_rect_filled(win, 12, 230 - 40, 36, 20, 4, COLOR_DARK_BORDER);
ui_draw_string(win, 18, 230 - 33, "SAV", COLOR_DARK_TEXT);
// Draw canvas content
if (canvas_buffer) {
@@ -93,7 +85,7 @@ static void paint_paint(ui_window_t win) {
}
}
static void paint_put_brush(ui_window_t win, int cx, int cy) {
static void paint_put_brush(ui_window_t win, int cx, int cy, int *min_x, int *min_y, int *max_x, int *max_y) {
if (!canvas_buffer) return;
for (int dy = 0; dy < 2; dy++) {
for (int dx = 0; dx < 2; dx++) {
@@ -101,26 +93,32 @@ static void paint_put_brush(ui_window_t win, int cx, int cy) {
int py = cy + dy;
if (px >= 0 && px < CANVAS_W && py >= 0 && py < CANVAS_H) {
canvas_buffer[py * CANVAS_W + px] = current_color;
ui_draw_rect(win, 60 + px, 30 + py, 1, 1, current_color);
ui_draw_rect(win, 60 + px, 0 + py, 1, 1, current_color);
if (px < *min_x) *min_x = px;
if (py < *min_y) *min_y = py;
if (px > *max_x) *max_x = px;
if (py > *max_y) *max_y = py;
}
}
}
ui_mark_dirty(win, 60 + cx, 30 + cy, 2, 2);
}
void paint_handle_mouse(ui_window_t win, int x, int y) {
int cx = x - 60;
int cy = y - 30;
int cy = y;
if (cx < 0 || cx >= CANVAS_W || cy < 0 || cy >= CANVAS_H) {
last_mx = -1;
return;
}
int min_x = CANVAS_W, min_y = CANVAS_H;
int max_x = -1, max_y = -1;
if (last_mx == -1) {
paint_put_brush(win, cx, cy);
paint_put_brush(win, cx, cy, &min_x, &min_y, &max_x, &max_y);
} else {
// Bresenham's line algorithm to fill gaps between points
int x0 = last_mx, y0 = last_my;
int x1 = cx, y1 = cy;
int dx = (x1 - x0 > 0) ? (x1 - x0) : (x0 - x1);
@@ -130,13 +128,18 @@ void paint_handle_mouse(ui_window_t win, int x, int y) {
int err = dx - dy;
while (1) {
paint_put_brush(win, x0, y0);
paint_put_brush(win, x0, y0, &min_x, &min_y, &max_x, &max_y);
if (x0 == x1 && y0 == y1) break;
int e2 = 2 * err;
if (e2 > -dy) { err -= dy; x0 += sx; }
if (e2 < dx) { err += dx; y0 += sy; }
}
}
if (min_x <= max_x && min_y <= max_y) {
ui_mark_dirty(win, 60 + min_x, 0 + min_y, (max_x - min_x) + 1, (max_y - min_y) + 1);
}
last_mx = cx;
last_my = cy;
}
@@ -146,11 +149,9 @@ void paint_reset_last_pos(void) {
last_my = -1;
}
// Simple window message dialog wrapper using syscall
static void wm_show_message(const char *title, const char *msg) {
// Wait, userland doesn't have wm_show_message syscall available yet, or maybe it does?
// We didn't add it or GUI_EVENT doesn't support it directly.
// For now we do nothing, or just open a small window.
}
static void paint_save(const char *path) {
@@ -181,13 +182,13 @@ void paint_load(const char *path) {
static void paint_click(ui_window_t win, int x, int y) {
// Check Buttons
if (x >= 12 && x < 48) {
if (y >= 260 - 65 && y < 260 - 45) {
if (y >= 230 - 65 && y < 230 - 45) {
paint_reset();
paint_paint(win);
ui_mark_dirty(win, 0, 0, 380, 260);
ui_mark_dirty(win, 0, 0, 380, 230);
return;
}
if (y >= 260 - 40 && y < 260 - 20) {
if (y >= 230 - 40 && y < 230 - 20) {
paint_save(current_file_path);
return;
}
@@ -196,12 +197,12 @@ static void paint_click(ui_window_t win, int x, int y) {
// Check Palette
if (x >= 15 && x < 45) {
for (int i = 0; i < 6; i++) {
int cy = 40 + (i * 25);
int cy = 10 + (i * 25);
if (y >= cy && y < cy + 20) {
uint32_t colors[] = {COLOR_BLACK, COLOR_RED, COLOR_APPLE_GREEN, COLOR_APPLE_BLUE, COLOR_APPLE_YELLOW, COLOR_WHITE};
current_color = colors[i];
paint_paint(win);
ui_mark_dirty(win, 0, 0, 380, 260);
ui_mark_dirty(win, 0, 0, 380, 230);
return;
}
}
@@ -227,11 +228,9 @@ int main(int argc, char **argv) {
if (ui_get_event(win, &ev)) {
if (ev.type == GUI_EVENT_PAINT) {
paint_paint(win);
ui_mark_dirty(win, 0, 0, 380, 260);
ui_mark_dirty(win, 0, 0, 380, 240);
} else if (ev.type == GUI_EVENT_CLICK) {
paint_click(win, ev.arg1, ev.arg2);
paint_paint(win);
ui_mark_dirty(win, 0, 0, 380, 260);
} else if (ev.type == GUI_EVENT_MOUSE_DOWN) {
paint_handle_mouse(win, ev.arg1, ev.arg2);
} else if (ev.type == GUI_EVENT_MOUSE_UP) {

Binary file not shown.

View File

@@ -689,3 +689,4 @@ int main(int argc, char **argv) {
}
return 0;
}

Binary file not shown.

View File

@@ -197,7 +197,7 @@ static void editor_insert_char(char ch) {
static void editor_paint(ui_window_t win) {
int offset_x = 4;
int offset_y = 24;
int offset_y = 0;
int content_width = win_w - 8;
int content_height = win_h - 28;
@@ -390,7 +390,7 @@ static void editor_handle_key(char c) {
static void editor_handle_click(int x, int y) {
int content_width = win_w - 8;
int button_x = 4 + content_width - 80;
int button_y = 24 + 3;
int button_y = 3;
if (x >= button_x && x < button_x + 70 && y >= button_y && y < button_y + 20) {
editor_save_file();
@@ -413,15 +413,15 @@ int main(int argc, char **argv) {
if (ui_get_event(win, &ev)) {
if (ev.type == GUI_EVENT_PAINT) {
editor_paint(win);
ui_mark_dirty(win, 0, 0, win_w, win_h);
ui_mark_dirty(win, 0, 0, win_w, win_h - 20);
} else if (ev.type == GUI_EVENT_CLICK) {
editor_handle_click(ev.arg1, ev.arg2);
editor_paint(win);
ui_mark_dirty(win, 0, 0, win_w, win_h);
ui_mark_dirty(win, 0, 0, win_w, win_h - 20);
} else if (ev.type == GUI_EVENT_KEY) {
editor_handle_key((char)ev.arg1);
editor_paint(win);
ui_mark_dirty(win, 0, 0, win_w, win_h);
ui_mark_dirty(win, 0, 0, win_w, win_h - 20);
} else if (ev.type == GUI_EVENT_CLOSE) {
sys_exit(0);
}

Binary file not shown.

View File

@@ -49,7 +49,7 @@ static void viewer_scale_rgb_to_argb(const unsigned char *rgb, int src_w, int sr
static void viewer_paint(ui_window_t win) {
int cx = 4;
int cy = 24;
int cy = 0;
int cw = win_w - 8;
int ch = win_h - 28;
@@ -75,21 +75,25 @@ static void viewer_paint(ui_window_t win) {
int ox = cx + (cw - disp_w) / 2;
int oy = cy + (ch - disp_h - 30) / 2;
for (int y = 0; y < disp_h; y++) {
int src_y = y * viewer_img_h / disp_h;
if (src_y >= viewer_img_h) src_y = viewer_img_h - 1;
for (int x = 0; x < disp_w; x++) {
int src_x = x * viewer_img_w / disp_w;
if (src_x >= viewer_img_w) src_x = viewer_img_w - 1;
uint32_t pixel = viewer_pixels[src_y * viewer_img_w + src_x];
ui_draw_rect(win, ox + x, oy + y, 1, 1, pixel);
uint32_t *temp_buf = malloc(disp_w * disp_h * sizeof(uint32_t));
if (temp_buf) {
for (int y = 0; y < disp_h; y++) {
int src_y = y * viewer_img_h / disp_h;
if (src_y >= viewer_img_h) src_y = viewer_img_h - 1;
for (int x = 0; x < disp_w; x++) {
int src_x = x * viewer_img_w / disp_w;
if (src_x >= viewer_img_w) src_x = viewer_img_w - 1;
temp_buf[y * disp_w + x] = viewer_pixels[src_y * viewer_img_w + src_x];
}
}
ui_draw_image(win, ox, oy, disp_w, disp_h, temp_buf);
free(temp_buf);
}
int btn_w = 160;
int btn_h = 22;
int btn_x = cx + (cw - btn_w) / 2;
int btn_y = win_h - 30;
int btn_y = (win_h - 20) - 30;
ui_draw_rounded_rect_filled(win, btn_x, btn_y, btn_w, btn_h, 6, 0xFF2D2D2D);
ui_draw_string(win, btn_x + 10, btn_y + 6, "Set as Wallpaper", 0xFFF0F0F0);
}
@@ -101,7 +105,7 @@ static void viewer_handle_click(ui_window_t win, int x, int y) {
int cw = win_w - 8;
int btn_w = 160;
int btn_x = cx + (cw - btn_w) / 2;
int btn_y = win_h - 30;
int btn_y = (win_h - 20) - 30;
if (x >= btn_x && x < btn_x + btn_w && y >= btn_y && y < btn_y + 22) {
// SYSTEM_CMD_SET_WALLPAPER is 3 based on syscall.c code
@@ -214,7 +218,7 @@ int main(int argc, char **argv) {
if (ui_get_event(win, &ev)) {
if (ev.type == GUI_EVENT_PAINT) {
viewer_paint(win);
ui_mark_dirty(win, 0, 0, win_w, win_h);
ui_mark_dirty(win, 0, 0, win_w, win_h - 20);
} else if (ev.type == GUI_EVENT_CLICK) {
viewer_handle_click(win, ev.arg1, ev.arg2);
} else if (ev.type == GUI_EVENT_CLOSE) {

Binary file not shown.

Binary file not shown.

View File

@@ -1003,9 +1003,9 @@ void draw_window(Window *win) {
draw_rect(win->x, win->y + 20, win->w, 8, COLOR_DARK_BG);
if (win->comp_pixels) {
graphics_blit_buffer(win->comp_pixels, win->x, win->y, win->w, win->h);
graphics_blit_buffer(win->comp_pixels, win->x, win->y + 20, win->w, win->h - 20);
} else if (win->pixels) {
graphics_blit_buffer(win->pixels, win->x, win->y, win->w, win->h);
graphics_blit_buffer(win->pixels, win->x, win->y + 20, win->w, win->h - 20);
}
if (win->paint) {
@@ -1051,12 +1051,9 @@ static void erase_cursor(int x, int y) {
int w = x2 - x1;
int h = y2 - y1;
// Check what's underneath the cursor and redraw it
if (y1 < sh - 28) {
// Desktop or window area - draw teal background
draw_rect(x1, y1, w, h, COLOR_TEAL);
} else {
// Taskbar
draw_rect(x1, y1, w, h, COLOR_GRAY);
}
}
@@ -1068,7 +1065,6 @@ static uint8_t rtc_read(uint8_t reg) {
}
static void draw_clock(int x, int y) {
// Wait for update in progress
while (rtc_read(0x0A) & 0x80);
uint8_t s = rtc_read(0x00);
@@ -1168,7 +1164,6 @@ void wm_paint(void) {
}
}
// Draw windows in z-order (lowest first)
for (int i = 0; i < window_count; i++) {
Window *win = sorted_windows[i];
if (!win->visible) continue;
@@ -1182,16 +1177,10 @@ void wm_paint(void) {
draw_window(win);
}
// 4. Top Menu Bar
draw_rect(0, 0, sw, 30, COLOR_TOPBAR_BG);
// Logo dropdown (top-left)
draw_boredos_logo(8, 8, 1);
// Clock (top-right)
draw_clock(sw - 80, 12);
// Top menu dropdown (if logo clicked)
if (start_menu_open) {
int menu_h = 85;
draw_rounded_rect_filled(8, 40, 160, menu_h, 8, COLOR_DARK_PANEL);
@@ -1201,17 +1190,15 @@ void wm_paint(void) {
draw_string(20, 108, "Restart", COLOR_DARK_TEXT);
}
// 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_y = sh - dock_h - 6;
int dock_item_size = 48;
int dock_spacing = 10;
int total_dock_width = 7 * (dock_item_size + dock_spacing);
int dock_bg_x = (sw - total_dock_width) / 2 - 12; // Rounded background extends beyond icons
int dock_bg_x = (sw - total_dock_width) / 2 - 12;
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;
@@ -1321,6 +1308,8 @@ bool rect_contains(int x, int y, int w, int h, int px, int py) {
}
void wm_bring_to_front(Window *win) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
// Clear focus from all windows
for (int i = 0; i < window_count; i++) {
all_windows[i]->focused = false;
@@ -1336,22 +1325,30 @@ void wm_bring_to_front(Window *win) {
win->focused = true;
win->z_index = max_z + 1;
force_redraw = true;
asm volatile("push %0; popfq" : : "r"(rflags));
}
void wm_add_window(Window *win) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
if (window_count < 32) {
all_windows[window_count++] = win;
wm_bring_to_front(win); // Ensure newly added windows are on top
}
asm volatile("push %0; popfq" : : "r"(rflags));
}
Window* wm_find_window_by_title(const char *title) {
if (!title) return NULL;
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
for (int i = 0; i < window_count; i++) {
if (all_windows[i] && all_windows[i]->title && str_eq(all_windows[i]->title, title)) {
asm volatile("push %0; popfq" : : "r"(rflags));
return all_windows[i];
}
}
asm volatile("push %0; popfq" : : "r"(rflags));
return NULL;
}
@@ -1363,6 +1360,9 @@ void wm_remove_window(Window *win) {
else serial_write("unknown");
serial_write("'\n");
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
int index = -1;
for (int i = 0; i < window_count; i++) {
if (all_windows[i] == win) {
@@ -1378,22 +1378,22 @@ void wm_remove_window(Window *win) {
}
window_count--;
// Free resources
if (win->pixels) kfree(win->pixels);
if (win->comp_pixels) kfree(win->comp_pixels);
// If the title was allocated in syscall.c, we should free it,
// but currently we don't know for sure if it was kmalloc'd or a literal.
// In syscall.c it is kmalloc'd. Let's assume we should free it if it's not a known literal.
// Safer to just free it since userland windows always have kmalloc'd titles.
if (win->title && win->handle_close) { // Heuristic: user windows have handle_close set in syscall.c
kfree(win->title);
}
kfree(win);
// Mark for redraw while protected
force_redraw = true;
} else {
asm volatile("push %0; popfq" : : "r"(rflags));
serial_write("WM: Window not found in all_windows list!\n");
return;
}
if (win->pixels) kfree(win->pixels);
if (win->comp_pixels) kfree(win->comp_pixels);
if (win->title && win->handle_close) {
kfree(win->title);
}
kfree(win);
asm volatile("push %0; popfq" : : "r"(rflags));
}
void wm_handle_click(int x, int y) {
@@ -1614,7 +1614,7 @@ void wm_handle_click(int x, int y) {
} else {
// Content click
if (topmost->handle_click) {
topmost->handle_click(topmost, x - topmost->x, y - topmost->y);
topmost->handle_click(topmost, x - topmost->x, y - topmost->y - 20);
}
}
pending_desktop_icon_click = -1;
@@ -1665,10 +1665,10 @@ void wm_handle_right_click(int x, int y) {
// If a window was clicked
if (topmost != NULL) {
// Don't process close button or title bar for right click
if (y >= topmost->y + 24) {
if (y >= topmost->y + 20) {
// Content right click
if (topmost->handle_right_click) {
topmost->handle_right_click(topmost, x - topmost->x, y - topmost->y);
topmost->handle_right_click(topmost, x - topmost->x, y - topmost->y - 20);
}
}
} else {
@@ -1718,12 +1718,10 @@ void wm_handle_right_click(int x, int y) {
bool right = buttons & 0x02;
if (left && !prev_left) {
// Mouse Down
drag_start_x = mx;
drag_start_y = 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_y = sh - dock_h - 6;
int dock_item_size = 48;
int dock_spacing = 10;
int total_dock_width = 7 * (dock_item_size + dock_spacing);
@@ -1778,8 +1776,6 @@ void wm_handle_right_click(int x, int y) {
start_menu_pending_app = NULL;
}
// Mouse moving with left button, check for file drag start
// 1. Check Desktop Icons
if (pending_desktop_icon_click != -1) {
int i = pending_desktop_icon_click;
DesktopIcon *icon = &desktop_icons[i];
@@ -1953,7 +1949,6 @@ void wm_handle_right_click(int x, int y) {
if (is_dragging_file) {
// Drop logic
// Check drop target - iterate through all windows to find if dropped on an Explorer
Window *drop_win = NULL;
int topmost_z = -1;
for (int w = 0; w < window_count; w++) {
@@ -1983,11 +1978,8 @@ void wm_handle_right_click(int x, int y) {
} else {
// Dropped on Desktop (or elsewhere)
if (drag_file_path[0] == ':' && drag_file_path[1] == ':' && drag_file_path[2] == 'A') {
// Dropped Start Menu App -> Create Shortcut
create_desktop_shortcut(drag_file_path + 7); // Skip ::APP::
create_desktop_shortcut(drag_file_path + 7);
} else {
// If source was NOT desktop, move to desktop
// Check if path starts with /Desktop/
bool from_desktop = (drag_file_path[0]=='/' && drag_file_path[1]=='D' && drag_file_path[2]=='e');
bool dropped_on_target = false;
for (int i = 0; i < desktop_icon_count; i++) {
@@ -2076,8 +2068,6 @@ void wm_handle_right_click(int x, int y) {
}
}
} else if (!dropped_on_target) {
// Moved within desktop
// Find which icon was dragged
int dragged_idx = -1;
for(int i=0; i<desktop_icon_count; i++) {
char path[128] = "/Desktop/";
@@ -2129,11 +2119,8 @@ void wm_handle_right_click(int x, int y) {
desktop_icons[dragged_idx].y = 20 + row * 80;
}
// Check for collision with other icons
// Folders already checked above, this is for overlap prevention
for (int i = 0; i < desktop_icon_count; i++) {
if (i == dragged_idx) continue;
// Simple distance check or rect overlap
int dx = desktop_icons[i].x - desktop_icons[dragged_idx].x;
int dy = desktop_icons[i].y - desktop_icons[dragged_idx].y;
if (dx < 0) dx = -dx;
@@ -2174,7 +2161,8 @@ void wm_handle_right_click(int x, int y) {
}
}
if (topmost && topmost->data) {
syscall_send_mouse_down_event(topmost, mx - topmost->x, my - topmost->y);
if (my >= topmost->y + 20)
syscall_send_mouse_down_event(topmost, mx - topmost->x, my - topmost->y - 20);
}
}
@@ -2192,7 +2180,8 @@ void wm_handle_right_click(int x, int y) {
}
}
if (topmost && topmost->data) {
syscall_send_mouse_up_event(topmost, mx - topmost->x, my - topmost->y);
if (my >= topmost->y + 20)
syscall_send_mouse_up_event(topmost, mx - topmost->x, my - topmost->y - 20);
}
}
@@ -2210,7 +2199,8 @@ void wm_handle_right_click(int x, int y) {
}
}
if (topmost && topmost->data) {
syscall_send_mouse_move_event(topmost, mx - topmost->x, my - topmost->y, buttons);
if (my >= topmost->y + 20)
syscall_send_mouse_move_event(topmost, mx - topmost->x, my - topmost->y - 20, buttons);
}
}
@@ -2346,12 +2336,10 @@ void wm_init(void) {
all_windows[2] = &win_about;
window_count = 3;
// Only show Explorer on desktop (initially hidden)
win_explorer.visible = false;
win_explorer.focused = false;
win_explorer.z_index = 10;
// Rest are hidden initially
win_cmd.visible = false;
win_about.visible = false;
@@ -2366,8 +2354,6 @@ uint32_t wm_get_ticks(void) {
void wm_timer_tick(void) {
timer_ticks++;
// Auto-refresh desktop every 5 seconds to save CPU in QEMU
// But NOT if the user is dragging a window or file.
if (!is_dragging && !is_dragging_file) {
desktop_refresh_timer++;
if (desktop_refresh_timer >= 300) {
@@ -2378,8 +2364,7 @@ void wm_timer_tick(void) {
}
}
// Only redraw if there are dirty areas (clock updates at most every second, cursor rarely moves in timer only)
// Most of the time, nothing changes between ticks
static uint8_t last_second = 0xFF;
@@ -2389,17 +2374,14 @@ void wm_timer_tick(void) {
if (current_sec != last_second) {
last_second = current_sec;
int sw = get_screen_width();
// Mark clock area in the top menu bar (around draw_clock at sw - 80, y=12)
wm_mark_dirty(sw - 110, 6, 110, 24);
}
// If force_redraw is set, do a full redraw
if (force_redraw) {
graphics_mark_screen_dirty();
force_redraw = false;
}
// Perform redraw if there are dirty areas
DirtyRect dirty = graphics_get_dirty_rect();
if (dirty.active) {
wm_paint();

View File

@@ -23,7 +23,6 @@
#define COLOR_APPLE_INDIGO 0xFF4B0082
#define COLOR_APPLE_VIOLET 0xFF9400D3
// --- Dark Mode Colors ---
#define COLOR_NOTEPAD_BG 0xFFF5F5DC
#define COLOR_DARK_BG 0xFF1E1E1E // Main dark background
#define COLOR_DARK_PANEL 0xFF2D2D2D // Slightly lighter panel background
@@ -36,7 +35,7 @@
#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
#define DESKTOP_TOP_DEADSPACE_HEIGHT 80 // stops files from being rendered under menu bar
typedef struct Window Window;
struct Window {
char *title;
@@ -46,10 +45,10 @@ struct Window {
int buf_len;
int cursor_pos;
bool focused;
int z_index; // Layering depth (higher = on top)
void *data; // Per-window private data
uint32_t *pixels; // Pointer to backing buffer for UI events (Back Buffer)
uint32_t *comp_pixels; // Pointer to composition buffer (Front Buffer)
int z_index;
void *data;
uint32_t *pixels;
uint32_t *comp_pixels;
// Callbacks
void (*paint)(Window *win);
@@ -88,7 +87,7 @@ 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_traffic_light(int x, int y);
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);