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 | |
23 | QT_BEGIN_NAMESPACE |
24 | |
25 | namespace QtWayland { |
26 | |
27 | DataDevice::DataDevice(QWaylandSeat *seat) |
28 | : m_compositor(seat->compositor()) |
29 | , m_seat(seat) |
30 | { |
31 | } |
32 | |
33 | void 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 | |
49 | void DataDevice::sourceDestroyed(DataSource *source) |
50 | { |
51 | if (m_selectionSource == source) |
52 | m_selectionSource = nullptr; |
53 | |
54 | if (m_dragDataSource == source) |
55 | m_dragDataSource = nullptr; |
56 | } |
57 | |
58 | #if QT_CONFIG(draganddrop) |
59 | void DataDevice::setDragFocus(QWaylandSurface *focus, const QPointF &localPosition) |
60 | { |
61 | if (m_dragFocusResource) { |
62 | send_leave(m_dragFocusResource->handle); |
63 | m_dragFocus = nullptr; |
64 | m_dragFocusResource = nullptr; |
65 | } |
66 | |
67 | if (!focus) |
68 | return; |
69 | |
70 | if (!m_dragDataSource && m_dragClient != focus->waylandClient()) |
71 | return; |
72 | |
73 | Resource *resource = resourceMap().value(focus->waylandClient()); |
74 | |
75 | if (!resource) |
76 | return; |
77 | |
78 | uint32_t serial = m_compositor->nextSerial(); |
79 | |
80 | DataOffer *offer = m_dragDataSource ? new DataOffer(m_dragDataSource, resource) : nullptr; |
81 | |
82 | if (m_dragDataSource && !offer) |
83 | return; |
84 | |
85 | if (offer) { |
86 | send_enter(resource->handle, serial, focus->resource(), |
87 | wl_fixed_from_double(d: localPosition.x()), wl_fixed_from_double(d: localPosition.y()), |
88 | offer->resource()->handle); |
89 | } |
90 | |
91 | m_dragFocus = focus; |
92 | m_dragFocusResource = resource; |
93 | } |
94 | |
95 | QWaylandSurface *DataDevice::dragIcon() const |
96 | { |
97 | return m_dragIcon; |
98 | } |
99 | |
100 | QWaylandSurface *DataDevice::dragOrigin() const |
101 | { |
102 | return m_dragOrigin; |
103 | } |
104 | |
105 | void DataDevice::dragMove(QWaylandSurface *target, const QPointF &pos) |
106 | { |
107 | if (target != m_dragFocus) |
108 | setDragFocus(focus: target, localPosition: pos); |
109 | if (!target || !m_dragFocusResource) |
110 | return; |
111 | uint time = m_compositor->currentTimeMsecs(); //### should be serial |
112 | send_motion(m_dragFocusResource->handle, time, |
113 | wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y())); |
114 | } |
115 | |
116 | void DataDevice::drop() |
117 | { |
118 | if (m_dragFocusResource) { |
119 | send_drop(m_dragFocusResource->handle); |
120 | setDragFocus(focus: nullptr, localPosition: QPoint()); |
121 | } else if (m_dragDataSource) { |
122 | m_dragDataSource->cancel(); |
123 | } |
124 | m_dragOrigin = nullptr; |
125 | setDragIcon(nullptr); |
126 | } |
127 | |
128 | void DataDevice::cancelDrag() |
129 | { |
130 | setDragFocus(focus: nullptr, localPosition: QPoint()); |
131 | } |
132 | |
133 | void DataDevice::data_device_start_drag(Resource *resource, struct ::wl_resource *source, struct ::wl_resource *origin, struct ::wl_resource *icon, uint32_t serial) |
134 | { |
135 | m_dragClient = resource->client(); |
136 | m_dragDataSource = source ? DataSource::fromResource(resource: source) : nullptr; |
137 | if (m_dragDataSource) |
138 | m_dragDataSource->setDevice(this); |
139 | m_dragOrigin = QWaylandSurface::fromResource(resource: origin); |
140 | QWaylandDrag *drag = m_seat->drag(); |
141 | setDragIcon(icon ? QWaylandSurface::fromResource(resource: icon) : nullptr); |
142 | Q_EMIT drag->dragStarted(); |
143 | Q_EMIT m_dragOrigin->dragStarted(drag); |
144 | |
145 | Q_UNUSED(serial); |
146 | //### need to verify that we have an implicit grab with this serial |
147 | } |
148 | |
149 | void DataDevice::setDragIcon(QWaylandSurface *icon) |
150 | { |
151 | if (icon == m_dragIcon) |
152 | return; |
153 | m_dragIcon = icon; |
154 | Q_EMIT m_seat->drag()->iconChanged(); |
155 | } |
156 | #endif // QT_CONFIG(draganddrop) |
157 | |
158 | void DataDevice::data_device_set_selection(Resource *, struct ::wl_resource *source, uint32_t serial) |
159 | { |
160 | Q_UNUSED(serial); |
161 | |
162 | DataSource *dataSource = source ? DataSource::fromResource(resource: source) : nullptr; |
163 | |
164 | if (m_selectionSource) |
165 | m_selectionSource->cancel(); |
166 | |
167 | m_selectionSource = dataSource; |
168 | QWaylandCompositorPrivate::get(compositor: m_compositor)->dataDeviceManager()->setCurrentSelectionSource(m_selectionSource); |
169 | if (m_selectionSource) |
170 | m_selectionSource->setDevice(this); |
171 | |
172 | QWaylandClient *focusClient = m_seat->keyboard()->focusClient(); |
173 | Resource *resource = focusClient ? resourceMap().value(focusClient->client()) : 0; |
174 | |
175 | if (resource && m_selectionSource) { |
176 | DataOffer *offer = new DataOffer(m_selectionSource, resource); |
177 | send_selection(resource->handle, offer->resource()->handle); |
178 | } else if (resource) { |
179 | send_selection(resource->handle, nullptr); |
180 | } |
181 | } |
182 | |
183 | |
184 | } |
185 | |
186 | QT_END_NAMESPACE |
187 | |