From 493d5d0982765b99f5729780569421ac72f8b2f1 Mon Sep 17 00:00:00 2001 From: Matthias Kronberg Date: Wed, 22 Jan 2025 13:17:51 +0100 Subject: [PATCH] Fix hovering through custom menu button (#5555) This change discards widgets which are fully covered by another widget in a higher layer from the hit test algorithm. * Closes * [x] I have followed the instructions in the PR template --------- Co-authored-by: Emil Ernerfeldt --- crates/egui/src/hit_test.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/crates/egui/src/hit_test.rs b/crates/egui/src/hit_test.rs index 81c8abbb..910e558b 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