From 98ea3631c40e03ac73acfbde1e09f604e2ddf636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Vr=C3=A1til?= Date: Wed, 1 Apr 2015 20:37:00 +0200 Subject: [PATCH] Revert "Pull in set of upstream Qt 5.5 fixes and improvements for XCB screen handling rebased to 5.4" This reverts commit bcc8b147be0f2fce38c2615aa71b89d0ea44a15b. --- ...lugins-to-explictly-destroy-qscreens.patch | 313 -------- ...sses-keep-their-own-instance-pointer.patch | 201 ----- ...e-screen_list-is-correctly-populated.patch | 190 ----- ...b-add-qt-qpa-screen-logging-category.patch | 250 ------ ...my-qscreen-when-there-are-no-outputs.patch | 89 --- ...ling-of-xrandr-events-in-xcb-backend.patch | 713 ------------------ ...root-window-and-there-are-no-screens.patch | 43 -- ...nsions-are-known-but-outputs-are-not.patch | 86 --- qt5-qtbase.spec | 31 +- qtbase-opensource-src-5.4.0-QTBUG-42985.patch | 600 +++++++++++++++ 10 files changed, 609 insertions(+), 1907 deletions(-) delete mode 100644 qt5-qtbase-5.5-0000-add-function-for-qpa-plugins-to-explictly-destroy-qscreens.patch delete mode 100644 qt5-qtbase-5.5-0001-have-xcb-windows-platform-integration-classes-keep-their-own-instance-pointer.patch delete mode 100644 qt5-qtbase-5.5-0002-ensure-qguiapplicationprivate-screen_list-is-correctly-populated.patch delete mode 100644 qt5-qtbase-5.5-0003-xcb-add-qt-qpa-screen-logging-category.patch delete mode 100644 qt5-qtbase-5.5-0004-xcb-do-not-create-dummy-qscreen-when-there-are-no-outputs.patch delete mode 100644 qt5-qtbase-5.5-0005-improve-handling-of-xrandr-events-in-xcb-backend.patch delete mode 100644 qt5-qtbase-5.5-0006-fix-segfault-when-requesting-root-window-and-there-are-no-screens.patch delete mode 100644 qt5-qtbase-5.5-0007-xcb-create-a-screen-if-dimensions-are-known-but-outputs-are-not.patch create mode 100644 qtbase-opensource-src-5.4.0-QTBUG-42985.patch diff --git a/qt5-qtbase-5.5-0000-add-function-for-qpa-plugins-to-explictly-destroy-qscreens.patch b/qt5-qtbase-5.5-0000-add-function-for-qpa-plugins-to-explictly-destroy-qscreens.patch deleted file mode 100644 index f42040a..0000000 --- a/qt5-qtbase-5.5-0000-add-function-for-qpa-plugins-to-explictly-destroy-qscreens.patch +++ /dev/null @@ -1,313 +0,0 @@ -commit 9b4fbe85d2e00c625c3d4abd975faf555000f685 -Author: Giulio Camuffo -Date: Sun Aug 31 16:16:53 2014 +0300 - - Add a function for QPA plugins to explicitly destroy QScreens - - Previously QPlatformScreen was automatically deleting its QScreen - in ~QPlatformScreen(). That means that we cannot use QScreen's - methods when the screen is being removed, because doing so would - call virtual methods of QPlatformScreen. By that point the - QPlatformScreen subclass object does not exist anymore, and we - call the default implementation instead of the subclassed one, or - get a crash for the pure virtual methods. This happens for example - when removing a screen which contains a QWindow with some QML item - using QQuickScreenAttached. - - This patch adds a QPlatformIntegration::destroyScreen() function, - which deletes the QScreen and later the QPlatformScreen. - - ~QPlatformScreen will still delete the QScreen if it was not deleted - with destroyScreen(), so code not ported to the new approach - will continue to work as before, with only a warning added. - - Task-number: QTBUG-41141 - Change-Id: Ie4a03dee08ceb4c3e94a81875411f6f723273fe1 - Reviewed-by: Jørgen Lind - Reviewed-by: Shawn Rutledge - -diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp -index 39b031e..93b1359 100644 ---- a/src/gui/kernel/qplatformintegration.cpp -+++ b/src/gui/kernel/qplatformintegration.cpp -@@ -429,7 +429,7 @@ QList QPlatformIntegration::possibleKeys(const QKeyEvent *) const - This adds the screen to QGuiApplication::screens(), and emits the - QGuiApplication::screenAdded() signal. - -- The screen is automatically removed when the QPlatformScreen is destroyed. -+ The screen should be deleted by calling QPlatformIntegration::destroyScreen(). - */ - void QPlatformIntegration::screenAdded(QPlatformScreen *ps) - { -@@ -439,6 +439,22 @@ void QPlatformIntegration::screenAdded(QPlatformScreen *ps) - emit qGuiApp->screenAdded(screen); - } - -+/*! -+ Should be called by the implementation whenever a screen is removed. -+ -+ This removes the screen from QGuiApplication::screens(), and deletes it. -+ -+ Failing to call this and manually deleting the QPlatformScreen instead may -+ lead to a crash due to a pure virtual call. -+*/ -+void QPlatformIntegration::destroyScreen(QPlatformScreen *screen) -+{ -+ QGuiApplicationPrivate::screen_list.removeOne(screen->d_func()->screen); -+ delete screen->d_func()->screen; -+ screen->d_func()->screen = Q_NULLPTR; -+ delete screen; -+} -+ - QStringList QPlatformIntegration::themeNames() const - { - return QStringList(); -diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h -index d510240..9b7e2df 100644 ---- a/src/gui/kernel/qplatformintegration.h -+++ b/src/gui/kernel/qplatformintegration.h -@@ -170,6 +170,7 @@ public: - - protected: - void screenAdded(QPlatformScreen *screen); -+ void destroyScreen(QPlatformScreen *screen); - }; - - QT_END_NAMESPACE -diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp -index 71710d1..fa6d785 100644 ---- a/src/gui/kernel/qplatformscreen.cpp -+++ b/src/gui/kernel/qplatformscreen.cpp -@@ -52,9 +52,11 @@ QPlatformScreen::QPlatformScreen() - QPlatformScreen::~QPlatformScreen() - { - Q_D(QPlatformScreen); -- -- QGuiApplicationPrivate::screen_list.removeOne(d->screen); -- delete d->screen; -+ if (d->screen) { -+ qWarning("Manually deleting a QPlatformScreen. Call QPlatformIntegration::destroyScreen instead."); -+ QGuiApplicationPrivate::screen_list.removeOne(d->screen); -+ delete d->screen; -+ } - } - - /*! -diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm -index 72bd096..180cb23 100644 ---- a/src/plugins/platforms/cocoa/qcocoaintegration.mm -+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm -@@ -337,7 +337,7 @@ QCocoaIntegration::~QCocoaIntegration() - - // Delete screens in reverse order to avoid crash in case of multiple screens - while (!mScreens.isEmpty()) { -- delete mScreens.takeLast(); -+ destroyScreen(mScreens.takeLast()); - } - - clearToolbars(); -@@ -397,7 +397,7 @@ void QCocoaIntegration::updateScreens() - // Now the leftovers in remainingScreens are no longer current, so we can delete them. - foreach (QCocoaScreen* screen, remainingScreens) { - mScreens.removeOne(screen); -- delete screen; -+ destroyScreen(screen); - } - // All screens in mScreens are siblings, because we ignored the mirrors. - foreach (QCocoaScreen* screen, mScreens) -diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm -index 461f160..ff4b753 100644 ---- a/src/plugins/platforms/ios/qiosintegration.mm -+++ b/src/plugins/platforms/ios/qiosintegration.mm -@@ -120,7 +120,7 @@ QIOSIntegration::~QIOSIntegration() - m_inputContext = 0; - - foreach (QScreen *screen, QGuiApplication::screens()) -- delete screen->handle(); -+ destroyScreen(screen->handle()); - - delete m_platformServices; - m_platformServices = 0; -diff --git a/src/plugins/platforms/kms/qkmsintegration.cpp b/src/plugins/platforms/kms/qkmsintegration.cpp -index d94d7d9..5ad58ba 100644 ---- a/src/plugins/platforms/kms/qkmsintegration.cpp -+++ b/src/plugins/platforms/kms/qkmsintegration.cpp -@@ -74,7 +74,7 @@ QKmsIntegration::~QKmsIntegration() - delete device; - } - foreach (QPlatformScreen *screen, m_screens) { -- delete screen; -+ destroyScreen(screen); - } - delete m_fontDatabase; - delete m_vtHandler; -diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp -index 777da98..4e83656 100644 ---- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp -+++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp -@@ -57,7 +57,7 @@ QLinuxFbIntegration::QLinuxFbIntegration(const QStringList ¶mList) - - QLinuxFbIntegration::~QLinuxFbIntegration() - { -- delete m_primaryScreen; -+ destroyScreen(m_primaryScreen); - } - - void QLinuxFbIntegration::initialize() -diff --git a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp -index 0b12e62..3fbed1e 100644 ---- a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp -+++ b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp -@@ -60,7 +60,7 @@ QMinimalEglIntegration::QMinimalEglIntegration() - - QMinimalEglIntegration::~QMinimalEglIntegration() - { -- delete mScreen; -+ destroyScreen(mScreen); - } - - bool QMinimalEglIntegration::hasCapability(QPlatformIntegration::Capability cap) const -diff --git a/src/plugins/platforms/openwfd/qopenwfdintegration.cpp b/src/plugins/platforms/openwfd/qopenwfdintegration.cpp -index 1e29fcc..26bdd14 100644 ---- a/src/plugins/platforms/openwfd/qopenwfdintegration.cpp -+++ b/src/plugins/platforms/openwfd/qopenwfdintegration.cpp -@@ -133,3 +133,8 @@ void QOpenWFDIntegration::addScreen(QOpenWFDScreen *screen) - { - screenAdded(screen); - } -+ -+void QOpenWFDIntegration::destroyScreen(QOpenWFDScreen *screen) -+{ -+ QPlatformIntegration::destroyScreen(screen); -+} -diff --git a/src/plugins/platforms/openwfd/qopenwfdintegration.h b/src/plugins/platforms/openwfd/qopenwfdintegration.h -index 6c086b7..9243205 100644 ---- a/src/plugins/platforms/openwfd/qopenwfdintegration.h -+++ b/src/plugins/platforms/openwfd/qopenwfdintegration.h -@@ -63,6 +63,7 @@ public: - QPlatformPrinterSupport *printerSupport() const; - - void addScreen(QOpenWFDScreen *screen); -+ void destroyScreen(QOpenWFDScreen *screen); - private: - QList mScreens; - QListmDevices; -diff --git a/src/plugins/platforms/openwfd/qopenwfdport.cpp b/src/plugins/platforms/openwfd/qopenwfdport.cpp -index 0bdc6b2..b643644 100644 ---- a/src/plugins/platforms/openwfd/qopenwfdport.cpp -+++ b/src/plugins/platforms/openwfd/qopenwfdport.cpp -@@ -140,7 +140,7 @@ void QOpenWFDPort::detach() - mAttached = false; - mOn = false; - -- delete mScreen; -+ mDevice->integration()->destroyScreen(mScreen); - - wfdDestroyPipeline(mDevice->handle(),mPipeline); - mPipelineId = WFD_INVALID_PIPELINE_ID; -diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp -index 34b79b6..d47da01 100644 ---- a/src/plugins/platforms/qnx/qqnxintegration.cpp -+++ b/src/plugins/platforms/qnx/qqnxintegration.cpp -@@ -554,7 +554,7 @@ void QQnxIntegration::removeDisplay(QQnxScreen *screen) - Q_CHECK_PTR(screen); - Q_ASSERT(m_screens.contains(screen)); - m_screens.removeAll(screen); -- screen->deleteLater(); -+ destroyScreen(screen); - } - - void QQnxIntegration::destroyDisplays() -diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h -index d1617ea..7fb37bc 100644 ---- a/src/plugins/platforms/windows/qwindowsintegration.h -+++ b/src/plugins/platforms/windows/qwindowsintegration.h -@@ -94,6 +94,7 @@ public: - static QWindowsIntegration *instance(); - - inline void emitScreenAdded(QPlatformScreen *s) { screenAdded(s); } -+ 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 fd57d9e..79219e3 100644 ---- a/src/plugins/platforms/windows/qwindowsscreen.cpp -+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp -@@ -462,7 +462,7 @@ void QWindowsScreenManager::removeScreen(int index) - if (movedWindowCount) - QWindowSystemInterface::flushWindowSystemEvents(); - } -- delete m_screens.takeAt(index); -+ QWindowsIntegration::instance()->emitDestroyScreen(m_screens.takeAt(index)); - } - - /*! -@@ -497,4 +497,11 @@ bool QWindowsScreenManager::handleScreenChanges() - return true; - } - -+void QWindowsScreenManager::clearScreens() -+{ -+ // Delete screens in reverse order to avoid crash in case of multiple screens -+ while (!m_screens.isEmpty()) -+ QWindowsIntegration::instance()->emitDestroyScreen(m_screens.takeLast()); -+} -+ - QT_END_NAMESPACE -diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h -index aa14083..924912d 100644 ---- a/src/plugins/platforms/windows/qwindowsscreen.h -+++ b/src/plugins/platforms/windows/qwindowsscreen.h -@@ -127,11 +127,7 @@ public: - - QWindowsScreenManager(); - -- inline void clearScreens() { -- // Delete screens in reverse order to avoid crash in case of multiple screens -- while (!m_screens.isEmpty()) -- delete m_screens.takeLast(); -- } -+ void clearScreens(); - - bool handleScreenChanges(); - bool handleDisplayChange(WPARAM wParam, LPARAM lParam); -diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp -index 5510c3b..ae59de5 100644 ---- a/src/plugins/platforms/xcb/qxcbconnection.cpp -+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp -@@ -279,11 +279,12 @@ void QXcbConnection::updateScreens() - ++xcbScreenNumber; - } // for each xcb screen - -+ QXcbIntegration *integration = static_cast(QGuiApplicationPrivate::platformIntegration()); - // Now activeScreens is the complete set of screens which are active at this time. - // Delete any existing screens which are not in activeScreens - for (int i = m_screens.count() - 1; i >= 0; --i) { - if (!activeScreens.contains(m_screens[i])) { -- delete m_screens[i]; -+ integration->destroyScreen(m_screens.at(i)); - m_screens.removeAt(i); - } - } -@@ -300,7 +301,7 @@ void QXcbConnection::updateScreens() - // 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)) -- ((QXcbIntegration*)QGuiApplicationPrivate::platformIntegration())->screenAdded(screen); -+ integration->screenAdded(screen); - } - - QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName) -@@ -431,9 +432,10 @@ QXcbConnection::~QXcbConnection() - - delete m_reader; - -+ QXcbIntegration *integration = static_cast(QGuiApplicationPrivate::platformIntegration()); - // Delete screens in reverse order to avoid crash in case of multiple screens - while (!m_screens.isEmpty()) -- delete m_screens.takeLast(); -+ integration->destroyScreen(m_screens.takeLast()); - - #ifdef XCB_USE_EGL - if (m_has_egl) diff --git a/qt5-qtbase-5.5-0001-have-xcb-windows-platform-integration-classes-keep-their-own-instance-pointer.patch b/qt5-qtbase-5.5-0001-have-xcb-windows-platform-integration-classes-keep-their-own-instance-pointer.patch deleted file mode 100644 index e9129be..0000000 --- a/qt5-qtbase-5.5-0001-have-xcb-windows-platform-integration-classes-keep-their-own-instance-pointer.patch +++ /dev/null @@ -1,201 +0,0 @@ -commit df39295f23c7d9ead8481a95b9c78caaff1e8bc8 -Author: Sandro Mani -Date: Mon Feb 16 10:22:14 2015 +0100 - - Have XCB/Windows platform integration classes keep their own instance pointer - - Through the chain of code called by QPlatformIntegrationFactory::create, there - are cases where QGuiApplicationPrivate::platform_integration is accessed - (typically through QGuiApplicationPrivate::platformIntegration()) before the call - to QPlatformIntegrationFactory::create has returned. - - Change-Id: I7805b72be5b56aed5cb8ce30cb908743c9b1f91b - Task-number: QTBUG-44388 - Reviewed-by: Shawn Rutledge - Reviewed-by: Friedemann Kleint - -diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp -index 58d6758..d06f605 100644 ---- a/src/plugins/platforms/windows/qwindowsintegration.cpp -+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp -@@ -235,9 +235,12 @@ QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate() - delete m_fontDatabase; - } - -+QWindowsIntegration *QWindowsIntegration::m_instance = Q_NULLPTR; -+ - QWindowsIntegration::QWindowsIntegration(const QStringList ¶mList) : - d(new QWindowsIntegrationPrivate(paramList)) - { -+ m_instance = this; - #ifndef QT_NO_CLIPBOARD - d->m_clipboard.registerViewer(); - #endif -@@ -246,6 +249,7 @@ QWindowsIntegration::QWindowsIntegration(const QStringList ¶mList) : - - QWindowsIntegration::~QWindowsIntegration() - { -+ m_instance = Q_NULLPTR; - } - - void QWindowsIntegration::initialize() -@@ -540,11 +544,6 @@ QPlatformAccessibility *QWindowsIntegration::accessibility() const - } - #endif - --QWindowsIntegration *QWindowsIntegration::instance() --{ -- return static_cast(QGuiApplicationPrivate::platformIntegration()); --} -- - unsigned QWindowsIntegration::options() const - { - return d->m_options; -diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h -index 7fb37bc..ff26342 100644 ---- a/src/plugins/platforms/windows/qwindowsintegration.h -+++ b/src/plugins/platforms/windows/qwindowsintegration.h -@@ -91,7 +91,7 @@ public: - Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE; - QList possibleKeys(const QKeyEvent *e) const Q_DECL_OVERRIDE; - -- static QWindowsIntegration *instance(); -+ static QWindowsIntegration *instance() { return m_instance; } - - inline void emitScreenAdded(QPlatformScreen *s) { screenAdded(s); } - inline void emitDestroyScreen(QPlatformScreen *s) { destroyScreen(s); } -@@ -104,6 +104,8 @@ public: - - private: - QScopedPointer d; -+ -+ static QWindowsIntegration *m_instance; - }; - - QT_END_NAMESPACE -diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp -index ae59de5..0091736 100644 ---- a/src/plugins/platforms/xcb/qxcbconnection.cpp -+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp -@@ -279,7 +279,7 @@ void QXcbConnection::updateScreens() - ++xcbScreenNumber; - } // for each xcb screen - -- QXcbIntegration *integration = static_cast(QGuiApplicationPrivate::platformIntegration()); -+ 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 - for (int i = m_screens.count() - 1; i >= 0; --i) { -@@ -432,7 +432,7 @@ QXcbConnection::~QXcbConnection() - - delete m_reader; - -- QXcbIntegration *integration = static_cast(QGuiApplicationPrivate::platformIntegration()); -+ QXcbIntegration *integration = QXcbIntegration::instance(); - // Delete screens in reverse order to avoid crash in case of multiple screens - while (!m_screens.isEmpty()) - integration->destroyScreen(m_screens.takeLast()); -diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp -index f0c4a7f..050a9be 100644 ---- a/src/plugins/platforms/xcb/qxcbintegration.cpp -+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp -@@ -118,11 +118,15 @@ static bool runningUnderDebugger() - #endif - } - -+QXcbIntegration *QXcbIntegration::m_instance = Q_NULLPTR; -+ - QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char **argv) - : m_services(new QGenericUnixServices) - , m_instanceName(0) - , m_canGrab(true) - { -+ m_instance = this; -+ - qRegisterMetaType(); - #ifdef XCB_USE_XLIB - XInitThreads(); -@@ -187,6 +191,7 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char - QXcbIntegration::~QXcbIntegration() - { - qDeleteAll(m_connections); -+ m_instance = Q_NULLPTR; - } - - QPlatformWindow *QXcbIntegration::createPlatformWindow(QWindow *window) const -diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h -index db6ad54..ffe49e7 100644 ---- a/src/plugins/platforms/xcb/qxcbintegration.h -+++ b/src/plugins/platforms/xcb/qxcbintegration.h -@@ -99,6 +99,9 @@ public: - #endif - - void sync(); -+ -+ static QXcbIntegration *instance() { return m_instance; } -+ - private: - QList m_connections; - -@@ -118,6 +121,8 @@ private: - mutable QByteArray m_wmClass; - const char *m_instanceName; - bool m_canGrab; -+ -+ static QXcbIntegration *m_instance; - }; - - QT_END_NAMESPACE -diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp -index 31dedd4..c9aaada 100644 ---- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp -+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp -@@ -359,7 +359,7 @@ void *QXcbNativeInterface::getTimestamp(const QXcbScreen *screen) - - void *QXcbNativeInterface::startupId() - { -- QXcbIntegration* integration = static_cast(QGuiApplicationPrivate::platformIntegration()); -+ QXcbIntegration* integration = QXcbIntegration::instance(); - QXcbConnection *defaultConnection = integration->defaultConnection(); - if (defaultConnection) - return reinterpret_cast(const_cast(defaultConnection->startupId().constData())); -@@ -368,7 +368,7 @@ void *QXcbNativeInterface::startupId() - - void *QXcbNativeInterface::x11Screen() - { -- QXcbIntegration *integration = static_cast(QGuiApplicationPrivate::platformIntegration()); -+ QXcbIntegration *integration = QXcbIntegration::instance(); - QXcbConnection *defaultConnection = integration->defaultConnection(); - if (defaultConnection) - return reinterpret_cast(defaultConnection->primaryScreenNumber()); -@@ -377,7 +377,7 @@ void *QXcbNativeInterface::x11Screen() - - void *QXcbNativeInterface::rootWindow() - { -- QXcbIntegration *integration = static_cast(QGuiApplicationPrivate::platformIntegration()); -+ QXcbIntegration *integration = QXcbIntegration::instance(); - QXcbConnection *defaultConnection = integration->defaultConnection(); - if (defaultConnection) - return reinterpret_cast(defaultConnection->rootWindow()); -@@ -397,7 +397,7 @@ void QXcbNativeInterface::setAppUserTime(QScreen* screen, xcb_timestamp_t time) - void QXcbNativeInterface::setStartupId(const char *data) - { - QByteArray startupId(data); -- QXcbIntegration *integration = static_cast(QGuiApplicationPrivate::platformIntegration()); -+ QXcbIntegration *integration = QXcbIntegration::instance(); - QXcbConnection *defaultConnection = integration->defaultConnection(); - if (defaultConnection) - defaultConnection->setStartupId(startupId); -diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp -index 0094278..7e85600 100644 ---- a/src/plugins/platforms/xcb/qxcbwindow.cpp -+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp -@@ -489,7 +489,7 @@ void QXcbWindow::create() - m_syncValue.hi = 0; - m_syncValue.lo = 0; - -- const QByteArray wmClass = static_cast(QGuiApplicationPrivate::platformIntegration())->wmClass(); -+ const QByteArray wmClass = QXcbIntegration::instance()->wmClass(); - if (!wmClass.isEmpty()) { - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, - m_window, atom(QXcbAtom::WM_CLASS), diff --git a/qt5-qtbase-5.5-0002-ensure-qguiapplicationprivate-screen_list-is-correctly-populated.patch b/qt5-qtbase-5.5-0002-ensure-qguiapplicationprivate-screen_list-is-correctly-populated.patch deleted file mode 100644 index c20f991..0000000 --- a/qt5-qtbase-5.5-0002-ensure-qguiapplicationprivate-screen_list-is-correctly-populated.patch +++ /dev/null @@ -1,190 +0,0 @@ -commit 52f5e50f11a3ba82e32dc2efc656e4021a3fa4f5 -Author: Sandro Mani -Date: Mon Feb 2 17:14:40 2015 +0100 - - 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 - -diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp -index 93b1359..13f2880 100644 ---- a/src/gui/kernel/qplatformintegration.cpp -+++ b/src/gui/kernel/qplatformintegration.cpp -@@ -431,11 +431,15 @@ QList 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 9b7e2df..067d8d9 100644 ---- a/src/gui/kernel/qplatformintegration.h -+++ b/src/gui/kernel/qplatformintegration.h -@@ -169,7 +169,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 ff26342..bfde2bd 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 79219e3..a401175 100644 ---- a/src/plugins/platforms/windows/qwindowsscreen.cpp -+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp -@@ -482,7 +482,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 0091736..e416865 100644 ---- a/src/plugins/platforms/xcb/qxcbconnection.cpp -+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp -@@ -182,9 +182,8 @@ QXcbScreen* QXcbConnection::findOrCreateScreen(QList& 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 activeScreens; -+ QList activeScreens; - QList newScreens; - QXcbScreen* primaryScreen = NULL; - while (it.rem) { -@@ -195,6 +194,7 @@ void QXcbConnection::updateScreens() - xcb_screen_t *xcbScreen = it.data; - QList 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 = -@@ -239,7 +239,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 -@@ -262,7 +262,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 -@@ -271,7 +271,6 @@ void QXcbConnection::updateScreens() - activeScreens << screen; - if (!primaryScreen) - primaryScreen = screen; -- ++screenNumber; - } - foreach (QPlatformScreen* s, siblings) - ((QXcbScreen*)s)->setVirtualSiblings(siblings); -@@ -280,28 +279,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 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) diff --git a/qt5-qtbase-5.5-0003-xcb-add-qt-qpa-screen-logging-category.patch b/qt5-qtbase-5.5-0003-xcb-add-qt-qpa-screen-logging-category.patch deleted file mode 100644 index b67d388..0000000 --- a/qt5-qtbase-5.5-0003-xcb-add-qt-qpa-screen-logging-category.patch +++ /dev/null @@ -1,250 +0,0 @@ -commit bbdef3ca98ba78a829dc725ba67fe6d466e20f9c -Author: Shawn Rutledge -Date: Mon Feb 23 10:30:26 2015 +0100 - - xcb: add qt.qpa.screen logging category - - Some existing debug output required recompiling with Q_XCB_DEBUG. - Being able to enable this debugging in the field will help with - troubleshooting any remaining screen management issues. - - Change-Id: Ie67b0009d4b00b0d39fde0fb4d8d54fcf89d6693 - Reviewed-by: Sandro Mani - Reviewed-by: Laszlo Agocs - Reviewed-by: Jørgen Lind - -diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp -index e416865..a8c1943 100644 ---- a/src/plugins/platforms/xcb/qxcbconnection.cpp -+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp -@@ -86,6 +86,7 @@ QT_BEGIN_NAMESPACE - - Q_LOGGING_CATEGORY(lcQpaXInput, "qt.qpa.input") - Q_LOGGING_CATEGORY(lcQpaXInputDevices, "qt.qpa.input.devices") -+Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen") - - #ifdef XCB_USE_XLIB - static const char * const xcbConnectionErrors[] = { -@@ -224,15 +225,11 @@ void QXcbConnection::updateScreens() - if (output == NULL) - continue; - --#ifdef Q_XCB_DEBUG -- QString outputName = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output), -- xcb_randr_get_output_info_name_length(output)); --#endif - - if (output->crtc == XCB_NONE) { --#ifdef Q_XCB_DEBUG -- qDebug("Screen output %s is not connected", qPrintable(outputName)); --#endif -+ qCDebug(lcQpaScreen, "output %s is not connected", qPrintable( -+ QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output), -+ xcb_randr_get_output_info_name_length(output)))); - continue; - } - -@@ -248,9 +245,6 @@ void QXcbConnection::updateScreens() - if (!primaryScreen || (primary && outputs[i] == primary->output)) { - primaryScreen = screen; - siblings.prepend(siblings.takeLast()); --#ifdef Q_XCB_DEBUG -- qDebug("Primary output is %d: %s", primary->output, qPrintable(outputName)); --#endif - } - } - free(output); -@@ -263,9 +257,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 (connectedOutputCount == 0) { --#ifdef Q_XCB_DEBUG -- qDebug("Found a screen with zero outputs"); --#endif -+ qCDebug(lcQpaScreen, "found a screen with zero outputs"); - QXcbScreen *screen = findOrCreateScreen(newScreens, xcbScreenNumber, xcbScreen); - siblings << screen; - activeScreens << screen; -@@ -298,18 +290,21 @@ void QXcbConnection::updateScreens() - if (newScreens.contains(primaryScreen)) { - newScreens.removeOne(primaryScreen); - m_screens.prepend(primaryScreen); -+ qCDebug(lcQpaScreen) << "adding as primary" << primaryScreen; - integration->screenAdded(primaryScreen, true); - } - - // Add the remaining new screens - foreach (QXcbScreen* screen, newScreens) { - m_screens.append(screen); -+ qCDebug(lcQpaScreen) << "adding" << 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) { -+ qCDebug(lcQpaScreen) << "removing" << screen; - integration->destroyScreen(screen); - } - -@@ -323,6 +318,9 @@ void QXcbConnection::updateScreens() - m_screens.prepend(primaryScreen); - } - } -+ -+ if (!m_screens.isEmpty()) -+ qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name(); - } - - QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName) -diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h -index 7286b6b..6e7e87d 100644 ---- a/src/plugins/platforms/xcb/qxcbconnection.h -+++ b/src/plugins/platforms/xcb/qxcbconnection.h -@@ -76,6 +76,7 @@ QT_BEGIN_NAMESPACE - - Q_DECLARE_LOGGING_CATEGORY(lcQpaXInput) - Q_DECLARE_LOGGING_CATEGORY(lcQpaXInputDevices) -+Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen) - - class QXcbScreen; - class QXcbWindow; -diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp -index 050a9be..0b9fbbe 100644 ---- a/src/plugins/platforms/xcb/qxcbintegration.cpp -+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp -@@ -178,9 +178,7 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char - m_connections << new QXcbConnection(m_nativeInterface.data(), m_canGrab, displayName); - - for (int i = 0; i < parameters.size() - 1; i += 2) { --#ifdef Q_XCB_DEBUG -- qDebug() << "QXcbIntegration: Connecting to additional display: " << parameters.at(i) << parameters.at(i+1); --#endif -+ qCDebug(lcQpaScreen) << "connecting to additional display: " << parameters.at(i) << parameters.at(i+1); - QString display = parameters.at(i) + ':' + parameters.at(i+1); - m_connections << new QXcbConnection(m_nativeInterface.data(), display.toLatin1().constData()); - } -diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp -index 7136455..2aebb84 100644 ---- a/src/plugins/platforms/xcb/qxcbscreen.cpp -+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp -@@ -93,25 +93,6 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, - if (dpr_scaling_enabled) - m_noFontHinting = true; - --#ifdef Q_XCB_DEBUG -- qDebug(); -- qDebug("Screen output %s of xcb screen %d:", m_outputName.toUtf8().constData(), m_number); -- qDebug(" width..........: %lf", m_sizeMillimeters.width()); -- qDebug(" height.........: %lf", m_sizeMillimeters.height()); -- qDebug(" geometry.......: %d x %d +%d +%d", m_geometry.width(), m_geometry.height(), m_geometry.x(), m_geometry.y()); -- qDebug(" virtual width..: %lf", m_virtualSizeMillimeters.width()); -- qDebug(" virtual height.: %lf", m_virtualSizeMillimeters.height()); -- qDebug(" virtual geom...: %d x %d", m_virtualSize.width(), m_virtualSize.height()); -- qDebug(" avail virt geom: %d x %d +%d +%d", m_availableGeometry.width(), m_availableGeometry.height(), m_availableGeometry.x(), m_availableGeometry.y()); -- qDebug(" orientation....: %d", m_orientation); -- qDebug(" pixel ratio....: %d", m_devicePixelRatio); -- qDebug(" depth..........: %d", screen()->root_depth); -- qDebug(" white pixel....: %x", screen()->white_pixel); -- qDebug(" black pixel....: %x", screen()->black_pixel); -- qDebug(" refresh rate...: %d", m_refreshRate); -- qDebug(" root ID........: %x", screen()->root); --#endif -- - QScopedPointer rootAttribs( - xcb_get_window_attributes_reply(xcb_connection(), - xcb_get_window_attributes_unchecked(xcb_connection(), screen()->root), NULL)); -@@ -146,10 +127,6 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, - atom(QXcbAtom::UTF8_STRING), 0, 1024), NULL); - if (windowManagerReply && windowManagerReply->format == 8 && windowManagerReply->type == atom(QXcbAtom::UTF8_STRING)) { - m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply), xcb_get_property_value_length(windowManagerReply)); --#ifdef Q_XCB_DEBUG -- qDebug(" window manager.: %s", qPrintable(m_windowManagerName)); -- qDebug(); --#endif - } - - free(windowManagerReply); -@@ -702,4 +679,48 @@ QXcbXSettings *QXcbScreen::xSettings() const - } - return m_xSettings; - } -+ -+static inline void formatRect(QDebug &debug, const QRect r) -+{ -+ debug << r.width() << 'x' << r.height() -+ << forcesign << r.x() << r.y() << noforcesign; -+} -+ -+static inline void formatSizeF(QDebug &debug, const QSizeF s) -+{ -+ debug << s.width() << 'x' << s.height() << "mm"; -+} -+ -+QDebug operator<<(QDebug debug, const QXcbScreen *screen) -+{ -+ const QDebugStateSaver saver(debug); -+ debug.nospace(); -+ debug << "QXcbScreen(" << (void *)screen; -+ if (screen) { -+ debug << fixed << qSetRealNumberPrecision(1); -+ debug << ", name=" << screen->name(); -+ debug << ", geometry="; -+ formatRect(debug, screen->geometry()); -+ debug << ", availableGeometry="; -+ formatRect(debug, screen->availableGeometry()); -+ debug << ", devicePixelRatio=" << screen->devicePixelRatio(); -+ debug << ", logicalDpi=" << screen->logicalDpi(); -+ debug << ", physicalSize="; -+ formatSizeF(debug, screen->physicalSize()); -+ // TODO 5.6 if (debug.verbosity() > 2) { -+ debug << ", screenNumber=" << screen->screenNumber(); -+ debug << ", virtualSize=" << screen->virtualSize().width() << "x" << screen->virtualSize().height() << " ("; -+ formatSizeF(debug, screen->virtualSize()); -+ debug << "), nativeGeometry="; -+ formatRect(debug, screen->nativeGeometry()); -+ debug << ", orientation=" << screen->orientation(); -+ debug << ", depth=" << screen->depth(); -+ debug << ", refreshRate=" << screen->refreshRate(); -+ debug << ", root=" << hex << screen->root(); -+ debug << ", windowManagerName=" << screen->windowManagerName(); -+ } -+ debug << ')'; -+ return debug; -+} -+ - QT_END_NAMESPACE -diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h -index e9ab2ed..81c3445 100644 ---- a/src/plugins/platforms/xcb/qxcbscreen.h -+++ b/src/plugins/platforms/xcb/qxcbscreen.h -@@ -49,6 +49,9 @@ QT_BEGIN_NAMESPACE - class QXcbConnection; - class QXcbCursor; - class QXcbXSettings; -+#ifndef QT_NO_DEBUG_STREAM -+class QDebug; -+#endif - - class QXcbScreen : public QXcbObject, public QPlatformScreen - { -@@ -67,6 +70,8 @@ public: - int depth() const { return m_screen->root_depth; } - QImage::Format format() const; - QSizeF physicalSize() const { return m_sizeMillimeters; } -+ QSize virtualSize() const { return m_virtualSize; } -+ QSizeF physicalVirtualSize() const { return m_virtualSizeMillimeters; } - QDpi logicalDpi() const; - qreal devicePixelRatio() const; - QPlatformCursor *cursor() const; -@@ -139,6 +144,10 @@ private: - QXcbXSettings *m_xSettings; - }; - -+#ifndef QT_NO_DEBUG_STREAM -+QDebug operator<<(QDebug, const QXcbScreen *); -+#endif -+ - QT_END_NAMESPACE - - #endif diff --git a/qt5-qtbase-5.5-0004-xcb-do-not-create-dummy-qscreen-when-there-are-no-outputs.patch b/qt5-qtbase-5.5-0004-xcb-do-not-create-dummy-qscreen-when-there-are-no-outputs.patch deleted file mode 100644 index e642ef8..0000000 --- a/qt5-qtbase-5.5-0004-xcb-do-not-create-dummy-qscreen-when-there-are-no-outputs.patch +++ /dev/null @@ -1,89 +0,0 @@ -commit 51ada7734ad780178ecced11e0dff454dfc2e5f2 -Author: Shawn Rutledge -Date: Mon Mar 2 10:48:21 2015 +0100 - - xcb: do not create a dummy QScreen when there are no outputs - - Whenever a QWindow is associated with a QScreen, the screen is expected - to be a real working one, so that rendering continues to be possible. - This partially reverts 52f5e50f11a3ba82e32dc2efc656e4021a3fa4f5 - - [ChangeLog][QPA][Xcb] If all QScreens (xcb outputs) are disconnected - while an application is running, QGuiApplication::primaryScreen() will - return null until a screen is connected again. - - Task-number: QTBUG-40174 - Task-number: QTBUG-42985 - Change-Id: Id1b29dd70eaf3f2e7fd477516ce7e2bf24e095f6 - Reviewed-by: Laszlo Agocs - Reviewed-by: Jørgen Lind - -diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp -index dc5501e..7f2bf16 100644 ---- a/src/gui/kernel/qguiapplication.cpp -+++ b/src/gui/kernel/qguiapplication.cpp -@@ -872,9 +872,14 @@ QWindowList QGuiApplication::topLevelWindows() - } - - /*! -- Returns the primary (or default) screen of the application. -+ Returns the primary (or default) screen of the application, or null if there is none - - This will be the screen where QWindows are initially shown, unless otherwise specified. -+ -+ On some platforms, it may be null when there are actually no screens connected. -+ It is not possible to start a new QGuiApplication while there are no screens. -+ Applications which were running at the time the primary screen was removed -+ will stop rendering graphics until one or more screens are restored. - */ - QScreen *QGuiApplication::primaryScreen() - { -diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp -index a8c1943..6efb876 100644 ---- a/src/plugins/platforms/xcb/qxcbconnection.cpp -+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp -@@ -254,16 +254,6 @@ void QXcbConnection::updateScreens() - } - free(primary); - } -- // 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 (connectedOutputCount == 0) { -- qCDebug(lcQpaScreen, "found a screen with zero outputs"); -- QXcbScreen *screen = findOrCreateScreen(newScreens, xcbScreenNumber, xcbScreen); -- siblings << screen; -- activeScreens << screen; -- if (!primaryScreen) -- primaryScreen = screen; -- } - foreach (QPlatformScreen* s, siblings) - ((QXcbScreen*)s)->setVirtualSiblings(siblings); - xcb_screen_next(&it); -@@ -321,6 +311,11 @@ void QXcbConnection::updateScreens() - - if (!m_screens.isEmpty()) - qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name(); -+ else -+ // QTBUG-40174, QTBUG-42985: If there are no outputs, then there must be -+ // no QScreen instances; a Qt application can survive this situation, and -+ // start rendering again later when there is a screen again. -+ qCDebug(lcQpaScreen) << "xcb connection has no outputs"; - } - - QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName) -diff --git a/src/widgets/kernel/qdesktopwidget.qdoc b/src/widgets/kernel/qdesktopwidget.qdoc -index e8bda3c..f46a629 100644 ---- a/src/widgets/kernel/qdesktopwidget.qdoc -+++ b/src/widgets/kernel/qdesktopwidget.qdoc -@@ -238,6 +238,11 @@ - \property QDesktopWidget::screenCount - \brief the number of screens currently available on the system. - -+ Note that on some platforms, screenCount will be zero if there are actually -+ no screens connected. Applications which were running at the time the -+ screenCount went to zero will stop rendering graphics until one or more -+ screens are restored. -+ - \since 4.6 - */ - diff --git a/qt5-qtbase-5.5-0005-improve-handling-of-xrandr-events-in-xcb-backend.patch b/qt5-qtbase-5.5-0005-improve-handling-of-xrandr-events-in-xcb-backend.patch deleted file mode 100644 index 47dbe00..0000000 --- a/qt5-qtbase-5.5-0005-improve-handling-of-xrandr-events-in-xcb-backend.patch +++ /dev/null @@ -1,713 +0,0 @@ -commit 3b30a8215e98f6164a1650ce7c7e2a42a3d8746f -Author: Daniel Vrátil -Date: Mon Feb 23 20:27:37 2015 +0100 - - Improve handling of XRandR events in XCB backend - - Querying X server for data can be very expensive, especially when there - are multiple processes querying it at the same time (which is exactly what - happens when screen configuration changes and all Qt applications receive - XRandR change notifications). This patch is aiming to reduce the number of - queries to X server as much as possible by making use of detailed information - available in the RRCrtcChangeNotify and RROutputChangeNotify events. - - Firstly, the backend now does not rebuild all QXcbScreens on any change (which - involved the very expensive xcb_randr_get_screen_resources() call), but only - builds the full set of QXcbScreens once in initializeScreens(), and then just - incrementally updates it. - - Secondly, it avoids querying X server for all screens geometry as much as - possible, and only does so when CRTC/Output change notification for a particular - screen is delivered. - - As a result, handling of all XRandR events on screen change is reduced from tens - of seconds to less then a seconds and applications are better responsive after - that, because we don't block the event loop for long. The X server is also more - responsive after the screen change, since we are not overloading it with requests. - - Change-Id: I9b8308341cada71dfc9590030909b1e68a335a1f - Reviewed-by: Shawn Rutledge - -diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp -index 6efb876..0db7603 100644 ---- a/src/plugins/platforms/xcb/qxcbconnection.cpp -+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp -@@ -49,6 +49,7 @@ - #include - #include - #include -+#include - - #include - -@@ -155,8 +156,29 @@ typedef struct { - } QGLXBufferSwapComplete; - #endif - --QXcbScreen* QXcbConnection::findOrCreateScreen(QList& newScreens, -- int screenNumber, xcb_screen_t* xcbScreen, xcb_randr_get_output_info_reply_t *output) -+QXcbScreen* QXcbConnection::findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc) -+{ -+ foreach (QXcbScreen *screen, m_screens) { -+ if (screen->root() == rootWindow && screen->crtc() == crtc) -+ return screen; -+ } -+ -+ return 0; -+} -+ -+QXcbScreen* QXcbConnection::findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output) -+{ -+ foreach (QXcbScreen *screen, m_screens) { -+ if (screen->root() == rootWindow && screen->output() == output) -+ return screen; -+ } -+ -+ return 0; -+} -+ -+QXcbScreen* QXcbConnection::createScreen(int screenNumber, xcb_screen_t* xcbScreen, -+ xcb_randr_output_t outputId, -+ xcb_randr_get_output_info_reply_t *output) - { - QString name; - if (output) -@@ -169,23 +191,147 @@ QXcbScreen* QXcbConnection::findOrCreateScreen(QList& newScreens, - displayName.truncate(dotPos); - name = displayName + QLatin1Char('.') + QString::number(screenNumber); - } -- foreach (QXcbScreen* scr, m_screens) -- if (scr->name() == name && scr->root() == xcbScreen->root) -- return scr; -- QXcbScreen *ret = new QXcbScreen(this, xcbScreen, output, name, screenNumber); -- newScreens << ret; -- return ret; -+ -+ return new QXcbScreen(this, xcbScreen, outputId, output, name, screenNumber); -+} -+ -+bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output) -+{ -+ xcb_generic_error_t *error = 0; -+ xcb_randr_get_output_primary_cookie_t primaryCookie = -+ xcb_randr_get_output_primary(xcb_connection(), rootWindow); -+ QScopedPointer primary ( -+ xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error)); -+ if (!primary || error) { -+ qWarning("failed to get the primary output of the screen"); -+ free(error); -+ error = NULL; -+ } -+ const bool isPrimary = primary ? (primary->output == output) : false; -+ -+ return isPrimary; -+} -+ -+xcb_screen_t* QXcbConnection::xcbScreenForRootWindow(xcb_window_t rootWindow, int *xcbScreenNumber) -+{ -+ xcb_screen_iterator_t xcbScreenIter = xcb_setup_roots_iterator(m_setup); -+ for (; xcbScreenIter.rem; xcb_screen_next(&xcbScreenIter)) { -+ if (xcbScreenIter.data->root == rootWindow) { -+ if (xcbScreenNumber) -+ *xcbScreenNumber = xcb_setup_roots_length(m_setup) - xcbScreenIter.rem; -+ return xcbScreenIter.data; -+ } -+ } -+ -+ return 0; - } - - /*! - \brief Synchronizes the screen list, adds new screens, removes deleted ones - */ --void QXcbConnection::updateScreens() -+void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) -+{ -+ if (event->subCode == XCB_RANDR_NOTIFY_CRTC_CHANGE) { -+ xcb_randr_crtc_change_t crtc = event->u.cc; -+ xcb_screen_t *xcbScreen = xcbScreenForRootWindow(crtc.window); -+ if (!xcbScreen) -+ // Not for us -+ return; -+ -+ qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc; -+ QXcbScreen *screen = findScreenForCrtc(crtc.window, crtc.crtc); -+ // Only update geometry when there's a valid mode on the CRTC -+ // CRTC with node mode could mean that output has been disabled, and we'll -+ // get RRNotifyOutputChange notification for that. -+ if (screen && crtc.mode) { -+ screen->updateGeometry(QRect(crtc.x, crtc.y, crtc.width, crtc.height), crtc.rotation); -+ if (screen->mode() != crtc.mode) -+ screen->updateRefreshRate(crtc.mode); -+ } -+ -+ } else if (event->subCode == XCB_RANDR_NOTIFY_OUTPUT_CHANGE) { -+ xcb_randr_output_change_t output = event->u.oc; -+ int xcbScreenNumber = 0; -+ xcb_screen_t *xcbScreen = xcbScreenForRootWindow(output.window, &xcbScreenNumber); -+ if (!xcbScreen) -+ // Not for us -+ return; -+ -+ QXcbScreen *screen = findScreenForOutput(output.window, output.output); -+ qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_OUTPUT_CHANGE:" << output.output; -+ -+ if (screen && output.connection == XCB_RANDR_CONNECTION_DISCONNECTED) { -+ qCDebug(lcQpaScreen) << "screen" << screen->name() << "has been disconnected"; -+ -+ // Known screen removed -> delete it -+ m_screens.removeOne(screen); -+ foreach (QXcbScreen *otherScreen, m_screens) -+ otherScreen->removeVirtualSibling((QPlatformScreen *) screen); -+ -+ QXcbIntegration::instance()->destroyScreen(screen); -+ -+ // QTBUG-40174, QTBUG-42985: If there are no outputs, then there must be -+ // no QScreen instances; a Qt application can survive this situation, and -+ // start rendering again later when there is a screen again. -+ -+ } else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) { -+ // New XRandR output is available and it's enabled -+ if (output.crtc != XCB_NONE && output.mode != XCB_NONE) { -+ xcb_randr_get_output_info_cookie_t outputInfoCookie = -+ xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp); -+ QScopedPointer outputInfo( -+ xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL)); -+ -+ screen = createScreen(xcbScreenNumber, xcbScreen, output.output, outputInfo.data()); -+ qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled"; -+ -+ screen->setPrimary(checkOutputIsPrimary(output.window, output.output)); -+ foreach (QXcbScreen *otherScreen, m_screens) -+ if (otherScreen->root() == output.window) -+ otherScreen->addVirtualSibling(screen); -+ m_screens << screen; -+ QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary()); -+ } -+ // else ignore disabled screens -+ } else if (screen) { -+ // Screen has been disabled -> remove -+ if (output.crtc == XCB_NONE && output.mode == XCB_NONE) { -+ qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled"; -+ m_screens.removeOne(screen); -+ foreach (QXcbScreen *otherScreen, m_screens) -+ otherScreen->removeVirtualSibling((QPlatformScreen *) screen); -+ QXcbIntegration::instance()->destroyScreen(screen); -+ } else { -+ // Just update existing screen -+ screen->updateGeometry(output.config_timestamp); -+ const bool wasPrimary = screen->isPrimary(); -+ screen->setPrimary(checkOutputIsPrimary(output.window, output.output)); -+ if (screen->mode() != output.mode) -+ screen->updateRefreshRate(output.mode); -+ -+ // If the screen became primary, reshuffle the order in QGuiApplicationPrivate -+ // TODO: add a proper mechanism for updating primary screen -+ if (!wasPrimary && screen->isPrimary()) { -+ QScreen *realScreen = static_cast(screen)->screen(); -+ QGuiApplicationPrivate::screen_list.removeOne(realScreen); -+ QGuiApplicationPrivate::screen_list.prepend(realScreen); -+ m_screens.removeOne(screen); -+ m_screens.prepend(screen); -+ } -+ qCDebug(lcQpaScreen) << "output has changed" << screen; -+ } -+ } -+ if (!m_screens.isEmpty()) -+ qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name(); -+ else -+ qCDebug(lcQpaScreen) << "no outputs"; -+ } -+} -+ -+void QXcbConnection::initializeScreens() - { - xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup); - int xcbScreenNumber = 0; // screen number in the xcb sense -- QList activeScreens; -- QList newScreens; - QXcbScreen* primaryScreen = NULL; - while (it.rem) { - // Each "screen" in xcb terminology is a virtual desktop, -@@ -200,59 +346,73 @@ void QXcbConnection::updateScreens() - xcb_generic_error_t *error = NULL; - xcb_randr_get_output_primary_cookie_t primaryCookie = - xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root); -+ // TODO: RRGetScreenResources has to be called on each X display at least once before -+ // RRGetScreenResourcesCurrent can be used - we can't know if we are the first application -+ // to do so or not, so we always call the slower version here. Ideally we should share some -+ // global flag (an atom on root window maybe) that at least other Qt apps would understand -+ // and could call RRGetScreenResourcesCurrent here, speeding up start. - xcb_randr_get_screen_resources_cookie_t resourcesCookie = - xcb_randr_get_screen_resources(xcb_connection(), xcbScreen->root); -- xcb_randr_get_output_primary_reply_t *primary = -- xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error); -+ QScopedPointer primary( -+ xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error)); - if (!primary || error) { -- qWarning("QXcbConnection: Failed to get the primary output of the screen"); -+ qWarning("failed to get the primary output of the screen"); - free(error); - } else { -- xcb_randr_get_screen_resources_reply_t *resources = -- xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error); -+ QScopedPointer resources( -+ xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error)); - if (!resources || error) { -- qWarning("QXcbConnection: Failed to get the screen resources"); -+ qWarning("failed to get the screen resources"); - free(error); - } else { - xcb_timestamp_t timestamp = resources->config_timestamp; -- outputCount = xcb_randr_get_screen_resources_outputs_length(resources); -- xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(resources); -+ outputCount = xcb_randr_get_screen_resources_outputs_length(resources.data()); -+ xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(resources.data()); - - for (int i = 0; i < outputCount; i++) { -- xcb_randr_get_output_info_reply_t *output = -+ QScopedPointer output( - xcb_randr_get_output_info_reply(xcb_connection(), -- xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL); -+ xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL)); -+ -+ // Invalid, disconnected or disabled output - if (output == NULL) - continue; - -+ if (output->connection != XCB_RANDR_CONNECTION_CONNECTED) { -+ qCDebug(lcQpaScreen, "Output %s is not connected", qPrintable( -+ QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), -+ xcb_randr_get_output_info_name_length(output.data())))); -+ continue; -+ } - - if (output->crtc == XCB_NONE) { -- qCDebug(lcQpaScreen, "output %s is not connected", qPrintable( -- QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output), -- xcb_randr_get_output_info_name_length(output)))); -+ qCDebug(lcQpaScreen, "Output %s is not enabled", qPrintable( -+ QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), -+ xcb_randr_get_output_info_name_length(output.data())))); - continue; - } - -- QXcbScreen *screen = findOrCreateScreen(newScreens, xcbScreenNumber, xcbScreen, output); -+ QXcbScreen *screen = createScreen(xcbScreenNumber, xcbScreen, outputs[i], output.data()); - siblings << screen; -- activeScreens << screen; - ++connectedOutputCount; -+ m_screens << screen; -+ - // 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 - // or currently disconnected output. - if (m_primaryScreenNumber == xcbScreenNumber) { - if (!primaryScreen || (primary && outputs[i] == primary->output)) { -+ if (primaryScreen) -+ primaryScreen->setPrimary(false); - primaryScreen = screen; -+ primaryScreen->setPrimary(true); - siblings.prepend(siblings.takeLast()); - } - } -- free(output); - } - } -- free(resources); - } -- free(primary); - } - foreach (QPlatformScreen* s, siblings) - ((QXcbScreen*)s)->setVirtualSiblings(siblings); -@@ -260,47 +420,7 @@ void QXcbConnection::updateScreens() - ++xcbScreenNumber; - } // for each xcb screen - -- QXcbIntegration *integration = QXcbIntegration::instance(); -- -- // 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 screensToDelete; -- for (int i = m_screens.count() - 1; i >= 0; --i) { -- if (!activeScreens.contains(m_screens[i])) { -- screensToDelete.append(m_screens.takeAt(i)); -- } -- } -- -- // If there is a new primary screen, add that one first -- if (newScreens.contains(primaryScreen)) { -- newScreens.removeOne(primaryScreen); -- m_screens.prepend(primaryScreen); -- qCDebug(lcQpaScreen) << "adding as primary" << primaryScreen; -- integration->screenAdded(primaryScreen, true); -- } -- -- // Add the remaining new screens -- foreach (QXcbScreen* screen, newScreens) { -- m_screens.append(screen); -- qCDebug(lcQpaScreen) << "adding" << 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) { -- qCDebug(lcQpaScreen) << "removing" << screen; -- 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) -+ // Ensure the primary screen is first in the list - if (primaryScreen) { - Q_ASSERT(!m_screens.isEmpty()); - if (m_screens.first() != primaryScreen) { -@@ -309,13 +429,15 @@ void QXcbConnection::updateScreens() - } - } - -+ // Push the screens to QApplication -+ QXcbIntegration *integration = QXcbIntegration::instance(); -+ foreach (QXcbScreen* screen, m_screens) { -+ qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")"; -+ integration->screenAdded(screen, screen->isPrimary()); -+ } -+ - if (!m_screens.isEmpty()) - qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name(); -- else -- // QTBUG-40174, QTBUG-42985: If there are no outputs, then there must be -- // no QScreen instances; a Qt application can survive this situation, and -- // start rendering again later when there is a screen again. -- qCDebug(lcQpaScreen) << "xcb connection has no outputs"; - } - - QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName) -@@ -395,7 +517,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra - m_netWmUserTime = XCB_CURRENT_TIME; - - initializeXRandr(); -- updateScreens(); -+ initializeScreens(); - - initializeGLX(); - initializeXFixes(); -@@ -967,14 +1089,14 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) - m_clipboard->handleXFixesSelectionRequest((xcb_xfixes_selection_notify_event_t *)event); - #endif - handled = true; -+ } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_NOTIFY) { -+ updateScreens((xcb_randr_notify_event_t *)event); -+ handled = true; - } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) { -- updateScreens(); - xcb_randr_screen_change_notify_event_t *change_event = (xcb_randr_screen_change_notify_event_t *)event; - foreach (QXcbScreen *s, m_screens) { -- if (s->root() == change_event->root ) { -+ if (s->root() == change_event->root ) - s->handleScreenChange(change_event); -- s->updateRefreshRate(); -- } - } - handled = true; - #ifndef QT_NO_XKB -@@ -1741,6 +1863,17 @@ void QXcbConnection::initializeXRandr() - has_randr_extension = false; - } - free(xrandr_query); -+ -+ xcb_screen_iterator_t rootIter = xcb_setup_roots_iterator(m_setup); -+ for (; rootIter.rem; xcb_screen_next(&rootIter)) { -+ xcb_randr_select_input(xcb_connection(), -+ rootIter.data->root, -+ XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE | -+ XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE | -+ XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE | -+ XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY -+ ); -+ } - } - - void QXcbConnection::initializeXShape() -diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h -index 6e7e87d..9c190d7 100644 ---- a/src/plugins/platforms/xcb/qxcbconnection.h -+++ b/src/plugins/platforms/xcb/qxcbconnection.h -@@ -35,6 +35,7 @@ - #define QXCBCONNECTION_H - - #include -+#include - - #include - #include -@@ -492,9 +493,15 @@ private: - void initializeXShape(); - void initializeXKB(); - void handleClientMessageEvent(const xcb_client_message_event_t *event); -- QXcbScreen* findOrCreateScreen(QList& newScreens, int screenNumber, -- xcb_screen_t* xcbScreen, xcb_randr_get_output_info_reply_t *output = NULL); -- void updateScreens(); -+ QXcbScreen* createScreen(int screenNumber, xcb_screen_t* xcbScreen, -+ xcb_randr_output_t outputId = XCB_NONE, -+ xcb_randr_get_output_info_reply_t *output = 0); -+ QXcbScreen* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc); -+ QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output); -+ xcb_screen_t* xcbScreenForRootWindow(xcb_window_t rootWindow, int *xcbScreenNumber = 0); -+ bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output); -+ void initializeScreens(); -+ void updateScreens(const xcb_randr_notify_event_t *event); - void handleButtonPress(xcb_generic_event_t *event); - void handleButtonRelease(xcb_generic_event_t *event); - -diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp -index 2aebb84..d89bdbb 100644 ---- a/src/plugins/platforms/xcb/qxcbscreen.cpp -+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp -@@ -48,10 +48,15 @@ - QT_BEGIN_NAMESPACE - - QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, -- xcb_randr_get_output_info_reply_t *output, QString outputName, int number) -+ xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output, -+ QString outputName, int number) - : QXcbObject(connection) - , m_screen(scr) -+ , m_output(outputId) - , m_crtc(output ? output->crtc : 0) -+ , m_mode(XCB_NONE) -+ , m_primary(false) -+ , m_rotation(XCB_RANDR_ROTATION_ROTATE_0) - , m_outputName(outputName) - , m_outputSizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize()) - , m_virtualSize(scr->width_in_pixels, scr->height_in_pixels) -@@ -67,11 +72,20 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, - , m_antialiasingEnabled(-1) - , m_xSettings(0) - { -- if (connection->hasXRandr()) -+ if (connection->hasXRandr()) { - xcb_randr_select_input(xcb_connection(), screen()->root, true); -- -- updateGeometry(output ? output->timestamp : 0); -- updateRefreshRate(); -+ xcb_randr_get_crtc_info_cookie_t crtcCookie = -+ xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, output ? output->timestamp : 0); -+ xcb_randr_get_crtc_info_reply_t *crtc = -+ xcb_randr_get_crtc_info_reply(xcb_connection(), crtcCookie, NULL); -+ if (crtc) { -+ updateGeometry(QRect(crtc->x, crtc->y, crtc->width, crtc->height), crtc->rotation); -+ updateRefreshRate(crtc->mode); -+ free(crtc); -+ } -+ } else { -+ updateGeometry(output ? output->timestamp : 0); -+ } - - const int dpr = int(devicePixelRatio()); - // On VNC, it can be that physical size is unknown while -@@ -352,9 +366,15 @@ QPlatformCursor *QXcbScreen::cursor() const - */ - void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *change_event) - { -- updateGeometry(change_event->config_timestamp); -+ // No need to do anything when screen rotation did not change - if any -+ // xcb output geometry has changed, we will get RRCrtcChangeNotify and -+ // RROutputChangeNotify events next -+ if (change_event->rotation == m_rotation) -+ return; - -- switch (change_event->rotation) { -+ m_rotation = change_event->rotation; -+ updateGeometry(change_event->timestamp); -+ switch (m_rotation) { - case XCB_RANDR_ROTATION_ROTATE_0: // xrandr --rotate normal - m_orientation = Qt::LandscapeOrientation; - m_virtualSize.setWidth(change_event->width); -@@ -398,35 +418,37 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan - - void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp) - { -- QRect xGeometry; -- QRect xAvailableGeometry; -+ xcb_randr_get_crtc_info_cookie_t crtcCookie = -+ xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, timestamp); -+ xcb_randr_get_crtc_info_reply_t *crtc = -+ xcb_randr_get_crtc_info_reply(xcb_connection(), crtcCookie, NULL); -+ if (crtc) { -+ updateGeometry(QRect(crtc->x, crtc->y, crtc->width, crtc->height), crtc->rotation); -+ free(crtc); -+ } -+} - -- if (connection()->hasXRandr()) { -- xcb_randr_get_crtc_info_reply_t *crtc = xcb_randr_get_crtc_info_reply(xcb_connection(), -- xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, timestamp), NULL); -- if (crtc) { -- xGeometry = QRect(crtc->x, crtc->y, crtc->width, crtc->height); -- xAvailableGeometry = xGeometry; -- switch (crtc->rotation) { -- case XCB_RANDR_ROTATION_ROTATE_0: // xrandr --rotate normal -- m_orientation = Qt::LandscapeOrientation; -- m_sizeMillimeters = m_outputSizeMillimeters; -- break; -- case XCB_RANDR_ROTATION_ROTATE_90: // xrandr --rotate left -- m_orientation = Qt::PortraitOrientation; -- m_sizeMillimeters = m_outputSizeMillimeters.transposed(); -- break; -- case XCB_RANDR_ROTATION_ROTATE_180: // xrandr --rotate inverted -- m_orientation = Qt::InvertedLandscapeOrientation; -- m_sizeMillimeters = m_outputSizeMillimeters; -- break; -- case XCB_RANDR_ROTATION_ROTATE_270: // xrandr --rotate right -- m_orientation = Qt::InvertedPortraitOrientation; -- m_sizeMillimeters = m_outputSizeMillimeters.transposed(); -- break; -- } -- free(crtc); -- } -+void QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation) -+{ -+ QRect xGeometry = geom; -+ QRect xAvailableGeometry = xGeometry; -+ switch (rotation) { -+ case XCB_RANDR_ROTATION_ROTATE_0: // xrandr --rotate normal -+ m_orientation = Qt::LandscapeOrientation; -+ m_sizeMillimeters = m_outputSizeMillimeters; -+ break; -+ case XCB_RANDR_ROTATION_ROTATE_90: // xrandr --rotate left -+ m_orientation = Qt::PortraitOrientation; -+ m_sizeMillimeters = m_outputSizeMillimeters.transposed(); -+ break; -+ case XCB_RANDR_ROTATION_ROTATE_180: // xrandr --rotate inverted -+ m_orientation = Qt::InvertedLandscapeOrientation; -+ m_sizeMillimeters = m_outputSizeMillimeters; -+ break; -+ case XCB_RANDR_ROTATION_ROTATE_270: // xrandr --rotate right -+ m_orientation = Qt::InvertedPortraitOrientation; -+ m_sizeMillimeters = m_outputSizeMillimeters.transposed(); -+ break; - } - - xcb_get_property_reply_t * workArea = -@@ -455,31 +477,38 @@ void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp) - m_geometry = QRect(xGeometry.topLeft()/dpr, xGeometry.size()/dpr); - m_nativeGeometry = QRect(xGeometry.topLeft(), xGeometry.size()); - m_availableGeometry = QRect(xAvailableGeometry.topLeft()/dpr, xAvailableGeometry.size()/dpr); -- - QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry); - } - --void QXcbScreen::updateRefreshRate() -+void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode) - { - if (!connection()->hasXRandr()) - return; - -- int rate = m_refreshRate; -- -- xcb_randr_get_screen_info_reply_t *screenInfoReply = -- xcb_randr_get_screen_info_reply(xcb_connection(), xcb_randr_get_screen_info_unchecked(xcb_connection(), m_screen->root), 0); -- -- if (screenInfoReply) { -- rate = screenInfoReply->rate; -- free(screenInfoReply); -- } -- -- if (rate == m_refreshRate) -+ if (m_mode == mode) - return; - -- m_refreshRate = rate; -+ // we can safely use get_screen_resources_current here, because in order to -+ // get here, we must have called get_screen_resources before -+ xcb_randr_get_screen_resources_current_cookie_t resourcesCookie = -+ xcb_randr_get_screen_resources_current_unchecked(xcb_connection(), m_screen->root); -+ xcb_randr_get_screen_resources_current_reply_t *resources = -+ xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, NULL); -+ if (resources) { -+ xcb_randr_mode_info_iterator_t modesIter = -+ xcb_randr_get_screen_resources_current_modes_iterator(resources); -+ for (; modesIter.rem; xcb_randr_mode_info_next(&modesIter)) { -+ xcb_randr_mode_info_t *modeInfo = modesIter.data; -+ if (modeInfo->id == mode) { -+ m_refreshRate = modeInfo->dot_clock / (modeInfo->htotal * modeInfo->vtotal); -+ m_mode = mode; -+ break; -+ } -+ } - -- QWindowSystemInterface::handleScreenRefreshRateChange(QPlatformScreen::screen(), rate); -+ free(resources); -+ QWindowSystemInterface::handleScreenRefreshRateChange(QPlatformScreen::screen(), m_refreshRate); -+ } - } - - QPixmap QXcbScreen::grabWindow(WId window, int x, int y, int width, int height) const -diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h -index 81c3445..a654a3e 100644 ---- a/src/plugins/platforms/xcb/qxcbscreen.h -+++ b/src/plugins/platforms/xcb/qxcbscreen.h -@@ -57,7 +57,8 @@ class QXcbScreen : public QXcbObject, public QPlatformScreen - { - public: - QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, -- xcb_randr_get_output_info_reply_t *output, QString outputName, int number); -+ xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output, -+ QString outputName, int number); - ~QXcbScreen(); - - QPixmap grabWindow(WId window, int x, int y, int width, int height) const; -@@ -79,11 +80,19 @@ public: - Qt::ScreenOrientation orientation() const { return m_orientation; } - QList virtualSiblings() const { return m_siblings; } - void setVirtualSiblings(QList sl) { m_siblings = sl; } -+ void removeVirtualSibling(QPlatformScreen *s) { m_siblings.removeOne(s); } -+ void addVirtualSibling(QPlatformScreen *s) { ((QXcbScreen *) s)->isPrimary() ? m_siblings.prepend(s) : m_siblings.append(s); } -+ -+ void setPrimary(bool primary) { m_primary = primary; } -+ bool isPrimary() const { return m_primary; } - - int screenNumber() const { return m_number; } - - xcb_screen_t *screen() const { return m_screen; } - xcb_window_t root() const { return m_screen->root; } -+ xcb_randr_output_t output() const { return m_output; } -+ xcb_randr_crtc_t crtc() const { return m_crtc; } -+ xcb_randr_mode_t mode() const { return m_mode; } - - xcb_window_t clientLeader() const { return m_clientLeader; } - -@@ -97,8 +106,9 @@ public: - QString name() const { return m_outputName; } - - void handleScreenChange(xcb_randr_screen_change_notify_event_t *change_event); -- void updateGeometry(xcb_timestamp_t timestamp); -- void updateRefreshRate(); -+ void updateGeometry(const QRect &geom, uint8_t rotation); -+ void updateGeometry(xcb_timestamp_t timestamp = XCB_TIME_CURRENT_TIME); -+ void updateRefreshRate(xcb_randr_mode_t mode); - - void readXResources(); - -@@ -116,7 +126,12 @@ private: - void sendStartupMessage(const QByteArray &message) const; - - xcb_screen_t *m_screen; -+ xcb_randr_output_t m_output; - xcb_randr_crtc_t m_crtc; -+ xcb_randr_mode_t m_mode; -+ bool m_primary; -+ uint8_t m_rotation; -+ - QString m_outputName; - QSizeF m_outputSizeMillimeters; - QSizeF m_sizeMillimeters; diff --git a/qt5-qtbase-5.5-0006-fix-segfault-when-requesting-root-window-and-there-are-no-screens.patch b/qt5-qtbase-5.5-0006-fix-segfault-when-requesting-root-window-and-there-are-no-screens.patch deleted file mode 100644 index 02dabf4..0000000 --- a/qt5-qtbase-5.5-0006-fix-segfault-when-requesting-root-window-and-there-are-no-screens.patch +++ /dev/null @@ -1,43 +0,0 @@ -commit 4c022338aa787c216c3afa217987e4125bd15b41 -Author: Jan Kundrát -Date: Wed Mar 11 16:42:10 2015 +0100 - - Fix segfault when requesting root window and there are no screens - - This was easy to hit with KDE Plasma 5.2.1; KWindowSystem called - QX11Info::appRootWindow() which in turn tried to dereference a nullptr - returned from QXcbConnection::primaryScreen(). - - #0 QXcbConnection::rootWindow (this=) - at qtgui-5.5.9999/src/plugins/platforms/xcb/qxcbconnection.cpp:1303 - #1 0x00007fc26da096d7 in QXcbNativeInterface::rootWindow (this=this@entry=0x7fc27d1734d0) - at qtgui-5.5.9999/work/qtgui-5.5.9999/src/plugins/platforms/xcb/qxcbnativeinterface.cpp:425 - #2 0x00007fc26da0ab21 in QXcbNativeInterface::nativeResourceForIntegration (this=0x7fc27d1734d0, resourceString=...) - at qtgui-5.5.9999/work/qtgui-5.5.9999/src/plugins/platforms/xcb/qxcbnativeinterface.cpp:223 - #3 0x00007fc27c563148 in QX11Info::appRootWindow (screen=screen@entry=-1) - at qtx11extras-5.5.9999/work/qtx11extras-5.5.9999/src/x11extras/qx11info_x11.cpp:158 - #4 0x00007fc27a98c444 in NETEventFilter::nativeEventFilter (this=0x7fc27d425b60, ev=0x7fc264004ad0) - at kwindowsystem-5.7.0/work/kwindowsystem-5.7.0/src/kwindowsystem_x11.cpp:192 - #5 0x00007fc2795d0a8a in QAbstractEventDispatcher::filterNativeEvent (this=, - eventType=..., message=message@entry=0x7fc264004ad0, result=result@entry=0x7ffc96ecf348) - at qtcore-5.5.9999/work/qtcore-5.5.9999/src/corelib/kernel/qabstracteventdispatcher.cpp:460 - #6 0x00007fc26d9ea941 in QXcbConnection::handleXcbEvent (this=this@entry=0x7fc27d173580, event=event@entry=0x7fc264004ad0) - at qtgui-5.5.9999/src/plugins/platforms/xcb/qxcbconnection.cpp:971 - - Change-Id: I98a5d767cd7e143f00666f6fc78e9dc10893513d - Reviewed-by: Shawn Rutledge - -diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp -index 0db7603..523ae79 100644 ---- a/src/plugins/platforms/xcb/qxcbconnection.cpp -+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp -@@ -1367,7 +1367,8 @@ xcb_timestamp_t QXcbConnection::getTimestamp() - - xcb_window_t QXcbConnection::rootWindow() - { -- return primaryScreen()->root(); -+ QXcbScreen *s = primaryScreen(); -+ return s ? s->root() : 0; - } - - void QXcbConnection::processXcbEvents() diff --git a/qt5-qtbase-5.5-0007-xcb-create-a-screen-if-dimensions-are-known-but-outputs-are-not.patch b/qt5-qtbase-5.5-0007-xcb-create-a-screen-if-dimensions-are-known-but-outputs-are-not.patch deleted file mode 100644 index 4c55941..0000000 --- a/qt5-qtbase-5.5-0007-xcb-create-a-screen-if-dimensions-are-known-but-outputs-are-not.patch +++ /dev/null @@ -1,86 +0,0 @@ -commit ebdf9916600f0b0cd4d25b538d1fd0fef6e89077 -Author: Shawn Rutledge -Date: Tue Mar 10 17:09:31 2015 +0100 - - xcb: create a screen if dimensions are known but outputs are not - - This partially reverts 51ada7734ad780178ecced11e0dff454dfc2e5f2 - because it's necessary to keep some scenarios with vnc and - remote X servers working. When an application is starting, - if we don't find the xrandr outputs but we know the dimensions - of the screen, we should still be able to put windows onto that - screen; but when we already had known xrandr outputs and then they - were removed, that's the case where we want to stop rendering - (and have no screen instances) until the screen(s) are reattached. - - Task-number: QTBUG-31389 - Task-number: QTBUG-40174 - Task-number: QTBUG-42985 - Change-Id: I13d0996ba6ece78c4ebcd2c3a59f1617c1c7f0fa - Reviewed-by: Uli Schlachter - Reviewed-by: Gatis Paeglis - Reviewed-by: Laszlo Agocs - -diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp -index 523ae79..89a0083 100644 ---- a/src/plugins/platforms/xcb/qxcbconnection.cpp -+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp -@@ -270,9 +270,8 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) - - QXcbIntegration::instance()->destroyScreen(screen); - -- // QTBUG-40174, QTBUG-42985: If there are no outputs, then there must be -- // no QScreen instances; a Qt application can survive this situation, and -- // start rendering again later when there is a screen again. -+ // QTBUG-40174, QTBUG-42985: If all screens are removed, wait -+ // and start rendering again later if a screen becomes available. - - } else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) { - // New XRandR output is available and it's enabled -@@ -332,13 +331,15 @@ void QXcbConnection::initializeScreens() - { - xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup); - int xcbScreenNumber = 0; // screen number in the xcb sense -- QXcbScreen* primaryScreen = NULL; -+ QXcbScreen* primaryScreen = Q_NULLPTR; -+ xcb_screen_t *xcbScreen = Q_NULLPTR; -+ bool hasOutputs = false; - while (it.rem) { - // Each "screen" in xcb terminology is a virtual desktop, - // potentially a collection of separate juxtaposed monitors. - // But we want a separate QScreen for each output (e.g. DVI-I-1, VGA-1, etc.) - // which will become virtual siblings. -- xcb_screen_t *xcbScreen = it.data; -+ xcbScreen = it.data; - QList siblings; - int outputCount = 0; - int connectedOutputCount = 0; -@@ -395,6 +396,7 @@ void QXcbConnection::initializeScreens() - QXcbScreen *screen = createScreen(xcbScreenNumber, xcbScreen, outputs[i], output.data()); - siblings << screen; - ++connectedOutputCount; -+ hasOutputs = true; - m_screens << screen; - - // There can be multiple outputs per screen, use either -@@ -420,6 +422,20 @@ void QXcbConnection::initializeScreens() - ++xcbScreenNumber; - } // for each xcb screen - -+ // If there's no randr extension, or there was some error above, or we found a -+ // screen which doesn't have outputs for some other reason (e.g. on VNC or ssh -X), -+ // but the dimensions are known anyway, and we don't already have any lingering -+ // (possibly disconnected) screens, then showing windows should be possible, -+ // so create one screen. (QTBUG-31389) -+ if (xcbScreen && !hasOutputs && xcbScreen->width_in_pixels > 0 && xcbScreen->height_in_pixels > 0 && m_screens.isEmpty()) { -+ QXcbScreen *screen = createScreen(0, xcbScreen, 0, Q_NULLPTR); -+ screen->setVirtualSiblings(QList() << screen); -+ m_screens << screen; -+ primaryScreen = screen; -+ primaryScreen->setPrimary(true); -+ qCDebug(lcQpaScreen) << "found a screen with zero outputs" << screen; -+ } -+ - // Ensure the primary screen is first in the list - if (primaryScreen) { - Q_ASSERT(!m_screens.isEmpty()); diff --git a/qt5-qtbase.spec b/qt5-qtbase.spec index 08a359a..3515a21 100644 --- a/qt5-qtbase.spec +++ b/qt5-qtbase.spec @@ -37,7 +37,7 @@ Summary: Qt5 - QtBase components Name: qt5-qtbase Version: 5.4.1 -Release: 6%{?dist} +Release: 7%{?dist} # See LGPL_EXCEPTIONS.txt, for exception details License: LGPLv2 with exceptions or GPLv3 with exceptions @@ -82,25 +82,16 @@ Patch12: qtbase-opensource-src-5.2.0-enable_ft_lcdfilter.patch # NEEDS REBASE Patch50: qt5-poll.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1083664 +# https://bugreports.qt.io/browse/QTBUG-42985 +Patch51: qtbase-opensource-src-5.4.0-QTBUG-42985.patch + ## upstream patches # workaround https://bugreports.qt-project.org/browse/QTBUG-43057 # 'make docs' crash on el6, use qSort instead of std::sort Patch100: qtbase-opensource-src-5.4.0-QTBUG-43057.patch # Qt 5.5 patches - -# better XCB screen integration support rebased on Qt 5.4.1 -# fixes screen-handling related crashes and massive performance improvement -# QTBUG-31389, QTBUG-38326, QTBUG-32973, QTBUG-40174, QTBUG-42985, QTBUG-42985, QTBUG-44388 -# https://bugzilla.redhat.com/show_bug.cgi?id=1083664 -Patch200: qt5-qtbase-5.5-0000-add-function-for-qpa-plugins-to-explictly-destroy-qscreens.patch -Patch201: qt5-qtbase-5.5-0001-have-xcb-windows-platform-integration-classes-keep-their-own-instance-pointer.patch -Patch202: qt5-qtbase-5.5-0002-ensure-qguiapplicationprivate-screen_list-is-correctly-populated.patch -Patch203: qt5-qtbase-5.5-0003-xcb-add-qt-qpa-screen-logging-category.patch -Patch204: qt5-qtbase-5.5-0004-xcb-do-not-create-dummy-qscreen-when-there-are-no-outputs.patch -Patch205: qt5-qtbase-5.5-0005-improve-handling-of-xrandr-events-in-xcb-backend.patch -Patch206: qt5-qtbase-5.5-0006-fix-segfault-when-requesting-root-window-and-there-are-no-screens.patch -Patch207: qt5-qtbase-5.5-0007-xcb-create-a-screen-if-dimensions-are-known-but-outputs-are-not.patch Patch208: qt5-qtbase-5.5-Get_display_number_when_screen_number_is_omitted.patch @@ -350,19 +341,12 @@ rm -fv mkspecs/linux-g++*/qmake.conf.multilib-optflags %patch12 -p1 -b .enable_ft_lcdfilter #patch50 -p1 -b .poll +%patch51 -p1 -b .QTBUG-42985 %if 0%{?rhel} == 6 %patch100 -p1 -b .QTBUG-43057 %endif -%patch200 -p1 -b .xcb0000 -%patch201 -p1 -b .xcb0001 -%patch202 -p1 -b .xcb0002 -%patch203 -p1 -b .xcb0003 -%patch204 -p1 -b .xcb0004 -%patch205 -p1 -b .xcb0005 -%patch206 -p1 -b .xcb0006 -%patch207 -p1 -b .xcb0007 %patch208 -p1 -b .ibus_get_display_number %patch212 -p1 -b .0012 @@ -881,6 +865,9 @@ fi %changelog +* Wed Apr 01 2015 Daniel Vrátil - 5.4.1-7 +- drop 5.5 XCB patches, the rebase is incomplete and does not work properly with Qt 5.4 + * Mon Mar 30 2015 Rex Dieter 5.4.1-6 - Crash due to unsafe access to QTextLayout::lineCount (#1207279,QTBUG-43562) diff --git a/qtbase-opensource-src-5.4.0-QTBUG-42985.patch b/qtbase-opensource-src-5.4.0-QTBUG-42985.patch new file mode 100644 index 0000000..60bd6bd --- /dev/null +++ b/qtbase-opensource-src-5.4.0-QTBUG-42985.patch @@ -0,0 +1,600 @@ +diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp +index 39b031e..7f808da 100644 +--- a/src/gui/kernel/qplatformintegration.cpp ++++ b/src/gui/kernel/qplatformintegration.cpp +@@ -429,16 +429,40 @@ QList QPlatformIntegration::possibleKeys(const QKeyEvent *) const + This adds the screen to QGuiApplication::screens(), and emits the + QGuiApplication::screenAdded() signal. + ++ If the added screen is a primary screen (isPrimary = true), it is prepended ++ to the QGuiApplicationPrivate::screen_list, since ++ QGuiApplication::primaryScreen always returns the first screen in the list. ++ + The screen is automatically removed when the QPlatformScreen is destroyed. + */ +-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); + } + ++/*! ++ Should be called by the implementation whenever a screen is removed. ++ ++ The implementation should ensure that the screen removed is not the ++ primary screen. ++*/ ++void QPlatformIntegration::screenRemoved(QPlatformScreen *ps) ++{ ++ if (ps->screen() == QGuiApplicationPrivate::screen_list.first()) { ++ qWarning("Primary screen removed, expect trouble"); ++ } ++ if (QGuiApplicationPrivate::screen_list.removeOne(ps->screen()) && qApp) { ++ Q_EMIT qApp->screenRemoved(ps->screen()); ++ } ++} ++ + QStringList QPlatformIntegration::themeNames() const + { + return QStringList(); +diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h +index d510240..5ec7896 100644 +--- a/src/gui/kernel/qplatformintegration.h ++++ b/src/gui/kernel/qplatformintegration.h +@@ -169,7 +169,8 @@ public: + #endif + + protected: +- void screenAdded(QPlatformScreen *screen); ++ void screenAdded(QPlatformScreen *screen, bool isPrimary = false); ++ void screenRemoved(QPlatformScreen *screen); + }; + + QT_END_NAMESPACE +diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp +index 71710d1..4fb7114 100644 +--- a/src/gui/kernel/qplatformscreen.cpp ++++ b/src/gui/kernel/qplatformscreen.cpp +@@ -52,8 +52,6 @@ QPlatformScreen::QPlatformScreen() + QPlatformScreen::~QPlatformScreen() + { + Q_D(QPlatformScreen); +- +- QGuiApplicationPrivate::screen_list.removeOne(d->screen); + delete d->screen; + } + +diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp +index ed6e8dd..8909eed 100644 +--- a/src/gui/kernel/qscreen.cpp ++++ b/src/gui/kernel/qscreen.cpp +@@ -66,16 +66,6 @@ QScreen::QScreen(QPlatformScreen *screen) + { + } + +- +-/*! +- Destroys the screen. +- */ +-QScreen::~QScreen() +-{ +- if (qApp) +- Q_EMIT qApp->screenRemoved(this); +-} +- + /*! + Get the platform screen handle. + */ +diff --git a/src/gui/kernel/qscreen.h b/src/gui/kernel/qscreen.h +index 766b3d8..144730a 100644 +--- a/src/gui/kernel/qscreen.h ++++ b/src/gui/kernel/qscreen.h +@@ -81,7 +81,6 @@ class Q_GUI_EXPORT QScreen : public QObject + Q_PROPERTY(qreal refreshRate READ refreshRate NOTIFY refreshRateChanged) + + public: +- ~QScreen(); + QPlatformScreen *handle() const; + + QString name() const; +diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp +index f56a29d..0dca2da 100644 +--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp ++++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp +@@ -276,7 +276,7 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c) + m_timestamp[QClipboard::Clipboard] = XCB_CURRENT_TIME; + m_timestamp[QClipboard::Selection] = XCB_CURRENT_TIME; + +- m_screen = connection()->primaryScreen(); ++ QXcbScreen * screen = connection()->primaryScreen(); + + int x = 0, y = 0, w = 3, h = 3; + +@@ -284,11 +284,11 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c) + Q_XCB_CALL(xcb_create_window(xcb_connection(), + XCB_COPY_FROM_PARENT, // depth -- same as root + m_owner, // window id +- m_screen->screen()->root, // parent window id ++ screen->screen()->root, // parent window id + x, y, w, h, + 0, // border width + XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class +- m_screen->screen()->root_visual, // visual ++ screen->screen()->root_visual, // visual + 0, // value mask + 0)); // value list + #ifndef QT_NO_DEBUG +@@ -462,8 +462,15 @@ bool QXcbClipboard::ownsMode(QClipboard::Mode mode) const + return m_timestamp[mode] != XCB_CURRENT_TIME; + } + ++QXcbScreen *QXcbClipboard::screen() const ++{ ++ return connection()->primaryScreen(); ++} ++ + xcb_window_t QXcbClipboard::requestor() const + { ++ QXcbScreen * screen = connection()->primaryScreen(); ++ + if (!m_requestor) { + const int x = 0, y = 0, w = 3, h = 3; + QXcbClipboard *that = const_cast(this); +@@ -472,11 +479,11 @@ xcb_window_t QXcbClipboard::requestor() const + Q_XCB_CALL(xcb_create_window(xcb_connection(), + XCB_COPY_FROM_PARENT, // depth -- same as root + window, // window id +- m_screen->screen()->root, // parent window id ++ screen->screen()->root, // parent window id + x, y, w, h, + 0, // border width + XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class +- m_screen->screen()->root_visual, // visual ++ screen->screen()->root_visual, // visual + 0, // value mask + 0)); // value list + #ifndef QT_NO_DEBUG +diff --git a/src/plugins/platforms/xcb/qxcbclipboard.h b/src/plugins/platforms/xcb/qxcbclipboard.h +index e76d502..b6cbda4 100644 +--- a/src/plugins/platforms/xcb/qxcbclipboard.h ++++ b/src/plugins/platforms/xcb/qxcbclipboard.h +@@ -59,7 +59,7 @@ public: + bool supportsMode(QClipboard::Mode mode) const; + bool ownsMode(QClipboard::Mode mode) const; + +- QXcbScreen *screen() const { return m_screen; } ++ QXcbScreen *screen() const; + + xcb_window_t requestor() const; + void setRequestor(xcb_window_t window); +@@ -91,8 +91,6 @@ private: + xcb_atom_t atomForMode(QClipboard::Mode mode) const; + QClipboard::Mode modeForAtom(xcb_atom_t atom) const; + +- QXcbScreen *m_screen; +- + // Selection and Clipboard + QXcbClipboardMime *m_xClipboard[2]; + QMimeData *m_clientClipboard[2]; +diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp +index 5510c3b..c9600f0 100644 +--- a/src/plugins/platforms/xcb/qxcbconnection.cpp ++++ b/src/plugins/platforms/xcb/qxcbconnection.cpp +@@ -182,7 +182,6 @@ QXcbScreen* QXcbConnection::findOrCreateScreen(QList& 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 activeScreens; + QList newScreens; +@@ -194,7 +193,7 @@ void QXcbConnection::updateScreens() + // which will become virtual siblings. + xcb_screen_t *xcbScreen = it.data; + QList siblings; +- int outputCount = 0; ++ int outputCount = 0, connectedOutputCount = 0; + if (has_randr_extension) { + xcb_generic_error_t *error = NULL; + xcb_randr_get_output_primary_cookie_t primaryCookie = +@@ -239,7 +238,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 +@@ -262,7 +261,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 +@@ -271,7 +270,6 @@ void QXcbConnection::updateScreens() + activeScreens << screen; + if (!primaryScreen) + primaryScreen = screen; +- ++screenNumber; + } + foreach (QPlatformScreen* s, siblings) + ((QXcbScreen*)s)->setVirtualSiblings(siblings); +@@ -279,28 +277,39 @@ void QXcbConnection::updateScreens() + ++xcbScreenNumber; + } // for each xcb screen + +- // 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: ((QXcbIntegration*)QGuiApplicationPrivate::platformIntegration())->screenAdded(); ++ // - screen removed: QPlatformScreen::~QPlatformScreen() via QXcbScreen::~QXcbScreen() ++ ++ // Gather screens to delete ++ QList screensToDelete; + for (int i = m_screens.count() - 1; i >= 0; --i) { + if (!activeScreens.contains(m_screens[i])) { +- delete m_screens[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); ++ ((QXcbIntegration*)QGuiApplicationPrivate::platformIntegration())->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); ++ ((QXcbIntegration*)QGuiApplicationPrivate::platformIntegration())->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)) +- ((QXcbIntegration*)QGuiApplicationPrivate::platformIntegration())->screenAdded(screen); ++ // And finally, 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) { ++ ((QXcbIntegration*)QGuiApplicationPrivate::platformIntegration())->screenRemoved(screen); ++ delete screen; ++ } + } + + QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName) +diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp +index 0094278..44d33e1 100644 +--- a/src/plugins/platforms/xcb/qxcbwindow.cpp ++++ b/src/plugins/platforms/xcb/qxcbwindow.cpp +@@ -257,9 +257,7 @@ QXcbWindow::QXcbWindow(QWindow *window) + , m_syncState(NoSyncNeeded) + , m_pendingSyncRequest(0) + { +- m_screen = static_cast(window->screen()->handle()); +- +- setConnection(m_screen->connection()); ++ setConnection(xcbscreen()->connection()); + + if (window->type() != Qt::ForeignWindow) + create(); +@@ -298,11 +296,13 @@ void QXcbWindow::create() + + Qt::WindowType type = window()->type(); + ++ QXcbScreen* screen = this->xcbscreen(); ++ + if (type == Qt::Desktop) { +- m_window = m_screen->root(); +- m_depth = m_screen->screen()->root_depth; +- m_visualId = m_screen->screen()->root_visual; +- const xcb_visualtype_t *visual = m_screen->visualForId(m_visualId); ++ m_window = screen->root(); ++ m_depth = screen->screen()->root_depth; ++ m_visualId = screen->screen()->root_visual; ++ const xcb_visualtype_t *visual = screen->visualForId(m_visualId); + m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask); + connection()->addWindowEventListener(m_window, this); + return; +@@ -343,7 +343,7 @@ void QXcbWindow::create() + rect.setHeight(defaultWindowHeight); + } + +- xcb_window_t xcb_parent_id = m_screen->root(); ++ xcb_window_t xcb_parent_id = screen->root(); + if (parent()) { + xcb_parent_id = static_cast(parent())->xcb_window(); + m_embedded = parent()->window()->type() == Qt::ForeignWindow; +@@ -358,7 +358,7 @@ void QXcbWindow::create() + #if (defined(XCB_USE_GLX) || defined(XCB_USE_EGL)) && defined(XCB_USE_XLIB) + if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) { + #if defined(XCB_USE_GLX) +- XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), &m_format); ++ XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(screen), screen->screenNumber(), &m_format); + #elif defined(XCB_USE_EGL) + EGLDisplay eglDisplay = connection()->egl_display(); + EGLConfig eglConfig = q_configFromGLFormat(eglDisplay, m_format, true); +@@ -387,8 +387,8 @@ void QXcbWindow::create() + Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), xcb_parent_id, visualInfo->visual, AllocNone); + + XSetWindowAttributes a; +- a.background_pixel = WhitePixel(DISPLAY_FROM_XCB(this), m_screen->screenNumber()); +- a.border_pixel = BlackPixel(DISPLAY_FROM_XCB(this), m_screen->screenNumber()); ++ a.background_pixel = WhitePixel(DISPLAY_FROM_XCB(this), screen->screenNumber()); ++ a.border_pixel = BlackPixel(DISPLAY_FROM_XCB(this), screen->screenNumber()); + a.colormap = cmap; + + m_visualId = visualInfo->visualid; +@@ -407,14 +407,14 @@ void QXcbWindow::create() + #endif //defined(XCB_USE_GLX) || defined(XCB_USE_EGL) + { + m_window = xcb_generate_id(xcb_connection()); +- m_visualId = m_screen->screen()->root_visual; +- m_depth = m_screen->screen()->root_depth; ++ m_visualId = screen->screen()->root_visual; ++ m_depth = screen->screen()->root_depth; + + uint32_t mask = 0; + uint32_t values[3]; + + if (m_format.alphaBufferSize() == 8) { +- xcb_depth_iterator_t depthIter = xcb_screen_allowed_depths_iterator(m_screen->screen()); ++ xcb_depth_iterator_t depthIter = xcb_screen_allowed_depths_iterator(screen->screen()); + while (depthIter.rem) { + if (depthIter.data->depth == 32) { + xcb_visualtype_iterator_t visualIter = xcb_depth_visuals_iterator(depthIter.data); +@@ -425,8 +425,8 @@ void QXcbWindow::create() + xcb_create_colormap(xcb_connection(), XCB_COLORMAP_ALLOC_NONE, colormap, + xcb_parent_id, m_visualId); + mask |= XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP; +- values[0] = m_screen->screen()->white_pixel; +- values[1] = m_screen->screen()->black_pixel; ++ values[0] = screen->screen()->white_pixel; ++ values[1] = screen->screen()->black_pixel; + values[2] = colormap; + break; + } +@@ -435,7 +435,7 @@ void QXcbWindow::create() + } + } + +- const xcb_visualtype_t *visual = m_screen->visualForId(m_visualId); ++ const xcb_visualtype_t *visual = screen->visualForId(m_visualId); + m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask); + + Q_XCB_CALL(xcb_create_window(xcb_connection(), +@@ -465,7 +465,7 @@ void QXcbWindow::create() + properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS); + properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING); + +- m_usingSyncProtocol = m_screen->syncRequestSupported(); ++ m_usingSyncProtocol = screen->syncRequestSupported(); + #if !defined(XCB_USE_GLX) + // synced resize only implemented on GLX + if (window()->supportsOpenGL()) +@@ -524,7 +524,7 @@ void QXcbWindow::create() + + xcb_set_wm_hints(xcb_connection(), m_window, &hints); + +- xcb_window_t leader = m_screen->clientLeader(); ++ xcb_window_t leader = screen->clientLeader(); + Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::WM_CLIENT_LEADER), XCB_ATOM_WINDOW, 32, + 1, &leader)); +@@ -550,7 +550,7 @@ void QXcbWindow::create() + + #ifdef XCB_USE_XLIB + // force sync to read outstanding requests - see QTBUG-29106 +- XSync(DISPLAY_FROM_XCB(m_screen), false); ++ XSync(DISPLAY_FROM_XCB(screen), false); + #endif + + #ifndef QT_NO_DRAGANDDROP +@@ -744,7 +744,7 @@ void QXcbWindow::show() + // Default to client leader if there is no transient parent, else modal dialogs can + // be hidden by their parents. + if (!transientXcbParent) +- transientXcbParent = static_cast(screen())->clientLeader(); ++ transientXcbParent = static_cast(xcbscreen())->clientLeader(); + if (transientXcbParent) { // ICCCM 4.1.2.6 + Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, +@@ -772,7 +772,7 @@ void QXcbWindow::show() + if (QGuiApplication::modalWindow() == window()) + requestActivateWindow(); + +- m_screen->windowShown(this); ++ xcbscreen()->windowShown(this); + + connection()->sync(); + } +@@ -784,10 +784,10 @@ void QXcbWindow::hide() + // send synthetic UnmapNotify event according to icccm 4.1.4 + xcb_unmap_notify_event_t event; + event.response_type = XCB_UNMAP_NOTIFY; +- event.event = m_screen->root(); ++ event.event = xcbscreen()->root(); + event.window = m_window; + event.from_configure = false; +- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, m_screen->root(), ++ Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbscreen()->root(), + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); + + xcb_flush(xcb_connection()); +@@ -1107,7 +1107,7 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two) + event.data.data32[3] = 0; + event.data.data32[4] = 0; + +- Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); ++ Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbscreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); + } + + void QXcbWindow::setWindowState(Qt::WindowState state) +@@ -1148,7 +1148,7 @@ void QXcbWindow::setWindowState(Qt::WindowState state) + event.data.data32[3] = 0; + event.data.data32[4] = 0; + +- Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); ++ Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbscreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); + } + break; + case Qt::WindowMaximized: +@@ -1391,7 +1391,7 @@ void QXcbWindow::setParent(const QPlatformWindow *parent) + xcb_parent_id = qXcbParent->xcb_window(); + m_embedded = qXcbParent->window()->type() == Qt::ForeignWindow; + } else { +- xcb_parent_id = m_screen->root(); ++ xcb_parent_id = xcbscreen()->root(); + m_embedded = false; + } + Q_XCB_CALL(xcb_reparent_window(xcb_connection(), xcb_window(), xcb_parent_id, topLeft.x(), topLeft.y())); +@@ -1559,7 +1559,7 @@ void QXcbWindow::requestActivateWindow() + event.data.data32[3] = 0; + event.data.data32[4] = 0; + +- Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); ++ Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbscreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); + } else { + Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, connection()->time())); + } +@@ -1796,15 +1796,15 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even + relayFocusToModalWindow(); + return; + } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_PING)) { +- if (event->window == m_screen->root()) ++ if (event->window == xcbscreen()->root()) + return; + + xcb_client_message_event_t reply = *event; + + reply.response_type = XCB_CLIENT_MESSAGE; +- reply.window = m_screen->root(); ++ reply.window = xcbscreen()->root(); + +- xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&reply); ++ xcb_send_event(xcb_connection(), 0, xcbscreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&reply); + xcb_flush(xcb_connection()); + } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_SYNC_REQUEST)) { + connection()->setTime(event->data.data32[1]); +@@ -1871,7 +1871,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * + if (!parent() && !fromSendEvent) { + // Do not trust the position, query it instead. + xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(), +- m_screen->root(), 0, 0); ++ xcbscreen()->root(), 0, 0); + xcb_translate_coordinates_reply_t *reply = xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); + if (reply) { + pos.setX(reply->dst_x); +@@ -1888,8 +1888,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * + QWindowSystemInterface::handleGeometryChange(window(), rect); + + QPlatformScreen *newScreen = screenForNativeGeometry(nativeRect); +- if (newScreen != m_screen) { +- m_screen = static_cast(newScreen); ++ if (newScreen != screen()) { + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); + int newDpr = devicePixelRatio(); + if (newDpr != dpr) { +@@ -1933,7 +1932,7 @@ QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const + const int dpr = int(devicePixelRatio()); + QPoint ret; + xcb_translate_coordinates_cookie_t cookie = +- xcb_translate_coordinates(xcb_connection(), xcb_window(), m_screen->root(), ++ xcb_translate_coordinates(xcb_connection(), xcb_window(), xcbscreen()->root(), + pos.x() * dpr, pos.y() * dpr); + xcb_translate_coordinates_reply_t *reply = + xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); +@@ -1954,7 +1953,7 @@ QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const + const int dpr = int(devicePixelRatio()); + QPoint ret; + xcb_translate_coordinates_cookie_t cookie = +- xcb_translate_coordinates(xcb_connection(), m_screen->root(), xcb_window(), ++ xcb_translate_coordinates(xcb_connection(), xcbscreen()->root(), xcb_window(), + pos.x() *dpr, pos.y() * dpr); + xcb_translate_coordinates_reply_t *reply = + xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); +@@ -2178,8 +2177,8 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev + m_windowState = newState; + } + return; +- } else if (event->atom == atom(QXcbAtom::_NET_WORKAREA) && event->window == m_screen->root()) { +- m_screen->updateGeometry(event->time); ++ } else if (event->atom == atom(QXcbAtom::_NET_WORKAREA) && event->window == xcbscreen()->root()) { ++ xcbscreen()->updateGeometry(event->time); + } + } + +@@ -2308,7 +2307,7 @@ bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) + xev.data.data32[3] = XCB_BUTTON_INDEX_1; + xev.data.data32[4] = 0; + xcb_ungrab_pointer(connection()->xcb_connection(), XCB_CURRENT_TIME); +- xcb_send_event(connection()->xcb_connection(), false, m_screen->root(), ++ xcb_send_event(connection()->xcb_connection(), false, xcbscreen()->root(), + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, + (const char *)&xev); + return true; +@@ -2444,13 +2443,18 @@ void QXcbWindow::postSyncWindowRequest() + if (!m_pendingSyncRequest) { + QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this); + m_pendingSyncRequest = e; +- QCoreApplication::postEvent(m_screen->connection(), e); ++ QCoreApplication::postEvent(xcbscreen()->connection(), e); + } + } + + qreal QXcbWindow::devicePixelRatio() const + { +- return m_screen ? m_screen->devicePixelRatio() : 1.0; ++ return xcbscreen() ? xcbscreen()->devicePixelRatio() : 1.0; ++} ++ ++QXcbScreen *QXcbWindow::xcbscreen() const ++{ ++ return static_cast(screen()); + } + + QT_END_NAMESPACE +diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h +index 254421e..966a834 100644 +--- a/src/plugins/platforms/xcb/qxcbwindow.h ++++ b/src/plugins/platforms/xcb/qxcbwindow.h +@@ -152,6 +152,8 @@ public: + void postSyncWindowRequest(); + void clearSyncWindowRequest() { m_pendingSyncRequest = 0; } + ++ QXcbScreen *xcbscreen() const; ++ + qreal devicePixelRatio() const; + + QPlatformScreen *screenForNativeGeometry(const QRect &newGeometry) const; +@@ -188,8 +190,6 @@ private: + void doFocusIn(); + void doFocusOut(); + +- QXcbScreen *m_screen; +- + xcb_window_t m_window; + + uint m_depth;