diff --git a/locker/src/screensaver.rs b/locker/src/screensaver.rs index 3250b76..7213aaa 100644 --- a/locker/src/screensaver.rs +++ b/locker/src/screensaver.rs @@ -26,7 +26,7 @@ struct UnlockDialog<'a> { monitor_geom: x::Rectangle, blanker_window: x::Window, embedder: Embedder<'a>, - event_to_forward: Option, + event_to_forward: Option, 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) -> anyhow::Result> { + fn start_unlock_dialog(&self, trigger_event: Option) -> anyhow::Result> { 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 or 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, }; diff --git a/xcb-xembed/src/embedder.rs b/xcb-xembed/src/embedder.rs index 1114cca..9ded397 100644 --- a/xcb-xembed/src/embedder.rs +++ b/xcb-xembed/src/embedder.rs @@ -122,13 +122,13 @@ impl<'a> Embedder<'a> { Ok(()) } - pub fn event(&mut self, event: &xcb::Event) -> Result { + pub fn event(&mut self, event: &x::Event) -> Result { if self.client == x::WINDOW_NONE { return Err(Error::ClientDestroyed); } match event { - xcb::Event::X(x::Event::PropertyNotify(ev)) if ev.window() == self.client && ev.atom() == intern_atom(self.conn, XEMBED_INFO_ATOM_NAME)? => { + 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 info.flags.contains(XEmbedFlags::MAPPED) { @@ -146,7 +146,7 @@ impl<'a> Embedder<'a> { } Ok(true) }, - xcb::Event::X(x::Event::ConfigureNotify(ev)) if ev.window() == self.client => { + x::Event::ConfigureNotify(ev) if ev.window() == self.client => { let mut cookies = Vec::new(); if ev.x() != 0 || ev.y() != 0 { cookies.push(self.conn.send_request_checked(&x::ConfigureWindow { @@ -169,7 +169,7 @@ impl<'a> Embedder<'a> { } Ok(true) }, - xcb::Event::X(x::Event::ClientMessage(ev)) if ev.window() == self.embedder && ev.r#type() == intern_atom(self.conn, XEMBED_MESSAGE_ATOM_NAME)? => { + x::Event::ClientMessage(ev) if ev.window() == self.embedder && ev.r#type() == intern_atom(self.conn, XEMBED_MESSAGE_ATOM_NAME)? => { match ev.data() { x::ClientMessageData::Data32(data) if data[1] == XEmbedMessage::RequestFocus as u32 => { debug!("Client requests focus"); @@ -188,7 +188,7 @@ impl<'a> Embedder<'a> { _ => Ok(false), } }, - xcb::Event::X(x::Event::KeyPress(ev)) if ev.event() == self.embedder && self.flags.contains(XEmbedFlags::MAPPED) => { + x::Event::KeyPress(ev) if ev.event() == self.embedder && self.flags.contains(XEmbedFlags::MAPPED) => { trace!("Forwarding key press to client ({:?} + {})", ev.state(), ev.detail()); self.conn.send_and_check_request(&x::SendEvent { propagate: false, @@ -199,7 +199,7 @@ impl<'a> Embedder<'a> { Ok(true) }, /* - xcb::Event::X(x::Event::KeyRelease(ev)) if ev.event() == self.embedder && self.flags.contains(XEmbedFlags::MAPPED) => { + x::Event::KeyRelease(ev) if ev.event() == self.embedder && self.flags.contains(XEmbedFlags::MAPPED) => { trace!("Forwarding key release to client ({:?} + {})", ev.state(), ev.detail()); self.conn.send_and_check_request(&x::SendEvent { propagate: false, @@ -210,7 +210,7 @@ impl<'a> Embedder<'a> { Ok(true) }, */ - xcb::Event::X(x::Event::MotionNotify(ev)) if ev.event() == self.embedder && self.flags.contains(XEmbedFlags::MAPPED) => { + x::Event::MotionNotify(ev) if ev.event() == self.embedder && self.flags.contains(XEmbedFlags::MAPPED) => { trace!("Forwarding pointer motion to client ({}, {})", ev.event_x(), ev.event_y()); self.conn.send_and_check_request(&x::SendEvent { propagate: false, @@ -220,7 +220,7 @@ impl<'a> Embedder<'a> { })?; Ok(true) }, - xcb::Event::X(x::Event::ButtonPress(ev)) if ev.event() == self.embedder && self.flags.contains(XEmbedFlags::MAPPED) => { + x::Event::ButtonPress(ev) if ev.event() == self.embedder && self.flags.contains(XEmbedFlags::MAPPED) => { trace!("Forwarding button press to client ({:?} + {}: {}, {})", ev.state(), ev.detail(), ev.event_x(), ev.event_y()); self.conn.send_and_check_request(&x::SendEvent { propagate: false, @@ -230,7 +230,7 @@ impl<'a> Embedder<'a> { })?; Ok(true) }, - xcb::Event::X(x::Event::ButtonRelease(ev)) if ev.event() == self.embedder && self.flags.contains(XEmbedFlags::MAPPED) => { + x::Event::ButtonRelease(ev) if ev.event() == self.embedder && self.flags.contains(XEmbedFlags::MAPPED) => { trace!("Forwarding button release to client ({:?} + {}: {}, {})", ev.state(), ev.detail(), ev.event_x(), ev.event_y()); self.conn.send_and_check_request(&x::SendEvent { propagate: false, @@ -240,12 +240,12 @@ impl<'a> Embedder<'a> { })?; Ok(true) }, - xcb::Event::X(x::Event::UnmapNotify(ev)) if ev.window() == self.client => { + x::Event::UnmapNotify(ev) if ev.window() == self.client => { debug!("Client was unmapped"); self.flags -= XEmbedFlags::MAPPED; Ok(true) }, - xcb::Event::X(x::Event::DestroyNotify(ev)) if ev.window() == self.client => { + x::Event::DestroyNotify(ev) if ev.window() == self.client => { debug!("Client was destroyed"); self.flags -= XEmbedFlags::MAPPED; self.client = x::WINDOW_NONE;