ipc: implement ext-data-control
This commit is contained in:
parent
be1462d0ef
commit
4abbe94995
13 changed files with 575 additions and 3 deletions
|
|
@ -3,6 +3,10 @@ use {
|
|||
std::rc::Rc,
|
||||
};
|
||||
|
||||
pub mod ext_data_control_device_v1;
|
||||
pub mod ext_data_control_manager_v1;
|
||||
pub mod ext_data_control_offer_v1;
|
||||
pub mod ext_data_control_source_v1;
|
||||
mod private;
|
||||
pub mod zwlr_data_control_device_v1;
|
||||
pub mod zwlr_data_control_manager_v1;
|
||||
|
|
|
|||
158
src/ifs/ipc/data_control/ext_data_control_device_v1.rs
Normal file
158
src/ifs/ipc/data_control/ext_data_control_device_v1.rs
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
use {
|
||||
crate::{
|
||||
client::Client,
|
||||
ifs::{
|
||||
ipc::data_control::{
|
||||
ext_data_control_offer_v1::ExtDataControlOfferV1,
|
||||
ext_data_control_source_v1::ExtDataControlSourceV1,
|
||||
private::{
|
||||
logic::{self, DataControlError},
|
||||
DataControlDevice, DataControlDeviceData, DataControlIpc, DataControlOfferData,
|
||||
},
|
||||
},
|
||||
wl_seat::WlSeatGlobal,
|
||||
},
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
wire::{
|
||||
ext_data_control_device_v1::*, ExtDataControlDeviceV1Id, ExtDataControlOfferV1Id,
|
||||
ExtDataControlSourceV1Id,
|
||||
},
|
||||
},
|
||||
std::rc::Rc,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct ExtDataControlDeviceV1 {
|
||||
pub id: ExtDataControlDeviceV1Id,
|
||||
pub data: DataControlDeviceData<ExtDataControlIpc>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl ExtDataControlDeviceV1 {
|
||||
pub fn new(
|
||||
id: ExtDataControlDeviceV1Id,
|
||||
client: &Rc<Client>,
|
||||
version: Version,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
) -> Self {
|
||||
Self {
|
||||
id,
|
||||
data: DataControlDeviceData {
|
||||
data_control_device_id: client.state.data_control_device_ids.next(),
|
||||
client: client.clone(),
|
||||
version,
|
||||
seat: seat.clone(),
|
||||
clipboard_data: Default::default(),
|
||||
primary_selection_data: Default::default(),
|
||||
},
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_data_offer(&self, offer: &Rc<ExtDataControlOfferV1>) {
|
||||
self.data.client.event(DataOffer {
|
||||
self_id: self.id,
|
||||
id: offer.id,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn send_selection(&self, offer: Option<&Rc<ExtDataControlOfferV1>>) {
|
||||
let id = offer.map(|o| o.id).unwrap_or(ExtDataControlOfferV1Id::NONE);
|
||||
self.data.client.event(Selection {
|
||||
self_id: self.id,
|
||||
id,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn send_primary_selection(&self, offer: Option<&Rc<ExtDataControlOfferV1>>) {
|
||||
let id = offer.map(|o| o.id).unwrap_or(ExtDataControlOfferV1Id::NONE);
|
||||
self.data.client.event(PrimarySelection {
|
||||
self_id: self.id,
|
||||
id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtDataControlDeviceV1RequestHandler for ExtDataControlDeviceV1 {
|
||||
type Error = ExtDataControlDeviceV1Error;
|
||||
|
||||
fn set_selection(&self, req: SetSelection, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
logic::device_set_selection(self, req.source.is_some().then_some(req.source))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
logic::device_destroy(self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_primary_selection(
|
||||
&self,
|
||||
req: SetPrimarySelection,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
logic::device_set_primary_selection(self, req.source.is_some().then_some(req.source))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ExtDataControlIpc;
|
||||
|
||||
impl DataControlIpc for ExtDataControlIpc {
|
||||
const PRIMARY_SELECTION_SINCE: Version = Version(1);
|
||||
type Device = ExtDataControlDeviceV1;
|
||||
type OfferId = ExtDataControlOfferV1Id;
|
||||
type Offer = ExtDataControlOfferV1;
|
||||
type SourceId = ExtDataControlSourceV1Id;
|
||||
type Source = ExtDataControlSourceV1;
|
||||
|
||||
fn create_offer(id: Self::OfferId, data: DataControlOfferData<Self>) -> Rc<Self::Offer> {
|
||||
let rc = Rc::new(ExtDataControlOfferV1 {
|
||||
id,
|
||||
data,
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(rc.data.client, rc);
|
||||
rc
|
||||
}
|
||||
}
|
||||
|
||||
impl DataControlDevice for ExtDataControlDeviceV1 {
|
||||
type Ipc = ExtDataControlIpc;
|
||||
|
||||
fn data(&self) -> &DataControlDeviceData<Self::Ipc> {
|
||||
&self.data
|
||||
}
|
||||
|
||||
fn send_data_offer(&self, offer: &Rc<<Self::Ipc as DataControlIpc>::Offer>) {
|
||||
self.send_data_offer(offer)
|
||||
}
|
||||
|
||||
fn send_selection(&self, offer: Option<&Rc<<Self::Ipc as DataControlIpc>::Offer>>) {
|
||||
self.send_selection(offer)
|
||||
}
|
||||
|
||||
fn send_primary_selection(&self, offer: Option<&Rc<<Self::Ipc as DataControlIpc>::Offer>>) {
|
||||
self.send_primary_selection(offer)
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
self = ExtDataControlDeviceV1;
|
||||
version = self.data.version;
|
||||
}
|
||||
|
||||
impl Object for ExtDataControlDeviceV1 {
|
||||
fn break_loops(&self) {
|
||||
logic::data_device_break_loops(self);
|
||||
}
|
||||
}
|
||||
|
||||
simple_add_obj!(ExtDataControlDeviceV1);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ExtDataControlDeviceV1Error {
|
||||
#[error(transparent)]
|
||||
DataControlError(#[from] DataControlError),
|
||||
}
|
||||
134
src/ifs/ipc/data_control/ext_data_control_manager_v1.rs
Normal file
134
src/ifs/ipc/data_control/ext_data_control_manager_v1.rs
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
use {
|
||||
crate::{
|
||||
client::{Client, ClientCaps, ClientError, CAP_DATA_CONTROL_MANAGER},
|
||||
globals::{Global, GlobalName},
|
||||
ifs::ipc::{
|
||||
data_control::{
|
||||
ext_data_control_device_v1::ExtDataControlDeviceV1,
|
||||
ext_data_control_source_v1::ExtDataControlSourceV1, DynDataControlDevice,
|
||||
},
|
||||
IpcLocation,
|
||||
},
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
wire::{ext_data_control_manager_v1::*, ExtDataControlManagerV1Id},
|
||||
},
|
||||
std::rc::Rc,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct ExtDataControlManagerV1Global {
|
||||
name: GlobalName,
|
||||
}
|
||||
|
||||
pub struct ExtDataControlManagerV1 {
|
||||
pub id: ExtDataControlManagerV1Id,
|
||||
pub client: Rc<Client>,
|
||||
pub version: Version,
|
||||
tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl ExtDataControlManagerV1Global {
|
||||
pub fn new(name: GlobalName) -> Self {
|
||||
Self { name }
|
||||
}
|
||||
|
||||
fn bind_(
|
||||
self: Rc<Self>,
|
||||
id: ExtDataControlManagerV1Id,
|
||||
client: &Rc<Client>,
|
||||
version: Version,
|
||||
) -> Result<(), ExtDataControlManagerV1Error> {
|
||||
let obj = Rc::new(ExtDataControlManagerV1 {
|
||||
id,
|
||||
client: client.clone(),
|
||||
version,
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtDataControlManagerV1RequestHandler for ExtDataControlManagerV1 {
|
||||
type Error = ExtDataControlManagerV1Error;
|
||||
|
||||
fn create_data_source(
|
||||
&self,
|
||||
req: CreateDataSource,
|
||||
_slf: &Rc<Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
let res = Rc::new(ExtDataControlSourceV1::new(
|
||||
req.id,
|
||||
&self.client,
|
||||
self.version,
|
||||
));
|
||||
track!(self.client, res);
|
||||
self.client.add_client_obj(&res)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_data_device(&self, req: GetDataDevice, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
let seat = self.client.lookup(req.seat)?;
|
||||
let dev = Rc::new(ExtDataControlDeviceV1::new(
|
||||
req.id,
|
||||
&self.client,
|
||||
self.version,
|
||||
&seat.global,
|
||||
));
|
||||
track!(self.client, dev);
|
||||
seat.global.add_data_control_device(dev.clone());
|
||||
self.client.add_client_obj(&dev)?;
|
||||
dev.clone()
|
||||
.handle_new_source(IpcLocation::Clipboard, seat.global.get_selection());
|
||||
dev.clone().handle_new_source(
|
||||
IpcLocation::PrimarySelection,
|
||||
seat.global.get_primary_selection(),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
global_base!(
|
||||
ExtDataControlManagerV1Global,
|
||||
ExtDataControlManagerV1,
|
||||
ExtDataControlManagerV1Error
|
||||
);
|
||||
|
||||
impl Global for ExtDataControlManagerV1Global {
|
||||
fn singleton(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn version(&self) -> u32 {
|
||||
1
|
||||
}
|
||||
|
||||
fn required_caps(&self) -> ClientCaps {
|
||||
CAP_DATA_CONTROL_MANAGER
|
||||
}
|
||||
}
|
||||
|
||||
simple_add_global!(ExtDataControlManagerV1Global);
|
||||
|
||||
object_base! {
|
||||
self = ExtDataControlManagerV1;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl Object for ExtDataControlManagerV1 {}
|
||||
|
||||
simple_add_obj!(ExtDataControlManagerV1);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ExtDataControlManagerV1Error {
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(ExtDataControlManagerV1Error, ClientError);
|
||||
76
src/ifs/ipc/data_control/ext_data_control_offer_v1.rs
Normal file
76
src/ifs/ipc/data_control/ext_data_control_offer_v1.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
use {
|
||||
crate::{
|
||||
ifs::ipc::data_control::{
|
||||
ext_data_control_device_v1::ExtDataControlIpc,
|
||||
private::{
|
||||
logic::{self, DataControlError},
|
||||
DataControlOffer, DataControlOfferData,
|
||||
},
|
||||
},
|
||||
leaks::Tracker,
|
||||
object::Object,
|
||||
wire::{ext_data_control_offer_v1::*, ExtDataControlOfferV1Id},
|
||||
},
|
||||
std::rc::Rc,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct ExtDataControlOfferV1 {
|
||||
pub id: ExtDataControlOfferV1Id,
|
||||
pub data: DataControlOfferData<ExtDataControlIpc>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl DataControlOffer for ExtDataControlOfferV1 {
|
||||
type Ipc = ExtDataControlIpc;
|
||||
|
||||
fn data(&self) -> &DataControlOfferData<Self::Ipc> {
|
||||
&self.data
|
||||
}
|
||||
|
||||
fn send_offer(&self, mime_type: &str) {
|
||||
self.send_offer(mime_type);
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtDataControlOfferV1 {
|
||||
pub fn send_offer(&self, mime_type: &str) {
|
||||
self.data.client.event(Offer {
|
||||
self_id: self.id,
|
||||
mime_type,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtDataControlOfferV1RequestHandler for ExtDataControlOfferV1 {
|
||||
type Error = ExtDataControlOfferV1Error;
|
||||
|
||||
fn receive(&self, req: Receive, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
logic::data_offer_receive(self, req.mime_type, req.fd);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
logic::data_offer_destroy(self)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
self = ExtDataControlOfferV1;
|
||||
version = self.data.device.data.version;
|
||||
}
|
||||
|
||||
impl Object for ExtDataControlOfferV1 {
|
||||
fn break_loops(&self) {
|
||||
logic::data_offer_break_loops(self);
|
||||
}
|
||||
}
|
||||
|
||||
simple_add_obj!(ExtDataControlOfferV1);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ExtDataControlOfferV1Error {
|
||||
#[error(transparent)]
|
||||
DataControlError(#[from] DataControlError),
|
||||
}
|
||||
107
src/ifs/ipc/data_control/ext_data_control_source_v1.rs
Normal file
107
src/ifs/ipc/data_control/ext_data_control_source_v1.rs
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
use {
|
||||
crate::{
|
||||
client::Client,
|
||||
ifs::ipc::{
|
||||
data_control::{
|
||||
ext_data_control_device_v1::ExtDataControlIpc,
|
||||
private::{
|
||||
logic::{self, DataControlError},
|
||||
DataControlSource, DataControlSourceData,
|
||||
},
|
||||
},
|
||||
IpcLocation, SourceData,
|
||||
},
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
wire::{ext_data_control_source_v1::*, ExtDataControlSourceV1Id},
|
||||
},
|
||||
std::{cell::Cell, rc::Rc},
|
||||
thiserror::Error,
|
||||
uapi::OwnedFd,
|
||||
};
|
||||
|
||||
pub struct ExtDataControlSourceV1 {
|
||||
pub id: ExtDataControlSourceV1Id,
|
||||
pub data: DataControlSourceData,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl DataControlSource for ExtDataControlSourceV1 {
|
||||
type Ipc = ExtDataControlIpc;
|
||||
|
||||
fn data(&self) -> &DataControlSourceData {
|
||||
&self.data
|
||||
}
|
||||
|
||||
fn send_cancelled(&self) {
|
||||
self.send_cancelled();
|
||||
}
|
||||
|
||||
fn send_send(&self, mime_type: &str, fd: Rc<OwnedFd>) {
|
||||
self.send_send(mime_type, fd);
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtDataControlSourceV1 {
|
||||
pub fn new(id: ExtDataControlSourceV1Id, client: &Rc<Client>, version: Version) -> Self {
|
||||
Self {
|
||||
id,
|
||||
data: DataControlSourceData {
|
||||
data: SourceData::new(client),
|
||||
version,
|
||||
location: Cell::new(IpcLocation::Clipboard),
|
||||
used: Cell::new(false),
|
||||
},
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_send(&self, mime_type: &str, fd: Rc<OwnedFd>) {
|
||||
self.data.data.client.event(Send {
|
||||
self_id: self.id,
|
||||
mime_type,
|
||||
fd,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn send_cancelled(&self) {
|
||||
self.data.data.client.event(Cancelled { self_id: self.id })
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtDataControlSourceV1RequestHandler for ExtDataControlSourceV1 {
|
||||
type Error = ExtDataControlSourceV1Error;
|
||||
|
||||
fn offer(&self, req: Offer, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
logic::data_source_offer(self, req.mime_type)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
logic::data_source_destroy(self)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
self = ExtDataControlSourceV1;
|
||||
version = self.data.version;
|
||||
}
|
||||
|
||||
impl Object for ExtDataControlSourceV1 {
|
||||
fn break_loops(&self) {
|
||||
logic::data_source_break_loops(self);
|
||||
}
|
||||
}
|
||||
|
||||
dedicated_add_obj!(
|
||||
ExtDataControlSourceV1,
|
||||
ExtDataControlSourceV1Id,
|
||||
ext_data_sources
|
||||
);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ExtDataControlSourceV1Error {
|
||||
#[error(transparent)]
|
||||
DataControlError(#[from] DataControlError),
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue