ei: add support for libei
This commit is contained in:
parent
084fe50259
commit
40e87f8f91
69 changed files with 4340 additions and 72 deletions
160
src/ei/ei_ifs/ei_connection.rs
Normal file
160
src/ei/ei_ifs/ei_connection.rs
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
use {
|
||||
crate::{
|
||||
ei::{
|
||||
ei_client::{EiClient, EiClientError},
|
||||
ei_ifs::{
|
||||
ei_callback::EiCallback,
|
||||
ei_seat::{
|
||||
EiSeat, EI_CAP_BUTTON, EI_CAP_KEYBOARD, EI_CAP_POINTER,
|
||||
EI_CAP_POINTER_ABSOLUTE, EI_CAP_SCROLL, EI_CAP_TOUCHSCREEN,
|
||||
},
|
||||
},
|
||||
ei_object::{EiObject, EiObjectId, EiVersion},
|
||||
EiContext,
|
||||
},
|
||||
ifs::wl_seat::WlSeatGlobal,
|
||||
leaks::Tracker,
|
||||
wire_ei::{
|
||||
ei_connection::{
|
||||
Disconnect, Disconnected, EiConnectionRequestHandler, InvalidObject, Seat,
|
||||
},
|
||||
EiButton, EiConnectionId, EiKeyboard, EiPointer, EiPointerAbsolute, EiScroll,
|
||||
EiTouchscreen,
|
||||
},
|
||||
},
|
||||
std::{cell::Cell, rc::Rc},
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct EiConnection {
|
||||
pub id: EiConnectionId,
|
||||
pub client: Rc<EiClient>,
|
||||
pub tracker: Tracker<Self>,
|
||||
pub version: EiVersion,
|
||||
}
|
||||
|
||||
impl EiConnection {
|
||||
pub fn send_invalid_object(&self, id: EiObjectId) {
|
||||
self.client.event(InvalidObject {
|
||||
self_id: self.id,
|
||||
last_serial: self.client.last_serial(),
|
||||
invalid_id: id,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn send_disconnected(&self, error: Option<&str>) {
|
||||
self.client.event(Disconnected {
|
||||
self_id: self.id,
|
||||
last_serial: self.client.last_serial(),
|
||||
reason: error.is_some() as _,
|
||||
explanation: error,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn send_seat(&self, seat: &EiSeat) {
|
||||
self.client.event(Seat {
|
||||
self_id: self.id,
|
||||
seat: seat.id,
|
||||
version: seat.version.0,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn announce_seat(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
let version = self.client.versions.ei_seat.version.get();
|
||||
if version == EiVersion(0) {
|
||||
return;
|
||||
}
|
||||
let xkb_state_id = match self.context() {
|
||||
EiContext::Sender => seat.seat_xkb_state().borrow().id,
|
||||
EiContext::Receiver => seat.latest_xkb_state().borrow().id,
|
||||
};
|
||||
let seat = Rc::new(EiSeat {
|
||||
id: self.client.new_id(),
|
||||
client: self.client.clone(),
|
||||
tracker: Default::default(),
|
||||
version,
|
||||
seat: seat.clone(),
|
||||
capabilities: Cell::new(0),
|
||||
kb_state_id: Cell::new(xkb_state_id),
|
||||
device: Default::default(),
|
||||
pointer: Default::default(),
|
||||
pointer_absolute: Default::default(),
|
||||
keyboard: Default::default(),
|
||||
button: Default::default(),
|
||||
scroll: Default::default(),
|
||||
touchscreen: Default::default(),
|
||||
});
|
||||
track!(self.client, seat);
|
||||
self.client.add_server_obj(&seat);
|
||||
self.send_seat(&seat);
|
||||
let v = &self.client.versions;
|
||||
let caps = [
|
||||
(EI_CAP_POINTER, EiPointer, &v.ei_pointer),
|
||||
(
|
||||
EI_CAP_POINTER_ABSOLUTE,
|
||||
EiPointerAbsolute,
|
||||
&v.ei_pointer_absolute,
|
||||
),
|
||||
(EI_CAP_SCROLL, EiScroll, &v.ei_scroll),
|
||||
(EI_CAP_BUTTON, EiButton, &v.ei_button),
|
||||
(EI_CAP_KEYBOARD, EiKeyboard, &v.ei_keyboard),
|
||||
(EI_CAP_TOUCHSCREEN, EiTouchscreen, &v.ei_touchscreen),
|
||||
];
|
||||
for (mask, interface, version) in caps {
|
||||
if version.version.get() > EiVersion(0) {
|
||||
seat.send_capability(interface, mask);
|
||||
}
|
||||
}
|
||||
seat.send_name(&seat.seat.seat_name());
|
||||
seat.send_done();
|
||||
seat.seat.add_ei_seat(&seat);
|
||||
}
|
||||
}
|
||||
|
||||
impl EiConnectionRequestHandler for EiConnection {
|
||||
type Error = EiConnectionError;
|
||||
|
||||
fn sync(
|
||||
&self,
|
||||
req: crate::wire_ei::ei_connection::Sync,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
let version = EiVersion(req.version);
|
||||
if version > self.client.versions.ei_callback.version.get() {
|
||||
return Err(EiConnectionError::CallbackVersion(req.version));
|
||||
}
|
||||
let cb = Rc::new(EiCallback {
|
||||
id: req.callback,
|
||||
client: self.client.clone(),
|
||||
tracker: Default::default(),
|
||||
version,
|
||||
});
|
||||
track!(self.client, cb);
|
||||
self.client.add_client_obj(&cb)?;
|
||||
cb.send_done(0);
|
||||
self.client.remove_obj(&*cb)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn disconnect(&self, _req: Disconnect, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.client.disconnect_announced.set(true);
|
||||
self.client.state.ei_clients.shutdown(self.client.id);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
ei_object_base! {
|
||||
self = EiConnection;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl EiObject for EiConnection {}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum EiConnectionError {
|
||||
#[error(transparent)]
|
||||
EiClientError(Box<EiClientError>),
|
||||
#[error("The callback version is too large: {0}")]
|
||||
CallbackVersion(u32),
|
||||
}
|
||||
efrom!(EiConnectionError, EiClientError);
|
||||
Loading…
Add table
Add a link
Reference in a new issue