diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index 8e09414a6bef..232cca3859e6 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -1018,12 +1018,7 @@ impl Context { /// /// If the widget already exists, its state (sense, Rect, etc) will be updated. #[allow(clippy::too_many_arguments)] - pub(crate) fn create_widget(&self, mut w: WidgetRect) -> Response { - if !w.enabled { - w.sense.click = false; - w.sense.drag = false; - } - + pub(crate) fn create_widget(&self, w: WidgetRect) -> Response { // Remember this widget self.write(|ctx| { let viewport = ctx.viewport(); @@ -1130,7 +1125,8 @@ impl Context { let input = &viewport.input; let memory = &mut ctx.memory; - if sense.click + if enabled + && sense.click && memory.has_focus(id) && (input.key_pressed(Key::Space) || input.key_pressed(Key::Enter)) { @@ -1139,7 +1135,10 @@ impl Context { } #[cfg(feature = "accesskit")] - if sense.click && input.has_accesskit_action_request(id, accesskit::Action::Default) { + if enabled + && sense.click + && input.has_accesskit_action_request(id, accesskit::Action::Default) + { res.clicked[PointerButton::Primary as usize] = true; } @@ -1159,7 +1158,7 @@ impl Context { for pointer_event in &input.pointer.pointer_events { if let PointerEvent::Released { click, button } = pointer_event { - if sense.click && clicked { + if enabled && sense.click && clicked { if let Some(click) = click { res.clicked[*button as usize] = true; res.double_clicked[*button as usize] = click.is_double(); diff --git a/crates/egui/src/hit_test.rs b/crates/egui/src/hit_test.rs index 2b778e9d719a..62a762aa52d1 100644 --- a/crates/egui/src/hit_test.rs +++ b/crates/egui/src/hit_test.rs @@ -78,6 +78,16 @@ pub fn hit_test( let top_layer = closest_hit.layer_id; close.retain(|w| w.layer_id == top_layer); + // If the widget is disabled, treat it as if it isn't sensing anything. + // This simplifies the code in `hit_test_on_close` so it doesn't have to check + // the `enabled` flag everywhere: + for w in &mut close { + if !w.enabled { + w.sense.click = false; + w.sense.drag = false; + } + } + let pos_in_layer = pos_in_layers.get(&top_layer).copied().unwrap_or(pos); let hits = hit_test_on_close(&close, pos_in_layer); diff --git a/crates/egui/src/interaction.rs b/crates/egui/src/interaction.rs index 2f1925c7528c..20d54887018f 100644 --- a/crates/egui/src/interaction.rs +++ b/crates/egui/src/interaction.rs @@ -161,18 +161,20 @@ pub(crate) fn interact( if dragged.is_none() { // Check if we started dragging something new: if let Some(widget) = interaction.potential_drag_id.and_then(|id| widgets.get(id)) { - let is_dragged = if widget.sense.click && widget.sense.drag { - // This widget is sensitive to both clicks and drags. - // When the mouse first is pressed, it could be either, - // so we postpone the decision until we know. - input.pointer.is_decidedly_dragging() - } else { - // This widget is just sensitive to drags, so we can mark it as dragged right away: - widget.sense.drag - }; - - if is_dragged { - dragged = Some(widget.id); + if widget.enabled { + let is_dragged = if widget.sense.click && widget.sense.drag { + // This widget is sensitive to both clicks and drags. + // When the mouse first is pressed, it could be either, + // so we postpone the decision until we know. + input.pointer.is_decidedly_dragging() + } else { + // This widget is just sensitive to drags, so we can mark it as dragged right away: + widget.sense.drag + }; + + if is_dragged { + dragged = Some(widget.id); + } } } } diff --git a/crates/egui/src/response.rs b/crates/egui/src/response.rs index a34ed8fa782a..ddd683c4c8f6 100644 --- a/crates/egui/src/response.rs +++ b/crates/egui/src/response.rs @@ -42,6 +42,13 @@ pub struct Response { pub interact_rect: Rect, /// The senses (click and/or drag) that the widget was interested in (if any). + /// + /// Note: if [`Self::enabled`] is `false`, then + /// the widget _effectively_ doesn't sense anything, + /// but can still have the same `Sense`. + /// This is because the sense informs the styling of the widget, + /// but we don't want to change the style when a widget is disabled + /// (that is handled by the `Painter` directly). pub sense: Sense, /// Was the widget enabled? diff --git a/crates/egui/src/widget_rect.rs b/crates/egui/src/widget_rect.rs index acf3dd95df50..ab95447e1fd2 100644 --- a/crates/egui/src/widget_rect.rs +++ b/crates/egui/src/widget_rect.rs @@ -29,6 +29,13 @@ pub struct WidgetRect { pub interact_rect: Rect, /// How the widget responds to interaction. + /// + /// Note: if [`Self::enabled`] is `false`, then + /// the widget _effectively_ doesn't sense anything, + /// but can still have the same `Sense`. + /// This is because the sense informs the styling of the widget, + /// but we don't want to change the style when a widget is disabled + /// (that is handled by the `Painter` directly). pub sense: Sense, /// Is the widget enabled?