diff --git a/crates/egui/src/input_state.rs b/crates/egui/src/input_state.rs index 1c0fe22f61c..ac6e6c5fa62 100644 --- a/crates/egui/src/input_state.rs +++ b/crates/egui/src/input_state.rs @@ -566,6 +566,10 @@ pub struct PointerState { /// Used to check for triple-clicks. last_last_click_time: f64, + /// When was the pointer last moved? + /// Used for things like showing hover ui/tooltip with a delay. + last_move_time: f64, + /// All button events that occurred this frame pub(crate) pointer_events: Vec, } @@ -585,6 +589,7 @@ impl Default for PointerState { has_moved_too_much_for_a_click: false, last_click_time: std::f64::NEG_INFINITY, last_last_click_time: std::f64::NEG_INFINITY, + last_move_time: std::f64::NEG_INFINITY, pointer_events: vec![], } } @@ -709,6 +714,9 @@ impl PointerState { } else { Vec2::default() }; + if self.velocity != Vec2::ZERO { + self.last_move_time = time; + } self } @@ -788,6 +796,12 @@ impl PointerState { self.velocity != Vec2::ZERO } + /// How long has it been (in seconds) since the pointer was last moved? + #[inline(always)] + pub fn time_since_last_movement(&self) -> f64 { + self.time - self.last_move_time + } + /// Was any pointer button pressed (`!down -> down`) this frame? /// This can sometimes return `true` even if `any_down() == false` /// because a press can be shorted than one frame. @@ -1033,6 +1047,7 @@ impl PointerState { last_click_time, last_last_click_time, pointer_events, + last_move_time, } = self; ui.label(format!("latest_pos: {latest_pos:?}")); @@ -1050,6 +1065,7 @@ impl PointerState { )); ui.label(format!("last_click_time: {last_click_time:#?}")); ui.label(format!("last_last_click_time: {last_last_click_time:#?}")); + ui.label(format!("last_move_time: {last_move_time:#?}")); ui.label(format!("pointer_events: {pointer_events:?}")); } } diff --git a/crates/egui/src/response.rs b/crates/egui/src/response.rs index bca858ef568..e95d07c204a 100644 --- a/crates/egui/src/response.rs +++ b/crates/egui/src/response.rs @@ -435,6 +435,15 @@ impl Response { } } + if !self.is_tooltip_open() + && self.ctx.input(|i| i.pointer.time_since_last_movement()) + < self.ctx.style().interaction.tooltip_delay + { + // Keep waiting until the mouse has been still for a while + self.ctx.request_repaint(); + return false; + } + // We don't want tooltips of things while we are dragging them, // but we do want tooltips while holding down on an item on a touch screen. if self diff --git a/crates/egui/src/style.rs b/crates/egui/src/style.rs index 4a8dba7c0d6..7c8494efba7 100644 --- a/crates/egui/src/style.rs +++ b/crates/egui/src/style.rs @@ -434,6 +434,9 @@ pub struct Interaction { /// If `false`, tooltips will show up anytime you hover anything, even is mouse is still moving pub show_tooltips_only_when_still: bool, + + /// Delay in seconds before showing tooltips after the mouse stops moving + pub tooltip_delay: f64, } /// Controls the visual style (colors etc) of egui. @@ -755,6 +758,7 @@ impl Default for Interaction { resize_grab_radius_side: 5.0, resize_grab_radius_corner: 10.0, show_tooltips_only_when_still: true, + tooltip_delay: 0.0, } } } @@ -1211,6 +1215,7 @@ impl Interaction { resize_grab_radius_side, resize_grab_radius_corner, show_tooltips_only_when_still, + tooltip_delay, } = self; ui.add(Slider::new(resize_grab_radius_side, 0.0..=20.0).text("resize_grab_radius_side")); ui.add( @@ -1220,6 +1225,7 @@ impl Interaction { show_tooltips_only_when_still, "Only show tooltips if mouse is still", ); + ui.add(Slider::new(tooltip_delay, 0.0..=1.0).text("tooltip_delay")); ui.vertical_centered(|ui| reset_button(ui, self)); }