Files
SUB-OS/include/gui/gui_wm.h
T
subhobhai943andClaude Opus 4.8 2c2e2d536e perf(gui): scene-dirty compositor + cursor overlay + 60 FPS pacer + animations
Rework the compositor so it stops repainting the whole screen every frame,
tripling the frame rate (17 -> 54 FPS at HD) and adding smooth animation.

- Scene-dirty skipping (gui/gui_desktop.c): the full scene is recomposited only
  when something other than the bare pointer changed -- input, an open animation,
  or a ~10 Hz heartbeat for live content (clock, graphs). Idle and pointer-only
  frames skip the recomposite entirely.
- Cursor save-under (gui/gui_cursor.c): the pointer is an overlay that stashes
  and restores the pixels beneath it, so moving the mouse never forces a full
  repaint -- pointer motion runs at the frame cap.
- 60 FPS frame pacer: each iteration is timed against the monotonic clock and
  padded to a 16.666 ms budget with the new ktime_delay_us() (HPET-precise
  busy-wait), giving consistent pacing instead of a free-running spin.
- Window open animation (gui/gui_wm.c): new windows grow from 60% to full size
  with a cubic ease-out over ~160 ms; gui_wm_update() drives it and reports
  while any window is still animating so the compositor keeps redrawing.
- Default display mode set to 1280x720 (HD) -- the sweet spot where the
  software compositor sustains a near-60 FPS cursor with headroom for effects.

Kernel: kernel/time/ktime.c gains ktime_delay_us(), a precise HPET-based delay
(bounded PIT fallback) used by the pacer.

Verified live (screenshotted): boots to 1280x720, logs in, tray reads ~54 FPS
(green) while the pointer moves, no cursor ghosting, windows render cleanly.
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
2026-08-25 23:05:44 +05:30

124 lines
3.4 KiB
C

#ifndef _GUI_WM_H
#define _GUI_WM_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <gui/gui_gfx.h>
#include <gui/gui_theme.h>
#define GUI_MAX_WINDOWS 16
#define GUI_TITLEBAR_HEIGHT 24
#define GUI_RESIZE_GRIP 12
#define GUI_MIN_WINDOW_W 160
#define GUI_MIN_WINDOW_H 100
typedef enum {
GUI_EVENT_MOUSE_MOVE,
GUI_EVENT_MOUSE_DOWN,
GUI_EVENT_MOUSE_UP,
GUI_EVENT_KEY_DOWN,
GUI_EVENT_FOCUS,
GUI_EVENT_RESIZE,
GUI_EVENT_CLOSE
} gui_event_type_t;
typedef struct {
gui_event_type_t type;
int mouse_x;
int mouse_y;
int rel_x;
int rel_y;
bool btn_left;
bool btn_right;
uint16_t key;
} gui_event_t;
// Where a window sits relative to the screen edges.
typedef enum {
GUI_SNAP_NONE = 0,
GUI_SNAP_LEFT,
GUI_SNAP_RIGHT,
GUI_SNAP_MAXIMIZED
} gui_snap_t;
typedef struct gui_window {
int id;
char title[64];
int x;
int y;
int width;
int height;
bool active;
bool minimized;
bool visible;
bool resizable;
// Drag / resize interaction state
bool is_dragging;
bool is_resizing;
int drag_off_x;
int drag_off_y;
// Geometry remembered across maximize / snap so restore is exact
gui_snap_t snap;
int saved_x;
int saved_y;
int saved_width;
int saved_height;
void* user_data;
// Open animation: the window grows from a fraction of its final size to
// full over a short interval. anim_open_ns == 0 means no animation running.
uint64_t anim_open_ns; // ktime_ns() when the open animation began
int target_w; // final geometry the animation resolves to
int target_h;
int center_x; // fixed centre the growth expands around
int center_y;
void (*paint)(struct gui_window* win);
void (*handle_event)(struct gui_window* win, const gui_event_t* ev);
} gui_window_t;
void gui_wm_init(void);
// The work area excludes the taskbar; windows maximize and snap inside it.
void gui_wm_set_workarea(int width, int height);
gui_window_t* gui_wm_create_window(const char* title, int x, int y, int w, int h);
// Advance any running open animations; returns true while at least one window
// is still animating (so the compositor keeps redrawing during the effect).
bool gui_wm_update(void);
void gui_wm_destroy_window(int win_id);
void gui_wm_focus_window(int win_id);
gui_window_t* gui_wm_get_window(int win_id);
gui_window_t* gui_wm_get_active_window(void);
int gui_wm_get_window_count(void);
// Enumerate in z-order, bottom-most first. Returns NULL past the end.
gui_window_t* gui_wm_get_window_at_index(int index);
void gui_wm_minimize_window(int win_id);
void gui_wm_restore_window(int win_id);
void gui_wm_toggle_maximize(int win_id);
void gui_wm_snap_window(int win_id, gui_snap_t snap);
void gui_wm_close_active(void);
void gui_wm_cycle_focus(void);
void gui_wm_cascade_windows(void);
void gui_wm_tile_windows(void);
// Keep the WM's press-edge detector in step when another layer (a menu, a
// modal dialog) consumed the click instead. Without this the WM still holds
// the pre-press state and reads the still-held button as a fresh press on the
// following frame, stealing focus from whatever the click just opened.
void gui_wm_sync_button_state(bool btn_left);
void gui_wm_handle_mouse(int x, int y, bool btn_left, bool btn_right);
void gui_wm_handle_key(uint16_t key);
void gui_wm_render(void);
#endif // _GUI_WM_H