1/*
2 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6#include "datasource.h"
7#include "wayland_pointer_p.h"
8// Qt
9#include <QMimeType>
10// Wayland
11#include <wayland-client-protocol.h>
12
13namespace KWayland
14{
15namespace Client
16{
17class Q_DECL_HIDDEN DataSource::Private
18{
19public:
20 explicit Private(DataSource *q);
21 void setup(wl_data_source *s);
22
23 WaylandPointer<wl_data_source, wl_data_source_destroy> source;
24 DataDeviceManager::DnDAction selectedAction = DataDeviceManager::DnDAction::None;
25
26private:
27 void setAction(DataDeviceManager::DnDAction action);
28 static void targetCallback(void *data, wl_data_source *dataSource, const char *mimeType);
29 static void sendCallback(void *data, wl_data_source *dataSource, const char *mimeType, int32_t fd);
30 static void cancelledCallback(void *data, wl_data_source *dataSource);
31 static void dndDropPerformedCallback(void *data, wl_data_source *wl_data_source);
32 static void dndFinishedCallback(void *data, wl_data_source *wl_data_source);
33 static void actionCallback(void *data, wl_data_source *wl_data_source, uint32_t dnd_action);
34
35 static const struct wl_data_source_listener s_listener;
36
37 DataSource *q;
38};
39
40const wl_data_source_listener DataSource::Private::s_listener =
41 {.target: targetCallback, .send: sendCallback, .cancelled: cancelledCallback, .dnd_drop_performed: dndDropPerformedCallback, .dnd_finished: dndFinishedCallback, .action: actionCallback};
42
43DataSource::Private::Private(DataSource *q)
44 : q(q)
45{
46}
47
48void DataSource::Private::targetCallback(void *data, wl_data_source *dataSource, const char *mimeType)
49{
50 auto d = reinterpret_cast<DataSource::Private *>(data);
51 Q_ASSERT(d->source == dataSource);
52 Q_EMIT d->q->targetAccepts(mimeType: QString::fromUtf8(utf8: mimeType));
53}
54
55void DataSource::Private::sendCallback(void *data, wl_data_source *dataSource, const char *mimeType, int32_t fd)
56{
57 auto d = reinterpret_cast<DataSource::Private *>(data);
58 Q_ASSERT(d->source == dataSource);
59 Q_EMIT d->q->sendDataRequested(mimeType: QString::fromUtf8(utf8: mimeType), fd);
60}
61
62void DataSource::Private::cancelledCallback(void *data, wl_data_source *dataSource)
63{
64 auto d = reinterpret_cast<DataSource::Private *>(data);
65 Q_ASSERT(d->source == dataSource);
66 Q_EMIT d->q->cancelled();
67}
68
69void DataSource::Private::dndDropPerformedCallback(void *data, wl_data_source *wl_data_source)
70{
71 Q_UNUSED(wl_data_source)
72 auto d = reinterpret_cast<DataSource::Private *>(data);
73 Q_EMIT d->q->dragAndDropPerformed();
74}
75
76void DataSource::Private::dndFinishedCallback(void *data, wl_data_source *wl_data_source)
77{
78 Q_UNUSED(wl_data_source)
79 auto d = reinterpret_cast<DataSource::Private *>(data);
80 Q_EMIT d->q->dragAndDropFinished();
81}
82
83void DataSource::Private::actionCallback(void *data, wl_data_source *wl_data_source, uint32_t dnd_action)
84{
85 Q_UNUSED(wl_data_source)
86 auto d = reinterpret_cast<Private *>(data);
87 switch (dnd_action) {
88 case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY:
89 d->setAction(DataDeviceManager::DnDAction::Copy);
90 break;
91 case WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE:
92 d->setAction(DataDeviceManager::DnDAction::Move);
93 break;
94 case WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK:
95 d->setAction(DataDeviceManager::DnDAction::Ask);
96 break;
97 case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE:
98 d->setAction(DataDeviceManager::DnDAction::None);
99 break;
100 default:
101 Q_UNREACHABLE();
102 }
103}
104
105void DataSource::Private::setAction(DataDeviceManager::DnDAction action)
106{
107 if (action == selectedAction) {
108 return;
109 }
110 selectedAction = action;
111 Q_EMIT q->selectedDragAndDropActionChanged();
112}
113
114void DataSource::Private::setup(wl_data_source *s)
115{
116 Q_ASSERT(!source.isValid());
117 Q_ASSERT(s);
118 source.setup(pointer: s);
119 wl_data_source_add_listener(wl_data_source: s, listener: &s_listener, data: this);
120}
121
122DataSource::DataSource(QObject *parent)
123 : QObject(parent)
124 , d(new Private(this))
125{
126}
127
128DataSource::~DataSource()
129{
130 release();
131}
132
133void DataSource::release()
134{
135 d->source.release();
136}
137
138void DataSource::destroy()
139{
140 d->source.destroy();
141}
142
143bool DataSource::isValid() const
144{
145 return d->source.isValid();
146}
147
148void DataSource::setup(wl_data_source *dataSource)
149{
150 d->setup(dataSource);
151}
152
153void DataSource::offer(const QString &mimeType)
154{
155 wl_data_source_offer(wl_data_source: d->source, mime_type: mimeType.toUtf8().constData());
156}
157
158void DataSource::offer(const QMimeType &mimeType)
159{
160 if (!mimeType.isValid()) {
161 return;
162 }
163 offer(mimeType: mimeType.name());
164}
165
166DataSource::operator wl_data_source *() const
167{
168 return d->source;
169}
170
171DataSource::operator wl_data_source *()
172{
173 return d->source;
174}
175
176void DataSource::setDragAndDropActions(DataDeviceManager::DnDActions actions)
177{
178 uint32_t wlActions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
179 if (actions.testFlag(flag: DataDeviceManager::DnDAction::Copy)) {
180 wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
181 }
182 if (actions.testFlag(flag: DataDeviceManager::DnDAction::Move)) {
183 wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
184 }
185 if (actions.testFlag(flag: DataDeviceManager::DnDAction::Ask)) {
186 wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
187 }
188 wl_data_source_set_actions(wl_data_source: d->source, dnd_actions: wlActions);
189}
190
191DataDeviceManager::DnDAction DataSource::selectedDragAndDropAction() const
192{
193 return d->selectedAction;
194}
195
196}
197}
198
199#include "moc_datasource.cpp"
200

source code of kwayland/src/client/datasource.cpp