Avoid constant redraws when tooltip follows cursor

This commit is contained in:
Héctor Ramón Jiménez 2025-11-27 04:12:07 +01:00
parent 5ec23c1243
commit 77708f0574
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
2 changed files with 24 additions and 27 deletions

View file

@ -16,7 +16,7 @@ struct Tooltip {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
enum Message { enum Message {
ChangePosition, ChangePosition,
SetImmediate(bool), ToggleImmediate(bool),
} }
impl Tooltip { impl Tooltip {
@ -33,8 +33,7 @@ impl Tooltip {
self.position = position; self.position = position;
} }
Message::ToggleImmediate(is_immediate) => {
Message::SetImmediate(is_immediate) => {
self.is_immediate = is_immediate; self.is_immediate = is_immediate;
} }
} }
@ -56,12 +55,12 @@ impl Tooltip {
let checkbox = checkbox(self.is_immediate) let checkbox = checkbox(self.is_immediate)
.label("Show immediately") .label("Show immediately")
.on_toggle(Message::SetImmediate); .on_toggle(Message::ToggleImmediate);
center( center(
column![tooltip, checkbox] column![tooltip, checkbox]
.align_x(alignment::Horizontal::Center) .align_x(alignment::Horizontal::Center)
.spacing(7), .spacing(10),
) )
.into() .into()
} }

View file

@ -225,49 +225,47 @@ where
let now = Instant::now(); let now = Instant::now();
let cursor_position = cursor.position_over(layout.bounds()); let cursor_position = cursor.position_over(layout.bounds());
match (&state, cursor_position) { match (*state, cursor_position) {
// Tooltip was idle, but is now hovered.
(State::Idle, Some(cursor_position)) => { (State::Idle, Some(cursor_position)) => {
shell.invalidate_layout();
shell.request_redraw_at(now + self.delay);
*state = State::Hovered { *state = State::Hovered {
cursor_position, cursor_position,
at: now, at: now,
}; };
}
// Tooltip was active and isn't hovered anymore.
(State::Hovered { .. }, None) => {
shell.invalidate_layout(); shell.invalidate_layout();
shell.request_redraw(); shell.request_redraw_at(now + self.delay);
*state = State::Idle;
} }
(State::Hovered { .. }, None) => {
*state = State::Idle;
// Tooltip is active, but not for long enough. shell.invalidate_layout();
}
(State::Hovered { at, .. }, Some(cursor_position)) (State::Hovered { at, .. }, Some(cursor_position))
if at.elapsed() < self.delay => if at.elapsed() < self.delay =>
{ {
let when = now + self.delay - at.elapsed();
shell.request_redraw_at(when);
*state = State::Hovered { *state = State::Hovered {
at: *at, at,
cursor_position, cursor_position,
}; };
}
// Tooltip has been active long enough, and is following the cursor shell.request_redraw_at(now + self.delay - at.elapsed());
// (thus requiring a redraw) }
(State::Hovered { at, .. }, Some(cursor_position)) (
if self.position == Position::FollowCursor => State::Hovered {
at,
cursor_position: last_position,
},
Some(cursor_position),
) if self.position == Position::FollowCursor
&& last_position != cursor_position =>
{ {
shell.request_redraw();
*state = State::Hovered { *state = State::Hovered {
at: *at, at,
cursor_position, cursor_position,
}; };
}
// No change in state. shell.request_redraw();
}
(State::Hovered { .. }, Some(_)) => (), (State::Hovered { .. }, Some(_)) => (),
(State::Idle, None) => (), (State::Idle, None) => (),
} }