1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qwldatadevice_p.h"
5
6#include "qwldatasource_p.h"
7#include "qwldataoffer_p.h"
8#include "qwaylandsurface_p.h"
9#include "qwldatadevicemanager_p.h"
10
11#if QT_CONFIG(draganddrop)
12#include "qwaylanddrag.h"
13#endif
14#include "qwaylandview.h"
15#include <QtWaylandCompositor/QWaylandClient>
16#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
17#include <QtWaylandCompositor/private/qwaylandseat_p.h>
18#include <QtWaylandCompositor/private/qwaylandpointer_p.h>
19
20#include <QtCore/QPointF>
21#include <QDebug>
22
23QT_BEGIN_NAMESPACE
24
25namespace QtWayland {
26
27DataDevice::DataDevice(QWaylandSeat *seat)
28 : m_compositor(seat->compositor())
29 , m_seat(seat)
30{
31}
32
33void DataDevice::setFocus(QWaylandClient *focusClient)
34{
35 if (!focusClient)
36 return;
37
38 Resource *resource = resourceMap().value(focusClient->client());
39
40 if (!resource)
41 return;
42
43 if (m_selectionSource) {
44 DataOffer *offer = new DataOffer(m_selectionSource, resource);
45 send_selection(resource->handle, offer->resource()->handle);
46 }
47}
48
49void DataDevice::sourceDestroyed(DataSource *source)
50{
51 if (m_selectionSource == source)
52 m_selectionSource = nullptr;
53}
54
55#if QT_CONFIG(draganddrop)
56void DataDevice::setDragFocus(QWaylandSurface *focus, const QPointF &localPosition)
57{
58 if (m_dragFocusResource) {
59 send_leave(m_dragFocusResource->handle);
60 m_dragFocus = nullptr;
61 m_dragFocusResource = nullptr;
62 }
63
64 if (!focus)
65 return;
66
67 if (!m_dragDataSource && m_dragClient != focus->waylandClient())
68 return;
69
70 Resource *resource = resourceMap().value(focus->waylandClient());
71
72 if (!resource)
73 return;
74
75 uint32_t serial = m_compositor->nextSerial();
76
77 DataOffer *offer = m_dragDataSource ? new DataOffer(m_dragDataSource, resource) : nullptr;
78
79 if (m_dragDataSource && !offer)
80 return;
81
82 send_enter(resource->handle, serial, focus->resource(),
83 wl_fixed_from_double(d: localPosition.x()), wl_fixed_from_double(d: localPosition.y()),
84 offer->resource()->handle);
85
86 m_dragFocus = focus;
87 m_dragFocusResource = resource;
88}
89
90QWaylandSurface *DataDevice::dragIcon() const
91{
92 return m_dragIcon;
93}
94
95QWaylandSurface *DataDevice::dragOrigin() const
96{
97 return m_dragOrigin;
98}
99
100void DataDevice::dragMove(QWaylandSurface *target, const QPointF &pos)
101{
102 if (target != m_dragFocus)
103 setDragFocus(focus: target, localPosition: pos);
104 if (!target || !m_dragFocusResource)
105 return;
106 uint time = m_compositor->currentTimeMsecs(); //### should be serial
107 send_motion(m_dragFocusResource->handle, time,
108 wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
109}
110
111void DataDevice::drop()
112{
113 if (m_dragFocusResource) {
114 send_drop(m_dragFocusResource->handle);
115 setDragFocus(focus: nullptr, localPosition: QPoint());
116 } else {
117 m_dragDataSource->cancel();
118 }
119 m_dragOrigin = nullptr;
120 setDragIcon(nullptr);
121}
122
123void DataDevice::cancelDrag()
124{
125 setDragFocus(focus: nullptr, localPosition: QPoint());
126}
127
128void DataDevice::data_device_start_drag(Resource *resource, struct ::wl_resource *source, struct ::wl_resource *origin, struct ::wl_resource *icon, uint32_t serial)
129{
130 m_dragClient = resource->client();
131 m_dragDataSource = source ? DataSource::fromResource(resource: source) : nullptr;
132 m_dragOrigin = QWaylandSurface::fromResource(resource: origin);
133 QWaylandDrag *drag = m_seat->drag();
134 setDragIcon(icon ? QWaylandSurface::fromResource(resource: icon) : nullptr);
135 Q_EMIT drag->dragStarted();
136 Q_EMIT m_dragOrigin->dragStarted(drag);
137
138 Q_UNUSED(serial);
139 //### need to verify that we have an implicit grab with this serial
140}
141
142void DataDevice::setDragIcon(QWaylandSurface *icon)
143{
144 if (icon == m_dragIcon)
145 return;
146 m_dragIcon = icon;
147 Q_EMIT m_seat->drag()->iconChanged();
148}
149#endif // QT_CONFIG(draganddrop)
150
151void DataDevice::data_device_set_selection(Resource *, struct ::wl_resource *source, uint32_t serial)
152{
153 Q_UNUSED(serial);
154
155 DataSource *dataSource = source ? DataSource::fromResource(resource: source) : nullptr;
156
157 if (m_selectionSource)
158 m_selectionSource->cancel();
159
160 m_selectionSource = dataSource;
161 QWaylandCompositorPrivate::get(compositor: m_compositor)->dataDeviceManager()->setCurrentSelectionSource(m_selectionSource);
162 if (m_selectionSource)
163 m_selectionSource->setDevice(this);
164
165 QWaylandClient *focusClient = m_seat->keyboard()->focusClient();
166 Resource *resource = focusClient ? resourceMap().value(focusClient->client()) : 0;
167
168 if (resource && m_selectionSource) {
169 DataOffer *offer = new DataOffer(m_selectionSource, resource);
170 send_selection(resource->handle, offer->resource()->handle);
171 } else if (resource) {
172 send_selection(resource->handle, nullptr);
173 }
174}
175
176
177}
178
179QT_END_NAMESPACE
180

source code of qtwayland/src/compositor/wayland_wrapper/qwldatadevice.cpp