cli: add commands to inspect clients
This commit is contained in:
parent
5e3465d861
commit
bd04b09171
12 changed files with 557 additions and 16 deletions
141
src/ifs/jay_client_query.rs
Normal file
141
src/ifs/jay_client_query.rs
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
use {
|
||||
crate::{
|
||||
client::{Client, ClientError, ClientId},
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
utils::copyhashmap::CopyHashMap,
|
||||
wire::{
|
||||
JayClientQueryId,
|
||||
jay_client_query::{
|
||||
AddAll, AddId, Comm, Destroy, Done, End, Exe, Execute, IsXwayland,
|
||||
JayClientQueryRequestHandler, Pid, SandboxAppId, SandboxEngine, SandboxInstanceId,
|
||||
Sandboxed, Start, Uid,
|
||||
},
|
||||
},
|
||||
},
|
||||
std::{cell::Cell, rc::Rc},
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct JayClientQuery {
|
||||
pub id: JayClientQueryId,
|
||||
pub client: Rc<Client>,
|
||||
pub tracker: Tracker<Self>,
|
||||
pub version: Version,
|
||||
ids: CopyHashMap<ClientId, ()>,
|
||||
all: Cell<bool>,
|
||||
}
|
||||
|
||||
impl JayClientQuery {
|
||||
pub fn new(client: &Rc<Client>, id: JayClientQueryId, version: Version) -> Self {
|
||||
Self {
|
||||
id,
|
||||
client: client.clone(),
|
||||
tracker: Default::default(),
|
||||
version,
|
||||
ids: Default::default(),
|
||||
all: Cell::new(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl JayClientQueryRequestHandler for JayClientQuery {
|
||||
type Error = JayClientQueryError;
|
||||
|
||||
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute(&self, _req: Execute, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let handle_client = |client: &Rc<Client>| {
|
||||
self.client.event(Start {
|
||||
self_id: self.id,
|
||||
id: client.id.raw(),
|
||||
});
|
||||
if !client.is_xwayland {
|
||||
self.client.event(Uid {
|
||||
self_id: self.id,
|
||||
uid: client.pid_info.uid,
|
||||
});
|
||||
self.client.event(Pid {
|
||||
self_id: self.id,
|
||||
pid: client.pid_info.pid,
|
||||
});
|
||||
self.client.event(Comm {
|
||||
self_id: self.id,
|
||||
comm: &client.pid_info.comm,
|
||||
});
|
||||
self.client.event(Exe {
|
||||
self_id: self.id,
|
||||
exe: &client.pid_info.exe,
|
||||
});
|
||||
}
|
||||
if client.acceptor.sandboxed {
|
||||
self.client.event(Sandboxed { self_id: self.id });
|
||||
}
|
||||
if client.is_xwayland {
|
||||
self.client.event(IsXwayland { self_id: self.id });
|
||||
}
|
||||
if let Some(engine) = &client.acceptor.sandbox_engine {
|
||||
self.client.event(SandboxEngine {
|
||||
self_id: self.id,
|
||||
engine,
|
||||
});
|
||||
}
|
||||
if let Some(app_id) = &client.acceptor.app_id {
|
||||
self.client.event(SandboxAppId {
|
||||
self_id: self.id,
|
||||
app_id,
|
||||
});
|
||||
}
|
||||
if let Some(instance_id) = &client.acceptor.instance_id {
|
||||
self.client.event(SandboxInstanceId {
|
||||
self_id: self.id,
|
||||
instance_id,
|
||||
});
|
||||
}
|
||||
self.client.event(End { self_id: self.id });
|
||||
};
|
||||
if self.all.get() {
|
||||
for client in self.client.state.clients.clients.borrow().values() {
|
||||
handle_client(&client.data);
|
||||
}
|
||||
} else {
|
||||
for &id in self.ids.lock().keys() {
|
||||
let Ok(client) = self.client.state.clients.get(id) else {
|
||||
continue;
|
||||
};
|
||||
handle_client(&client);
|
||||
}
|
||||
}
|
||||
self.client.event(Done { self_id: self.id });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_all(&self, _req: AddAll, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.all.set(true);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_id(&self, req: AddId, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.ids.set(ClientId::from_raw(req.id), ());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
self = JayClientQuery;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl Object for JayClientQuery {}
|
||||
|
||||
simple_add_obj!(JayClientQuery);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum JayClientQueryError {
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(JayClientQueryError, ClientError);
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
use {
|
||||
crate::{
|
||||
cli::CliLogLevel,
|
||||
client::{CAP_JAY_COMPOSITOR, Client, ClientCaps, ClientError},
|
||||
client::{CAP_JAY_COMPOSITOR, Client, ClientCaps, ClientError, ClientId},
|
||||
globals::{Global, GlobalName},
|
||||
ifs::{
|
||||
jay_client_query::JayClientQuery,
|
||||
jay_color_management::JayColorManagement,
|
||||
jay_ei_session_builder::JayEiSessionBuilder,
|
||||
jay_idle::JayIdle,
|
||||
|
|
@ -26,7 +27,10 @@ use {
|
|||
object::{Object, Version},
|
||||
screenshoter::take_screenshot,
|
||||
utils::{errorfmt::ErrorFmt, toplevel_identifier::ToplevelIdentifier},
|
||||
wire::{JayCompositorId, JayScreenshotId, jay_compositor::*},
|
||||
wire::{
|
||||
JayCompositorId, JayScreenshotId,
|
||||
jay_compositor::{self, *},
|
||||
},
|
||||
},
|
||||
bstr::ByteSlice,
|
||||
log::Level,
|
||||
|
|
@ -74,7 +78,7 @@ impl Global for JayCompositorGlobal {
|
|||
}
|
||||
|
||||
fn version(&self) -> u32 {
|
||||
17
|
||||
18
|
||||
}
|
||||
|
||||
fn required_caps(&self) -> ClientCaps {
|
||||
|
|
@ -223,7 +227,7 @@ impl JayCompositorRequestHandler for JayCompositor {
|
|||
}
|
||||
|
||||
fn get_client_id(&self, _req: GetClientId, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.client.event(ClientId {
|
||||
self.client.event(jay_compositor::ClientId {
|
||||
self_id: self.id,
|
||||
client_id: self.client.id.raw(),
|
||||
});
|
||||
|
|
@ -367,7 +371,6 @@ impl JayCompositorRequestHandler for JayCompositor {
|
|||
}
|
||||
|
||||
fn select_toplevel(&self, req: SelectToplevel, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let seat = self.client.lookup(req.seat)?;
|
||||
let obj = JaySelectToplevel::new(&self.client, req.id, self.version);
|
||||
track!(self.client, obj);
|
||||
self.client.add_client_obj(&obj)?;
|
||||
|
|
@ -375,12 +378,22 @@ impl JayCompositorRequestHandler for JayCompositor {
|
|||
tl: Default::default(),
|
||||
jst: obj.clone(),
|
||||
};
|
||||
seat.global.select_toplevel(selector);
|
||||
let seat = if req.seat.is_none() {
|
||||
match self.client.state.seat_queue.last() {
|
||||
Some(s) => s.deref().clone(),
|
||||
None => {
|
||||
obj.done(None);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.client.lookup(req.seat)?.global.clone()
|
||||
};
|
||||
seat.select_toplevel(selector);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn select_workspace(&self, req: SelectWorkspace, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let seat = self.client.lookup(req.seat)?;
|
||||
let obj = Rc::new(JaySelectWorkspace {
|
||||
id: req.id,
|
||||
client: self.client.clone(),
|
||||
|
|
@ -393,7 +406,15 @@ impl JayCompositorRequestHandler for JayCompositor {
|
|||
ws: Default::default(),
|
||||
jsw: obj.clone(),
|
||||
};
|
||||
seat.global.select_workspace(selector);
|
||||
let seat = if req.seat.is_none() {
|
||||
match self.client.state.seat_queue.last() {
|
||||
Some(s) => s.deref().clone(),
|
||||
None => return Ok(()),
|
||||
}
|
||||
} else {
|
||||
self.client.lookup(req.seat)?.global.clone()
|
||||
};
|
||||
seat.select_workspace(selector);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -470,6 +491,22 @@ impl JayCompositorRequestHandler for JayCompositor {
|
|||
self.client.add_client_obj(&obj)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_client_query(
|
||||
&self,
|
||||
req: CreateClientQuery,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
let obj = Rc::new(JayClientQuery::new(&self.client, req.id, self.version));
|
||||
track!(self.client, obj);
|
||||
self.client.add_client_obj(&obj)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn kill_client(&self, req: KillClient, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.client.state.clients.kill(ClientId::from_raw(req.id));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use {
|
|||
crate::{
|
||||
client::{Client, ClientError},
|
||||
ifs::{
|
||||
jay_toplevel::{ID_SINCE, JayToplevel},
|
||||
jay_toplevel::{CLIENT_ID_SINCE, ID_SINCE, JayToplevel},
|
||||
wl_seat::ToplevelSelector,
|
||||
},
|
||||
leaks::Tracker,
|
||||
|
|
@ -78,6 +78,9 @@ impl JaySelectToplevel {
|
|||
self.send_done(jtl.id);
|
||||
if jtl.version >= ID_SINCE {
|
||||
jtl.send_id();
|
||||
if jtl.version >= CLIENT_ID_SINCE {
|
||||
jtl.send_client_id();
|
||||
}
|
||||
jtl.send_done();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use {
|
|||
};
|
||||
|
||||
pub const ID_SINCE: Version = Version(12);
|
||||
pub const CLIENT_ID_SINCE: Version = Version(18);
|
||||
|
||||
pub struct JayToplevel {
|
||||
pub id: JayToplevelId,
|
||||
|
|
@ -47,6 +48,15 @@ impl JayToplevel {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn send_client_id(&self) {
|
||||
if let Some(cl) = &self.toplevel.tl_data().client {
|
||||
self.client.event(ClientId {
|
||||
self_id: self.id,
|
||||
id: cl.id.raw(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_done(&self) {
|
||||
self.client.event(Done { self_id: self.id })
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue