Implement kiosk mode for cosmic-greeter
This commit is contained in:
parent
54f2d2c67e
commit
ec822e421f
2 changed files with 65 additions and 20 deletions
42
src/main.rs
42
src/main.rs
|
|
@ -9,7 +9,7 @@ use smithay::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use std::{ffi::OsString, sync::Arc};
|
use std::{env, ffi::OsString, process, sync::Arc};
|
||||||
use tracing::{error, info, warn};
|
use tracing::{error, info, warn};
|
||||||
|
|
||||||
use crate::wayland::handlers::compositor::client_compositor_state;
|
use crate::wayland::handlers::compositor::client_compositor_state;
|
||||||
|
|
@ -56,6 +56,18 @@ fn main() -> Result<()> {
|
||||||
// potentially tell the session we are setup now
|
// potentially tell the session we are setup now
|
||||||
session::setup_socket(event_loop.handle(), &state)?;
|
session::setup_socket(event_loop.handle(), &state)?;
|
||||||
|
|
||||||
|
let mut args = env::args().skip(1);
|
||||||
|
let mut child_opt = if let Some(exec) = args.next() {
|
||||||
|
// Run command in kiosk mode
|
||||||
|
let mut command = process::Command::new(&exec);
|
||||||
|
command.args(args);
|
||||||
|
command.envs(session::get_env(&state)?);
|
||||||
|
info!("Running {:?}", exec);
|
||||||
|
Some(command.spawn()?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
if let Err(err) = theme::watch_theme(event_loop.handle()) {
|
if let Err(err) = theme::watch_theme(event_loop.handle()) {
|
||||||
warn!(?err, "Failed to watch theme");
|
warn!(?err, "Failed to watch theme");
|
||||||
}
|
}
|
||||||
|
|
@ -83,8 +95,36 @@ fn main() -> Result<()> {
|
||||||
|
|
||||||
// send out events
|
// send out events
|
||||||
let _ = state.common.display_handle.flush_clients();
|
let _ = state.common.display_handle.flush_clients();
|
||||||
|
|
||||||
|
// check if kiosk child is running
|
||||||
|
if let Some(ref mut child) = child_opt {
|
||||||
|
match child.try_wait() {
|
||||||
|
// Kiosk child exited with status
|
||||||
|
Ok(Some(exit_status)) => {
|
||||||
|
info!("Command exited with status {:?}", exit_status);
|
||||||
|
match exit_status.code() {
|
||||||
|
// Exiting with the same status as the kiosk child
|
||||||
|
Some(code) => process::exit(code),
|
||||||
|
// The kiosk child exited with signal, exiting with error
|
||||||
|
None => process::exit(1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Command still running
|
||||||
|
Ok(None) => {}
|
||||||
|
// Kiosk child disappeared, exiting with error
|
||||||
|
Err(err) => {
|
||||||
|
warn!(?err, "Failed to wait for command");
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// kill kiosk child if loop exited
|
||||||
|
if let Some(mut child) = child_opt {
|
||||||
|
let _ = child.kill();
|
||||||
|
}
|
||||||
|
|
||||||
// drop eventloop & state before logger
|
// drop eventloop & state before logger
|
||||||
std::mem::drop(event_loop);
|
std::mem::drop(event_loop);
|
||||||
std::mem::drop(state);
|
std::mem::drop(state);
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,29 @@ unsafe fn set_cloexec(fd: RawFd) -> rustix::io::Result<()> {
|
||||||
rustix::io::fcntl_setfd(fd, flags | rustix::io::FdFlags::CLOEXEC)
|
rustix::io::fcntl_setfd(fd, flags | rustix::io::FdFlags::CLOEXEC)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_env(state: &State) -> Result<HashMap<String, String>> {
|
||||||
|
let mut env = HashMap::new();
|
||||||
|
env.insert(
|
||||||
|
String::from("WAYLAND_DISPLAY"),
|
||||||
|
state
|
||||||
|
.common
|
||||||
|
.socket
|
||||||
|
.clone()
|
||||||
|
.into_string()
|
||||||
|
.map_err(|_| anyhow!("wayland socket is no valid utf-8 string?"))?,
|
||||||
|
);
|
||||||
|
if let Some(display) = state
|
||||||
|
.common
|
||||||
|
.shell
|
||||||
|
.xwayland_state
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.display)
|
||||||
|
{
|
||||||
|
env.insert(String::from("DISPLAY"), format!(":{}", display));
|
||||||
|
}
|
||||||
|
Ok(env)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn setup_socket(handle: LoopHandle<State>, state: &State) -> Result<()> {
|
pub fn setup_socket(handle: LoopHandle<State>, state: &State) -> Result<()> {
|
||||||
if let Ok(fd_num) = std::env::var("COSMIC_SESSION_SOCK") {
|
if let Ok(fd_num) = std::env::var("COSMIC_SESSION_SOCK") {
|
||||||
if let Ok(fd) = fd_num.parse::<RawFd>() {
|
if let Ok(fd) = fd_num.parse::<RawFd>() {
|
||||||
|
|
@ -72,25 +95,7 @@ pub fn setup_socket(handle: LoopHandle<State>, state: &State) -> Result<()> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut env = HashMap::new();
|
let env = get_env(state)?;
|
||||||
env.insert(
|
|
||||||
String::from("WAYLAND_DISPLAY"),
|
|
||||||
state
|
|
||||||
.common
|
|
||||||
.socket
|
|
||||||
.clone()
|
|
||||||
.into_string()
|
|
||||||
.map_err(|_| anyhow!("wayland socket is no valid utf-8 string?"))?,
|
|
||||||
);
|
|
||||||
if let Some(display) = state
|
|
||||||
.common
|
|
||||||
.shell
|
|
||||||
.xwayland_state
|
|
||||||
.as_ref()
|
|
||||||
.map(|s| s.display)
|
|
||||||
{
|
|
||||||
env.insert(String::from("DISPLAY"), format!(":{}", display));
|
|
||||||
}
|
|
||||||
let message = serde_json::to_string(&Message::SetEnv { variables: env })
|
let message = serde_json::to_string(&Message::SetEnv { variables: env })
|
||||||
.with_context(|| "Failed to encode environment variables into json")?;
|
.with_context(|| "Failed to encode environment variables into json")?;
|
||||||
let bytes = message.into_bytes();
|
let bytes = message.into_bytes();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue