summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSandro Mani <manisandro@gmail.com>2015-02-02 17:14:40 +0100
committerShawn Rutledge <shawn.rutledge@digia.com>2015-02-25 12:15:05 +0000
commit52f5e50f11a3ba82e32dc2efc656e4021a3fa4f5 (patch)
tree7c77a6e56d24ea1a34cc963546dad12ace95f3de
parentdf39295f23c7d9ead8481a95b9c78caaff1e8bc8 (diff)
Ensure QGuiApplicationPrivate::screen_list is correctly populated
Ensure QGuiApplicationPrivate::screen_list always contains at least one screen, and that the first item (returned by QGuiApplication::primaryScreen) is always the current primary screen Task-number: QTBUG-42985 Change-Id: I08b880b3e94387f28230ed5fc738bceea943bad3 Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com>
-rw-r--r--src/gui/kernel/qplatformintegration.cpp8
-rw-r--r--src/gui/kernel/qplatformintegration.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp3
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp59
5 files changed, 50 insertions, 24 deletions
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index d2db6af52b..6043ae0cfd 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -443,11 +443,15 @@ QList<int> QPlatformIntegration::possibleKeys(const QKeyEvent *) const
The screen should be deleted by calling QPlatformIntegration::destroyScreen().
*/
-void QPlatformIntegration::screenAdded(QPlatformScreen *ps)
+void QPlatformIntegration::screenAdded(QPlatformScreen *ps, bool isPrimary)
{
QScreen *screen = new QScreen(ps);
ps->d_func()->screen = screen;
- QGuiApplicationPrivate::screen_list << screen;
+ if (isPrimary) {
+ QGuiApplicationPrivate::screen_list.prepend(screen);
+ } else {
+ QGuiApplicationPrivate::screen_list.append(screen);
+ }
emit qGuiApp->screenAdded(screen);
}
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index a0756a4992..e6a2ef6a1f 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -171,7 +171,7 @@ public:
#endif
protected:
- void screenAdded(QPlatformScreen *screen);
+ void screenAdded(QPlatformScreen *screen, bool isPrimary = false);
void destroyScreen(QPlatformScreen *screen);
};
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index 901538fa2e..8a2d14f172 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -93,7 +93,7 @@ public:
static QWindowsIntegration *instance() { return m_instance; }
- inline void emitScreenAdded(QPlatformScreen *s) { screenAdded(s); }
+ inline void emitScreenAdded(QPlatformScreen *s, bool isPrimary = false) { screenAdded(s, isPrimary); }
inline void emitDestroyScreen(QPlatformScreen *s) { destroyScreen(s); }
unsigned options() const;
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 059ebf19f6..4ab4ac352e 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -514,7 +514,8 @@ bool QWindowsScreenManager::handleScreenChanges()
} else {
QWindowsScreen *newScreen = new QWindowsScreen(newData);
m_screens.push_back(newScreen);
- QWindowsIntegration::instance()->emitScreenAdded(newScreen);
+ QWindowsIntegration::instance()->emitScreenAdded(newScreen,
+ newData.flags & QWindowsScreenData::PrimaryScreen);
qCDebug(lcQpaWindows) << "New Monitor: " << newData;
} // exists
} // for new screens.
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index a8c55239d5..e8fab31480 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -143,9 +143,8 @@ QXcbScreen* QXcbConnection::findOrCreateScreen(QList<QXcbScreen *>& newScreens,
void QXcbConnection::updateScreens()
{
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
- int screenNumber = 0; // index of this QScreen in QGuiApplication::screens()
int xcbScreenNumber = 0; // screen number in the xcb sense
- QSet<QXcbScreen *> activeScreens;
+ QList<QXcbScreen *> activeScreens;
QList<QXcbScreen *> newScreens;
QXcbScreen* primaryScreen = NULL;
while (it.rem) {
@@ -156,6 +155,7 @@ void QXcbConnection::updateScreens()
xcb_screen_t *xcbScreen = it.data;
QList<QPlatformScreen *> siblings;
int outputCount = 0;
+ int connectedOutputCount = 0;
if (has_randr_extension) {
xcb_generic_error_t *error = NULL;
xcb_randr_get_output_primary_cookie_t primaryCookie =
@@ -200,7 +200,7 @@ void QXcbConnection::updateScreens()
QXcbScreen *screen = findOrCreateScreen(newScreens, xcbScreenNumber, xcbScreen, output);
siblings << screen;
activeScreens << screen;
- ++screenNumber;
+ ++connectedOutputCount;
// There can be multiple outputs per screen, use either
// the first or an exact match. An exact match isn't
// always available if primary->output is XCB_NONE
@@ -223,7 +223,7 @@ void QXcbConnection::updateScreens()
}
// If there's no randr extension, or there was some error above, or the screen
// doesn't have outputs for some other reason (e.g. on VNC or ssh -X), just assume there is one screen.
- if (outputCount == 0) {
+ if (connectedOutputCount == 0) {
#ifdef Q_XCB_DEBUG
qDebug("Found a screen with zero outputs");
#endif
@@ -232,7 +232,6 @@ void QXcbConnection::updateScreens()
activeScreens << screen;
if (!primaryScreen)
primaryScreen = screen;
- ++screenNumber;
}
foreach (QPlatformScreen* s, siblings)
((QXcbScreen*)s)->setVirtualSiblings(siblings);
@@ -241,28 +240,50 @@ void QXcbConnection::updateScreens()
} // for each xcb screen
QXcbIntegration *integration = QXcbIntegration::instance();
- // Now activeScreens is the complete set of screens which are active at this time.
- // Delete any existing screens which are not in activeScreens
+
+ // Rebuild screen list, ensuring primary screen is always in front,
+ // both in the QXcbConnection::m_screens list as well as in the
+ // QGuiApplicationPrivate::screen_list list, which gets updated via
+ // - screen added: integration->screenAdded()
+ // - screen removed: integration->destroyScreen
+
+ // Gather screens to delete
+ QList<QXcbScreen*> screensToDelete;
for (int i = m_screens.count() - 1; i >= 0; --i) {
if (!activeScreens.contains(m_screens[i])) {
- integration->destroyScreen(m_screens.at(i));
- m_screens.removeAt(i);
+ screensToDelete.append(m_screens.takeAt(i));
}
}
- // Add any new screens, and make sure the primary screen comes first
- // since it is used by QGuiApplication::primaryScreen()
+ // If there is a new primary screen, add that one first
+ if (newScreens.contains(primaryScreen)) {
+ newScreens.removeOne(primaryScreen);
+ m_screens.prepend(primaryScreen);
+ integration->screenAdded(primaryScreen, true);
+ }
+
+ // Add the remaining new screens
foreach (QXcbScreen* screen, newScreens) {
- if (screen == primaryScreen)
- m_screens.prepend(screen);
- else
- m_screens.append(screen);
+ m_screens.append(screen);
+ integration->screenAdded(screen);
}
- // Now that they are in the right order, emit the added signals for new screens only
- foreach (QXcbScreen* screen, m_screens)
- if (newScreens.contains(screen))
- integration->screenAdded(screen);
+ // Delete the old screens, now that the new ones were added
+ // and we are sure that there is at least one screen available
+ foreach (QXcbScreen* screen, screensToDelete) {
+ integration->destroyScreen(screen);
+ }
+
+ // Ensure that the primary screen is first in m_screens too
+ // (in case the assignment of primary was the only change,
+ // without adding or removing screens)
+ if (primaryScreen) {
+ Q_ASSERT(!m_screens.isEmpty());
+ if (m_screens.first() != primaryScreen) {
+ m_screens.removeOne(primaryScreen);
+ m_screens.prepend(primaryScreen);
+ }
+ }
}
QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName)