Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwaylanddatadevice.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 Klarälvdalens Datakonsult AB (KDAB).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4
6
10#include "qwaylanddnd_p.h"
15
16#include <QtWaylandClient/private/qwayland-xdg-toplevel-drag-v1.h>
17
18#include <QtCore/QMimeData>
19#include <QtGui/QGuiApplication>
20#include <QtGui/private/qguiapplication_p.h>
21
22#if QT_CONFIG(clipboard)
23#include <qpa/qplatformclipboard.h>
24#endif
25#include <qpa/qplatformdrag.h>
26#include <qpa/qwindowsysteminterface.h>
27
29
30namespace QtWaylandClient {
31
32using namespace Qt::StringLiterals;
33
34QWaylandDataDevice::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWaylandInputDevice *inputDevice)
35 : QObject(inputDevice)
36 , QtWayland::wl_data_device(manager->get_data_device(inputDevice->wl_seat()))
37 , m_display(manager->display())
38 , m_inputDevice(inputDevice)
39{
40}
41
43{
44 if (version() >= WL_DATA_DEVICE_RELEASE_SINCE_VERSION)
45 release();
46 else
47 wl_data_device_destroy(object());
48}
49
50QWaylandDataOffer *QWaylandDataDevice::selectionOffer() const
51{
52 return m_selectionOffer.data();
53}
54
56{
57 if (m_selectionOffer.isNull())
58 return;
59
60 m_selectionOffer.reset();
61
62#if QT_CONFIG(clipboard)
63 QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
64#endif
65}
66
67QWaylandDataSource *QWaylandDataDevice::selectionSource() const
68{
69 return m_selectionSource.data();
70}
71
72void QWaylandDataDevice::setSelectionSource(QWaylandDataSource *source)
73{
74 if (source)
75 connect(source, &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::selectionSourceCancelled);
76 set_selection(source ? source->object() : nullptr, m_inputDevice->serial());
77 m_selectionSource.reset(source);
78}
79
80#if QT_CONFIG(draganddrop)
82{
83 return m_dragOffer.data();
84}
85
87{
89
90 if (!origin) {
91 qCDebug(lcQpaWayland) << "Couldn't start a drag because the origin window could not be found.";
92 return false;
93 }
94
95 // dragging data without mimetypes is a legal operation in Qt terms
96 // but Wayland uses a mimetype to determine if a drag is accepted or not
97 // In this rare case, insert a placeholder
98 if (mimeData->formats().isEmpty())
99 mimeData->setData("application/x-qt-avoid-empty-placeholder"_L1, QByteArray("1"));
100
101 static const QString plain = QStringLiteral("text/plain");
102 static const QString utf8 = QStringLiteral("text/plain;charset=utf-8");
103
106
108
109 if (version() >= 3)
111
115 if (!drag->currentDrag()) {
116 return;
117 }
118 // in old versions drop action is not set, so we guess
119 if (m_dragSource->version() < 3) {
121 } else {
124 }
125 });
127 [this](bool accepted, Qt::DropAction action) {
129 if (m_toplevelDrag) {
130 // If the widget was dropped but the drag not accepted it
131 // should be its own window in the future. To distinguish
132 // from canceling mid-drag the drag is accepted here as the
133 // we know if the widget is over a zone where it can be
134 // incorporated or not
135 response = { true, Qt::MoveAction };
136 }
139 });
142 if (m_toplevelDrag) {
144 m_toplevelDrag = nullptr;
145 }
146 });
147
148 if (mimeData->hasFormat("application/x-qt-mainwindowdrag-window"_L1)
152 QDataStream windowStream(mimeData->data("application/x-qt-mainwindowdrag-window"_L1));
154 QWindow *dockWindow = reinterpret_cast<QWindow *>(dockWindowPtr);
155 QDataStream offsetStream(mimeData->data("application/x-qt-mainwindowdrag-position"_L1));
157 if (auto waylandWindow = static_cast<QWaylandWindow *>(dockWindow->handle())) {
161 m_dragSource->object()));
163 }
164 }
165 }
166
168 return true;
169}
170
172{
174}
175#endif
176
177void QWaylandDataDevice::data_device_data_offer(struct ::wl_data_offer *id)
178{
179 new QWaylandDataOffer(m_display, id);
180}
181
182#if QT_CONFIG(draganddrop)
184{
186
187 QMimeData *dragData = nullptr;
189 if (drag) {
192 } else if (m_dragOffer) {
195 } else {
196 return;
197 }
198
202
203 // re-evaluate as it could have changed during user code above
205 if (drag) {
209 } else if (m_dragOffer) {
211 }
212}
213
215{
218 return; // Ignore foreign surfaces
219
223
224 QMimeData *dragData = nullptr;
226
229 if (drag) {
232 } else if (m_dragOffer) {
235 }
236
240 if (drag) {
242 }
243
245}
246
248{
249 if (m_dragWindow)
253
255 if (!drag) {
257 }
258}
259
261{
262 Q_UNUSED(time);
263
265
266 if (!drag && !m_dragOffer)
267 return;
268
269 if (!m_dragWindow)
270 return;
271
273
274 QMimeData *dragData = nullptr;
276 if (drag) {
279 } else {
282 }
283
287
288 if (drag) {
290 }
291
293}
294#endif // QT_CONFIG(draganddrop)
295
296void QWaylandDataDevice::data_device_selection(wl_data_offer *id)
297{
298 if (id)
299 m_selectionOffer.reset(static_cast<QWaylandDataOffer *>(wl_data_offer_get_user_data(id)));
300 else
301 m_selectionOffer.reset();
302
303#if QT_CONFIG(clipboard)
304 QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
305#endif
306}
307
308void QWaylandDataDevice::selectionSourceCancelled()
309{
310 m_selectionSource.reset();
311#if QT_CONFIG(clipboard)
312 QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
313#endif
314}
315
316#if QT_CONFIG(draganddrop)
318{
321 if (m_toplevelDrag) {
323 m_toplevelDrag = nullptr;
324 }
325}
326
328{
330 if (wnd) {
332 if (wwnd && wwnd->decoration()) {
334 wwnd->decoration()->margins().top());
335 }
336 }
337 return pnt;
338}
339
341{
342 if (response.isAccepted()) {
343 if (version() >= 3)
345
347 } else {
349 }
350}
351
353{
354
356 if (actions & Qt::CopyAction)
360
361 // wayland does not support LinkAction at the time of writing
362 return wlActions;
363}
364
365
366#endif // QT_CONFIG(draganddrop)
367
368}
369
370QT_END_NAMESPACE
371
372#include "moc_qwaylanddatadevice_p.cpp"
QWaylandDataSource * selectionSource() const
QWaylandDataOffer * selectionOffer() const
void setSelectionSource(QWaylandDataSource *source)