Recover previous locked state
This commit is contained in:
parent
7366808e8c
commit
08202f1572
4 changed files with 83 additions and 27 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -996,6 +996,7 @@ dependencies = [
|
||||||
"cosmic-dbus-networkmanager",
|
"cosmic-dbus-networkmanager",
|
||||||
"cosmic-greeter-config",
|
"cosmic-greeter-config",
|
||||||
"cosmic-greeter-daemon",
|
"cosmic-greeter-daemon",
|
||||||
|
"dirs",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"freedesktop_entry_parser",
|
"freedesktop_entry_parser",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ cosmic-comp-config.workspace = true
|
||||||
cosmic-config = { workspace = true, features = ["calloop", "macro"] }
|
cosmic-config = { workspace = true, features = ["calloop", "macro"] }
|
||||||
cosmic-greeter-config.workspace = true
|
cosmic-greeter-config.workspace = true
|
||||||
cosmic-greeter-daemon = { path = "daemon" }
|
cosmic-greeter-daemon = { path = "daemon" }
|
||||||
|
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 = ["tokio", "wayland"] }
|
||||||
|
|
|
||||||
103
src/locker.rs
103
src/locker.rs
|
|
@ -22,16 +22,30 @@ use cosmic_config::CosmicConfigEntry;
|
||||||
use std::{
|
use std::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
env,
|
||||||
ffi::{CStr, CString},
|
ffi::{CStr, CString},
|
||||||
fs,
|
fs,
|
||||||
os::fd::OwnedFd,
|
os::fd::OwnedFd,
|
||||||
path::Path,
|
path::{Path, PathBuf},
|
||||||
process,
|
process,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use tokio::{sync::mpsc, task, time};
|
use tokio::{sync::mpsc, task, time};
|
||||||
use wayland_client::{protocol::wl_output::WlOutput, Proxy};
|
use wayland_client::{protocol::wl_output::WlOutput, Proxy};
|
||||||
|
|
||||||
|
fn lockfile_opt() -> Option<PathBuf> {
|
||||||
|
let runtime_dir = dirs::runtime_dir()?;
|
||||||
|
let session_id_str = env::var("XDG_SESSION_ID").ok()?;
|
||||||
|
let session_id = match session_id_str.parse::<u64>() {
|
||||||
|
Ok(ok) => ok,
|
||||||
|
Err(err) => {
|
||||||
|
log::warn!("failed to parse session ID {:?}: {}", session_id_str, err);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some(runtime_dir.join(format!("cosmic-greeter-{}.lock", session_id)))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main(current_user: pwd::Passwd) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn main(current_user: pwd::Passwd) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init();
|
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init();
|
||||||
|
|
||||||
|
|
@ -69,6 +83,7 @@ pub fn main(current_user: pwd::Passwd) -> Result<(), Box<dyn std::error::Error>>
|
||||||
let flags = Flags {
|
let flags = Flags {
|
||||||
current_user,
|
current_user,
|
||||||
icon_opt,
|
icon_opt,
|
||||||
|
lockfile_opt: lockfile_opt(),
|
||||||
wallpapers,
|
wallpapers,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -189,6 +204,7 @@ impl pam_client::ConversationHandler for Conversation {
|
||||||
pub struct Flags {
|
pub struct Flags {
|
||||||
current_user: pwd::Passwd,
|
current_user: pwd::Passwd,
|
||||||
icon_opt: Option<widget::image::Handle>,
|
icon_opt: Option<widget::image::Handle>,
|
||||||
|
lockfile_opt: Option<PathBuf>,
|
||||||
wallpapers: Vec<(String, cosmic_bg_config::Source)>,
|
wallpapers: Vec<(String, cosmic_bg_config::Source)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -315,31 +331,46 @@ impl cosmic::Application for App {
|
||||||
core.window.show_minimize = false;
|
core.window.show_minimize = false;
|
||||||
core.window.use_template = false;
|
core.window.use_template = false;
|
||||||
|
|
||||||
(
|
let already_locked = match flags.lockfile_opt {
|
||||||
App {
|
Some(ref lockfile) => lockfile.exists(),
|
||||||
core,
|
None => false,
|
||||||
flags,
|
};
|
||||||
state: State::Unlocked,
|
|
||||||
surface_ids: HashMap::new(),
|
let mut app = App {
|
||||||
active_surface_id_opt: None,
|
core,
|
||||||
surface_images: HashMap::new(),
|
flags,
|
||||||
surface_names: HashMap::new(),
|
state: State::Unlocked,
|
||||||
text_input_ids: HashMap::new(),
|
surface_ids: HashMap::new(),
|
||||||
inhibit_opt: None,
|
active_surface_id_opt: None,
|
||||||
network_icon_opt: None,
|
surface_images: HashMap::new(),
|
||||||
power_info_opt: None,
|
surface_names: HashMap::new(),
|
||||||
value_tx_opt: None,
|
text_input_ids: HashMap::new(),
|
||||||
prompt_opt: None,
|
inhibit_opt: None,
|
||||||
error_opt: None,
|
network_icon_opt: None,
|
||||||
},
|
power_info_opt: None,
|
||||||
if cfg!(feature = "logind") {
|
value_tx_opt: None,
|
||||||
|
prompt_opt: None,
|
||||||
|
error_opt: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let command = if cfg!(feature = "logind") {
|
||||||
|
if already_locked {
|
||||||
|
// Recover previously locked state
|
||||||
|
log::info!("recovering previous locked state");
|
||||||
|
app.state = State::Locking;
|
||||||
|
lock()
|
||||||
|
} else {
|
||||||
// When logind feature is used, wait for lock signal
|
// When logind feature is used, wait for lock signal
|
||||||
Command::none()
|
Command::none()
|
||||||
} else {
|
}
|
||||||
// When logind feature not used, lock immediately
|
} else {
|
||||||
lock()
|
// When logind feature not used, lock immediately
|
||||||
},
|
log::info!("locking immediately");
|
||||||
)
|
app.state = State::Locking;
|
||||||
|
lock()
|
||||||
|
};
|
||||||
|
|
||||||
|
(app, command)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle application events here.
|
/// Handle application events here.
|
||||||
|
|
@ -425,6 +456,7 @@ impl cosmic::Application for App {
|
||||||
self.state = State::Locked;
|
self.state = State::Locked;
|
||||||
// Allow suspend
|
// Allow suspend
|
||||||
self.inhibit_opt = None;
|
self.inhibit_opt = None;
|
||||||
|
// Create lock surfaces
|
||||||
let mut commands = Vec::with_capacity(self.surface_ids.len());
|
let mut commands = Vec::with_capacity(self.surface_ids.len());
|
||||||
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()));
|
||||||
|
|
@ -513,6 +545,13 @@ impl cosmic::Application for App {
|
||||||
self.error_opt = None;
|
self.error_opt = None;
|
||||||
// Clear value_tx
|
// Clear value_tx
|
||||||
self.value_tx_opt = None;
|
self.value_tx_opt = None;
|
||||||
|
// Try to create lockfile when locking
|
||||||
|
if let Some(ref lockfile) = self.flags.lockfile_opt {
|
||||||
|
if let Err(err) = fs::File::create(lockfile) {
|
||||||
|
log::warn!("failed to create lockfile {:?}: {}", lockfile, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Tell compositor to lock
|
||||||
return lock();
|
return lock();
|
||||||
}
|
}
|
||||||
State::Unlocking => {
|
State::Unlocking => {
|
||||||
|
|
@ -531,10 +570,18 @@ impl cosmic::Application for App {
|
||||||
self.error_opt = None;
|
self.error_opt = None;
|
||||||
// Clear value_tx
|
// Clear value_tx
|
||||||
self.value_tx_opt = None;
|
self.value_tx_opt = None;
|
||||||
|
// Try to delete lockfile when unlocking
|
||||||
|
if let Some(ref lockfile) = self.flags.lockfile_opt {
|
||||||
|
if let Err(err) = fs::remove_file(lockfile) {
|
||||||
|
log::warn!("failed to remove lockfile {:?}: {}", lockfile, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Destroy lock surfaces
|
||||||
let mut commands = Vec::with_capacity(self.surface_ids.len() + 1);
|
let mut commands = Vec::with_capacity(self.surface_ids.len() + 1);
|
||||||
for (_output, surface_id) in self.surface_ids.iter() {
|
for (_output, surface_id) in self.surface_ids.iter() {
|
||||||
commands.push(destroy_lock_surface(*surface_id));
|
commands.push(destroy_lock_surface(*surface_id));
|
||||||
}
|
}
|
||||||
|
// 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 Command::batch(commands);
|
||||||
|
|
@ -642,7 +689,13 @@ impl cosmic::Application for App {
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
match self.flags.current_user.gecos.as_ref().filter(|s| !s.is_empty()) {
|
match self
|
||||||
|
.flags
|
||||||
|
.current_user
|
||||||
|
.gecos
|
||||||
|
.as_ref()
|
||||||
|
.filter(|s| !s.is_empty())
|
||||||
|
{
|
||||||
Some(gecos) => {
|
Some(gecos) => {
|
||||||
let full_name = gecos.split(",").next().unwrap_or_default();
|
let full_name = gecos.split(",").next().unwrap_or_default();
|
||||||
column = column.push(
|
column = column.push(
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ use logind_zbus::{
|
||||||
session::SessionProxy,
|
session::SessionProxy,
|
||||||
};
|
};
|
||||||
use std::{any::TypeId, error::Error, os::fd::OwnedFd, sync::Arc};
|
use std::{any::TypeId, error::Error, os::fd::OwnedFd, sync::Arc};
|
||||||
use tokio::time;
|
|
||||||
use zbus::Connection;
|
use zbus::Connection;
|
||||||
|
|
||||||
use crate::locker::Message;
|
use crate::locker::Message;
|
||||||
|
|
@ -68,7 +67,9 @@ pub fn subscription() -> Subscription<Message> {
|
||||||
pub async fn handler(msg_tx: &mut mpsc::Sender<Message>) -> Result<(), Box<dyn Error>> {
|
pub async fn handler(msg_tx: &mut mpsc::Sender<Message>) -> Result<(), Box<dyn Error>> {
|
||||||
let connection = Connection::system().await?;
|
let connection = Connection::system().await?;
|
||||||
let manager = ManagerProxy::new(&connection).await?;
|
let manager = ManagerProxy::new(&connection).await?;
|
||||||
let session_path = manager.get_session_by_PID(std::os::unix::process::parent_id()).await?;
|
let session_path = manager
|
||||||
|
.get_session_by_PID(std::os::unix::process::parent_id())
|
||||||
|
.await?;
|
||||||
let session = SessionProxy::builder(&connection)
|
let session = SessionProxy::builder(&connection)
|
||||||
.path(&session_path)?
|
.path(&session_path)?
|
||||||
.build()
|
.build()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue