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 return; // Ignore foreign surfaces
222
226
227 QMimeData *dragData = nullptr;
229
232 if (drag) {
235 } else if (m_dragOffer) {
238 }
239
243 if (drag) {
245 }
246
248}
249
251{
252 if (m_dragWindow)
256
258 if (!drag) {
260 }
261}
262
264{
265 Q_UNUSED(time);
266
268
269 if (!drag && !m_dragOffer)
270 return;
271
272 if (!m_dragWindow)
273 return;
274
276
277 QMimeData *dragData = nullptr;
279 if (drag) {
282 } else {
285 }
286
290
291 if (drag) {
293 }
294
296}
297#endif // QT_CONFIG(draganddrop)
298
299void QWaylandDataDevice::data_device_selection(wl_data_offer *id)
300{
301 if (id)
302 m_selectionOffer.reset(static_cast<QWaylandDataOffer *>(wl_data_offer_get_user_data(id)));
303 else
304 m_selectionOffer.reset();
305
306#if QT_CONFIG(clipboard)
307 QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
308#endif
309}
310
311void QWaylandDataDevice::selectionSourceCancelled()
312{
313 m_selectionSource.reset();
314#if QT_CONFIG(clipboard)
315 QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
316#endif
317}
318
319#if QT_CONFIG(draganddrop)
321{
324 if (m_toplevelDrag) {
326 m_toplevelDrag = nullptr;
327 }
328}
329
331{
333 if (wnd) {
335 if (wwnd && wwnd->decoration()) {
337 wwnd->decoration()->margins().top());
338 }
339 }
340 return pnt;
341}
342
344{
345 if (response.isAccepted()) {
346 if (version() >= 3)
348
350 } else {
352 }
353}
354
356{
357
359 if (actions & Qt::CopyAction)
363
364 // wayland does not support LinkAction at the time of writing
365 return wlActions;
366}
367
368
369#endif // QT_CONFIG(draganddrop)
370
371}
372
373QT_END_NAMESPACE
374
375#include "moc_qwaylanddatadevice_p.cpp"
QWaylandDataSource * selectionSource() const
QWaylandDataOffer * selectionOffer() const
void setSelectionSource(QWaylandDataSource *source)
Combined button and popup list for selecting options.