From 07fce7aae1ebe03a344160e3083837044d7de850 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 7 Feb 2024 19:45:30 +0100 Subject: [PATCH] Stop display link when window is occluded (#7511) Release Notes: - Fixed a bug that caused the window to become unresponsive after foregrounding. --------- Co-authored-by: Conrad --- crates/gpui/src/platform/mac/window.rs | 27 ++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index b15e8c8de5..b6d0e3b886 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -12,7 +12,7 @@ use cocoa::{ CGPoint, NSApplication, NSBackingStoreBuffered, NSEventModifierFlags, NSFilenamesPboardType, NSPasteboard, NSScreen, NSView, NSViewHeightSizable, NSViewWidthSizable, NSWindow, NSWindowButton, NSWindowCollectionBehavior, - NSWindowStyleMask, NSWindowTitleVisibility, + NSWindowOcclusionState, NSWindowStyleMask, NSWindowTitleVisibility, }, base::{id, nil}, foundation::{ @@ -249,6 +249,10 @@ unsafe fn build_window_class(name: &'static str, superclass: &Class) -> *const C sel!(windowDidResize:), window_did_resize as extern "C" fn(&Object, Sel, id), ); + decl.add_method( + sel!(windowDidChangeOcclusionState:), + window_did_change_occlusion_state as extern "C" fn(&Object, Sel, id), + ); decl.add_method( sel!(windowWillEnterFullScreen:), window_will_enter_fullscreen as extern "C" fn(&Object, Sel, id), @@ -530,14 +534,12 @@ impl MacWindow { let native_view = NSView::init(native_view); assert!(!native_view.is_null()); - let display_link = start_display_link(native_window.screen(), native_view); - let window = Self(Arc::new(Mutex::new(MacWindowState { handle, executor, native_window, native_view: NonNull::new_unchecked(native_view), - display_link, + display_link: nil, renderer: MetalRenderer::new(instance_buffer_pool), kind: options.kind, request_frame_callback: None, @@ -1332,6 +1334,23 @@ extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) { } } +extern "C" fn window_did_change_occlusion_state(this: &Object, _: Sel, _: id) { + let window_state = unsafe { get_window_state(this) }; + let mut lock = window_state.lock(); + unsafe { + if lock + .native_window + .occlusionState() + .contains(NSWindowOcclusionState::NSWindowOcclusionStateVisible) + { + lock.display_link = + start_display_link(lock.native_window.screen(), lock.native_view.as_ptr()); + } else { + lock.display_link = nil; + } + } +} + extern "C" fn window_did_resize(this: &Object, _: Sel, _: id) { let window_state = unsafe { get_window_state(this) }; window_state.as_ref().lock().move_traffic_light();