mirror of
https://github.com/JannisHeydemann/BoredOS.git
synced 2026-05-30 02:16:58 +00:00
Compare commits
9 Commits
full_1.71
...
Full_V1.72
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b7f134e27 | ||
|
|
0491c4ad0f | ||
|
|
c6fe9971d8 | ||
|
|
88f178e368 | ||
|
|
d824b4610a | ||
|
|
a4f16b0604 | ||
|
|
83413fdd2b | ||
|
|
2a918bc7ba | ||
|
|
2624b4f8df |
2
LICENSE
2
LICENSE
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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 |
@@ -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
|
||||||
|
|||||||
BIN
screenshot.jpg
BIN
screenshot.jpg
Binary file not shown.
|
Before Width: | Height: | Size: 317 KiB After Width: | Height: | Size: 342 KiB |
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
33
src/core/version.c
Normal 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';
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
1986
src/userland/gui/word.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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: ");
|
||||||
@@ -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);
|
stbtt_GetFontVMetrics(info, &font->ascent, &font->descent, &font->line_gap);
|
||||||
|
|
||||||
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; // — (—)
|
if (codepoint == 128) codepoint = 0x2014;
|
||||||
if (codepoint == 129) codepoint = 0x2013; // – (–)
|
if (codepoint == 129) codepoint = 0x2013;
|
||||||
if (codepoint == 130) codepoint = 0x2022; // • (•)
|
if (codepoint == 130) codepoint = 0x2022;
|
||||||
if (codepoint == 131) codepoint = 0x2026; // … (…)
|
if (codepoint == 131) codepoint = 0x2026;
|
||||||
if (codepoint == 132) codepoint = 0x2122; // ™ (™)
|
if (codepoint == 132) codepoint = 0x2122;
|
||||||
if (codepoint == 133) codepoint = 0x20AC; // € (€)
|
if (codepoint == 133) codepoint = 0x20AC;
|
||||||
if (codepoint == 134) codepoint = 0x00B7; // · (·)
|
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; // — (—)
|
if (codepoint == 128) codepoint = 0x2014;
|
||||||
if (codepoint == 129) codepoint = 0x2013; // – (–)
|
if (codepoint == 129) codepoint = 0x2013;
|
||||||
if (codepoint == 130) codepoint = 0x2022; // • (•)
|
if (codepoint == 130) codepoint = 0x2022;
|
||||||
if (codepoint == 131) codepoint = 0x2026; // … (…)
|
if (codepoint == 131) codepoint = 0x2026;
|
||||||
if (codepoint == 132) codepoint = 0x2122; // ™ (™)
|
if (codepoint == 132) codepoint = 0x2122;
|
||||||
if (codepoint == 133) codepoint = 0x20AC; // € (€)
|
if (codepoint == 133) codepoint = 0x20AC;
|
||||||
if (codepoint == 134) codepoint = 0x00B7; // · (·)
|
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++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
184
src/wm/wm.c
184
src/wm/wm.c
@@ -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,19 +2070,33 @@ 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) {
|
||||||
bool is_dir;
|
Window *topmost_at_drag = NULL;
|
||||||
if (explorer_get_file_at(drag_start_x, drag_start_y, drag_file_path, &is_dir)) {
|
int tops_z = -1;
|
||||||
is_dragging_file = true;
|
for (int w = 0; w < window_count; w++) {
|
||||||
drag_icon_type = is_dir ? 1 : 0;
|
Window *w_ptr = all_windows[w];
|
||||||
drag_src_win = NULL;
|
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) {
|
||||||
// Find which explorer window was clicked to clear its state
|
topmost_at_drag = w_ptr;
|
||||||
for (int w = 0; w < window_count; w++) {
|
tops_z = w_ptr->z_index;
|
||||||
Window *win = all_windows[w];
|
}
|
||||||
if (win->visible && rect_contains(win->x, win->y, win->w, win->h, drag_start_x, drag_start_y)) {
|
}
|
||||||
if (str_starts_with(win->title, "Files")) {
|
}
|
||||||
drag_src_win = win;
|
|
||||||
explorer_clear_click_state(win);
|
if (!topmost_at_drag || str_starts_with(topmost_at_drag->title, "Files")) {
|
||||||
|
bool is_dir;
|
||||||
|
if (explorer_get_file_at(drag_start_x, drag_start_y, drag_file_path, &is_dir)) {
|
||||||
|
is_dragging_file = true;
|
||||||
|
drag_icon_type = is_dir ? 1 : 0;
|
||||||
|
drag_src_win = NULL;
|
||||||
|
|
||||||
|
// Find which explorer window was clicked to clear its state
|
||||||
|
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, drag_start_x, drag_start_y)) {
|
||||||
|
if (str_starts_with(win->title, "Files")) {
|
||||||
|
drag_src_win = win;
|
||||||
|
explorer_clear_click_state(win);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
int topmost_z = -1;
|
if (!target) {
|
||||||
for (int w = 0; w < window_count; w++) {
|
int topmost_z = -1;
|
||||||
Window *win = all_windows[w];
|
for (int w = 0; w < window_count; w++) {
|
||||||
if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
|
Window *win = all_windows[w];
|
||||||
if (win->z_index > topmost_z) {
|
if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
|
||||||
topmost = win;
|
if (win->z_index > topmost_z) {
|
||||||
topmost_z = win->z_index;
|
target = win;
|
||||||
|
topmost_z = win->z_index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (topmost && topmost->data) {
|
|
||||||
if (my >= topmost->y + 20)
|
if (target && target->data) {
|
||||||
syscall_send_mouse_up_event(topmost, mx - topmost->x, my - topmost->y - 20);
|
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;
|
||||||
int topmost_z = -1;
|
if (!target) {
|
||||||
for (int w = 0; w < window_count; w++) {
|
int topmost_z = -1;
|
||||||
Window *win = all_windows[w];
|
for (int w = 0; w < window_count; w++) {
|
||||||
if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
|
Window *win = all_windows[w];
|
||||||
if (win->z_index > topmost_z) {
|
if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
|
||||||
topmost = win;
|
if (win->z_index > topmost_z) {
|
||||||
topmost_z = win->z_index;
|
target = win;
|
||||||
|
topmost_z = win->z_index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (topmost && topmost->data) {
|
|
||||||
if (my >= topmost->y + 20)
|
if (target && target->data) {
|
||||||
syscall_send_mouse_move_event(topmost, mx - topmost->x, my - topmost->y - 20, buttons);
|
int rel_y = my - target->y - 20;
|
||||||
|
syscall_send_mouse_move_event(target, mx - target->x, rel_y, buttons);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user