From 731b38e768ad0cc8bc9000f6b7215f63882d4011 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Wed, 4 May 2022 17:28:05 +0200 Subject: xcb: only set primary for monitor on primary X screen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's possible to have multiple X screens, and a primary monitor on each X screen. We should only use one on primary X screen as primary QScreen. The reference of QXcbScreen pointer should be used correctly. Fixes: QTBUG-102758 Pick-to: 6.3 Change-Id: I1eafd509c8c109606967a4abe9ad7e9d8c0dd464 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/xcb/qxcbconnection.h | 4 +- .../platforms/xcb/qxcbconnection_screens.cpp | 49 +++++++++++++--------- src/plugins/platforms/xcb/qxcbscreen.cpp | 5 ++- 3 files changed, 36 insertions(+), 22 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 24e2d4a121..6ce7184570 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -226,14 +226,14 @@ private: xcb_randr_get_output_info_reply_t *outputInfo); void destroyScreen(QXcbScreen *screen); void initializeScreens(bool initialized); - 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; QXcbScreen* findScreenForMonitorInfo(const QList &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); bool compressEvent(xcb_generic_event_t *event) const; inline bool timeGreaterThan(xcb_timestamp_t a, xcb_timestamp_t b) const diff --git a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp index 5aab3a04f2..149824bc92 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp @@ -309,11 +309,14 @@ void QXcbConnection::initializeScreens(bool initialized) xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup()); int xcbScreenNumber = 0; // screen number in the xcb sense QXcbScreen *primaryScreen = nullptr; + if (isAtLeastXRandR15() && initialized) + m_screens.clear(); + while (it.rem) { if (isAtLeastXRandR15()) - initializeScreensFromMonitor(&it, xcbScreenNumber, primaryScreen, initialized); + initializeScreensFromMonitor(&it, xcbScreenNumber, &primaryScreen, initialized); else if (isAtLeastXRandR12()) - initializeScreensFromOutput(&it, xcbScreenNumber, primaryScreen); + initializeScreensFromOutput(&it, xcbScreenNumber, &primaryScreen); xcb_screen_next(&it); ++xcbScreenNumber; @@ -346,7 +349,7 @@ void QXcbConnection::initializeScreens(bool initialized) } } -void QXcbConnection::initializeScreensFromOutput(xcb_screen_iterator_t *it, int xcbScreenNumber, QXcbScreen *primaryScreen) +void QXcbConnection::initializeScreensFromOutput(xcb_screen_iterator_t *it, int xcbScreenNumber, QXcbScreen **primaryScreen) { // Each "screen" in xcb terminology is a virtual desktop, // potentially a collection of separate juxtaposed monitors. @@ -420,11 +423,11 @@ void QXcbConnection::initializeScreensFromOutput(xcb_screen_iterator_t *it, int // always available if primary->output is XCB_NONE // or currently disconnected output. if (primaryScreenNumber() == xcbScreenNumber) { - if (!primaryScreen || (primary && outputs[i] == primary->output)) { - if (primaryScreen) - primaryScreen->setPrimary(false); - primaryScreen = screen; - primaryScreen->setPrimary(true); + if (!(*primaryScreen) || (primary && outputs[i] == primary->output)) { + if (*primaryScreen) + (*primaryScreen)->setPrimary(false); + *primaryScreen = screen; + (*primaryScreen)->setPrimary(true); siblings.prepend(siblings.takeLast()); } } @@ -440,15 +443,15 @@ void QXcbConnection::initializeScreensFromOutput(xcb_screen_iterator_t *it, int qCDebug(lcQpaScreen) << "created fake screen" << screen; m_screens << screen; if (primaryScreenNumber() == xcbScreenNumber) { - primaryScreen = screen; - primaryScreen->setPrimary(true); + *primaryScreen = screen; + (*primaryScreen)->setPrimary(true); } siblings << screen; } virtualDesktop->setScreens(std::move(siblings)); } -void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int xcbScreenNumber, QXcbScreen *primaryScreen, bool initialized) +void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int xcbScreenNumber, QXcbScreen **primaryScreen, bool initialized) { // Each "screen" in xcb terminology is a virtual desktop, // potentially a collection of separate juxtaposed monitors. @@ -463,8 +466,6 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int m_virtualDesktops.append(virtualDesktop); } QList old = virtualDesktop->m_screens; - if (initialized) - m_screens.clear(); QList siblings; @@ -482,21 +483,30 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int QXcbScreen *screen = nullptr; if (!initialized) { screen = new QXcbScreen(this, virtualDesktop, monitor_info, monitors_r->timestamp); - m_screens << screen; } else { - screen = findScreenForMonitorInfo(virtualDesktop->m_screens, monitor_info); + screen = findScreenForMonitorInfo(old, monitor_info); if (!screen) { screen = createScreen_monitor(virtualDesktop, monitor_info, monitors_r->timestamp); QHighDpiScaling::updateHighDpiScaling(); } else { - m_screens << screen; updateScreen_monitor(screen, monitor_info, monitors_r->timestamp); old.removeAll(screen); } } - + m_screens << screen; siblings << screen; + // similar logic with QXcbConnection::initializeScreensFromOutput() + if (primaryScreenNumber() == xcbScreenNumber) { + if (!(*primaryScreen) || monitor_info->primary) { + if (*primaryScreen) + (*primaryScreen)->setPrimary(false); + *primaryScreen = screen; + (*primaryScreen)->setPrimary(true); + siblings.prepend(siblings.takeLast()); + } + } + xcb_randr_monitor_info_next(&monitor_iter); } free(monitors_r); @@ -518,9 +528,10 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int } if (primaryScreenNumber() == xcbScreenNumber) { - primaryScreen = screen; - primaryScreen->setPrimary(true); + *primaryScreen = screen; + (*primaryScreen)->setPrimary(true); } + siblings << screen; m_screens << screen; } diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index f5ba55897c..bb33f393ec 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -678,7 +678,10 @@ void QXcbScreen::setMonitor(xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp m_sizeMillimeters = virtualDesktop()->physicalSize(); m_outputName = getName(monitorInfo); - m_primary = monitorInfo->primary; + if (connection()->primaryScreenNumber() == virtualDesktop()->number() && monitorInfo->primary) + m_primary = true; + else + m_primary = false; m_cursor = new QXcbCursor(connection(), this); -- cgit v1.2.3