Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
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
6
#
include
"qwaylanddatadevice_p.h"
7
8
#
include
"qwaylanddatadevicemanager_p.h"
9
#
include
"qwaylanddataoffer_p.h"
10
#
include
"qwaylanddatasource_p.h"
11
#
include
"qwaylanddnd_p.h"
12
#
include
"qwaylandinputdevice_p.h"
13
#
include
"qwaylanddisplay_p.h"
14
#
include
"qwaylandabstractdecoration_p.h"
15
#
include
"qwaylandsurface_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
29
QT_BEGIN_NAMESPACE
30
31
namespace
QtWaylandClient
{
32
33
using
namespace
Qt
::
StringLiterals
;
34
35
QWaylandDataDevice
::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
43
QWaylandDataDevice
::~
QWaylandDataDevice
()
44
{
45
if
(version() >= WL_DATA_DEVICE_RELEASE_SINCE_VERSION)
46
release();
47
else
48
wl_data_device_destroy(object());
49
}
50
51
QWaylandDataOffer *
QWaylandDataDevice
::
selectionOffer
()
const
52
{
53
return
m_selectionOffer.get();
54
}
55
56
void
QWaylandDataDevice
::
invalidateSelectionOffer
()
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
68
QWaylandDataSource *
QWaylandDataDevice
::
selectionSource
()
const
69
{
70
return
m_selectionSource.get();
71
}
72
73
void
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
)
82
QWaylandDataOffer
*
QWaylandDataDevice
::
dragOffer
()
const
83
{
84
return
m_dragOffer
.
get
();
85
}
86
87
bool
QWaylandDataDevice
::
startDrag
(
QMimeData
*
mimeData
,
Qt
::
DropActions
supportedActions
,
QWaylandWindow
*
icon
)
88
{
89
auto
*
origin
=
m_display
->
lastInputSurface
();
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
105
if
(
mimeData
->
hasFormat
(
plain
) && !
mimeData
->
hasFormat
(
utf8
))
106
mimeData
->
setData
(
utf8
,
mimeData
->
data
(
plain
));
107
108
m_dragSource
.
reset
(
new
QWaylandDataSource
(
m_display
->
dndSelectionHandler
(),
mimeData
));
109
110
if
(
version
() >= 3)
111
m_dragSource
->
set_actions
(
dropActionsToWl
(
supportedActions
));
112
113
connect
(
m_dragSource
.
get
(), &
QWaylandDataSource
::
cancelled
,
114
this
, &
QWaylandDataDevice
::
dragSourceCancelled
);
115
connect
(
m_dragSource
.
get
(), &
QWaylandDataSource
::
dndResponseUpdated
,
116
this
, [
this
](
bool
accepted
,
Qt
::
DropAction
action
) {
117
auto
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
());
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) {
123
drag
->
setResponse
(
accepted
);
124
}
else
{
125
QPlatformDropQtResponse
response
(
accepted
,
action
);
126
drag
->
setResponse
(
response
);
127
}
128
});
129
connect
(
m_dragSource
.
get
(), &
QWaylandDataSource
::
dndDropped
,
130
this
, [
this
](
bool
accepted
,
Qt
::
DropAction
action
) {
131
QPlatformDropQtResponse
response
(
accepted
,
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
}
140
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())
141
->
setDropResponse
(
response
);
142
});
143
connect
(
m_dragSource
.
get
(), &
QWaylandDataSource
::
finished
,
this
, [
this
]() {
144
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
finishDrag
();
145
if
(
m_toplevelDrag
) {
146
m_toplevelDrag
->
destroy
();
147
m_toplevelDrag
=
nullptr
;
148
}
149
});
150
151
if
(
mimeData
->
hasFormat
(
"application/x-qt-mainwindowdrag-window"_L1
)
152
&&
m_display
->
xdgToplevelDragManager
()) {
153
qintptr
dockWindowPtr
;
154
QPoint
offset
;
155
QDataStream
windowStream
(
mimeData
->
data
(
"application/x-qt-mainwindowdrag-window"_L1
));
156
windowStream
>>
dockWindowPtr
;
157
QWindow
*
dockWindow
=
reinterpret_cast
<
QWindow
*>(
dockWindowPtr
);
158
QDataStream
offsetStream
(
mimeData
->
data
(
"application/x-qt-mainwindowdrag-position"_L1
));
159
offsetStream
>>
offset
;
160
if
(
auto
waylandWindow
=
static_cast
<
QWaylandWindow
*>(
dockWindow
->
handle
())) {
161
if
(
auto
toplevel
=
waylandWindow
->
surfaceRole
<
xdg_toplevel
>()) {
162
m_toplevelDrag
=
new
QtWayland
::
xdg_toplevel_drag_v1
(
163
m_display
->
xdgToplevelDragManager
()->
get_xdg_toplevel_drag
(
164
m_dragSource
->
object
()));
165
m_toplevelDrag
->
attach
(
toplevel
,
offset
.
x
(),
offset
.
y
());
166
}
167
}
168
}
169
170
start_drag
(
m_dragSource
->
object
(),
origin
->
object
(),
icon
->
wlSurface
(),
m_display
->
lastInputSerial
());
171
return
true
;
172
}
173
174
void
QWaylandDataDevice
::
cancelDrag
()
175
{
176
m_dragSource
.
reset
();
177
}
178
#
endif
179
180
void
QWaylandDataDevice
::data_device_data_offer(
struct
::wl_data_offer *id)
181
{
182
new
QWaylandDataOffer(m_display, id);
183
}
184
185
#
if
QT_CONFIG
(
draganddrop
)
186
void
QWaylandDataDevice
::
data_device_drop
()
187
{
188
QDrag
*
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
189
190
QMimeData
*
dragData
=
nullptr
;
191
Qt
::
DropActions
supportedActions
;
192
if
(
drag
) {
193
dragData
=
drag
->
mimeData
();
194
supportedActions
=
drag
->
supportedActions
();
195
}
else
if
(
m_dragOffer
) {
196
dragData
=
m_dragOffer
->
mimeData
();
197
supportedActions
=
m_dragOffer
->
supportedActions
();
198
}
else
{
199
return
;
200
}
201
202
QPlatformDropQtResponse
response
=
QWindowSystemInterface
::
handleDrop
(
m_dragWindow
,
dragData
,
m_dragPoint
,
supportedActions
,
203
QGuiApplication
::
mouseButtons
(),
204
m_inputDevice
->
modifiers
());
205
206
// re-evaluate as it could have changed during user code above
207
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
208
if
(
drag
) {
209
auto
platformDrag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
());
210
platformDrag
->
setDropResponse
(
response
);
211
platformDrag
->
finishDrag
();
212
}
else
if
(
m_dragOffer
213
&&
response
.
isAccepted
()
214
&&
m_dragOffer
->
version
() >=
WL_DATA_OFFER_FINISH_SINCE_VERSION
) {
215
m_dragOffer
->
finish
();
216
}
217
}
218
219
void
QWaylandDataDevice
::
data_device_enter
(
uint32_t
serial
,
wl_surface
*
surface
,
wl_fixed_t
x_fixed
,
wl_fixed_t
y_fixed
,
wl_data_offer
*
id
)
220
{
221
const
qreal
x
=
wl_fixed_to_double
(
x_fixed
);
222
const
qreal
y
=
wl_fixed_to_double
(
y_fixed
);
223
auto
*
dragWaylandSurface
=
surface
?
QWaylandSurface
::
fromWlSurface
(
surface
) :
nullptr
;
224
if
(!
dragWaylandSurface
)
225
return
;
226
227
auto
dragWaylandWindow
=
dragWaylandSurface
->
waylandWindow
();
228
if
(!
dragWaylandWindow
)
229
return
;
// Ignore foreign surfaces
230
231
m_dragWindow
=
dragWaylandWindow
->
window
();
232
m_dragPoint
=
QPoint
(
x
,
y
);
233
m_enterSerial
=
serial
;
234
235
QMimeData
*
dragData
=
nullptr
;
236
Qt
::
DropActions
supportedActions
;
237
238
m_dragOffer
.
reset
(
static_cast
<
QWaylandDataOffer
*>(
wl_data_offer_get_user_data
(
id
)));
239
QDrag
*
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
240
if
(
drag
) {
241
dragData
=
drag
->
mimeData
();
242
supportedActions
=
drag
->
supportedActions
();
243
}
else
if
(
m_dragOffer
) {
244
dragData
=
m_dragOffer
->
mimeData
();
245
supportedActions
=
m_dragOffer
->
supportedActions
();
246
}
247
248
const
QPlatformDragQtResponse
&
response
=
QWindowSystemInterface
::
handleDrag
(
249
m_dragWindow
,
dragData
,
m_dragPoint
,
supportedActions
,
QGuiApplication
::
mouseButtons
(),
250
m_inputDevice
->
modifiers
());
251
if
(
drag
) {
252
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
setResponse
(
response
);
253
}
254
255
sendResponse
(
supportedActions
,
response
);
256
}
257
258
void
QWaylandDataDevice
::
data_device_leave
()
259
{
260
if
(
m_dragWindow
)
261
QWindowSystemInterface
::
handleDrag
(
m_dragWindow
,
nullptr
,
QPoint
(),
Qt
::
IgnoreAction
,
262
QGuiApplication
::
mouseButtons
(),
263
m_inputDevice
->
modifiers
());
264
265
QDrag
*
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
266
if
(!
drag
) {
267
m_dragOffer
.
reset
();
268
}
269
}
270
271
void
QWaylandDataDevice
::
data_device_motion
(
uint32_t
time
,
wl_fixed_t
x_fixed
,
wl_fixed_t
y_fixed
)
272
{
273
Q_UNUSED
(
time
);
274
const
qreal
x
=
wl_fixed_to_double
(
x_fixed
);
275
const
qreal
y
=
wl_fixed_to_double
(
y_fixed
);
276
277
QDrag
*
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
278
279
if
(!
drag
&& !
m_dragOffer
)
280
return
;
281
282
if
(!
m_dragWindow
)
283
return
;
284
285
m_dragPoint
=
QPoint
(
x
,
y
);
286
287
QMimeData
*
dragData
=
nullptr
;
288
Qt
::
DropActions
supportedActions
;
289
if
(
drag
) {
290
dragData
=
drag
->
mimeData
();
291
supportedActions
=
drag
->
supportedActions
();
292
}
else
{
293
dragData
=
m_dragOffer
->
mimeData
();
294
supportedActions
=
m_dragOffer
->
supportedActions
();
295
}
296
297
const
QPlatformDragQtResponse
response
=
QWindowSystemInterface
::
handleDrag
(
m_dragWindow
,
dragData
,
m_dragPoint
,
supportedActions
,
298
QGuiApplication
::
mouseButtons
(),
299
m_inputDevice
->
modifiers
());
300
301
if
(
drag
) {
302
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
setResponse
(
response
);
303
}
304
305
sendResponse
(
supportedActions
,
response
);
306
}
307
#
endif
// QT_CONFIG(draganddrop)
308
309
void
QWaylandDataDevice
::data_device_selection(wl_data_offer *id)
310
{
311
if
(id)
312
m_selectionOffer.reset(
static_cast
<QWaylandDataOffer *>(wl_data_offer_get_user_data(id)));
313
else
314
m_selectionOffer.reset();
315
316
#
if
QT_CONFIG
(
clipboard
)
317
QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
318
#
endif
319
}
320
321
void
QWaylandDataDevice
::selectionSourceCancelled()
322
{
323
m_selectionSource.reset();
324
#
if
QT_CONFIG
(
clipboard
)
325
QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
326
#
endif
327
}
328
329
#
if
QT_CONFIG
(
draganddrop
)
330
void
QWaylandDataDevice
::
dragSourceCancelled
()
331
{
332
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
finishDrag
();
333
m_dragSource
.
reset
();
334
if
(
m_toplevelDrag
) {
335
m_toplevelDrag
->
destroy
();
336
m_toplevelDrag
=
nullptr
;
337
}
338
}
339
340
void
QWaylandDataDevice
::
sendResponse
(
Qt
::
DropActions
supportedActions
,
const
QPlatformDragQtResponse
&
response
)
341
{
342
if
(
response
.
isAccepted
()) {
343
if
(
version
() >= 3)
344
m_dragOffer
->
set_actions
(
dropActionsToWl
(
supportedActions
),
dropActionsToWl
(
response
.
acceptedAction
()));
345
346
m_dragOffer
->
accept
(
m_enterSerial
,
m_dragOffer
->
firstFormat
());
347
}
else
{
348
m_dragOffer
->
accept
(
m_enterSerial
,
QString
());
349
}
350
}
351
352
int
QWaylandDataDevice
::
dropActionsToWl
(
Qt
::
DropActions
actions
)
353
{
354
355
int
wlActions
=
WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE
;
356
if
(
actions
&
Qt
::
CopyAction
)
357
wlActions
|=
WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY
;
358
if
(
actions
& (
Qt
::
MoveAction
|
Qt
::
TargetMoveAction
))
359
wlActions
|=
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE
;
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
370
QT_END_NAMESPACE
371
372
#
include
"moc_qwaylanddatadevice_p.cpp"
QtWaylandClient::QWaylandDataDevice
Definition
qwaylanddatadevice_p.h:51
QtWaylandClient::QWaylandDataDevice::~QWaylandDataDevice
~QWaylandDataDevice() override
Definition
qwaylanddatadevice.cpp:43
QtWaylandClient::QWaylandDataDevice::selectionSource
QWaylandDataSource * selectionSource() const
Definition
qwaylanddatadevice.cpp:68
QtWaylandClient::QWaylandDataDevice::selectionOffer
QWaylandDataOffer * selectionOffer() const
Definition
qwaylanddatadevice.cpp:51
QtWaylandClient::QWaylandDataDevice::setSelectionSource
void setSelectionSource(QWaylandDataSource *source)
Definition
qwaylanddatadevice.cpp:73
QtWaylandClient::QWaylandDataDevice::invalidateSelectionOffer
void invalidateSelectionOffer()
Definition
qwaylanddatadevice.cpp:56
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
QtWaylandClient
Definition
qwaylandclientextension.h:16
qtbase
src
plugins
platforms
wayland
qwaylanddatadevice.cpp
Generated on
for Qt by
1.18.0