checkpoint: BoredWord application

This commit is contained in:
boreddevnl 2026-03-17 14:41:13 +01:00
parent d824b4610a
commit 88f178e368
13 changed files with 1976 additions and 56 deletions

BIN
disk.img

Binary file not shown.

View file

@ -497,6 +497,83 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
}
}
asm volatile("push %0; popfq" : : "r"(rflags));
}
} else if (cmd == 18) { // GUI_CMD_DRAW_STRING_SCALED_SLOPED
Window *win = (Window *)arg2;
uint64_t coords = arg3;
int ux = coords & 0xFFFFFFFF;
int uy = coords >> 32;
const char *user_str = (const char *)arg4;
// Unpack color, scale, slope from arg5
uint64_t packed1 = arg5;
uint32_t color = packed1 & 0xFFFFFFFF;
uint32_t scale_bits = packed1 >> 32;
float scale = *(float*)&scale_bits;
// Slope is passed via arg6 in the system call, but syscall5 only takes 5 args.
// Oh right, we only have syscall5. Let's make a packed struct or just use a generic pointer for coords.
// Even better, let's just make it a pointer to a struct.
// Wait, I will just use `regs->r9` (arg6) directly since the syscall handler has access to all registers:
uint64_t arg6 = regs->r9;
uint32_t slope_bits = arg6 & 0xFFFFFFFF;
float slope = *(float*)&slope_bits;
if (win && user_str) {
extern void draw_string_scaled_sloped(int x, int y, const char *str, uint32_t color, float scale, float slope);
extern void graphics_set_render_target(uint32_t *buffer, int w, int h);
// Copy string safely to kernel stack buffer
char kernel_str[256];
int i = 0;
while (i < 255 && user_str[i]) {
kernel_str[i] = user_str[i];
i++;
}
kernel_str[i] = 0;
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
ttf_font_t *font = win->font ? (ttf_font_t*)win->font : graphics_get_current_ttf();
if (win->pixels) {
if (ux >= -100 && ux < win->w && uy >= -100 && uy < (win->h - 20)) {
graphics_set_render_target(win->pixels, win->w, win->h - 20);
if (font) {
int baseline = uy + font_manager_get_font_ascent_scaled(font, scale) - 2;
int cur_x = ux;
const char *s = kernel_str;
while (*s) {
extern void font_manager_render_char_sloped(ttf_font_t *font, int x, int y, char c, uint32_t color, float scale, float slope, void (*put_pixel_fn)(int, int, uint32_t));
font_manager_render_char_sloped(font, cur_x, baseline, *s, color, scale, slope, put_pixel);
char buf[2] = {*s, 0};
cur_x += font_manager_get_string_width_scaled(font, buf, scale);
s++;
}
} else {
draw_string_scaled_sloped(ux, uy, kernel_str, color, scale, slope);
}
graphics_set_render_target(NULL, 0, 0);
}
} else {
if (font) {
int baseline = win->y + uy + font_manager_get_font_ascent_scaled(font, scale) - 2;
int cur_x = win->x + ux;
const char *s = kernel_str;
while (*s) {
extern void font_manager_render_char_sloped(ttf_font_t *font, int x, int y, char c, uint32_t color, float scale, float slope, void (*put_pixel_fn)(int, int, uint32_t));
font_manager_render_char_sloped(font, cur_x, baseline, *s, color, scale, slope, put_pixel);
char buf[2] = {*s, 0};
cur_x += font_manager_get_string_width_scaled(font, buf, scale);
s++;
}
} else {
draw_string_scaled_sloped(win->x + ux, win->y + uy, kernel_str, color, scale, slope);
}
}
asm volatile("push %0; popfq" : : "r"(rflags));
}
} else if (cmd == GUI_CMD_DRAW_IMAGE) {

1516
src/userland/gui/word.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -6,6 +6,7 @@
extern uint64_t syscall3(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3);
extern uint64_t syscall4(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4);
extern uint64_t syscall5(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5);
extern uint64_t syscall6(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6);
// sys_gui uses syscall #3
#define SYS_GUI 3
@ -71,6 +72,16 @@ void ui_draw_string_scaled(ui_window_t win, int x, int y, const char *str, uint3
syscall5(SYS_GUI, GUI_CMD_DRAW_STRING_SCALED, (uint64_t)win, coords, (uint64_t)str, packed_arg5);
}
void ui_draw_string_scaled_sloped(ui_window_t win, int x, int y, const char *str, uint32_t color, float scale, float slope) {
uint64_t coords = ((uint64_t)x & 0xFFFFFFFF) | ((uint64_t)y << 32);
// Pack color into lower 32, scale (as uint32_t representation) into upper 32
uint32_t scale_bits = *(uint32_t*)&scale;
uint32_t slope_bits = *(uint32_t*)&slope;
uint64_t packed_arg5 = ((uint64_t)scale_bits << 32) | (color & 0xFFFFFFFF);
syscall6(SYS_GUI, GUI_CMD_DRAW_STRING_SCALED_SLOPED, (uint64_t)win, coords, (uint64_t)str, packed_arg5, (uint64_t)slope_bits);
}
uint32_t ui_get_string_width_scaled(const char *str, float scale) {
uint32_t scale_bits = *(uint32_t*)&scale;
return (uint32_t)syscall4(SYS_GUI, GUI_CMD_GET_STRING_WIDTH_SCALED, (uint64_t)str, (uint64_t)scale_bits, 0);

View file

@ -21,6 +21,7 @@
#define GUI_CMD_GET_FONT_HEIGHT_SCALED 13
#define GUI_CMD_WINDOW_SET_TITLE 15
#define GUI_CMD_SET_FONT 16
#define GUI_CMD_DRAW_STRING_SCALED_SLOPED 18
// Event Types
#define GUI_EVENT_NONE 0
@ -62,6 +63,7 @@ void ui_get_screen_size(uint64_t *out_w, uint64_t *out_h);
void ui_draw_string_bitmap(ui_window_t win, int x, int y, const char *str, uint32_t color);
void ui_draw_string_scaled(ui_window_t win, int x, int y, const char *str, uint32_t color, float scale);
void ui_draw_string_scaled_sloped(ui_window_t win, int x, int y, const char *str, uint32_t color, float scale, float slope);
uint32_t ui_get_string_width_scaled(const char *str, float scale);
uint32_t ui_get_font_height_scaled(float scale);
void ui_window_set_title(ui_window_t win, const char *title);

View file

@ -59,6 +59,18 @@ uint64_t syscall5(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3,
return ret;
}
uint64_t syscall6(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6) {
uint64_t ret;
register uint64_t r10 asm("r10") = arg4;
register uint64_t r8 asm("r8") = arg5;
register uint64_t r9 asm("r9") = arg6;
asm volatile("syscall"
: "=a"(ret)
: "a"(sys_num), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory");
return ret;
}
void sys_exit(int status) {
syscall1(SYS_EXIT, (uint64_t)status);

View file

@ -750,6 +750,8 @@ static void explorer_open_target(const char *path) {
} else {
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/word.elf", path);
} else if (explorer_is_markdown_file(path)) {
process_create_elf("A:/bin/markdown.elf", path);
} else if (explorer_str_ends_with(path, ".pnt")) {
@ -842,6 +844,8 @@ static void explorer_draw_file_icon(int x, int y, bool is_dir, uint32_t color, c
if (full_path[explorer_strlen(full_path) - 1] != '/') explorer_strcat(full_path, "/");
explorer_strcat(full_path, filename);
draw_image_icon(x + 5, y + 5, full_path);
} else if (explorer_str_ends_with(filename, ".pdf")) {
draw_pdf_icon(x + 5, y + 5, "");
} else if (explorer_str_ends_with(filename, ".elf")) {
draw_elf_icon(x + 5, y + 5, "");
} else {

View file

@ -17,12 +17,10 @@ float kfabsf(float x) {
}
float kpowf(float b, float e) {
// Very simplified pow for stb_truetype's needs
if (e == 0) return 1.0f;
if (e == 1) return b;
if (e == 0.5f) return ksqrtf(b);
// Fallback/log-based would be complex, let's see if this suffices
float res = 1.0f;
for (int i = 0; i < (int)e; i++) res *= b;
return res;
@ -33,13 +31,11 @@ float kfmodf(float x, float y) {
}
float kcosf(float x) {
// Taylor series for cos(x) around 0
float x2 = x * x;
return 1.0f - (x2 / 2.0f) + (x2 * x2 / 24.0f) - (x2 * x2 * x2 / 720.0f);
}
float kacosf(float x) {
// Very rough approximation for acos(x)
if (x >= 1.0f) return 0;
if (x <= -1.0f) return 3.14159f;
return 1.57079f - x - (x*x*x)/6.0f;
@ -59,6 +55,15 @@ static inline uint32_t alpha_blend(uint32_t bg, uint32_t fg, uint8_t alpha) {
static ttf_font_t *default_font = NULL;
#define MAX_LOADED_FONTS 8
typedef struct {
char path[128];
ttf_font_t *font;
} loaded_font_t;
static loaded_font_t loaded_fonts[MAX_LOADED_FONTS];
static int loaded_font_count = 0;
#define FONT_CACHE_SIZE 2048
typedef struct {
char c;
@ -67,15 +72,22 @@ typedef struct {
unsigned char *bitmap;
} font_cache_entry_t;
// Cache is disabled for now due to race conditions and collisions
// static font_cache_entry_t g_font_cache[FONT_CACHE_SIZE];
bool font_manager_init(void) {
// We'll load a default font later if available
return true;
}
ttf_font_t* font_manager_load(const char *path, float size) {
(void)size;
for(int i=0; i<loaded_font_count; i++) {
int match = 1;
for(int j=0; path[j] || loaded_fonts[i].path[j]; j++) {
if (path[j] != loaded_fonts[i].path[j]) { match = 0; break; }
}
if (match) return loaded_fonts[i].font;
}
FAT32_FileHandle *fh = fat32_open(path, "r");
if (!fh || !fh->valid) {
serial_write("[FONT] Failed to open font file: ");
@ -126,6 +138,13 @@ ttf_font_t* font_manager_load(const char *path, float size) {
stbtt_GetFontVMetrics(info, &font->ascent, &font->descent, &font->line_gap);
if (!default_font) default_font = font;
if (loaded_font_count < MAX_LOADED_FONTS) {
int i=0; while(path[i] && i<127) { loaded_fonts[loaded_font_count].path[i] = path[i]; i++; }
loaded_fonts[loaded_font_count].path[i] = 0;
loaded_fonts[loaded_font_count].font = font;
loaded_font_count++;
}
return font;
}
@ -145,16 +164,16 @@ void font_manager_render_char_scaled(ttf_font_t *font, int x, int y, char c, uin
unsigned char *bitmap = NULL;
int w, h, xoff, yoff;
float real_scale = stbtt_ScaleForPixelHeight(info, scale); // Convert pixel size back to stbtt scale
float real_scale = stbtt_ScaleForPixelHeight(info, scale);
int codepoint = (unsigned char)c;
if (codepoint == 128) codepoint = 0x2014; // &mdash; (—)
if (codepoint == 129) codepoint = 0x2013; // &ndash; ()
if (codepoint == 130) codepoint = 0x2022; // &bull; (•)
if (codepoint == 131) codepoint = 0x2026; // &hellip; (…)
if (codepoint == 132) codepoint = 0x2122; // &trade; (™)
if (codepoint == 133) codepoint = 0x20AC; // &euro; (€)
if (codepoint == 134) codepoint = 0x00B7; // &middot; (·)
if (codepoint == 128) codepoint = 0x2014;
if (codepoint == 129) codepoint = 0x2013;
if (codepoint == 130) codepoint = 0x2022;
if (codepoint == 131) codepoint = 0x2026;
if (codepoint == 132) codepoint = 0x2122;
if (codepoint == 133) codepoint = 0x20AC;
if (codepoint == 134) codepoint = 0x00B7;
bitmap = stbtt_GetCodepointBitmap(info, 0, real_scale, codepoint, &w, &h, &xoff, &yoff);
@ -174,6 +193,46 @@ void font_manager_render_char_scaled(ttf_font_t *font, int x, int y, char c, uin
}
}
void font_manager_render_char_sloped(ttf_font_t *font, int x, int y, char c, uint32_t color, float scale, float slope, void (*put_pixel_fn)(int, int, uint32_t)) {
if (!font) font = default_font;
if (!font) return;
stbtt_fontinfo *info = (stbtt_fontinfo *)font->info;
unsigned char *bitmap = NULL;
int w, h, xoff, yoff;
float real_scale = stbtt_ScaleForPixelHeight(info, scale);
int codepoint = (unsigned char)c;
if (codepoint == 128) codepoint = 0x2014;
if (codepoint == 129) codepoint = 0x2013;
if (codepoint == 130) codepoint = 0x2022;
if (codepoint == 131) codepoint = 0x2026;
if (codepoint == 132) codepoint = 0x2122;
if (codepoint == 133) codepoint = 0x20AC;
if (codepoint == 134) codepoint = 0x00B7;
bitmap = stbtt_GetCodepointBitmap(info, 0, real_scale, codepoint, &w, &h, &xoff, &yoff);
if (bitmap) {
for (int row = 0; row < h; row++) {
int slant_offset = (int)((h - row) * slope);
for (int col = 0; col < w; col++) {
unsigned char alpha = bitmap[row * w + col];
if (alpha > 0) {
int px = x + col + xoff + slant_offset;
int py = y + row + yoff;
uint32_t bg = graphics_get_pixel(px, py);
put_pixel_fn(px, py, alpha_blend(bg, color, alpha));
}
}
}
stbtt_FreeBitmap(bitmap, NULL);
}
}
int font_manager_get_string_width(ttf_font_t *font, const char *s) {
if (!font) font = default_font;
if (!font) return 0;
@ -211,15 +270,14 @@ int font_manager_get_string_width_scaled(ttf_font_t *font, const char *s, float
while (*s) {
int advance, lsb;
int codepoint = (unsigned char)*s;
if (codepoint == 128) codepoint = 0x2014; // &mdash; (—)
if (codepoint == 129) codepoint = 0x2013; // &ndash; ()
if (codepoint == 130) codepoint = 0x2022; // &bull; (•)
if (codepoint == 131) codepoint = 0x2026; // &hellip; (…)
if (codepoint == 132) codepoint = 0x2122; // &trade; (™)
if (codepoint == 133) codepoint = 0x20AC; // &euro; (€)
if (codepoint == 134) codepoint = 0x00B7; // &middot; (·)
if (codepoint == 128) codepoint = 0x2014;
if (codepoint == 129) codepoint = 0x2013;
if (codepoint == 130) codepoint = 0x2022;
if (codepoint == 131) codepoint = 0x2026;
if (codepoint == 132) codepoint = 0x2122;
if (codepoint == 133) codepoint = 0x20AC;
if (codepoint == 134) codepoint = 0x00B7;
stbtt_GetCodepointHMetrics(info, codepoint, &advance, &lsb);
// Round per-character to match draw_string's accumulation
width += (int)(advance * real_scale + 0.5f);
s++;
}

View file

@ -5,7 +5,6 @@
#include <stdbool.h>
#include <stddef.h>
// stb_truetype math stubs
extern float ksqrtf(float x);
extern float kpowf(float b, float e);
extern float kfmodf(float x, float y);
@ -24,21 +23,18 @@ extern float kfabsf(float x);
#define STBTT_assert(x) ((void)0)
// Memory management
#define STBTT_malloc(x,u) kmalloc(x)
#define STBTT_free(x,u) kfree(x)
// String functions
#define STBTT_memcpy mem_memcpy
#define STBTT_memset mem_memset
// Data types
typedef uint64_t STBTT_ptrsize;
typedef struct {
void *data;
size_t size;
void *info; // stbtt_fontinfo
void *info;
float scale;
float pixel_height;
int ascent;
@ -50,6 +46,7 @@ bool font_manager_init(void);
ttf_font_t* font_manager_load(const char *path, float size);
void font_manager_render_char(ttf_font_t *font, int x, int y, char c, uint32_t color, void (*put_pixel_fn)(int, int, uint32_t));
void font_manager_render_char_scaled(ttf_font_t *font, int x, int y, char c, uint32_t color, float scale, void (*put_pixel_fn)(int, int, uint32_t));
void font_manager_render_char_sloped(ttf_font_t *font, int x, int y, char c, uint32_t color, float scale, float slope, void (*put_pixel_fn)(int, int, uint32_t));
int font_manager_get_string_width(ttf_font_t *font, const char *s);
int font_manager_get_string_width_scaled(ttf_font_t *font, const char *s, float scale);

View file

@ -6,6 +6,7 @@
#include "font.h"
#include "io.h"
#include "font_manager.h"
#include "../mem/memory_manager.h"
static struct limine_framebuffer *g_fb = NULL;
static uint32_t g_bg_color = 0xFF696969;
@ -329,6 +330,128 @@ void draw_rounded_rect_filled(int x, int y, int w, int h, int radius, uint32_t c
}
}
static uint32_t blend_color_alpha(uint32_t bottom, uint32_t top, int alpha) {
if (alpha <= 0) return bottom;
if (alpha >= 255) return top;
int rb = (bottom >> 16) & 0xFF;
int gb = (bottom >> 8) & 0xFF;
int bb = bottom & 0xFF;
int rt = (top >> 16) & 0xFF;
int gt = (top >> 8) & 0xFF;
int bt = top & 0xFF;
int rr = rb + (((rt - rb) * alpha) >> 8);
int gg = gb + (((gt - gb) * alpha) >> 8);
int bb_new = bb + (((bt - bb) * alpha) >> 8);
return (rr << 16) | (gg << 8) | bb_new;
}
void draw_rounded_rect_blurred(int x, int y, int w, int h, int radius, uint32_t tint_color, int blur_radius, int alpha) {
if (!g_fb) return;
int sw = get_screen_width();
int sh = get_screen_height();
if (x < 0) { w += x; x = 0; }
if (y < 0) { h += y; y = 0; }
if (x + w > sw) w = sw - x;
if (y + h > sh) h = sh - y;
if (w <= 0 || h <= 0) return;
if (radius > w / 2) radius = w / 2;
if (radius > h / 2) radius = h / 2;
if (radius < 1) radius = 1;
uint32_t *tmp_buf = (uint32_t *)kmalloc(w * h * sizeof(uint32_t));
if (!tmp_buf) {
draw_rounded_rect_filled(x, y, w, h, radius, tint_color);
return;
}
for (int r = 0; r < h; r++) {
int g_y = y + r;
for (int c = 0; c < w; c++) {
int g_x = x + c;
int r_sum = 0, g_sum = 0, b_sum = 0, count = 0;
int start_kx = g_x - blur_radius;
int end_kx = g_x + blur_radius;
if (start_kx < 0) start_kx = 0;
if (end_kx >= sw) end_kx = sw - 1;
for (int kx = start_kx; kx <= end_kx; kx++) {
uint32_t pixel = g_back_buffer[g_y * sw + kx];
r_sum += (pixel >> 16) & 0xFF;
g_sum += (pixel >> 8) & 0xFF;
b_sum += pixel & 0xFF;
count++;
}
if(count == 0) count = 1;
uint32_t out_pixel = ((r_sum / count) << 16) | ((g_sum / count) << 8) | (b_sum / count);
tmp_buf[r * w + c] = out_pixel;
}
}
for (int c = 0; c < w; c++) {
for (int r = 0; r < h; r++) {
int g_y = y + r;
int g_x = x + c;
if (g_clip_enabled) {
if (g_x < g_clip_x || g_x >= g_clip_x + g_clip_w ||
g_y < g_clip_y || g_y >= g_clip_y + g_clip_h) {
continue;
}
}
bool in_corner = false;
int dx = 0, dy = 0;
if (c < radius && r < radius) {
dx = radius - c - 1; dy = radius - r - 1;
in_corner = true;
} else if (c >= w - radius && r < radius) {
dx = c - (w - radius); dy = radius - r - 1;
in_corner = true;
} else if (c < radius && r >= h - radius) {
dx = radius - c - 1; dy = r - (h - radius);
in_corner = true;
} else if (c >= w - radius && r >= h - radius) {
dx = c - (w - radius); dy = r - (h - radius);
in_corner = true;
}
if (in_corner) {
if (dx*dx + dy*dy >= radius*radius) {
continue;
}
}
int r_sum = 0, g_sum = 0, b_sum = 0, count = 0;
int start_kr = r - blur_radius;
int end_kr = r + blur_radius;
if (start_kr < 0) start_kr = 0;
if (end_kr >= h) end_kr = h - 1;
for (int kr = start_kr; kr <= end_kr; kr++) {
uint32_t pixel = tmp_buf[kr * w + c];
r_sum += (pixel >> 16) & 0xFF;
g_sum += (pixel >> 8) & 0xFF;
b_sum += pixel & 0xFF;
count++;
}
if(count == 0) count = 1;
uint32_t blurred_pixel = ((r_sum / count) << 16) | ((g_sum / count) << 8) | (b_sum / count);
uint32_t final_pixel = blend_color_alpha(blurred_pixel, tint_color, alpha);
g_back_buffer[g_y * sw + g_x] = final_pixel;
}
}
kfree(tmp_buf);
}
void draw_char(int x, int y, char c, uint32_t color) {
if (g_current_ttf) {
font_manager_render_char(g_current_ttf, x, y, c, color, put_pixel);
@ -463,6 +586,37 @@ void draw_string_scaled(int x, int y, const char *s, uint32_t color, float scale
}
}
void draw_string_sloped(int x, int y, const char *s, uint32_t color, float slope) {
if (g_current_ttf) draw_string_scaled_sloped(x, y, s, color, g_current_ttf->pixel_height, slope);
else draw_string_scaled(x, y, s, color, 15.0f); // Fast fallback if no ttf
}
void draw_string_scaled_sloped(int x, int y, const char *s, uint32_t color, float scale, float slope) {
if (!s) return;
int cur_x = x;
if (g_current_ttf) {
int baseline = y + font_manager_get_font_ascent_scaled(g_current_ttf, scale) - 2;
int line_height = font_manager_get_font_line_height_scaled(g_current_ttf, scale);
while (*s) {
if (*s == '\n') {
cur_x = x;
baseline += line_height;
} else {
font_manager_render_char_sloped(g_current_ttf, cur_x, baseline, *s, color, scale, slope, put_pixel);
char buf[2] = {*s, 0};
cur_x += font_manager_get_string_width_scaled(g_current_ttf, buf, scale);
}
s++;
}
return;
}
// Fallback to normal draw_string_scaled if no TTF
draw_string_scaled(x, y, s, color, scale);
}
void draw_desktop_background(void) {
if (!g_fb) return;

View file

@ -21,10 +21,13 @@ uint32_t graphics_get_pixel(int x, int y);
void draw_rect(int x, int y, int w, int h, uint32_t color);
void draw_rounded_rect(int x, int y, int w, int h, int radius, uint32_t color);
void draw_rounded_rect_filled(int x, int y, int w, int h, int radius, uint32_t color);
void draw_rounded_rect_blurred(int x, int y, int w, int h, int radius, uint32_t tint_color, int blur_radius, int alpha);
void draw_char(int x, int y, char c, uint32_t color);
void draw_char_bitmap(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_scaled(int x, int y, const char *s, uint32_t color, float scale);
void draw_string_sloped(int x, int y, const char *s, uint32_t color, float slope);
void draw_string_scaled_sloped(int x, int y, const char *s, uint32_t color, float scale, float slope);
void draw_desktop_background(void);
void graphics_set_bg_color(uint32_t color);
void graphics_set_bg_pattern(const uint32_t *pattern); // 128x128 pattern

View file

@ -129,6 +129,7 @@ int desktop_max_cols = 23;
int mouse_speed = 10;
static int mouse_accum_x = 0;
static int mouse_accum_y = 0;
Window *active_mouse_capture_win = NULL;
// Helper to check if string ends with suffix
static bool str_ends_with(const char *str, const char *suffix) {
@ -508,6 +509,33 @@ void draw_document_icon(int x, int y, const char *label) {
draw_icon_label(x, y, label);
}
void draw_pdf_icon(int x, int y, const char *label) {
uint32_t icon_buf[48 * 48];
for (int i = 0; i < 48 * 48; i++) icon_buf[i] = 0xFFFF00FF;
graphics_set_render_target(icon_buf, 48, 48);
// Document shape
draw_rounded_rect_filled(4, 4, 40, 40, 8, 0xFFFFFFFF);
// Red banner
draw_rounded_rect_filled(8, 8, 32, 14, 4, 0xFFDF2020);
// PDF text roughly (simplified to lines for now)
draw_rect(14, 25, 20, 2, 0xFFBBBBBB);
draw_rect(14, 33, 14, 2, 0xFFBBBBBB);
graphics_set_render_target(NULL, 0, 0);
int dx = x + 24, dy = y + 12;
for (int ty = 0; ty < 32; ty++) {
for (int tx = 0; tx < 32; tx++) {
int src_x = tx * 48 / 32;
int src_y = ty * 48 / 32;
uint32_t c1 = icon_buf[src_y * 48 + src_x];
if (c1 != 0xFFFF00FF) put_pixel(dx + tx, dy + ty, c1);
}
}
draw_icon_label(x, y, label);
}
void draw_elf_icon(int x, int y, const char *label) {
uint32_t icon_buf[48 * 48];
for (int i = 0; i < 48 * 48; i++) icon_buf[i] = 0xFFFF00FF;
@ -912,6 +940,23 @@ static long long isqrt(long long n) {
return x;
}
static void draw_dock_word(int x, int y) {
// Rich blue document style
draw_rounded_rect_filled(x, y, 48, 48, 10, 0xFF4A90E2);
draw_rounded_rect_filled(x + 1, y + 1, 46, 28, 9, 0xFF5D9CE6);
draw_rounded_rect_filled(x + 1, y + 24, 46, 23, 9, 0xFF3A80D2);
// White document page in center
draw_rounded_rect_filled(x + 8, y + 8, 32, 32, 4, 0xFFFFFFFF);
// Blue header edge
draw_rounded_rect_filled(x + 8, y + 8, 32, 8, 4, 0xFF2868B8);
// Text lines using dark grey
draw_rect(x + 14, y + 22, 20, 2, 0xFF666666);
draw_rect(x + 14, y + 27, 20, 2, 0xFF666666);
draw_rect(x + 14, y + 32, 14, 2, 0xFF666666);
}
static void draw_dock_notepad(int x, int y) {
draw_rounded_rect_filled(x, y, 48, 48, 10, 0xFFCC9A00);
draw_rounded_rect_filled(x + 1, y + 1, 46, 28, 9, 0xFFFFD700);
@ -1225,7 +1270,21 @@ void wm_paint(void) {
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
DirtyRect dirty = graphics_get_dirty_rect();
if (dirty.active) {
int d_h = 60;
int d_y = sh - d_h - 6;
int d_item_sz = 48;
int d_space = 10;
int d_tw = 10 * (d_item_sz + d_space);
int d_bg_x = (sw - d_tw) / 2 - 12;
int d_bg_w = d_tw + 24;
if (!(dirty.x >= d_bg_x + d_bg_w || dirty.x + dirty.w <= d_bg_x ||
dirty.y >= d_y + d_h || dirty.y + dirty.h <= d_y)) {
graphics_mark_dirty(d_bg_x - 10, d_y - 10, d_bg_w + 20, d_h + 20);
dirty = graphics_get_dirty_rect();
}
graphics_set_clipping(dirty.x, dirty.y, dirty.w, dirty.h);
} else {
graphics_clear_clipping();
@ -1274,6 +1333,7 @@ void wm_paint(void) {
draw_image_icon(icon->x, icon->y, full_path);
draw_icon_label(icon->x, icon->y, icon->name);
}
else if (str_ends_with(icon->name, ".pdf")) draw_pdf_icon(icon->x, icon->y, icon->name);
else draw_document_icon(icon->x, icon->y, icon->name);
}
}
@ -1324,10 +1384,12 @@ void wm_paint(void) {
int dock_y = sh - dock_h - 6;
int dock_item_size = 48;
int dock_spacing = 10;
int total_dock_width = 10 * (dock_item_size + dock_spacing);
int total_dock_width = 11 * (dock_item_size + dock_spacing);
int dock_bg_x = (sw - total_dock_width) / 2 - 12;
int dock_bg_w = total_dock_width + 24;
draw_rounded_rect_filled(dock_bg_x, dock_y, dock_bg_w, dock_h, 18, COLOR_DOCK_BG);
// Draw blurred dock background with reduced radius and tint
draw_rounded_rect_blurred(dock_bg_x, dock_y, dock_bg_w, dock_h, 18, COLOR_DOCK_BG, 5, 140);
int dock_x = (sw - total_dock_width) / 2;
int dock_item_y = dock_y + 6;
@ -1351,7 +1413,8 @@ void wm_paint(void) {
draw_dock_taskman(dock_x, dock_item_y);
dock_x += dock_item_size + dock_spacing;
draw_dock_clock(dock_x, dock_item_y);
// Editor removed from dock
dock_x += dock_item_size + dock_spacing;
draw_dock_word(dock_x, dock_item_y);
// Desktop Context Menu (with rounded corners)
if (desktop_menu_visible) {
@ -1533,6 +1596,10 @@ void wm_remove_window(Window *win) {
}
window_count--;
if (active_mouse_capture_win == win) {
active_mouse_capture_win = NULL;
}
// Mark for redraw while protected
force_redraw = true;
} else {
@ -1905,7 +1972,7 @@ void wm_handle_right_click(int x, int y) {
int dock_y = sh - dock_h - 6;
int dock_item_size = 48;
int dock_spacing = 10;
int total_dock_width = 10 * (dock_item_size + dock_spacing);
int total_dock_width = 11 * (dock_item_size + dock_spacing);
int dock_bg_x = (sw - total_dock_width) / 2 - 12;
int dock_bg_w = total_dock_width + 24;
@ -1926,6 +1993,7 @@ void wm_handle_right_click(int x, int y) {
else if (item == 7) start_menu_pending_app = "Browser";
else if (item == 8) start_menu_pending_app = "Task Manager";
else if (item == 9) start_menu_pending_app = "Clock";
else if (item == 10) start_menu_pending_app = "Word Processor";
}
} else {
wm_handle_click(mx, my);
@ -2048,6 +2116,10 @@ void wm_handle_right_click(int x, int y) {
Window *existing = wm_find_window_by_title("Txtedit");
if (existing) wm_bring_to_front(existing);
else process_create_elf("/bin/txtedit.elf", NULL);
} else if (str_starts_with(start_menu_pending_app, "Word Processor")) {
Window *existing = wm_find_window_by_title("Word Processor");
if (existing) wm_bring_to_front(existing);
else process_create_elf("/bin/word.elf", NULL);
} else if (str_starts_with(start_menu_pending_app, "Terminal")) {
cmd_reset(); wm_bring_to_front(&win_cmd);
} else if (str_starts_with(start_menu_pending_app, "Calculator")) {
@ -2160,6 +2232,8 @@ void wm_handle_right_click(int x, int y) {
process_create_elf("/bin/paint.elf", path);
} else if (str_ends_with(icon->name, ".md")) {
process_create_elf("/bin/markdown.elf", path);
} else if (str_ends_with(icon->name, ".pdf")) {
process_create_elf("/bin/word.elf", path);
} else if (is_image_file(icon->name)) {
process_create_elf("/bin/viewer.elf", path);
} else {
@ -2385,46 +2459,57 @@ void wm_handle_right_click(int x, int y) {
}
}
if (topmost && topmost->data) {
active_mouse_capture_win = topmost;
if (my >= topmost->y + 20)
syscall_send_mouse_down_event(topmost, mx - topmost->x, my - topmost->y - 20);
} else {
active_mouse_capture_win = NULL;
}
}
if (!left && prev_left) {
// Left button released - send MOUSE_UP event to topmost window
Window *topmost = NULL;
int topmost_z = -1;
for (int w = 0; w < window_count; w++) {
Window *win = all_windows[w];
if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
if (win->z_index > topmost_z) {
topmost = win;
topmost_z = win->z_index;
// Left button released - send MOUSE_UP event to captured or topmost window
Window *target = active_mouse_capture_win;
if (!target) {
int topmost_z = -1;
for (int w = 0; w < window_count; w++) {
Window *win = all_windows[w];
if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
if (win->z_index > topmost_z) {
target = win;
topmost_z = win->z_index;
}
}
}
}
if (topmost && topmost->data) {
if (my >= topmost->y + 20)
syscall_send_mouse_up_event(topmost, mx - topmost->x, my - topmost->y - 20);
if (target && target->data) {
int rel_y = my - target->y - 20;
// Provide coordinates clamped if escaping bounds slightly on UP? Usually raw is fine.
syscall_send_mouse_up_event(target, mx - target->x, rel_y);
}
active_mouse_capture_win = NULL;
}
if (dx != 0 || dy != 0) {
// Mouse moved - send MOUSE_MOVE event to topmost window
Window *topmost = NULL;
int topmost_z = -1;
for (int w = 0; w < window_count; w++) {
Window *win = all_windows[w];
if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
if (win->z_index > topmost_z) {
topmost = win;
topmost_z = win->z_index;
// Mouse moved - send MOUSE_MOVE event to captured window (if dragging) or topmost
Window *target = active_mouse_capture_win;
if (!target) {
int topmost_z = -1;
for (int w = 0; w < window_count; w++) {
Window *win = all_windows[w];
if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
if (win->z_index > topmost_z) {
target = win;
topmost_z = win->z_index;
}
}
}
}
if (topmost && topmost->data) {
if (my >= topmost->y + 20)
syscall_send_mouse_move_event(topmost, mx - topmost->x, my - topmost->y - 20, buttons);
if (target && target->data) {
int rel_y = my - target->y - 20;
syscall_send_mouse_move_event(target, mx - target->x, rel_y, buttons);
}
}

View file

@ -99,6 +99,7 @@ void draw_traffic_light(int x, int y);
void draw_icon(int x, int y, const char *label);
void draw_folder_icon(int x, int y, const char *label);
void draw_document_icon(int x, int y, const char *label);
void draw_pdf_icon(int x, int y, const char *label);
void draw_elf_icon(int x, int y, const char *label);
void draw_image_icon(int x, int y, const char *label);
void draw_notepad_icon(int x, int y, const char *label);