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// Qt-Security score:significant reason:default
4
5
7
11#include "qwaylanddnd_p.h"
16
17#include <QtWaylandClient/private/qwayland-xdg-toplevel-drag-v1.h>
18
19#include <QtCore/QMimeData>
20#include <QtGui/QGuiApplication>
21#include <QtGui/private/qguiapplication_p.h>
22
23#if QT_CONFIG(clipboard)
24#include <qpa/qplatformclipboard.h>
25#endif
26#include <qpa/qplatformdrag.h>
27#include <qpa/qwindowsysteminterface.h>
28
30
31namespace QtWaylandClient {
32
33using namespace Qt::StringLiterals;
34
35QWaylandDataDevice::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWaylandInputDevice *inputDevice)
36 : QObject(inputDevice)
37 , QtWayland::wl_data_device(manager->get_data_device(inputDevice->wl_seat()))
38 , m_display(manager->display())
39 , m_inputDevice(inputDevice)
40{
41}
42
44{
45 if (version() >= WL_DATA_DEVICE_RELEASE_SINCE_VERSION)
46 release();
47 else
48 wl_data_device_destroy(object());
49}
50
51QWaylandDataOffer *QWaylandDataDevice::selectionOffer() const
52{
53 return m_selectionOffer.get();
54}
55
57{
58 if (!m_selectionOffer)
59 return;
60
61 m_selectionOffer.reset();
62
63#if QT_CONFIG(clipboard)
64 QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
65#endif
66}
67
68QWaylandDataSource *QWaylandDataDevice::selectionSource() const
69{
70 return m_selectionSource.get();
71}
72
73void QWaylandDataDevice::setSelectionSource(QWaylandDataSource *source)
74{
75 if (source)
76 connect(source, &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::selectionSourceCancelled);
77 set_selection(source ? source->object() : nullptr, m_inputDevice->serial());
78 m_selectionSource.reset(source);
79}
80
81#if QT_CONFIG(draganddrop)
83{
84 return m_dragOffer.get();
85}
86
88{
90
91 if (!origin) {
92 qCDebug(lcQpaWayland) << "Couldn't start a drag because the origin window could not be found.";
93 return false;
94 }
95
96 // dragging data without mimetypes is a legal operation in Qt terms
97 // but Wayland uses a mimetype to determine if a drag is accepted or not
98 // In this rare case, insert a placeholder
99 if (mimeData->formats().isEmpty())
100 mimeData->setData("application/x-qt-avoid-empty-placeholder"_L1, QByteArray("1"));
101
102 static const QString plain = QStringLiteral("text/plain");
103 static const QString utf8 = QStringLiteral("text/plain;charset=utf-8");
104
107
109
110 if (version() >= 3)
112
116 this, [this](bool accepted, Qt::DropAction action) {
118 if (!drag->currentDrag()) {
119 return;
120 }
121 // in old versions drop action is not set, so we guess
122 if (m_dragSource->version() < 3) {
124 } else {
127 }
128 });
130 this, [this](bool accepted, Qt::DropAction action) {
132 if (m_toplevelDrag) {
133 // If the widget was dropped but the drag not accepted it
134 // should be its own window in the future. To distinguish
135 // from canceling mid-drag the drag is accepted here as the
136 // we know if the widget is over a zone where it can be
137 // incorporated or not
138 response = { true, Qt::MoveAction };
139 }
142 });
143 connect(m_dragSource.get(), &QWaylandDataSource::finished, this, [this]() {
145 if (m_toplevelDrag) {
147 m_toplevelDrag = nullptr;
148 }
149 });
150
151 if (mimeData->hasFormat("application/x-qt-mainwindowdrag-window"_L1)
155 QDataStream windowStream(mimeData->data("application/x-qt-mainwindowdrag-window"_L1));
157 QWindow *dockWindow = reinterpret_cast<QWindow *>(dockWindowPtr);
158 QDataStream offsetStream(mimeData->data("application/x-qt-mainwindowdrag-position"_L1));
160 if (auto waylandWindow = static_cast<QWaylandWindow *>(dockWindow->handle())) {
164 m_dragSource->object()));
166 }
167 }
168 }
169
171 return true;
172}
173
175{
177}
178#endif
179
180void QWaylandDataDevice::data_device_data_offer(struct ::wl_data_offer *id)
181{
182 new QWaylandDataOffer(m_display, id);
183}
184
185#if QT_CONFIG(draganddrop)
187{
189
190 QMimeData *dragData = nullptr;
192 if (drag) {
195 } else if (m_dragOffer) {
198 } else {
199 return;
200 }
201
205
206 // re-evaluate as it could have changed during user code above
208 if (drag) {
212 } else if (m_dragOffer && response.isAccepted()) {
214 }
215}
216
218{
221
224 return; // Ignore foreign surfaces
225
229
230 QMimeData *dragData = nullptr;
232
235 if (drag) {
238 } else if (m_dragOffer) {
241 }
242
246 if (drag) {
248 }
249
251}
252
254{
255 if (m_dragWindow)
259
261 if (!drag) {
263 }
264}
265
267{
268 Q_UNUSED(time);
271
273
274 if (!drag && !m_dragOffer)
275 return;
276
277 if (!m_dragWindow)
278 return;
279
281
282 QMimeData *dragData = nullptr;
284 if (drag) {
287 } else {
290 }
291
295
296 if (drag) {
298 }
299
301}
302#endif // QT_CONFIG(draganddrop)
303
304void QWaylandDataDevice::data_device_selection(wl_data_offer *id)
305{
306 if (id)
307 m_selectionOffer.reset(static_cast<QWaylandDataOffer *>(wl_data_offer_get_user_data(id)));
308 else
309 m_selectionOffer.reset();
310
311#if QT_CONFIG(clipboard)
312 QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
313#endif
314}
315
316void QWaylandDataDevice::selectionSourceCancelled()
317{
318 m_selectionSource.reset();
319#if QT_CONFIG(clipboard)
320 QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
321#endif
322}
323
324#if QT_CONFIG(draganddrop)
326{
329 if (m_toplevelDrag) {
331 m_toplevelDrag = nullptr;
332 }
333}
334
336{
337 QPoint pnt(x, y);
338 if (wnd) {
340 if (wwnd && wwnd->decoration()) {
342 wwnd->decoration()->margins().top());
343 }
344 }
345 return pnt;
346}
347
349{
350 if (response.isAccepted()) {
351 if (version() >= 3)
353
355 } else {
357 }
358}
359
361{
362
364 if (actions & Qt::CopyAction)
368
369 // wayland does not support LinkAction at the time of writing
370 return wlActions;
371}
372
373
374#endif // QT_CONFIG(draganddrop)
375
376}
377
378QT_END_NAMESPACE
379
380#include "moc_qwaylanddatadevice_p.cpp"
QWaylandDataSource * selectionSource() const
QWaylandDataOffer * selectionOffer() const
void setSelectionSource(QWaylandDataSource *source)
Combined button and popup list for selecting options.