9 Commits

Author SHA1 Message Date
boreddevnl
7b7f134e27 feat: centralize OS version info in kernel syscall 2026-03-17 16:06:00 +01:00
boreddevnl
0491c4ad0f TWEAK: change version number for V1.72 and 3.1.2 2026-03-17 15:50:25 +01:00
boreddevnl
c6fe9971d8 BFIX: export bugs in word.c and fixed explorer always ZTop in wm 2026-03-17 15:48:42 +01:00
boreddevnl
88f178e368 checkpoint: BoredWord application 2026-03-17 14:41:13 +01:00
boreddevnl
d824b4610a FIX: Replace blocking k_beep with an asynchronous k_beep 2026-03-16 17:22:42 +01:00
boreddevnl
a4f16b0604 RM: remove broken file artifact 2026-03-16 17:19:06 +01:00
boreddevnl
83413fdd2b fix: Broken script in documentation 2026-03-16 17:16:20 +01:00
boreddevnl
2a918bc7ba Tweak: Updatedscreenshot.jpg and fixed boredos.svg alignment 2026-03-16 15:59:37 +01:00
boreddevnl
2624b4f8df update LICENSE 2026-03-16 15:21:17 +01:00
26 changed files with 2644 additions and 103 deletions

View File

@@ -3,7 +3,7 @@
Copyright(C) Chris (boreddevnl) 2024-2026 Copyright(C) Chris (boreddevnl) 2024-2026
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/\> Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.

View File

