From 5a63419aa3431f493b62e33b597622570cb8d7ef Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sat, 21 Aug 2021 21:59:25 +0200 Subject: [PATCH] Bug fix: clicking the edge of a menu button would flicker the menu There was a very annoying bug where clicking the edge of a menu button would open the menu and immediately close it. --- egui/src/context.rs | 2 ++ egui/src/response.rs | 21 ++++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/egui/src/context.rs b/egui/src/context.rs index 2ae81b47..23eac2c4 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -159,6 +159,8 @@ impl CtxRef { enabled: bool, ) -> Response { let gap = 0.5; // Just to make sure we don't accidentally hover two things at once (a small eps should be sufficient). + + // Make it easier to click things: let interact_rect = rect.expand2( (0.5 * item_spacing - Vec2::splat(gap)) .at_least(Vec2::splat(0.0)) diff --git a/egui/src/response.rs b/egui/src/response.rs index 78d215ab..dff4404b 100644 --- a/egui/src/response.rs +++ b/egui/src/response.rs @@ -142,12 +142,23 @@ impl Response { /// `true` if there was a click *outside* this widget this frame. pub fn clicked_elsewhere(&self) -> bool { - // We do not use self.clicked(), because we want to catch all click within our frame, - // even if we aren't clickable. This is important for windows and such that should close - // then the user clicks elsewhere. + // We do not use self.clicked(), because we want to catch all clicks within our frame, + // even if we aren't clickable (or even enabled). + // This is important for windows and such that should close then the user clicks elsewhere. let pointer = &self.ctx.input().pointer; - if let Some(pos) = pointer.interact_pos() { - pointer.any_click() && !self.rect.contains(pos) + + if pointer.any_click() { + // We detect clicks/hover on a "interact_rect" that is slightly larger than + // self.rect. See Context::interact. + // This means we can be hovered and clicked even though `!self.rect.contains(pos)` is true, + // hence the extra complexity here. + if self.hovered() { + false + } else if let Some(pos) = pointer.interact_pos() { + !self.rect.contains(pos) + } else { + false // clicked without a pointer, weird + } } else { false }