Checkpoint

Antonio Scandurra created

Change summary

crates/gpui3/src/app.rs               | 18 ++++++++++++++++--
crates/gpui3/src/app/model_context.rs |  4 ++--
crates/gpui3/src/window.rs            | 11 ++++-------
3 files changed, 22 insertions(+), 11 deletions(-)

Detailed changes

crates/gpui3/src/app.rs 🔗

@@ -13,7 +13,7 @@ use crate::{
     TextStyleRefinement, TextSystem, Window, WindowContext, WindowHandle, WindowId,
 };
 use anyhow::{anyhow, Result};
-use collections::{HashMap, VecDeque};
+use collections::{HashMap, HashSet, VecDeque};
 use futures::Future;
 use parking_lot::Mutex;
 use slotmap::SlotMap;
@@ -64,6 +64,7 @@ impl App {
                 unit_entity,
                 entities,
                 windows: SlotMap::with_key(),
+                pending_notifications: Default::default(),
                 pending_effects: Default::default(),
                 observers: SubscriberSet::new(),
                 event_handlers: SubscriberSet::new(),
@@ -106,7 +107,8 @@ pub struct AppContext {
     pub(crate) unit_entity: Handle<()>,
     pub(crate) entities: EntityMap,
     pub(crate) windows: SlotMap<WindowId, Option<Window>>,
-    pub(crate) pending_effects: VecDeque<Effect>,
+    pub(crate) pending_notifications: HashSet<EntityId>,
+    pending_effects: VecDeque<Effect>,
     pub(crate) observers: SubscriberSet<EntityId, Handler>,
     pub(crate) event_handlers: SubscriberSet<EntityId, EventHandler>,
     pub(crate) release_handlers: SubscriberSet<EntityId, ReleaseHandler>,
@@ -148,6 +150,17 @@ impl AppContext {
         })
     }
 
+    pub(crate) fn push_effect(&mut self, effect: Effect) {
+        match &effect {
+            Effect::Notify { emitter } => {
+                if self.pending_notifications.insert(*emitter) {
+                    self.pending_effects.push_back(effect);
+                }
+            }
+            Effect::Emit { .. } => self.pending_effects.push_back(effect),
+        }
+    }
+
     fn flush_effects(&mut self) {
         loop {
             self.release_dropped_entities();
@@ -197,6 +210,7 @@ impl AppContext {
     }
 
     fn apply_notify_effect(&mut self, emitter: EntityId) {
+        self.pending_notifications.remove(&emitter);
         self.observers
             .clone()
             .retain(&emitter, |handler| handler(self));

crates/gpui3/src/app/model_context.rs 🔗

@@ -116,7 +116,7 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
     }
 
     pub fn notify(&mut self) {
-        self.app.pending_effects.push_back(Effect::Notify {
+        self.app.push_effect(Effect::Notify {
             emitter: self.entity_id,
         });
     }
@@ -124,7 +124,7 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
 
 impl<'a, T: EventEmitter + Send + Sync + 'static> ModelContext<'a, T> {
     pub fn emit(&mut self, event: T::Event) {
-        self.app.pending_effects.push_back(Effect::Emit {
+        self.app.push_effect(Effect::Emit {
             emitter: self.entity_id,
             event: Box::new(event),
         });

crates/gpui3/src/window.rs 🔗

@@ -997,12 +997,9 @@ impl<'a, 'w, S: Send + Sync + 'static> ViewContext<'a, 'w, S> {
 
     pub fn notify(&mut self) {
         self.window_cx.notify();
-        self.window_cx
-            .app
-            .pending_effects
-            .push_back(Effect::Notify {
-                emitter: self.entity_id,
-            });
+        self.window_cx.app.push_effect(Effect::Notify {
+            emitter: self.entity_id,
+        });
     }
 
     pub fn run_on_main<R>(
@@ -1052,7 +1049,7 @@ impl<'a, 'w, S: Send + Sync + 'static> ViewContext<'a, 'w, S> {
 
 impl<'a, 'w, S: EventEmitter + Send + Sync + 'static> ViewContext<'a, 'w, S> {
     pub fn emit(&mut self, event: S::Event) {
-        self.window_cx.app.pending_effects.push_back(Effect::Emit {
+        self.window_cx.app.push_effect(Effect::Emit {
             emitter: self.entity_id,
             event: Box::new(event),
         });