1use std::os::fd::BorrowedFd;
4
5use ext::ext_data_control_device_v1::ExtDataControlDeviceV1;
6use ext::ext_data_control_manager_v1::ExtDataControlManagerV1;
7use ext::ext_data_control_offer_v1::ExtDataControlOfferV1;
8use ext::ext_data_control_source_v1::ExtDataControlSourceV1;
9use wayland_client::protocol::wl_seat::WlSeat;
10use wayland_client::{Dispatch, Proxy as _, QueueHandle};
11use wayland_protocols::ext::data_control::v1::client as ext;
12use wayland_protocols_wlr::data_control::v1::client as zwlr;
13use zwlr::zwlr_data_control_device_v1::ZwlrDataControlDeviceV1;
14use zwlr::zwlr_data_control_manager_v1::ZwlrDataControlManagerV1;
15use zwlr::zwlr_data_control_offer_v1::ZwlrDataControlOfferV1;
16use zwlr::zwlr_data_control_source_v1::ZwlrDataControlSourceV1;
17
18#[derive(Clone)]
19pub enum Manager {
20 Zwlr(ZwlrDataControlManagerV1),
21 Ext(ExtDataControlManagerV1),
22}
23
24#[derive(Clone)]
25pub enum Device {
26 Zwlr(ZwlrDataControlDeviceV1),
27 Ext(ExtDataControlDeviceV1),
28}
29
30#[derive(Clone)]
31pub enum Source {
32 Zwlr(ZwlrDataControlSourceV1),
33 Ext(ExtDataControlSourceV1),
34}
35
36#[derive(Clone, PartialEq, Eq, Hash)]
37pub enum Offer {
38 Zwlr(ZwlrDataControlOfferV1),
39 Ext(ExtDataControlOfferV1),
40}
41
42impl Manager {
43 pub fn get_data_device<D, U>(&self, seat: &WlSeat, qh: &QueueHandle<D>, udata: U) -> Device
44 where
45 D: Dispatch<ZwlrDataControlDeviceV1, U> + 'static,
46 D: Dispatch<ExtDataControlDeviceV1, U> + 'static,
47 U: Send + Sync + 'static,
48 {
49 match self {
50 Manager::Zwlr(manager) => Device::Zwlr(manager.get_data_device(seat, qh, udata)),
51 Manager::Ext(manager) => Device::Ext(manager.get_data_device(seat, qh, udata)),
52 }
53 }
54
55 pub fn create_data_source<D>(&self, qh: &QueueHandle<D>) -> Source
56 where
57 D: Dispatch<ZwlrDataControlSourceV1, ()> + 'static,
58 D: Dispatch<ExtDataControlSourceV1, ()> + 'static,
59 {
60 match self {
61 Manager::Zwlr(manager) => Source::Zwlr(manager.create_data_source(qh, ())),
62 Manager::Ext(manager) => Source::Ext(manager.create_data_source(qh, ())),
63 }
64 }
65}
66
67impl Device {
68 pub fn destroy(&self) {
69 match self {
70 Device::Zwlr(device) => device.destroy(),
71 Device::Ext(device) => device.destroy(),
72 }
73 }
74
75 #[track_caller]
76 pub fn set_selection(&self, source: Option<&Source>) {
77 match self {
78 Device::Zwlr(device) => device.set_selection(source.map(Source::zwlr)),
79 Device::Ext(device) => device.set_selection(source.map(Source::ext)),
80 }
81 }
82
83 #[track_caller]
84 pub fn set_primary_selection(&self, source: Option<&Source>) {
85 match self {
86 Device::Zwlr(device) => device.set_primary_selection(source.map(Source::zwlr)),
87 Device::Ext(device) => device.set_primary_selection(source.map(Source::ext)),
88 }
89 }
90}
91
92impl Source {
93 pub fn destroy(&self) {
94 match self {
95 Source::Zwlr(source) => source.destroy(),
96 Source::Ext(source) => source.destroy(),
97 }
98 }
99
100 pub fn offer(&self, mime_type: String) {
101 match self {
102 Source::Zwlr(source) => source.offer(mime_type),
103 Source::Ext(source) => source.offer(mime_type),
104 }
105 }
106
107 pub fn is_alive(&self) -> bool {
108 match self {
109 Source::Zwlr(source) => source.is_alive(),
110 Source::Ext(source) => source.is_alive(),
111 }
112 }
113
114 #[track_caller]
115 pub fn zwlr(&self) -> &ZwlrDataControlSourceV1 {
116 if let Self::Zwlr(v) = self {
117 v
118 } else {
119 panic!("tried to convert non-Zwlr Source to Zwlr")
120 }
121 }
122
123 #[track_caller]
124 pub fn ext(&self) -> &ExtDataControlSourceV1 {
125 if let Self::Ext(v) = self {
126 v
127 } else {
128 panic!("tried to convert non-Ext Source to Ext")
129 }
130 }
131}
132
133impl Offer {
134 pub fn destroy(&self) {
135 match self {
136 Offer::Zwlr(offer) => offer.destroy(),
137 Offer::Ext(offer) => offer.destroy(),
138 }
139 }
140
141 pub fn receive(&self, mime_type: String, fd: BorrowedFd) {
142 match self {
143 Offer::Zwlr(offer) => offer.receive(mime_type, fd),
144 Offer::Ext(offer) => offer.receive(mime_type, fd),
145 }
146 }
147}
148
149impl From<ZwlrDataControlSourceV1> for Source {
150 fn from(v: ZwlrDataControlSourceV1) -> Self {
151 Self::Zwlr(v)
152 }
153}
154
155impl From<ExtDataControlSourceV1> for Source {
156 fn from(v: ExtDataControlSourceV1) -> Self {
157 Self::Ext(v)
158 }
159}
160
161impl From<ZwlrDataControlOfferV1> for Offer {
162 fn from(v: ZwlrDataControlOfferV1) -> Self {
163 Self::Zwlr(v)
164 }
165}
166
167impl From<ExtDataControlOfferV1> for Offer {
168 fn from(v: ExtDataControlOfferV1) -> Self {
169 Self::Ext(v)
170 }
171}
172
173macro_rules! impl_dispatch_manager {
175 ($handler:ty => [$($iface:ty),*]) => {
176 $(
177 impl Dispatch<$iface, ()> for $handler {
178 fn event(
179 _state: &mut Self,
180 _proxy: &$iface,
181 _event: <$iface as wayland_client::Proxy>::Event,
182 _data: &(),
183 _conn: &wayland_client::Connection,
184 _qhandle: &wayland_client::QueueHandle<Self>,
185 ) {
186 }
187 }
188 )*
189 };
190
191 ($handler:ty) => {
192 impl_dispatch_manager!($handler => [
193 wayland_protocols_wlr::data_control::v1::client::zwlr_data_control_manager_v1::ZwlrDataControlManagerV1,
194 wayland_protocols::ext::data_control::v1::client::ext_data_control_manager_v1::ExtDataControlManagerV1
195 ]);
196 };
197}
198pub(crate) use impl_dispatch_manager;
199
200macro_rules! impl_dispatch_device {
201 ($handler:ty, $udata:ty, $code:expr => [$(($iface:ty, $opcode:path, $offer:ty)),*]) => {
202 $(
203 impl Dispatch<$iface, $udata> for $handler {
204 fn event(
205 state: &mut Self,
206 _proxy: &$iface,
207 event: <$iface as wayland_client::Proxy>::Event,
208 data: &$udata,
209 _conn: &wayland_client::Connection,
210 _qhandle: &wayland_client::QueueHandle<Self>,
211 ) {
212 type Event = <$iface as wayland_client::Proxy>::Event;
213
214 ($code)(state, event, data)
215 }
216
217 event_created_child!($handler, $iface, [
218 $opcode => ($offer, ()),
219 ]);
220 }
221 )*
222 };
223
224 ($handler:ty, $udata:ty, $code:expr) => {
225 impl_dispatch_device!($handler, $udata, $code => [
226 (
227 wayland_protocols_wlr::data_control::v1::client::zwlr_data_control_device_v1::ZwlrDataControlDeviceV1,
228 wayland_protocols_wlr::data_control::v1::client::zwlr_data_control_device_v1::EVT_DATA_OFFER_OPCODE,
229 wayland_protocols_wlr::data_control::v1::client::zwlr_data_control_offer_v1::ZwlrDataControlOfferV1
230 ),
231 (
232 wayland_protocols::ext::data_control::v1::client::ext_data_control_device_v1::ExtDataControlDeviceV1,
233 wayland_protocols::ext::data_control::v1::client::ext_data_control_device_v1::EVT_DATA_OFFER_OPCODE,
234 wayland_protocols::ext::data_control::v1::client::ext_data_control_offer_v1::ExtDataControlOfferV1
235 )
236 ]);
237 };
238}
239pub(crate) use impl_dispatch_device;
240
241macro_rules! impl_dispatch_source {
242 ($handler:ty, $code:expr => [$($iface:ty),*]) => {
243 $(
244 impl Dispatch<$iface, ()> for $handler {
245 fn event(
246 state: &mut Self,
247 proxy: &$iface,
248 event: <$iface as wayland_client::Proxy>::Event,
249 _data: &(),
250 _conn: &wayland_client::Connection,
251 _qhandle: &wayland_client::QueueHandle<Self>,
252 ) {
253 type Event = <$iface as wayland_client::Proxy>::Event;
254
255 let source = $crate::data_control::Source::from(proxy.clone());
256 ($code)(state, source, event)
257 }
258 }
259 )*
260 };
261
262 ($handler:ty, $code:expr) => {
263 impl_dispatch_source!($handler, $code => [
264 wayland_protocols_wlr::data_control::v1::client::zwlr_data_control_source_v1::ZwlrDataControlSourceV1,
265 wayland_protocols::ext::data_control::v1::client::ext_data_control_source_v1::ExtDataControlSourceV1
266 ]);
267 };
268}
269pub(crate) use impl_dispatch_source;
270
271macro_rules! impl_dispatch_offer {
272 ($handler:ty, $code:expr => [$($iface:ty),*]) => {
273 $(
274 impl Dispatch<$iface, ()> for $handler {
275 fn event(
276 state: &mut Self,
277 proxy: &$iface,
278 event: <$iface as wayland_client::Proxy>::Event,
279 _data: &(),
280 _conn: &wayland_client::Connection,
281 _qhandle: &wayland_client::QueueHandle<Self>,
282 ) {
283 type Event = <$iface as wayland_client::Proxy>::Event;
284
285 let offer = $crate::data_control::Offer::from(proxy.clone());
286 ($code)(state, offer, event)
287 }
288 }
289 )*
290 };
291
292 ($handler:ty, $code:expr) => {
293 impl_dispatch_offer!($handler, $code => [
294 wayland_protocols_wlr::data_control::v1::client::zwlr_data_control_offer_v1::ZwlrDataControlOfferV1,
295 wayland_protocols::ext::data_control::v1::client::ext_data_control_offer_v1::ExtDataControlOfferV1
296 ]);
297 };
298
299 ($handler:ty) => {
300 impl_dispatch_offer!($handler, |_, _, _: Event| ());
301 };
302}
303pub(crate) use impl_dispatch_offer;