summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel/qwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/kernel/qwindow.cpp')
-rw-r--r--src/gui/kernel/qwindow.cpp345
1 files changed, 227 insertions, 118 deletions
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index f2dacda0f5..b40fd7e8e8 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.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 "qwindow.h"
@@ -54,7 +18,7 @@
#include "qwindow_p.h"
#include "qguiapplication_p.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
# include "qaccessible.h"
#endif
#include "qhighdpiscaling_p.h"
@@ -164,7 +128,7 @@ QWindow::QWindow(QScreen *targetScreen)
, QSurface(QSurface::Window)
{
Q_D(QWindow);
- d->init(targetScreen);
+ d->init(nullptr, targetScreen);
}
static QWindow *nonDesktopParent(QWindow *parent)
@@ -205,11 +169,11 @@ QWindow::QWindow(QWindow *parent)
\sa setParent()
*/
QWindow::QWindow(QWindowPrivate &dd, QWindow *parent)
- : QObject(dd, nonDesktopParent(parent))
+ : QObject(dd, nullptr)
, QSurface(QSurface::Window)
{
Q_D(QWindow);
- d->init();
+ d->init(nonDesktopParent(parent));
}
/*!
@@ -219,6 +183,8 @@ QWindow::~QWindow()
{
Q_D(QWindow);
d->destroy();
+ // Decouple from parent before window goes under
+ setParent(nullptr);
QGuiApplicationPrivate::window_list.removeAll(this);
if (!QGuiApplicationPrivate::is_app_closing)
QGuiApplicationPrivate::instance()->modalWindowList.removeOne(this);
@@ -242,15 +208,19 @@ QWindowPrivate::QWindowPrivate()
QWindowPrivate::~QWindowPrivate()
= default;
-void QWindowPrivate::init(QScreen *targetScreen)
+void QWindowPrivate::init(QWindow *parent, QScreen *targetScreen)
{
Q_Q(QWindow);
+ q->QObject::setParent(parent);
+
isWindow = true;
parentWindow = static_cast<QWindow *>(q->QObject::parent());
+ QScreen *connectScreen = targetScreen ? targetScreen : QGuiApplication::primaryScreen();
+
if (!parentWindow)
- connectToScreen(targetScreen ? targetScreen : QGuiApplication::primaryScreen());
+ connectToScreen(connectScreen);
// If your application aborts here, you are probably creating a QWindow
// before the screen list is populated.
@@ -260,6 +230,27 @@ void QWindowPrivate::init(QScreen *targetScreen)
QGuiApplicationPrivate::window_list.prepend(q);
requestedFormat = QSurfaceFormat::defaultFormat();
+ devicePixelRatio = connectScreen->devicePixelRatio();
+
+ QObject::connect(q, &QWindow::screenChanged, q, [q, this](QScreen *){
+ // We may have changed scaling; trigger resize event if needed,
+ // except on Windows, where we send resize events during WM_DPICHANGED
+ // event handling. FIXME: unify DPI change handling across all platforms.
+#ifndef Q_OS_WIN
+ if (q->handle()) {
+ QWindowSystemInterfacePrivate::GeometryChangeEvent gce(q, QHighDpi::fromNativePixels(q->handle()->geometry(), q));
+ QGuiApplicationPrivate::processGeometryChangeEvent(&gce);
+ }
+#else
+ Q_UNUSED(q);
+#endif
+ updateDevicePixelRatio();
+ });
+
+ if (parentWindow) {
+ QChildWindowEvent childAddedEvent(QEvent::ChildWindowAdded, q);
+ QCoreApplication::sendEvent(parentWindow, &childAddedEvent);
+ }
}
/*!
@@ -464,14 +455,14 @@ void QWindowPrivate::updateSiblingPosition(SiblingPosition position)
QObjectList &siblings = q->parent()->d_ptr->children;
- const int siblingCount = siblings.size() - 1;
+ const qsizetype siblingCount = siblings.size() - 1;
if (siblingCount == 0)
return;
- const int currentPosition = siblings.indexOf(q);
+ const qsizetype currentPosition = siblings.indexOf(q);
Q_ASSERT(currentPosition >= 0);
- const int targetPosition = position == PositionTop ? siblingCount : 0;
+ const qsizetype targetPosition = position == PositionTop ? siblingCount : 0;
if (currentPosition == targetPosition)
return;
@@ -530,7 +521,9 @@ void QWindowPrivate::setTopLevelScreen(QScreen *newScreen, bool recreate)
}
}
-void QWindowPrivate::create(bool recursive, WId nativeHandle)
+static constexpr auto kForeignWindowId = "_q_foreignWinId";
+
+void QWindowPrivate::create(bool recursive)
{
Q_Q(QWindow);
if (platformWindow)
@@ -544,6 +537,13 @@ void QWindowPrivate::create(bool recursive, WId nativeHandle)
if (q->parent())
q->parent()->create();
+ if (platformWindow) {
+ // Creating the parent window will end up creating any child window
+ // that was already visible, via setVisible. If this applies to us,
+ // we will already have a platform window at this point.
+ return;
+ }
+
// QPlatformWindow will poll geometry() during construction below. Set the
// screen here so that high-dpi scaling will use the correct scale factor.
if (q->isTopLevel()) {
@@ -551,6 +551,8 @@ void QWindowPrivate::create(bool recursive, WId nativeHandle)
setTopLevelScreen(screen, false);
}
+ const WId nativeHandle = q->property(kForeignWindowId).value<WId>();
+
QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
platformWindow = nativeHandle ? platformIntegration->createForeignWindow(q, nativeHandle)
: platformIntegration->createPlatformWindow(q);
@@ -586,6 +588,8 @@ void QWindowPrivate::create(bool recursive, WId nativeHandle)
QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated);
QGuiApplication::sendEvent(q, &e);
+ updateDevicePixelRatio();
+
if (needsUpdate)
q->requestUpdate();
}
@@ -603,6 +607,37 @@ QRectF QWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const
return QRectF();
}
+void QWindowPrivate::setMinOrMaxSize(QSize *oldSizeMember, const QSize &size,
+ qxp::function_ref<void()> funcWidthChanged,
+ qxp::function_ref<void()> funcHeightChanged)
+{
+ Q_Q(QWindow);
+ Q_ASSERT(oldSizeMember);
+ const QSize adjustedSize =
+ size.expandedTo(QSize(0, 0)).boundedTo(QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX));
+ if (*oldSizeMember == adjustedSize)
+ return;
+ const bool widthChanged = adjustedSize.width() != oldSizeMember->width();
+ const bool heightChanged = adjustedSize.height() != oldSizeMember->height();
+ *oldSizeMember = adjustedSize;
+
+ if (platformWindow && q->isTopLevel())
+ platformWindow->propagateSizeHints();
+
+ if (widthChanged)
+ funcWidthChanged();
+ if (heightChanged)
+ funcHeightChanged();
+
+ // resize window if current size is outside of min and max limits
+ if (minimumSize.width() <= maximumSize.width()
+ || minimumSize.height() <= maximumSize.height()) {
+ const QSize currentSize = q->size();
+ const QSize boundedSize = currentSize.expandedTo(minimumSize).boundedTo(maximumSize);
+ q->resize(boundedSize);
+ }
+}
+
/*!
Sets the \a surfaceType of the window.
@@ -672,7 +707,7 @@ bool QWindow::isVisible() const
into an actual native surface. However, the window remains hidden until setVisible() is called.
Note that it is not usually necessary to call this function directly, as it will be implicitly
- called by show(), setVisible(), and other functions that require access to the platform
+ called by show(), setVisible(), winId(), and other functions that require access to the platform
resources.
Call destroy() to free the platform resources if necessary.
@@ -688,6 +723,9 @@ void QWindow::create()
/*!
Returns the window's platform id.
+ \note This function will cause the platform window to be created if it is not already.
+ Returns 0, if the platform window creation failed.
+
For platforms where this id might be useful, the value returned
will uniquely represent the window inside the corresponding screen.
@@ -700,6 +738,9 @@ WId QWindow::winId() const
if (!d->platformWindow)
const_cast<QWindow *>(this)->create();
+ if (!d->platformWindow)
+ return 0;
+
return d->platformWindow->winId();
}
@@ -743,6 +784,10 @@ void QWindow::setParent(QWindow *parent)
return;
}
+ QEvent parentAboutToChangeEvent(QEvent::ParentWindowAboutToChange);
+ QCoreApplication::sendEvent(this, &parentAboutToChangeEvent);
+
+ const auto previousParent = d->parentWindow;
QObject::setParent(parent);
d->parentWindow = parent;
@@ -765,6 +810,19 @@ void QWindow::setParent(QWindow *parent)
}
QGuiApplicationPrivate::updateBlockedStatus(this);
+
+ if (previousParent) {
+ QChildWindowEvent childRemovedEvent(QEvent::ChildWindowRemoved, this);
+ QCoreApplication::sendEvent(previousParent, &childRemovedEvent);
+ }
+
+ if (parent) {
+ QChildWindowEvent childAddedEvent(QEvent::ChildWindowAdded, this);
+ QCoreApplication::sendEvent(parent, &childAddedEvent);
+ }
+
+ QEvent parentChangedEvent(QEvent::ParentWindowChange);
+ QCoreApplication::sendEvent(this, &parentChangedEvent);
}
/*!
@@ -1256,6 +1314,8 @@ bool QWindow::isExposed() const
Typically active windows should appear active from a style perspective.
To get the window that currently has focus, use QGuiApplication::focusWindow().
+
+ \sa requestActivate()
*/
bool QWindow::isActive() const
{
@@ -1329,14 +1389,31 @@ Qt::ScreenOrientation QWindow::contentOrientation() const
qreal QWindow::devicePixelRatio() const
{
Q_D(const QWindow);
+ return d->devicePixelRatio;
+}
+
+/*
+ Updates the cached devicePixelRatio value by polling for a new value.
+ Sends QEvent::DevicePixelRatioChange to the window if the DPR has changed.
+ Returns true if the DPR was changed.
+*/
+bool QWindowPrivate::updateDevicePixelRatio()
+{
+ Q_Q(QWindow);
// If there is no platform window use the associated screen's devicePixelRatio,
// which typically is the primary screen and will be correct for single-display
// systems (a very common case).
- if (!d->platformWindow)
- return screen()->devicePixelRatio();
+ const qreal newDevicePixelRatio = platformWindow ?
+ platformWindow->devicePixelRatio() * QHighDpiScaling::factor(q) : q->screen()->devicePixelRatio();
- return d->platformWindow->devicePixelRatio() * QHighDpiScaling::factor(this);
+ if (newDevicePixelRatio == devicePixelRatio)
+ return false;
+
+ devicePixelRatio = newDevicePixelRatio;
+ QEvent dprChangeEvent(QEvent::DevicePixelRatioChange);
+ QGuiApplication::sendEvent(q, &dprChangeEvent);
+ return true;
}
Qt::WindowState QWindowPrivate::effectiveState(Qt::WindowStates state)
@@ -1391,8 +1468,13 @@ void QWindow::setWindowStates(Qt::WindowStates state)
if (d->platformWindow)
d->platformWindow->setWindowState(state);
+
+ auto originalEffectiveState = QWindowPrivate::effectiveState(d->windowState);
d->windowState = state;
- emit windowStateChanged(QWindowPrivate::effectiveState(d->windowState));
+ auto newEffectiveState = QWindowPrivate::effectiveState(d->windowState);
+ if (newEffectiveState != originalEffectiveState)
+ emit windowStateChanged(newEffectiveState);
+
d->updateVisibility();
}
@@ -1567,17 +1649,9 @@ QSize QWindow::sizeIncrement() const
void QWindow::setMinimumSize(const QSize &size)
{
Q_D(QWindow);
- QSize adjustedSize = QSize(qBound(0, size.width(), QWINDOWSIZE_MAX), qBound(0, size.height(), QWINDOWSIZE_MAX));
- if (d->minimumSize == adjustedSize)
- return;
- QSize oldSize = d->minimumSize;
- d->minimumSize = adjustedSize;
- if (d->platformWindow && isTopLevel())
- d->platformWindow->propagateSizeHints();
- if (d->minimumSize.width() != oldSize.width())
- emit minimumWidthChanged(d->minimumSize.width());
- if (d->minimumSize.height() != oldSize.height())
- emit minimumHeightChanged(d->minimumSize.height());
+ d->setMinOrMaxSize(
+ &d->minimumSize, size, [this, d]() { emit minimumWidthChanged(d->minimumSize.width()); },
+ [this, d]() { emit minimumHeightChanged(d->minimumSize.height()); });
}
/*!
@@ -1610,20 +1684,18 @@ void QWindow::setY(int arg)
\property QWindow::width
\brief the width of the window's geometry
*/
-void QWindow::setWidth(int arg)
+void QWindow::setWidth(int w)
{
- if (width() != arg)
- resize(arg, height());
+ resize(w, height());
}
/*!
\property QWindow::height
\brief the height of the window's geometry
*/
-void QWindow::setHeight(int arg)
+void QWindow::setHeight(int h)
{
- if (height() != arg)
- resize(width(), arg);
+ resize(width(), h);
}
/*!
@@ -1654,17 +1726,9 @@ void QWindow::setMinimumHeight(int h)
void QWindow::setMaximumSize(const QSize &size)
{
Q_D(QWindow);
- QSize adjustedSize = QSize(qBound(0, size.width(), QWINDOWSIZE_MAX), qBound(0, size.height(), QWINDOWSIZE_MAX));
- if (d->maximumSize == adjustedSize)
- return;
- QSize oldSize = d->maximumSize;
- d->maximumSize = adjustedSize;
- if (d->platformWindow && isTopLevel())
- d->platformWindow->propagateSizeHints();
- if (d->maximumSize.width() != oldSize.width())
- emit maximumWidthChanged(d->maximumSize.width());
- if (d->maximumSize.height() != oldSize.height())
- emit maximumHeightChanged(d->maximumSize.height());
+ d->setMinOrMaxSize(
+ &d->maximumSize, size, [this, d]() { emit maximumWidthChanged(d->maximumSize.width()); },
+ [this, d]() { emit maximumHeightChanged(d->maximumSize.height()); });
}
/*!
@@ -1891,6 +1955,10 @@ void QWindow::setFramePosition(const QPoint &point)
For interactively moving windows, see startSystemMove(). For interactively
resizing windows, see startSystemResize().
+ \note Not all windowing systems support setting or querying top level window positions.
+ On such a system, programmatically moving windows may not have any effect, and artificial
+ values may be returned for the current positions, such as \c QPoint(0, 0).
+
\sa position(), startSystemMove()
*/
void QWindow::setPosition(const QPoint &pt)
@@ -1914,6 +1982,10 @@ void QWindow::setPosition(int posx, int posy)
\fn QPoint QWindow::position() const
\brief Returns the position of the window on the desktop excluding any window frame
+ \note Not all windowing systems support setting or querying top level window positions.
+ On such a system, programmatically moving windows may not have any effect, and artificial
+ values may be returned for the current positions, such as \c QPoint(0, 0).
+
\sa setPosition()
*/
@@ -1945,12 +2017,16 @@ void QWindow::resize(int w, int h)
void QWindow::resize(const QSize &newSize)
{
Q_D(QWindow);
+
+ const QSize oldSize = size();
+ if (newSize == oldSize)
+ return;
+
d->positionPolicy = QWindowPrivate::WindowFrameExclusive;
if (d->platformWindow) {
d->platformWindow->setGeometry(
QHighDpi::toNativeWindowGeometry(QRect(position(), newSize), this));
} else {
- const QSize oldSize = d->geometry.size();
d->geometry.setSize(newSize);
if (newSize.width() != oldSize.width())
emit widthChanged(newSize.width());
@@ -1987,6 +2063,16 @@ void QWindowPrivate::destroy()
QObject *object = childrenWindows.at(i);
if (object->isWindowType()) {
QWindow *w = static_cast<QWindow*>(object);
+ auto *childPlatformWindow = w->handle();
+ if (!childPlatformWindow)
+ continue;
+
+ // Decouple the foreign window from this window,
+ // so that destroying our native handle doesn't
+ // bring down the foreign window as well.
+ if (childPlatformWindow->isForeignWindow())
+ childPlatformWindow->setParent(nullptr);
+
qt_window_private(w)->destroy();
}
}
@@ -2159,20 +2245,26 @@ QObject *QWindow::focusObject() const
/*!
Shows the window.
- This is equivalent to calling showFullScreen(), showMaximized(), or showNormal(),
+ For child windows, this is equivalent to calling showNormal().
+ Otherwise, it is equivalent to calling showFullScreen(), showMaximized(), or showNormal(),
depending on the platform's default behavior for the window type and flags.
\sa showFullScreen(), showMaximized(), showNormal(), hide(), QStyleHints::showIsFullScreen(), flags()
*/
void QWindow::show()
{
- Qt::WindowState defaultState = QGuiApplicationPrivate::platformIntegration()->defaultWindowState(d_func()->windowFlags);
- if (defaultState == Qt::WindowFullScreen)
- showFullScreen();
- else if (defaultState == Qt::WindowMaximized)
- showMaximized();
- else
+ if (parent()) {
showNormal();
+ } else {
+ const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
+ Qt::WindowState defaultState = platformIntegration->defaultWindowState(d_func()->windowFlags);
+ if (defaultState == Qt::WindowFullScreen)
+ showFullScreen();
+ else if (defaultState == Qt::WindowMaximized)
+ showMaximized();
+ else
+ showNormal();
+ }
}
/*!
@@ -2272,8 +2364,15 @@ bool QWindow::close()
if (!d->platformWindow)
return true;
- QBoolBlocker inCloseReset(d->inClose);
- return d->platformWindow->close();
+ // The window might be deleted during close,
+ // as a result of delivering the close event.
+ QPointer guard(this);
+ d->inClose = true;
+ bool success = d->platformWindow->close();
+ if (guard)
+ d->inClose = false;
+
+ return success;
}
bool QWindowPrivate::participatesInLastWindowClosed() const
@@ -2453,7 +2552,7 @@ bool QWindow::event(QEvent *ev)
case QEvent::FocusIn: {
focusInEvent(static_cast<QFocusEvent *>(ev));
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::State state;
state.active = true;
QAccessibleStateChangeEvent event(this, state);
@@ -2463,7 +2562,7 @@ bool QWindow::event(QEvent *ev)
case QEvent::FocusOut: {
focusOutEvent(static_cast<QFocusEvent *>(ev));
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::State state;
state.active = true;
QAccessibleStateChangeEvent event(this, state);
@@ -2517,13 +2616,6 @@ bool QWindow::event(QEvent *ev)
setIcon(icon());
break;
- case QEvent::WindowStateChange: {
- Q_D(QWindow);
- emit windowStateChanged(QWindowPrivate::effectiveState(d->windowState));
- d->updateVisibility();
- break;
- }
-
#if QT_CONFIG(tabletevent)
case QEvent::TabletPress:
case QEvent::TabletMove:
@@ -2583,11 +2675,13 @@ bool QWindow::event(QEvent *ev)
/*!
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. Otherwise, the event is delivered after a
- delay of 5 ms. The additional time is there to give the event loop
- a bit of idle time to gather system events, and can be overridden
- using the QT_QPA_UPDATE_IDLE_TIME environment variable.
+ The event is delivered in sync with the display vsync on platforms where
+ this is possible. Otherwise, the event is delivered after a delay of at
+ most 5 ms. If the window's associated screen reports a
+ \l{QScreen::refreshRate()}{refresh rate} higher than 60 Hz, the interval is
+ scaled down to a value smaller than 5. The additional time is there to give
+ the event loop a bit of idle time to gather system events, and can be
+ overridden using the QT_QPA_UPDATE_IDLE_TIME environment variable.
When driving animations, this function should be called once after drawing
has completed. Calling this function multiple times will result in a single
@@ -2763,7 +2857,7 @@ QPointF QWindow::mapToGlobal(const QPointF &pos) const
// QTBUG-43252, prefer platform implementation for foreign windows.
if (d->platformWindow
&& (d->platformWindow->isForeignWindow() || d->platformWindow->isEmbedded())) {
- return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapToGlobalF(QHighDpi::toNativeLocalPosition(pos, this)), this);
+ return QHighDpi::fromNativeGlobalPosition(d->platformWindow->mapToGlobalF(QHighDpi::toNativeLocalPosition(pos, this)), this);
}
if (!QHighDpiScaling::isActive())
@@ -2776,7 +2870,12 @@ QPointF QWindow::mapToGlobal(const QPointF &pos) const
// Map the position (and the window's global position) to native coordinates, perform
// the addition, and then map back to device independent coordinates.
QPointF nativeLocalPos = QHighDpi::toNativeLocalPosition(pos, this);
- QPointF nativeWindowGlobalPos = QHighDpi::toNativeGlobalPosition(QPointF(d->globalPosition()), this);
+ // Get the native window position directly from the platform window
+ // if available (it can be null if the window hasn't been shown yet),
+ // or fall back to scaling the QWindow position.
+ QPointF nativeWindowGlobalPos = d->platformWindow
+ ? d->platformWindow->mapToGlobal(QPoint(0,0)).toPointF()
+ : QHighDpi::toNativeGlobalPosition(QPointF(d->globalPosition()), this);
QPointF nativeGlobalPos = nativeLocalPos + nativeWindowGlobalPos;
QPointF deviceIndependentGlobalPos = QHighDpi::fromNativeGlobalPosition(nativeGlobalPos, this);
return deviceIndependentGlobalPos;
@@ -2805,7 +2904,7 @@ QPointF QWindow::mapFromGlobal(const QPointF &pos) const
// QTBUG-43252, prefer platform implementation for foreign windows.
if (d->platformWindow
&& (d->platformWindow->isForeignWindow() || d->platformWindow->isEmbedded())) {
- return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapFromGlobalF(QHighDpi::toNativeLocalPosition(pos, this)), this);
+ return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapFromGlobalF(QHighDpi::toNativeGlobalPosition(pos, this)), this);
}
if (!QHighDpiScaling::isActive())
@@ -2814,7 +2913,12 @@ QPointF QWindow::mapFromGlobal(const QPointF &pos) const
// Calculate local position in the native coordinate system. (See comment for the
// corresponding mapToGlobal() code above).
QPointF nativeGlobalPos = QHighDpi::toNativeGlobalPosition(pos, this);
- QPointF nativeWindowGlobalPos = QHighDpi::toNativeGlobalPosition(QPointF(d->globalPosition()), this);
+ // Get the native window position directly from the platform window
+ // if available (it can be null if the window hasn't been shown yet),
+ // or fall back to scaling the QWindow position.
+ QPointF nativeWindowGlobalPos = d->platformWindow
+ ? d->platformWindow->mapToGlobal(QPoint(0,0)).toPointF()
+ : QHighDpi::toNativeGlobalPosition(QPointF(d->globalPosition()), this);
QPointF nativeLocalPos = nativeGlobalPos - nativeWindowGlobalPos;
QPointF deviceIndependentLocalPos = QHighDpi::fromNativeLocalPosition(nativeLocalPos, this);
return deviceIndependentLocalPos;
@@ -2867,13 +2971,6 @@ QWindow *QWindowPrivate::topLevelWindow(QWindow::AncestorMode mode) const
return window;
}
-#if QT_CONFIG(opengl)
-QOpenGLContext *QWindowPrivate::shareContext() const
-{
- return qt_gl_global_share_context();
-};
-#endif
-
/*!
Creates a local representation of a window created by another process or by
using native libraries below Qt.
@@ -2903,7 +3000,11 @@ QWindow *QWindow::fromWinId(WId id)
}
QWindow *window = new QWindow;
- qt_window_private(window)->create(false, id);
+
+ // Persist the winId in a private property so that we
+ // can recreate the window after being destroyed.
+ window->setProperty(kForeignWindowId, id);
+ window->create();
if (!window->handle()) {
delete window;
@@ -3052,6 +3153,14 @@ void *QWindow::resolveInterface(const char *name, int revision) const
QT_NATIVE_INTERFACE_RETURN_IF(QCocoaWindow, platformWindow);
#endif
+#if QT_CONFIG(wayland)
+ QT_NATIVE_INTERFACE_RETURN_IF(QWaylandWindow, platformWindow);
+#endif
+
+#if defined(Q_OS_WASM)
+ QT_NATIVE_INTERFACE_RETURN_IF(QWasmWindow, platformWindow);
+#endif
+
return nullptr;
}
@@ -3094,7 +3203,7 @@ QDebug operator<<(QDebug debug, const QWindow *window)
}
#endif // !QT_NO_DEBUG_STREAM
-#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(vulkan) || defined(Q_QDOC)
/*!
Associates this window with the specified Vulkan \a instance.