summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2021-09-14 21:22:08 +0200
committerLiang Qi <liang.qi@qt.io>2021-09-18 16:29:39 +0200
commitd8f37d94e537aaab4fa960b80aacabe79bcc14c4 (patch)
tree8aabb56368e160f81fd1fee6aff0f4b41b8d410e /src/plugins/platforms
parentb2c3b3e8fe0d8bdc88051d0120aaa8d5cf8acce0 (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')
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_screens.cpp36
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp37
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h1
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(); }