Changeset View
Changeset View
Standalone View
Standalone View
src/server/outputdevice_interface.cpp
Show All 18 Lines | |||||
19 | *********************************************************************/ | 19 | *********************************************************************/ | ||
20 | #include "outputdevice_interface.h" | 20 | #include "outputdevice_interface.h" | ||
21 | #include "global_p.h" | 21 | #include "global_p.h" | ||
22 | #include "display.h" | 22 | #include "display.h" | ||
23 | #include "logging.h" | 23 | #include "logging.h" | ||
24 | 24 | | |||
25 | #include <wayland-server.h> | 25 | #include <wayland-server.h> | ||
26 | #include "wayland-org_kde_kwin_outputdevice-server-protocol.h" | 26 | #include "wayland-org_kde_kwin_outputdevice-server-protocol.h" | ||
27 | #include <QDebug> | | |||
28 | 27 | | |||
29 | namespace KWayland | 28 | namespace KWayland | ||
30 | { | 29 | { | ||
31 | namespace Server | 30 | namespace Server | ||
32 | { | 31 | { | ||
33 | 32 | | |||
34 | class OutputDeviceInterface::Private : public Global::Private | 33 | class OutputDeviceInterface::Private : public Global::Private | ||
35 | { | 34 | { | ||
36 | public: | 35 | public: | ||
37 | struct ResourceData { | 36 | struct ResourceData { | ||
38 | wl_resource *resource; | 37 | wl_resource *resource; | ||
39 | uint32_t version; | 38 | uint32_t version; | ||
40 | }; | 39 | }; | ||
41 | Private(OutputDeviceInterface *q, Display *d); | 40 | Private(OutputDeviceInterface *q, Display *d); | ||
42 | ~Private(); | 41 | ~Private(); | ||
43 | 42 | | |||
44 | | ||||
45 | void updateGeometry(); | 43 | void updateGeometry(); | ||
46 | void updateUuid(); | 44 | void updateUuid(); | ||
47 | void updateEdid(); | 45 | void updateEdid(); | ||
48 | void updateEnabled(); | 46 | void updateEnabled(); | ||
49 | void updateScale(); | 47 | void updateScale(); | ||
48 | void updateCloneGroupId(); | ||||
49 | void updateReplicationSource(TriggerReason trigger, TriggerDirection direction); | ||||
50 | void updateColorCurves(); | 50 | void updateColorCurves(); | ||
51 | void updateEisaId(); | 51 | void updateEisaId(); | ||
52 | void updateSerialNumber(); | 52 | void updateSerialNumber(); | ||
53 | 53 | | |||
54 | void sendGeometry(wl_resource *resource); | 54 | void sendGeometry(wl_resource *resource); | ||
55 | void sendMode(wl_resource *resource, const Mode &mode); | 55 | void sendMode(wl_resource *resource, const Mode &mode); | ||
56 | void sendDone(const ResourceData &data); | 56 | void sendDone(const ResourceData &data); | ||
57 | void sendUuid(const ResourceData &data); | 57 | void sendUuid(const ResourceData &data); | ||
58 | void sendEdid(const ResourceData &data); | 58 | void sendEdid(const ResourceData &data); | ||
59 | void sendEnabled(const ResourceData &data); | 59 | void sendEnabled(const ResourceData &data); | ||
60 | void sendScale(const ResourceData &data); | 60 | void sendScale(const ResourceData &data); | ||
61 | void sendColorCurves(const ResourceData &data); | 61 | void sendColorCurves(const ResourceData &data); | ||
62 | void sendCloneGroupId(const ResourceData &data); | ||||
63 | void sendReplicationSource(const ResourceData &data, TriggerReason trigger, | ||||
64 | TriggerDirection direction); | ||||
62 | void sendEisaId(const ResourceData &data); | 65 | void sendEisaId(const ResourceData &data); | ||
63 | void sendSerialNumber(const ResourceData &data); | 66 | void sendSerialNumber(const ResourceData &data); | ||
64 | 67 | | |||
68 | void setViewGeometry(const QRect &geo); | ||||
69 | void resetViewGeometry(); | ||||
70 | | ||||
71 | void resetLogicalPosition(); | ||||
72 | void resetLogicalSize(); | ||||
73 | | ||||
74 | void setClientsScale(int scale); | ||||
75 | void resetClientsScale(); | ||||
76 | void addReplica(OutputDeviceInterface *replica); | ||||
77 | void removeReplica(OutputDeviceInterface *replica); | ||||
78 | | ||||
65 | QSize physicalSize; | 79 | QSize physicalSize; | ||
80 | QRect viewGeometry; | ||||
81 | | ||||
66 | QPoint globalPosition; | 82 | QPoint globalPosition; | ||
83 | QPoint logicalPosition; | ||||
84 | QSize globalSize; | ||||
85 | QSize logicalSize; | ||||
86 | | ||||
67 | QString manufacturer = QStringLiteral("org.kde.kwin"); | 87 | QString manufacturer = QStringLiteral("org.kde.kwin"); | ||
68 | QString model = QStringLiteral("none"); | 88 | QString model = QStringLiteral("none"); | ||
69 | qreal scale = 1.0; | 89 | qreal scale = 1.0; | ||
90 | int clientsScale = 1; | ||||
70 | QString serialNumber; | 91 | QString serialNumber; | ||
71 | QString eisaId; | 92 | QString eisaId; | ||
72 | SubPixel subPixel = SubPixel::Unknown; | 93 | SubPixel subPixel = SubPixel::Unknown; | ||
73 | Transform transform = Transform::Normal; | 94 | Transform transform = Transform::Normal; | ||
74 | ColorCurves colorCurves; | 95 | ColorCurves colorCurves; | ||
75 | QList<Mode> modes; | 96 | QList<Mode> modes; | ||
76 | Mode currentMode; | 97 | Mode currentMode; | ||
98 | quint32 cloneGroupId = 0; | ||||
99 | OutputDeviceInterface *replicationSource = nullptr; | ||||
100 | QVector<OutputDeviceInterface*> replicas; | ||||
77 | QList<ResourceData> resources; | 101 | QList<ResourceData> resources; | ||
78 | 102 | | |||
79 | QByteArray edid; | 103 | QByteArray edid; | ||
80 | Enablement enabled = Enablement::Enabled; | 104 | Enablement enabled = Enablement::Enabled; | ||
81 | QByteArray uuid; | 105 | QByteArray uuid; | ||
82 | 106 | | |||
83 | static OutputDeviceInterface *get(wl_resource *native); | 107 | static OutputDeviceInterface *get(wl_resource *native); | ||
84 | 108 | | |||
85 | private: | 109 | private: | ||
86 | static Private *cast(wl_resource *native); | 110 | static Private *cast(wl_resource *native); | ||
87 | static void unbind(wl_resource *resource); | 111 | static void unbind(wl_resource *resource); | ||
88 | void bind(wl_client *client, uint32_t version, uint32_t id) override; | 112 | void bind(wl_client *client, uint32_t version, uint32_t id) override; | ||
89 | int32_t toTransform() const; | 113 | int32_t toTransform() const; | ||
90 | int32_t toSubPixel() const; | 114 | int32_t toSubPixel() const; | ||
91 | 115 | | |||
92 | static const quint32 s_version; | 116 | static const quint32 s_version; | ||
93 | OutputDeviceInterface *q; | 117 | OutputDeviceInterface *q; | ||
94 | static QVector<Private*> s_privates; | 118 | static QVector<Private*> s_privates; | ||
95 | }; | 119 | }; | ||
96 | 120 | | |||
97 | const quint32 OutputDeviceInterface::Private::s_version = 2; | 121 | const quint32 OutputDeviceInterface::Private::s_version = 3; | ||
98 | 122 | | |||
99 | QVector<OutputDeviceInterface::Private*> OutputDeviceInterface::Private::s_privates; | 123 | QVector<OutputDeviceInterface::Private*> OutputDeviceInterface::Private::s_privates; | ||
100 | 124 | | |||
101 | OutputDeviceInterface::Private::Private(OutputDeviceInterface *q, Display *d) | 125 | OutputDeviceInterface::Private::Private(OutputDeviceInterface *q, Display *d) | ||
102 | : Global::Private(d, &org_kde_kwin_outputdevice_interface, s_version) | 126 | : Global::Private(d, &org_kde_kwin_outputdevice_interface, s_version) | ||
103 | , q(q) | 127 | , q(q) | ||
104 | { | 128 | { | ||
105 | s_privates << this; | 129 | s_privates << this; | ||
Show All 40 Lines | 159 | { | |||
146 | ); | 170 | ); | ||
147 | connect(this, &OutputDeviceInterface::subPixelChanged, this, [this, d] { d->updateGeometry(); }); | 171 | connect(this, &OutputDeviceInterface::subPixelChanged, this, [this, d] { d->updateGeometry(); }); | ||
148 | connect(this, &OutputDeviceInterface::transformChanged, this, [this, d] { d->updateGeometry(); }); | 172 | connect(this, &OutputDeviceInterface::transformChanged, this, [this, d] { d->updateGeometry(); }); | ||
149 | connect(this, &OutputDeviceInterface::globalPositionChanged, this, [this, d] { d->updateGeometry(); }); | 173 | connect(this, &OutputDeviceInterface::globalPositionChanged, this, [this, d] { d->updateGeometry(); }); | ||
150 | connect(this, &OutputDeviceInterface::modelChanged, this, [this, d] { d->updateGeometry(); }); | 174 | connect(this, &OutputDeviceInterface::modelChanged, this, [this, d] { d->updateGeometry(); }); | ||
151 | connect(this, &OutputDeviceInterface::manufacturerChanged, this, [this, d] { d->updateGeometry(); }); | 175 | connect(this, &OutputDeviceInterface::manufacturerChanged, this, [this, d] { d->updateGeometry(); }); | ||
152 | connect(this, &OutputDeviceInterface::scaleFChanged, this, [this, d] { d->updateScale(); }); | 176 | connect(this, &OutputDeviceInterface::scaleFChanged, this, [this, d] { d->updateScale(); }); | ||
153 | connect(this, &OutputDeviceInterface::scaleChanged, this, [this, d] { d->updateScale(); }); | 177 | connect(this, &OutputDeviceInterface::scaleChanged, this, [this, d] { d->updateScale(); }); | ||
178 | connect(this, &OutputDeviceInterface::cloneGroupIdChanged, this, [this, d] { d->updateCloneGroupId(); }); | ||||
179 | connect(this, &OutputDeviceInterface::replicationSourceChanged, | ||||
180 | this, [this, d](OutputDeviceInterface *source, TriggerReason trigger, | ||||
181 | TriggerDirection direction) { | ||||
182 | Q_UNUSED(source) | ||||
183 | d->updateReplicationSource(trigger, direction); | ||||
184 | }); | ||||
154 | connect(this, &OutputDeviceInterface::colorCurvesChanged, this, [this, d] { d->updateColorCurves(); }); | 185 | connect(this, &OutputDeviceInterface::colorCurvesChanged, this, [this, d] { d->updateColorCurves(); }); | ||
155 | } | 186 | } | ||
156 | 187 | | |||
157 | OutputDeviceInterface::~OutputDeviceInterface() = default; | 188 | OutputDeviceInterface::~OutputDeviceInterface() | ||
189 | { | ||||
190 | Q_D(); | ||||
191 | | ||||
192 | if (d->replicationSource) { | ||||
193 | d->replicationSource->d_func()->removeReplica(this); | ||||
194 | d->replicationSource = nullptr; | ||||
195 | } | ||||
196 | | ||||
197 | for (auto *replica : d->replicas) { | ||||
198 | replica->setReplicationSource(nullptr, TriggerReason::Hotplug); | ||||
199 | } | ||||
200 | } | ||||
158 | 201 | | |||
159 | QSize OutputDeviceInterface::pixelSize() const | 202 | QSize OutputDeviceInterface::pixelSize() const | ||
160 | { | 203 | { | ||
161 | Q_D(); | 204 | Q_D(); | ||
162 | 205 | | |||
163 | if (d->currentMode.id == -1) { | 206 | if (d->currentMode.id == -1) { | ||
164 | return QSize(); | 207 | return QSize(); | ||
165 | } | 208 | } | ||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Line(s) | 262 | return mode.size == mode_it.size && | |||
220 | mode.refreshRate == mode_it.refreshRate && | 263 | mode.refreshRate == mode_it.refreshRate && | ||
221 | mode.id == mode_it.id; | 264 | mode.id == mode_it.id; | ||
222 | } | 265 | } | ||
223 | ); | 266 | ); | ||
224 | auto emitChanges = [this, d, mode] { | 267 | auto emitChanges = [this, d, mode] { | ||
225 | emit modesChanged(); | 268 | emit modesChanged(); | ||
226 | if (mode.flags.testFlag(ModeFlag::Current)) { | 269 | if (mode.flags.testFlag(ModeFlag::Current)) { | ||
227 | d->currentMode = mode; | 270 | d->currentMode = mode; | ||
271 | d->resetLogicalSize(); | ||||
272 | d->resetViewGeometry(); | ||||
228 | emit refreshRateChanged(mode.refreshRate); | 273 | emit refreshRateChanged(mode.refreshRate); | ||
229 | emit pixelSizeChanged(mode.size); | 274 | emit pixelSizeChanged(mode.size); | ||
230 | emit currentModeChanged(); | 275 | emit currentModeChanged(); | ||
231 | } | 276 | } | ||
232 | }; | 277 | }; | ||
233 | if (existingModeIt != d->modes.end()) { | 278 | if (existingModeIt != d->modes.end()) { | ||
234 | if ((*existingModeIt).flags == mode.flags) { | 279 | if ((*existingModeIt).flags == mode.flags) { | ||
235 | // nothing to do | 280 | // nothing to do | ||
Show All 35 Lines | 315 | auto existingModeIt = std::find_if(d->modes.begin(), d->modes.end(), | |||
271 | [modeId](const Mode &mode) { | 316 | [modeId](const Mode &mode) { | ||
272 | return mode.id == modeId; | 317 | return mode.id == modeId; | ||
273 | } | 318 | } | ||
274 | ); | 319 | ); | ||
275 | 320 | | |||
276 | Q_ASSERT(existingModeIt != d->modes.end()); | 321 | Q_ASSERT(existingModeIt != d->modes.end()); | ||
277 | (*existingModeIt).flags |= ModeFlag::Current; | 322 | (*existingModeIt).flags |= ModeFlag::Current; | ||
278 | d->currentMode = *existingModeIt; | 323 | d->currentMode = *existingModeIt; | ||
324 | d->resetLogicalSize(); | ||||
325 | d->resetViewGeometry(); | ||||
279 | emit modesChanged(); | 326 | emit modesChanged(); | ||
280 | emit refreshRateChanged((*existingModeIt).refreshRate); | 327 | emit refreshRateChanged((*existingModeIt).refreshRate); | ||
281 | emit pixelSizeChanged((*existingModeIt).size); | 328 | emit pixelSizeChanged((*existingModeIt).size); | ||
282 | emit currentModeChanged(); | 329 | emit currentModeChanged(); | ||
283 | } | 330 | } | ||
284 | 331 | | |||
332 | void OutputDeviceInterface::setCloneGroupId(const quint32 groupId) | ||||
333 | { | ||||
334 | Q_D(); | ||||
335 | if (d->cloneGroupId == groupId) { | ||||
336 | return; | ||||
337 | } | ||||
338 | d->cloneGroupId = groupId; | ||||
339 | emit cloneGroupIdChanged(groupId); | ||||
340 | } | ||||
341 | | ||||
342 | void OutputDeviceInterface::setReplicationSource(OutputDeviceInterface *source, | ||||
343 | TriggerReason trigger) | ||||
344 | { | ||||
345 | Q_D(); | ||||
346 | if (d->replicationSource == source) { | ||||
347 | return; | ||||
348 | } | ||||
349 | if (source) { | ||||
350 | source->d_func()->addReplica(this); | ||||
351 | } else { | ||||
352 | d->replicationSource->d_func()->removeReplica(this); | ||||
353 | } | ||||
354 | d->replicationSource = source; | ||||
355 | | ||||
356 | d->resetLogicalPosition(); | ||||
357 | d->resetLogicalSize(); | ||||
358 | d->resetViewGeometry(); | ||||
359 | | ||||
360 | emit replicationSourceChanged(source, trigger, source ? TriggerDirection::Up : | ||||
361 | TriggerDirection::Down); | ||||
362 | } | ||||
363 | | ||||
285 | int32_t OutputDeviceInterface::Private::toTransform() const | 364 | int32_t OutputDeviceInterface::Private::toTransform() const | ||
286 | { | 365 | { | ||
287 | switch (transform) { | 366 | switch (transform) { | ||
288 | case Transform::Normal: | 367 | case Transform::Normal: | ||
289 | return WL_OUTPUT_TRANSFORM_NORMAL; | 368 | return WL_OUTPUT_TRANSFORM_NORMAL; | ||
290 | case Transform::Rotated90: | 369 | case Transform::Rotated90: | ||
291 | return WL_OUTPUT_TRANSFORM_90; | 370 | return WL_OUTPUT_TRANSFORM_90; | ||
292 | case Transform::Rotated180: | 371 | case Transform::Rotated180: | ||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Line(s) | 407 | { | |||
337 | ResourceData r; | 416 | ResourceData r; | ||
338 | r.resource = resource; | 417 | r.resource = resource; | ||
339 | r.version = version; | 418 | r.version = version; | ||
340 | resources << r; | 419 | resources << r; | ||
341 | 420 | | |||
342 | sendGeometry(resource); | 421 | sendGeometry(resource); | ||
343 | sendScale(r); | 422 | sendScale(r); | ||
344 | sendColorCurves(r); | 423 | sendColorCurves(r); | ||
424 | sendReplicationSource(r, TriggerReason::None, TriggerDirection::None); | ||||
345 | sendEisaId(r); | 425 | sendEisaId(r); | ||
346 | sendSerialNumber(r); | 426 | sendSerialNumber(r); | ||
347 | 427 | | |||
348 | auto currentModeIt = modes.constEnd(); | 428 | auto currentModeIt = modes.constEnd(); | ||
349 | for (auto it = modes.constBegin(); it != modes.constEnd(); ++it) { | 429 | for (auto it = modes.constBegin(); it != modes.constEnd(); ++it) { | ||
350 | const Mode &mode = *it; | 430 | const Mode &mode = *it; | ||
351 | if (mode.flags.testFlag(ModeFlag::Current)) { | 431 | if (mode.flags.testFlag(ModeFlag::Current)) { | ||
352 | // needs to be sent as last mode | 432 | // needs to be sent as last mode | ||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Line(s) | 504 | { | |||
440 | 520 | | |||
441 | org_kde_kwin_outputdevice_send_colorcurves(data.resource, &wlRed, &wlGreen, &wlBlue); | 521 | org_kde_kwin_outputdevice_send_colorcurves(data.resource, &wlRed, &wlGreen, &wlBlue); | ||
442 | 522 | | |||
443 | wl_array_release(&wlRed); | 523 | wl_array_release(&wlRed); | ||
444 | wl_array_release(&wlGreen); | 524 | wl_array_release(&wlGreen); | ||
445 | wl_array_release(&wlBlue); | 525 | wl_array_release(&wlBlue); | ||
446 | } | 526 | } | ||
447 | 527 | | |||
528 | void OutputDeviceInterface::Private::sendCloneGroupId(const ResourceData &data) | ||||
529 | { | ||||
530 | if (wl_resource_get_version(data.resource) < ORG_KDE_KWIN_OUTPUTDEVICE_CLONE_SINCE_VERSION) { | ||||
531 | return; | ||||
532 | } | ||||
533 | org_kde_kwin_outputdevice_send_clone(data.resource, cloneGroupId); | ||||
534 | } | ||||
535 | | ||||
536 | uint32_t toTrigger(OutputDeviceInterface::TriggerReason trigger) | ||||
537 | { | ||||
538 | using Reason = OutputDeviceInterface::TriggerReason; | ||||
539 | | ||||
540 | uint32_t reason = ORG_KDE_KWIN_OUTPUTDEVICE_TRIGGER_REASON_NONE; | ||||
541 | switch (trigger) { | ||||
542 | case Reason::Explicit: | ||||
543 | reason = ORG_KDE_KWIN_OUTPUTDEVICE_TRIGGER_REASON_EXPLICIT; | ||||
544 | break; | ||||
545 | case Reason::Hotplug: | ||||
546 | reason = ORG_KDE_KWIN_OUTPUTDEVICE_TRIGGER_REASON_HOTPLUG; | ||||
547 | break; | ||||
548 | case Reason::Dpms: | ||||
549 | reason = ORG_KDE_KWIN_OUTPUTDEVICE_TRIGGER_REASON_DPMS; | ||||
550 | break; | ||||
551 | case Reason::Enablement: | ||||
552 | reason = ORG_KDE_KWIN_OUTPUTDEVICE_TRIGGER_REASON_ENABLEMENT; | ||||
553 | break; | ||||
554 | case Reason::None: | ||||
555 | break; | ||||
556 | default: | ||||
557 | Q_UNREACHABLE(); | ||||
558 | break; | ||||
559 | } | ||||
560 | return reason; | ||||
561 | } | ||||
562 | | ||||
563 | uint32_t toDirection(OutputDeviceInterface::TriggerDirection direction) | ||||
564 | { | ||||
565 | using Direction = OutputDeviceInterface::TriggerDirection; | ||||
566 | | ||||
567 | uint32_t dir = ORG_KDE_KWIN_OUTPUTDEVICE_TRIGGER_DIRECTION_NONE; | ||||
568 | switch (direction) { | ||||
569 | case Direction::Up: | ||||
570 | dir = ORG_KDE_KWIN_OUTPUTDEVICE_TRIGGER_DIRECTION_UP; | ||||
571 | break; | ||||
572 | case Direction::Down: | ||||
573 | dir = ORG_KDE_KWIN_OUTPUTDEVICE_TRIGGER_DIRECTION_DOWN; | ||||
574 | break; | ||||
575 | case Direction::None: | ||||
576 | break; | ||||
577 | default: | ||||
578 | Q_UNREACHABLE(); | ||||
579 | break; | ||||
580 | } | ||||
581 | return dir; | ||||
582 | } | ||||
583 | | ||||
584 | void OutputDeviceInterface::Private::sendReplicationSource(const ResourceData &data, | ||||
585 | TriggerReason trigger, | ||||
586 | TriggerDirection direction) | ||||
587 | { | ||||
588 | if (wl_resource_get_version(data.resource) < ORG_KDE_KWIN_OUTPUTDEVICE_REPLICATE_SINCE_VERSION) { | ||||
589 | return; | ||||
590 | } | ||||
591 | | ||||
592 | org_kde_kwin_outputdevice_send_replicate(data.resource, | ||||
593 | replicationSource ? replicationSource->uuid().constData() : nullptr, | ||||
594 | toTrigger(trigger), toDirection(direction)); | ||||
595 | } | ||||
596 | | ||||
448 | void KWayland::Server::OutputDeviceInterface::Private::sendSerialNumber(const ResourceData &data) | 597 | void KWayland::Server::OutputDeviceInterface::Private::sendSerialNumber(const ResourceData &data) | ||
449 | { | 598 | { | ||
450 | if (wl_resource_get_version(data.resource) >= ORG_KDE_KWIN_OUTPUTDEVICE_SERIAL_NUMBER_SINCE_VERSION) { | 599 | if (wl_resource_get_version(data.resource) >= ORG_KDE_KWIN_OUTPUTDEVICE_SERIAL_NUMBER_SINCE_VERSION) { | ||
451 | org_kde_kwin_outputdevice_send_serial_number(data.resource, | 600 | org_kde_kwin_outputdevice_send_serial_number(data.resource, | ||
452 | qPrintable(serialNumber)); | 601 | qPrintable(serialNumber)); | ||
453 | } | 602 | } | ||
454 | } | 603 | } | ||
455 | 604 | | |||
Show All 22 Lines | |||||
478 | void OutputDeviceInterface::Private::updateScale() | 627 | void OutputDeviceInterface::Private::updateScale() | ||
479 | { | 628 | { | ||
480 | for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) { | 629 | for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) { | ||
481 | sendScale(*it); | 630 | sendScale(*it); | ||
482 | sendDone(*it); | 631 | sendDone(*it); | ||
483 | } | 632 | } | ||
484 | } | 633 | } | ||
485 | 634 | | |||
635 | void OutputDeviceInterface::Private::updateCloneGroupId() | ||||
636 | { | ||||
637 | for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) { | ||||
638 | sendCloneGroupId(*it); | ||||
639 | sendDone(*it); | ||||
640 | } | ||||
641 | } | ||||
642 | | ||||
643 | void OutputDeviceInterface::Private::updateReplicationSource(TriggerReason trigger, | ||||
644 | TriggerDirection direction) | ||||
645 | { | ||||
646 | for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) { | ||||
647 | sendReplicationSource(*it, trigger, direction); | ||||
648 | sendDone(*it); | ||||
649 | } | ||||
650 | } | ||||
651 | | ||||
486 | void OutputDeviceInterface::Private::updateColorCurves() | 652 | void OutputDeviceInterface::Private::updateColorCurves() | ||
487 | { | 653 | { | ||
488 | for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) { | 654 | for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) { | ||
489 | sendColorCurves(*it); | 655 | sendColorCurves(*it); | ||
490 | sendDone(*it); | 656 | sendDone(*it); | ||
491 | } | 657 | } | ||
492 | } | 658 | } | ||
493 | 659 | | |||
660 | void OutputDeviceInterface::Private::setViewGeometry(const QRect &geo) | ||||
661 | { | ||||
662 | if (viewGeometry == geo) { | ||||
663 | return; | ||||
664 | } | ||||
665 | viewGeometry = geo; | ||||
666 | resetClientsScale(); | ||||
667 | emit q->viewGeometryChanged(geo); | ||||
668 | } | ||||
669 | | ||||
670 | void OutputDeviceInterface::Private::resetViewGeometry() | ||||
671 | { | ||||
672 | if (!replicationSource) { | ||||
673 | setViewGeometry(QRect(QPoint(0, 0), q->pixelSize())); | ||||
674 | return; | ||||
675 | } | ||||
676 | | ||||
677 | // Fit view into output mode keeping the aspect ratio. | ||||
678 | const QSize modeSize = q->pixelSize(); | ||||
679 | const QSize sourceSize = replicationSource->pixelSize(); | ||||
680 | | ||||
681 | QSize viewSize; | ||||
682 | viewSize.setWidth(modeSize.width()); | ||||
683 | viewSize.setHeight(viewSize.width() * sourceSize.height() / (double)sourceSize.width()); | ||||
684 | | ||||
685 | if (viewSize.height() > modeSize.height()) { | ||||
686 | const QSize oldSize = viewSize; | ||||
687 | viewSize.setHeight(modeSize.height()); | ||||
688 | viewSize.setWidth(oldSize.width() * viewSize.height() / (double)oldSize.height()); | ||||
689 | } | ||||
690 | | ||||
691 | Q_ASSERT(viewSize.height() <= modeSize.height()); | ||||
692 | Q_ASSERT(viewSize.width() <= modeSize.width()); | ||||
693 | | ||||
694 | const QPoint pos((modeSize.width() - viewSize.width()) / 2, | ||||
695 | (modeSize.height() - viewSize.height()) / 2); | ||||
696 | | ||||
697 | setViewGeometry(QRect(pos, viewSize)); | ||||
698 | } | ||||
699 | | ||||
700 | void OutputDeviceInterface::Private::resetLogicalPosition() | ||||
701 | { | ||||
702 | const QPoint pos = replicationSource ? replicationSource->d_func()->logicalPosition : | ||||
703 | globalPosition; | ||||
704 | if (logicalPosition == pos) { | ||||
705 | return; | ||||
706 | } | ||||
707 | logicalPosition = pos; | ||||
708 | for (auto *replica : replicas) { | ||||
709 | replica->d_func()->resetLogicalPosition(); | ||||
710 | } | ||||
711 | emit q->logicalPositionChanged(pos); | ||||
712 | } | ||||
713 | | ||||
714 | void OutputDeviceInterface::Private::resetLogicalSize() | ||||
715 | { | ||||
716 | const QSize size = replicationSource ? replicationSource->d_func()->logicalSize : | ||||
717 | q->pixelSize() / scale; | ||||
718 | if (logicalSize == size) { | ||||
719 | return; | ||||
720 | } | ||||
721 | logicalSize = size; | ||||
722 | for (auto *replica : replicas) { | ||||
723 | replica->d_func()->resetLogicalSize(); | ||||
724 | } | ||||
725 | emit q->logicalSizeChanged(size); | ||||
726 | } | ||||
727 | | ||||
728 | void OutputDeviceInterface::Private::addReplica(OutputDeviceInterface *replica) | ||||
729 | { | ||||
730 | replicas << replica; | ||||
731 | resetClientsScale(); | ||||
732 | } | ||||
733 | | ||||
734 | void OutputDeviceInterface::Private::removeReplica(OutputDeviceInterface *replica) | ||||
735 | { | ||||
736 | replicas.removeOne(replica); | ||||
737 | resetClientsScale(); | ||||
738 | } | ||||
739 | | ||||
740 | void OutputDeviceInterface::Private::setClientsScale(int scale) | ||||
741 | { | ||||
742 | if (clientsScale == scale) { | ||||
743 | return; | ||||
744 | } | ||||
745 | clientsScale = scale; | ||||
746 | for (auto *replica : replicas) { | ||||
747 | replica->d_func()->setClientsScale(scale); | ||||
748 | } | ||||
749 | resetLogicalSize(); | ||||
750 | emit q->clientsScaleChanged(scale); | ||||
751 | } | ||||
752 | | ||||
753 | void OutputDeviceInterface::Private::resetClientsScale() | ||||
754 | { | ||||
755 | if (replicationSource) { | ||||
756 | // The clients scale is set on the replication source. | ||||
757 | setClientsScale(replicationSource->clientsScale()); | ||||
758 | return; | ||||
759 | } | ||||
760 | | ||||
761 | const QSize size = q->viewGeometry().size(); | ||||
762 | | ||||
763 | int maxWidth = size.width(); | ||||
764 | int maxHeight = size.height(); | ||||
765 | for (auto *replica : replicas) { | ||||
766 | const QSize replicaSize = replica->viewGeometry().size(); | ||||
767 | maxWidth = qMax(replicaSize.width(), maxWidth); | ||||
768 | maxHeight = qMax(replicaSize.height(), maxHeight); | ||||
769 | } | ||||
770 | | ||||
771 | if (size.width() == maxWidth && size.height() == maxHeight) { | ||||
772 | setClientsScale(std::ceil(scale)); | ||||
773 | return; | ||||
774 | } | ||||
775 | | ||||
776 | qreal factor = qMax(maxWidth / (qreal)size.width(), maxHeight / (qreal)size.height()); | ||||
777 | setClientsScale(std::ceil(factor)); | ||||
778 | } | ||||
779 | | ||||
494 | bool OutputDeviceInterface::ColorCurves::operator==(const ColorCurves &cc) const | 780 | bool OutputDeviceInterface::ColorCurves::operator==(const ColorCurves &cc) const | ||
495 | { | 781 | { | ||
496 | return red == cc.red && green == cc.green && blue == cc.blue; | 782 | return red == cc.red && green == cc.green && blue == cc.blue; | ||
497 | } | 783 | } | ||
498 | bool OutputDeviceInterface::ColorCurves::operator!=(const ColorCurves &cc) const { | 784 | bool OutputDeviceInterface::ColorCurves::operator!=(const ColorCurves &cc) const { | ||
499 | return !operator==(cc); | 785 | return !operator==(cc); | ||
500 | } | 786 | } | ||
501 | 787 | | |||
502 | #define SETTER(setterName, type, argumentName) \ | 788 | #define SETTER(setterName, type, argumentName) \ | ||
503 | void OutputDeviceInterface::setterName(type arg) \ | 789 | void OutputDeviceInterface::setterName(type arg) \ | ||
504 | { \ | 790 | { \ | ||
505 | Q_D(); \ | 791 | Q_D(); \ | ||
506 | if (d->argumentName == arg) { \ | 792 | if (d->argumentName == arg) { \ | ||
507 | return; \ | 793 | return; \ | ||
508 | } \ | 794 | } \ | ||
509 | d->argumentName = arg; \ | 795 | d->argumentName = arg; \ | ||
510 | emit argumentName##Changed(d->argumentName); \ | 796 | emit argumentName##Changed(d->argumentName); \ | ||
511 | } | 797 | } | ||
512 | 798 | | |||
513 | SETTER(setPhysicalSize, const QSize&, physicalSize) | 799 | SETTER(setPhysicalSize, const QSize&, physicalSize) | ||
514 | SETTER(setGlobalPosition, const QPoint&, globalPosition) | | |||
515 | SETTER(setManufacturer, const QString&, manufacturer) | 800 | SETTER(setManufacturer, const QString&, manufacturer) | ||
516 | SETTER(setModel, const QString&, model) | 801 | SETTER(setModel, const QString&, model) | ||
517 | SETTER(setSerialNumber, const QString&, serialNumber) | 802 | SETTER(setSerialNumber, const QString&, serialNumber) | ||
518 | SETTER(setEisaId, const QString&, eisaId) | 803 | SETTER(setEisaId, const QString&, eisaId) | ||
519 | SETTER(setSubPixel, SubPixel, subPixel) | 804 | SETTER(setSubPixel, SubPixel, subPixel) | ||
520 | SETTER(setTransform, Transform, transform) | 805 | SETTER(setTransform, Transform, transform) | ||
521 | 806 | | |||
522 | #undef SETTER | 807 | #undef SETTER | ||
523 | 808 | | |||
809 | void OutputDeviceInterface::setGlobalPosition(const QPoint& pos) \ | ||||
810 | { | ||||
811 | Q_D(); | ||||
812 | if (d->globalPosition == pos) { | ||||
813 | return; | ||||
814 | } | ||||
815 | d->globalPosition = pos; | ||||
816 | for (auto *replica : d->replicas) { | ||||
817 | replica->d_func()->resetLogicalPosition(); | ||||
818 | } | ||||
819 | d->resetLogicalPosition(); | ||||
820 | emit globalPositionChanged(pos); | ||||
821 | } | ||||
822 | | ||||
524 | void OutputDeviceInterface::setScale(int scale) | 823 | void OutputDeviceInterface::setScale(int scale) | ||
525 | { | 824 | { | ||
526 | Q_D(); | 825 | Q_D(); | ||
527 | if (d->scale == scale) { | 826 | if (d->scale == scale) { | ||
528 | return; | 827 | return; | ||
529 | } | 828 | } | ||
530 | d->scale = scale; | 829 | d->scale = scale; | ||
830 | d->resetClientsScale(); | ||||
531 | emit scaleChanged(d->scale); | 831 | emit scaleChanged(d->scale); | ||
532 | emit scaleFChanged(d->scale); | 832 | emit scaleFChanged(d->scale); | ||
533 | } | 833 | } | ||
534 | 834 | | |||
535 | void OutputDeviceInterface::setScaleF(qreal scale) | 835 | void OutputDeviceInterface::setScaleF(qreal scale) | ||
536 | { | 836 | { | ||
537 | Q_D(); | 837 | Q_D(); | ||
538 | if (qFuzzyCompare(d->scale, scale)) { | 838 | if (qFuzzyCompare(d->scale, scale)) { | ||
539 | return; | 839 | return; | ||
540 | } | 840 | } | ||
541 | d->scale = scale; | 841 | d->scale = scale; | ||
842 | d->resetClientsScale(); | ||||
542 | emit scaleChanged(qRound(d->scale)); | 843 | emit scaleChanged(qRound(d->scale)); | ||
543 | emit scaleFChanged(d->scale); | 844 | emit scaleFChanged(d->scale); | ||
544 | } | 845 | } | ||
545 | 846 | | |||
546 | QSize OutputDeviceInterface::physicalSize() const | 847 | QSize OutputDeviceInterface::physicalSize() const | ||
547 | { | 848 | { | ||
548 | Q_D(); | 849 | Q_D(); | ||
549 | return d->physicalSize; | 850 | return d->physicalSize; | ||
550 | } | 851 | } | ||
551 | 852 | | |||
552 | QPoint OutputDeviceInterface::globalPosition() const | 853 | QPoint OutputDeviceInterface::globalPosition() const | ||
553 | { | 854 | { | ||
554 | Q_D(); | 855 | Q_D(); | ||
555 | return d->globalPosition; | 856 | return d->globalPosition; | ||
556 | } | 857 | } | ||
557 | 858 | | |||
859 | QPoint OutputDeviceInterface::logicalPosition() const | ||||
860 | { | ||||
861 | Q_D(); | ||||
862 | return d->logicalPosition; | ||||
863 | } | ||||
864 | | ||||
865 | QSize OutputDeviceInterface::logicalSize() const | ||||
866 | { | ||||
867 | Q_D(); | ||||
868 | return d->logicalSize; | ||||
869 | } | ||||
870 | | ||||
871 | QRect OutputDeviceInterface::viewGeometry() const | ||||
872 | { | ||||
873 | Q_D(); | ||||
874 | return d->viewGeometry; | ||||
875 | } | ||||
876 | | ||||
558 | QString OutputDeviceInterface::manufacturer() const | 877 | QString OutputDeviceInterface::manufacturer() const | ||
559 | { | 878 | { | ||
560 | Q_D(); | 879 | Q_D(); | ||
561 | return d->manufacturer; | 880 | return d->manufacturer; | ||
562 | } | 881 | } | ||
563 | 882 | | |||
564 | QString OutputDeviceInterface::model() const | 883 | QString OutputDeviceInterface::model() const | ||
565 | { | 884 | { | ||
566 | Q_D(); | 885 | Q_D(); | ||
567 | return d->model; | 886 | return d->model; | ||
568 | } | 887 | } | ||
569 | 888 | | |||
889 | quint32 OutputDeviceInterface::cloneGroupId() const | ||||
890 | { | ||||
891 | Q_D(); | ||||
892 | return d->cloneGroupId; | ||||
893 | } | ||||
894 | | ||||
895 | OutputDeviceInterface* OutputDeviceInterface::replicationSource() const | ||||
896 | { | ||||
897 | Q_D(); | ||||
898 | return d->replicationSource; | ||||
899 | } | ||||
900 | | ||||
570 | QString OutputDeviceInterface::serialNumber() const | 901 | QString OutputDeviceInterface::serialNumber() const | ||
571 | { | 902 | { | ||
572 | Q_D(); | 903 | Q_D(); | ||
573 | return d->serialNumber; | 904 | return d->serialNumber; | ||
574 | } | 905 | } | ||
575 | 906 | | |||
576 | QString OutputDeviceInterface::eisaId() const | 907 | QString OutputDeviceInterface::eisaId() const | ||
577 | { | 908 | { | ||
578 | Q_D(); | 909 | Q_D(); | ||
579 | return d->eisaId; | 910 | return d->eisaId; | ||
580 | } | 911 | } | ||
581 | 912 | | |||
582 | int OutputDeviceInterface::scale() const | 913 | int OutputDeviceInterface::scale() const | ||
583 | { | 914 | { | ||
584 | Q_D(); | 915 | Q_D(); | ||
585 | return qRound(d->scale); | 916 | return qRound(d->scale); | ||
586 | } | 917 | } | ||
587 | 918 | | |||
588 | qreal OutputDeviceInterface::scaleF() const | 919 | qreal OutputDeviceInterface::scaleF() const | ||
589 | { | 920 | { | ||
590 | Q_D(); | 921 | Q_D(); | ||
591 | return d->scale; | 922 | return d->scale; | ||
592 | } | 923 | } | ||
593 | 924 | | |||
925 | int OutputDeviceInterface::clientsScale() const | ||||
926 | { | ||||
927 | Q_D(); | ||||
928 | return d->clientsScale; | ||||
929 | } | ||||
594 | 930 | | |||
595 | OutputDeviceInterface::SubPixel OutputDeviceInterface::subPixel() const | 931 | OutputDeviceInterface::SubPixel OutputDeviceInterface::subPixel() const | ||
596 | { | 932 | { | ||
597 | Q_D(); | 933 | Q_D(); | ||
598 | return d->subPixel; | 934 | return d->subPixel; | ||
599 | } | 935 | } | ||
600 | 936 | | |||
601 | OutputDeviceInterface::Transform OutputDeviceInterface::transform() const | 937 | OutputDeviceInterface::Transform OutputDeviceInterface::transform() const | ||
▲ Show 20 Lines • Show All 141 Lines • Show Last 20 Lines |