update libcosmic

this uses a subsurface for the greeter menu and a text input that manages its own input string state
This commit is contained in:
Ashley Wulber 2025-02-21 17:05:50 -05:00 committed by Jeremy Soller
parent 5527c9b866
commit 7918485651
9 changed files with 2440 additions and 1464 deletions

2685
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -13,7 +13,15 @@ cosmic-greeter-daemon = { path = "daemon" }
dirs = "5" dirs = "5"
env_logger.workspace = true env_logger.workspace = true
freedesktop_entry_parser = "1.3.0" freedesktop_entry_parser = "1.3.0"
libcosmic = { workspace = true, features = ["tokio", "wayland"] } libcosmic = { workspace = true, features = [
"autosize",
"winit",
"multi-window",
"desktop",
"wayland",
"tokio",
"dbus-config",
] }
log.workspace = true log.workspace = true
pam-client = "0.5.0" pam-client = "0.5.0"
pwd.workspace = true pwd.workspace = true
@ -81,6 +89,7 @@ serde = "1"
tokio = "1.39.1" tokio = "1.39.1"
zbus = "4" zbus = "4"
[workspace.dependencies.cosmic-bg-config] [workspace.dependencies.cosmic-bg-config]
git = "https://github.com/pop-os/cosmic-bg" git = "https://github.com/pop-os/cosmic-bg"
default-features = false default-features = false
@ -103,3 +112,11 @@ default-features = false
[workspace.dependencies.libcosmic] [workspace.dependencies.libcosmic]
git = "https://github.com/pop-os/libcosmic" git = "https://github.com/pop-os/libcosmic"
default-features = false default-features = false
[patch.'https://github.com/pop-os/libcosmic']
libcosmic = { git = "https://github.com/pop-os/libcosmic//", branch = "drop-menu-tree-changes" }
cosmic-config = { git = "https://github.com/pop-os/libcosmic//", branch = "drop-menu-tree-changes" }
cosmic-theme = { git = "https://github.com/pop-os/libcosmic//", branch = "drop-menu-tree-changes" }
# libcosmic = { path = "../libcosmic" }
# cosmic-config = { path = "../libcosmic/cosmic-config" }
# cosmic-theme = { path = "../libcosmic/cosmic-theme" }

File diff suppressed because it is too large Load diff

View file

@ -11,10 +11,9 @@ use tokio::sync::mpsc;
pub fn subscription() -> Subscription<Message> { pub fn subscription() -> Subscription<Message> {
struct GreetdSubscription; struct GreetdSubscription;
cosmic::iced::subscription::channel( Subscription::run_with_id(
std::any::TypeId::of::<GreetdSubscription>(), std::any::TypeId::of::<GreetdSubscription>(),
1, cosmic::iced_futures::stream::channel(1, |mut sender| async move {
|mut sender| async move {
let (tx, mut rx) = mpsc::channel::<greetd_ipc::Request>(1); let (tx, mut rx) = mpsc::channel::<greetd_ipc::Request>(1);
_ = sender.send(Message::GreetdChannel(tx)).await; _ = sender.send(Message::GreetdChannel(tx)).await;
@ -123,6 +122,6 @@ pub fn subscription() -> Subscription<Message> {
} }
futures_util::future::pending().await futures_util::future::pending().await
}, }),
) )
} }

View file

