Files
cleonos/cleonos/c/apps/uwm/uwm_app.c

311 lines
8.3 KiB
C
Raw Normal View History

2026-04-25 20:03:34 +08:00
#include "uwm.h"
static void ush_uwm_usage(void) {
ush_writeln("usage: uwm");
2026-04-26 00:43:06 +08:00
ush_writeln("keys: q quit, tab focus, 1/2/3 restore, wasd/arrow move");
ush_writeln("keys: m minimize, x close, t pin top, +/- resize");
ush_writeln("mouse: drag titlebar, resize bottom-right, use taskbar/start");
2026-04-25 20:03:34 +08:00
}
static int ush_uwm_parse_args(const char *arg) {
char first[USH_PATH_MAX];
const char *rest = "";
2026-04-26 00:43:06 +08:00
if (arg == (const char *)0 || arg[0] == 0) {
2026-04-25 20:03:34 +08:00
return 1;
}
if (ush_split_first_and_rest(arg, first, (u64)sizeof(first), &rest) == 0) {
return 0;
}
2026-04-26 00:43:06 +08:00
if (rest != (const char *)0 && rest[0] != 0) {
2026-04-25 20:03:34 +08:00
return 0;
}
if (ush_streq(first, "--help") != 0 || ush_streq(first, "-h") != 0) {
return 2;
}
return 0;
}
2026-04-26 00:43:06 +08:00
static int ush_uwm_fail(ush_uwm_session *sess, const char *message) {
if (sess != (ush_uwm_session *)0 && message != (const char *)0) {
ush_copy(sess->last_error, (u64)sizeof(sess->last_error), message);
}
return 0;
}
static int ush_uwm_work_bottom(const ush_uwm_session *sess) {
int bottom;
if (sess == (const ush_uwm_session *)0) {
return USH_UWM_TOP_CLAMP_Y;
}
bottom = sess->screen_h - USH_UWM_TASKBAR_H;
if (bottom < USH_UWM_TOP_CLAMP_Y) {
bottom = USH_UWM_TOP_CLAMP_Y;
}
return bottom;
}
static int ush_uwm_fit_dimension(int wanted, int min_value, int max_value) {
if (max_value < 64) {
return 64;
}
if (max_value < min_value) {
return max_value;
}
return ush_uwm_clampi(wanted, min_value, max_value);
}
static void ush_uwm_init_window(ush_uwm_window *win, ush_uwm_window_kind kind, const char *title, const char *subtitle,
int x, int y, int w, int h, ush_uwm_u32 accent, int topmost, int closed) {
if (win == (ush_uwm_window *)0) {
return;
}
win->id = 0ULL;
win->x = x;
win->y = y;
win->w = w;
win->h = h;
win->pixels = (ush_uwm_u32 *)0;
win->pixel_count = 0ULL;
win->alive = 0;
win->minimized = 0;
win->closed = closed;
win->topmost = topmost;
win->dirty = 1;
win->kind = kind;
win->accent = accent;
ush_copy(win->title, (u64)sizeof(win->title), title);
ush_copy(win->subtitle, (u64)sizeof(win->subtitle), subtitle);
}
static int ush_uwm_boot_window(ush_uwm_session *sess, int index) {
ush_uwm_window *win;
if (sess == (ush_uwm_session *)0 || ush_uwm_window_index_valid(index) == 0) {
return 0;
}
win = &sess->windows[index];
if (win->closed != 0) {
return 0;
}
if (win->pixels == (ush_uwm_u32 *)0 && ush_uwm_alloc_pixels(win) == 0) {
return 0;
}
ush_uwm_render_window(sess, index);
if (ush_uwm_create_window(win) == 0) {
return 0;
}
if (ush_uwm_present_window(win) == 0) {
ush_uwm_destroy_kernel_window(win);
return 0;
}
return 1;
}
2026-04-25 20:03:34 +08:00
int ush_uwm_prepare_session(ush_uwm_session *sess) {
cleonos_fb_info fb;
2026-04-26 00:43:06 +08:00
int work_bottom;
int work_h;
2026-04-25 20:03:34 +08:00
int base_w;
int base_h;
2026-04-26 00:43:06 +08:00
int start_w;
int start_h;
int app_gap;
int i;
const char *titles[USH_UWM_APP_COUNT] = {"FILE EXPLORER", "NOTEPAD", "EDGE"};
const char *subtitles[USH_UWM_APP_COUNT] = {"LOCAL DISK AND SYSTEM FILES", "EDIT TEXT INSIDE CLEONOS",
"WEB PREVIEW AND HTTP TOOLS"};
const ush_uwm_u32 accents[USH_UWM_APP_COUNT] = {0x000078D7U, 0x0000A300U, 0x00007ACCU};
2026-04-25 20:03:34 +08:00
if (sess == (ush_uwm_session *)0) {
return 0;
}
ush_zero(sess, (u64)sizeof(*sess));
2026-04-26 00:43:06 +08:00
ush_copy(sess->last_error, (u64)sizeof(sess->last_error), "uwm: init failed");
2026-04-25 20:03:34 +08:00
if (cleonos_sys_fb_info(&fb) == 0ULL || fb.width == 0ULL || fb.height == 0ULL || fb.bpp != 32ULL) {
2026-04-26 00:43:06 +08:00
return ush_uwm_fail(sess, "uwm: framebuffer unavailable");
2026-04-25 20:03:34 +08:00
}
if (fb.width > 4096ULL || fb.height > 4096ULL) {
2026-04-26 00:43:06 +08:00
return ush_uwm_fail(sess, "uwm: framebuffer is larger than 4096x4096");
2026-04-25 20:03:34 +08:00
}
sess->screen_w = (int)fb.width;
sess->screen_h = (int)fb.height;
sess->active_window = 0;
sess->drag_window = -1;
2026-04-26 00:43:06 +08:00
sess->resize_window = -1;
2026-04-25 20:03:34 +08:00
sess->tty_before = cleonos_sys_tty_active();
2026-04-26 00:43:06 +08:00
work_bottom = ush_uwm_work_bottom(sess);
work_h = work_bottom - USH_UWM_TOP_CLAMP_Y;
if (work_h < 80) {
work_h = 80;
2026-04-25 20:03:34 +08:00
}
2026-04-26 00:43:06 +08:00
base_w = ush_uwm_fit_dimension(USH_UWM_APP_START_W, USH_UWM_MIN_WINDOW_W, sess->screen_w - 48);
base_h = ush_uwm_fit_dimension(USH_UWM_APP_START_H, USH_UWM_MIN_WINDOW_H, work_h - 32);
app_gap = (sess->screen_w > 900) ? 120 : 58;
for (i = 0; i < (int)USH_UWM_APP_COUNT; i++) {
2026-04-25 20:03:34 +08:00
int max_x = sess->screen_w - base_w;
2026-04-26 00:43:06 +08:00
int max_y = work_bottom - base_h;
int x = 56 + (i * app_gap);
int y = 64 + (i * 46);
2026-04-25 20:03:34 +08:00
if (max_x < 0) {
max_x = 0;
}
2026-04-26 00:43:06 +08:00
if (max_y < USH_UWM_TOP_CLAMP_Y) {
max_y = USH_UWM_TOP_CLAMP_Y;
2026-04-25 20:03:34 +08:00
}
2026-04-26 00:43:06 +08:00
ush_uwm_init_window(&sess->windows[i], USH_UWM_KIND_APP, titles[i], subtitles[i], ush_uwm_clampi(x, 0, max_x),
ush_uwm_clampi(y, USH_UWM_TOP_CLAMP_Y, max_y), base_w, base_h, accents[i], 0, 0);
}
ush_uwm_init_window(&sess->windows[USH_UWM_TASKBAR_INDEX], USH_UWM_KIND_TASKBAR, "TASKBAR", "", 0,
sess->screen_h - USH_UWM_TASKBAR_H, sess->screen_w, USH_UWM_TASKBAR_H, 0x000078D7U, 1, 0);
if (sess->windows[USH_UWM_TASKBAR_INDEX].y < USH_UWM_TOP_CLAMP_Y) {
sess->windows[USH_UWM_TASKBAR_INDEX].y = USH_UWM_TOP_CLAMP_Y;
}
start_w = ush_uwm_fit_dimension(USH_UWM_START_W, 180, sess->screen_w - 16);
start_h = ush_uwm_fit_dimension(USH_UWM_START_H, 160, work_h - 8);
ush_uwm_init_window(&sess->windows[USH_UWM_START_INDEX], USH_UWM_KIND_START, "START", "", 0,
sess->screen_h - USH_UWM_TASKBAR_H - start_h, start_w, start_h, 0x000078D7U, 1, 1);
if (sess->windows[USH_UWM_START_INDEX].y < USH_UWM_TOP_CLAMP_Y) {
sess->windows[USH_UWM_START_INDEX].y = USH_UWM_TOP_CLAMP_Y;
2026-04-25 20:03:34 +08:00
}
return 1;
}
int ush_uwm_start(ush_uwm_session *sess) {
int i;
2026-04-26 00:43:06 +08:00
int started = 0;
2026-04-25 20:03:34 +08:00
if (sess == (ush_uwm_session *)0) {
return 0;
}
2026-04-26 00:43:06 +08:00
if (ush_uwm_boot_window(sess, USH_UWM_TASKBAR_INDEX) == 0) {
return ush_uwm_fail(sess, "uwm: taskbar create failed");
}
2026-04-25 20:03:34 +08:00
2026-04-26 00:43:06 +08:00
for (i = 0; i < (int)USH_UWM_APP_COUNT; i++) {
if (ush_uwm_boot_window(sess, i) != 0) {
started++;
2026-04-25 20:03:34 +08:00
}
2026-04-26 00:43:06 +08:00
}
2026-04-25 20:03:34 +08:00
2026-04-26 00:43:06 +08:00
if (started == 0) {
return ush_uwm_fail(sess, "uwm: app window create failed");
}
2026-04-25 20:03:34 +08:00
2026-04-26 00:43:06 +08:00
for (i = (int)USH_UWM_APP_COUNT - 1; i >= 0; i--) {
if (sess->windows[i].alive != 0) {
ush_uwm_set_active(sess, i);
break;
2026-04-25 20:03:34 +08:00
}
}
2026-04-26 00:43:06 +08:00
ush_uwm_refresh_taskbar(sess);
2026-04-25 20:03:34 +08:00
return 1;
}
void ush_uwm_stop(ush_uwm_session *sess) {
int i;
if (sess == (ush_uwm_session *)0) {
return;
}
for (i = 0; i < (int)USH_UWM_WINDOW_COUNT; i++) {
ush_uwm_destroy_window(&sess->windows[i]);
}
}
int ush_uwm_switch_to_display_tty(ush_uwm_session *sess) {
if (sess == (ush_uwm_session *)0) {
return 0;
}
if (sess->tty_before != USH_UWM_TTY_DISPLAY) {
(void)cleonos_sys_tty_switch(USH_UWM_TTY_DISPLAY);
sess->tty_switched = 1;
}
return 1;
}
void ush_uwm_restore_tty(ush_uwm_session *sess) {
if (sess == (ush_uwm_session *)0) {
return;
}
if (sess->tty_switched != 0) {
(void)cleonos_sys_tty_switch(sess->tty_before);
sess->tty_switched = 0;
}
}
int ush_cmd_uwm(const char *arg) {
ush_uwm_session sess;
int parse_result;
int success = 0;
parse_result = ush_uwm_parse_args(arg);
if (parse_result == 2) {
ush_uwm_usage();
return 1;
}
if (parse_result == 0) {
ush_uwm_usage();
return 0;
}
if (ush_uwm_prepare_session(&sess) == 0) {
2026-04-26 00:43:06 +08:00
ush_writeln(sess.last_error);
2026-04-25 20:03:34 +08:00
return 0;
}
ush_uwm_drain_startup_keys();
(void)ush_uwm_switch_to_display_tty(&sess);
if (ush_uwm_start(&sess) == 0) {
ush_uwm_stop(&sess);
ush_uwm_restore_tty(&sess);
2026-04-26 00:43:06 +08:00
ush_writeln(sess.last_error);
2026-04-25 20:03:34 +08:00
return 0;
}
if (ush_uwm_loop(&sess) != 0) {
success = 1;
}
ush_uwm_stop(&sess);
ush_uwm_restore_tty(&sess);
ush_writeln("uwm: exit");
return success;
}