feat: dropdown popups

This commit is contained in:
Ashley Wulber 2025-03-14 12:11:19 -04:00 committed by Michael Murphy
parent bb7cc2b568
commit df7e95e30a
21 changed files with 352 additions and 157 deletions

View file

@ -1,3 +1,3 @@
{ {
"rust-analyzer.check.overrideCommand": ["just", "check-json"] // "rust-analyzer.check.overrideCommand": ["just", "check-json"]
} }

34
Cargo.lock generated
View file

@ -1519,7 +1519,7 @@ dependencies = [
[[package]] [[package]]
name = "cosmic-config" name = "cosmic-config"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" source = "git+https://github.com/pop-os/libcosmic#337b80d4ca02a63631668212bccbace22b8bb49f"
dependencies = [ dependencies = [
"atomicwrites", "atomicwrites",
"cosmic-config-derive", "cosmic-config-derive",
@ -1541,7 +1541,7 @@ dependencies = [
[[package]] [[package]]
name = "cosmic-config-derive" name = "cosmic-config-derive"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" source = "git+https://github.com/pop-os/libcosmic#337b80d4ca02a63631668212bccbace22b8bb49f"
dependencies = [ dependencies = [
"quote", "quote",
"syn 1.0.109", "syn 1.0.109",
@ -1822,8 +1822,8 @@ dependencies = [
[[package]] [[package]]
name = "cosmic-text" name = "cosmic-text"
version = "0.13.1" version = "0.13.2"
source = "git+https://github.com/pop-os/cosmic-text.git#60f2c2b0c2e7cf8734b3ad0fc94ef7bce94f649b" source = "git+https://github.com/pop-os/cosmic-text.git#500a8fc6d172de5c9e08c6013070b6b7fcdf79dd"
dependencies = [ dependencies = [
"bitflags 2.8.0", "bitflags 2.8.0",
"fontdb 0.16.2", "fontdb 0.16.2",
@ -1845,7 +1845,7 @@ dependencies = [
[[package]] [[package]]
name = "cosmic-theme" name = "cosmic-theme"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" source = "git+https://github.com/pop-os/libcosmic#337b80d4ca02a63631668212bccbace22b8bb49f"
dependencies = [ dependencies = [
"almost", "almost",
"cosmic-config", "cosmic-config",
@ -3189,7 +3189,7 @@ dependencies = [
[[package]] [[package]]
name = "iced" name = "iced"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" source = "git+https://github.com/pop-os/libcosmic#337b80d4ca02a63631668212bccbace22b8bb49f"
dependencies = [ dependencies = [
"dnd", "dnd",
"iced_accessibility", "iced_accessibility",
@ -3207,7 +3207,7 @@ dependencies = [
[[package]] [[package]]
name = "iced_accessibility" name = "iced_accessibility"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" source = "git+https://github.com/pop-os/libcosmic#337b80d4ca02a63631668212bccbace22b8bb49f"
dependencies = [ dependencies = [
"accesskit", "accesskit",
"accesskit_winit", "accesskit_winit",
@ -3216,7 +3216,7 @@ dependencies = [
[[package]] [[package]]
name = "iced_core" name = "iced_core"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" source = "git+https://github.com/pop-os/libcosmic#337b80d4ca02a63631668212bccbace22b8bb49f"
dependencies = [ dependencies = [
"bitflags 2.8.0", "bitflags 2.8.0",
"bytes", "bytes",
@ -3241,7 +3241,7 @@ dependencies = [
[[package]] [[package]]
name = "iced_futures" name = "iced_futures"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" source = "git+https://github.com/pop-os/libcosmic#337b80d4ca02a63631668212bccbace22b8bb49f"
dependencies = [ dependencies = [
"futures", "futures",
"iced_core", "iced_core",
@ -3267,7 +3267,7 @@ dependencies = [
[[package]] [[package]]
name = "iced_graphics" name = "iced_graphics"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" source = "git+https://github.com/pop-os/libcosmic#337b80d4ca02a63631668212bccbace22b8bb49f"
dependencies = [ dependencies = [
"bitflags 2.8.0", "bitflags 2.8.0",
"bytemuck", "bytemuck",
@ -3289,7 +3289,7 @@ dependencies = [
[[package]] [[package]]
name = "iced_renderer" name = "iced_renderer"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" source = "git+https://github.com/pop-os/libcosmic#337b80d4ca02a63631668212bccbace22b8bb49f"
dependencies = [ dependencies = [
"iced_graphics", "iced_graphics",
"iced_tiny_skia", "iced_tiny_skia",
@ -3301,7 +3301,7 @@ dependencies = [
[[package]] [[package]]
name = "iced_runtime" name = "iced_runtime"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" source = "git+https://github.com/pop-os/libcosmic#337b80d4ca02a63631668212bccbace22b8bb49f"
dependencies = [ dependencies = [
"bytes", "bytes",
"cosmic-client-toolkit", "cosmic-client-toolkit",
@ -3317,7 +3317,7 @@ dependencies = [
[[package]] [[package]]
name = "iced_tiny_skia" name = "iced_tiny_skia"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" source = "git+https://github.com/pop-os/libcosmic#337b80d4ca02a63631668212bccbace22b8bb49f"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"cosmic-text", "cosmic-text",
@ -3333,7 +3333,7 @@ dependencies = [
[[package]] [[package]]
name = "iced_wgpu" name = "iced_wgpu"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" source = "git+https://github.com/pop-os/libcosmic#337b80d4ca02a63631668212bccbace22b8bb49f"
dependencies = [ dependencies = [
"as-raw-xcb-connection", "as-raw-xcb-connection",
"bitflags 2.8.0", "bitflags 2.8.0",
@ -3364,7 +3364,7 @@ dependencies = [
[[package]] [[package]]
name = "iced_widget" name = "iced_widget"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" source = "git+https://github.com/pop-os/libcosmic#337b80d4ca02a63631668212bccbace22b8bb49f"
dependencies = [ dependencies = [
"cosmic-client-toolkit", "cosmic-client-toolkit",
"dnd", "dnd",
@ -3383,7 +3383,7 @@ dependencies = [
[[package]] [[package]]
name = "iced_winit" name = "iced_winit"
version = "0.14.0-dev" version = "0.14.0-dev"
source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" source = "git+https://github.com/pop-os/libcosmic#337b80d4ca02a63631668212bccbace22b8bb49f"
dependencies = [ dependencies = [
"cosmic-client-toolkit", "cosmic-client-toolkit",
"dnd", "dnd",
@ -4389,7 +4389,7 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]] [[package]]
name = "libcosmic" name = "libcosmic"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic#64ddcb3bf2aed84256fe8261a0b05e1831720463" source = "git+https://github.com/pop-os/libcosmic#337b80d4ca02a63631668212bccbace22b8bb49f"
dependencies = [ dependencies = [
"apply", "apply",
"ashpd 0.9.2", "ashpd 0.9.2",

View file

@ -57,11 +57,9 @@ cosmic-client-toolkit = { git = "https://github.com/pop-os/cosmic-protocols//",
# For development and testing purposes # For development and testing purposes
# [patch.'https://github.com/pop-os/libcosmic'] # [patch.'https://github.com/pop-os/libcosmic']
# libcosmic = { git = "https://github.com/pop-os/libcosmic//", branch = "font" } # libcosmic = { git = "https://github.com/pop-os/libcosmic//", branch = "drop-menu-tree-changes" }
# cosmic-config = { git = "https://github.com/pop-os/libcosmic//", branch = "font" } # cosmic-config = { git = "https://github.com/pop-os/libcosmic//", branch = "drop-menu-tree-changes" }
# cosmic-theme = { git = "https://github.com/pop-os/libcosmic//", branch = "font" } # cosmic-theme = { git = "https://github.com/pop-os/libcosmic//", branch = "drop-menu-tree-changes" }
# iced_futures = { git = "https://github.com/pop-os/libcosmic//", branch = "font" }
# libcosmic = { path = "../libcosmic" } # libcosmic = { path = "../libcosmic" }
# cosmic-config = { path = "../libcosmic/cosmic-config" } # cosmic-config = { path = "../libcosmic/cosmic-config" }
# cosmic-theme = { path = "../libcosmic/cosmic-theme" } # cosmic-theme = { path = "../libcosmic/cosmic-theme" }

View file

@ -21,10 +21,7 @@ use crate::pages::{self, system, time};
use crate::subscription::desktop_files; use crate::subscription::desktop_files;
use crate::widget::{page_title, search_header}; use crate::widget::{page_title, search_header};
use crate::PageCommands; use crate::PageCommands;
use cosmic::app::command::set_theme;
use cosmic::app::context_drawer::ContextDrawer; use cosmic::app::context_drawer::ContextDrawer;
#[cfg(feature = "single-instance")]
use cosmic::app::DbusActivationMessage;
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
use cosmic::cctk::{sctk::output::OutputInfo, wayland_client::protocol::wl_output::WlOutput}; use cosmic::cctk::{sctk::output::OutputInfo, wayland_client::protocol::wl_output::WlOutput};
use cosmic::iced::Subscription; use cosmic::iced::Subscription;
@ -37,6 +34,7 @@ use cosmic::{
window, Length, window, Length,
}, },
prelude::*, prelude::*,
surface,
widget::{ widget::{
column, container, icon, id_container, nav_bar, scrollable, segmented_button, settings, column, container, icon, id_container, nav_bar, scrollable, segmented_button, settings,
}, },
@ -164,6 +162,7 @@ pub enum Message {
SearchSubmit, SearchSubmit,
SetTheme(cosmic::theme::Theme), SetTheme(cosmic::theme::Theme),
SetWindowTitle, SetWindowTitle,
Surface(surface::Action),
} }
impl cosmic::Application for SettingsApp { impl cosmic::Application for SettingsApp {
@ -244,7 +243,7 @@ impl cosmic::Application for SettingsApp {
.id(self.search_id.clone()) .id(self.search_id.clone())
.on_clear(Message::SearchClear) .on_clear(Message::SearchClear)
.on_input(Message::SearchChanged) .on_input(Message::SearchChanged)
.on_submit(Message::SearchSubmit) .on_submit(|_| Message::SearchSubmit)
.into() .into()
} else { } else {
icon::from_name("system-search-symbolic") icon::from_name("system-search-symbolic")
@ -581,7 +580,9 @@ impl cosmic::Application for SettingsApp {
#[cfg(feature = "page-power")] #[cfg(feature = "page-power")]
crate::pages::Message::Power(message) => { crate::pages::Message::Power(message) => {
page::update!(self.pages, message, power::Page); if let Some(page) = self.pages.page_mut::<power::Page>() {
return page.update(message).map(Into::into);
}
} }
#[cfg(feature = "page-networking")] #[cfg(feature = "page-networking")]
@ -725,7 +726,7 @@ impl cosmic::Application for SettingsApp {
} }
} }
Message::SetTheme(t) => return set_theme(t), Message::SetTheme(t) => return cosmic::command::set_theme(t),
Message::OpenContextDrawer(page, title) => { Message::OpenContextDrawer(page, title) => {
self.core.window.show_context = true; self.core.window.show_context = true;
@ -741,17 +742,22 @@ impl cosmic::Application for SettingsApp {
Message::Error(error) => { Message::Error(error) => {
tracing::error!(error, "error occurred"); tracing::error!(error, "error occurred");
} }
Message::Surface(a) => {
return cosmic::task::message(cosmic::Action::Cosmic(
cosmic::app::Action::Surface(a),
));
}
} }
Task::none() Task::none()
} }
#[cfg(feature = "single-instance")] #[cfg(feature = "single-instance")]
fn dbus_activation(&mut self, msg: DbusActivationMessage) -> Task<Self::Message> { fn dbus_activation(&mut self, msg: cosmic::dbus_activation::Message) -> Task<Self::Message> {
match msg.msg { match msg.msg {
cosmic::app::DbusActivationDetails::Activate cosmic::dbus_activation::Details::Activate
| cosmic::app::DbusActivationDetails::Open { .. } => None, | cosmic::dbus_activation::Details::Open { .. } => None,
cosmic::app::DbusActivationDetails::ActivateAction { action, .. } => { cosmic::dbus_activation::Details::ActivateAction { action, .. } => {
PageCommands::from_str(&action) PageCommands::from_str(&action)
.ok() .ok()
.and_then(|action| self.subtask_to_page(&action)) .and_then(|action| self.subtask_to_page(&action))

View file

@ -3,6 +3,7 @@ use std::collections::HashSet;
use cosmic::{ use cosmic::{
iced::{Element, Length}, iced::{Element, Length},
iced_core::text::Wrapping, iced_core::text::Wrapping,
surface,
widget::{self, icon, settings, svg, text}, widget::{self, icon, settings, svg, text},
Apply, Apply,
}; };
@ -42,6 +43,7 @@ pub enum Message {
SetIncrement(usize), SetIncrement(usize),
SetSignin(bool), SetSignin(bool),
SetMovement(ZoomMovement), SetMovement(ZoomMovement),
Surface(surface::Action),
} }
impl Default for Page { impl Default for Page {
@ -219,10 +221,17 @@ pub fn magnifier(
) )
.add(settings::item( .add(settings::item(
&descriptions[increment], &descriptions[increment],
widget::dropdown( widget::dropdown::popup_dropdown(
&page.increment_values, &page.increment_values,
page.increment_idx, page.increment_idx,
Message::SetIncrement, Message::SetIncrement,
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(
crate::pages::Message::AccessibilityMagnifier(a),
)
},
), ),
)) ))
.add(settings::item( .add(settings::item(
@ -365,6 +374,9 @@ impl Page {
)); ));
} }
} }
Message::Surface(a) => {
return cosmic::task::message(crate::app::Message::Surface(a));
}
} }
cosmic::iced::Task::none() cosmic::iced::Task::none()

View file

@ -66,12 +66,17 @@ impl Page {
Task::none() Task::none()
} }
Message::Inner(inner) => self Message::Inner(inner) => {
.inner if let inner::Message::Surface(a) = inner {
.update(inner) return cosmic::task::message(crate::app::Message::Surface(a));
.map(Message::Inner) } else {
.map(crate::pages::Message::Dock) self.inner
.map(crate::app::Message::PageMessage), .update(inner)
.map(Message::Inner)
.map(crate::pages::Message::Dock)
.map(crate::app::Message::PageMessage)
}
}
} }
} }
} }

View file

@ -2,7 +2,7 @@ use cosmic::{
cctk::sctk::reexports::client::{backend::ObjectId, protocol::wl_output::WlOutput, Proxy}, cctk::sctk::reexports::client::{backend::ObjectId, protocol::wl_output::WlOutput, Proxy},
cosmic_config::{self, CosmicConfigEntry}, cosmic_config::{self, CosmicConfigEntry},
iced::{Alignment, Length}, iced::{Alignment, Length},
theme, surface, theme,
widget::{ widget::{
button, container, dropdown, horizontal_space, icon, row, settings, slider, text, toggler, button, container, dropdown, horizontal_space, icon, row, settings, slider, text, toggler,
}, },
@ -122,15 +122,22 @@ pub(crate) fn behavior_and_position<
)) ))
.add(settings::item( .add(settings::item(
&descriptions[position], &descriptions[position],
dropdown( dropdown::popup_dropdown(
page.anchors.as_slice(), page.anchors.as_slice(),
Some(panel_config.anchor as usize), Some(panel_config.anchor as usize),
Message::PanelAnchor, Message::PanelAnchor,
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(crate::pages::Message::Panel(
super::Message(a),
))
},
), ),
)) ))
.add(settings::item( .add(settings::item(
&descriptions[display], &descriptions[display],
dropdown( dropdown::popup_dropdown(
page.outputs.as_slice(), page.outputs.as_slice(),
match &panel_config.output { match &panel_config.output {
CosmicPanelOuput::All => Some(0), CosmicPanelOuput::All => Some(0),
@ -138,6 +145,13 @@ pub(crate) fn behavior_and_position<
CosmicPanelOuput::Name(n) => page.outputs.iter().position(|o| o == n), CosmicPanelOuput::Name(n) => page.outputs.iter().position(|o| o == n),
}, },
Message::Output, Message::Output,
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(crate::pages::Message::Panel(
super::Message(a),
))
},
), ),
)) ))
.apply(Element::from) .apply(Element::from)
@ -181,7 +195,7 @@ pub(crate) fn style<
)) ))
.add(settings::item( .add(settings::item(
&descriptions[appearance], &descriptions[appearance],
dropdown( dropdown::popup_dropdown(
inner.backgrounds.as_slice(), inner.backgrounds.as_slice(),
match panel_config.background { match panel_config.background {
CosmicPanelBackground::ThemeDefault => Some(0), CosmicPanelBackground::ThemeDefault => Some(0),
@ -190,6 +204,13 @@ pub(crate) fn style<
CosmicPanelBackground::Color(_) => None, CosmicPanelBackground::Color(_) => None,
}, },
Message::Appearance, Message::Appearance,
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(crate::pages::Message::Panel(
super::Message(a),
))
},
), ),
)) ))
.add(settings::flex_item( .add(settings::flex_item(
@ -423,6 +444,7 @@ pub enum Message {
PanelConfig(CosmicPanelConfig), PanelConfig(CosmicPanelConfig),
ResetPanel, ResetPanel,
FullReset, FullReset,
Surface(surface::Action),
} }
impl PageInner { impl PageInner {
@ -570,6 +592,9 @@ impl PageInner {
return Task::none(); return Task::none();
} }
Message::ResetPanel | Message::FullReset => {} Message::ResetPanel | Message::FullReset => {}
Message::Surface(a) => {
unimplemented!()
}
} }
if panel_config.anchor_gap || !panel_config.expand_to_edges { if panel_config.anchor_gap || !panel_config.expand_to_edges {

View file

@ -23,11 +23,15 @@ pub struct Message(pub inner::Message);
impl Page { impl Page {
pub fn update(&mut self, message: Message) -> Task<crate::app::Message> { pub fn update(&mut self, message: Message) -> Task<crate::app::Message> {
self.inner if let inner::Message::Surface(a) = message.0 {
.update(message.0) return cosmic::task::message(crate::app::Message::Surface(a));
.map(Message) } else {
.map(crate::pages::Message::Panel) self.inner
.map(crate::app::Message::PageMessage) .update(message.0)
.map(Message)
.map(crate::pages::Message::Panel)
.map(crate::app::Message::PageMessage)
}
} }
} }

View file

@ -16,13 +16,16 @@ use std::{
#[cfg(feature = "xdg-portal")] #[cfg(feature = "xdg-portal")]
use cosmic::dialog::file_chooser; use cosmic::dialog::file_chooser;
use cosmic::iced::{Alignment, Color, Length};
use cosmic::iced_runtime::core::image::Handle as ImageHandle; use cosmic::iced_runtime::core::image::Handle as ImageHandle;
use cosmic::widget::{ use cosmic::widget::{
button, dropdown, list_column, row, button, dropdown, list_column, row,
segmented_button::{self, SingleSelectModel}, segmented_button::{self, SingleSelectModel},
settings, tab_bar, text, toggler, settings, tab_bar, text, toggler,
}; };
use cosmic::{
iced::{window, Alignment, Color, Length},
surface,
};
use cosmic::{ use cosmic::{
widget::{color_picker::ColorPickerUpdate, icon, ColorPickerModel}, widget::{color_picker::ColorPickerUpdate, icon, ColorPickerModel},
Apply, Element, Task, Apply, Element, Task,
@ -106,6 +109,7 @@ pub enum Message {
Slideshow(bool), Slideshow(bool),
/// State change from cosmic-bg /// State change from cosmic-bg
UpdateState(cosmic_bg_config::state::State), UpdateState(cosmic_bg_config::state::State),
Surface(surface::Action),
} }
impl From<Message> for crate::app::Message { impl From<Message> for crate::app::Message {
@ -990,6 +994,9 @@ impl Page {
))), ))),
); );
} }
Message::Surface(a) => {
return cosmic::task::message(crate::app::Message::Surface(a));
}
} }
self.config_apply(); self.config_apply();
@ -1236,8 +1243,14 @@ pub fn settings() -> Section<crate::pages::Message> {
children.push(element.into()); children.push(element.into());
} }
let wallpaper_fit = let wallpaper_fit = cosmic::widget::dropdown::popup_dropdown(
cosmic::widget::dropdown(&page.fit_options, Some(page.selected_fit), Message::Fit); &page.fit_options,
Some(page.selected_fit),
Message::Fit,
window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::DesktopWallpaper(a)),
);
children.push({ children.push({
let mut column = list_column() let mut column = list_column()
@ -1258,14 +1271,26 @@ pub fn settings() -> Section<crate::pages::Message> {
// The rotation frequency dropdown should only be shown when the slideshow is enabled. // The rotation frequency dropdown should only be shown when the slideshow is enabled.
if slideshow_enabled { if slideshow_enabled {
column column
.add(settings::item( .add(settings::item(&descriptions[change_label], {
&descriptions[change_label], let dropdown = dropdown(
dropdown(
&page.rotation_options, &page.rotation_options,
Some(page.selected_rotation), Some(page.selected_rotation),
Message::RotationFrequency, Message::RotationFrequency,
), );
)) #[cfg(feature = "wayland")]
let dropdown = {
dropdown.with_popup(
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(
crate::pages::Message::DesktopWallpaper(a),
)
},
)
};
dropdown
}))
.into() .into()
} else { } else {
column.into() column.into()

View file

@ -3,8 +3,9 @@
use cosmic::{ use cosmic::{
iced::Length, iced::Length,
surface,
widget::{self, settings, toggler}, widget::{self, settings, toggler},
Apply, Element, Apply, Element, Task,
}; };
use cosmic_config::{ConfigGet, ConfigSet}; use cosmic_config::{ConfigGet, ConfigSet};
@ -26,6 +27,7 @@ pub enum Message {
ShowMaximizeButton(bool), ShowMaximizeButton(bool),
ShowMinimizeButton(bool), ShowMinimizeButton(bool),
SetEdgeSnapThreshold(u32), SetEdgeSnapThreshold(u32),
Surface(surface::Action),
} }
pub struct Page { pub struct Page {
@ -107,7 +109,7 @@ impl Default for Page {
} }
impl Page { impl Page {
pub fn update(&mut self, message: Message) { pub fn update(&mut self, message: Message) -> cosmic::iced::Task<crate::app::Message> {
match message { match message {
Message::SuperKey(id) => { Message::SuperKey(id) => {
let action = match id { let action = match id {
@ -115,7 +117,7 @@ impl Page {
1 => Some(shortcuts::action::System::WorkspaceOverview), 1 => Some(shortcuts::action::System::WorkspaceOverview),
2 => Some(shortcuts::action::System::AppLibrary), 2 => Some(shortcuts::action::System::AppLibrary),
3 => None, 3 => None,
_ => return, _ => return cosmic::iced::Task::none(),
}; };
self.super_key_active = Some(id); self.super_key_active = Some(id);
@ -186,7 +188,11 @@ impl Page {
error!(?err, "Failed to set config 'edge_snap_threshold'"); error!(?err, "Failed to set config 'edge_snap_threshold'");
} }
} }
} Message::Surface(a) => {
return cosmic::task::message(crate::app::Message::Surface(a));
}
};
cosmic::iced::Task::none()
} }
} }
@ -233,13 +239,20 @@ pub fn window_management() -> Section<crate::pages::Message> {
settings::section() settings::section()
.title(&section.title) .title(&section.title)
.add( .add(settings::item::builder(&descriptions[super_key]).control(
settings::item::builder(&descriptions[super_key]).control(widget::dropdown( widget::dropdown::popup_dropdown(
&page.super_key_selections, &page.super_key_selections,
page.super_key_active, page.super_key_active,
Message::SuperKey, Message::SuperKey,
)), cosmic::iced::window::Id::RESERVED,
) Message::Surface,
|a| {
crate::app::Message::PageMessage(
crate::pages::Message::WindowManagement(a),
)
},
),
))
.add(settings::flex_item( .add(settings::flex_item(
&descriptions[edge_gravity], &descriptions[edge_gravity],
toggler(page.edge_snap_threshold != 0).on_toggle(|is_enabled| { toggler(page.edge_snap_threshold != 0).on_toggle(|is_enabled| {
@ -310,7 +323,7 @@ pub fn focus_navigation() -> Section<crate::pages::Message> {
}) })
.select_on_focus(true) .select_on_focus(true)
.on_input(Message::SetFocusFollowsCursorDelay) .on_input(Message::SetFocusFollowsCursorDelay)
.on_submit(Message::SaveFocusFollowsCursorDelay(true)) .on_submit(|_| Message::SaveFocusFollowsCursorDelay(true))
.width(Length::Fixed(80.0)), .width(Length::Fixed(80.0)),
)) ))
.add(settings::item( .add(settings::item(

View file

@ -11,7 +11,7 @@ use cosmic::iced_widget::scrollable::{Direction, RelativeOffset, Scrollbar};
use cosmic::widget::{ use cosmic::widget::{
self, column, container, dropdown, list_column, segmented_button, tab_bar, text, toggler, self, column, container, dropdown, list_column, segmented_button, tab_bar, text, toggler,
}; };
use cosmic::{Apply, Element, Task}; use cosmic::{surface, Apply, Element, Task};
use cosmic_config::{ConfigGet, ConfigSet}; use cosmic_config::{ConfigGet, ConfigSet};
use cosmic_randr_shell::{ use cosmic_randr_shell::{
AdaptiveSyncAvailability, AdaptiveSyncState, List, Output, OutputKey, Transform, AdaptiveSyncAvailability, AdaptiveSyncState, List, Output, OutputKey, Transform,
@ -108,6 +108,7 @@ pub enum Message {
randr: Arc<Result<List, cosmic_randr_shell::Error>>, randr: Arc<Result<List, cosmic_randr_shell::Error>>,
}, },
SetXwaylandDescaling(bool), SetXwaylandDescaling(bool),
Surface(surface::Action),
} }
impl From<Message> for app::Message { impl From<Message> for app::Message {
@ -626,6 +627,10 @@ impl Page {
error!(?err, "Failed to set config 'descale_xwayland'"); error!(?err, "Failed to set config 'descale_xwayland'");
} }
} }
Message::Surface(a) => {
return cosmic::task::message(crate::app::Message::Surface(a));
}
} }
self.last_pan = 0.5; self.last_pan = 0.5;
@ -1226,18 +1231,28 @@ pub fn display_configuration() -> Section<crate::pages::Message> {
let mut items = vec![ let mut items = vec![
widget::settings::item( widget::settings::item(
&descriptions[resolution], &descriptions[resolution],
dropdown( dropdown::popup_dropdown(
&page.cache.resolutions, &page.cache.resolutions,
page.cache.resolution_selected, page.cache.resolution_selected,
Message::Resolution, Message::Resolution,
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(crate::pages::Message::Displays(a))
},
), ),
), ),
widget::settings::item( widget::settings::item(
&descriptions[refresh_rate], &descriptions[refresh_rate],
dropdown( dropdown::popup_dropdown(
&page.cache.refresh_rates, &page.cache.refresh_rates,
page.cache.refresh_rate_selected, page.cache.refresh_rate_selected,
Message::RefreshRate, Message::RefreshRate,
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(crate::pages::Message::Displays(a))
},
), ),
), ),
]; ];
@ -1245,10 +1260,15 @@ pub fn display_configuration() -> Section<crate::pages::Message> {
if let Some(vrr_selected) = page.cache.vrr_selected { if let Some(vrr_selected) = page.cache.vrr_selected {
items.push(widget::settings::item( items.push(widget::settings::item(
&descriptions[vrr], &descriptions[vrr],
dropdown( dropdown::popup_dropdown(
&page.cache.vrr_modes, &page.cache.vrr_modes,
Some(vrr_selected), Some(vrr_selected),
Message::VariableRefreshRate, Message::VariableRefreshRate,
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(crate::pages::Message::Displays(a))
},
), ),
)); ));
} }
@ -1256,7 +1276,16 @@ pub fn display_configuration() -> Section<crate::pages::Message> {
items.extend(vec![ items.extend(vec![
widget::settings::item( widget::settings::item(
&descriptions[scale], &descriptions[scale],
dropdown(&DPI_SCALE_LABELS, page.cache.scale_selected, Message::Scale), dropdown::popup_dropdown(
&DPI_SCALE_LABELS,
page.cache.scale_selected,
Message::Scale,
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(crate::pages::Message::Displays(a))
},
),
), ),
widget::settings::item( widget::settings::item(
&descriptions[additional_scale_options], &descriptions[additional_scale_options],
@ -1271,7 +1300,7 @@ pub fn display_configuration() -> Section<crate::pages::Message> {
), ),
widget::settings::item( widget::settings::item(
&descriptions[orientation], &descriptions[orientation],
dropdown( dropdown::popup_dropdown(
&page.cache.orientations, &page.cache.orientations,
page.cache.orientation_selected, page.cache.orientation_selected,
|id| { |id| {
@ -1282,6 +1311,11 @@ pub fn display_configuration() -> Section<crate::pages::Message> {
_ => Transform::Rotate270, _ => Transform::Rotate270,
}) })
}, },
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(crate::pages::Message::Displays(a))
},
), ),
), ),
]); ]);

View file

@ -516,7 +516,7 @@ fn context_drawer(
}) })
.select_on_focus(true) .select_on_focus(true)
.on_input(move |text| ShortcutMessage::InputBinding(bind_id, text)) .on_input(move |text| ShortcutMessage::InputBinding(bind_id, text))
.on_submit(ShortcutMessage::SubmitBinding(bind_id)) .on_submit(move |_| ShortcutMessage::SubmitBinding(bind_id))
.padding([0, space_xs]) .padding([0, space_xs])
.id(shortcut.id.clone()) .id(shortcut.id.clone())
.into(); .into();

View file

@ -231,13 +231,13 @@ impl Page {
let name_input = widget::text_input("", &self.add_shortcut.name) let name_input = widget::text_input("", &self.add_shortcut.name)
.padding([6, 12]) .padding([6, 12])
.on_input(Message::NameInput) .on_input(Message::NameInput)
.on_submit(Message::NameSubmit) .on_submit(|_| Message::NameSubmit)
.id(self.name_id.clone()); .id(self.name_id.clone());
let task_input = widget::text_input("", &self.add_shortcut.task) let task_input = widget::text_input("", &self.add_shortcut.task)
.padding([6, 12]) .padding([6, 12])
.on_input(Message::TaskInput) .on_input(Message::TaskInput)
.on_submit(Message::EditCombination) .on_submit(|_| Message::EditCombination)
.id(self.task_id.clone()); .id(self.task_id.clone());
let name_control = widget::column() let name_control = widget::column()
@ -267,7 +267,7 @@ impl Page {
) )
.padding([0, 12]) .padding([0, 12])
.on_input(move |input| Message::KeyInput(id, input)) .on_input(move |input| Message::KeyInput(id, input))
.on_submit(Message::AddKeybinding) .on_submit(|_| Message::AddKeybinding)
.id(widget_id.clone()) .id(widget_id.clone())
.apply(widget::container) .apply(widget::container)
.padding([8, 24]); .padding([8, 24]);

View file

@ -250,7 +250,7 @@ impl page::Page<crate::pages::Message> for Page {
*password_hidden, *password_hidden,
) )
.on_input(|input| Message::PasswordUpdate(SecureString::from(input))) .on_input(|input| Message::PasswordUpdate(SecureString::from(input)))
.on_submit(Message::ConnectWithPassword); .on_submit(|_| Message::ConnectWithPassword);
let controls = widget::column::with_capacity(2) let controls = widget::column::with_capacity(2)
.spacing(12) .spacing(12)

View file

@ -145,7 +145,7 @@ impl page::Page<crate::pages::Message> for Page {
*password_hidden, *password_hidden,
) )
.on_input(|input| Message::PasswordUpdate(SecureString::from(input))) .on_input(|input| Message::PasswordUpdate(SecureString::from(input)))
.on_submit(Message::ConnectWithPassword); .on_submit(|_| Message::ConnectWithPassword);
let primary_action = widget::button::suggested(fl!("connect")) let primary_action = widget::button::suggested(fl!("connect"))
.on_press(Message::ConnectWithPassword); .on_press(Message::ConnectWithPassword);

View file

@ -7,8 +7,8 @@ use chrono::TimeDelta;
use cosmic::iced::{Alignment, Length}; use cosmic::iced::{Alignment, Length};
use cosmic::iced_widget::{column, row}; use cosmic::iced_widget::{column, row};
use cosmic::widget::{self, radio, settings, text}; use cosmic::widget::{self, radio, settings, text};
use cosmic::Apply;
use cosmic::Task; use cosmic::Task;
use cosmic::{surface, Apply};
use cosmic_config::{Config, CosmicConfigEntry}; use cosmic_config::{Config, CosmicConfigEntry};
use cosmic_idle_config::CosmicIdleConfig; use cosmic_idle_config::CosmicIdleConfig;
use cosmic_settings_page::{self as page, section, Section}; use cosmic_settings_page::{self as page, section, Section};
@ -193,10 +193,11 @@ pub enum Message {
ScreenOffTimeChange(Option<Duration>), ScreenOffTimeChange(Option<Duration>),
SuspendOnAcTimeChange(Option<Duration>), SuspendOnAcTimeChange(Option<Duration>),
SuspendOnBatteryTimeChange(Option<Duration>), SuspendOnBatteryTimeChange(Option<Duration>),
Surface(surface::Action),
} }
impl Page { impl Page {
pub fn update(&mut self, message: Message) { pub fn update(&mut self, message: Message) -> Task<crate::app::Message> {
let runtime = tokio::runtime::Runtime::new().unwrap(); let runtime = tokio::runtime::Runtime::new().unwrap();
let backend = runtime.block_on(backend::get_backend()); let backend = runtime.block_on(backend::get_backend());
@ -241,7 +242,11 @@ impl Page {
Message::DeviceConnect(connected_device) => { Message::DeviceConnect(connected_device) => {
self.connected_devices.push(connected_device) self.connected_devices.push(connected_device)
} }
Message::Surface(a) => {
return cosmic::task::message(crate::app::Message::Surface(a));
}
}; };
Task::none()
} }
} }
@ -417,7 +422,14 @@ fn power_saving_row<'a>(
settings::item( settings::item(
label, label,
widget::dropdown(labels, selected, move |i| on_select(times.get(i).copied())), widget::dropdown::popup_dropdown(
labels,
selected,
move |i| on_select(times.get(i).copied()),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::Power(a)),
),
) )
.into() .into()
} }

View file

@ -4,7 +4,8 @@
use std::{collections::BTreeMap, time::Duration}; use std::{collections::BTreeMap, time::Duration};
use cosmic::{ use cosmic::{
iced::{Alignment, Length}, iced::{window, Alignment, Length},
surface,
widget::{self, settings}, widget::{self, settings},
Element, Task, Element, Task,
}; };
@ -48,6 +49,8 @@ pub enum Message {
SourceVolumeApply(NodeId), SourceVolumeApply(NodeId),
/// Toggle the mute status of the input output. /// Toggle the mute status of the input output.
SourceMuteToggle, SourceMuteToggle,
/// Surface Action
Surface(surface::Action),
} }
#[derive(Debug)] #[derive(Debug)]
@ -315,7 +318,6 @@ impl Page {
return command; return command;
} }
} }
Message::Pulse(pulse::Event::SourceVolume(volume)) => { Message::Pulse(pulse::Event::SourceVolume(volume)) => {
if self.sink_volume_debounce { if self.sink_volume_debounce {
return Task::none(); return Task::none();
@ -324,7 +326,6 @@ impl Page {
self.source_volume = volume; self.source_volume = volume;
self.source_volume_text = volume.to_string(); self.source_volume_text = volume.to_string();
} }
Message::SinkVolumeChanged(volume) => { Message::SinkVolumeChanged(volume) => {
self.sink_volume = volume; self.sink_volume = volume;
self.sink_volume_text = volume.to_string(); self.sink_volume_text = volume.to_string();
@ -345,7 +346,6 @@ impl Page {
return command; return command;
} }
} }
Message::Pulse(pulse::Event::SinkVolume(volume)) => { Message::Pulse(pulse::Event::SinkVolume(volume)) => {
if self.sink_volume_debounce { if self.sink_volume_debounce {
return Task::none(); return Task::none();
@ -354,27 +354,22 @@ impl Page {
self.sink_volume = volume; self.sink_volume = volume;
self.sink_volume_text = volume.to_string(); self.sink_volume_text = volume.to_string();
} }
Message::Pulse(pulse::Event::DefaultSink(sink)) => { Message::Pulse(pulse::Event::DefaultSink(sink)) => {
if !self.changing_sink_profile { if !self.changing_sink_profile {
self.set_default_sink(sink); self.set_default_sink(sink);
} }
} }
Message::Pulse(pulse::Event::DefaultSource(source)) => { Message::Pulse(pulse::Event::DefaultSource(source)) => {
if !self.changing_source_profile { if !self.changing_source_profile {
self.set_default_source(source); self.set_default_source(source);
} }
} }
Message::Pulse(pulse::Event::SinkMute(mute)) => { Message::Pulse(pulse::Event::SinkMute(mute)) => {
self.sink_mute = mute; self.sink_mute = mute;
} }
Message::Pulse(pulse::Event::SourceMute(mute)) => { Message::Pulse(pulse::Event::SourceMute(mute)) => {
self.source_mute = mute; self.source_mute = mute;
} }
Message::Pulse(pulse::Event::CardInfo(card)) => { Message::Pulse(pulse::Event::CardInfo(card)) => {
let device_id = match card.variant { let device_id = match card.variant {
pulse::DeviceVariant::Alsa { alsa_card, .. } => DeviceId::Alsa(alsa_card), pulse::DeviceVariant::Alsa { alsa_card, .. } => DeviceId::Alsa(alsa_card),
@ -386,7 +381,6 @@ impl Page {
self.active_profiles self.active_profiles
.insert(device_id, card.active_profile.map(|p| p.name)); .insert(device_id, card.active_profile.map(|p| p.name));
} }
Message::Pipewire(pipewire::DeviceEvent::Add(device)) => { Message::Pipewire(pipewire::DeviceEvent::Add(device)) => {
let device_id = match device.variant { let device_id = match device.variant {
pipewire::DeviceVariant::Alsa { alsa_card, .. } => DeviceId::Alsa(alsa_card), pipewire::DeviceVariant::Alsa { alsa_card, .. } => DeviceId::Alsa(alsa_card),
@ -439,7 +433,6 @@ impl Page {
card.devices card.devices
.sort_unstable_by(|_, av, _, bv| av.description.cmp(&bv.description)); .sort_unstable_by(|_, av, _, bv| av.description.cmp(&bv.description));
} }
Message::Pipewire(pipewire::DeviceEvent::Remove(node_id)) => { Message::Pipewire(pipewire::DeviceEvent::Remove(node_id)) => {
let mut remove = None; let mut remove = None;
for (card_id, card) in &mut self.devices { for (card_id, card) in &mut self.devices {
@ -473,7 +466,6 @@ impl Page {
} }
} }
} }
Message::SinkChanged(pos) => { Message::SinkChanged(pos) => {
if let Some(node_id) = self.sink_ids.get(pos) { if let Some(node_id) = self.sink_ids.get(pos) {
for card in self.devices.values() { for card in self.devices.values() {
@ -488,7 +480,6 @@ impl Page {
} }
} }
} }
Message::SourceChanged(pos) => { Message::SourceChanged(pos) => {
if let Some(node_id) = self.source_ids.get(pos) { if let Some(node_id) = self.source_ids.get(pos) {
for card in self.devices.values() { for card in self.devices.values() {
@ -503,31 +494,26 @@ impl Page {
} }
} }
} }
Message::SinkVolumeApply(node_id) => { Message::SinkVolumeApply(node_id) => {
self.sink_volume_debounce = false; self.sink_volume_debounce = false;
wpctl_set_volume(node_id, self.sink_volume); wpctl_set_volume(node_id, self.sink_volume);
} }
Message::SourceVolumeApply(node_id) => { Message::SourceVolumeApply(node_id) => {
self.source_volume_debounce = false; self.source_volume_debounce = false;
wpctl_set_volume(node_id, self.source_volume); wpctl_set_volume(node_id, self.source_volume);
} }
Message::SinkMuteToggle => { Message::SinkMuteToggle => {
self.sink_mute = !self.sink_mute; self.sink_mute = !self.sink_mute;
if let Some(&node_id) = self.sink_ids.get(self.active_sink.unwrap_or(0)) { if let Some(&node_id) = self.sink_ids.get(self.active_sink.unwrap_or(0)) {
wpctl_set_mute(node_id, self.sink_mute); wpctl_set_mute(node_id, self.sink_mute);
} }
} }
Message::SourceMuteToggle => { Message::SourceMuteToggle => {
self.source_mute = !self.source_mute; self.source_mute = !self.source_mute;
if let Some(&node_id) = self.source_ids.get(self.active_source.unwrap_or(0)) { if let Some(&node_id) = self.source_ids.get(self.active_source.unwrap_or(0)) {
wpctl_set_mute(node_id, self.source_mute); wpctl_set_mute(node_id, self.source_mute);
} }
} }
Message::SinkProfileChanged(profile) => { Message::SinkProfileChanged(profile) => {
self.active_sink_profile = Some(profile); self.active_sink_profile = Some(profile);
@ -548,7 +534,6 @@ impl Page {
} }
} }
} }
Message::SinkProfileSelect(device_id) => { Message::SinkProfileSelect(device_id) => {
self.changing_sink_profile = false; self.changing_sink_profile = false;
let sink_pos = self.active_sink.unwrap_or(0); let sink_pos = self.active_sink.unwrap_or(0);
@ -560,7 +545,6 @@ impl Page {
} }
} }
} }
Message::SourceProfileChanged(profile) => { Message::SourceProfileChanged(profile) => {
self.active_source_profile = Some(profile); self.active_source_profile = Some(profile);
if let Some(profile) = self.source_profile_names.get(profile).cloned() { if let Some(profile) = self.source_profile_names.get(profile).cloned() {
@ -580,7 +564,6 @@ impl Page {
} }
} }
} }
Message::SourceProfileSelect(device_id) => { Message::SourceProfileSelect(device_id) => {
self.changing_source_profile = false; self.changing_source_profile = false;
let source_pos = self.active_source.unwrap_or(0); let source_pos = self.active_source.unwrap_or(0);
@ -592,6 +575,9 @@ impl Page {
} }
} }
} }
Message::Surface(a) => {
return cosmic::task::message(crate::app::Message::Surface(a));
}
} }
Task::none() Task::none()
} }
@ -629,11 +615,13 @@ fn input() -> Section<crate::pages::Message> {
widget::slider(0..=150, page.source_volume, Message::SourceVolumeChanged) widget::slider(0..=150, page.source_volume, Message::SourceVolumeChanged)
.breakpoints(&[100]), .breakpoints(&[100]),
); );
let mut devices = widget::dropdown::popup_dropdown(
let devices = widget::dropdown(
&page.sources, &page.sources,
Some(page.active_source.unwrap_or(0)), Some(page.active_source.unwrap_or(0)),
Message::SourceChanged, Message::SourceChanged,
window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::Sound(a)),
); );
let mut controls = settings::section() let mut controls = settings::section()
@ -645,10 +633,13 @@ fn input() -> Section<crate::pages::Message> {
.add(settings::item(&*section.descriptions[device], devices)); .add(settings::item(&*section.descriptions[device], devices));
if !page.source_profiles.is_empty() { if !page.source_profiles.is_empty() {
let dropdown = widget::dropdown( let mut dropdown = widget::dropdown::popup_dropdown(
&page.source_profiles, &page.source_profiles,
page.active_source_profile, page.active_source_profile,
Message::SourceProfileChanged, Message::SourceProfileChanged,
window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::Sound(a)),
); );
controls = controls.add(settings::item(&*section.descriptions[profile], dropdown)); controls = controls.add(settings::item(&*section.descriptions[profile], dropdown));
@ -692,10 +683,13 @@ fn output() -> Section<crate::pages::Message> {
.breakpoints(&[100]), .breakpoints(&[100]),
); );
let devices = widget::dropdown( let devices = widget::dropdown::popup_dropdown(
&page.sinks, &page.sinks,
Some(page.active_sink.unwrap_or(0)), Some(page.active_sink.unwrap_or(0)),
Message::SinkChanged, Message::SinkChanged,
window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::Sound(a)),
); );
let mut controls = settings::section() let mut controls = settings::section()
@ -707,10 +701,13 @@ fn output() -> Section<crate::pages::Message> {
.add(settings::item(&*section.descriptions[device], devices)); .add(settings::item(&*section.descriptions[device], devices));
if !page.sink_profiles.is_empty() { if !page.sink_profiles.is_empty() {
let dropdown = widget::dropdown( let dropdown = widget::dropdown::popup_dropdown(
&page.sink_profiles, &page.sink_profiles,
page.active_sink_profile, page.active_sink_profile,
Message::SinkProfileChanged, Message::SinkProfileChanged,
window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::Sound(a)),
); );
controls = controls.add(settings::item(&*section.descriptions[profile], dropdown)); controls = controls.add(settings::item(&*section.descriptions[profile], dropdown));

View file

@ -182,7 +182,7 @@ fn device() -> Section<crate::pages::Message> {
) )
.width(250) .width(250)
.on_input(Message::HostnameInput) .on_input(Message::HostnameInput)
.on_submit(Message::HostnameSubmit); .on_submit(|_| Message::HostnameSubmit);
let device_name = settings::item::builder(&*desc[device]) let device_name = settings::item::builder(&*desc[device])
.description(&*desc[device_desc]) .description(&*desc[device_desc])

View file

@ -9,6 +9,7 @@ use std::{
}; };
use cosmic::{ use cosmic::{
surface,
widget::{self, dropdown, icon, settings}, widget::{self, dropdown, icon, settings},
Apply, Element, Task, Apply, Element, Task,
}; };
@ -50,6 +51,7 @@ pub enum Category {
pub enum Message { pub enum Message {
SetDefault(Category, usize), SetDefault(Category, usize),
Update(CachedMimeApps), Update(CachedMimeApps),
Surface(surface::Action),
} }
impl From<Message> for crate::app::Message { impl From<Message> for crate::app::Message {
@ -267,10 +269,12 @@ impl Page {
_ = std::process::Command::new("update-desktop-database").status(); _ = std::process::Command::new("update-desktop-database").status();
} }
} }
Message::Update(mime_apps) => { Message::Update(mime_apps) => {
self.mime_apps = Some(mime_apps); self.mime_apps = Some(mime_apps);
} }
Message::Surface(a) => {
return cosmic::task::message(crate::app::Message::Surface(a));
}
} }
Task::none() Task::none()
@ -289,9 +293,14 @@ fn apps() -> Section<crate::pages::Message> {
let meta = &mime_apps.apps[DROPDOWN_WEB_BROWSER]; let meta = &mime_apps.apps[DROPDOWN_WEB_BROWSER];
settings::flex_item( settings::flex_item(
fl!("default-apps", "web-browser"), fl!("default-apps", "web-browser"),
dropdown(&meta.apps, meta.selected, |id| { dropdown::popup_dropdown(
Message::SetDefault(Category::WebBrowser, id) &meta.apps,
}) meta.selected,
|id| Message::SetDefault(Category::WebBrowser, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::DefaultApps(a)),
)
.icons(&meta.icons), .icons(&meta.icons),
) )
.min_item_width(300.0) .min_item_width(300.0)
@ -300,9 +309,14 @@ fn apps() -> Section<crate::pages::Message> {
let meta = &mime_apps.apps[DROPDOWN_FILE_MANAGER]; let meta = &mime_apps.apps[DROPDOWN_FILE_MANAGER];
settings::flex_item( settings::flex_item(
fl!("default-apps", "file-manager"), fl!("default-apps", "file-manager"),
dropdown(&meta.apps, meta.selected, |id| { dropdown::popup_dropdown(
Message::SetDefault(Category::FileManager, id) &meta.apps,
}) meta.selected,
|id| Message::SetDefault(Category::FileManager, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::DefaultApps(a)),
)
.icons(&meta.icons), .icons(&meta.icons),
) )
}) })
@ -310,9 +324,14 @@ fn apps() -> Section<crate::pages::Message> {
let meta = &mime_apps.apps[DROPDOWN_MAIL]; let meta = &mime_apps.apps[DROPDOWN_MAIL];
settings::flex_item( settings::flex_item(
fl!("default-apps", "mail-client"), fl!("default-apps", "mail-client"),
dropdown(&meta.apps, meta.selected, |id| { dropdown::popup_dropdown(
Message::SetDefault(Category::Mail, id) &meta.apps,
}) meta.selected,
|id| Message::SetDefault(Category::Mail, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::DefaultApps(a)),
)
.icons(&meta.icons), .icons(&meta.icons),
) )
}) })
@ -320,9 +339,14 @@ fn apps() -> Section<crate::pages::Message> {
let meta = &mime_apps.apps[DROPDOWN_MUSIC]; let meta = &mime_apps.apps[DROPDOWN_MUSIC];
settings::flex_item( settings::flex_item(
fl!("default-apps", "music"), fl!("default-apps", "music"),
dropdown(&meta.apps, meta.selected, |id| { dropdown::popup_dropdown(
Message::SetDefault(Category::Audio, id) &meta.apps,
}) meta.selected,
|id| Message::SetDefault(Category::Audio, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::DefaultApps(a)),
)
.icons(&meta.icons), .icons(&meta.icons),
) )
}) })
@ -330,9 +354,14 @@ fn apps() -> Section<crate::pages::Message> {
let meta = &mime_apps.apps[DROPDOWN_VIDEO]; let meta = &mime_apps.apps[DROPDOWN_VIDEO];
settings::flex_item( settings::flex_item(
fl!("default-apps", "video"), fl!("default-apps", "video"),
dropdown(&meta.apps, meta.selected, |id| { dropdown::popup_dropdown(
Message::SetDefault(Category::Video, id) &meta.apps,
}) meta.selected,
|id| Message::SetDefault(Category::Video, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::DefaultApps(a)),
)
.icons(&meta.icons), .icons(&meta.icons),
) )
}) })
@ -340,9 +369,14 @@ fn apps() -> Section<crate::pages::Message> {
let meta = &mime_apps.apps[DROPDOWN_PHOTO]; let meta = &mime_apps.apps[DROPDOWN_PHOTO];
settings::flex_item( settings::flex_item(
fl!("default-apps", "photos"), fl!("default-apps", "photos"),
dropdown(&meta.apps, meta.selected, |id| { dropdown::popup_dropdown(
Message::SetDefault(Category::Image, id) &meta.apps,
}) meta.selected,
|id| Message::SetDefault(Category::Image, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::DefaultApps(a)),
)
.icons(&meta.icons), .icons(&meta.icons),
) )
}) })
@ -350,9 +384,14 @@ fn apps() -> Section<crate::pages::Message> {
let meta = &mime_apps.apps[DROPDOWN_CALENDAR]; let meta = &mime_apps.apps[DROPDOWN_CALENDAR];
settings::flex_item( settings::flex_item(
fl!("default-apps", "calendar"), fl!("default-apps", "calendar"),
dropdown(&meta.apps, meta.selected, |id| { dropdown::popup_dropdown(
Message::SetDefault(Category::Calendar, id) &meta.apps,
}) meta.selected,
|id| Message::SetDefault(Category::Calendar, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::DefaultApps(a)),
)
.icons(&meta.icons), .icons(&meta.icons),
) )
}) })
@ -360,9 +399,14 @@ fn apps() -> Section<crate::pages::Message> {
let meta = &mime_apps.apps[DROPDOWN_TERMINAL]; let meta = &mime_apps.apps[DROPDOWN_TERMINAL];
settings::flex_item( settings::flex_item(
fl!("default-apps", "terminal"), fl!("default-apps", "terminal"),
dropdown(&meta.apps, meta.selected, |id| { dropdown::popup_dropdown(
Message::SetDefault(Category::Terminal, id) &meta.apps,
}) meta.selected,
|id| Message::SetDefault(Category::Terminal, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::DefaultApps(a)),
)
.icons(&meta.icons), .icons(&meta.icons),
) )
}) })
@ -370,9 +414,14 @@ fn apps() -> Section<crate::pages::Message> {
let meta = &mime_apps.apps[DROPDOWN_TEXT_EDITOR]; let meta = &mime_apps.apps[DROPDOWN_TEXT_EDITOR];
settings::flex_item( settings::flex_item(
fl!("default-apps", "text-editor"), fl!("default-apps", "text-editor"),
dropdown(&meta.apps, meta.selected, |id| { dropdown::popup_dropdown(
Message::SetDefault(Category::TextEditor, id) &meta.apps,
}) meta.selected,
|id| Message::SetDefault(Category::TextEditor, id),
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| crate::app::Message::PageMessage(crate::pages::Message::DefaultApps(a)),
)
.icons(&meta.icons), .icons(&meta.icons),
) )
}) })

