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
+26 -26
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
);
}
}
}
+48 -11
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
}