diff --git a/src/comp.rs b/src/comp.rs index 759bcdf..666ec1b 100644 --- a/src/comp.rs +++ b/src/comp.rs @@ -1,10 +1,10 @@ -use std::os::unix::prelude::IntoRawFd; - // SPDX-License-Identifier: GPL-3.0-only use crate::process::{ProcessEvent, ProcessHandler}; +use serde::{Deserialize, Serialize}; +use std::{collections::HashMap, os::unix::prelude::IntoRawFd}; use tokio::{ io::{AsyncBufReadExt, BufReader, Lines}, - net::UnixStream, + net::{unix::ReadHalf, UnixStream}, sync::{ mpsc::{self, unbounded_channel}, oneshot, @@ -12,6 +12,13 @@ use tokio::{ }; use tokio_util::sync::CancellationToken; +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "snake_case", tag = "message")] +pub enum Message { + SetEnv { variables: HashMap }, + NewPrivilegedClient { fd: u32 }, +} + async fn receive_event(rx: &mut mpsc::UnboundedReceiver) -> Option<()> { match rx.recv().await? { ProcessEvent::Started => { @@ -34,20 +41,38 @@ async fn receive_event(rx: &mut mpsc::UnboundedReceiver) -> Option } } -async fn receive_ipc(rx: &mut Lines>) -> Option<()> { +async fn receive_ipc( + rx: &mut Lines>>, + env_tx: &mut Option>>, +) -> Option<()> { let line = rx .next_line() .await .expect("failed to get next line of ipc")?; - let message = serde_json::from_str::<()>(&line).expect("invalid message from cosmic-comp"); + match serde_json::from_str::(&line).expect("invalid message from cosmic-comp") { + Message::SetEnv { variables } => { + if let Some(env_tx) = env_tx.take() { + env_tx + .send(variables.into_iter().collect()) + .expect("failed to send environmental variables"); + } + } + Message::NewPrivilegedClient { fd } => { + unreachable!("compositor should not send NewPrivilegedClient") + } + } Some(()) } -pub async fn run_compositor(token: CancellationToken, wayland_display_tx: oneshot::Sender) { - let mut wayland_display_tx = Some(wayland_display_tx); +pub async fn run_compositor( + token: CancellationToken, + env_tx: oneshot::Sender>, +) { + let mut env_tx = Some(env_tx); let (tx, mut rx) = unbounded_channel::(); - let (session, comp) = UnixStream::pair().expect("failed to create pair of unix sockets"); - let mut session = BufReader::new(session).lines(); + let (mut session, comp) = UnixStream::pair().expect("failed to create pair of unix sockets"); + let (session_rx, session_tx) = session.split(); + let mut session = BufReader::new(session_rx).lines(); let comp = { let std_stream = comp .into_std() @@ -66,7 +91,7 @@ pub async fn run_compositor(token: CancellationToken, wayland_display_tx: onesho exit = receive_event(&mut rx) => if exit.is_none() { break; }, - exit = receive_ipc(&mut session) => if exit.is_none() { + exit = receive_ipc(&mut session, &mut env_tx) => if exit.is_none() { break; } } diff --git a/src/main.rs b/src/main.rs index b1680fb..f0211ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,25 +31,22 @@ async fn main() -> Result<()> { info!("Starting cosmic-session"); let token = CancellationToken::new(); - let (wayland_display_tx, wayland_display_rx) = oneshot::channel(); - tokio::spawn(comp::run_compositor( - token.child_token(), - wayland_display_tx, - )); - let wayland_display = wayland_display_rx + let (env_tx, env_rx) = oneshot::channel(); + tokio::spawn(comp::run_compositor(token.child_token(), env_tx)); + let env_vars = env_rx .await - .expect("failed to get WAYLAND_DISPLAY"); - info!("got WAYLAND_DISPLAY: {}", wayland_display); + .expect("failed to receive environmental variables"); + info!("got environmental variables: {:?}", env_vars); tokio::spawn(panel::run_panel( token.child_token(), "testing-panel", - wayland_display.clone(), + env_vars.clone(), )); tokio::spawn(panel::run_panel( token.child_token(), "testing-dock", - wayland_display.clone(), + env_vars.clone(), )); let mut signals = Signals::new(vec![libc::SIGTERM, libc::SIGINT]).unwrap(); diff --git a/src/panel.rs b/src/panel.rs index 0af1674..8d31710 100644 --- a/src/panel.rs +++ b/src/panel.rs @@ -3,12 +3,9 @@ use crate::process::{ProcessEvent, ProcessHandler}; use tokio::sync::mpsc::unbounded_channel; use tokio_util::sync::CancellationToken; -pub async fn run_panel(token: CancellationToken, config: &str, wayland_display: String) { +pub async fn run_panel(token: CancellationToken, config: &str, env_vars: Vec<(String, String)>) { let (tx, mut rx) = unbounded_channel::(); - ProcessHandler::new(tx, &token).run("cosmic-panel", vec![config.to_string()], vec![( - "WAYLAND_DISPLAY".into(), - wayland_display, - )]); + ProcessHandler::new(tx, &token).run("cosmic-panel", vec![config.to_string()], env_vars); while let Some(event) = rx.recv().await { match event { ProcessEvent::Started => {