@@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 130" width="100%"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 415 130" width="100%">
<style> <style>
text { text {
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
disk.img

Binary file not shown.

View File

@@ -13,30 +13,31 @@ Applications reside entirely in the `src/userland/` directory. Create a new file
// src/userland/gui/hello.c // src/userland/gui/hello.c
#include <stdlib.h> #include <stdlib.h>
#include <libui.h> #include <libui.h>
#include <syscall.h>
int main(void) { int main(void) {
// Attempt to open a 300x200 window // Attempt to open a 300x200 window
int wid = ui_create_window("My Custom App", 300, 200, 0); ui_window_t wid = ui_window_create("My Custom App", 100, 100, 300, 200);
if (wid < 0) { if (wid < 0) {
printf("Error creating window!\n"); printf("Error creating window!\n");
return 1; return 1;
} }
// Write text in center // Write text in center
ui_draw_string(wid, "Hello, BoredOS!!", 50, 90, 0xFFFFFFFF); ui_draw_string(wid, 50, 90, "Hello, BoredOS!!", 0xFFFFFFFF);
// Commit drawing to screen // Commit drawing to screen
ui_swap_buffers(wid); ui_mark_dirty(wid, 0, 0, 300, 200);
ui_event_t event; gui_event_t event;
while (1) { while (1) {
if (ui_poll_event(&event)) { if (ui_get_event(wid, &event)) {
if (event.window_id == wid && event.type == UI_EVENT_WINDOW_CLOSE) { if (event.type == GUI_EVENT_CLOSE) {
break; // Exit loop if 'X' is clicked break; // Exit loop if 'X' is clicked
} }
} }
syscall1(SYSTEM_CMD_YIELD, 0); sys_yield();
} }
return 0; // Returning 0 smoothly exits the process via crt0.asm return 0; // Returning 0 smoothly exits the process via crt0.asm

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 KiB

After

Width:  |  Height:  |  Size: 342 KiB

View File

@@ -113,14 +113,35 @@ void k_shutdown(void) {
outw(0x4004, 0x3400); // VirtualBox fallback outw(0x4004, 0x3400); // VirtualBox fallback
} }
volatile uint64_t beep_end_tick = 0;
bool beep_active = false;
void k_beep(int freq, int ms) { void k_beep(int freq, int ms) {
if (freq <= 0) return; if (freq <= 0) {
outb(0x61, inb(0x61) & 0xFC);
beep_active = false;
return;
}
int div = 1193180 / freq; int div = 1193180 / freq;
outb(0x43, 0xB6); outb(0x43, 0xB6);
outb(0x42, div & 0xFF); outb(0x42, div & 0xFF);
outb(0x42, (div >> 8) & 0xFF); outb(0x42, (div >> 8) & 0xFF);
outb(0x61, inb(0x61) | 0x03); outb(0x61, inb(0x61) | 0x03);
k_sleep(ms);
outb(0x61, inb(0x61) & 0xFC); uint32_t ticks = ms / 16;
if (ticks == 0 && ms > 0) ticks = 1;
extern volatile uint64_t kernel_ticks;
beep_end_tick = kernel_ticks + ticks;
beep_active = true;
}
void k_beep_process(void) {
if (beep_active) {
extern volatile uint64_t kernel_ticks;
if (kernel_ticks >= beep_end_tick) {
outb(0x61, inb(0x61) & 0xFC);
beep_active = false;
}
}
} }

View File

@@ -6,6 +6,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
// Kernel string utilities // Kernel string utilities
void k_memset(void *dest, int val, size_t len); void k_memset(void *dest, int val, size_t len);
@@ -23,5 +24,6 @@ void k_sleep(int ms);
void k_reboot(void); void k_reboot(void);
void k_shutdown(void); void k_shutdown(void);
void k_beep(int freq, int ms); void k_beep(int freq, int ms);
void k_beep_process(void);
#endif #endif

33
src/core/version.c Normal file
View File

@@ -0,0 +1,33 @@
// Copyright (c) 2023-2026 Chris (boreddevnl)
// This software is released under the GNU General Public License v3.0. See LICENSE file for details.
// This header needs to maintain in any file it is present in, as per the GPL license terms.
#include "syscall.h"
#include <stddef.h>
extern void mem_memcpy(void *dest, const void *src, size_t len);
void get_os_info(os_info_t *info) {
if (!info) return;
char *p = (char *)info;
for (size_t i = 0; i < sizeof(os_info_t); i++) p[i] = 0;
const char *os_name = "BoredOS";
const char *os_version = "1.72";
const char *os_codename = "Retrowave";
const char *kernel_name = "Boredkernel";
const char *kernel_version = "3.1.2";
const char *build_date = __DATE__;
const char *build_time = __TIME__;
const char *build_arch = "x86_64";
int j;
j = 0; while (os_name[j] && j < 63) { info->os_name[j] = os_name[j]; j++; } info->os_name[j] = '\0';
j = 0; while (os_version[j] && j < 63) { info->os_version[j] = os_version[j]; j++; } info->os_version[j] = '\0';
j = 0; while (os_codename[j] && j < 63) { info->os_codename[j] = os_codename[j]; j++; } info->os_codename[j] = '\0';
j = 0; while (kernel_name[j] && j < 63) { info->kernel_name[j] = kernel_name[j]; j++; } info->kernel_name[j] = '\0';
j = 0; while (kernel_version[j] && j < 63) { info->kernel_version[j] = kernel_version[j]; j++; } info->kernel_version[j] = '\0';
j = 0; while (build_date[j] && j < 63) { info->build_date[j] = build_date[j]; j++; } info->build_date[j] = '\0';
j = 0; while (build_time[j] && j < 63) { info->build_time[j] = build_time[j]; j++; } info->build_time[j] = '\0';
j = 0; while (build_arch[j] && j < 63) { info->build_arch[j] = build_arch[j]; j++; } info->build_arch[j] = '\0';
}

View File

@@ -18,6 +18,9 @@ uint64_t timer_handler(registers_t *regs) {
wm_timer_tick(); wm_timer_tick();
network_process_frames(); network_process_frames();
extern void k_beep_process(void);
k_beep_process();
outb(0x20, 0x20); // EOI after processing to prevent nested timer interrupts outb(0x20, 0x20); // EOI after processing to prevent nested timer interrupts
extern uint64_t process_schedule(uint64_t current_rsp); extern uint64_t process_schedule(uint64_t current_rsp);
return process_schedule((uint64_t)regs); return process_schedule((uint64_t)regs);

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)); asm volatile("push %0; popfq" : : "r"(rflags));
} }
} else if (cmd == GUI_CMD_DRAW_IMAGE) { } else if (cmd == GUI_CMD_DRAW_IMAGE) {
@@ -929,16 +1006,8 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
} else if (cmd == 14) { // SYSTEM_CMD_BEEP } else if (cmd == 14) { // SYSTEM_CMD_BEEP
int freq = (int)arg2; int freq = (int)arg2;
int ms = (int)arg3; int ms = (int)arg3;
if (freq > 0) { extern void k_beep(int freq, int ms);
int div = 1193180 / freq; k_beep(freq, ms);
outb(0x43, 0xB6);
outb(0x42, div & 0xFF);
outb(0x42, (div >> 8) & 0xFF);
outb(0x61, inb(0x61) | 0x03);
}
// Sleep - kernel side
k_sleep(ms);
outb(0x61, inb(0x61) & 0xFC);
return 0; return 0;
} else if (cmd == 15) { // SYSTEM_CMD_MEMINFO } else if (cmd == 15) { // SYSTEM_CMD_MEMINFO
uint64_t *out = (uint64_t *)arg2; uint64_t *out = (uint64_t *)arg2;
@@ -1189,6 +1258,12 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
return 0; return 0;
} }
return -1; return -1;
} else if (cmd == 49) { // SYSTEM_CMD_GET_OS_INFO
os_info_t *info = (os_info_t *)arg2;
if (!info) return -1;
extern void get_os_info(os_info_t *info);
get_os_info(info);
return 0;
} }
return -1; return -1;
} }

