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 randr;
|
||||||
mod reexec;
|
mod reexec;
|
||||||
mod run_privileged;
|
mod run_privileged;
|
||||||
|
mod run_tagged;
|
||||||
pub mod screenshot;
|
pub mod screenshot;
|
||||||
mod seat_test;
|
mod seat_test;
|
||||||
mod set_log_level;
|
mod set_log_level;
|
||||||
|
|
@ -24,7 +25,7 @@ use {
|
||||||
cli::{
|
cli::{
|
||||||
clients::ClientsArgs, color_management::ColorManagementArgs,
|
clients::ClientsArgs, color_management::ColorManagementArgs,
|
||||||
damage_tracking::DamageTrackingArgs, idle::IdleCmd, input::InputArgs, randr::RandrArgs,
|
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,
|
compositor::start_compositor,
|
||||||
format::{Format, ref_formats},
|
format::{Format, ref_formats},
|
||||||
|
|
@ -72,6 +73,8 @@ pub enum Cmd {
|
||||||
Idle(IdleArgs),
|
Idle(IdleArgs),
|
||||||
/// Run a privileged program.
|
/// Run a privileged program.
|
||||||
RunPrivileged(RunPrivilegedArgs),
|
RunPrivileged(RunPrivilegedArgs),
|
||||||
|
/// Run a program with a connection tag.
|
||||||
|
RunTagged(RunTaggedArgs),
|
||||||
/// Tests the events produced by a seat.
|
/// Tests the events produced by a seat.
|
||||||
SeatTest(SeatTestArgs),
|
SeatTest(SeatTestArgs),
|
||||||
/// Run the desktop portal.
|
/// Run the desktop portal.
|
||||||
|
|
@ -245,6 +248,7 @@ pub fn main() {
|
||||||
Cmd::Idle(a) => idle::main(cli.global, a),
|
Cmd::Idle(a) => idle::main(cli.global, a),
|
||||||
Cmd::Unlock => unlock::main(cli.global),
|
Cmd::Unlock => unlock::main(cli.global),
|
||||||
Cmd::RunPrivileged(a) => run_privileged::main(cli.global, a),
|
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::SeatTest(a) => seat_test::main(cli.global, a),
|
||||||
Cmd::Portal => portal::run_freestanding(cli.global),
|
Cmd::Portal => portal::run_freestanding(cli.global),
|
||||||
Cmd::Randr(a) => randr::main(cli.global, a),
|
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 ext_session_lock_v1;
|
||||||
pub mod head_management;
|
pub mod head_management;
|
||||||
pub mod ipc;
|
pub mod ipc;
|
||||||
|
pub mod jay_acceptor_request;
|
||||||
pub mod jay_client_query;
|
pub mod jay_client_query;
|
||||||
pub mod jay_color_management;
|
pub mod jay_color_management;
|
||||||
pub mod jay_compositor;
|
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},
|
client::{CAP_JAY_COMPOSITOR, Client, ClientCaps, ClientError, ClientId},
|
||||||
globals::{Global, GlobalName},
|
globals::{Global, GlobalName},
|
||||||
ifs::{
|
ifs::{
|
||||||
|
jay_acceptor_request::JayAcceptorRequest,
|
||||||
jay_client_query::JayClientQuery,
|
jay_client_query::JayClientQuery,
|
||||||
jay_color_management::JayColorManagement,
|
jay_color_management::JayColorManagement,
|
||||||
jay_ei_session_builder::JayEiSessionBuilder,
|
jay_ei_session_builder::JayEiSessionBuilder,
|
||||||
|
|
@ -515,6 +516,27 @@ impl JayCompositorRequestHandler for JayCompositor {
|
||||||
self.client.add_client_obj(&obj)?;
|
self.client.add_client_obj(&obj)?;
|
||||||
Ok(())
|
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! {
|
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),
|
id: id(jay_tree_query),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
request get_tagged_acceptor (since = 25) {
|
||||||
|
id: id(jay_acceptor_request),
|
||||||
|
tag: str,
|
||||||
|
}
|
||||||
|
|
||||||
# events
|
# events
|
||||||
|
|
||||||
event client_id {
|
event client_id {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue