add basic input blocking through libmonado (#190)
This commit is contained in:
73
src/backend/openxr/blocker.rs
Normal file
73
src/backend/openxr/blocker.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
use libmonado::{ClientState, Monado};
|
||||
use log::{info, warn};
|
||||
|
||||
use crate::{backend::overlay::OverlayID, state::AppState};
|
||||
|
||||
pub(super) struct InputBlocker {
|
||||
hovered_last_frame: bool,
|
||||
}
|
||||
|
||||
impl InputBlocker {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
hovered_last_frame: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, state: &AppState, watch_id: OverlayID, monado: &mut Monado) {
|
||||
if !state.session.config.block_game_input {
|
||||
return;
|
||||
}
|
||||
|
||||
let any_hovered = state.input_state.pointers.iter().any(|p| {
|
||||
p.interaction.hovered_id.is_some_and(|id| {
|
||||
id != watch_id || !state.session.config.block_game_input_ignore_watch
|
||||
})
|
||||
});
|
||||
|
||||
match (any_hovered, self.hovered_last_frame) {
|
||||
(true, false) => {
|
||||
info!("Blocking input");
|
||||
set_clients_io_active(monado, false);
|
||||
}
|
||||
(false, true) => {
|
||||
info!("Unblocking input");
|
||||
set_clients_io_active(monado, true);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.hovered_last_frame = any_hovered;
|
||||
}
|
||||
}
|
||||
|
||||
fn set_clients_io_active(monado: &mut Monado, active: bool) {
|
||||
match monado.clients() {
|
||||
Ok(clients) => {
|
||||
for mut client in clients {
|
||||
let name = match client.name() {
|
||||
Ok(n) => n,
|
||||
Err(e) => {
|
||||
warn!("Failed to get client name: {e}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let state = match client.state() {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
warn!("Failed to get client state: {e}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if name != "wlx-overlay-s" && state.contains(ClientState::ClientSessionVisible) {
|
||||
if let Err(e) = client.set_io_active(active) {
|
||||
warn!("Failed to set io active for client: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => warn!("Failed to get clients from Monado: {e}"),
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ use crate::{
|
||||
#[cfg(feature = "wayvr")]
|
||||
use crate::{gui::modular::button::WayVRAction, overlays::wayvr::wayvr_action};
|
||||
|
||||
mod blocker;
|
||||
mod helpers;
|
||||
mod input;
|
||||
mod lines;
|
||||
@@ -108,6 +109,8 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
|
||||
.ok()
|
||||
});
|
||||
|
||||
let mut blocker = monado.is_some().then(blocker::InputBlocker::new);
|
||||
|
||||
let (session, mut frame_wait, mut frame_stream) = unsafe {
|
||||
let raw_session = helpers::create_overlay_session(
|
||||
&xr_instance,
|
||||
@@ -268,6 +271,14 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
|
||||
input_source.update(&xr_state, &mut app)?;
|
||||
app.input_state.post_update(&app.session);
|
||||
|
||||
if let Some(ref mut blocker) = blocker {
|
||||
blocker.update(
|
||||
&app,
|
||||
watch_id,
|
||||
monado.as_mut().unwrap(), // safe
|
||||
);
|
||||
}
|
||||
|
||||
if app
|
||||
.input_state
|
||||
.pointers
|
||||
|
||||
@@ -273,6 +273,12 @@ pub struct GeneralConfig {
|
||||
#[serde(default = "def_false")]
|
||||
pub focus_follows_mouse_mode: bool,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
pub block_game_input: bool,
|
||||
|
||||
#[serde(default = "def_true")]
|
||||
pub block_game_input_ignore_watch: bool,
|
||||
|
||||
#[serde(default = "def_font")]
|
||||
pub primary_font: Arc<str>,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user