View File

@@ -10,6 +10,17 @@
typedef struct Window Window; typedef struct Window Window;
typedef struct registers_t registers_t; typedef struct registers_t registers_t;
typedef struct {
char os_name[64];
char os_version[64];
char os_codename[64];
char kernel_name[64];
char kernel_version[64];
char build_date[64];
char build_time[64];
char build_arch[64];
} os_info_t;
// MSRs used for syscalls in x86_64 // MSRs used for syscalls in x86_64
#define MSR_EFER 0xC0000080 #define MSR_EFER 0xC0000080
#define MSR_STAR 0xC0000081 #define MSR_STAR 0xC0000081
@@ -46,6 +57,7 @@ typedef struct registers_t registers_t;
#define SYSTEM_CMD_GET_CPU_MODEL 45 #define SYSTEM_CMD_GET_CPU_MODEL 45
#define SYSTEM_CMD_SLEEP 46 #define SYSTEM_CMD_SLEEP 46
#define SYSTEM_CMD_SET_RESOLUTION 47 #define SYSTEM_CMD_SET_RESOLUTION 47
#define SYSTEM_CMD_GET_OS_INFO 49
void syscall_init(void); void syscall_init(void);
uint64_t syscall_handler_c(registers_t *regs); uint64_t syscall_handler_c(registers_t *regs);

View File

