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
4
5
#
include
"qwaylanddatadevice_p.h"
6
7
#
include
"qwaylanddatadevicemanager_p.h"
8
#
include
"qwaylanddataoffer_p.h"
9
#
include
"qwaylanddatasource_p.h"
10
#
include
"qwaylanddnd_p.h"
11
#
include
"qwaylandinputdevice_p.h"
12
#
include
"qwaylanddisplay_p.h"
13
#
include
"qwaylandabstractdecoration_p.h"
14
#
include
"qwaylandsurface_p.h"
15
16
#
include
<
QtWaylandClient
/
private
/
qwayland
-
xdg
-
toplevel
-
drag
-
v1
.
h
>
17
18
#
include
<
QtCore
/
QMimeData
>
19
#
include
<
QtGui
/
QGuiApplication
>
20
#
include
<
QtGui
/
private
/
qguiapplication_p
.
h
>
21
22
#
if
QT_CONFIG
(
clipboard
)
23
#
include
<
qpa
/
qplatformclipboard
.
h
>
24
#
endif
25
#
include
<
qpa
/
qplatformdrag
.
h
>
26
#
include
<
qpa
/
qwindowsysteminterface
.
h
>
27
28
QT_BEGIN_NAMESPACE
29
30
namespace
QtWaylandClient
{
31
32
using
namespace
Qt
::
StringLiterals
;
33
34
QWaylandDataDevice
::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWaylandInputDevice *inputDevice)
35
: QObject(inputDevice)
36
, QtWayland::wl_data_device(manager->get_data_device(inputDevice->wl_seat()))
37
, m_display(manager->display())
38
, m_inputDevice(inputDevice)
39
{
40
}
41
42
QWaylandDataDevice
::~
QWaylandDataDevice
()
43
{
44
if
(version() >= WL_DATA_DEVICE_RELEASE_SINCE_VERSION)
45
release();
46
else
47
wl_data_device_destroy(object());
48
}
49
50
QWaylandDataOffer *
QWaylandDataDevice
::
selectionOffer
()
const
51
{
52
return
m_selectionOffer.data();
53
}
54
55
void
QWaylandDataDevice
::
invalidateSelectionOffer
()
56
{
57
if
(m_selectionOffer.isNull())
58
return
;
59
60
m_selectionOffer.reset();
61
62
#
if
QT_CONFIG
(
clipboard
)
63
QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
64
#
endif
65
}
66
67
QWaylandDataSource *
QWaylandDataDevice
::
selectionSource
()
const
68
{
69
return
m_selectionSource.data();
70
}
71
72
void
QWaylandDataDevice
::
setSelectionSource
(QWaylandDataSource *source)
73
{
74
if
(source)
75
connect(source, &QWaylandDataSource::cancelled,
this
, &QWaylandDataDevice::selectionSourceCancelled);
76
set_selection(source ? source->object() :
nullptr
, m_inputDevice->serial());
77
m_selectionSource.reset(source);
78
}
79
80
#
if
QT_CONFIG
(
draganddrop
)
81
QWaylandDataOffer
*
QWaylandDataDevice
::
dragOffer
()
const
82
{
83
return
m_dragOffer
.
data
();
84
}
85
86
bool
QWaylandDataDevice
::
startDrag
(
QMimeData
*
mimeData
,
Qt
::
DropActions
supportedActions
,
QWaylandWindow
*
icon
)
87
{
88
auto
*
origin
=
m_display
->
lastInputWindow
();
89
90
if
(!
origin
) {
91
qCDebug
(
lcQpaWayland
) <<
"Couldn't start a drag because the origin window could not be found."
;
92
return
false
;
93
}
94
95
// dragging data without mimetypes is a legal operation in Qt terms
96
// but Wayland uses a mimetype to determine if a drag is accepted or not
97
// In this rare case, insert a placeholder
98
if
(
mimeData
->
formats
().
isEmpty
())
99
mimeData
->
setData
(
"application/x-qt-avoid-empty-placeholder"_L1
,
QByteArray
(
"1"
));
100
101
static
const
QString
plain
=
QStringLiteral
(
"text/plain"
);
102
static
const
QString
utf8
=
QStringLiteral
(
"text/plain;charset=utf-8"
);
103
104
if
(
mimeData
->
hasFormat
(
plain
) && !
mimeData
->
hasFormat
(
utf8
))
105
mimeData
->
setData
(
utf8
,
mimeData
->
data
(
plain
));
106
107
m_dragSource
.
reset
(
new
QWaylandDataSource
(
m_display
->
dndSelectionHandler
(),
mimeData
));
108
109
if
(
version
() >= 3)
110
m_dragSource
->
set_actions
(
dropActionsToWl
(
supportedActions
));
111
112
connect
(
m_dragSource
.
data
(), &
QWaylandDataSource
::
cancelled
,
this
, &
QWaylandDataDevice
::
dragSourceCancelled
);
113
connect
(
m_dragSource
.
data
(), &
QWaylandDataSource
::
dndResponseUpdated
,
this
, [
this
](
bool
accepted
,
Qt
::
DropAction
action
) {
114
auto
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
());
115
if
(!
drag
->
currentDrag
()) {
116
return
;
117
}
118
// in old versions drop action is not set, so we guess
119
if
(
m_dragSource
->
version
() < 3) {
120
drag
->
setResponse
(
accepted
);
121
}
else
{
122
QPlatformDropQtResponse
response
(
accepted
,
action
);
123
drag
->
setResponse
(
response
);
124
}
125
});
126
connect
(
m_dragSource
.
data
(), &
QWaylandDataSource
::
dndDropped
,
this
,
127
[
this
](
bool
accepted
,
Qt
::
DropAction
action
) {
128
QPlatformDropQtResponse
response
(
accepted
,
action
);
129
if
(
m_toplevelDrag
) {
130
// If the widget was dropped but the drag not accepted it
131
// should be its own window in the future. To distinguish
132
// from canceling mid-drag the drag is accepted here as the
133
// we know if the widget is over a zone where it can be
134
// incorporated or not
135
response
= {
true
,
Qt
::
MoveAction
};
136
}
137
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())
138
->
setDropResponse
(
response
);
139
});
140
connect
(
m_dragSource
.
data
(), &
QWaylandDataSource
::
finished
,
this
, [
this
]() {
141
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
finishDrag
();
142
if
(
m_toplevelDrag
) {
143
m_toplevelDrag
->
destroy
();
144
m_toplevelDrag
=
nullptr
;
145
}
146
});
147
148
if
(
mimeData
->
hasFormat
(
"application/x-qt-mainwindowdrag-window"_L1
)
149
&&
m_display
->
xdgToplevelDragManager
()) {
150
qintptr
dockWindowPtr
;
151
QPoint
offset
;
152
QDataStream
windowStream
(
mimeData
->
data
(
"application/x-qt-mainwindowdrag-window"_L1
));
153
windowStream
>>
dockWindowPtr
;
154
QWindow
*
dockWindow
=
reinterpret_cast
<
QWindow
*>(
dockWindowPtr
);
155
QDataStream
offsetStream
(
mimeData
->
data
(
"application/x-qt-mainwindowdrag-position"_L1
));
156
offsetStream
>>
offset
;
157
if
(
auto
waylandWindow
=
static_cast
<
QWaylandWindow
*>(
dockWindow
->
handle
())) {
158
if
(
auto
toplevel
=
waylandWindow
->
surfaceRole
<
xdg_toplevel
>()) {
159
m_toplevelDrag
=
new
QtWayland
::
xdg_toplevel_drag_v1
(
160
m_display
->
xdgToplevelDragManager
()->
get_xdg_toplevel_drag
(
161
m_dragSource
->
object
()));
162
m_toplevelDrag
->
attach
(
toplevel
,
offset
.
x
(),
offset
.
y
());
163
}
164
}
165
}
166
167
start_drag
(
m_dragSource
->
object
(),
origin
->
wlSurface
(),
icon
->
wlSurface
(),
m_display
->
lastInputSerial
());
168
return
true
;
169
}
170
171
void
QWaylandDataDevice
::
cancelDrag
()
172
{
173
m_dragSource
.
reset
();
174
}
175
#
endif
176
177
void
QWaylandDataDevice
::data_device_data_offer(
struct
::wl_data_offer *id)
178
{
179
new
QWaylandDataOffer(m_display, id);
180
}
181
182
#
if
QT_CONFIG
(
draganddrop
)
183
void
QWaylandDataDevice
::
data_device_drop
()
184
{
185
QDrag
*
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
186
187
QMimeData
*
dragData
=
nullptr
;
188
Qt
::
DropActions
supportedActions
;
189
if
(
drag
) {
190
dragData
=
drag
->
mimeData
();
191
supportedActions
=
drag
->
supportedActions
();
192
}
else
if
(
m_dragOffer
) {
193
dragData
=
m_dragOffer
->
mimeData
();
194
supportedActions
=
m_dragOffer
->
supportedActions
();
195
}
else
{
196
return
;
197
}
198
199
QPlatformDropQtResponse
response
=
QWindowSystemInterface
::
handleDrop
(
m_dragWindow
,
dragData
,
m_dragPoint
,
supportedActions
,
200
QGuiApplication
::
mouseButtons
(),
201
m_inputDevice
->
modifiers
());
202
203
// re-evaluate as it could have changed during user code above
204
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
205
if
(
drag
) {
206
auto
platformDrag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
());
207
platformDrag
->
setDropResponse
(
response
);
208
platformDrag
->
finishDrag
();
209
}
else
if
(
m_dragOffer
) {
210
m_dragOffer
->
finish
();
211
}
212
}
213
214
void
QWaylandDataDevice
::
data_device_enter
(
uint32_t
serial
,
wl_surface
*
surface
,
wl_fixed_t
x
,
wl_fixed_t
y
,
wl_data_offer
*
id
)
215
{
216
auto
*
dragWaylandWindow
=
surface
?
QWaylandWindow
::
fromWlSurface
(
surface
) :
nullptr
;
217
if
(!
dragWaylandWindow
)
218
return
;
// Ignore foreign surfaces
219
220
m_dragWindow
=
dragWaylandWindow
->
window
();
221
m_dragPoint
=
calculateDragPosition
(
x
,
y
,
m_dragWindow
);
222
m_enterSerial
=
serial
;
223
224
QMimeData
*
dragData
=
nullptr
;
225
Qt
::
DropActions
supportedActions
;
226
227
m_dragOffer
.
reset
(
static_cast
<
QWaylandDataOffer
*>(
wl_data_offer_get_user_data
(
id
)));
228
QDrag
*
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
229
if
(
drag
) {
230
dragData
=
drag
->
mimeData
();
231
supportedActions
=
drag
->
supportedActions
();
232
}
else
if
(
m_dragOffer
) {
233
dragData
=
m_dragOffer
->
mimeData
();
234
supportedActions
=
m_dragOffer
->
supportedActions
();
235
}
236
237
const
QPlatformDragQtResponse
&
response
=
QWindowSystemInterface
::
handleDrag
(
238
m_dragWindow
,
dragData
,
m_dragPoint
,
supportedActions
,
QGuiApplication
::
mouseButtons
(),
239
m_inputDevice
->
modifiers
());
240
if
(
drag
) {
241
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
setResponse
(
response
);
242
}
243
244
sendResponse
(
supportedActions
,
response
);
245
}
246
247
void
QWaylandDataDevice
::
data_device_leave
()
248
{
249
if
(
m_dragWindow
)
250
QWindowSystemInterface
::
handleDrag
(
m_dragWindow
,
nullptr
,
QPoint
(),
Qt
::
IgnoreAction
,
251
QGuiApplication
::
mouseButtons
(),
252
m_inputDevice
->
modifiers
());
253
254
QDrag
*
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
255
if
(!
drag
) {
256
m_dragOffer
.
reset
();
257
}
258
}
259
260
void
QWaylandDataDevice
::
data_device_motion
(
uint32_t
time
,
wl_fixed_t
x
,
wl_fixed_t
y
)
261
{
262
Q_UNUSED
(
time
);
263
264
QDrag
*
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
265
266
if
(!
drag
&& !
m_dragOffer
)
267
return
;
268
269
if
(!
m_dragWindow
)
270
return
;
271
272
m_dragPoint
=
calculateDragPosition
(
x
,
y
,
m_dragWindow
);
273
274
QMimeData
*
dragData
=
nullptr
;
275
Qt
::
DropActions
supportedActions
;
276
if
(
drag
) {
277
dragData
=
drag
->
mimeData
();
278
supportedActions
=
drag
->
supportedActions
();
279
}
else
{
280
dragData
=
m_dragOffer
->
mimeData
();
281
supportedActions
=
m_dragOffer
->
supportedActions
();
282
}
283
284
const
QPlatformDragQtResponse
response
=
QWindowSystemInterface
::
handleDrag
(
m_dragWindow
,
dragData
,
m_dragPoint
,
supportedActions
,
285
QGuiApplication
::
mouseButtons
(),
286
m_inputDevice
->
modifiers
());
287
288
if
(
drag
) {
289
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
setResponse
(
response
);
290
}
291
292
sendResponse
(
supportedActions
,
response
);
293
}
294
#
endif
// QT_CONFIG(draganddrop)
295
296
void
QWaylandDataDevice
::data_device_selection(wl_data_offer *id)
297
{
298
if
(id)
299
m_selectionOffer.reset(
static_cast
<QWaylandDataOffer *>(wl_data_offer_get_user_data(id)));
300
else
301
m_selectionOffer.reset();
302
303
#
if
QT_CONFIG
(
clipboard
)
304
QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
305
#
endif
306
}
307
308
void
QWaylandDataDevice
::selectionSourceCancelled()
309
{
310
m_selectionSource.reset();
311
#
if
QT_CONFIG
(
clipboard
)
312
QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
313
#
endif
314
}
315
316
#
if
QT_CONFIG
(
draganddrop
)
317
void
QWaylandDataDevice
::
dragSourceCancelled
()
318
{
319
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
finishDrag
();
320
m_dragSource
.
reset
();
321
if
(
m_toplevelDrag
) {
322
m_toplevelDrag
->
destroy
();
323
m_toplevelDrag
=
nullptr
;
324
}
325
}
326
327
QPoint
QWaylandDataDevice
::
calculateDragPosition
(
int
x
,
int
y
,
QWindow
*
wnd
)
const
328
{
329
QPoint
pnt
(
wl_fixed_to_int
(
x
),
wl_fixed_to_int
(
y
));
330
if
(
wnd
) {
331
QWaylandWindow
*
wwnd
=
static_cast
<
QWaylandWindow
*>(
m_dragWindow
->
handle
());
332
if
(
wwnd
&&
wwnd
->
decoration
()) {
333
pnt
-=
QPoint
(
wwnd
->
decoration
()->
margins
().
left
(),
334
wwnd
->
decoration
()->
margins
().
top
());
335
}
336
}
337
return
pnt
;
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:48
QtWaylandClient::QWaylandDataDevice::~QWaylandDataDevice
~QWaylandDataDevice() override
Definition
qwaylanddatadevice.cpp:42
QtWaylandClient::QWaylandDataDevice::selectionSource
QWaylandDataSource * selectionSource() const
Definition
qwaylanddatadevice.cpp:67
QtWaylandClient::QWaylandDataDevice::selectionOffer
QWaylandDataOffer * selectionOffer() const
Definition
qwaylanddatadevice.cpp:50
QtWaylandClient::QWaylandDataDevice::setSelectionSource
void setSelectionSource(QWaylandDataSource *source)
Definition
qwaylanddatadevice.cpp:72
QtWaylandClient::QWaylandDataDevice::invalidateSelectionOffer
void invalidateSelectionOffer()
Definition
qwaylanddatadevice.cpp:55
QPlatformGraphicsBufferHelper
\inmodule QtGui
QtWaylandClient
Definition
qwaylandclientextension.h:15
qtbase
src
plugins
platforms
wayland
qwaylanddatadevice.cpp
Generated on
for Qt by
1.14.0