GCC Code Coverage Report


Directory: ./
File: src/client/output.cpp
Date: 2024-01-22 17:25:27
Exec Total Coverage
Lines: 182 188 96.8%
Branches: 66 98 67.3%

Line Branch Exec Source
1 /********************************************************************
2 Copyright 2013 Martin Gräßlin <mgraesslin@kde.org>
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 "output.h"
21 #include "wayland_pointer_p.h"
22 // Qt
23 #include <QPoint>
24 #include <QRect>
25 #include <QSize>
26 #include <QVector>
27 // wayland
28 #include <wayland-client-protocol.h>
29
30 namespace Wrapland
31 {
32
33 namespace Client
34 {
35
36 namespace
37 {
38 typedef QList<Output::Mode> Modes;
39 }
40
41 class Q_DECL_HIDDEN Output::Private
42 {
43 public:
44 Private(Output* q);
45 ~Private();
46 void setup(wl_output* o);
47
48 WaylandPointer<wl_output, wl_output_release> output;
49 167 EventQueue* queue = nullptr;
50 QSize physicalSize;
51 QPoint globalPosition;
52 QString manufacturer;
53 QString model;
54 167 int scale = 1;
55 167 SubPixel subPixel = SubPixel::Unknown;
56 167 Transform transform = Transform::Normal;
57 Modes modes;
58
1/2
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
167 Modes::iterator currentMode = modes.end();
59
60 static Output* get(wl_output* o);
61
62 private:
63 static void geometryCallback(void* data,
64 wl_output* output,
65 int32_t x,
66 int32_t y,
67 int32_t physicalWidth,
68 int32_t physicalHeight,
69 int32_t subPixel,
70 char const* make,
71 char const* model,
72 int32_t transform);
73 static void modeCallback(void* data,
74 wl_output* output,
75 uint32_t flags,
76 int32_t width,
77 int32_t height,
78 int32_t refresh);
79 static void doneCallback(void* data, wl_output* output);
80 static void scaleCallback(void* data, wl_output* output, int32_t scale);
81 void setPhysicalSize(QSize const& size);
82 void setGlobalPosition(QPoint const& pos);
83 void setManufacturer(QString const& manufacturer);
84 void setModel(QString const& model);
85 void setScale(int scale);
86 void setSubPixel(SubPixel subPixel);
87 void setTransform(Transform transform);
88 void addMode(uint32_t flags, int32_t width, int32_t height, int32_t refresh);
89
90 Output* q;
91 static struct wl_output_listener s_outputListener;
92
93 static QVector<Private*> s_allOutputs;
94 };
95
96 QVector<Output::Private*> Output::Private::s_allOutputs;
97
98 501 Output::Private::Private(Output* q)
99 167 : q(q)
100 {
101
1/2
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
167 s_allOutputs << this;
102 167 }
103
104 167 Output::Private::~Private()
105 {
106
1/2
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
167 s_allOutputs.removeOne(this);
107 167 }
108
109 9 Output* Output::Private::get(wl_output* o)
110 {
111 18 auto it = std::find_if(s_allOutputs.constBegin(), s_allOutputs.constEnd(), [o](Private* p) {
112 9 const wl_output* reference = p->output;
113 9 return reference == o;
114 });
115
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 if (it != s_allOutputs.constEnd()) {
116 8 return (*it)->q;
117 }
118 1 return nullptr;
119 9 }
120
121 167 void Output::Private::setup(wl_output* o)
122 {
123
1/2
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
167 Q_ASSERT(o);
124
1/2
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
167 Q_ASSERT(!output);
125 167 output.setup(o);
126 167 wl_output_add_listener(output, &s_outputListener, this);
127 167 }
128
129 3 bool Output::Mode::operator==(Output::Mode const& m) const
130 {
131
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
3 return size == m.size && refreshRate == m.refreshRate && flags == m.flags && output == m.output;
132 }
133
134 167 Output::Output(QObject* parent)
135 167 : QObject(parent)
136
2/4
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 167 times.
167 , d(new Private(this))
137 167 {
138 167 }
139
140 323 Output::~Output()
141 323 {
142
1/2
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
167 d->output.release();
143 323 }
144
145 wl_output_listener Output::Private::s_outputListener = {
146 geometryCallback,
147 modeCallback,
148 doneCallback,
149 scaleCallback,
150 };
151
152 109 void Output::Private::geometryCallback(void* data,
153 wl_output* output,
154 int32_t x,
155 int32_t y,
156 int32_t physicalWidth,
157 int32_t physicalHeight,
158 int32_t subPixel,
159 char const* make,
160 char const* model,
161 int32_t transform)
162 {
163 Q_UNUSED(transform)
164 109 auto o = reinterpret_cast<Output::Private*>(data);
165
1/2
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
109 Q_ASSERT(o->output == output);
166 109 o->setGlobalPosition(QPoint(x, y));
167
1/2
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
109 o->setManufacturer(make);
168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 109 times.
109 o->setModel(model);
169 109 o->setPhysicalSize(QSize(physicalWidth, physicalHeight));
170 218 auto toSubPixel = [subPixel]() {
171
6/7
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 104 times.
✗ Branch 6 not taken.
109 switch (subPixel) {
172 case WL_OUTPUT_SUBPIXEL_NONE:
173 1 return SubPixel::None;
174 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
175 1 return SubPixel::HorizontalRGB;
176 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
177 1 return SubPixel::HorizontalBGR;
178 case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
179 1 return SubPixel::VerticalRGB;
180 case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
181 1 return SubPixel::VerticalBGR;
182 104 case WL_OUTPUT_SUBPIXEL_UNKNOWN:
183 default:
184 104 return SubPixel::Unknown;
185 }
186 109 };
187 109 o->setSubPixel(toSubPixel());
188 218 auto toTransform = [transform]() {
189
8/9
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 102 times.
✗ Branch 8 not taken.
109 switch (transform) {
190 case WL_OUTPUT_TRANSFORM_90:
191 1 return Transform::Rotated90;
192 case WL_OUTPUT_TRANSFORM_180:
193 1 return Transform::Rotated180;
194 case WL_OUTPUT_TRANSFORM_270:
195 1 return Transform::Rotated270;
196 case WL_OUTPUT_TRANSFORM_FLIPPED:
197 1 return Transform::Flipped;
198 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
199 1 return Transform::Flipped90;
200 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
201 1 return Transform::Flipped180;
202 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
203 1 return Transform::Flipped270;
204 102 case WL_OUTPUT_TRANSFORM_NORMAL:
205 default:
206 102 return Transform::Normal;
207 }
208 109 };
209 109 o->setTransform(toTransform());
210 109 }
211
212 134 void Output::Private::modeCallback(void* data,
213 wl_output* output,
214 uint32_t flags,
215 int32_t width,
216 int32_t height,
217 int32_t refresh)
218 {
219 134 auto o = reinterpret_cast<Output::Private*>(data);
220
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 Q_ASSERT(o->output == output);
221 134 o->addMode(flags, width, height, refresh);
222 134 }
223
224 134 void Output::Private::addMode(uint32_t flags, int32_t width, int32_t height, int32_t refresh)
225 {
226 134 Mode mode;
227
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 mode.output = QPointer<Output>(q);
228 134 mode.refreshRate = refresh;
229 134 mode.size = QSize(width, height);
230
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 98 times.
134 if (flags & WL_OUTPUT_MODE_CURRENT) {
231 98 mode.flags |= Mode::Flag::Current;
232 98 }
233
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 22 times.
134 if (flags & WL_OUTPUT_MODE_PREFERRED) {
234 22 mode.flags |= Mode::Flag::Preferred;
235 22 }
236
237
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 modes.append(mode);
238 134 bool existing = false;
239
240
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 98 times.
134 if (flags & WL_OUTPUT_MODE_CURRENT) {
241
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 51 times.
149 for (int i = modes.size() - 2; i >= 0; i--) {
242
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 auto& m = modes[i];
243
244
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 46 times.
51 if (m.flags.testFlag(Mode::Flag::Current)) {
245 5 m.flags &= ~Mode::Flags(Mode::Flag::Current);
246
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 Q_EMIT q->modeChanged(m);
247 5 }
248
249
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
51 if (m.refreshRate == mode.refreshRate && m.size == mode.size) {
250
4/8
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
5 modes.erase(modes.begin() + i);
251 5 existing = true;
252 5 }
253 51 }
254
255
2/4
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 98 times.
✗ Branch 3 not taken.
98 currentMode = modes.end() - 1;
256 98 }
257
258
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 129 times.
134 if (existing) {
259
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 Q_EMIT q->modeChanged(mode);
260 5 } else {
261
1/2
✓ Branch 0 taken 129 times.
✗ Branch 1 not taken.
129 Q_EMIT q->modeAdded(mode);
262 }
263 134 }
264
265 98 void Output::Private::scaleCallback(void* data, wl_output* output, int32_t scale)
266 {
267 98 auto o = reinterpret_cast<Output::Private*>(data);
268
1/2
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
98 Q_ASSERT(o->output == output);
269 98 o->setScale(scale);
270 98 }
271
272 114 void Output::Private::doneCallback(void* data, wl_output* output)
273 {
274 114 auto o = reinterpret_cast<Output::Private*>(data);
275
1/2
✓ Branch 0 taken 114 times.
✗ Branch 1 not taken.
114 Q_ASSERT(o->output == output);
276 114 Q_EMIT o->q->changed();
277 114 }
278
279 167 void Output::setup(wl_output* output)
280 {
281 167 d->setup(output);
282 167 }
283
284 EventQueue* Output::eventQueue() const
285 {
286 return d->queue;
287 }
288
289 156 void Output::setEventQueue(EventQueue* queue)
290 {
291 156 d->queue = queue;
292 156 }
293
294 109 void Output::Private::setGlobalPosition(QPoint const& pos)
295 {
296 109 globalPosition = pos;
297 109 }
298
299 109 void Output::Private::setManufacturer(QString const& m)
300 {
301 109 manufacturer = m;
302 109 }
303
304 109 void Output::Private::setModel(QString const& m)
305 {
306 109 model = m;
307 109 }
308
309 109 void Output::Private::setPhysicalSize(QSize const& size)
310 {
311 109 physicalSize = size;
312 109 }
313
314 98 void Output::Private::setScale(int s)
315 {
316 98 scale = s;
317 98 }
318
319 2 QRect Output::geometry() const
320 {
321
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (d->currentMode == d->modes.end()) {
322 1 return QRect();
323 }
324 1 return QRect(d->globalPosition, pixelSize());
325 2 }
326
327 109 void Output::Private::setSubPixel(Output::SubPixel s)
328 {
329 109 subPixel = s;
330 109 }
331
332 109 void Output::Private::setTransform(Output::Transform t)
333 {
334 109 transform = t;
335 109 }
336
337 2 QPoint Output::globalPosition() const
338 {
339 2 return d->globalPosition;
340 }
341
342 2 QString Output::manufacturer() const
343 {
344 2 return d->manufacturer;
345 }
346
347 2 QString Output::model() const
348 {
349 2 return d->model;
350 }
351
352 3 wl_output* Output::output()
353 {
354 3 return d->output;
355 }
356
357 2 QSize Output::physicalSize() const
358 {
359 2 return d->physicalSize;
360 }
361
362 6 QSize Output::pixelSize() const
363 {
364
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (d->currentMode == d->modes.end()) {
365 1 return QSize();
366 }
367 5 return (*d->currentMode).size;
368 6 }
369
370 2 int Output::refreshRate() const
371 {
372
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (d->currentMode == d->modes.end()) {
373 1 return 0;
374 }
375 1 return (*d->currentMode).refreshRate;
376 2 }
377
378 8 int Output::scale() const
379 {
380 8 return d->scale;
381 }
382
383 16 bool Output::isValid() const
384 {
385 16 return d->output.isValid();
386 }
387
388 12 Output::SubPixel Output::subPixel() const
389 {
390 12 return d->subPixel;
391 }
392
393 16 Output::Transform Output::transform() const
394 {
395 16 return d->transform;
396 }
397
398 2 QList<Output::Mode> Output::modes() const
399 {
400 2 return d->modes;
401 }
402
403 12 Output::operator wl_output*()
404 {
405 12 return d->output;
406 }
407
408 Output::operator wl_output*() const
409 {
410 return d->output;
411 }
412
413 9 Output* Output::get(wl_output* o)
414 {
415 9 return Private::get(o);
416 }
417
418 void Output::release()
419 {
420 d->output.release();
421 }
422
423 }
424 }
425