@ -1,8 +1,11 @@
use cosmic::iced::widget::{
image::{draw, FilterMethod, Handle},
Container,
};
use cosmic::iced::ContentFit; use cosmic::iced::ContentFit;
use cosmic::iced::{
widget::{
image::{draw, FilterMethod, Handle},
Container,
},
Rotation,
};
use cosmic::iced_core::event::{self, Event}; use cosmic::iced_core::event::{self, Event};
use cosmic::iced_core::layout; use cosmic::iced_core::layout;
use cosmic::iced_core::mouse; use cosmic::iced_core::mouse;
@ -10,26 +13,16 @@ use cosmic::iced_core::overlay;
use cosmic::iced_core::renderer; use cosmic::iced_core::renderer;
use cosmic::iced_core::widget::{Operation, Tree}; use cosmic::iced_core::widget::{Operation, Tree};
use cosmic::iced_core::{Clipboard, Element, Layout, Length, Rectangle, Shell, Size, Widget}; use cosmic::iced_core::{Clipboard, Element, Layout, Length, Rectangle, Shell, Size, Widget};
use cosmic::iced_renderer::core::widget::OperationOutputWrapper; use cosmic::{Renderer, Theme};
pub use cosmic::iced_style::container::StyleSheet; pub struct ImageContainer<'a, Message> {
pub struct ImageContainer<'a, Message, Theme, Renderer>
where
Renderer: cosmic::iced_core::Renderer + cosmic::iced_core::image::Renderer<Handle = Handle>,
Theme: StyleSheet,
{
container: Container<'a, Message, Theme, Renderer>, container: Container<'a, Message, Theme, Renderer>,
image_opt: Option<Handle>, image_opt: Option<Handle>,
content_fit: ContentFit, content_fit: ContentFit,
} }
impl<'a, Message, Renderer> ImageContainer<'a, Message, cosmic::Theme, Renderer> impl<'a, Message> ImageContainer<'a, Message> {
where pub fn new(container: Container<'a, Message, Theme, Renderer>) -> Self {
Renderer: cosmic::iced_core::Renderer + cosmic::iced_core::image::Renderer<Handle = Handle>,
cosmic::Theme: StyleSheet,
{
pub fn new(container: Container<'a, Message, cosmic::Theme, Renderer>) -> Self {
Self { Self {
container, container,
image_opt: None, image_opt: None,
@ -48,11 +41,7 @@ where
} }
} }
impl<'a, Message, Renderer> Widget<Message, cosmic::Theme, Renderer> impl<'a, Message> Widget<Message, Theme, Renderer> for ImageContainer<'a, Message> {
for ImageContainer<'a, Message, cosmic::Theme, Renderer>
where
Renderer: cosmic::iced_core::Renderer + cosmic::iced_core::image::Renderer<Handle = Handle>,
{
fn children(&self) -> Vec<Tree> { fn children(&self) -> Vec<Tree> {
self.container.children() self.container.children()
} }
@ -79,7 +68,7 @@ where
tree: &mut Tree, tree: &mut Tree,
layout: Layout<'_>, layout: Layout<'_>,
renderer: &Renderer, renderer: &Renderer,
operation: &mut dyn Operation<OperationOutputWrapper<Message>>, operation: &mut dyn Operation<()>,
) { ) {
self.container.operate(tree, layout, renderer, operation) self.container.operate(tree, layout, renderer, operation)
} }
@ -116,7 +105,7 @@ where
&self, &self,
tree: &Tree, tree: &Tree,
renderer: &mut Renderer, renderer: &mut Renderer,
theme: &cosmic::Theme, theme: &Theme,
renderer_style: &renderer::Style, renderer_style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor: mouse::Cursor, cursor: mouse::Cursor,
@ -129,42 +118,43 @@ where
image, image,
self.content_fit, self.content_fit,
FilterMethod::Linear, FilterMethod::Linear,
Rotation::default(),
1.,
[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0],
), ),
None => {} None => {}
} }
self.container.draw( use cosmic::iced_renderer::core::Renderer as IcedRenderer;
tree, renderer.with_layer(layout.bounds(), |renderer| {
renderer, self.container.draw(
theme, tree,
renderer_style, renderer,
layout, theme,
cursor, renderer_style,
viewport, layout,
) cursor,
viewport,
)
});
} }
fn overlay<'b>( fn overlay<'b>(
&'b mut self, &'b mut self,
tree: &'b mut Tree, state: &'b mut Tree,
layout: Layout<'_>, layout: Layout<'_>,
renderer: &Renderer, renderer: &Renderer,
) -> Option<overlay::Element<'b, Message, cosmic::Theme, Renderer>> { translation: cosmic::iced::Vector,
self.container.overlay(tree, layout, renderer) ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
self.container.overlay(state, layout, renderer, translation)
} }
} }
impl<'a, Message, Renderer> From<ImageContainer<'a, Message, cosmic::Theme, Renderer>> impl<'a, Message> From<ImageContainer<'a, Message>> for Element<'a, Message, Theme, Renderer>
for Element<'a, Message, cosmic::Theme, Renderer>
where where
Message: 'a, Message: 'a,
Renderer:
'a + cosmic::iced_core::Renderer + cosmic::iced_core::image::Renderer<Handle = Handle>,
{ {
fn from( fn from(container: ImageContainer<'a, Message>) -> Element<'a, Message, Theme, Renderer> {
container: ImageContainer<'a, Message, cosmic::Theme, Renderer>,
) -> Element<'a, Message, cosmic::Theme, Renderer> {
Element::new(container) Element::new(container)
} }
} }

View file

@ -1,7 +1,8 @@
// Copyright 2023 System76 <info@system76.com> // Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use cosmic::app::{message, Command, Core, Settings}; use cosmic::app::{message, Core, Settings, Task};
use cosmic::surface_message::{MessageWrapper, SurfaceMessage, SurfaceMessageHandler};
use cosmic::{ use cosmic::{
executor, executor,
iced::{ iced::{
@ -11,8 +12,9 @@ use cosmic::{
wayland::{Event as WaylandEvent, OutputEvent, SessionLockEvent}, wayland::{Event as WaylandEvent, OutputEvent, SessionLockEvent},
}, },
futures::{self, SinkExt}, futures::{self, SinkExt},
subscription, platform_specific::shell::wayland::commands::session_lock::{
wayland::session_lock::{destroy_lock_surface, get_lock_surface, lock, unlock}, destroy_lock_surface, get_lock_surface, lock, unlock,
},
Length, Subscription, Length, Subscription,
}, },
iced_runtime::core::window::Id as SurfaceId, iced_runtime::core::window::Id as SurfaceId,
@ -48,7 +50,7 @@ pub fn main(current_user: pwd::Passwd) -> Result<(), Box<dyn std::error::Error>>
let icon_path = Path::new("/var/lib/AccountsService/icons").join(&current_user.name); let icon_path = Path::new("/var/lib/AccountsService/icons").join(&current_user.name);
let icon_opt = if icon_path.is_file() { let icon_opt = if icon_path.is_file() {
match fs::read(&icon_path) { match fs::read(&icon_path) {
Ok(icon_data) => Some(widget::image::Handle::from_memory(icon_data)), Ok(icon_data) => Some(widget::image::Handle::from_bytes(icon_data)),
Err(err) => { Err(err) => {
log::error!("failed to read {:?}: {:?}", icon_path, err); log::error!("failed to read {:?}: {:?}", icon_path, err);
None None
@ -119,20 +121,24 @@ impl Conversation {
log::error!("failed to convert prompt to UTF-8: {:?}", err); log::error!("failed to convert prompt to UTF-8: {:?}", err);
pam_client::ErrorCode::CONV_ERR pam_client::ErrorCode::CONV_ERR
})?; })?;
let runtime = tokio::runtime::Builder::new_current_thread()
futures::executor::block_on(async { .enable_all()
self.msg_tx .build()
.send(Message::Prompt( .unwrap();
prompt.to_string(), runtime
secret, .block_on(async {
Some(String::new()), self.msg_tx
)) .send(Message::Prompt(
.await prompt.to_string(),
}) secret,
.map_err(|err| { Some(String::new()),
log::error!("failed to send prompt: {:?}", err); ))
pam_client::ErrorCode::CONV_ERR .await
})?; })
.map_err(|err| {
log::error!("failed to send prompt: {:?}", err);
pam_client::ErrorCode::CONV_ERR
})?;
let value = self.value_rx.blocking_recv().ok_or_else(|| { let value = self.value_rx.blocking_recv().ok_or_else(|| {
log::error!("failed to receive value: channel closed"); log::error!("failed to receive value: channel closed");
@ -201,6 +207,21 @@ pub struct Flags {
wallpapers: Vec<(String, cosmic_bg_config::Source)>, wallpapers: Vec<(String, cosmic_bg_config::Source)>,
} }
impl SurfaceMessageHandler for Message {
fn to_surface_message(self) -> MessageWrapper<Self> {
match self {
Message::Surface(msg) => MessageWrapper::Surface(msg),
msg => MessageWrapper::Message(msg),
}
}
}
impl From<SurfaceMessage> for Message {
fn from(value: SurfaceMessage) -> Self {
Message::Surface(value)
}
}
/// Messages that are used specifically by our [`App`]. /// Messages that are used specifically by our [`App`].
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Message { pub enum Message {
@ -214,6 +235,7 @@ pub enum Message {
PowerInfo(Option<(String, f64)>), PowerInfo(Option<(String, f64)>),
Prompt(String, bool, Option<String>), Prompt(String, bool, Option<String>),
Submit, Submit,
Surface(SurfaceMessage),
Suspend, Suspend,
Error(String), Error(String),
Lock, Lock,
@ -267,7 +289,7 @@ impl App {
cosmic_bg_config::Source::Path(path) => { cosmic_bg_config::Source::Path(path) => {
match fs::read(path) { match fs::read(path) {
Ok(bytes) => { Ok(bytes) => {
let image = widget::image::Handle::from_memory(bytes); let image = widget::image::Handle::from_bytes(bytes);
self.surface_images.insert(*surface_id, image); self.surface_images.insert(*surface_id, image);
//TODO: what to do about duplicates? //TODO: what to do about duplicates?
break; break;
@ -316,7 +338,7 @@ impl cosmic::Application for App {
} }
/// Creates the application, and optionally emits command on initialize. /// Creates the application, and optionally emits command on initialize.
fn init(mut core: Core, flags: Self::Flags) -> (Self, Command<Self::Message>) { fn init(mut core: Core, flags: Self::Flags) -> (Self, Task<Self::Message>) {
core.window.show_window_menu = false; core.window.show_window_menu = false;
core.window.show_headerbar = false; core.window.show_headerbar = false;
core.window.sharp_corners = true; core.window.sharp_corners = true;
@ -354,7 +376,7 @@ impl cosmic::Application for App {
lock() lock()
} else { } else {
// When logind feature is used, wait for lock signal // When logind feature is used, wait for lock signal
Command::none() Task::none()
} }
} else { } else {
// When logind feature not used, lock immediately // When logind feature not used, lock immediately
@ -367,7 +389,7 @@ impl cosmic::Application for App {
} }
/// Handle application events here. /// Handle application events here.
fn update(&mut self, message: Self::Message) -> Command<Self::Message> { fn update(&mut self, message: Self::Message) -> Task<Self::Message> {
match message { match message {
Message::None => {} Message::None => {}
Message::OutputEvent(output_event, output) => { Message::OutputEvent(output_event, output) => {
@ -376,6 +398,7 @@ impl cosmic::Application for App {
log::info!("output {}: created", output.id()); log::info!("output {}: created", output.id());
let surface_id = SurfaceId::unique(); let surface_id = SurfaceId::unique();
match self.surface_ids.insert(output.clone(), surface_id) { match self.surface_ids.insert(output.clone(), surface_id) {
Some(old_surface_id) => { Some(old_surface_id) => {
//TODO: remove old surface? //TODO: remove old surface?
@ -384,6 +407,7 @@ impl cosmic::Application for App {
output.id(), output.id(),
old_surface_id old_surface_id
); );
return Task::none();
} }
None => {} None => {}
} }
@ -409,7 +433,7 @@ impl cosmic::Application for App {
.insert(surface_id, text_input_id.clone()); .insert(surface_id, text_input_id.clone());
if matches!(self.state, State::Locked) { if matches!(self.state, State::Locked) {
return Command::batch([ return Task::batch([
get_lock_surface(surface_id, output), get_lock_surface(surface_id, output),
widget::text_input::focus(text_input_id), widget::text_input::focus(text_input_id),
]); ]);
@ -454,7 +478,7 @@ impl cosmic::Application for App {
for (output, surface_id) in self.surface_ids.iter() { for (output, surface_id) in self.surface_ids.iter() {
commands.push(get_lock_surface(*surface_id, output.clone())); commands.push(get_lock_surface(*surface_id, output.clone()));
} }
return Command::batch(commands); return Task::batch(commands);
} }
SessionLockEvent::Unlocked => { SessionLockEvent::Unlocked => {
log::info!("session unlocked"); log::info!("session unlocked");
@ -504,7 +528,7 @@ impl cosmic::Application for App {
Some(value_tx) => { Some(value_tx) => {
// Clear errors // Clear errors
self.error_opt = None; self.error_opt = None;
return cosmic::command::future(async move { return cosmic::task::future(async move {
value_tx.send(value).await.unwrap(); value_tx.send(value).await.unwrap();
Message::Channel(value_tx) Message::Channel(value_tx)
}); });
@ -517,7 +541,7 @@ impl cosmic::Application for App {
}, },
Message::Suspend => { Message::Suspend => {
#[cfg(feature = "logind")] #[cfg(feature = "logind")]
return cosmic::command::future(async move { return cosmic::task::future(async move {
match crate::logind::suspend().await { match crate::logind::suspend().await {
Ok(()) => message::none(), Ok(()) => message::none(),
Err(err) => { Err(err) => {
@ -577,7 +601,7 @@ impl cosmic::Application for App {
// Tell compositor to unlock // Tell compositor to unlock
commands.push(unlock()); commands.push(unlock());
// Wait to exit until `Unlocked` event, when server has processed unlock // Wait to exit until `Unlocked` event, when server has processed unlock
return Command::batch(commands); return Task::batch(commands);
} }
State::Locking => { State::Locking => {
log::info!("session still locking"); log::info!("session still locking");
@ -587,8 +611,9 @@ impl cosmic::Application for App {
} }
} }
} }
Message::Surface(_) => {}
} }
Command::none() Task::none()
} }
// Not used for layer surface window // Not used for layer surface window
@ -607,13 +632,13 @@ impl cosmic::Application for App {
let date = dt.format_localized("%A, %B %-d", locale); let date = dt.format_localized("%A, %B %-d", locale);
column = column column = column
.push(widget::text::title2(format!("{}", date)).style(style::Text::Accent)); .push(widget::text::title2(format!("{}", date)).class(style::Text::Accent));
let time = dt.format_localized("%R", locale); let time = dt.format_localized("%R", locale);
column = column.push( column = column.push(
widget::text(format!("{}", time)) widget::text(format!("{}", time))
.size(112.0) .size(112.0)
.style(style::Text::Accent), .class(style::Text::Accent),
); );
column column
@ -634,18 +659,18 @@ impl cosmic::Application for App {
//TODO: implement these buttons //TODO: implement these buttons
let button_row = iced::widget::row![ let button_row = iced::widget::row![
widget::button(widget::icon::from_name( widget::button::custom(widget::icon::from_name(
"applications-accessibility-symbolic" "applications-accessibility-symbolic"
)) ))
.padding(12.0) .padding(12.0)
.on_press(Message::None), .on_press(Message::None),
widget::button(widget::icon::from_name("input-keyboard-symbolic")) widget::button::custom(widget::icon::from_name("input-keyboard-symbolic"))
.padding(12.0) .padding(12.0)
.on_press(Message::None), .on_press(Message::None),
widget::button(widget::icon::from_name("system-users-symbolic")) widget::button::custom(widget::icon::from_name("system-users-symbolic"))
.padding(12.0) .padding(12.0)
.on_press(Message::None), .on_press(Message::None),
widget::button(widget::icon::from_name("system-suspend-symbolic")) widget::button::custom(widget::icon::from_name("system-suspend-symbolic"))
.padding(12.0) .padding(12.0)
.on_press(Message::Suspend), .on_press(Message::Suspend),
] ]
@ -714,7 +739,7 @@ impl cosmic::Application for App {
*secret, *secret,
) )
.on_input(|value| Message::Prompt(prompt.clone(), *secret, Some(value))) .on_input(|value| Message::Prompt(prompt.clone(), *secret, Some(value)))
.on_submit(Message::Submit); .on_submit(|_| Message::Submit);
if let Some(text_input_id) = self.text_input_ids.get(&surface_id) { if let Some(text_input_id) = self.text_input_ids.get(&surface_id) {
text_input = text_input.id(text_input_id.clone()); text_input = text_input.id(text_input_id.clone());
@ -746,18 +771,18 @@ impl cosmic::Application for App {
widget::container( widget::container(
widget::layer_container( widget::layer_container(
iced::widget::row![left_element, right_element] iced::widget::row![left_element, right_element]
.align_items(alignment::Alignment::Center), .align_y(alignment::Alignment::Center),
) )
.layer(cosmic::cosmic_theme::Layer::Background) .layer(cosmic::cosmic_theme::Layer::Background)
.padding(16) .padding(16)
.style(cosmic::theme::Container::Custom(Box::new( .class(cosmic::theme::Container::Custom(Box::new(
|theme: &cosmic::Theme| { |theme: &cosmic::Theme| {
// Use background appearance as the base // Use background appearance as the base
let mut appearance = widget::container::StyleSheet::appearance( let mut appearance = widget::container::Catalog::style(
theme, theme,
&cosmic::theme::Container::Background, &cosmic::theme::Container::Background,
); );
appearance.border = iced::Border::with_radius(16.0); appearance.border = iced::Border::default().rounded(16.0);
appearance appearance
}, },
))) )))
@ -768,12 +793,12 @@ impl cosmic::Application for App {
.height(Length::Fill) .height(Length::Fill)
.align_x(alignment::Horizontal::Center) .align_x(alignment::Horizontal::Center)
.align_y(alignment::Vertical::Top) .align_y(alignment::Vertical::Top)
.style(cosmic::theme::Container::Transparent), .class(cosmic::theme::Container::Transparent),
) )
.image(match self.surface_images.get(&surface_id) { .image(match self.surface_images.get(&surface_id) {
Some(some) => some.clone(), Some(some) => some.clone(),
//TODO: default image //TODO: default image
None => widget::image::Handle::from_pixels(1, 1, vec![0x00, 0x00, 0x00, 0xFF]), None => widget::image::Handle::from_rgba(1, 1, vec![0x00, 0x00, 0x00, 0xFF]),
}) })
.content_fit(iced::ContentFit::Cover) .content_fit(iced::ContentFit::Cover)
.into() .into()
@ -782,7 +807,7 @@ impl cosmic::Application for App {
fn subscription(&self) -> Subscription<Self::Message> { fn subscription(&self) -> Subscription<Self::Message> {
let mut subscriptions = Vec::with_capacity(7); let mut subscriptions = Vec::with_capacity(7);
subscriptions.push(event::listen_with(|event, _| match event { subscriptions.push(event::listen_with(|event, _, _| match event {
iced::Event::PlatformSpecific(iced::event::PlatformSpecific::Wayland( iced::Event::PlatformSpecific(iced::event::PlatformSpecific::Wayland(
wayland_event, wayland_event,
)) => match wayland_event { )) => match wayland_event {
@ -812,26 +837,24 @@ impl cosmic::Application for App {
if matches!(self.state, State::Locked) { if matches!(self.state, State::Locked) {
struct HeartbeatSubscription; struct HeartbeatSubscription;
subscriptions.push(subscription::channel( subscriptions.push(Subscription::run_with_id(
TypeId::of::<HeartbeatSubscription>(), TypeId::of::<HeartbeatSubscription>(),
16, cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move {
|mut msg_tx| async move {
loop { loop {
// Send heartbeat once a second to update time // Send heartbeat once a second to update time
//TODO: only send this when needed //TODO: only send this when needed
msg_tx.send(Message::None).await.unwrap(); msg_tx.send(Message::None).await.unwrap();
time::sleep(time::Duration::new(1, 0)).await; time::sleep(time::Duration::new(1, 0)).await;
} }
}, }),
)); ));
struct PamSubscription; struct PamSubscription;
//TODO: how to avoid cloning this on every time subscription is called? //TODO: how to avoid cloning this on every time subscription is called?
let username = self.flags.current_user.name.clone(); let username = self.flags.current_user.name.clone();
subscriptions.push(subscription::channel( subscriptions.push(Subscription::run_with_id(
TypeId::of::<PamSubscription>(), TypeId::of::<PamSubscription>(),
16, cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move {
|mut msg_tx| async move {
loop { loop {
let (value_tx, value_rx) = mpsc::channel(16); let (value_tx, value_rx) = mpsc::channel(16);
msg_tx.send(Message::Channel(value_tx)).await.unwrap(); msg_tx.send(Message::Channel(value_tx)).await.unwrap();
@ -862,7 +885,7 @@ impl cosmic::Application for App {
loop { loop {
time::sleep(time::Duration::new(60, 0)).await; time::sleep(time::Duration::new(60, 0)).await;
} }
}, }),
)); ));
} }

View file

@ -1,6 +1,6 @@
use cosmic::iced::{ use cosmic::iced::{
futures::{channel::mpsc, SinkExt, StreamExt}, futures::{channel::mpsc, SinkExt, StreamExt},
subscription, Subscription, Subscription,
}; };
use logind_zbus::{ use logind_zbus::{
manager::{InhibitType, ManagerProxy}, manager::{InhibitType, ManagerProxy},
@ -46,10 +46,9 @@ async fn inhibit(manager: &ManagerProxy<'_>) -> zbus::Result<OwnedFd> {
pub fn subscription() -> Subscription<Message> { pub fn subscription() -> Subscription<Message> {
struct LogindSubscription; struct LogindSubscription;
subscription::channel( Subscription::run_with_id(
TypeId::of::<LogindSubscription>(), TypeId::of::<LogindSubscription>(),
16, cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move {
|mut msg_tx| async move {
match handler(&mut msg_tx).await { match handler(&mut msg_tx).await {
Ok(()) => {} Ok(()) => {}
Err(err) => { Err(err) => {
@ -59,7 +58,7 @@ pub fn subscription() -> Subscription<Message> {
} }
std::process::exit(1); std::process::exit(1);
}, }),
) )
} }

View file

@ -1,6 +1,6 @@
use cosmic::iced::{ use cosmic::iced::{
futures::{channel::mpsc, SinkExt, StreamExt}, futures::{channel::mpsc, SinkExt, StreamExt},
subscription, Subscription, Subscription,
}; };
use cosmic_dbus_networkmanager::{device::SpecificDevice, nm::NetworkManager}; use cosmic_dbus_networkmanager::{device::SpecificDevice, nm::NetworkManager};
use std::{any::TypeId, cmp}; use std::{any::TypeId, cmp};
@ -37,10 +37,9 @@ impl NetworkIcon {
pub fn subscription() -> Subscription<Option<&'static str>> { pub fn subscription() -> Subscription<Option<&'static str>> {
struct NetworkSubscription; struct NetworkSubscription;
subscription::channel( Subscription::run_with_id(
TypeId::of::<NetworkSubscription>(), TypeId::of::<NetworkSubscription>(),
16, cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move {
|mut msg_tx| async move {
match handler(&mut msg_tx).await { match handler(&mut msg_tx).await {
Ok(()) => {} Ok(()) => {}
Err(err) => { Err(err) => {
@ -56,7 +55,7 @@ pub fn subscription() -> Subscription<Option<&'static str>> {
loop { loop {
time::sleep(time::Duration::new(60, 0)).await; time::sleep(time::Duration::new(60, 0)).await;
} }
}, }),
) )
} }

View file

@ -1,6 +1,6 @@
use cosmic::iced::{ use cosmic::iced::{
futures::{channel::mpsc, SinkExt, StreamExt}, futures::{channel::mpsc, SinkExt, StreamExt},
subscription, Subscription, Subscription,
}; };
use std::any::TypeId; use std::any::TypeId;
use tokio::time; use tokio::time;
@ -10,10 +10,9 @@ use zbus::{Connection, Result};
pub fn subscription() -> Subscription<Option<(String, f64)>> { pub fn subscription() -> Subscription<Option<(String, f64)>> {
struct PowerSubscription; struct PowerSubscription;
subscription::channel( Subscription::run_with_id(
TypeId::of::<PowerSubscription>(), TypeId::of::<PowerSubscription>(),
16, cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move {
|mut msg_tx| async move {
match handler(&mut msg_tx).await { match handler(&mut msg_tx).await {
Ok(()) => {} Ok(()) => {}
Err(err) => { Err(err) => {
@ -29,7 +28,7 @@ pub fn subscription() -> Subscription<Option<(String, f64)>> {
loop { loop {
time::sleep(time::Duration::new(60, 0)).await; time::sleep(time::Duration::new(60, 0)).await;
} }
}, }),
) )
} }