1use std::{
2 ops::DerefMut,
3 sync::{Arc, Mutex},
4};
5
6use crate::{
7 data_device_manager::data_offer::DataDeviceOffer,
8 reexports::client::{
9 event_created_child,
10 protocol::{
11 wl_data_device::{self, WlDataDevice},
12 wl_data_offer::{self, WlDataOffer},
13 wl_seat::WlSeat,
14 },
15 Connection, Dispatch, Proxy, QueueHandle,
16 },
17};
18
19use super::{
20 data_offer::{DataOfferData, DataOfferHandler, DragOffer, SelectionOffer},
21 DataDeviceManagerState,
22};
23
24/// Handler trait for DataDevice events.
25///
26/// The functions defined in this trait are called as DataDevice events are received from the compositor.
27pub trait DataDeviceHandler: Sized {
28 // Introduces a new data offer
29 // ASHLEY left out because the data offer will be introduced to the user once the type is known
30 // either through the enter method or the selection method.
31 // fn data_offer(
32 // &mut self,
33 // conn: &Connection,
34 // qh: &QueueHandle<Self>,
35 // data_device: DataDevice,
36 // offer: WlDataOffer,
37 // );
38
39 /// The data device pointer has entered a surface at the provided location
40 fn enter(&mut self, conn: &Connection, qh: &QueueHandle<Self>, data_device: &WlDataDevice);
41
42 /// The drag and drop pointer has left the surface and the session ends.
43 /// The offer will be destroyed unless it was previously dropped.
44 /// In the case of a dropped offer, the client must destroy it manually after it is finished.
45 fn leave(&mut self, conn: &Connection, qh: &QueueHandle<Self>, data_device: &WlDataDevice);
46
47 /// Drag and Drop motion.
48 fn motion(&mut self, conn: &Connection, qh: &QueueHandle<Self>, data_device: &WlDataDevice);
49
50 /// Advertises a new selection.
51 fn selection(&mut self, conn: &Connection, qh: &QueueHandle<Self>, data_device: &WlDataDevice);
52
53 /// Drop performed.
54 /// After the next data offer action event, data may be able to be received, unless the action is "ask".
55 fn drop_performed(
56 &mut self,
57 conn: &Connection,
58 qh: &QueueHandle<Self>,
59 data_device: &WlDataDevice,
60 );
61}
62
63#[derive(Debug, Eq, PartialEq)]
64pub struct DataDevice {
65 pub(crate) device: WlDataDevice,
66}
67
68impl DataDevice {
69 pub fn data(&self) -> &DataDeviceData {
70 self.device.data().unwrap()
71 }
72
73 /// Unset the selection of the provided data device as a response to the event with with provided serial.
74 pub fn unset_selection(&self, serial: u32) {
75 self.device.set_selection(None, serial);
76 }
77
78 pub fn inner(&self) -> &WlDataDevice {
79 &self.device
80 }
81}
82
83impl Drop for DataDevice {
84 fn drop(&mut self) {
85 if self.device.version() >= 2 {
86 self.device.release()
87 }
88 }
89}
90
91impl<D> Dispatch<wl_data_device::WlDataDevice, DataDeviceData, D> for DataDeviceManagerState
92where
93 D: Dispatch<wl_data_device::WlDataDevice, DataDeviceData>
94 + Dispatch<wl_data_offer::WlDataOffer, DataOfferData>
95 + DataDeviceHandler
96 + DataOfferHandler
97 + 'static,
98{
99 event_created_child!(D, WlDataDevice, [
100 0 => (WlDataOffer, Default::default())
101 ]);
102
103 fn event(
104 state: &mut D,
105 data_device: &wl_data_device::WlDataDevice,
106 event: wl_data_device::Event,
107 data: &DataDeviceData,
108 conn: &Connection,
109 qh: &QueueHandle<D>,
110 ) {
111 use wayland_client::protocol::wl_data_device::Event;
112 let mut inner = data.inner.lock().unwrap();
113
114 match event {
115 Event::DataOffer { id } => {
116 inner.undetermined_offers.push(id.clone());
117 let data = id.data::<DataOfferData>().unwrap();
118 data.init_undetermined_offer(&id);
119 }
120 Event::Enter { serial, surface, x, y, id } => {
121 // XXX the spec isn't clear here.
122 if let Some(offer) = inner.drag_offer.take() {
123 offer.destroy();
124 }
125
126 if let Some(offer) = id {
127 if let Some(i) = inner.undetermined_offers.iter().position(|o| o == &offer) {
128 inner.undetermined_offers.remove(i);
129 }
130
131 let data = offer.data::<DataOfferData>().unwrap();
132 data.to_dnd_offer(serial, surface, x, y, None);
133
134 inner.drag_offer = Some(offer.clone());
135 // XXX Drop done here to prevent Mutex deadlocks.
136 drop(inner);
137 state.enter(conn, qh, data_device);
138 }
139 }
140 Event::Leave => {
141 // We must destroy the offer we've got on enter.
142 if let Some(offer) = inner.drag_offer.take() {
143 let data = offer.data::<DataOfferData>().unwrap();
144 if !data.leave() {
145 inner.drag_offer = Some(offer);
146 }
147 }
148 // XXX Drop done here to prevent Mutex deadlocks.
149 drop(inner);
150 state.leave(conn, qh, data_device);
151 }
152 Event::Motion { time, x, y } => {
153 if let Some(offer) = inner.drag_offer.take() {
154 let data = offer.data::<DataOfferData>().unwrap();
155 // Update the data offer location.
156 data.motion(x, y, time);
157 inner.drag_offer = Some(offer);
158 }
159
160 // XXX Drop done here to prevent Mutex deadlocks.
161 drop(inner);
162 state.motion(conn, qh, data_device);
163 }
164 Event::Drop => {
165 if let Some(offer) = inner.drag_offer.take() {
166 let data = offer.data::<DataOfferData>().unwrap();
167
168 let mut drag_inner = data.inner.lock().unwrap();
169
170 if let DataDeviceOffer::Drag(ref mut o) = drag_inner.deref_mut().offer {
171 o.dropped = true;
172 }
173 drop(drag_inner);
174
175 inner.drag_offer = Some(offer);
176 }
177 // XXX Drop done here to prevent Mutex deadlocks.
178 drop(inner);
179 // Pass the info about the drop to the user.
180 state.drop_performed(conn, qh, data_device);
181 }
182 Event::Selection { id } => {
183 // We must drop the current offer regardless.
184 if let Some(offer) = inner.selection_offer.take() {
185 offer.destroy();
186 }
187
188 if let Some(offer) = id {
189 if let Some(i) = inner.undetermined_offers.iter().position(|o| o == &offer) {
190 inner.undetermined_offers.remove(i);
191 }
192
193 let data = offer.data::<DataOfferData>().unwrap();
194 data.to_selection_offer();
195 inner.selection_offer = Some(offer.clone());
196 // XXX Drop done here to prevent Mutex deadlocks.
197 drop(inner);
198 state.selection(conn, qh, data_device);
199 }
200 }
201 _ => unreachable!(),
202 }
203 }
204}
205
206#[derive(Debug)]
207pub struct DataDeviceData {
208 /// The seat associated with this device.
209 pub(crate) seat: WlSeat,
210 /// The inner mutable storage.
211 pub(crate) inner: Arc<Mutex<DataDeviceInner>>,
212}
213
214impl DataDeviceData {
215 pub(crate) fn new(seat: WlSeat) -> Self {
216 Self { seat, inner: Default::default() }
217 }
218
219 /// Get the seat associated with this data device.
220 pub fn seat(&self) -> &WlSeat {
221 &self.seat
222 }
223
224 /// Get the active dnd offer if it exists.
225 pub fn drag_offer(&self) -> Option<DragOffer> {
226 self.inner.lock().unwrap().drag_offer.as_ref().and_then(|offer| {
227 let data = offer.data::<DataOfferData>().unwrap();
228 data.as_drag_offer()
229 })
230 }
231
232 /// Get the active selection offer if it exists.
233 pub fn selection_offer(&self) -> Option<SelectionOffer> {
234 self.inner.lock().unwrap().selection_offer.as_ref().and_then(|offer| {
235 let data = offer.data::<DataOfferData>().unwrap();
236 data.as_selection_offer()
237 })
238 }
239}
240
241#[derive(Debug, Default)]
242pub(crate) struct DataDeviceInner {
243 /// the active dnd offer and its data
244 pub drag_offer: Option<WlDataOffer>,
245 /// the active selection offer and its data
246 pub selection_offer: Option<WlDataOffer>,
247 /// the active undetermined offers and their data
248 pub undetermined_offers: Vec<WlDataOffer>,
249}
250