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.cpp334
1 files changed, 214 insertions, 120 deletions
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 9e5b687851..3e5777ad49 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -45,6 +45,7 @@
#ifndef QT_NO_OPENGL
#include <qpa/qplatformopenglcontext.h>
#include "qopenglcontext.h"
+#include "qopenglcontext_p.h"
#endif
#include "qscreen.h"
@@ -117,7 +118,7 @@ QT_BEGIN_NAMESPACE
application, isExposed() will simply return the same value as isVisible().
QWindow::Visibility queried through visibility() is a convenience API
- combining the functions of visible() and windowState().
+ combining the functions of visible() and windowStates().
\section1 Rendering
@@ -318,34 +319,104 @@ void QWindow::setVisibility(Visibility v)
}
}
-void QWindowPrivate::updateVisibility()
+/*
+ Subclasses may override this function to run custom setVisible
+ logic. Subclasses that do so must call the base class implementation
+ at some point to make the native window visible, and must not
+ call QWindow::setVisble() since that will recurse back here.
+*/
+void QWindowPrivate::setVisible(bool visible)
{
Q_Q(QWindow);
- QWindow::Visibility old = visibility;
+ if (this->visible != visible) {
+ this->visible = visible;
+ emit q->visibleChanged(visible);
+ updateVisibility();
+ } else if (platformWindow) {
+ // Visibility hasn't changed, and the platform window is in sync
+ return;
+ }
+
+ if (!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 (parentWindow && !parentWindow->handle())
+ return;
+
+ // We only need to create the window if it's being shown
+ if (visible)
+ q->create();
+ }
if (visible) {
- switch (windowState) {
- case Qt::WindowMinimized:
- visibility = QWindow::Minimized;
- break;
- case Qt::WindowMaximized:
- visibility = QWindow::Maximized;
- break;
- case Qt::WindowFullScreen:
- visibility = QWindow::FullScreen;
- break;
- case Qt::WindowNoState:
- visibility = QWindow::Windowed;
- break;
- default:
- Q_ASSERT(false);
- break;
+ // remove posted quit events when showing a new window
+ QCoreApplication::removePostedEvents(qApp, QEvent::Quit);
+
+ if (q->type() == Qt::Window) {
+ QGuiApplicationPrivate *app_priv = QGuiApplicationPrivate::instance();
+ QString &firstWindowTitle = app_priv->firstWindowTitle;
+ if (!firstWindowTitle.isEmpty()) {
+ q->setTitle(firstWindowTitle);
+ firstWindowTitle = QString();
+ }
+ if (!app_priv->forcedWindowIcon.isNull())
+ q->setIcon(app_priv->forcedWindowIcon);
+
+ // Handling of the -qwindowgeometry, -geometry command line arguments
+ static bool geometryApplied = false;
+ if (!geometryApplied) {
+ geometryApplied = true;
+ QGuiApplicationPrivate::applyWindowGeometrySpecificationTo(q);
+ }
}
- } else {
- visibility = QWindow::Hidden;
+
+ QShowEvent showEvent;
+ QGuiApplication::sendEvent(q, &showEvent);
}
+ if (q->isModal()) {
+ if (visible)
+ QGuiApplicationPrivate::showModalWindow(q);
+ else
+ QGuiApplicationPrivate::hideModalWindow(q);
+ // QShapedPixmapWindow is used on some platforms for showing a drag pixmap, so don't block
+ // input to this window as it is performing a drag - QTBUG-63846
+ } else if (visible && QGuiApplication::modalWindow() && !qobject_cast<QShapedPixmapWindow *>(q)) {
+ QGuiApplicationPrivate::updateBlockedStatus(q);
+ }
+
+#ifndef QT_NO_CURSOR
+ if (visible && (hasCursor || QGuiApplication::overrideCursor()))
+ applyCursor();
+#endif
+
+ if (platformWindow)
+ platformWindow->setVisible(visible);
+
+ if (!visible) {
+ QHideEvent hideEvent;
+ QGuiApplication::sendEvent(q, &hideEvent);
+ }
+}
+
+void QWindowPrivate::updateVisibility()
+{
+ Q_Q(QWindow);
+
+ QWindow::Visibility old = visibility;
+
+ if (!visible)
+ visibility = QWindow::Hidden;
+ else if (windowState & Qt::WindowMinimized)
+ visibility = QWindow::Minimized;
+ else if (windowState & Qt::WindowFullScreen)
+ visibility = QWindow::FullScreen;
+ else if (windowState & Qt::WindowMaximized)
+ visibility = QWindow::Maximized;
+ else
+ visibility = QWindow::Windowed;
+
if (visibility != old)
emit q->visibilityChanged(visibility);
}
@@ -444,6 +515,8 @@ void QWindowPrivate::create(bool recursive, WId nativeHandle)
return;
}
+ platformWindow->initialize();
+
QObjectList childObjects = q->children();
for (int i = 0; i < childObjects.size(); i ++) {
QObject *object = childObjects.at(i);
@@ -526,75 +599,7 @@ void QWindow::setVisible(bool visible)
{
Q_D(QWindow);
- 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;
- }
-
- 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;
-
- // We only need to create the window if it's being shown
- if (visible)
- create();
- }
-
- if (visible) {
- // remove posted quit events when showing a new window
- QCoreApplication::removePostedEvents(qApp, QEvent::Quit);
-
- if (type() == Qt::Window) {
- QGuiApplicationPrivate *app_priv = QGuiApplicationPrivate::instance();
- QString &firstWindowTitle = app_priv->firstWindowTitle;
- if (!firstWindowTitle.isEmpty()) {
- setTitle(firstWindowTitle);
- firstWindowTitle = QString();
- }
- if (!app_priv->forcedWindowIcon.isNull())
- setIcon(app_priv->forcedWindowIcon);
-
- // Handling of the -qwindowgeometry, -geometry command line arguments
- static bool geometryApplied = false;
- if (!geometryApplied) {
- geometryApplied = true;
- QGuiApplicationPrivate::applyWindowGeometrySpecificationTo(this);
- }
- }
-
- QShowEvent showEvent;
- QGuiApplication::sendEvent(this, &showEvent);
- }
-
- if (isModal()) {
- if (visible)
- QGuiApplicationPrivate::showModalWindow(this);
- else
- QGuiApplicationPrivate::hideModalWindow(this);
- // QShapedPixmapWindow is used on some platforms for showing a drag pixmap, so don't block
- // input to this window as it is performing a drag - QTBUG-63846
- } else if (visible && QGuiApplication::modalWindow() && !qobject_cast<QShapedPixmapWindow *>(this)) {
- QGuiApplicationPrivate::updateBlockedStatus(this);
- }
-
-#ifndef QT_NO_CURSOR
- if (visible && (d->hasCursor || QGuiApplication::overrideCursor()))
- d->applyCursor();
-#endif
-
- if (d->platformWindow)
- d->platformWindow->setVisible(visible);
-
- if (!visible) {
- QHideEvent hideEvent;
- QGuiApplication::sendEvent(this, &hideEvent);
- }
+ d->setVisible(visible);
}
bool QWindow::isVisible() const
@@ -970,6 +975,11 @@ QString QWindow::filePath() const
The window icon might be used by the windowing system for example to
decorate the window, and/or in the task switcher.
+
+ \note On \macos, the window title bar icon is meant for windows representing
+ documents, and will only show up if a file path is also set.
+
+ \sa setFilePath()
*/
void QWindow::setIcon(const QIcon &icon)
{
@@ -982,7 +992,7 @@ void QWindow::setIcon(const QIcon &icon)
}
/*!
- \brief Sets the window's icon in the windowing system
+ \brief Returns the window's icon in the windowing system
\sa setIcon()
*/
@@ -1065,15 +1075,12 @@ qreal QWindow::opacity() const
The window manager may or may not choose to display any areas of the window
not included in the mask, thus it is the application's responsibility to
clear to transparent the areas that are not part of the mask.
-
- Setting the mask before the window has been created has no effect.
*/
void QWindow::setMask(const QRegion &region)
{
Q_D(QWindow);
- if (!d->platformWindow)
- return;
- d->platformWindow->setMask(QHighDpi::toNativeLocalRegion(region, this));
+ if (d->platformWindow)
+ d->platformWindow->setMask(QHighDpi::toNativeLocalRegion(region, this));
d->mask = region;
}
@@ -1220,6 +1227,17 @@ qreal QWindow::devicePixelRatio() const
return d->platformWindow->devicePixelRatio() * QHighDpiScaling::factor(this);
}
+Qt::WindowState QWindowPrivate::effectiveState(Qt::WindowStates state)
+{
+ if (state & Qt::WindowMinimized)
+ return Qt::WindowMinimized;
+ else if (state & Qt::WindowFullScreen)
+ return Qt::WindowFullScreen;
+ else if (state & Qt::WindowMaximized)
+ return Qt::WindowMaximized;
+ return Qt::WindowNoState;
+}
+
/*!
\brief set the screen-occupation state of the window
@@ -1228,31 +1246,69 @@ qreal QWindow::devicePixelRatio() const
The enum value Qt::WindowActive is not an accepted parameter.
- \sa showNormal(), showFullScreen(), showMinimized(), showMaximized()
+ \sa showNormal(), showFullScreen(), showMinimized(), showMaximized(), setWindowStates()
*/
void QWindow::setWindowState(Qt::WindowState state)
{
- if (state == Qt::WindowActive) {
- qWarning("QWindow::setWindowState does not accept Qt::WindowActive");
- return;
- }
+ setWindowStates(state);
+}
+
+/*!
+ \brief set the screen-occupation state of the window
+ \since 5.10
+
+ The window \a state represents whether the window appears in the
+ windowing system as maximized, minimized and/or fullscreen.
+ The window can be in a combination of several states. For example, if
+ the window is both minimized and maximized, the window will appear
+ minimized, but clicking on the task bar entry will restore it to the
+ maximized state.
+
+ The enum value Qt::WindowActive should not be set.
+
+ \sa showNormal(), showFullScreen(), showMinimized(), showMaximized()
+ */
+void QWindow::setWindowStates(Qt::WindowStates state)
+{
Q_D(QWindow);
+ if (state & Qt::WindowActive) {
+ qWarning("QWindow::setWindowStates does not accept Qt::WindowActive");
+ state &= ~Qt::WindowActive;
+ }
+
if (d->platformWindow)
d->platformWindow->setWindowState(state);
d->windowState = state;
- emit windowStateChanged(d->windowState);
+ emit windowStateChanged(QWindowPrivate::effectiveState(d->windowState));
d->updateVisibility();
}
/*!
\brief the screen-occupation state of the window
- \sa setWindowState()
+ \sa setWindowState(), windowStates()
*/
Qt::WindowState QWindow::windowState() const
{
Q_D(const QWindow);
+ return QWindowPrivate::effectiveState(d->windowState);
+}
+
+/*!
+ \brief the screen-occupation state of the window
+ \since 5.10
+
+ The window can be in a combination of several states. For example, if
+ the window is both minimized and maximized, the window will appear
+ minimized, but clicking on the task bar entry will restore it to
+ the maximized state.
+
+ \sa setWindowStates()
+*/
+Qt::WindowStates QWindow::windowStates() const
+{
+ Q_D(const QWindow);
return d->windowState;
}
@@ -1260,7 +1316,7 @@ Qt::WindowState QWindow::windowState() const
\fn QWindow::windowStateChanged(Qt::WindowState windowState)
This signal is emitted when the \a windowState changes, either
- by being set explicitly with setWindowState(), or automatically when
+ by being set explicitly with setWindowStates(), or automatically when
the user clicks one of the titlebar buttons or by other means.
*/
@@ -1835,11 +1891,16 @@ void QWindowPrivate::destroy()
QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed);
QGuiApplication::sendEvent(q, &e);
- delete platformWindow;
+ // Unset platformWindow before deleting, so that the destructor of the
+ // platform window does not recurse back into the platform window via
+ // this window during destruction (e.g. as a result of platform events).
+ QPlatformWindow *pw = platformWindow;
+ platformWindow = nullptr;
+ delete pw;
+
resizeEventPending = true;
receivedExpose = false;
exposed = false;
- platformWindow = 0;
if (wasVisible)
maybeQuitOnLastWindowClosed();
@@ -2006,42 +2067,42 @@ void QWindow::hide()
/*!
Shows the window as minimized.
- Equivalent to calling setWindowState(Qt::WindowMinimized) and then
+ Equivalent to calling setWindowStates(Qt::WindowMinimized) and then
setVisible(true).
- \sa setWindowState(), setVisible()
+ \sa setWindowStates(), setVisible()
*/
void QWindow::showMinimized()
{
- setWindowState(Qt::WindowMinimized);
+ setWindowStates(Qt::WindowMinimized);
setVisible(true);
}
/*!
Shows the window as maximized.
- Equivalent to calling setWindowState(Qt::WindowMaximized) and then
+ Equivalent to calling setWindowStates(Qt::WindowMaximized) and then
setVisible(true).
- \sa setWindowState(), setVisible()
+ \sa setWindowStates(), setVisible()
*/
void QWindow::showMaximized()
{
- setWindowState(Qt::WindowMaximized);
+ setWindowStates(Qt::WindowMaximized);
setVisible(true);
}
/*!
Shows the window as fullscreen.
- Equivalent to calling setWindowState(Qt::WindowFullScreen) and then
+ Equivalent to calling setWindowStates(Qt::WindowFullScreen) and then
setVisible(true).
- \sa setWindowState(), setVisible()
+ \sa setWindowStates(), setVisible()
*/
void QWindow::showFullScreen()
{
- setWindowState(Qt::WindowFullScreen);
+ setWindowStates(Qt::WindowFullScreen);
setVisible(true);
#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
// activating it here before libscreen activates it causes problems
@@ -2052,14 +2113,14 @@ void QWindow::showFullScreen()
/*!
Shows the window as normal, i.e. neither maximized, minimized, nor fullscreen.
- Equivalent to calling setWindowState(Qt::WindowNoState) and then
+ Equivalent to calling setWindowStates(Qt::WindowNoState) and then
setVisible(true).
- \sa setWindowState(), setVisible()
+ \sa setWindowStates(), setVisible()
*/
void QWindow::showNormal()
{
- setWindowState(Qt::WindowNoState);
+ setWindowStates(Qt::WindowNoState);
setVisible(true);
}
@@ -2255,7 +2316,7 @@ bool QWindow::event(QEvent *ev)
case QEvent::WindowStateChange: {
Q_D(QWindow);
- emit windowStateChanged(d->windowState);
+ emit windowStateChanged(QWindowPrivate::effectiveState(d->windowState));
d->updateVisibility();
break;
}
@@ -2517,7 +2578,7 @@ QPoint QWindowPrivate::globalPosition() const
QPoint offset = q->position();
for (const QWindow *p = q->parent(); p; p = p->parent()) {
QPlatformWindow *pw = p->handle();
- if (pw && pw->isForeignWindow()) {
+ if (pw && (pw->isForeignWindow() || pw->isEmbedded())) {
// Use mapToGlobal() for foreign windows
offset += p->mapToGlobal(QPoint(0, 0));
break;
@@ -2576,6 +2637,13 @@ QWindow *QWindowPrivate::topLevelWindow() 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.
@@ -2722,6 +2790,8 @@ bool QWindowPrivate::applyCursor()
if (!platformWindow)
return true;
QCursor *c = QGuiApplication::overrideCursor();
+ if (c != nullptr && platformCursor->capabilities().testFlag(QPlatformCursor::OverrideCursor))
+ return true;
if (!c && hasCursor)
c = &cursor;
platformCursor->changeCursor(c, q);
@@ -2771,6 +2841,30 @@ QDebug operator<<(QDebug debug, const QWindow *window)
}
#endif // !QT_NO_DEBUG_STREAM
+#if QT_CONFIG(vulkan)
+
+/*!
+ Associates this window with the specified Vulkan \a instance.
+
+ \a instance must stay valid as long as this QWindow instance exists.
+ */
+void QWindow::setVulkanInstance(QVulkanInstance *instance)
+{
+ Q_D(QWindow);
+ d->vulkanInstance = instance;
+}
+
+/*!
+ \return the associrated Vulkan instance or \c null if there is none.
+ */
+QVulkanInstance *QWindow::vulkanInstance() const
+{
+ Q_D(const QWindow);
+ return d->vulkanInstance;
+}
+
+#endif // QT_CONFIG(vulkan)
+
QT_END_NAMESPACE
#include "moc_qwindow.cpp"