Changeset View
Changeset View
Standalone View
Standalone View
backends/xrandr/xrandrconfig.cpp
Show First 20 Lines • Show All 102 Lines • ▼ Show 20 Line(s) | |||||
103 | { | 103 | { | ||
104 | delete m_outputs.take(id); | 104 | delete m_outputs.take(id); | ||
105 | } | 105 | } | ||
106 | 106 | | |||
107 | KScreen::ConfigPtr XRandRConfig::toKScreenConfig() const | 107 | KScreen::ConfigPtr XRandRConfig::toKScreenConfig() const | ||
108 | { | 108 | { | ||
109 | KScreen::ConfigPtr config(new KScreen::Config); | 109 | KScreen::ConfigPtr config(new KScreen::Config); | ||
110 | 110 | | |||
111 | auto features = Config::Feature::Writable | Config::Feature::PrimaryDisplay; | 111 | const Config::Features features = Config::Feature::Writable | Config::Feature::PrimaryDisplay | | ||
112 | Config::Feature::OutputReplication; | ||||
112 | config->setSupportedFeatures(features); | 113 | config->setSupportedFeatures(features); | ||
113 | 114 | | |||
114 | KScreen::OutputList kscreenOutputs; | 115 | KScreen::OutputList kscreenOutputs; | ||
115 | 116 | | |||
116 | for (auto iter = m_outputs.constBegin(); iter != m_outputs.constEnd(); ++iter) { | 117 | for (auto iter = m_outputs.constBegin(); iter != m_outputs.constEnd(); ++iter) { | ||
117 | KScreen::OutputPtr kscreenOutput = (*iter)->toKScreenOutput(); | 118 | KScreen::OutputPtr kscreenOutput = (*iter)->toKScreenOutput(); | ||
118 | kscreenOutputs.insert(kscreenOutput->id(), kscreenOutput); | 119 | kscreenOutputs.insert(kscreenOutput->id(), kscreenOutput); | ||
119 | } | 120 | } | ||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Line(s) | 160 | for (const KScreen::OutputPtr &kscreenOutput : kscreenOutputs) { | |||
192 | } | 193 | } | ||
193 | 194 | | |||
194 | if (kscreenOutput->rotation() != currentOutput->rotation()) { | 195 | if (kscreenOutput->rotation() != currentOutput->rotation()) { | ||
195 | if (!toChange.contains(outputId)) { | 196 | if (!toChange.contains(outputId)) { | ||
196 | toChange.insert(outputId, kscreenOutput); | 197 | toChange.insert(outputId, kscreenOutput); | ||
197 | } | 198 | } | ||
198 | } | 199 | } | ||
199 | 200 | | |||
201 | if (uint(kscreenOutput->replicationSource()) != currentOutput->replicationSource()) { | ||||
202 | currentOutput->setReplicationSource(kscreenOutput->replicationSource()); | ||||
203 | if (int sourceId = kscreenOutput->replicationSource()) { | ||||
204 | kscreenOutput->setPos(config->output(sourceId)->pos()); | ||||
205 | } | ||||
206 | if (!toChange.contains(outputId)) { | ||||
207 | toChange.insert(outputId, kscreenOutput); | ||||
208 | } | ||||
209 | } | ||||
210 | | ||||
200 | XRandRMode *currentMode = currentOutput->modes().value( | 211 | XRandRMode *currentMode = currentOutput->modes().value( | ||
201 | kscreenOutput->currentModeId().toInt()); | 212 | kscreenOutput->currentModeId().toInt()); | ||
202 | // For some reason, in some environments currentMode is null | 213 | // For some reason, in some environments currentMode is null | ||
203 | // which doesn't make sense because it is the *current* mode... | 214 | // which doesn't make sense because it is the *current* mode... | ||
204 | // Since we haven't been able to figure out the reason why | 215 | // Since we haven't been able to figure out the reason why | ||
205 | // this happens, we are adding this debug code to try to | 216 | // this happens, we are adding this debug code to try to | ||
206 | // figure out how this happened. | 217 | // figure out how this happened. | ||
207 | if (!currentMode) { | 218 | if (!currentMode) { | ||
▲ Show 20 Lines • Show All 108 Lines • ▼ Show 20 Line(s) | 324 | if (!enableOutput(output)) { | |||
316 | forceScreenSizeUpdate = true; | 327 | forceScreenSizeUpdate = true; | ||
317 | } | 328 | } | ||
318 | } | 329 | } | ||
319 | 330 | | |||
320 | if (oldPrimaryOutput != primaryOutput) { | 331 | if (oldPrimaryOutput != primaryOutput) { | ||
321 | setPrimaryOutput(primaryOutput); | 332 | setPrimaryOutput(primaryOutput); | ||
322 | } | 333 | } | ||
323 | 334 | | |||
335 | for (auto *out : m_outputs) { | ||||
336 | if (out->applyReplicationSource()) { | ||||
davidedmundson: this goes against the pattern above where we build up a changeset list and then apply it
Also… | |||||
337 | KScreen::OutputPtr kscreenOut = kscreenOutputs[out->id()]; | ||||
338 | changeOutput(kscreenOut); | ||||
339 | forceScreenSizeUpdate = true; | ||||
340 | } | ||||
341 | } | ||||
342 | | ||||
324 | if (forceScreenSizeUpdate || intermediateScreenSize != newScreenSize) { | 343 | if (forceScreenSizeUpdate || intermediateScreenSize != newScreenSize) { | ||
325 | QSize newSize = newScreenSize; | 344 | QSize newSize = newScreenSize; | ||
326 | if (forceScreenSizeUpdate) { | 345 | if (forceScreenSizeUpdate) { | ||
327 | newSize = screenSize(config); | 346 | newSize = screenSize(config); | ||
328 | qCDebug(KSCREEN_XRANDR) << "Forced to change screen size: " << newSize; | 347 | qCDebug(KSCREEN_XRANDR) << "Forced to change screen size: " << newSize; | ||
329 | } | 348 | } | ||
330 | setScreenSize(newSize); | 349 | setScreenSize(newSize); | ||
331 | } | 350 | } | ||
▲ Show 20 Lines • Show All 255 Lines • ▼ Show 20 Line(s) | 548 | { | |||
587 | } | 606 | } | ||
588 | return (reply->status == XCB_RANDR_SET_CONFIG_SUCCESS); | 607 | return (reply->status == XCB_RANDR_SET_CONFIG_SUCCESS); | ||
589 | } | 608 | } | ||
590 | 609 | | |||
591 | bool XRandRConfig::changeOutput(const OutputPtr &kscreenOutput) const | 610 | bool XRandRConfig::changeOutput(const OutputPtr &kscreenOutput) const | ||
592 | { | 611 | { | ||
593 | XRandROutput *xOutput = output(kscreenOutput->id()); | 612 | XRandROutput *xOutput = output(kscreenOutput->id()); | ||
594 | Q_ASSERT(xOutput); | 613 | Q_ASSERT(xOutput); | ||
614 | | ||||
595 | if (!xOutput->crtc()) { | 615 | if (!xOutput->crtc()) { | ||
596 | qCDebug(KSCREEN_XRANDR) << "Output" << kscreenOutput->id() | 616 | qCDebug(KSCREEN_XRANDR) << "Output" << kscreenOutput->id() | ||
597 | << "has no CRTC, falling back to enableOutput()"; | 617 | << "has no CRTC, falling back to enableOutput()"; | ||
598 | return enableOutput(kscreenOutput); | 618 | return enableOutput(kscreenOutput); | ||
599 | } | 619 | } | ||
600 | 620 | | |||
601 | int modeId = kscreenOutput->currentMode() ? kscreenOutput->currentModeId().toInt() : | 621 | int modeId = kscreenOutput->currentMode() ? kscreenOutput->currentModeId().toInt() : | ||
602 | kscreenOutput->preferredModeId().toInt(); | 622 | kscreenOutput->preferredModeId().toInt(); | ||
603 | 623 | | |||
604 | qCDebug(KSCREEN_XRANDR) << "RRSetCrtcConfig (change output)" << "\n" | 624 | qCDebug(KSCREEN_XRANDR) << "RRSetCrtcConfig (change output)" << "\n" | ||
605 | << "\tOutput:" << kscreenOutput->id() << "(" << kscreenOutput->name() | 625 | << "\tOutput:" << kscreenOutput->id() << "(" << kscreenOutput->name() | ||
606 | << ")" << "\n" | 626 | << ")" << "\n" | ||
607 | << "\tCRTC:" << xOutput->crtc()->crtc() << "\n" | 627 | << "\tCRTC:" << xOutput->crtc()->crtc() << "\n" | ||
608 | << "\tPos:" << kscreenOutput->pos() << "\n" | 628 | << "\tPos:" << kscreenOutput->pos() << "\n" | ||
609 | << "\tMode:" << modeId << kscreenOutput->currentMode() << "\n" | 629 | << "\tMode:" << modeId << kscreenOutput->currentMode() << "\n" | ||
610 | << "\tRotation:" << kscreenOutput->rotation(); | 630 | << "\tRotation:" << kscreenOutput->rotation(); | ||
611 | 631 | | |||
632 | auto sendConfig = [kscreenOutput, xOutput, modeId]() { | ||||
612 | xcb_randr_output_t outputs[1] { static_cast<xcb_randr_output_t>(kscreenOutput->id()) }; | 633 | xcb_randr_output_t outputs[1] { static_cast<xcb_randr_output_t>(kscreenOutput->id()) }; | ||
613 | | ||||
614 | auto cookie = xcb_randr_set_crtc_config(XCB::connection(), xOutput->crtc()->crtc(), | 634 | auto cookie = xcb_randr_set_crtc_config(XCB::connection(), xOutput->crtc()->crtc(), | ||
615 | XCB_CURRENT_TIME, XCB_CURRENT_TIME, | 635 | XCB_CURRENT_TIME, XCB_CURRENT_TIME, | ||
616 | kscreenOutput->pos().rx(), kscreenOutput->pos().ry(), | 636 | kscreenOutput->pos().rx(), kscreenOutput->pos().ry(), | ||
617 | modeId, | 637 | modeId, | ||
618 | kscreenOutput->rotation(), | 638 | kscreenOutput->rotation(), | ||
619 | 1, outputs); | 639 | 1, outputs); | ||
620 | 640 | | |||
621 | XCB::ScopedPointer<xcb_randr_set_crtc_config_reply_t> | 641 | XCB::ScopedPointer<xcb_randr_set_crtc_config_reply_t> | ||
622 | reply(xcb_randr_set_crtc_config_reply(XCB::connection(), cookie, nullptr)); | 642 | reply(xcb_randr_set_crtc_config_reply(XCB::connection(), cookie, nullptr)); | ||
623 | | ||||
624 | if (!reply) { | 643 | if (!reply) { | ||
625 | qCDebug(KSCREEN_XRANDR) << "\tResult: unknown (error)"; | 644 | qCDebug(KSCREEN_XRANDR) << "\tResult: unknown (error)"; | ||
626 | return false; | 645 | return false; | ||
627 | } | 646 | } | ||
628 | qCDebug(KSCREEN_XRANDR) << "\tResult: " << reply->status; | 647 | qCDebug(KSCREEN_XRANDR) << "\tResult: " << reply->status; | ||
648 | return (reply->status == XCB_RANDR_SET_CONFIG_SUCCESS); | ||||
649 | }; | ||||
650 | | ||||
651 | if (!sendConfig()) { | ||||
652 | return false; | ||||
653 | } | ||||
629 | 654 | | |||
630 | if (reply->status == XCB_RANDR_SET_CONFIG_SUCCESS) { | | |||
631 | xOutput->update(xOutput->crtc()->crtc(), modeId, | 655 | xOutput->update(xOutput->crtc()->crtc(), modeId, | ||
632 | XCB_RANDR_CONNECTION_CONNECTED, kscreenOutput->isPrimary()); | 656 | XCB_RANDR_CONNECTION_CONNECTED, kscreenOutput->isPrimary()); | ||
657 | if (uint(kscreenOutput->replicationSource()) == xOutput->replicationSource()) { | ||||
658 | xOutput->updateReplicationSource(); | ||||
davidedmundson: this method returns an important bool that's not checked | |||||
659 | if (!sendConfig()) { | ||||
davidedmundson: why do we send config twice? | |||||
660 | return false; | ||||
633 | } | 661 | } | ||
634 | return (reply->status == XCB_RANDR_SET_CONFIG_SUCCESS); | 662 | } | ||
663 | return true; | ||||
635 | } | 664 | } |
this goes against the pattern above where we build up a changeset list and then apply it
Also potentially we call changeOutput twice if it's in the toChange above. We want to avoid that