diff --git a/egui/src/context.rs b/egui/src/context.rs index 438f1e3a..9cff1ccd 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -108,11 +108,14 @@ impl CtxRef { /// If the given [`Id`] is not unique, an error will be printed at the given position. /// Call this for [`Id`]:s that need interaction or persistence. - pub(crate) fn register_interaction_id(&self, id: Id, new_pos: Pos2) { - let prev_pos = self.frame_state().used_ids.insert(id, new_pos); - if let Some(prev_pos) = prev_pos { - if prev_pos.distance(new_pos) < 0.1 { - // Likely same Widget being interacted with twice, which is fine. + pub(crate) fn register_interaction_id(&self, id: Id, new_rect: Rect) { + let prev_rect = self.frame_state().used_ids.insert(id, new_rect); + if let Some(prev_rect) = prev_rect { + // it is ok to reuse the same ID for e.g. a frame around a widget, + // or to check for interaction with the same widget twice: + if prev_rect.expand(0.1).contains_rect(new_rect) + || new_rect.expand(0.1).contains_rect(prev_rect) + { return; } @@ -132,11 +135,11 @@ impl CtxRef { let id_str = id.short_debug_format(); - if prev_pos.distance(new_pos) < 4.0 { - show_error(new_pos, format!("Double use of ID {}", id_str)); + if prev_rect.min.distance(new_rect.min) < 4.0 { + show_error(new_rect.min, format!("Double use of ID {}", id_str)); } else { - show_error(prev_pos, format!("First use of ID {}", id_str)); - show_error(new_pos, format!("Second use of ID {}", id_str)); + show_error(prev_rect.min, format!("First use of ID {}", id_str)); + show_error(new_rect.min, format!("Second use of ID {}", id_str)); } // TODO: a tooltip explaining this. @@ -218,7 +221,7 @@ impl CtxRef { response.clicked[PointerButton::Primary as usize] = true; } - self.register_interaction_id(id, rect.min); + self.register_interaction_id(id, rect); if sense.click || sense.drag { let mut memory = self.memory(); diff --git a/egui/src/frame_state.rs b/egui/src/frame_state.rs index 79b8d1f6..df932365 100644 --- a/egui/src/frame_state.rs +++ b/egui/src/frame_state.rs @@ -7,7 +7,7 @@ use epaint::ahash; pub(crate) struct FrameState { /// All `Id`s that were used this frame. /// Used to debug `Id` clashes of widgets. - pub(crate) used_ids: ahash::AHashMap, + pub(crate) used_ids: ahash::AHashMap, /// Starts off as the screen_rect, shrinks as panels are added. /// The `CentralPanel` does not change this. diff --git a/egui/src/memory.rs b/egui/src/memory.rs index e95cdb60..de74d160 100644 --- a/egui/src/memory.rs +++ b/egui/src/memory.rs @@ -230,7 +230,7 @@ impl Focus { } } - pub(crate) fn end_frame(&mut self, used_ids: &epaint::ahash::AHashMap) { + pub(crate) fn end_frame(&mut self, used_ids: &epaint::ahash::AHashMap) { if let Some(id) = self.id { // Allow calling `request_focus` one frame and not using it until next frame let recently_gained_focus = self.id_previous_frame != Some(id); @@ -284,7 +284,7 @@ impl Memory { pub(crate) fn end_frame( &mut self, input: &InputState, - used_ids: &epaint::ahash::AHashMap, + used_ids: &epaint::ahash::AHashMap, ) { self.areas.end_frame(); self.interaction.focus.end_frame(used_ids); diff --git a/egui/src/widgets/text_edit.rs b/egui/src/widgets/text_edit.rs index d88ce1ff..50a229cf 100644 --- a/egui/src/widgets/text_edit.rs +++ b/egui/src/widgets/text_edit.rs @@ -381,8 +381,14 @@ impl<'t, S: TextBuffer> Widget for TextEdit<'t, S> { let max_rect = ui.available_rect_before_wrap().shrink2(margin); let mut content_ui = ui.child_ui(max_rect, *ui.layout()); let response = self.content_ui(&mut content_ui); + let id = response.id; let frame_rect = response.rect.expand2(margin); - let response = response | ui.allocate_rect(frame_rect, Sense::hover()); + ui.allocate_rect(frame_rect, Sense::hover()); + let frame_response = ui.interact(frame_rect, id, Sense::click()); + let response = response | frame_response; + if response.clicked() { + ui.memory().request_focus(response.id); + } if frame { let visuals = ui.style().interact(&response);