par_term/tab/
refresh_task.rs1use crate::tab::Tab;
8use std::sync::Arc;
9use std::sync::atomic::Ordering;
10use tokio::runtime::Runtime;
11
12impl Tab {
13 pub fn start_refresh_task(
15 &mut self,
16 runtime: Arc<Runtime>,
17 window: Arc<winit::window::Window>,
18 active_fps: u32,
19 inactive_fps: u32,
20 ) {
21 let terminal_clone = Arc::clone(&self.terminal);
22 let is_active = Arc::clone(&self.is_active);
23 let active_interval_ms = (1000 / active_fps.max(1)) as u64;
24 let inactive_interval_ms = (1000 / inactive_fps.max(1)) as u64;
25
26 let handle = runtime.spawn(async move {
27 let mut last_gen = 0u64;
28 let mut idle_streak = 0u32;
29 const MAX_INACTIVE_IDLE_INTERVAL_MS: u64 = 250;
30
31 loop {
32 let is_active_now = is_active.load(Ordering::Relaxed);
33 let interval_ms = if is_active_now {
35 active_interval_ms
36 } else if idle_streak > 0 {
37 (inactive_interval_ms << idle_streak.min(4)).min(MAX_INACTIVE_IDLE_INTERVAL_MS)
38 } else {
39 inactive_interval_ms
40 };
41 tokio::time::sleep(tokio::time::Duration::from_millis(interval_ms)).await;
42
43 let should_redraw = if let Ok(term) = terminal_clone.try_read() {
44 let current_gen = term.update_generation();
45 if current_gen > last_gen {
46 last_gen = current_gen;
47 true
48 } else {
49 false
50 }
51 } else {
52 false
53 };
54
55 if should_redraw {
56 idle_streak = 0;
57 window.request_redraw();
58 } else if is_active_now {
59 idle_streak = 0;
60 } else {
61 idle_streak = idle_streak.saturating_add(1);
62 }
63 }
64 });
65
66 self.refresh_task = Some(handle);
67 }
68
69 pub fn stop_refresh_task(&mut self) {
71 if let Some(handle) = self.refresh_task.take() {
72 handle.abort();
73 }
74 }
75}