- Add serializable state structs (WorkspaceState, TabState, PaneState, etc.)
- Implement Workspace::save() to persist open tabs, cursor positions,
viewport scroll, and pane bounds to .fackr/workspace.json
- Implement Workspace::load() to restore workspace state on startup,
handling missing files gracefully
- Add Cursors::from_cursor() constructor for state restoration
- Call workspace.save() on editor exit
- Replace empty default tab when opening explicit file to avoid
spurious [new] tab appearing as tab 1
Add active window focus system where keyboard input is routed to the
last-activated component instead of using fixed priority.
Changes:
- Add Focus enum (Editor, Terminal, FussMode, ServerManager, Prompt)
- Add HitRegion enum for mouse hit testing
- Add focus field to Editor struct
- Implement hit_test() to determine clicked region
- Implement return_focus() helper for closing components
- Add click-to-focus in mouse handler
- Update toggle handlers to set focus when opening/closing
- Refactor keyboard routing from priority-based to focus-based
Behavior:
- Clicking any component gives it keyboard focus
- Keyboard shortcuts that open components also focus them
- Clicking in split panes makes that pane active
- ESC closes focused component and returns focus sensibly
Add methods to determine which pane contains a screen coordinate:
- Tab::pane_at_screen_position() - finds pane by normalized coordinates
- Workspace::pane_at_position() - wrapper for active tab
When both fuss mode and terminal are visible, fuss mode now only renders
above the terminal instead of using full screen height. This prevents
visual artifacts where fuss mode content would render into the terminal
area.
- Add max_rows parameter to render_fuss
- Calculate available height based on terminal start row