cli: add run-tagged subcommand
This commit is contained in:
parent
a1df575262
commit
3e7ca00565
7 changed files with 176 additions and 1 deletions
|
|
@ -11,6 +11,7 @@ mod quit;
|
|||
mod randr;
|
||||
mod reexec;
|
||||
mod run_privileged;
|
||||
mod run_tagged;
|
||||
pub mod screenshot;
|
||||
mod seat_test;
|
||||
mod set_log_level;
|
||||
|
|
@ -24,7 +25,7 @@ use {
|
|||
cli::{
|
||||
clients::ClientsArgs, color_management::ColorManagementArgs,
|
||||
damage_tracking::DamageTrackingArgs, idle::IdleCmd, input::InputArgs, randr::RandrArgs,
|
||||
reexec::ReexecArgs, tree::TreeArgs, xwayland::XwaylandArgs,
|
||||
reexec::ReexecArgs, run_tagged::RunTaggedArgs, tree::TreeArgs, xwayland::XwaylandArgs,
|
||||
},
|
||||
compositor::start_compositor,
|
||||
format::{Format, ref_formats},
|
||||
|
|
@ -72,6 +73,8 @@ pub enum Cmd {
|
|||
Idle(IdleArgs),
|
||||
/// Run a privileged program.
|
||||
RunPrivileged(RunPrivilegedArgs),
|
||||
/// Run a program with a connection tag.
|
||||
RunTagged(RunTaggedArgs),
|
||||
/// Tests the events produced by a seat.
|
||||
SeatTest(SeatTestArgs),
|
||||
/// Run the desktop portal.
|
||||
|
|
@ -245,6 +248,7 @@ pub fn main() {
|
|||
Cmd::Idle(a) => idle::main(cli.global, a),
|
||||
Cmd::Unlock => unlock::main(cli.global),
|
||||
Cmd::RunPrivileged(a) => run_privileged::main(cli.global, a),
|
||||
Cmd::RunTagged(a) => run_tagged::main(cli.global, a),
|
||||
Cmd::SeatTest(a) => seat_test::main(cli.global, a),
|
||||
Cmd::Portal => portal::run_freestanding(cli.global),
|
||||
Cmd::Randr(a) => randr::main(cli.global, a),
|
||||
|
|
|
|||
74
src/cli/run_tagged.rs
Normal file
74
src/cli/run_tagged.rs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
use {
|
||||
crate::{
|
||||
cli::GlobalArgs,
|
||||
compositor::WAYLAND_DISPLAY,
|
||||
tools::tool_client::{Handle, ToolClient, with_tool_client},
|
||||
utils::{errorfmt::ErrorFmt, oserror::OsError},
|
||||
wire::{jay_acceptor_request, jay_compositor},
|
||||
},
|
||||
clap::{Args, ValueHint},
|
||||
std::{cell::Cell, env, rc::Rc},
|
||||
uapi::UstrPtr,
|
||||
};
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct RunTaggedArgs {
|
||||
/// Specifies a tag to apply to all spawned wayland connections.
|
||||
tag: String,
|
||||
/// The program to run.
|
||||
#[clap(required = true, trailing_var_arg = true, value_hint = ValueHint::CommandWithArguments)]
|
||||
pub program: Vec<String>,
|
||||
}
|
||||
|
||||
pub fn main(global: GlobalArgs, run_tagged_args: RunTaggedArgs) {
|
||||
with_tool_client(global.log_level.into(), |tc| async move {
|
||||
let run_tagged = Rc::new(RunTagged { tc: tc.clone() });
|
||||
run_tagged.run(run_tagged_args).await;
|
||||
});
|
||||
}
|
||||
|
||||
struct RunTagged {
|
||||
tc: Rc<ToolClient>,
|
||||
}
|
||||
|
||||
impl RunTagged {
|
||||
async fn run(&self, args: RunTaggedArgs) {
|
||||
let tc = &self.tc;
|
||||
let comp = tc.jay_compositor().await;
|
||||
let req = tc.id();
|
||||
tc.send(jay_compositor::GetTaggedAcceptor {
|
||||
self_id: comp,
|
||||
id: req,
|
||||
tag: &args.tag,
|
||||
});
|
||||
let res = Rc::new(Cell::new(None));
|
||||
jay_acceptor_request::Done::handle(&tc, req, res.clone(), |res, ev| {
|
||||
res.set(Some(Ok(ev.name.to_owned())));
|
||||
});
|
||||
jay_acceptor_request::Failed::handle(&tc, req, res.clone(), |res, ev| {
|
||||
res.set(Some(Err(ev.msg.to_owned())));
|
||||
});
|
||||
tc.round_trip().await;
|
||||
match res.take().unwrap() {
|
||||
Ok(n) => {
|
||||
unsafe {
|
||||
env::set_var(WAYLAND_DISPLAY, &n);
|
||||
}
|
||||
let mut argv = UstrPtr::new();
|
||||
for arg in &args.program {
|
||||
argv.push(arg.as_str());
|
||||
}
|
||||
let program = args.program[0].as_str();
|
||||
let res = uapi::execvp(program, &argv).unwrap_err();
|
||||
fatal!(
|
||||
"Could not execute `{}`: {}",
|
||||
program,
|
||||
ErrorFmt(OsError::from(res)),
|
||||
);
|
||||
}
|
||||
Err(msg) => {
|
||||
fatal!("Could not create acceptor: {}", msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ pub mod ext_session_lock_manager_v1;
|
|||
pub mod ext_session_lock_v1;
|
||||
pub mod head_management;
|
||||
pub mod ipc;
|
||||
pub mod jay_acceptor_request;
|
||||
pub mod jay_client_query;
|
||||
pub mod jay_color_management;
|
||||
pub mod jay_compositor;
|
||||
|
|
|
|||
60
src/ifs/jay_acceptor_request.rs
Normal file
60
src/ifs/jay_acceptor_request.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
use {
|
||||
crate::{
|
||||
client::{Client, ClientError},
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
utils::errorfmt::ErrorFmt,
|
||||
wire::{JayAcceptorRequestId, jay_acceptor_request::*},
|
||||
},
|
||||
std::{error::Error, rc::Rc},
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct JayAcceptorRequest {
|
||||
pub id: JayAcceptorRequestId,
|
||||
pub client: Rc<Client>,
|
||||
pub tracker: Tracker<Self>,
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
impl JayAcceptorRequest {
|
||||
pub fn send_done(&self, name: &str) {
|
||||
self.client.event(Done {
|
||||
self_id: self.id,
|
||||
name,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn send_failed(&self, err: impl Error) {
|
||||
let msg = &ErrorFmt(err).to_string();
|
||||
self.client.event(Failed {
|
||||
self_id: self.id,
|
||||
msg,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl JayAcceptorRequestRequestHandler for JayAcceptorRequest {
|
||||
type Error = JayAcceptorRequestError;
|
||||
|
||||
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
self = JayAcceptorRequest;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl Object for JayAcceptorRequest {}
|
||||
|
||||
simple_add_obj!(JayAcceptorRequest);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum JayAcceptorRequestError {
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(JayAcceptorRequestError, ClientError);
|
||||
|
|
@ -4,6 +4,7 @@ use {
|
|||
client::{CAP_JAY_COMPOSITOR, Client, ClientCaps, ClientError, ClientId},
|
||||
globals::{Global, GlobalName},
|
||||
ifs::{
|
||||
jay_acceptor_request::JayAcceptorRequest,
|
||||
jay_client_query::JayClientQuery,
|
||||
jay_color_management::JayColorManagement,
|
||||
jay_ei_session_builder::JayEiSessionBuilder,
|
||||
|
|
@ -515,6 +516,27 @@ impl JayCompositorRequestHandler for JayCompositor {
|
|||
self.client.add_client_obj(&obj)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_tagged_acceptor(
|
||||
&self,
|
||||
req: GetTaggedAcceptor<'_>,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
let obj = Rc::new(JayAcceptorRequest {
|
||||
id: req.id,
|
||||
client: self.client.clone(),
|
||||
tracker: Default::default(),
|
||||
version: self.version,
|
||||
});
|
||||
track!(self.client, obj);
|
||||
self.client.add_client_obj(&obj)?;
|
||||
let state = &self.client.state;
|
||||
match state.tagged_acceptors.get(state, req.tag) {
|
||||
Ok(d) => obj.send_done(&d),
|
||||
Err(e) => obj.send_failed(e),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
|
|
|
|||
9
wire/jay_acceptor_request.txt
Normal file
9
wire/jay_acceptor_request.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
request destroy { }
|
||||
|
||||
event done {
|
||||
name: str,
|
||||
}
|
||||
|
||||
event failed {
|
||||
msg: str,
|
||||
}
|
||||
|
|
@ -121,6 +121,11 @@ request create_tree_query (since = 18) {
|
|||
id: id(jay_tree_query),
|
||||
}
|
||||
|
||||
request get_tagged_acceptor (since = 25) {
|
||||
id: id(jay_acceptor_request),
|
||||
tag: str,
|
||||
}
|
||||
|
||||
# events
|
||||
|
||||
event client_id {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue