feat(gui,kernel): 1080p HD desktop, polished chrome, ktime clock + live FPS

GUI polish / HD:
- Default display mode raised to 1920x1080 (video=1920x1080); make run/vnc use
  vgamem_mb=64 and -m 512M. The growable heap absorbs the larger backbuffer,
  shadow and wallpaper (observed: one 16 MB growth to a 48 MB heap).
- Wallpaper: three-stop vertical gradient, a soft concentric-frame edge vignette
  for depth, a finer faint grid, and a centred brand mark.
- Window chrome: brighter/saturated titlebar gradient when focused, an accent
  underline on the active window, and larger/softer drop shadows.
- Default session windows are placed and sized for the HD work area.
- Live FPS pill in the taskbar tray (green/amber/red by rate); tray widened so
  FPS + CPU trace + memory badge + clock no longer overlap.

Kernel:
- kernel/time/ktime.c + include/kernel/ktime.h (new): a unified monotonic
  high-resolution clock that prefers the HPET (nanosecond) and falls back to the
  100 Hz PIT tick. Wired ktime_init() into boot; drives the compositor's FPS
  sampling. New `ktime` LazyBox applet reports the source and uptime.

Verified live (screenshotted): boots to 1920x1080, KTIME reports
"source: HPET, nanosecond resolution", the polished desktop renders with the
active-window accent and vignette, and the tray shows a live FPS reading.
Clean build on x86_64/aarch64/armv8i; 0 panics / 0 OOM.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Fh5z6V7nGPbHvqVG5p4CXX
This commit is contained in:
subhobhai943andClaude Opus 4.8 committed 2026-08-25 22:40:35 +05:30
1 parent ef6714a004
commit 4ecf119377
7 files changed
+154 -26

No files matched your search

+3 -3
View File
@@ -126,7 +126,7 @@ CORE_SRCS = kernel/main.c kernel/task.c kernel/sync.c kernel/timer.c kernel/prin
kernel/syslog.c kernel/module.c kernel/kobject.c kernel/metrics.c kernel/namespace.c \
kernel/signal.c kernel/workqueue.c kernel/tsc.c kernel/vt_art.c \
kernel/sub/sub_runtime.c kernel/sub/sub_vm.c kernel/nt/ob.c kernel/nt/reg.c kernel/nt/io.c \
kernel/wait.c kernel/futex.c kernel/rcu.c kernel/ktest.c \
kernel/wait.c kernel/futex.c kernel/rcu.c kernel/ktest.c kernel/time/ktime.c \
kernel/elf.c kernel/exec.c \
lib/string.c lib/vsprintf.c lib/bitmap.c lib/rbtree.c lib/kfifo.c lib/hashtable.c lib/font8x8.c \
init/cmdline.c init/service.c init/bootlogo.c init/logo_data.c usr/initramfs.c block/block.c block/elevator.c \
@@ -451,14 +451,14 @@ $(IMAGE): $(BUILD_DIR)/boot/boot.bin $(BUILD_DIR)/boot/stage2.bin $(BUILD_DIR)/k
# -----------------------------------------------------------------------------
# -vga std gives the Bochs VBE adapter the kernel drives. vgamem_mb is raised
# because a 1280x720 32-bit framebuffer needs more than the 8 MB default.
QEMU_VGA = -device VGA,vgamem_mb=32
QEMU_VGA = -device VGA,vgamem_mb=64
# `make run` boots straight into the SUB-OS Graphical Desktop Environment. The
# guest window scales with zoom-to-fit; pass `nogui`/`text` on the kernel
# command line for the emergency TTY. Use `make run-headless` for serial only.
run qemu: $(TARGET)
ifeq ($(ARCH), x86_64)
qemu-system-x86_64 -drive format=raw,file=$(IMAGE) -m 256M \
qemu-system-x86_64 -drive format=raw,file=$(IMAGE) -m 512M \
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
-device e1000,netdev=net0 $(QEMU_VGA) -display gtk,zoom-to-fit=on -serial stdio
else ifneq ($(filter $(ARCH), aarch64 arm64),)
+65 -19
View File
@@ -24,6 +24,7 @@
#include <drivers/keyboard.h>
#include <drivers/rtc.h>
#include <drivers/cpufreq.h>
#include <kernel/ktime.h>
#include <mm/pmm.h>
#include <mm/kmalloc.h>
#include <arch/arch.h>
@@ -82,6 +83,9 @@ static bool g_clock_seconds = true;
static int g_selected_icon = -1;
static int g_hover_menu_item = -1;
static uint64_t g_frames = 0;
static uint32_t g_fps = 0; // frames per second, sampled from ktime
static uint64_t g_fps_last_ms = 0;
static uint64_t g_fps_last_frames = 0;
/*
* Cached wallpaper.
@@ -178,28 +182,50 @@ void gui_desktop_init(void) {
// Wallpaper and desktop icons
// ===========================================================================
/* Paint the wallpaper straight into the back buffer. */
/* Paint the wallpaper straight into the back buffer. A three-stop vertical
* gradient gives the sky depth, a soft edge vignette frames it, and an optional
* fine grid adds texture without banding. Painted once and cached. */
static void desktop_paint_background(int sw, int wh) {
gui_gfx_draw_gradient_v(0, 0, sw, wh, 0xFF0B132B, 0xFF1C2541);
// Three-stop vertical gradient: deep space blue -> indigo -> a touch lighter.
int mid = wh * 55 / 100;
gui_gfx_draw_gradient_v(0, 0, sw, mid, 0xFF070B18, 0xFF141C38);
gui_gfx_draw_gradient_v(0, mid, sw, wh - mid, 0xFF141C38, 0xFF1D2A52);
if (g_show_grid) {
// Blend rather than stamp a fixed colour: the gradient's lower half is
// lighter than any single grid tone, so a constant colour disappears
// there and only shows near the top of the screen.
for (int y = 0; y < wh; y += 40) {
gui_gfx_fill_rect_blend(0, y, sw, 1, GUI_COLOR_BLACK, 40);
// A finer, fainter grid than before reads as texture rather than lines.
for (int y = 0; y < wh; y += 48) {
gui_gfx_fill_rect_blend(0, y, sw, 1, 0xFF3B4E80, 22);
}
for (int x = 0; x < sw; x += 40) {
gui_gfx_fill_rect_blend(x, 0, 1, wh, GUI_COLOR_BLACK, 40);
for (int x = 0; x < sw; x += 48) {
gui_gfx_fill_rect_blend(x, 0, 1, wh, 0xFF3B4E80, 22);
}
}
// Branding, offset to the right so it clears the icon column.
int bx = sw / 2 + 40;
int by = wh / 2 - 30;
gui_gfx_draw_string_16_shadow(bx - 60, by, "SUB-OS DESKTOP", 0xFF38BDF8, 0xFF0284C7);
gui_gfx_draw_string(bx - 76, by + 22, "Modular Monolithic Kernel v0.2.0-LTS", 0xFF64748B);
gui_gfx_draw_string(bx - 76, by + 36, "F5 cycle F6 cascade F7 tile F8 max", 0xFF475569);
// Soft vignette: concentric 1px frames darkening toward the edges. The
// alpha falls off with depth, so the corners recede smoothly.
int depth = (wh < sw ? wh : sw) / 6;
for (int i = 0; i < depth; i++) {
uint8_t a = (uint8_t)(((depth - i) * 42) / depth);
if (a == 0) continue;
gui_gfx_fill_rect_blend(i, i, sw - 2 * i, 1, GUI_COLOR_BLACK, a); // top
gui_gfx_fill_rect_blend(i, wh - 1 - i, sw - 2 * i, 1, GUI_COLOR_BLACK, a); // bottom
gui_gfx_fill_rect_blend(i, i, 1, wh - 2 * i, GUI_COLOR_BLACK, a); // left
gui_gfx_fill_rect_blend(sw - 1 - i, i, 1, wh - 2 * i, GUI_COLOR_BLACK, a); // right
}
// Centred brand mark with a subtle glow (drawn as a shadowed 16px title).
const char* brand = "SUB-OS";
int glyph_w = 16; // draw_string_16 advances ~16px per glyph
int bw = (int)strlen(brand) * glyph_w;
int bx = (sw - bw) / 2;
int by = wh / 2 - 40;
gui_gfx_draw_string_16_shadow(bx, by, brand, 0xFF7DD3FC, 0xFF0C4A6E);
const char* sub = "Modular Monolithic Kernel - v0.2.0-LTS";
int sw2 = (int)strlen(sub) * 8;
gui_gfx_draw_string((sw - sw2) / 2, by + 24, sub, 0xFF64748B);
const char* hint = "F5 cycle F6 cascade F7 tile F8 maximize";
int hw = (int)strlen(hint) * 8;
gui_gfx_draw_string((sw - hw) / 2, by + 40, hint, 0xFF3E4C6B);
}
void gui_desktop_invalidate_background(void) {
@@ -314,7 +340,7 @@ void gui_desktop_render_taskbar(void) {
// One button per window, in z-order
int tab_x = 106;
int tray_x = sw - 200;
int tray_x = sw - 260; // widened tray: FPS pill + CPU trace + mem + clock
for (int i = 0; i < gui_wm_get_window_count() && tab_x < tray_x - 106; i++) {
gui_window_t* win = gui_wm_get_window_at_index(i);
if (!win || !win->visible) continue;
@@ -358,6 +384,14 @@ void gui_desktop_render_taskbar(void) {
gui_gfx_draw_string(sw - 140, ty + 12, buf, GUI_COLOR_BLACK);
(void)total;
// Live FPS pill, tinted by how smooth the compositor is running.
char fps[16];
snprintf(fps, sizeof(fps), "%u FPS", g_fps);
uint32_t fps_col = (g_fps >= 45) ? GUI_THEME_SUCCESS
: (g_fps >= 20) ? GUI_THEME_WARNING
: GUI_THEME_DANGER;
gui_gfx_draw_string(sw - 205, ty + 12, fps, fps_col);
rtc_time_t now;
rtc_get_time(&now);
if (g_clock_seconds) {
@@ -679,9 +713,12 @@ int gui_desktop_run(void) {
fbcon_enable(false);
gui_desktop_init();
// Open a default session so the desktop is not empty on first boot.
launch_app(2); // System Monitor
launch_app(0); // Terminal
// Open a default session so the desktop is not empty on first boot. Placed
// and sized for the HD work area rather than the old 800x600 defaults.
int sw = gui_gfx_get_width();
int wh = gui_desktop_workarea_height();
gui_app_sysmon_launch(sw - 620, 60, 560, 360);
gui_app_terminal_launch(120, 90, sw - 820, wh - 200);
// Discard anything the console left in the keyboard queue; a stale key
// arriving on frame 0 would otherwise act as a desktop shortcut.
@@ -764,6 +801,15 @@ int gui_desktop_run(void) {
g_frames++;
g_pushed_pixels += gui_gfx_last_present_pixels();
// Sample the frame rate roughly twice a second from the monotonic clock.
uint64_t now_ms = ktime_ms();
uint64_t dt = now_ms - g_fps_last_ms;
if (dt >= 500) {
g_fps = (uint32_t)(((g_frames - g_fps_last_frames) * 1000ULL) / dt);
g_fps_last_ms = now_ms;
g_fps_last_frames = g_frames;
}
if ((g_frames & 0xFF) == 0) {
uint64_t full = (uint64_t)gui_gfx_get_width() * (uint64_t)gui_gfx_get_height();
uint64_t avg = g_pushed_pixels / 256;
+12 -3
View File
@@ -616,15 +616,24 @@ void gui_wm_render(void) {
gui_window_t* win = gui_wm_get_window(g_window_order[i]);
if (!win || !win->visible || win->minimized) continue;
gui_gfx_draw_shadow(win->x, win->y, win->width, win->height, 6);
// A larger, softer drop shadow reads as real depth on the HD desktop.
gui_gfx_draw_shadow(win->x, win->y, win->width, win->height,
win->active ? 12 : 7);
uint32_t border = win->active ? GUI_THEME_PRIMARY : GUI_THEME_BORDER;
gui_gfx_draw_rect(win->x, win->y, win->width, win->height, border);
uint32_t top_bg = win->active ? 0xFF1E293B : 0xFF0F172A;
uint32_t bot_bg = win->active ? 0xFF0F172A : 0xFF0A0E1A;
// Brighter, more saturated titlebar when focused; muted when not.
uint32_t top_bg = win->active ? 0xFF24345A : 0xFF141C2E;
uint32_t bot_bg = win->active ? 0xFF141E38 : 0xFF0B1120;
gui_gfx_draw_gradient_v(win->x + 1, win->y + 1, win->width - 2,
GUI_TITLEBAR_HEIGHT - 1, top_bg, bot_bg);
// Accent underline on the active window's titlebar; plain divider otherwise.
if (win->active) {
gui_gfx_fill_rect(win->x + 1, win->y + GUI_TITLEBAR_HEIGHT - 1,
win->width - 2, 2, GUI_THEME_PRIMARY);
}
gui_gfx_draw_line(win->x, win->y + GUI_TITLEBAR_HEIGHT,
win->x + win->width - 1, win->y + GUI_TITLEBAR_HEIGHT, border);
+17
View File
@@ -0,0 +1,17 @@
#ifndef _KERNEL_KTIME_H
#define _KERNEL_KTIME_H
// Unified monotonic high-resolution clock. Prefers the HPET (nanosecond grade)
// and falls back to the 100 Hz timer tick when no HPET is present.
#include <stdint.h>
#include <stdbool.h>
void ktime_init(void);
uint64_t ktime_ns(void); // nanoseconds since ktime_init
uint64_t ktime_us(void);
uint64_t ktime_ms(void);
const char* ktime_source(void); // "HPET" or "PIT"
bool ktime_is_highres(void); // true when backed by the HPET
#endif // _KERNEL_KTIME_H
+3 -1
View File
@@ -76,6 +76,7 @@
#include <drivers/hpet.h>
#include <drivers/nvram.h>
#include <drivers/lpt.h>
#include <kernel/ktime.h>
#include <drivers/virtio_input.h>
#include <gui/gui.h>
#include <init/init.h>
@@ -135,6 +136,7 @@ static void subos_modular_core_boot(void) {
nvram_init();
lpt_init();
#endif
ktime_init();
canvas_init();
pty_init();
virtio_rng_init();
@@ -330,7 +332,7 @@ void kernel_main(void* memory_map, uint64_t memory_map_count) {
printk(ANSI_BRIGHT_CYAN " SUB-OS 64-Bit [%s] Modular Monolithic Kernel %s\n" ANSI_RESET, arch_get_name(), kernel_get_version());
printk(ANSI_BRIGHT_CYAN "=================================================================\n\n" ANSI_RESET);
init_early("root=/dev/sda console=tty1 init=/bin/lazybox video=1280x720 quiet");
init_early("root=/dev/sda console=tty1 init=/bin/lazybox video=1920x1080 quiet");
rtc_init();
printk(KERN_INFO "[1/14] Initializing 64-Bit GDT, IDT, PIC & PIT Timer... ");
+39
View File
@@ -0,0 +1,39 @@
// Unified monotonic high-resolution clock for SUB-OS.
//
// When the HPET is available it provides true nanosecond timing; otherwise the
// clock degrades gracefully to the 100 Hz kernel timer tick (10 ms resolution).
// Either way the epoch is the moment ktime_init() ran.
#include <kernel/ktime.h>
#include <drivers/hpet.h>
#include <arch/arch.h>
#include <kernel/printk.h>
#define TICK_HZ 100ULL
#define NS_PER_TICK (1000000000ULL / TICK_HZ) // 10,000,000 ns at 100 Hz
static bool g_use_hpet = false;
static uint64_t g_base_tick = 0;
void ktime_init(void) {
g_use_hpet = hpet_available();
g_base_tick = pit_get_ticks();
printk(ANSI_BRIGHT_GREEN "KTIME: " ANSI_RESET
"Monotonic clock online (source: %s%s)\n",
g_use_hpet ? "HPET" : "PIT 100 Hz",
g_use_hpet ? ", nanosecond resolution" : "");
}
uint64_t ktime_ns(void) {
if (g_use_hpet) {
return hpet_get_ns();
}
uint64_t ticks = pit_get_ticks() - g_base_tick;
return ticks * NS_PER_TICK;
}
uint64_t ktime_us(void) { return ktime_ns() / 1000ULL; }
uint64_t ktime_ms(void) { return ktime_ns() / 1000000ULL; }
const char* ktime_source(void) { return g_use_hpet ? "HPET" : "PIT"; }
bool ktime_is_highres(void) { return g_use_hpet; }
+15
View File
@@ -35,6 +35,7 @@
#include <drivers/hpet.h>
#include <drivers/nvram.h>
#include <drivers/lpt.h>
#include <kernel/ktime.h>
#include <kernel/sub_lang.h>
#include <kernel/cpp_kernel.h>
#include <userland/snake.h>
@@ -718,6 +719,19 @@ static int applet_iodev(int argc, char** argv) {
return 0;
}
static int applet_ktime(int argc, char** argv) {
(void)argc; (void)argv;
uint64_t ns = ktime_ns();
printk(ANSI_BRIGHT_CYAN "Monotonic clock (ktime):\n" ANSI_RESET);
printk(" Source : %s%s\n", ktime_source(),
ktime_is_highres() ? " (nanosecond resolution)" : " (10 ms tick)");
printk(" Uptime : %llu.%03llu s (%llu ns)\n",
(unsigned long long)(ns / 1000000000ULL),
(unsigned long long)((ns / 1000000ULL) % 1000ULL),
(unsigned long long)ns);
return 0;
}
static int applet_hpet(int argc, char** argv) {
(void)argc; (void)argv;
if (!hpet_available()) {
@@ -2465,6 +2479,7 @@ static const lazybox_applet_t applets[] = {
{"reg", applet_reg, "reg query|add|set|stats", "NT configuration registry", "Kernel"},
{"iodev", applet_iodev, "iodev", "NT I/O Manager devices & IRP","Kernel"},
{"hpet", applet_hpet, "hpet", "High Precision Event Timer", "Hardware"},
{"ktime", applet_ktime, "ktime", "Monotonic high-res clock", "Kernel"},
{"nvram", applet_nvram, "nvram", "Dump CMOS NVRAM bytes", "Hardware"},
{"lpt", applet_lpt, "lpt [text]", "Send text to LPT1 parallel", "Hardware"},
{"rand", applet_rand, "rand [count]", "Generate random numbers", "Crypto"},