From 73446cdafc99d45a5b7c1eb8ba179e4201c22900 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Fri, 24 Oct 2025 13:58:54 -0400 Subject: [PATCH] fix: focus find on window focus if text box did not have focus --- src/main.rs | 37 +++++++++++++++++++++++++++++++++---- src/text_box.rs | 21 +++++++++++++++++++++ 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 7324257..5e98415 100644 --- a/src/main.rs +++ b/src/main.rs @@ -351,6 +351,7 @@ pub enum Message { DialogMessage(DialogMessage), Find(Option), FindCaseSensitive(bool), + FindFocused(bool), FindNext, FindPrevious, FindReplace, @@ -466,7 +467,7 @@ pub struct App { auto_scroll: Option, dialog_opt: Option>, dialog_page_opt: Option, - find_opt: Option, + find_opt: Option, find_replace_id: widget::Id, find_replace_value: String, find_search_id: widget::Id, @@ -480,6 +481,12 @@ pub struct App { modifiers: Modifiers, } +#[derive(Debug, Clone, Copy)] +struct FindField { + replace: bool, + has_focus: bool, +} + impl App { pub fn active_tab(&self) -> Option<&Tab> { self.tab_model.active_data() @@ -780,7 +787,12 @@ impl App { } _ => Task::none(), } - } else if self.find_opt.is_some() { + } else if self.find_opt.is_some_and( + |FindField { + replace: _, + has_focus, + }| has_focus, + ) { widget::text_input::focus(self.find_search_id.clone()) } else { widget::text_input::focus(self.text_box_id.clone()) @@ -1811,7 +1823,10 @@ impl Application for App { } } Message::Find(find_opt) => { - self.find_opt = find_opt; + self.find_opt = find_opt.map(|f| FindField { + replace: f, + has_focus: true, + }); // Focus correct input return self.update_focus(); @@ -1938,6 +1953,14 @@ impl Application for App { config_set!(find_wrap_around, find_wrap_around); return self.update_config(); } + Message::FindFocused(has_focus) => { + if let Some(f) = self.find_opt.as_mut() { + *f = FindField { + replace: f.replace, + has_focus, + }; + } + } Message::GitProjectStatus(project_status) => { self.git_project_status = Some(project_status); } @@ -2809,6 +2832,7 @@ impl Application for App { Some(Tab::Editor(tab)) => { let mut text_box = text_box(&tab.editor, self.config.metrics(tab.zoom_adj())) .id(self.text_box_id.clone()) + .on_focus(Message::FindFocused(false)) .on_auto_scroll(Message::AutoScroll) .on_changed(Message::TabChanged(tab_id)) .has_context_menu(tab.context_menu.is_some()) @@ -2918,7 +2942,11 @@ impl Application for App { None => {} } - if let Some(replace) = &self.find_opt { + if let Some(FindField { + replace, + has_focus: _, + }) = &self.find_opt + { let find_input = widget::text_input::text_input(fl!("find-placeholder"), &self.find_search_value) .id(self.find_search_id.clone()) @@ -2930,6 +2958,7 @@ impl Application for App { Message::FindNext } }) + .on_focus(Message::FindFocused(true)) .width(Length::Fixed(320.0)) .trailing_icon( button::custom(icon_cache_get("edit-clear-symbolic", 16)) diff --git a/src/text_box.rs b/src/text_box.rs index d409974..c0cd7ff 100644 --- a/src/text_box.rs +++ b/src/text_box.rs @@ -44,6 +44,7 @@ pub struct TextBox<'a, Message> { padding: Padding, on_auto_scroll: Option) -> Message + 'a>>, on_changed: Option, + on_focus: Option, click_timing: Duration, has_context_menu: bool, on_context_menu: Option) -> Message + 'a>>, @@ -63,6 +64,7 @@ where padding: Padding::new(0.0), on_auto_scroll: None, on_changed: None, + on_focus: None, click_timing: Duration::from_millis(500), has_context_menu: false, on_context_menu: None, @@ -118,6 +120,11 @@ where self.line_numbers = true; self } + + pub fn on_focus(mut self, on_focus: Message) -> Self { + self.on_focus = Some(on_focus); + self + } } pub fn text_box<'a, Message>( @@ -948,6 +955,13 @@ where } } + if let Some(on_focus) = self.on_focus.as_ref() + && state.emit_focus + { + state.emit_focus = false; + shell.publish(on_focus.clone()); + } + let mut status = Status::Ignored; match event { Event::Keyboard(KeyEvent::KeyPressed { @@ -1034,6 +1048,10 @@ where if let Some(p) = cursor_position.position_in(layout.bounds()) { state.is_focused = true; + if let Some(on_focus) = self.on_focus.as_ref() { + shell.publish(on_focus.clone()); + } + // Handle left click drag if let Button::Left = button { let x_logical = p.x - self.padding.left; @@ -1263,6 +1281,7 @@ pub struct State { dragging: Option, editor_offset_x: Cell, is_focused: bool, + emit_focus: bool, scale_factor: Cell, scrollbar_v_rect: Cell>, scrollbar_h_rect: Cell>>, @@ -1278,6 +1297,7 @@ impl State { dragging: None, editor_offset_x: Cell::new(0), is_focused: false, + emit_focus: false, scale_factor: Cell::new(1.0), scrollbar_v_rect: Cell::new(Rectangle::default()), scrollbar_h_rect: Cell::new(None), @@ -1293,6 +1313,7 @@ impl operation::Focusable for State { fn focus(&mut self) { self.is_focused = true; + self.emit_focus = true; } fn unfocus(&mut self) {