diff options
Diffstat (limited to 'src/gui/kernel/qwindow.cpp')
-rw-r--r-- | src/gui/kernel/qwindow.cpp | 128 |
1 files changed, 84 insertions, 44 deletions
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 2ff19f5175..a20f4329b1 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -214,7 +220,7 @@ void QWindowPrivate::init() // If your application aborts here, you are probably creating a QWindow // before the screen list is populated. - if (!parentWindow && !topLevelScreen) { + if (Q_UNLIKELY(!parentWindow && !topLevelScreen)) { qFatal("Cannot create window: no screens available"); exit(1); } @@ -361,7 +367,7 @@ void QWindowPrivate::emitScreenChangedRecursion(QScreen *newScreen) { Q_Q(QWindow); emit q->screenChanged(newScreen); - foreach (QObject *child, q->children()) { + for (QObject *child : q->children()) { if (child->isWindowType()) static_cast<QWindow *>(child)->d_func()->emitScreenChangedRecursion(newScreen); } @@ -394,8 +400,11 @@ void QWindowPrivate::create(bool recursive) if (platformWindow) return; + if (q->parent()) + q->parent()->create(); + platformWindow = QGuiApplicationPrivate::platformIntegration()->createPlatformWindow(q); - Q_ASSERT(platformWindow); + Q_ASSERT(platformWindow || q->type() == Qt::ForeignWindow); if (!platformWindow) { qWarning() << "Failed to create platform window for" << q << "with flags" << q->flags(); @@ -405,13 +414,21 @@ void QWindowPrivate::create(bool recursive) QObjectList childObjects = q->children(); for (int i = 0; i < childObjects.size(); i ++) { QObject *object = childObjects.at(i); - if (object->isWindowType()) { - QWindow *window = static_cast<QWindow *>(object); - if (recursive) - window->d_func()->create(true); - if (window->d_func()->platformWindow) - window->d_func()->platformWindow->setParent(platformWindow); - } + if (!object->isWindowType()) + continue; + + QWindow *childWindow = static_cast<QWindow *>(object); + if (recursive) + childWindow->d_func()->create(recursive); + + // The child may have had deferred creation due to this window not being created + // at the time setVisible was called, so we re-apply the visible state, which + // may result in creating the child, and emitting the appropriate signals. + if (childWindow->isVisible()) + childWindow->setVisible(true); + + if (QPlatformWindow *childPlatformWindow = childWindow->d_func()->platformWindow) + childPlatformWindow->setParent(this->platformWindow); } QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated); @@ -476,14 +493,23 @@ void QWindow::setVisible(bool visible) { Q_D(QWindow); - if (d->visible == visible) + if (d->visible != visible) { + d->visible = visible; + emit visibleChanged(visible); + d->updateVisibility(); + } else if (d->platformWindow) { + // Visibility hasn't changed, and the platform window is in sync return; - d->visible = visible; - emit visibleChanged(visible); - d->updateVisibility(); + } - if (!d->platformWindow) - create(); + if (!d->platformWindow) { + // If we have a parent window, but the parent hasn't been created yet, we + // can defer creation until the parent is created or we're re-parented. + if (parent() && !parent()->handle()) + return; + else + create(); + } if (visible) { // remove posted quit events when showing a new window @@ -522,6 +548,7 @@ void QWindow::setVisible(bool visible) if (visible && (d->hasCursor || QGuiApplication::overrideCursor())) d->applyCursor(); #endif + d->platformWindow->setVisible(visible); if (!visible) { @@ -618,12 +645,17 @@ void QWindow::setParent(QWindow *parent) else d->connectToScreen(newScreen); + // If we were set visible, but not created because we were a child, and we're now + // re-parented into a created parent, or to being a top level, we need re-apply the + // visibility state, which will also create. + if (isVisible() && (!parent || parent->handle())) + setVisible(true); + if (d->platformWindow) { - if (parent && parent->d_func()->platformWindow) { - d->platformWindow->setParent(parent->d_func()->platformWindow); - } else { - d->platformWindow->setParent(0); - } + if (parent) + parent->create(); + + d->platformWindow->setParent(parent ? parent->d_func()->platformWindow : 0); } QGuiApplicationPrivate::updateBlockedStatus(this); @@ -972,7 +1004,7 @@ QRegion QWindow::mask() const /*! Requests the window to be activated, i.e. receive keyboard focus. - \sa isActive(), QGuiApplication::focusWindow() + \sa isActive(), QGuiApplication::focusWindow(), QWindowsWindowFunctions::setWindowActivationBehavior() */ void QWindow::requestActivate() { @@ -1115,7 +1147,7 @@ qreal QWindow::devicePixelRatio() const void QWindow::setWindowState(Qt::WindowState state) { if (state == Qt::WindowActive) { - qWarning() << "QWindow::setWindowState does not accept Qt::WindowActive"; + qWarning("QWindow::setWindowState does not accept Qt::WindowActive"); return; } @@ -1439,9 +1471,9 @@ void QWindow::setGeometry(const QRect &rect) { Q_D(QWindow); d->positionAutomatic = false; - if (rect == geometry()) + const QRect oldRect = geometry(); + if (rect == oldRect) return; - QRect oldRect = geometry(); d->positionPolicy = QWindowPrivate::WindowFrameExclusive; if (d->platformWindow) { @@ -1479,7 +1511,8 @@ QScreen *QWindowPrivate::screenForGeometry(const QRect &newGeometry) QScreen *fallback = currentScreen; QPoint center = newGeometry.center(); if (!q->parent() && currentScreen && !currentScreen->geometry().contains(center)) { - Q_FOREACH (QScreen* screen, currentScreen->virtualSiblings()) { + const auto screens = currentScreen->virtualSiblings(); + for (QScreen* screen : screens) { if (screen->geometry().contains(center)) return screen; if (screen->geometry().intersects(newGeometry)) @@ -1656,8 +1689,10 @@ void QWindow::destroy() QGuiApplicationPrivate::currentMouseWindow = parent(); if (QGuiApplicationPrivate::currentMousePressWindow == this) QGuiApplicationPrivate::currentMousePressWindow = parent(); - if (QGuiApplicationPrivate::tabletPressTarget == this) - QGuiApplicationPrivate::tabletPressTarget = parent(); + + for (int i = 0; i < QGuiApplicationPrivate::tabletDevicePoints.size(); ++i) + if (QGuiApplicationPrivate::tabletDevicePoints.at(i).target == this) + QGuiApplicationPrivate::tabletDevicePoints[i].target = parent(); bool wasVisible = isVisible(); d->visibilityOnDestroy = wasVisible && d->platformWindow; @@ -2402,7 +2437,8 @@ QWindow *QWindowPrivate::topLevelWindow() const This can be used, on platforms which support it, to embed a QWindow inside a native window, or to embed a native window inside a QWindow. - If foreign windows are not supported, this function returns 0. + If foreign windows are not supported or embedding the native window + failed in the platform plugin, this function returns 0. \note The resulting QWindow should not be used to manipulate the underlying native window (besides re-parenting), or to observe state changes of the @@ -2415,7 +2451,7 @@ QWindow *QWindowPrivate::topLevelWindow() const QWindow *QWindow::fromWinId(WId id) { if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ForeignWindows)) { - qWarning() << "QWindow::fromWinId(): platform plugin does not support foreign windows."; + qWarning("QWindow::fromWinId(): platform plugin does not support foreign windows."); return 0; } @@ -2423,6 +2459,10 @@ QWindow *QWindow::fromWinId(WId id) window->setFlags(Qt::ForeignWindow); window->setProperty("_q_foreignWinId", QVariant::fromValue(id)); window->create(); + if (!window->handle()) { + delete window; + return nullptr; + } return window; } |