[SCM] qtbase packaging branch, ubuntu, updated. ubuntu/5.5.1+dfsg-13ubuntu2-10-ga6888e3

Timo Jyrinki timo at moszumanska.debian.org
Tue Feb 23 14:11:05 UTC 2016


Gitweb-URL: http://git.debian.org/?p=pkg-kde/qt/qtbase.git;a=commitdiff;h=69bfeb3

The following commit has been merged in the ubuntu branch:
commit 69bfeb3cbc20be9521d250ae9d180b2cc33527a0
Author: Timo Jyrinki <timo.jyrinki at canonical.com>
Date:   Tue Feb 23 14:08:23 2016 +0000

    xcb-Use-a-placeholder-QScreen-when-there-are-no-outp.patch
    
    * xcb-Use-a-placeholder-QScreen-when-there-are-no-outp.patch:
      - Another multi-monitor crasher fix (LP: #1548766)
---
 debian/changelog                                   |   2 +
 debian/patches/series                              |   1 +
 ...laceholder-QScreen-when-there-are-no-outp.patch | 721 +++++++++++++++++++++
 3 files changed, 724 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index e9252b0..eab2a91 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -4,6 +4,8 @@ qtbase-opensource-src (5.5.1+dfsg-14ubuntu2) UNRELEASED; urgency=medium
     started failing without any Qt changes (LP: #1548686)
   * debian/patches/Fix-for-deferredDelete-bug-when-calling-the-glib-loo.patch:
     - Fix DeferredDelete events handling. (LP: #1460970)
+  * xcb-Use-a-placeholder-QScreen-when-there-are-no-outp.patch:
+    - Another multi-monitor crasher fix (LP: #1548766)
 
  -- Timo Jyrinki <timo-jyrinki at ubuntu.com>  Fri, 19 Feb 2016 08:46:28 +0000
 
diff --git a/debian/patches/series b/debian/patches/series
index 816aa6d..ccb786e 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -26,6 +26,7 @@ xcb_fix_drag_and_drop_when_window_is_hidden.patch
 fix_not_delivering_focus.patch
 fix_potential_division_by_zero.patch
 Fix-for-deferredDelete-bug-when-calling-the-glib-loo.patch
+xcb-Use-a-placeholder-QScreen-when-there-are-no-outp.patch
 
 # Debian specific.
 gnukfreebsd.diff
diff --git a/debian/patches/xcb-Use-a-placeholder-QScreen-when-there-are-no-outp.patch b/debian/patches/xcb-Use-a-placeholder-QScreen-when-there-are-no-outp.patch
new file mode 100644
index 0000000..ce63211
--- /dev/null
+++ b/debian/patches/xcb-Use-a-placeholder-QScreen-when-there-are-no-outp.patch
@@ -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 at wp.pl>
+Date: Fri, 16 Oct 2015 22:51:59 +0200
+Subject: [PATCH] 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 at 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
++}
++
+ /*!
+     rief 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.7.0
+

-- 
qtbase packaging



More information about the pkg-kde-commits mailing list