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

View file

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