emilk / emilk/egui

`Response::interact(Sense::click())` not respecting widget layering in 0.26.x

Open
#4,147 5 comments 1 reaction 0 assignees View on GitHub
bug
Dominant language
Rust
Stars
30.6k
Forks
2.1k
Avg merge
1d 9h
Merged PRs (30d)
72

Description

**Describe the bug**
Scenario: Using `Response::interact(Sense::click())` to sense clicks on elements that are usually hover only, like egui::Frame, when that element also contains other ui elements.

Before 0.26.x (I checked with 0.25.0) this worked as expected, it was possible to load up the egui::Frame with other components like buttons, dropdowns, etc and still sense click anywhere else on the frame.

As of 0.26.1 `frame_response.interact(Sense::click()).clicked()` doesn't sense clicks.

As of 0.26.2 `frame_response.interact(Sense::click()).clicked()` senses clicks but steals them from any component added to the frame.

**To Reproduce**
Use the following example code and observer the click reactions to the button inside the frame, and clicking anywhere on the frame to toggle the outer set.
Replace `example/hello_world/main.rs` with the following code:
```Rust
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release

use eframe::egui;

fn main() -> Result<(), eframe::Error> {
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default().with_inner_size([320.0, 240.0]),
..Default::default()
};
eframe::run_native(
"My egui App",
options,
Box::new(|cc| {
// This gives us image support:
egui_extras::install_image_loaders(&cc.egui_ctx);

Box::::default()
}),
)
}
#[derive(Default)]
struct MyApp {
inner_set: bool,
frame_set: bool,
}

impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |ui| {
ui.label("outer: ");
if self.frame_set {
ui.label("SET");
} else {
ui.label("UNSET");
}

let frame_response = egui::Frame::popup(ui.style())
.fill(egui::Color32::LIGHT_YELLOW)
.show(ui, |ui| {
ui.label("Select my text");

ui.add_space(20.0);

ui.label("Click anywhere else on frame to toggle outer");

ui.horizontal(|ui| {
if ui.button("Toggle inner").clicked() {
self.inner_set = !self.inner_set;
}
if self.inner_set {
ui.label("SET");
} else {
ui.label("UNSET");
}
});
});

if frame_response
.response
.interact(egui::Sense::click())
.clicked()
{
self.frame_set = !self.frame_set;
}
});
}
}
```

**Expected behavior**
I expect it to work as it did in 0.25.0 and before, to sense clicks anywhere ELSE in the frame that does not also observe clicks.

**Screenshots**
I think the example is more graphic. Test the example with 0.25.0 to see how it used to work.

Contributor guide

Open the contributing guide

Research direction

Start by replacing example/hello_world/main.rs with the reproducer and compare its click behavior in egui 0.25.0, 0.26.1, and 0.26.2. Trace Response::interact(Sense::click()) and widget event layering to understand why clicks are missed or stolen; done means inner buttons still receive clicks while the surrounding frame senses clicks elsewhere.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.