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
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.data();
54
}
55
56
void
QWaylandDataDevice
::
invalidateSelectionOffer
()
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
68
QWaylandDataSource *
QWaylandDataDevice
::
selectionSource
()
const
69
{
70
return
m_selectionSource.data();
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
.
data
();
85
}
86
87
bool
QWaylandDataDevice
::
startDrag
(
QMimeData
*
mimeData
,
Qt
::
DropActions
supportedActions
,
QWaylandWindow
*
icon
)
88
{
89
auto
*
origin
=
m_display
->
lastInputWindow
();
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
.
data
(), &
QWaylandDataSource
::
cancelled
,
this
, &
QWaylandDataDevice
::
dragSourceCancelled
);
114
connect
(
m_dragSource
.
data
(), &
QWaylandDataSource
::
dndResponseUpdated
,
this
, [
this
](
bool
accepted
,
Qt
::
DropAction
action
) {
115
auto
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
());
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) {
121
drag
->
setResponse
(
accepted
);
122
}
else
{
123
QPlatformDropQtResponse
response
(
accepted
,
action
);
124
drag
->
setResponse
(
response
);
125
}
126
});
127
connect
(
m_dragSource
.
data
(), &
QWaylandDataSource
::
dndDropped
,
this
,
128
[
this
](
bool
accepted
,
Qt
::
DropAction
action
) {
129
QPlatformDropQtResponse
response
(
accepted
,
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
}
138
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())
139
->
setDropResponse
(
response
);
140
});
141
connect
(
m_dragSource
.
data
(), &
QWaylandDataSource
::
finished
,
this
, [
this
]() {
142
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
finishDrag
();
143
if
(
m_toplevelDrag
) {
144
m_toplevelDrag
->
destroy
();
145
m_toplevelDrag
=
nullptr
;
146
}
147
});
148
149
if
(
mimeData
->
hasFormat
(
"application/x-qt-mainwindowdrag-window"_L1
)
150
&&
m_display
->
xdgToplevelDragManager
()) {
151
qintptr
dockWindowPtr
;
152
QPoint
offset
;
153
QDataStream
windowStream
(
mimeData
->
data
(
"application/x-qt-mainwindowdrag-window"_L1
));
154
windowStream
>>
dockWindowPtr
;
155
QWindow
*
dockWindow
=
reinterpret_cast
<
QWindow
*>(
dockWindowPtr
);
156
QDataStream
offsetStream
(
mimeData
->
data
(
"application/x-qt-mainwindowdrag-position"_L1
));
157
offsetStream
>>
offset
;
158
if
(
auto
waylandWindow
=
static_cast
<
QWaylandWindow
*>(
dockWindow
->
handle
())) {
159
if
(
auto
toplevel
=
waylandWindow
->
surfaceRole
<
xdg_toplevel
>()) {
160
m_toplevelDrag
=
new
QtWayland
::
xdg_toplevel_drag_v1
(
161
m_display
->
xdgToplevelDragManager
()->
get_xdg_toplevel_drag
(
162
m_dragSource
->
object
()));
163
m_toplevelDrag
->
attach
(
toplevel
,
offset
.
x
(),
offset
.
y
());
164
}
165
}
166
}
167
168
start_drag
(
m_dragSource
->
object
(),
origin
->
wlSurface
(),
icon
->
wlSurface
(),
m_display
->
lastInputSerial
());
169
return
true
;
170
}
171
172
void
QWaylandDataDevice
::
cancelDrag
()
173
{
174
m_dragSource
.
reset
();
175
}
176
#
endif
177
178
void
QWaylandDataDevice
::data_device_data_offer(
struct
::wl_data_offer *id)
179
{
180
new
QWaylandDataOffer(m_display, id);
181
}
182
183
#
if
QT_CONFIG
(
draganddrop
)
184
void
QWaylandDataDevice
::
data_device_drop
()
185
{
186
QDrag
*
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
187
188
QMimeData
*
dragData
=
nullptr
;
189
Qt
::
DropActions
supportedActions
;
190
if
(
drag
) {
191
dragData
=
drag
->
mimeData
();
192
supportedActions
=
drag
->
supportedActions
();
193
}
else
if
(
m_dragOffer
) {
194
dragData
=
m_dragOffer
->
mimeData
();
195
supportedActions
=
m_dragOffer
->
supportedActions
();
196
}
else
{
197
return
;
198
}
199
200
QPlatformDropQtResponse
response
=
QWindowSystemInterface
::
handleDrop
(
m_dragWindow
,
dragData
,
m_dragPoint
,
supportedActions
,
201
QGuiApplication
::
mouseButtons
(),
202
m_inputDevice
->
modifiers
());
203
204
// re-evaluate as it could have changed during user code above
205
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
206
if
(
drag
) {
207
auto
platformDrag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
());
208
platformDrag
->
setDropResponse
(
response
);
209
platformDrag
->
finishDrag
();
210
}
else
if
(
m_dragOffer
&&
response
.
isAccepted
()) {
211
m_dragOffer
->
finish
();
212
}
213
}
214
215
void
QWaylandDataDevice
::
data_device_enter
(
uint32_t
serial
,
wl_surface
*
surface
,
wl_fixed_t
x
,
wl_fixed_t
y
,
wl_data_offer
*
id
)
216
{
217
auto
*
dragWaylandWindow
=
surface
?
QWaylandWindow
::
fromWlSurface
(
surface
) :
nullptr
;
218
if
(!
dragWaylandWindow
)
219
return
;
// Ignore foreign surfaces
220
221
m_dragWindow
=
dragWaylandWindow
->
window
();
222
m_dragPoint
=
calculateDragPosition
(
x
,
y
,
m_dragWindow
);
223
m_enterSerial
=
serial
;
224
225
QMimeData
*
dragData
=
nullptr
;
226
Qt
::
DropActions
supportedActions
;
227
228
m_dragOffer
.
reset
(
static_cast
<
QWaylandDataOffer
*>(
wl_data_offer_get_user_data
(
id
)));
229
QDrag
*
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
230
if
(
drag
) {
231
dragData
=
drag
->
mimeData
();
232
supportedActions
=
drag
->
supportedActions
();
233
}
else
if
(
m_dragOffer
) {
234
dragData
=
m_dragOffer
->
mimeData
();
235
supportedActions
=
m_dragOffer
->
supportedActions
();
236
}
237
238
const
QPlatformDragQtResponse
&
response
=
QWindowSystemInterface
::
handleDrag
(
239
m_dragWindow
,
dragData
,
m_dragPoint
,
supportedActions
,
QGuiApplication
::
mouseButtons
(),
240
m_inputDevice
->
modifiers
());
241
if
(
drag
) {
242
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
setResponse
(
response
);
243
}
244
245
sendResponse
(
supportedActions
,
response
);
246
}
247
248
void
QWaylandDataDevice
::
data_device_leave
()
249
{
250
if
(
m_dragWindow
)
251
QWindowSystemInterface
::
handleDrag
(
m_dragWindow
,
nullptr
,
QPoint
(),
Qt
::
IgnoreAction
,
252
QGuiApplication
::
mouseButtons
(),
253
m_inputDevice
->
modifiers
());
254
255
QDrag
*
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
256
if
(!
drag
) {
257
m_dragOffer
.
reset
();
258
}
259
}
260
261
void
QWaylandDataDevice
::
data_device_motion
(
uint32_t
time
,
wl_fixed_t
x
,
wl_fixed_t
y
)
262
{
263
Q_UNUSED
(
time
);
264
265
QDrag
*
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
266
267
if
(!
drag
&& !
m_dragOffer
)
268
return
;
269
270
if
(!
m_dragWindow
)
271
return
;
272
273
m_dragPoint
=
calculateDragPosition
(
x
,
y
,
m_dragWindow
);
274
275
QMimeData
*
dragData
=
nullptr
;
276
Qt
::
DropActions
supportedActions
;
277
if
(
drag
) {
278
dragData
=
drag
->
mimeData
();
279
supportedActions
=
drag
->
supportedActions
();
280
}
else
{
281
dragData
=
m_dragOffer
->
mimeData
();
282
supportedActions
=
m_dragOffer
->
supportedActions
();
283
}
284
285
const
QPlatformDragQtResponse
response
=
QWindowSystemInterface
::
handleDrag
(
m_dragWindow
,
dragData
,
m_dragPoint
,
supportedActions
,
286
QGuiApplication
::
mouseButtons
(),
287
m_inputDevice
->
modifiers
());
288
289
if
(
drag
) {
290
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
setResponse
(
response
);
291
}
292
293
sendResponse
(
supportedActions
,
response
);
294
}
295
#
endif
// QT_CONFIG(draganddrop)
296
297
void
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
309
void
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
)
318
void
QWaylandDataDevice
::
dragSourceCancelled
()
319
{
320
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
finishDrag
();
321
m_dragSource
.
reset
();
322
if
(
m_toplevelDrag
) {
323
m_toplevelDrag
->
destroy
();
324
m_toplevelDrag
=
nullptr
;
325
}
326
}
327
328
QPoint
QWaylandDataDevice
::
calculateDragPosition
(
int
x
,
int
y
,
QWindow
*
wnd
)
const
329
{
330
QPoint
pnt
(
wl_fixed_to_int
(
x
),
wl_fixed_to_int
(
y
));
331
if
(
wnd
) {
332
QWaylandWindow
*
wwnd
=
static_cast
<
QWaylandWindow
*>(
m_dragWindow
->
handle
());
333
if
(
wwnd
&&
wwnd
->
decoration
()) {
334
pnt
-=
QPoint
(
wwnd
->
decoration
()->
margins
().
left
(),
335
wwnd
->
decoration
()->
margins
().
top
());
336
}
337
}
338
return
pnt
;
339
}
340
341
void
QWaylandDataDevice
::
sendResponse
(
Qt
::
DropActions
supportedActions
,
const
QPlatformDragQtResponse
&
response
)
342
{
343
if
(
response
.
isAccepted
()) {
344
if
(
version
() >= 3)
345
m_dragOffer
->
set_actions
(
dropActionsToWl
(
supportedActions
),
dropActionsToWl
(
response
.
acceptedAction
()));
346
347
m_dragOffer
->
accept
(
m_enterSerial
,
m_dragOffer
->
firstFormat
());
348
}
else
{
349
m_dragOffer
->
accept
(
m_enterSerial
,
QString
());
350
}
351
}
352
353
int
QWaylandDataDevice
::
dropActionsToWl
(
Qt
::
DropActions
actions
)
354
{
355
356
int
wlActions
=
WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE
;
357
if
(
actions
&
Qt
::
CopyAction
)
358
wlActions
|=
WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY
;
359
if
(
actions
& (
Qt
::
MoveAction
|
Qt
::
TargetMoveAction
))
360
wlActions
|=
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE
;
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
371
QT_END_NAMESPACE
372
373
#
include
"moc_qwaylanddatadevice_p.cpp"
QtWaylandClient::QWaylandDataDevice
Definition
qwaylanddatadevice_p.h:49
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
qrandomaccessasyncfile_darwin.mm:17
QtWaylandClient
Definition
qwaylandclientextension.h:16
qtbase
src
plugins
platforms
wayland
qwaylanddatadevice.cpp
Generated on
for Qt by
1.16.1