- Enable gold and remove reduced relocations - merges

This commit is contained in:
Helio Chissini de Castro 2015-12-13 20:15:33 +01:00
commit df97d65ed7
7 changed files with 1000 additions and 451 deletions

View 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

View File

@ -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

View 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

View 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

View File

@ -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

View File

@ -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:

View File

@ -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