Make full-screen and window bounds callbacks take a WindowContext

Antonio Scandurra created

Change summary

crates/gpui/src/app.rs                  | 116 +++++---------------------
crates/gpui/src/app/window.rs           |  73 ++++++++++++++++
crates/vim/src/test/vim_test_context.rs |   4 
crates/vim/src/vim.rs                   |   5 
crates/zed/src/zed.rs                   |   3 
5 files changed, 98 insertions(+), 103 deletions(-)

Detailed changes

crates/gpui/src/app.rs 🔗

@@ -500,10 +500,10 @@ type FocusObservationCallback = Box<dyn FnMut(bool, &mut WindowContext) -> bool>
 type ReleaseObservationCallback = Box<dyn FnMut(&dyn Any, &mut AppContext)>;
 type ActionObservationCallback = Box<dyn FnMut(TypeId, &mut AppContext)>;
 type WindowActivationCallback = Box<dyn FnMut(bool, &mut WindowContext) -> bool>;
-type WindowFullscreenCallback = Box<dyn FnMut(bool, &mut AppContext) -> bool>;
-type WindowBoundsCallback = Box<dyn FnMut(WindowBounds, Uuid, &mut AppContext) -> bool>;
+type WindowFullscreenCallback = Box<dyn FnMut(bool, &mut WindowContext) -> bool>;
+type WindowBoundsCallback = Box<dyn FnMut(WindowBounds, Uuid, &mut WindowContext) -> bool>;
 type KeystrokeCallback =
-    Box<dyn FnMut(&Keystroke, &MatchResult, Option<&Box<dyn Action>>, &mut AppContext) -> bool>;
+    Box<dyn FnMut(&Keystroke, &MatchResult, Option<&Box<dyn Action>>, &mut WindowContext) -> bool>;
 type ActiveLabeledTasksCallback = Box<dyn FnMut(&mut AppContext) -> bool>;
 type DeserializeActionCallback = fn(json: &str) -> anyhow::Result<Box<dyn Action>>;
 type WindowShouldCloseSubscriptionCallback = Box<dyn FnMut(&mut AppContext) -> bool>;
@@ -1067,72 +1067,7 @@ impl AppContext {
         )
     }
 
