Skip to content

Commit

Permalink
x11: Introduce the -x command line option to enable X11 forwarding
Browse files Browse the repository at this point in the history
Instead of enabling X11 forwarding unconditionally but hiding it behind
the HOST_DISPLAY variable, enable it if the --direct-x11 flag is used.
In that case, directly set it as the DISPLAY environment variable.

This makes it easier for users to enable the feature and use it
correctly. Eventually, we can flip the logic of the flag to make direct
X11 the default.

Keep the server at :1 to keep churn down, and because it seems like a
generally helpful distinction, since the server is usually :0 on the
host.

Signed-off-by: Asahi Lina <[email protected]>
  • Loading branch information
asahilina committed Oct 30, 2024
1 parent 84730c8 commit 0979707
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 25 deletions.
11 changes: 11 additions & 0 deletions crates/muvm/src/bin/muvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,17 @@ fn main() -> Result<()> {
options.server_port.to_string(),
);

if options.direct_x11 {
let display = env::var("DISPLAY").context("X11 forwarding requested but DISPLAY is unset")?;
env.insert("HOST_DISPLAY".to_string(), display);

// And forward XAUTHORITY. This will be modified to fix the
// display name in muvm-guest.
if let Ok(xauthority) = env::var("XAUTHORITY") {
env.insert("XAUTHORITY".to_string(), xauthority);
}
}

let mut krun_config = KrunConfig {
args: Vec::new(),
envs: Vec::new(),
Expand Down
7 changes: 7 additions & 0 deletions crates/muvm/src/cli_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub struct Options {
pub passt_socket: Option<PathBuf>,
pub server_port: u32,
pub fex_images: Vec<String>,
pub direct_x11: bool,
pub command: PathBuf,
pub command_args: Vec<String>,
}
Expand Down Expand Up @@ -98,6 +99,11 @@ pub fn options() -> OptionParser<Options> {
.argument("SERVER_PORT")
.fallback(3334)
.display_fallback();
let direct_x11 = long("direct-x11")
.short('x')
.help("Use direct X11 forwarding instead of sommelier + XWayland")
.flag(true, false);

let command = positional("COMMAND").help("the command you want to execute in the vm");
let command_args = any::<String, _, _>("COMMAND_ARGS", |arg| {
(!["--help", "-h"].contains(&&*arg)).then_some(arg)
Expand All @@ -113,6 +119,7 @@ pub fn options() -> OptionParser<Options> {
passt_socket,
server_port,
fex_images,
direct_x11,
// positionals
command,
command_args,
Expand Down
13 changes: 0 additions & 13 deletions crates/muvm/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,6 @@ pub fn prepare_env_vars(env: Vec<(String, Option<String>)>) -> Result<HashMap<St
env_map.insert(key, value);
}

// If we have an X11 display in the host, set HOST_DISPLAY in the guest.
// muvm-guest will then use this to set up xauth and replace it with :1
// (which is forwarded to the host display).
if let Ok(display) = env::var("DISPLAY") {
env_map.insert("HOST_DISPLAY".to_string(), display);

// And forward XAUTHORITY. This will be modified to fix the
// display name in muvm-guest.
if let Ok(xauthority) = env::var("XAUTHORITY") {
env_map.insert("XAUTHORITY".to_string(), xauthority);
}
}

debug!(env:? = env_map; "env vars");

Ok(env_map)
Expand Down
12 changes: 6 additions & 6 deletions crates/muvm/src/guest/bin/muvm-guest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ fn main() -> Result<()> {
let pulse_path = pulse_path.join("native");
setup_socket_proxy(pulse_path, 3333)?;

setup_x11_forwarding(run_path)?;

// Will not return if successful.
exec_sommelier(&options.command, &options.command_args)
.context("Failed to execute sommelier")?;
if !setup_x11_forwarding(run_path)? {
// Will not return if successful.
exec_sommelier(&options.command, &options.command_args)
.context("Failed to execute sommelier")?;
}

// Fallback option if sommelier is not present.
// Fallback option if sommelier is not present or for direct X11 mode.
debug!(command:? = options.command, command_args:? = options.command_args; "exec");
let err = Command::new(&options.command)
.args(options.command_args)
Expand Down
12 changes: 6 additions & 6 deletions crates/muvm/src/guest/x11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ use super::socket::setup_socket_proxy;

use crate::utils::env::find_in_path;

pub fn setup_x11_forwarding<P>(run_path: P) -> Result<()>
pub fn setup_x11_forwarding<P>(run_path: P) -> Result<bool>
where
P: AsRef<Path>,
{
// Set by muvm if DISPLAY was provided from the host.
let host_display = match env::var("HOST_DISPLAY") {
Ok(d) => d,
Err(_) => return Ok(()),
Err(_) => return Ok(false),
};

if !host_display.starts_with(':') {
Expand All @@ -35,14 +35,14 @@ where

cmd.spawn().context("Failed to spawn `x112virtgpu`")?;
} else {
log::error!("x112virtgpu not available, X11 forwarding will operate in socket forwarding mode. This is probably not what you want.");
setup_socket_proxy(Path::new("/tmp/.X11-unix/X1"), 6000)?;
}

// Set HOST_DISPLAY to :1, which is the display number within the guest
// at which the actual host display is accessible.
// SAFETY: Safe if and only if `muvm-guest` program is not multithreaded.
// See https://doc.rust-lang.org/std/env/fn.set_var.html#safety
env::set_var("HOST_DISPLAY", ":1");
env::set_var("DISPLAY", ":1");
env::set_var("XSHMFENCE_NO_MEMFD", "1");

if let Ok(xauthority) = std::env::var("XAUTHORITY") {
let src_path = format!("/run/muvm-host/{}", xauthority);
Expand Down Expand Up @@ -100,5 +100,5 @@ where
env::set_var("XAUTHORITY", dst_path);
}

Ok(())
Ok(true)
}

0 comments on commit 0979707

Please sign in to comment.