diff --git a/src/userland/gui/viewer.c b/src/userland/gui/viewer.c index 7b401a3..e533fca 100644 --- a/src/userland/gui/viewer.c +++ b/src/userland/gui/viewer.c @@ -9,8 +9,8 @@ #include #include -#define VIEWER_MAX_W 800 -#define VIEWER_MAX_H 600 +#define VIEWER_MAX_W 4096 +#define VIEWER_MAX_H 4096 static uint32_t *viewer_pixels = NULL; static uint32_t **viewer_frames = NULL; @@ -24,6 +24,8 @@ static int viewer_img_h = 0; static char viewer_title[64] = "Viewer"; static bool viewer_has_image = false; static char viewer_file_path[256]; +static bool resize_pending = false; +static uint64_t last_resize_tick = 0; static int win_w = 500; static int win_h = 400; @@ -80,11 +82,13 @@ static void viewer_scale_rgba_to_argb(const unsigned char *rgba, int src_w, int } static void viewer_paint(ui_window_t win) { - int cx = 4; + int cx = 0; int cy = 0; - int cw = win_w - 8; - int ch = win_h - 28; + int cw = win_w; + int ch = win_h - 20; // 20px header + // Clear background + ui_draw_rect(win, 0, 0, win_w, win_h, 0xFF000000); // Black background if (!viewer_has_image) { ui_draw_string(win, cx + 20, cy + ch / 2, "No image loaded", 0xFF888888); @@ -94,46 +98,42 @@ static void viewer_paint(ui_window_t win) { uint32_t *pixels = viewer_pixels; if (viewer_frames) pixels = viewer_frames[viewer_current_frame]; + // Maintain aspect ratio while fitting to window int disp_w = viewer_img_w; int disp_h = viewer_img_h; - - if (disp_w > cw - 8) { - disp_h = disp_h * (cw - 8) / disp_w; - disp_w = cw - 8; - } - if (disp_h > ch - 40) { - disp_w = disp_w * (ch - 40) / disp_h; - disp_h = ch - 40; - } + + float sw = (float)cw / (float)viewer_img_w; + float sh = (float)ch / (float)viewer_img_h; + float scale = (sw < sh) ? sw : sh; + + disp_w = (int)(viewer_img_w * scale); + disp_h = (int)(viewer_img_h * scale); int ox = cx + (cw - disp_w) / 2; int oy = cy + (ch - disp_h) / 2; + if (disp_w <= 0 || disp_h <= 0) return; + uint32_t *temp_buf = malloc(disp_w * disp_h * sizeof(uint32_t)); if (temp_buf) { - if (disp_w == viewer_img_w && disp_h == viewer_img_h) { - // Fast path: 1:1 - for (int i = 0; i < disp_w * disp_h; i++) temp_buf[i] = pixels[i]; - } else { - // Fixed-point 16.16 - uint32_t step_x = (viewer_img_w << 16) / disp_w; - uint32_t step_y = (viewer_img_h << 16) / disp_h; - uint32_t curr_y = 0; + // Fixed-point 16.16 + uint32_t step_x = (viewer_img_w << 16) / disp_w; + uint32_t step_y = (viewer_img_h << 16) / disp_h; + uint32_t curr_y = 0; - for (int y = 0; y < disp_h; y++) { - uint32_t src_y = curr_y >> 16; - if (src_y >= (uint32_t)viewer_img_h) src_y = viewer_img_h - 1; - uint32_t curr_x = 0; - uint32_t src_row_off = src_y * viewer_img_w; - uint32_t dst_row_off = y * disp_w; - for (int x = 0; x < disp_w; x++) { - uint32_t src_x = curr_x >> 16; - if (src_x >= (uint32_t)viewer_img_w) src_x = viewer_img_w - 1; - temp_buf[dst_row_off + x] = pixels[src_row_off + src_x]; - curr_x += step_x; - } - curr_y += step_y; + for (int y = 0; y < disp_h; y++) { + uint32_t src_y = curr_y >> 16; + if (src_y >= (uint32_t)viewer_img_h) src_y = viewer_img_h - 1; + uint32_t curr_x = 0; + uint32_t src_row_off = src_y * viewer_img_w; + uint32_t dst_row_off = y * disp_w; + for (int x = 0; x < disp_w; x++) { + uint32_t src_x = curr_x >> 16; + if (src_x >= (uint32_t)viewer_img_w) src_x = viewer_img_w - 1; + temp_buf[dst_row_off + x] = pixels[src_row_off + src_x]; + curr_x += step_x; } + curr_y += step_y; } ui_draw_image(win, ox, oy, disp_w, disp_h, temp_buf); free(temp_buf); @@ -271,8 +271,13 @@ void viewer_open_file(const char *path) { viewer_title[ti] = 0; win_w = fit_w + 16; - if (win_w < 200) win_w = 200; win_h = fit_h + 34; + + // Cap initial window size to 1024x768 (or image size if smaller) + if (win_w > 1024) win_w = 1024; + if (win_h > 768) win_h = 768; + + if (win_w < 200) win_w = 200; if (win_h < 100) win_h = 100; } @@ -284,18 +289,37 @@ int main(int argc, char **argv) { ui_window_t win = ui_window_create(viewer_title, 100, 50, win_w, win_h); if (!win) return 1; + ui_window_set_resizable(win, true); + gui_event_t ev; while (1) { 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 - 20); + } else if (ev.type == GUI_EVENT_RESIZE) { + win_w = ev.arg1; + win_h = ev.arg2; + resize_pending = true; + last_resize_tick = sys_system(16, 0, 0, 0, 0); + // Fast background clear during active resize + ui_draw_rect(win, 0, 0, win_w, win_h, 0xFF000000); + ui_mark_dirty(win, 0, 0, win_w, win_h - 20); } else if (ev.type == GUI_EVENT_CLICK) { // No actions currently } else if (ev.type == GUI_EVENT_CLOSE) { sys_exit(0); } } else { + if (resize_pending) { + uint64_t now = sys_system(16, 0, 0, 0, 0); + if (now > last_resize_tick + 10) { + viewer_paint(win); + ui_mark_dirty(win, 0, 0, win_w, win_h - 20); + resize_pending = false; + } + } + if (viewer_has_image && viewer_frame_count > 1) { uint64_t now = sys_system(16, 0, 0, 0, 0); if (now >= viewer_next_frame_tick) { diff --git a/src/wm/explorer.c b/src/wm/explorer.c index 832aebd..7e8bd4a 100644 --- a/src/wm/explorer.c +++ b/src/wm/explorer.c @@ -408,7 +408,7 @@ bool explorer_delete_recursive(const char *path) { for (int k = i + 1; k < len; k++) filename[j++] = path[k]; filename[j] = 0; - char drive_prefix[3] = "A:"; + char drive_prefix[3] = "/"; if (path[0] && path[1] == ':') { drive_prefix[0] = path[0]; } @@ -810,15 +810,15 @@ static void explorer_open_target(const char *path) { if (explorer_str_ends_with(path, ".elf")) { process_create_elf(path, NULL); } else if (explorer_str_ends_with(path, ".pdf")) { - process_create_elf("A:/bin/boredword.elf", path); + process_create_elf("/bin/boredword.elf", path); } else if (explorer_is_markdown_file(path)) { - process_create_elf("A:/bin/markdown.elf", path); + process_create_elf("/bin/markdown.elf", path); } else if (explorer_str_ends_with(path, ".pnt")) { - process_create_elf("A:/bin/paint.elf", path); + process_create_elf("/bin/paint.elf", path); } else if (explorer_is_image_file(path)) { - process_create_elf("A:/bin/viewer.elf", path); + process_create_elf("/bin/viewer.elf", path); } else { - process_create_elf("A:/bin/txtedit.elf", path); + process_create_elf("/bin/txtedit.elf", path); } } } @@ -1702,7 +1702,7 @@ static void explorer_handle_file_context_menu_click(Window *win, int x, int y) { state->dialog_input_cursor = explorer_strlen(state->dialog_input); explorer_strcpy(state->dialog_target_path, full_path); } else if (clicked_action == 110) { // Open with Text Editor - process_create_elf("A:/bin/txtedit.elf", full_path); + process_create_elf("/bin/txtedit.elf", full_path); } else if (clicked_action == ACTION_RESTORE) { explorer_restore_file(win, state->file_context_menu_item); } else if (clicked_action == ACTION_CREATE_SHORTCUT) { @@ -1886,7 +1886,7 @@ Window* explorer_create_window(const char *path) { state->explorer_scroll_row = 0; state->dialog_state = DIALOG_NONE; - if (explorer_strcmp(path, "/") == 0) explorer_load_directory(win, "A:/"); + if (explorer_strcmp(path, "/") == 0) explorer_load_directory(win, "/"); else explorer_load_directory(win, path); explorer_wins[explorer_win_count++] = win; @@ -1923,11 +1923,11 @@ void explorer_init(void) { state->dialog_state = DIALOG_NONE; explorer_wins[explorer_win_count++] = &win_explorer; - explorer_load_directory(&win_explorer, "A:/"); + explorer_load_directory(&win_explorer, "/"); } void explorer_reset(void) { ExplorerState *state = (ExplorerState*)win_explorer.data; - explorer_load_directory(&win_explorer, "A:/"); + explorer_load_directory(&win_explorer, "/"); state->explorer_scroll_row = 0; win_explorer.focused = false; }