From 824e7e421a8164e1696bd7182ad208d488e645e7 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 5 Feb 2024 14:48:54 -0800 Subject: [PATCH] Disable extra frames for ProMotion when screen is not active. (#7410) This was causing an issue where windows about 1/10 of the way across the display would hang for a fully second after being deactivated. Release Notes: - N/A Co-authored-by: max Co-authored-by: nathan Co-authored-by: antonio --- crates/gpui/src/platform/mac/window.rs | 1 + crates/gpui/src/window.rs | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 946e608a7a686d2680b98b1388c652e2cedcf3f5..b15e8c8de5c47c25ffff0f744597bc2f6b6b2b89 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -1530,6 +1530,7 @@ extern "C" fn display_layer(this: &Object, _: Sel, _: id) { extern "C" fn step(this: &Object, _: Sel, display_link: id) { let window_state = unsafe { get_window_state(this) }; let mut lock = window_state.lock(); + if lock.display_link == display_link { if let Some(mut callback) = lock.request_frame_callback.take() { drop(lock); diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index 13051be58221ca2a25e8c2ac013a049471f4065d..5bb85bf8764b05a7965f5dcb6b7925bd2118620c 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -269,7 +269,7 @@ pub struct Window { scale_factor: f32, bounds: WindowBounds, bounds_observers: SubscriberSet<(), AnyObserver>, - active: bool, + active: Rc>, pub(crate) dirty: Rc>, pub(crate) last_input_timestamp: Rc>, pub(crate) refreshing: bool, @@ -334,11 +334,13 @@ impl Window { let bounds = platform_window.bounds(); let text_system = Arc::new(WindowTextSystem::new(cx.text_system().clone())); let dirty = Rc::new(Cell::new(true)); + let active = Rc::new(Cell::new(false)); let last_input_timestamp = Rc::new(Cell::new(Instant::now())); platform_window.on_request_frame(Box::new({ let mut cx = cx.to_async(); let dirty = dirty.clone(); + let active = active.clone(); let last_input_timestamp = last_input_timestamp.clone(); move || { if dirty.get() { @@ -350,9 +352,12 @@ impl Window { }) .log_err(); }) - } else if last_input_timestamp.get().elapsed() < Duration::from_secs(1) { - // Keep presenting the current scene for 1 extra second since the - // last input to prevent the display from underclocking the refresh rate. + } + // Keep presenting the current scene for 1 extra second since the + // last input to prevent the display from underclocking the refresh rate. + else if active.get() + && last_input_timestamp.get().elapsed() < Duration::from_secs(1) + { handle.update(&mut cx, |_, cx| cx.present()).log_err(); } } @@ -378,7 +383,7 @@ impl Window { move |active| { handle .update(&mut cx, |_, cx| { - cx.window.active = active; + cx.window.active.set(active); cx.window .activation_observers .clone() @@ -422,7 +427,7 @@ impl Window { scale_factor, bounds, bounds_observers: SubscriberSet::new(), - active: false, + active, dirty, last_input_timestamp, refreshing: false, @@ -750,7 +755,7 @@ impl<'a> WindowContext<'a> { /// Returns whether this window is focused by the operating system (receiving key events). pub fn is_window_active(&self) -> bool { - self.window.active + self.window.active.get() } /// Toggle zoom on the window. @@ -1006,7 +1011,7 @@ impl<'a> WindowContext<'a> { self.window.focus, ); self.window.next_frame.focus = self.window.focus; - self.window.next_frame.window_active = self.window.active; + self.window.next_frame.window_active = self.window.active.get(); self.window.root_view = Some(root_view); // Set the cursor only if we're the active window. @@ -2512,7 +2517,7 @@ impl WindowHandle { pub fn is_active(&self, cx: &AppContext) -> Option { cx.windows .get(self.id) - .and_then(|window| window.as_ref().map(|window| window.active)) + .and_then(|window| window.as_ref().map(|window| window.active.get())) } }