chore: updates after iced rebase
This commit is contained in:
parent
63cd93bddd
commit
89671a793f
10 changed files with 2367 additions and 2486 deletions
|
|
@ -11,6 +11,7 @@ use cosmic::cctk::wayland_protocols::xdg::shell::client::xdg_positioner::Gravity
|
|||
use cosmic::iced::event::listen_with;
|
||||
use cosmic::iced::{Point, Size, window};
|
||||
use cosmic::iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings;
|
||||
use cosmic::iced_runtime::task::widget;
|
||||
use cosmic::widget::text;
|
||||
use cosmic::{
|
||||
Element,
|
||||
|
|
@ -39,9 +40,7 @@ use cosmic::{
|
|||
use cosmic_greeter_config::Config as CosmicGreeterConfig;
|
||||
use cosmic_greeter_daemon::{UserData, UserFilter};
|
||||
use cosmic_randr_shell::{KdlParseWithError, List};
|
||||
use cosmic_settings_subscriptions::cosmic_a11y_manager::{
|
||||
AccessibilityEvent, AccessibilityRequest,
|
||||
};
|
||||
use cosmic_settings_a11y_manager_subscription::{AccessibilityEvent, AccessibilityRequest};
|
||||
use greetd_ipc::Request;
|
||||
use kdl::KdlDocument;
|
||||
use std::process::Stdio;
|
||||
|
|
@ -536,9 +535,11 @@ impl App {
|
|||
.width(Length::Fixed(16.0))
|
||||
.into()
|
||||
} 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)
|
||||
.align_x(iced::alignment::Horizontal::Left)
|
||||
.into(),
|
||||
|
|
@ -615,7 +616,7 @@ impl App {
|
|||
}
|
||||
let item_cnt = items.len();
|
||||
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"))
|
||||
.align_x(iced::alignment::Horizontal::Left)
|
||||
.into(),
|
||||
|
|
@ -767,7 +768,7 @@ impl App {
|
|||
|
||||
// Add top spacing for better visual appearance
|
||||
// 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 {
|
||||
SocketState::Pending => {
|
||||
|
|
@ -799,10 +800,9 @@ impl App {
|
|||
} else {
|
||||
// Empty transparent box for users without icons
|
||||
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)
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fixed(78.0))
|
||||
|
|
@ -942,7 +942,9 @@ impl App {
|
|||
.width(Length::Fill)
|
||||
};
|
||||
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(
|
||||
iced::widget::row![left_element, right_element].align_y(Alignment::Start),
|
||||
)
|
||||
|
|
@ -962,7 +964,9 @@ impl App {
|
|||
.class(cosmic::theme::Container::Background)
|
||||
.width(Length::Fixed(800.0))
|
||||
.into(),
|
||||
widget::Space::with_height(Length::FillPortion(4)).into(),
|
||||
widget::space::vertical()
|
||||
.height(Length::FillPortion(4))
|
||||
.into(),
|
||||
]))
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
|
|
@ -1285,7 +1289,7 @@ impl cosmic::Application for App {
|
|||
id: surface_id,
|
||||
layer: Layer::Overlay,
|
||||
keyboard_interactivity: KeyboardInteractivity::Exclusive,
|
||||
pointer_interactivity: true,
|
||||
input_zone: None,
|
||||
anchor: Anchor::TOP | Anchor::LEFT | Anchor::BOTTOM | Anchor::RIGHT,
|
||||
output: IcedOutput::Output(output),
|
||||
namespace: "cosmic-locker".into(),
|
||||
|
|
@ -1484,19 +1488,21 @@ impl cosmic::Application for App {
|
|||
|
||||
// Start spinner animation if not already running
|
||||
if self.spinner_handle.is_none() {
|
||||
let (spinner_task, handle) = cosmic::task::stream(
|
||||
cosmic::iced_futures::stream::channel(1, |mut msg_tx| async move {
|
||||
let mut interval = time::interval(Duration::from_millis(16)); // ~60fps
|
||||
loop {
|
||||
msg_tx
|
||||
.send(cosmic::Action::App(Message::SpinnerTick))
|
||||
.await
|
||||
.unwrap();
|
||||
interval.tick().await;
|
||||
}
|
||||
}),
|
||||
)
|
||||
.abortable();
|
||||
let (spinner_task, handle) =
|
||||
cosmic::task::stream(cosmic::iced_futures::stream::channel(
|
||||
1,
|
||||
|mut msg_tx: iced::futures::channel::mpsc::Sender<_>| async move {
|
||||
let mut interval = time::interval(Duration::from_millis(16)); // ~60fps
|
||||
loop {
|
||||
msg_tx
|
||||
.send(cosmic::Action::App(Message::SpinnerTick))
|
||||
.await
|
||||
.unwrap();
|
||||
interval.tick().await;
|
||||
}
|
||||
},
|
||||
))
|
||||
.abortable();
|
||||
self.spinner_handle = Some(handle);
|
||||
return spinner_task;
|
||||
}
|
||||
|
|
@ -1606,22 +1612,24 @@ impl cosmic::Application for App {
|
|||
});
|
||||
|
||||
if self.heartbeat_handle.is_none() {
|
||||
let (heartbeat, handle) = cosmic::task::stream(
|
||||
cosmic::iced_futures::stream::channel(1, |mut msg_tx| async move {
|
||||
let mut interval = time::interval(Duration::from_secs(1));
|
||||
let (heartbeat, handle) =
|
||||
cosmic::task::stream(cosmic::iced_futures::stream::channel(
|
||||
1,
|
||||
|mut msg_tx: iced::futures::channel::mpsc::Sender<_>| async move {
|
||||
let mut interval = time::interval(Duration::from_secs(1));
|
||||
|
||||
loop {
|
||||
// Send heartbeat once a second to update time
|
||||
msg_tx
|
||||
.send(cosmic::Action::App(Message::Heartbeat))
|
||||
.await
|
||||
.unwrap();
|
||||
loop {
|
||||
// Send heartbeat once a second to update time
|
||||
msg_tx
|
||||
.send(cosmic::Action::App(Message::Heartbeat))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
interval.tick().await;
|
||||
}
|
||||
}),
|
||||
)
|
||||
.abortable();
|
||||
interval.tick().await;
|
||||
}
|
||||
},
|
||||
))
|
||||
.abortable();
|
||||
|
||||
self.heartbeat_handle = Some(handle);
|
||||
return heartbeat;
|
||||
|
|
|
|||
|
|
@ -38,139 +38,145 @@ fn greetd_error_to_message(error_type: greetd_ipc::ErrorType, description: &str)
|
|||
|
||||
pub fn subscription() -> Subscription<Message> {
|
||||
struct GreetdSubscription;
|
||||
Subscription::run_with_id(
|
||||
std::any::TypeId::of::<GreetdSubscription>(),
|
||||
cosmic::iced_futures::stream::channel(1, |mut sender| async move {
|
||||
let (tx, mut rx) = mpsc::channel::<greetd_ipc::Request>(1);
|
||||
_ = sender.send(Message::GreetdChannel(tx)).await;
|
||||
Subscription::run_with(std::any::TypeId::of::<GreetdSubscription>(), |_| {
|
||||
cosmic::iced_futures::stream::channel(
|
||||
1,
|
||||
|mut sender: cosmic::iced::futures::channel::mpsc::Sender<_>| async move {
|
||||
let (tx, mut rx) = mpsc::channel::<greetd_ipc::Request>(1);
|
||||
_ = sender.send(Message::GreetdChannel(tx)).await;
|
||||
|
||||
let socket_path =
|
||||
std::env::var_os("GREETD_SOCK").expect("GREETD_SOCK environment not set");
|
||||
let socket_path =
|
||||
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 {
|
||||
_ = sender.send(Message::Reconnect).await;
|
||||
loop {
|
||||
_ = sender.send(Message::Reconnect).await;
|
||||
|
||||
let mut stream = match UnixStream::connect(&socket_path).await {
|
||||
Ok(stream) => stream,
|
||||
Err(why) => {
|
||||
tracing::error!("greetd IPC socket connection failed: {why:?}");
|
||||
_ = sender.send(Message::Socket(SocketState::Error(Arc::new(why))));
|
||||
let mut stream = match UnixStream::connect(&socket_path).await {
|
||||
Ok(stream) => stream,
|
||||
Err(why) => {
|
||||
tracing::error!("greetd IPC socket connection failed: {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 {
|
||||
if let Err(why) = request.write_to(&mut stream).await {
|
||||
tracing::error!("error writing to GREETD_SOCK stream: {why:?}");
|
||||
break;
|
||||
}
|
||||
while let Some(request) = rx.recv().await {
|
||||
if let Err(why) = request.write_to(&mut stream).await {
|
||||
tracing::error!("error writing to GREETD_SOCK stream: {why:?}");
|
||||
break;
|
||||
}
|
||||
|
||||
match greetd_ipc::Response::read_from(&mut stream).await {
|
||||
Ok(response) => {
|
||||
match response {
|
||||
greetd_ipc::Response::AuthMessage {
|
||||
auth_message_type,
|
||||
auth_message,
|
||||
} => match auth_message_type {
|
||||
greetd_ipc::AuthMessageType::Secret => {
|
||||
_ = sender
|
||||
.send(
|
||||
common::Message::Prompt(
|
||||
auth_message,
|
||||
true,
|
||||
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)
|
||||
match greetd_ipc::Response::read_from(&mut stream).await {
|
||||
Ok(response) => {
|
||||
match response {
|
||||
greetd_ipc::Response::AuthMessage {
|
||||
auth_message_type,
|
||||
auth_message,
|
||||
} => match auth_message_type {
|
||||
greetd_ipc::AuthMessageType::Secret => {
|
||||
_ = sender
|
||||
.send(
|
||||
common::Message::Prompt(
|
||||
auth_message,
|
||||
true,
|
||||
Some(String::new()),
|
||||
)
|
||||
.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
|
||||
);
|
||||
)
|
||||
.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(),
|
||||
)
|
||||
.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
|
||||
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
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::error!("failed to read socket: {:?}", err);
|
||||
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");
|
||||
interval.tick().await;
|
||||
}
|
||||
|
||||
futures_util::future::pending().await
|
||||
}),
|
||||
)
|
||||
futures_util::future::pending().await
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
171
src/locker.rs
171
src/locker.rs
|
|
@ -211,9 +211,7 @@ impl Conversation {
|
|||
|
||||
futures::executor::block_on(async {
|
||||
self.msg_tx
|
||||
.send(cosmic::Action::App(
|
||||
Message::Error(prompt.to_string()),
|
||||
))
|
||||
.send(cosmic::Action::App(Message::Error(prompt.to_string())))
|
||||
.await
|
||||
})
|
||||
.map_err(|err| {
|
||||
|
|
@ -367,9 +365,11 @@ impl App {
|
|||
.width(Length::Fixed(16.0))
|
||||
.into()
|
||||
} 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)
|
||||
.align_x(iced::alignment::Horizontal::Left)
|
||||
.into(),
|
||||
|
|
@ -477,7 +477,7 @@ impl App {
|
|||
|
||||
// Add top spacing for better visual appearance
|
||||
// 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
|
||||
if let Some(icon_handle) = &self.flags.user_icon {
|
||||
|
|
@ -496,7 +496,7 @@ impl App {
|
|||
} else {
|
||||
// Empty transparent box for users without icons
|
||||
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)
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fixed(78.0))
|
||||
|
|
@ -602,7 +602,9 @@ impl App {
|
|||
};
|
||||
|
||||
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(
|
||||
iced::widget::row![left_element, right_element].align_y(Alignment::Start),
|
||||
)
|
||||
|
|
@ -622,7 +624,9 @@ impl App {
|
|||
.width(Length::Fill)
|
||||
.height(Length::Shrink)
|
||||
.into(),
|
||||
widget::Space::with_height(Length::FillPortion(4)).into(),
|
||||
widget::space::vertical()
|
||||
.height(Length::FillPortion(4))
|
||||
.into(),
|
||||
]))
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
|
|
@ -865,72 +869,77 @@ impl cosmic::Application for App {
|
|||
}
|
||||
|
||||
let username = self.flags.user_data.name.clone();
|
||||
let (locked_task, locked_handle) = cosmic::task::stream(
|
||||
cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move {
|
||||
// Send heartbeat once a second to update time.
|
||||
let heartbeat_future = {
|
||||
let mut output = msg_tx.clone();
|
||||
async move {
|
||||
let mut interval =
|
||||
tokio::time::interval(Duration::from_secs(1));
|
||||
let (locked_task, locked_handle) =
|
||||
cosmic::task::stream(cosmic::iced_futures::stream::channel(
|
||||
16,
|
||||
|mut msg_tx: futures::channel::mpsc::Sender<_>| async move {
|
||||
// Send heartbeat once a second to update time.
|
||||
let heartbeat_future = {
|
||||
let mut output = msg_tx.clone();
|
||||
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 {
|
||||
output
|
||||
.send(cosmic::Action::App(Message::None))
|
||||
let (value_tx, value_rx) = mpsc::channel(16);
|
||||
msg_tx
|
||||
.send(cosmic::Action::App(Message::Channel(value_tx)))
|
||||
.await
|
||||
.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 {
|
||||
loop {
|
||||
let (value_tx, value_rx) = mpsc::channel(16);
|
||||
msg_tx
|
||||
.send(cosmic::Action::App(Message::Channel(value_tx)))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
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()
|
||||
};
|
||||
|
||||
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();
|
||||
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!(pam_future);
|
||||
futures::future::select(heartbeat_future, pam_future).await;
|
||||
}),
|
||||
)
|
||||
.abortable();
|
||||
futures::pin_mut!(heartbeat_future);
|
||||
futures::pin_mut!(pam_future);
|
||||
futures::future::select(heartbeat_future, pam_future).await;
|
||||
},
|
||||
))
|
||||
.abortable();
|
||||
|
||||
let mut commands = Vec::with_capacity(self.common.surface_ids.len() + 1);
|
||||
commands.push(locked_task);
|
||||
|
|
@ -1046,20 +1055,22 @@ impl cosmic::Application for App {
|
|||
Some(value_tx) => {
|
||||
// Start spinner animation if not already running
|
||||
if self.spinner_handle.is_none() {
|
||||
let (spinner_task, handle) = cosmic::task::stream(
|
||||
cosmic::iced_futures::stream::channel(1, |mut msg_tx| async move {
|
||||
let mut interval =
|
||||
tokio::time::interval(Duration::from_millis(16)); // ~60fps
|
||||
loop {
|
||||
msg_tx
|
||||
.send(cosmic::Action::App(Message::SpinnerTick))
|
||||
.await
|
||||
.unwrap();
|
||||
interval.tick().await;
|
||||
}
|
||||
}),
|
||||
)
|
||||
.abortable();
|
||||
let (spinner_task, handle) =
|
||||
cosmic::task::stream(cosmic::iced_futures::stream::channel(
|
||||
1,
|
||||
|mut msg_tx: futures::channel::mpsc::Sender<_>| async move {
|
||||
let mut interval =
|
||||
tokio::time::interval(Duration::from_millis(16)); // ~60fps
|
||||
loop {
|
||||
msg_tx
|
||||
.send(cosmic::Action::App(Message::SpinnerTick))
|
||||
.await
|
||||
.unwrap();
|
||||
interval.tick().await;
|
||||
}
|
||||
},
|
||||
))
|
||||
.abortable();
|
||||
self.spinner_handle = Some(handle);
|
||||
|
||||
return Task::batch([
|
||||
|
|
|
|||
|
|
@ -46,8 +46,7 @@ async fn inhibit(manager: &ManagerProxy<'_>) -> zbus::Result<OwnedFd> {
|
|||
pub fn subscription() -> Subscription<Message> {
|
||||
struct LogindSubscription;
|
||||
|
||||
Subscription::run_with_id(
|
||||
TypeId::of::<LogindSubscription>(),
|
||||
Subscription::run_with(TypeId::of::<LogindSubscription>(), |_| {
|
||||
cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move {
|
||||
match handler(&mut msg_tx).await {
|
||||
Ok(()) => {}
|
||||
|
|
@ -58,8 +57,8 @@ pub fn subscription() -> Subscription<Message> {
|
|||
}
|
||||
|
||||
std::process::exit(1);
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//TODO: use never type?
|
||||
|
|
|
|||
|
|
@ -36,8 +36,7 @@ impl NetworkIcon {
|
|||
pub fn subscription() -> Subscription<Option<&'static str>> {
|
||||
struct NetworkSubscription;
|
||||
|
||||
Subscription::run_with_id(
|
||||
TypeId::of::<NetworkSubscription>(),
|
||||
Subscription::run_with(TypeId::of::<NetworkSubscription>(), |_| {
|
||||
cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move {
|
||||
match handler(&mut msg_tx).await {
|
||||
Ok(()) => {}
|
||||
|
|
@ -52,8 +51,8 @@ pub fn subscription() -> Subscription<Option<&'static str>> {
|
|||
|
||||
//TODO: should we retry on error?
|
||||
futures_util::future::pending().await
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//TODO: use never type?
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@ use zbus::{Connection, Result};
|
|||
pub fn subscription() -> Subscription<Option<(String, f64)>> {
|
||||
struct PowerSubscription;
|
||||
|
||||
Subscription::run_with_id(
|
||||
TypeId::of::<PowerSubscription>(),
|
||||
Subscription::run_with(TypeId::of::<PowerSubscription>(), |_| {
|
||||
cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move {
|
||||
match handler(&mut msg_tx).await {
|
||||
Ok(()) => {}
|
||||
|
|
@ -25,8 +24,8 @@ pub fn subscription() -> Subscription<Option<(String, f64)>> {
|
|||
|
||||
//TODO: should we retry on error?
|
||||
futures_util::future::pending().await
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//TODO: use never type?
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use cosmic::iced::{
|
|||
futures::{self, SinkExt},
|
||||
stream,
|
||||
};
|
||||
use cosmic_settings_subscriptions::cosmic_a11y_manager::{
|
||||
use cosmic_settings_a11y_manager_subscription::{
|
||||
self as thread, AccessibilityEvent, AccessibilityRequest,
|
||||
};
|
||||
use std::sync::LazyLock;
|
||||
|
|
@ -24,16 +24,15 @@ pub enum WaylandUpdate {
|
|||
}
|
||||
|
||||
pub fn a11y_subscription() -> iced::Subscription<WaylandUpdate> {
|
||||
Subscription::run_with_id(
|
||||
std::any::TypeId::of::<WaylandUpdate>(),
|
||||
Subscription::run_with(std::any::TypeId::of::<WaylandUpdate>(), |_| {
|
||||
stream::channel(50, move |mut output| async move {
|
||||
let mut state = State::Waiting;
|
||||
|
||||
loop {
|
||||
state = start_listening(state, &mut output).await;
|
||||
}
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async fn start_listening(
|
||||
|
|
@ -42,7 +41,8 @@ async fn start_listening(
|
|||
) -> State {
|
||||
match state {
|
||||
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 = {
|
||||
if guard.is_none() {
|
||||
if let Ok(WaylandWatcher { rx, tx }) = WaylandWatcher::new() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue