Skip to main content

smithay_client_toolkit/data_device_manager/
data_source.rs

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