diff --git a/.gitignore b/.gitignore index 6202538..d1fab2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ /qtbase-opensource-src-5.5.1.tar.xz -/qtbase-opensource-src-5.6.0-beta2.tar.xz /qtbase-opensource-src-5.6.0-beta.tar.gz diff --git a/0001-XCB-prevent-a-fp-division-by-zero.patch b/0001-XCB-prevent-a-fp-division-by-zero.patch deleted file mode 100644 index 9a186ab..0000000 --- a/0001-XCB-prevent-a-fp-division-by-zero.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 40c927e7331ea4ac9ca50de48560b700e657cded Mon Sep 17 00:00:00 2001 -From: Giuseppe D'Angelo -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 -Reviewed-by: Błażej Szczygieł -Reviewed-by: Shawn Rutledge ---- - 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(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 - diff --git a/0002-xcb-compare-to-previous-state-when-sending-geometry-.patch b/0002-xcb-compare-to-previous-state-when-sending-geometry-.patch deleted file mode 100644 index 2c74c52..0000000 --- a/0002-xcb-compare-to-previous-state-when-sending-geometry-.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 56f6252e7285c9c61a99416fa2a8571fd67c597f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= - -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ø ---- - 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(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 - diff --git a/0011-xcb-Don-t-cache-the-screen-for-a-window.patch b/0011-xcb-Don-t-cache-the-screen-for-a-window.patch deleted file mode 100644 index fdd795e..0000000 --- a/0011-xcb-Don-t-cache-the-screen-for-a-window.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 0c33a823c560bdf18a513ae460eea4d7bdf9e115 Mon Sep 17 00:00:00 2001 -From: Alexander Volkov -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ł -Reviewed-by: Shawn Rutledge ---- - 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(parent())->parentScreen() : m_xcbScreen; -+ return parent() ? static_cast(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(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(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(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 - diff --git a/0012-xcb-Use-a-placeholder-QScreen-when-there-are-no-outp.patch b/0012-xcb-Use-a-placeholder-QScreen-when-there-are-no-outp.patch deleted file mode 100644 index 665827e..0000000 --- a/0012-xcb-Use-a-placeholder-QScreen-when-there-are-no-outp.patch +++ /dev/null @@ -1,721 +0,0 @@ -From a094af001795c9651b299d700a992150d1aba33a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= -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 ---- - 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 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 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(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 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 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 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 siblings; - for (int i = 0; i < outputCount; i++) { - QScopedPointer 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() << 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(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 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(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 - diff --git a/qt5-qtbase-QTBUG-47041.patch b/qt5-qtbase-QTBUG-47041.patch deleted file mode 100644 index ff1395c..0000000 --- a/qt5-qtbase-QTBUG-47041.patch +++ /dev/null @@ -1,45 +0,0 @@ -From b0b08cc0e4e38504d6b833702f7477aee4e2a192 Mon Sep 17 00:00:00 2001 -From: Ralf Jung -Date: Sun, 5 Jul 2015 12:15:29 +0200 -Subject: [PATCH] When a screen comes back online, the windows need to be told - about it - -On my system, this fixes the misbehavior of Qt applications when the (only) active screen is -switched, e.g. from an external screen to the laptop. -This behavior is caused by the screen() of widgets to be set to NULL when their screen goes away. -When a new screen comes online, the widgets *should* be told about it, but they are not. The only -place that "maybeSetScreen" is called is when an existing screen changes its geometry, but not -when a screen gets enabled without its geometry being affected in any way (e.g. because it was -just disabled via xrandr, but has been connected all along). This makes sure that "maybeSetScreen" -is also called when a screen gets enabled. - -Task-number: QTBUG-47041 -Change-Id: Ic72d6beaa544bf9a4efdbea0830b1bc0d6ce5362 -Reviewed-by: Dmitry Shachnev -Reviewed-by: Shawn Rutledge ---- - src/plugins/platforms/xcb/qxcbconnection.cpp | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp -index 74f48b0..0867615 100644 ---- a/src/plugins/platforms/xcb/qxcbconnection.cpp -+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp -@@ -252,6 +252,14 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) - 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(window->handle()); -+ if (xcbWin) -+ xcbWin->maybeSetScreen(screen); -+ } - } - // else ignore disabled screens - } else if (screen) { --- -2.3.5 - diff --git a/qt5-qtbase.spec b/qt5-qtbase.spec index b5b04b7..e29afe6 100644 --- a/qt5-qtbase.spec +++ b/qt5-qtbase.spec @@ -39,12 +39,16 @@ Summary: Qt5 - QtBase components Name: qt5-qtbase Version: 5.6.0 -Release: 0.15%{?dist} +Release: 0.16%{?dist} # See LGPL_EXCEPTIONS.txt, for exception details License: LGPLv2 with exceptions or GPLv3 with exceptions Url: http://qt-project.org/ +%if 0%{?prerelease:1} +Source0: http://download.qt.io/development_releases/qt/5.6/%{version}-%{prerelease}/submodules/%{qt_module}-opensource-src-%{version}-%{prerelease}.tar.gz +%else Source0: http://download.qt.io/official_releases/qt/5.6/%{version}%{?prerelease:-%{prerelease}}/submodules/%{qt_module}-opensource-src-%{version}%{?prerelease:-%{prerelease}}.tar.gz +%endif # header file to workaround multilib issue # https://bugzilla.redhat.com/show_bug.cgi?id=1036956 @@ -83,11 +87,6 @@ Patch52: qtbase-opensource-src-5.6.0-moc_WORDSIZE.patch # '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 - # recently passed code review, not integrated yet # https://codereview.qt-project.org/126102/ Patch150: moc-get-the-system-defines-from-the-compiler-itself.patch @@ -331,10 +330,6 @@ rm -fv mkspecs/linux-g++*/qmake.conf.multilib-optflags %patch100 -p1 -b .QTBUG-43057 %endif -%patch101 -p1 -b .0001 -%patch102 -p1 -b .0002 -%patch111 -p1 -b .0011 -%patch112 -p1 -b .0012 %patch150 -p1 -b .moc_system_defines # drop -fexceptions from $RPM_OPT_FLAGS @@ -868,6 +863,9 @@ fi %changelog +* Fri Dec 18 2015 Rex Dieter 5.6.0-0.16 +- 5.6.0-beta (final) + * Wed Dec 16 2015 Rex Dieter - 5.6.0-0.15 - pull in another upstream moc fix/improvement (#1290020,QTBUG-49972) - fix bootstrap/docs diff --git a/qtbase-opensource-src-5.6.0-xcb-gerrit-138201.patch b/qtbase-opensource-src-5.6.0-xcb-gerrit-138201.patch deleted file mode 100644 index 52e4020..0000000 --- a/qtbase-opensource-src-5.6.0-xcb-gerrit-138201.patch +++ /dev/null @@ -1,704 +0,0 @@ -From 56657b57083caa77e368452b07224bb70082bbc6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= -Date: Fri, 16 Oct 2015 22:51:59 +0200 -Subject: [PATCH] xcb: QScreen is a placeholder whenever 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 ---- - src/gui/kernel/qscreen.cpp | 4 +- - src/plugins/platforms/xcb/qxcbconnection.cpp | 265 +++++++++++++++------------ - 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, 205 insertions(+), 172 deletions(-) - -diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp -index b6b5037..4338db2 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 901764b..66a794a 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 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) { -@@ -260,16 +224,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 +233,138 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) - QScopedPointer 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"; -+ // Find a fake screen -+ foreach (QPlatformScreen *screen, virtualDesktop->screens()) { -+ QXcbScreen *xcbScreen = (QXcbScreen *)screen; -+ if (xcbScreen->output() == XCB_NONE) { -+ screen = xcbScreen; -+ break; -+ } -+ } - -- screen->setPrimary(checkOutputIsPrimary(output.window, output.output)); -- virtualDesktop->addScreen(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(window->handle()); -- if (xcbWin) -- xcbWin->maybeSetScreen(screen); -+ if (screen) { -+ // Transform the fake screen into a physical screen -+ screen->setOutput(output.output, outputInfo.data()); -+ updateScreen(screen, output); -+ } 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 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 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. -+ screen->setOutput(XCB_NONE, Q_NULLPTR); -+ } 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 +372,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 +381,6 @@ void QXcbConnection::initializeScreens() - xcb_screen_t *xcbScreen = it.data; - QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber); - m_virtualDesktops.append(virtualDesktop); -- QList 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 +397,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 +424,7 @@ void QXcbConnection::initializeScreens() - qWarning("failed to get the primary output of the screen"); - free(error); - } else { -+ QList siblings; - for (int i = 0; i < outputCount; i++) { - QScopedPointer output( - xcb_randr_get_output_info_reply(xcb_connection(), -@@ -416,9 +448,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 +466,22 @@ 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); -+ 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 +489,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() << 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 +581,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 2a53b18..bf3c0a6 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(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 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 d0efb68..cbb67f0 100644 ---- a/src/plugins/platforms/xcb/qxcbwindow.cpp -+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp -@@ -627,14 +627,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(screen)->screen()); -- QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(0, 0), window()->size()))); -- } --} -- - void QXcbWindow::setGeometry(const QRect &rect) - { - QPlatformWindow::setGeometry(rect); -@@ -850,15 +842,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()); - -@@ -1186,8 +1176,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)); - } - -@@ -1440,8 +1428,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; - } -@@ -1997,7 +1983,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); -@@ -2297,8 +2283,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); - } -@@ -2316,8 +2300,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); -@@ -2333,8 +2315,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) -@@ -2654,8 +2634,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 fd7d69c..4d7ea96 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 - diff --git a/sources b/sources index ecbcf83..a6a86ec 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -53ce29b757fec734085627cdf25f176f qtbase-opensource-src-5.6.0-beta.tar.gz +e5812c1aceef2f9be87999da70896032 qtbase-opensource-src-5.6.0-beta.tar.gz