From a195795978a9cbf16af54d55eba6d14cc5c51c76 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 22 Apr 2025 19:34:41 +0800 Subject: [PATCH] input: Refactor window.focused_input by use better way to ensure update. (#809) --- crates/story/src/input_story.rs | 14 ++++++++++++-- crates/ui/src/input/element.rs | 27 ++++++++++++++++++++++++++- crates/ui/src/input/input.rs | 11 +---------- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/crates/story/src/input_story.rs b/crates/story/src/input_story.rs index 051d0825..bf158bb1 100644 --- a/crates/story/src/input_story.rs +++ b/crates/story/src/input_story.rs @@ -9,7 +9,7 @@ use gpui_component::{ button::{Button, ButtonVariant, ButtonVariants as _}, h_flex, input::{InputEvent, TextInput}, - v_flex, FocusableCycle, Icon, IconName, Sizable, + v_flex, ContextModal, FocusableCycle, Icon, IconName, Root, Sizable, }; actions!(input_story, [Tab, TabPrev]); @@ -200,7 +200,7 @@ impl Focusable for InputStory { } impl Render for InputStory { - fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { + fn render(&mut self, window: &mut Window, cx: &mut Context) -> impl IntoElement { v_flex() .key_context(CONTEXT) .id("input-story") @@ -239,6 +239,16 @@ impl Render for InputStory { .max_w_md() .child(self.input_esc.clone()), ) + .child( + section("Focused Input") + .max_w_md() + .whitespace_normal() + .overflow_hidden() + .child(div().child(format!( + "Value: {:?}", + window.focused_input(cx).map(|input| input.read(cx).text()) + ))), + ) .child( h_flex() .items_center() diff --git a/crates/ui/src/input/element.rs b/crates/ui/src/input/element.rs index 8d6d929d..213ac517 100644 --- a/crates/ui/src/input/element.rs +++ b/crates/ui/src/input/element.rs @@ -5,7 +5,7 @@ use gpui::{ }; use smallvec::SmallVec; -use crate::ActiveTheme as _; +use crate::{ActiveTheme as _, ContextModal as _, Root}; use super::TextInput; @@ -502,6 +502,31 @@ impl Element for TextElement { cx, ); + // Set Root focused_input when self is focused + if focused { + let input_view = self.input.clone(); + if Root::read(window, cx).focused_input.as_ref() != Some(&input_view) { + Root::update(window, cx, |root, _, cx| { + root.focused_input = Some(input_view); + cx.notify(); + }); + } + } + + // And reset focused_input when next_frame start + + window.on_next_frame({ + let input_view = self.input.clone(); + move |window, cx| { + if !focused && Root::read(window, cx).focused_input.as_ref() == Some(&input_view) { + Root::update(window, cx, |root, _, cx| { + root.focused_input = None; + cx.notify(); + }); + } + } + }); + // Paint selections if let Some(path) = prepaint.selection_path.take() { window.paint_path(path, cx.theme().selection); diff --git a/crates/ui/src/input/input.rs b/crates/ui/src/input/input.rs index 490c16df..fca6fbe4 100644 --- a/crates/ui/src/input/input.rs +++ b/crates/ui/src/input/input.rs @@ -1478,12 +1478,7 @@ impl TextInput { self.focus_handle.is_focused(window) && self.blink_cursor.read(cx).visible() } - fn on_focus(&mut self, window: &mut Window, cx: &mut Context) { - let input_entity = cx.entity(); - Root::update(window, cx, |root, _, _| { - root.focused_input = Some(input_entity) - }); - + fn on_focus(&mut self, _: &mut Window, cx: &mut Context) { self.blink_cursor.update(cx, |cursor, cx| { cursor.start(cx); }); @@ -1491,10 +1486,6 @@ impl TextInput { } fn on_blur(&mut self, window: &mut Window, cx: &mut Context) { - Root::update(window, cx, |root, _, _| { - root.focused_input = None; - }); - self.unselect(window, cx); self.blink_cursor.update(cx, |cursor, cx| { cursor.stop(cx);