Changeset View
Changeset View
Standalone View
Standalone View
backends/xrandr/xrandrconfig.cpp
Show First 20 Lines • Show All 149 Lines • ▼ Show 20 Line(s) | 129 | { | |||
---|---|---|---|---|---|
150 | 150 | | |||
151 | for (const XRandROutput *xrandrOutput : m_outputs) { | 151 | for (const XRandROutput *xrandrOutput : m_outputs) { | ||
152 | if (xrandrOutput->isPrimary()) { | 152 | if (xrandrOutput->isPrimary()) { | ||
153 | oldPrimaryOutput = xrandrOutput->id(); | 153 | oldPrimaryOutput = xrandrOutput->id(); | ||
154 | break; | 154 | break; | ||
155 | } | 155 | } | ||
156 | } | 156 | } | ||
157 | 157 | | |||
158 | KScreen::OutputList toDisable, toEnable, toChange, toReplicate; | 158 | KScreen::OutputList toDisable, toEnable, toChange; | ||
159 | 159 | | |||
160 | for (const KScreen::OutputPtr &kscreenOutput : kscreenOutputs) { | 160 | for (const KScreen::OutputPtr &kscreenOutput : kscreenOutputs) { | ||
161 | xcb_randr_output_t outputId = kscreenOutput->id(); | 161 | xcb_randr_output_t outputId = kscreenOutput->id(); | ||
162 | XRandROutput *currentOutput = output(outputId); | 162 | XRandROutput *currentOutput = output(outputId); | ||
163 | //Only set the output as primary if it is enabled. | 163 | //Only set the output as primary if it is enabled. | ||
164 | if (kscreenOutput->isPrimary() && kscreenOutput->isEnabled()) { | 164 | if (kscreenOutput->isPrimary() && kscreenOutput->isEnabled()) { | ||
165 | primaryOutput = outputId; | 165 | primaryOutput = outputId; | ||
166 | } | 166 | } | ||
167 | 167 | | |||
168 | const bool currentEnabled = currentOutput->isEnabled(); | 168 | const bool currentEnabled = currentOutput->isEnabled(); | ||
169 | 169 | | |||
170 | if (!kscreenOutput->isEnabled() && currentEnabled) { | 170 | if (!kscreenOutput->isEnabled() && currentEnabled) { | ||
171 | toDisable.insert(outputId, kscreenOutput); | 171 | toDisable.insert(outputId, kscreenOutput); | ||
172 | continue; | 172 | continue; | ||
173 | } else if (kscreenOutput->isEnabled() && !currentEnabled) { | 173 | } else if (kscreenOutput->isEnabled() && !currentEnabled) { | ||
174 | toEnable.insert(outputId, kscreenOutput); | 174 | toEnable.insert(outputId, kscreenOutput); | ||
175 | ++neededCrtcs; | 175 | ++neededCrtcs; | ||
176 | continue; | 176 | continue; | ||
177 | } else if (!kscreenOutput->isEnabled() && !currentEnabled) { | 177 | } else if (!kscreenOutput->isEnabled() && !currentEnabled) { | ||
178 | continue; | 178 | continue; | ||
179 | } | 179 | } | ||
180 | 180 | | |||
181 | ++neededCrtcs; | 181 | ++neededCrtcs; | ||
182 | 182 | | |||
183 | // Update replication when it is supposed to be a replica or changes not to be anymore. | | |||
184 | if (kscreenOutput->replicationSource() || currentOutput->replicationSource()) { | | |||
185 | if (int sourceId = kscreenOutput->replicationSource()) { | | |||
186 | kscreenOutput->setPos(config->output(sourceId)->pos()); | | |||
187 | } | | |||
188 | if (!toReplicate.contains(outputId)) { | | |||
189 | toReplicate.insert(outputId, kscreenOutput); | | |||
190 | } | | |||
191 | } | | |||
192 | | ||||
193 | if (kscreenOutput->currentModeId() != currentOutput->currentModeId()) { | 183 | if (kscreenOutput->currentModeId() != currentOutput->currentModeId()) { | ||
194 | if (!toChange.contains(outputId)) { | 184 | if (!toChange.contains(outputId)) { | ||
195 | toChange.insert(outputId, kscreenOutput); | 185 | toChange.insert(outputId, kscreenOutput); | ||
196 | } | 186 | } | ||
197 | } | 187 | } | ||
198 | 188 | | |||
199 | if (kscreenOutput->pos() != currentOutput->position()) { | 189 | if (kscreenOutput->pos() != currentOutput->position()) { | ||
200 | if (!toChange.contains(outputId)) { | 190 | if (!toChange.contains(outputId)) { | ||
201 | toChange.insert(outputId, kscreenOutput); | 191 | toChange.insert(outputId, kscreenOutput); | ||
202 | } | 192 | } | ||
203 | } | 193 | } | ||
204 | 194 | | |||
205 | if (kscreenOutput->rotation() != currentOutput->rotation()) { | 195 | if (kscreenOutput->rotation() != currentOutput->rotation()) { | ||
206 | if (!toChange.contains(outputId)) { | 196 | if (!toChange.contains(outputId)) { | ||
207 | toChange.insert(outputId, kscreenOutput); | 197 | toChange.insert(outputId, kscreenOutput); | ||
208 | } | 198 | } | ||
209 | } | 199 | } | ||
210 | 200 | | |||
201 | if (kscreenOutput->explicitLogicalSize() != currentOutput->logicalSize()) { | ||||
202 | if (!toChange.contains(outputId)) { | ||||
203 | toChange.insert(outputId, kscreenOutput); | ||||
204 | } | ||||
205 | } | ||||
206 | | ||||
211 | XRandRMode *currentMode = currentOutput->modes().value( | 207 | XRandRMode *currentMode = currentOutput->modes().value( | ||
212 | kscreenOutput->currentModeId().toInt()); | 208 | kscreenOutput->currentModeId().toInt()); | ||
213 | // For some reason, in some environments currentMode is null | 209 | // For some reason, in some environments currentMode is null | ||
214 | // which doesn't make sense because it is the *current* mode... | 210 | // which doesn't make sense because it is the *current* mode... | ||
215 | // Since we haven't been able to figure out the reason why | 211 | // Since we haven't been able to figure out the reason why | ||
216 | // this happens, we are adding this debug code to try to | 212 | // this happens, we are adding this debug code to try to | ||
217 | // figure out how this happened. | 213 | // figure out how this happened. | ||
218 | if (!currentMode) { | 214 | if (!currentMode) { | ||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Line(s) | |||||
286 | } | 282 | } | ||
287 | 283 | | |||
288 | // Grab the server so that no-one else can do changes to XRandR and to block | 284 | // Grab the server so that no-one else can do changes to XRandR and to block | ||
289 | // change notifications until we are done | 285 | // change notifications until we are done | ||
290 | XCB::GrabServer grabber; | 286 | XCB::GrabServer grabber; | ||
291 | 287 | | |||
292 | //If there is nothing to do, not even bother | 288 | //If there is nothing to do, not even bother | ||
293 | if (oldPrimaryOutput == primaryOutput && toDisable.isEmpty() && | 289 | if (oldPrimaryOutput == primaryOutput && toDisable.isEmpty() && | ||
294 | toEnable.isEmpty() && toChange.isEmpty() && toReplicate.isEmpty()) { | 290 | toEnable.isEmpty() && toChange.isEmpty()) { | ||
295 | if (newScreenSize != currentScreenSize) { | 291 | if (newScreenSize != currentScreenSize) { | ||
296 | setScreenSize(newScreenSize); | 292 | setScreenSize(newScreenSize); | ||
297 | } | 293 | } | ||
298 | return; | 294 | return; | ||
299 | } | 295 | } | ||
300 | 296 | | |||
301 | for (const KScreen::OutputPtr &output : toDisable) { | 297 | for (const KScreen::OutputPtr &output : toDisable) { | ||
302 | disableOutput(output); | 298 | disableOutput(output); | ||
Show All 19 Lines | |||||
322 | 318 | | |||
323 | for (const KScreen::OutputPtr &output : toEnable) { | 319 | for (const KScreen::OutputPtr &output : toEnable) { | ||
324 | if (!enableOutput(output)) { | 320 | if (!enableOutput(output)) { | ||
325 | qCDebug(KSCREEN_XRANDR) << "Output failed to be Enabled: " << output->name(); | 321 | qCDebug(KSCREEN_XRANDR) << "Output failed to be Enabled: " << output->name(); | ||
326 | forceScreenSizeUpdate = true; | 322 | forceScreenSizeUpdate = true; | ||
327 | } | 323 | } | ||
328 | } | 324 | } | ||
329 | 325 | | |||
330 | for (KScreen::OutputPtr &output : toReplicate) { | | |||
331 | if (replicateOutput(output)) { | | |||
332 | forceScreenSizeUpdate = true; | | |||
333 | } | | |||
334 | } | | |||
335 | | ||||
336 | if (oldPrimaryOutput != primaryOutput) { | 326 | if (oldPrimaryOutput != primaryOutput) { | ||
337 | setPrimaryOutput(primaryOutput); | 327 | setPrimaryOutput(primaryOutput); | ||
338 | } | 328 | } | ||
339 | 329 | | |||
340 | if (forceScreenSizeUpdate || intermediateScreenSize != newScreenSize) { | 330 | if (forceScreenSizeUpdate || intermediateScreenSize != newScreenSize) { | ||
341 | QSize newSize = newScreenSize; | 331 | QSize newSize = newScreenSize; | ||
342 | if (forceScreenSizeUpdate) { | 332 | if (forceScreenSizeUpdate) { | ||
343 | newSize = screenSize(config); | 333 | newSize = screenSize(config); | ||
▲ Show 20 Lines • Show All 217 Lines • ▼ Show 20 Line(s) | 539 | for (XRandRCrtc *crtc : m_crtcs) { | |||
561 | } | 551 | } | ||
562 | } | 552 | } | ||
563 | 553 | | |||
564 | if (!freeCrtc) { | 554 | if (!freeCrtc) { | ||
565 | qCWarning(KSCREEN_XRANDR) << "Failed to get free CRTC for output" << kscreenOutput->id(); | 555 | qCWarning(KSCREEN_XRANDR) << "Failed to get free CRTC for output" << kscreenOutput->id(); | ||
566 | return false; | 556 | return false; | ||
567 | } | 557 | } | ||
568 | 558 | | |||
559 | XRandROutput *xOutput = output(kscreenOutput->id()); | ||||
569 | const int modeId = kscreenOutput->currentMode() ? kscreenOutput->currentModeId().toInt() : | 560 | const int modeId = kscreenOutput->currentMode() ? kscreenOutput->currentModeId().toInt() : | ||
570 | kscreenOutput->preferredModeId().toInt(); | 561 | kscreenOutput->preferredModeId().toInt(); | ||
562 | xOutput->updateLogicalSize(kscreenOutput); | ||||
571 | 563 | | |||
572 | qCDebug(KSCREEN_XRANDR) << "RRSetCrtcConfig (enable output)" << "\n" | 564 | qCDebug(KSCREEN_XRANDR) << "RRSetCrtcConfig (enable output)" << "\n" | ||
573 | << "\tOutput:" << kscreenOutput->id() << "(" << kscreenOutput->name() | 565 | << "\tOutput:" << kscreenOutput->id() << "(" << kscreenOutput->name() | ||
574 | << ")" << "\n" | 566 | << ")" << "\n" | ||
575 | << "\tNew CRTC:" << freeCrtc->crtc() << "\n" | 567 | << "\tNew CRTC:" << freeCrtc->crtc() << "\n" | ||
576 | << "\tPos:" << kscreenOutput->pos() << "\n" | 568 | << "\tPos:" << kscreenOutput->pos() << "\n" | ||
577 | << "\tMode:" << kscreenOutput->currentMode() | 569 | << "\tMode:" << kscreenOutput->currentMode() | ||
578 | << "Preferred:" << kscreenOutput->preferredModeId() << "\n" | 570 | << "Preferred:" << kscreenOutput->preferredModeId() << "\n" | ||
579 | << "\tRotation:" << kscreenOutput->rotation(); | 571 | << "\tRotation:" << kscreenOutput->rotation(); | ||
580 | 572 | | |||
581 | if (!sendConfig(kscreenOutput, freeCrtc)) { | 573 | if (!sendConfig(kscreenOutput, freeCrtc)) { | ||
582 | return false; | 574 | return false; | ||
583 | } | 575 | } | ||
584 | 576 | | |||
585 | output(kscreenOutput->id())->update(freeCrtc->crtc(), modeId, XCB_RANDR_CONNECTION_CONNECTED, | 577 | xOutput->update(freeCrtc->crtc(), modeId, XCB_RANDR_CONNECTION_CONNECTED, | ||
586 | kscreenOutput->isPrimary()); | 578 | kscreenOutput->isPrimary()); | ||
587 | return true; | 579 | return true; | ||
588 | } | 580 | } | ||
589 | 581 | | |||
590 | bool XRandRConfig::changeOutput(const KScreen::OutputPtr &kscreenOutput) const | 582 | bool XRandRConfig::changeOutput(const KScreen::OutputPtr &kscreenOutput) const | ||
591 | { | 583 | { | ||
592 | XRandROutput *xOutput = output(kscreenOutput->id()); | 584 | XRandROutput *xOutput = output(kscreenOutput->id()); | ||
593 | Q_ASSERT(xOutput); | 585 | Q_ASSERT(xOutput); | ||
594 | 586 | | |||
595 | if (!xOutput->crtc()) { | 587 | if (!xOutput->crtc()) { | ||
596 | qCDebug(KSCREEN_XRANDR) << "Output" << kscreenOutput->id() | 588 | qCDebug(KSCREEN_XRANDR) << "Output" << kscreenOutput->id() | ||
597 | << "has no CRTC, falling back to enableOutput()"; | 589 | << "has no CRTC, falling back to enableOutput()"; | ||
598 | return enableOutput(kscreenOutput); | 590 | return enableOutput(kscreenOutput); | ||
599 | } | 591 | } | ||
600 | 592 | | |||
601 | int modeId = kscreenOutput->currentMode() ? kscreenOutput->currentModeId().toInt() : | 593 | int modeId = kscreenOutput->currentMode() ? kscreenOutput->currentModeId().toInt() : | ||
602 | kscreenOutput->preferredModeId().toInt(); | 594 | kscreenOutput->preferredModeId().toInt(); | ||
595 | xOutput->updateLogicalSize(kscreenOutput); | ||||
603 | 596 | | |||
604 | qCDebug(KSCREEN_XRANDR) << "RRSetCrtcConfig (change output)" << "\n" | 597 | qCDebug(KSCREEN_XRANDR) << "RRSetCrtcConfig (change output)" << "\n" | ||
605 | << "\tOutput:" << kscreenOutput->id() << "(" << kscreenOutput->name() | 598 | << "\tOutput:" << kscreenOutput->id() << "(" << kscreenOutput->name() | ||
606 | << ")" << "\n" | 599 | << ")" << "\n" | ||
607 | << "\tCRTC:" << xOutput->crtc()->crtc() << "\n" | 600 | << "\tCRTC:" << xOutput->crtc()->crtc() << "\n" | ||
608 | << "\tPos:" << kscreenOutput->pos() << "\n" | 601 | << "\tPos:" << kscreenOutput->pos() << "\n" | ||
609 | << "\tMode:" << modeId << kscreenOutput->currentMode() << "\n" | 602 | << "\tMode:" << modeId << kscreenOutput->currentMode() << "\n" | ||
610 | << "\tRotation:" << kscreenOutput->rotation(); | 603 | << "\tRotation:" << kscreenOutput->rotation(); | ||
611 | 604 | | |||
612 | if (!sendConfig(kscreenOutput, xOutput->crtc())) { | 605 | if (!sendConfig(kscreenOutput, xOutput->crtc())) { | ||
613 | return false; | 606 | return false; | ||
614 | } | 607 | } | ||
615 | 608 | | |||
616 | xOutput->update(xOutput->crtc()->crtc(), modeId, | 609 | xOutput->update(xOutput->crtc()->crtc(), modeId, | ||
617 | XCB_RANDR_CONNECTION_CONNECTED, kscreenOutput->isPrimary()); | 610 | XCB_RANDR_CONNECTION_CONNECTED, kscreenOutput->isPrimary()); | ||
618 | return true; | 611 | return true; | ||
619 | } | 612 | } | ||
620 | 613 | | |||
621 | bool XRandRConfig::replicateOutput(const KScreen::OutputPtr &kscreenOutput) const | | |||
622 | { | | |||
623 | XRandROutput *xOutput = output(kscreenOutput->id()); | | |||
624 | Q_ASSERT(xOutput); | | |||
625 | | ||||
626 | if (!xOutput->crtc()) { | | |||
627 | qCDebug(KSCREEN_XRANDR) << "Output" << kscreenOutput->id() | | |||
628 | << "has no CRTC, falling back to enableOutput()"; | | |||
629 | enableOutput(kscreenOutput); | | |||
630 | } | | |||
631 | | ||||
632 | int modeId = kscreenOutput->currentMode() ? kscreenOutput->currentModeId().toInt() : | | |||
633 | kscreenOutput->preferredModeId().toInt(); | | |||
634 | | ||||
635 | qCDebug(KSCREEN_XRANDR) << "RRSetCrtcConfig (change output)" << "\n" | | |||
636 | << "\tOutput:" << kscreenOutput->id() << "(" << kscreenOutput->name() | | |||
637 | << ")" << "\n" | | |||
638 | << "\tCRTC:" << xOutput->crtc()->crtc() << "\n" | | |||
639 | << "\tPos:" << kscreenOutput->pos() << "\n" | | |||
640 | << "\tMode:" << modeId << kscreenOutput->currentMode() << "\n" | | |||
641 | << "\tRotation:" << kscreenOutput->rotation(); | | |||
642 | | ||||
643 | if (!xOutput->setReplicationSource(kscreenOutput->replicationSource())) { | | |||
644 | return false; | | |||
645 | } | | |||
646 | if (!sendConfig(kscreenOutput, xOutput->crtc())) { | | |||
647 | return false; | | |||
648 | } | | |||
649 | | ||||
650 | xOutput->update(xOutput->crtc()->crtc(), modeId, | | |||
651 | XCB_RANDR_CONNECTION_CONNECTED, kscreenOutput->isPrimary()); | | |||
652 | return true; | | |||
653 | } | | |||
654 | | ||||
655 | bool XRandRConfig::sendConfig(const KScreen::OutputPtr &kscreenOutput, XRandRCrtc *crtc) const | 614 | bool XRandRConfig::sendConfig(const KScreen::OutputPtr &kscreenOutput, XRandRCrtc *crtc) const | ||
656 | { | 615 | { | ||
657 | xcb_randr_output_t outputs[1] { static_cast<xcb_randr_output_t>(kscreenOutput->id()) }; | 616 | xcb_randr_output_t outputs[1] { static_cast<xcb_randr_output_t>(kscreenOutput->id()) }; | ||
658 | const int modeId = kscreenOutput->currentMode() ? kscreenOutput->currentModeId().toInt() : | 617 | const int modeId = kscreenOutput->currentMode() ? kscreenOutput->currentModeId().toInt() : | ||
659 | kscreenOutput->preferredModeId().toInt(); | 618 | kscreenOutput->preferredModeId().toInt(); | ||
660 | 619 | | |||
661 | auto cookie = xcb_randr_set_crtc_config(XCB::connection(), crtc->crtc(), | 620 | auto cookie = xcb_randr_set_crtc_config(XCB::connection(), crtc->crtc(), | ||
662 | XCB_CURRENT_TIME, XCB_CURRENT_TIME, | 621 | XCB_CURRENT_TIME, XCB_CURRENT_TIME, | ||
Show All 14 Lines |