add basic input blocking through libmonado (#190)

This commit is contained in:
Orion
2025-04-11 13:14:09 +02:00
committed by GitHub
parent 5b23de0599
commit 1ae50a35ec
3 changed files with 90 additions and 0 deletions

View 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}"),
}
}

View File

@@ -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

View File

@@ -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>,