@@ -237,13 +237,29 @@ int main(int argc, char **argv) {
if (config.separator[0]) { if (config.separator[0]) {
strcpy(info_lines[info_line_count++], config.separator); strcpy(info_lines[info_line_count++], config.separator);
} }
os_info_t os_info;
sys_get_os_info(&os_info);
if (config.os_label[0]) { if (config.os_label[0]) {
strcpy(info_lines[info_line_count], config.os_label); strcpy(info_lines[info_line_count], config.os_label);
strcat(info_lines[info_line_count++], ": BoredOS V1.71 'Retrowave'"); strcat(info_lines[info_line_count], ": ");
strcat(info_lines[info_line_count], os_info.os_name);
strcat(info_lines[info_line_count], " V");
strcat(info_lines[info_line_count], os_info.os_version);
strcat(info_lines[info_line_count], " '");
strcat(info_lines[info_line_count], os_info.os_codename);
strcat(info_lines[info_line_count], "'");
info_line_count++;
} }
if (config.kernel_label[0]) { if (config.kernel_label[0]) {
strcpy(info_lines[info_line_count], config.kernel_label); strcpy(info_lines[info_line_count], config.kernel_label);
strcat(info_lines[info_line_count++], ": Boredkernel V3.1.1 x86_64"); strcat(info_lines[info_line_count], ": ");
strcat(info_lines[info_line_count], os_info.kernel_name);
strcat(info_lines[info_line_count], " V");
strcat(info_lines[info_line_count], os_info.kernel_version);
strcat(info_lines[info_line_count], " ");
strcat(info_lines[info_line_count], os_info.build_arch);
info_line_count++;
} }
if (config.uptime_label[0]) { if (config.uptime_label[0]) {
uint64_t ticks = sys_system(16, 0, 0, 0, 0); uint64_t ticks = sys_system(16, 0, 0, 0, 0);

View File

@@ -84,10 +84,9 @@ static void draw_ascii_logo(ui_window_t win, int x, int y) {
} }
static void about_paint(ui_window_t win) { static void about_paint(ui_window_t win) {
int w = 340; int w = 380;
int h = 240; int h = 260;
// Clear background to prevent alpha-blended text from accumulating on repaints
ui_draw_rect(win, 0, 0, w, h, 0xFF1E1E1E); ui_draw_rect(win, 0, 0, w, h, 0xFF1E1E1E);
int offset_x = 15; int offset_x = 15;
@@ -96,19 +95,51 @@ static void about_paint(ui_window_t win) {
draw_ascii_logo(win, 14, offset_y); draw_ascii_logo(win, 14, offset_y);
int fh = ui_get_font_height(); int fh = ui_get_font_height();
ui_draw_string(win, offset_x, offset_y + 105, "BoredOS 'Retrowave'", 0xFFFFFFFF); os_info_t os_info;
ui_draw_string(win, offset_x, offset_y + 105 + fh, "BoredOS Version 1.71", 0xFFFFFFFF); sys_get_os_info(&os_info);
ui_draw_string(win, offset_x, offset_y + 105 + fh*2, "Kernel Version 3.1.1", 0xFFFFFFFF);
char os_name_str[128];
os_name_str[0] = 0;
strcat(os_name_str, os_info.os_name);
strcat(os_name_str, " '");
strcat(os_name_str, os_info.os_codename);
strcat(os_name_str, "'");
char os_version_str[128];
os_version_str[0] = 0;
strcat(os_version_str, os_info.os_name);
strcat(os_version_str, " Version ");
strcat(os_version_str, os_info.os_version);
char kernel_version_str[128];
kernel_version_str[0] = 0;
strcat(kernel_version_str, os_info.kernel_name);
strcat(kernel_version_str, " Version ");
strcat(kernel_version_str, os_info.kernel_version);
strcat(kernel_version_str, " ");
strcat(kernel_version_str, os_info.build_arch);
char build_date_str[128];
build_date_str[0] = 0;
strcat(build_date_str, "Build Date: ");
strcat(build_date_str, os_info.build_date);
strcat(build_date_str, " ");
strcat(build_date_str, os_info.build_time);
ui_draw_string(win, offset_x, offset_y + 105, os_name_str, 0xFFFFFFFF);
ui_draw_string(win, offset_x, offset_y + 105 + fh, os_version_str, 0xFFFFFFFF);
ui_draw_string(win, offset_x, offset_y + 105 + fh*2, kernel_version_str, 0xFFFFFFFF);
ui_draw_string(win, offset_x, offset_y + 105 + fh*3, build_date_str, 0xFFFFFFFF);
// Copyright // Copyright
ui_draw_string(win, offset_x, offset_y + 105 + fh*3, "(C) 2026 boreddevnl.", 0xFFFFFFFF); ui_draw_string(win, offset_x, offset_y + 105 + fh*4, "(C) 2026 boreddevnl.", 0xFFFFFFFF);
ui_draw_string(win, offset_x, offset_y + 105 + fh*4, "All rights reserved.", 0xFFFFFFFF); ui_draw_string(win, offset_x, offset_y + 105 + fh*5, "All rights reserved.", 0xFFFFFFFF);
ui_mark_dirty(win, 0, 0, w, h); ui_mark_dirty(win, 0, 0, w, h);
} }
int main(void) { int main(void) {
ui_window_t win_about = ui_window_create("About BoredOS", 250, 180, 340, 240); ui_window_t win_about = ui_window_create("About BoredOS", 250, 180, 380, 260);
about_paint(win_about); about_paint(win_about);
@@ -121,7 +152,6 @@ int main(void) {
sys_exit(0); sys_exit(0);
} }
} else { } else {
// Avoid high CPU usage
sleep(10); sleep(10);
} }
} }

