Root causes fixed:
- _focused was a stray class annotation in @dataclass, causing field
ordering issues — moved to proper dataclass field
- xdotool type --window WID not supported on all versions — removed
--window flag, use focused window instead
- xdotool commands with --window may fail silently — switched to
absolute coordinates (window is at 0,0 filling the display)
- All xdotool errors were silently swallowed — now logged with stderr
Mouse events:
- Use absolute mousemove + click (no --window) since window fills display
- Separate mousemove and click into two calls for reliability
- Fire-and-forget for mousemove to reduce latency
Keyboard events:
- xdotool type (no --window) for printable characters
- xdotool key (no --window) for special keys and modifier combos
- Window focused once via _ensure_focus, not per-event
Diagnostics:
- Backend logs first 5 input events received per WebSocket session
- Backend logs xdotool stderr on failure
- Frontend logs first 10 input events sent + WS state warnings
- Frontend uses capture phase for keyboard events
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Capture stderr from GUI apps and show meaningful exit reasons (signal names,
error messages) instead of generic "Application exited"
- Add /api/display/discover-apps endpoint that scans .desktop files for
installed GUI apps, replacing manual-only app configuration
- Settings > Applications now shows discoverable apps with one-click Add,
with manual form available as fallback
- Fix WiFi: start wpa_supplicant before bringing interface up, handle rfkill
blocks, add retry logic and error messages to scan results
- Fix WiFi scan frontend bug: response is {networks:[...]} not a bare array
- Add iw and wpasupplicant to install.sh dependencies
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove dock button creation from display.js initGuiApps (apps belong in right panel)
- Register GUI app modules dynamically in loadPanelApps for newly added apps
- Refresh right panel immediately after adding/removing apps in Settings
- Expose loadPanelApps globally for cross-module panel refresh
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each configured GUI app (e.g. Nextcloud) gets its own dock icon and
opens as a regular Atlus tab. Under the hood: Xvfb virtual display,
ImageMagick captures individual window pixmaps as JPEG, streams over
WebSocket to a canvas element, with xdotool forwarding mouse/keyboard
input back to the X11 window. Apps persist in background when tab is
closed, and streaming pauses when no viewers are attached.
New files: backend/display.py (DisplayManager + ManagedGuiApp),
backend/routers/display.py (WebSocket + REST), frontend display.js/css.
Config: gui_apps array in settings for registered applications.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>