GCC Code Coverage Report


Directory: ./
File: server/data_device.cpp
Date: 2024-01-22 17:25:27
Exec Total Coverage
Lines: 91 98 92.9%
Branches: 33 48 68.8%

Line Branch Exec Source
1 /********************************************************************
2 Copyright © 2020 Roman Gilg <subdiff@gmail.com>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) version 3, or any
8 later version accepted by the membership of KDE e.V. (or its
9 successor approved by the membership of KDE e.V.), which shall
10 act as a proxy defined in Section 6 of version 3 of the license.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 *********************************************************************/
20 #include "data_device.h"
21
22 #include "data_device_manager.h"
23 #include "data_offer_p.h"
24 #include "data_source.h"
25 #include "data_source_p.h"
26 #include "seat.h"
27 #include "selection_p.h"
28 #include "surface.h"
29 #include "surface_p.h"
30
31 #include "wayland/resource.h"
32
33 #include <wayland-server.h>
34
35 namespace Wrapland::Server
36 {
37
38 class data_device::Private : public Wayland::Resource<data_device>
39 {
40 public:
41 using source_res_t = Wrapland::Server::data_source_res;
42
43 Private(Client* client, uint32_t version, uint32_t id, Seat* seat, data_device* q_ptr);
44 ~Private() override;
45
46 data_offer* createDataOffer(data_source* source);
47
48 Seat* seat;
49 32 data_source* source = nullptr;
50 32 Surface* surface = nullptr;
51 32 Surface* icon = nullptr;
52
53 32 data_source* selection = nullptr;
54 QMetaObject::Connection selectionDestroyedConnection;
55
56 private:
57 static void startDragCallback(wl_client* wlClient,
58 wl_resource* wlResource,
59 wl_resource* wlSource,
60 wl_resource* wlOrigin,
61 wl_resource* wlIcon,
62 uint32_t serial);
63 static void set_selection_callback(wl_client* wlClient,
64 wl_resource* wlResource,
65 wl_resource* wlSource,
66 uint32_t id);
67
68 void startDrag(data_source* dataSource, Surface* origin, Surface* icon, quint32 serial) const;
69
70 static const struct wl_data_device_interface s_interface;
71 };
72
73 const struct wl_data_device_interface data_device::Private::s_interface = {
74 startDragCallback,
75 set_selection_callback,
76 destroyCallback,
77 };
78
79
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
64 data_device::Private::Private(Client* client,
80 uint32_t version,
81 uint32_t id,
82 Seat* seat,
83 data_device* q_ptr)
84 64 : Wayland::Resource<data_device>(client,
85 32 version,
86 32 id,
87 &wl_data_device_interface,
88 &s_interface,
89 32 q_ptr)
90 32 , seat(seat)
91 32 {
92 32 }
93
94 64 data_device::Private::~Private() = default;
95
96 13 void data_device::Private::startDragCallback([[maybe_unused]] wl_client* wlClient,
97 wl_resource* wlResource,
98 wl_resource* wlSource,
99 wl_resource* wlOrigin,
100 wl_resource* wlIcon,
101 uint32_t serial)
102 {
103 13 auto priv = get_handle(wlResource)->d_ptr;
104
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9 times.
13 auto source = wlSource ? Resource<data_source_res>::get_handle(wlSource)->src() : nullptr;
105 13 auto origin = Resource<Surface>::get_handle(wlOrigin);
106
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9 times.
13 auto icon = wlIcon ? Resource<Surface>::get_handle(wlIcon) : nullptr;
107
108 13 priv->startDrag(source, origin, icon, serial);
109 13 }
110
111 13 void data_device::Private::startDrag(data_source* dataSource,
112 Surface* origin,
113 Surface* _icon,
114 quint32 serial) const
115 {
116 // TODO(unknown author): verify serial
117
118 13 auto pointerGrab = false;
119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (seat->hasPointer()) {
120 13 auto& pointers = seat->pointers();
121
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6 times.
13 pointerGrab = pointers.has_implicit_grab(serial) && pointers.get_focus().surface == origin;
122 13 }
123
124
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 7 times.
13 if (!pointerGrab) {
125 // Client doesn't have pointer grab.
126
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (!seat->hasTouch()) {
127 // Client has no pointer grab and no touch capability.
128 6 return;
129 }
130 1 auto& touches = seat->touches();
131
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!touches.has_implicit_grab(serial) || touches.get_focus().surface != origin) {
132 // Client neither has pointer nor touch grab. No drag start allowed.
133 return;
134 }
135 1 }
136
137 7 seat->drags().start(dataSource, origin, _icon, serial);
138 13 }
139
140 18 void data_device::Private::set_selection_callback(wl_client* /*wlClient*/,
141 wl_resource* wlResource,
142 wl_resource* wlSource,
143 uint32_t /*id*/)
144 {
145 // TODO(unknown author): verify serial
146 18 auto handle = Resource::get_handle(wlResource);
147
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 14 times.
18 auto source_res = wlSource ? Wayland::Resource<data_source_res>::get_handle(wlSource) : nullptr;
148
149 // TODO(romangg): move errors into Wayland namespace.
150
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (source_res && source_res->src()->supported_dnd_actions()
151
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 && wl_resource_get_version(wlSource) >= WL_DATA_SOURCE_ACTION_SINCE_VERSION) {
152 wl_resource_post_error(
153 wlSource, WL_DATA_SOURCE_ERROR_INVALID_SOURCE, "Data source is for drag and drop");
154 return;
155 }
156
157 18 set_selection(handle, handle->d_ptr, wlSource);
158 18 }
159
160 31 data_offer* data_device::Private::createDataOffer(data_source* source)
161 {
162
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 1 times.
31 if (!source) {
163 // A data offer can only exist together with a source.
164 1 return nullptr;
165 }
166
167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 auto offer = new data_offer(client->handle, version, source);
168
169
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (!offer->d_ptr->resource) {
170 // TODO(unknown author): send error?
171 delete offer;
172 return nullptr;
173 }
174
175 30 send<wl_data_device_send_data_offer>(offer->d_ptr->resource);
176 30 offer->send_all_offers();
177 30 return offer;
178 31 }
179
180 32 data_device::data_device(Client* client, uint32_t version, uint32_t id, Seat* seat)
181
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
32 : d_ptr(new Private(client, version, id, seat, this))
182 32 {
183 32 }
184
185 2 Seat* data_device::seat() const
186 {
187 2 return d_ptr->seat;
188 }
189
190 30 data_source* data_device::selection() const
191 {
192 30 return d_ptr->selection;
193 }
194
195 32 void data_device::send_selection(data_source* source)
196 {
197
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 9 times.
32 if (!source) {
198 9 send_clear_selection();
199 9 return;
200 }
201
202 23 auto offer = d_ptr->createDataOffer(source);
203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (!offer) {
204 return;
205 }
206
207 23 d_ptr->send<wl_data_device_send_selection>(offer->d_ptr->resource);
208 32 }
209
210 9 void data_device::send_clear_selection()
211 {
212 9 d_ptr->send<wl_data_device_send_selection>(nullptr);
213 9 }
214
215 8 data_offer* data_device::create_offer(data_source* source)
216 {
217 8 return d_ptr->createDataOffer(source);
218 }
219
220 8 void data_device::enter(uint32_t serial, Surface* surface, QPointF const& pos, data_offer* offer)
221 {
222
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 assert(surface);
223 16 d_ptr->send<wl_data_device_send_enter>(serial,
224 8 surface->d_ptr->resource,
225 8 wl_fixed_from_double(pos.x()),
226 8 wl_fixed_from_double(pos.y()),
227
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 offer ? offer->d_ptr->resource : nullptr);
228 8 }
229
230 4 void data_device::motion(uint32_t time, QPointF const& pos)
231 {
232 8 d_ptr->send<wl_data_device_send_motion>(
233 4 time, wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
234 4 }
235
236 2 void data_device::leave()
237 {
238 2 d_ptr->send<wl_data_device_send_leave>();
239 2 }
240
241 3 void data_device::drop()
242 {
243 3 d_ptr->send<wl_data_device_send_drop>();
244 3 }
245
246 50 Client* data_device::client() const
247 {
248 50 return d_ptr->client->handle;
249 }
250
251 }
252