mirror of
https://github.com/JannisHeydemann/BoredOS.git
synced 2026-05-30 02:16:58 +00:00
Memory fixes userspace
This commit is contained in:
@@ -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);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
// 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.
@@ -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;
|
||||
|
||||
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.
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);
|
||||
|
||||
Reference in New Issue
Block a user