diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-09-01 15:48:22 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-01 15:48:22 +0300 |
| commit | 207be3c771d281baae6e5fa0fb74be9a056e97a2 (patch) | |
| tree | d7b037ecdf629224a048c841d11659efdc23507d /src/client/timer.rs | |
| parent | 8a6d697308162874a236c84aac0b0f8c7ac01f83 (diff) | |
refactor: render the shell in the client (#3487)
* feat: add opt-in client-rendered shell
* feat: add client-owned shell mouse controls
* feat: complete client-owned shell chrome
* feat: add client-owned shell settings and notifications
* feat: run client shell custom commands
* feat: render popup terminals in client shell
* feat: add client-owned scrollback and copy mode
* fix: preserve client worktree trust defaults
* feat: render startup diagnostics in client shell
* feat: render onboarding in client shell
* feat: render product announcements in client shell
* feat: render release notes in client shell
* feat: render mobile switcher in client shell
* feat: render kitty graphics in client shell
* fix: preserve client shell lifecycle coherence
* refactor: route client shell commands through endpoint connections
* refactor: make the client-rendered shell the default
* refactor: remove monolithic launch mode
* refactor: complete client-rendered shell cutover
* perf: retain client pane surface updates
* perf: scale retained pane surface updates
* perf: remove remote pane input latency
* test: make client shell checks platform-independent
* fix: prevent client timer starvation
* test: fix client shell platform gates
* test: accept retained surfaces in cross-area checks
* test: make client mode assertions platform-neutral
* fix: badge only outdated integrations
Diffstat (limited to 'src/client/timer.rs')
| -rw-r--r-- | src/client/timer.rs | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/client/timer.rs b/src/client/timer.rs new file mode 100644 index 00000000..bd5c249a --- /dev/null +++ b/src/client/timer.rs @@ -0,0 +1,78 @@ +use std::time::{Duration, Instant}; + +pub(super) struct ClientLoopTimer { + deadline: Option<Instant>, +} + +impl ClientLoopTimer { + pub(super) fn new() -> Self { + Self { deadline: None } + } + + pub(super) fn deadline(&mut self, now: Instant, delay: Duration) -> Instant { + let requested = now.checked_add(delay).unwrap_or(now); + let deadline = self + .deadline + .map_or(requested, |current| current.min(requested)); + self.deadline = Some(deadline); + deadline + } + + pub(super) fn fired(&mut self) { + self.deadline = None; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn incoming_events_do_not_postpone_timer_deadline() { + let start = Instant::now(); + let delay = Duration::from_millis(100); + let mut timer = ClientLoopTimer::new(); + + let first_deadline = timer.deadline(start, delay); + assert_eq!( + timer.deadline(start + Duration::from_millis(25), delay), + first_deadline + ); + assert_eq!( + timer.deadline(start + Duration::from_millis(50), delay), + first_deadline + ); + assert_eq!( + timer.deadline(start + Duration::from_millis(75), delay), + first_deadline + ); + + timer.fired(); + assert_eq!( + timer.deadline(first_deadline, delay), + first_deadline + delay + ); + } + + #[test] + fn earlier_client_work_can_pull_the_timer_deadline_forward() { + let start = Instant::now(); + let mut timer = ClientLoopTimer::new(); + + assert_eq!( + timer.deadline(start, Duration::from_millis(100)), + start + Duration::from_millis(100) + ); + assert_eq!( + timer.deadline(start + Duration::from_millis(20), Duration::from_millis(10)), + start + Duration::from_millis(30) + ); + assert_eq!( + timer.deadline( + start + Duration::from_millis(25), + Duration::from_millis(100) + ), + start + Duration::from_millis(30) + ); + } +} |
