diff options
Diffstat (limited to 'src/gui/kernel/qplatformwindow.cpp')
-rw-r--r-- | src/gui/kernel/qplatformwindow.cpp | 121 |
1 files changed, 55 insertions, 66 deletions
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index f9e984c9cb..5c0ae2ee2a 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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: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 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 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. -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qplatformwindow.h" #include "qplatformwindow_p.h" @@ -229,7 +193,7 @@ bool QPlatformWindow::isActive() const */ bool QPlatformWindow::isAncestorOf(const QPlatformWindow *child) const { - for (const QPlatformWindow *parent = child->parent(); parent; parent = child->parent()) { + for (const QPlatformWindow *parent = child->parent(); parent; parent = parent->parent()) { if (parent == this) return true; } @@ -406,18 +370,18 @@ void QPlatformWindow::setMask(const QRegion ®ion) Reimplement to let Qt be able to request activation/focus for a window Some window systems will probably not have callbacks for this functionality, - and then calling QWindowSystemInterface::handleWindowActivated(QWindow *w) + and then calling QWindowSystemInterface::handleFocusWindowChanged(QWindow *w) would be sufficient. If the window system has some event handling/callbacks then call - QWindowSystemInterface::handleWindowActivated(QWindow *w) when the window system + QWindowSystemInterface::handleFocusWindowChanged(QWindow *w) when the window system gives the notification. - Default implementation calls QWindowSystem::handleWindowActivated(QWindow *w) + Default implementation calls QWindowSystem::handleFocusWindowChanged(QWindow *w) */ void QPlatformWindow::requestActivateWindow() { - QWindowSystemInterface::handleWindowActivated(window()); + QWindowSystemInterface::handleFocusWindowChanged(window()); } /*! @@ -678,16 +642,16 @@ void QPlatformWindow::invalidateSurface() { } -static QSize fixInitialSize(QSize size, const QWindow *w, - int defaultWidth, int defaultHeight) +static QSize fixInitialSize(QSize size, const QWindow *w, int deviceIndependentDefaultWidth, + int deviceIndependentDefaultHeight) { if (size.width() == 0) { const int minWidth = w->minimumWidth(); - size.setWidth(minWidth > 0 ? minWidth : defaultWidth); + size.setWidth(minWidth > 0 ? minWidth : deviceIndependentDefaultWidth); } if (size.height() == 0) { const int minHeight = w->minimumHeight(); - size.setHeight(minHeight > 0 ? minHeight : defaultHeight); + size.setHeight(minHeight > 0 ? minHeight : deviceIndependentDefaultHeight); } return size; } @@ -700,6 +664,10 @@ static QSize fixInitialSize(QSize size, const QWindow *w, layout new windows to optimize usage of the available desktop space. However if the given window already has geometry which the application has initialized, it takes priority. + + \a initialGeometry has to be provided in native pixels. + \a defaultWidth has to be provided in device independent pixels + \a defaultHeight has to be provided in device independent pixels */ QRect QPlatformWindow::initialGeometry(const QWindow *w, const QRect &initialGeometry, int defaultWidth, int defaultHeight, @@ -709,9 +677,10 @@ QRect QPlatformWindow::initialGeometry(const QWindow *w, const QRect &initialGeo *resultingScreenReturn = w->screen(); if (!w->isTopLevel()) { const qreal factor = QHighDpiScaling::factor(w); - const QSize size = fixInitialSize(QHighDpi::fromNative(initialGeometry.size(), factor), - w, defaultWidth, defaultHeight); - return QRect(initialGeometry.topLeft(), QHighDpi::toNative(size, factor)); + const QSize deviceIndependentSize = + fixInitialSize(QHighDpi::fromNative(initialGeometry.size(), factor), w, + defaultWidth, defaultHeight); + return QRect(initialGeometry.topLeft(), QHighDpi::toNative(deviceIndependentSize, factor)); } const auto *wp = qt_window_private(const_cast<QWindow*>(w)); const bool position = wp->positionAutomatic && w->type() != Qt::Popup; @@ -725,26 +694,28 @@ QRect QPlatformWindow::initialGeometry(const QWindow *w, const QRect &initialGeo if (resultingScreenReturn) *resultingScreenReturn = screen; // initialGeometry refers to window's screen - QRect rect(QHighDpi::fromNativePixels(initialGeometry, w)); + QRect deviceIndependentRect(QHighDpi::fromNativePixels(initialGeometry, w)); if (wp->resizeAutomatic) - rect.setSize(fixInitialSize(rect.size(), w, defaultWidth, defaultHeight)); + deviceIndependentRect.setSize( + fixInitialSize(deviceIndependentRect.size(), w, defaultWidth, defaultHeight)); if (position) { - const QRect availableGeometry = screen->availableGeometry(); + const QRect availableDeviceIndependentGeometry = screen->availableGeometry(); // Center unless the geometry ( + unknown window frame) is too large for the screen). - if (rect.height() < (availableGeometry.height() * 8) / 9 - && rect.width() < (availableGeometry.width() * 8) / 9) { + if (deviceIndependentRect.height() < (availableDeviceIndependentGeometry.height() * 8) / 9 + && deviceIndependentRect.width() + < (availableDeviceIndependentGeometry.width() * 8) / 9) { const QWindow *tp = w->transientParent(); if (tp) { // A transient window should be centered w.r.t. its transient parent. - rect.moveCenter(tp->geometry().center()); + deviceIndependentRect.moveCenter(tp->geometry().center()); } else { // Center the window on the screen. (Only applicable on platforms // which do not provide a better way.) - rect.moveCenter(availableGeometry.center()); + deviceIndependentRect.moveCenter(availableDeviceIndependentGeometry.center()); } } } - return QHighDpi::toNativePixels(rect, screen); + return QHighDpi::toNativePixels(deviceIndependentRect, screen); } /*! @@ -756,20 +727,29 @@ QRect QPlatformWindow::initialGeometry(const QWindow *w, const QRect &initialGeo should be delivered using QPlatformWindow::deliverUpdateRequest() to not get out of sync with the internal state of QWindow. - The default implementation posts an UpdateRequest event to the - window after 5 ms. The additional time is there to give the event - loop a bit of idle time to gather system events. + The default implementation posts an UpdateRequest event to the window after + an interval that is at most 5 ms. If the window's associated screen reports + a \l{QPlatformScreen::refreshRate()}{refresh rate} higher than 60 Hz, the + interval is scaled down to a valid smaller than 5. The additional time is + there to give the event loop a bit of idle time to gather system events. */ void QPlatformWindow::requestUpdate() { Q_D(QPlatformWindow); - static int updateInterval = []() { - bool ok = false; - int customUpdateInterval = qEnvironmentVariableIntValue("QT_QPA_UPDATE_IDLE_TIME", &ok); - return ok ? customUpdateInterval : 5; - }(); + static bool customUpdateIntervalValid = false; + static int customUpdateInterval = qEnvironmentVariableIntValue("QT_QPA_UPDATE_IDLE_TIME", + &customUpdateIntervalValid); + int updateInterval = customUpdateInterval; + if (!customUpdateIntervalValid) { + updateInterval = 5; + if (QPlatformScreen *currentScreen = screen()) { + const qreal refreshRate = currentScreen->refreshRate(); + if (refreshRate > 60.0) + updateInterval /= refreshRate / 60.0; + } + } Q_ASSERT(!d->updateTimer.isActive()); d->updateTimer.start(updateInterval, Qt::PreciseTimer, window()); @@ -798,6 +778,15 @@ void QPlatformWindow::deliverUpdateRequest() QWindow *w = window(); QWindowPrivate *wp = qt_window_private(w); + + // We expect that the platform plugins send DevicePixelRatioChange events. + // As a fail-safe make a final check here to make sure the cached DPR value is + // always up to date before delivering the update request. + if (wp->updateDevicePixelRatio()) { + qWarning() << "The cached device pixel ratio value was stale on window update. " + << "Please file a QTBUG which explains how to reproduce."; + } + wp->updateRequestPending = false; QEvent request(QEvent::UpdateRequest); QCoreApplication::sendEvent(w, &request); |