config: add Client
This commit is contained in:
parent
52994c085a
commit
ab095b89cf
6 changed files with 133 additions and 11 deletions
|
|
@ -10,6 +10,7 @@ use {
|
|||
logging,
|
||||
},
|
||||
Axis, Direction, ModifiedKeySym, PciId, Workspace,
|
||||
client::Client,
|
||||
exec::Command,
|
||||
input::{
|
||||
FocusFollowsMouseMode, InputDevice, Seat, SwitchEvent, acceleration::AccelProfile,
|
||||
|
|
@ -81,7 +82,7 @@ struct KeyHandler {
|
|||
latched: Vec<Box<dyn FnOnce()>>,
|
||||
}
|
||||
|
||||
pub(crate) struct Client {
|
||||
pub(crate) struct ConfigClient {
|
||||
configure: extern "C" fn(),
|
||||
srv_data: *const u8,
|
||||
srv_unref: unsafe extern "C" fn(data: *const u8),
|
||||
|
|
@ -145,7 +146,7 @@ struct Task {
|
|||
waker: Waker,
|
||||
}
|
||||
|
||||
impl Drop for Client {
|
||||
impl Drop for ConfigClient {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
(self.srv_unref)(self.srv_data);
|
||||
|
|
@ -154,13 +155,13 @@ impl Drop for Client {
|
|||
}
|
||||
|
||||
thread_local! {
|
||||
pub(crate) static CLIENT: Cell<*const Client> = const { Cell::new(ptr::null()) };
|
||||
pub(crate) static CLIENT: Cell<*const ConfigClient> = const { Cell::new(ptr::null()) };
|
||||
}
|
||||
|
||||
unsafe fn with_client<T, F: FnOnce(&Client) -> T>(data: *const u8, f: F) -> T {
|
||||
unsafe fn with_client<T, F: FnOnce(&ConfigClient) -> T>(data: *const u8, f: F) -> T {
|
||||
struct Reset<'a> {
|
||||
cell: &'a Cell<*const Client>,
|
||||
val: *const Client,
|
||||
cell: &'a Cell<*const ConfigClient>,
|
||||
val: *const ConfigClient,
|
||||
}
|
||||
impl Drop for Reset<'_> {
|
||||
fn drop(&mut self) {
|
||||
|
|
@ -168,7 +169,7 @@ unsafe fn with_client<T, F: FnOnce(&Client) -> T>(data: *const u8, f: F) -> T {
|
|||
}
|
||||
}
|
||||
CLIENT.with(|cell| unsafe {
|
||||
let client = data as *const Client;
|
||||
let client = data as *const ConfigClient;
|
||||
Rc::increment_strong_count(client);
|
||||
let client = Rc::from_raw(client);
|
||||
let old = cell.replace(client.deref());
|
||||
|
|
@ -214,7 +215,7 @@ pub unsafe extern "C" fn init(
|
|||
size: usize,
|
||||
f: extern "C" fn(),
|
||||
) -> *const u8 {
|
||||
let client = Rc::new(Client {
|
||||
let client = Rc::new(ConfigClient {
|
||||
configure: f,
|
||||
srv_data,
|
||||
srv_unref,
|
||||
|
|
@ -251,7 +252,7 @@ pub unsafe extern "C" fn init(
|
|||
}
|
||||
|
||||
pub unsafe extern "C" fn unref(data: *const u8) {
|
||||
let client = data as *const Client;
|
||||
let client = data as *const ConfigClient;
|
||||
unsafe {
|
||||
drop(Rc::from_raw(client));
|
||||
}
|
||||
|
|
@ -278,7 +279,7 @@ macro_rules! get_response {
|
|||
}
|
||||
}
|
||||
|
||||
impl Client {
|
||||
impl ConfigClient {
|
||||
fn send(&self, msg: &ClientMessage) {
|
||||
let mut buf = self.bufs.borrow_mut().pop().unwrap_or_default();
|
||||
buf.clear();
|
||||
|
|
@ -1259,6 +1260,28 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn clients(&self) -> Vec<Client> {
|
||||
let res = self.send_with_response(&ClientMessage::GetClients);
|
||||
get_response!(res, vec!(), GetClients { clients });
|
||||
clients
|
||||
}
|
||||
|
||||
pub fn client_exists(&self, client: Client) -> bool {
|
||||
let res = self.send_with_response(&ClientMessage::ClientExists { client });
|
||||
get_response!(res, false, ClientExists { exists });
|
||||
exists
|
||||
}
|
||||
|
||||
pub fn client_is_xwayland(&self, client: Client) -> bool {
|
||||
let res = self.send_with_response(&ClientMessage::ClientIsXwayland { client });
|
||||
get_response!(res, false, ClientIsXwayland { is_xwayland });
|
||||
is_xwayland
|
||||
}
|
||||
|
||||
pub fn client_kill(&self, client: Client) {
|
||||
self.send(&ClientMessage::ClientKill { client });
|
||||
}
|
||||
|
||||
fn handle_msg(&self, msg: &[u8]) {
|
||||
self.handle_msg2(msg);
|
||||
self.dispatch_futures();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use {
|
|||
crate::{
|
||||
_private::{PollableId, WireMode},
|
||||
Axis, Direction, PciId, Workspace,
|
||||
client::Client,
|
||||
input::{
|
||||
FocusFollowsMouseMode, InputDevice, Seat, SwitchEvent, acceleration::AccelProfile,
|
||||
capability::Capability,
|
||||
|
|
@ -565,6 +566,16 @@ pub enum ClientMessage<'a> {
|
|||
GetConnectorWorkspaces {
|
||||
connector: Connector,
|
||||
},
|
||||
GetClients,
|
||||
ClientExists {
|
||||
client: Client,
|
||||
},
|
||||
ClientKill {
|
||||
client: Client,
|
||||
},
|
||||
ClientIsXwayland {
|
||||
client: Client,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
|
@ -728,6 +739,15 @@ pub enum Response {
|
|||
GetConnectorWorkspaces {
|
||||
workspaces: Vec<Workspace>,
|
||||
},
|
||||
GetClients {
|
||||
clients: Vec<Client>,
|
||||
},
|
||||
ClientExists {
|
||||
exists: bool,
|
||||
},
|
||||
ClientIsXwayland {
|
||||
is_xwayland: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
|
|
|||
36
jay-config/src/client.rs
Normal file
36
jay-config/src/client.rs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
//! Tools for inspecting and manipulating clients.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A client connected to the compositor.
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct Client(pub u64);
|
||||
|
||||
impl Client {
|
||||
/// Returns whether the client exists.
|
||||
pub fn exists(self) -> bool {
|
||||
self.0 != 0 && get!(false).client_exists(self)
|
||||
}
|
||||
|
||||
/// Returns whether the client does not exist.
|
||||
///
|
||||
/// This is a shorthand for `!self.exists()`.
|
||||
pub fn does_not_exist(self) -> bool {
|
||||
!self.exists()
|
||||
}
|
||||
|
||||
/// Returns whether this client is XWayland.
|
||||
pub fn is_xwayland(self) -> bool {
|
||||
get!(false).client_is_xwayland(self)
|
||||
}
|
||||
|
||||
/// Disconnects the client.
|
||||
pub fn kill(self) {
|
||||
get!().client_kill(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns all current clients.
|
||||
pub fn clients() -> Vec<Client> {
|
||||
get!().clients()
|
||||
}
|
||||
|
|
@ -58,6 +58,7 @@ use {
|
|||
mod macros;
|
||||
#[doc(hidden)]
|
||||
pub mod _private;
|
||||
pub mod client;
|
||||
pub mod embedded;
|
||||
pub mod exec;
|
||||
pub mod input;
|
||||
|
|
|
|||
|
|
@ -106,7 +106,6 @@ impl Clients {
|
|||
ClientId(self.next_client_id.fetch_add(1))
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "it"), expect(dead_code))]
|
||||
pub fn get(&self, id: ClientId) -> Result<Rc<Client>, ClientError> {
|
||||
let clients = self.clients.borrow();
|
||||
match clients.get(&id) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use {
|
|||
self, BackendColorSpace, BackendTransferFunction, ConnectorId, DrmDeviceId,
|
||||
InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId,
|
||||
},
|
||||
client::{Client, ClientId},
|
||||
cmm::cmm_transfer_function::TransferFunction,
|
||||
compositor::MAX_EXTENTS,
|
||||
config::ConfigProxy,
|
||||
|
|
@ -38,6 +39,7 @@ use {
|
|||
ipc::{ClientMessage, Response, ServerMessage, WorkspaceSource},
|
||||
},
|
||||
Axis, Direction, Workspace,
|
||||
client::Client as ConfigClient,
|
||||
input::{
|
||||
FocusFollowsMouseMode, InputDevice, Seat,
|
||||
acceleration::{ACCEL_PROFILE_ADAPTIVE, ACCEL_PROFILE_FLAT, AccelProfile},
|
||||
|
|
@ -1717,6 +1719,39 @@ impl ConfigProxyHandler {
|
|||
self.keymaps.remove(&keymap);
|
||||
}
|
||||
|
||||
fn get_client(&self, client: ConfigClient) -> Result<Rc<Client>, CphError> {
|
||||
self.state
|
||||
.clients
|
||||
.get(ClientId::from_raw(client.0))
|
||||
.ok()
|
||||
.ok_or(CphError::ClientDoesNotExist(client))
|
||||
}
|
||||
|
||||
fn handle_get_clients(&self) {
|
||||
let mut clients = vec![];
|
||||
for client in self.state.clients.clients.borrow().values() {
|
||||
clients.push(ConfigClient(client.data.id.raw()));
|
||||
}
|
||||
self.respond(Response::GetClients { clients });
|
||||
}
|
||||
|
||||
fn handle_client_exists(&self, client: ConfigClient) {
|
||||
self.respond(Response::ClientExists {
|
||||
exists: self.get_client(client).is_ok(),
|
||||
});
|
||||
}
|
||||
|
||||
fn handle_client_is_xwayland(&self, client: ConfigClient) -> Result<(), CphError> {
|
||||
self.respond(Response::ClientIsXwayland {
|
||||
is_xwayland: self.get_client(client)?.is_xwayland,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_client_kill(&self, client: ConfigClient) {
|
||||
self.state.clients.kill(ClientId::from_raw(client.0));
|
||||
}
|
||||
|
||||
pub fn handle_request(self: &Rc<Self>, msg: &[u8]) {
|
||||
if let Err(e) = self.handle_request_(msg) {
|
||||
log::error!("Could not handle client request: {}", ErrorFmt(e));
|
||||
|
|
@ -2130,6 +2165,12 @@ impl ConfigProxyHandler {
|
|||
ClientMessage::GetConnectorWorkspaces { connector } => self
|
||||
.handle_get_connector_workspaces(connector)
|
||||
.wrn("get_connector_workspaces")?,
|
||||
ClientMessage::GetClients => self.handle_get_clients(),
|
||||
ClientMessage::ClientExists { client } => self.handle_client_exists(client),
|
||||
ClientMessage::ClientIsXwayland { client } => self
|
||||
.handle_client_is_xwayland(client)
|
||||
.wrn("client_is_xwayland")?,
|
||||
ClientMessage::ClientKill { client } => self.handle_client_kill(client),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -2205,6 +2246,8 @@ enum CphError {
|
|||
UnknownColorSpace(ColorSpace),
|
||||
#[error("Unknown transfer function {0:?}")]
|
||||
UnknownTransferFunction(ConfigTransferFunction),
|
||||
#[error("Client {0:?} does not exist")]
|
||||
ClientDoesNotExist(ConfigClient),
|
||||
}
|
||||
|
||||
trait WithRequestName {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue