chore: updates after iced rebase

This commit is contained in:
Ashley Wulber 2026-02-24 15:49:22 -05:00 committed by Jacob Kauffmann
parent 63cd93bddd
commit 89671a793f
10 changed files with 2367 additions and 2486 deletions

4282
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -40,13 +40,20 @@ xdg = "3.0"
#TODO: reduce features #TODO: reduce features
tokio = { workspace = true, features = ["full"] } tokio = { workspace = true, features = ["full"] }
wayland-client = "0.31.11" wayland-client = "0.31.11"
cosmic-settings-subscriptions = { git = "https://github.com/pop-os/cosmic-settings-subscriptions", default-features = false, features = [ # cosmic-settings-subscriptions = { git = "https://github.com/pop-os/cosmic-settings-subscriptions", default-features = false, features = [
"accessibility", # "accessibility",
"cosmic_a11y_manager", # "cosmic_a11y_manager",
] } # ] }
# cosmic-settings-daemon-config = { git = "https://github.com/pop-os/cosmic-settings-daemon", default-features = false, features = [
# "greeter",
# ] }
cosmic-settings-accessibility-subscription = { git = "https://github.com/pop-os/cosmic-settings", default-features = false, branch = "iced-rebase" }
cosmic-settings-a11y-manager-subscription = { git = "https://github.com/pop-os/cosmic-settings", default-features = false, branch = "iced-rebase" }
cosmic-settings-daemon-config = { git = "https://github.com/pop-os/cosmic-settings-daemon", default-features = false, features = [ cosmic-settings-daemon-config = { git = "https://github.com/pop-os/cosmic-settings-daemon", default-features = false, features = [
"greeter", "greeter",
] } ], branch = "iced-rebase" }
cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit" } cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit" }
cosmic-protocols = { git = "https://github.com/pop-os/cosmic-protocols", default-features = false, features = [ cosmic-protocols = { git = "https://github.com/pop-os/cosmic-protocols", default-features = false, features = [
"client", "client",
@ -129,14 +136,20 @@ cosmic-randr-shell = { git = "https://github.com/pop-os/cosmic-randr", default-f
[workspace.dependencies.cosmic-applets-config] [workspace.dependencies.cosmic-applets-config]
git = "https://github.com/pop-os/cosmic-applets" git = "https://github.com/pop-os/cosmic-applets"
branch = "iced-rebase"
# path = "../cosmic-applets/cosmic-applets-config"
default-features = false default-features = false
[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"
branch = "iced-rebase"
# path = "../cosmic-bg/config"
default-features = false default-features = false
[workspace.dependencies.cosmic-comp-config] [workspace.dependencies.cosmic-comp-config]
git = "https://github.com/pop-os/cosmic-comp" git = "https://github.com/pop-os/cosmic-comp"
branch = "iced-rebase"
# path = "../cosmic-comp/cosmic-comp-config"
default-features = false default-features = false
features = ["output", "randr"] features = ["output", "randr"]
@ -145,14 +158,19 @@ path = "cosmic-greeter-config"
[workspace.dependencies.cosmic-config] [workspace.dependencies.cosmic-config]
git = "https://github.com/pop-os/libcosmic" git = "https://github.com/pop-os/libcosmic"
branch = "iced-rebase"
# path = "../libcosmic/cosmic-config"
default-features = false default-features = false
[workspace.dependencies.cosmic-theme] [workspace.dependencies.cosmic-theme]
git = "https://github.com/pop-os/libcosmic" git = "https://github.com/pop-os/libcosmic"
branch = "iced-rebase"
# path = "../libcosmic/cosmic-theme"
default-features = false default-features = false
[workspace.dependencies.libcosmic] [workspace.dependencies.libcosmic]
git = "https://github.com/pop-os/libcosmic" git = "https://github.com/pop-os/libcosmic"
branch = "iced-rebase"
default-features = false default-features = false
[patch."https://github.com/smithay/client-toolkit.git"] [patch."https://github.com/smithay/client-toolkit.git"]
@ -162,6 +180,9 @@ sctk = { package = "smithay-client-toolkit", version = "0.20.0" }
cosmic-protocols = { git = "https://github.com/pop-os/cosmic-protocols//" } cosmic-protocols = { git = "https://github.com/pop-os/cosmic-protocols//" }
cctk = { git = "https://github.com/pop-os/cosmic-protocols//", package = "cosmic-client-toolkit" } cctk = { git = "https://github.com/pop-os/cosmic-protocols//", package = "cosmic-client-toolkit" }
# libcosmic = { path = "../libcosmic" } [patch."https://github.com/pop-os/libcosmic"]
# cosmic-config = { path = "../libcosmic/cosmic-config" } iced_core = { git = "https://github.com/pop-os/libcosmic//", branch = "iced-rebase" }
# cosmic-theme = { path = "../libcosmic/cosmic-theme" } iced_futures = { git = "https://github.com/pop-os/libcosmic//", branch = "iced-rebase" }
libcosmic = { git = "https://github.com/pop-os/libcosmic//", branch = "iced-rebase" }
cosmic-config = { git = "https://github.com/pop-os/libcosmic//", branch = "iced-rebase" }
cosmic-theme = { git = "https://github.com/pop-os/libcosmic//", branch = "iced-rebase" }

View file

@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "1.85.1" channel = "1.92.0"
components = ["clippy", "rustfmt"] components = ["clippy", "rustfmt"]

View file

@ -11,6 +11,7 @@ use cosmic::cctk::wayland_protocols::xdg::shell::client::xdg_positioner::Gravity
use cosmic::iced::event::listen_with; use cosmic::iced::event::listen_with;
use cosmic::iced::{Point, Size, window}; use cosmic::iced::{Point, Size, window};
use cosmic::iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings; use cosmic::iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings;
use cosmic::iced_runtime::task::widget;
use cosmic::widget::text; use cosmic::widget::text;
use cosmic::{ use cosmic::{
Element, Element,
@ -39,9 +40,7 @@ use cosmic::{
use cosmic_greeter_config::Config as CosmicGreeterConfig; use cosmic_greeter_config::Config as CosmicGreeterConfig;
use cosmic_greeter_daemon::{UserData, UserFilter}; use cosmic_greeter_daemon::{UserData, UserFilter};
use cosmic_randr_shell::{KdlParseWithError, List}; use cosmic_randr_shell::{KdlParseWithError, List};
use cosmic_settings_subscriptions::cosmic_a11y_manager::{ use cosmic_settings_a11y_manager_subscription::{AccessibilityEvent, AccessibilityRequest};
AccessibilityEvent, AccessibilityRequest,
};
use greetd_ipc::Request; use greetd_ipc::Request;
use kdl::KdlDocument; use kdl::KdlDocument;
use std::process::Stdio; use std::process::Stdio;
@ -536,9 +535,11 @@ impl App {
.width(Length::Fixed(16.0)) .width(Length::Fixed(16.0))
.into() .into()
} else { } else {
widget::Space::with_width(Length::Fixed(17.0)).into() widget::space::horizontal()
.width(Length::Fixed(17.0))
.into()
}, },
widget::Space::with_width(Length::Fixed(8.0)).into(), widget::space::horizontal().width(Length::Fixed(8.0)).into(),
widget::text(label) widget::text(label)
.align_x(iced::alignment::Horizontal::Left) .align_x(iced::alignment::Horizontal::Left)
.into(), .into(),
@ -615,7 +616,7 @@ impl App {
} }
let item_cnt = items.len(); let item_cnt = items.len();
let menu_button = widget::menu::menu_button(vec![ let menu_button = widget::menu::menu_button(vec![
Element::from(widget::Space::with_width(Length::Fixed(10.0))), Element::from(widget::space::horizontal().width(Length::Fixed(10.0))),
widget::text(fl!("enter-user")) widget::text(fl!("enter-user"))
.align_x(iced::alignment::Horizontal::Left) .align_x(iced::alignment::Horizontal::Left)
.into(), .into(),
@ -767,7 +768,7 @@ impl App {
// Add top spacing for better visual appearance // Add top spacing for better visual appearance
// Bottom of the password text input field should align with bottom of time widget // Bottom of the password text input field should align with bottom of time widget
column = column.push(widget::Space::with_height(Length::Fixed(space_height))); column = column.push(widget::space::vertical().height(Length::Fixed(space_height)));
match &self.socket_state { match &self.socket_state {
SocketState::Pending => { SocketState::Pending => {
@ -799,10 +800,9 @@ impl App {
} else { } else {
// Empty transparent box for users without icons // Empty transparent box for users without icons
column = column.push( column = column.push(
widget::container(widget::Space::new( widget::container(
Length::Fixed(78.0), widget::space::horizontal().width(Length::Fixed(78.0)),
Length::Fixed(78.0), )
))
.padding(0.0) .padding(0.0)
.width(Length::Fill) .width(Length::Fill)
.height(Length::Fixed(78.0)) .height(Length::Fixed(78.0))
@ -942,7 +942,9 @@ impl App {
.width(Length::Fill) .width(Length::Fill)
}; };
let menu = widget::container(widget::column::with_children(vec![ let menu = widget::container(widget::column::with_children(vec![
widget::Space::with_height(Length::FillPortion(1)).into(), widget::space::vertical()
.height(Length::FillPortion(1))
.into(),
widget::layer_container( widget::layer_container(
iced::widget::row![left_element, right_element].align_y(Alignment::Start), iced::widget::row![left_element, right_element].align_y(Alignment::Start),
) )
@ -962,7 +964,9 @@ impl App {
.class(cosmic::theme::Container::Background) .class(cosmic::theme::Container::Background)
.width(Length::Fixed(800.0)) .width(Length::Fixed(800.0))
.into(), .into(),
widget::Space::with_height(Length::FillPortion(4)).into(), widget::space::vertical()
.height(Length::FillPortion(4))
.into(),
])) ]))
.width(Length::Fill) .width(Length::Fill)
.height(Length::Fill) .height(Length::Fill)
@ -1285,7 +1289,7 @@ impl cosmic::Application for App {
id: surface_id, id: surface_id,
layer: Layer::Overlay, layer: Layer::Overlay,
keyboard_interactivity: KeyboardInteractivity::Exclusive, keyboard_interactivity: KeyboardInteractivity::Exclusive,
pointer_interactivity: true, input_zone: None,
anchor: Anchor::TOP | Anchor::LEFT | Anchor::BOTTOM | Anchor::RIGHT, anchor: Anchor::TOP | Anchor::LEFT | Anchor::BOTTOM | Anchor::RIGHT,
output: IcedOutput::Output(output), output: IcedOutput::Output(output),
namespace: "cosmic-locker".into(), namespace: "cosmic-locker".into(),
@ -1484,19 +1488,21 @@ impl cosmic::Application for App {
// Start spinner animation if not already running // Start spinner animation if not already running
if self.spinner_handle.is_none() { if self.spinner_handle.is_none() {
let (spinner_task, handle) = cosmic::task::stream( let (spinner_task, handle) =
cosmic::iced_futures::stream::channel(1, |mut msg_tx| async move { cosmic::task::stream(cosmic::iced_futures::stream::channel(
let mut interval = time::interval(Duration::from_millis(16)); // ~60fps 1,
loop { |mut msg_tx: iced::futures::channel::mpsc::Sender<_>| async move {
msg_tx let mut interval = time::interval(Duration::from_millis(16)); // ~60fps
.send(cosmic::Action::App(Message::SpinnerTick)) loop {
.await msg_tx
.unwrap(); .send(cosmic::Action::App(Message::SpinnerTick))
interval.tick().await; .await
} .unwrap();
}), interval.tick().await;
) }
.abortable(); },
))
.abortable();
self.spinner_handle = Some(handle); self.spinner_handle = Some(handle);
return spinner_task; return spinner_task;
} }
@ -1606,22 +1612,24 @@ impl cosmic::Application for App {
}); });
if self.heartbeat_handle.is_none() { if self.heartbeat_handle.is_none() {
let (heartbeat, handle) = cosmic::task::stream( let (heartbeat, handle) =
cosmic::iced_futures::stream::channel(1, |mut msg_tx| async move { cosmic::task::stream(cosmic::iced_futures::stream::channel(
let mut interval = time::interval(Duration::from_secs(1)); 1,
|mut msg_tx: iced::futures::channel::mpsc::Sender<_>| async move {
let mut interval = time::interval(Duration::from_secs(1));
loop { loop {
// Send heartbeat once a second to update time // Send heartbeat once a second to update time
msg_tx msg_tx
.send(cosmic::Action::App(Message::Heartbeat)) .send(cosmic::Action::App(Message::Heartbeat))
.await .await
.unwrap(); .unwrap();
interval.tick().await; interval.tick().await;
} }
}), },
) ))
.abortable(); .abortable();
self.heartbeat_handle = Some(handle); self.heartbeat_handle = Some(handle);
return heartbeat; return heartbeat;

View file

@ -38,139 +38,145 @@ fn greetd_error_to_message(error_type: greetd_ipc::ErrorType, description: &str)
pub fn subscription() -> Subscription<Message> { pub fn subscription() -> Subscription<Message> {
struct GreetdSubscription; struct GreetdSubscription;
Subscription::run_with_id( Subscription::run_with(std::any::TypeId::of::<GreetdSubscription>(), |_| {
std::any::TypeId::of::<GreetdSubscription>(), cosmic::iced_futures::stream::channel(
cosmic::iced_futures::stream::channel(1, |mut sender| async move { 1,
let (tx, mut rx) = mpsc::channel::<greetd_ipc::Request>(1); |mut sender: cosmic::iced::futures::channel::mpsc::Sender<_>| async move {
_ = sender.send(Message::GreetdChannel(tx)).await; let (tx, mut rx) = mpsc::channel::<greetd_ipc::Request>(1);
_ = sender.send(Message::GreetdChannel(tx)).await;
let socket_path = let socket_path =
std::env::var_os("GREETD_SOCK").expect("GREETD_SOCK environment not set"); std::env::var_os("GREETD_SOCK").expect("GREETD_SOCK environment not set");
let mut interval = tokio::time::interval(Duration::from_secs(1)); let mut interval = tokio::time::interval(Duration::from_secs(1));
loop { loop {
_ = sender.send(Message::Reconnect).await; _ = sender.send(Message::Reconnect).await;
let mut stream = match UnixStream::connect(&socket_path).await { let mut stream = match UnixStream::connect(&socket_path).await {
Ok(stream) => stream, Ok(stream) => stream,
Err(why) => { Err(why) => {
tracing::error!("greetd IPC socket connection failed: {why:?}"); tracing::error!("greetd IPC socket connection failed: {why:?}");
_ = sender.send(Message::Socket(SocketState::Error(Arc::new(why)))); _ = sender.send(Message::Socket(SocketState::Error(Arc::new(why))));
break; break;
} }
}; };
_ = sender.send(Message::Socket(SocketState::Open)).await; _ = sender.send(Message::Socket(SocketState::Open)).await;
while let Some(request) = rx.recv().await { while let Some(request) = rx.recv().await {
if let Err(why) = request.write_to(&mut stream).await { if let Err(why) = request.write_to(&mut stream).await {
tracing::error!("error writing to GREETD_SOCK stream: {why:?}"); tracing::error!("error writing to GREETD_SOCK stream: {why:?}");
break; break;
} }
match greetd_ipc::Response::read_from(&mut stream).await { match greetd_ipc::Response::read_from(&mut stream).await {
Ok(response) => { Ok(response) => {
match response { match response {
greetd_ipc::Response::AuthMessage { greetd_ipc::Response::AuthMessage {
auth_message_type, auth_message_type,
auth_message, auth_message,
} => match auth_message_type { } => match auth_message_type {
greetd_ipc::AuthMessageType::Secret => { greetd_ipc::AuthMessageType::Secret => {
_ = sender _ = sender
.send( .send(
common::Message::Prompt( common::Message::Prompt(
auth_message, auth_message,
true, true,
Some(String::new()), Some(String::new()),
) )
.into(),
)
.await;
}
greetd_ipc::AuthMessageType::Visible => {
_ = sender
.send(
common::Message::Prompt(
auth_message,
false,
Some(String::new()),
)
.into(),
)
.await;
}
greetd_ipc::AuthMessageType::Info => {
_ = sender
.send(
common::Message::Prompt(auth_message, false, None)
.into(), .into(),
) )
.await; .await;
} }
greetd_ipc::AuthMessageType::Error => { greetd_ipc::AuthMessageType::Visible => {
_ = sender.send(Message::Error(auth_message)).await; _ = sender
} .send(
}, common::Message::Prompt(
greetd_ipc::Response::Error { auth_message,
error_type, false,
description, Some(String::new()),
} => { )
match request { .into(),
greetd_ipc::Request::CancelSession => { )
// Do not send errors for cancel session to gui .await;
tracing::warn!( }
"error while cancelling session: {}", greetd_ipc::AuthMessageType::Info => {
description _ = sender
); .send(
common::Message::Prompt(
auth_message,
false,
None,
)
.into(),
)
.await;
}
greetd_ipc::AuthMessageType::Error => {
_ = sender.send(Message::Error(auth_message)).await;
}
},
greetd_ipc::Response::Error {
error_type,
description,
} => {
match request {
greetd_ipc::Request::CancelSession => {
// Do not send errors for cancel session to gui
tracing::warn!(
"error while cancelling session: {}",
description
);
// Reconnect to socket
break;
}
_ => {
_ = sender
.send(Message::Error(greetd_error_to_message(
error_type,
&description,
)))
.await;
}
}
}
greetd_ipc::Response::Success => match request {
greetd_ipc::Request::CreateSession { .. } => {
// User has no auth required, proceed to login
_ = sender.send(Message::Login).await;
}
greetd_ipc::Request::PostAuthMessageResponse { .. } => {
// All auth is completed, proceed to login
_ = sender.send(Message::Login).await;
}
greetd_ipc::Request::StartSession { .. } => {
// Session has been started, exit greeter
_ = sender.send(Message::Exit).await;
}
greetd_ipc::Request::CancelSession => {
tracing::info!("greetd IPC session canceled");
// Reconnect to socket // Reconnect to socket
break; break;
} }
_ => { },
_ = sender
.send(Message::Error(greetd_error_to_message(
error_type,
&description,
)))
.await;
}
}
} }
greetd_ipc::Response::Success => match request { }
greetd_ipc::Request::CreateSession { .. } => { Err(err) => {
// User has no auth required, proceed to login tracing::error!("failed to read socket: {:?}", err);
_ = sender.send(Message::Login).await; break;
}
greetd_ipc::Request::PostAuthMessageResponse { .. } => {
// All auth is completed, proceed to login
_ = sender.send(Message::Login).await;
}
greetd_ipc::Request::StartSession { .. } => {
// Session has been started, exit greeter
_ = sender.send(Message::Exit).await;
}
greetd_ipc::Request::CancelSession => {
tracing::info!("greetd IPC session canceled");
// Reconnect to socket
break;
}
},
} }
} }
Err(err) => {
tracing::error!("failed to read socket: {:?}", err);
break;
}
} }
tracing::info!("reconnecting to greetd IPC socket");
interval.tick().await;
} }
tracing::info!("reconnecting to greetd IPC socket"); futures_util::future::pending().await
interval.tick().await; },
} )
})
futures_util::future::pending().await
}),
)
} }

View file

@ -211,9 +211,7 @@ impl Conversation {
futures::executor::block_on(async { futures::executor::block_on(async {
self.msg_tx self.msg_tx
.send(cosmic::Action::App( .send(cosmic::Action::App(Message::Error(prompt.to_string())))
Message::Error(prompt.to_string()),
))
.await .await
}) })
.map_err(|err| { .map_err(|err| {
@ -367,9 +365,11 @@ impl App {
.width(Length::Fixed(16.0)) .width(Length::Fixed(16.0))
.into() .into()
} else { } else {
widget::Space::with_width(Length::Fixed(17.0)).into() widget::space::horizontal()
.width(Length::Fixed(17.0))
.into()
}, },
widget::Space::with_width(Length::Fixed(8.0)).into(), widget::space::horizontal().width(Length::Fixed(8.0)).into(),
widget::text(label) widget::text(label)
.align_x(iced::alignment::Horizontal::Left) .align_x(iced::alignment::Horizontal::Left)
.into(), .into(),
@ -477,7 +477,7 @@ impl App {
// Add top spacing for better visual appearance // Add top spacing for better visual appearance
// Bottom of the password text input field should align with bottom of time widget // Bottom of the password text input field should align with bottom of time widget
column = column.push(widget::Space::with_height(Length::Fixed(space_height))); column = column.push(widget::space::vertical().height(Length::Fixed(space_height)));
// Display user icon or empty transparent box // Display user icon or empty transparent box
if let Some(icon_handle) = &self.flags.user_icon { if let Some(icon_handle) = &self.flags.user_icon {
@ -496,7 +496,7 @@ impl App {
} else { } else {
// Empty transparent box for users without icons // Empty transparent box for users without icons
column = column.push( column = column.push(
widget::container(widget::Space::new(Length::Fixed(78.0), Length::Fixed(78.0))) widget::container(widget::space::horizontal().width(Length::Fixed(78.0)))
.padding(0.0) .padding(0.0)
.width(Length::Fill) .width(Length::Fill)
.height(Length::Fixed(78.0)) .height(Length::Fixed(78.0))
@ -602,7 +602,9 @@ impl App {
}; };
widget::container(widget::column::with_children(vec![ widget::container(widget::column::with_children(vec![
widget::Space::with_height(Length::FillPortion(1)).into(), widget::space::vertical()
.height(Length::FillPortion(1))
.into(),
widget::layer_container( widget::layer_container(
iced::widget::row![left_element, right_element].align_y(Alignment::Start), iced::widget::row![left_element, right_element].align_y(Alignment::Start),
) )
@ -622,7 +624,9 @@ impl App {
.width(Length::Fill) .width(Length::Fill)
.height(Length::Shrink) .height(Length::Shrink)
.into(), .into(),
widget::Space::with_height(Length::FillPortion(4)).into(), widget::space::vertical()
.height(Length::FillPortion(4))
.into(),
])) ]))
.width(Length::Fill) .width(Length::Fill)
.height(Length::Fill) .height(Length::Fill)
@ -865,72 +869,77 @@ impl cosmic::Application for App {
} }
let username = self.flags.user_data.name.clone(); let username = self.flags.user_data.name.clone();
let (locked_task, locked_handle) = cosmic::task::stream( let (locked_task, locked_handle) =
cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move { cosmic::task::stream(cosmic::iced_futures::stream::channel(
// Send heartbeat once a second to update time. 16,
let heartbeat_future = { |mut msg_tx: futures::channel::mpsc::Sender<_>| async move {
let mut output = msg_tx.clone(); // Send heartbeat once a second to update time.
async move { let heartbeat_future = {
let mut interval = let mut output = msg_tx.clone();
tokio::time::interval(Duration::from_secs(1)); async move {
let mut interval =
tokio::time::interval(Duration::from_secs(1));
loop {
output
.send(cosmic::Action::App(Message::None))
.await
.unwrap();
interval.tick().await;
}
}
};
let pam_future = async {
loop { loop {
output let (value_tx, value_rx) = mpsc::channel(16);
.send(cosmic::Action::App(Message::None)) msg_tx
.send(cosmic::Action::App(Message::Channel(value_tx)))
.await .await
.unwrap(); .unwrap();
interval.tick().await; let pam_res = {
} let username = username.clone();
} let msg_tx = msg_tx.clone();
}; task::spawn_blocking(move || {
pam_thread(
username,
Conversation { msg_tx, value_rx },
)
})
.await
.unwrap()
};
let pam_future = async { match pam_res {
loop { Ok(()) => {
let (value_tx, value_rx) = mpsc::channel(16); tracing::info!("successfully authenticated");
msg_tx msg_tx
.send(cosmic::Action::App(Message::Channel(value_tx))) .send(cosmic::Action::App(Message::Unlock))
.await .await
.unwrap(); .unwrap();
break;
let pam_res = { }
let username = username.clone(); Err(err) => {
let msg_tx = msg_tx.clone(); tracing::warn!("authentication error: {}", err);
task::spawn_blocking(move || { msg_tx
pam_thread(username, Conversation { msg_tx, value_rx }) .send(cosmic::Action::App(Message::Error(
}) pam_error_to_message(&err),
.await )))
.unwrap() .await
}; .unwrap();
}
match pam_res {
Ok(()) => {
tracing::info!("successfully authenticated");
msg_tx
.send(cosmic::Action::App(Message::Unlock))
.await
.unwrap();
break;
}
Err(err) => {
tracing::warn!("authentication error: {}", err);
msg_tx
.send(cosmic::Action::App(Message::Error(
pam_error_to_message(&err),
)))
.await
.unwrap();
} }
} }
} };
};
futures::pin_mut!(heartbeat_future); futures::pin_mut!(heartbeat_future);
futures::pin_mut!(pam_future); futures::pin_mut!(pam_future);
futures::future::select(heartbeat_future, pam_future).await; futures::future::select(heartbeat_future, pam_future).await;
}), },
) ))
.abortable(); .abortable();
let mut commands = Vec::with_capacity(self.common.surface_ids.len() + 1); let mut commands = Vec::with_capacity(self.common.surface_ids.len() + 1);
commands.push(locked_task); commands.push(locked_task);
@ -1046,20 +1055,22 @@ impl cosmic::Application for App {
Some(value_tx) => { Some(value_tx) => {
// Start spinner animation if not already running // Start spinner animation if not already running
if self.spinner_handle.is_none() { if self.spinner_handle.is_none() {
let (spinner_task, handle) = cosmic::task::stream( let (spinner_task, handle) =
cosmic::iced_futures::stream::channel(1, |mut msg_tx| async move { cosmic::task::stream(cosmic::iced_futures::stream::channel(
let mut interval = 1,
tokio::time::interval(Duration::from_millis(16)); // ~60fps |mut msg_tx: futures::channel::mpsc::Sender<_>| async move {
loop { let mut interval =
msg_tx tokio::time::interval(Duration::from_millis(16)); // ~60fps
.send(cosmic::Action::App(Message::SpinnerTick)) loop {
.await msg_tx
.unwrap(); .send(cosmic::Action::App(Message::SpinnerTick))
interval.tick().await; .await
} .unwrap();
}), interval.tick().await;
) }
.abortable(); },
))
.abortable();
self.spinner_handle = Some(handle); self.spinner_handle = Some(handle);
return Task::batch([ return Task::batch([

View file

@ -46,8 +46,7 @@ async fn inhibit(manager: &ManagerProxy<'_>) -> zbus::Result<OwnedFd> {
pub fn subscription() -> Subscription<Message> { pub fn subscription() -> Subscription<Message> {
struct LogindSubscription; struct LogindSubscription;
Subscription::run_with_id( Subscription::run_with(TypeId::of::<LogindSubscription>(), |_| {
TypeId::of::<LogindSubscription>(),
cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move { cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move {
match handler(&mut msg_tx).await { match handler(&mut msg_tx).await {
Ok(()) => {} Ok(()) => {}
@ -58,8 +57,8 @@ pub fn subscription() -> Subscription<Message> {
} }
std::process::exit(1); std::process::exit(1);
}), })
) })
} }
//TODO: use never type? //TODO: use never type?

View file

@ -36,8 +36,7 @@ impl NetworkIcon {
pub fn subscription() -> Subscription<Option<&'static str>> { pub fn subscription() -> Subscription<Option<&'static str>> {
struct NetworkSubscription; struct NetworkSubscription;
Subscription::run_with_id( Subscription::run_with(TypeId::of::<NetworkSubscription>(), |_| {
TypeId::of::<NetworkSubscription>(),
cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move { cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move {
match handler(&mut msg_tx).await { match handler(&mut msg_tx).await {
Ok(()) => {} Ok(()) => {}
@ -52,8 +51,8 @@ pub fn subscription() -> Subscription<Option<&'static str>> {
//TODO: should we retry on error? //TODO: should we retry on error?
futures_util::future::pending().await futures_util::future::pending().await
}), })
) })
} }
//TODO: use never type? //TODO: use never type?

View file

@ -9,8 +9,7 @@ use zbus::{Connection, Result};
pub fn subscription() -> Subscription<Option<(String, f64)>> { pub fn subscription() -> Subscription<Option<(String, f64)>> {
struct PowerSubscription; struct PowerSubscription;
Subscription::run_with_id( Subscription::run_with(TypeId::of::<PowerSubscription>(), |_| {
TypeId::of::<PowerSubscription>(),
cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move { cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move {
match handler(&mut msg_tx).await { match handler(&mut msg_tx).await {
Ok(()) => {} Ok(()) => {}
@ -25,8 +24,8 @@ pub fn subscription() -> Subscription<Option<(String, f64)>> {
//TODO: should we retry on error? //TODO: should we retry on error?
futures_util::future::pending().await futures_util::future::pending().await
}), })
) })
} }
//TODO: use never type? //TODO: use never type?

View file

@ -7,7 +7,7 @@ use cosmic::iced::{
futures::{self, SinkExt}, futures::{self, SinkExt},
stream, stream,
}; };
use cosmic_settings_subscriptions::cosmic_a11y_manager::{ use cosmic_settings_a11y_manager_subscription::{
self as thread, AccessibilityEvent, AccessibilityRequest, self as thread, AccessibilityEvent, AccessibilityRequest,
}; };
use std::sync::LazyLock; use std::sync::LazyLock;
@ -24,16 +24,15 @@ pub enum WaylandUpdate {
} }
pub fn a11y_subscription() -> iced::Subscription<WaylandUpdate> { pub fn a11y_subscription() -> iced::Subscription<WaylandUpdate> {
Subscription::run_with_id( Subscription::run_with(std::any::TypeId::of::<WaylandUpdate>(), |_| {
std::any::TypeId::of::<WaylandUpdate>(),
stream::channel(50, move |mut output| async move { stream::channel(50, move |mut output| async move {
let mut state = State::Waiting; let mut state = State::Waiting;
loop { loop {
state = start_listening(state, &mut output).await; state = start_listening(state, &mut output).await;
} }
}), })
) })
} }
async fn start_listening( async fn start_listening(
@ -42,7 +41,8 @@ async fn start_listening(
) -> State { ) -> State {
match state { match state {
State::Waiting => { State::Waiting => {
let mut guard = WAYLAND_RX.lock().await; let mut guard: tokio::sync::MutexGuard<'_, Option<tokio::sync::mpsc::Receiver<_>>> =
WAYLAND_RX.lock().await;
let rx = { let rx = {
if guard.is_none() { if guard.is_none() {
if let Ok(WaylandWatcher { rx, tx }) = WaylandWatcher::new() { if let Ok(WaylandWatcher { rx, tx }) = WaylandWatcher::new() {