diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 4c7c68942ed9d4d2e2df0971b0f541269afae7e8..5313cf66ab2128b937fc0109787b214577637017 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -37,14 +37,14 @@ pub use visual_test_context::*; use crate::InspectorElementRegistry; use crate::{ Action, ActionBuildError, ActionRegistry, Any, AnyView, AnyWindowHandle, AppContext, Arena, - Asset, AssetSource, BackgroundExecutor, Bounds, ClipboardItem, CursorStyle, DispatchPhase, - DisplayId, EventEmitter, FocusHandle, FocusMap, ForegroundExecutor, Global, KeyBinding, - KeyContext, Keymap, Keystroke, LayoutId, Menu, MenuItem, OwnedMenu, PathPromptOptions, Pixels, - Platform, PlatformDisplay, PlatformKeyboardLayout, PlatformKeyboardMapper, Point, Priority, - PromptBuilder, PromptButton, PromptHandle, PromptLevel, Render, RenderImage, - RenderablePromptHandle, Reservation, ScreenCaptureSource, SharedString, SubscriberSet, - Subscription, SvgRenderer, Task, TextRenderingMode, TextSystem, ThermalState, Window, - WindowAppearance, WindowHandle, WindowId, WindowInvalidator, + ArenaBox, Asset, AssetSource, BackgroundExecutor, Bounds, ClipboardItem, CursorStyle, + DispatchPhase, DisplayId, EventEmitter, FocusHandle, FocusMap, ForegroundExecutor, Global, + KeyBinding, KeyContext, Keymap, Keystroke, LayoutId, Menu, MenuItem, OwnedMenu, + PathPromptOptions, Pixels, Platform, PlatformDisplay, PlatformKeyboardLayout, + PlatformKeyboardMapper, Point, Priority, PromptBuilder, PromptButton, PromptHandle, + PromptLevel, Render, RenderImage, RenderablePromptHandle, Reservation, ScreenCaptureSource, + SharedString, SubscriberSet, Subscription, SvgRenderer, Task, TextRenderingMode, TextSystem, + ThermalState, Window, WindowAppearance, WindowHandle, WindowId, WindowInvalidator, colors::{Colors, GlobalColors}, current_platform, hash, init_app_menus, }; @@ -643,6 +643,8 @@ pub struct App { /// Per-App element arena. This isolates element allocations between different /// App instances (important for tests where multiple Apps run concurrently). pub(crate) element_arena: RefCell, + /// Per-App event arena. + pub(crate) event_arena: Arena, } impl App { @@ -722,6 +724,7 @@ impl App { #[cfg(any(test, feature = "test-support", debug_assertions))] name: None, element_arena: RefCell::new(Arena::new(1024 * 1024)), + event_arena: Arena::new(1024 * 1024), }), }); @@ -1340,7 +1343,7 @@ impl App { emitter, event_type, event, - } => self.apply_emit_effect(emitter, event_type, event), + } => self.apply_emit_effect(emitter, event_type, &*event), Effect::RefreshWindows => { self.apply_refresh_effect(); @@ -1377,6 +1380,7 @@ impl App { } if self.pending_effects.is_empty() { + self.event_arena.clear(); break; } } @@ -1434,12 +1438,12 @@ impl App { .retain(&emitter, |handler| handler(self)); } - fn apply_emit_effect(&mut self, emitter: EntityId, event_type: TypeId, event: Box) { + fn apply_emit_effect(&mut self, emitter: EntityId, event_type: TypeId, event: &dyn Any) { self.event_listeners .clone() .retain(&emitter, |(stored_type, handler)| { if *stored_type == event_type { - handler(event.as_ref(), self) + handler(event, self) } else { true } @@ -2407,7 +2411,7 @@ pub(crate) enum Effect { Emit { emitter: EntityId, event_type: TypeId, - event: Box, + event: ArenaBox, }, RefreshWindows, NotifyGlobalObservers { diff --git a/crates/gpui/src/app/context.rs b/crates/gpui/src/app/context.rs index e2902e48260c69fef9ff2bf77d674fa2ce338593..28d30ab37e7d7b502afc3f471416f2589380ce85 100644 --- a/crates/gpui/src/app/context.rs +++ b/crates/gpui/src/app/context.rs @@ -752,10 +752,14 @@ impl Context<'_, T> { T: EventEmitter, Evt: 'static, { + let event = self + .event_arena + .alloc(|| event) + .map(|it| it as &mut dyn Any); self.app.pending_effects.push_back(Effect::Emit { emitter: self.entity_state.entity_id, event_type: TypeId::of::(), - event: Box::new(event), + event, }); } }