xcb: fix for multi-X11Screen systems via xrandr 1.5
Fix support for systems with several X11 screens (or "virtual desktops" i.e. DISPLAY=":0.0" and ":0.1"). Namely, call QWindowSystemInterface::handle*() only after we settled on which screen will be primary. Also cleanup some code logic, particularly, make sure that QXcbConnection::m_screens is stores screen in a reliable order: - Primary screen for primary virtual desktop - Other screens for primary virtual desktop - Screens for other virtual desktops (primary screen is first) Pick-to: 6.5 Fixes: QTBUG-110898 Fixes: QTBUG-130714 Change-Id: I3e78e56466998dff4d7da83db45f0ed61463f041 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io> Reviewed-by: Liang Qi <liang.qi@qt.io> (cherry picked from commit 64590233aff4f7e9797f37484dbdd6d8465a1ea9) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
b63cceb1b0
commit
2b3d867d9f
@ -226,9 +226,6 @@ private:
|
|||||||
void initializeScreensWithoutXRandR(xcb_screen_iterator_t *it, int screenNumber, QXcbScreen **primaryScreen);
|
void initializeScreensWithoutXRandR(xcb_screen_iterator_t *it, int screenNumber, QXcbScreen **primaryScreen);
|
||||||
void initializeScreensFromOutput(xcb_screen_iterator_t *it, int screenNumber, QXcbScreen **primaryScreen);
|
void initializeScreensFromOutput(xcb_screen_iterator_t *it, int screenNumber, QXcbScreen **primaryScreen);
|
||||||
|
|
||||||
void updateScreen_monitor(QXcbScreen *screen, xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp_t timestamp = XCB_NONE);
|
|
||||||
QXcbScreen *createScreen_monitor(QXcbVirtualDesktop *virtualDesktop,
|
|
||||||
xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp_t timestamp = XCB_NONE);
|
|
||||||
QXcbVirtualDesktop* virtualDesktopForNumber(int n) const;
|
QXcbVirtualDesktop* virtualDesktopForNumber(int n) const;
|
||||||
QXcbScreen* findScreenForMonitorInfo(const QList<QPlatformScreen *> &screens, xcb_randr_monitor_info_t *monitorInfo);
|
QXcbScreen* findScreenForMonitorInfo(const QList<QPlatformScreen *> &screens, xcb_randr_monitor_info_t *monitorInfo);
|
||||||
void initializeScreensFromMonitor(xcb_screen_iterator_t *it, int screenNumber, QXcbScreen **primaryScreen, bool initialized);
|
void initializeScreensFromMonitor(xcb_screen_iterator_t *it, int screenNumber, QXcbScreen **primaryScreen, bool initialized);
|
||||||
|
@ -246,40 +246,6 @@ void QXcbConnection::destroyScreen(QXcbScreen *screen)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QXcbConnection::updateScreen_monitor(QXcbScreen *screen, xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp_t timestamp)
|
|
||||||
{
|
|
||||||
screen->setMonitor(monitorInfo, timestamp);
|
|
||||||
|
|
||||||
if (screen->isPrimary()) {
|
|
||||||
const int idx = m_screens.indexOf(screen);
|
|
||||||
if (idx > 0) {
|
|
||||||
std::as_const(m_screens).first()->setPrimary(false);
|
|
||||||
m_screens.swapItemsAt(0, idx);
|
|
||||||
}
|
|
||||||
screen->virtualDesktop()->setPrimaryScreen(screen);
|
|
||||||
QWindowSystemInterface::handlePrimaryScreenChanged(screen);
|
|
||||||
}
|
|
||||||
qCDebug(lcQpaScreen) << "updateScreen_monitor: update" << screen << "(Primary:" << screen->isPrimary() << ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
QXcbScreen *QXcbConnection::createScreen_monitor(QXcbVirtualDesktop *virtualDesktop, xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp_t timestamp)
|
|
||||||
{
|
|
||||||
QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, monitorInfo, timestamp);
|
|
||||||
|
|
||||||
if (screen->isPrimary()) {
|
|
||||||
if (!m_screens.isEmpty())
|
|
||||||
std::as_const(m_screens).first()->setPrimary(false);
|
|
||||||
|
|
||||||
m_screens.prepend(screen);
|
|
||||||
} else {
|
|
||||||
m_screens.append(screen);
|
|
||||||
}
|
|
||||||
qCDebug(lcQpaScreen) << "createScreen_monitor: adding" << screen << "(Primary:" << screen->isPrimary() << ")";
|
|
||||||
virtualDesktop->addScreen(screen);
|
|
||||||
QWindowSystemInterface::handleScreenAdded(screen, screen->isPrimary());
|
|
||||||
return screen;
|
|
||||||
}
|
|
||||||
|
|
||||||
QXcbVirtualDesktop *QXcbConnection::virtualDesktopForNumber(int n) const
|
QXcbVirtualDesktop *QXcbConnection::virtualDesktopForNumber(int n) const
|
||||||
{
|
{
|
||||||
for (QXcbVirtualDesktop *virtualDesktop : m_virtualDesktops) {
|
for (QXcbVirtualDesktop *virtualDesktop : m_virtualDesktops) {
|
||||||
@ -489,7 +455,8 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int
|
|||||||
virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
|
virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
|
||||||
m_virtualDesktops.append(virtualDesktop);
|
m_virtualDesktops.append(virtualDesktop);
|
||||||
}
|
}
|
||||||
QList<QPlatformScreen*> old = virtualDesktop->m_screens;
|
QList<QPlatformScreen *> old = virtualDesktop->m_screens;
|
||||||
|
QList<QXcbScreen *> newScreens;
|
||||||
|
|
||||||
QList<QPlatformScreen *> siblings;
|
QList<QPlatformScreen *> siblings;
|
||||||
|
|
||||||
@ -510,25 +477,26 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int
|
|||||||
} else {
|
} else {
|
||||||
screen = findScreenForMonitorInfo(old, monitor_info);
|
screen = findScreenForMonitorInfo(old, monitor_info);
|
||||||
if (!screen) {
|
if (!screen) {
|
||||||
screen = createScreen_monitor(virtualDesktop, monitor_info, monitors_r->timestamp);
|
screen = new QXcbScreen(this, virtualDesktop, monitor_info, monitors_r->timestamp);
|
||||||
|
newScreens.append(screen);
|
||||||
} else {
|
} else {
|
||||||
updateScreen_monitor(screen, monitor_info, monitors_r->timestamp);
|
screen->setMonitor(monitor_info, monitors_r->timestamp);
|
||||||
old.removeAll(screen);
|
old.removeAll(screen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!m_screens.contains(screen))
|
|
||||||
m_screens << screen;
|
|
||||||
siblings << screen;
|
|
||||||
|
|
||||||
// similar logic with QXcbConnection::initializeScreensFromOutput()
|
if (screen->isPrimary()) {
|
||||||
if (primaryScreenNumber() == xcbScreenNumber) {
|
siblings.prepend (screen);
|
||||||
if (!(*primaryScreen) || monitor_info->primary) {
|
if (primaryScreenNumber() == xcbScreenNumber) {
|
||||||
if (*primaryScreen)
|
if (*primaryScreen)
|
||||||
(*primaryScreen)->setPrimary(false);
|
(*primaryScreen)->setPrimary(false);
|
||||||
*primaryScreen = screen;
|
*primaryScreen = screen;
|
||||||
(*primaryScreen)->setPrimary(true);
|
(*primaryScreen)->setPrimary(true);
|
||||||
siblings.prepend(siblings.takeLast());
|
} else { // Only screens on the main virtual desktop can be primary
|
||||||
|
screen->setPrimary(false);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
siblings.append(screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_randr_monitor_info_next(&monitor_iter);
|
xcb_randr_monitor_info_next(&monitor_iter);
|
||||||
@ -551,20 +519,47 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int
|
|||||||
qCDebug(lcQpaScreen) << "create a fake screen: " << screen;
|
qCDebug(lcQpaScreen) << "create a fake screen: " << screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (primaryScreenNumber() == xcbScreenNumber) {
|
siblings << screen;
|
||||||
*primaryScreen = screen;
|
}
|
||||||
|
|
||||||
|
if (primaryScreenNumber() == xcbScreenNumber) {
|
||||||
|
// If no screen was reported to be primary, use the first one
|
||||||
|
if (!*primaryScreen) {
|
||||||
|
(*primaryScreen) = static_cast<QXcbScreen *>(siblings.first());
|
||||||
(*primaryScreen)->setPrimary(true);
|
(*primaryScreen)->setPrimary(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
siblings << screen;
|
// Prepand the siblings to the current list of screens
|
||||||
m_screens << screen;
|
QList<QXcbScreen *> new_m_screens;
|
||||||
|
new_m_screens.reserve( siblings.size() + m_screens.size() );
|
||||||
|
for (QPlatformScreen *ps:siblings) {
|
||||||
|
new_m_screens.append(static_cast<QXcbScreen *>(ps));
|
||||||
|
}
|
||||||
|
new_m_screens.append(std::move(m_screens));
|
||||||
|
m_screens = std::move(new_m_screens);
|
||||||
|
} else {
|
||||||
|
for (QPlatformScreen *ps:siblings) {
|
||||||
|
m_screens.append(static_cast<QXcbScreen *>(ps));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
|
if (primaryScreenNumber() == xcbScreenNumber && !newScreens.contains(*primaryScreen)) {
|
||||||
|
qCDebug(lcQpaScreen) << "assigning screen as primary: " << *primaryScreen;
|
||||||
|
virtualDesktop->setPrimaryScreen(*primaryScreen);
|
||||||
|
QWindowSystemInterface::handlePrimaryScreenChanged(*primaryScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (QXcbScreen *screen: newScreens) {
|
||||||
|
qCDebug(lcQpaScreen) << "adding screen: " << screen << "(Primary:" << screen->isPrimary() << ")";
|
||||||
|
virtualDesktop->addScreen(screen);
|
||||||
|
QWindowSystemInterface::handleScreenAdded(screen, screen->isPrimary());
|
||||||
|
}
|
||||||
|
|
||||||
for (QPlatformScreen *ps : old) {
|
for (QPlatformScreen *ps : old) {
|
||||||
virtualDesktop->removeScreen(ps);
|
|
||||||
qCDebug(lcQpaScreen) << "destroy screen: " << ps;
|
qCDebug(lcQpaScreen) << "destroy screen: " << ps;
|
||||||
QWindowSystemInterface::handleScreenRemoved(ps);
|
QWindowSystemInterface::handleScreenRemoved(ps);
|
||||||
|
virtualDesktop->removeScreen(ps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user