From 3be8f6e98990f7e8a3af11400bbecaecddda336c Mon Sep 17 00:00:00 2001 From: Nick Senger Date: Tue, 10 May 2022 17:18:08 -0700 Subject: fix: prevent building overlay with stale layout --- lazy/src/component.rs | 36 +++++++++++++++++++++++++++++++++--- lazy/src/pure/component.rs | 40 ++++++++++++++++++++++++++++++---------- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/lazy/src/component.rs b/lazy/src/component.rs index 9e5937e9..06392c33 100644 --- a/lazy/src/component.rs +++ b/lazy/src/component.rs @@ -376,6 +376,38 @@ where let mut local_messages = Vec::new(); let mut local_shell = Shell::new(&mut local_messages); + if self + .instance + .state + .borrow() + .as_ref() + .and_then(|state| state.borrow_cache().as_ref()) + .and_then(|cache| cache.borrow_overlay().as_ref()) + .is_none() + { + let component = + self.instance.state.take().unwrap().into_heads().component; + + self.instance.state = RefCell::new(Some( + StateBuilder { + component, + message: PhantomData, + cache_builder: |state| { + Some( + CacheBuilder { + element: state.view(), + overlay_builder: |element| { + element.overlay(layout, renderer) + }, + } + .build(), + ) + }, + } + .build(), + )); + } + let event_status = self .with_overlay_mut_maybe(|overlay| { overlay.on_event( @@ -410,9 +442,7 @@ where Some( CacheBuilder { element: state.view(), - overlay_builder: |element| { - element.overlay(layout, renderer) - }, + overlay_builder: |_| None, } .build(), ) diff --git a/lazy/src/pure/component.rs b/lazy/src/pure/component.rs index 2971d2b7..bf6ff908 100644 --- a/lazy/src/pure/component.rs +++ b/lazy/src/pure/component.rs @@ -415,6 +415,35 @@ where let mut local_messages = Vec::new(); let mut local_shell = Shell::new(&mut local_messages); + if self + .overlay + .as_ref() + .and_then(|overlay| overlay.borrow_overlay().as_ref()) + .is_none() + { + let overlay = self.overlay.take().unwrap().into_heads(); + + self.overlay = Some( + OverlayBuilder { + instance: overlay.instance, + instance_ref_builder: |instance| instance.state.borrow(), + tree: overlay.tree, + types: PhantomData, + overlay_builder: |instance, tree| { + instance + .as_ref() + .unwrap() + .borrow_element() + .as_ref() + .unwrap() + .as_widget() + .overlay(&mut tree.children[0], layout, renderer) + }, + } + .build(), + ); + } + let event_status = self .with_overlay_mut_maybe(|overlay| { overlay.on_event( @@ -464,16 +493,7 @@ where instance_ref_builder: |instance| instance.state.borrow(), tree: overlay.tree, types: PhantomData, - overlay_builder: |instance, tree| { - instance - .as_ref() - .unwrap() - .borrow_element() - .as_ref() - .unwrap() - .as_widget() - .overlay(&mut tree.children[0], layout, renderer) - }, + overlay_builder: |_, _| None, } .build(), ); -- cgit From 4c98de0a53b9a59a3a03cee0c5d7ce34ac434067 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 13 May 2022 18:45:03 +0200 Subject: Revert "fix: prevent building overlay with stale layout" This reverts commit 3be8f6e98990f7e8a3af11400bbecaecddda336c. --- lazy/src/component.rs | 36 +++--------------------------------- lazy/src/pure/component.rs | 40 ++++++++++------------------------------ 2 files changed, 13 insertions(+), 63 deletions(-) diff --git a/lazy/src/component.rs b/lazy/src/component.rs index 06392c33..9e5937e9 100644 --- a/lazy/src/component.rs +++ b/lazy/src/component.rs @@ -376,38 +376,6 @@ where let mut local_messages = Vec::new(); let mut local_shell = Shell::new(&mut local_messages); - if self - .instance - .state - .borrow() - .as_ref() - .and_then(|state| state.borrow_cache().as_ref()) - .and_then(|cache| cache.borrow_overlay().as_ref()) - .is_none() - { - let component = - self.instance.state.take().unwrap().into_heads().component; - - self.instance.state = RefCell::new(Some( - StateBuilder { - component, - message: PhantomData, - cache_builder: |state| { - Some( - CacheBuilder { - element: state.view(), - overlay_builder: |element| { - element.overlay(layout, renderer) - }, - } - .build(), - ) - }, - } - .build(), - )); - } - let event_status = self .with_overlay_mut_maybe(|overlay| { overlay.on_event( @@ -442,7 +410,9 @@ where Some( CacheBuilder { element: state.view(), - overlay_builder: |_| None, + overlay_builder: |element| { + element.overlay(layout, renderer) + }, } .build(), ) diff --git a/lazy/src/pure/component.rs b/lazy/src/pure/component.rs index bf6ff908..2971d2b7 100644 --- a/lazy/src/pure/component.rs +++ b/lazy/src/pure/component.rs @@ -415,35 +415,6 @@ where let mut local_messages = Vec::new(); let mut local_shell = Shell::new(&mut local_messages); - if self - .overlay - .as_ref() - .and_then(|overlay| overlay.borrow_overlay().as_ref()) - .is_none() - { - let overlay = self.overlay.take().unwrap().into_heads(); - - self.overlay = Some( - OverlayBuilder { - instance: overlay.instance, - instance_ref_builder: |instance| instance.state.borrow(), - tree: overlay.tree, - types: PhantomData, - overlay_builder: |instance, tree| { - instance - .as_ref() - .unwrap() - .borrow_element() - .as_ref() - .unwrap() - .as_widget() - .overlay(&mut tree.children[0], layout, renderer) - }, - } - .build(), - ); - } - let event_status = self .with_overlay_mut_maybe(|overlay| { overlay.on_event( @@ -493,7 +464,16 @@ where instance_ref_builder: |instance| instance.state.borrow(), tree: overlay.tree, types: PhantomData, - overlay_builder: |_, _| None, + overlay_builder: |instance, tree| { + instance + .as_ref() + .unwrap() + .borrow_element() + .as_ref() + .unwrap() + .as_widget() + .overlay(&mut tree.children[0], layout, renderer) + }, } .build(), ); -- cgit From 296e157dcf2efe1ae52ae6cc35060b2f0cf212bf Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 13 May 2022 19:07:54 +0200 Subject: Relayout base layer when layout is invalidated from an overlay --- native/src/shell.rs | 5 ++++ native/src/user_interface.rs | 67 +++++++++++++++++++++++++++++--------------- 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/native/src/shell.rs b/native/src/shell.rs index 4a0aa9c6..b96d23e5 100644 --- a/native/src/shell.rs +++ b/native/src/shell.rs @@ -31,6 +31,11 @@ impl<'a, Message> Shell<'a, Message> { } } + /// Returns whether the current layout is invalid or not. + pub fn is_layout_invalid(&self) -> bool { + self.is_layout_invalid + } + /// Publish the given `Message` for an application to process it. pub fn publish(&mut self, message: Message) { self.messages.push(message); diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs index f80786aa..785ee56a 100644 --- a/native/src/user_interface.rs +++ b/native/src/user_interface.rs @@ -177,40 +177,61 @@ where clipboard: &mut dyn Clipboard, messages: &mut Vec, ) -> (State, Vec) { + use std::mem::ManuallyDrop; + let mut state = State::Updated; + let mut manual_overlay = ManuallyDrop::new( + self.root.overlay(Layout::new(&self.base), renderer), + ); - let (base_cursor, overlay_statuses) = if let Some(mut overlay) = - self.root.overlay(Layout::new(&self.base), renderer) - { + let (base_cursor, overlay_statuses) = if manual_overlay.is_some() { let bounds = self.bounds; + + let mut overlay = manual_overlay.as_mut().unwrap(); let mut layout = overlay.layout(renderer, bounds); + let mut event_statuses = Vec::new(); - let event_statuses = events - .iter() - .cloned() - .map(|event| { - let mut shell = Shell::new(messages); + for event in events.iter().cloned() { + let mut shell = Shell::new(messages); - let event_status = overlay.on_event( - event, - Layout::new(&layout), - cursor_position, - renderer, - clipboard, - &mut shell, + let event_status = overlay.on_event( + event, + Layout::new(&layout), + cursor_position, + renderer, + clipboard, + &mut shell, + ); + + event_statuses.push(event_status); + + if shell.is_layout_invalid() { + let _ = ManuallyDrop::into_inner(manual_overlay); + + self.base = renderer.layout( + &self.root, + &layout::Limits::new(Size::ZERO, self.bounds), + ); + + manual_overlay = ManuallyDrop::new( + self.root.overlay(Layout::new(&self.base), renderer), ); + if manual_overlay.is_none() { + break; + } + + overlay = manual_overlay.as_mut().unwrap(); + shell.revalidate_layout(|| { layout = overlay.layout(renderer, bounds); }); + } - if shell.are_widgets_invalid() { - state = State::Outdated; - } - - event_status - }) - .collect(); + if shell.are_widgets_invalid() { + state = State::Outdated; + } + } let base_cursor = if layout.bounds().contains(cursor_position) { // TODO: Type-safe cursor availability @@ -226,6 +247,8 @@ where (cursor_position, vec![event::Status::Ignored; events.len()]) }; + let _ = ManuallyDrop::into_inner(manual_overlay); + let event_statuses = events .iter() .cloned() -- cgit From ea389ac34c5a4929b7369da0f163ab6ae07bc000 Mon Sep 17 00:00:00 2001 From: Nick Senger Date: Fri, 13 May 2022 12:38:16 -0700 Subject: remove rebuild of component overlay from `on_event` --- lazy/src/component.rs | 4 +--- lazy/src/pure/component.rs | 11 +---------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/lazy/src/component.rs b/lazy/src/component.rs index 9e5937e9..2029c2a3 100644 --- a/lazy/src/component.rs +++ b/lazy/src/component.rs @@ -410,9 +410,7 @@ where Some( CacheBuilder { element: state.view(), - overlay_builder: |element| { - element.overlay(layout, renderer) - }, + overlay_builder: |_| None, } .build(), ) diff --git a/lazy/src/pure/component.rs b/lazy/src/pure/component.rs index 2971d2b7..b6e10054 100644 --- a/lazy/src/pure/component.rs +++ b/lazy/src/pure/component.rs @@ -464,16 +464,7 @@ where instance_ref_builder: |instance| instance.state.borrow(), tree: overlay.tree, types: PhantomData, - overlay_builder: |instance, tree| { - instance - .as_ref() - .unwrap() - .borrow_element() - .as_ref() - .unwrap() - .as_widget() - .overlay(&mut tree.children[0], layout, renderer) - }, + overlay_builder: |_, _| None, } .build(), ); -- cgit