fix: jiggler should not prevent primary session timeout

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 is contained in:
Alex P 2025-10-17 15:30:02 +03:00
parent c9d8dcb553
commit f2431e9bbf
2 changed files with 4 additions and 11 deletions

View File

@ -139,12 +139,6 @@ func runJiggler() {
if err != nil {
logger.Warn().Msgf("Failed to reset mouse position: %v", err)
}
if sessionManager != nil {
if primarySession := sessionManager.GetPrimarySession(); primarySession != nil {
sessionManager.UpdateLastActive(primarySession.ID)
}
}
}
}
}

View File

@ -242,7 +242,7 @@ func (sm *SessionManager) AddSession(session *Session, clientSettings *SessionSe
existing.RPCChannel = session.RPCChannel
existing.HidChannel = session.HidChannel
existing.flushCandidates = session.flushCandidates
// Preserve existing mode and nickname
// Preserve mode and nickname
session.Mode = existing.Mode
session.Nickname = existing.Nickname
session.CreatedAt = existing.CreatedAt
@ -1199,11 +1199,10 @@ func (sm *SessionManager) transferPrimaryRole(fromSessionID, toSessionID, transf
// Promote target session
toSession.Mode = SessionModePrimary
toSession.hidRPCAvailable = false // Force re-handshake
// Only reset LastActive for emergency promotions to prevent immediate re-timeout
// For manual transfers, preserve existing LastActive to maintain timeout accuracy
toSession.hidRPCAvailable = false
// Reset LastActive only for emergency promotions to prevent immediate re-timeout
if transferType == "emergency_timeout_promotion" || transferType == "emergency_promotion_deadlock_prevention" {
toSession.LastActive = time.Now() // Reset for emergency promotions only
toSession.LastActive = time.Now()
}
sm.primarySessionID = toSessionID