Skip to content

Commit

Permalink
wayland.selection: Introduce DataDeviceKind
Browse files Browse the repository at this point in the history
  • Loading branch information
PolyMeilex committed Dec 26, 2024
1 parent 9b8178a commit 9eb0022
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 71 deletions.
22 changes: 13 additions & 9 deletions src/wayland/selection/device.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
use std::any::Any;
use std::any::TypeId;

use wayland_protocols::ext::data_control::v1::server::ext_data_control_device_v1::ExtDataControlDeviceV1;
use wayland_protocols::wp::primary_selection::zv1::server::zwp_primary_selection_device_v1::ZwpPrimarySelectionDeviceV1 as PrimaryDevice;
use wayland_protocols_wlr::data_control::v1::server::zwlr_data_control_device_v1::ZwlrDataControlDeviceV1;
Expand All @@ -17,6 +14,14 @@ use super::primary_selection::PrimaryDeviceUserData;
use super::private::selection_dispatch;
use super::wlr_data_control::DataControlDeviceUserData;

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub(crate) enum DataDeviceKind {
Core,
Primary,
WlrDataControl,
ExtDataControl,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum DataControlDevice {
Wlr(ZwlrDataControlDeviceV1),
Expand Down Expand Up @@ -100,13 +105,12 @@ impl SelectionDevice {
selection_dispatch!(self; Self(device) => device.id())
}

/// Get the [`TypeId`] of the underlying data device provider.
pub fn inner_type_id(&self) -> TypeId {
pub fn device_kind(&self) -> DataDeviceKind {
match self {
Self::DataDevice(device) => device.type_id(),
Self::Primary(device) => device.type_id(),
Self::DataControl(DataControlDevice::Wlr(device)) => device.type_id(),
Self::DataControl(DataControlDevice::Ext(device)) => device.type_id(),
Self::DataDevice(_) => DataDeviceKind::Core,
Self::Primary(_) => DataDeviceKind::Primary,
Self::DataControl(DataControlDevice::Wlr(_)) => DataDeviceKind::WlrDataControl,
Self::DataControl(DataControlDevice::Ext(_)) => DataDeviceKind::ExtDataControl,
}
}

Expand Down
111 changes: 49 additions & 62 deletions src/wayland/selection/offer.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
use std::any::TypeId;
use std::os::unix::io::OwnedFd;
use std::sync::Arc;

use tracing::debug;
use wayland_protocols::wp::primary_selection::zv1::server::zwp_primary_selection_device_v1::ZwpPrimarySelectionDeviceV1 as PrimaryDevice;
use wayland_protocols::wp::primary_selection::zv1::server::zwp_primary_selection_offer_v1::{
self, ZwpPrimarySelectionOfferV1 as PrimaryOffer,
};
use wayland_protocols_wlr::data_control::v1::server::zwlr_data_control_device_v1::ZwlrDataControlDeviceV1;
use wayland_protocols_wlr::data_control::v1::server::zwlr_data_control_offer_v1::{
self, ZwlrDataControlOfferV1,
};
use wayland_server::backend::protocol::Message;
use wayland_server::backend::ObjectId;
use wayland_server::backend::{ClientId, Handle, ObjectData};
use wayland_server::protocol::wl_data_device::WlDataDevice;
use wayland_server::protocol::wl_data_offer;
use wayland_server::protocol::wl_seat::WlSeat;
use wayland_server::DisplayHandle;
Expand All @@ -24,12 +20,11 @@ use zwlr_data_control_offer_v1::Request as DataControlRequest;
use zwp_primary_selection_offer_v1::Request as PrimaryRequest;

use crate::input::Seat;
use wayland_protocols::ext::data_control::v1::server::ext_data_control_device_v1::ExtDataControlDeviceV1;
use wayland_protocols::ext::data_control::v1::server::ext_data_control_offer_v1::{
self, ExtDataControlOfferV1,
};

use super::device::SelectionDevice;
use super::device::{DataDeviceKind, SelectionDevice};
use super::private::selection_dispatch;
use super::source::{CompositorSelectionProvider, SelectionSourceProvider};
use super::SelectionHandler;
Expand Down Expand Up @@ -99,44 +94,34 @@ impl SelectionOffer {
// NOTE: the types are tied to the `SelectionDevice`, so every
// RTTI like checking is safe and reliable.

let type_id = device.inner_type_id();
let device_kind = device.device_kind();
let data = Arc::new(OfferReplyData {
type_id,
device_kind,
seat: device.seat(),
source: data,
});
let backend = dh.backend_handle();

let interface = if type_id == TypeId::of::<WlDataDevice>() {
WlDataOffer::interface()
} else if type_id == TypeId::of::<PrimaryDevice>() {
PrimaryOffer::interface()
} else if type_id == TypeId::of::<ZwlrDataControlDeviceV1>() {
ZwlrDataControlOfferV1::interface()
} else if type_id == TypeId::of::<ExtDataControlDeviceV1>() {
ExtDataControlOfferV1::interface()
} else {
unreachable!()
let interface = match device_kind {
DataDeviceKind::Core => WlDataOffer::interface(),
DataDeviceKind::Primary => PrimaryOffer::interface(),
DataDeviceKind::WlrDataControl => ZwlrDataControlOfferV1::interface(),
DataDeviceKind::ExtDataControl => ExtDataControlOfferV1::interface(),
};

let offer = backend
.create_object::<D>(client_id, interface, device.version(), data)
.unwrap();

if type_id == TypeId::of::<WlDataDevice>() {
Self::DataDevice(WlDataOffer::from_id(dh, offer).unwrap())
} else if type_id == TypeId::of::<PrimaryDevice>() {
Self::Primary(PrimaryOffer::from_id(dh, offer).unwrap())
} else if type_id == TypeId::of::<ZwlrDataControlDeviceV1>() {
Self::DataControl(DataControlOffer::Wlr(
match device_kind {
DataDeviceKind::Core => Self::DataDevice(WlDataOffer::from_id(dh, offer).unwrap()),
DataDeviceKind::Primary => Self::Primary(PrimaryOffer::from_id(dh, offer).unwrap()),
DataDeviceKind::WlrDataControl => Self::DataControl(DataControlOffer::Wlr(
ZwlrDataControlOfferV1::from_id(dh, offer).unwrap(),
))
} else if type_id == TypeId::of::<ExtDataControlDeviceV1>() {
Self::DataControl(DataControlOffer::Ext(
)),
DataDeviceKind::ExtDataControl => Self::DataControl(DataControlOffer::Ext(
ExtDataControlOfferV1::from_id(dh, offer).unwrap(),
))
} else {
unreachable!()
)),
}
}

Expand All @@ -146,7 +131,7 @@ impl SelectionOffer {
}

struct OfferReplyData<U: Clone + Send + Sync + 'static> {
type_id: TypeId,
device_kind: DataDeviceKind,
source: OfferReplySource<U>,
seat: WlSeat,
}
Expand All @@ -163,45 +148,47 @@ where
msg: Message<ObjectId, OwnedFd>,
) -> Option<Arc<dyn ObjectData<D>>> {
let dh = DisplayHandle::from(dh.clone());
let type_id = self.type_id;

// NOTE: we can't parse message more than once, since it expects the `OwnedFd` which
// we can't clone. To achieve that, we use RTTI passed along the selection data, to
// make the parsing work only once.
let (mime_type, fd, object_name) = if type_id == TypeId::of::<WlDataDevice>() {
if let Ok((_resource, DataOfferRequest::Receive { mime_type, fd })) =
WlDataOffer::parse_request(&dh, msg)
{
(mime_type, fd, "wl_data_offer")
} else {
return None;
let (mime_type, fd, object_name) = match self.device_kind {
DataDeviceKind::Core => {
if let Ok((_resource, DataOfferRequest::Receive { mime_type, fd })) =
WlDataOffer::parse_request(&dh, msg)
{
(mime_type, fd, "wl_data_offer")
} else {
return None;
}
}
} else if type_id == TypeId::of::<PrimaryDevice>() {
if let Ok((_resource, PrimaryRequest::Receive { mime_type, fd })) =
PrimaryOffer::parse_request(&dh, msg)
{
(mime_type, fd, "primary_selection_offer")
} else {
return None;
DataDeviceKind::Primary => {
if let Ok((_resource, PrimaryRequest::Receive { mime_type, fd })) =
PrimaryOffer::parse_request(&dh, msg)
{
(mime_type, fd, "primary_selection_offer")
} else {
return None;
}
}
} else if type_id == TypeId::of::<ZwlrDataControlDeviceV1>() {
if let Ok((_resource, DataControlRequest::Receive { mime_type, fd })) =
ZwlrDataControlOfferV1::parse_request(&dh, msg)
{
(mime_type, fd, "wlr_data_control_offer")
} else {
return None;
DataDeviceKind::WlrDataControl => {
if let Ok((_resource, DataControlRequest::Receive { mime_type, fd })) =
ZwlrDataControlOfferV1::parse_request(&dh, msg)
{
(mime_type, fd, "wlr_data_control_offer")
} else {
return None;
}
}
} else if type_id == TypeId::of::<ExtDataControlDeviceV1>() {
if let Ok((_resource, ext_data_control_offer_v1::Request::Receive { mime_type, fd })) =
ExtDataControlOfferV1::parse_request(&dh, msg)
{
(mime_type, fd, "ext_data_control_offer")
} else {
return None;
DataDeviceKind::ExtDataControl => {
if let Ok((_resource, ext_data_control_offer_v1::Request::Receive { mime_type, fd })) =
ExtDataControlOfferV1::parse_request(&dh, msg)
{
(mime_type, fd, "ext_data_control_offer")
} else {
return None;
}
}
} else {
return None;
};

if !self.source.contains_mime_type(&mime_type) {
Expand Down

0 comments on commit 9eb0022

Please sign in to comment.