- Enable gold and remove reduced relocations - merges
This commit is contained in:
commit
df97d65ed7
58
0001-XCB-prevent-a-fp-division-by-zero.patch
Normal file
58
0001-XCB-prevent-a-fp-division-by-zero.patch
Normal file
@ -0,0 +1,58 @@
|
||||
From 40c927e7331ea4ac9ca50de48560b700e657cded Mon Sep 17 00:00:00 2001
|
||||
From: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
|
||||
Date: Tue, 8 Dec 2015 18:28:24 +0100
|
||||
Subject: [PATCH 01/12] XCB: prevent a fp division by zero
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
For certain devices vci->resolution is zero, which causes a SIGFPE
|
||||
if FE_INVALID exceptions are enabled. Try to prevent that.
|
||||
|
||||
Task-number: QTBUG-42717
|
||||
Change-Id: I388735f5dfb6218496787dbb74cf0c0f43cc928f
|
||||
Reviewed-by: Alexander Volkov <a.volkov@rusbitech.ru>
|
||||
Reviewed-by: Błażej Szczygieł <spaz16@wp.pl>
|
||||
Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com>
|
||||
---
|
||||
src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 11 +++++++----
|
||||
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
|
||||
index 8097cce..1a12370 100644
|
||||
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
|
||||
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
|
||||
@@ -406,6 +406,9 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
|
||||
#endif // XCB_USE_XINPUT22
|
||||
case XIValuatorClass: {
|
||||
XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
|
||||
+ // Some devices (mice) report a resolution of 0; they will be excluded later,
|
||||
+ // for now just prevent a division by zero
|
||||
+ const int vciResolution = vci->resolution ? vci->resolution : 1;
|
||||
if (vci->label == atom(QXcbAtom::AbsMTPositionX))
|
||||
caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition;
|
||||
else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor))
|
||||
@@ -414,16 +417,16 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
|
||||
caps |= QTouchDevice::Pressure;
|
||||
else if (vci->label == atom(QXcbAtom::RelX)) {
|
||||
hasRelativeCoords = true;
|
||||
- dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution);
|
||||
+ dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
|
||||
} else if (vci->label == atom(QXcbAtom::RelY)) {
|
||||
hasRelativeCoords = true;
|
||||
- dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
|
||||
+ dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
|
||||
} else if (vci->label == atom(QXcbAtom::AbsX)) {
|
||||
caps |= QTouchDevice::Position;
|
||||
- dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
|
||||
+ dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
|
||||
} else if (vci->label == atom(QXcbAtom::AbsY)) {
|
||||
caps |= QTouchDevice::Position;
|
||||
- dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution);
|
||||
+ dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
|
||||
}
|
||||
break;
|
||||
}
|
||||
--
|
||||
2.5.0
|
||||
|
@ -0,0 +1,86 @@
|
||||
From 56f6252e7285c9c61a99416fa2a8571fd67c597f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?=
|
||||
<tor.arne.vestbo@theqtcompany.com>
|
||||
Date: Tue, 1 Dec 2015 16:27:09 +0100
|
||||
Subject: [PATCH 02/12] xcb: compare to previous state when sending geometry
|
||||
and expose events
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
By calculating the previous geometry and passing it on when calling
|
||||
handleGeometryChange we can detect cases where setGeometry() on a
|
||||
QWindow didn't result in the expected geometry. The new (actual)
|
||||
geometry is delivered as a resize event.
|
||||
|
||||
This also allows us to only send expose events when the size of the
|
||||
window has actually changed (instead of also sending when the window
|
||||
has just moved).
|
||||
|
||||
Due to the async delivery of geometry changes on the xcb platform we
|
||||
need to avoid using QWindowPrivate's cached state of the geometry, as
|
||||
that will result in duplicate resize events when events are not flushed
|
||||
in between two system resize events coming in with the same size.
|
||||
|
||||
Change-Id: I3d4abe4a1095dd96e6e354288d5b646c623c30dd
|
||||
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>
|
||||
---
|
||||
src/plugins/platforms/xcb/qxcbwindow.cpp | 33 ++++++++++++++++++++++++++------
|
||||
1 file changed, 27 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||||
index 6023ee6..98bcc62 100644
|
||||
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||||
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||||
@@ -2007,21 +2007,42 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
|
||||
}
|
||||
}
|
||||
|
||||
- const QRect rect = QRect(pos, QSize(event->width, event->height));
|
||||
- QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(rect);
|
||||
+ // The original geometry requested by setGeometry() might be different
|
||||
+ // from what we end up with after applying window constraints.
|
||||
+ QRect requestedGeometry = geometry();
|
||||
+
|
||||
+ const QRect actualGeometry = QRect(pos, QSize(event->width, event->height));
|
||||
+ QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(actualGeometry);
|
||||
|
||||
QXcbScreen *currentScreen = m_xcbScreen;
|
||||
m_xcbScreen = static_cast<QXcbScreen*>(newScreen);
|
||||
if (!newScreen)
|
||||
return;
|
||||
|
||||
- QPlatformWindow::setGeometry(rect);
|
||||
- QWindowSystemInterface::handleGeometryChange(window(), rect);
|
||||
+ // Persist the actual geometry so that QWindow::geometry() can
|
||||
+ // be queried in the resize event.
|
||||
+ QPlatformWindow::setGeometry(actualGeometry);
|
||||
+
|
||||
+ // As we're delivering the geometry change through QPA in n async fashion we can't
|
||||
+ // pass on the current geometry of the QWindowPrivate, as that may have not been
|
||||
+ // updated yet by a geometry change that's still in the QPA event queue. Instead
|
||||
+ // we fall back to the default argument value of QRect(), which will result in
|
||||
+ // QGuiApplication looking up the previous geometry from QWindowPrivate, but this
|
||||
+ // time in sync with the even delivery/processing.
|
||||
+ QWindowSystemInterface::handleGeometryChange(window(), actualGeometry,
|
||||
+ requestedGeometry != actualGeometry ? requestedGeometry : QRect());
|
||||
+
|
||||
if (newScreen != currentScreen)
|
||||
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
|
||||
|
||||
- if (m_mapped)
|
||||
- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
|
||||
+ // For expose events we have no way of telling QGuiApplication to used the locally
|
||||
+ // cached version of the previous state, so we may in some situations end up with
|
||||
+ // an additional expose event.
|
||||
+ QRect previousGeometry = requestedGeometry != actualGeometry ?
|
||||
+ requestedGeometry : qt_window_private(window())->geometry;
|
||||
+
|
||||
+ if (m_mapped && actualGeometry.size() != previousGeometry.size())
|
||||
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), actualGeometry.size()));
|
||||
|
||||
if (m_usingSyncProtocol && m_syncState == SyncReceived)
|
||||
m_syncState = SyncAndConfigureReceived;
|
||||
--
|
||||
2.5.0
|
||||
|
116
0011-xcb-Don-t-cache-the-screen-for-a-window.patch
Normal file
116
0011-xcb-Don-t-cache-the-screen-for-a-window.patch
Normal file
@ -0,0 +1,116 @@
|
||||
From 0c33a823c560bdf18a513ae460eea4d7bdf9e115 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Volkov <a.volkov@rusbitech.ru>
|
||||
Date: Tue, 24 Nov 2015 15:09:41 +0300
|
||||
Subject: [PATCH 11/12] xcb: Don't cache the screen for a window
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
QXcbWindow::m_xcbScreen was introduced in 4e1b09fa8ff1a9ab42c0a29a2efe1ae7f4700d71
|
||||
(Keep screen geometries from overlapping) to map the window
|
||||
geometry for the right screen, because it wasn't possible to
|
||||
rely on QPlatformWindow::screen().
|
||||
|
||||
But we don't need it since a705b4ec1f6f7133390054f8b6b8077ef0550311
|
||||
(Introduce cross platform high-dpi scaling), because QGuiApplication
|
||||
triggers GeometryChangeEvent right after processing WindowScreenChangedEvent.
|
||||
|
||||
So just use QPlatformWindow::screen() instead of cached m_xcbScreen.
|
||||
|
||||
m_xcbScreen was also used in d4bc56cb4218f6f8378f04c23865156b349b037d
|
||||
(Fix screen detection on configureNotify) to compare the new screen
|
||||
after receiving ConfigureNotify to the correct old screen. Just send
|
||||
WindowScreenChangedEvent event and leave making the comparison to
|
||||
QGuiApplication.
|
||||
|
||||
Change-Id: Ibe717ae4bf4c40b0a04cd62fe2ecaee5df5f4060
|
||||
Reviewed-by: Błażej Szczygieł <spaz16@wp.pl>
|
||||
Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com>
|
||||
---
|
||||
src/plugins/platforms/xcb/qxcbwindow.cpp | 16 ++++++----------
|
||||
src/plugins/platforms/xcb/qxcbwindow.h | 2 --
|
||||
2 files changed, 6 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||||
index 98bcc62..6add0a6 100644
|
||||
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||||
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||||
@@ -143,7 +143,7 @@ const quint32 XEMBED_VERSION = 0;
|
||||
|
||||
QXcbScreen *QXcbWindow::parentScreen()
|
||||
{
|
||||
- return parent() ? static_cast<QXcbWindow*>(parent())->parentScreen() : m_xcbScreen;
|
||||
+ return parent() ? static_cast<QXcbWindow*>(parent())->parentScreen() : xcbScreen();
|
||||
}
|
||||
|
||||
// Returns \c true if we should set WM_TRANSIENT_FOR on \a w
|
||||
@@ -266,7 +266,6 @@ static const char *wm_window_type_property_id = "_q_xcb_wm_window_type";
|
||||
QXcbWindow::QXcbWindow(QWindow *window)
|
||||
: QPlatformWindow(window)
|
||||
, m_window(0)
|
||||
- , m_xcbScreen(0)
|
||||
, m_syncCounter(0)
|
||||
, m_gravity(XCB_GRAVITY_STATIC)
|
||||
, m_mapped(false)
|
||||
@@ -322,7 +321,6 @@ void QXcbWindow::create()
|
||||
QRect rect = windowGeometry();
|
||||
QXcbScreen *platformScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
|
||||
|
||||
- m_xcbScreen = platformScreen;
|
||||
if (type == Qt::Desktop) {
|
||||
m_window = platformScreen->root();
|
||||
m_depth = platformScreen->screen()->root_depth;
|
||||
@@ -638,13 +636,12 @@ void QXcbWindow::setGeometry(const QRect &rect)
|
||||
|
||||
propagateSizeHints();
|
||||
|
||||
- QXcbScreen *currentScreen = m_xcbScreen;
|
||||
+ QXcbScreen *currentScreen = xcbScreen();
|
||||
QXcbScreen *newScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
|
||||
|
||||
if (!newScreen)
|
||||
newScreen = xcbScreen();
|
||||
|
||||
- m_xcbScreen = newScreen;
|
||||
const QRect wmGeometry = windowToWmGeometry(rect);
|
||||
|
||||
if (newScreen && newScreen != currentScreen)
|
||||
@@ -2013,9 +2010,6 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
|
||||
|
||||
const QRect actualGeometry = QRect(pos, QSize(event->width, event->height));
|
||||
QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(actualGeometry);
|
||||
-
|
||||
- QXcbScreen *currentScreen = m_xcbScreen;
|
||||
- m_xcbScreen = static_cast<QXcbScreen*>(newScreen);
|
||||
if (!newScreen)
|
||||
return;
|
||||
|
||||
@@ -2032,8 +2026,10 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
|
||||
QWindowSystemInterface::handleGeometryChange(window(), actualGeometry,
|
||||
requestedGeometry != actualGeometry ? requestedGeometry : QRect());
|
||||
|
||||
- if (newScreen != currentScreen)
|
||||
- QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
|
||||
+ // QPlatformScreen::screen() is updated asynchronously, so we can't compare it
|
||||
+ // with the newScreen. Just send the WindowScreenChanged event and QGuiApplication
|
||||
+ // will make the comparison later.
|
||||
+ QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
|
||||
|
||||
// For expose events we have no way of telling QGuiApplication to used the locally
|
||||
// cached version of the previous state, so we may in some situations end up with
|
||||
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
|
||||
index 43e66a7..0d14673 100644
|
||||
--- a/src/plugins/platforms/xcb/qxcbwindow.h
|
||||
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
|
||||
@@ -214,8 +214,6 @@ protected:
|
||||
|
||||
xcb_window_t m_window;
|
||||
|
||||
- QXcbScreen *m_xcbScreen;
|
||||
-
|
||||
uint m_depth;
|
||||
QImage::Format m_imageFormat;
|
||||
bool m_imageRgbSwap;
|
||||
--
|
||||
2.5.0
|
||||
|
721
0012-xcb-Use-a-placeholder-QScreen-when-there-are-no-outp.patch
Normal file
721
0012-xcb-Use-a-placeholder-QScreen-when-there-are-no-outp.patch
Normal file
@ -0,0 +1,721 @@
|
||||
From a094af001795c9651b299d700a992150d1aba33a Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= <spaz16@wp.pl>
|
||||
Date: Fri, 16 Oct 2015 22:51:59 +0200
|
||||
Subject: [PATCH 12/12] xcb: Use a placeholder QScreen when there are no
|
||||
outputs connected
|
||||
|
||||
If no screens are available, windows could disappear, could stop rendering
|
||||
graphics, or the application could crash. This is a real use case in several
|
||||
scenarios: with x11vnc, when all monitors are physically disconnected from a
|
||||
desktop machine, or in some cases even when the monitor sleeps. Now when the
|
||||
last screen is disconnected, it is transformed into a fake screen. When a
|
||||
physical screen appears, the fake QScreen is transformed into a representation
|
||||
of the physical screen. Every virtual desktop has its own fake screen, and
|
||||
primary screens must belong to the primary virtual desktop. It fixes updating
|
||||
screen geometry on temporarily disabled screens in the middle of the mode
|
||||
switch.
|
||||
|
||||
Expected results: Windows don't disappear, the application doesn't
|
||||
crash, and QMenu is displayed on the appropriate screen.
|
||||
|
||||
This reverts patch 51ada7734ad780178ecced11e0dff454dfc2e5f2
|
||||
|
||||
Change-Id: I6e8eb682b0c8425d08ffdaecbd4c6c7700c914b4
|
||||
Task-number: QTBUG-42985
|
||||
Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com>
|
||||
---
|
||||
src/gui/kernel/qscreen.cpp | 4 +-
|
||||
src/plugins/platforms/xcb/qxcbconnection.cpp | 273 +++++++++++++++------------
|
||||
src/plugins/platforms/xcb/qxcbconnection.h | 10 +-
|
||||
src/plugins/platforms/xcb/qxcbscreen.cpp | 49 +++--
|
||||
src/plugins/platforms/xcb/qxcbscreen.h | 10 +-
|
||||
src/plugins/platforms/xcb/qxcbwindow.cpp | 38 +---
|
||||
src/plugins/platforms/xcb/qxcbwindow.h | 1 -
|
||||
7 files changed, 212 insertions(+), 173 deletions(-)
|
||||
|
||||
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp
|
||||
index fb322ae..52e7686 100644
|
||||
--- a/src/gui/kernel/qscreen.cpp
|
||||
+++ b/src/gui/kernel/qscreen.cpp
|
||||
@@ -116,8 +116,8 @@ QScreen::~QScreen()
|
||||
bool movingFromVirtualSibling = primaryScreen && primaryScreen->handle()->virtualSiblings().contains(handle());
|
||||
|
||||
// Move any leftover windows to the primary screen
|
||||
- foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
|
||||
- if (window->screen() != this)
|
||||
+ foreach (QWindow *window, QGuiApplication::allWindows()) {
|
||||
+ if (!window->isTopLevel() || window->screen() != this)
|
||||
continue;
|
||||
|
||||
const bool wasVisible = window->isVisible();
|
||||
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
|
||||
index 50d49ca..231fe9a 100644
|
||||
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
|
||||
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
|
||||
@@ -179,42 +179,6 @@ QXcbScreen* QXcbConnection::findScreenForOutput(xcb_window_t rootWindow, xcb_ran
|
||||
return 0;
|
||||
}
|
||||
|
||||
-QXcbScreen* QXcbConnection::createScreen(QXcbVirtualDesktop* virtualDesktop,
|
||||
- xcb_randr_output_t outputId,
|
||||
- xcb_randr_get_output_info_reply_t *output)
|
||||
-{
|
||||
- QString name;
|
||||
- if (output)
|
||||
- name = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output),
|
||||
- xcb_randr_get_output_info_name_length(output));
|
||||
- else {
|
||||
- QByteArray displayName = m_displayName;
|
||||
- int dotPos = displayName.lastIndexOf('.');
|
||||
- if (dotPos != -1)
|
||||
- displayName.truncate(dotPos);
|
||||
- name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + QString::number(virtualDesktop->number());
|
||||
- }
|
||||
-
|
||||
- return new QXcbScreen(this, virtualDesktop, outputId, output, name);
|
||||
-}
|
||||
-
|
||||
-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;
|
||||
-}
|
||||
-
|
||||
QXcbVirtualDesktop* QXcbConnection::virtualDesktopForRootWindow(xcb_window_t rootWindow)
|
||||
{
|
||||
foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops) {
|
||||
@@ -237,8 +201,9 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
|
||||
// Not for us
|
||||
return;
|
||||
|
||||
- qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc;
|
||||
QXcbScreen *screen = findScreenForCrtc(crtc.window, crtc.crtc);
|
||||
+ qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc
|
||||
+ << "mode" << crtc.mode << "relevant screen" << screen;
|
||||
// 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.
|
||||
@@ -260,16 +225,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
|
||||
|
||||
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);
|
||||
- virtualDesktop->removeScreen(screen);
|
||||
-
|
||||
- QXcbIntegration::instance()->destroyScreen(screen);
|
||||
-
|
||||
- // QTBUG-40174, QTBUG-42985: If all screens are removed, wait
|
||||
- // and start rendering again later if a screen becomes available.
|
||||
-
|
||||
+ destroyScreen(screen);
|
||||
} 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) {
|
||||
@@ -278,59 +234,142 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
|
||||
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo(
|
||||
xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL));
|
||||
|
||||
- screen = createScreen(virtualDesktop, output.output, outputInfo.data());
|
||||
- qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
|
||||
-
|
||||
- screen->setPrimary(checkOutputIsPrimary(output.window, output.output));
|
||||
- virtualDesktop->addScreen(screen);
|
||||
- m_screens << screen;
|
||||
- QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
|
||||
+ // Find a fake screen
|
||||
+ foreach (QPlatformScreen *scr, virtualDesktop->screens()) {
|
||||
+ QXcbScreen *xcbScreen = (QXcbScreen *)scr;
|
||||
+ if (xcbScreen->output() == XCB_NONE) {
|
||||
+ screen = xcbScreen;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- // Windows which had null screens have already had expose events by now.
|
||||
- // They need to be told the screen is back, it's OK to render.
|
||||
- foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
|
||||
- QXcbWindow *xcbWin = static_cast<QXcbWindow*>(window->handle());
|
||||
- if (xcbWin)
|
||||
- xcbWin->maybeSetScreen(screen);
|
||||
+ if (screen) {
|
||||
+ QString nameWas = screen->name();
|
||||
+ // Transform the fake screen into a physical screen
|
||||
+ screen->setOutput(output.output, outputInfo.data());
|
||||
+ updateScreen(screen, output);
|
||||
+ qCDebug(lcQpaScreen) << "output" << screen->name()
|
||||
+ << "is connected and enabled; was fake:" << nameWas;
|
||||
+ } else {
|
||||
+ screen = createScreen(virtualDesktop, output, outputInfo.data());
|
||||
+ qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
|
||||
}
|
||||
}
|
||||
- // else ignore disabled screens
|
||||
} else if (screen) {
|
||||
- // Screen has been disabled -> remove
|
||||
if (output.crtc == XCB_NONE && output.mode == XCB_NONE) {
|
||||
+ // Screen has been disabled
|
||||
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));
|
||||
if (outputInfo->crtc == XCB_NONE) {
|
||||
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled";
|
||||
- m_screens.removeOne(screen);
|
||||
- virtualDesktop->removeScreen(screen);
|
||||
- QXcbIntegration::instance()->destroyScreen(screen);
|
||||
+ destroyScreen(screen);
|
||||
} else {
|
||||
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been temporarily disabled for the mode switch";
|
||||
+ // Reset crtc to skip RRCrtcChangeNotify events,
|
||||
+ // because they may be invalid in the middle of the mode switch
|
||||
+ screen->setCrtc(XCB_NONE);
|
||||
}
|
||||
} 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
|
||||
- if (!wasPrimary && screen->isPrimary()) {
|
||||
- const int idx = m_screens.indexOf(screen);
|
||||
- m_screens.swap(0, idx);
|
||||
- QXcbIntegration::instance()->setPrimaryScreen(screen);
|
||||
- }
|
||||
+ updateScreen(screen, output);
|
||||
qCDebug(lcQpaScreen) << "output has changed" << screen;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+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;
|
||||
+}
|
||||
+
|
||||
+void QXcbConnection::updateScreen(QXcbScreen *screen, const xcb_randr_output_change_t &outputChange)
|
||||
+{
|
||||
+ screen->setCrtc(outputChange.crtc); // Set the new crtc, because it can be invalid
|
||||
+ screen->updateGeometry(outputChange.config_timestamp);
|
||||
+ if (screen->mode() != outputChange.mode)
|
||||
+ screen->updateRefreshRate(outputChange.mode);
|
||||
+ // Only screen which belongs to the primary virtual desktop can be a primary screen
|
||||
+ if (screen->screenNumber() == m_primaryScreenNumber) {
|
||||
+ if (!screen->isPrimary() && checkOutputIsPrimary(outputChange.window, outputChange.output)) {
|
||||
+ screen->setPrimary(true);
|
||||
+
|
||||
+ // If the screen became primary, reshuffle the order in QGuiApplicationPrivate
|
||||
+ const int idx = m_screens.indexOf(screen);
|
||||
+ if (idx > 0) {
|
||||
+ m_screens.first()->setPrimary(false);
|
||||
+ m_screens.swap(0, idx);
|
||||
+ }
|
||||
+ screen->virtualDesktop()->setPrimaryScreen(screen);
|
||||
+ QXcbIntegration::instance()->setPrimaryScreen(screen);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+QXcbScreen *QXcbConnection::createScreen(QXcbVirtualDesktop *virtualDesktop,
|
||||
+ const xcb_randr_output_change_t &outputChange,
|
||||
+ xcb_randr_get_output_info_reply_t *outputInfo)
|
||||
+{
|
||||
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputChange.output, outputInfo);
|
||||
+ // Only screen which belongs to the primary virtual desktop can be a primary screen
|
||||
+ if (screen->screenNumber() == m_primaryScreenNumber)
|
||||
+ screen->setPrimary(checkOutputIsPrimary(outputChange.window, outputChange.output));
|
||||
+
|
||||
+ if (screen->isPrimary()) {
|
||||
if (!m_screens.isEmpty())
|
||||
- qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
|
||||
- else
|
||||
- qCDebug(lcQpaScreen) << "no outputs";
|
||||
+ m_screens.first()->setPrimary(false);
|
||||
+
|
||||
+ m_screens.prepend(screen);
|
||||
+ } else {
|
||||
+ m_screens.append(screen);
|
||||
+ }
|
||||
+ virtualDesktop->addScreen(screen);
|
||||
+ QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
|
||||
+
|
||||
+ return screen;
|
||||
+}
|
||||
+
|
||||
+void QXcbConnection::destroyScreen(QXcbScreen *screen)
|
||||
+{
|
||||
+ QXcbVirtualDesktop *virtualDesktop = screen->virtualDesktop();
|
||||
+ if (virtualDesktop->screens().count() == 1) {
|
||||
+ // If there are no other screens on the same virtual desktop,
|
||||
+ // then transform the physical screen into a fake screen.
|
||||
+ const QString nameWas = screen->name();
|
||||
+ screen->setOutput(XCB_NONE, Q_NULLPTR);
|
||||
+ qCDebug(lcQpaScreen) << "transformed" << nameWas << "to fake" << screen;
|
||||
+ } else {
|
||||
+ // There is more than one screen on the same virtual desktop, remove the screen
|
||||
+ m_screens.removeOne(screen);
|
||||
+ virtualDesktop->removeScreen(screen);
|
||||
+
|
||||
+ // When primary screen is removed, set the new primary screen
|
||||
+ // which belongs to the primary virtual desktop.
|
||||
+ if (screen->isPrimary()) {
|
||||
+ QXcbScreen *newPrimary = (QXcbScreen *)virtualDesktop->screens().at(0);
|
||||
+ newPrimary->setPrimary(true);
|
||||
+ const int idx = m_screens.indexOf(newPrimary);
|
||||
+ if (idx > 0)
|
||||
+ m_screens.swap(0, idx);
|
||||
+ QXcbIntegration::instance()->setPrimaryScreen(newPrimary);
|
||||
+ }
|
||||
+
|
||||
+ QXcbIntegration::instance()->destroyScreen(screen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,8 +377,7 @@ 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 = Q_NULLPTR;
|
||||
- bool hasOutputs = false;
|
||||
+ QXcbScreen *primaryScreen = Q_NULLPTR;
|
||||
while (it.rem) {
|
||||
// Each "screen" in xcb terminology is a virtual desktop,
|
||||
// potentially a collection of separate juxtaposed monitors.
|
||||
@@ -348,8 +386,6 @@ void QXcbConnection::initializeScreens()
|
||||
xcb_screen_t *xcbScreen = it.data;
|
||||
QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
|
||||
m_virtualDesktops.append(virtualDesktop);
|
||||
- QList<QPlatformScreen *> siblings;
|
||||
- int outputCount = 0;
|
||||
if (has_randr_extension) {
|
||||
xcb_generic_error_t *error = NULL;
|
||||
// RRGetScreenResourcesCurrent is fast but it may return nothing if the
|
||||
@@ -366,7 +402,7 @@ void QXcbConnection::initializeScreens()
|
||||
} else {
|
||||
xcb_timestamp_t timestamp;
|
||||
xcb_randr_output_t *outputs = Q_NULLPTR;
|
||||
- outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data());
|
||||
+ int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data());
|
||||
if (outputCount) {
|
||||
timestamp = resources_current->config_timestamp;
|
||||
outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.data());
|
||||
@@ -393,6 +429,7 @@ void QXcbConnection::initializeScreens()
|
||||
qWarning("failed to get the primary output of the screen");
|
||||
free(error);
|
||||
} else {
|
||||
+ QList<QPlatformScreen *> siblings;
|
||||
for (int i = 0; i < outputCount; i++) {
|
||||
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> output(
|
||||
xcb_randr_get_output_info_reply(xcb_connection(),
|
||||
@@ -416,9 +453,8 @@ void QXcbConnection::initializeScreens()
|
||||
continue;
|
||||
}
|
||||
|
||||
- QXcbScreen *screen = createScreen(virtualDesktop, outputs[i], output.data());
|
||||
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputs[i], output.data());
|
||||
siblings << screen;
|
||||
- hasOutputs = true;
|
||||
m_screens << screen;
|
||||
|
||||
// There can be multiple outputs per screen, use either
|
||||
@@ -435,11 +471,23 @@ void QXcbConnection::initializeScreens()
|
||||
}
|
||||
}
|
||||
}
|
||||
+ virtualDesktop->setScreens(siblings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
- virtualDesktop->setScreens(siblings);
|
||||
+ if (virtualDesktop->screens().isEmpty()) {
|
||||
+ // If there are no XRandR outputs or XRandR extension is missing,
|
||||
+ // then create a fake/legacy screen.
|
||||
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, XCB_NONE, Q_NULLPTR);
|
||||
+ qCDebug(lcQpaScreen) << "created fake screen" << screen;
|
||||
+ m_screens << screen;
|
||||
+ if (m_primaryScreenNumber == xcbScreenNumber) {
|
||||
+ primaryScreen = screen;
|
||||
+ primaryScreen->setPrimary(true);
|
||||
+ }
|
||||
+ virtualDesktop->addScreen(screen);
|
||||
+ }
|
||||
xcb_screen_next(&it);
|
||||
++xcbScreenNumber;
|
||||
} // for each xcb screen
|
||||
@@ -447,39 +495,25 @@ void QXcbConnection::initializeScreens()
|
||||
foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops)
|
||||
virtualDesktop->subscribeToXFixesSelectionNotify();
|
||||
|
||||
- // 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)
|
||||
- QXcbVirtualDesktop *virtualDesktop = m_virtualDesktops.value(0);
|
||||
- if (virtualDesktop && !hasOutputs && !virtualDesktop->size().isEmpty() && m_screens.isEmpty()) {
|
||||
- QXcbScreen *screen = createScreen(virtualDesktop, 0, Q_NULLPTR);
|
||||
- virtualDesktop->setScreens(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());
|
||||
- if (m_screens.first() != primaryScreen) {
|
||||
- m_screens.removeOne(primaryScreen);
|
||||
- m_screens.prepend(primaryScreen);
|
||||
+ if (m_virtualDesktops.isEmpty()) {
|
||||
+ qFatal("QXcbConnection: no screens available");
|
||||
+ } else {
|
||||
+ // Ensure the primary screen is first on the list
|
||||
+ if (primaryScreen) {
|
||||
+ if (m_screens.first() != primaryScreen) {
|
||||
+ m_screens.removeOne(primaryScreen);
|
||||
+ m_screens.prepend(primaryScreen);
|
||||
+ }
|
||||
}
|
||||
- }
|
||||
|
||||
- // 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());
|
||||
- }
|
||||
+ // Push the screens to QGuiApplication
|
||||
+ foreach (QXcbScreen *screen, m_screens) {
|
||||
+ qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")";
|
||||
+ QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
|
||||
+ }
|
||||
|
||||
- if (!m_screens.isEmpty())
|
||||
qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
|
||||
+ }
|
||||
}
|
||||
|
||||
QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName)
|
||||
@@ -553,9 +587,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
|
||||
initializeXFixes();
|
||||
initializeScreens();
|
||||
|
||||
- if (m_screens.isEmpty())
|
||||
- qFatal("QXcbConnection: no screens available");
|
||||
-
|
||||
initializeXRender();
|
||||
m_xi2Enabled = false;
|
||||
#if defined(XCB_USE_XINPUT2)
|
||||
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
|
||||
index 3c82170..fb7cc13 100644
|
||||
--- a/src/plugins/platforms/xcb/qxcbconnection.h
|
||||
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
|
||||
@@ -518,15 +518,17 @@ private:
|
||||
void initializeXShape();
|
||||
void initializeXKB();
|
||||
void handleClientMessageEvent(const xcb_client_message_event_t *event);
|
||||
- QXcbScreen* createScreen(QXcbVirtualDesktop *virtualDesktop,
|
||||
- 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);
|
||||
QXcbVirtualDesktop* virtualDesktopForRootWindow(xcb_window_t rootWindow);
|
||||
+ void updateScreens(const xcb_randr_notify_event_t *event);
|
||||
bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output);
|
||||
+ void updateScreen(QXcbScreen *screen, const xcb_randr_output_change_t &outputChange);
|
||||
+ QXcbScreen *createScreen(QXcbVirtualDesktop *virtualDesktop,
|
||||
+ const xcb_randr_output_change_t &outputChange,
|
||||
+ xcb_randr_get_output_info_reply_t *outputInfo);
|
||||
+ void destroyScreen(QXcbScreen *screen);
|
||||
void initializeScreens();
|
||||
- void updateScreens(const xcb_randr_notify_event_t *event);
|
||||
bool compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const;
|
||||
|
||||
bool m_xi2Enabled;
|
||||
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
|
||||
index 0e99d58..f05432e 100644
|
||||
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
|
||||
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
|
||||
@@ -81,6 +81,13 @@ void QXcbVirtualDesktop::addScreen(QPlatformScreen *s)
|
||||
((QXcbScreen *) s)->isPrimary() ? m_screens.prepend(s) : m_screens.append(s);
|
||||
}
|
||||
|
||||
+void QXcbVirtualDesktop::setPrimaryScreen(QPlatformScreen *s)
|
||||
+{
|
||||
+ const int idx = m_screens.indexOf(s);
|
||||
+ Q_ASSERT(idx > -1);
|
||||
+ m_screens.swap(0, idx);
|
||||
+}
|
||||
+
|
||||
QXcbXSettings *QXcbVirtualDesktop::xSettings() const
|
||||
{
|
||||
if (!m_xSettings) {
|
||||
@@ -149,16 +156,15 @@ void QXcbVirtualDesktop::updateWorkArea()
|
||||
}
|
||||
|
||||
QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
|
||||
- xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
|
||||
- QString outputName)
|
||||
+ xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output)
|
||||
: QXcbObject(connection)
|
||||
, m_virtualDesktop(virtualDesktop)
|
||||
, m_output(outputId)
|
||||
- , m_crtc(output ? output->crtc : 0)
|
||||
+ , m_crtc(output ? output->crtc : XCB_NONE)
|
||||
, m_mode(XCB_NONE)
|
||||
, m_primary(false)
|
||||
, m_rotation(XCB_RANDR_ROTATION_ROTATE_0)
|
||||
- , m_outputName(outputName)
|
||||
+ , m_outputName(getOutputName(output))
|
||||
, m_outputSizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize())
|
||||
, m_virtualSize(virtualDesktop->size())
|
||||
, m_virtualSizeMillimeters(virtualDesktop->physicalSize())
|
||||
@@ -268,6 +274,22 @@ QXcbScreen::~QXcbScreen()
|
||||
delete m_cursor;
|
||||
}
|
||||
|
||||
+QString QXcbScreen::getOutputName(xcb_randr_get_output_info_reply_t *outputInfo)
|
||||
+{
|
||||
+ QString name;
|
||||
+ if (outputInfo) {
|
||||
+ name = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(outputInfo),
|
||||
+ xcb_randr_get_output_info_name_length(outputInfo));
|
||||
+ } else {
|
||||
+ QByteArray displayName = connection()->displayName();
|
||||
+ int dotPos = displayName.lastIndexOf('.');
|
||||
+ if (dotPos != -1)
|
||||
+ displayName.truncate(dotPos);
|
||||
+ name = QString::fromLocal8Bit(displayName) + QLatin1Char('.')
|
||||
+ + QString::number(m_virtualDesktop->number());
|
||||
+ }
|
||||
+ return name;
|
||||
+}
|
||||
|
||||
QWindow *QXcbScreen::topLevelAt(const QPoint &p) const
|
||||
{
|
||||
@@ -392,6 +414,16 @@ QPlatformCursor *QXcbScreen::cursor() const
|
||||
return m_cursor;
|
||||
}
|
||||
|
||||
+void QXcbScreen::setOutput(xcb_randr_output_t outputId,
|
||||
+ xcb_randr_get_output_info_reply_t *outputInfo)
|
||||
+{
|
||||
+ m_output = outputId;
|
||||
+ m_crtc = outputInfo ? outputInfo->crtc : XCB_NONE;
|
||||
+ m_mode = XCB_NONE;
|
||||
+ m_outputName = getOutputName(outputInfo);
|
||||
+ // TODO: Send an event to the QScreen instance that the screen changed its name
|
||||
+}
|
||||
+
|
||||
/*!
|
||||
\brief handle the XCB screen change event and update properties
|
||||
|
||||
@@ -460,19 +492,10 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan
|
||||
|
||||
updateGeometry(change_event->timestamp);
|
||||
|
||||
- QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
|
||||
QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), m_orientation);
|
||||
|
||||
QDpi ldpi = logicalDpi();
|
||||
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QPlatformScreen::screen(), ldpi.first, ldpi.second);
|
||||
-
|
||||
- // Windows which had null screens have already had expose events by now.
|
||||
- // They need to be told the screen is back, it's OK to render.
|
||||
- foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
|
||||
- QXcbWindow *xcbWin = static_cast<QXcbWindow*>(window->handle());
|
||||
- if (xcbWin)
|
||||
- xcbWin->maybeSetScreen(this);
|
||||
- }
|
||||
}
|
||||
|
||||
void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)
|
||||
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
|
||||
index c68c290..79620f4 100644
|
||||
--- a/src/plugins/platforms/xcb/qxcbscreen.h
|
||||
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
|
||||
@@ -72,6 +72,7 @@ public:
|
||||
void setScreens(QList<QPlatformScreen *> sl) { m_screens = sl; }
|
||||
void removeScreen(QPlatformScreen *s) { m_screens.removeOne(s); }
|
||||
void addScreen(QPlatformScreen *s);
|
||||
+ void setPrimaryScreen(QPlatformScreen *s);
|
||||
|
||||
QXcbXSettings *xSettings() const;
|
||||
|
||||
@@ -101,10 +102,11 @@ class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen
|
||||
{
|
||||
public:
|
||||
QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
|
||||
- xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
|
||||
- QString outputName);
|
||||
+ xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *outputInfo);
|
||||
~QXcbScreen();
|
||||
|
||||
+ QString getOutputName(xcb_randr_get_output_info_reply_t *outputInfo);
|
||||
+
|
||||
QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
|
||||
|
||||
QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE;
|
||||
@@ -137,6 +139,10 @@ public:
|
||||
xcb_randr_crtc_t crtc() const { return m_crtc; }
|
||||
xcb_randr_mode_t mode() const { return m_mode; }
|
||||
|
||||
+ void setOutput(xcb_randr_output_t outputId,
|
||||
+ xcb_randr_get_output_info_reply_t *outputInfo);
|
||||
+ void setCrtc(xcb_randr_crtc_t crtc) { m_crtc = crtc; }
|
||||
+
|
||||
void windowShown(QXcbWindow *window);
|
||||
QString windowManagerName() const { return m_windowManagerName; }
|
||||
bool syncRequestSupported() const { return m_syncRequestSupported; }
|
||||
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||||
index 6add0a6..bdbb9e9 100644
|
||||
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||||
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||||
@@ -622,14 +622,6 @@ void QXcbWindow::destroy()
|
||||
m_pendingSyncRequest->invalidate();
|
||||
}
|
||||
|
||||
-void QXcbWindow::maybeSetScreen(QXcbScreen *screen)
|
||||
-{
|
||||
- if (!window()->screen() && screen->geometry().contains(geometry().topLeft())) {
|
||||
- QWindowSystemInterface::handleWindowScreenChanged(window(), static_cast<QPlatformScreen *>(screen)->screen());
|
||||
- QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(0, 0), window()->size())));
|
||||
- }
|
||||
-}
|
||||
-
|
||||
void QXcbWindow::setGeometry(const QRect &rect)
|
||||
{
|
||||
QPlatformWindow::setGeometry(rect);
|
||||
@@ -845,15 +837,13 @@ void QXcbWindow::hide()
|
||||
Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window));
|
||||
|
||||
// send synthetic UnmapNotify event according to icccm 4.1.4
|
||||
- if (xcbScreen()) {
|
||||
- xcb_unmap_notify_event_t event;
|
||||
- event.response_type = XCB_UNMAP_NOTIFY;
|
||||
- event.event = xcbScreen()->root();
|
||||
- event.window = m_window;
|
||||
- event.from_configure = false;
|
||||
- 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_unmap_notify_event_t event;
|
||||
+ event.response_type = XCB_UNMAP_NOTIFY;
|
||||
+ event.event = xcbScreen()->root();
|
||||
+ event.window = m_window;
|
||||
+ event.from_configure = false;
|
||||
+ 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());
|
||||
|
||||
@@ -1181,8 +1171,6 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
|
||||
event.data.data32[3] = 0;
|
||||
event.data.data32[4] = 0;
|
||||
|
||||
- if (!xcbScreen())
|
||||
- return;
|
||||
Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
|
||||
}
|
||||
|
||||
@@ -1435,8 +1423,6 @@ void QXcbWindow::setParent(const QPlatformWindow *parent)
|
||||
xcb_parent_id = qXcbParent->xcb_window();
|
||||
m_embedded = qXcbParent->window()->type() == Qt::ForeignWindow;
|
||||
} else {
|
||||
- if (!xcbScreen())
|
||||
- return;
|
||||
xcb_parent_id = xcbScreen()->root();
|
||||
m_embedded = false;
|
||||
}
|
||||
@@ -1992,7 +1978,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
|
||||
{
|
||||
bool fromSendEvent = (event->response_type & 0x80);
|
||||
QPoint pos(event->x, event->y);
|
||||
- if (!parent() && !fromSendEvent && xcbScreen()) {
|
||||
+ if (!parent() && !fromSendEvent) {
|
||||
// Do not trust the position, query it instead.
|
||||
xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(),
|
||||
xcbScreen()->root(), 0, 0);
|
||||
@@ -2305,8 +2291,6 @@ void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
|
||||
return;
|
||||
|
||||
const QPoint local(event->event_x, event->event_y);
|
||||
- if (!xcbScreen())
|
||||
- return;
|
||||
QPoint global = QPoint(event->root_x, event->root_y);
|
||||
QWindowSystemInterface::handleEnterEvent(window(), local, global);
|
||||
}
|
||||
@@ -2324,8 +2308,6 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
|
||||
|
||||
if (enterWindow) {
|
||||
QPoint local(enter->event_x, enter->event_y);
|
||||
- if (!xcbScreen())
|
||||
- return;
|
||||
QPoint global = QPoint(event->root_x, event->root_y);
|
||||
|
||||
QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global);
|
||||
@@ -2341,8 +2323,6 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
|
||||
connection()->setTime(event->time);
|
||||
|
||||
const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE;
|
||||
- if (!xcbScreen())
|
||||
- return;
|
||||
|
||||
if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) {
|
||||
if (propertyDeleted)
|
||||
@@ -2662,8 +2642,6 @@ bool QXcbWindow::needsSync() const
|
||||
|
||||
void QXcbWindow::postSyncWindowRequest()
|
||||
{
|
||||
- if (!xcbScreen())
|
||||
- return;
|
||||
if (!m_pendingSyncRequest) {
|
||||
QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this);
|
||||
m_pendingSyncRequest = e;
|
||||
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
|
||||
index 0d14673..69c0819 100644
|
||||
--- a/src/plugins/platforms/xcb/qxcbwindow.h
|
||||
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
|
||||
@@ -167,7 +167,6 @@ public:
|
||||
|
||||
virtual void create();
|
||||
virtual void destroy();
|
||||
- void maybeSetScreen(QXcbScreen *screen);
|
||||
QXcbScreen *screenForNativeGeometry(const QRect &newGeometry) const;
|
||||
|
||||
public Q_SLOTS:
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,56 +0,0 @@
|
||||
From ae51e360f986698eaf41fdb38f8a878a50f69be1 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Volkov <a.volkov@rusbitech.ru>
|
||||
Date: Fri, 19 Jun 2015 13:34:11 +0300
|
||||
Subject: [PATCH 197/412] xcb: Ignore disabling of outputs in the middle of the
|
||||
mode switch
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
X server may send RROutputChangeNotify event with null crtc and mode,
|
||||
when it switches an output mode. Request RROutputInfo to distinguish
|
||||
this case from the case when the output is explicitly disabled.
|
||||
|
||||
Change-Id: I4c2356ec71dbcc8013009ea8a6f46dd11f19d6bb
|
||||
Task-number: QTBUG-44158
|
||||
Task-number: QTBUG-46786
|
||||
Task-number: QTBUG-46822
|
||||
Reviewed-by: Daniel Vrátil <dvratil@redhat.com>
|
||||
Reviewed-by: Gatis Paeglis <gatis.paeglis@digia.com>
|
||||
Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com>
|
||||
---
|
||||
src/plugins/platforms/xcb/qxcbconnection.cpp | 18 +++++++++++++-----
|
||||
1 file changed, 13 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
|
||||
index 0867615..29e1fd1 100644
|
||||
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
|
||||
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
|
||||
@@ -265,11 +265,19 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
|
||||
} 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);
|
||||
+ 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));
|
||||
+ if (outputInfo->crtc == 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 {
|
||||
+ qCDebug(lcQpaScreen) << "output" << screen->name() << "has been temporarily disabled for the mode switch";
|
||||
+ }
|
||||
} else {
|
||||
// Just update existing screen
|
||||
screen->updateGeometry(output.config_timestamp);
|
||||
--
|
||||
2.5.0
|
||||
|
386
138201.patch
386
138201.patch
@ -1,386 +0,0 @@
|
||||
diff -rupN qtbase-opensource-src-5.5.1/src/plugins/platforms/xcb/qxcbconnection.cpp qtbase-opensource-src-5.5.1-new/src/plugins/platforms/xcb/qxcbconnection.cpp
|
||||
--- qtbase-opensource-src-5.5.1/src/plugins/platforms/xcb/qxcbconnection.cpp 2015-10-13 06:35:27.000000000 +0200
|
||||
+++ qtbase-opensource-src-5.5.1-new/src/plugins/platforms/xcb/qxcbconnection.cpp 2015-10-21 21:02:53.056198256 +0200
|
||||
@@ -229,7 +229,6 @@ void QXcbConnection::updateScreens(const
|
||||
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;
|
||||
QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(output.window);
|
||||
@@ -242,20 +241,18 @@ void QXcbConnection::updateScreens(const
|
||||
|
||||
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 all screens are removed, wait
|
||||
- // and start rendering again later if a screen becomes available.
|
||||
-
|
||||
+ destroyScreen(screen, true);
|
||||
} 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) {
|
||||
+ // QTBUG-40174, QTBUG-42985: If virtual screen exists,
|
||||
+ // remove it and next add a physical screen.
|
||||
+ if (m_onlyVirtualScreen) {
|
||||
+ qCDebug(lcQpaScreen) << "default screen" << screen->name() << "has been removed";
|
||||
+ destroyScreen(m_screens.at(0), false);
|
||||
+ m_onlyVirtualScreen = false;
|
||||
+ }
|
||||
+
|
||||
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(
|
||||
@@ -270,34 +267,25 @@ void QXcbConnection::updateScreens(const
|
||||
otherScreen->addVirtualSibling(screen);
|
||||
m_screens << screen;
|
||||
QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
|
||||
-
|
||||
- // Windows which had null screens have already had expose events by now.
|
||||
- // They need to be told the screen is back, it's OK to render.
|
||||
- foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
|
||||
- QXcbWindow *xcbWin = static_cast<QXcbWindow*>(window->handle());
|
||||
- if (xcbWin)
|
||||
- xcbWin->maybeSetScreen(screen);
|
||||
- }
|
||||
+ maybeSetScreenForTopLevelWindows(screen);
|
||||
}
|
||||
- // else ignore disabled screens
|
||||
} else if (screen) {
|
||||
- // Screen has been disabled -> remove
|
||||
if (output.crtc == XCB_NONE && output.mode == XCB_NONE) {
|
||||
+ // Screen has been disabled
|
||||
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));
|
||||
if (outputInfo->crtc == 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);
|
||||
+ destroyScreen(screen, true);
|
||||
} else {
|
||||
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been temporarily disabled for the mode switch";
|
||||
+ screen->setCrtc(XCB_NONE); //Invalidate crtc
|
||||
}
|
||||
} else {
|
||||
// Just update existing screen
|
||||
+ screen->setCrtc(output.crtc); //Set the new crtc, because it may be invalidated
|
||||
screen->updateGeometry(output.config_timestamp);
|
||||
const bool wasPrimary = screen->isPrimary();
|
||||
screen->setPrimary(checkOutputIsPrimary(output.window, output.output));
|
||||
@@ -316,19 +304,61 @@ void QXcbConnection::updateScreens(const
|
||||
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::destroyScreen(QXcbScreen *screen, bool canCreateVirtualScreen)
|
||||
+{
|
||||
+ // 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 all screens are removed, add a virtual
|
||||
+ // screen and remove it later if a physical screen becomes available.
|
||||
+ if (canCreateVirtualScreen && m_screens.isEmpty())
|
||||
+ createVirtualScreen();
|
||||
+}
|
||||
+void QXcbConnection::createVirtualScreen()
|
||||
+{
|
||||
+ QXcbVirtualDesktop *virtualDesktop = m_virtualDesktops.value(0);
|
||||
+ if (virtualDesktop && !virtualDesktop->size().isEmpty()) {
|
||||
+ Q_ASSERT(m_screens.isEmpty());
|
||||
+ QXcbScreen *screen = createScreen(virtualDesktop, 0, Q_NULLPTR);
|
||||
+ screen->setVirtualSiblings(QList<QPlatformScreen *>() << screen);
|
||||
+ screen->setPrimary(true);
|
||||
+ m_onlyVirtualScreen = true;
|
||||
+ m_screens << screen;
|
||||
+ QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
|
||||
+ maybeSetScreenForTopLevelWindows(screen);
|
||||
+ qCDebug(lcQpaScreen) << "virtual screen was created" << screen;
|
||||
+ }
|
||||
+}
|
||||
+void QXcbConnection::maybeSetScreenForTopLevelWindows(QXcbScreen *screen)
|
||||
+{
|
||||
+ // Windows which had null screens have already had expose events by now.
|
||||
+ // They need to be told the screen is back, it's OK to render.
|
||||
+ bool doFlush = false;
|
||||
+ foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
|
||||
+ QXcbWindow *xcbWin = static_cast<QXcbWindow*>(window->handle());
|
||||
+ if (xcbWin)
|
||||
+ doFlush |= xcbWin->maybeSetScreen(screen);
|
||||
+ }
|
||||
+ // Flush Window System Events to prevent disappearing windows
|
||||
+ if (doFlush)
|
||||
+ QWindowSystemInterface::flushWindowSystemEvents();
|
||||
+}
|
||||
|
||||
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 = Q_NULLPTR;
|
||||
- bool hasOutputs = false;
|
||||
while (it.rem) {
|
||||
// Each "screen" in xcb terminology is a virtual desktop,
|
||||
// potentially a collection of separate juxtaposed monitors.
|
||||
@@ -407,7 +437,6 @@ void QXcbConnection::initializeScreens()
|
||||
|
||||
QXcbScreen *screen = createScreen(virtualDesktop, outputs[i], output.data());
|
||||
siblings << screen;
|
||||
- hasOutputs = true;
|
||||
m_screens << screen;
|
||||
|
||||
// There can be multiple outputs per screen, use either
|
||||
@@ -434,39 +463,23 @@ 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)
|
||||
- QXcbVirtualDesktop *virtualDesktop = m_virtualDesktops.value(0);
|
||||
- if (virtualDesktop && !hasOutputs && !virtualDesktop->size().isEmpty() && m_screens.isEmpty()) {
|
||||
- QXcbScreen *screen = createScreen(virtualDesktop, 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());
|
||||
- if (m_screens.first() != primaryScreen) {
|
||||
- m_screens.removeOne(primaryScreen);
|
||||
- m_screens.prepend(primaryScreen);
|
||||
+ if (m_screens.isEmpty()) {
|
||||
+ createVirtualScreen();
|
||||
+ } else {
|
||||
+ // Ensure the primary screen is first in the list
|
||||
+ if (primaryScreen) {
|
||||
+ if (m_screens.first() != primaryScreen) {
|
||||
+ m_screens.removeOne(primaryScreen);
|
||||
+ m_screens.prepend(primaryScreen);
|
||||
+ }
|
||||
}
|
||||
- }
|
||||
|
||||
- // 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();
|
||||
+ // Push the screens to QGuiApplication
|
||||
+ foreach (QXcbScreen *screen, m_screens) {
|
||||
+ qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")";
|
||||
+ QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName)
|
||||
@@ -474,6 +487,7 @@ QXcbConnection::QXcbConnection(QXcbNativ
|
||||
, m_canGrabServer(canGrabServer)
|
||||
, m_defaultVisualId(defaultVisualId)
|
||||
, m_primaryScreenNumber(0)
|
||||
+ , m_onlyVirtualScreen(false)
|
||||
, m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
|
||||
, m_nativeInterface(nativeInterface)
|
||||
#ifdef XCB_USE_XLIB
|
||||
@@ -1110,8 +1124,19 @@ void QXcbConnection::handleXcbEvent(xcb_
|
||||
handled = false;
|
||||
break;
|
||||
case XCB_PROPERTY_NOTIFY:
|
||||
- HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent);
|
||||
+ {
|
||||
+ // Update geometry for all screens, because availableGeometry must be changed
|
||||
+ const xcb_property_notify_event_t *propertyNotifyEvent = (const xcb_property_notify_event_t *)event;
|
||||
+ if (propertyNotifyEvent->atom == atom(QXcbAtom::_NET_WORKAREA)) {
|
||||
+ foreach (QXcbScreen *screen, m_screens) {
|
||||
+ if (propertyNotifyEvent->window == screen->root())
|
||||
+ screen->updateGeometry(propertyNotifyEvent->time);
|
||||
+ }
|
||||
+ } else {
|
||||
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent);
|
||||
+ }
|
||||
break;
|
||||
+ }
|
||||
#if defined(XCB_USE_XINPUT2)
|
||||
case XCB_GE_GENERIC:
|
||||
// Here the windowEventListener is invoked from xi2HandleEvent()
|
||||
diff -rupN qtbase-opensource-src-5.5.1/src/plugins/platforms/xcb/qxcbconnection.h qtbase-opensource-src-5.5.1-new/src/plugins/platforms/xcb/qxcbconnection.h
|
||||
--- qtbase-opensource-src-5.5.1/src/plugins/platforms/xcb/qxcbconnection.h 2015-10-13 06:35:27.000000000 +0200
|
||||
+++ qtbase-opensource-src-5.5.1-new/src/plugins/platforms/xcb/qxcbconnection.h 2015-10-21 21:00:21.767613360 +0200
|
||||
@@ -519,6 +519,9 @@ private:
|
||||
QXcbVirtualDesktop* virtualDesktopForRootWindow(xcb_window_t rootWindow);
|
||||
bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output);
|
||||
void initializeScreens();
|
||||
+ void destroyScreen(QXcbScreen *screen, bool canCreateVirtualScreen);
|
||||
+ void createVirtualScreen();
|
||||
+ void maybeSetScreenForTopLevelWindows(QXcbScreen *screen);
|
||||
void updateScreens(const xcb_randr_notify_event_t *event);
|
||||
|
||||
bool m_xi2Enabled;
|
||||
@@ -583,6 +586,7 @@ private:
|
||||
QList<QXcbVirtualDesktop *> m_virtualDesktops;
|
||||
QList<QXcbScreen *> m_screens;
|
||||
int m_primaryScreenNumber;
|
||||
+ bool m_onlyVirtualScreen;
|
||||
|
||||
xcb_atom_t m_allAtoms[QXcbAtom::NAtoms];
|
||||
|
||||
diff -rupN qtbase-opensource-src-5.5.1/src/plugins/platforms/xcb/qxcbscreen.cpp qtbase-opensource-src-5.5.1-new/src/plugins/platforms/xcb/qxcbscreen.cpp
|
||||
--- qtbase-opensource-src-5.5.1/src/plugins/platforms/xcb/qxcbscreen.cpp 2015-10-13 06:35:27.000000000 +0200
|
||||
+++ qtbase-opensource-src-5.5.1-new/src/plugins/platforms/xcb/qxcbscreen.cpp 2015-10-21 21:00:21.768613377 +0200
|
||||
@@ -438,14 +438,6 @@ void QXcbScreen::handleScreenChange(xcb_
|
||||
|
||||
QDpi ldpi = logicalDpi();
|
||||
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QPlatformScreen::screen(), ldpi.first, ldpi.second);
|
||||
-
|
||||
- // Windows which had null screens have already had expose events by now.
|
||||
- // They need to be told the screen is back, it's OK to render.
|
||||
- foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
|
||||
- QXcbWindow *xcbWin = static_cast<QXcbWindow*>(window->handle());
|
||||
- if (xcbWin)
|
||||
- xcbWin->maybeSetScreen(this);
|
||||
- }
|
||||
}
|
||||
|
||||
void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)
|
||||
diff -rupN qtbase-opensource-src-5.5.1/src/plugins/platforms/xcb/qxcbscreen.h qtbase-opensource-src-5.5.1-new/src/plugins/platforms/xcb/qxcbscreen.h
|
||||
--- qtbase-opensource-src-5.5.1/src/plugins/platforms/xcb/qxcbscreen.h 2015-10-13 06:35:27.000000000 +0200
|
||||
+++ qtbase-opensource-src-5.5.1-new/src/plugins/platforms/xcb/qxcbscreen.h 2015-10-21 21:00:21.768613377 +0200
|
||||
@@ -116,6 +116,8 @@ public:
|
||||
xcb_randr_crtc_t crtc() const { return m_crtc; }
|
||||
xcb_randr_mode_t mode() const { return m_mode; }
|
||||
|
||||
+ void setCrtc(xcb_randr_crtc_t crtc) { m_crtc = crtc; }
|
||||
+
|
||||
void windowShown(QXcbWindow *window);
|
||||
QString windowManagerName() const { return m_windowManagerName; }
|
||||
bool syncRequestSupported() const { return m_syncRequestSupported; }
|
||||
diff -rupN qtbase-opensource-src-5.5.1/src/plugins/platforms/xcb/qxcbwindow.cpp qtbase-opensource-src-5.5.1-new/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||||
--- qtbase-opensource-src-5.5.1/src/plugins/platforms/xcb/qxcbwindow.cpp 2015-10-13 06:35:27.000000000 +0200
|
||||
+++ qtbase-opensource-src-5.5.1-new/src/plugins/platforms/xcb/qxcbwindow.cpp 2015-10-21 21:01:17.324562601 +0200
|
||||
@@ -694,12 +694,17 @@ void QXcbWindow::destroy()
|
||||
m_pendingSyncRequest->invalidate();
|
||||
}
|
||||
|
||||
-void QXcbWindow::maybeSetScreen(QXcbScreen *screen)
|
||||
+bool QXcbWindow::maybeSetScreen(QXcbScreen *screen)
|
||||
{
|
||||
- if (!window()->screen() && screen->geometry().contains(geometry().topLeft())) {
|
||||
+ // Every window must have a screen. Otherwise application can
|
||||
+ // crash and the window contents are invisible e.g. in x11vnc.
|
||||
+ if (!window()->screen()) {
|
||||
QWindowSystemInterface::handleWindowScreenChanged(window(), static_cast<QPlatformScreen *>(screen)->screen());
|
||||
- QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(0, 0), window()->size())));
|
||||
+ if (screen->geometry().contains(geometry().topLeft()))
|
||||
+ QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(0, 0), window()->size())));
|
||||
+ return true;
|
||||
}
|
||||
+ return false;
|
||||
}
|
||||
|
||||
void QXcbWindow::setGeometry(const QRect &rect)
|
||||
@@ -1243,8 +1248,6 @@ void QXcbWindow::changeNetWmState(bool s
|
||||
event.data.data32[3] = 0;
|
||||
event.data.data32[4] = 0;
|
||||
|
||||
- if (!xcbScreen())
|
||||
- return;
|
||||
Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
|
||||
}
|
||||
|
||||
@@ -1493,8 +1496,6 @@ void QXcbWindow::setParent(const QPlatfo
|
||||
xcb_parent_id = qXcbParent->xcb_window();
|
||||
m_embedded = qXcbParent->window()->type() == Qt::ForeignWindow;
|
||||
} else {
|
||||
- if (!xcbScreen())
|
||||
- return;
|
||||
xcb_parent_id = xcbScreen()->root();
|
||||
m_embedded = false;
|
||||
}
|
||||
@@ -2323,8 +2324,6 @@ void QXcbWindow::handleEnterNotifyEvent(
|
||||
|
||||
const int dpr = int(devicePixelRatio());
|
||||
const QPoint local(event->event_x/dpr, event->event_y/dpr);
|
||||
- if (!xcbScreen())
|
||||
- return;
|
||||
QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
|
||||
QWindowSystemInterface::handleEnterEvent(window(), local, global);
|
||||
}
|
||||
@@ -2343,8 +2342,6 @@ void QXcbWindow::handleLeaveNotifyEvent(
|
||||
if (enterWindow) {
|
||||
const int dpr = int(devicePixelRatio());
|
||||
QPoint local(enter->event_x/dpr, enter->event_y/dpr);
|
||||
- if (!xcbScreen())
|
||||
- return;
|
||||
QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
|
||||
|
||||
QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global);
|
||||
@@ -2360,8 +2357,6 @@ void QXcbWindow::handlePropertyNotifyEve
|
||||
connection()->setTime(event->time);
|
||||
|
||||
const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE;
|
||||
- if (!xcbScreen())
|
||||
- return;
|
||||
|
||||
if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) {
|
||||
if (propertyDeleted)
|
||||
@@ -2403,8 +2398,6 @@ void QXcbWindow::handlePropertyNotifyEve
|
||||
return;
|
||||
} else if (event->atom == atom(QXcbAtom::_NET_FRAME_EXTENTS)) {
|
||||
m_dirtyFrameMargins = true;
|
||||
- } else if (event->atom == atom(QXcbAtom::_NET_WORKAREA) && xcbScreen() && event->window == xcbScreen()->root()) {
|
||||
- xcbScreen()->updateGeometry(event->time);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2682,8 +2675,6 @@ bool QXcbWindow::needsSync() const
|
||||
|
||||
void QXcbWindow::postSyncWindowRequest()
|
||||
{
|
||||
- if (!xcbScreen())
|
||||
- return;
|
||||
if (!m_pendingSyncRequest) {
|
||||
QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this);
|
||||
m_pendingSyncRequest = e;
|
||||
diff -rupN qtbase-opensource-src-5.5.1/src/plugins/platforms/xcb/qxcbwindow.h qtbase-opensource-src-5.5.1-new/src/plugins/platforms/xcb/qxcbwindow.h
|
||||
--- qtbase-opensource-src-5.5.1/src/plugins/platforms/xcb/qxcbwindow.h 2015-10-13 06:35:27.000000000 +0200
|
||||
+++ qtbase-opensource-src-5.5.1-new/src/plugins/platforms/xcb/qxcbwindow.h 2015-10-21 21:00:21.769613394 +0200
|
||||
@@ -158,7 +158,7 @@ public:
|
||||
|
||||
virtual void create();
|
||||
virtual void destroy();
|
||||
- void maybeSetScreen(QXcbScreen *screen);
|
||||
+ bool maybeSetScreen(QXcbScreen *screen);
|
||||
QXcbScreen *screenForNativeGeometry(const QRect &newGeometry) const;
|
||||
|
||||
public Q_SLOTS:
|
@ -39,7 +39,7 @@
|
||||
Summary: Qt5 - QtBase components
|
||||
Name: qt5-qtbase
|
||||
Version: 5.6.0
|
||||
Release: 0.8%{?dist}
|
||||
Release: 0.10%{?dist}
|
||||
|
||||
# See LGPL_EXCEPTIONS.txt, for exception details
|
||||
License: LGPLv2 with exceptions or GPLv3 with exceptions
|
||||
@ -73,15 +73,16 @@ Patch50: qt5-poll.patch
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1083664
|
||||
Patch51: qtbase-opensource-src-5.5-disconnect_displays.patch
|
||||
|
||||
# xcb: QScreen is a placeholder whenever there are no outputs connected
|
||||
# https://codereview.qt-project.org/#/c/138201/
|
||||
Patch52: qtbase-opensource-src-5.6.0-xcb-gerrit-138201.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
|
||||
|
||||
Patch101: 0001-XCB-prevent-a-fp-division-by-zero.patch
|
||||
Patch102: 0002-xcb-compare-to-previous-state-when-sending-geometry-.patch
|
||||
Patch111: 0011-xcb-Don-t-cache-the-screen-for-a-window.patch
|
||||
Patch112: 0012-xcb-Use-a-placeholder-QScreen-when-there-are-no-outp.patch
|
||||
|
||||
# macros, be mindful to keep sync'd with macros.qt5
|
||||
Source10: macros.qt5
|
||||
%define _qt5 %{name}
|
||||
@ -312,14 +313,17 @@ rm -fv mkspecs/linux-g++*/qmake.conf.multilib-optflags
|
||||
%patch4 -p1 -b .QTBUG-35459
|
||||
%patch12 -p1 -b .enable_ft_lcdfilter
|
||||
|
||||
%patch51 -p1 -b .disconnect_displays
|
||||
|
||||
%patch52 -p1 -b .138201
|
||||
#patch51 -p1 -b .disconnect_displays
|
||||
|
||||
%if 0%{?rhel} == 6
|
||||
%patch100 -p1 -b .QTBUG-43057
|
||||
%endif
|
||||
|
||||
%patch101 -p1 -b .0001
|
||||
%patch102 -p1 -b .0002
|
||||
%patch111 -p1 -b .0011
|
||||
%patch112 -p1 -b .0012
|
||||
|
||||
# drop -fexceptions from $RPM_OPT_FLAGS
|
||||
RPM_OPT_FLAGS=`echo $RPM_OPT_FLAGS | sed 's|-fexceptions||g'`
|
||||
|
||||
@ -853,10 +857,16 @@ fi
|
||||
|
||||
|
||||
%changelog
|
||||
* Sun Dec 13 2015 Helio Chissini de Castro <helio@kde.org> - 5.6.0-0.8
|
||||
* Sun Dec 13 2015 Helio Chissini de Castro <helio@kde.org> - 5.6.0-0.10
|
||||
- We're back to gold linker
|
||||
- Remove reduce relocations
|
||||
|
||||
* Sat Dec 12 2015 Rex Dieter <rdieter@fedoraproject.org> 5.6.0-0.9
|
||||
- drop disconnect_displays.patch so we can better test latest xcb/display work
|
||||
|
||||
* Fri Dec 11 2015 Rex Dieter <rdieter@fedoraproject.org> 5.6.0-0.8
|
||||
- sync latest xcb/screen/display related upstream commits
|
||||
|
||||
* Thu Dec 10 2015 Helio Chissini de Castro <helio@kde.org> - 5.6.0-0.7
|
||||
- Official beta release
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user