Consider all non-interactie widgets under the mouse pointer hovered (#4291)
At least all those above any interactive widget. * Closes https://github.com/emilk/egui/issues/4286 I feel there is still more thinking to be done about what is considered `hovered` and how it relates to `contains_pointer`, but this PR at least fixes tooltips for uninteractive widgets
This commit is contained in:
parent
21835c3176
commit
bb06befef1
|
|
@ -242,18 +242,39 @@ pub(crate) fn interact(
|
|||
.chain(&long_touched)
|
||||
.copied()
|
||||
.collect()
|
||||
} else if hits.click.is_some() || hits.drag.is_some() {
|
||||
// We are hovering over an interactive widget or two.
|
||||
hits.click.iter().chain(&hits.drag).map(|w| w.id).collect()
|
||||
} else {
|
||||
// Whatever is topmost is what we are hovering.
|
||||
// TODO(emilk): consider handle hovering over multiple top-most widgets?
|
||||
// TODO(emilk): allow hovering close widgets?
|
||||
hits.contains_pointer
|
||||
.last()
|
||||
.map(|w| w.id)
|
||||
.into_iter()
|
||||
.collect()
|
||||
// We may be hovering a an interactive widget or two.
|
||||
// We must also consider the case where non-interactive widgets
|
||||
// are _on top_ of an interactive widget.
|
||||
// For instance: a label in a draggable window.
|
||||
// In that case we want to hover _both_ widgets,
|
||||
// otherwise we won't see tooltips for the label.
|
||||
//
|
||||
// Because of how `Ui` work, we will often allocate the `Ui` rect
|
||||
// _after_ adding the children in it (once we know the size it will occopy)
|
||||
// so we will also have a lot of such `Ui` widgets rects covering almost any widget.
|
||||
//
|
||||
// So: we want to hover _all_ widgets above the interactive widget (if any),
|
||||
// but none below it (an interactive widget stops the hover search).
|
||||
//
|
||||
// To know when to stop we need to first know the order of the widgets,
|
||||
// which luckily we have in the `WidgetRects`.
|
||||
|
||||
let order = |id| widgets.order(id).map(|(_layer, order)| order); // we ignore the layer, since all widgets at this point is in the same layer
|
||||
|
||||
let click_order = hits.click.and_then(|w| order(w.id)).unwrap_or(0);
|
||||
let drag_order = hits.drag.and_then(|w| order(w.id)).unwrap_or(0);
|
||||
let top_interactive_order = click_order.max(drag_order);
|
||||
|
||||
let mut hovered: IdSet = hits.click.iter().chain(&hits.drag).map(|w| w.id).collect();
|
||||
|
||||
for w in &hits.contains_pointer {
|
||||
if top_interactive_order <= order(w.id).unwrap_or(0) {
|
||||
hovered.insert(w.id);
|
||||
}
|
||||
}
|
||||
|
||||
hovered
|
||||
};
|
||||
|
||||
InteractionSnapshot {
|
||||
|
|
|
|||
|
|
@ -72,6 +72,11 @@ impl WidgetRects {
|
|||
self.by_id.get(&id).map(|(_, w)| w)
|
||||
}
|
||||
|
||||
/// In which layer, and in which order in that layer?
|
||||
pub fn order(&self, id: Id) -> Option<(LayerId, usize)> {
|
||||
self.by_id.get(&id).map(|(idx, w)| (w.layer_id, *idx))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn contains(&self, id: Id) -> bool {
|
||||
self.by_id.contains_key(&id)
|
||||
|
|
|
|||
Loading…
Reference in New Issue