diff --git a/src/backend/common.rs b/src/backend/common.rs index 1151390..abd09ee 100644 --- a/src/backend/common.rs +++ b/src/backend/common.rs @@ -50,12 +50,14 @@ where overlays.insert(watch.state.id, watch); let mut keyboard = create_keyboard(&app); + keyboard.state.show_hide = true; keyboard.state.want_visible = true; overlays.insert(keyboard.state.id, keyboard); let mut first = true; for mut screen in screens { if first { + screen.state.show_hide = true; screen.state.want_visible = true; first = false; } @@ -94,6 +96,19 @@ where pub fn iter_mut<'a>(&'a mut self) -> impl Iterator> { self.overlays.values_mut() } + + pub fn show_hide(&mut self) { + let any_shown = self + .overlays + .values() + .any(|o| o.state.show_hide && o.state.want_visible); + + self.overlays.values_mut().for_each(|o| { + if o.state.show_hide { + o.state.want_visible = !any_shown; + } + }) + } } pub enum OverlaySelector { diff --git a/src/backend/openvr/mod.rs b/src/backend/openvr/mod.rs index 6e6b5c1..88dd75a 100644 --- a/src/backend/openvr/mod.rs +++ b/src/backend/openvr/mod.rs @@ -147,6 +147,15 @@ pub fn openvr_run(running: Arc) -> Result<(), BackendError> { input_source.update(&mut input_mngr, &mut system_mngr, &mut state); state.input_state.post_update(); + if state + .input_state + .pointers + .iter() + .any(|p| p.now.show_hide && !p.before.show_hide) + { + overlays.show_hide(); + } + overlays .iter_mut() .for_each(|o| o.state.auto_movement(&mut state)); diff --git a/src/backend/openxr/input.rs b/src/backend/openxr/input.rs index 543e560..e5bdc40 100644 --- a/src/backend/openxr/input.rs +++ b/src/backend/openxr/input.rs @@ -1,3 +1,5 @@ +use std::time::{Duration, Instant}; + use glam::{bool, Affine3A, Quat, Vec3}; use openxr as xr; @@ -6,6 +8,28 @@ use crate::{backend::input::Pointer, state::AppState}; use super::XrState; type XrSession = xr::Session; +static DOUBLE_CLICK_TIME: Duration = Duration::from_millis(500); + +pub(super) struct DoubleClickCounter { + pub(super) last_click: Option, +} + +impl DoubleClickCounter { + pub(super) fn new() -> Self { + Self { last_click: None } + } + + // submit a click. returns true if it should count as a double click + pub(super) fn click(&mut self) -> bool { + let now = Instant::now(); + let double_click = match self.last_click { + Some(last_click) => now - last_click < DOUBLE_CLICK_TIME, + None => false, + }; + self.last_click = if double_click { None } else { Some(now) }; + double_click + } +} pub(super) struct OpenXrInputSource { action_set: xr::ActionSet, diff --git a/src/backend/openxr/mod.rs b/src/backend/openxr/mod.rs index 0bbcd6f..58c43e1 100644 --- a/src/backend/openxr/mod.rs +++ b/src/backend/openxr/mod.rs @@ -16,7 +16,7 @@ use crate::{ backend::{ common::OverlayContainer, input::interact, - openxr::{lines::LinePool, overlay::OpenXrOverlayData}, + openxr::{input::DoubleClickCounter, lines::LinePool, overlay::OpenXrOverlayData}, }, graphics::WlxGraphics, state::AppState, @@ -114,6 +114,8 @@ pub fn openxr_run(running: Arc) -> Result<(), BackendError> { let mut session_running = false; let mut event_storage = xr::EventDataBuffer::new(); + let mut show_hide_counter = DoubleClickCounter::new(); + 'main_loop: loop { if !running.load(Ordering::Relaxed) { log::warn!("Received shutdown signal."); @@ -184,6 +186,17 @@ pub fn openxr_run(running: Arc) -> Result<(), BackendError> { input_source.update(&xr_state, &mut app_state); app_state.input_state.post_update(); + if app_state + .input_state + .pointers + .iter() + .any(|p| p.now.show_hide && !p.before.show_hide) + { + if show_hide_counter.click() { + overlays.show_hide(); + } + } + let (_, views) = xr_state .session .locate_views( diff --git a/src/overlays/keyboard.rs b/src/overlays/keyboard.rs index 3e903ff..529aaae 100644 --- a/src/overlays/keyboard.rs +++ b/src/overlays/keyboard.rs @@ -114,7 +114,6 @@ where OverlayData { state: OverlayState { name: Arc::from("kbd"), - show_hide: true, size: (size.x as _, size.y as _), grabbable: true, spawn_scale: width, diff --git a/src/overlays/screen.rs b/src/overlays/screen.rs index 26fff3d..b067a94 100644 --- a/src/overlays/screen.rs +++ b/src/overlays/screen.rs @@ -334,7 +334,6 @@ where name: output.name.clone(), size, want_visible: session.show_screens.iter().any(|s| s == &*output.name), - show_hide: true, grabbable: true, spawn_scale: 1.5 * session.config.desktop_view_scale, spawn_point: vec3a(0., 0.5, -1.), diff --git a/src/overlays/watch.rs b/src/overlays/watch.rs index 83756f5..34f5c54 100644 --- a/src/overlays/watch.rs +++ b/src/overlays/watch.rs @@ -98,7 +98,8 @@ where app.tasks.enqueue(TaskType::Overlay( OverlaySelector::Name("kbd".into()), Box::new(|_app, o| { - o.want_visible = !o.want_visible; + o.show_hide = !o.show_hide; + o.want_visible = o.show_hide; }), )); } else { @@ -144,7 +145,8 @@ where app.tasks.enqueue(TaskType::Overlay( OverlaySelector::Id(scr_idx), Box::new(|_app, o| { - o.want_visible = !o.want_visible; + o.show_hide = !o.show_hide; + o.want_visible = o.show_hide; }), )); } else {