From 2315aca8b5131453f6ecf98d8b8deb88be7d6cc5 Mon Sep 17 00:00:00 2001 From: Nova Date: Sat, 10 Dec 2022 09:17:37 -0500 Subject: [PATCH] feat(startup settings): use /proc/{pid}/environ --- src/core/client.rs | 38 +++++++++++++++++++++++++++++++++++++- src/nodes/root.rs | 21 +++------------------ src/nodes/startup.rs | 19 +++++++------------ src/wayland/panel_item.rs | 11 +++++++++-- src/wayland/surface.rs | 12 ++++++++++++ 5 files changed, 68 insertions(+), 33 deletions(-) diff --git a/src/core/client.rs b/src/core/client.rs index b1c29a0..37699a1 100644 --- a/src/core/client.rs +++ b/src/core/client.rs @@ -1,7 +1,13 @@ use super::{eventloop::EventLoop, scenegraph::Scenegraph}; use crate::{ core::registry::Registry, - nodes::{data, drawable, fields, hmd, input, items, root::Root, spatial, startup, Node}, + nodes::{ + data, drawable, fields, hmd, input, items, + root::Root, + spatial, + startup::{self, StartupSettings, DESKTOP_STARTUP_IDS}, + Node, + }, }; use color_eyre::{ eyre::{eyre, Result}, @@ -10,9 +16,11 @@ use color_eyre::{ use lazy_static::lazy_static; use once_cell::sync::OnceCell; use parking_lot::Mutex; +use rustc_hash::FxHashMap; use stardust_xr::messenger::{self, MessageSenderHandle}; use std::{ fs, + iter::FromIterator, path::PathBuf, sync::{Arc, Weak}, }; @@ -25,6 +33,7 @@ lazy_static! { event_loop: Weak::new(), index: 0, pid: None, + env: None, exe: None, stop_notifier: Default::default(), @@ -37,10 +46,26 @@ lazy_static! { }); } +pub fn get_env(pid: i32) -> Result, std::io::Error> { + let env = fs::read_to_string(format!("/proc/{pid}/environ"))?; + Ok(FxHashMap::from_iter( + env.split('\0') + .filter_map(|var| var.split_once('=')) + .map(|(k, v)| (k.to_string(), v.to_string())), + )) +} +pub fn startup_settings(env: &FxHashMap) -> Option { + DESKTOP_STARTUP_IDS + .lock() + .get(env.get("STARDUST_STARTUP_TOKEN")?) + .cloned() +} + pub struct Client { event_loop: Weak, index: usize, pid: Option, + env: Option>, exe: Option, stop_notifier: Arc, join_handle: OnceCell>>, @@ -57,6 +82,7 @@ impl Client { connection: UnixStream, ) -> Arc { let pid = connection.peer_cred().ok().and_then(|c| c.pid()); + let env = pid.and_then(|pid| get_env(pid).ok()); let exe = pid.and_then(|pid| fs::read_link(format!("/proc/{}/exe", pid)).ok()); info!( index = index, @@ -74,6 +100,7 @@ impl Client { event_loop: Arc::downgrade(event_loop), index, pid, + env, exe, stop_notifier: Default::default(), join_handle: OnceCell::new(), @@ -94,6 +121,15 @@ impl Client { input::create_interface(&client); startup::create_interface(&client); + if let Some(startup_settings) = client.env.as_ref().and_then(|env| startup_settings(env)) { + client + .root + .get() + .unwrap() + .spatial() + .set_local_transform(startup_settings.transform); + } + let _ = client.join_handle.set(tokio::spawn({ let client = client.clone(); async move { diff --git a/src/nodes/root.rs b/src/nodes/root.rs index 7811d56..81629a0 100644 --- a/src/nodes/root.rs +++ b/src/nodes/root.rs @@ -1,9 +1,8 @@ use super::spatial::Spatial; -use super::startup::DESKTOP_STARTUP_IDS; use super::Node; use crate::core::client::Client; use crate::core::registry::Registry; -use color_eyre::eyre::{eyre, Result}; +use color_eyre::eyre::Result; use glam::Mat4; use stardust_xr::schemas::flex::{deserialize, serialize}; @@ -19,7 +18,6 @@ pub struct Root { impl Root { pub fn create(client: &Arc) -> Arc { let node = Node::create(client, "", "", false); - node.add_local_signal("apply_desktop_startup_id", Root::apply_desktop_startup_id); node.add_local_signal("subscribe_logic_step", Root::subscribe_logic_step); node.add_local_signal("set_base_prefixes", Root::set_base_prefixes); let node = node.add_to_scenegraph(); @@ -31,21 +29,8 @@ impl Root { }) } - fn apply_desktop_startup_id( - node: &Node, - _calling_client: Arc, - data: &[u8], - ) -> Result<()> { - let startup_settings = DESKTOP_STARTUP_IDS - .lock() - .remove(flexbuffers::Reader::get_root(data)?.get_str()?) - .ok_or_else(|| eyre!("Desktop startup ID not found in the list!"))?; - node.spatial - .get() - .unwrap() - .set_local_transform(startup_settings.transform); - - Ok(()) + pub fn spatial(&self) -> &Arc { + self.node.spatial.get().unwrap() } fn subscribe_logic_step(_node: &Node, calling_client: Arc, _data: &[u8]) -> Result<()> { diff --git a/src/nodes/startup.rs b/src/nodes/startup.rs index edc3387..0c2a4f5 100644 --- a/src/nodes/startup.rs +++ b/src/nodes/startup.rs @@ -1,7 +1,10 @@ use crate::core::client::Client; -use super::Node; -use color_eyre::eyre::{eyre, Result}; +use super::{ + spatial::find_spatial, + Node, +}; +use color_eyre::eyre::Result; use glam::Mat4; use parking_lot::Mutex; use rustc_hash::FxHashMap; @@ -23,15 +26,7 @@ impl StartupSettings { } fn set_root_flex(node: &Node, calling_client: Arc, data: &[u8]) -> Result<()> { - let startup_id = flexbuffers::Reader::get_root(data)?.get_str()?; - let spatial_node = calling_client - .scenegraph - .get_node(startup_id) - .ok_or_else(|| eyre!("Root spatial node does not exist"))?; - let spatial = spatial_node - .spatial - .get() - .ok_or_else(|| eyre!("Root spatial node is not a spatial"))?; + let spatial = find_spatial(&calling_client, "Root spatial", deserialize(data)?)?; node.startup_settings.get().unwrap().lock().transform = spatial.global_transform(); Ok(()) @@ -43,7 +38,7 @@ impl StartupSettings { _data: &[u8], ) -> Result> { let id = nanoid::nanoid!(); - let data = flexbuffers::singleton(id.as_str()); + let data = serialize(&id)?; DESKTOP_STARTUP_IDS .lock() .insert(id, node.startup_settings.get().unwrap().lock().clone()); diff --git a/src/wayland/panel_item.rs b/src/wayland/panel_item.rs index 4ff1783..b0e5fbd 100644 --- a/src/wayland/panel_item.rs +++ b/src/wayland/panel_item.rs @@ -4,7 +4,7 @@ use super::{ }; use crate::{ core::{ - client::{Client, INTERNAL_CLIENT}, + client::{get_env, startup_settings, Client, INTERNAL_CLIENT}, registry::Registry, }, nodes::{ @@ -68,7 +68,7 @@ impl PanelItem { &nanoid!(), true, )); - Spatial::add_to(&node, None, Mat4::IDENTITY, false).unwrap(); + let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false).unwrap(); let specialization = ItemType::Panel(PanelItem { node: Arc::downgrade(&node), @@ -103,6 +103,13 @@ impl PanelItem { node.add_local_signal("keyboard_deactivate", PanelItem::keyboard_deactivate_flex); node.add_local_signal("keyboard_key_state", PanelItem::keyboard_key_state_flex); node.add_local_signal("resize", PanelItem::resize_flex); + if let Some(startup_settings) = core_surface + .pid() + .and_then(|pid| get_env(pid).ok()) + .and_then(|env| startup_settings(&env)) + { + spatial.set_local_transform(startup_settings.transform); + } node } diff --git a/src/wayland/surface.rs b/src/wayland/surface.rs index e7dac7c..e05ed92 100644 --- a/src/wayland/surface.rs +++ b/src/wayland/surface.rs @@ -213,6 +213,18 @@ impl CoreSurface { }); } + pub fn pid(&self) -> Option { + Some( + self.weak_surface + .upgrade() + .ok()? + .client()? + .get_credentials(&self.dh) + .ok()? + .pid, + ) + } + pub fn wayland_state(&self) -> Arc> { self.state.upgrade().unwrap() }