summaryrefslogtreecommitdiff
path: root/src/client/timer.rs
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-09-01 15:48:22 +0300
committerGitHub <noreply@github.com>2026-09-01 15:48:22 +0300
commit207be3c771d281baae6e5fa0fb74be9a056e97a2 (patch)
treed7b037ecdf629224a048c841d11659efdc23507d /src/client/timer.rs
parent8a6d697308162874a236c84aac0b0f8c7ac01f83 (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.rs78
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)
+ );
+ }
+}