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 | |
55 | #if QT_CONFIG(draganddrop) |
56 | void 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 | |
90 | QWaylandSurface *DataDevice::dragIcon() const |
91 | { |
92 | return m_dragIcon; |
93 | } |
94 | |
95 | QWaylandSurface *DataDevice::dragOrigin() const |
96 | { |
97 | return m_dragOrigin; |
98 | } |
99 | |
100 | void 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 | |
111 | void 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 | |
123 | void DataDevice::cancelDrag() |
124 | { |
125 | setDragFocus(focus: nullptr, localPosition: QPoint()); |
126 | } |
127 | |
128 | void 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 | |
142 | void 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 | |
151 | void 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 | |
179 | QT_END_NAMESPACE |
180 | |