Skip to content

Commit

Permalink
Refactor Response to use bit set
Browse files Browse the repository at this point in the history
  • Loading branch information
polwel committed Jan 1, 2025
1 parent 3ffe1ed commit d1fc9ca
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 161 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1260,6 +1260,7 @@ dependencies = [
"accesskit",
"ahash",
"backtrace",
"bitflags 2.6.0",
"document-features",
"emath",
"epaint",
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ ahash = { version = "0.8.11", default-features = false, features = [
"std",
] }
backtrace = "0.3"
bitflags = "2.6"
bytemuck = "1.7.2"
criterion = { version = "0.5.1", default-features = false }
dify = { version = "0.7", default-features = false }
Expand Down
1 change: 1 addition & 0 deletions crates/egui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ emath = { workspace = true, default-features = false }
epaint = { workspace = true, default-features = false }

ahash.workspace = true
bitflags.workspace = true
nohash-hasher.workspace = true
profiling.workspace = true

Expand Down
79 changes: 46 additions & 33 deletions crates/egui/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::{
os::OperatingSystem,
output::FullOutput,
pass_state::PassState,
resize, scroll_area,
resize, response, scroll_area,
util::IdTypeMap,
viewport::ViewportClass,
Align2, CursorIcon, DeferredViewportUiCallback, FontDefinitions, Grid, Id, ImmediateViewport,
Expand Down Expand Up @@ -1213,7 +1213,7 @@ impl Context {
#[deprecated = "Use Response.contains_pointer or Context::read_response instead"]
pub fn widget_contains_pointer(&self, id: Id) -> bool {
self.read_response(id)
.map_or(false, |response| response.contains_pointer)
.map_or(false, |response| response.contains_pointer())
}

/// Do all interaction for an existing widget, without (re-)registering it.
Expand All @@ -1237,26 +1237,21 @@ impl Context {
rect,
interact_rect,
sense,
enabled,
contains_pointer: false,
hovered: false,
highlighted,
clicked: false,
fake_primary_click: false,
long_touched: false,
drag_started: false,
dragged: false,
drag_stopped: false,
is_pointer_button_down_on: false,
flags: response::Flags::empty(),
interact_pointer_pos: None,
changed: false,
intrinsic_size: None,
};

res.flags.set(response::Flags::ENABLED, enabled);
res.flags.set(response::Flags::HIGHLIGHTED, highlighted);

self.write(|ctx| {
let viewport = ctx.viewports.entry(ctx.viewport_id()).or_default();

res.contains_pointer = viewport.interact_widgets.contains_pointer.contains(&id);
res.flags.set(
response::Flags::CONTAINS_POINTER,
viewport.interact_widgets.contains_pointer.contains(&id),
);

let input = &viewport.input;
let memory = &mut ctx.memory;
Expand All @@ -1267,31 +1262,46 @@ impl Context {
&& (input.key_pressed(Key::Space) || input.key_pressed(Key::Enter))
{
// Space/enter works like a primary click for e.g. selected buttons
res.fake_primary_click = true;
res.flags.set(response::Flags::FAKE_PRIMARY_CLICKED, true);
}

#[cfg(feature = "accesskit")]
if enabled
&& sense.click
&& input.has_accesskit_action_request(id, accesskit::Action::Click)
{
res.fake_primary_click = true;
res.flags.set(response::Flags::FAKE_PRIMARY_CLICKED, true);
}

if enabled && sense.click && Some(id) == viewport.interact_widgets.long_touched {
res.long_touched = true;
res.flags.set(response::Flags::LONG_TOUCHED, true);
}

let interaction = memory.interaction();

res.is_pointer_button_down_on = interaction.potential_click_id == Some(id)
|| interaction.potential_drag_id == Some(id);
res.flags.set(
response::Flags::IS_POINTER_BUTTON_DOWN_ON,
interaction.potential_click_id == Some(id)
|| interaction.potential_drag_id == Some(id),
);

if res.enabled {
res.hovered = viewport.interact_widgets.hovered.contains(&id);
res.dragged = Some(id) == viewport.interact_widgets.dragged;
res.drag_started = Some(id) == viewport.interact_widgets.drag_started;
res.drag_stopped = Some(id) == viewport.interact_widgets.drag_stopped;
if res.enabled() {
res.flags.set(
response::Flags::HOVERED,
viewport.interact_widgets.hovered.contains(&id),
);
res.flags.set(
response::Flags::DRAGGED,
Some(id) == viewport.interact_widgets.dragged,
);
res.flags.set(
response::Flags::DRAG_STARTED,
Some(id) == viewport.interact_widgets.drag_started,
);
res.flags.set(
response::Flags::DRAG_STOPPED,
Some(id) == viewport.interact_widgets.drag_stopped,
);
}

let clicked = Some(id) == viewport.interact_widgets.clicked;
Expand All @@ -1305,19 +1315,22 @@ impl Context {
}
PointerEvent::Released { click, .. } => {
if enabled && sense.click && clicked && click.is_some() {
res.clicked = true;
res.flags.set(response::Flags::CLICKED, true);
}

res.is_pointer_button_down_on = false;
res.dragged = false;
res.flags
.set(response::Flags::IS_POINTER_BUTTON_DOWN_ON, false);
res.flags.set(response::Flags::DRAGGED, false);
}
}
}

// is_pointer_button_down_on is false when released, but we want interact_pointer_pos
// to still work.
let is_interacted_with =
res.is_pointer_button_down_on || res.long_touched || clicked || res.drag_stopped;
let is_interacted_with = res.is_pointer_button_down_on()
|| res.long_touched()
|| clicked
|| res.drag_stopped();
if is_interacted_with {
res.interact_pointer_pos = input.pointer.interact_pos();
if let (Some(to_global), Some(pos)) = (
Expand All @@ -1330,10 +1343,10 @@ impl Context {

if input.pointer.any_down() && !is_interacted_with {
// We don't hover widgets while interacting with *other* widgets:
res.hovered = false;
res.flags.set(response::Flags::HOVERED, false);
}

let pointer_pressed_elsewhere = any_press && !res.hovered;
let pointer_pressed_elsewhere = any_press && !res.hovered();
if pointer_pressed_elsewhere && memory.has_focus(id) {
memory.surrender_focus(id);
}
Expand Down Expand Up @@ -3131,7 +3144,7 @@ impl Context {
// TODO(emilk): `Sense::hover_highlight()`
let response =
ui.add(Label::new(RichText::new(text).monospace()).sense(Sense::click()));
if response.hovered && is_visible {
if response.hovered() && is_visible {
ui.ctx()
.debug_painter()
.debug_rect(area.rect(), Color32::RED, "");
Expand Down
Loading

0 comments on commit d1fc9ca

Please sign in to comment.