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
= {
accepted
,
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
if
(
drag
) {
203
auto
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
());
204
drag
->
setDropResponse
(
response
);
205
drag
->
finishDrag
();
206
}
else
if
(
m_dragOffer
) {
207
m_dragOffer
->
finish
();
208
}
209
}
210
211
void
QWaylandDataDevice
::
data_device_enter
(
uint32_t
serial
,
wl_surface
*
surface
,
wl_fixed_t
x
,
wl_fixed_t
y
,
wl_data_offer
*
id
)
212
{
213
auto
*
dragWaylandWindow
=
surface
?
QWaylandWindow
::
fromWlSurface
(
surface
) :
nullptr
;
214
if
(!
dragWaylandWindow
)
215
return
;
// Ignore foreign surfaces
216
217
m_dragWindow
=
dragWaylandWindow
->
window
();
218
m_dragPoint
=
calculateDragPosition
(
x
,
y
,
m_dragWindow
);
219
m_enterSerial
=
serial
;
220
221
QMimeData
*
dragData
=
nullptr
;
222
Qt
::
DropActions
supportedActions
;
223
224
m_dragOffer
.
reset
(
static_cast
<
QWaylandDataOffer
*>(
wl_data_offer_get_user_data
(
id
)));
225
QDrag
*
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
226
if
(
drag
) {
227
dragData
=
drag
->
mimeData
();
228
supportedActions
=
drag
->
supportedActions
();
229
}
else
if
(
m_dragOffer
) {
230
dragData
=
m_dragOffer
->
mimeData
();
231
supportedActions
=
m_dragOffer
->
supportedActions
();
232
}
233
234
const
QPlatformDragQtResponse
&
response
=
QWindowSystemInterface
::
handleDrag
(
235
m_dragWindow
,
dragData
,
m_dragPoint
,
supportedActions
,
QGuiApplication
::
mouseButtons
(),
236
m_inputDevice
->
modifiers
());
237
if
(
drag
) {
238
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
setResponse
(
response
);
239
}
240
241
sendResponse
(
supportedActions
,
response
);
242
}
243
244
void
QWaylandDataDevice
::
data_device_leave
()
245
{
246
if
(
m_dragWindow
)
247
QWindowSystemInterface
::
handleDrag
(
m_dragWindow
,
nullptr
,
QPoint
(),
Qt
::
IgnoreAction
,
248
QGuiApplication
::
mouseButtons
(),
249
m_inputDevice
->
modifiers
());
250
251
QDrag
*
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
252
if
(!
drag
) {
253
m_dragOffer
.
reset
();
254
}
255
}
256
257
void
QWaylandDataDevice
::
data_device_motion
(
uint32_t
time
,
wl_fixed_t
x
,
wl_fixed_t
y
)
258
{
259
Q_UNUSED
(
time
);
260
261
QDrag
*
drag
=
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
currentDrag
();
262
263
if
(!
drag
&& !
m_dragOffer
)
264
return
;
265
266
if
(!
m_dragWindow
)
267
return
;
268
269
m_dragPoint
=
calculateDragPosition
(
x
,
y
,
m_dragWindow
);
270
271
QMimeData
*
dragData
=
nullptr
;
272
Qt
::
DropActions
supportedActions
;
273
if
(
drag
) {
274
dragData
=
drag
->
mimeData
();
275
supportedActions
=
drag
->
supportedActions
();
276
}
else
{
277
dragData
=
m_dragOffer
->
mimeData
();
278
supportedActions
=
m_dragOffer
->
supportedActions
();
279
}
280
281
const
QPlatformDragQtResponse
response
=
QWindowSystemInterface
::
handleDrag
(
m_dragWindow
,
dragData
,
m_dragPoint
,
supportedActions
,
282
QGuiApplication
::
mouseButtons
(),
283
m_inputDevice
->
modifiers
());
284
285
if
(
drag
) {
286
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
setResponse
(
response
);
287
}
288
289
sendResponse
(
supportedActions
,
response
);
290
}
291
#
endif
// QT_CONFIG(draganddrop)
292
293
void
QWaylandDataDevice
::data_device_selection(wl_data_offer *id)
294
{
295
if
(id)
296
m_selectionOffer.reset(
static_cast
<QWaylandDataOffer *>(wl_data_offer_get_user_data(id)));
297
else
298
m_selectionOffer.reset();
299
300
#
if
QT_CONFIG
(
clipboard
)
301
QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
302
#
endif
303
}
304
305
void
QWaylandDataDevice
::selectionSourceCancelled()
306
{
307
m_selectionSource.reset();
308
#
if
QT_CONFIG
(
clipboard
)
309
QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
310
#
endif
311
}
312
313
#
if
QT_CONFIG
(
draganddrop
)
314
void
QWaylandDataDevice
::
dragSourceCancelled
()
315
{
316
static_cast
<
QWaylandDrag
*>(
QGuiApplicationPrivate
::
platformIntegration
()->
drag
())->
finishDrag
();
317
m_dragSource
.
reset
();
318
if
(
m_toplevelDrag
) {
319
m_toplevelDrag
->
destroy
();
320
m_toplevelDrag
=
nullptr
;
321
}
322
}
323
324
QPoint
QWaylandDataDevice
::
calculateDragPosition
(
int
x
,
int
y
,
QWindow
*
wnd
)
const
325
{
326
QPoint
pnt
(
wl_fixed_to_int
(
x
),
wl_fixed_to_int
(
y
));
327
if
(
wnd
) {
328
QWaylandWindow
*
wwnd
=
static_cast
<
QWaylandWindow
*>(
m_dragWindow
->
handle
());
329
if
(
wwnd
&&
wwnd
->
decoration
()) {
330
pnt
-=
QPoint
(
wwnd
->
decoration
()->
margins
().
left
(),
331
wwnd
->
decoration
()->
margins
().
top
());
332
}
333
}
334
return
pnt
;
335
}
336
337
void
QWaylandDataDevice
::
sendResponse
(
Qt
::
DropActions
supportedActions
,
const
QPlatformDragQtResponse
&
response
)
338
{
339
if
(
response
.
isAccepted
()) {
340
if
(
version
() >= 3)
341
m_dragOffer
->
set_actions
(
dropActionsToWl
(
supportedActions
),
dropActionsToWl
(
response
.
acceptedAction
()));
342
343
m_dragOffer
->
accept
(
m_enterSerial
,
m_dragOffer
->
firstFormat
());
344
}
else
{
345
m_dragOffer
->
accept
(
m_enterSerial
,
QString
());
346
}
347
}
348
349
int
QWaylandDataDevice
::
dropActionsToWl
(
Qt
::
DropActions
actions
)
350
{
351
352
int
wlActions
=
WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE
;
353
if
(
actions
&
Qt
::
CopyAction
)
354
wlActions
|=
WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY
;
355
if
(
actions
& (
Qt
::
MoveAction
|
Qt
::
TargetMoveAction
))
356
wlActions
|=
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE
;
357
358
// wayland does not support LinkAction at the time of writing
359
return
wlActions
;
360
}
361
362
363
#
endif
// QT_CONFIG(draganddrop)
364
365
}
366
367
QT_END_NAMESPACE
368
369
#
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
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qstandardpaths_haiku.cpp:21
QtWaylandClient
Definition
qwaylandclientextension.h:15
qtwayland
src
client
qwaylanddatadevice.cpp
Generated on Tue Apr 22 2025 17:12:10 for Qt by
1.13.2