1use crate::reexports::client::{
2 protocol::{
3 wl_data_device_manager::DndAction,
4 wl_data_source::{self, WlDataSource},
5 wl_surface::WlSurface,
6 },
7 Connection, Dispatch, Proxy, QueueHandle, WEnum,
8};
9
10use super::{data_device::DataDevice, DataDeviceManagerState, WritePipe};
11
12#[derive(Debug, Default)]
13pub struct DataSourceData {}
14
15pub trait DataSourceDataExt: Send + Sync {
16 fn data_source_data(&self) -> &DataSourceData;
17}
18
19impl DataSourceDataExt for DataSourceData {
20 fn data_source_data(&self) -> &DataSourceData {
21 self
22 }
23}
24
25/// Handler trait for DataSource events.
26///
27/// The functions defined in this trait are called as DataSource events are received from the compositor.
28pub trait DataSourceHandler: Sized {
29 /// This may be called multiple times, once for each accepted mime type from the destination, if any.
30 fn accept_mime(
31 &mut self,
32 conn: &Connection,
33 qh: &QueueHandle<Self>,
34 source: &WlDataSource,
35 mime: Option<String>,
36 );
37
38 /// The client has requested the data for this source to be sent.
39 /// Send the data, then close the fd.
40 fn send_request(
41 &mut self,
42 conn: &Connection,
43 qh: &QueueHandle<Self>,
44 source: &WlDataSource,
45 mime: String,
46 fd: WritePipe,
47 );
48
49 /// The data source is no longer valid
50 /// Cleanup & destroy this resource
51 fn cancelled(&mut self, conn: &Connection, qh: &QueueHandle<Self>, source: &WlDataSource);
52
53 /// A drop was performed.
54 /// The data source will be used and should not be destroyed yet
55 fn dnd_dropped(&mut self, conn: &Connection, qh: &QueueHandle<Self>, source: &WlDataSource);
56
57 /// The drag and drop finished.
58 /// The data source may be destroyed.
59 fn dnd_finished(&mut self, conn: &Connection, qh: &QueueHandle<Self>, source: &WlDataSource);
60
61 /// An action was selected by the compositor.
62 fn action(
63 &mut self,
64 conn: &Connection,
65 qh: &QueueHandle<Self>,
66 source: &WlDataSource,
67 action: DndAction,
68 );
69}
70
71impl<D, U> Dispatch<wl_data_source::WlDataSource, U, D> for DataDeviceManagerState
72where
73 D: Dispatch<wl_data_source::WlDataSource, U> + DataSourceHandler,
74 U: DataSourceDataExt,
75{
76 fn event(
77 state: &mut D,
78 source: &wl_data_source::WlDataSource,
79 event: <wl_data_source::WlDataSource as wayland_client::Proxy>::Event,
80 _data: &U,
81 conn: &wayland_client::Connection,
82 qh: &wayland_client::QueueHandle<D>,
83 ) {
84 match event {
85 wl_data_source::Event::Target { mime_type } => {
86 state.accept_mime(conn, qh, source, mime_type)
87 }
88 wl_data_source::Event::Send { mime_type, fd } => {
89 state.send_request(conn, qh, source, mime_type, fd.into());
90 }
91 wl_data_source::Event::Cancelled => {
92 state.cancelled(conn, qh, source);
93 }
94 wl_data_source::Event::DndDropPerformed => {
95 state.dnd_dropped(conn, qh, source);
96 }
97 wl_data_source::Event::DndFinished => {
98 state.dnd_finished(conn, qh, source);
99 }
100 wl_data_source::Event::Action { dnd_action } => match dnd_action {
101 WEnum::Value(dnd_action) => {
102 state.action(conn, qh, source, dnd_action);
103 }
104 WEnum::Unknown(_) => {}
105 },
106 _ => unimplemented!(),
107 };
108 }
109}
110
111#[derive(Debug, PartialEq, Eq, Clone)]
112pub struct CopyPasteSource {
113 pub(crate) inner: WlDataSource,
114}
115
116impl CopyPasteSource {
117 /// Set the selection of the provided data device as a response to the event with with provided serial.
118 pub fn set_selection(&self, device: &DataDevice, serial: u32) {
119 device.device.set_selection(Some(&self.inner), serial);
120 }
121
122 pub fn inner(&self) -> &WlDataSource {
123 &self.inner
124 }
125}
126
127impl Drop for CopyPasteSource {
128 fn drop(&mut self) {
129 self.inner.destroy();
130 }
131}
132
133#[derive(Debug, PartialEq, Eq, Clone)]
134pub struct DragSource {
135 pub(crate) inner: WlDataSource,
136}
137
138impl DragSource {
139 /// Start a normal drag and drop operation.
140 /// This can be used for both intra-client DnD or inter-client Dnd.
141 /// The drag is cancelled when the DragSource is dropped.
142 pub fn start_drag(
143 &self,
144 device: &DataDevice,
145 origin: &WlSurface,
146 icon: Option<&WlSurface>,
147 serial: u32,
148 ) {
149 device.device.start_drag(Some(&self.inner), origin, icon, serial);
150 }
151
152 /// Start an internal drag and drop operation.
153 /// This will pass a NULL source, and the client is expected to handle data passing internally.
154 /// Only Enter, Leave, & Motion events will be sent to the client
155 pub fn start_internal_drag(
156 device: &DataDevice,
157 origin: &WlSurface,
158 icon: Option<&WlSurface>,
159 serial: u32,
160 ) {
161 device.device.start_drag(None, origin, icon, serial);
162 }
163
164 /// Set the actions that this drag source supports.
165 /// This can only be done once, and must be done before the drag is started.
166 pub fn set_actions(&self, dnd_actions: DndAction) {
167 if self.inner.version() >= 3 {
168 self.inner.set_actions(dnd_actions);
169 }
170 self.inner.set_actions(dnd_actions);
171 }
172
173 /// Retrieve a reference to the inner wl_data_source.
174 pub fn inner(&self) -> &WlDataSource {
175 &self.inner
176 }
177}
178
179impl Drop for DragSource {
180 fn drop(&mut self) {
181 self.inner.destroy();
182 }
183}
184