Replaced custom jiggler implementation with dev branch version:
- Uses rpcAbsMouseReport() instead of gadget.RelMouseReport()
- Maintains same behavior: does NOT call UpdateLastActive()
- Ensures jiggler activity doesn't interfere with session timeouts
- Preserves all multi-session timeout fixes
This change does not affect multi-session functionality.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problem: The jiggler was calling sessionManager.UpdateLastActive() which
prevented the primary session timeout from ever triggering. This made it
impossible to automatically demote inactive primary sessions.
Root cause analysis:
- Jiggler is automated mouse movement to prevent remote PC sleep
- It was incorrectly updating LastActive timestamp as if it were user input
- This reset the inactivity timer every time jiggler ran
- Primary session timeout requires LastActive to remain unchanged during
actual user inactivity
Changes:
- Removed sessionManager.UpdateLastActive() call from jiggler.go:145
- Added comment explaining why jiggler should not update LastActive
- Session timeout now correctly tracks only REAL user input:
* Keyboard events (via USB HID)
* Mouse events (via USB HID)
* Native operations
- Jiggler mouse movement is explicitly excluded from activity tracking
This works together with the previous fix that removed LastActive reset
during WebSocket reconnections.
Impact:
- Primary sessions will now correctly timeout after configured inactivity
- Jiggler continues to prevent remote PC sleep as intended
- Only genuine user input resets the inactivity timer
Test:
1. Enable jiggler with short interval (e.g., every 10 seconds)
2. Set primary timeout to 60 seconds
3. Leave primary tab in background with no user input
4. Jiggler will keep remote PC awake
5. After 60 seconds, primary session is correctly demoted
This commit addresses three critical issues discovered during testing:
Issue 1 - Intermittent mouse control loss requiring page refresh:
When a session was promoted to primary, the HID queue handlers were fetching
a fresh session copy from the session manager instead of using the original
session pointer. This meant the queue handler had a stale Mode field (observer)
while the manager had the updated Mode (primary). The permission check would
fail, silently dropping all mouse input until the page was refreshed.
Issue 2 - Missing permission failure diagnostics:
When keyboard/mouse input was blocked due to insufficient permissions, there
was no debug logging to help diagnose why input wasn't working. This made
troubleshooting observer mode issues extremely difficult.
Issue 3 - Session timeout despite active jiggler:
The server-side jiggler moves the mouse every 30s after inactivity to prevent
screen savers, but wasn't updating the session's LastActive timestamp. This
caused sessions to timeout after 60s even with the jiggler active.
Issue 4 - Session flapping after emergency promotion:
When a session timed out and another was promoted, the newly promoted session
had a stale LastActive timestamp (60+ seconds old), causing immediate re-timeout.
This created an infinite loop where both sessions rapidly alternated between
primary and observer every second.
Issue 5 - Unnecessary WebSocket reconnections:
The WebSocket fallback was unconditionally closing and reconnecting during
emergency promotions, even when the connection was healthy. This caused
spurious "Connection Issue Detected" overlays during normal promotions.
Changes:
- webrtc.go: Use original session pointer in handleQueues() (line 197)
- hidrpc.go: Add debug logging when permission checks block input (lines 31-34, 61-64, 75-78)
- jiggler.go: Update primary session LastActive after mouse movement (lines 146-152)
- session_manager.go: Reset LastActive to time.Now() on promotion (line 1090)
- devices.$id.tsx: Only reconnect if connection is unhealthy (lines 413-425)
This ensures:
1. Queue handlers always have up-to-date session state
2. Permission failures are visible in logs for debugging
3. Jiggler prevents both screen savers AND session timeout
4. Newly promoted sessions get full timeout period (no immediate re-timeout)
5. Emergency promotions only reconnect when connection is actually stale
6. No spurious "Connection Issue" overlays during normal promotions
Ensure the jiggler config loads the defaults so they can be saved.
Ensure the file.Sync occurs before acknowledging save.
Also fixup the old KeyboardLayout to use en-US not en_US
* feat: add timezone support to jiggler and fix custom settings persistence
- Add timezone field to JigglerConfig with comprehensive IANA timezone list
- Fix custom settings not loading current values
- Remove business hours preset, add as examples in custom settings
- Improve error handling for invalid cron expressions
* fix: format jiggler.go with gofmt
* fix: add embedded timezone data and validation
- Import time/tzdata to embed timezone database in binary
- Add timezone validation in runJigglerCronTab() to gracefully fallback to UTC
- Add timezone to debug logging in rpcSetJigglerConfig
- Fixes 'unknown time zone' errors when system lacks timezone data
* refactor: add timezone field comments from jiggler options
* chore: move tzdata to backend
* refactor: fix JigglerSetting linting
- Adjusted useEffect dependency to include send function for better data fetching
- Modified layout classes for improved responsiveness and consistency
- Cleaned up code formatting for better readability
---------
Co-authored-by: Siyuan Miao <i@xswan.net>