From 91af7c99b174fa3b188675fe0c27d1e1d69403f0 Mon Sep 17 00:00:00 2001 From: Aleksander Date: Sun, 9 Mar 2025 21:14:50 +0100 Subject: [PATCH] WayVR: Read the `WAYVR_DISPLAY_AUTH` environment variable from external processes, matching it to our virtual display. This enables applications to be run via Flatpak or any other wrapper application. --- src/backend/wayvr/mod.rs | 52 +++++++++++++++---------------- src/backend/wayvr/process.rs | 59 +++++++++++++++++++++++++++++------- src/gui/modular/button.rs | 8 ++++- src/overlays/screen.rs | 4 +-- 4 files changed, 83 insertions(+), 40 deletions(-) diff --git a/src/backend/wayvr/mod.rs b/src/backend/wayvr/mod.rs index 9531ccb..55c29c1 100644 --- a/src/backend/wayvr/mod.rs +++ b/src/backend/wayvr/mod.rs @@ -346,35 +346,35 @@ impl WayVR { WayVRTask::NewToplevel(client_id, toplevel) => { // Attach newly created toplevel surfaces to displays for client in &self.state.manager.clients { - if client.client.id() == client_id { - if let Some(process_handle) = - process::find_by_pid(&self.state.processes, client.pid) + if client.client.id() != client_id { + continue; + } + + if let Some(process_handle) = + process::find_by_pid(&self.state.processes, client.pid) + { + let window_handle = self + .state + .wm + .borrow_mut() + .create_window(client.display_handle, &toplevel); + + if let Some(display) = + self.state.displays.get_mut(&client.display_handle) { - let window_handle = self - .state - .wm - .borrow_mut() - .create_window(client.display_handle, &toplevel); - - if let Some(display) = - self.state.displays.get_mut(&client.display_handle) - { - display.add_window(window_handle, process_handle, &toplevel); - self.state.signals.send(WayVRSignal::BroadcastStateChanged( - packet_server::WvrStateChanged::WindowCreated, - )); - } else { - // This shouldn't happen, scream if it does - log::error!("Could not attach window handle into display"); - } + display.add_window(window_handle, process_handle, &toplevel); + self.state.signals.send(WayVRSignal::BroadcastStateChanged( + packet_server::WvrStateChanged::WindowCreated, + )); } else { - log::error!( - "WayVR window creation failed: Unexpected process ID {}. It wasn't registered before.", - client.pid - ); + // This shouldn't happen, scream if it does + log::error!("Could not attach window handle into display"); } - - break; + } else { + log::error!( + "WayVR window creation failed: Unexpected process ID {}. It wasn't registered before.", + client.pid + ); } } } diff --git a/src/backend/wayvr/process.rs b/src/backend/wayvr/process.rs index ebd7135..3dff6ff 100644 --- a/src/backend/wayvr/process.rs +++ b/src/backend/wayvr/process.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, io::Read}; use wayvr_ipc::packet_server; @@ -88,6 +88,23 @@ impl Drop for WayVRProcess { } } +fn get_process_env_value(pid: i32, key: &str) -> anyhow::Result> { + let path = format!("/proc/{}/environ", pid); + let mut env_data = String::new(); + std::fs::File::open(path)?.read_to_string(&mut env_data)?; + let lines: Vec<&str> = env_data.split('\0').filter(|s| !s.is_empty()).collect(); + + for line in lines { + if let Some(cell) = line.split_once('=') { + if cell.0 == key { + return Ok(Some(String::from(cell.1))); + } + } + } + + Ok(None) +} + impl WayVRProcess { fn is_running(&mut self) -> bool { match self.child.try_wait() { @@ -153,22 +170,42 @@ impl ExternalProcess { gen_id!(ProcessVec, Process, ProcessCell, ProcessHandle); pub fn find_by_pid(processes: &ProcessVec, pid: u32) -> Option { + log::debug!("Finding process with PID {}", pid); + for (idx, cell) in processes.vec.iter().enumerate() { - if let Some(cell) = cell { - match &cell.obj { - Process::Managed(wayvr_process) => { - if wayvr_process.child.id() == pid { - return Some(ProcessVec::get_handle(cell, idx)); - } + let Some(cell) = cell else { + continue; + }; + match &cell.obj { + Process::Managed(wayvr_process) => { + if wayvr_process.child.id() == pid { + return Some(ProcessVec::get_handle(cell, idx)); } - Process::External(external_process) => { - if external_process.pid == pid { - return Some(ProcessVec::get_handle(cell, idx)); - } + } + Process::External(external_process) => { + if external_process.pid == pid { + return Some(ProcessVec::get_handle(cell, idx)); } } } } + + log::debug!("Finding by PID failed, trying WAYVR_DISPLAY_AUTH..."); + + if let Ok(Some(value)) = get_process_env_value(pid as i32, "WAYVR_DISPLAY_AUTH") { + for (idx, cell) in processes.vec.iter().enumerate() { + let Some(cell) = cell else { + continue; + }; + if let Process::Managed(wayvr_process) = &cell.obj { + if wayvr_process.auth_key == value { + return Some(ProcessVec::get_handle(cell, idx)); + } + } + } + } + + log::debug!("Process find with PID {} failed", pid); None } diff --git a/src/gui/modular/button.rs b/src/gui/modular/button.rs index 1215024..5a15cc8 100644 --- a/src/gui/modular/button.rs +++ b/src/gui/modular/button.rs @@ -326,7 +326,13 @@ fn modular_button_up(button: &mut ModularControl, _: &mut (), app: &mut AppState } } -fn modular_button_scroll(button: &mut ModularControl, _: &mut (), app: &mut AppState, delta_y: f32, delta_x: f32) { +fn modular_button_scroll( + button: &mut ModularControl, + _: &mut (), + app: &mut AppState, + delta_y: f32, + _delta_x: f32, +) { // want panic let ModularData::Button(data) = button.state.as_mut().unwrap() else { panic!("modular_button_scroll: button state is not Button"); diff --git a/src/overlays/screen.rs b/src/overlays/screen.rs index dba6212..7282285 100644 --- a/src/overlays/screen.rs +++ b/src/overlays/screen.rs @@ -3,7 +3,6 @@ use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; use std::{ f32::consts::PI, - ops::Add, ptr, sync::{atomic::AtomicU64, Arc}, time::{Duration, Instant}, @@ -151,7 +150,8 @@ impl InteractionHandler for ScreenInteractionHandler { app.hid_provider.mouse_move(pos); } fn on_scroll(&mut self, app: &mut AppState, _hit: &PointerHit, delta_y: f32, delta_x: f32) { - app.hid_provider.wheel((delta_y*64.) as i32, (delta_x*64.) as i32) + app.hid_provider + .wheel((delta_y * 64.) as i32, (delta_x * 64.) as i32) } fn on_left(&mut self, _app: &mut AppState, _hand: usize) {} }