Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions crates/egui/src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,10 +724,9 @@ impl Response {
/// ```
#[must_use]
pub fn interact(&self, sense: Sense) -> Self {
if (self.sense | sense) == self.sense {
// Early-out: we already sense everything we need to sense.
return self.clone();
}
// We could check here if the new Sense equals the old one to avoid the extra create_widget
// call. But that would break calling `interact` on a response from `Context::read_response`
// or `Ui::response`. (See https://github.com/emilk/egui/pull/7713 for more details.)

self.ctx.create_widget(
WidgetRect {
Expand Down
45 changes: 44 additions & 1 deletion tests/egui_tests/tests/regression_tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use egui::accesskit::Role;
use egui::{Align, Color32, Image, Label, Layout, RichText, TextWrapMode, include_image};
use egui::{Align, Color32, Image, Label, Layout, RichText, Sense, TextWrapMode, include_image};
use egui_kittest::Harness;
use egui_kittest::kittest::Queryable as _;

Expand Down Expand Up @@ -75,3 +75,46 @@ fn combobox_should_have_value() {
Some("Option 1")
);
}

/// This test ensures that `ui.response().interact(...)` works correctly.
///
/// This was broken, because there was an optimization in [`egui::Response::interact`]
/// which caused the [`Sense`] of the original response to flip-flop between `click` and `hover`
/// between frames.
///
/// See <https://github.com/emilk/egui/pull/7713> for more details.
#[test]
fn interact_on_ui_response_should_be_stable() {
let mut first_frame = true;
let mut click_count = 0;
let mut harness = Harness::new_ui(|ui| {
let ui_response = ui.response();
if !first_frame {
assert!(
ui_response.sense.contains(Sense::click()),
"ui.response() didn't have click sense even though we called interact(Sense::click()) last frame"
);
}

// Add a label so we have something to click with kittest
ui.add(
Label::new("senseless label")
.sense(Sense::hover())
.selectable(false),
);

let click_response = ui_response.interact(Sense::click());
if click_response.clicked() {
click_count += 1;
}
first_frame = false;
});

for i in 0..=10 {
harness.run_steps(i);
harness.get_by_label("senseless label").click();
}

drop(harness);
assert_eq!(click_count, 10, "We missed some clicks!");
}
Loading