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 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};
20
21use super::{
22 data_offer::{DataOfferData, DataOfferHandler, DragOffer, SelectionOffer},
23 DataDeviceManagerState,
24};
25
26pub trait DataDeviceHandler: Sized {
30 fn 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 );
51
52 fn leave(&mut self, conn: &Connection, qh: &QueueHandle<Self>, data_device: &WlDataDevice);
56
57 fn motion(
59 &mut self,
60 conn: &Connection,
61 qh: &QueueHandle<Self>,
62 data_device: &WlDataDevice,
63 x: f64,
64 y: f64,
65 );
66
67 fn selection(&mut self, conn: &Connection, qh: &QueueHandle<Self>, data_device: &WlDataDevice);
69
70 fn drop_performed(
73 &mut self,
74 conn: &Connection,
75 qh: &QueueHandle<Self>,
76 data_device: &WlDataDevice,
77 );
78}
79
80#[derive(Debug, Eq, PartialEq)]
81pub struct DataDevice {
82 pub(crate) device: WlDataDevice,
83}
84
85impl DataDevice {
86 pub fn data(&self) -> &DataDeviceData {
87 self.device.data().unwrap()
88 }
89
90 pub fn unset_selection(&self, serial: u32) {
92 self.device.set_selection(None, serial);
93 }
94
95 pub fn inner(&self) -> &WlDataDevice {
96 &self.device
97 }
98}
99
100impl Drop for DataDevice {
101 fn drop(&mut self) {
102 if self.device.version() >= 2 {
103 self.device.release()
104 }
105 }
106}
107
108impl<D> Dispatch<wl_data_device::WlDataDevice, DataDeviceData, D> for DataDeviceManagerState
109where
110 D: Dispatch<wl_data_device::WlDataDevice, DataDeviceData>
111 + Dispatch<wl_data_offer::WlDataOffer, DataOfferData>
112 + DataDeviceHandler
113 + DataOfferHandler
114 + 'static,
115{
116 event_created_child!(D, WlDataDevice, [
117 0 => (WlDataOffer, Default::default())
118 ]);
119
120 fn 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 ) {
128 use wayland_client::protocol::wl_data_device::Event;
129 let mut inner = data.inner.lock().unwrap();
130
131 match event {
132 Event::DataOffer { id } => {
133 inner.undetermined_offers.push(id.clone());
134 let data = id.data::<DataOfferData>().unwrap();
135 data.init_undetermined_offer(&id);
136 }
137 Event::Enter { serial, surface, x, y, id } => {
138 if let Some(offer) = inner.drag_offer.take() {
140 offer.destroy();
141 }
142
143 if let Some(offer) = id {
144 if let Some(i) = inner.undetermined_offers.iter().position(|o| o == &offer) {
145 inner.undetermined_offers.remove(i);
146 }
147
148 let data = offer.data::<DataOfferData>().unwrap();
149 data.to_dnd_offer(serial, surface.clone(), x, y, None);
150
151 inner.drag_offer = Some(offer.clone());
152 }
153 drop(inner);
155 state.enter(conn, qh, data_device, x, y, &surface);
156 }
157 Event::Leave => {
158 if let Some(offer) = inner.drag_offer.take() {
160 let data = offer.data::<DataOfferData>().unwrap();
161 if !data.leave() {
162 inner.drag_offer = Some(offer);
163 }
164 }
165 drop(inner);
167 state.leave(conn, qh, data_device);
168 }
169 Event::Motion { time, x, y } => {
170 if let Some(offer) = inner.drag_offer.take() {
171 let data = offer.data::<DataOfferData>().unwrap();
172 data.motion(x, y, time);
174 inner.drag_offer = Some(offer);
175 }
176
177 drop(inner);
179 state.motion(conn, qh, data_device, x, y);
180 }
181 Event::Drop => {
182 if let Some(offer) = inner.drag_offer.take() {
183 let data = offer.data::<DataOfferData>().unwrap();
184
185 let mut drag_inner = data.inner.lock().unwrap();
186
187 if let DataDeviceOffer::Drag(ref mut o) = drag_inner.deref_mut().offer {
188 o.dropped = true;
189 }
190 drop(drag_inner);
191
192 inner.drag_offer = Some(offer);
193 }
194 drop(inner);
196 state.drop_performed(conn, qh, data_device);
198 }
199 Event::Selection { id } => {
200 if let Some(offer) = inner.selection_offer.take() {
202 offer.destroy();
203 }
204
205 if let Some(offer) = id {
206 if let Some(i) = inner.undetermined_offers.iter().position(|o| o == &offer) {
207 inner.undetermined_offers.remove(i);
208 }
209
210 let data = offer.data::<DataOfferData>().unwrap();
211 data.to_selection_offer();
212 inner.selection_offer = Some(offer.clone());
213 drop(inner);
215 state.selection(conn, qh, data_device);
216 }
217 }
218 _ => unreachable!(),
219 }
220 }
221}
222
223#[derive(Debug)]
224pub struct DataDeviceData {
225 pub(crate) seat: WlSeat,
227 pub(crate) inner: Arc<Mutex<DataDeviceInner>>,
229}
230
231impl DataDeviceData {
232 pub(crate) fn new(seat: WlSeat) -> Self {
233 Self { seat, inner: Default::default() }
234 }
235
236 pub fn seat(&self) -> &WlSeat {
238 &self.seat
239 }
240
241 pub fn drag_offer(&self) -> Option<DragOffer> {
243 self.inner.lock().unwrap().drag_offer.as_ref().and_then(|offer| {
244 let data = offer.data::<DataOfferData>().unwrap();
245 data.as_drag_offer()
246 })
247 }
248
249 pub fn selection_offer(&self) -> Option<SelectionOffer> {
251 self.inner.lock().unwrap().selection_offer.as_ref().and_then(|offer| {
252 let data = offer.data::<DataOfferData>().unwrap();
253 data.as_selection_offer()
254 })
255 }
256}
257
258#[derive(Debug, Default)]
259pub(crate) struct DataDeviceInner {
260 pub drag_offer: Option<WlDataOffer>,
262 pub selection_offer: Option<WlDataOffer>,
264 pub undetermined_offers: Vec<WlDataOffer>,
266}