smithay_client_toolkit/data_device_manager/
data_source.rs

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}