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.
This commit is contained in:
Aleksander
2025-03-09 21:14:50 +01:00
parent 0b7cd61d05
commit 91af7c99b1
4 changed files with 83 additions and 40 deletions

View File

@@ -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
);
}
}
}

View File

@@ -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<Option<String>> {
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<ProcessHandle> {
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
}

View File

@@ -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");

View File

@@ -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) {}
}