Have remote commands return a success/failure message

This commit is contained in:
2022-05-14 14:55:22 -07:00
parent aafe026092
commit 8394d45d1a
8 changed files with 181 additions and 34 deletions

View File

@ -22,10 +22,10 @@ use std::{
process::{exit, Child, Command, Stdio},
time::{Duration, Instant},
};
use xcb::{randr, x, xfixes, xinput, Xid};
use xcb::{randr, x, xfixes, xinput, Xid, XidNew};
use xcb_xembed::embedder::Embedder;
use bscreensaver_command::{BCommand, create_command_window};
use bscreensaver_command::{BCommand, create_command_window, bscreensaver_command_response};
use bscreensaver_util::{*, settings::Configuration};
use pidfd::{CreatePidFd, PidFd};
@ -543,22 +543,60 @@ fn handle_xcb_events<'a>(conn: &'a xcb::Connection, state: &mut State<'a>, comma
// TODO: implement some sort of hysteresis/debouncing for mouse motion
state.last_user_activity = Instant::now();
},
xcb::Event::X(x::Event::ClientMessage(ev)) => match ev.r#type() {
b if b == command_atoms.blank => blank_screen(conn, state)?,
l if l == command_atoms.lock => lock_screen(conn, state)?,
d if d == command_atoms.deactivate => {
state.last_user_activity = Instant::now();
match state.blanker_state {
BlankerState::Idle => (),
BlankerState::Blanked => unblank_screen(conn, state)?,
BlankerState::Locked => if state.unlock_dialog.is_none() {
state.unlock_dialog = Some(start_unlock_dialog(conn, state, None)?);
xcb::Event::X(x::Event::ClientMessage(ev)) => {
let res = match ev.r#type() {
b if b == command_atoms.blank => Some(blank_screen(conn, state)),
l if l == command_atoms.lock => Some(lock_screen(conn, state)),
d if d == command_atoms.deactivate => {
state.last_user_activity = Instant::now();
match state.blanker_state {
BlankerState::Idle => Some(Ok(())),
BlankerState::Blanked => Some(unblank_screen(conn, state)),
BlankerState::Locked => {
if state.unlock_dialog.is_none() {
match start_unlock_dialog(conn, state, None) {
Ok(unlock_dialog) => {
state.unlock_dialog = Some(unlock_dialog);
Some(Ok(()))
},
Err(err) => Some(Err(err)),
}
} else {
Some(Ok(()))
}
},
}
},
r if r == command_atoms.restart => Some(restart_daemon(state)),
e if e == command_atoms.exit => Some(exit_daemon(state)),
_ => None,
};
if let Some(res) = res {
let is_success = if let Err(err) = res {
warn!("Failed to handle remote command {}: {}", ev.r#type().resource_id(), err);
false
} else {
true
};
let reply_window = match ev.data() {
x::ClientMessageData::Data32(data) => {
match unsafe { x::Window::new(data[0]) } {
x::WINDOW_NONE => None,
wid => Some(wid),
}
},
_ => None,
};
if let Some(reply_window) = reply_window {
if let Err(err) = bscreensaver_command_response(conn, reply_window, is_success) {
info!("Failed to send command response: {}", err);
}
} else {
debug!("Command sender did not include a reply window");
}
},
r if r == command_atoms.restart => restart_daemon(state)?,
e if e == command_atoms.exit => exit_daemon(state)?,
_ => (),
}
},
xcb::Event::X(x::Event::MapNotify(ev)) if ev.window() == unlock_dialog_window(&state) => {
debug!("Unlock dialog mapped, requesting focus");
@ -710,10 +748,7 @@ fn start_unlock_dialog<'a>(conn: &'a xcb::Connection, state: &State<'a>, trigger
child_out.read_exact(&mut xid_buf)?;
let client_window = {
let wid: u32 = ((xid_buf[0] as u32) << 24) | ((xid_buf[1] as u32) << 16) | ((xid_buf[2] as u32) << 8) | (xid_buf[3] as u32);
unsafe {
use xcb::XidNew;
x::Window::new(wid)
}
unsafe { x::Window::new(wid) }
};
debug!("Dialog process created plug window 0x{:x}", client_window.resource_id());