1986
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 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 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 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 // sys_gui uses syscall #3
#define SYS_GUI 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); 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 ui_get_string_width_scaled(const char *str, float scale) {
uint32_t scale_bits = *(uint32_t*)&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); 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_GET_FONT_HEIGHT_SCALED 13
#define GUI_CMD_WINDOW_SET_TITLE 15 #define GUI_CMD_WINDOW_SET_TITLE 15
#define GUI_CMD_SET_FONT 16 #define GUI_CMD_SET_FONT 16
#define GUI_CMD_DRAW_STRING_SCALED_SLOPED 18
// Event Types // Event Types
#define GUI_EVENT_NONE 0 #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_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(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_string_width_scaled(const char *str, float scale);
uint32_t ui_get_font_height_scaled(float scale); uint32_t ui_get_font_height_scaled(float scale);
void ui_window_set_title(ui_window_t win, const char *title); 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; 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) { void sys_exit(int status) {
syscall1(SYS_EXIT, (uint64_t)status); syscall1(SYS_EXIT, (uint64_t)status);
@@ -239,3 +251,7 @@ void sys_yield(void) {
syscall1(SYS_SYSTEM, SYSTEM_CMD_YIELD); syscall1(SYS_SYSTEM, SYSTEM_CMD_YIELD);
} }
int sys_get_os_info(os_info_t *info) {
return (int)syscall5(SYS_SYSTEM, SYSTEM_CMD_GET_OS_INFO, (uint64_t)info, 0, 0, 0);
}

View File

@@ -75,6 +75,7 @@
#define SYSTEM_CMD_SET_RAW_MODE 41 #define SYSTEM_CMD_SET_RAW_MODE 41
#define SYSTEM_CMD_TCP_RECV_NB 42 #define SYSTEM_CMD_TCP_RECV_NB 42
#define SYSTEM_CMD_YIELD 43 #define SYSTEM_CMD_YIELD 43
#define SYSTEM_CMD_GET_OS_INFO 49
// Internal assembly entry into Ring 0 // Internal assembly entry into Ring 0
extern uint64_t syscall0(uint64_t sys_num); extern uint64_t syscall0(uint64_t sys_num);
@@ -91,6 +92,19 @@ void *sys_sbrk(int incr);
void sys_kill(int pid); void sys_kill(int pid);
int sys_system(int cmd, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4); int sys_system(int cmd, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4);
typedef struct {
char os_name[64];
char os_version[64];
char os_codename[64];
char kernel_name[64];
char kernel_version[64];
char build_date[64];
char build_time[64];
char build_arch[64];
} os_info_t;
int sys_get_os_info(os_info_t *info);
// FS API // FS API
int sys_open(const char *path, const char *mode); int sys_open(const char *path, const char *mode);
int sys_read(int fd, void *buf, uint32_t len); int sys_read(int fd, void *buf, uint32_t len);

View File

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

View File

@@ -17,12 +17,10 @@ float kfabsf(float x) {
} }
float kpowf(float b, float e) { float kpowf(float b, float e) {
// Very simplified pow for stb_truetype's needs
if (e == 0) return 1.0f; if (e == 0) return 1.0f;
if (e == 1) return b; if (e == 1) return b;
if (e == 0.5f) return ksqrtf(b); if (e == 0.5f) return ksqrtf(b);
// Fallback/log-based would be complex, let's see if this suffices
float res = 1.0f; float res = 1.0f;
for (int i = 0; i < (int)e; i++) res *= b; for (int i = 0; i < (int)e; i++) res *= b;
return res; return res;
@@ -33,13 +31,11 @@ float kfmodf(float x, float y) {
} }
float kcosf(float x) { float kcosf(float x) {
// Taylor series for cos(x) around 0
float x2 = x * x; float x2 = x * x;
return 1.0f - (x2 / 2.0f) + (x2 * x2 / 24.0f) - (x2 * x2 * x2 / 720.0f); return 1.0f - (x2 / 2.0f) + (x2 * x2 / 24.0f) - (x2 * x2 * x2 / 720.0f);
} }
float kacosf(float x) { float kacosf(float x) {
// Very rough approximation for acos(x)
if (x >= 1.0f) return 0; if (x >= 1.0f) return 0;
if (x <= -1.0f) return 3.14159f; if (x <= -1.0f) return 3.14159f;
return 1.57079f - x - (x*x*x)/6.0f; 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; 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 #define FONT_CACHE_SIZE 2048
typedef struct { typedef struct {
char c; char c;
@@ -67,15 +72,22 @@ typedef struct {
unsigned char *bitmap; unsigned char *bitmap;
} font_cache_entry_t; } 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) { bool font_manager_init(void) {
// We'll load a default font later if available
return true; return true;
} }
ttf_font_t* font_manager_load(const char *path, float size) { 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"); FAT32_FileHandle *fh = fat32_open(path, "r");
if (!fh || !fh->valid) { if (!fh || !fh->valid) {
serial_write("[FONT] Failed to open font file: "); serial_write("[FONT] Failed to open font file: ");
@@ -127,6 +139,13 @@ ttf_font_t* font_manager_load(const char *path, float size) {
if (!default_font) default_font = font; 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; 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; unsigned char *bitmap = NULL;
int w, h, xoff, yoff; 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; int codepoint = (unsigned char)c;
if (codepoint == 128) codepoint = 0x2014; // &mdash; (—) if (codepoint == 128) codepoint = 0x2014;
if (codepoint == 129) codepoint = 0x2013; // &ndash; () if (codepoint == 129) codepoint = 0x2013;
if (codepoint == 130) codepoint = 0x2022; // &bull; (•) if (codepoint == 130) codepoint = 0x2022;
if (codepoint == 131) codepoint = 0x2026; // &hellip; (…) if (codepoint == 131) codepoint = 0x2026;
if (codepoint == 132) codepoint = 0x2122; // &trade; (™) if (codepoint == 132) codepoint = 0x2122;
if (codepoint == 133) codepoint = 0x20AC; // &euro; (€) if (codepoint == 133) codepoint = 0x20AC;
if (codepoint == 134) codepoint = 0x00B7; // &middot; (·) if (codepoint == 134) codepoint = 0x00B7;
bitmap = stbtt_GetCodepointBitmap(info, 0, real_scale, codepoint, &w, &h, &xoff, &yoff); 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) { int font_manager_get_string_width(ttf_font_t *font, const char *s) {
if (!font) font = default_font; if (!font) font = default_font;
if (!font) return 0; 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) { while (*s) {
int advance, lsb; int advance, lsb;
int codepoint = (unsigned char)*s; int codepoint = (unsigned char)*s;
if (codepoint == 128) codepoint = 0x2014; // &mdash; (—) if (codepoint == 128) codepoint = 0x2014;
if (codepoint == 129) codepoint = 0x2013; // &ndash; () if (codepoint == 129) codepoint = 0x2013;
if (codepoint == 130) codepoint = 0x2022; // &bull; (•) if (codepoint == 130) codepoint = 0x2022;
if (codepoint == 131) codepoint = 0x2026; // &hellip; (…) if (codepoint == 131) codepoint = 0x2026;
if (codepoint == 132) codepoint = 0x2122; // &trade; (™) if (codepoint == 132) codepoint = 0x2122;
if (codepoint == 133) codepoint = 0x20AC; // &euro; (€) if (codepoint == 133) codepoint = 0x20AC;
if (codepoint == 134) codepoint = 0x00B7; // &middot; (·) if (codepoint == 134) codepoint = 0x00B7;
stbtt_GetCodepointHMetrics(info, codepoint, &advance, &lsb); stbtt_GetCodepointHMetrics(info, codepoint, &advance, &lsb);
// Round per-character to match draw_string's accumulation
width += (int)(advance * real_scale + 0.5f); width += (int)(advance * real_scale + 0.5f);
s++; s++;
} }

View File

@@ -5,7 +5,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
// stb_truetype math stubs
extern float ksqrtf(float x); extern float ksqrtf(float x);
extern float kpowf(float b, float e); extern float kpowf(float b, float e);
extern float kfmodf(float x, float y); extern float kfmodf(float x, float y);
@@ -24,21 +23,18 @@ extern float kfabsf(float x);
#define STBTT_assert(x) ((void)0) #define STBTT_assert(x) ((void)0)
// Memory management
#define STBTT_malloc(x,u) kmalloc(x) #define STBTT_malloc(x,u) kmalloc(x)
#define STBTT_free(x,u) kfree(x) #define STBTT_free(x,u) kfree(x)
// String functions
#define STBTT_memcpy mem_memcpy #define STBTT_memcpy mem_memcpy
#define STBTT_memset mem_memset #define STBTT_memset mem_memset
// Data types
typedef uint64_t STBTT_ptrsize; typedef uint64_t STBTT_ptrsize;
typedef struct { typedef struct {
void *data; void *data;
size_t size; size_t size;
void *info; // stbtt_fontinfo void *info;
float scale; float scale;
float pixel_height; float pixel_height;
int ascent; int ascent;
@@ -50,6 +46,7 @@ bool font_manager_init(void);
ttf_font_t* font_manager_load(const char *path, float size); 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(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_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(ttf_font_t *font, const char *s);
int font_manager_get_string_width_scaled(ttf_font_t *font, const char *s, float scale); 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 "font.h"
#include "io.h" #include "io.h"
#include "font_manager.h" #include "font_manager.h"
#include "../mem/memory_manager.h"
static struct limine_framebuffer *g_fb = NULL; static struct limine_framebuffer *g_fb = NULL;
static uint32_t g_bg_color = 0xFF696969; 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) { void draw_char(int x, int y, char c, uint32_t color) {
if (g_current_ttf) { if (g_current_ttf) {
font_manager_render_char(g_current_ttf, x, y, c, color, put_pixel); 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) { void draw_desktop_background(void) {
if (!g_fb) return; 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_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(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_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(int x, int y, char c, uint32_t color);
void draw_char_bitmap(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(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_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 draw_desktop_background(void);
void graphics_set_bg_color(uint32_t color); void graphics_set_bg_color(uint32_t color);
void graphics_set_bg_pattern(const uint32_t *pattern); // 128x128 pattern 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; int mouse_speed = 10;
static int mouse_accum_x = 0; static int mouse_accum_x = 0;
static int mouse_accum_y = 0; static int mouse_accum_y = 0;
Window *active_mouse_capture_win = NULL;
// Helper to check if string ends with suffix // Helper to check if string ends with suffix
static bool str_ends_with(const char *str, const char *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); 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) { void draw_elf_icon(int x, int y, const char *label) {
uint32_t icon_buf[48 * 48]; uint32_t icon_buf[48 * 48];
for (int i = 0; i < 48 * 48; i++) icon_buf[i] = 0xFFFF00FF; 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; 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) { static void draw_dock_notepad(int x, int y) {
draw_rounded_rect_filled(x, y, 48, 48, 10, 0xFFCC9A00); draw_rounded_rect_filled(x, y, 48, 48, 10, 0xFFCC9A00);
draw_rounded_rect_filled(x + 1, y + 1, 46, 28, 9, 0xFFFFD700); 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)); asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
DirtyRect dirty = graphics_get_dirty_rect(); DirtyRect dirty = graphics_get_dirty_rect();
if (dirty.active) { 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); graphics_set_clipping(dirty.x, dirty.y, dirty.w, dirty.h);
} else { } else {
graphics_clear_clipping(); graphics_clear_clipping();
@@ -1274,6 +1333,7 @@ void wm_paint(void) {
draw_image_icon(icon->x, icon->y, full_path); draw_image_icon(icon->x, icon->y, full_path);
draw_icon_label(icon->x, icon->y, icon->name); 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); 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_y = sh - dock_h - 6;
int dock_item_size = 48; int dock_item_size = 48;
int dock_spacing = 10; 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_x = (sw - total_dock_width) / 2 - 12;
int dock_bg_w = total_dock_width + 24; 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_x = (sw - total_dock_width) / 2;
int dock_item_y = dock_y + 6; int dock_item_y = dock_y + 6;
@@ -1351,7 +1413,8 @@ void wm_paint(void) {
draw_dock_taskman(dock_x, dock_item_y); draw_dock_taskman(dock_x, dock_item_y);
dock_x += dock_item_size + dock_spacing; dock_x += dock_item_size + dock_spacing;
draw_dock_clock(dock_x, dock_item_y); 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) // Desktop Context Menu (with rounded corners)
if (desktop_menu_visible) { if (desktop_menu_visible) {
@@ -1533,6 +1596,10 @@ void wm_remove_window(Window *win) {
} }
window_count--; window_count--;
if (active_mouse_capture_win == win) {
active_mouse_capture_win = NULL;
}
// Mark for redraw while protected // Mark for redraw while protected
force_redraw = true; force_redraw = true;
} else { } else {
@@ -1905,7 +1972,7 @@ void wm_handle_right_click(int x, int y) {
int dock_y = sh - dock_h - 6; int dock_y = sh - dock_h - 6;
int dock_item_size = 48; int dock_item_size = 48;
int dock_spacing = 10; 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_x = (sw - total_dock_width) / 2 - 12;
int dock_bg_w = total_dock_width + 24; 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 == 7) start_menu_pending_app = "Browser";
else if (item == 8) start_menu_pending_app = "Task Manager"; else if (item == 8) start_menu_pending_app = "Task Manager";
else if (item == 9) start_menu_pending_app = "Clock"; else if (item == 9) start_menu_pending_app = "Clock";
else if (item == 10) start_menu_pending_app = "Word Processor";
} }
} else { } else {
wm_handle_click(mx, my); wm_handle_click(mx, my);
@@ -2002,6 +2070,19 @@ void wm_handle_right_click(int x, int y) {
} }
// 2. Check Explorer Items // 2. Check Explorer Items
if (!is_dragging_file) { if (!is_dragging_file) {
Window *topmost_at_drag = NULL;
int tops_z = -1;
for (int w = 0; w < window_count; w++) {
Window *w_ptr = all_windows[w];
if (w_ptr->visible && rect_contains(w_ptr->x, w_ptr->y, w_ptr->w, w_ptr->h, drag_start_x, drag_start_y)) {
if (w_ptr->z_index > tops_z) {
topmost_at_drag = w_ptr;
tops_z = w_ptr->z_index;
}
}
}
if (!topmost_at_drag || str_starts_with(topmost_at_drag->title, "Files")) {
bool is_dir; bool is_dir;
if (explorer_get_file_at(drag_start_x, drag_start_y, drag_file_path, &is_dir)) { if (explorer_get_file_at(drag_start_x, drag_start_y, drag_file_path, &is_dir)) {
is_dragging_file = true; is_dragging_file = true;
@@ -2020,6 +2101,7 @@ void wm_handle_right_click(int x, int y) {
} }
} }
} }
}
if (is_dragging_file) force_redraw = true; if (is_dragging_file) force_redraw = true;
} }
@@ -2048,6 +2130,10 @@ void wm_handle_right_click(int x, int y) {
Window *existing = wm_find_window_by_title("Txtedit"); Window *existing = wm_find_window_by_title("Txtedit");
if (existing) wm_bring_to_front(existing); if (existing) wm_bring_to_front(existing);
else process_create_elf("/bin/txtedit.elf", NULL); 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")) { } else if (str_starts_with(start_menu_pending_app, "Terminal")) {
cmd_reset(); wm_bring_to_front(&win_cmd); cmd_reset(); wm_bring_to_front(&win_cmd);
} else if (str_starts_with(start_menu_pending_app, "Calculator")) { } else if (str_starts_with(start_menu_pending_app, "Calculator")) {
@@ -2160,6 +2246,8 @@ void wm_handle_right_click(int x, int y) {
process_create_elf("/bin/paint.elf", path); process_create_elf("/bin/paint.elf", path);
} else if (str_ends_with(icon->name, ".md")) { } else if (str_ends_with(icon->name, ".md")) {
process_create_elf("/bin/markdown.elf", path); 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)) { } else if (is_image_file(icon->name)) {
process_create_elf("/bin/viewer.elf", path); process_create_elf("/bin/viewer.elf", path);
} else { } else {
@@ -2361,6 +2449,9 @@ void wm_handle_right_click(int x, int y) {
} }
} }
} }
}
if (is_dragging_file) {
is_dragging_file = false; is_dragging_file = false;
force_redraw = true; force_redraw = true;
} }
@@ -2385,46 +2476,57 @@ void wm_handle_right_click(int x, int y) {
} }
} }
if (topmost && topmost->data) { if (topmost && topmost->data) {
active_mouse_capture_win = topmost;
if (my >= topmost->y + 20) if (my >= topmost->y + 20)
syscall_send_mouse_down_event(topmost, mx - topmost->x, 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) { if (!left && prev_left) {
// Left button released - send MOUSE_UP event to topmost window // Left button released - send MOUSE_UP event to captured or topmost window
Window *topmost = NULL; Window *target = active_mouse_capture_win;
if (!target) {
int topmost_z = -1; int topmost_z = -1;
for (int w = 0; w < window_count; w++) { for (int w = 0; w < window_count; w++) {
Window *win = all_windows[w]; Window *win = all_windows[w];
if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) { if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
if (win->z_index > topmost_z) { if (win->z_index > topmost_z) {
topmost = win; target = win;
topmost_z = win->z_index; 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) { if (dx != 0 || dy != 0) {
// Mouse moved - send MOUSE_MOVE event to topmost window // Mouse moved - send MOUSE_MOVE event to captured window (if dragging) or topmost
Window *topmost = NULL; Window *target = active_mouse_capture_win;
if (!target) {
int topmost_z = -1; int topmost_z = -1;
for (int w = 0; w < window_count; w++) { for (int w = 0; w < window_count; w++) {
Window *win = all_windows[w]; Window *win = all_windows[w];
if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) { if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
if (win->z_index > topmost_z) { if (win->z_index > topmost_z) {
topmost = win; target = win;
topmost_z = win->z_index; 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_icon(int x, int y, const char *label);
void draw_folder_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_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_elf_icon(int x, int y, const char *label);
void draw_image_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); void draw_notepad_icon(int x, int y, const char *label);

View File