fix: kernel and desktop bug fixes
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user