Compare commits
2 Commits
8e66dc234e
...
b6282d82c6
Author | SHA1 | Date | |
---|---|---|---|
b6282d82c6 | |||
4ed974335e |
1421
Cargo.lock
generated
1421
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -10,3 +10,7 @@ members = [
|
||||
"systemd",
|
||||
"xcb-xembed",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
[patch.crates-io]
|
||||
xkb = { git = "https://github.com/kelnos/rust-xkb", branch = "remove-missing-keysyms" }
|
||||
|
2
Makefile
2
Makefile
@ -63,7 +63,7 @@ install: all
|
||||
$(INSTALL) -m 0644 $(RELEASE_MANPAGES) $(DESTDIR)$(MANDIR)/man1
|
||||
|
||||
$(DEV_TARGETS): $(SOURCES)
|
||||
HELPER_DIR=target/debug cargo build
|
||||
HELPER_DIR=$(shell pwd)/target/debug cargo build
|
||||
|
||||
$(RELEASE_TARGETS): $(SOURCES)
|
||||
HELPER_DIR=$(HELPER_DIR) cargo build --release
|
||||
|
@ -4,9 +4,9 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
async-io = "1.6"
|
||||
async-std = { version = "1.11", features = ["attributes"] }
|
||||
async-io = "2.3"
|
||||
async-std = { version = "1.12", features = ["attributes"] }
|
||||
futures = "0.3"
|
||||
futures-lite = "1.12"
|
||||
nix = "0.23"
|
||||
futures-lite = "2.3"
|
||||
nix = { version = "0.29", features = ["fs"] }
|
||||
xcb = "1"
|
||||
|
@ -1,12 +1,24 @@
|
||||
use async_io::{Async, ReadableOwned};
|
||||
use futures::prelude::*;
|
||||
use futures_lite::ready;
|
||||
use nix::{fcntl::{fcntl, F_GETFL, F_SETFL, OFlag}, unistd::read};
|
||||
use std::{io, os::unix::io::AsRawFd, pin::Pin, sync::Arc, task::{Context, Poll}};
|
||||
use nix::{fcntl::{fcntl, OFlag, F_GETFL, F_SETFL}, unistd::read};
|
||||
use std::{io, os::{fd::{AsFd, BorrowedFd}, unix::io::AsRawFd}, pin::Pin, sync::Arc, task::{Context, Poll}};
|
||||
|
||||
struct XcbAsFdWrapper(xcb::Connection);
|
||||
|
||||
impl AsFd for XcbAsFdWrapper {
|
||||
fn as_fd(&self) -> std::os::unix::prelude::BorrowedFd<'_> {
|
||||
let fd = self.0.as_raw_fd();
|
||||
if fd < 0 {
|
||||
panic!("XCB file descriptor is invalid");
|
||||
}
|
||||
unsafe { BorrowedFd::borrow_raw(fd) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AsyncConnection {
|
||||
conn: Arc<Async<xcb::Connection>>,
|
||||
readable: Option<ReadableOwned<xcb::Connection>>,
|
||||
conn: Arc<Async<XcbAsFdWrapper>>,
|
||||
readable: Option<ReadableOwned<XcbAsFdWrapper>>,
|
||||
}
|
||||
|
||||
impl AsyncConnection {
|
||||
@ -14,7 +26,7 @@ impl AsyncConnection {
|
||||
let flags = fcntl(conn.as_raw_fd(), F_GETFL)?;
|
||||
fcntl(conn.as_raw_fd(), F_SETFL(OFlag::from_bits_truncate(flags) | OFlag::O_NONBLOCK))?;
|
||||
Ok(Self {
|
||||
conn: Arc::new(Async::new(conn)?),
|
||||
conn: Arc::new(Async::new(XcbAsFdWrapper(conn))?),
|
||||
readable: None,
|
||||
})
|
||||
}
|
||||
@ -23,7 +35,7 @@ impl AsyncConnection {
|
||||
impl AsyncRead for AsyncConnection {
|
||||
fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<std::io::Result<usize>> {
|
||||
loop {
|
||||
match read(self.conn.as_raw_fd(), buf) {
|
||||
match read(self.conn.as_fd().as_raw_fd(), buf) {
|
||||
Err(nix::Error::EAGAIN) => (),
|
||||
Err(err) => {
|
||||
self.readable = None;
|
||||
|
@ -5,6 +5,6 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
bscreensaver-util = { path = "../util" }
|
||||
clap = "3"
|
||||
nix = "0.23"
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
nix = { version = "0.29", features = ["poll"] }
|
||||
xcb = "1"
|
||||
|
@ -1,8 +1,8 @@
|
||||
use nix::poll::{poll, PollFd, PollFlags};
|
||||
use std::{cmp, error::Error as StdError, fmt, time::{Duration, Instant}, os::unix::prelude::AsRawFd};
|
||||
use nix::poll::{poll, PollFd, PollFlags, PollTimeout};
|
||||
use std::{error::Error as StdError, fmt, os::unix::prelude::AsRawFd, time::{Duration, Instant}};
|
||||
use xcb::{x, Xid};
|
||||
|
||||
use bscreensaver_util::{create_atom, BSCREENSAVER_WM_CLASS};
|
||||
use bscreensaver_util::{borrow_raw_fd, create_atom, BSCREENSAVER_WM_CLASS};
|
||||
|
||||
const COMMAND_WINDOW_ID_ATOM_NAME: &[u8] = b"BSCREENSAVER_COMMAND_WINDOW_ID";
|
||||
const COMMAND_WINDOW_WM_NAME: &[u8] = b"bscreensaver command window";
|
||||
@ -268,16 +268,13 @@ pub fn bscreensaver_command(command: BCommand, timeout: Option<Duration>) -> Res
|
||||
let poll_timeout = timeout.map(|to| {
|
||||
let since_start = start.elapsed();
|
||||
if since_start > to {
|
||||
0i32
|
||||
Err(Error::Timeout)
|
||||
} else {
|
||||
cmp::max(i32::MAX as u128, (to - since_start).as_millis()) as i32
|
||||
}
|
||||
}).unwrap_or(-1);
|
||||
if poll_timeout == 0 {
|
||||
break 'outer1 Err(Error::Timeout);
|
||||
Ok(u16::try_from((to - since_start).as_millis()).unwrap_or(u16::MAX).into())
|
||||
}
|
||||
}).unwrap_or(Ok(PollTimeout::NONE))?;
|
||||
|
||||
let mut pfds = vec![PollFd::new(conn.as_raw_fd(), PollFlags::POLLIN)];
|
||||
let mut pfds = vec![PollFd::new(borrow_raw_fd(conn.as_raw_fd()), PollFlags::POLLIN)];
|
||||
poll(pfds.as_mut_slice(), poll_timeout)?;
|
||||
}
|
||||
}
|
||||
|
@ -1,58 +1,48 @@
|
||||
use clap::{Arg, Command};
|
||||
use std::{env, io, process::exit, time::Duration};
|
||||
use clap::{CommandFactory, Parser};
|
||||
use std::{io, process::exit, time::Duration};
|
||||
|
||||
use bscreensaver_command::{BCommand, Error, bscreensaver_command};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(name = "bscreensaver-command", version, author, about = "Send commands to the running bscreensaver instance", long_about = None)]
|
||||
struct Args {
|
||||
/// Blanks the screen right now
|
||||
#[arg(short = 'b', long = "blank")]
|
||||
blank: bool,
|
||||
|
||||
/// Lock the screen right now
|
||||
#[arg(short = 'l', long = "lock")]
|
||||
lock: bool,
|
||||
|
||||
/// Deactivates the screen lock, presenting the unlock dialog if needed. This can be used to 'reset' things so the screensaver thinks there has been user input
|
||||
#[arg(short = 'd', long = "deactivate")]
|
||||
deactivate: bool,
|
||||
|
||||
/// Restarts the bscreensaver daemon
|
||||
#[arg(short = 'r', long = "restart")]
|
||||
restart: bool,
|
||||
|
||||
/// Causes the bscreensaver daemon to exit now, even if the screen is locked
|
||||
#[arg(short = 'x', long = "exit")]
|
||||
exit: bool,
|
||||
}
|
||||
|
||||
fn main() -> io::Result<()> {
|
||||
let mut command = Command::new("bscreensaver-command")
|
||||
.author(env!("CARGO_PKG_AUTHORS"))
|
||||
.version(env!("CARGO_PKG_VERSION"))
|
||||
.about("Send commands to the running bscreensaver instance")
|
||||
.arg(
|
||||
Arg::new("blank")
|
||||
.long("blank")
|
||||
.short('b')
|
||||
.help("Blanks the screen right now")
|
||||
)
|
||||
.arg(
|
||||
Arg::new("lock")
|
||||
.long("lock")
|
||||
.short('l')
|
||||
.help("Lock the screen right now")
|
||||
)
|
||||
.arg(
|
||||
Arg::new("deactivate")
|
||||
.long("deactivate")
|
||||
.short('d')
|
||||
.help("Deactivates the screen lock, presenting the unlock dialog if needed. This can be used to 'reset' things so the screensaver thinks there has been user input")
|
||||
)
|
||||
.arg(
|
||||
Arg::new("restart")
|
||||
.long("restart")
|
||||
.short('r')
|
||||
.help("Restarts the bscreensaver daemon")
|
||||
)
|
||||
.arg(
|
||||
Arg::new("exit")
|
||||
.long("exit")
|
||||
.short('x')
|
||||
.help("Causes the bscreensaver daemon to exit now, even if the screen is locked")
|
||||
);
|
||||
let args = command.get_matches_mut();
|
||||
let args = Args::parse();
|
||||
|
||||
let command =
|
||||
if args.is_present("blank") {
|
||||
if args.blank {
|
||||
BCommand::Blank
|
||||
} else if args.is_present("lock") {
|
||||
} else if args.lock {
|
||||
BCommand::Lock
|
||||
} else if args.is_present("deactivate") {
|
||||
} else if args.deactivate {
|
||||
BCommand::Deactivate
|
||||
} else if args.is_present("restart") {
|
||||
} else if args.restart {
|
||||
BCommand::Restart
|
||||
} else if args.is_present("exit") {
|
||||
} else if args.exit {
|
||||
BCommand::Exit
|
||||
} else {
|
||||
command.print_help()?;
|
||||
Args::command().print_help()?;
|
||||
exit(1);
|
||||
};
|
||||
|
||||
|
@ -12,4 +12,4 @@ bscreensaver-util = { path = "../util" }
|
||||
futures = "0.3"
|
||||
log = "0.4"
|
||||
xcb = { version = "1", features = ["dpms"] }
|
||||
zbus = "3"
|
||||
zbus = "4"
|
||||
|
@ -3,7 +3,7 @@ use bscreensaver_util::init_logging;
|
||||
use futures::{future::FutureExt, pin_mut, select};
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use std::{io, process::exit, time::{Duration, Instant}};
|
||||
use zbus::{dbus_interface, fdo::{self, DBusProxy, RequestNameFlags}, names::{BusName, UniqueName, WellKnownName}, ConnectionBuilder, MessageHeader};
|
||||
use zbus::{interface, fdo::{self, DBusProxy, RequestNameFlags}, names::{BusName, UniqueName, WellKnownName}, ConnectionBuilder, MessageHeader};
|
||||
|
||||
use bscreensaver_command::{bscreensaver_command, BCommand};
|
||||
use bscreensaver_util::opt_contains;
|
||||
@ -25,7 +25,7 @@ struct ScreenSaver {
|
||||
state: Arc<Mutex<State>>,
|
||||
}
|
||||
|
||||
#[dbus_interface(name = "org.freedesktop.ScreenSaver")]
|
||||
#[interface(name = "org.freedesktop.ScreenSaver")]
|
||||
impl ScreenSaver {
|
||||
async fn inhibit(
|
||||
&mut self,
|
||||
@ -47,7 +47,7 @@ impl ScreenSaver {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
let peer = hdr.sender()?;
|
||||
let peer = hdr.sender();
|
||||
let cookie = rand_u32().await
|
||||
.map_err(|err| fdo::Error::IOError(err.to_string()))?;
|
||||
self.state.lock().await.inhibitors.push(Inhibitor {
|
||||
|
@ -7,12 +7,18 @@ edition = "2021"
|
||||
anyhow = "1"
|
||||
bscreensaver-util = { path = "../util" }
|
||||
chrono = "0.4"
|
||||
gethostname = "0.2"
|
||||
glib = { version = "0.15", features = ["log"] }
|
||||
gtk = "0.15"
|
||||
gtk-sys = "0.15"
|
||||
gdk-sys = "0.15"
|
||||
gdkx11 = "0.15"
|
||||
gethostname = "0.4"
|
||||
glib = { version = "0.18", features = ["log"] }
|
||||
gtk = "0.18"
|
||||
gtk-sys = "0.18"
|
||||
gdk-sys = "0.18"
|
||||
gdkx11 = "0.18"
|
||||
log = "0.4"
|
||||
pam-client = "0.5"
|
||||
shell-words = "1"
|
||||
|
||||
[build-dependencies]
|
||||
# pam-sys specifies default-features = false, which drops the 'runtime'
|
||||
# feature; this ends up conflicting with the xkbcommon-sys build in another
|
||||
# module, which causes pam-sys to fail to build
|
||||
bindgen = { version = "0.69", features = ["runtime"] }
|
||||
|
@ -1,7 +1,7 @@
|
||||
use chrono::prelude::*;
|
||||
use gdkx11::X11Window;
|
||||
use gethostname::gethostname;
|
||||
use glib::{GString, clone};
|
||||
use glib::{ControlFlow, GString, clone};
|
||||
use gtk::{prelude::*, Button, Entry, Label, Plug, Window};
|
||||
use log::{debug, error, warn};
|
||||
use std::{io::{self, Write}, sync::mpsc, thread, time::Duration, ffi::CString};
|
||||
@ -215,7 +215,7 @@ fn main() -> anyhow::Result<()> {
|
||||
vbox.pack_start(&label, false, false, 0);
|
||||
glib::timeout_add_seconds_local(1, move || {
|
||||
set_time_label(&label);
|
||||
glib::Continue(true)
|
||||
ControlFlow::Continue
|
||||
});
|
||||
|
||||
let sep = gtk::Separator::builder()
|
||||
@ -275,19 +275,19 @@ fn main() -> anyhow::Result<()> {
|
||||
.build();
|
||||
top_vbox.pack_end(&timer, false, false, 0);
|
||||
let delta = (DIALOG_UPDATE_INTERVAL.as_millis() as f64) / (DIALOG_TIMEOUT.as_millis() as f64);
|
||||
glib::timeout_add_local(DIALOG_UPDATE_INTERVAL, clone!(@weak timer => @default-return Continue(false), move || {
|
||||
glib::timeout_add_local(DIALOG_UPDATE_INTERVAL, clone!(@weak timer => @default-return ControlFlow::Break, move || {
|
||||
let new_fraction = timer.fraction() - delta;
|
||||
if new_fraction <= 0.0 {
|
||||
DialogExitStatus::AuthTimedOut.exit();
|
||||
}
|
||||
timer.set_fraction(new_fraction);
|
||||
Continue(true)
|
||||
ControlFlow::Continue
|
||||
}));
|
||||
|
||||
let (tx, rx) = glib::MainContext::channel(glib::Priority::default());
|
||||
let username = bscreensaver_util::get_username()?;
|
||||
|
||||
rx.attach(None, clone!(@weak dialog, @weak auth_vbox, @weak accept_button_box, @weak timer, @strong username, => @default-return glib::Continue(false), move |op| {
|
||||
rx.attach(None, clone!(@weak dialog, @weak auth_vbox, @weak accept_button_box, @weak timer, @strong username, => @default-return ControlFlow::Break, move |op| {
|
||||
for child in auth_vbox.children() {
|
||||
auth_vbox.remove(&child);
|
||||
}
|
||||
@ -366,7 +366,7 @@ fn main() -> anyhow::Result<()> {
|
||||
if ev.keyval().name() == Some(GString::from("Escape")) {
|
||||
DialogExitStatus::AuthCanceled.exit();
|
||||
}
|
||||
gtk::Inhibit(false)
|
||||
glib::Propagation::Stop
|
||||
}));
|
||||
input_box.grab_focus();
|
||||
|
||||
@ -388,7 +388,7 @@ fn main() -> anyhow::Result<()> {
|
||||
};
|
||||
|
||||
dialog.show_all();
|
||||
glib::Continue(true)
|
||||
ControlFlow::Continue
|
||||
}));
|
||||
|
||||
thread::spawn(move || {
|
||||
|
@ -42,13 +42,13 @@ assets = [
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
clap = "3"
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
bscreensaver-command = { path = "../command" }
|
||||
bscreensaver-util = { path = "../util" }
|
||||
libc = "0.2"
|
||||
log = "0.4"
|
||||
nix = "0.23"
|
||||
nix = { version = "0.29", features = ["process", "signal"] }
|
||||
xcb = { version = "1", features = ["randr", "xkb", "xfixes", "xinput"] }
|
||||
xcb-xembed = { path = "../xcb-xembed" }
|
||||
xkb = { version = "0.3", features = ["x11"] }
|
||||
xkbcommon-sys = { version = "1", feature = "x11" }
|
||||
xkbcommon-sys = { version = "=1.4.1", features = ["x11"] }
|
||||
|
@ -1,23 +1,13 @@
|
||||
use clap::{Arg, Command as ClapCommand};
|
||||
use clap::Parser;
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use nix::{
|
||||
poll::{poll, PollFd, PollFlags},
|
||||
unistd::{execv, fork, setsid, ForkResult},
|
||||
sys::{
|
||||
poll::{poll, PollFd, PollFlags, PollTimeout}, sys::{
|
||||
signal::{sigprocmask, SigSet, SigmaskHow, Signal},
|
||||
signalfd::{SignalFd, SfdFlags},
|
||||
},
|
||||
signalfd::{SfdFlags, SignalFd},
|
||||
}, unistd::{execv, fork, setsid, ForkResult}
|
||||
};
|
||||
use std::{
|
||||
env,
|
||||
ffi::CString,
|
||||
fs::read_link,
|
||||
io,
|
||||
os::unix::io::AsRawFd,
|
||||
rc::Rc,
|
||||
process::exit,
|
||||
sync::Mutex,
|
||||
time::{Duration, Instant}, path::PathBuf,
|
||||
env, ffi::CString, fs::read_link, io, os::{fd::AsFd, unix::io::AsRawFd}, path::PathBuf, process::exit, rc::Rc, sync::Mutex, time::{Duration, Instant}
|
||||
};
|
||||
use xcb::{randr, x, xfixes, xinput};
|
||||
|
||||
@ -30,33 +20,35 @@ const LOCKED_ARG: &str = "locked";
|
||||
macro_rules! maybe_add_fd {
|
||||
($pfds:expr, $fd:expr) => {
|
||||
if let Some(fd) = $fd {
|
||||
$pfds.push(PollFd::new(fd, PollFlags::POLLIN));
|
||||
if fd >= 0 {
|
||||
$pfds.push(PollFd::new(borrow_raw_fd(fd), PollFlags::POLLIN));
|
||||
Some(fd)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(name = "bscreensaver", version, author, about = "Blanks and locks the screen after a period of time", long_about = None)]
|
||||
struct Args {
|
||||
/// Starts up in already blanked
|
||||
#[arg(long = BLANKED_ARG)]
|
||||
blanked: bool,
|
||||
|
||||
/// Stats up already blanked and locked
|
||||
#[arg(long = LOCKED_ARG)]
|
||||
locked: bool,
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
init_logging("BSCREENSAVER_LOG");
|
||||
|
||||
let config = Configuration::load()?;
|
||||
|
||||
let args = ClapCommand::new("Blanks and locks the screen after a period of time")
|
||||
.author(env!("CARGO_PKG_AUTHORS"))
|
||||
.version(env!("CARGO_PKG_VERSION"))
|
||||
.arg(
|
||||
Arg::new("blanked")
|
||||
.long(BLANKED_ARG)
|
||||
.help("Starts up in the blanked screensaver")
|
||||
)
|
||||
.arg(
|
||||
Arg::new("locked")
|
||||
.long(LOCKED_ARG)
|
||||
.help("Starts up in the blanked and locked screensaver")
|
||||
)
|
||||
.get_matches();
|
||||
let args = Args::parse();
|
||||
|
||||
let mut signal_fd = init_signals()?;
|
||||
|
||||
@ -91,12 +83,12 @@ fn main() -> anyhow::Result<()> {
|
||||
};
|
||||
let mut screensaver = Screensaver::new(&config, &helper_dir, &command_handlers, &conn, screen)?;
|
||||
|
||||
if args.is_present(LOCKED_ARG) {
|
||||
if args.locked {
|
||||
match screensaver.lock_screen() {
|
||||
Err(err) => error!("POSSIBLY FAILED TO LOCK SCREEN ON STARTUP: {}", err),
|
||||
Ok(_) => debug!("Got --{} arg; screen locked on startup", LOCKED_ARG),
|
||||
}
|
||||
} else if args.is_present(BLANKED_ARG) {
|
||||
} else if args.blanked {
|
||||
match screensaver.blank_screen() {
|
||||
Err(err) => warn!("Possibly failed to blank screen on startup: {}", err),
|
||||
Ok(_) => debug!("Got --{} arg; screen locked on startup", BLANKED_ARG),
|
||||
@ -120,9 +112,16 @@ fn main() -> anyhow::Result<()> {
|
||||
warn!("Error handling event: {}", err);
|
||||
}
|
||||
|
||||
let conn_fd = conn.as_raw_fd();
|
||||
if conn_fd < 0 {
|
||||
error!("Lost connection to X server; attempting to restart");
|
||||
(command_handlers.restart_handler)(&mut screensaver, None)?;
|
||||
}
|
||||
let conn_fd = borrow_raw_fd(conn_fd);
|
||||
|
||||
let mut pfds = Vec::new();
|
||||
pfds.push(PollFd::new(signal_fd.as_raw_fd(), PollFlags::POLLIN));
|
||||
pfds.push(PollFd::new(conn.as_raw_fd(), PollFlags::POLLIN));
|
||||
pfds.push(PollFd::new(borrow_raw_fd(signal_fd.as_raw_fd()), PollFlags::POLLIN));
|
||||
pfds.push(PollFd::new(conn_fd.as_fd(), PollFlags::POLLIN));
|
||||
let dbus_service_fd = maybe_add_fd!(&mut pfds, subservices.lock().unwrap().dbus_service().map(|ds| ds.pidfd().as_raw_fd()));
|
||||
let systemd_service_fd = maybe_add_fd!(&mut pfds, subservices.lock().unwrap().systemd_service().map(|ds| ds.pidfd().as_raw_fd()));
|
||||
let dialog_fd = maybe_add_fd!(&mut pfds, screensaver.unlock_dialog_pidfd().map(|udpfd| udpfd.as_raw_fd()));
|
||||
@ -135,21 +134,19 @@ fn main() -> anyhow::Result<()> {
|
||||
BlankerState::Blanked => Some(config.lock_timeout - since_last_activity),
|
||||
BlankerState::Locked => None,
|
||||
};
|
||||
let poll_timeout = poll_timeout.map(|pt| if pt.as_millis() > i32::MAX as u128 {
|
||||
i32::MAX
|
||||
} else {
|
||||
pt.as_millis() as i32
|
||||
}).unwrap_or(-1);
|
||||
let poll_timeout = poll_timeout
|
||||
.map(|pt| PollTimeout::try_from(pt).unwrap_or(PollTimeout::MAX))
|
||||
.unwrap_or(PollTimeout::NONE);
|
||||
|
||||
trace!("about to poll (timeout={})", poll_timeout);
|
||||
trace!("about to poll (timeout={})", poll_timeout.as_millis().map(|pt| pt.to_string()).unwrap_or("(?)".into()));
|
||||
let nready = poll(pfds.as_mut_slice(), poll_timeout)?; // FIXME: maybe shouldn't quit here on errors if screen is locked
|
||||
trace!("polled; {} FD ready", nready);
|
||||
if nready > 0 {
|
||||
for pfd in pfds {
|
||||
if pfd.revents().filter(|pf| pf.contains(PollFlags::POLLIN)).is_some() {
|
||||
let result = match pfd.as_raw_fd() {
|
||||
let result = match pfd.as_fd().as_raw_fd() {
|
||||
fd if fd == signal_fd.as_raw_fd() => handle_signals(&mut screensaver, &mut subservices.lock().unwrap(), &mut signal_fd),
|
||||
fd if fd == conn.as_raw_fd() => screensaver.handle_xcb_events(),
|
||||
fd if fd == conn_fd.as_raw_fd() => screensaver.handle_xcb_events(),
|
||||
fd if opt_contains(&dbus_service_fd, &fd) => subservices.lock().unwrap().handle_quit(),
|
||||
fd if opt_contains(&systemd_service_fd, &fd) => subservices.lock().unwrap().handle_quit(),
|
||||
fd if opt_contains(&dialog_fd, &fd) => screensaver.handle_unlock_dialog_quit(),
|
||||
|
@ -547,7 +547,7 @@ fn find_backlight_control(conn: &xcb::Connection, output: randr::Output) -> anyh
|
||||
if let Ok(reply) = conn.wait_for_reply(cookie) {
|
||||
let values = reply.valid_values();
|
||||
if reply.range() && values.len() == 2 {
|
||||
let min_level = values[0];
|
||||
let min_level = values[0] + 1;
|
||||
let max_level = values[1];
|
||||
let range = max_level - min_level;
|
||||
if range > 0 {
|
||||
@ -577,7 +577,7 @@ fn find_backlight_control(conn: &xcb::Connection, output: randr::Output) -> anyh
|
||||
debug!("Found sysfs backlight control at {:?}", cur_path);
|
||||
return Ok(Some(BacklightControl {
|
||||
location: BacklightLocation::Sysfs(cur_path),
|
||||
min_level: 0,
|
||||
min_level: 1,
|
||||
max_level,
|
||||
step: calc_step(0, max_level),
|
||||
}));
|
||||
|
@ -12,7 +12,7 @@ fn pidfd_open(pid: RawFd) -> nix::Result<PidFd> {
|
||||
} else {
|
||||
// SAFETY: pointer is checked for null; libc must be sane
|
||||
let errno = unsafe { *errno_location };
|
||||
Err(nix::errno::Errno::from_i32(errno))
|
||||
Err(nix::errno::Errno::from_raw(errno))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,6 @@ edition = "2021"
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
bscreensaver-util = { path = "../util" }
|
||||
glib = "0.15"
|
||||
gtk = { version = "0.15", features = ["v3_20"] }
|
||||
glib = "0.18"
|
||||
gtk = "0.18"
|
||||
log = "0.4"
|
||||
|
@ -1,5 +1,5 @@
|
||||
use gtk::{glib, prelude::*};
|
||||
use glib::clone;
|
||||
use glib::{clone, Propagation::{Proceed, Stop}};
|
||||
use log::warn;
|
||||
use std::{env, process::exit, time::Duration, ffi::CString};
|
||||
|
||||
@ -31,7 +31,7 @@ fn main() -> anyhow::Result<()> {
|
||||
.build();
|
||||
app.connect_activate(move |app| show_ui(&app, &config));
|
||||
|
||||
exit(app.run_with_args(&env::args().into_iter().collect::<Vec<String>>()));
|
||||
exit(app.run_with_args(&env::args().into_iter().collect::<Vec<String>>()).into());
|
||||
}
|
||||
|
||||
fn show_ui(app: >k::Application, config: &Configuration) {
|
||||
@ -226,7 +226,11 @@ fn show_ui(app: >k::Application, config: &Configuration) {
|
||||
handle_brightness_keys_checkbox: handle_brightness_keys_checkbox.clone(),
|
||||
};
|
||||
mainwin.connect_delete_event(clone!(@strong config, @strong widgets, @strong app, @strong mainwin => move |_,_| {
|
||||
Inhibit(!confirm_cancel(&config, &widgets, &mainwin))
|
||||
if !confirm_cancel(&config, &widgets, &mainwin) {
|
||||
Stop
|
||||
} else {
|
||||
Proceed
|
||||
}
|
||||
}));
|
||||
custom_new_login_command_button.connect_clicked(clone!(@strong mainwin, @strong widgets => move |_| {
|
||||
run_file_chooser(&mainwin, &widgets);
|
||||
|
@ -5,13 +5,13 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
async-std = { version = "1.11", features = ["attributes"] }
|
||||
async-std = { version = "1.12", features = ["attributes"] }
|
||||
async-xcb = { path = "../async-xcb" }
|
||||
bscreensaver-command = { path = "../command" }
|
||||
bscreensaver-util = { path = "../util" }
|
||||
futures = "0.3"
|
||||
log = "0.4"
|
||||
nix = "0.23"
|
||||
nix = "0.29"
|
||||
xcb = "1"
|
||||
zbus = "3"
|
||||
logind-zbus = "3"
|
||||
zbus = "4"
|
||||
logind-zbus = "^4.0.1"
|
||||
|
@ -92,8 +92,5 @@ async fn do_bscreensaver_command(command: BCommand) -> anyhow::Result<()> {
|
||||
|
||||
async fn register_sleep_lock<'a>(manager_proxy: &ManagerProxy<'a>) -> anyhow::Result<zbus::zvariant::OwnedFd> {
|
||||
debug!("Registering sleep lock");
|
||||
// ManagerProxy uses RawFd for the return value, which rust's type system thinks is an i32,
|
||||
// which means the generated proxy uses the wrong dbus type signature. So instead, use a raw
|
||||
// Proxy instance and do it all ourselves.
|
||||
Ok((*manager_proxy).call("Inhibit", &(InhibitType::Sleep, "bscreensaver", "blank before sleep", "delay")).await?)
|
||||
Ok(manager_proxy.inhibit(InhibitType::Sleep, "bscreensaver", "blank before sleep", "delay").await?)
|
||||
}
|
||||
|
@ -7,13 +7,13 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
clap = "3"
|
||||
env_logger = "0.9"
|
||||
clap = "4"
|
||||
env_logger = "0.11"
|
||||
humantime = "2"
|
||||
lazy_static = "1"
|
||||
libc = "0.2"
|
||||
shell-words = "1"
|
||||
toml = "0.5"
|
||||
toml = "0.8"
|
||||
xcb = "1"
|
||||
xdg = "2"
|
||||
zbus = "3"
|
||||
zbus = "4"
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::{ffi::CStr, io};
|
||||
use std::{ffi::CStr, io, os::fd::{BorrowedFd, RawFd}};
|
||||
use xcb::x;
|
||||
|
||||
pub mod desktop;
|
||||
@ -77,3 +77,10 @@ pub fn get_username() -> io::Result<String> {
|
||||
.map(|s| s.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn borrow_raw_fd<'a>(fd: RawFd) -> BorrowedFd<'a> {
|
||||
if fd < 0 {
|
||||
panic!("Can't borrow invalid file descriptor");
|
||||
}
|
||||
unsafe { BorrowedFd::borrow_raw(fd) }
|
||||
}
|
||||
|
@ -13,6 +13,6 @@ keywords = ["gui", "x11", "xcb", "xembed"]
|
||||
categories = ["gui"]
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1"
|
||||
bitflags = "2"
|
||||
log = "0.4"
|
||||
xcb = { version = "1", features = ["xfixes"] }
|
||||
|
@ -130,7 +130,7 @@ impl<'a> Embedder<'a> {
|
||||
match event {
|
||||
x::Event::PropertyNotify(ev) if ev.window() == self.client && ev.atom() == intern_atom(self.conn, XEMBED_INFO_ATOM_NAME)? => {
|
||||
let info = fetch_xembed_info(self.conn, self.client)?;
|
||||
if (self.flags & XEmbedFlags::MAPPED) != (info.flags & XEmbedFlags::MAPPED) {
|
||||
if self.flags.contains(XEmbedFlags::MAPPED) != info.flags.contains(XEmbedFlags::MAPPED) {
|
||||
if info.flags.contains(XEmbedFlags::MAPPED) {
|
||||
debug!("Mapping client window");
|
||||
self.conn.send_and_check_request(&x::MapWindow {
|
||||
|
Loading…
Reference in New Issue
Block a user