fix: focus inputs on open of context drawer
This commit is contained in:
parent
4ae20bc1db
commit
8cdf308db5
4 changed files with 62 additions and 6 deletions
|
|
@ -1,7 +1,8 @@
|
||||||
use cosmic::app::ContextDrawer;
|
use cosmic::app::ContextDrawer;
|
||||||
use cosmic::iced::{Alignment, Length};
|
use cosmic::iced::{Alignment, Length};
|
||||||
use cosmic::widget::{button, icon, settings, text};
|
use cosmic::widget::text_input::focus;
|
||||||
use cosmic::{Apply, Element, Task, widget};
|
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::section::Entity;
|
||||||
use cosmic_settings_page::{self as page, Content, Info, Section};
|
use cosmic_settings_page::{self as page, Content, Info, Section};
|
||||||
use freedesktop_desktop_entry::DesktopEntry;
|
use freedesktop_desktop_entry::DesktopEntry;
|
||||||
|
|
@ -9,8 +10,12 @@ use itertools::Itertools;
|
||||||
use slotmap::{Key, SlotMap};
|
use slotmap::{Key, SlotMap};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::sync::LazyLock;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
|
pub static ADD_APPLICATION_SEARCH: LazyLock<widget::Id> =
|
||||||
|
LazyLock::new(|| widget::Id::new("ADD_APPLICATION_SEARCH"));
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CachedApps {
|
pub struct CachedApps {
|
||||||
apps: HashMap<DirectoryType, Vec<DesktopEntry>>,
|
apps: HashMap<DirectoryType, Vec<DesktopEntry>>,
|
||||||
|
|
@ -51,6 +56,7 @@ pub enum Message {
|
||||||
ShowApplicationSidebar(DirectoryType),
|
ShowApplicationSidebar(DirectoryType),
|
||||||
UpdateApplications(CachedApps),
|
UpdateApplications(CachedApps),
|
||||||
UpdateStartupApplications(CachedApps),
|
UpdateStartupApplications(CachedApps),
|
||||||
|
FocusAddApplicationSearch,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
|
@ -116,6 +122,7 @@ impl page::Page<crate::pages::Message> for Page {
|
||||||
let search = widget::search_input("", &self.application_search)
|
let search = widget::search_input("", &self.application_search)
|
||||||
.on_input(|i| Message::ApplicationSearch(i).into())
|
.on_input(|i| Message::ApplicationSearch(i).into())
|
||||||
.on_clear(Message::ApplicationSearch(String::new()).into())
|
.on_clear(Message::ApplicationSearch(String::new()).into())
|
||||||
|
.id(ADD_APPLICATION_SEARCH.clone())
|
||||||
.apply(Element::from);
|
.apply(Element::from);
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
|
|
@ -220,7 +227,8 @@ impl Page {
|
||||||
}
|
}
|
||||||
Message::ShowApplicationSidebar(directory_type) => {
|
Message::ShowApplicationSidebar(directory_type) => {
|
||||||
self.context = Some(Context::AddApplication(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) => {
|
Message::AddStartupApplication(directory_type, app) => {
|
||||||
let mut file_name = app.clone().appid;
|
let mut file_name = app.clone().appid;
|
||||||
|
|
@ -319,6 +327,26 @@ impl Page {
|
||||||
self.target_directory_type = None;
|
self.target_directory_type = None;
|
||||||
self.context = 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))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use cosmic::cosmic_theme::Spacing;
|
||||||
use cosmic::iced::core::{Color, Length};
|
use cosmic::iced::core::{Color, Length};
|
||||||
use cosmic::widget::color_picker::ColorPickerUpdate;
|
use cosmic::widget::color_picker::ColorPickerUpdate;
|
||||||
use cosmic::widget::{ColorPickerModel, container, flex_row, settings, text};
|
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 cosmic_config::ConfigGet;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
@ -295,6 +295,7 @@ impl Content {
|
||||||
}
|
}
|
||||||
ContextView::MonospaceFont | ContextView::SystemFont => {
|
ContextView::MonospaceFont | ContextView::SystemFont => {
|
||||||
self.font_config.reset();
|
self.font_config.reset();
|
||||||
|
return task::message(super::Message::FocusFontInput);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,20 @@
|
||||||
// Copyright 2024 System76 <info@system76.com>
|
// Copyright 2024 System76 <info@system76.com>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, LazyLock};
|
||||||
|
|
||||||
use cosmic::config::{CosmicTk, FontConfig};
|
use cosmic::config::{CosmicTk, FontConfig};
|
||||||
use cosmic::{Apply, Element, Task, widget};
|
use cosmic::{Apply, Element, Task, widget};
|
||||||
use cosmic_config::ConfigSet;
|
use cosmic_config::ConfigSet;
|
||||||
|
use mime::FONT;
|
||||||
|
|
||||||
use crate::app;
|
use crate::app;
|
||||||
use crate::widget::selection_context_item;
|
use crate::widget::selection_context_item;
|
||||||
|
|
||||||
use super::{ContextView, Message, drawer};
|
use super::{ContextView, Message, drawer};
|
||||||
|
|
||||||
|
pub static FONT_SEARCH: LazyLock<widget::Id> = LazyLock::new(|| widget::Id::new("FONT_SEARCH"));
|
||||||
|
|
||||||
const INTERFACE_FONT: &str = "interface_font";
|
const INTERFACE_FONT: &str = "interface_font";
|
||||||
const MONOSPACE_FONT: &str = "monospace_font";
|
const MONOSPACE_FONT: &str = "monospace_font";
|
||||||
|
|
||||||
|
|
@ -164,6 +167,7 @@ impl Model {
|
||||||
.on_clear(Message::DrawerFont(drawer::FontMessage::Search(
|
.on_clear(Message::DrawerFont(drawer::FontMessage::Search(
|
||||||
String::new(),
|
String::new(),
|
||||||
)))
|
)))
|
||||||
|
.id(FONT_SEARCH.clone())
|
||||||
.apply(Element::from)
|
.apply(Element::from)
|
||||||
.map(crate::pages::Message::Appearance)
|
.map(crate::pages::Message::Appearance)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,9 @@ use cosmic::iced::Subscription;
|
||||||
use cosmic::iced::core::{Alignment, Length};
|
use cosmic::iced::core::{Alignment, Length};
|
||||||
use cosmic::widget::color_picker::ColorPickerUpdate;
|
use cosmic::widget::color_picker::ColorPickerUpdate;
|
||||||
use cosmic::widget::space::horizontal;
|
use cosmic::widget::space::horizontal;
|
||||||
|
use cosmic::widget::text_input::focus;
|
||||||
use cosmic::widget::{button, container, row, settings, text};
|
use cosmic::widget::{button, container, row, settings, text};
|
||||||
use cosmic::{Apply, Element, Task, widget};
|
use cosmic::{Apply, Element, Task, task, widget};
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
use cosmic_panel_config::CosmicPanelConfig;
|
use cosmic_panel_config::CosmicPanelConfig;
|
||||||
use cosmic_settings_page::{self as page, Section, section};
|
use cosmic_settings_page::{self as page, Section, section};
|
||||||
|
|
@ -32,6 +33,7 @@ use ron::ser::PrettyConfig;
|
||||||
use slotmap::{Key, SlotMap};
|
use slotmap::{Key, SlotMap};
|
||||||
|
|
||||||
use crate::app;
|
use crate::app;
|
||||||
|
use crate::pages::desktop::appearance::font_config::FONT_SEARCH;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum ContextView {
|
pub enum ContextView {
|
||||||
|
|
@ -138,6 +140,7 @@ pub enum Message {
|
||||||
#[cfg(feature = "xdg-portal")]
|
#[cfg(feature = "xdg-portal")]
|
||||||
ExportSuccess,
|
ExportSuccess,
|
||||||
|
|
||||||
|
FocusFontInput,
|
||||||
GapSize(u32),
|
GapSize(u32),
|
||||||
#[cfg(feature = "xdg-portal")]
|
#[cfg(feature = "xdg-portal")]
|
||||||
ImportError,
|
ImportError,
|
||||||
|
|
@ -505,6 +508,26 @@ impl Page {
|
||||||
self.drawer.reset(&self.theme_manager);
|
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);
|
let mut tasks = cosmic::Task::batch(tasks);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue