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:
parent
5527c9b866
commit
7918485651
9 changed files with 2440 additions and 1464 deletions
2685
Cargo.lock
generated
2685
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
19
Cargo.toml
19
Cargo.toml
|
|
@ -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" }
|
||||||
|
|
|
||||||
965
src/greeter.rs
965
src/greeter.rs
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
||||||
},
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
123
src/locker.rs
123
src/locker.rs
|
|
@ -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(¤t_user.name);
|
let icon_path = Path::new("/var/lib/AccountsService/icons").join(¤t_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;
|
||||||
}
|
}
|
||||||
},
|
}),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
},
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
},
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
},
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue