Pull in set of upstream Qt 5.5 fixes and improvements for XCB screen handling rebased to 5.4
This commit is contained in:
parent
4aed2cfe1e
commit
bcc8b147be
|
@ -0,0 +1,313 @@
|
|||
commit 9b4fbe85d2e00c625c3d4abd975faf555000f685
|
||||
Author: Giulio Camuffo <giuliocamuffo@gmail.com>
|
||||
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 <jorgen.lind@theqtcompany.com>
|
||||
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
|
||||
|
||||
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<int> 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<QPlatformScreen *> mScreens;
|
||||
QList<QOpenWFDDevice *>mDevices;
|
||||
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<QXcbIntegration *>(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<QXcbIntegration *>(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)
|
|
@ -0,0 +1,201 @@
|
|||
commit df39295f23c7d9ead8481a95b9c78caaff1e8bc8
|
||||
Author: Sandro Mani <manisandro@gmail.com>
|
||||
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 <shawn.rutledge@digia.com>
|
||||
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
|
||||
|
||||
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<QWindowsIntegration *>(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<int> 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<QWindowsIntegrationPrivate> 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<QXcbIntegration *>(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<QXcbIntegration *>(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<QXcbWindow*>();
|
||||
#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<QXcbConnection *> 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<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration());
|
||||
+ QXcbIntegration* integration = QXcbIntegration::instance();
|
||||
QXcbConnection *defaultConnection = integration->defaultConnection();
|
||||
if (defaultConnection)
|
||||
return reinterpret_cast<void *>(const_cast<char *>(defaultConnection->startupId().constData()));
|
||||
@@ -368,7 +368,7 @@ void *QXcbNativeInterface::startupId()
|
||||
|
||||
void *QXcbNativeInterface::x11Screen()
|
||||
{
|
||||
- QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration());
|
||||
+ QXcbIntegration *integration = QXcbIntegration::instance();
|
||||
QXcbConnection *defaultConnection = integration->defaultConnection();
|
||||
if (defaultConnection)
|
||||
return reinterpret_cast<void *>(defaultConnection->primaryScreenNumber());
|
||||
@@ -377,7 +377,7 @@ void *QXcbNativeInterface::x11Screen()
|
||||
|
||||
void *QXcbNativeInterface::rootWindow()
|
||||
{
|
||||
- QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration());
|
||||
+ QXcbIntegration *integration = QXcbIntegration::instance();
|
||||
QXcbConnection *defaultConnection = integration->defaultConnection();
|
||||
if (defaultConnection)
|
||||
return reinterpret_cast<void *>(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<QXcbIntegration *>(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<QXcbIntegration *>(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),
|
|
@ -0,0 +1,190 @@
|
|||
commit 52f5e50f11a3ba82e32dc2efc656e4021a3fa4f5
|
||||
Author: Sandro Mani <manisandro@gmail.com>
|
||||
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 <jorgen.lind@theqtcompany.com>
|
||||
|
||||
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<int> QPlatformIntegration::possibleKeys(const QKeyEvent *) const
|
||||
|
||||
The screen should be deleted by calling QPlatformIntegration::destroyScreen().
|
||||
*/
|
||||
-void QPlatformIntegration::screenAdded(QPlatformScreen *ps)
|
||||
+void QPlatformIntegration::screenAdded(QPlatformScreen *ps, bool isPrimary)
|
||||
{
|
||||
QScreen *screen = new QScreen(ps);
|
||||
ps->d_func()->screen = screen;
|
||||
- QGuiApplicationPrivate::screen_list << screen;
|
||||
+ if (isPrimary) {
|
||||
+ QGuiApplicationPrivate::screen_list.prepend(screen);
|
||||
+ } else {
|
||||
+ QGuiApplicationPrivate::screen_list.append(screen);
|
||||
+ }
|
||||
emit qGuiApp->screenAdded(screen);
|
||||
}
|
||||
|
||||
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
|
||||
index 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<QXcbScreen *>& newScreens,
|
||||
void QXcbConnection::updateScreens()
|
||||
{
|
||||
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
|
||||
- int screenNumber = 0; // index of this QScreen in QGuiApplication::screens()
|
||||
int xcbScreenNumber = 0; // screen number in the xcb sense
|
||||
- QSet<QXcbScreen *> activeScreens;
|
||||
+ QList<QXcbScreen *> activeScreens;
|
||||
QList<QXcbScreen *> newScreens;
|
||||
QXcbScreen* primaryScreen = NULL;
|
||||
while (it.rem) {
|
||||
@@ -195,6 +194,7 @@ void QXcbConnection::updateScreens()
|
||||
xcb_screen_t *xcbScreen = it.data;
|
||||
QList<QPlatformScreen *> siblings;
|
||||
int outputCount = 0;
|
||||
+ int connectedOutputCount = 0;
|
||||
if (has_randr_extension) {
|
||||
xcb_generic_error_t *error = NULL;
|
||||
xcb_randr_get_output_primary_cookie_t primaryCookie =
|
||||
@@ -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<QXcbScreen*> screensToDelete;
|
||||
for (int i = m_screens.count() - 1; i >= 0; --i) {
|
||||
if (!activeScreens.contains(m_screens[i])) {
|
||||
- integration->destroyScreen(m_screens.at(i));
|
||||
- m_screens.removeAt(i);
|
||||
+ screensToDelete.append(m_screens.takeAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
- // Add any new screens, and make sure the primary screen comes first
|
||||
- // since it is used by QGuiApplication::primaryScreen()
|
||||
+ // If there is a new primary screen, add that one first
|
||||
+ if (newScreens.contains(primaryScreen)) {
|
||||
+ newScreens.removeOne(primaryScreen);
|
||||
+ m_screens.prepend(primaryScreen);
|
||||
+ integration->screenAdded(primaryScreen, true);
|
||||
+ }
|
||||
+
|
||||
+ // Add the remaining new screens
|
||||
foreach (QXcbScreen* screen, newScreens) {
|
||||
- if (screen == primaryScreen)
|
||||
- m_screens.prepend(screen);
|
||||
- else
|
||||
- m_screens.append(screen);
|
||||
+ m_screens.append(screen);
|
||||
+ integration->screenAdded(screen);
|
||||
}
|
||||
|
||||
- // Now that they are in the right order, emit the added signals for new screens only
|
||||
- foreach (QXcbScreen* screen, m_screens)
|
||||
- if (newScreens.contains(screen))
|
||||
- integration->screenAdded(screen);
|
||||
+ // Delete the old screens, now that the new ones were added
|
||||
+ // and we are sure that there is at least one screen available
|
||||
+ foreach (QXcbScreen* screen, screensToDelete) {
|
||||
+ integration->destroyScreen(screen);
|
||||
+ }
|
||||
+
|
||||
+ // Ensure that the primary screen is first in m_screens too
|
||||
+ // (in case the assignment of primary was the only change,
|
||||
+ // without adding or removing screens)
|
||||
+ if (primaryScreen) {
|
||||
+ Q_ASSERT(!m_screens.isEmpty());
|
||||
+ if (m_screens.first() != primaryScreen) {
|
||||
+ m_screens.removeOne(primaryScreen);
|
||||
+ m_screens.prepend(primaryScreen);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName)
|
|
@ -0,0 +1,250 @@
|
|||
commit bbdef3ca98ba78a829dc725ba67fe6d466e20f9c
|
||||
Author: Shawn Rutledge <shawn.rutledge@digia.com>
|
||||
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 <manisandro@gmail.com>
|
||||
Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
|
||||
Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com>
|
||||
|
||||
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<xcb_get_window_attributes_reply_t, QScopedPointerPodDeleter> 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
|
|
@ -0,0 +1,89 @@
|
|||
commit 51ada7734ad780178ecced11e0dff454dfc2e5f2
|
||||
Author: Shawn Rutledge <shawn.rutledge@digia.com>
|
||||
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 <laszlo.agocs@theqtcompany.com>
|
||||
Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com>
|
||||
|
||||
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
|
||||
*/
|
||||
|
|
@ -0,0 +1,713 @@
|
|||
commit 3b30a8215e98f6164a1650ce7c7e2a42a3d8746f
|
||||
Author: Daniel Vrátil <dvratil@redhat.com>
|
||||
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 <shawn.rutledge@digia.com>
|
||||
|
||||
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 <QAbstractEventDispatcher>
|
||||
#include <QTimer>
|
||||
#include <QByteArray>
|
||||
+#include <QScopedPointer>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -155,8 +156,29 @@ typedef struct {
|
||||
} QGLXBufferSwapComplete;
|
||||
#endif
|
||||
|
||||
-QXcbScreen* QXcbConnection::findOrCreateScreen(QList<QXcbScreen *>& 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<QXcbScreen *>& 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<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> 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<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> 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<QPlatformScreen*>(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<QXcbScreen *> activeScreens;
|
||||
- QList<QXcbScreen *> 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<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> 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<xcb_randr_get_screen_resources_reply_t, QScopedPointerPodDeleter> 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<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> 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<QXcbScreen*> 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 <xcb/xcb.h>
|
||||
+#include <xcb/randr.h>
|
||||
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
@@ -492,9 +493,15 @@ private:
|
||||
void initializeXShape();
|
||||
void initializeXKB();
|
||||
void handleClientMessageEvent(const xcb_client_message_event_t *event);
|
||||
- QXcbScreen* findOrCreateScreen(QList<QXcbScreen *>& 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<QPlatformScreen *> virtualSiblings() const { return m_siblings; }
|
||||
void setVirtualSiblings(QList<QPlatformScreen *> 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;
|
|
@ -0,0 +1,43 @@
|
|||
commit 4c022338aa787c216c3afa217987e4125bd15b41
|
||||
Author: Jan Kundrát <jkt@kde.org>
|
||||
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=<optimized out>)
|
||||
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=<optimized out>,
|
||||
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 <shawn.rutledge@digia.com>
|
||||
|
||||
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()
|
|
@ -0,0 +1,86 @@
|
|||
commit ebdf9916600f0b0cd4d25b538d1fd0fef6e89077
|
||||
Author: Shawn Rutledge <shawn.rutledge@digia.com>
|
||||
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 <psychon@znc.in>
|
||||
Reviewed-by: Gatis Paeglis <gatis.paeglis@digia.com>
|
||||
Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
|
||||
|
||||
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<QPlatformScreen *> 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<QPlatformScreen *>() << 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());
|
|
@ -37,7 +37,7 @@
|
|||
Summary: Qt5 - QtBase components
|
||||
Name: qt5-qtbase
|
||||
Version: 5.4.1
|
||||
Release: 3%{?dist}
|
||||
Release: 4%{?dist}
|
||||
|
||||
# See LGPL_EXCEPTIONS.txt, for exception details
|
||||
License: LGPLv2 with exceptions or GPLv3 with exceptions
|
||||
|
@ -82,15 +82,25 @@ 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 rebased on Qt 5.4.1 for better XCB screen integration
|
||||
# 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
|
||||
|
||||
|
||||
Patch272: 0072-CMake-Fix-QObject-connect-failing-on-ARM.patch
|
||||
Patch294: 0094-Fix-Meta-.-shortcuts-on-XCB.patch
|
||||
Patch332: 0132-Call-ofono-nm-Registered-delayed-in-constructor-othe.patch
|
||||
|
@ -336,12 +346,20 @@ 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
|
||||
|
||||
%patch272 -p1 -b .0072
|
||||
%patch294 -p1 -b .0094
|
||||
%patch332 -p1 -b .0132
|
||||
|
@ -857,6 +875,9 @@ fi
|
|||
|
||||
|
||||
%changelog
|
||||
* Wed Mar 25 2015 Daniel Vrátil <dvratil@redhat.com> - 5.4.1-4
|
||||
- pull in set of upstream Qt 5.5 fixes and improvements for XCB screen handling rebased to 5.4
|
||||
|
||||
* Fri Feb 27 2015 Rex Dieter <rdieter@fedoraproject.org> - 5.4.1-3
|
||||
- pull in handful of upstream fixes, particularly...
|
||||
- Fix a division by zero when processing malformed BMP files (QTBUG-44547, CVE-2015-0295)
|
||||
|
|
|
@ -1,600 +0,0 @@
|
|||
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<int> 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<QXcbClipboard *>(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<QXcbScreen *>& newScreens,
|
||||
void QXcbConnection::updateScreens()
|
||||
{
|
||||
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
|
||||
- int screenNumber = 0; // index of this QScreen in QGuiApplication::screens()
|
||||
int xcbScreenNumber = 0; // screen number in the xcb sense
|
||||
QSet<QXcbScreen *> activeScreens;
|
||||
QList<QXcbScreen *> newScreens;
|
||||
@@ -194,7 +193,7 @@ void QXcbConnection::updateScreens()
|
||||
// which will become virtual siblings.
|
||||
xcb_screen_t *xcbScreen = it.data;
|
||||
QList<QPlatformScreen *> 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<QXcbScreen*> 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<QXcbScreen *>(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<QXcbWindow *>(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<QXcbScreen *>(screen())->clientLeader();
|
||||
+ transientXcbParent = static_cast<QXcbScreen *>(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<QXcbScreen*>(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<QXcbScreen *>(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;
|
Loading…
Reference in New Issue