diff --git a/crates/gpui3/src/app.rs b/crates/gpui3/src/app.rs index cb187d0343..526ed6d2b3 100644 --- a/crates/gpui3/src/app.rs +++ b/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>, - pub(crate) pending_effects: VecDeque, + pub(crate) pending_notifications: HashSet, + pending_effects: VecDeque, pub(crate) observers: SubscriberSet, pub(crate) event_handlers: SubscriberSet, pub(crate) release_handlers: SubscriberSet, @@ -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)); diff --git a/crates/gpui3/src/app/model_context.rs b/crates/gpui3/src/app/model_context.rs index 82175f9a27..4b77099cb1 100644 --- a/crates/gpui3/src/app/model_context.rs +++ b/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), }); diff --git a/crates/gpui3/src/window.rs b/crates/gpui3/src/window.rs index 40942e08b9..c05d4fd6f1 100644 --- a/crates/gpui3/src/window.rs +++ b/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( @@ -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), });