From 50ccdf5c167897baf39a929f8ec714d053733631 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 11 Jan 2024 13:22:59 +0100 Subject: [PATCH] Reuse input handler when reusing a view tree --- crates/gpui/src/platform.rs | 2 +- crates/gpui/src/platform/mac/window.rs | 4 +- crates/gpui/src/platform/test/window.rs | 4 +- crates/gpui/src/window.rs | 86 ++++++++++++++++++------- 4 files changed, 67 insertions(+), 29 deletions(-) diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index c41bf998f698443d5b6ca93dee2966206596d533..5a2335919ebe6ff9b2277e02d4f6f55b4dc9a80c 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -145,7 +145,7 @@ pub trait PlatformWindow { fn modifiers(&self) -> Modifiers; fn as_any_mut(&mut self) -> &mut dyn Any; fn set_input_handler(&mut self, input_handler: Box); - fn clear_input_handler(&mut self); + fn take_input_handler(&mut self) -> Option>; fn prompt(&self, level: PromptLevel, msg: &str, answers: &[&str]) -> oneshot::Receiver; fn activate(&self); fn set_title(&mut self, title: &str); diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 7c96fc0198895ce426f483c2c03ce0c888df8d3c..534c43284078697333c6a7e95186160b13302ad6 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -770,8 +770,8 @@ impl PlatformWindow for MacWindow { self.0.as_ref().lock().input_handler = Some(input_handler); } - fn clear_input_handler(&mut self) { - self.0.as_ref().lock().input_handler = None; + fn take_input_handler(&mut self) -> Option> { + self.0.as_ref().lock().input_handler.take() } fn prompt(&self, level: PromptLevel, msg: &str, answers: &[&str]) -> oneshot::Receiver { diff --git a/crates/gpui/src/platform/test/window.rs b/crates/gpui/src/platform/test/window.rs index 029fd7300998f55f089696d6e01199b9c687ddfd..f05e13e3a027e2be9d4f17690fe7162a73396d03 100644 --- a/crates/gpui/src/platform/test/window.rs +++ b/crates/gpui/src/platform/test/window.rs @@ -167,8 +167,8 @@ impl PlatformWindow for TestWindow { self.0.lock().input_handler = Some(input_handler); } - fn clear_input_handler(&mut self) { - self.0.lock().input_handler = None; + fn take_input_handler(&mut self) -> Option> { + self.0.lock().input_handler.take() } fn prompt( diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index 3bdd8607c031008e161b64d607a6b41ff870f702..65f6aa42fffdaab131f4f9c96e65abb756ad5071 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -296,6 +296,11 @@ pub(crate) struct ElementStateBox { type_name: &'static str, } +struct RequestedInputHandler { + view_id: EntityId, + handler: Option>, +} + pub(crate) struct Frame { focus: Option, window_active: bool, @@ -308,6 +313,7 @@ pub(crate) struct Frame { pub(crate) next_stacking_order_id: u32, content_mask_stack: Vec>, element_offset_stack: Vec>, + requested_input_handler: Option, pub(crate) view_stack: Vec, pub(crate) reused_views: FxHashSet, } @@ -323,9 +329,10 @@ impl Frame { scene: Scene::default(), z_index_stack: StackingOrder::default(), next_stacking_order_id: 0, - depth_map: Default::default(), + depth_map: Vec::new(), content_mask_stack: Vec::new(), element_offset_stack: Vec::new(), + requested_input_handler: None, view_stack: Vec::new(), reused_views: FxHashSet::default(), } @@ -947,7 +954,7 @@ impl<'a> WindowContext<'a> { &mut self, mut handler: impl FnMut(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { - let view_id = self.parent_view_id().unwrap(); + let view_id = self.parent_view_id(); let order = self.window.next_frame.z_index_stack.clone(); self.window .next_frame @@ -1036,7 +1043,7 @@ impl<'a> WindowContext<'a> { /// Called during painting to track which z-index is on top at each pixel position pub fn add_opaque_layer(&mut self, bounds: Bounds) { let stacking_order = self.window.next_frame.z_index_stack.clone(); - let view_id = self.parent_view_id().unwrap(); + let view_id = self.parent_view_id(); self.window .next_frame .depth_map @@ -1093,7 +1100,7 @@ impl<'a> WindowContext<'a> { ) { let scale_factor = self.scale_factor(); let content_mask = self.content_mask(); - let view_id = self.parent_view_id().unwrap(); + let view_id = self.parent_view_id(); let window = &mut *self.window; for shadow in shadows { let mut shadow_bounds = bounds; @@ -1121,7 +1128,7 @@ impl<'a> WindowContext<'a> { pub fn paint_quad(&mut self, quad: PaintQuad) { let scale_factor = self.scale_factor(); let content_mask = self.content_mask(); - let view_id = self.parent_view_id().unwrap(); + let view_id = self.parent_view_id(); let window = &mut *self.window; window.next_frame.scene.insert( @@ -1144,7 +1151,7 @@ impl<'a> WindowContext<'a> { pub fn paint_path(&mut self, mut path: Path, color: impl Into) { let scale_factor = self.scale_factor(); let content_mask = self.content_mask(); - let view_id = self.parent_view_id().unwrap(); + let view_id = self.parent_view_id(); path.content_mask = content_mask; path.color = color.into(); @@ -1174,7 +1181,7 @@ impl<'a> WindowContext<'a> { size: size(width, height), }; let content_mask = self.content_mask(); - let view_id = self.parent_view_id().unwrap(); + let view_id = self.parent_view_id(); let window = &mut *self.window; window.next_frame.scene.insert( @@ -1231,7 +1238,7 @@ impl<'a> WindowContext<'a> { size: tile.bounds.size.map(Into::into), }; let content_mask = self.content_mask().scale(scale_factor); - let view_id = self.parent_view_id().unwrap(); + let view_id = self.parent_view_id(); let window = &mut *self.window; window.next_frame.scene.insert( &window.next_frame.z_index_stack, @@ -1284,7 +1291,7 @@ impl<'a> WindowContext<'a> { size: tile.bounds.size.map(Into::into), }; let content_mask = self.content_mask().scale(scale_factor); - let view_id = self.parent_view_id().unwrap(); + let view_id = self.parent_view_id(); let window = &mut *self.window; window.next_frame.scene.insert( @@ -1329,7 +1336,7 @@ impl<'a> WindowContext<'a> { Ok((params.size, Cow::Owned(bytes))) })?; let content_mask = self.content_mask().scale(scale_factor); - let view_id = self.parent_view_id().unwrap(); + let view_id = self.parent_view_id(); let window = &mut *self.window; window.next_frame.scene.insert( @@ -1368,7 +1375,7 @@ impl<'a> WindowContext<'a> { })?; let content_mask = self.content_mask().scale(scale_factor); let corner_radii = corner_radii.scale(scale_factor); - let view_id = self.parent_view_id().unwrap(); + let view_id = self.parent_view_id(); let window = &mut *self.window; window.next_frame.scene.insert( @@ -1392,7 +1399,7 @@ impl<'a> WindowContext<'a> { let scale_factor = self.scale_factor(); let bounds = bounds.scale(scale_factor); let content_mask = self.content_mask().scale(scale_factor); - let view_id = self.parent_view_id().unwrap(); + let view_id = self.parent_view_id(); let window = &mut *self.window; window.next_frame.scene.insert( &window.next_frame.z_index_stack, @@ -1408,14 +1415,27 @@ impl<'a> WindowContext<'a> { } pub(crate) fn reuse_view(&mut self) { - let view_id = self.parent_view_id().unwrap(); - let window = &mut self.window; - let grafted_view_ids = window + let view_id = self.parent_view_id(); + let grafted_view_ids = self + .window .next_frame .dispatch_tree - .graft(view_id, &mut window.rendered_frame.dispatch_tree); + .graft(view_id, &mut self.window.rendered_frame.dispatch_tree); for view_id in grafted_view_ids { - assert!(window.next_frame.reused_views.insert(view_id)); + assert!(self.window.next_frame.reused_views.insert(view_id)); + + // Reuse the previous input handler if it was associated with one of + // the views grafted from the tree in the previous frame. + if self + .window + .rendered_frame + .requested_input_handler + .as_ref() + .map_or(false, |requested| requested.view_id == view_id) + { + self.window.next_frame.requested_input_handler = + self.window.rendered_frame.requested_input_handler.take(); + } } } @@ -1430,7 +1450,11 @@ impl<'a> WindowContext<'a> { } self.text_system().start_frame(); - self.window.platform_window.clear_input_handler(); + if let Some(requested_handler) = self.window.rendered_frame.requested_input_handler.as_mut() + { + requested_handler.handler = self.window.platform_window.take_input_handler(); + } + self.window.layout_engine.as_mut().unwrap().clear(); self.window.next_frame.clear(); let root_view = self.window.root_view.take().unwrap(); @@ -1486,6 +1510,13 @@ impl<'a> WindowContext<'a> { .reuse_views(&mut self.window.rendered_frame); self.window.next_frame.scene.finish(); + // Register requested input handler with the platform window. + if let Some(requested_input) = self.window.next_frame.requested_input_handler.as_mut() { + if let Some(handler) = requested_input.handler.take() { + self.window.platform_window.set_input_handler(handler); + } + } + let previous_focus_path = self.window.rendered_frame.focus_path(); let previous_window_active = self.window.rendered_frame.window_active; mem::swap(&mut self.window.rendered_frame, &mut self.window.next_frame); @@ -2054,7 +2085,7 @@ impl<'a> WindowContext<'a> { result } else { let (result, state) = f(None, cx); - let parent_view_id = cx.parent_view_id().unwrap(); + let parent_view_id = cx.parent_view_id(); cx.window_mut() .next_frame .element_states @@ -2072,8 +2103,13 @@ impl<'a> WindowContext<'a> { }) } - fn parent_view_id(&self) -> Option { - self.window.next_frame.view_stack.last().copied() + fn parent_view_id(&self) -> EntityId { + *self + .window + .next_frame + .view_stack + .last() + .expect("a view should always be on the stack while drawing") } /// Set an input handler, such as [`ElementInputHandler`][element_input_handler], which interfaces with the @@ -2087,9 +2123,11 @@ impl<'a> WindowContext<'a> { input_handler: impl PlatformInputHandler, ) { if focus_handle.is_focused(self) { - self.window - .platform_window - .set_input_handler(Box::new(input_handler)); + let view_id = self.parent_view_id(); + self.window.next_frame.requested_input_handler = Some(RequestedInputHandler { + view_id, + handler: Some(Box::new(input_handler)), + }) } }