1use std::{
2 ops::DerefMut,
3 sync::{Arc, Mutex},
4};
56use wayland_client::protocol::wl_surface::WlSurface;
78use crate::{
9 data_device_manager::data_offer::DataDeviceOffer,
10 reexports::client::{
11 event_created_child,
12 protocol::{
13 wl_data_device::{self, WlDataDevice},
14 wl_data_offer::{self, WlDataOffer},
15 wl_seat::WlSeat,
16 },
17 Connection, Dispatch, Proxy, QueueHandle,
18 },
19};
2021use super::{
22 data_offer::{DataOfferData, DataOfferHandler, DragOffer, SelectionOffer},
23 DataDeviceManagerState,
24};
2526/// Handler trait for DataDevice events.
27///
28/// The functions defined in this trait are called as DataDevice events are received from the compositor.
29pub trait DataDeviceHandler: Sized {
30// Introduces a new data offer
31 // ASHLEY left out because the data offer will be introduced to the user once the type is known
32 // either through the enter method or the selection method.
33 // fn data_offer(
34 // &mut self,
35 // conn: &Connection,
36 // qh: &QueueHandle<Self>,
37 // data_device: DataDevice,
38 // offer: WlDataOffer,
39 // );
4041/// The data device pointer has entered a surface at the provided location
42fn enter(
43&mut self,
44 conn: &Connection,
45 qh: &QueueHandle<Self>,
46 data_device: &WlDataDevice,
47 x: f64,
48 y: f64,
49 wl_surface: &WlSurface,
50 );
5152/// The drag and drop pointer has left the surface and the session ends.
53 /// The offer will be destroyed unless it was previously dropped.
54 /// In the case of a dropped offer, the client must destroy it manually after it is finished.
55fn leave(&mut self, conn: &Connection, qh: &QueueHandle<Self>, data_device: &WlDataDevice);
5657/// Drag and Drop motion.
58fn motion(
59&mut self,
60 conn: &Connection,
61 qh: &QueueHandle<Self>,
62 data_device: &WlDataDevice,
63 x: f64,
64 y: f64,
65 );
6667/// Advertises a new selection.
68fn selection(&mut self, conn: &Connection, qh: &QueueHandle<Self>, data_device: &WlDataDevice);
6970/// Drop performed.
71 /// After the next data offer action event, data may be able to be received, unless the action is "ask".
72fn drop_performed(
73&mut self,
74 conn: &Connection,
75 qh: &QueueHandle<Self>,
76 data_device: &WlDataDevice,
77 );
78}
7980#[derive(Debug, Eq, PartialEq)]
81pub struct DataDevice {
82pub(crate) device: WlDataDevice,
83}
8485impl DataDevice {
86pub fn data(&self) -> &DataDeviceData {
87self.device.data().unwrap()
88 }
8990/// Unset the selection of the provided data device as a response to the event with with provided serial.
91pub fn unset_selection(&self, serial: u32) {
92self.device.set_selection(None, serial);
93 }
9495pub fn inner(&self) -> &WlDataDevice {
96&self.device
97 }
98}
99100impl Drop for DataDevice {
101fn drop(&mut self) {
102if self.device.version() >= 2 {
103self.device.release()
104 }
105 }
106}
107108impl<D> Dispatch<wl_data_device::WlDataDevice, DataDeviceData, D> for DataDeviceManagerState
109where
110D: Dispatch<wl_data_device::WlDataDevice, DataDeviceData>
111 + Dispatch<wl_data_offer::WlDataOffer, DataOfferData>
112 + DataDeviceHandler
113 + DataOfferHandler
114 + 'static,
115{
116event_created_child!(D, WlDataDevice, [
1170 => (WlDataOffer, Default::default())
118 ]);
119120fn event(
121 state: &mut D,
122 data_device: &wl_data_device::WlDataDevice,
123 event: wl_data_device::Event,
124 data: &DataDeviceData,
125 conn: &Connection,
126 qh: &QueueHandle<D>,
127 ) {
128use wayland_client::protocol::wl_data_device::Event;
129let mut inner = data.inner.lock().unwrap();
130131match event {
132 Event::DataOffer { id } => {
133 inner.undetermined_offers.push(id.clone());
134let data = id.data::<DataOfferData>().unwrap();
135 data.init_undetermined_offer(&id);
136 }
137 Event::Enter { serial, surface, x, y, id } => {
138// XXX the spec isn't clear here.
139if let Some(offer) = inner.drag_offer.take() {
140 offer.destroy();
141 }
142143if let Some(offer) = id {
144if let Some(i) = inner.undetermined_offers.iter().position(|o| o == &offer) {
145 inner.undetermined_offers.remove(i);
146 }
147148let data = offer.data::<DataOfferData>().unwrap();
149 data.to_dnd_offer(serial, surface.clone(), x, y, None);
150151 inner.drag_offer = Some(offer.clone());
152 }
153// XXX Drop done here to prevent Mutex deadlocks.
154drop(inner);
155 state.enter(conn, qh, data_device, x, y, &surface);
156 }
157 Event::Leave => {
158// We must destroy the offer we've got on enter.
159if let Some(offer) = inner.drag_offer.take() {
160let data = offer.data::<DataOfferData>().unwrap();
161if !data.leave() {
162 inner.drag_offer = Some(offer);
163 }
164 }
165// XXX Drop done here to prevent Mutex deadlocks.
166drop(inner);
167 state.leave(conn, qh, data_device);
168 }
169 Event::Motion { time, x, y } => {
170if let Some(offer) = inner.drag_offer.take() {
171let data = offer.data::<DataOfferData>().unwrap();
172// Update the data offer location.
173data.motion(x, y, time);
174 inner.drag_offer = Some(offer);
175 }
176177// XXX Drop done here to prevent Mutex deadlocks.
178drop(inner);
179 state.motion(conn, qh, data_device, x, y);
180 }
181 Event::Drop => {
182if let Some(offer) = inner.drag_offer.take() {
183let data = offer.data::<DataOfferData>().unwrap();
184185let mut drag_inner = data.inner.lock().unwrap();
186187if let DataDeviceOffer::Drag(ref mut o) = drag_inner.deref_mut().offer {
188 o.dropped = true;
189 }
190 drop(drag_inner);
191192 inner.drag_offer = Some(offer);
193 }
194// XXX Drop done here to prevent Mutex deadlocks.
195drop(inner);
196// Pass the info about the drop to the user.
197state.drop_performed(conn, qh, data_device);
198 }
199 Event::Selection { id } => {
200// We must drop the current offer regardless.
201if let Some(offer) = inner.selection_offer.take() {
202 offer.destroy();
203 }
204205if let Some(offer) = id {
206if let Some(i) = inner.undetermined_offers.iter().position(|o| o == &offer) {
207 inner.undetermined_offers.remove(i);
208 }
209210let data = offer.data::<DataOfferData>().unwrap();
211 data.to_selection_offer();
212 inner.selection_offer = Some(offer.clone());
213// XXX Drop done here to prevent Mutex deadlocks.
214drop(inner);
215 state.selection(conn, qh, data_device);
216 }
217 }
218_ => unreachable!(),
219 }
220 }
221}
222223#[derive(Debug)]
224pub struct DataDeviceData {
225/// The seat associated with this device.
226pub(crate) seat: WlSeat,
227/// The inner mutable storage.
228pub(crate) inner: Arc<Mutex<DataDeviceInner>>,
229}
230231impl DataDeviceData {
232pub(crate) fn new(seat: WlSeat) -> Self {
233Self { seat, inner: Default::default() }
234 }
235236/// Get the seat associated with this data device.
237pub fn seat(&self) -> &WlSeat {
238&self.seat
239 }
240241/// Get the active dnd offer if it exists.
242pub fn drag_offer(&self) -> Option<DragOffer> {
243self.inner.lock().unwrap().drag_offer.as_ref().and_then(|offer| {
244let data = offer.data::<DataOfferData>().unwrap();
245 data.as_drag_offer()
246 })
247 }
248249/// Get the active selection offer if it exists.
250pub fn selection_offer(&self) -> Option<SelectionOffer> {
251self.inner.lock().unwrap().selection_offer.as_ref().and_then(|offer| {
252let data = offer.data::<DataOfferData>().unwrap();
253 data.as_selection_offer()
254 })
255 }
256}
257258#[derive(Debug, Default)]
259pub(crate) struct DataDeviceInner {
260/// the active dnd offer and its data
261pub drag_offer: Option<WlDataOffer>,
262/// the active selection offer and its data
263pub selection_offer: Option<WlDataOffer>,
264/// the active undetermined offers and their data
265pub undetermined_offers: Vec<WlDataOffer>,
266}