GCC Code Coverage Report


Directory: ./
File: lib/output.cpp
Date: 2023-04-20 22:59:23
Exec Total Coverage
Lines: 375 417 89.9%
Branches: 128 197 65.0%

Line Branch Exec Source
1 /*************************************************************************************
2 * Copyright (C) 2012 by Alejandro Fiestas Olivares <afiestas@kde.org> *
3 * Copyright (C) 2014 by Daniel Vrátil <dvratil@redhat.com> *
4 * Copyright © 2020 Roman Gilg <subdiff@gmail.com> *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of the GNU Lesser General Public *
8 * License as published by the Free Software Foundation; either *
9 * version 2.1 of the License, or (at your option) any later version. *
10 * *
11 * This library is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14 * Lesser General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU Lesser General Public *
17 * License along with this library; if not, write to the Free Software *
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
19 *************************************************************************************/
20 #include "output_p.h"
21
22 #include "disman_debug.h"
23 #include "mode.h"
24
25 #include <QCryptographicHash>
26 #include <QRect>
27
28 #include <sstream>
29
30 namespace Disman
31 {
32
33 865 Output::Private::Private()
34 865 : id(0)
35 865 , type(Unknown)
36 865 , replication_source(0)
37 865 , rotation(None)
38 865 , scale(1.0)
39 865 , enabled(false)
40 {
41 865 }
42
43 265 Output::Private::Private(const Private& other)
44 265 : id(other.id)
45 265 , name(other.name)
46 265 , description(other.description)
47 265 , hash(other.hash)
48 265 , type(other.type)
49 265 , replication_source(other.replication_source)
50 265 , resolution(other.resolution)
51 265 , refresh_rate(other.refresh_rate)
52 265 , adapt_sync{other.adapt_sync}
53 265 , preferredMode(other.preferredMode)
54 265 , preferred_modes(other.preferred_modes)
55 265 , physical_size(other.physical_size)
56 265 , position(other.position)
57 265 , rotation(other.rotation)
58 265 , scale(other.scale)
59 265 , enabled(other.enabled)
60 265 , supports_adapt_sync_toggle{other.supports_adapt_sync_toggle}
61 265 , follow_preferred_mode(other.follow_preferred_mode)
62 265 , auto_resolution{other.auto_resolution}
63 265 , auto_refresh_rate{other.auto_refresh_rate}
64 265 , auto_rotate{other.auto_rotate}
65 265 , auto_rotate_only_in_tablet_mode{other.auto_rotate_only_in_tablet_mode}
66 265 , retention{other.retention}
67 530 , global{other.global}
68 {
69
2/2
✓ Branch 6 taken 2511 times.
✓ Branch 7 taken 265 times.
2776 for (auto const& [key, otherMode] : other.modeList) {
70 2511 modeList.insert({key, otherMode->clone()});
71 }
72 265 }
73
74 1200 ModePtr Output::Private::mode(QSize const& resolution, int refresh) const
75 {
76
2/2
✓ Branch 7 taken 7269 times.
✓ Branch 8 taken 29 times.
7298 for (auto const& [key, mode] : modeList) {
77
5/6
✓ Branch 3 taken 1171 times.
✓ Branch 4 taken 6098 times.
✓ Branch 7 taken 1171 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1171 times.
✓ Branch 10 taken 6098 times.
7269 if (resolution == mode->size() && refresh == mode->refresh()) {
78 1171 return mode;
79 }
80 }
81 29 return ModePtr();
82 }
83
84 bool Output::Private::compareModeMap(const ModeMap& before, const ModeMap& after)
85 {
86 if (before.size() != after.size()) {
87 return false;
88 }
89
90 for (auto const& [before_key, before_val] : before) {
91 auto ita = after.find(before_key);
92 if (ita == after.end()) {
93 return false;
94 }
95
96 const auto& mb = before_val;
97 const auto& ma = ita->second;
98
99 if (mb->id() != ma->id()) {
100 return false;
101 }
102 if (mb->size() != ma->size()) {
103 return false;
104 }
105 if (mb->refresh() != ma->refresh()) {
106 return false;
107 }
108 if (mb->name() != ma->name()) {
109 return false;
110 }
111 }
112 // They're the same
113 return true;
114 }
115
116 60 void Output::Private::apply_global()
117 {
118
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 2 times.
60 if (!global.valid) {
119 58 return;
120 }
121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (retention == Output::Retention::Individual) {
122 return;
123 }
124
125 2 resolution = global.resolution;
126 2 refresh_rate = global.refresh;
127 2 adapt_sync = global.adapt_sync;
128 2 rotation = global.rotation;
129 2 scale = global.scale;
130 2 auto_resolution = global.auto_resolution;
131 2 auto_refresh_rate = global.auto_refresh_rate;
132 2 auto_rotate = global.auto_rotate;
133 2 auto_rotate_only_in_tablet_mode = global.auto_rotate_only_in_tablet_mode;
134 }
135
136 865 Output::Output()
137 : QObject(nullptr)
138 865 , d(new Private())
139 {
140 865 }
141
142 265 Output::Output(Output::Private* dd)
143 : QObject()
144 265 , d(dd)
145 {
146 265 }
147
148 4432 Output::~Output()
149 {
150
1/2
✓ Branch 0 taken 1108 times.
✗ Branch 1 not taken.
2216 delete d;
151 4432 }
152
153 265 OutputPtr Output::clone() const
154 {
155 265 return OutputPtr(new Output(new Private(*d)));
156 }
157
158 20 bool Output::compare(OutputPtr output) const
159 {
160
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 if (!output) {
161 return false;
162 }
163
164
1/2
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
40 auto const simple_data_compare = d->id == output->d->id && d->name == output->d->name
165
2/4
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
20 && d->description == output->d->description && d->hash == output->d->hash
166
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
20 && d->type == output->d->type && d->replication_source == output->d->replication_source
167
3/4
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 3 times.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
20 && d->resolution == output->d->resolution && d->refresh_rate == output->d->refresh_rate
168
3/4
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 1 times.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
17 && d->adapt_sync == output->d->adapt_sync && d->preferredMode == output->d->preferredMode
169
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 && d->preferred_modes == output->d->preferred_modes
170
2/4
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 16 times.
✗ Branch 7 not taken.
16 && d->physical_size == output->d->physical_size && d->position == output->d->position
171
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 && d->enforced_geometry == output->d->enforced_geometry
172
4/4
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 5 times.
16 && d->rotation == output->d->rotation && d->scale == output->d->scale
173
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 && d->enabled == output->d->enabled
174
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 && d->follow_preferred_mode == output->d->follow_preferred_mode
175
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 && d->auto_resolution == output->d->auto_resolution
176
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 && d->auto_refresh_rate == output->d->auto_refresh_rate
177
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 && d->auto_rotate == output->d->auto_rotate
178
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 && d->auto_rotate_only_in_tablet_mode == output->d->auto_rotate_only_in_tablet_mode
179
2/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
40 && d->retention == output->d->retention;
180
181 20 auto const& own_global = d->global;
182 20 auto const& other_global = output->d->global;
183
184 20 auto const global_data_compare = own_global.resolution == other_global.resolution
185
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 && own_global.refresh == other_global.refresh
186
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 && own_global.adapt_sync == other_global.adapt_sync
187
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 && own_global.rotation == other_global.rotation && own_global.scale == other_global.scale
188
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 && own_global.auto_resolution == other_global.auto_resolution
189
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 && own_global.auto_refresh_rate == other_global.auto_refresh_rate
190
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 && own_global.auto_rotate == other_global.auto_rotate
191 9 && own_global.auto_rotate_only_in_tablet_mode
192
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 == other_global.auto_rotate_only_in_tablet_mode
193
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
29 && own_global.valid == other_global.valid;
194
195 // We assume the mode list is the same when hashes are. So nothing more to compare.
196
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
20 return simple_data_compare && global_data_compare;
197 }
198
199 4686 int Output::id() const
200 {
201 4686 return d->id;
202 }
203
204 866 void Output::set_id(int id)
205 {
206 866 d->id = id;
207 866 }
208
209 2137 std::string Output::name() const
210 {
211 2137 return d->name;
212 }
213
214 1964 void Output::set_name(std::string const& name)
215 {
216 1964 d->name = name;
217 1964 }
218
219 850 std::string Output::description() const
220 {
221 850 return d->description;
222 }
223
224 1963 void Output::set_description(std::string const& description)
225 {
226 1963 d->description = description;
227 1963 }
228
229 9716 std::string Output::hash() const
230 {
231 9716 return d->hash;
232 }
233
234 1639 void Output::set_hash(std::string const& input)
235 {
236 1639 auto const hash = QCryptographicHash::hash(input.c_str(), QCryptographicHash::Md5);
237 1639 d->hash = QString::fromLatin1(hash.toHex()).toStdString();
238 1639 }
239
240 void Output::set_hash_raw(std::string const& hash)
241 {
242 d->hash = hash;
243 }
244
245 64 Output::Type Output::type() const
246 {
247 64 return d->type;
248 }
249
250 1960 void Output::setType(Type type)
251 {
252 1960 d->type = type;
253 1960 }
254
255 230 ModePtr Output::mode(std::string const& id) const
256 {
257
2/2
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 226 times.
230 if (d->modeList.find(id) == d->modeList.end()) {
258 4 return ModePtr();
259 }
260
261 226 return d->modeList[id];
262 }
263
264 2 ModePtr Output::mode(QSize const& resolution, int refresh) const
265 {
266
1/2
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
6 for (auto const& [key, mode] : d->modeList) {
267
5/6
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 4 times.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 4 times.
6 if (mode->size() == resolution && mode->refresh() == refresh) {
268 2 return mode;
269 }
270 }
271
272 return {};
273 }
274
275 869 ModeMap Output::modes() const
276 {
277 869 return d->modeList;
278 }
279
280 1987 void Output::set_modes(const ModeMap& modes)
281 {
282 1987 d->modeList = modes;
283 1987 }
284
285 2083 void Output::set_mode(ModePtr const& mode)
286 {
287 2083 set_resolution(mode->size());
288 2083 set_refresh_rate(mode->refresh());
289 2083 }
290
291 void Output::set_to_preferred_mode()
292 {
293 set_mode(preferred_mode());
294 }
295
296 7812 ModePtr Output::commanded_mode() const
297 {
298
2/2
✓ Branch 7 taken 65567 times.
✓ Branch 8 taken 1294 times.
66861 for (auto const& [key, mode] : d->modeList) {
299
6/6
✓ Branch 3 taken 7436 times.
✓ Branch 4 taken 58131 times.
✓ Branch 7 taken 6518 times.
✓ Branch 8 taken 918 times.
✓ Branch 9 taken 6518 times.
✓ Branch 10 taken 59049 times.
65567 if (mode->size() == d->resolution && mode->refresh() == d->refresh_rate) {
300 6518 return mode;
301 }
302 }
303 1294 return ModePtr();
304 }
305
306 3904 bool Output::set_resolution(QSize const& size)
307 {
308 3904 d->resolution = size;
309 3904 return commanded_mode() != nullptr;
310 }
311
312 3904 bool Output::set_refresh_rate(int rate)
313 {
314 3904 d->refresh_rate = rate;
315 3904 return commanded_mode() != nullptr;
316 }
317
318 QSize Output::best_resolution() const
319 {
320 return d->best_resolution(modes());
321 }
322
323 int Output::best_refresh_rate(QSize const& resolution) const
324 {
325 return d->best_refresh_rate(modes(), resolution);
326 }
327
328 63 ModePtr Output::best_mode() const
329 {
330 63 return d->best_mode(modes());
331 }
332
333 2106 ModePtr Output::auto_mode() const
334 {
335 // Pick the preferred mode if the resolution and refresh rate is set to auto.
336 // Picking the highest one causes issues for monitors that advertise preferred modes lower
337 // than the highest available monitor (best example would be a 640x480 CRT that
338 // exposes a 800x600 mode, but there's also a gaming monitor that gives a preferred
339 // 144Hz mode, but exposes a 165Hz mode when "overclocking")
340
5/6
✓ Branch 1 taken 1315 times.
✓ Branch 2 taken 791 times.
✓ Branch 4 taken 1315 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1315 times.
✓ Branch 7 taken 791 times.
2106 if (auto_resolution() && auto_refresh_rate()) {
341 1315 return preferred_mode();
342 }
343
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 791 times.
791 auto const resolution = auto_resolution() ? best_resolution() : d->resolution;
344
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 791 times.
791 auto const refresh_rate = auto_refresh_rate() ? best_refresh_rate(resolution) : d->refresh_rate;
345
346
2/2
✓ Branch 2 taken 763 times.
✓ Branch 3 taken 28 times.
791 if (auto mode = d->mode(resolution, refresh_rate)) {
347 763 return mode;
348
2/2
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 763 times.
791 }
349 28 return preferred_mode();
350 }
351
352 1956 void Output::set_preferred_modes(std::vector<std::string> const& modes)
353 {
354 1956 d->preferredMode = std::string();
355 1956 d->preferred_modes = modes;
356 1956 }
357
358 5 std::vector<std::string> const& Output::preferred_modes() const
359 {
360 5 return d->preferred_modes;
361 }
362
363 1346 ModePtr Output::preferred_mode() const
364 {
365
2/2
✓ Branch 1 taken 1000 times.
✓ Branch 2 taken 346 times.
1346 if (!d->preferredMode.empty()) {
366 1000 return d->modeList.at(d->preferredMode);
367 }
368
2/2
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 329 times.
346 if (d->preferred_modes.empty()) {
369 17 return d->best_mode(modes());
370 }
371
372 329 auto best = d->best_mode(d->preferred_modes);
373
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 329 times.
329 Q_ASSERT_X(best, "preferred_mode", "biggest mode must exist");
374
375 329 d->preferredMode = best->id();
376 329 return best;
377 329 }
378
379 2528 void Output::set_position(const QPointF& position)
380 {
381 2528 d->position = position;
382 2528 }
383
384 // TODO KF6: make the Rotation enum an enum class and align values with Wayland transformation
385 // property
386 1388 Output::Rotation Output::rotation() const
387 {
388 1388 return d->rotation;
389 }
390
391 2446 void Output::set_rotation(Output::Rotation rotation)
392 {
393 2446 d->rotation = rotation;
394 2446 }
395
396 1093 double Output::scale() const
397 {
398 1093 return d->scale;
399 }
400
401 2246 void Output::set_scale(double scale)
402 {
403 2246 d->scale = scale;
404 2246 }
405
406 914 QRectF Output::geometry() const
407 {
408 914 auto geo = QRectF(d->position, QSizeF());
409
410
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 914 times.
914 if (d->enforced_geometry.isValid()) {
411 return d->enforced_geometry;
412 }
413
414 914 auto const mode = auto_mode();
415
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 914 times.
914 if (!mode) {
416 return geo;
417 }
418
419 914 auto size = mode->size();
420
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 914 times.
914 if (!size.isValid()) {
421 return geo;
422 }
423
424
2/2
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 899 times.
914 if (!horizontal()) {
425 15 size = size.transposed();
426 }
427
428 914 geo.setSize(size / d->scale);
429 914 return geo;
430 914 }
431
432 void Output::force_geometry(QRectF const& geo)
433 {
434 d->enforced_geometry = geo;
435 }
436
437 522 QPointF Output::position() const
438 {
439 522 return d->position;
440 }
441
442 921 bool Output::horizontal() const
443 {
444
4/4
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 901 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 15 times.
921 return ((rotation() == Output::None) || (rotation() == Output::Inverted));
445 }
446
447 2177 bool Output::enabled() const
448 {
449 2177 return d->enabled;
450 }
451
452 2645 void Output::set_enabled(bool enabled)
453 {
454 2645 d->enabled = enabled;
455 2645 }
456
457 1178 bool Output::adaptive_sync() const
458 {
459 1178 return d->adapt_sync;
460 }
461
462 2105 void Output::set_adaptive_sync(bool adapt)
463 {
464 2105 d->adapt_sync = adapt;
465 2105 }
466
467 1241 bool Output::adaptive_sync_toggle_support() const
468 {
469 1241 return d->supports_adapt_sync_toggle;
470 }
471
472 1631 void Output::set_adaptive_sync_toggle_support(bool support)
473 {
474 1631 d->supports_adapt_sync_toggle = support;
475 1631 }
476
477 804 int Output::replication_source() const
478 {
479 804 return d->replication_source;
480 }
481
482 536 void Output::set_replication_source(int source)
483 {
484 536 d->replication_source = source;
485
486 // Needs to be unset in case we run in-process. That value is not meant for consumption by
487 // the frontend anyway.
488 536 d->enforced_geometry = QRectF();
489 536 }
490
491 765 QSize Output::physical_size() const
492 {
493 765 return d->physical_size;
494 }
495
496 1656 void Output::set_physical_size(const QSize& size)
497 {
498 1656 d->physical_size = size;
499 1656 }
500
501 652 bool Disman::Output::follow_preferred_mode() const
502 {
503 652 return d->follow_preferred_mode;
504 }
505
506 void Disman::Output::set_follow_preferred_mode(bool follow)
507 {
508 d->follow_preferred_mode = follow;
509 }
510
511 3653 bool Output::auto_resolution() const
512 {
513 3653 return d->auto_resolution;
514 }
515
516 648 void Output::set_auto_resolution(bool auto_res)
517 {
518 648 d->auto_resolution = auto_res;
519 648 }
520
521 2862 bool Output::auto_refresh_rate() const
522 {
523 2862 return d->auto_refresh_rate;
524 }
525
526 648 void Output::set_auto_refresh_rate(bool auto_rate)
527 {
528 648 d->auto_refresh_rate = auto_rate;
529 648 }
530
531 1302 bool Output::auto_rotate() const
532 {
533 1302 return d->auto_rotate;
534 }
535
536 104 void Output::set_auto_rotate(bool auto_rot)
537 {
538 104 d->auto_rotate = auto_rot;
539 104 }
540
541 648 bool Output::auto_rotate_only_in_tablet_mode() const
542 {
543 648 return d->auto_rotate_only_in_tablet_mode;
544 }
545
546 104 void Output::set_auto_rotate_only_in_tablet_mode(bool only)
547 {
548 104 d->auto_rotate_only_in_tablet_mode = only;
549 104 }
550
551 3638 Output::Retention Output::retention() const
552 {
553 3638 return d->retention;
554 }
555
556 589 void Output::set_retention(Retention retention)
557 {
558 589 d->retention = retention;
559 589 }
560
561 47 bool Output::positionable() const
562 {
563
3/4
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 44 times.
✗ Branch 5 not taken.
47 return enabled() && !replication_source();
564 }
565
566 104 void Output::apply(const OutputPtr& other)
567 {
568 104 set_name(other->d->name);
569 104 set_description(other->d->description);
570 104 d->hash = other->d->hash;
571 104 setType(other->d->type);
572 104 set_position(other->geometry().topLeft());
573 104 set_rotation(other->d->rotation);
574 104 set_scale(other->d->scale);
575 104 set_enabled(other->d->enabled);
576
577 104 set_replication_source(other->d->replication_source);
578
579 104 set_preferred_modes(other->d->preferred_modes);
580 104 ModeMap modes;
581
2/2
✓ Branch 8 taken 1319 times.
✓ Branch 9 taken 104 times.
1423 for (auto const& [key, mode] : other->modes()) {
582 1319 modes.insert({key, mode->clone()});
583 104 }
584 104 set_modes(modes);
585
586 104 set_resolution(other->d->resolution);
587 104 set_refresh_rate(other->d->refresh_rate);
588
589 104 set_auto_resolution(other->d->auto_resolution);
590 104 set_auto_refresh_rate(other->d->auto_refresh_rate);
591 104 set_auto_rotate(other->d->auto_rotate);
592 104 set_auto_rotate_only_in_tablet_mode(other->d->auto_rotate_only_in_tablet_mode);
593 104 set_retention(other->d->retention);
594
595 104 d->global = other->d->global;
596
597 104 Q_EMIT updated();
598 104 }
599
600 2 Output::GlobalData Output::global_data() const
601 {
602 2 return d->global;
603 }
604
605 297 void Output::set_global_data(GlobalData data)
606 {
607
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 297 times.
297 assert(data.resolution.isValid());
608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 297 times.
297 assert(data.refresh > 0);
609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 297 times.
297 assert(data.scale > 0);
610
611 297 d->global = data;
612
3/6
✓ Branch 1 taken 297 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 297 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 297 times.
✗ Branch 6 not taken.
297 d->global.valid = data.resolution.isValid() && data.refresh > 0 && data.scale > 0;
613 297 }
614
615 650 std::string Output::log() const
616 {
617 1950 auto stream_size = [](QSizeF const& size) -> std::string {
618 1950 std::stringstream ss;
619 1950 ss << size.width() << "x" << size.height();
620 1950 return ss.str();
621 1950 };
622 1300 auto stream_mode = [&stream_size](Disman::ModePtr const& mode) {
623 650 std::stringstream ss;
624
1/2
✓ Branch 1 taken 650 times.
✗ Branch 2 not taken.
650 if (mode) {
625 1950 ss << stream_size(mode->size()) << "@" << mode->refresh() << " (id " << mode->id()
626 1300 << ")";
627 } else {
628 ss << "null";
629 }
630 650 return ss.str();
631 650 };
632 1300 auto stream_rect = [&stream_size](QRectF const& rect) {
633 650 std::stringstream ss;
634 650 ss << "x,y: " << rect.x() << "," << rect.y() << " w/h:" << stream_size(rect.size());
635 650 return ss.str();
636 650 };
637 1950 auto stream_geometry = [this, &stream_rect]() {
638 650 std::stringstream ss;
639 650 ss << stream_rect(geometry()) << " (scale: " << scale() << ")";
640 650 return ss.str();
641 650 };
642 650 auto stream_retention = [](Retention retention) -> std::string {
643
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 650 times.
650 switch (retention) {
644 case Retention::Global:
645 return "global";
646 case Retention::Individual:
647 return "individual";
648 650 case Retention::Undefined:
649 default:
650 650 return "undefined";
651 }
652 };
653 3896 auto stream_auto = [this]() -> std::string {
654 650 std::string ret;
655 650 auto comma{false};
656 1950 auto print = [&](auto check, std::string const& name) {
657
2/2
✓ Branch 0 taken 458 times.
✓ Branch 1 taken 1492 times.
1950 if (!check) {
658 458 return;
659 }
660
2/2
✓ Branch 0 taken 842 times.
✓ Branch 1 taken 650 times.
1492 if (comma) {
661 842 ret += ", ";
662 }
663 1492 ret += name;
664 1492 comma = true;
665 650 };
666 650 print(auto_resolution(), "resolution");
667 650 print(auto_refresh_rate(), "refresh");
668 650 print(auto_rotate(), "rotate");
669
5/6
✓ Branch 1 taken 646 times.
✓ Branch 2 taken 4 times.
✓ Branch 4 taken 646 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 646 times.
✓ Branch 7 taken 4 times.
650 if (auto_rotate() && auto_rotate_only_in_tablet_mode()) {
670 646 ret += " (only in tablet mode)";
671 }
672 650 return ret;
673 650 };
674 1300 auto stream_physical_size = [this, &stream_size]() -> std::string {
675 650 std::stringstream ss;
676 650 ss << "physical size[mm]: " << stream_size(physical_size());
677 650 return ss.str();
678 650 };
679 650 auto stream_replication_source = [this]() -> std::string {
680 650 auto source = replication_source();
681
2/2
✓ Branch 0 taken 648 times.
✓ Branch 1 taken 2 times.
650 if (!source) {
682 648 return "";
683 }
684 2 std::stringstream ss;
685 2 ss << ", replicates: " << source;
686 2 return ss.str();
687 2 };
688
689 650 auto const gap = std::string(" ");
690 650 std::stringstream ss;
691
692 1300 ss << "Output " << id() << ", " << description() << " (" << name() << ")" << std::endl
693 1300 << gap << "mode: " << stream_mode(auto_mode()) << std::endl
694 650 << gap << "adapt sync: " << (adaptive_sync() ? "yes" : "no")
695
4/4
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 648 times.
✓ Branch 7 taken 432 times.
✓ Branch 8 taken 218 times.
1300 << " (supports toggle: " << (adaptive_sync_toggle_support() ? "yes" : "no") << ")"
696 650 << std::endl
697 1300 << gap << stream_geometry() << std::endl
698 1300 << gap << "auto: " << stream_auto() << std::endl
699 1300 << gap << stream_physical_size() << std::endl
700 650 << gap << "enabled: " << (enabled() ? "yes" : "no")
701 1950 << ", retention: " << stream_retention(retention()) << stream_replication_source()
702
3/4
✓ Branch 2 taken 644 times.
✓ Branch 3 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 650 times.
2600 << (follow_preferred_mode() ? ", hotplug-mode-update: QXL/SPICE" : "") << std::endl
703 1300 << gap << "hash: " << hash() << std::endl
704 650 << "}";
705
706 650 return ss.str();
707 650 }
708 }
709
710 273 QDebug operator<<(QDebug dbg, const Disman::OutputPtr& output)
711 {
712
1/2
✓ Branch 1 taken 273 times.
✗ Branch 2 not taken.
273 if (output) {
713 273 dbg << output->log().c_str();
714 } else {
715 dbg << "Output {null}";
716 }
717 273 return dbg;
718 }
719