Be more aggressive about handling user activity

Previously we only trigger unblanking or showing the unlock dialog if
core key or motion events come through.  Now we also do this when xinput
events come in.  We also now reset the last-user-activity time for core
events.

This also changes xcb-xembed to explicitly only handle core events.
This commit is contained in:
2022-06-08 00:30:11 -07:00
parent b0c2ffc74a
commit d3de9f7fad
2 changed files with 44 additions and 36 deletions

View File

@ -26,7 +26,7 @@ struct UnlockDialog<'a> {
monitor_geom: x::Rectangle,
blanker_window: x::Window,
embedder: Embedder<'a>,
event_to_forward: Option<xcb::Event>,
event_to_forward: Option<x::Event>,
child: Child,
child_pidfd: PidFd,
}
@ -109,16 +109,21 @@ impl<'a> Screensaver<'a> {
loop {
if let Some(event) = self.conn.poll_for_event()? {
let embedder_handled = if let Some(mut unlock_dialog) = self.unlock_dialog.take() {
match unlock_dialog.embedder.event(&event) {
Err(err) => {
// XXX: should we assume unlock dialog is dead here?
warn!("Error sending event to unlock dialog: {}", err);
false
},
Ok(handled) => {
self.unlock_dialog = Some(unlock_dialog);
handled
},
if let xcb::Event::X(xev) = &event {
match unlock_dialog.embedder.event(xev) {
Err(err) => {
// XXX: should we assume unlock dialog is dead here?
warn!("Error sending event to unlock dialog: {}", err);
false
},
Ok(handled) => {
self.unlock_dialog = Some(unlock_dialog);
handled
},
}
} else {
self.unlock_dialog = Some(unlock_dialog);
false
}
} else {
false
@ -148,10 +153,7 @@ impl<'a> Screensaver<'a> {
},
}
},
xcb::Event::Input(_) => {
// TODO: implement some sort of hysteresis/debouncing for mouse motion
self.last_user_activity = Instant::now();
},
ev @ xcb::Event::Input(_) => self.handle_user_activity(ev)?,
xcb::Event::X(x::Event::ClientMessage(ev)) => {
let res = match ev.r#type() {
b if b == self.command_atoms.blank => Some(self.blank_screen()),
@ -259,18 +261,24 @@ impl<'a> Screensaver<'a> {
}
fn handle_user_activity(&mut self, ev: xcb::Event) -> anyhow::Result<()> {
// TODO: implement some sort of hysteresis/debouncing for mouse motion
self.last_user_activity = Instant::now();
match self.blanker_state {
BlankerState::Idle => Ok(()),
BlankerState::Blanked => self.unblank_screen(),
BlankerState::Locked => match &self.unlock_dialog {
None => {
self.unlock_dialog = match self.start_unlock_dialog(Some(ev)) {
Err(err) => {
error!("Unable to start unlock dialog: {}", err);
None
match ev {
xcb::Event::X(xev) => self.unlock_dialog = match self.start_unlock_dialog(Some(xev)) {
Err(err) => {
error!("Unable to start unlock dialog: {}", err);
None
},
Ok(unlock_dialog) => Some(unlock_dialog),
},
Ok(unlock_dialog) => Some(unlock_dialog),
};
_ => (),
}
Ok(())
},
Some(unlock_dialog) => {
@ -331,7 +339,7 @@ impl<'a> Screensaver<'a> {
Ok(())
}
fn start_unlock_dialog(&self, trigger_event: Option<xcb::Event>) -> anyhow::Result<UnlockDialog<'a>> {
fn start_unlock_dialog(&self, trigger_event: Option<x::Event>) -> anyhow::Result<UnlockDialog<'a>> {
let mut monitor_data = None;
for monitor in &self.monitors {
let cookie = self.conn.send_request(&x::QueryPointer {
@ -359,15 +367,15 @@ impl<'a> Screensaver<'a> {
}
let trigger_event = match trigger_event {
Some(xcb::Event::X(x::Event::KeyPress(ev))) => match keysym_for_keypress(self.conn, &ev) {
Some(x::Event::KeyPress(ev)) => match keysym_for_keypress(self.conn, &ev) {
Err(err) => {
warn!("Failed to get keysym for key press event: {}", err);
Some(xcb::Event::X(x::Event::KeyPress(ev)))
Some(x::Event::KeyPress(ev))
},
Ok(Some(keysym)) if keysym == xkb::key::KP_Enter || keysym == xkb::key::ISO_Enter || keysym == xkb::key::Return || keysym == xkb::key::Escape =>
// don't forward an <enter> or <esc> to the dialog, as that will make it activate/close immediately
None,
_ => Some(xcb::Event::X(x::Event::KeyPress(ev))),
_ => Some(x::Event::KeyPress(ev)),
},
te => te,
};