| /**************************************************************************** |
| ** |
| ** 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$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qwindow.h" |
| |
| #include <qpa/qplatformwindow.h> |
| #include <qpa/qplatformintegration.h> |
| #include "qsurfaceformat.h" |
| #ifndef QT_NO_OPENGL |
| #include <qpa/qplatformopenglcontext.h> |
| #include "qopenglcontext.h" |
| #include "qopenglcontext_p.h" |
| #endif |
| #include "qscreen.h" |
| |
| #include "qwindow_p.h" |
| #include "qguiapplication_p.h" |
| #ifndef QT_NO_ACCESSIBILITY |
| # include "qaccessible.h" |
| #endif |
| #include "qhighdpiscaling_p.h" |
| #if QT_CONFIG(draganddrop) |
| #include "qshapedpixmapdndwindow_p.h" |
| #endif // QT_CONFIG(draganddrop) |
| |
| #include <private/qevent_p.h> |
| |
| #include <QtCore/QTimer> |
| #include <QtCore/QDebug> |
| |
| #include <QStyleHints> |
| #include <qpa/qplatformcursor.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| /*! |
| \class QWindow |
| \inmodule QtGui |
| \since 5.0 |
| \brief The QWindow class represents a window in the underlying windowing system. |
| |
| A window that is supplied a parent becomes a native child window of |
| their parent window. |
| |
| An application will typically use QWidget or QQuickView for its UI, and not |
| QWindow directly. Still, it is possible to render directly to a QWindow |
| with QBackingStore or QOpenGLContext, when wanting to keep dependencies to |
| a minimum or when wanting to use OpenGL directly. The |
| \l{Raster Window Example} and \l{OpenGL Window Example} |
| are useful reference examples for how to render to a QWindow using |
| either approach. |
| |
| \section1 Resource Management |
| |
| Windows can potentially use a lot of memory. A usual measurement is |
| width times height times color depth. A window might also include multiple |
| buffers to support double and triple buffering, as well as depth and stencil |
| buffers. To release a window's memory resources, call the destroy() function. |
| |
| \section1 Content Orientation |
| |
| QWindow has reportContentOrientationChange() that can be used to specify |
| the layout of the window contents in relation to the screen. The content |
| orientation is simply a hint to the windowing system about which |
| orientation the window contents are in. It's useful when you wish to keep |
| the same window size, but rotate the contents instead, especially when |
| doing rotation animations between different orientations. The windowing |
| system might use this value to determine the layout of system popups or |
| dialogs. |
| |
| \section1 Visibility and Windowing System Exposure |
| |
| By default, the window is not visible, and you must call setVisible(true), |
| or show() or similar to make it visible. To make a window hidden again, |
| call setVisible(false) or hide(). The visible property describes the state |
| the application wants the window to be in. Depending on the underlying |
| system, a visible window might still not be shown on the screen. It could, |
| for instance, be covered by other opaque windows or moved outside the |
| physical area of the screen. On windowing systems that have exposure |
| notifications, the isExposed() accessor describes whether the window should |
| be treated as directly visible on screen. The exposeEvent() function is |
| called whenever an area of the window is invalidated, for example due to the |
| exposure in the windowing system changing. On windowing systems that do not |
| make this information visible to the 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 windowStates(). |
| |
| \section1 Rendering |
| |
| There are two Qt APIs that can be used to render content into a window, |
| QBackingStore for rendering with a QPainter and flushing the contents |
| to a window with type QSurface::RasterSurface, and QOpenGLContext for |
| rendering with OpenGL to a window with type QSurface::OpenGLSurface. |
| |
| The application can start rendering as soon as isExposed() returns \c true, |
| and can keep rendering until it isExposed() returns \c false. To find out when |
| isExposed() changes, reimplement exposeEvent(). The window will always get |
| a resize event before the first expose event. |
| |
| \section1 Initial Geometry |
| |
| If the window's width and height are left uninitialized, the window will |
| get a reasonable default geometry from the platform window. If the position |
| is left uninitialized, then the platform window will allow the windowing |
| system to position the window. For example on X11, the window manager |
| usually does some kind of smart positioning to try to avoid having new |
| windows completely obscure existing windows. However setGeometry() |
| initializes both the position and the size, so if you want a fixed size but |
| an automatic position, you should call resize() or setWidth() and |
| setHeight() instead. |
| */ |
| |
| /*! |
| Creates a window as a top level on the \a targetScreen. |
| |
| The window is not shown until setVisible(true), show(), or similar is called. |
| |
| \sa setScreen() |
| */ |
| QWindow::QWindow(QScreen *targetScreen) |
| : QObject(*new QWindowPrivate(), nullptr) |
| , QSurface(QSurface::Window) |
| { |
| Q_D(QWindow); |
| d->init(targetScreen); |
| } |
| |
| static QWindow *nonDesktopParent(QWindow *parent) |
| { |
| if (parent && parent->type() == Qt::Desktop) { |
| qWarning("QWindows cannot be reparented into desktop windows"); |
| return nullptr; |
| } |
| |
| return parent; |
| } |
| |
| /*! |
| Creates a window as a child of the given \a parent window. |
| |
| The window will be embedded inside the parent window, its coordinates |
| relative to the parent. |
| |
| The screen is inherited from the parent. |
| |
| \sa setParent() |
| */ |
| QWindow::QWindow(QWindow *parent) |
| : QWindow(*new QWindowPrivate(), parent) |
| { |
| } |
| |
| /*! |
| Creates a window as a child of the given \a parent window with the \a dd |
| private implementation. |
| |
| The window will be embedded inside the parent window, its coordinates |
| relative to the parent. |
| |
| The screen is inherited from the parent. |
| |
| \internal |
| \sa setParent() |
| */ |
| QWindow::QWindow(QWindowPrivate &dd, QWindow *parent) |
| : QObject(dd, nonDesktopParent(parent)) |
| , QSurface(QSurface::Window) |
| { |
| Q_D(QWindow); |
| d->init(); |
| } |
| |
| /*! |
| Destroys the window. |
| */ |
| QWindow::~QWindow() |
| { |
| Q_D(QWindow); |
| d->destroy(); |
| QGuiApplicationPrivate::window_list.removeAll(this); |
| if (!QGuiApplicationPrivate::is_app_closing) |
| QGuiApplicationPrivate::instance()->modalWindowList.removeOne(this); |
| |
| // focus_window is normally cleared in destroy(), but the window may in |
| // some cases end up becoming the focus window again. Clear it again |
| // here as a workaround. See QTBUG-75326. |
| if (QGuiApplicationPrivate::focus_window == this) |
| QGuiApplicationPrivate::focus_window = nullptr; |
| } |
| |
| void QWindowPrivate::init(QScreen *targetScreen) |
| { |
| Q_Q(QWindow); |
| |
| parentWindow = static_cast<QWindow *>(q->QObject::parent()); |
| |
| if (!parentWindow) |
| connectToScreen(targetScreen ? targetScreen : QGuiApplication::primaryScreen()); |
| |
| // If your application aborts here, you are probably creating a QWindow |
| // before the screen list is populated. |
| if (Q_UNLIKELY(!parentWindow && !topLevelScreen)) { |
| qFatal("Cannot create window: no screens available"); |
| exit(1); |
| } |
| QGuiApplicationPrivate::window_list.prepend(q); |
| |
| requestedFormat = QSurfaceFormat::defaultFormat(); |
| } |
| |
| /*! |
| \enum QWindow::Visibility |
| \since 5.1 |
| |
| This enum describes what part of the screen the window occupies or should |
| occupy. |
| |
| \value Windowed The window occupies part of the screen, but not necessarily |
| the entire screen. This state will occur only on windowing systems which |
| support showing multiple windows simultaneously. In this state it is |
| possible for the user to move and resize the window manually, if |
| WindowFlags permit it and if it is supported by the windowing system. |
| |
| \value Minimized The window is reduced to an entry or icon on the task bar, |
| dock, task list or desktop, depending on how the windowing system handles |
| minimized windows. |
| |
| \value Maximized The window occupies one entire screen, and the titlebar is |
| still visible. On most windowing systems this is the state achieved by |
| clicking the maximize button on the toolbar. |
| |
| \value FullScreen The window occupies one entire screen, is not resizable, |
| and there is no titlebar. On some platforms which do not support showing |
| multiple simultaneous windows, this can be the usual visibility when the |
| window is not hidden. |
| |
| \value AutomaticVisibility This means to give the window a default visible |
| state, which might be fullscreen or windowed depending on the platform. |
| It can be given as a parameter to setVisibility but will never be |
| read back from the visibility accessor. |
| |
| \value Hidden The window is not visible in any way, however it may remember |
| a latent visibility which can be restored by setting AutomaticVisibility. |
| */ |
| |
| /*! |
| \property QWindow::visibility |
| \brief the screen-occupation state of the window |
| \since 5.1 |
| |
| Visibility is whether the window should appear in the windowing system as |
| normal, minimized, maximized, fullscreen or hidden. |
| |
| To set the visibility to AutomaticVisibility means to give the window |
| a default visible state, which might be fullscreen or windowed depending on |
| the platform. |
| When reading the visibility property you will always get the actual state, |
| never AutomaticVisibility. |
| */ |
| QWindow::Visibility QWindow::visibility() const |
| { |
| Q_D(const QWindow); |
| return d->visibility; |
| } |
| |
| void QWindow::setVisibility(Visibility v) |
| { |
| switch (v) { |
| case Hidden: |
| hide(); |
| break; |
| case AutomaticVisibility: |
| show(); |
| break; |
| case Windowed: |
| showNormal(); |
| break; |
| case Minimized: |
| showMinimized(); |
| break; |
| case Maximized: |
| showMaximized(); |
| break; |
| case FullScreen: |
| showFullScreen(); |
| break; |
| default: |
| Q_ASSERT(false); |
| break; |
| } |
| } |
| |
| /* |
| 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); |
| |
| 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) { |
| // 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); |
| } |
| } |
| |
| 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() |
| #if QT_CONFIG(draganddrop) |
| && !qobject_cast<QShapedPixmapWindow *>(q) |
| #endif // QT_CONFIG(draganddrop) |
| ) { |
| 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); |
| } |
| |
| void QWindowPrivate::updateSiblingPosition(SiblingPosition position) |
| { |
| Q_Q(QWindow); |
| |
| if (!q->parent()) |
| return; |
| |
| QObjectList &siblings = q->parent()->d_ptr->children; |
| |
| const int siblingCount = siblings.size() - 1; |
| if (siblingCount == 0) |
| return; |
| |
| const int currentPosition = siblings.indexOf(q); |
| Q_ASSERT(currentPosition >= 0); |
| |
| const int targetPosition = position == PositionTop ? siblingCount : 0; |
| |
| if (currentPosition == targetPosition) |
| return; |
| |
| siblings.move(currentPosition, targetPosition); |
| } |
| |
| inline bool QWindowPrivate::windowRecreationRequired(QScreen *newScreen) const |
| { |
| Q_Q(const QWindow); |
| const QScreen *oldScreen = q->screen(); |
| return oldScreen != newScreen && (platformWindow || !oldScreen) |
| && !(oldScreen && oldScreen->virtualSiblings().contains(newScreen)); |
| } |
| |
| inline void QWindowPrivate::disconnectFromScreen() |
| { |
| if (topLevelScreen) |
| topLevelScreen = nullptr; |
| } |
| |
| void QWindowPrivate::connectToScreen(QScreen *screen) |
| { |
| disconnectFromScreen(); |
| topLevelScreen = screen; |
| } |
| |
| void QWindowPrivate::emitScreenChangedRecursion(QScreen *newScreen) |
| { |
| Q_Q(QWindow); |
| emit q->screenChanged(newScreen); |
| for (QObject *child : q->children()) { |
| if (child->isWindowType()) |
| static_cast<QWindow *>(child)->d_func()->emitScreenChangedRecursion(newScreen); |
| } |
| } |
| |
| void QWindowPrivate::setTopLevelScreen(QScreen *newScreen, bool recreate) |
| { |
| Q_Q(QWindow); |
| if (parentWindow) { |
| qWarning() << q << '(' << newScreen << "): Attempt to set a screen on a child window."; |
| return; |
| } |
| if (newScreen != topLevelScreen) { |
| const bool shouldRecreate = recreate && windowRecreationRequired(newScreen); |
| const bool shouldShow = visibilityOnDestroy && !topLevelScreen; |
| if (shouldRecreate && platformWindow) |
| q->destroy(); |
| connectToScreen(newScreen); |
| if (shouldShow) |
| q->setVisible(true); |
| else if (newScreen && shouldRecreate) |
| create(true); |
| emitScreenChangedRecursion(newScreen); |
| } |
| } |
| |
| void QWindowPrivate::create(bool recursive, WId nativeHandle) |
| { |
| Q_Q(QWindow); |
| if (platformWindow) |
| return; |
| |
| // avoid losing update requests when re-creating |
| const bool needsUpdate = updateRequestPending; |
| // the platformWindow, if there was one, is now gone, so make this flag reflect reality now |
| updateRequestPending = false; |
| |
| if (q->parent()) |
| q->parent()->create(); |
| |
| QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration(); |
| platformWindow = nativeHandle ? platformIntegration->createForeignWindow(q, nativeHandle) |
| : platformIntegration->createPlatformWindow(q); |
| Q_ASSERT(platformWindow); |
| |
| if (!platformWindow) { |
| qWarning() << "Failed to create platform window for" << q << "with flags" << q->flags(); |
| return; |
| } |
| |
| platformWindow->initialize(); |
| |
| QObjectList childObjects = q->children(); |
| for (int i = 0; i < childObjects.size(); i ++) { |
| QObject *object = childObjects.at(i); |
| 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); |
| QGuiApplication::sendEvent(q, &e); |
| |
| if (needsUpdate) |
| q->requestUpdate(); |
| } |
| |
| void QWindowPrivate::clearFocusObject() |
| { |
| } |
| |
| // Allows for manipulating the suggested geometry before a resize/move |
| // event in derived classes for platforms that support it, for example to |
| // implement heightForWidth(). |
| QRectF QWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const |
| { |
| Q_UNUSED(rect) |
| return QRectF(); |
| } |
| |
| /*! |
| Sets the \a surfaceType of the window. |
| |
| Specifies whether the window is meant for raster rendering with |
| QBackingStore, or OpenGL rendering with QOpenGLContext. |
| |
| The surfaceType will be used when the native surface is created |
| in the create() function. Calling this function after the native |
| surface has been created requires calling destroy() and create() |
| to release the old native surface and create a new one. |
| |
| \sa QBackingStore, QOpenGLContext, create(), destroy() |
| */ |
| void QWindow::setSurfaceType(SurfaceType surfaceType) |
| { |
| Q_D(QWindow); |
| d->surfaceType = surfaceType; |
| } |
| |
| /*! |
| Returns the surface type of the window. |
| |
| \sa setSurfaceType() |
| */ |
| QWindow::SurfaceType QWindow::surfaceType() const |
| { |
| Q_D(const QWindow); |
| return d->surfaceType; |
| } |
| |
| /*! |
| \property QWindow::visible |
| \brief whether the window is visible or not |
| |
| This property controls the visibility of the window in the windowing system. |
| |
| By default, the window is not visible, you must call setVisible(true), or |
| show() or similar to make it visible. |
| |
| \sa show() |
| */ |
| void QWindow::setVisible(bool visible) |
| { |
| Q_D(QWindow); |
| |
| d->setVisible(visible); |
| } |
| |
| bool QWindow::isVisible() const |
| { |
| Q_D(const QWindow); |
| |
| return d->visible; |
| } |
| |
| /*! |
| Allocates the platform resources associated with the window. |
| |
| It is at this point that the surface format set using setFormat() gets resolved |
| 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 |
| resources. |
| |
| Call destroy() to free the platform resources if necessary. |
| |
| \sa destroy() |
| */ |
| void QWindow::create() |
| { |
| Q_D(QWindow); |
| d->create(false); |
| } |
| |
| /*! |
| Returns the window's platform id. |
| |
| For platforms where this id might be useful, the value returned |
| will uniquely represent the window inside the corresponding screen. |
| |
| \sa screen() |
| */ |
| WId QWindow::winId() const |
| { |
| Q_D(const QWindow); |
| |
| if(!d->platformWindow) |
| const_cast<QWindow *>(this)->create(); |
| |
| return d->platformWindow->winId(); |
| } |
| |
| /*! |
| Returns the parent window, if any. |
| |
| If \a mode is IncludeTransients, then the transient parent is returned |
| if there is no parent. |
| |
| A window without a parent is known as a top level window. |
| |
| \since 5.9 |
| */ |
| QWindow *QWindow::parent(AncestorMode mode) const |
| { |
| Q_D(const QWindow); |
| return d->parentWindow ? d->parentWindow : (mode == IncludeTransients ? transientParent() : nullptr); |
| } |
| |
| /*! |
| Returns the parent window, if any. |
| |
| A window without a parent is known as a top level window. |
| */ |
| QWindow *QWindow::parent() const |
| { |
| Q_D(const QWindow); |
| return d->parentWindow; |
| } |
| |
| /*! |
| Sets the \a parent Window. This will lead to the windowing system managing |
| the clip of the window, so it will be clipped to the \a parent window. |
| |
| Setting \a parent to be \nullptr will make the window become a top level |
| window. |
| |
| If \a parent is a window created by fromWinId(), then the current window |
| will be embedded inside \a parent, if the platform supports it. |
| */ |
| void QWindow::setParent(QWindow *parent) |
| { |
| parent = nonDesktopParent(parent); |
| |
| Q_D(QWindow); |
| if (d->parentWindow == parent) |
| return; |
| |
| QScreen *newScreen = parent ? parent->screen() : screen(); |
| if (d->windowRecreationRequired(newScreen)) { |
| qWarning() << this << '(' << parent << "): Cannot change screens (" << screen() << newScreen << ')'; |
| return; |
| } |
| |
| QObject::setParent(parent); |
| d->parentWindow = parent; |
| |
| if (parent) |
| d->disconnectFromScreen(); |
| 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->create(); |
| |
| d->platformWindow->setParent(parent ? parent->d_func()->platformWindow : nullptr); |
| } |
| |
| QGuiApplicationPrivate::updateBlockedStatus(this); |
| } |
| |
| /*! |
| Returns whether the window is top level, i.e. has no parent window. |
| */ |
| bool QWindow::isTopLevel() const |
| { |
| Q_D(const QWindow); |
| return d->parentWindow == nullptr; |
| } |
| |
| /*! |
| Returns whether the window is modal. |
| |
| A modal window prevents other windows from getting any input. |
| |
| \sa QWindow::modality |
| */ |
| bool QWindow::isModal() const |
| { |
| Q_D(const QWindow); |
| return d->modality != Qt::NonModal; |
| } |
| |
| /*! \property QWindow::modality |
| \brief the modality of the window |
| |
| A modal window prevents other windows from receiving input events. Qt |
| supports two types of modality: Qt::WindowModal and Qt::ApplicationModal. |
| |
| By default, this property is Qt::NonModal |
| |
| \sa Qt::WindowModality |
| */ |
| |
| Qt::WindowModality QWindow::modality() const |
| { |
| Q_D(const QWindow); |
| return d->modality; |
| } |
| |
| void QWindow::setModality(Qt::WindowModality modality) |
| { |
| Q_D(QWindow); |
| if (d->modality == modality) |
| return; |
| d->modality = modality; |
| emit modalityChanged(modality); |
| } |
| |
| /*! \fn void QWindow::modalityChanged(Qt::WindowModality modality) |
| |
| This signal is emitted when the Qwindow::modality property changes to \a modality. |
| */ |
| |
| /*! |
| Sets the window's surface \a format. |
| |
| The format determines properties such as color depth, alpha, depth and |
| stencil buffer size, etc. For example, to give a window a transparent |
| background (provided that the window system supports compositing, and |
| provided that other content in the window does not make it opaque again): |
| |
| \code |
| QSurfaceFormat format; |
| format.setAlphaBufferSize(8); |
| window.setFormat(format); |
| \endcode |
| |
| The surface format will be resolved in the create() function. Calling |
| this function after create() has been called will not re-resolve the |
| surface format of the native surface. |
| |
| When the format is not explicitly set via this function, the format returned |
| by QSurfaceFormat::defaultFormat() will be used. This means that when having |
| multiple windows, individual calls to this function can be replaced by one |
| single call to QSurfaceFormat::setDefaultFormat() before creating the first |
| window. |
| |
| \sa create(), destroy(), QSurfaceFormat::setDefaultFormat() |
| */ |
| void QWindow::setFormat(const QSurfaceFormat &format) |
| { |
| Q_D(QWindow); |
| d->requestedFormat = format; |
| } |
| |
| /*! |
| Returns the requested surface format of this window. |
| |
| If the requested format was not supported by the platform implementation, |
| the requestedFormat will differ from the actual window format. |
| |
| This is the value set with setFormat(). |
| |
| \sa setFormat(), format() |
| */ |
| QSurfaceFormat QWindow::requestedFormat() const |
| { |
| Q_D(const QWindow); |
| return d->requestedFormat; |
| } |
| |
| /*! |
| Returns the actual format of this window. |
| |
| After the window has been created, this function will return the actual surface format |
| of the window. It might differ from the requested format if the requested format could |
| not be fulfilled by the platform. It might also be a superset, for example certain |
| buffer sizes may be larger than requested. |
| |
| \note Depending on the platform, certain values in this surface format may still |
| contain the requested values, that is, the values that have been passed to |
| setFormat(). Typical examples are the OpenGL version, profile and options. These may |
| not get updated during create() since these are context specific and a single window |
| may be used together with multiple contexts over its lifetime. Use the |
| QOpenGLContext's format() instead to query such values. |
| |
| \sa create(), requestedFormat(), QOpenGLContext::format() |
| */ |
| QSurfaceFormat QWindow::format() const |
| { |
| Q_D(const QWindow); |
| if (d->platformWindow) |
| return d->platformWindow->format(); |
| return d->requestedFormat; |
| } |
| |
| /*! |
| \property QWindow::flags |
| \brief the window flags of the window |
| |
| The window flags control the window's appearance in the windowing system, |
| whether it's a dialog, popup, or a regular window, and whether it should |
| have a title bar, etc. |
| |
| The actual window flags might differ from the flags set with setFlags() |
| if the requested flags could not be fulfilled. |
| |
| \sa setFlag() |
| */ |
| void QWindow::setFlags(Qt::WindowFlags flags) |
| { |
| Q_D(QWindow); |
| if (d->windowFlags == flags) |
| return; |
| |
| if (d->platformWindow) |
| d->platformWindow->setWindowFlags(flags); |
| d->windowFlags = flags; |
| } |
| |
| Qt::WindowFlags QWindow::flags() const |
| { |
| Q_D(const QWindow); |
| Qt::WindowFlags flags = d->windowFlags; |
| |
| if (d->platformWindow && d->platformWindow->isForeignWindow()) |
| flags |= Qt::ForeignWindow; |
| |
| return flags; |
| } |
| |
| /*! |
| \since 5.9 |
| |
| Sets the window flag \a flag on this window if \a on is true; |
| otherwise clears the flag. |
| |
| \sa setFlags(), flags(), type() |
| */ |
| void QWindow::setFlag(Qt::WindowType flag, bool on) |
| { |
| Q_D(QWindow); |
| if (on) |
| setFlags(d->windowFlags | flag); |
| else |
| setFlags(d->windowFlags & ~flag); |
| } |
| |
| /*! |
| Returns the type of the window. |
| |
| This returns the part of the window flags that represents |
| whether the window is a dialog, tooltip, popup, regular window, etc. |
| |
| \sa flags(), setFlags() |
| */ |
| Qt::WindowType QWindow::type() const |
| { |
| return static_cast<Qt::WindowType>(int(flags() & Qt::WindowType_Mask)); |
| } |
| |
| /*! |
| \property QWindow::title |
| \brief the window's title in the windowing system |
| |
| The window title might appear in the title area of the window decorations, |
| depending on the windowing system and the window flags. It might also |
| be used by the windowing system to identify the window in other contexts, |
| such as in the task switcher. |
| |
| \sa flags() |
| */ |
| void QWindow::setTitle(const QString &title) |
| { |
| Q_D(QWindow); |
| bool changed = false; |
| if (d->windowTitle != title) { |
| d->windowTitle = title; |
| changed = true; |
| } |
| if (d->platformWindow && type() != Qt::Desktop) |
| d->platformWindow->setWindowTitle(title); |
| if (changed) |
| emit windowTitleChanged(title); |
| } |
| |
| QString QWindow::title() const |
| { |
| Q_D(const QWindow); |
| return d->windowTitle; |
| } |
| |
| /*! |
| \brief set the file name this window is representing. |
| |
| The windowing system might use \a filePath to display the |
| path of the document this window is representing in the tile bar. |
| |
| */ |
| void QWindow::setFilePath(const QString &filePath) |
| { |
| Q_D(QWindow); |
| d->windowFilePath = filePath; |
| if (d->platformWindow) |
| d->platformWindow->setWindowFilePath(filePath); |
| } |
| |
| /*! |
| \brief the file name this window is representing. |
| |
| \sa setFilePath() |
| */ |
| QString QWindow::filePath() const |
| { |
| Q_D(const QWindow); |
| return d->windowFilePath; |
| } |
| |
| /*! |
| \brief Sets the window's \a icon in the windowing system |
| |
| 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) |
| { |
| Q_D(QWindow); |
| d->windowIcon = icon; |
| if (d->platformWindow) |
| d->platformWindow->setWindowIcon(icon); |
| QEvent e(QEvent::WindowIconChange); |
| QCoreApplication::sendEvent(this, &e); |
| } |
| |
| /*! |
| \brief Returns the window's icon in the windowing system |
| |
| \sa setIcon() |
| */ |
| QIcon QWindow::icon() const |
| { |
| Q_D(const QWindow); |
| if (d->windowIcon.isNull()) |
| return QGuiApplication::windowIcon(); |
| return d->windowIcon; |
| } |
| |
| /*! |
| Raise the window in the windowing system. |
| |
| Requests that the window be raised to appear above other windows. |
| */ |
| void QWindow::raise() |
| { |
| Q_D(QWindow); |
| |
| d->updateSiblingPosition(QWindowPrivate::PositionTop); |
| |
| if (d->platformWindow) |
| d->platformWindow->raise(); |
| } |
| |
| /*! |
| Lower the window in the windowing system. |
| |
| Requests that the window be lowered to appear below other windows. |
| */ |
| void QWindow::lower() |
| { |
| Q_D(QWindow); |
| |
| d->updateSiblingPosition(QWindowPrivate::PositionBottom); |
| |
| if (d->platformWindow) |
| d->platformWindow->lower(); |
| } |
| |
| /*! |
| \brief Start a system-specific resize operation |
| \since 5.15 |
| |
| Calling this will start an interactive resize operation on the window by platforms |
| that support it. The actual behavior may vary depending on the platform. Usually, |
| it will make the window resize so that its edge follows the mouse cursor. |
| |
| On platforms that support it, this method of resizing windows is preferred over |
| \c setGeometry, because it allows a more native look-and-feel of resizing windows, e.g. |
| letting the window manager snap this window against other windows, or special resizing |
| behavior with animations when dragged to the edge of the screen. |
| |
| \a edges should either be a single edge, or two adjacent edges (a corner). Other values |
| are not allowed. |
| |
| Returns true if the operation was supported by the system. |
| */ |
| bool QWindow::startSystemResize(Qt::Edges edges) |
| { |
| Q_D(QWindow); |
| if (Q_UNLIKELY(!isVisible() || !d->platformWindow || d->maximumSize == d->minimumSize)) |
| return false; |
| |
| const bool isSingleEdge = edges == Qt::TopEdge || edges == Qt::RightEdge || edges == Qt::BottomEdge || edges == Qt::LeftEdge; |
| const bool isCorner = |
| edges == (Qt::TopEdge | Qt::LeftEdge) || |
| edges == (Qt::TopEdge | Qt::RightEdge) || |
| edges == (Qt::BottomEdge | Qt::RightEdge) || |
| edges == (Qt::BottomEdge | Qt::LeftEdge); |
| |
| if (Q_UNLIKELY(!isSingleEdge && !isCorner)) { |
| qWarning() << "Invalid edges" << edges << "passed to QWindow::startSystemResize, ignoring."; |
| return false; |
| } |
| |
| return d->platformWindow->startSystemResize(edges); |
| } |
| |
| /*! |
| \brief Start a system-specific move operation |
| \since 5.15 |
| |
| Calling this will start an interactive move operation on the window by platforms |
| that support it. The actual behavior may vary depending on the platform. Usually, |
| it will make the window follow the mouse cursor until a mouse button is released. |
| |
| On platforms that support it, this method of moving windows is preferred over |
| \c setPosition, because it allows a more native look-and-feel of moving windows, e.g. |
| letting the window manager snap this window against other windows, or special tiling |
| or resizing behavior with animations when dragged to the edge of the screen. |
| Furthermore, on some platforms such as Wayland, \c setPosition is not supported, so |
| this is the only way the application can influence its position. |
| |
| Returns true if the operation was supported by the system. |
| */ |
| bool QWindow::startSystemMove() |
| { |
| Q_D(QWindow); |
| if (Q_UNLIKELY(!isVisible() || !d->platformWindow)) |
| return false; |
| |
| return d->platformWindow->startSystemMove(); |
| } |
| |
| /*! |
| \property QWindow::opacity |
| \brief The opacity of the window in the windowing system. |
| \since 5.1 |
| |
| If the windowing system supports window opacity, this can be used to fade the |
| window in and out, or to make it semitransparent. |
| |
| A value of 1.0 or above is treated as fully opaque, whereas a value of 0.0 or below |
| is treated as fully transparent. Values inbetween represent varying levels of |
| translucency between the two extremes. |
| |
| The default value is 1.0. |
| */ |
| void QWindow::setOpacity(qreal level) |
| { |
| Q_D(QWindow); |
| if (level == d->opacity) |
| return; |
| d->opacity = level; |
| if (d->platformWindow) { |
| d->platformWindow->setOpacity(level); |
| emit opacityChanged(level); |
| } |
| } |
| |
| qreal QWindow::opacity() const |
| { |
| Q_D(const QWindow); |
| return d->opacity; |
| } |
| |
| /*! |
| Sets the mask of the window. |
| |
| The mask is a hint to the windowing system that the application does not |
| want to receive mouse or touch input outside the given \a region. |
| |
| 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. |
| */ |
| void QWindow::setMask(const QRegion ®ion) |
| { |
| Q_D(QWindow); |
| if (d->platformWindow) |
| d->platformWindow->setMask(QHighDpi::toNativeLocalRegion(region, this)); |
| d->mask = region; |
| } |
| |
| /*! |
| Returns the mask set on the window. |
| |
| The mask is a hint to the windowing system that the application does not |
| want to receive mouse or touch input outside the given region. |
| */ |
| QRegion QWindow::mask() const |
| { |
| Q_D(const QWindow); |
| return d->mask; |
| } |
| |
| /*! |
| Requests the window to be activated, i.e. receive keyboard focus. |
| |
| \sa isActive(), QGuiApplication::focusWindow(), QWindowsWindowFunctions::setWindowActivationBehavior() |
| */ |
| void QWindow::requestActivate() |
| { |
| Q_D(QWindow); |
| if (flags() & Qt::WindowDoesNotAcceptFocus) { |
| qWarning() << "requestActivate() called for " << this << " which has Qt::WindowDoesNotAcceptFocus set."; |
| return; |
| } |
| if (d->platformWindow) |
| d->platformWindow->requestActivateWindow(); |
| } |
| |
| /*! |
| Returns if this window is exposed in the windowing system. |
| |
| When the window is not exposed, it is shown by the application |
| but it is still not showing in the windowing system, so the application |
| should minimize rendering and other graphical activities. |
| |
| An exposeEvent() is sent every time this value changes. |
| |
| \sa exposeEvent() |
| */ |
| bool QWindow::isExposed() const |
| { |
| Q_D(const QWindow); |
| return d->exposed; |
| } |
| |
| /*! |
| \property QWindow::active |
| \brief the active status of the window |
| \since 5.1 |
| |
| \sa requestActivate() |
| */ |
| |
| /*! |
| Returns \c true if the window should appear active from a style perspective. |
| |
| This is the case for the window that has input focus as well as windows |
| that are in the same parent / transient parent chain as the focus window. |
| |
| To get the window that currently has focus, use QGuiApplication::focusWindow(). |
| */ |
| bool QWindow::isActive() const |
| { |
| Q_D(const QWindow); |
| if (!d->platformWindow) |
| return false; |
| |
| QWindow *focus = QGuiApplication::focusWindow(); |
| |
| // Means the whole application lost the focus |
| if (!focus) |
| return false; |
| |
| if (focus == this) |
| return true; |
| |
| if (QWindow *p = parent(IncludeTransients)) |
| return p->isActive(); |
| else |
| return isAncestorOf(focus); |
| } |
| |
| /*! |
| \property QWindow::contentOrientation |
| \brief the orientation of the window's contents |
| |
| This is a hint to the window manager in case it needs to display |
| additional content like popups, dialogs, status bars, or similar |
| in relation to the window. |
| |
| The recommended orientation is QScreen::orientation() but |
| an application doesn't have to support all possible orientations, |
| and thus can opt to ignore the current screen orientation. |
| |
| The difference between the window and the content orientation |
| determines how much to rotate the content by. QScreen::angleBetween(), |
| QScreen::transformBetween(), and QScreen::mapBetween() can be used |
| to compute the necessary transform. |
| |
| The default value is Qt::PrimaryOrientation |
| */ |
| void QWindow::reportContentOrientationChange(Qt::ScreenOrientation orientation) |
| { |
| Q_D(QWindow); |
| if (d->contentOrientation == orientation) |
| return; |
| if (d->platformWindow) |
| d->platformWindow->handleContentOrientationChange(orientation); |
| d->contentOrientation = orientation; |
| emit contentOrientationChanged(orientation); |
| } |
| |
| Qt::ScreenOrientation QWindow::contentOrientation() const |
| { |
| Q_D(const QWindow); |
| return d->contentOrientation; |
| } |
| |
| /*! |
| Returns the ratio between physical pixels and device-independent pixels |
| for the window. This value is dependent on the screen the window is on, |
| and may change when the window is moved. |
| |
| 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 the associated QScreen's device pixel ratio. |
| |
| \sa QScreen::devicePixelRatio() |
| */ |
| qreal QWindow::devicePixelRatio() const |
| { |
| Q_D(const 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(); |
| |
| 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 |
| |
| The window \a state represents whether the window appears in the |
| windowing system as maximized, minimized, fullscreen, or normal. |
| |
| The enum value Qt::WindowActive is not an accepted parameter. |
| |
| \sa showNormal(), showFullScreen(), showMinimized(), showMaximized(), setWindowStates() |
| */ |
| void QWindow::setWindowState(Qt::WindowState state) |
| { |
| 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(QWindowPrivate::effectiveState(d->windowState)); |
| d->updateVisibility(); |
| } |
| |
| /*! |
| \brief the screen-occupation state of the window |
| |
| \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; |
| } |
| |
| /*! |
| \fn QWindow::windowStateChanged(Qt::WindowState windowState) |
| |
| This signal is emitted when the \a windowState changes, either |
| by being set explicitly with setWindowStates(), or automatically when |
| the user clicks one of the titlebar buttons or by other means. |
| */ |
| |
| /*! |
| \property QWindow::transientParent |
| \brief the window for which this window is a transient pop-up |
| \since 5.13 |
| |
| This is a hint to the window manager that this window is a dialog or pop-up |
| on behalf of the transient parent. |
| |
| In order to cause the window to be centered above its transient \a parent by |
| default, depending on the window manager, it may also be necessary to call |
| setFlags() with a suitable \l Qt::WindowType (such as \c Qt::Dialog). |
| |
| \sa parent() |
| */ |
| void QWindow::setTransientParent(QWindow *parent) |
| { |
| Q_D(QWindow); |
| if (parent && !parent->isTopLevel()) { |
| qWarning() << parent << "must be a top level window."; |
| return; |
| } |
| if (parent == this) { |
| qWarning() << "transient parent" << parent << "cannot be same as window"; |
| return; |
| } |
| |
| d->transientParent = parent; |
| |
| QGuiApplicationPrivate::updateBlockedStatus(this); |
| emit transientParentChanged(parent); |
| } |
| |
| QWindow *QWindow::transientParent() const |
| { |
| Q_D(const QWindow); |
| return d->transientParent.data(); |
| } |
| |
| /* |
| The setter for the QWindow::transientParent property. |
| The only reason this exists is to set the transientParentPropertySet flag |
| so that Qt Quick knows whether it was set programmatically (because of |
| Window declaration context) or because the user set the property. |
| */ |
| void QWindowPrivate::setTransientParent(QWindow *parent) |
| { |
| Q_Q(QWindow); |
| q->setTransientParent(parent); |
| transientParentPropertySet = true; |
| } |
| |
| /*! |
| \enum QWindow::AncestorMode |
| |
| This enum is used to control whether or not transient parents |
| should be considered ancestors. |
| |
| \value ExcludeTransients Transient parents are not considered ancestors. |
| \value IncludeTransients Transient parents are considered ancestors. |
| */ |
| |
| /*! |
| Returns \c true if the window is an ancestor of the given \a child. If \a mode |
| is IncludeTransients, then transient parents are also considered ancestors. |
| */ |
| bool QWindow::isAncestorOf(const QWindow *child, AncestorMode mode) const |
| { |
| if (child->parent() == this || (mode == IncludeTransients && child->transientParent() == this)) |
| return true; |
| |
| if (QWindow *parent = child->parent(mode)) { |
| if (isAncestorOf(parent, mode)) |
| return true; |
| } else if (handle() && child->handle()) { |
| if (handle()->isAncestorOf(child->handle())) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /*! |
| Returns the minimum size of the window. |
| |
| \sa setMinimumSize() |
| */ |
| QSize QWindow::minimumSize() const |
| { |
| Q_D(const QWindow); |
| return d->minimumSize; |
| } |
| |
| /*! |
| Returns the maximum size of the window. |
| |
| \sa setMaximumSize() |
| */ |
| QSize QWindow::maximumSize() const |
| { |
| Q_D(const QWindow); |
| return d->maximumSize; |
| } |
| |
| /*! |
| Returns the base size of the window. |
| |
| \sa setBaseSize() |
| */ |
| QSize QWindow::baseSize() const |
| { |
| Q_D(const QWindow); |
| return d->baseSize; |
| } |
| |
| /*! |
| Returns the size increment of the window. |
| |
| \sa setSizeIncrement() |
| */ |
| QSize QWindow::sizeIncrement() const |
| { |
| Q_D(const QWindow); |
| return d->sizeIncrement; |
| } |
| |
| /*! |
| Sets the minimum size of the window. |
| |
| This is a hint to the window manager to prevent resizing below the specified \a size. |
| |
| \sa setMaximumSize(), minimumSize() |
| */ |
| 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()); |
| } |
| |
| /*! |
| \property QWindow::x |
| \brief the x position of the window's geometry |
| */ |
| void QWindow::setX(int arg) |
| { |
| Q_D(QWindow); |
| if (x() != arg) |
| setGeometry(QRect(arg, y(), width(), height())); |
| else |
| d->positionAutomatic = false; |
| } |
| |
| /*! |
| \property QWindow::y |
| \brief the y position of the window's geometry |
| */ |
| void QWindow::setY(int arg) |
| { |
| Q_D(QWindow); |
| if (y() != arg) |
| setGeometry(QRect(x(), arg, width(), height())); |
| else |
| d->positionAutomatic = false; |
| } |
| |
| /*! |
| \property QWindow::width |
| \brief the width of the window's geometry |
| */ |
| void QWindow::setWidth(int arg) |
| { |
| if (width() != arg) |
| resize(arg, height()); |
| } |
| |
| /*! |
| \property QWindow::height |
| \brief the height of the window's geometry |
| */ |
| void QWindow::setHeight(int arg) |
| { |
| if (height() != arg) |
| resize(width(), arg); |
| } |
| |
| /*! |
| \property QWindow::minimumWidth |
| \brief the minimum width of the window's geometry |
| */ |
| void QWindow::setMinimumWidth(int w) |
| { |
| setMinimumSize(QSize(w, minimumHeight())); |
| } |
| |
| /*! |
| \property QWindow::minimumHeight |
| \brief the minimum height of the window's geometry |
| */ |
| void QWindow::setMinimumHeight(int h) |
| { |
| setMinimumSize(QSize(minimumWidth(), h)); |
| } |
| |
| /*! |
| Sets the maximum size of the window. |
| |
| This is a hint to the window manager to prevent resizing above the specified \a size. |
| |
| \sa setMinimumSize(), maximumSize() |
| */ |
| 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()); |
| } |
| |
| /*! |
| \property QWindow::maximumWidth |
| \brief the maximum width of the window's geometry |
| */ |
| void QWindow::setMaximumWidth(int w) |
| { |
| setMaximumSize(QSize(w, maximumHeight())); |
| } |
| |
| /*! |
| \property QWindow::maximumHeight |
| \brief the maximum height of the window's geometry |
| */ |
| void QWindow::setMaximumHeight(int h) |
| { |
| setMaximumSize(QSize(maximumWidth(), h)); |
| } |
| |
| /*! |
| Sets the base \a size of the window. |
| |
| The base size is used to calculate a proper window size if the |
| window defines sizeIncrement(). |
| |
| \sa setMinimumSize(), setMaximumSize(), setSizeIncrement(), baseSize() |
| */ |
| void QWindow::setBaseSize(const QSize &size) |
| { |
| Q_D(QWindow); |
| if (d->baseSize == size) |
| return; |
| d->baseSize = size; |
| if (d->platformWindow && isTopLevel()) |
| d->platformWindow->propagateSizeHints(); |
| } |
| |
| /*! |
| Sets the size increment (\a size) of the window. |
| |
| When the user resizes the window, the size will move in steps of |
| sizeIncrement().width() pixels horizontally and |
| sizeIncrement().height() pixels vertically, with baseSize() as the |
| basis. |
| |
| By default, this property contains a size with zero width and height. |
| |
| The windowing system might not support size increments. |
| |
| \sa setBaseSize(), setMinimumSize(), setMaximumSize() |
| */ |
| void QWindow::setSizeIncrement(const QSize &size) |
| { |
| Q_D(QWindow); |
| if (d->sizeIncrement == size) |
| return; |
| d->sizeIncrement = size; |
| if (d->platformWindow && isTopLevel()) |
| d->platformWindow->propagateSizeHints(); |
| } |
| |
| /*! |
| Sets the geometry of the window, excluding its window frame, to a |
| rectangle constructed from \a posx, \a posy, \a w and \a h. |
| |
| The geometry is in relation to the virtualGeometry() of its screen. |
| |
| \sa geometry() |
| */ |
| void QWindow::setGeometry(int posx, int posy, int w, int h) |
| { |
| setGeometry(QRect(posx, posy, w, h)); |
| } |
| |
| /*! |
| \brief Sets the geometry of the window, excluding its window frame, to \a rect. |
| |
| The geometry is in relation to the virtualGeometry() of its screen. |
| |
| \sa geometry() |
| */ |
| void QWindow::setGeometry(const QRect &rect) |
| { |
| Q_D(QWindow); |
| d->positionAutomatic = false; |
| const QRect oldRect = geometry(); |
| if (rect == oldRect) |
| return; |
| |
| d->positionPolicy = QWindowPrivate::WindowFrameExclusive; |
| if (d->platformWindow) { |
| QRect nativeRect; |
| QScreen *newScreen = d->screenForGeometry(rect); |
| if (newScreen && isTopLevel()) |
| nativeRect = QHighDpi::toNativePixels(rect, newScreen); |
| else |
| nativeRect = QHighDpi::toNativeLocalPosition(rect, newScreen); |
| d->platformWindow->setGeometry(nativeRect); |
| } else { |
| d->geometry = rect; |
| |
| if (rect.x() != oldRect.x()) |
| emit xChanged(rect.x()); |
| if (rect.y() != oldRect.y()) |
| emit yChanged(rect.y()); |
| if (rect.width() != oldRect.width()) |
| emit widthChanged(rect.width()); |
| if (rect.height() != oldRect.height()) |
| emit heightChanged(rect.height()); |
| } |
| } |
| |
| /* |
| This is equivalent to QPlatformWindow::screenForGeometry, but in platform |
| independent coordinates. The duplication is unfortunate, but there is a |
| chicken and egg problem here: we cannot convert to native coordinates |
| before we know which screen we are on. |
| */ |
| QScreen *QWindowPrivate::screenForGeometry(const QRect &newGeometry) const |
| { |
| Q_Q(const QWindow); |
| QScreen *currentScreen = q->screen(); |
| QScreen *fallback = currentScreen; |
| QPoint center = newGeometry.center(); |
| if (!q->parent() && currentScreen && !currentScreen->geometry().contains(center)) { |
| const auto screens = currentScreen->virtualSiblings(); |
| for (QScreen* screen : screens) { |
| if (screen->geometry().contains(center)) |
| return screen; |
| if (screen->geometry().intersects(newGeometry)) |
| fallback = screen; |
| } |
| } |
| return fallback; |
| } |
| |
| |
| /*! |
| Returns the geometry of the window, excluding its window frame. |
| |
| The geometry is in relation to the virtualGeometry() of its screen. |
| |
| \sa frameMargins(), frameGeometry() |
| */ |
| QRect QWindow::geometry() const |
| { |
| Q_D(const QWindow); |
| if (d->platformWindow) { |
| const auto nativeGeometry = d->platformWindow->geometry(); |
| return isTopLevel() |
| ? QHighDpi::fromNativePixels(nativeGeometry, this) |
| : QHighDpi::fromNativeLocalPosition(nativeGeometry, this); |
| } |
| return d->geometry; |
| } |
| |
| /*! |
| Returns the window frame margins surrounding the window. |
| |
| \sa geometry(), frameGeometry() |
| */ |
| QMargins QWindow::frameMargins() const |
| { |
| Q_D(const QWindow); |
| if (d->platformWindow) |
| return QHighDpi::fromNativePixels(d->platformWindow->frameMargins(), this); |
| return QMargins(); |
| } |
| |
| /*! |
| Returns the geometry of the window, including its window frame. |
| |
| The geometry is in relation to the virtualGeometry() of its screen. |
| |
| \sa geometry(), frameMargins() |
| */ |
| QRect QWindow::frameGeometry() const |
| { |
| Q_D(const QWindow); |
| if (d->platformWindow) { |
| QMargins m = frameMargins(); |
| return QHighDpi::fromNativePixels(d->platformWindow->geometry(), this).adjusted(-m.left(), -m.top(), m.right(), m.bottom()); |
| } |
| return d->geometry; |
| } |
| |
| /*! |
| Returns the top left position of the window, including its window frame. |
| |
| This returns the same value as frameGeometry().topLeft(). |
| |
| \sa geometry(), frameGeometry() |
| */ |
| QPoint QWindow::framePosition() const |
| { |
| Q_D(const QWindow); |
| if (d->platformWindow) { |
| QMargins margins = frameMargins(); |
| return QHighDpi::fromNativePixels(d->platformWindow->geometry().topLeft(), this) - QPoint(margins.left(), margins.top()); |
| } |
| return d->geometry.topLeft(); |
| } |
| |
| /*! |
| Sets the upper left position of the window (\a point) including its window frame. |
| |
| The position is in relation to the virtualGeometry() of its screen. |
| |
| \sa setGeometry(), frameGeometry() |
| */ |
| void QWindow::setFramePosition(const QPoint &point) |
| { |
| Q_D(QWindow); |
| d->positionPolicy = QWindowPrivate::WindowFrameInclusive; |
| d->positionAutomatic = false; |
| if (d->platformWindow) { |
| d->platformWindow->setGeometry(QHighDpi::toNativePixels(QRect(point, size()), this)); |
| } else { |
| d->geometry.moveTopLeft(point); |
| } |
| } |
| |
| /*! |
| \brief set the position of the window on the desktop to \a pt |
| |
| The position is in relation to the virtualGeometry() of its screen. |
| |
| For interactively moving windows, see startSystemMove(). For interactively |
| resizing windows, see startSystemResize(). |
| |
| \sa position(), startSystemMove() |
| */ |
| void QWindow::setPosition(const QPoint &pt) |
| { |
| setGeometry(QRect(pt, size())); |
| } |
| |
| /*! |
| \brief set the position of the window on the desktop to \a posx, \a posy |
| |
| The position is in relation to the virtualGeometry() of its screen. |
| |
| \sa position() |
| */ |
| void QWindow::setPosition(int posx, int posy) |
| { |
| setPosition(QPoint(posx, posy)); |
| } |
| |
| /*! |
| \fn QPoint QWindow::position() const |
| \brief Returns the position of the window on the desktop excluding any window frame |
| |
| \sa setPosition() |
| */ |
| |
| /*! |
| \fn QSize QWindow::size() const |
| \brief Returns the size of the window excluding any window frame |
| |
| \sa resize() |
| */ |
| |
| /*! |
| set the size of the window, excluding any window frame, to a QSize |
| constructed from width \a w and height \a h |
| |
| For interactively resizing windows, see startSystemResize(). |
| |
| \sa size(), geometry() |
| */ |
| void QWindow::resize(int w, int h) |
| { |
| resize(QSize(w, h)); |
| } |
| |
| /*! |
| \brief set the size of the window, excluding any window frame, to \a newSize |
| |
| \sa size(), geometry() |
| */ |
| void QWindow::resize(const QSize &newSize) |
| { |
| Q_D(QWindow); |
| d->positionPolicy = QWindowPrivate::WindowFrameExclusive; |
| if (d->platformWindow) { |
| d->platformWindow->setGeometry(QHighDpi::toNativePixels(QRect(position(), newSize), this)); |
| } else { |
| const QSize oldSize = d->geometry.size(); |
| d->geometry.setSize(newSize); |
| if (newSize.width() != oldSize.width()) |
| emit widthChanged(newSize.width()); |
| if (newSize.height() != oldSize.height()) |
| emit heightChanged(newSize.height()); |
| } |
| } |
| |
| /*! |
| Releases the native platform resources associated with this window. |
| |
| \sa create() |
| */ |
| void QWindow::destroy() |
| { |
| Q_D(QWindow); |
| if (!d->platformWindow) |
| return; |
| |
| if (d->platformWindow->isForeignWindow()) |
| return; |
| |
| d->destroy(); |
| } |
| |
| void QWindowPrivate::destroy() |
| { |
| if (!platformWindow) |
| return; |
| |
| Q_Q(QWindow); |
| QObjectList childrenWindows = q->children(); |
| for (int i = 0; i < childrenWindows.size(); i++) { |
| QObject *object = childrenWindows.at(i); |
| if (object->isWindowType()) { |
| QWindow *w = static_cast<QWindow*>(object); |
| qt_window_private(w)->destroy(); |
| } |
| } |
| |
| if (QGuiApplicationPrivate::focus_window == q) |
| QGuiApplicationPrivate::focus_window = q->parent(); |
| if (QGuiApplicationPrivate::currentMouseWindow == q) |
| QGuiApplicationPrivate::currentMouseWindow = q->parent(); |
| if (QGuiApplicationPrivate::currentMousePressWindow == q) |
| QGuiApplicationPrivate::currentMousePressWindow = q->parent(); |
| |
| for (int i = 0; i < QGuiApplicationPrivate::tabletDevicePoints.size(); ++i) |
| if (QGuiApplicationPrivate::tabletDevicePoints.at(i).target == q) |
| QGuiApplicationPrivate::tabletDevicePoints[i].target = q->parent(); |
| |
| bool wasVisible = q->isVisible(); |
| visibilityOnDestroy = wasVisible && platformWindow; |
| |
| q->setVisible(false); |
| |
| // Let subclasses act, typically by doing graphics resource cleaup, when |
| // the window, to which graphics resource may be tied, is going away. |
| // |
| // NB! This is disfunctional when destroy() is invoked from the dtor since |
| // a reimplemented event() will not get called in the subclasses at that |
| // stage. However, the typical QWindow cleanup involves either close() or |
| // going through QWindowContainer, both of which will do an explicit, early |
| // destroy(), which is good here. |
| |
| QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed); |
| QGuiApplication::sendEvent(q, &e); |
| |
| // 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; |
| } |
| |
| /*! |
| Returns the platform window corresponding to the window. |
| |
| \internal |
| */ |
| QPlatformWindow *QWindow::handle() const |
| { |
| Q_D(const QWindow); |
| return d->platformWindow; |
| } |
| |
| /*! |
| Returns the platform surface corresponding to the window. |
| |
| \internal |
| */ |
| QPlatformSurface *QWindow::surfaceHandle() const |
| { |
| Q_D(const QWindow); |
| return d->platformWindow; |
| } |
| |
| /*! |
| Sets whether keyboard grab should be enabled or not (\a grab). |
| |
| If the return value is true, the window receives all key events until |
| setKeyboardGrabEnabled(false) is called; other windows get no key events at |
| all. Mouse events are not affected. Use setMouseGrabEnabled() if you want |
| to grab that. |
| |
| \sa setMouseGrabEnabled() |
| */ |
| bool QWindow::setKeyboardGrabEnabled(bool grab) |
| { |
| Q_D(QWindow); |
| if (d->platformWindow) |
| return d->platformWindow->setKeyboardGrabEnabled(grab); |
| return false; |
| } |
| |
| /*! |
| Sets whether mouse grab should be enabled or not (\a grab). |
| |
| If the return value is true, the window receives all mouse events until setMouseGrabEnabled(false) is |
| called; other windows get no mouse events at all. Keyboard events are not affected. |
| Use setKeyboardGrabEnabled() if you want to grab that. |
| |
| \sa setKeyboardGrabEnabled() |
| */ |
| bool QWindow::setMouseGrabEnabled(bool grab) |
| { |
| Q_D(QWindow); |
| if (d->platformWindow) |
| return d->platformWindow->setMouseGrabEnabled(grab); |
| return false; |
| } |
| |
| /*! |
| 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. |
| |
| \sa setScreen(), QScreen::virtualSiblings() |
| */ |
| QScreen *QWindow::screen() const |
| { |
| Q_D(const QWindow); |
| return d->parentWindow ? d->parentWindow->screen() : d->topLevelScreen.data(); |
| } |
| |
| /*! |
| Sets the screen on which the window should be shown. |
| |
| If the window has been created, it will be recreated on the \a newScreen. |
| |
| \note If the screen is part of a virtual desktop of multiple screens, |
| the window will not move automatically to \a newScreen. To place the |
| window relative to the screen, use the screen's topLeft() position. |
| |
| This function only works for top level windows. |
| |
| \sa screen(), QScreen::virtualSiblings() |
| */ |
| void QWindow::setScreen(QScreen *newScreen) |
| { |
| Q_D(QWindow); |
| if (!newScreen) |
| newScreen = QGuiApplication::primaryScreen(); |
| d->setTopLevelScreen(newScreen, newScreen != nullptr); |
| } |
| |
| /*! |
| \fn QWindow::screenChanged(QScreen *screen) |
| |
| This signal is emitted when a window's \a screen changes, either |
| by being set explicitly with setScreen(), or automatically when |
| the window's screen is removed. |
| */ |
| |
| /*! |
| Returns the accessibility interface for the object that the window represents |
| \internal |
| \sa QAccessible |
| */ |
| QAccessibleInterface *QWindow::accessibleRoot() const |
| { |
| return nullptr; |
| } |
| |
| /*! |
| \fn QWindow::focusObjectChanged(QObject *object) |
| |
| This signal is emitted when the final receiver of events tied to focus |
| is changed to \a object. |
| |
| \sa focusObject() |
| */ |
| |
| /*! |
| Returns the QObject that will be the final receiver of events tied focus, such |
| as key events. |
| */ |
| QObject *QWindow::focusObject() const |
| { |
| return const_cast<QWindow *>(this); |
| } |
| |
| /*! |
| Shows the window. |
| |
| This 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 |
| showNormal(); |
| } |
| |
| /*! |
| Hides the window. |
| |
| Equivalent to calling setVisible(false). |
| |
| \sa show(), setVisible() |
| */ |
| void QWindow::hide() |
| { |
| setVisible(false); |
| } |
| |
| /*! |
| Shows the window as minimized. |
| |
| Equivalent to calling setWindowStates(Qt::WindowMinimized) and then |
| setVisible(true). |
| |
| \sa setWindowStates(), setVisible() |
| */ |
| void QWindow::showMinimized() |
| { |
| setWindowStates(Qt::WindowMinimized); |
| setVisible(true); |
| } |
| |
| /*! |
| Shows the window as maximized. |
| |
| Equivalent to calling setWindowStates(Qt::WindowMaximized) and then |
| setVisible(true). |
| |
| \sa setWindowStates(), setVisible() |
| */ |
| void QWindow::showMaximized() |
| { |
| setWindowStates(Qt::WindowMaximized); |
| setVisible(true); |
| } |
| |
| /*! |
| Shows the window as fullscreen. |
| |
| Equivalent to calling setWindowStates(Qt::WindowFullScreen) and then |
| setVisible(true). |
| |
| \sa setWindowStates(), setVisible() |
| */ |
| void QWindow::showFullScreen() |
| { |
| 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 |
| requestActivate(); |
| #endif |
| } |
| |
| /*! |
| Shows the window as normal, i.e. neither maximized, minimized, nor fullscreen. |
| |
| Equivalent to calling setWindowStates(Qt::WindowNoState) and then |
| setVisible(true). |
| |
| \sa setWindowStates(), setVisible() |
| */ |
| void QWindow::showNormal() |
| { |
| setWindowStates(Qt::WindowNoState); |
| setVisible(true); |
| } |
| |
| /*! |
| Close the window. |
| |
| This closes the window, effectively calling destroy(), and potentially |
| quitting the application. Returns \c true on success, false if it has a parent |
| window (in which case the top level window should be closed instead). |
| |
| \sa destroy(), QGuiApplication::quitOnLastWindowClosed() |
| */ |
| bool QWindow::close() |
| { |
| Q_D(QWindow); |
| |
| // Do not close non top level windows |
| if (parent()) |
| return false; |
| |
| if (!d->platformWindow) |
| return true; |
| |
| return d->platformWindow->close(); |
| } |
| |
| /*! |
| The expose event (\a ev) is sent by the window system whenever an area of |
| the window is invalidated, for example due to the exposure in the windowing |
| system changing. |
| |
| The application can start rendering into the window with QBackingStore |
| and QOpenGLContext as soon as it gets an exposeEvent() such that |
| isExposed() is true. |
| |
| If the window is moved off screen, is made totally obscured by another |
| window, iconified or similar, this function might be called and the |
| value of isExposed() might change to false. When this happens, |
| an application should stop its rendering as it is no longer visible |
| to the user. |
| |
| A resize event will always be sent before the expose event the first time |
| a window is shown. |
| |
| \sa isExposed() |
| */ |
| void QWindow::exposeEvent(QExposeEvent *ev) |
| { |
| ev->ignore(); |
| } |
| |
| /*! |
| Override this to handle window move events (\a ev). |
| */ |
| void QWindow::moveEvent(QMoveEvent *ev) |
| { |
| ev->ignore(); |
| } |
| |
| /*! |
| Override this to handle resize events (\a ev). |
| |
| The resize event is called whenever the window is resized in the windowing system, |
| either directly through the windowing system acknowledging a setGeometry() or resize() request, |
| or indirectly through the user resizing the window manually. |
| */ |
| void QWindow::resizeEvent(QResizeEvent *ev) |
| { |
| ev->ignore(); |
| } |
| |
| /*! |
| Override this to handle show events (\a ev). |
| |
| The function is called when the window has requested becoming visible. |
| |
| If the window is successfully shown by the windowing system, this will |
| be followed by a resize and an expose event. |
| */ |
| void QWindow::showEvent(QShowEvent *ev) |
| { |
| ev->ignore(); |
| } |
| |
| /*! |
| Override this to handle hide events (\a ev). |
| |
| The function is called when the window has requested being hidden in the |
| windowing system. |
| */ |
| void QWindow::hideEvent(QHideEvent *ev) |
| { |
| ev->ignore(); |
| } |
| |
| /*! |
| Override this to handle any event (\a ev) sent to the window. |
| Return \c true if the event was recognized and processed. |
| |
| Remember to call the base class version if you wish for mouse events, |
| key events, resize events, etc to be dispatched as usual. |
| */ |
| bool QWindow::event(QEvent *ev) |
| { |
| switch (ev->type()) { |
| case QEvent::MouseMove: |
| mouseMoveEvent(static_cast<QMouseEvent*>(ev)); |
| break; |
| |
| case QEvent::MouseButtonPress: |
| mousePressEvent(static_cast<QMouseEvent*>(ev)); |
| break; |
| |
| case QEvent::MouseButtonRelease: |
| mouseReleaseEvent(static_cast<QMouseEvent*>(ev)); |
| break; |
| |
| case QEvent::MouseButtonDblClick: |
| mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev)); |
| break; |
| |
| case QEvent::TouchBegin: |
| case QEvent::TouchUpdate: |
| case QEvent::TouchEnd: |
| case QEvent::TouchCancel: |
| touchEvent(static_cast<QTouchEvent *>(ev)); |
| break; |
| |
| case QEvent::Move: |
| moveEvent(static_cast<QMoveEvent*>(ev)); |
| break; |
| |
| case QEvent::Resize: |
| resizeEvent(static_cast<QResizeEvent*>(ev)); |
| break; |
| |
| case QEvent::KeyPress: |
| keyPressEvent(static_cast<QKeyEvent *>(ev)); |
| break; |
| |
| case QEvent::KeyRelease: |
| keyReleaseEvent(static_cast<QKeyEvent *>(ev)); |
| break; |
| |
| case QEvent::FocusIn: { |
| focusInEvent(static_cast<QFocusEvent *>(ev)); |
| #ifndef QT_NO_ACCESSIBILITY |
| QAccessible::State state; |
| state.active = true; |
| QAccessibleStateChangeEvent event(this, state); |
| QAccessible::updateAccessibility(&event); |
| #endif |
| break; } |
| |
| case QEvent::FocusOut: { |
| focusOutEvent(static_cast<QFocusEvent *>(ev)); |
| #ifndef QT_NO_ACCESSIBILITY |
| QAccessible::State state; |
| state.active = true; |
| QAccessibleStateChangeEvent event(this, state); |
| QAccessible::updateAccessibility(&event); |
| #endif |
| break; } |
| |
| #if QT_CONFIG(wheelevent) |
| case QEvent::Wheel: |
| wheelEvent(static_cast<QWheelEvent*>(ev)); |
| break; |
| #endif |
| |
| case QEvent::Close: |
| if (ev->isAccepted()) { |
| Q_D(QWindow); |
| bool wasVisible = isVisible(); |
| destroy(); |
| if (wasVisible) { |
| // FIXME: This check for visibility is a workaround for both QWidgetWindow |
| // and QWindow having logic to emit lastWindowClosed, and possibly quit the |
| // application. We should find a better way to handle this. |
| d->maybeQuitOnLastWindowClosed(); |
| } |
| } |
| break; |
| |
| case QEvent::Expose: |
| exposeEvent(static_cast<QExposeEvent *>(ev)); |
| break; |
| |
| case QEvent::Show: |
| showEvent(static_cast<QShowEvent *>(ev)); |
| break; |
| |
| case QEvent::Hide: |
| hideEvent(static_cast<QHideEvent *>(ev)); |
| break; |
| |
| case QEvent::ApplicationWindowIconChange: |
| 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: |
| case QEvent::TabletRelease: |
| tabletEvent(static_cast<QTabletEvent *>(ev)); |
| break; |
| #endif |
| |
| case QEvent::PlatformSurface: { |
| if ((static_cast<QPlatformSurfaceEvent *>(ev))->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) { |
| #ifndef QT_NO_OPENGL |
| QOpenGLContext *context = QOpenGLContext::currentContext(); |
| if (context && context->surface() == static_cast<QSurface *>(this)) |
| context->doneCurrent(); |
| #endif |
| } |
| break; |
| } |
| |
| default: |
| return QObject::event(ev); |
| } |
| return true; |
| } |
| |
| /*! |
| 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. |
| |
| 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. |
| |
| \since 5.5 |
| */ |
| void QWindow::requestUpdate() |
| { |
| Q_ASSERT_X(QThread::currentThread() == QCoreApplication::instance()->thread(), |
| "QWindow", "Updates can only be scheduled from the GUI (main) thread"); |
| |
| Q_D(QWindow); |
| if (d->updateRequestPending || !d->platformWindow) |
| return; |
| d->updateRequestPending = true; |
| d->platformWindow->requestUpdate(); |
| } |
| |
| /*! |
| Override this to handle key press events (\a ev). |
| |
| \sa keyReleaseEvent() |
| */ |
| void QWindow::keyPressEvent(QKeyEvent *ev) |
| { |
| ev->ignore(); |
| } |
| |
| /*! |
| Override this to handle key release events (\a ev). |
| |
| \sa keyPressEvent() |
| */ |
| void QWindow::keyReleaseEvent(QKeyEvent *ev) |
| { |
| ev->ignore(); |
| } |
| |
| /*! |
| Override this to handle focus in events (\a ev). |
| |
| Focus in events are sent when the window receives keyboard focus. |
| |
| \sa focusOutEvent() |
| */ |
| void QWindow::focusInEvent(QFocusEvent *ev) |
| { |
| ev->ignore(); |
| } |
| |
| /*! |
| Override this to handle focus out events (\a ev). |
| |
| Focus out events are sent when the window loses keyboard focus. |
| |
| \sa focusInEvent() |
| */ |
| void QWindow::focusOutEvent(QFocusEvent *ev) |
| { |
| ev->ignore(); |
| } |
| |
| /*! |
| Override this to handle mouse press events (\a ev). |
| |
| \sa mouseReleaseEvent() |
| */ |
| void QWindow::mousePressEvent(QMouseEvent *ev) |
| { |
| ev->ignore(); |
| } |
| |
| /*! |
| Override this to handle mouse release events (\a ev). |
| |
| \sa mousePressEvent() |
| */ |
| void QWindow::mouseReleaseEvent(QMouseEvent *ev) |
| { |
| ev->ignore(); |
| } |
| |
| /*! |
| Override this to handle mouse double click events (\a ev). |
| |
| \sa mousePressEvent(), QStyleHints::mouseDoubleClickInterval() |
| */ |
| void QWindow::mouseDoubleClickEvent(QMouseEvent *ev) |
| { |
| ev->ignore(); |
| } |
| |
| /*! |
| Override this to handle mouse move events (\a ev). |
| */ |
| void QWindow::mouseMoveEvent(QMouseEvent *ev) |
| { |
| ev->ignore(); |
| } |
| |
| #if QT_CONFIG(wheelevent) |
| /*! |
| Override this to handle mouse wheel or other wheel events (\a ev). |
| */ |
| void QWindow::wheelEvent(QWheelEvent *ev) |
| { |
| ev->ignore(); |
| } |
| #endif // QT_CONFIG(wheelevent) |
| |
| /*! |
| Override this to handle touch events (\a ev). |
| */ |
| void QWindow::touchEvent(QTouchEvent *ev) |
| { |
| ev->ignore(); |
| } |
| |
| #if QT_CONFIG(tabletevent) |
| /*! |
| Override this to handle tablet press, move, and release events (\a ev). |
| |
| Proximity enter and leave events are not sent to windows, they are |
| delivered to the application instance. |
| */ |
| void QWindow::tabletEvent(QTabletEvent *ev) |
| { |
| ev->ignore(); |
| } |
| #endif |
| |
| /*! |
| Override this to handle platform dependent events. |
| Will be given \a eventType, \a message and \a result. |
| |
| This might make your application non-portable. |
| |
| Should return true only if the event was handled. |
| */ |
| |
| #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) |
| bool QWindow::nativeEvent(const QByteArray &eventType, void *message, qintptr *result) |
| #else |
| bool QWindow::nativeEvent(const QByteArray &eventType, void *message, long *result) |
| #endif |
| { |
| Q_UNUSED(eventType); |
| Q_UNUSED(message); |
| Q_UNUSED(result); |
| return false; |
| } |
| |
| /*! |
| \fn QPoint QWindow::mapToGlobal(const QPoint &pos) const |
| |
| Translates the window coordinate \a pos to global screen |
| coordinates. For example, \c{mapToGlobal(QPoint(0,0))} would give |
| the global coordinates of the top-left pixel of the window. |
| |
| \sa mapFromGlobal() |
| */ |
| QPoint QWindow::mapToGlobal(const QPoint &pos) const |
| { |
| Q_D(const QWindow); |
| // QTBUG-43252, prefer platform implementation for foreign windows. |
| if (d->platformWindow |
| && (d->platformWindow->isForeignWindow() || d->platformWindow->isEmbedded())) { |
| return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapToGlobal(QHighDpi::toNativeLocalPosition(pos, this)), this); |
| } |
| |
| if (QHighDpiScaling::isActive()) |
| return QHighDpiScaling::mapPositionToGlobal(pos, d->globalPosition(), this); |
| |
| return pos + d->globalPosition(); |
| } |
| |
| |
| /*! |
| \fn QPoint QWindow::mapFromGlobal(const QPoint &pos) const |
| |
| Translates the global screen coordinate \a pos to window |
| coordinates. |
| |
| \sa mapToGlobal() |
| */ |
| QPoint QWindow::mapFromGlobal(const QPoint &pos) const |
| { |
| Q_D(const QWindow); |
| // QTBUG-43252, prefer platform implementation for foreign windows. |
| if (d->platformWindow |
| && (d->platformWindow->isForeignWindow() || d->platformWindow->isEmbedded())) { |
| return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapFromGlobal(QHighDpi::toNativeLocalPosition(pos, this)), this); |
| } |
| |
| if (QHighDpiScaling::isActive()) |
| return QHighDpiScaling::mapPositionFromGlobal(pos, d->globalPosition(), this); |
| |
| return pos - d->globalPosition(); |
| } |
| |
| QPoint QWindowPrivate::globalPosition() const |
| { |
| Q_Q(const QWindow); |
| QPoint offset = q->position(); |
| for (const QWindow *p = q->parent(); p; p = p->parent()) { |
| QPlatformWindow *pw = p->handle(); |
| if (pw && (pw->isForeignWindow() || pw->isEmbedded())) { |
| // Use mapToGlobal() for foreign windows |
| offset += p->mapToGlobal(QPoint(0, 0)); |
| break; |
| } else { |
| offset += p->position(); |
| } |
| } |
| return offset; |
| } |
| |
| Q_GUI_EXPORT QWindowPrivate *qt_window_private(QWindow *window) |
| { |
| return window->d_func(); |
| } |
| |
| void QWindowPrivate::maybeQuitOnLastWindowClosed() |
| { |
| if (!QCoreApplication::instance()) |
| return; |
| |
| Q_Q(QWindow); |
| if (!q->isTopLevel()) |
| return; |
| // Attempt to close the application only if this has WA_QuitOnClose set and a non-visible parent |
| bool quitOnClose = QGuiApplication::quitOnLastWindowClosed() && !q->parent(); |
| 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() || w->type() == Qt::ToolTip) |
| continue; |
| lastWindowClosed = false; |
| break; |
| } |
| if (lastWindowClosed) { |
| QGuiApplicationPrivate::emitLastWindowClosed(); |
| if (quitOnClose) { |
| QCoreApplicationPrivate *applicationPrivate = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance())); |
| applicationPrivate->maybeQuit(); |
| } |
| } |
| } |
| |
| QWindow *QWindowPrivate::topLevelWindow(QWindow::AncestorMode mode) const |
| { |
| Q_Q(const QWindow); |
| |
| QWindow *window = const_cast<QWindow *>(q); |
| |
| while (window) { |
| QWindow *parent = window->parent(mode); |
| if (!parent) |
| break; |
| |
| window = parent; |
| } |
| |
| 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. |
| |
| Given the handle \a id to a native window, this method creates a QWindow |
| object which can be used to represent the window when invoking methods like |
| setParent() and setTransientParent(). |
| |
| 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 or embedding the native window |
| failed in the platform plugin, this function returns \nullptr. |
| |
| \note The resulting QWindow should not be used to manipulate the underlying |
| native window (besides re-parenting), or to observe state changes of the |
| native window. Any support for these kind of operations is incidental, highly |
| platform dependent and untested. |
| |
| \sa setParent() |
| */ |
| QWindow *QWindow::fromWinId(WId id) |
| { |
| if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ForeignWindows)) { |
| qWarning("QWindow::fromWinId(): platform plugin does not support foreign windows."); |
| return nullptr; |
| } |
| |
| QWindow *window = new QWindow; |
| qt_window_private(window)->create(false, id); |
| |
| if (!window->handle()) { |
| delete window; |
| return nullptr; |
| } |
| |
| return window; |
| } |
| |
| /*! |
| Causes an alert to be shown for \a msec miliseconds. If \a msec is \c 0 (the |
| default), then the alert is shown indefinitely until the window becomes |
| active again. This function has no effect on an active window. |
| |
| In alert state, the window indicates that it demands attention, for example by |
| flashing or bouncing the taskbar entry. |
| |
| \since 5.1 |
| */ |
| |
| void QWindow::alert(int msec) |
| { |
| Q_D(QWindow); |
| if (!d->platformWindow || d->platformWindow->isAlertState() || isActive()) |
| return; |
| d->platformWindow->setAlertState(true); |
| if (d->platformWindow->isAlertState() && msec) |
| QTimer::singleShot(msec, this, SLOT(_q_clearAlert())); |
| } |
| |
| void QWindowPrivate::_q_clearAlert() |
| { |
| if (platformWindow && platformWindow->isAlertState()) |
| platformWindow->setAlertState(false); |
| } |
| |
| #ifndef QT_NO_CURSOR |
| /*! |
| \brief set the cursor shape for this window |
| |
| The mouse \a cursor will assume this shape when it is over this |
| window, unless an override cursor is set. |
| See the \l{Qt::CursorShape}{list of predefined cursor objects} for a |
| range of useful shapes. |
| |
| If no cursor has been set, or after a call to unsetCursor(), the |
| parent window's cursor is used. |
| |
| By default, the cursor has the Qt::ArrowCursor shape. |
| |
| Some underlying window implementations will reset the cursor if it |
| leaves a window even if the mouse is grabbed. If you want to have |
| a cursor set for all windows, even when outside the window, consider |
| QGuiApplication::setOverrideCursor(). |
| |
| \sa QGuiApplication::setOverrideCursor() |
| */ |
| void QWindow::setCursor(const QCursor &cursor) |
| { |
| Q_D(QWindow); |
| d->setCursor(&cursor); |
| } |
| |
| /*! |
| \brief Restores the default arrow cursor for this window. |
| */ |
| void QWindow::unsetCursor() |
| { |
| Q_D(QWindow); |
| d->setCursor(nullptr); |
| } |
| |
| /*! |
| \brief the cursor shape for this window |
| |
| \sa setCursor(), unsetCursor() |
| */ |
| QCursor QWindow::cursor() const |
| { |
| Q_D(const QWindow); |
| return d->cursor; |
| } |
| |
| void QWindowPrivate::setCursor(const QCursor *newCursor) |
| { |
| |
| Q_Q(QWindow); |
| if (newCursor) { |
| const Qt::CursorShape newShape = newCursor->shape(); |
| if (newShape <= Qt::LastCursor && hasCursor && newShape == cursor.shape()) |
| return; // Unchanged and no bitmap/custom cursor. |
| cursor = *newCursor; |
| hasCursor = true; |
| } else { |
| if (!hasCursor) |
| return; |
| cursor = QCursor(Qt::ArrowCursor); |
| hasCursor = false; |
| } |
| // Only attempt to emit signal if there is an actual platform cursor |
| if (applyCursor()) { |
| QEvent event(QEvent::CursorChange); |
| QGuiApplication::sendEvent(q, &event); |
| } |
| } |
| |
| // Apply the cursor and returns true iff the platform cursor exists |
| bool QWindowPrivate::applyCursor() |
| { |
| Q_Q(QWindow); |
| if (QScreen *screen = q->screen()) { |
| if (QPlatformCursor *platformCursor = screen->handle()->cursor()) { |
| 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); |
| return true; |
| } |
| } |
| return false; |
| } |
| #endif // QT_NO_CURSOR |
| |
| #ifndef QT_NO_DEBUG_STREAM |
| QDebug operator<<(QDebug debug, const QWindow *window) |
| { |
| QDebugStateSaver saver(debug); |
| debug.nospace(); |
| if (window) { |
| debug << window->metaObject()->className() << '(' << (const void *)window; |
| if (!window->objectName().isEmpty()) |
| debug << ", name=" << window->objectName(); |
| if (debug.verbosity() > 2) { |
| const QRect geometry = window->geometry(); |
| if (window->isVisible()) |
| debug << ", visible"; |
| if (window->isExposed()) |
| debug << ", exposed"; |
| debug << ", state=" << window->windowState() |
| << ", type=" << window->type() << ", flags=" << window->flags() |
| << ", surface type=" << window->surfaceType(); |
| if (window->isTopLevel()) |
| debug << ", toplevel"; |
| debug << ", " << geometry.width() << 'x' << geometry.height() |
| << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign; |
| const QMargins margins = window->frameMargins(); |
| if (!margins.isNull()) |
| debug << ", margins=" << margins; |
| debug << ", devicePixelRatio=" << window->devicePixelRatio(); |
| if (const QPlatformWindow *platformWindow = window->handle()) |
| debug << ", winId=0x" << Qt::hex << platformWindow->winId() << Qt::dec; |
| if (const QScreen *screen = window->screen()) |
| debug << ", on " << screen->name(); |
| } |
| debug << ')'; |
| } else { |
| debug << "QWindow(0x0)"; |
| } |
| return debug; |
| } |
| #endif // !QT_NO_DEBUG_STREAM |
| |
| #if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC) |
| |
| /*! |
| 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 associated Vulkan instance if any was set, otherwise \nullptr. |
| */ |
| QVulkanInstance *QWindow::vulkanInstance() const |
| { |
| Q_D(const QWindow); |
| return d->vulkanInstance; |
| } |
| |
| #endif // QT_CONFIG(vulkan) |
| |
| QT_END_NAMESPACE |
| |
| #include "moc_qwindow.cpp" |