smithay_client_toolkit/data_device_manager/
data_device.rs1use std::{
2 ops::DerefMut,
3 sync::{Arc, Mutex},
4};
5
6use wayland_client::protocol::wl_surface::WlSurface;
7
8use crate::{
9 data_device_manager::data_offer::DataDeviceOffer,
10 dispatch2::Dispatch2,
11 reexports::client::{
12 event_created_child,
13 protocol::{
14 wl_data_device::{self, WlDataDevice},
15 wl_data_offer::{self, WlDataOffer},
16 wl_seat::WlSeat,
17 },
18 Connection, Dispatch, Proxy, QueueHandle,
19 },
20};
21
22use super::data_offer::{DataOfferData, DataOfferHandler, DragOffer, SelectionOffer};
23
24pub trait DataDeviceHandler: Sized {
28 fn enter(
41 &mut self,
42 conn: &Connection,
43 qh: &QueueHandle<Self>,
44 data_device: &WlDataDevice,
45 x: f64,
46 y: f64,
47 wl_surface: &WlSurface,
48 );
49
50 fn leave(&mut self, conn: &Connection, qh: &QueueHandle<Self>, data_device: &WlDataDevice);
54
55 fn motion(
57 &mut self,
58 conn: &Connection,
59 qh: &QueueHandle<Self>,
60 data_device: &WlDataDevice,
61 x: f64,
62 y: f64,
63 );
64
65 fn selection(&mut self, conn: &Connection, qh: &QueueHandle<Self>, data_device: &WlDataDevice);
67
68 fn drop_performed(
71 &mut self,
72 conn: &Connection,
73 qh: &QueueHandle<Self>,
74 data_device: &WlDataDevice,
75 );
76}
77
78#[derive(Debug, Eq, PartialEq)]
79pub struct DataDevice {
80 pub(crate) device: WlDataDevice,
81}
82
83impl DataDevice {
84 pub fn data(&self) -> &DataDeviceData {
85 self.device.data().unwrap()
86 }
87
88 pub fn unset_selection(&self, serial: u32) {
90 self.device.set_selection(None, serial);
91 }
92
93 pub fn inner(&self) -> &WlDataDevice {
94 &self.device
95 }
96}
97
98impl Drop for DataDevice {
99 fn drop(&mut self) {
100 if self.device.version() >= 2 {
101 self.device.release()
102 }
103 }
104}
105
106impl<D> Dispatch2<wl_data_device::WlDataDevice, D> for DataDeviceData
107where
108 D: Dispatch<wl_data_offer::WlDataOffer, DataOfferData>
109 + DataDeviceHandler
110 + DataOfferHandler
111 + 'static,
112{
113 event_created_child!(D, WlDataDevice, [
114 0 => (WlDataOffer, Default::default())
115 ]);
116
117 fn event(
118 &self,
119 state: &mut D,
120 data_device: &wl_data_device::WlDataDevice,
121 event: wl_data_device::Event,
122 conn: &Connection,
123 qh: &QueueHandle<D>,
124 ) {
125 use wayland_client::protocol::wl_data_device::Event;
126 let mut inner = self.inner.lock().unwrap();
127
128 match event {
129 Event::DataOffer { id } => {
130 inner.undetermined_offers.push(id.clone());
131 let data = id.data::<DataOfferData>().unwrap();
132 data.init_undetermined_offer(&id);
133 }
134 Event::Enter { serial, surface, x, y, id } => {
135 if let Some(offer) = inner.drag_offer.take() {
137 offer.destroy();
138 }
139
140 if let Some(offer) = id {
141 if let Some(i) = inner.undetermined_offers.iter().position(|o| o == &offer) {
142 inner.undetermined_offers.remove(i);
143 }
144
145 let data = offer.data::<DataOfferData>().unwrap();
146 data.to_dnd_offer(serial, surface.clone(), x, y, None);
147
148 inner.drag_offer = Some(offer.clone());
149 }
150 drop(inner);
152 state.enter(conn, qh, data_device, x, y, &surface);
153 }
154 Event::Leave => {
155 if let Some(offer) = inner.drag_offer.take() {
157 let data = offer.data::<DataOfferData>().unwrap();
158 if !data.leave() {
159 inner.drag_offer = Some(offer);
160 }
161 }
162 drop(inner);
164 state.leave(conn, qh, data_device);
165 }
166 Event::Motion { time, x, y } => {
167 if let Some(offer) = inner.drag_offer.take() {
168 let data = offer.data::<DataOfferData>().unwrap();
169 data.motion(x, y, time);
171 inner.drag_offer = Some(offer);
172 }
173
174 drop(inner);
176 state.motion(conn, qh, data_device, x, y);
177 }
178 Event::Drop => {
179 if let Some(offer) = inner.drag_offer.take() {
180 let data = offer.data::<DataOfferData>().unwrap();
181
182 let mut drag_inner = data.inner.lock().unwrap();
183
184 if let DataDeviceOffer::Drag(ref mut o) = drag_inner.deref_mut().offer {
185 o.dropped = true;
186 }
187 drop(drag_inner);
188
189 inner.drag_offer = Some(offer);
190 }
191 drop(inner);
193 state.drop_performed(conn, qh, data_device);
195 }
196 Event::Selection { id } => {
197 if let Some(offer) = inner.selection_offer.take() {
199 offer.destroy();
200 }
201
202 if let Some(offer) = id {
203 if let Some(i) = inner.undetermined_offers.iter().position(|o| o == &offer) {
204 inner.undetermined_offers.remove(i);
205 }
206
207 let data = offer.data::<DataOfferData>().unwrap();
208 data.to_selection_offer();
209 inner.selection_offer = Some(offer.clone());
210 drop(inner);
212 state.selection(conn, qh, data_device);
213 }
214 }
215 _ => unreachable!(),
216 }
217 }
218}
219
220#[derive(Debug)]
221pub struct DataDeviceData {
222 pub(crate) seat: WlSeat,
224 pub(crate) inner: Arc<Mutex<DataDeviceInner>>,
226}
227
228impl DataDeviceData {
229 pub(crate) fn new(seat: WlSeat) -> Self {
230 Self { seat, inner: Default::default() }
231 }
232
233 pub fn seat(&self) -> &WlSeat {
235 &self.seat
236 }
237
238 pub fn drag_offer(&self) -> Option<DragOffer> {
240 self.inner.lock().unwrap().drag_offer.as_ref().and_then(|offer| {
241 let data = offer.data::<DataOfferData>().unwrap();
242 data.as_drag_offer()
243 })
244 }
245
246 pub fn selection_offer(&self) -> Option<SelectionOffer> {
248 self.inner.lock().unwrap().selection_offer.as_ref().and_then(|offer| {
249 let data = offer.data::<DataOfferData>().unwrap();
250 data.as_selection_offer()
251 })
252 }
253}
254
255#[derive(Debug, Default)]
256pub(crate) struct DataDeviceInner {
257 pub drag_offer: Option<WlDataOffer>,
259 pub selection_offer: Option<WlDataOffer>,
261 pub undetermined_offers: Vec<WlDataOffer>,
263}