diff --git a/src/catacomb.rs b/src/catacomb.rs index e81910b..673a345 100644 --- a/src/catacomb.rs +++ b/src/catacomb.rs @@ -115,10 +115,10 @@ pub struct Catacomb { pub touch_state: TouchState, pub frame_pacer: FramePacer, pub seat_name: String, + pub display_on: bool, pub windows: Windows, pub seat: Seat, pub terminated: bool, - pub sleeping: bool, pub backend: Udev, // Smithay state. @@ -317,13 +317,13 @@ impl Catacomb { backend, seat, accelerometer_token: accel_token, + display_on: true, idle_inhibitors: Default::default(), key_bindings: Default::default(), ime_override: Default::default(), frame_pacer: Default::default(), last_focus: Default::default(), terminated: Default::default(), - sleeping: Default::default(), stalled: Default::default(), locker: Default::default(), } @@ -341,7 +341,7 @@ impl Catacomb { #[cfg_attr(feature = "profiling", profiling::function)] pub fn create_frame(&mut self) { // Skip rendering while the screen is off. - if self.sleeping { + if !self.display_on { self.stalled = true; return; } @@ -442,11 +442,11 @@ impl Catacomb { } /// Set output power mode. - pub fn set_sleep(&mut self, sleep: bool) { - self.sleeping = sleep; + pub fn set_display_status(&mut self, on: bool) { + self.display_on = on; - // Pause accelerometer checks during sleep. - if sleep { + // Pause accelerometer checks while display is off. + if on { trace_error!(self.event_loop.disable(&self.accelerometer_token)); } else if !self.windows.orientation_locked() { trace_error!(self.event_loop.enable(&self.accelerometer_token)); @@ -456,7 +456,7 @@ impl Catacomb { self.idle_notifier_state.notify_activity(&self.seat); } - self.backend.set_sleep(sleep); + self.backend.set_display_status(on); } /// Lock the output's orientation. diff --git a/src/input.rs b/src/input.rs index 9f84513..9acff12 100644 --- a/src/input.rs +++ b/src/input.rs @@ -29,6 +29,9 @@ pub const HOLD_DURATION: Duration = Duration::from_secs(1); /// Maximum time between taps to be considered a double-tap. const MAX_DOUBLE_TAP_DURATION: Duration = Duration::from_millis(300); +/// Square of the maximum distance between taps to be considered a double-tap. +const MAX_DOUBLE_TAP_DISTANCE: f64 = 400.; + /// Square of the maximum distance before touch input is considered a drag. const MAX_TAP_DISTANCE: f64 = 400.; @@ -47,6 +50,7 @@ pub struct TouchState { pub user_gestures: Vec, pub position: Point, + last_tap: Option<(Instant, Point)>, pending_single_tap: Option, event_loop: LoopHandle<'static, Catacomb>, velocity_timer: Option, @@ -57,7 +61,6 @@ pub struct TouchState { events: Vec, slot: Option, start: TouchStart, - last_tap: Instant, is_drag: bool, } @@ -65,13 +68,13 @@ impl TouchState { pub fn new(event_loop: LoopHandle<'static, Catacomb>) -> Self { Self { event_loop, - last_tap: Instant::now(), pending_single_tap: Default::default(), velocity_timer: Default::default(), input_surface: Default::default(), user_gestures: Default::default(), active_app_id: Default::default(), tap_surface: Default::default(), + last_tap: Default::default(), position: Default::default(), velocity: Default::default(), is_drag: Default::default(), @@ -162,11 +165,22 @@ impl TouchState { return Some(TouchAction::Drag); } - if self.last_tap.elapsed() <= MAX_DOUBLE_TAP_DURATION { - (!touching).then_some(TouchAction::DoubleTap) - } else { - (!touching).then_some(TouchAction::Tap) + // Only report taps after release. + if touching { + return None; + } + + // Report double-taps. + if let Some(last_tap) = self.last_tap.take() { + let last_tap_delta = last_tap.1 - self.position; + if last_tap.0.elapsed() <= MAX_DOUBLE_TAP_DURATION + && last_tap_delta.x.powi(2) + last_tap_delta.y.powi(2) <= MAX_DOUBLE_TAP_DISTANCE + { + return Some(TouchAction::DoubleTap); + } } + + Some(TouchAction::Tap) } /// Find gestures matching an origin point. @@ -327,7 +341,7 @@ impl Catacomb { /// Process new input events. pub fn handle_input(&mut self, event: InputEvent) { // Ignore non-keyboard input events while the screen is off. - if self.sleeping && !matches!(event, InputEvent::Keyboard { .. }) { + if !self.display_on && !matches!(event, InputEvent::Keyboard { .. }) { return; } @@ -480,7 +494,7 @@ impl Catacomb { let pending_single_tap = self.event_loop.insert_source(timer, Self::on_single_tap).unwrap(); self.touch_state.pending_single_tap = Some(pending_single_tap); - self.touch_state.last_tap = Instant::now(); + self.touch_state.last_tap = Some((Instant::now(), self.touch_state.position)); }, Some(TouchAction::DoubleTap) => { // Cancel single-tap. diff --git a/src/ipc_server.rs b/src/ipc_server.rs index cf6e7db..3cd829c 100644 --- a/src/ipc_server.rs +++ b/src/ipc_server.rs @@ -148,9 +148,11 @@ fn handle_message(buffer: &mut String, mut stream: UnixStream, catacomb: &mut Ca binding.app_id.base() != app_id || binding.key != key || binding.mods != mods }); }, - IpcMessage::Dpms { state: Some(state) } => catacomb.set_sleep(state == DpmsState::Off), + IpcMessage::Dpms { state: Some(state) } => { + catacomb.set_display_status(state == DpmsState::On) + }, IpcMessage::Dpms { state: None } => { - let state = if catacomb.sleeping { DpmsState::Off } else { DpmsState::On }; + let state = if catacomb.display_on { DpmsState::On } else { DpmsState::Off }; send_reply(&mut stream, &IpcMessage::DpmsReply { state }); }, // Ignore IPC replies. diff --git a/src/udev.rs b/src/udev.rs index 5e6b9f5..0daffdd 100644 --- a/src/udev.rs +++ b/src/udev.rs @@ -222,17 +222,17 @@ impl Udev { trace_error!(self.session.change_vt(vt)); } - /// Set power saving state. - pub fn set_sleep(&mut self, sleep: bool) { + /// Set output power saving state. + pub fn set_display_status(&mut self, on: bool) { let output_device = match &mut self.output_device { Some(output_device) => output_device, None => return, }; - output_device.set_enabled(!sleep); + output_device.set_enabled(on); // Request immediate redraw, so vblanks start coming in again. - if !sleep { + if on { self.schedule_redraw(Duration::ZERO); } }