diff options
Diffstat (limited to 'src/gui/kernel/qwindow.cpp')
-rw-r--r-- | src/gui/kernel/qwindow.cpp | 161 |
1 files changed, 104 insertions, 57 deletions
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 6561e0f502..a1057691f2 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. ** @@ -10,9 +10,9 @@ ** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** 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. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -23,8 +23,8 @@ ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** 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. ** ** $QT_END_LICENSE$ @@ -338,26 +338,20 @@ inline bool QWindowPrivate::windowRecreationRequired(QScreen *newScreen) const { Q_Q(const QWindow); const QScreen *oldScreen = q->screen(); - return oldScreen != newScreen && platformWindow + return oldScreen != newScreen && (platformWindow || !oldScreen) && !(oldScreen && oldScreen->virtualSiblings().contains(newScreen)); } inline void QWindowPrivate::disconnectFromScreen() { - if (topLevelScreen) { - Q_Q(QWindow); - QObject::disconnect(topLevelScreen, &QObject::destroyed, q, &QWindow::screenDestroyed); + if (topLevelScreen) topLevelScreen = 0; - } } void QWindowPrivate::connectToScreen(QScreen *screen) { - Q_Q(QWindow); disconnectFromScreen(); topLevelScreen = screen; - if (topLevelScreen) - QObject::connect(topLevelScreen, &QObject::destroyed, q, &QWindow::screenDestroyed); } void QWindowPrivate::emitScreenChangedRecursion(QScreen *newScreen) @@ -379,10 +373,13 @@ void QWindowPrivate::setTopLevelScreen(QScreen *newScreen, bool recreate) } if (newScreen != topLevelScreen) { const bool shouldRecreate = recreate && windowRecreationRequired(newScreen); - if (shouldRecreate) + const bool shouldShow = visibilityOnDestroy && !topLevelScreen; + if (shouldRecreate && platformWindow) q->destroy(); connectToScreen(newScreen); - if (newScreen && shouldRecreate) + if (shouldShow) + q->setVisible(true); + else if (newScreen && shouldRecreate) create(true); emitScreenChangedRecursion(newScreen); } @@ -404,6 +401,11 @@ void QWindowPrivate::create(bool recursive) window->d_func()->platformWindow->setParent(platformWindow); } } + + if (platformWindow) { + QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated); + QGuiApplication::sendEvent(q, &e); + } } } @@ -1073,6 +1075,10 @@ Qt::ScreenOrientation QWindow::contentOrientation() const Common values are 1.0 on normal displays and 2.0 on Apple "retina" displays. + \note For windows not backed by a platform window, meaning that create() was not + called, the function will fall back to QGuiApplication::devicePixelRatio() which in + turn returns the highest screen device pixel ratio found on the system. + \sa QScreen::devicePixelRatio(), QGuiApplication::devicePixelRatio() */ qreal QWindow::devicePixelRatio() const @@ -1604,12 +1610,19 @@ void QWindow::destroy() QGuiApplicationPrivate::focus_window = parent(); if (QGuiApplicationPrivate::currentMouseWindow == this) QGuiApplicationPrivate::currentMouseWindow = parent(); + if (QGuiApplicationPrivate::currentMousePressWindow == this) + QGuiApplicationPrivate::currentMousePressWindow = parent(); if (QGuiApplicationPrivate::tabletPressTarget == this) QGuiApplicationPrivate::tabletPressTarget = parent(); bool wasVisible = isVisible(); + d->visibilityOnDestroy = wasVisible && d->platformWindow; setVisible(false); + + QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed); + QGuiApplication::sendEvent(this, &e); + delete d->platformWindow; d->resizeEventPending = true; d->receivedExpose = false; @@ -1678,7 +1691,7 @@ bool QWindow::setMouseGrabEnabled(bool grab) } /*! - Returns the screen on which the window is shown. + Returns the screen on which the window is shown, or null if there is none. For child windows, this returns the screen of the corresponding top level window. @@ -1687,7 +1700,7 @@ bool QWindow::setMouseGrabEnabled(bool grab) QScreen *QWindow::screen() const { Q_D(const QWindow); - return d->parentWindow ? d->parentWindow->screen() : d->topLevelScreen; + return d->parentWindow ? d->parentWindow->screen() : d->topLevelScreen.data(); } /*! @@ -1707,24 +1720,7 @@ void QWindow::setScreen(QScreen *newScreen) Q_D(QWindow); if (!newScreen) newScreen = QGuiApplication::primaryScreen(); - d->setTopLevelScreen(newScreen, true /* recreate */); -} - -void QWindow::screenDestroyed(QObject *object) -{ - Q_D(QWindow); - if (d->parentWindow || QGuiApplication::closingDown()) - return; - if (object == static_cast<QObject *>(d->topLevelScreen)) { - const bool wasVisible = isVisible(); - setScreen(0); - // destroy() might have hidden our window, show it again. - // This might not be the best behavior if the new screen isn't a virtual sibling - // of the old one. This can be removed once platform plugins have the power to - // update the QScreen of its QWindows itself. - if (wasVisible && d->platformWindow) - setVisible(true); - } + d->setTopLevelScreen(newScreen, newScreen != 0); } /*! @@ -2059,12 +2055,61 @@ bool QWindow::event(QEvent *ev) break; #endif + case QEvent::Timer: { + Q_D(QWindow); + if (static_cast<QTimerEvent *>(ev)->timerId() == d->updateTimer) { + killTimer(d->updateTimer); + d->updateTimer = 0; + d->deliverUpdateRequest(); + } else { + QObject::event(ev); + } + break; + } + default: return QObject::event(ev); } return true; } +void QWindowPrivate::deliverUpdateRequest() +{ + Q_Q(QWindow); + updateRequestPending = false; + QEvent request(QEvent::UpdateRequest); + QCoreApplication::sendEvent(q, &request); +} + +/*! + Schedules a QEvent::UpdateRequest event to be delivered to this window. + + The event is delivered in sync with the display vsync on platforms + where this is possible. When driving animations, this function should + be called once after drawing has completed. + + Calling this function multiple times will result in a single event + being delivered to the window. + + Subclasses of QWindow should reimplement event(), intercept the event and + call the application's rendering code, then call the base class + implementation. + + \note The subclass' reimplementation of event() must invoke the base class + implementation, unless it is absolutely sure that the event does not need to + be handled by the base class. For example, the default implementation of + this function relies on QEvent::Timer events. Filtering them away would + therefore break the delivery of the update events. +*/ +void QWindow::requestUpdate() +{ + Q_D(QWindow); + if (d->updateRequestPending || !d->platformWindow) + return; + d->updateRequestPending = true; + d->platformWindow->requestUpdate(); +} + /*! Override this to handle key press events (\a ev). @@ -2206,10 +2251,12 @@ bool QWindow::nativeEvent(const QByteArray &eventType, void *message, long *resu QPoint QWindow::mapToGlobal(const QPoint &pos) const { Q_D(const QWindow); - if (d->platformWindow && d->platformWindow->isEmbedded(0)) + // QTBUG-43252, prefer platform implementation for foreign windows. + if (d->platformWindow + && (type() == Qt::ForeignWindow || d->platformWindow->isEmbedded(0))) { return d->platformWindow->mapToGlobal(pos); - else - return pos + d_func()->globalPosition(); + } + return pos + d_func()->globalPosition(); } @@ -2224,10 +2271,12 @@ QPoint QWindow::mapToGlobal(const QPoint &pos) const QPoint QWindow::mapFromGlobal(const QPoint &pos) const { Q_D(const QWindow); - if (d->platformWindow && d->platformWindow->isEmbedded(0)) + // QTBUG-43252, prefer platform implementation for foreign windows. + if (d->platformWindow + && (type() == Qt::ForeignWindow || d->platformWindow->isEmbedded(0))) { return d->platformWindow->mapFromGlobal(pos); - else - return pos - d_func()->globalPosition(); + } + return pos - d_func()->globalPosition(); } @@ -2244,24 +2293,22 @@ void QWindowPrivate::maybeQuitOnLastWindowClosed() Q_Q(QWindow); // Attempt to close the application only if this has WA_QuitOnClose set and a non-visible parent bool quitOnClose = QGuiApplication::quitOnLastWindowClosed() && !q->parent(); - - if (quitOnClose) { - QWindowList list = QGuiApplication::topLevelWindows(); - bool lastWindowClosed = true; - for (int i = 0; i < list.size(); ++i) { - QWindow *w = list.at(i); - if (!w->isVisible() || w->transientParent()) - continue; - lastWindowClosed = false; - break; - } - if (lastWindowClosed) { - QGuiApplicationPrivate::emitLastWindowClosed(); + QWindowList list = QGuiApplication::topLevelWindows(); + bool lastWindowClosed = true; + for (int i = 0; i < list.size(); ++i) { + QWindow *w = list.at(i); + if (!w->isVisible() || w->transientParent()) + continue; + lastWindowClosed = false; + break; + } + if (lastWindowClosed) { + QGuiApplicationPrivate::emitLastWindowClosed(); + if (quitOnClose) { QCoreApplicationPrivate *applicationPrivate = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance())); applicationPrivate->maybeQuit(); } } - } QWindow *QWindowPrivate::topLevelWindow() const |