From 8cdf308db5e02de11599477aca41474242dbcd71 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Fri, 5 Jun 2026 15:37:44 -0400 Subject: [PATCH] fix: focus inputs on open of context drawer --- .../src/pages/applications/startup_apps.rs | 34 +++++++++++++++++-- .../src/pages/desktop/appearance/drawer.rs | 3 +- .../pages/desktop/appearance/font_config.rs | 6 +++- .../src/pages/desktop/appearance/mod.rs | 25 +++++++++++++- 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/cosmic-settings/src/pages/applications/startup_apps.rs b/cosmic-settings/src/pages/applications/startup_apps.rs index d5cd855..4735771 100644 --- a/cosmic-settings/src/pages/applications/startup_apps.rs +++ b/cosmic-settings/src/pages/applications/startup_apps.rs @@ -1,7 +1,8 @@ use cosmic::app::ContextDrawer; use cosmic::iced::{Alignment, Length}; -use cosmic::widget::{button, icon, settings, text}; -use cosmic::{Apply, Element, Task, widget}; +use cosmic::widget::text_input::focus; +use cosmic::widget::{Id, button, icon, settings, text}; +use cosmic::{Apply, Element, Task, task, widget}; use cosmic_settings_page::section::Entity; use cosmic_settings_page::{self as page, Content, Info, Section}; use freedesktop_desktop_entry::DesktopEntry; @@ -9,8 +10,12 @@ use itertools::Itertools; use slotmap::{Key, SlotMap}; use std::collections::{HashMap, HashSet}; use std::path::PathBuf; +use std::sync::LazyLock; use tracing::error; +pub static ADD_APPLICATION_SEARCH: LazyLock = + LazyLock::new(|| widget::Id::new("ADD_APPLICATION_SEARCH")); + #[derive(Clone, Debug)] pub struct CachedApps { apps: HashMap>, @@ -51,6 +56,7 @@ pub enum Message { ShowApplicationSidebar(DirectoryType), UpdateApplications(CachedApps), UpdateStartupApplications(CachedApps), + FocusAddApplicationSearch, } #[derive(Clone, Debug, Eq, PartialEq, Hash)] @@ -116,6 +122,7 @@ impl page::Page for Page { let search = widget::search_input("", &self.application_search) .on_input(|i| Message::ApplicationSearch(i).into()) .on_clear(Message::ApplicationSearch(String::new()).into()) + .id(ADD_APPLICATION_SEARCH.clone()) .apply(Element::from); Some( @@ -220,7 +227,8 @@ impl Page { } Message::ShowApplicationSidebar(directory_type) => { self.context = Some(Context::AddApplication(directory_type)); - return cosmic::task::message(crate::app::Message::OpenContextDrawer(self.entity)); + return cosmic::task::message(crate::app::Message::OpenContextDrawer(self.entity)) + .chain(task::message(Message::FocusAddApplicationSearch)); } Message::AddStartupApplication(directory_type, app) => { let mut file_name = app.clone().appid; @@ -319,6 +327,26 @@ impl Page { self.target_directory_type = None; self.context = None; } + Message::FocusAddApplicationSearch => { + // retry until the widget is in the tree and focused or the dialog is removed. + if matches!(self.context, Some(Context::AddApplication(_))) { + return cosmic::iced::runtime::task::widget( + cosmic::iced::core::widget::operation::focusable::find_focused(), + ) + .collect() + .then(|id| { + if id + .first() + .is_some_and(|id| *id == ADD_APPLICATION_SEARCH.clone()) + { + Task::none() + } else { + focus(ADD_APPLICATION_SEARCH.clone()) + .chain(task::message(Message::FocusAddApplicationSearch)) + } + }); + } + } _ => {} } diff --git a/cosmic-settings/src/pages/desktop/appearance/drawer.rs b/cosmic-settings/src/pages/desktop/appearance/drawer.rs index 5e33fd6..3bfca74 100644 --- a/cosmic-settings/src/pages/desktop/appearance/drawer.rs +++ b/cosmic-settings/src/pages/desktop/appearance/drawer.rs @@ -5,7 +5,7 @@ use cosmic::cosmic_theme::Spacing; use cosmic::iced::core::{Color, Length}; use cosmic::widget::color_picker::ColorPickerUpdate; use cosmic::widget::{ColorPickerModel, container, flex_row, settings, text}; -use cosmic::{Apply, Element, Task, widget}; +use cosmic::{Apply, Element, Task, task, widget}; use cosmic_config::ConfigGet; use std::sync::Arc; use tracing::error; @@ -295,6 +295,7 @@ impl Content { } ContextView::MonospaceFont | ContextView::SystemFont => { self.font_config.reset(); + return task::message(super::Message::FocusFontInput); } _ => {} } diff --git a/cosmic-settings/src/pages/desktop/appearance/font_config.rs b/cosmic-settings/src/pages/desktop/appearance/font_config.rs index 92905dd..420a044 100644 --- a/cosmic-settings/src/pages/desktop/appearance/font_config.rs +++ b/cosmic-settings/src/pages/desktop/appearance/font_config.rs @@ -1,17 +1,20 @@ // Copyright 2024 System76 // SPDX-License-Identifier: GPL-3.0-only -use std::sync::Arc; +use std::sync::{Arc, LazyLock}; use cosmic::config::{CosmicTk, FontConfig}; use cosmic::{Apply, Element, Task, widget}; use cosmic_config::ConfigSet; +use mime::FONT; use crate::app; use crate::widget::selection_context_item; use super::{ContextView, Message, drawer}; +pub static FONT_SEARCH: LazyLock = LazyLock::new(|| widget::Id::new("FONT_SEARCH")); + const INTERFACE_FONT: &str = "interface_font"; const MONOSPACE_FONT: &str = "monospace_font"; @@ -164,6 +167,7 @@ impl Model { .on_clear(Message::DrawerFont(drawer::FontMessage::Search( String::new(), ))) + .id(FONT_SEARCH.clone()) .apply(Element::from) .map(crate::pages::Message::Appearance) } diff --git a/cosmic-settings/src/pages/desktop/appearance/mod.rs b/cosmic-settings/src/pages/desktop/appearance/mod.rs index ff3b3ea..4eadb07 100644 --- a/cosmic-settings/src/pages/desktop/appearance/mod.rs +++ b/cosmic-settings/src/pages/desktop/appearance/mod.rs @@ -23,8 +23,9 @@ use cosmic::iced::Subscription; use cosmic::iced::core::{Alignment, Length}; use cosmic::widget::color_picker::ColorPickerUpdate; use cosmic::widget::space::horizontal; +use cosmic::widget::text_input::focus; use cosmic::widget::{button, container, row, settings, text}; -use cosmic::{Apply, Element, Task, widget}; +use cosmic::{Apply, Element, Task, task, widget}; #[cfg(feature = "wayland")] use cosmic_panel_config::CosmicPanelConfig; use cosmic_settings_page::{self as page, Section, section}; @@ -32,6 +33,7 @@ use ron::ser::PrettyConfig; use slotmap::{Key, SlotMap}; use crate::app; +use crate::pages::desktop::appearance::font_config::FONT_SEARCH; #[derive(Clone, Copy, Debug)] pub enum ContextView { @@ -138,6 +140,7 @@ pub enum Message { #[cfg(feature = "xdg-portal")] ExportSuccess, + FocusFontInput, GapSize(u32), #[cfg(feature = "xdg-portal")] ImportError, @@ -505,6 +508,26 @@ impl Page { self.drawer.reset(&self.theme_manager); } } + + Message::FocusFontInput => { + // retry until the widget is in the tree and focused or the dialog is removed. + if matches!( + self.context_view, + Some(ContextView::SystemFont | ContextView::MonospaceFont) + ) { + return cosmic::iced::runtime::task::widget( + cosmic::iced::core::widget::operation::focusable::find_focused(), + ) + .collect() + .then(|id| { + if id.first().is_some_and(|id| *id == FONT_SEARCH.clone()) { + Task::none() + } else { + focus(FONT_SEARCH.clone()).chain(task::message(Message::FocusFontInput)) + } + }); + } + } } let mut tasks = cosmic::Task::batch(tasks);