-    fn observe_window_activation<F>(&mut self, window_id: usize, callback: F) -> Subscription
-    where
-        F: 'static + FnMut(bool, &mut WindowContext) -> bool,
-    {
-        let subscription_id = post_inc(&mut self.next_subscription_id);
-        self.pending_effects
-            .push_back(Effect::WindowActivationObservation {
-                window_id,
-                subscription_id,
-                callback: Box::new(callback),
-            });
-        Subscription::WindowActivationObservation(
-            self.window_activation_observations
-                .subscribe(window_id, subscription_id),
-        )
-    }
-
-    fn observe_fullscreen<F>(&mut self, window_id: usize, callback: F) -> Subscription
-    where
-        F: 'static + FnMut(bool, &mut AppContext) -> bool,
-    {
-        let subscription_id = post_inc(&mut self.next_subscription_id);
-        self.pending_effects
-            .push_back(Effect::WindowFullscreenObservation {
-                window_id,
-                subscription_id,
-                callback: Box::new(callback),
-            });
-        Subscription::WindowActivationObservation(
-            self.window_activation_observations
-                .subscribe(window_id, subscription_id),
-        )
-    }
-
-    fn observe_window_bounds<F>(&mut self, window_id: usize, callback: F) -> Subscription
-    where
-        F: 'static + FnMut(WindowBounds, Uuid, &mut AppContext) -> bool,
-    {
-        let subscription_id = post_inc(&mut self.next_subscription_id);
-        self.pending_effects
-            .push_back(Effect::WindowBoundsObservation {
-                window_id,
-                subscription_id,
-                callback: Box::new(callback),
-            });
-        Subscription::WindowBoundsObservation(
-            self.window_bounds_observations
-                .subscribe(window_id, subscription_id),
-        )
-    }
-
-    pub fn observe_keystrokes<F>(&mut self, window_id: usize, callback: F) -> Subscription
-    where
-        F: 'static
-            + FnMut(&Keystroke, &MatchResult, Option<&Box<dyn Action>>, &mut AppContext) -> bool,
-    {
-        let subscription_id = post_inc(&mut self.next_subscription_id);
-        self.keystroke_observations
-            .add_callback(window_id, subscription_id, Box::new(callback));
-        Subscription::KeystrokeObservation(
-            self.keystroke_observations
-                .subscribe(window_id, subscription_id),
-        )
-    }
-
-    pub fn observe_active_labeled_tasks<F>(&mut self, callback: F) -> Subscription
+    fn observe_active_labeled_tasks<F>(&mut self, callback: F) -> Subscription
     where
         F: 'static + FnMut(&mut AppContext) -> bool,
     {
@@ -1906,10 +1841,10 @@ impl AppContext {
         handled_by: Option<Box<dyn Action>>,
         result: MatchResult,
     ) {
-        self.update(|this| {
-            let mut observations = this.keystroke_observations.clone();
+        self.update_window(window_id, |cx| {
+            let mut observations = cx.keystroke_observations.clone();
             observations.emit(window_id, move |callback| {
-                callback(&keystroke, &result, handled_by.as_ref(), this)
+                callback(&keystroke, &result, handled_by.as_ref(), cx)
             });
         });
     }
@@ -3266,9 +3201,8 @@ impl<'a, 'b, 'c, V: View> ViewContext<'a, 'b, 'c, V> {
         F: 'static + FnMut(&mut V, bool, &mut ViewContext<V>),
     {
         let observer = self.weak_handle();
-        let window_id = self.window_id;
         self.window_context
-            .observe_window_activation(window_id, move |active, cx| {
+            .observe_window_activation(move |active, cx| {
                 if let Some(observer) = observer.upgrade(cx) {
                     observer.update(cx, |observer, cx| {
                         callback(observer, active, cx);
@@ -3285,18 +3219,16 @@ impl<'a, 'b, 'c, V: View> ViewContext<'a, 'b, 'c, V> {
         F: 'static + FnMut(&mut V, bool, &mut ViewContext<V>),
     {
         let observer = self.weak_handle();
-        let window_id = self.window_id;
-        self.window_context
-            .observe_fullscreen(window_id, move |active, cx| {
-                if let Some(observer) = observer.upgrade(cx) {
-                    observer.update(cx, |observer, cx| {
-                        callback(observer, active, cx);
-                    });
-                    true
-                } else {
-                    false
-                }
-            })
+        self.window_context.observe_fullscreen(move |active, cx| {
+            if let Some(observer) = observer.upgrade(cx) {
+                observer.update(cx, |observer, cx| {
+                    callback(observer, active, cx);
+                });
+                true
+            } else {
+                false
+            }
+        })
     }
 
     pub fn observe_keystrokes<F>(&mut self, mut callback: F) -> Subscription
@@ -3311,10 +3243,8 @@ impl<'a, 'b, 'c, V: View> ViewContext<'a, 'b, 'c, V> {
             ) -> bool,
     {
         let observer = self.weak_handle();
-        let window_id = self.window_id;
-        self.window_context.observe_keystrokes(
-            window_id,
-            move |keystroke, result, handled_by, cx| {
+        self.window_context
+            .observe_keystrokes(move |keystroke, result, handled_by, cx| {
                 if let Some(observer) = observer.upgrade(cx) {
                     observer.update(cx, |observer, cx| {
                         callback(observer, keystroke, handled_by, result, cx);
@@ -3323,8 +3253,7 @@ impl<'a, 'b, 'c, V: View> ViewContext<'a, 'b, 'c, V> {
                 } else {
                     false
                 }
-            },
-        )
+            })
     }
 
     pub fn observe_window_bounds<F>(&mut self, mut callback: F) -> Subscription
@@ -3332,9 +3261,8 @@ impl<'a, 'b, 'c, V: View> ViewContext<'a, 'b, 'c, V> {
         F: 'static + FnMut(&mut V, WindowBounds, Uuid, &mut ViewContext<V>),
     {
         let observer = self.weak_handle();
-        let window_id = self.window_id;
         self.window_context
-            .observe_window_bounds(window_id, move |bounds, display, cx| {
+            .observe_window_bounds(move |bounds, display, cx| {
                 if let Some(observer) = observer.upgrade(cx) {
                     observer.update(cx, |observer, cx| {
                         callback(observer, bounds, display, cx);

crates/gpui/src/app/window.rs 🔗

@@ -15,8 +15,8 @@ use crate::{
     util::post_inc,
     Action, AnyView, AnyViewHandle, AnyWeakViewHandle, AppContext, Drawable, Effect, Entity,
     ModelContext, ModelHandle, MouseRegion, MouseRegionId, ParentId, ReadModel, ReadView,
-    SceneBuilder, UpdateModel, UpdateView, UpgradeViewHandle, View, ViewContext, ViewHandle,
-    WeakViewHandle, WindowInvalidation,
+    SceneBuilder, Subscription, UpdateModel, UpdateView, UpgradeViewHandle, View, ViewContext,
+    ViewHandle, WeakViewHandle, WindowInvalidation,
 };
 use anyhow::{anyhow, bail, Result};
 use collections::{HashMap, HashSet};
@@ -239,6 +239,75 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
         Some(result)
     }
 
+    pub(crate) fn observe_window_activation<F>(&mut self, callback: F) -> Subscription
+    where
+        F: 'static + FnMut(bool, &mut WindowContext) -> bool,
+    {
+        let window_id = self.window_id;
+        let subscription_id = post_inc(&mut self.next_subscription_id);
+        self.pending_effects
+            .push_back(Effect::WindowActivationObservation {
+                window_id,
+                subscription_id,
+                callback: Box::new(callback),
+            });
+        Subscription::WindowActivationObservation(
+            self.window_activation_observations
+                .subscribe(window_id, subscription_id),
+        )
+    }
+
+    pub(crate) fn observe_fullscreen<F>(&mut self, callback: F) -> Subscription
+    where
+        F: 'static + FnMut(bool, &mut WindowContext) -> bool,
+    {
+        let window_id = self.window_id;
+        let subscription_id = post_inc(&mut self.next_subscription_id);
+        self.pending_effects
+            .push_back(Effect::WindowFullscreenObservation {
+                window_id,
+                subscription_id,
+                callback: Box::new(callback),
+            });
+        Subscription::WindowActivationObservation(
+            self.window_activation_observations
+                .subscribe(window_id, subscription_id),
+        )
+    }
+
+    pub(crate) fn observe_window_bounds<F>(&mut self, callback: F) -> Subscription
+    where
+        F: 'static + FnMut(WindowBounds, Uuid, &mut WindowContext) -> bool,
+    {
+        let window_id = self.window_id;
+        let subscription_id = post_inc(&mut self.next_subscription_id);
+        self.pending_effects
+            .push_back(Effect::WindowBoundsObservation {
+                window_id,
+                subscription_id,
+                callback: Box::new(callback),
+            });
+        Subscription::WindowBoundsObservation(
+            self.window_bounds_observations
+                .subscribe(window_id, subscription_id),
+        )
+    }
+
+    pub fn observe_keystrokes<F>(&mut self, callback: F) -> Subscription
+    where
+        F: 'static
+            + FnMut(&Keystroke, &MatchResult, Option<&Box<dyn Action>>, &mut WindowContext) -> bool,
+    {
+        let window_id = self.window_id;
+        let subscription_id = post_inc(&mut self.next_subscription_id);
+        self.keystroke_observations
+            .add_callback(window_id, subscription_id, Box::new(callback));
+        Subscription::KeystrokeObservation(
+            self.keystroke_observations
+                .subscribe(window_id, subscription_id),
+        )
+    }
+
     /// Return keystrokes that would dispatch the given action on the given view.
     pub(crate) fn keystrokes_for_action(
         &mut self,

crates/vim/src/test/vim_test_context.rs 🔗

@@ -31,11 +31,9 @@ impl<'a> VimTestContext<'a> {
             });
         });
 
-        let window_id = cx.window_id;
-
         // Setup search toolbars and keypress hook
         cx.update_workspace(|workspace, cx| {
-            observe_keystrokes(window_id, cx);
+            observe_keystrokes(cx);
             workspace.active_pane().update(cx, |pane, cx| {
                 pane.toolbar().update(cx, |toolbar, cx| {
                     let buffer_search_bar = cx.add_view(BufferSearchBar::new);

crates/vim/src/vim.rs 🔗

@@ -16,6 +16,7 @@ use collections::CommandPaletteFilter;
 use editor::{Bias, Cancel, Editor, EditorMode};
 use gpui::{
     actions, impl_actions, AppContext, Subscription, ViewContext, ViewHandle, WeakViewHandle,
+    WindowContext,
 };
 use language::CursorShape;
 use motion::Motion;
@@ -95,8 +96,8 @@ pub fn init(cx: &mut AppContext) {
     .detach();
 }
 
-pub fn observe_keystrokes(window_id: usize, cx: &mut AppContext) {
-    cx.observe_keystrokes(window_id, |_keystroke, _result, handled_by, cx| {
+pub fn observe_keystrokes(cx: &mut WindowContext) {
+    cx.observe_keystrokes(|_keystroke, _result, handled_by, cx| {
         if let Some(handled_by) = handled_by {
             // Keystroke is handled by the vim system, so continue forward
             // Also short circuit if it is the special cancel action

crates/zed/src/zed.rs 🔗

@@ -333,8 +333,7 @@ pub fn initialize_workspace(
 
     auto_update::notify_of_any_new_update(cx.weak_handle(), cx);
 
-    let window_id = cx.window_id();
-    vim::observe_keystrokes(window_id, cx);
+    vim::observe_keystrokes(cx);
 
     cx.on_window_should_close(|workspace, cx| {
         if let Some(task) = workspace.close(&Default::default(), cx) {