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:
@ -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,
|
||||
};
|
||||
|
Reference in New Issue
Block a user