mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-15 10:48:38 +00:00
Memory fixes userspace
This commit is contained in:
parent
786eac0345
commit
2801dbc21f
57 changed files with 215 additions and 183 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -18,6 +18,6 @@ limine 2/Makefile
|
|||
limine 2/limine
|
||||
limine 2/limine.dSYM/Contents/Resources/DWARF/limine
|
||||
limine 2/limine.exe
|
||||
build/*
|
||||
boredos.dump
|
||||
qemu-debug.log
|
||||
build/
|
||||
|
|
|
|||
BIN
boredos.iso
BIN
boredos.iso
Binary file not shown.
BIN
build/about.o
BIN
build/about.o
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
build/cmd.o
BIN
build/cmd.o
Binary file not shown.
BIN
build/explorer.o
BIN
build/explorer.o
Binary file not shown.
BIN
build/fat32.o
BIN
build/fat32.o
Binary file not shown.
BIN
build/icmp.o
BIN
build/icmp.o
Binary file not shown.
BIN
build/main.o
BIN
build/main.o
Binary file not shown.
BIN
build/ps2.o
BIN
build/ps2.o
Binary file not shown.
BIN
build/vm.o
BIN
build/vm.o
Binary file not shown.
Binary file not shown.
BIN
build/wm.o
BIN
build/wm.o
Binary file not shown.
BIN
disk.img
BIN
disk.img
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.
|
|
@ -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++) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
|
@ -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.
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
|
@ -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...
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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.
|
|
@ -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.
|
|
@ -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.
|
|
@ -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);
|
||||
ui_draw_rounded_rect_filled(win, 10, 0, 40, 230, 6, COLOR_DARK_PANEL);
|
||||
|
||||
// Toolbar area - dark mode
|
||||
ui_draw_rounded_rect_filled(win, 10, 30, 40, 260 - 40, 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.
|
|
@ -689,3 +689,4 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -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.
|
|
@ -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;
|
||||
|
||||
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;
|
||||
uint32_t pixel = viewer_pixels[src_y * viewer_img_w + src_x];
|
||||
ui_draw_rect(win, ox + x, oy + y, 1, 1, pixel);
|
||||
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.
100
src/kernel/wm.c
100
src/kernel/wm.c
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue