diff --git a/crates/egui/src/hit_test.rs b/crates/egui/src/hit_test.rs index 81c8abbb87c..910e558b984 100644 --- a/crates/egui/src/hit_test.rs +++ b/crates/egui/src/hit_test.rs @@ -2,7 +2,7 @@ use ahash::HashMap; use emath::TSTransform; -use crate::{ahash, emath, LayerId, Pos2, Rect, Sense, WidgetRect, WidgetRects}; +use crate::{ahash, emath, id::IdSet, LayerId, Pos2, Rect, Sense, WidgetRect, WidgetRects}; /// Result of a hit-test against [`WidgetRects`]. /// @@ -133,6 +133,23 @@ pub fn hit_test( } } + // Find widgets which are hidden behind another widget and discard them. + // This is the case when a widget fully contains another widget and is on a different layer. + // It prevents "hovering through" widgets when there is a clickable widget behind. + + let mut hidden = IdSet::default(); + for (i, current) in close.iter().enumerate().rev() { + for next in &close[i + 1..] { + if next.interact_rect.contains_rect(current.interact_rect) + && current.layer_id != next.layer_id + { + hidden.insert(current.id); + } + } + } + + close.retain(|c| !hidden.contains(&c.id)); + let mut hits = hit_test_on_close(&close, pos); hits.contains_pointer = close