Stability improvements

This commit is contained in:
boreddevnl 2026-02-26 21:45:57 +01:00
parent 2801dbc21f
commit fcc290f3f9
32 changed files with 171 additions and 97 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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.

BIN
disk.img

Binary file not shown.

Binary file not shown.

View file

@ -287,6 +287,7 @@ void draw_char(int x, int y, char c, uint32_t color) {
} }
void draw_string(int x, int y, const char *s, uint32_t color) { void draw_string(int x, int y, const char *s, uint32_t color) {
if (!s) return;
int cur_x = x; int cur_x = x;
int cur_y = y; int cur_y = y;
while (*s) { while (*s) {
@ -370,22 +371,22 @@ void graphics_set_bg_image(uint32_t *pixels, int w, int h) {
void draw_boredos_logo(int x, int y, int scale) { void draw_boredos_logo(int x, int y, int scale) {
static const uint8_t brewos_bmp[] = { static const uint8_t brewos_bmp[] = {
0,0,1,1,1,0,0,0,0,0,0,1,1,1,0,0, // 0: Ears 0,0,1,1,1,0,0,0,0,0,0,1,1,1,0,0,
0,1,1,1,1,0,0,0,0,0,0,1,1,1,1,0, // 1: Ears 0,1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,
1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1, // 2: Ears (Separated) 1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,
1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1, // 3: Forehead / Ears 1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1,
1,1,1,2,2,2,2,2,2,2,2,2,2,1,1,1, // 4: Face 1,1,1,2,2,2,2,2,2,2,2,2,2,1,1,1,
1,1,2,2,2,1,1,2,2,1,1,2,2,2,1,1, // 5: Eyes start 1,1,2,2,2,1,1,2,2,1,1,2,2,2,1,1,
1,1,2,2,1,1,1,1,1,1,1,1,2,2,1,1, // 6: Eyes 1,1,2,2,1,1,1,1,1,1,1,1,2,2,1,1,
1,1,2,2,1,1,1,1,1,1,1,1,2,2,1,1, // 7: Eyes 1,1,2,2,1,1,1,1,1,1,1,1,2,2,1,1,
1,1,2,2,1,1,1,1,1,1,1,1,2,2,1,1, // 8: Eyes 1,1,2,2,1,1,1,1,1,1,1,1,2,2,1,1,
1,1,2,2,2,1,1,2,2,1,1,2,2,2,1,1, // 9: Under eyes 1,1,2,2,2,1,1,2,2,1,1,2,2,2,1,1,
1,1,2,2,2,2,2,1,1,2,2,2,2,2,1,1, // 10: Nose 1,1,2,2,2,2,2,1,1,2,2,2,2,2,1,1,
1,1,2,2,2,2,2,2,2,2,2,2,2,2,1,1, // 11: Cheeks 1,1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,
1,1,1,2,2,2,2,2,2,2,2,2,2,1,1,1, // 12: Jaw 1,1,1,2,2,2,2,2,2,2,2,2,2,1,1,1,
0,1,1,1,2,2,2,2,2,2,2,2,1,1,1,0, // 13: Chin 0,1,1,1,2,2,2,2,2,2,2,2,1,1,1,0,
0,0,1,1,1,2,2,2,2,2,2,1,1,1,0,0, // 14: Chin outline 0,0,1,1,1,2,2,2,2,2,2,1,1,1,0,0,
0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0 // 15: Bottom 0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0
}; };
for (int r = 0; r < 16; r++) { for (int r = 0; r < 16; r++) {
@ -435,6 +436,15 @@ void graphics_flip_buffer(void) {
} }
void graphics_set_clipping(int x, int y, int w, int h) { void graphics_set_clipping(int x, int y, int w, int h) {
if (x < 0) { w += x; x = 0; }
if (y < 0) { h += y; y = 0; }
int sw = get_screen_width();
int sh = get_screen_height();
if (x + w > sw) w = sw - x;
if (y + h > sh) h = sh - y;
if (w < 0) w = 0;
if (h < 0) h = 0;
g_clip_x = x; g_clip_x = x;
g_clip_y = y; g_clip_y = y;
g_clip_w = w; g_clip_w = w;
@ -459,9 +469,7 @@ void graphics_blit_buffer(uint32_t *src, int dst_x, int dst_y, int w, int h) {
if (vx < 0 || vx >= sw) continue; if (vx < 0 || vx >= sw) continue;
uint32_t pcol = src[y * w + x]; uint32_t pcol = src[y * w + x];
// Alpha blending support:
// If the alpha byte is 0, we treat it as transparent ONLY if the color is also 0.
// This handles common 0xRRGGBB as opaque.
if ((pcol & 0xFF000000) != 0 || (pcol & 0xFFFFFF) != 0) { if ((pcol & 0xFF000000) != 0 || (pcol & 0xFFFFFF) != 0) {
g_back_buffer[vy * sw + vx] = pcol; g_back_buffer[vy * sw + vx] = pcol;
} }

View file

@ -84,7 +84,32 @@ void kmain(void) {
platform_init(); platform_init();
serial_write("[DEBUG] platform_init OK\n"); serial_write("[DEBUG] platform_init OK\n");
// 1. Graphics Init // 1. Memory Detection and Heap Init
uint64_t heap_phys_addr = 0;
size_t heap_size = 0;
if (memmap_request.response != NULL) {
for (uint64_t i = 0; i < memmap_request.response->entry_count; i++) {
struct limine_memmap_entry *entry = memmap_request.response->entries[i];
if (entry->type == LIMINE_MEMMAP_USABLE) {
if (entry->length > heap_size) {
heap_size = entry->length;
heap_phys_addr = entry->base;
}
}
}
}
if (heap_size > 512 * 1024 * 1024) heap_size = 512 * 1024 * 1024; // Cap at 512MB
if (heap_phys_addr != 0) {
memory_manager_init_at((void*)p2v(heap_phys_addr), heap_size);
serial_write("[DEBUG] memory_manager_init OK\n");
} else {
serial_write("[DEBUG] ERROR: No usable memory for heap!\n");
hcf();
}
// 2. Graphics Init
if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 1) { if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 1) {
serial_write("[DEBUG] No framebuffer! Halting.\n"); serial_write("[DEBUG] No framebuffer! Halting.\n");
hcf(); hcf();
@ -94,20 +119,19 @@ void kmain(void) {
graphics_init(fb); graphics_init(fb);
serial_write("[DEBUG] graphics_init OK\n"); serial_write("[DEBUG] graphics_init OK\n");
// 1.5 GDT & TSS Init // 3. GDT & TSS Init
gdt_init(); gdt_init();
serial_write("[DEBUG] gdt_init OK\n"); serial_write("[DEBUG] gdt_init OK\n");
// 1.6 Paging Init // 4. Paging Init
paging_init(); paging_init();
serial_write("[DEBUG] paging_init OK\n"); serial_write("[DEBUG] paging_init OK\n");
// 1.7 Syscall Init // 5. Syscall Init
syscall_init(); syscall_init();
serial_write("[DEBUG] syscall_init OK\n"); serial_write("[DEBUG] syscall_init OK\n");
// Set up a user page and jump to user space // 6. Interrupts Init
// 2. Interrupts Init
idt_init(); idt_init();
idt_register_interrupts(); idt_register_interrupts();
idt_load(); idt_load();
@ -115,33 +139,8 @@ void kmain(void) {
process_init(); process_init();
serial_write("[DEBUG] Skipping user mode test, proceeding with normal boot.\n"); serial_write("[DEBUG] Skipping user mode test, proceeding with normal boot.\n");
// 2.5 Memory Manager Init - Calculate available RAM from Limine
size_t total_usable_memory = 0;
if (memmap_request.response != NULL) {
for (uint64_t i = 0; i < memmap_request.response->entry_count; i++) {
struct limine_memmap_entry *entry = memmap_request.response->entries[i];
// Count usable memory regions
if (entry->type == LIMINE_MEMMAP_USABLE) {
total_usable_memory += entry->length;
}
}
}
// Initialize memory manager with available memory (cap at 2GB for practical reasons)
size_t pool_size = total_usable_memory > (2 * 1024 * 1024 * 1024) ?
(2 * 1024 * 1024 * 1024) : total_usable_memory;
if (pool_size == 0) {
pool_size = 512 * 1024 * 1024; // Fallback to 512MB if detection fails
}
memory_manager_init_with_size(pool_size);
// Initialize FAT32 RAMFS and mount Limine modules // Initialize FAT32 RAMFS and mount Limine modules
fat32_init(); fat32_init();
if (module_request.response != NULL) { if (module_request.response != NULL) {
@ -181,6 +180,7 @@ void kmain(void) {
// Timer interrupt will drive the redraw system // Timer interrupt will drive the redraw system
while (1) { while (1) {
wm_process_input(); wm_process_input();
wm_process_deferred_thumbs();
wallpaper_process_pending(); wallpaper_process_pending();
asm("hlt"); asm("hlt");
} }

View file

@ -3,10 +3,8 @@
#include <stdint.h> #include <stdint.h>
// --- Internal State --- // --- Internal State ---
#define KERNEL_HEAP_SIZE (32 * 1024 * 1024) // 32MB Static Heap static uint8_t *memory_pool = NULL;
static uint8_t memory_pool_buffer[KERNEL_HEAP_SIZE]; static size_t memory_pool_size = 0;
static uint8_t *memory_pool = memory_pool_buffer;
static size_t memory_pool_size = KERNEL_HEAP_SIZE;
static MemBlock block_list[MAX_ALLOCATIONS]; static MemBlock block_list[MAX_ALLOCATIONS];
static int block_count = 0; static int block_count = 0;
static size_t total_allocated = 0; static size_t total_allocated = 0;
@ -137,9 +135,11 @@ static size_t calculate_fragmentation(void) {
// --- Public API --- // --- Public API ---
void memory_manager_init_with_size(size_t pool_size) { void memory_manager_init_at(void *pool_address, size_t pool_size) {
if (initialized) return; if (initialized) return;
memory_pool = (uint8_t *)pool_address;
memory_pool_size = pool_size;
// Clear metadata // Clear metadata
mem_memset(block_list, 0, sizeof(block_list)); mem_memset(block_list, 0, sizeof(block_list));
@ -158,6 +158,14 @@ void memory_manager_init_with_size(size_t pool_size) {
initialized = true; initialized = true;
} }
void memory_manager_init_with_size(size_t pool_size) {
// This is now just a wrapper if init_at wasn't called.
// However, in BoredOS we now prefer explicit init_at.
if (initialized) return;
// Fallback: we still need a buffer if no address is provided?
// Let's assume for now that BoredOS always calls init_at.
}
void memory_manager_init(void) { void memory_manager_init(void) {
memory_manager_init_with_size(DEFAULT_POOL_SIZE); memory_manager_init_with_size(DEFAULT_POOL_SIZE);
} }

View file

@ -6,8 +6,8 @@
#include <stdbool.h> #include <stdbool.h>
// Memory Manager Configuration // Memory Manager Configuration
#define DEFAULT_POOL_SIZE (512 * 1024 * 1024) // 512MB default (can be overridden) #define DEFAULT_POOL_SIZE (128 * 1024 * 1024) // 128MB default
#define MAX_ALLOCATIONS 4096 // Increased for larger pools #define MAX_ALLOCATIONS 16384 // Increased for larger pools
#define MAX_FRAGMENTATION_SLOTS 2048 #define MAX_FRAGMENTATION_SLOTS 2048
// Allocation block metadata // Allocation block metadata
@ -35,6 +35,7 @@ typedef struct {
// Public API // Public API
void memory_manager_init(void); void memory_manager_init(void);
void memory_manager_init_with_size(size_t pool_size); void memory_manager_init_with_size(size_t pool_size);
void memory_manager_init_at(void *pool_address, size_t pool_size);
// Allocation/Deallocation // Allocation/Deallocation
void* kmalloc(size_t size); void* kmalloc(size_t size);

View file

@ -239,6 +239,8 @@ void process_create_elf(const char* filepath, const char* args_str) {
*(--stack_ptr) = 0; // R15 *(--stack_ptr) = 0; // R15
new_proc->kernel_stack = (uint64_t)kernel_stack + 16384; new_proc->kernel_stack = (uint64_t)kernel_stack + 16384;
new_proc->kernel_stack_alloc = kernel_stack;
new_proc->user_stack_alloc = stack;
new_proc->rsp = (uint64_t)stack_ptr; new_proc->rsp = (uint64_t)stack_ptr;
// We only increment process_count after success // We only increment process_count after success
@ -333,6 +335,13 @@ uint64_t process_terminate_current(void) {
paging_switch_directory(current_process->pml4_phys); paging_switch_directory(current_process->pml4_phys);
// 5. Actually free the memory (after switching state to avoid issues)
if (to_delete->kernel_stack_alloc) kfree(to_delete->kernel_stack_alloc);
if (to_delete->user_stack_alloc) kfree(to_delete->user_stack_alloc);
// NOTE: In a real system we would also free all physical pages
// used by the user page table. For now we just free the stacks.
return current_process->rsp; return current_process->rsp;
} }

View file

@ -35,6 +35,9 @@ typedef struct process {
void *fds[MAX_PROCESS_FDS]; void *fds[MAX_PROCESS_FDS];
void *kernel_stack_alloc; // Original pointer from kmalloc for freeing
void *user_stack_alloc; // Original pointer from kmalloc for freeing
struct process *next; struct process *next;
} process_t; } process_t;

View file

@ -27,20 +27,20 @@ static bool str_eq(const char *s1, const char *s2) {
} }
// --- State --- // --- State ---
static int mx = 400, my = 300; // Mouse Pos static int mx = 400, my = 300;
static int prev_mx = 400, prev_my = 300; // Previous mouse position static int prev_mx = 400, prev_my = 300;
static bool start_menu_open = false; static bool start_menu_open = false;
static char *start_menu_pending_app = NULL; // For click vs drag detection static char *start_menu_pending_app = NULL;
static int pending_desktop_icon_click = -1; // For desktop icon click vs drag static int pending_desktop_icon_click = -1;
// Desktop Context Menu // Desktop Context Menu
static bool desktop_menu_visible = false; static bool desktop_menu_visible = false;
static int desktop_menu_x = 0; static int desktop_menu_x = 0;
static int desktop_menu_y = 0; static int desktop_menu_y = 0;
static int desktop_menu_target_icon = -1; // -1 for background static int desktop_menu_target_icon = -1;
// Desktop Dialog State // Desktop Dialog State
static int desktop_dialog_state = 0; // 0=None, 8=Rename static int desktop_dialog_state = 0;
static char desktop_dialog_input[64]; static char desktop_dialog_input[64];
static int desktop_dialog_cursor = 0; static int desktop_dialog_cursor = 0;
static int desktop_dialog_target = -1; static int desktop_dialog_target = -1;
@ -62,7 +62,7 @@ static int drag_offset_y = 0;
// File Dragging State // File Dragging State
bool is_dragging_file = false; bool is_dragging_file = false;
static char drag_file_path[256]; static char drag_file_path[256];
static int drag_icon_type = 0; // 0=File, 1=Folder, 2=App static int drag_icon_type = 0;
static int drag_start_x = 0; static int drag_start_x = 0;
static int drag_start_y = 0; static int drag_start_y = 0;
static int drag_icon_orig_x = 0; static int drag_icon_orig_x = 0;
@ -74,7 +74,7 @@ static Window *all_windows[32];
static int window_count = 0; static int window_count = 0;
// Redraw system // Redraw system
static bool force_redraw = true; // Force full redraw on next tick static bool force_redraw = true;
static uint32_t timer_ticks = 0; static uint32_t timer_ticks = 0;
static int desktop_refresh_timer = 0; static int desktop_refresh_timer = 0;
@ -88,7 +88,7 @@ static int last_cursor_y = 300;
typedef struct { typedef struct {
char name[64]; char name[64];
int x, y; int x, y;
int type; // 0=File, 1=Folder, 2=App int type;
} DesktopIcon; } DesktopIcon;
static DesktopIcon desktop_icons[MAX_DESKTOP_ICONS]; static DesktopIcon desktop_icons[MAX_DESKTOP_ICONS];
@ -101,7 +101,7 @@ int desktop_max_rows_per_col = 13;
int desktop_max_cols = 23; int desktop_max_cols = 23;
// Mouse Settings // Mouse Settings
int mouse_speed = 10; // Default 1.0x (range 1-50) int mouse_speed = 10;
static int mouse_accum_x = 0; static int mouse_accum_x = 0;
static int mouse_accum_y = 0; static int mouse_accum_y = 0;
@ -141,9 +141,7 @@ static void refresh_desktop_icons(void) {
bool file_processed[MAX_DESKTOP_ICONS]; bool file_processed[MAX_DESKTOP_ICONS];
for(int i=0; i<MAX_DESKTOP_ICONS; i++) file_processed[i] = false; for(int i=0; i<MAX_DESKTOP_ICONS; i++) file_processed[i] = false;
// 1. Preserve existing icons in their current order
for (int i = 0; i < desktop_icon_count; i++) { for (int i = 0; i < desktop_icon_count; i++) {
// Find if this icon still exists in the file list
int found_idx = -1; int found_idx = -1;
for (int j = 0; j < file_count; j++) { for (int j = 0; j < file_count; j++) {
if (!file_processed[j] && str_eq(desktop_icons[i].name, files[j].name) != 0) { if (!file_processed[j] && str_eq(desktop_icons[i].name, files[j].name) != 0) {
@ -162,10 +160,9 @@ static void refresh_desktop_icons(void) {
} }
} }
// 2. Add new files (not currently on desktop) to the end
for (int i = 0; i < file_count; i++) { for (int i = 0; i < file_count; i++) {
if (!file_processed[i]) { if (!file_processed[i]) {
if (files[i].name[0] == '.') continue; // Skip . and .. if (files[i].name[0] == '.') continue;
if (new_count >= MAX_DESKTOP_ICONS) break; if (new_count >= MAX_DESKTOP_ICONS) break;
DesktopIcon *dest = &new_icons[new_count]; DesktopIcon *dest = &new_icons[new_count];
@ -186,14 +183,12 @@ static void refresh_desktop_icons(void) {
for(int i=0; i<new_count; i++) desktop_icons[i] = new_icons[i]; for(int i=0; i<new_count; i++) desktop_icons[i] = new_icons[i];
kfree(files); kfree(files);
// 3. Layout Icons
if (desktop_auto_align) { if (desktop_auto_align) {
int start_x = 20; int start_x = 20;
int start_y = 30; int start_y = 30;
int grid_x = 0; int grid_x = 0;
int grid_y = 0; int grid_y = 0;
// Find Recycle Bin index
int recycle_idx = -1; int recycle_idx = -1;
for (int i = 0; i < desktop_icon_count; i++) { for (int i = 0; i < desktop_icon_count; i++) {
if (str_starts_with(desktop_icons[i].name, "Recycle Bin")) { if (str_starts_with(desktop_icons[i].name, "Recycle Bin")) {
@ -521,6 +516,42 @@ static struct {
} thumb_cache[THUMB_CACHE_SIZE]; } thumb_cache[THUMB_CACHE_SIZE];
static int thumb_cache_next = 0; // Round-robin eviction static int thumb_cache_next = 0; // Round-robin eviction
// Deferred Thumbnail Request Queue
#define THUMB_QUEUE_SIZE 16
static char thumb_request_queue[THUMB_QUEUE_SIZE][256];
static int thumb_queue_head = 0;
static int thumb_queue_tail = 0;
static void thumb_request_push(const char *path) {
if (!path) return;
// Check if already in queue
int curr = thumb_queue_head;
while (curr != thumb_queue_tail) {
if (str_eq(thumb_request_queue[curr], path) != 0) return;
curr = (curr + 1) % THUMB_QUEUE_SIZE;
}
// Push if space
int next_tail = (thumb_queue_tail + 1) % THUMB_QUEUE_SIZE;
if (next_tail != thumb_queue_head) {
int i = 0;
while (path[i] && i < 255) {
thumb_request_queue[thumb_queue_tail][i] = path[i];
i++;
}
thumb_request_queue[thumb_queue_tail][i] = 0;
thumb_queue_tail = next_tail;
}
}
static bool thumb_cache_is_failed(const char *path) {
for (int i = 0; i < THUMB_CACHE_SIZE; i++) {
if (thumb_cache[i].failed && str_eq(thumb_cache[i].path, path) != 0) return true;
}
return false;
}
static uint32_t* thumb_cache_lookup(const char *path) { static uint32_t* thumb_cache_lookup(const char *path) {
for (int i = 0; i < THUMB_CACHE_SIZE; i++) { for (int i = 0; i < THUMB_CACHE_SIZE; i++) {
if (thumb_cache[i].valid && str_eq(thumb_cache[i].path, path) != 0) { if (thumb_cache[i].valid && str_eq(thumb_cache[i].path, path) != 0) {
@ -530,14 +561,7 @@ static uint32_t* thumb_cache_lookup(const char *path) {
return NULL; return NULL;
} }
static bool thumb_cache_is_failed(const char *path) {
for (int i = 0; i < THUMB_CACHE_SIZE; i++) {
if (thumb_cache[i].failed && str_eq(thumb_cache[i].path, path) != 0) {
return true;
}
}
return false;
}
static uint32_t* thumb_cache_decode(const char *path) { static uint32_t* thumb_cache_decode(const char *path) {
// Open and read the JPG file // Open and read the JPG file
@ -566,11 +590,14 @@ static uint32_t* thumb_cache_decode(const char *path) {
// Decode JPEG // Decode JPEG
njInit(); njInit();
if (njDecode(buf, total) != NJ_OK) { if (njDecode(buf, total) != NJ_OK) {
serial_write("[WM] njDecode failed for deferred thumb\n");
njDone(); njDone();
kfree(buf); kfree(buf);
return NULL; return NULL;
} }
serial_write("[WM] njDecode OK for deferred thumb\n");
int img_w = njGetWidth(); int img_w = njGetWidth();
int img_h = njGetHeight(); int img_h = njGetHeight();
unsigned char *img = njGetImage(); unsigned char *img = njGetImage();
@ -627,22 +654,8 @@ void draw_image_icon(int x, int y, const char *label) {
if (!thumb && !thumb_cache_is_failed(label)) { if (!thumb && !thumb_cache_is_failed(label)) {
thumb = thumb_cache_lookup(label); thumb = thumb_cache_lookup(label);
if (!thumb) { if (!thumb) {
// Try to decode and cache // Queue for background decoding
graphics_set_render_target(NULL, 0, 0); // Restore before file I/O thumb_request_push(label);
thumb = thumb_cache_decode(label);
if (!thumb) {
// Mark as failed so we don't retry every frame
int slot = thumb_cache_next;
int p = 0;
while (label[p] && p < 255) { thumb_cache[slot].path[p] = label[p]; p++; }
thumb_cache[slot].path[p] = 0;
thumb_cache[slot].valid = false;
thumb_cache[slot].failed = true;
thumb_cache_next = (thumb_cache_next + 1) % THUMB_CACHE_SIZE;
}
// Re-set render target for icon drawing
for (int i = 0; i < 48 * 48; i++) icon_buf[i] = 0xFFFF00FF;
graphics_set_render_target(icon_buf, 48, 48);
} }
} }
@ -1097,6 +1110,9 @@ void wm_paint(void) {
int sw = get_screen_width(); int sw = get_screen_width();
int sh = get_screen_height(); int sh = get_screen_height();
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
DirtyRect dirty = graphics_get_dirty_rect(); DirtyRect dirty = graphics_get_dirty_rect();
if (dirty.active) { if (dirty.active) {
graphics_set_clipping(dirty.x, dirty.y, dirty.w, dirty.h); graphics_set_clipping(dirty.x, dirty.y, dirty.w, dirty.h);
@ -1299,6 +1315,9 @@ void wm_paint(void) {
// Flip the buffer - display the rendered frame atomically // Flip the buffer - display the rendered frame atomically
graphics_flip_buffer(); graphics_flip_buffer();
// Restore IRQs
asm volatile("push %0; popfq" : : "r"(rflags));
} }
// --- Input Handling --- // --- Input Handling ---
@ -2299,11 +2318,14 @@ void wm_handle_key(char c) {
} }
void wm_process_input(void) { void wm_process_input(void) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
while (key_head != key_tail) { while (key_head != key_tail) {
char c = key_queue[key_tail]; char c = key_queue[key_tail];
key_tail = (key_tail + 1) % INPUT_QUEUE_SIZE; key_tail = (key_tail + 1) % INPUT_QUEUE_SIZE;
wm_dispatch_key(c); wm_dispatch_key(c);
} }
asm volatile("push %0; popfq" : : "r"(rflags));
} }
void wm_mark_dirty(int x, int y, int w, int h) { void wm_mark_dirty(int x, int y, int w, int h) {
@ -2314,6 +2336,28 @@ void wm_refresh(void) {
force_redraw = true; force_redraw = true;
} }
void wm_process_deferred_thumbs(void) {
if (thumb_queue_head == thumb_queue_tail) return;
char path[256];
int i = 0;
while (thumb_request_queue[thumb_queue_head][i]) {
path[i] = thumb_request_queue[thumb_queue_head][i];
i++;
}
path[i] = 0;
serial_write("[WM] Processing deferred thumb: ");
serial_write(path);
serial_write("\n");
// Pop from queue
thumb_queue_head = (thumb_queue_head + 1) % THUMB_QUEUE_SIZE;
// Process (this takes time but it's okay because we are in the main loop with IRQs enabled)
thumb_cache_decode(path);
}
void wm_init(void) { void wm_init(void) {
disk_manager_init(); disk_manager_init();
disk_manager_scan(); disk_manager_scan();

View file

@ -64,6 +64,7 @@ void wm_handle_key(char c);
void wm_handle_click(int x, int y); void wm_handle_click(int x, int y);
void wm_handle_right_click(int x, int y); void wm_handle_right_click(int x, int y);
void wm_process_input(void); void wm_process_input(void);
void wm_process_deferred_thumbs(void);
void wm_add_window(Window *win); void wm_add_window(Window *win);
void wm_remove_window(Window *win); void wm_remove_window(Window *win);
void wm_bring_to_front(Window *win); void wm_bring_to_front(Window *win);