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.data();
54}
55
57{
58 if (m_selectionOffer.isNull())
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.data();
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.data();
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 if (!drag->currentDrag()) {
117 return;
118 }
119 // in old versions drop action is not set, so we guess
120 if (m_dragSource->version() < 3) {
122 } else {
125 }
126 });
128 [this](bool accepted, Qt::DropAction action) {
130 if (m_toplevelDrag) {
131 // If the widget was dropped but the drag not accepted it
132 // should be its own window in the future. To distinguish
133 // from canceling mid-drag the drag is accepted here as the
134 // we know if the widget is over a zone where it can be
135 // incorporated or not
136 response = { true, Qt::MoveAction };
137 }
140 });
143 if (m_toplevelDrag) {
145 m_toplevelDrag = nullptr;
146 }
147 });
148
149 if (mimeData->hasFormat("application/x-qt-mainwindowdrag-window"_L1)
153 QDataStream windowStream(mimeData->data("application/x-qt-mainwindowdrag-window"_L1));
155 QWindow *dockWindow = reinterpret_cast<QWindow *>(dockWindowPtr);
156 QDataStream offsetStream(mimeData->data("application/x-qt-mainwindowdrag-position"_L1));
158 if (auto waylandWindow = static_cast<QWaylandWindow *>(dockWindow->handle())) {
162 m_dragSource->object()));
164 }
165 }
166 }
167
169 return true;
170}
171
173{
175}
176#endif
177
178void QWaylandDataDevice::data_device_data_offer(struct ::wl_data_offer *id)
179{
180 new QWaylandDataOffer(m_display, id);
181}
182
183#if QT_CONFIG(draganddrop)
185{
187
188 QMimeData *dragData = nullptr;
190 if (drag) {
193 } else if (m_dragOffer) {
196 } else {
197 return;
198 }
199
203
204 // re-evaluate as it could have changed during user code above
206 if (drag) {
210 } else if (m_dragOffer && response.isAccepted()) {
212 }
213}
214
216{
219 return; // Ignore foreign surfaces
220
224
225 QMimeData *dragData = nullptr;
227
230 if (drag) {
233 } else if (m_dragOffer) {
236 }
237
241 if (drag) {
243 }
244
246}
247
249{
250 if (m_dragWindow)
254
256 if (!drag) {
258 }
259}
260
262{
263 Q_UNUSED(time);
264
266
267 if (!drag && !m_dragOffer)
268 return;
269
270 if (!m_dragWindow)
271 return;
272
274
275 QMimeData *dragData = nullptr;
277 if (drag) {
280 } else {
283 }
284
288
289 if (drag) {
291 }
292
294}
295#endif // QT_CONFIG(draganddrop)
296
297void QWaylandDataDevice::data_device_selection(wl_data_offer *id)
298{
299 if (id)
300 m_selectionOffer.reset(static_cast<QWaylandDataOffer *>(wl_data_offer_get_user_data(id)));
301 else
302 m_selectionOffer.reset();
303
304#if QT_CONFIG(clipboard)
305 QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
306#endif
307}
308
309void QWaylandDataDevice::selectionSourceCancelled()
310{
311 m_selectionSource.reset();
312#if QT_CONFIG(clipboard)
313 QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
314#endif
315}
316
317#if QT_CONFIG(draganddrop)
319{
322 if (m_toplevelDrag) {
324 m_toplevelDrag = nullptr;
325 }
326}
327
329{
331 if (wnd) {
333 if (wwnd && wwnd->decoration()) {
335 wwnd->decoration()->margins().top());
336 }
337 }
338 return pnt;
339}
340
342{
343 if (response.isAccepted()) {
344 if (version() >= 3)
346
348 } else {
350 }
351}
352
354{
355
357 if (actions & Qt::CopyAction)
361
362 // wayland does not support LinkAction at the time of writing
363 return wlActions;
364}
365
366
367#endif // QT_CONFIG(draganddrop)
368
369}
370
371QT_END_NAMESPACE
372
373#include "moc_qwaylanddatadevice_p.cpp"
QWaylandDataSource * selectionSource() const
QWaylandDataOffer * selectionOffer() const
void setSelectionSource(QWaylandDataSource *source)
Combined button and popup list for selecting options.