View file

@ -600,14 +600,14 @@ fn user_list() -> Section<crate::pages::Message> {
Message::ToggleEdit(idx, EditorField::Username) Message::ToggleEdit(idx, EditorField::Username)
}) })
.on_input(move |name| Message::Edit(idx, EditorField::Username, name)) .on_input(move |name| Message::Edit(idx, EditorField::Username, name))
.on_submit(Message::ApplyEdit(idx, EditorField::Username)); .on_submit(move |_| Message::ApplyEdit(idx, EditorField::Username));
let password = let password =
widget::editable_input("", &user.password, user.password_edit, move |_| { widget::editable_input("", &user.password, user.password_edit, move |_| {
Message::ToggleEdit(idx, EditorField::Password) Message::ToggleEdit(idx, EditorField::Password)
}) })
.on_input(move |pass| Message::Edit(idx, EditorField::Password, pass)) .on_input(move |pass| Message::Edit(idx, EditorField::Password, pass))
.on_submit(Message::ApplyEdit(idx, EditorField::Password)) .on_submit(move |_| Message::ApplyEdit(idx, EditorField::Password))
.password(); .password();
let fullname = widget::editable_input( let fullname = widget::editable_input(
@ -617,7 +617,7 @@ fn user_list() -> Section<crate::pages::Message> {
move |_| Message::ToggleEdit(idx, EditorField::FullName), move |_| Message::ToggleEdit(idx, EditorField::FullName),
) )
.on_input(move |name| Message::Edit(idx, EditorField::FullName, name)) .on_input(move |name| Message::Edit(idx, EditorField::FullName, name))
.on_submit(Message::ApplyEdit(idx, EditorField::FullName)); .on_submit(move |_| Message::ApplyEdit(idx, EditorField::FullName));
let fullname_text = text::body(&user.full_name); let fullname_text = text::body(&user.full_name);

View file

@ -7,6 +7,7 @@ use chrono::{Datelike, Timelike};
use cosmic::{ use cosmic::{
cosmic_config::{self, ConfigGet, ConfigSet}, cosmic_config::{self, ConfigGet, ConfigSet},
iced_core::text::Wrapping, iced_core::text::Wrapping,
surface,
widget::{self, dropdown, settings}, widget::{self, dropdown, settings},
Apply, Element, Task, Apply, Element, Task,
}; };
@ -276,6 +277,10 @@ impl Page {
self.update_local_time(); self.update_local_time();
} }
Message::Surface(a) => {
return cosmic::task::message(crate::app::Message::Surface(a));
}
Message::None => (), Message::None => (),
} }
@ -365,6 +370,7 @@ pub enum Message {
TimezoneContext, TimezoneContext,
TimezoneSearch(String), TimezoneSearch(String),
UpdateTime, UpdateTime,
Surface(surface::Action),
} }
impl page::AutoBind<crate::pages::Message> for Page {} impl page::AutoBind<crate::pages::Message> for Page {}
@ -416,23 +422,32 @@ fn format() -> Section<crate::pages::Message> {
) )
// First day of week // First day of week
.add( .add(
settings::item::builder(&section.descriptions[first]).control(dropdown( settings::item::builder(&section.descriptions[first]).control(
&*WEEKDAYS, dropdown::popup_dropdown(
match page.first_day_of_week { &*WEEKDAYS,
4 => Some(0), // friday match page.first_day_of_week {
5 => Some(1), // saturday 4 => Some(0), // friday
0 => Some(3), // monday 5 => Some(1), // saturday
_ => Some(2), // sunday 0 => Some(3), // monday
}, _ => Some(2), // sunday
|v| { },
match v { |v| {
0 => Message::FirstDayOfWeek(4), // friday match v {
1 => Message::FirstDayOfWeek(5), // saturday 0 => Message::FirstDayOfWeek(4), // friday
3 => Message::FirstDayOfWeek(0), // monday 1 => Message::FirstDayOfWeek(5), // saturday
_ => Message::FirstDayOfWeek(6), // sunday 3 => Message::FirstDayOfWeek(0), // monday
} _ => Message::FirstDayOfWeek(6), // sunday
}, }
)), },
cosmic::iced::window::Id::RESERVED,
Message::Surface,
|a| {
crate::app::Message::PageMessage(
crate::pages::Message::DateAndTime(a),
)
},
),
),
) )
// Date on top panel toggle // Date on top panel toggle
.add( .add(