diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index 88c5b8211d..fa9960c1fb 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -646,8 +646,6 @@ impl AppContext { } /// Repeatedly called during `flush_effects` to handle a focused handle being dropped. - /// For now, we simply blur the window if this happens, but we may want to support invoking - /// a window blur handler to restore focus to some logical element. fn release_dropped_focus_handles(&mut self) { for window_handle in self.windows() { window_handle diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 16de7ef62a..d8ca026f71 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -2419,6 +2419,29 @@ impl<'a, V: 'static> ViewContext<'a, V> { subscription } + /// Register a listener to be called when the window loses focus. + /// Unlike [on_focus_changed], returns a subscription and persists until the subscription + /// is dropped. + pub fn on_window_focus_lost( + &mut self, + mut listener: impl FnMut(&mut V, &mut ViewContext) + 'static, + ) -> Subscription { + let view = self.view.downgrade(); + let (subscription, activate) = self.window.focus_listeners.insert( + (), + Box::new(move |event, cx| { + view.update(cx, |view, cx| { + if event.blurred.is_none() && event.focused.is_none() { + listener(view, cx) + } + }) + .is_ok() + }), + ); + self.app.defer(move |_| activate()); + subscription + } + /// Register a listener to be called when the given focus handle or one of its descendants loses focus. /// Unlike [on_focus_changed], returns a subscription and persists until the subscription /// is dropped. diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index a352b0a67a..2bcf6ec13e 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -532,6 +532,11 @@ impl Workspace { cx.notify() }) .detach(); + cx.on_window_focus_lost(|this, cx| { + let focus_handle = this.focus_handle(cx); + cx.focus(&focus_handle); + }) + .detach(); let weak_handle = cx.view().downgrade(); let pane_history_timestamp = Arc::new(AtomicUsize::new(0));