From 44e65e544f4f212f3e19268b46d14416c42f9766 Mon Sep 17 00:00:00 2001 From: temportalflux Date: Fri, 26 Jun 2026 11:06:01 -0400 Subject: [PATCH] rework focus handle semantics to only use Window::set_focus_handle during prepaint instead of requiring changes to Interactivity --- crates/gpui_elements/src/editable_text.rs | 4 ++++ .../gpui_elements/src/editable_text/element.rs | 18 +++++------------- .../gpui_elements/src/editable_text/state.rs | 1 - 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/crates/gpui_elements/src/editable_text.rs b/crates/gpui_elements/src/editable_text.rs index c7524e4bd6..2a22f1b115 100644 --- a/crates/gpui_elements/src/editable_text.rs +++ b/crates/gpui_elements/src/editable_text.rs @@ -17,6 +17,10 @@ //! Standard library strings are not ideal though for large text documents. For such uses, //! it is encouraged that implementers consider rolling their own [`UnicodeTextStorage`] medium. //! +//! Unlike other elements, editable text internally owns its [`FocusHandle`](gpui::FocusHandle). +//! This is required due to limitations of the [`Interactivity`](gpui::Interactivity) api and +//! that a user cannot interact with a text-input field if it cannot be focused. +//! //! ### Usage Samples //! //! A single-line text input with a fixed width and text that does not wrap diff --git a/crates/gpui_elements/src/editable_text/element.rs b/crates/gpui_elements/src/editable_text/element.rs index bbd6a295f7..35675f6470 100644 --- a/crates/gpui_elements/src/editable_text/element.rs +++ b/crates/gpui_elements/src/editable_text/element.rs @@ -267,12 +267,10 @@ impl Element for EditableTextElement { } }; - let focus_handle; let show_placeholder; let storage_version; { let state = state.read(cx); - focus_handle = state.focus_handle(cx); show_placeholder = state.storage().content_utf8().is_empty(); storage_version = state.storage().version(); @@ -282,16 +280,6 @@ impl Element for EditableTextElement { } } - // NOTE: Unlike other elements, a FocusHandle is owned by the state. - // This means the user is currently unable to provide a focus handle. - // This was born out of Interactivity not having a way to read the focus handle. - // This might be able to be eliminated entirely if focus handle can be passed thru on_mouse_down. - - // TODO: This required a gpui api change in order to sync the focus handle between Interactivity and TextInputStateBase - // maybe use `set_focus_handle` during prepaint? - //window.set_focus_handle(focus_handle, cx); - self.interactivity.track_focus(focus_handle); - let placeholder = self.placeholder.clone(); let placeholder_color = self.colors.placeholder; let supports_multiline = self.supports_multiline; @@ -472,7 +460,8 @@ impl Element for EditableTextElement { let is_focused = focus_handle.is_focused(window); let caret_visible = caret.update(cx, |caret, cx| caret.update_focus(is_focused, cx)); - let prepaint = self.interactivity().prepaint( + window.set_focus_handle(&focus_handle, cx); + let prepaint = self.interactivity.prepaint( global_id, inspector_id, bounds, @@ -546,6 +535,7 @@ impl Element for EditableTextElement { } window.on_mouse_event({ + let focus_handle = prepaint.focus_handle.clone(); let state = request_layout.clone(); move |event: &MouseDownEvent, phase, window, cx| { if phase != DispatchPhase::Bubble { @@ -558,6 +548,8 @@ impl Element for EditableTextElement { return; } + window.focus(&focus_handle, cx); + let text_position = event.position + to_local_position; state.update(cx, |state, cx| { state.on_mouse_down(event, text_position, window, cx); diff --git a/crates/gpui_elements/src/editable_text/state.rs b/crates/gpui_elements/src/editable_text/state.rs index 62a4c26802..4ddbd26c4a 100644 --- a/crates/gpui_elements/src/editable_text/state.rs +++ b/crates/gpui_elements/src/editable_text/state.rs @@ -1013,7 +1013,6 @@ impl<'app> EditableTextActionHandler> for EditableTextState ) { let caret_pos = self.index_for_pixel_point(text_position, window.line_height()); - window.focus(&self.focus_handle, cx); self.is_selecting = true; let is_same_position = self