summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2022-05-04 17:28:05 +0200
committerLiang Qi <liang.qi@qt.io>2022-05-20 19:16:19 +0200
commit731b38e768ad0cc8bc9000f6b7215f63882d4011 (patch)
tree65da7fe8884ee7836fce1af8afb0292488f20717 /src/plugins
parentbd1023a824efeafbd48c79d4dfbdd5f017044ceb (diff)
xcb: only set primary for monitor on primary X screen
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ø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_screens.cpp49
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp5
3 files changed, 36 insertions, 22 deletions
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<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);
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<QPlatformScreen*> old = virtualDesktop->m_screens;
- if (initialized)
- m_screens.clear();
QList<QPlatformScreen *> 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);