Format Rust sources at 100 columns
This commit is contained in:
1 parent
4661f595f8
commit
610478f8c7
336 files changed
+23497
-7892
No files matched your search
@@ -32,7 +32,8 @@ impl Appearance {
|
||||
.and_then(|path| std::fs::read_to_string(path).ok())
|
||||
.and_then(|source| Document::parse(&source).ok());
|
||||
let mut theme = ferese_theme_client::service::current().presented;
|
||||
if let Some(path) = path.filter(|path| ferese_config::config_path().as_deref() != Some(*path))
|
||||
if let Some(path) =
|
||||
path.filter(|path| ferese_config::config_path().as_deref() != Some(*path))
|
||||
&& let Some(document) = &doc
|
||||
&& let Ok(mut connection) = ferese_ipc::Connection::connect()
|
||||
{
|
||||
@@ -49,7 +50,11 @@ impl Appearance {
|
||||
Self::from_document(user, doc, &theme)
|
||||
}
|
||||
|
||||
fn from_document(user: &str, doc: Option<Document>, theme: &ferese_config::theme::ResolvedTheme) -> Self {
|
||||
fn from_document(
|
||||
user: &str,
|
||||
doc: Option<Document>,
|
||||
theme: &ferese_config::theme::ResolvedTheme,
|
||||
) -> Self {
|
||||
let doc = doc.map(|doc| doc.with_theme(theme));
|
||||
let string = |key: &str, fallback: &str| {
|
||||
doc.as_ref()
|
||||
@@ -80,7 +85,9 @@ impl Appearance {
|
||||
let loaded = load_wallpaper(&wallpaper_path, if reduce_transparency { 0. } else { blur });
|
||||
let wallpaper_loaded = loaded.is_ok();
|
||||
let wallpaper = loaded.unwrap_or_else(|_| {
|
||||
image::Handle::from_bytes(include_bytes!("../../../assets/wallpapers/ferese.png").as_slice())
|
||||
image::Handle::from_bytes(
|
||||
include_bytes!("../../../assets/wallpapers/ferese.png").as_slice(),
|
||||
)
|
||||
});
|
||||
let boolean = |key, fallback| {
|
||||
doc.as_ref()
|
||||
@@ -134,7 +141,10 @@ impl Appearance {
|
||||
if self.wallpaper_pending.as_ref() == Some(&desired) {
|
||||
return None;
|
||||
}
|
||||
if self.wallpaper_loaded && path == self.wallpaper_path && reduce == self.reduce_transparency {
|
||||
if self.wallpaper_loaded
|
||||
&& path == self.wallpaper_path
|
||||
&& reduce == self.reduce_transparency
|
||||
{
|
||||
if self.wallpaper_pending.take().is_some() {
|
||||
self.wallpaper_revision = self.wallpaper_revision.wrapping_add(1);
|
||||
}
|
||||
@@ -149,7 +159,11 @@ impl Appearance {
|
||||
))
|
||||
}
|
||||
|
||||
pub fn finish_wallpaper(&mut self, revision: u64, result: Result<image::Handle, String>) -> Result<(), String> {
|
||||
pub fn finish_wallpaper(
|
||||
&mut self,
|
||||
revision: u64,
|
||||
result: Result<image::Handle, String>,
|
||||
) -> Result<(), String> {
|
||||
if revision != self.wallpaper_revision {
|
||||
return Ok(());
|
||||
}
|
||||
@@ -165,7 +179,11 @@ impl Appearance {
|
||||
}
|
||||
|
||||
pub fn clock_format(&self) -> &'static str {
|
||||
if self.twelve_hour { "%I:%M %p" } else { "%H:%M" }
|
||||
if self.twelve_hour {
|
||||
"%I:%M %p"
|
||||
} else {
|
||||
"%H:%M"
|
||||
}
|
||||
}
|
||||
|
||||
pub fn theme(&self) -> cosmic::Theme {
|
||||
@@ -188,7 +206,8 @@ impl Appearance {
|
||||
}
|
||||
|
||||
fn account_picture(user: &str) -> Option<image::Handle> {
|
||||
let mut candidates = vec![std::path::PathBuf::from("/var/lib/AccountsService/icons").join(user)];
|
||||
let mut candidates =
|
||||
vec![std::path::PathBuf::from("/var/lib/AccountsService/icons").join(user)];
|
||||
if let Some(home) = std::env::var_os("HOME") {
|
||||
candidates.push(std::path::PathBuf::from(home).join(".face"));
|
||||
}
|
||||
@@ -206,11 +225,13 @@ fn account_picture(user: &str) -> Option<image::Handle> {
|
||||
side,
|
||||
)
|
||||
.to_image();
|
||||
let mut pixels = ::image::imageops::resize(&square, 256, 256, ::image::imageops::FilterType::Lanczos3);
|
||||
let mut pixels =
|
||||
::image::imageops::resize(&square, 256, 256, ::image::imageops::FilterType::Lanczos3);
|
||||
// Clip the decoded thumbnail, so the avatar stays circular even on
|
||||
// renderers that do not support rounded image clipping.
|
||||
for (x, y, pixel) in pixels.enumerate_pixels_mut() {
|
||||
let distance = ((x as f32 + 0.5 - 128.).powi(2) + (y as f32 + 0.5 - 128.).powi(2)).sqrt();
|
||||
let distance =
|
||||
((x as f32 + 0.5 - 128.).powi(2) + (y as f32 + 0.5 - 128.).powi(2)).sqrt();
|
||||
let coverage = (128. - distance).clamp(0., 1.);
|
||||
pixel[3] = (pixel[3] as f32 * coverage).round() as u8;
|
||||
}
|
||||
@@ -235,7 +256,11 @@ fn decode_avatar(path: &std::path::Path) -> Result<::image::RgbaImage, String> {
|
||||
.custom_flags(libc::O_NONBLOCK)
|
||||
.open(path)
|
||||
.map_err(|error| error.to_string())?;
|
||||
if !file.metadata().map_err(|error| error.to_string())?.is_file() {
|
||||
if !file
|
||||
.metadata()
|
||||
.map_err(|error| error.to_string())?
|
||||
.is_file()
|
||||
{
|
||||
return Err("Avatar is not a regular file".into());
|
||||
}
|
||||
|
||||
@@ -323,7 +348,10 @@ mod tests {
|
||||
}
|
||||
match load_wallpaper(file.path(), 2.).unwrap() {
|
||||
image::Handle::Rgba {
|
||||
width, height, pixels, ..
|
||||
width,
|
||||
height,
|
||||
pixels,
|
||||
..
|
||||
} => {
|
||||
assert_eq!((width, height), (640, 360));
|
||||
assert_eq!(pixels.len(), 640 * 360 * 4);
|
||||
@@ -378,7 +406,10 @@ mod tests {
|
||||
assert!(appearance.request_wallpaper(&theme).is_none());
|
||||
theme.tokens.background.lock_path = Some(initial.clone());
|
||||
let (_, path, _) = appearance.request_wallpaper(&theme).unwrap();
|
||||
assert_eq!(path, initial, "an explicit lock image overrides the desktop wallpaper");
|
||||
assert_eq!(
|
||||
path, initial,
|
||||
"an explicit lock image overrides the desktop wallpaper"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -395,7 +426,11 @@ mod tests {
|
||||
assert!(decode_avatar(file.path()).is_err());
|
||||
|
||||
file.as_file().set_len(8 * 1024 * 1024 + 1).unwrap();
|
||||
assert!(decode_avatar(file.path()).unwrap_err().contains("file limit"));
|
||||
assert!(
|
||||
decode_avatar(file.path())
|
||||
.unwrap_err()
|
||||
.contains("file limit")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -429,9 +464,12 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
let document = Document::parse(&std::fs::read_to_string(&config).unwrap()).unwrap();
|
||||
let theme = ferese_config::theme::resolve(&document, directory.path(), jiff::Timestamp::now(), |_| {
|
||||
Err("unexpected file".into())
|
||||
})
|
||||
let theme = ferese_config::theme::resolve(
|
||||
&document,
|
||||
directory.path(),
|
||||
jiff::Timestamp::now(),
|
||||
|_| Err("unexpected file".into()),
|
||||
)
|
||||
.unwrap()
|
||||
.theme;
|
||||
let appearance = Appearance::from_document("no-such-test-user", Some(document), &theme);
|
||||
|
||||
@@ -14,7 +14,8 @@ struct Response {
|
||||
}
|
||||
#[repr(C)]
|
||||
struct Conversation {
|
||||
callback: unsafe extern "C" fn(c_int, *mut *const Message, *mut *mut Response, *mut c_void) -> c_int,
|
||||
callback:
|
||||
unsafe extern "C" fn(c_int, *mut *const Message, *mut *mut Response, *mut c_void) -> c_int,
|
||||
data: *mut c_void,
|
||||
}
|
||||
struct Credentials {
|
||||
@@ -38,7 +39,8 @@ unsafe extern "C" fn converse(
|
||||
unsafe {
|
||||
*out = std::ptr::null_mut();
|
||||
let credentials = &mut *(data as *mut Credentials);
|
||||
let responses = libc::calloc(count as usize, std::mem::size_of::<Response>()) as *mut Response;
|
||||
let responses =
|
||||
libc::calloc(count as usize, std::mem::size_of::<Response>()) as *mut Response;
|
||||
if responses.is_null() {
|
||||
return CONV_ERR;
|
||||
}
|
||||
@@ -49,11 +51,13 @@ unsafe extern "C" fn converse(
|
||||
} else {
|
||||
match (*msg).style {
|
||||
1 => {
|
||||
credentials.password_prompts = credentials.password_prompts.saturating_add(1);
|
||||
(credentials.password_prompts == 1).then_some(credentials.password.as_slice())
|
||||
credentials.password_prompts =
|
||||
credentials.password_prompts.saturating_add(1);
|
||||
(credentials.password_prompts == 1)
|
||||
.then_some(credentials.password.as_slice())
|
||||
} // Never send the password as a second-factor response.
|
||||
2 => Some(credentials.user.as_bytes_with_nul()), // PAM_PROMPT_ECHO_ON
|
||||
3 | 4 => Some(&[][..]), // PAM_ERROR_MSG / PAM_TEXT_INFO
|
||||
3 | 4 => Some(&[][..]), // PAM_ERROR_MSG / PAM_TEXT_INFO
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
@@ -61,7 +65,11 @@ unsafe extern "C" fn converse(
|
||||
if !bytes.is_empty() {
|
||||
let allocation = libc::malloc(bytes.len()) as *mut c_char;
|
||||
if !allocation.is_null() {
|
||||
std::ptr::copy_nonoverlapping(bytes.as_ptr(), allocation.cast(), bytes.len());
|
||||
std::ptr::copy_nonoverlapping(
|
||||
bytes.as_ptr(),
|
||||
allocation.cast(),
|
||||
bytes.len(),
|
||||
);
|
||||
(*responses.add(i)).text = allocation;
|
||||
continue;
|
||||
}
|
||||
@@ -131,7 +139,12 @@ fn authenticate_with(user: &str, password: &str, config: Option<&CStr>) -> bool
|
||||
let Ok(library) = libloading::Library::new("libpam.so.0") else {
|
||||
return false;
|
||||
};
|
||||
type Start = unsafe extern "C" fn(*const c_char, *const c_char, *const Conversation, *mut *mut c_void) -> c_int;
|
||||
type Start = unsafe extern "C" fn(
|
||||
*const c_char,
|
||||
*const c_char,
|
||||
*const Conversation,
|
||||
*mut *mut c_void,
|
||||
) -> c_int;
|
||||
type StartConf = unsafe extern "C" fn(
|
||||
*const c_char,
|
||||
*const c_char,
|
||||
|
||||
@@ -22,7 +22,8 @@ fn main() -> iced::Result {
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
let preview = args == ["--preview"] || (args.len() == 3 && args[0] == "--preview" && args[1] == "--config");
|
||||
let preview = args == ["--preview"]
|
||||
|| (args.len() == 3 && args[0] == "--preview" && args[1] == "--config");
|
||||
let config = if preview && args.len() == 3 {
|
||||
Some(std::path::PathBuf::from(&args[2]))
|
||||
} else {
|
||||
@@ -113,7 +114,8 @@ impl AuthState {
|
||||
}
|
||||
|
||||
fn retry_ready(&mut self, now: Instant) -> bool {
|
||||
if matches!(self, Self::Rejected(at) if now.saturating_duration_since(*at) >= Duration::from_secs(2)) {
|
||||
if matches!(self, Self::Rejected(at) if now.saturating_duration_since(*at) >= Duration::from_secs(2))
|
||||
{
|
||||
*self = Self::Ready;
|
||||
true
|
||||
} else {
|
||||
@@ -202,14 +204,17 @@ impl cosmic::Application for Locker {
|
||||
if self.preview {
|
||||
Subscription::none()
|
||||
} else {
|
||||
ferese_theme_client::service::subscription().map(|snapshot| Message::ThemeChanged(Box::new(snapshot)))
|
||||
ferese_theme_client::service::subscription()
|
||||
.map(|snapshot| Message::ThemeChanged(Box::new(snapshot)))
|
||||
},
|
||||
event::listen_with(|event, _, _| match event {
|
||||
Event::PlatformSpecific(PlatformSpecific::Wayland(
|
||||
wayland::Event::Output(..) | wayland::Event::SessionLock(..),
|
||||
))
|
||||
| Event::Window(window::Event::Opened { .. })
|
||||
| Event::Keyboard(iced::keyboard::Event::ModifiersChanged(_)) => Some(Message::Event(Box::new(event))),
|
||||
| Event::Keyboard(iced::keyboard::Event::ModifiersChanged(_)) => {
|
||||
Some(Message::Event(Box::new(event)))
|
||||
}
|
||||
_ => None,
|
||||
}),
|
||||
if self.appearance.show_clock || self.appearance.show_date {
|
||||
@@ -236,13 +241,18 @@ impl cosmic::Application for Locker {
|
||||
self.appearance.accent = palette.accent;
|
||||
self.appearance.on_accent = palette.on_accent;
|
||||
self.appearance.radius = palette.radius;
|
||||
self.appearance.font = ferese_theme::font(Some(&snapshot.presented.tokens.typography.font_family));
|
||||
self.appearance.font =
|
||||
ferese_theme::font(Some(&snapshot.presented.tokens.typography.font_family));
|
||||
let theme = cosmic::command::set_theme(self.appearance.theme());
|
||||
if let Some((revision, path, blur)) = self.appearance.request_wallpaper(&snapshot.theme) {
|
||||
if let Some((revision, path, blur)) =
|
||||
self.appearance.request_wallpaper(&snapshot.theme)
|
||||
{
|
||||
let wallpaper = cosmic::task::future(async move {
|
||||
let result = tokio::task::spawn_blocking(move || appearance::load_wallpaper(&path, blur))
|
||||
.await
|
||||
.unwrap_or_else(|e| Err(e.to_string()));
|
||||
let result = tokio::task::spawn_blocking(move || {
|
||||
appearance::load_wallpaper(&path, blur)
|
||||
})
|
||||
.await
|
||||
.unwrap_or_else(|e| Err(e.to_string()));
|
||||
Message::WallpaperLoaded(revision, result)
|
||||
});
|
||||
return Task::batch([theme, wallpaper]);
|
||||
@@ -284,7 +294,10 @@ impl cosmic::Application for Locker {
|
||||
return focus();
|
||||
}
|
||||
|
||||
if !self.confirmation.confirmed() || !self.state.may_submit() || self.password.is_empty() {
|
||||
if !self.confirmation.confirmed()
|
||||
|| !self.state.may_submit()
|
||||
|| self.password.is_empty()
|
||||
{
|
||||
return Task::none();
|
||||
}
|
||||
|
||||
@@ -337,9 +350,10 @@ impl Locker {
|
||||
Event::Keyboard(iced::keyboard::Event::ModifiersChanged(modifiers)) => {
|
||||
self.caps_lock = modifiers.contains(iced::keyboard::Modifiers::CAPS_LOCK);
|
||||
}
|
||||
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::Output(event, output)))
|
||||
if !self.preview =>
|
||||
{
|
||||
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::Output(
|
||||
event,
|
||||
output,
|
||||
))) if !self.preview => {
|
||||
if matches!(event, wayland::OutputEvent::Removed) {
|
||||
if let Some(id) = self.outputs.remove(&output) {
|
||||
return session_lock::destroy_lock_surface(id);
|
||||
@@ -352,33 +366,33 @@ impl Locker {
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::SessionLock(event))) if !self.preview => {
|
||||
match event {
|
||||
wayland::SessionLockEvent::Locked if self.confirmation.observe(&event) => {
|
||||
use std::io::Write;
|
||||
if std::env::var_os("FERESE_LOCK_READY").is_some() {
|
||||
let _ = writeln!(std::io::stdout().lock(), "FERESE_LOCKED");
|
||||
}
|
||||
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::SessionLock(
|
||||
event,
|
||||
))) if !self.preview => match event {
|
||||
wayland::SessionLockEvent::Locked if self.confirmation.observe(&event) => {
|
||||
use std::io::Write;
|
||||
if std::env::var_os("FERESE_LOCK_READY").is_some() {
|
||||
let _ = writeln!(std::io::stdout().lock(), "FERESE_LOCKED");
|
||||
}
|
||||
wayland::SessionLockEvent::Requested if !self.started => {
|
||||
self.started = true;
|
||||
return Task::batch(
|
||||
self.outputs
|
||||
.iter()
|
||||
.map(|(output, id)| session_lock::get_lock_surface(*id, output.clone())),
|
||||
);
|
||||
}
|
||||
wayland::SessionLockEvent::Focused(..) => return focus(),
|
||||
wayland::SessionLockEvent::Unlocked if self.state == AuthState::Unlocking => {
|
||||
return iced::exit();
|
||||
}
|
||||
wayland::SessionLockEvent::Finished | wayland::SessionLockEvent::NotSupported => {
|
||||
eprintln!("ferese-lock: compositor refused the lock");
|
||||
return iced::exit();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
wayland::SessionLockEvent::Requested if !self.started => {
|
||||
self.started = true;
|
||||
return Task::batch(
|
||||
self.outputs.iter().map(|(output, id)| {
|
||||
session_lock::get_lock_surface(*id, output.clone())
|
||||
}),
|
||||
);
|
||||
}
|
||||
wayland::SessionLockEvent::Focused(..) => return focus(),
|
||||
wayland::SessionLockEvent::Unlocked if self.state == AuthState::Unlocking => {
|
||||
return iced::exit();
|
||||
}
|
||||
wayland::SessionLockEvent::Finished | wayland::SessionLockEvent::NotSupported => {
|
||||
eprintln!("ferese-lock: compositor refused the lock");
|
||||
return iced::exit();
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
Event::Window(window::Event::Opened { .. }) => {
|
||||
return focus();
|
||||
}
|
||||
@@ -403,7 +417,14 @@ impl Locker {
|
||||
fn screen_content(&self, size: iced::Size) -> Element<'_, Message> {
|
||||
let avatar_size = (size.height * 0.08).clamp(56., 88.);
|
||||
let clock_size = (size.height * 0.06)
|
||||
.min(size.width * if self.appearance.twelve_hour { 0.055 } else { 0.085 })
|
||||
.min(
|
||||
size.width
|
||||
* if self.appearance.twelve_hour {
|
||||
0.055
|
||||
} else {
|
||||
0.085
|
||||
},
|
||||
)
|
||||
.clamp(32., 72.) as u16;
|
||||
let margin = if size.width < 640. { 24. } else { 36. };
|
||||
let top = (size.height * 0.09).max(24.);
|
||||
@@ -412,7 +433,9 @@ impl Locker {
|
||||
.password()
|
||||
.padding([4, 10])
|
||||
.size(14)
|
||||
.style(ferese_theme::controls::lock_input(a.radius, a.accent, a.panel))
|
||||
.style(ferese_theme::controls::lock_input(
|
||||
a.radius, a.accent, a.panel,
|
||||
))
|
||||
.font(a.font)
|
||||
.id(widget::Id::new("password"));
|
||||
|
||||
@@ -468,8 +491,15 @@ impl Locker {
|
||||
self.label(&self.user, 16).class(iced::Color::WHITE),
|
||||
widget::Space::new().height(6),
|
||||
input,
|
||||
self.label(if self.caps_lock { "Caps Lock is on" } else { self.status }, 12)
|
||||
.class(iced::Color::WHITE.scale_alpha(0.68)),
|
||||
self.label(
|
||||
if self.caps_lock {
|
||||
"Caps Lock is on"
|
||||
} else {
|
||||
self.status
|
||||
},
|
||||
12
|
||||
)
|
||||
.class(iced::Color::WHITE.scale_alpha(0.68)),
|
||||
]
|
||||
.spacing(12)
|
||||
.align_x(iced::Alignment::Center)
|
||||
@@ -492,10 +522,17 @@ impl Locker {
|
||||
}
|
||||
|
||||
if a.show_date {
|
||||
clock = clock.push(self.label(&self.date, 18).class(iced::Color::WHITE.scale_alpha(0.72)));
|
||||
clock = clock.push(
|
||||
self.label(&self.date, 18)
|
||||
.class(iced::Color::WHITE.scale_alpha(0.72)),
|
||||
);
|
||||
}
|
||||
|
||||
let clock_height = if a.show_clock { clock_size as f32 * 1.3 } else { 0. } + if a.show_date { 24. } else { 0. };
|
||||
let clock_height = if a.show_clock {
|
||||
clock_size as f32 * 1.3
|
||||
} else {
|
||||
0.
|
||||
} + if a.show_date { 24. } else { 0. };
|
||||
let gap = (size.height * 0.44 - top - clock_height).max(24.);
|
||||
let foreground = container(
|
||||
column![
|
||||
@@ -529,12 +566,14 @@ impl Locker {
|
||||
})
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.class(theme::Container::custom(move |_| widget::container::Style {
|
||||
text_color: Some(iced::Color::WHITE.scale_alpha(0.65)),
|
||||
background: Some(iced::Background::Color(iced::Color::from_rgba(
|
||||
0.025, 0.035, 0.06, a.dim,
|
||||
))),
|
||||
..Default::default()
|
||||
.class(theme::Container::custom(move |_| {
|
||||
widget::container::Style {
|
||||
text_color: Some(iced::Color::WHITE.scale_alpha(0.65)),
|
||||
background: Some(iced::Background::Color(iced::Color::from_rgba(
|
||||
0.025, 0.035, 0.06, a.dim,
|
||||
))),
|
||||
..Default::default()
|
||||
}
|
||||
}));
|
||||
let background: Element<'_, Message> = image(a.wallpaper.clone())
|
||||
.width(Length::Fill)
|
||||
@@ -588,6 +627,8 @@ mod tests {
|
||||
}
|
||||
#[test]
|
||||
fn password_messages_are_redacted() {
|
||||
assert!(!format!("{:?}", Message::Input(Zeroizing::new("secret".into()))).contains("secret"));
|
||||
assert!(
|
||||
!format!("{:?}", Message::Input(Zeroizing::new("secret".into()))).contains("secret")
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -18,8 +18,10 @@ impl Dispatch<wl_registry::WlRegistry, GlobalListContents> for Registry {
|
||||
}
|
||||
}
|
||||
pub fn check_protocol() -> Result<(), String> {
|
||||
let connection = Connection::connect_to_env().map_err(|e| format!("Wayland connection: {e}"))?;
|
||||
let (globals, _) = registry_queue_init::<Registry>(&connection).map_err(|e| format!("Wayland registry: {e}"))?;
|
||||
let connection =
|
||||
Connection::connect_to_env().map_err(|e| format!("Wayland connection: {e}"))?;
|
||||
let (globals, _) = registry_queue_init::<Registry>(&connection)
|
||||
.map_err(|e| format!("Wayland registry: {e}"))?;
|
||||
if globals
|
||||
.contents()
|
||||
.clone_list()
|
||||
@@ -70,7 +72,11 @@ pub struct Confirmation {
|
||||
}
|
||||
impl Confirmation {
|
||||
pub fn observe(&mut self, event: &cosmic::iced::event::wayland::SessionLockEvent) -> bool {
|
||||
if !matches!(event, cosmic::iced::event::wayland::SessionLockEvent::Locked) || self.confirmed {
|
||||
if !matches!(
|
||||
event,
|
||||
cosmic::iced::event::wayland::SessionLockEvent::Locked
|
||||
) || self.confirmed
|
||||
{
|
||||
return false;
|
||||
}
|
||||
self.confirmed = true;
|
||||
@@ -88,7 +94,12 @@ mod tests {
|
||||
fn invalid_confirmation_returns_without_waiting_for_or_killing_the_locker() {
|
||||
for message in ["unexpected", "FERESE_LOCKED"] {
|
||||
let mut child = Command::new("sh")
|
||||
.args(["-c", "printf '%s\\n' \"$1\"; exec sleep 3", "lock-fixture", message])
|
||||
.args([
|
||||
"-c",
|
||||
"printf '%s\\n' \"$1\"; exec sleep 3",
|
||||
"lock-fixture",
|
||||
message,
|
||||
])
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
@@ -105,7 +116,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn only_compositor_confirmation_marks_the_lock_ready_once() {
|
||||
use cosmic::iced::event::wayland::SessionLockEvent::{Finished, Locked, NotSupported, Requested};
|
||||
use cosmic::iced::event::wayland::SessionLockEvent::{
|
||||
Finished, Locked, NotSupported, Requested,
|
||||
};
|
||||
let mut c = Confirmation::default();
|
||||
for event in [Requested, Requested, Finished, NotSupported] {
|
||||
assert!(!c.observe(&event));
|
||||
@@ -131,7 +144,9 @@ pub fn minute_ticks() -> impl cosmic::iced::futures::Stream<Item = ()> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn retry_deadline(at: &std::time::Instant) -> impl cosmic::iced::futures::Stream<Item = ()> + use<> {
|
||||
pub fn retry_deadline(
|
||||
at: &std::time::Instant,
|
||||
) -> impl cosmic::iced::futures::Stream<Item = ()> + use<> {
|
||||
let at = *at;
|
||||
cosmic::iced::futures::stream::once(async move {
|
||||
tokio::time::sleep(Duration::from_secs(2).saturating_sub(at.elapsed())).await;
|
||||
@@ -149,6 +164,9 @@ mod clock_tests {
|
||||
until_next_minute(Duration::from_millis(119_999)),
|
||||
Duration::from_millis(1)
|
||||
);
|
||||
assert_eq!(until_next_minute(Duration::from_secs(125)), Duration::from_secs(55));
|
||||
assert_eq!(
|
||||
until_next_minute(Duration::from_secs(125)),
|
||||
Duration::from_secs(55)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user