diff options
| author | 2022-05-14 23:52:42 +0200 | |
|---|---|---|
| committer | 2022-05-14 23:52:42 +0200 | |
| commit | ba33e92818ec181508b4957d1eae5b2beb9ea221 (patch) | |
| tree | e7fe5a47206a09ba05f5b0962eb4dfb32510ab5d /native/src | |
| parent | 5de337f214530faab1d5fe47784afd7006c3f7f0 (diff) | |
| parent | ea389ac34c5a4929b7369da0f163ab6ae07bc000 (diff) | |
| download | iced-ba33e92818ec181508b4957d1eae5b2beb9ea221.tar.gz iced-ba33e92818ec181508b4957d1eae5b2beb9ea221.tar.bz2 iced-ba33e92818ec181508b4957d1eae5b2beb9ea221.zip | |
Merge pull request #1341 from nicksenger/fix/component-overlay-rebuild
fix: prevent building component overlay with stale layout
Diffstat (limited to '')
| -rw-r--r-- | native/src/shell.rs | 5 | ||||
| -rw-r--r-- | 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<Message>,      ) -> (State, Vec<event::Status>) { +        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() | 
