From f493065376f74228edbe97143cef075f915d98f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Thu, 27 Nov 2025 04:29:24 +0100 Subject: [PATCH] Add explicit `Open` state to `tooltip` widget This allows us to properly invalidate layout. --- widget/src/tooltip.rs | 78 +++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/widget/src/tooltip.rs b/widget/src/tooltip.rs index 1502b94a..a5207ed1 100644 --- a/widget/src/tooltip.rs +++ b/widget/src/tooltip.rs @@ -228,47 +228,41 @@ where match (*state, cursor_position) { (State::Idle, Some(cursor_position)) => { - *state = State::Hovered { - cursor_position, - at: now, - }; + if self.delay == Duration::ZERO { + *state = State::Open { cursor_position }; + shell.invalidate_layout(); + } else { + *state = State::Hovered { at: now }; + } - shell.invalidate_layout(); shell.request_redraw_at(now + self.delay); } (State::Hovered { .. }, None) => { *state = State::Idle; - - shell.invalidate_layout(); } - (State::Hovered { at, .. }, Some(cursor_position)) - if at.elapsed() < self.delay => - { - *state = State::Hovered { - at, - cursor_position, - }; - + (State::Hovered { at, .. }, _) if at.elapsed() < self.delay => { shell.request_redraw_at(now + self.delay - at.elapsed()); } + (State::Hovered { .. }, Some(cursor_position)) => { + *state = State::Open { cursor_position }; + shell.invalidate_layout(); + } ( - State::Hovered { - at, + State::Open { cursor_position: last_position, }, Some(cursor_position), ) if self.position == Position::FollowCursor && last_position != cursor_position => { - *state = State::Hovered { - at, - cursor_position, - }; - + *state = State::Open { cursor_position }; shell.request_redraw(); } - (State::Hovered { .. }, Some(_)) => (), - (State::Idle, None) => (), + (State::Open { .. }, None) => { + *state = State::Idle; + shell.invalidate_layout(); + } + (State::Open { .. }, Some(_)) | (State::Idle, None) => (), } } @@ -342,25 +336,21 @@ where translation, ); - let tooltip = match *state { - State::Hovered { + let tooltip = if let State::Open { cursor_position } = *state { + Some(overlay::Element::new(Box::new(Overlay { + position: layout.position() + translation, + tooltip: &mut self.tooltip, + tree: children.next().unwrap(), cursor_position, - at, - } if at.elapsed() > self.delay => { - Some(overlay::Element::new(Box::new(Overlay { - position: layout.position() + translation, - tooltip: &mut self.tooltip, - tree: children.next().unwrap(), - cursor_position, - content_bounds: layout.bounds(), - snap_within_viewport: self.snap_within_viewport, - positioning: self.position, - gap: self.gap, - padding: self.padding, - class: &self.class, - }))) - } - _ => None, + content_bounds: layout.bounds(), + snap_within_viewport: self.snap_within_viewport, + positioning: self.position, + gap: self.gap, + padding: self.padding, + class: &self.class, + }))) + } else { + None }; if content.is_some() || tooltip.is_some() { @@ -411,9 +401,11 @@ enum State { #[default] Idle, Hovered { - cursor_position: Point, at: Instant, }, + Open { + cursor_position: Point, + }, } struct Overlay<'a, 'b, Message, Theme, Renderer>