diff options
author | Liang Qi <liang.qi@qt.io> | 2021-09-14 21:22:08 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2021-09-18 16:29:39 +0200 |
commit | d8f37d94e537aaab4fa960b80aacabe79bcc14c4 (patch) | |
tree | 8aabb56368e160f81fd1fee6aff0f4b41b8d410e /src/plugins/platforms/xcb | |
parent | b2c3b3e8fe0d8bdc88051d0120aaa8d5cf8acce0 (diff) |
xcb: convert last screen to fake when no screen
available for xrandr 1.5 like we did before for xrandr 1.4
(since a094af001795c9651b299d700a992150d1aba33a).
Tested with following combination:
* qtbase -DECM_ENABLE_SANITIZERS=address cmake build
* examples/widgets/widgets/wiggly with
ASAN_OPTIONS=verify_asan_link_order=0 env
* xrandr --output LastScreen --off and --auto.
Fixes: QTBUG-96247
Task-number: QTBUG-42985
Change-Id: Idd95d1a3aa057d23e3adb6635dd1acbb2c853497
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src/plugins/platforms/xcb')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection_screens.cpp | 36 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbscreen.cpp | 37 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbscreen.h | 1 |
3 files changed, 57 insertions, 17 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp index 420b296f35..22285b836d 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp @@ -378,7 +378,8 @@ void QXcbConnection::initializeScreens(bool initialized) } } - qCDebug(lcQpaScreen) << "primary output is" << qAsConst(m_screens).first()->name(); + if (!m_screens.isEmpty()) + qCDebug(lcQpaScreen) << "primary output is" << qAsConst(m_screens).first()->name(); } } @@ -499,6 +500,8 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int m_virtualDesktops.append(virtualDesktop); } QList<QPlatformScreen*> old = virtualDesktop->m_screens; + if (initialized) + m_screens.clear(); QList<QPlatformScreen *> siblings; @@ -523,6 +526,7 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int 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); } @@ -530,14 +534,29 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int siblings << screen; + if (primaryScreenNumber() == xcbScreenNumber) { + primaryScreen = screen; + primaryScreen->setPrimary(true); + } + xcb_randr_monitor_info_next(&monitor_iter); } if (siblings.isEmpty()) { - // If there are no XRandR outputs or XRandR extension is missing, - // then create a fake/legacy screen. - auto screen = new QXcbScreen(this, virtualDesktop, nullptr); - qCDebug(lcQpaScreen) << "created fake screen" << screen; + QXcbScreen *screen = nullptr; + if (initialized && !old.isEmpty()) { + // If there are no other screens on the same virtual desktop, + // then transform the physical screen into a fake screen. + screen = static_cast<QXcbScreen *>(old.takeFirst()); + const QString nameWas = screen->name(); + screen->setMonitor(nullptr, XCB_NONE); + qCDebug(lcQpaScreen) << "transformed" << nameWas << "to fake" << screen; + } else { + // If there are no XRandR outputs or XRandR extension is missing, + // then create a fake/legacy screen. + screen = new QXcbScreen(this, virtualDesktop, nullptr); + qCDebug(lcQpaScreen) << "create a fake screen: " << screen; + } if (primaryScreenNumber() == xcbScreenNumber) { primaryScreen = screen; @@ -548,8 +567,11 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int } if (initialized) { - for (QPlatformScreen *ps : old) - destroyScreen(static_cast<QXcbScreen*>(ps)); + for (QPlatformScreen *ps : old) { + virtualDesktop->removeScreen(ps); + qCDebug(lcQpaScreen) << "destroy screen: " << ps; + QWindowSystemInterface::handleScreenRemoved(ps); + } } virtualDesktop->setScreens(std::move(siblings)); diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 3a6185a083..1ecf995f7c 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -622,18 +622,28 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe void QXcbScreen::setMonitor(xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp_t timestamp) { - if (!connection()->isAtLeastXRandR15() || !monitorInfo) + if (!connection()->isAtLeastXRandR15()) return; + m_outputs.clear(); + m_crtcs.clear(); + + if (!monitorInfo) { + m_monitor = nullptr; + m_output = XCB_NONE; + m_crtc = XCB_NONE; + m_mode = XCB_NONE; + m_outputName = defaultName(); + // TODO: Send an event to the QScreen instance that the screen changed its name + return; + } + xcb_randr_select_input(xcb_connection(), screen()->root, true); m_monitor = monitorInfo; QRect monitorGeometry = QRect(m_monitor->x, m_monitor->y, m_monitor->width, m_monitor->height); - m_outputs.clear(); - m_crtcs.clear(); - int outputCount = xcb_randr_monitor_info_outputs_length(m_monitor); xcb_randr_output_t *outputs = nullptr; if (outputCount) { @@ -702,6 +712,18 @@ void QXcbScreen::setMonitor(xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp m_cursor = new QXcbCursor(connection(), this); } +QString QXcbScreen::defaultName() +{ + QString name; + QByteArray displayName = connection()->displayName(); + int dotPos = displayName.lastIndexOf('.'); + if (dotPos != -1) + displayName.truncate(dotPos); + name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + + QString::number(m_virtualDesktop->number()); + return name; +} + QXcbScreen::~QXcbScreen() { delete m_cursor; @@ -714,12 +736,7 @@ QString QXcbScreen::getOutputName(xcb_randr_get_output_info_reply_t *outputInfo) name = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(outputInfo), xcb_randr_get_output_info_name_length(outputInfo)); } else { - QByteArray displayName = connection()->displayName(); - int dotPos = displayName.lastIndexOf('.'); - if (dotPos != -1) - displayName.truncate(dotPos); - name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') - + QString::number(m_virtualDesktop->number()); + name = defaultName(); } return name; } diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index 133349fdf1..04d90e0c68 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -196,6 +196,7 @@ public: xcb_randr_get_output_info_reply_t *outputInfo); void setCrtc(xcb_randr_crtc_t crtc) { m_crtc = crtc; } void setMonitor(xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp_t timestamp = XCB_NONE); + QString defaultName(); void windowShown(QXcbWindow *window); QString windowManagerName() const { return m_virtualDesktop->windowManagerName(); } |