fix: kernel and desktop bug fixes

This commit is contained in:
2026-05-14 11:31:14 +02:00
parent a7ff1f0a72
commit bb12aeb9b9
11 changed files with 507 additions and 106 deletions
+14 -3
View File
@@ -58,10 +58,21 @@ inline int menu_row_height(const MenuRow& row) {
}
inline int menu_total_height() {
// Single-pass walk to avoid O(N^2) from menu_row_visible repeatedly
// counting categories from the start.
int h = 10; // top + bottom padding
for (int i = 0; i < menu_row_count; i++)
if (menu_row_visible(i))
h += menu_row_height(menu_rows[i]);
int cur_cat = -1;
for (int i = 0; i < menu_row_count; i++) {
const MenuRow& row = menu_rows[i];
if (row.is_category) cur_cat++;
bool visible = true;
if (!row.is_category) {
if (cur_cat >= 0 && cur_cat < MENU_NUM_CATS) {
visible = menu_cat_expanded[cur_cat];
}
}
if (visible) h += menu_row_height(row);
}
return h;
}
+10 -6
View File
@@ -677,8 +677,10 @@ void gui::desktop_handle_mouse(DesktopState* ds) {
ds->vol_popup_open = false;
}
// Forward continuous mouse events to focused window (hover, drag, release)
if (!left_pressed && ds->focused_window >= 0) {
// Forward continuous mouse events to focused window (hover, drag, release).
// Scroll is sent separately below; clearing ev.scroll here prevents local
// on_mouse handlers from receiving the same scroll twice.
if (!left_pressed && ds->focused_window >= 0 && ds->focused_window < ds->window_count) {
Window* win = &ds->windows[ds->focused_window];
if (win->state != WIN_MINIMIZED && win->state != WIN_CLOSED) {
Rect cr = desktop_content_rect(win);
@@ -695,16 +697,18 @@ void gui::desktop_handle_mouse(DesktopState* ds) {
wev.mouse.prev_buttons = prev;
montauk::win_sendevent(win->ext_win_id, &wev);
} else if (win->on_mouse) {
ev.x = mx;
ev.y = my;
win->on_mouse(win, ev);
MouseEvent hover = ev;
hover.x = mx;
hover.y = my;
hover.scroll = 0;
win->on_mouse(win, hover);
}
}
}
}
// Handle scroll events on focused window
if (ev.scroll != 0 && ds->focused_window >= 0) {
if (ev.scroll != 0 && ds->focused_window >= 0 && ds->focused_window < ds->window_count) {
Window* win = &ds->windows[ds->focused_window];
Rect cr = desktop_content_rect(win);
if (cr.contains(mx, my)) {
+7 -5
View File
@@ -10,14 +10,16 @@ void gui::desktop_draw_panel(DesktopState* ds) {
Framebuffer& fb = ds->fb;
int sw = ds->screen_w;
// Panel gradient background (slightly lighter at top)
// Panel gradient background (slightly lighter at top).
// Saturating add so light panel colors don't wrap around to dark via uint8_t overflow.
Color pc = ds->settings.panel_color;
for (int y = 0; y < PANEL_HEIGHT; y++) {
int t = y * 255 / PANEL_HEIGHT;
uint8_t r = pc.r + (10 - t * 10 / 255);
uint8_t g = pc.g + (10 - t * 10 / 255);
uint8_t b = pc.b + (10 - t * 10 / 255);
fb.fill_rect(0, y, sw, 1, Color::from_rgb(r, g, b));
int delta = 10 - t * 10 / 255;
int r = (int)pc.r + delta; if (r > 255) r = 255;
int g = (int)pc.g + delta; if (g > 255) g = 255;
int b = (int)pc.b + delta; if (b > 255) b = 255;
fb.fill_rect(0, y, sw, 1, Color::from_rgb((uint8_t)r, (uint8_t)g, (uint8_t)b));
}
// Bottom highlight line (skip when wallpaper is set — the white bleeds through)
+44 -15
View File
@@ -72,8 +72,14 @@ void gui::desktop_close_window(DesktopState* ds, int idx) {
if (win->on_close) win->on_close(win);
// Free content buffer (skip for external windows — shared memory)
if (win->content && !win->external) {
if (win->external) {
// Drop our mapping of the shared pixel buffer so the page table doesn't
// keep leaking mappings each time the user closes an external window.
if (win->content != nullptr) {
montauk::win_unmap(win->ext_win_id);
win->content = nullptr;
}
} else if (win->content) {
montauk::free(win->content);
win->content = nullptr;
}
@@ -182,23 +188,46 @@ void gui::desktop_draw_window(DesktopState* ds, int idx) {
Rect cr = desktop_content_rect(win);
if (win->content) {
if (win->external && (cr.w != win->content_w || cr.h != win->content_h)) {
// Nearest-neighbor scale for external windows (fixed-size shared buffer)
// Nearest-neighbor scale for external windows (fixed-size shared buffer).
// Pre-clip the destination range so the inner loop avoids per-pixel
// framebuffer bounds checks. Avoid stack-allocated lookup tables —
// the desktop user stack is only 32 KiB and shared with TrueType.
int src_w = win->content_w;
int src_h = win->content_h;
int dst_w = cr.w;
int dst_h = cr.h;
uint32_t* buf = fb.buffer();
int pitch = fb.pitch();
for (int y = 0; y < dst_h; y++) {
int dy = cr.y + y;
if (dy < 0 || dy >= fb.height()) continue;
int sy = y * src_h / dst_h;
uint32_t* dst_row = (uint32_t*)((uint8_t*)buf + dy * pitch);
uint32_t* src_row = win->content + sy * src_w;
for (int x = 0; x < dst_w; x++) {
int dx = cr.x + x;
if (dx < 0 || dx >= fb.width()) continue;
dst_row[dx] = src_row[x * src_w / dst_w];
if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0) {
// nothing to do
} else {
int fbw = fb.width();
int fbh = fb.height();
uint32_t* buf = fb.buffer();
int pitch = fb.pitch();
int x_start = 0;
int x_end = dst_w;
if (cr.x < 0) x_start = -cr.x;
if (cr.x + dst_w > fbw) x_end = fbw - cr.x;
if (x_start < 0) x_start = 0;
if (x_end > dst_w) x_end = dst_w;
int y_start = 0;
int y_end = dst_h;
if (cr.y < 0) y_start = -cr.y;
if (cr.y + dst_h > fbh) y_end = fbh - cr.y;
if (y_start < 0) y_start = 0;
if (y_end > dst_h) y_end = dst_h;
for (int y = y_start; y < y_end; y++) {
int dy = cr.y + y;
int sy = y * src_h / dst_h;
if (sy >= src_h) sy = src_h - 1;
uint32_t* dst_row = (uint32_t*)((uint8_t*)buf + dy * pitch);
uint32_t* src_row = win->content + sy * src_w;
for (int x = x_start; x < x_end; x++) {
int sx = x * src_w / dst_w;
if (sx >= src_w) sx = src_w - 1;
dst_row[cr.x + x] = src_row[sx];
}
}
}
} else {
+11 -1
View File
@@ -384,7 +384,11 @@ void file_push_history(FileDialogState* st) {
if (montauk::streq(st->history[st->history_pos], st->current_path)) return;
}
st->history_pos++;
if (st->history_pos >= MAX_HISTORY) st->history_pos = MAX_HISTORY - 1;
if (st->history_pos >= MAX_HISTORY) {
for (int i = 1; i < MAX_HISTORY; i++)
safe_copy(st->history[i - 1], sizeof(st->history[i - 1]), st->history[i]);
st->history_pos = MAX_HISTORY - 1;
}
safe_copy(st->history[st->history_pos], sizeof(st->history[st->history_pos]), st->current_path);
st->history_count = st->history_pos + 1;
}
@@ -664,6 +668,12 @@ void file_activate_selected(FileDialogState* st, bool from_double_click) {
}
void file_go_home(FileDialogState* st) {
if (st->home_dir[0] && is_dir_path(st->home_dir)) {
safe_copy(st->current_path, sizeof(st->current_path), st->home_dir);
file_read_dir(st);
file_push_history(st);
return;
}
file_read_drives(st);
file_push_history(st);
}