config: allow spawning clients with tags
This commit is contained in:
parent
8b19315f50
commit
a1df575262
11 changed files with 80 additions and 7 deletions
|
|
@ -348,7 +348,15 @@ impl ConfigClient {
|
||||||
.drain()
|
.drain()
|
||||||
.map(|(a, b)| (a, b.into_raw_fd()))
|
.map(|(a, b)| (a, b.into_raw_fd()))
|
||||||
.collect();
|
.collect();
|
||||||
if fds.is_empty() {
|
if command.tag.is_some() {
|
||||||
|
self.send(&ClientMessage::Run3 {
|
||||||
|
prog: &command.prog,
|
||||||
|
args: command.args.clone(),
|
||||||
|
env,
|
||||||
|
fds,
|
||||||
|
tag: command.tag.as_deref(),
|
||||||
|
});
|
||||||
|
} else if fds.is_empty() {
|
||||||
self.send(&ClientMessage::Run {
|
self.send(&ClientMessage::Run {
|
||||||
prog: &command.prog,
|
prog: &command.prog,
|
||||||
args: command.args.clone(),
|
args: command.args.clone(),
|
||||||
|
|
|
||||||
|
|
@ -834,6 +834,13 @@ pub enum ClientMessage<'a> {
|
||||||
SetXWaylandEnabled {
|
SetXWaylandEnabled {
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
},
|
},
|
||||||
|
Run3 {
|
||||||
|
prog: &'a str,
|
||||||
|
args: Vec<String>,
|
||||||
|
env: Vec<(String, String)>,
|
||||||
|
fds: Vec<(i32, i32)>,
|
||||||
|
tag: Option<&'a str>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ pub struct Command {
|
||||||
pub(crate) args: Vec<String>,
|
pub(crate) args: Vec<String>,
|
||||||
pub(crate) env: HashMap<String, String>,
|
pub(crate) env: HashMap<String, String>,
|
||||||
pub(crate) fds: RefCell<HashMap<i32, OwnedFd>>,
|
pub(crate) fds: RefCell<HashMap<i32, OwnedFd>>,
|
||||||
|
pub(crate) tag: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Command {
|
impl Command {
|
||||||
|
|
@ -37,6 +38,7 @@ impl Command {
|
||||||
args: vec![],
|
args: vec![],
|
||||||
env: Default::default(),
|
env: Default::default(),
|
||||||
fds: Default::default(),
|
fds: Default::default(),
|
||||||
|
tag: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,6 +99,12 @@ impl Command {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds a tag to Wayland connections created by the spawned command.
|
||||||
|
pub fn tag(&mut self, tag: &str) -> &mut Self {
|
||||||
|
self.tag = Some(tag.to_owned());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Executes the command.
|
/// Executes the command.
|
||||||
///
|
///
|
||||||
/// This consumes all attached file descriptors.
|
/// This consumes all attached file descriptors.
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use {
|
||||||
},
|
},
|
||||||
client::{CAP_JAY_COMPOSITOR, Client, ClientCaps, ClientId},
|
client::{CAP_JAY_COMPOSITOR, Client, ClientCaps, ClientId},
|
||||||
cmm::cmm_eotf::Eotf,
|
cmm::cmm_eotf::Eotf,
|
||||||
compositor::MAX_EXTENTS,
|
compositor::{MAX_EXTENTS, WAYLAND_DISPLAY},
|
||||||
config::ConfigProxy,
|
config::ConfigProxy,
|
||||||
criteria::{
|
criteria::{
|
||||||
CritLiteralOrRegex, CritMgrExt, CritTarget, CritUpstreamNode,
|
CritLiteralOrRegex, CritMgrExt, CritTarget, CritUpstreamNode,
|
||||||
|
|
@ -26,6 +26,7 @@ use {
|
||||||
output_schedule::map_cursor_hz,
|
output_schedule::map_cursor_hz,
|
||||||
scale::Scale,
|
scale::Scale,
|
||||||
state::{ConnectorData, DeviceHandlerData, DrmDevData, OutputData, State},
|
state::{ConnectorData, DeviceHandlerData, DrmDevData, OutputData, State},
|
||||||
|
tagged_acceptor::TaggedAcceptorError,
|
||||||
theme::{Color, ThemeSized},
|
theme::{Color, ThemeSized},
|
||||||
tree::{
|
tree::{
|
||||||
ContainerNode, ContainerSplit, FloatNode, Node, NodeVisitorBase, OutputNode,
|
ContainerNode, ContainerSplit, FloatNode, Node, NodeVisitorBase, OutputNode,
|
||||||
|
|
@ -1823,9 +1824,18 @@ impl ConfigProxyHandler {
|
||||||
&self,
|
&self,
|
||||||
prog: &str,
|
prog: &str,
|
||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
env: Vec<(String, String)>,
|
mut env: Vec<(String, String)>,
|
||||||
fds: Vec<(i32, i32)>,
|
fds: Vec<(i32, i32)>,
|
||||||
|
tag: Option<&str>,
|
||||||
) -> Result<(), CphError> {
|
) -> Result<(), CphError> {
|
||||||
|
if let Some(tag) = tag {
|
||||||
|
let display = self
|
||||||
|
.state
|
||||||
|
.tagged_acceptors
|
||||||
|
.get(&self.state, tag)
|
||||||
|
.map_err(CphError::CreateTaggedAcceptor)?;
|
||||||
|
env.push((WAYLAND_DISPLAY.to_string(), display.to_string()));
|
||||||
|
}
|
||||||
let fds: Vec<_> = fds
|
let fds: Vec<_> = fds
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(a, b)| (a, Rc::new(OwnedFd::new(b))))
|
.map(|(a, b)| (a, Rc::new(OwnedFd::new(b))))
|
||||||
|
|
@ -2816,7 +2826,7 @@ impl ConfigProxyHandler {
|
||||||
ClientMessage::GetSeats => self.handle_get_seats(),
|
ClientMessage::GetSeats => self.handle_get_seats(),
|
||||||
ClientMessage::RemoveSeat { .. } => {}
|
ClientMessage::RemoveSeat { .. } => {}
|
||||||
ClientMessage::Run { prog, args, env } => {
|
ClientMessage::Run { prog, args, env } => {
|
||||||
self.handle_run(prog, args, env, vec![]).wrn("run")?
|
self.handle_run(prog, args, env, vec![], None).wrn("run")?
|
||||||
}
|
}
|
||||||
ClientMessage::GrabKb { kb, grab } => self.handle_grab(kb, grab).wrn("grab")?,
|
ClientMessage::GrabKb { kb, grab } => self.handle_grab(kb, grab).wrn("grab")?,
|
||||||
ClientMessage::SetColor { colorable, color } => {
|
ClientMessage::SetColor { colorable, color } => {
|
||||||
|
|
@ -3024,7 +3034,7 @@ impl ConfigProxyHandler {
|
||||||
args,
|
args,
|
||||||
env,
|
env,
|
||||||
fds,
|
fds,
|
||||||
} => self.handle_run(prog, args, env, fds).wrn("run")?,
|
} => self.handle_run(prog, args, env, fds, None).wrn("run")?,
|
||||||
ClientMessage::DisableDefaultSeat => self.state.create_default_seat.set(false),
|
ClientMessage::DisableDefaultSeat => self.state.create_default_seat.set(false),
|
||||||
ClientMessage::DestroyKeymap { keymap } => self.handle_destroy_keymap(keymap),
|
ClientMessage::DestroyKeymap { keymap } => self.handle_destroy_keymap(keymap),
|
||||||
ClientMessage::GetConnectorName { connector } => self
|
ClientMessage::GetConnectorName { connector } => self
|
||||||
|
|
@ -3394,6 +3404,13 @@ impl ConfigProxyHandler {
|
||||||
ClientMessage::SetXWaylandEnabled { enabled } => self
|
ClientMessage::SetXWaylandEnabled { enabled } => self
|
||||||
.handle_set_x_wayland_enabled(enabled)
|
.handle_set_x_wayland_enabled(enabled)
|
||||||
.wrn("set_x_wayland_enabled")?,
|
.wrn("set_x_wayland_enabled")?,
|
||||||
|
ClientMessage::Run3 {
|
||||||
|
prog,
|
||||||
|
args,
|
||||||
|
env,
|
||||||
|
fds,
|
||||||
|
tag,
|
||||||
|
} => self.handle_run(prog, args, env, fds, tag).wrn("run")?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -3549,6 +3566,8 @@ enum CphError {
|
||||||
UnknownFallbackOutputMode(FallbackOutputMode),
|
UnknownFallbackOutputMode(FallbackOutputMode),
|
||||||
#[error("Unknown tile state {0:?}")]
|
#[error("Unknown tile state {0:?}")]
|
||||||
UnknownTileState(ConfigTileState),
|
UnknownTileState(ConfigTileState),
|
||||||
|
#[error("Could not create a tagged acceptor")]
|
||||||
|
CreateTaggedAcceptor(#[source] TaggedAcceptorError),
|
||||||
}
|
}
|
||||||
|
|
||||||
trait WithRequestName {
|
trait WithRequestName {
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,6 @@ impl TaggedAcceptors {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[expect(dead_code)]
|
|
||||||
pub fn get(&self, state: &Rc<State>, tag: &str) -> Result<Rc<String>, TaggedAcceptorError> {
|
pub fn get(&self, state: &Rc<State>, tag: &str) -> Result<Rc<String>, TaggedAcceptorError> {
|
||||||
let acceptors = &mut *self.acceptors.borrow_mut();
|
let acceptors = &mut *self.acceptors.borrow_mut();
|
||||||
if let Some(acceptor) = acceptors.get(tag) {
|
if let Some(acceptor) = acceptors.get(tag) {
|
||||||
|
|
|
||||||
|
|
@ -421,6 +421,7 @@ pub struct Exec {
|
||||||
pub args: Vec<String>,
|
pub args: Vec<String>,
|
||||||
pub envs: Vec<(String, String)>,
|
pub envs: Vec<(String, String)>,
|
||||||
pub privileged: bool,
|
pub privileged: bool,
|
||||||
|
pub tag: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ impl Parser for ExecParser<'_> {
|
||||||
args: vec![],
|
args: vec![],
|
||||||
envs: vec![],
|
envs: vec![],
|
||||||
privileged: false,
|
privileged: false,
|
||||||
|
tag: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,6 +71,7 @@ impl Parser for ExecParser<'_> {
|
||||||
args,
|
args,
|
||||||
envs: vec![],
|
envs: vec![],
|
||||||
privileged: false,
|
privileged: false,
|
||||||
|
tag: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,12 +81,13 @@ impl Parser for ExecParser<'_> {
|
||||||
table: &IndexMap<Spanned<String>, Spanned<Value>>,
|
table: &IndexMap<Spanned<String>, Spanned<Value>>,
|
||||||
) -> ParseResult<Self> {
|
) -> ParseResult<Self> {
|
||||||
let mut ext = Extractor::new(self.0, span, table);
|
let mut ext = Extractor::new(self.0, span, table);
|
||||||
let (prog_opt, shell_opt, args_val, envs_val, privileged) = ext.extract((
|
let (prog_opt, shell_opt, args_val, envs_val, privileged, tag) = ext.extract((
|
||||||
opt(str("prog")),
|
opt(str("prog")),
|
||||||
opt(str("shell")),
|
opt(str("shell")),
|
||||||
opt(arr("args")),
|
opt(arr("args")),
|
||||||
opt(val("env")),
|
opt(val("env")),
|
||||||
recover(opt(bol("privileged"))),
|
recover(opt(bol("privileged"))),
|
||||||
|
opt(str("tag")),
|
||||||
))?;
|
))?;
|
||||||
let prog;
|
let prog;
|
||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
|
|
@ -112,11 +115,21 @@ impl Parser for ExecParser<'_> {
|
||||||
None => vec![],
|
None => vec![],
|
||||||
Some(e) => e.parse_map(&mut EnvParser)?,
|
Some(e) => e.parse_map(&mut EnvParser)?,
|
||||||
};
|
};
|
||||||
|
if let Some(privileged) = privileged
|
||||||
|
&& privileged.value
|
||||||
|
&& tag.is_some()
|
||||||
|
{
|
||||||
|
log::warn!(
|
||||||
|
"Exec is privileged and tagged but tagged execs are always unprivileged: {}",
|
||||||
|
self.0.error3(privileged.span),
|
||||||
|
);
|
||||||
|
}
|
||||||
Ok(Exec {
|
Ok(Exec {
|
||||||
prog,
|
prog,
|
||||||
args,
|
args,
|
||||||
envs,
|
envs,
|
||||||
privileged: privileged.despan().unwrap_or(false),
|
privileged: privileged.despan().unwrap_or(false),
|
||||||
|
tag: tag.despan_into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1646,6 +1646,9 @@ fn create_command(exec: &Exec) -> Command {
|
||||||
if exec.privileged {
|
if exec.privileged {
|
||||||
command.privileged();
|
command.privileged();
|
||||||
}
|
}
|
||||||
|
if let Some(tag) = &exec.tag {
|
||||||
|
command.tag(tag);
|
||||||
|
}
|
||||||
command
|
command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1291,6 +1291,10 @@
|
||||||
"privileged": {
|
"privileged": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "If `true`, the executable gets access to privileged wayland protocols.\n\nThe default is `false`.\n"
|
"description": "If `true`, the executable gets access to privileged wayland protocols.\n\nThe default is `false`.\n"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Specifies a tag to apply to all spawned wayland connections.\n"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": []
|
"required": []
|
||||||
|
|
|
||||||
|
|
@ -2723,6 +2723,12 @@ The table has the following fields:
|
||||||
|
|
||||||
The value of this field should be a boolean.
|
The value of this field should be a boolean.
|
||||||
|
|
||||||
|
- `tag` (optional):
|
||||||
|
|
||||||
|
Specifies a tag to apply to all spawned wayland connections.
|
||||||
|
|
||||||
|
The value of this field should be a string.
|
||||||
|
|
||||||
|
|
||||||
<a name="types-FallbackOutputMode"></a>
|
<a name="types-FallbackOutputMode"></a>
|
||||||
### `FallbackOutputMode`
|
### `FallbackOutputMode`
|
||||||
|
|
|
||||||
|
|
@ -858,6 +858,11 @@ Exec:
|
||||||
If `true`, the executable gets access to privileged wayland protocols.
|
If `true`, the executable gets access to privileged wayland protocols.
|
||||||
|
|
||||||
The default is `false`.
|
The default is `false`.
|
||||||
|
tag:
|
||||||
|
kind: string
|
||||||
|
required: false
|
||||||
|
description: |
|
||||||
|
Specifies a tag to apply to all spawned wayland connections.
|
||||||
|
|
||||||
|
|
||||||
SimpleActionName:
|
SimpleActionName:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue