Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwindow.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qwindow.h"
6
7#include <qpa/qplatformwindow.h>
8#include <qpa/qplatformintegration.h>
9#ifndef QT_NO_CONTEXTMENU
10#include <qpa/qplatformtheme.h>
11#endif
12#include "qsurfaceformat.h"
13#ifndef QT_NO_OPENGL
14#include <qpa/qplatformopenglcontext.h>
15#include "qopenglcontext.h"
17#endif
18#include "qscreen.h"
19
20#include "qwindow_p.h"
22#if QT_CONFIG(accessibility)
23# include "qaccessible.h"
24# include <private/qaccessiblecache_p.h>
25#endif
27#if QT_CONFIG(draganddrop)
28#include "qshapedpixmapdndwindow_p.h"
29#endif // QT_CONFIG(draganddrop)
30
31#include <private/qevent_p.h>
32#include <private/qeventpoint_p.h>
33#include <private/qguiapplication_p.h>
34
35#include <QtCore/QTimer>
36#include <QtCore/QDebug>
37
38#include <QStyleHints>
39#include <qpa/qplatformcursor.h>
40#include <qpa/qplatformwindow_p.h>
41
43
44/*!
45 \class QWindow
46 \inmodule QtGui
47 \since 5.0
48 \brief The QWindow class represents a window in the underlying windowing system.
49
50 A window that is supplied a parent becomes a native child window of
51 their parent window.
52
53 An application will typically use QWidget or QQuickView for its UI, and not
54 QWindow directly. Still, it is possible to render directly to a QWindow
55 with QBackingStore or QOpenGLContext, when wanting to keep dependencies to
56 a minimum or when wanting to use OpenGL directly. The
57 \l{Raster Window Example} and \l{OpenGL Window Example}
58 are useful reference examples for how to render to a QWindow using
59 either approach.
60
61 \section1 Resource Management
62
63 Windows can potentially use a lot of memory. A usual measurement is
64 width times height times color depth. A window might also include multiple
65 buffers to support double and triple buffering, as well as depth and stencil
66 buffers. To release a window's memory resources, call the destroy() function.
67
68 \section1 Content Orientation
69
70 QWindow has reportContentOrientationChange() that can be used to specify
71 the layout of the window contents in relation to the screen. The content
72 orientation is simply a hint to the windowing system about which
73 orientation the window contents are in. It's useful when you wish to keep
74 the same window size, but rotate the contents instead, especially when
75 doing rotation animations between different orientations. The windowing
76 system might use this value to determine the layout of system popups or
77 dialogs.
78
79 \section1 Visibility and Windowing System Exposure
80
81 By default, the window is not visible, and you must call setVisible(true),
82 or show() or similar to make it visible. To make a window hidden again,
83 call setVisible(false) or hide(). The visible property describes the state
84 the application wants the window to be in. Depending on the underlying
85 system, a visible window might still not be shown on the screen. It could,
86 for instance, be covered by other opaque windows or moved outside the
87 physical area of the screen. On windowing systems that have exposure
88 notifications, the isExposed() accessor describes whether the window should
89 be treated as directly visible on screen. The exposeEvent() function is
90 called whenever an area of the window is invalidated, for example due to the
91 exposure in the windowing system changing. On windowing systems that do not
92 make this information visible to the application, isExposed() will simply
93 return the same value as isVisible().
94
95 QWindow::Visibility queried through visibility() is a convenience API
96 combining the functions of visible() and windowStates().
97
98 \section1 Rendering
99
100 There are two Qt APIs that can be used to render content into a window,
101 QBackingStore for rendering with a QPainter and flushing the contents
102 to a window with type QSurface::RasterSurface, and QOpenGLContext for
103 rendering with OpenGL to a window with type QSurface::OpenGLSurface.
104
105 The application can start rendering as soon as isExposed() returns \c true,
106 and can keep rendering until it isExposed() returns \c false. To find out when
107 isExposed() changes, reimplement exposeEvent(). The window will always get
108 a resize event before the first expose event.
109
110 \section1 Initial Geometry
111
112 If the window's width and height are left uninitialized, the window will
113 get a reasonable default geometry from the platform window. If the position
114 is left uninitialized, then the platform window will allow the windowing
115 system to position the window. For example on X11, the window manager
116 usually does some kind of smart positioning to try to avoid having new
117 windows completely obscure existing windows. However setGeometry()
118 initializes both the position and the size, so if you want a fixed size but
119 an automatic position, you should call resize() or setWidth() and
120 setHeight() instead.
121*/
122
123/*!
124 Creates a window as a top level on the \a targetScreen.
125
126 The window is not shown until setVisible(true), show(), or similar is called.
127
128 \sa setScreen()
129*/
130QWindow::QWindow(QScreen *targetScreen)
131 : QObject(*new QWindowPrivate(), nullptr)
132 , QSurface(QSurface::Window)
133{
134 Q_D(QWindow);
135 d->init(nullptr, targetScreen);
136}
137
138/*!
139 Creates a window as a child of the given \a parent window.
140
141 The window will be embedded inside the parent window, its coordinates
142 relative to the parent.
143
144 The screen is inherited from the parent.
145
146 \sa setParent()
147*/
148QWindow::QWindow(QWindow *parent)
149 : QWindow(*new QWindowPrivate(), parent)
150{
151}
152
153/*!
154 Creates a window as a child of the given \a parent window with the \a dd
155 private implementation.
156
157 The window will be embedded inside the parent window, its coordinates
158 relative to the parent.
159
160 The screen is inherited from the parent.
161
162 \internal
163 \sa setParent()
164*/
165QWindow::QWindow(QWindowPrivate &dd, QWindow *parent)
166 : QObject(dd, nullptr)
167 , QSurface(QSurface::Window)
168{
169 Q_D(QWindow);
170 d->init(parent);
171}
172
173/*!
174 Destroys the window.
175*/
176QWindow::~QWindow()
177{
178 Q_D(QWindow);
179
180#if QT_CONFIG(accessibility)
181 if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing && QAccessible::isActive())
182 QAccessibleCache::instance()->sendObjectDestroyedEvent(this);
183#endif
184
185 // Delete child windows up front, instead of waiting for ~QObject,
186 // in case the destruction of the child references its parent as
187 // a (no longer valid) QWindow.
188 qDeleteAll(findChildren<QWindow *>(Qt::FindDirectChildrenOnly));
189
190 d->destroy();
191 // Decouple from parent before window goes under
192 setParent(nullptr);
193 QGuiApplicationPrivate::window_list.removeAll(this);
194 QGuiApplicationPrivate::popup_list.removeAll(this);
195 if (!QGuiApplicationPrivate::is_app_closing)
196 QGuiApplicationPrivate::instance()->modalWindowList.removeOne(this);
197
198 // thse are normally cleared in destroy(), but the window may in
199 // some cases end up becoming the focus window again, or receive an enter
200 // event. Clear it again here as a workaround. See QTBUG-75326.
201 if (QGuiApplicationPrivate::focus_window == this)
202 QGuiApplicationPrivate::focus_window = nullptr;
203 if (QGuiApplicationPrivate::currentMouseWindow == this)
204 QGuiApplicationPrivate::currentMouseWindow = nullptr;
205 if (QGuiApplicationPrivate::currentMousePressWindow == this)
206 QGuiApplicationPrivate::currentMousePressWindow = nullptr;
207
208 d->isWindow = false;
209}
210
211QWindowPrivate::QWindowPrivate(decltype(QObjectPrivateVersion) version)
212 : QObjectPrivate(version)
213{}
214
215QWindowPrivate::~QWindowPrivate()
216 = default;
217
218void QWindowPrivate::init(QWindow *parent, QScreen *targetScreen)
219{
220 Q_Q(QWindow);
221
222 q->QObject::setParent(parent);
223
224 isWindow = true;
225 parentWindow = static_cast<QWindow *>(q->QObject::parent());
226
227 QScreen *connectScreen = targetScreen ? targetScreen : QGuiApplication::primaryScreen();
228
229 if (!parentWindow)
230 connectToScreen(connectScreen);
231
232 // If your application aborts here, you are probably creating a QWindow
233 // before the screen list is populated.
234 if (Q_UNLIKELY(!parentWindow && !topLevelScreen)) {
235 qFatal("Cannot create window: no screens available");
236 }
237 QGuiApplicationPrivate::window_list.prepend(q);
238
239 requestedFormat = QSurfaceFormat::defaultFormat();
240 devicePixelRatio = connectScreen->devicePixelRatio();
241
242 QObject::connect(q, &QWindow::screenChanged, q, [q, this](QScreen *){
243 // We may have changed scaling; trigger resize event if needed,
244 // except on Windows, where we send resize events during WM_DPICHANGED
245 // event handling. FIXME: unify DPI change handling across all platforms.
246#ifndef Q_OS_WIN
247 if (const auto *handle = q->handle()) {
248 QWindowSystemInterfacePrivate::GeometryChangeEvent gce(q,
249 QHighDpi::fromNativeWindowGeometry(handle->QPlatformWindow::geometry(), q),
250 QHighDpi::fromNativePixels(handle->geometry(), q));
251 QGuiApplicationPrivate::processGeometryChangeEvent(&gce);
252 }
253#else
254 Q_UNUSED(q);
255#endif
256 updateDevicePixelRatio();
257 });
258
259 if (parentWindow) {
260 QChildWindowEvent childAddedEvent(QEvent::ChildWindowAdded, q);
261 QCoreApplication::sendEvent(parentWindow, &childAddedEvent);
262 }
263}
264
265/*!
266 \enum QWindow::Visibility
267 \since 5.1
268
269 This enum describes what part of the screen the window occupies or should
270 occupy.
271
272 \value Windowed The window occupies part of the screen, but not necessarily
273 the entire screen. This state will occur only on windowing systems which
274 support showing multiple windows simultaneously. In this state it is
275 possible for the user to move and resize the window manually, if
276 WindowFlags permit it and if it is supported by the windowing system.
277
278 \value Minimized The window is reduced to an entry or icon on the task bar,
279 dock, task list or desktop, depending on how the windowing system handles
280 minimized windows.
281
282 \value Maximized The window occupies one entire screen, and the titlebar is
283 still visible. On most windowing systems this is the state achieved by
284 clicking the maximize button on the toolbar.
285
286 \value FullScreen The window occupies one entire screen, is not resizable,
287 and there is no titlebar. On some platforms which do not support showing
288 multiple simultaneous windows, this can be the usual visibility when the
289 window is not hidden.
290
291 \value AutomaticVisibility This means to give the window a default visible
292 state, which might be fullscreen or windowed depending on the platform.
293 It can be given as a parameter to setVisibility but will never be
294 read back from the visibility accessor.
295
296 \value Hidden The window is not visible in any way, however it may remember
297 a latent visibility which can be restored by setting AutomaticVisibility.
298*/
299
300/*!
301 \property QWindow::visibility
302 \brief the screen-occupation state of the window
303 \since 5.1
304
305 Visibility is whether the window should appear in the windowing system as
306 normal, minimized, maximized, fullscreen or hidden.
307
308 To set the visibility to AutomaticVisibility means to give the window
309 a default visible state, which might be fullscreen or windowed depending on
310 the platform.
311 When reading the visibility property you will always get the actual state,
312 never AutomaticVisibility.
313
314 The default value is Hidden.
315*/
316QWindow::Visibility QWindow::visibility() const
317{
318 Q_D(const QWindow);
319 return d->visibility;
320}
321
322void QWindow::setVisibility(Visibility v)
323{
324 switch (v) {
325 case Hidden:
326 hide();
327 break;
328 case AutomaticVisibility:
329 show();
330 break;
331 case Windowed:
332 showNormal();
333 break;
334 case Minimized:
335 showMinimized();
336 break;
337 case Maximized:
338 showMaximized();
339 break;
340 case FullScreen:
341 showFullScreen();
342 break;
343 default:
344 Q_ASSERT(false);
345 }
346}
347
348/*
349 Subclasses may override this function to run custom setVisible
350 logic. Subclasses that do so must call the base class implementation
351 at some point to make the native window visible, and must not
352 call QWindow::setVisble() since that will recurse back here.
353*/
354void QWindowPrivate::setVisible(bool visible)
355{
356 Q_Q(QWindow);
357
358 if (this->visible != visible) {
359 this->visible = visible;
360 emit q->visibleChanged(visible);
361 updateVisibility();
362 } else if (platformWindow) {
363 // Visibility hasn't changed, and the platform window is in sync
364 return;
365 }
366
367 if (!platformWindow) {
368 // If we have a parent window, but the parent hasn't been created yet, we
369 // can defer creation until the parent is created or we're re-parented.
370 if (parentWindow && !parentWindow->handle())
371 return;
372
373 // We only need to create the window if it's being shown
374 if (visible) {
375 // FIXME: At this point we've already updated the visible state of
376 // the QWindow, so if the platform layer reads the window state during
377 // creation, and reflects that in the native window, it will end up
378 // with a visible window. This may in turn result in resize or expose
379 // events from the platform before we have sent the show event below.
380 q->create();
381 }
382 }
383
384 if (visible) {
385 // remove posted quit events when showing a new window
386 QCoreApplication::removePostedEvents(qApp, QEvent::Quit);
387
388 if (q->type() == Qt::Window) {
389 QGuiApplicationPrivate *app_priv = QGuiApplicationPrivate::instance();
390 QString &firstWindowTitle = app_priv->firstWindowTitle;
391 if (!firstWindowTitle.isEmpty()) {
392 q->setTitle(firstWindowTitle);
393 firstWindowTitle = QString();
394 }
395 if (!app_priv->forcedWindowIcon.isNull())
396 q->setIcon(app_priv->forcedWindowIcon);
397
398 // Handling of the -qwindowgeometry, -geometry command line arguments
399 static bool geometryApplied = false;
400 if (!geometryApplied) {
401 geometryApplied = true;
402 QGuiApplicationPrivate::applyWindowGeometrySpecificationTo(q);
403 }
404 }
405
406 QShowEvent showEvent;
407 QGuiApplication::sendEvent(q, &showEvent);
408 }
409
410 if (q->isModal()) {
411 if (visible)
412 QGuiApplicationPrivate::showModalWindow(q);
413 else
414 QGuiApplicationPrivate::hideModalWindow(q);
415 // QShapedPixmapWindow is used on some platforms for showing a drag pixmap, so don't block
416 // input to this window as it is performing a drag - QTBUG-63846
417 } else if (visible && QGuiApplication::modalWindow()
418#if QT_CONFIG(draganddrop)
419 && !qobject_cast<QShapedPixmapWindow *>(q)
420#endif // QT_CONFIG(draganddrop)
421 ) {
422 QGuiApplicationPrivate::updateBlockedStatus(q);
423 }
424
425 if (q->type() == Qt::Popup) {
426 if (visible)
427 QGuiApplicationPrivate::activatePopup(q);
428 else
429 QGuiApplicationPrivate::closePopup(q);
430 }
431
432#ifndef QT_NO_CURSOR
433 if (visible && (hasCursor || QGuiApplication::overrideCursor()))
434 applyCursor();
435#endif
436
437 if (platformWindow)
438 platformWindow->setVisible(visible);
439
440 if (!visible) {
441 QHideEvent hideEvent;
442 QGuiApplication::sendEvent(q, &hideEvent);
443 }
444}
445
446void QWindowPrivate::updateVisibility()
447{
448 Q_Q(QWindow);
449
450 QWindow::Visibility old = visibility;
451
452 if (!visible)
453 visibility = QWindow::Hidden;
454 else if (windowState & Qt::WindowMinimized)
455 visibility = QWindow::Minimized;
456 else if (windowState & Qt::WindowFullScreen)
457 visibility = QWindow::FullScreen;
458 else if (windowState & Qt::WindowMaximized)
459 visibility = QWindow::Maximized;
460 else
461 visibility = QWindow::Windowed;
462
463 if (visibility != old)
464 emit q->visibilityChanged(visibility);
465}
466
467void QWindowPrivate::updateSiblingPosition(SiblingPosition position)
468{
469 Q_Q(QWindow);
470
471 if (!q->parent())
472 return;
473
474 QObjectList &siblings = q->parent()->d_ptr->children;
475
476 const qsizetype siblingCount = siblings.size() - 1;
477 if (siblingCount == 0)
478 return;
479
480 const qsizetype currentPosition = siblings.indexOf(q);
481 Q_ASSERT(currentPosition >= 0);
482
483 const qsizetype targetPosition = position == PositionTop ? siblingCount : 0;
484
485 if (currentPosition == targetPosition)
486 return;
487
488 siblings.move(currentPosition, targetPosition);
489}
490
491bool QWindowPrivate::windowRecreationRequired(QScreen *newScreen) const
492{
493 Q_Q(const QWindow);
494 const QScreen *oldScreen = q->screen();
495 return oldScreen != newScreen && (platformWindow || !oldScreen)
496 && !(oldScreen && oldScreen->virtualSiblings().contains(newScreen));
497}
498
499void QWindowPrivate::disconnectFromScreen()
500{
501 if (topLevelScreen)
502 topLevelScreen = nullptr;
503}
504
505void QWindowPrivate::connectToScreen(QScreen *screen)
506{
507 disconnectFromScreen();
508 topLevelScreen = screen;
509}
510
511void QWindowPrivate::emitScreenChangedRecursion(QScreen *newScreen)
512{
513 Q_Q(QWindow);
514 emit q->screenChanged(newScreen);
515 for (QObject *child : q->children()) {
516 if (child->isWindowType())
517 static_cast<QWindow *>(child)->d_func()->emitScreenChangedRecursion(newScreen);
518 }
519}
520
521void QWindowPrivate::setTopLevelScreen(QScreen *newScreen, bool recreate)
522{
523 Q_Q(QWindow);
524 if (parentWindow) {
525 qWarning() << q << '(' << newScreen << "): Attempt to set a screen on a child window.";
526 return;
527 }
528 if (newScreen != topLevelScreen) {
529 const bool shouldRecreate = recreate && windowRecreationRequired(newScreen);
530 const bool shouldShow = visibilityOnDestroy && !topLevelScreen;
531 if (shouldRecreate && platformWindow)
532 q->destroy();
533 connectToScreen(newScreen);
534 if (shouldShow)
535 q->setVisible(true);
536 else if (newScreen && shouldRecreate)
537 create(true);
538 emitScreenChangedRecursion(newScreen);
539 }
540}
541
542static constexpr auto kForeignWindowId = "_q_foreignWinId";
543
544void QWindowPrivate::create(bool recursive)
545{
546 Q_Q(QWindow);
547 if (platformWindow)
548 return;
549
550 // avoid losing update requests when re-creating
551 const bool needsUpdate = updateRequestPending;
552 // the platformWindow, if there was one, is now gone, so make this flag reflect reality now
553 updateRequestPending = false;
554
555 if (q->parent())
556 q->parent()->create();
557
558 if (platformWindow) {
559 // Creating the parent window will end up creating any child window
560 // that was already visible, via setVisible. If this applies to us,
561 // we will already have a platform window at this point.
562 return;
563 }
564
565 // QPlatformWindow will poll geometry() during construction below. Set the
566 // screen here so that high-dpi scaling will use the correct scale factor.
567 if (q->isTopLevel()) {
568 if (QScreen *screen = screenForGeometry(geometry))
569 setTopLevelScreen(screen, false);
570 }
571
572 const WId nativeHandle = q->property(kForeignWindowId).value<WId>();
573
574 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
575 platformWindow = nativeHandle ? platformIntegration->createForeignWindow(q, nativeHandle)
576 : platformIntegration->createPlatformWindow(q);
577 Q_ASSERT(platformWindow);
578
579 if (!platformWindow) {
580 qWarning() << "Failed to create platform window for" << q << "with flags" << q->flags();
581 return;
582 }
583
584 platformWindow->initialize();
585
586 QObjectList childObjects = q->children();
587 for (int i = 0; i < childObjects.size(); i ++) {
588 QObject *object = childObjects.at(i);
589 if (!object->isWindowType())
590 continue;
591
592 QWindow *childWindow = static_cast<QWindow *>(object);
593 if (recursive)
594 childWindow->d_func()->create(recursive);
595
596 // The child may have had deferred creation due to this window not being created
597 // at the time setVisible was called, so we re-apply the visible state, which
598 // may result in creating the child, and emitting the appropriate signals.
599 if (childWindow->isVisible())
600 childWindow->setVisible(true);
601
602 if (QPlatformWindow *childPlatformWindow = childWindow->d_func()->platformWindow)
603 childPlatformWindow->setParent(this->platformWindow);
604 }
605
606 QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated);
607 QGuiApplication::sendEvent(q, &e);
608
609 updateDevicePixelRatio();
610
611 if (needsUpdate)
612 q->requestUpdate();
613}
614
615void QWindowPrivate::clearFocusObject()
616{
617}
618
619// Allows for manipulating the suggested geometry before a resize/move
620// event in derived classes for platforms that support it, for example to
621// implement heightForWidth().
622QRectF QWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const
623{
624 Q_UNUSED(rect);
625 return QRectF();
626}
627
628void QWindowPrivate::setMinOrMaxSize(QSize *oldSizeMember, const QSize &size,
629 qxp::function_ref<void()> funcWidthChanged,
630 qxp::function_ref<void()> funcHeightChanged)
631{
632 Q_Q(QWindow);
633 Q_ASSERT(oldSizeMember);
634 const QSize adjustedSize =
635 size.expandedTo(QSize(0, 0)).boundedTo(QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX));
636 if (*oldSizeMember == adjustedSize)
637 return;
638 const bool widthChanged = adjustedSize.width() != oldSizeMember->width();
639 const bool heightChanged = adjustedSize.height() != oldSizeMember->height();
640 *oldSizeMember = adjustedSize;
641
642 if (platformWindow && q->isTopLevel())
643 platformWindow->propagateSizeHints();
644
645 if (widthChanged)
646 funcWidthChanged();
647 if (heightChanged)
648 funcHeightChanged();
649
650 // resize window if current size is outside of min and max limits
651 if (minimumSize.width() <= maximumSize.width()
652 || minimumSize.height() <= maximumSize.height()) {
653 const QSize currentSize = q->size();
654 const QSize boundedSize = currentSize.expandedTo(minimumSize).boundedTo(maximumSize);
655 q->resize(boundedSize);
656 }
657}
658
659/*!
660 Sets the \a surfaceType of the window.
661
662 Specifies whether the window is meant for raster rendering with
663 QBackingStore, or OpenGL rendering with QOpenGLContext.
664
665 The surfaceType will be used when the native surface is created
666 in the create() function. Calling this function after the native
667 surface has been created requires calling destroy() and create()
668 to release the old native surface and create a new one.
669
670 \sa QBackingStore, QOpenGLContext, create(), destroy()
671*/
672void QWindow::setSurfaceType(SurfaceType surfaceType)
673{
674 Q_D(QWindow);
675 d->surfaceType = surfaceType;
676}
677
678/*!
679 Returns the surface type of the window.
680
681 \sa setSurfaceType()
682*/
683QWindow::SurfaceType QWindow::surfaceType() const
684{
685 Q_D(const QWindow);
686 return d->surfaceType;
687}
688
689/*!
690 \property QWindow::visible
691 \brief whether the window is visible or not
692
693 This property controls the visibility of the window in the windowing system.
694
695 By default, the window is not visible, you must call setVisible(true), or
696 show() or similar to make it visible.
697
698 \note Hiding a window does not remove the window from the windowing system,
699 it only hides it. On windowing systems that give full screen applications a
700 dedicated desktop (such as macOS), hiding a full screen window will not remove
701 that desktop, but leave it blank. Another window from the same application
702 might be shown full screen, and will fill that desktop. Use QWindow::close to
703 completely remove a window from the windowing system.
704
705 \sa show()
706*/
707void QWindow::setVisible(bool visible)
708{
709 Q_D(QWindow);
710
711 d->setVisible(visible);
712}
713
714bool QWindow::isVisible() const
715{
716 Q_D(const QWindow);
717
718 return d->visible;
719}
720
721/*!
722 Allocates the platform resources associated with the window.
723
724 It is at this point that the surface format set using setFormat() gets resolved
725 into an actual native surface. However, the window remains hidden until setVisible() is called.
726
727 Note that it is not usually necessary to call this function directly, as it will be implicitly
728 called by show(), setVisible(), winId(), and other functions that require access to the platform
729 resources.
730
731 Call destroy() to free the platform resources if necessary.
732
733 \sa destroy()
734*/
735void QWindow::create()
736{
737 Q_D(QWindow);
738 d->create(false);
739}
740
741/*!
742 Returns the window's platform id.
743
744 \note This function will cause the platform window to be created if it is not already.
745 Returns 0, if the platform window creation failed.
746
747 For platforms where this id might be useful, the value returned
748 will uniquely represent the window inside the corresponding screen.
749
750 \sa screen()
751*/
752WId QWindow::winId() const
753{
754 Q_D(const QWindow);
755
756 if (!d->platformWindow)
757 const_cast<QWindow *>(this)->create();
758
759 if (!d->platformWindow)
760 return 0;
761
762 return d->platformWindow->winId();
763}
764
765 /*!
766 Returns the parent window, if any.
767
768 If \a mode is IncludeTransients, then the transient parent is returned
769 if there is no parent.
770
771 A window without a parent is known as a top level window.
772
773 \since 5.9
774*/
775QWindow *QWindow::parent(AncestorMode mode) const
776{
777 Q_D(const QWindow);
778 return d->parentWindow ? d->parentWindow : (mode == IncludeTransients ? transientParent() : nullptr);
779}
780
781/*!
782 Sets the \a parent Window. This will lead to the windowing system managing
783 the clip of the window, so it will be clipped to the \a parent window.
784
785 Setting \a parent to be \nullptr will make the window become a top level
786 window.
787
788 If \a parent is a window created by fromWinId(), then the current window
789 will be embedded inside \a parent, if the platform supports it.
790*/
791void QWindow::setParent(QWindow *parent)
792{
793 Q_D(QWindow);
794 if (d->parentWindow == parent
795 // Allow explicit reparenting to top level for embedded windows
796 && !(d->platformWindow && d->platformWindow->isEmbedded())) {
797 return;
798 }
799
800 QScreen *oldScreen = screen();
801 QScreen *newScreen = parent ? parent->screen() : oldScreen;
802 if (d->windowRecreationRequired(newScreen)) {
803 qWarning() << this << '(' << parent << "): Cannot change screens (" << oldScreen << newScreen << ')';
804 return;
805 }
806
807 QEvent parentAboutToChangeEvent(QEvent::ParentWindowAboutToChange);
808 QCoreApplication::sendEvent(this, &parentAboutToChangeEvent);
809
810 const auto previousParent = d->parentWindow;
811 QObject::setParent(parent);
812 d->parentWindow = parent;
813
814 if (parent)
815 d->disconnectFromScreen();
816 else
817 d->connectToScreen(newScreen);
818
819 // If we were set visible, but not created because we were a child, and we're now
820 // re-parented into a created parent, or to being a top level, we need re-apply the
821 // visibility state, which will also create.
822 if (isVisible() && (!parent || parent->handle()))
823 setVisible(true);
824
825 if (d->platformWindow) {
826 if (parent)
827 parent->create();
828
829 d->platformWindow->setParent(parent ? parent->d_func()->platformWindow : nullptr);
830 }
831
832 QGuiApplicationPrivate::updateBlockedStatus(this);
833
834 if (previousParent) {
835 QChildWindowEvent childRemovedEvent(QEvent::ChildWindowRemoved, this);
836 QCoreApplication::sendEvent(previousParent, &childRemovedEvent);
837 }
838
839 if (parent) {
840 QChildWindowEvent childAddedEvent(QEvent::ChildWindowAdded, this);
841 QCoreApplication::sendEvent(parent, &childAddedEvent);
842 }
843
844 QEvent parentChangedEvent(QEvent::ParentWindowChange);
845 QCoreApplication::sendEvent(this, &parentChangedEvent);
846#if QT_CONFIG(accessibility)
847 if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing) {
848 QAccessibleEvent qaEvent(this, QAccessible::ParentChanged);
849 QAccessible::updateAccessibility(&qaEvent);
850 }
851#endif
852
853 // The QPA layer should detect screen changes for child windows, and emit
854 // QWSI::handleWindowScreenChanged, but due to the ordering above where the
855 // parentWindow member is updated before calling setParent on the platform
856 // window we'll end up treating those callbacks from the QPA layer as noops
857 // in processWindowScreenChangedEvent since the screen is already up to date.
858 // To work around this we emit an explicit update here.
859 if (parent && screen() != oldScreen)
860 d->emitScreenChangedRecursion(screen());
861}
862
863/*!
864 Returns whether the window is top level, i.e. has no parent window.
865*/
866bool QWindow::isTopLevel() const
867{
868 Q_D(const QWindow);
869 return d->parentWindow == nullptr;
870}
871
872/*!
873 Returns whether the window is modal.
874
875 A modal window prevents other windows from getting any input.
876
877 \sa QWindow::modality
878*/
879bool QWindow::isModal() const
880{
881 Q_D(const QWindow);
882 return d->modality != Qt::NonModal;
883}
884
885/*! \property QWindow::modality
886 \brief the modality of the window
887
888 A modal window prevents other windows from receiving input events. Qt
889 supports two types of modality: Qt::WindowModal and Qt::ApplicationModal.
890
891 By default, this property is Qt::NonModal
892
893 \sa Qt::WindowModality
894*/
895
896Qt::WindowModality QWindow::modality() const
897{
898 Q_D(const QWindow);
899 return d->modality;
900}
901
902void QWindow::setModality(Qt::WindowModality modality)
903{
904 Q_D(QWindow);
905 if (d->modality == modality)
906 return;
907 d->modality = modality;
908 emit modalityChanged(modality);
909}
910
911/*! \fn void QWindow::modalityChanged(Qt::WindowModality modality)
912
913 This signal is emitted when the Qwindow::modality property changes to \a modality.
914*/
915
916/*!
917 Sets the window's surface \a format.
918
919 The format determines properties such as color depth, alpha, depth and
920 stencil buffer size, etc. For example, to give a window a transparent
921 background (provided that the window system supports compositing, and
922 provided that other content in the window does not make it opaque again):
923
924 \code
925 QSurfaceFormat format;
926 format.setAlphaBufferSize(8);
927 window.setFormat(format);
928 \endcode
929
930 The surface format will be resolved in the create() function. Calling
931 this function after create() has been called will not re-resolve the
932 surface format of the native surface.
933
934 When the format is not explicitly set via this function, the format returned
935 by QSurfaceFormat::defaultFormat() will be used. This means that when having
936 multiple windows, individual calls to this function can be replaced by one
937 single call to QSurfaceFormat::setDefaultFormat() before creating the first
938 window.
939
940 \sa create(), destroy(), QSurfaceFormat::setDefaultFormat()
941*/
942void QWindow::setFormat(const QSurfaceFormat &format)
943{
944 Q_D(QWindow);
945 d->requestedFormat = format;
946}
947
948/*!
949 Returns the requested surface format of this window.
950
951 If the requested format was not supported by the platform implementation,
952 the requestedFormat will differ from the actual window format.
953
954 This is the value set with setFormat().
955
956 \sa setFormat(), format()
957 */
958QSurfaceFormat QWindow::requestedFormat() const
959{
960 Q_D(const QWindow);
961 return d->requestedFormat;
962}
963
964/*!
965 Returns the actual format of this window.
966
967 After the window has been created, this function will return the actual surface format
968 of the window. It might differ from the requested format if the requested format could
969 not be fulfilled by the platform. It might also be a superset, for example certain
970 buffer sizes may be larger than requested.
971
972 \note Depending on the platform, certain values in this surface format may still
973 contain the requested values, that is, the values that have been passed to
974 setFormat(). Typical examples are the OpenGL version, profile and options. These may
975 not get updated during create() since these are context specific and a single window
976 may be used together with multiple contexts over its lifetime. Use the
977 QOpenGLContext's format() instead to query such values.
978
979 \sa create(), requestedFormat(), QOpenGLContext::format()
980*/
981QSurfaceFormat QWindow::format() const
982{
983 Q_D(const QWindow);
984 if (d->platformWindow)
985 return d->platformWindow->format();
986 return d->requestedFormat;
987}
988
989/*!
990 \property QWindow::flags
991 \brief the window flags of the window
992
993 The window flags control the window's appearance in the windowing system,
994 whether it's a dialog, popup, or a regular window, and whether it should
995 have a title bar, etc.
996
997 The actual window flags might differ from the flags set with setFlags()
998 if the requested flags could not be fulfilled.
999
1000 \sa setFlag()
1001*/
1002void QWindow::setFlags(Qt::WindowFlags flags)
1003{
1004 Q_D(QWindow);
1005 if (d->windowFlags == flags)
1006 return;
1007
1008 if (d->platformWindow) {
1009 d->platformWindow->setWindowFlags(flags);
1010 } else if (d->windowFlags & Qt::ExpandedClientAreaHint &&
1011 !(flags & Qt::ExpandedClientAreaHint)) {
1012 // A window with an expanded client area had geometry that
1013 // covered the entire frame, so if the flag is removed and
1014 // the window then created we need to apply the current
1015 // geometry with that in mind.
1016 d->positionPolicy = QWindowPrivate::WindowFrameInclusive;
1017 }
1018
1019 d->windowFlags = flags;
1020
1021 emit flagsChanged(this->flags());
1022}
1023
1024Qt::WindowFlags QWindow::flags() const
1025{
1026 Q_D(const QWindow);
1027 Qt::WindowFlags flags = d->windowFlags;
1028
1029 if (d->platformWindow && d->platformWindow->isForeignWindow())
1030 flags |= Qt::ForeignWindow;
1031
1032 return flags;
1033}
1034
1035/*!
1036 \since 5.9
1037
1038 Sets the window flag \a flag on this window if \a on is true;
1039 otherwise clears the flag.
1040
1041 \sa setFlags(), flags(), type()
1042*/
1043void QWindow::setFlag(Qt::WindowType flag, bool on)
1044{
1045 Q_D(QWindow);
1046 if (on)
1047 setFlags(d->windowFlags | flag);
1048 else
1049 setFlags(d->windowFlags & ~flag);
1050}
1051
1052/*!
1053 Returns the type of the window.
1054
1055 This returns the part of the window flags that represents
1056 whether the window is a dialog, tooltip, popup, regular window, etc.
1057
1058 \sa flags(), setFlags()
1059*/
1060Qt::WindowType QWindow::type() const
1061{
1062 return static_cast<Qt::WindowType>(int(flags() & Qt::WindowType_Mask));
1063}
1064
1065/*!
1066 \property QWindow::title
1067 \brief the window's title in the windowing system
1068
1069 The window title might appear in the title area of the window decorations,
1070 depending on the windowing system and the window flags. It might also
1071 be used by the windowing system to identify the window in other contexts,
1072 such as in the task switcher.
1073
1074 \sa flags()
1075*/
1076void QWindow::setTitle(const QString &title)
1077{
1078 Q_D(QWindow);
1079 bool changed = false;
1080 if (d->windowTitle != title) {
1081 d->windowTitle = title;
1082 changed = true;
1083 }
1084 if (d->platformWindow)
1085 d->platformWindow->setWindowTitle(title);
1086 if (changed)
1087 emit windowTitleChanged(title);
1088}
1089
1090QString QWindow::title() const
1091{
1092 Q_D(const QWindow);
1093 return d->windowTitle;
1094}
1095
1096/*!
1097 \brief set the file name this window is representing.
1098
1099 The windowing system might use \a filePath to display the
1100 path of the document this window is representing in the tile bar.
1101
1102*/
1103void QWindow::setFilePath(const QString &filePath)
1104{
1105 Q_D(QWindow);
1106 d->windowFilePath = filePath;
1107 if (d->platformWindow)
1108 d->platformWindow->setWindowFilePath(filePath);
1109}
1110
1111/*!
1112 \brief the file name this window is representing.
1113
1114 \sa setFilePath()
1115*/
1116QString QWindow::filePath() const
1117{
1118 Q_D(const QWindow);
1119 return d->windowFilePath;
1120}
1121
1122/*!
1123 \brief Sets the window's \a icon in the windowing system
1124
1125 The window icon might be used by the windowing system for example to
1126 decorate the window, and/or in the task switcher.
1127
1128 \note On \macos, the window title bar icon is meant for windows representing
1129 documents, and will only show up if a file path is also set.
1130
1131 \sa setFilePath()
1132*/
1133void QWindow::setIcon(const QIcon &icon)
1134{
1135 Q_D(QWindow);
1136 d->windowIcon = icon;
1137 if (d->platformWindow)
1138 d->platformWindow->setWindowIcon(icon);
1139 QEvent e(QEvent::WindowIconChange);
1140 QCoreApplication::sendEvent(this, &e);
1141}
1142
1143/*!
1144 \brief Returns the window's icon in the windowing system
1145
1146 \sa setIcon()
1147*/
1148QIcon QWindow::icon() const
1149{
1150 Q_D(const QWindow);
1151 if (d->windowIcon.isNull())
1152 return QGuiApplication::windowIcon();
1153 return d->windowIcon;
1154}
1155
1156/*!
1157 Raise the window in the windowing system.
1158
1159 Requests that the window be raised to appear above other windows.
1160*/
1161void QWindow::raise()
1162{
1163 Q_D(QWindow);
1164
1165 d->updateSiblingPosition(QWindowPrivate::PositionTop);
1166
1167 if (d->platformWindow)
1168 d->platformWindow->raise();
1169}
1170
1171/*!
1172 Lower the window in the windowing system.
1173
1174 Requests that the window be lowered to appear below other windows.
1175*/
1176void QWindow::lower()
1177{
1178 Q_D(QWindow);
1179
1180 d->updateSiblingPosition(QWindowPrivate::PositionBottom);
1181
1182 if (d->platformWindow)
1183 d->platformWindow->lower();
1184}
1185
1186/*!
1187 \brief Start a system-specific resize operation
1188 \since 5.15
1189
1190 Calling this will start an interactive resize operation on the window by platforms
1191 that support it. The actual behavior may vary depending on the platform. Usually,
1192 it will make the window resize so that its edge follows the mouse cursor.
1193
1194 On platforms that support it, this method of resizing windows is preferred over
1195 \c setGeometry, because it allows a more native look and feel of resizing windows, e.g.
1196 letting the window manager snap this window against other windows, or special resizing
1197 behavior with animations when dragged to the edge of the screen.
1198
1199 \a edges should either be a single edge, or two adjacent edges (a corner). Other values
1200 are not allowed.
1201
1202 Returns true if the operation was supported by the system.
1203*/
1204bool QWindow::startSystemResize(Qt::Edges edges)
1205{
1206 Q_D(QWindow);
1207 if (Q_UNLIKELY(!isVisible() || !d->platformWindow || d->maximumSize == d->minimumSize))
1208 return false;
1209
1210 const bool isSingleEdge = edges == Qt::TopEdge || edges == Qt::RightEdge || edges == Qt::BottomEdge || edges == Qt::LeftEdge;
1211 const bool isCorner =
1212 edges == (Qt::TopEdge | Qt::LeftEdge) ||
1213 edges == (Qt::TopEdge | Qt::RightEdge) ||
1214 edges == (Qt::BottomEdge | Qt::RightEdge) ||
1215 edges == (Qt::BottomEdge | Qt::LeftEdge);
1216
1217 if (Q_UNLIKELY(!isSingleEdge && !isCorner)) {
1218 qWarning() << "Invalid edges" << edges << "passed to QWindow::startSystemResize, ignoring.";
1219 return false;
1220 }
1221
1222 return d->platformWindow->startSystemResize(edges);
1223}
1224
1225/*!
1226 \brief Start a system-specific move operation
1227 \since 5.15
1228
1229 Calling this will start an interactive move operation on the window by platforms
1230 that support it. The actual behavior may vary depending on the platform. Usually,
1231 it will make the window follow the mouse cursor until a mouse button is released.
1232
1233 On platforms that support it, this method of moving windows is preferred over
1234 \c setPosition, because it allows a more native look-and-feel of moving windows, e.g.
1235 letting the window manager snap this window against other windows, or special tiling
1236 or resizing behavior with animations when dragged to the edge of the screen.
1237 Furthermore, on some platforms such as Wayland, \c setPosition is not supported, so
1238 this is the only way the application can influence its position.
1239
1240 Returns true if the operation was supported by the system.
1241*/
1242bool QWindow::startSystemMove()
1243{
1244 Q_D(QWindow);
1245 if (Q_UNLIKELY(!isVisible() || !d->platformWindow))
1246 return false;
1247
1248 return d->platformWindow->startSystemMove();
1249}
1250
1251/*!
1252 \property QWindow::opacity
1253 \brief The opacity of the window in the windowing system.
1254 \since 5.1
1255
1256 If the windowing system supports window opacity, this can be used to fade the
1257 window in and out, or to make it semitransparent.
1258
1259 A value of 1.0 or above is treated as fully opaque, whereas a value of 0.0 or below
1260 is treated as fully transparent. Values inbetween represent varying levels of
1261 translucency between the two extremes.
1262
1263 The default value is 1.0.
1264*/
1265void QWindow::setOpacity(qreal level)
1266{
1267 Q_D(QWindow);
1268 if (level == d->opacity)
1269 return;
1270 d->opacity = level;
1271 if (d->platformWindow) {
1272 d->platformWindow->setOpacity(level);
1273 emit opacityChanged(level);
1274 }
1275}
1276
1277qreal QWindow::opacity() const
1278{
1279 Q_D(const QWindow);
1280 return d->opacity;
1281}
1282
1283/*!
1284 Sets the mask of the window.
1285
1286 The mask is a hint to the windowing system that the application does not
1287 want to receive mouse or touch input outside the given \a region.
1288
1289 The window manager may or may not choose to display any areas of the window
1290 not included in the mask, thus it is the application's responsibility to
1291 clear to transparent the areas that are not part of the mask.
1292*/
1293void QWindow::setMask(const QRegion &region)
1294{
1295 Q_D(QWindow);
1296 if (d->platformWindow)
1297 d->platformWindow->setMask(QHighDpi::toNativeLocalRegion(region, this));
1298 d->mask = region;
1299}
1300
1301/*!
1302 Returns the mask set on the window.
1303
1304 The mask is a hint to the windowing system that the application does not
1305 want to receive mouse or touch input outside the given region.
1306*/
1307QRegion QWindow::mask() const
1308{
1309 Q_D(const QWindow);
1310 return d->mask;
1311}
1312
1313/*!
1314 Requests the window to be activated, i.e. receive keyboard focus.
1315
1316 \sa isActive(), QGuiApplication::focusWindow()
1317*/
1318void QWindow::requestActivate()
1319{
1320 Q_D(QWindow);
1321 if (flags() & Qt::WindowDoesNotAcceptFocus) {
1322 qWarning() << "requestActivate() called for " << this << " which has Qt::WindowDoesNotAcceptFocus set.";
1323 return;
1324 }
1325 if (d->platformWindow)
1326 d->platformWindow->requestActivateWindow();
1327}
1328
1329/*!
1330 Returns if this window is exposed in the windowing system.
1331
1332 When the window is not exposed, it is shown by the application
1333 but it is still not showing in the windowing system, so the application
1334 should minimize animations and other graphical activities.
1335
1336 An exposeEvent() is sent every time this value changes.
1337
1338 \sa exposeEvent()
1339*/
1340bool QWindow::isExposed() const
1341{
1342 Q_D(const QWindow);
1343 return d->exposed;
1344}
1345
1346/*!
1347 \property QWindow::active
1348 \brief the active status of the window
1349 \since 5.1
1350
1351 \sa requestActivate()
1352*/
1353
1354/*!
1355 Returns \c true if the window is active.
1356
1357 This is the case for the window that has input focus as well as windows
1358 that are in the same parent / transient parent chain as the focus window.
1359
1360 Typically active windows should appear active from a style perspective.
1361
1362 To get the window that currently has focus, use QGuiApplication::focusWindow().
1363
1364 \sa requestActivate()
1365*/
1366bool QWindow::isActive() const
1367{
1368 Q_D(const QWindow);
1369 if (!d->platformWindow)
1370 return false;
1371
1372 QWindow *focus = QGuiApplication::focusWindow();
1373
1374 // Means the whole application lost the focus
1375 if (!focus)
1376 return false;
1377
1378 if (focus == this)
1379 return true;
1380
1381 if (QWindow *p = parent(IncludeTransients))
1382 return p->isActive();
1383 else
1384 return isAncestorOf(focus);
1385}
1386
1387/*!
1388 \property QWindow::contentOrientation
1389 \brief the orientation of the window's contents
1390
1391 This is a hint to the window manager in case it needs to display
1392 additional content like popups, dialogs, status bars, or similar
1393 in relation to the window.
1394
1395 The recommended orientation is QScreen::orientation() but
1396 an application doesn't have to support all possible orientations,
1397 and thus can opt to ignore the current screen orientation.
1398
1399 The difference between the window and the content orientation
1400 determines how much to rotate the content by. QScreen::angleBetween(),
1401 QScreen::transformBetween(), and QScreen::mapBetween() can be used
1402 to compute the necessary transform.
1403
1404 The default value is Qt::PrimaryOrientation
1405*/
1406void QWindow::reportContentOrientationChange(Qt::ScreenOrientation orientation)
1407{
1408 Q_D(QWindow);
1409 if (d->contentOrientation == orientation)
1410 return;
1411 if (d->platformWindow)
1412 d->platformWindow->handleContentOrientationChange(orientation);
1413 d->contentOrientation = orientation;
1414 emit contentOrientationChanged(orientation);
1415}
1416
1417Qt::ScreenOrientation QWindow::contentOrientation() const
1418{
1419 Q_D(const QWindow);
1420 return d->contentOrientation;
1421}
1422
1423/*!
1424 Returns the ratio between physical pixels and device-independent pixels
1425 for the window. This value is dependent on the screen the window is on,
1426 and may change when the window is moved.
1427
1428 The QWindow instance receives an event of type
1429 QEvent::DevicePixelRatioChange when the device pixel ratio changes.
1430
1431 Common values are 1.0 on normal displays and 2.0 on Apple "retina" displays.
1432
1433 \note For windows not backed by a platform window, meaning that create() was not
1434 called, the function will fall back to the associated QScreen's device pixel ratio.
1435
1436 \sa QScreen::devicePixelRatio(), QEvent::DevicePixelRatioChange
1437*/
1438qreal QWindow::devicePixelRatio() const
1439{
1440 Q_D(const QWindow);
1441 return d->devicePixelRatio;
1442}
1443
1444/*
1445 Updates the cached devicePixelRatio value by polling for a new value.
1446 Sends QEvent::DevicePixelRatioChange to the window if the DPR has changed.
1447 Returns true if the DPR was changed.
1448*/
1449bool QWindowPrivate::updateDevicePixelRatio()
1450{
1451 Q_Q(QWindow);
1452
1453 const qreal newDevicePixelRatio = [this, q]{
1454 if (platformWindow)
1455 return platformWindow->devicePixelRatio() * QHighDpiScaling::factor(q);
1456
1457 // If there is no platform window use the associated screen's devicePixelRatio,
1458 // which typically is the primary screen and will be correct for single-display
1459 // systems (a very common case).
1460 if (auto *screen = q->screen())
1461 return screen->devicePixelRatio();
1462
1463 // In some cases we are running without any QScreens, so fall back to QGuiApp
1464 return qGuiApp->devicePixelRatio();
1465 }();
1466
1467 if (newDevicePixelRatio == devicePixelRatio)
1468 return false;
1469
1470 devicePixelRatio = newDevicePixelRatio;
1471 QEvent dprChangeEvent(QEvent::DevicePixelRatioChange);
1472 QGuiApplication::sendEvent(q, &dprChangeEvent);
1473 return true;
1474}
1475
1476Qt::WindowState QWindowPrivate::effectiveState(Qt::WindowStates state)
1477{
1478 if (state & Qt::WindowMinimized)
1479 return Qt::WindowMinimized;
1480 else if (state & Qt::WindowFullScreen)
1481 return Qt::WindowFullScreen;
1482 else if (state & Qt::WindowMaximized)
1483 return Qt::WindowMaximized;
1484 return Qt::WindowNoState;
1485}
1486
1487/*!
1488 \brief set the screen-occupation state of the window
1489
1490 The window \a state represents whether the window appears in the
1491 windowing system as maximized, minimized, fullscreen, or normal.
1492
1493 The enum value Qt::WindowActive is not an accepted parameter.
1494
1495 \sa showNormal(), showFullScreen(), showMinimized(), showMaximized(), setWindowStates()
1496*/
1497void QWindow::setWindowState(Qt::WindowState state)
1498{
1499 setWindowStates(state);
1500}
1501
1502/*!
1503 \brief set the screen-occupation state of the window
1504 \since 5.10
1505
1506 The window \a state represents whether the window appears in the
1507 windowing system as maximized, minimized and/or fullscreen.
1508
1509 The window can be in a combination of several states. For example, if
1510 the window is both minimized and maximized, the window will appear
1511 minimized, but clicking on the task bar entry will restore it to the
1512 maximized state.
1513
1514 The enum value Qt::WindowActive should not be set.
1515
1516 \sa showNormal(), showFullScreen(), showMinimized(), showMaximized()
1517 */
1518void QWindow::setWindowStates(Qt::WindowStates state)
1519{
1520 Q_D(QWindow);
1521 if (state & Qt::WindowActive) {
1522 qWarning("QWindow::setWindowStates does not accept Qt::WindowActive");
1523 state &= ~Qt::WindowActive;
1524 }
1525
1526 if (d->platformWindow)
1527 d->platformWindow->setWindowState(state);
1528
1529 auto originalEffectiveState = QWindowPrivate::effectiveState(d->windowState);
1530 d->windowState = state;
1531 auto newEffectiveState = QWindowPrivate::effectiveState(d->windowState);
1532 if (newEffectiveState != originalEffectiveState)
1533 emit windowStateChanged(newEffectiveState);
1534
1535 d->updateVisibility();
1536}
1537
1538/*!
1539 \brief the screen-occupation state of the window
1540
1541 \sa setWindowState(), windowStates()
1542*/
1543Qt::WindowState QWindow::windowState() const
1544{
1545 Q_D(const QWindow);
1546 return QWindowPrivate::effectiveState(d->windowState);
1547}
1548
1549/*!
1550 \brief the screen-occupation state of the window
1551 \since 5.10
1552
1553 The window can be in a combination of several states. For example, if
1554 the window is both minimized and maximized, the window will appear
1555 minimized, but clicking on the task bar entry will restore it to
1556 the maximized state.
1557
1558 \sa setWindowStates()
1559*/
1560Qt::WindowStates QWindow::windowStates() const
1561{
1562 Q_D(const QWindow);
1563 return d->windowState;
1564}
1565
1566/*!
1567 \fn QWindow::windowStateChanged(Qt::WindowState windowState)
1568
1569 This signal is emitted when the \a windowState changes, either
1570 by being set explicitly with setWindowStates(), or automatically when
1571 the user clicks one of the titlebar buttons or by other means.
1572*/
1573
1574/*!
1575 \property QWindow::transientParent
1576 \brief the window for which this window is a transient pop-up
1577 \since 5.13
1578
1579 This is a hint to the window manager that this window is a dialog or pop-up
1580 on behalf of the transient parent.
1581
1582 In order to cause the window to be centered above its transient \a parent by
1583 default, depending on the window manager, it may also be necessary to call
1584 setFlags() with a suitable \l Qt::WindowType (such as \c Qt::Dialog).
1585
1586 \sa parent()
1587*/
1588void QWindow::setTransientParent(QWindow *parent)
1589{
1590 Q_D(QWindow);
1591 if (parent && !parent->isTopLevel()) {
1592 qWarning() << parent << "must be a top level window.";
1593 return;
1594 }
1595 if (parent == this) {
1596 qWarning() << "transient parent" << parent << "cannot be same as window";
1597 return;
1598 }
1599
1600 d->transientParent = parent;
1601
1602 QGuiApplicationPrivate::updateBlockedStatus(this);
1603 emit transientParentChanged(parent);
1604}
1605
1606QWindow *QWindow::transientParent() const
1607{
1608 Q_D(const QWindow);
1609 return d->transientParent.data();
1610}
1611
1612/*
1613 The setter for the QWindow::transientParent property.
1614 The only reason this exists is to set the transientParentPropertySet flag
1615 so that Qt Quick knows whether it was set programmatically (because of
1616 Window declaration context) or because the user set the property.
1617*/
1618void QWindowPrivate::setTransientParent(QWindow *parent)
1619{
1620 Q_Q(QWindow);
1621 q->setTransientParent(parent);
1622 transientParentPropertySet = true;
1623}
1624
1625/*!
1626 \enum QWindow::AncestorMode
1627
1628 This enum is used to control whether or not transient parents
1629 should be considered ancestors.
1630
1631 \value ExcludeTransients Transient parents are not considered ancestors.
1632 \value IncludeTransients Transient parents are considered ancestors.
1633*/
1634
1635/*!
1636 Returns \c true if the window is an ancestor of the given \a child. If \a mode
1637 is IncludeTransients, then transient parents are also considered ancestors.
1638*/
1639bool QWindow::isAncestorOf(const QWindow *child, AncestorMode mode) const
1640{
1641 if (child->parent() == this || (mode == IncludeTransients && child->transientParent() == this))
1642 return true;
1643
1644 if (QWindow *parent = child->parent(mode)) {
1645 if (isAncestorOf(parent, mode))
1646 return true;
1647 } else if (handle() && child->handle()) {
1648 if (handle()->isAncestorOf(child->handle()))
1649 return true;
1650 }
1651
1652 return false;
1653}
1654
1655/*!
1656 Returns the minimum size of the window.
1657
1658 \sa setMinimumSize()
1659*/
1660QSize QWindow::minimumSize() const
1661{
1662 Q_D(const QWindow);
1663 return d->minimumSize;
1664}
1665
1666/*!
1667 Returns the maximum size of the window.
1668
1669 \sa setMaximumSize()
1670*/
1671QSize QWindow::maximumSize() const
1672{
1673 Q_D(const QWindow);
1674 return d->maximumSize;
1675}
1676
1677/*!
1678 Returns the base size of the window.
1679
1680 \sa setBaseSize()
1681*/
1682QSize QWindow::baseSize() const
1683{
1684 Q_D(const QWindow);
1685 return d->baseSize;
1686}
1687
1688/*!
1689 Returns the size increment of the window.
1690
1691 \sa setSizeIncrement()
1692*/
1693QSize QWindow::sizeIncrement() const
1694{
1695 Q_D(const QWindow);
1696 return d->sizeIncrement;
1697}
1698
1699/*!
1700 Sets the minimum size of the window.
1701
1702 This is a hint to the window manager to prevent resizing below the specified \a size.
1703
1704 \sa setMaximumSize(), minimumSize()
1705*/
1706void QWindow::setMinimumSize(const QSize &size)
1707{
1708 Q_D(QWindow);
1709 d->setMinOrMaxSize(
1710 &d->minimumSize, size, [this, d]() { emit minimumWidthChanged(d->minimumSize.width()); },
1711 [this, d]() { emit minimumHeightChanged(d->minimumSize.height()); });
1712}
1713
1714/*!
1715 \property QWindow::x
1716 \brief the x position of the window's geometry
1717*/
1718void QWindow::setX(int arg)
1719{
1720 Q_D(QWindow);
1721 if (x() != arg)
1722 setGeometry(QRect(arg, y(), width(), height()));
1723 else
1724 d->positionAutomatic = false;
1725}
1726
1727/*!
1728 \property QWindow::y
1729 \brief the y position of the window's geometry
1730*/
1731void QWindow::setY(int arg)
1732{
1733 Q_D(QWindow);
1734 if (y() != arg)
1735 setGeometry(QRect(x(), arg, width(), height()));
1736 else
1737 d->positionAutomatic = false;
1738}
1739
1740/*!
1741 \property QWindow::width
1742 \brief the width of the window's geometry
1743*/
1744void QWindow::setWidth(int w)
1745{
1746 resize(w, height());
1747}
1748
1749/*!
1750 \property QWindow::height
1751 \brief the height of the window's geometry
1752*/
1753void QWindow::setHeight(int h)
1754{
1755 resize(width(), h);
1756}
1757
1758/*!
1759 \property QWindow::minimumWidth
1760 \brief the minimum width of the window's geometry
1761*/
1762void QWindow::setMinimumWidth(int w)
1763{
1764 setMinimumSize(QSize(w, minimumHeight()));
1765}
1766
1767/*!
1768 \property QWindow::minimumHeight
1769 \brief the minimum height of the window's geometry
1770*/
1771void QWindow::setMinimumHeight(int h)
1772{
1773 setMinimumSize(QSize(minimumWidth(), h));
1774}
1775
1776/*!
1777 Sets the maximum size of the window.
1778
1779 This is a hint to the window manager to prevent resizing above the specified \a size.
1780
1781 \sa setMinimumSize(), maximumSize()
1782*/
1783void QWindow::setMaximumSize(const QSize &size)
1784{
1785 Q_D(QWindow);
1786 d->setMinOrMaxSize(
1787 &d->maximumSize, size, [this, d]() { emit maximumWidthChanged(d->maximumSize.width()); },
1788 [this, d]() { emit maximumHeightChanged(d->maximumSize.height()); });
1789}
1790
1791/*!
1792 \property QWindow::maximumWidth
1793 \brief the maximum width of the window's geometry
1794*/
1795void QWindow::setMaximumWidth(int w)
1796{
1797 setMaximumSize(QSize(w, maximumHeight()));
1798}
1799
1800/*!
1801 \property QWindow::maximumHeight
1802 \brief the maximum height of the window's geometry
1803*/
1804void QWindow::setMaximumHeight(int h)
1805{
1806 setMaximumSize(QSize(maximumWidth(), h));
1807}
1808
1809/*!
1810 Sets the base \a size of the window.
1811
1812 The base size is used to calculate a proper window size if the
1813 window defines sizeIncrement().
1814
1815 \sa setMinimumSize(), setMaximumSize(), setSizeIncrement(), baseSize()
1816*/
1817void QWindow::setBaseSize(const QSize &size)
1818{
1819 Q_D(QWindow);
1820 if (d->baseSize == size)
1821 return;
1822 d->baseSize = size;
1823 if (d->platformWindow && isTopLevel())
1824 d->platformWindow->propagateSizeHints();
1825}
1826
1827/*!
1828 Sets the size increment (\a size) of the window.
1829
1830 When the user resizes the window, the size will move in steps of
1831 sizeIncrement().width() pixels horizontally and
1832 sizeIncrement().height() pixels vertically, with baseSize() as the
1833 basis.
1834
1835 By default, this property contains a size with zero width and height.
1836
1837 The windowing system might not support size increments.
1838
1839 \sa setBaseSize(), setMinimumSize(), setMaximumSize()
1840*/
1841void QWindow::setSizeIncrement(const QSize &size)
1842{
1843 Q_D(QWindow);
1844 if (d->sizeIncrement == size)
1845 return;
1846 d->sizeIncrement = size;
1847 if (d->platformWindow && isTopLevel())
1848 d->platformWindow->propagateSizeHints();
1849}
1850
1851/*!
1852 Sets the geometry of the window, excluding its window frame, to a
1853 rectangle constructed from \a posx, \a posy, \a w and \a h.
1854
1855 The geometry is in relation to the virtualGeometry() of its screen.
1856
1857 \sa geometry()
1858*/
1859void QWindow::setGeometry(int posx, int posy, int w, int h)
1860{
1861 setGeometry(QRect(posx, posy, w, h));
1862}
1863
1864/*!
1865 \brief Sets the geometry of the window, excluding its window frame, to \a rect.
1866
1867 The geometry is in relation to the virtualGeometry() of its screen.
1868
1869 \sa geometry()
1870*/
1871void QWindow::setGeometry(const QRect &rect)
1872{
1873 Q_D(QWindow);
1874 d->positionAutomatic = false;
1875 const QRect oldRect = geometry();
1876 if (rect == oldRect)
1877 return;
1878
1879 d->positionPolicy = QWindowPrivate::WindowFrameExclusive;
1880 if (d->platformWindow) {
1881 // Setting a new geometry may move the window to a new screen.
1882 // The QHighDpi layer needs to know the new screen to be able
1883 // to resolve the resulting geometry based on the screen's DPR,
1884 // so we update the screen before passing the geometry on to
1885 // the platform layer. FIXME: Find a way to tell QHighDpi about
1886 // the new screen without actually changing the screen, so that
1887 // the geometry change is the trigger for the screen change.
1888 QScreen *newScreen = d->screenForGeometry(rect);
1889 if (newScreen && isTopLevel())
1890 d->setTopLevelScreen(newScreen, true);
1891 d->platformWindow->setGeometry(QHighDpi::toNativeWindowGeometry(rect, this));
1892 } else {
1893 d->geometry = rect;
1894
1895 if (rect.x() != oldRect.x())
1896 emit xChanged(rect.x());
1897 if (rect.y() != oldRect.y())
1898 emit yChanged(rect.y());
1899 if (rect.width() != oldRect.width())
1900 emit widthChanged(rect.width());
1901 if (rect.height() != oldRect.height())
1902 emit heightChanged(rect.height());
1903 }
1904}
1905
1906/*
1907 This is equivalent to QPlatformWindow::screenForGeometry, but in platform
1908 independent coordinates. The duplication is unfortunate, but there is a
1909 chicken and egg problem here: we cannot convert to native coordinates
1910 before we know which screen we are on.
1911*/
1912QScreen *QWindowPrivate::screenForGeometry(const QRect &newGeometry) const
1913{
1914 Q_Q(const QWindow);
1915 QScreen *currentScreen = q->screen();
1916 QScreen *fallback = currentScreen;
1917 QPoint center = newGeometry.center();
1918 if (!q->parent() && currentScreen && !currentScreen->geometry().contains(center)) {
1919 const auto screens = currentScreen->virtualSiblings();
1920 for (QScreen* screen : screens) {
1921 if (screen->geometry().contains(center))
1922 return screen;
1923 if (screen->geometry().intersects(newGeometry))
1924 fallback = screen;
1925 }
1926 }
1927 return fallback;
1928}
1929
1930
1931/*!
1932 Returns the geometry of the window, excluding its window frame.
1933
1934 The geometry is in relation to the virtualGeometry() of its screen.
1935
1936 \sa frameMargins(), frameGeometry()
1937*/
1938QRect QWindow::geometry() const
1939{
1940 Q_D(const QWindow);
1941 if (d->platformWindow) {
1942 const auto nativeGeometry = d->platformWindow->geometry();
1943 return QHighDpi::fromNativeWindowGeometry(nativeGeometry, this);
1944 }
1945 return d->geometry;
1946}
1947
1948/*!
1949 Returns the window frame margins surrounding the window.
1950
1951 \sa geometry(), frameGeometry()
1952*/
1953QMargins QWindow::frameMargins() const
1954{
1955 Q_D(const QWindow);
1956 if (d->platformWindow)
1957 return QHighDpi::fromNativePixels(d->platformWindow->frameMargins(), this);
1958 return QMargins();
1959}
1960
1961/*!
1962 Returns the geometry of the window, including its window frame.
1963
1964 The geometry is in relation to the virtualGeometry() of its screen.
1965
1966 \sa geometry(), frameMargins()
1967*/
1968QRect QWindow::frameGeometry() const
1969{
1970 Q_D(const QWindow);
1971 if (d->platformWindow) {
1972 QMargins m = frameMargins();
1973 return QHighDpi::fromNativeWindowGeometry(d->platformWindow->geometry(), this).adjusted(-m.left(), -m.top(), m.right(), m.bottom());
1974 }
1975 return d->geometry;
1976}
1977
1978/*!
1979 Returns the top left position of the window, including its window frame.
1980
1981 This returns the same value as frameGeometry().topLeft().
1982
1983 \sa geometry(), frameGeometry()
1984*/
1985QPoint QWindow::framePosition() const
1986{
1987 Q_D(const QWindow);
1988 if (d->platformWindow) {
1989 QMargins margins = frameMargins();
1990 return QHighDpi::fromNativeWindowGeometry(d->platformWindow->geometry().topLeft(), this) - QPoint(margins.left(), margins.top());
1991 }
1992 return d->geometry.topLeft();
1993}
1994
1995/*!
1996 Sets the upper left position of the window (\a point) including its window frame.
1997
1998 The position is in relation to the virtualGeometry() of its screen.
1999
2000 \sa setGeometry(), frameGeometry()
2001*/
2002void QWindow::setFramePosition(const QPoint &point)
2003{
2004 Q_D(QWindow);
2005 d->positionPolicy = QWindowPrivate::WindowFrameInclusive;
2006 d->positionAutomatic = false;
2007 if (d->platformWindow) {
2008 d->platformWindow->setGeometry(QHighDpi::toNativeWindowGeometry(QRect(point, size()), this));
2009 } else {
2010 d->geometry.moveTopLeft(point);
2011 }
2012}
2013
2014/*!
2015 \fn void QWindow::setFramePosition(int x, int y)
2016 \brief Sets the upper left position of the window, including its window frame, to \a x, \a y
2017
2018 The position is in relation to the virtualGeometry() of its screen.
2019
2020 \since 6.12
2021 \sa setGeometry(), frameGeometry()
2022*/
2023
2024/*!
2025 Returns the safe area margins of the window.
2026
2027 The safe area represents the part of the window where content
2028 can be safely placed without risk of being obscured by, or
2029 conflicting with, other UI elements, such as system UIs.
2030
2031 The margins are relative to the internal geometry of the
2032 window, i.e QRect(0, 0, width(), height()).
2033
2034 \code
2035 void PaintDeviceWindow::paintEvent(QPaintEvent *)
2036 {
2037 QPainter painter(this);
2038 QRect rect(0, 0, width(), height());
2039 painter.fillRect(rect, QGradient::SunnyMorning);
2040 painter.fillRect(rect - safeAreaMargins(), QGradient::DustyGrass);
2041 }
2042 \endcode
2043
2044 \since 6.9
2045 \sa geometry(), safeAreaMarginsChanged()
2046*/
2047QMargins QWindow::safeAreaMargins() const
2048{
2049 Q_D(const QWindow);
2050 if (d->platformWindow)
2051 return QHighDpi::fromNativePixels(d->platformWindow->safeAreaMargins(), this);
2052 return {};
2053}
2054
2055/*!
2056 \fn void QWindow::safeAreaMarginsChanged(QMargins margins)
2057 \since 6.9
2058
2059 This signal is emitted when the safe area margins changed to \a margins.
2060
2061 \sa safeAreaMargins()
2062*/
2063
2064/*!
2065 \brief set the position of the window on the desktop to \a pt
2066
2067 The position is in relation to the virtualGeometry() of its screen.
2068
2069 For interactively moving windows, see startSystemMove(). For interactively
2070 resizing windows, see startSystemResize().
2071
2072 \note Not all windowing systems support setting or querying top level window positions.
2073 On such a system, programmatically moving windows may not have any effect, and artificial
2074 values may be returned for the current positions, such as \c QPoint(0, 0).
2075
2076 \sa position(), startSystemMove()
2077*/
2078void QWindow::setPosition(const QPoint &pt)
2079{
2080 setGeometry(QRect(pt, size()));
2081}
2082
2083/*!
2084 \brief set the position of the window on the desktop to \a posx, \a posy
2085
2086 The position is in relation to the virtualGeometry() of its screen.
2087
2088 \sa position()
2089*/
2090void QWindow::setPosition(int posx, int posy)
2091{
2092 setPosition(QPoint(posx, posy));
2093}
2094
2095/*!
2096 \fn QPoint QWindow::position() const
2097 \brief Returns the position of the window on the desktop excluding any window frame
2098
2099 \note Not all windowing systems support setting or querying top level window positions.
2100 On such a system, programmatically moving windows may not have any effect, and artificial
2101 values may be returned for the current positions, such as \c QPoint(0, 0).
2102
2103 \sa setPosition()
2104*/
2105
2106/*!
2107 \fn QSize QWindow::size() const
2108 \brief Returns the size of the window excluding any window frame
2109
2110 \sa resize()
2111*/
2112
2113/*!
2114 set the size of the window, excluding any window frame, to a QSize
2115 constructed from width \a w and height \a h
2116
2117 For interactively resizing windows, see startSystemResize().
2118
2119 \sa size(), geometry()
2120*/
2121void QWindow::resize(int w, int h)
2122{
2123 resize(QSize(w, h));
2124}
2125
2126/*!
2127 \brief set the size of the window, excluding any window frame, to \a newSize
2128
2129 \sa size(), geometry()
2130*/
2131void QWindow::resize(const QSize &newSize)
2132{
2133 Q_D(QWindow);
2134
2135 const QSize oldSize = size();
2136 if (newSize == oldSize)
2137 return;
2138
2139 d->positionPolicy = QWindowPrivate::WindowFrameExclusive;
2140 if (d->platformWindow) {
2141 d->platformWindow->setGeometry(
2142 QHighDpi::toNativeWindowGeometry(QRect(position(), newSize), this));
2143 } else {
2144 d->geometry.setSize(newSize);
2145 if (newSize.width() != oldSize.width())
2146 emit widthChanged(newSize.width());
2147 if (newSize.height() != oldSize.height())
2148 emit heightChanged(newSize.height());
2149 }
2150}
2151
2152/*!
2153 Releases the native platform resources associated with this window.
2154
2155 \sa create()
2156*/
2157void QWindow::destroy()
2158{
2159 Q_D(QWindow);
2160 if (!d->platformWindow)
2161 return;
2162
2163 if (d->platformWindow->isForeignWindow())
2164 return;
2165
2166 d->destroy();
2167}
2168
2169void QWindowPrivate::destroy()
2170{
2171 if (!platformWindow)
2172 return;
2173
2174 Q_Q(QWindow);
2175 QObjectList childrenWindows = q->children();
2176 for (int i = 0; i < childrenWindows.size(); i++) {
2177 QObject *object = childrenWindows.at(i);
2178 if (object->isWindowType()) {
2179 QWindow *w = static_cast<QWindow*>(object);
2180 qt_window_private(w)->destroy();
2181 }
2182 }
2183
2184 bool wasVisible = q->isVisible();
2185 visibilityOnDestroy = wasVisible && platformWindow;
2186
2187 q->setVisible(false);
2188
2189 // Let subclasses act, typically by doing graphics resource cleaup, when
2190 // the window, to which graphics resource may be tied, is going away.
2191 //
2192 // NB! This is dysfunctional when destroy() is invoked from the dtor since
2193 // a reimplemented event() will not get called in the subclasses at that
2194 // stage. However, the typical QWindow cleanup involves either close() or
2195 // going through QWindowContainer, both of which will do an explicit, early
2196 // destroy(), which is good here.
2197
2198 QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed);
2199 QGuiApplication::sendEvent(q, &e);
2200
2201 // Unset platformWindow before deleting, so that the destructor of the
2202 // platform window does not recurse back into the platform window via
2203 // this window during destruction (e.g. as a result of platform events).
2204 delete std::exchange(platformWindow, nullptr);
2205
2206 if (QGuiApplicationPrivate::focus_window == q)
2207 QGuiApplicationPrivate::focus_window = q->parent();
2208 if (QGuiApplicationPrivate::currentMouseWindow == q)
2209 QGuiApplicationPrivate::currentMouseWindow = q->parent();
2210 if (QGuiApplicationPrivate::currentMousePressWindow == q)
2211 QGuiApplicationPrivate::currentMousePressWindow = q->parent();
2212
2213 for (int i = 0; i < QGuiApplicationPrivate::tabletDevicePoints.size(); ++i)
2214 if (QGuiApplicationPrivate::tabletDevicePoints.at(i).target == q)
2215 QGuiApplicationPrivate::tabletDevicePoints[i].target = q->parent();
2216
2217 resizeEventPending = true;
2218 receivedExpose = false;
2219 exposed = false;
2220
2221 // Position set via setFramePosition will have propagated back to
2222 // our geometry member as client geometry, so when creating the
2223 // window again we need to ensure the policy matches that.
2224 positionPolicy = QWindowPrivate::WindowFrameExclusive;
2225}
2226
2227/*!
2228 Returns the platform window corresponding to the window.
2229
2230 \internal
2231*/
2232QPlatformWindow *QWindow::handle() const
2233{
2234 Q_D(const QWindow);
2235 return d->platformWindow;
2236}
2237
2238/*!
2239 Returns the platform surface corresponding to the window.
2240
2241 \internal
2242*/
2243QPlatformSurface *QWindow::surfaceHandle() const
2244{
2245 Q_D(const QWindow);
2246 return d->platformWindow;
2247}
2248
2249/*!
2250 Sets whether keyboard grab should be enabled or not (\a grab).
2251
2252 If the return value is true, the window receives all key events until
2253 setKeyboardGrabEnabled(false) is called; other windows get no key events at
2254 all. Mouse events are not affected. Use setMouseGrabEnabled() if you want
2255 to grab that.
2256
2257 \sa setMouseGrabEnabled()
2258*/
2259bool QWindow::setKeyboardGrabEnabled(bool grab)
2260{
2261 Q_D(QWindow);
2262 if (d->platformWindow)
2263 return d->platformWindow->setKeyboardGrabEnabled(grab);
2264 return false;
2265}
2266
2267/*!
2268 Sets whether mouse grab should be enabled or not (\a grab).
2269
2270 If the return value is true, the window receives all mouse events until setMouseGrabEnabled(false) is
2271 called; other windows get no mouse events at all. Keyboard events are not affected.
2272 Use setKeyboardGrabEnabled() if you want to grab that.
2273
2274 \sa setKeyboardGrabEnabled()
2275*/
2276bool QWindow::setMouseGrabEnabled(bool grab)
2277{
2278 Q_D(QWindow);
2279 if (d->platformWindow)
2280 return d->platformWindow->setMouseGrabEnabled(grab);
2281 return false;
2282}
2283
2284/*!
2285 Returns the screen on which the window is shown, or null if there is none.
2286
2287 For child windows, this returns the screen of the corresponding top level window.
2288
2289 \sa setScreen(), QScreen::virtualSiblings()
2290*/
2291QScreen *QWindow::screen() const
2292{
2293 Q_D(const QWindow);
2294 return d->parentWindow ? d->parentWindow->screen() : d->topLevelScreen.data();
2295}
2296
2297/*!
2298 Sets the screen on which the window should be shown.
2299
2300 If the window has been created, it will be recreated on the \a newScreen.
2301
2302 \note If the screen is part of a virtual desktop of multiple screens,
2303 the window will not move automatically to \a newScreen. To place the
2304 window relative to the screen, use the screen's topLeft() position.
2305
2306 This function only works for top level windows.
2307
2308 \sa screen(), QScreen::virtualSiblings()
2309*/
2310void QWindow::setScreen(QScreen *newScreen)
2311{
2312 Q_D(QWindow);
2313 if (!newScreen)
2314 newScreen = QGuiApplication::primaryScreen();
2315 d->setTopLevelScreen(newScreen, newScreen != nullptr);
2316}
2317
2318/*!
2319 \fn QWindow::screenChanged(QScreen *screen)
2320
2321 This signal is emitted when a window's \a screen changes, either
2322 by being set explicitly with setScreen(), or automatically when
2323 the window's screen is removed.
2324*/
2325
2326/*!
2327 Returns the accessibility interface for the object that the window represents
2328 \internal
2329 \sa QAccessible
2330 */
2331QAccessibleInterface *QWindow::accessibleRoot() const
2332{
2333 return nullptr;
2334}
2335
2336/*!
2337 \fn QWindow::focusObjectChanged(QObject *object)
2338
2339 This signal is emitted when the final receiver of events tied to focus
2340 is changed to \a object.
2341
2342 \sa focusObject()
2343*/
2344
2345/*!
2346 Returns the QObject that will be the final receiver of events tied focus, such
2347 as key events.
2348*/
2349QObject *QWindow::focusObject() const
2350{
2351 return const_cast<QWindow *>(this);
2352}
2353
2354/*!
2355 Shows the window.
2356
2357 For child windows, this is equivalent to calling showNormal().
2358 Otherwise, it is equivalent to calling showFullScreen(), showMaximized(), or showNormal(),
2359 depending on the platform's default behavior for the window type and flags.
2360
2361 \sa showFullScreen(), showMaximized(), showNormal(), hide(), QStyleHints::showIsFullScreen(), flags()
2362*/
2363void QWindow::show()
2364{
2365 if (parent()) {
2366 showNormal();
2367 } else {
2368 const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
2369 Qt::WindowState defaultState = platformIntegration->defaultWindowState(d_func()->windowFlags);
2370 if (defaultState == Qt::WindowFullScreen)
2371 showFullScreen();
2372 else if (defaultState == Qt::WindowMaximized)
2373 showMaximized();
2374 else
2375 showNormal();
2376 }
2377}
2378
2379/*!
2380 Hides the window.
2381
2382 Equivalent to calling setVisible(false).
2383
2384 \sa show(), setVisible()
2385*/
2386void QWindow::hide()
2387{
2388 setVisible(false);
2389}
2390
2391/*!
2392 Shows the window as minimized.
2393
2394 Equivalent to calling setWindowStates(Qt::WindowMinimized) and then
2395 setVisible(true).
2396
2397 \sa setWindowStates(), setVisible()
2398*/
2399void QWindow::showMinimized()
2400{
2401 setWindowStates(Qt::WindowMinimized);
2402 setVisible(true);
2403}
2404
2405/*!
2406 Shows the window as maximized.
2407
2408 Equivalent to calling setWindowStates(Qt::WindowMaximized) and then
2409 setVisible(true).
2410
2411 \sa setWindowStates(), setVisible()
2412*/
2413void QWindow::showMaximized()
2414{
2415 setWindowStates(Qt::WindowMaximized);
2416 setVisible(true);
2417}
2418
2419/*!
2420 Shows the window as fullscreen.
2421
2422 Equivalent to calling setWindowStates(Qt::WindowFullScreen) and then
2423 setVisible(true).
2424
2425 See the \l{QWidget::showFullScreen()} documentation for platform-specific
2426 considerations and limitations.
2427
2428 \sa setWindowStates(), setVisible()
2429*/
2430void QWindow::showFullScreen()
2431{
2432 setWindowStates(Qt::WindowFullScreen);
2433 setVisible(true);
2434#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
2435 // activating it here before libscreen activates it causes problems
2436 requestActivate();
2437#endif
2438}
2439
2440/*!
2441 Shows the window as normal, i.e. neither maximized, minimized, nor fullscreen.
2442
2443 Equivalent to calling setWindowStates(Qt::WindowNoState) and then
2444 setVisible(true).
2445
2446 \sa setWindowStates(), setVisible()
2447*/
2448void QWindow::showNormal()
2449{
2450 setWindowStates(Qt::WindowNoState);
2451 setVisible(true);
2452}
2453
2454/*!
2455 Close the window.
2456
2457 This closes the window, effectively calling destroy(), and potentially
2458 quitting the application. Returns \c true on success, false if it has a parent
2459 window (in which case the top level window should be closed instead).
2460
2461 \sa destroy(), QGuiApplication::quitOnLastWindowClosed(), closeEvent()
2462*/
2463bool QWindow::close()
2464{
2465 Q_D(QWindow);
2466 if (d->inClose)
2467 return true;
2468
2469 // Do not close non top level windows
2470 if (!isTopLevel())
2471 return false;
2472
2473 if (!d->platformWindow) {
2474 // dock widgets can transition back and forth to being popups;
2475 // avoid getting stuck
2476 if (QGuiApplicationPrivate::activePopupWindow() == this)
2477 QGuiApplicationPrivate::closePopup(this);
2478 return true;
2479 }
2480
2481 // The window might be deleted during close,
2482 // as a result of delivering the close event.
2483 QPointer guard(this);
2484 d->inClose = true;
2485 bool success = d->platformWindow->close();
2486 if (guard)
2487 d->inClose = false;
2488
2489 return success;
2490}
2491
2492bool QWindowPrivate::participatesInLastWindowClosed() const
2493{
2494 Q_Q(const QWindow);
2495
2496 if (!q->isTopLevel())
2497 return false;
2498
2499 // Tool-tip widgets do not normally have Qt::WA_QuitOnClose,
2500 // but since we do not have a similar flag for non-widget
2501 // windows we need an explicit exclusion here as well.
2502 if (q->type() == Qt::ToolTip)
2503 return false;
2504
2505 // A window with a transient parent is not a primary window,
2506 // it's a secondary window.
2507 if (q->transientParent())
2508 return false;
2509
2510 return true;
2511}
2512
2513bool QWindowPrivate::treatAsVisible() const
2514{
2515 Q_Q(const QWindow);
2516 return q->isVisible();
2517}
2518
2519/*! \internal
2520 Returns the popup window that has consumed \a event, if any.
2521 \a activePopupOnPress is the window that we have observed previously handling the press.
2522*/
2523const QWindow *QWindowPrivate::forwardToPopup(QEvent *event, const QWindow */*activePopupOnPress*/)
2524{
2525 Q_Q(const QWindow);
2526 qCDebug(lcPopup) << "checking for popup alternative to" << q << "for" << event
2527 << "active popup?" << QGuiApplicationPrivate::activePopupWindow();
2528 QWindow *ret = nullptr;
2529 if (QWindow *popupWindow = QGuiApplicationPrivate::activePopupWindow()) {
2530 if (q == popupWindow)
2531 return nullptr; // avoid infinite recursion: we're already handling it
2532 if (event->isPointerEvent()) {
2533 // detach eventPoints before modifying them
2534 QScopedPointer<QPointerEvent> pointerEvent(static_cast<QPointerEvent *>(event)->clone());
2535 for (int i = 0; i < pointerEvent->pointCount(); ++i) {
2536 QEventPoint &eventPoint = pointerEvent->point(i);
2537 const QPoint globalPos = eventPoint.globalPosition().toPoint();
2538 const QPointF mapped = popupWindow->mapFromGlobal(globalPos);
2539 QMutableEventPoint::setPosition(eventPoint, mapped);
2540 QMutableEventPoint::setScenePosition(eventPoint, mapped);
2541 }
2542
2543 /* Popups are expected to be able to directly handle the
2544 drag-release sequence after pressing to open, as well as
2545 any other mouse events that occur within the popup's bounds. */
2546 if (QCoreApplication::sendSpontaneousEvent(popupWindow, pointerEvent.get())) {
2547 event->setAccepted(pointerEvent->isAccepted());
2548 if (pointerEvent->isAccepted())
2549 ret = popupWindow;
2550 }
2551 qCDebug(lcPopup) << q << "forwarded" << event->type() << "to popup" << popupWindow
2552 << "handled?" << (ret != nullptr)
2553 << "accepted?" << event->isAccepted();
2554 return ret;
2555 } else if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
2556 if (QCoreApplication::sendSpontaneousEvent(popupWindow, event))
2557 ret = popupWindow;
2558 qCDebug(lcPopup) << q << "forwarded" << event->type() << "to popup" << popupWindow
2559 << "handled?" << (ret != nullptr)
2560 << "accepted?" << event->isAccepted();
2561 return ret;
2562 }
2563 }
2564 return ret;
2565}
2566
2567/*!
2568 The expose event (\a ev) is sent by the window system when a window moves
2569 between the un-exposed and exposed states.
2570
2571 An exposed window is potentially visible to the user. If the window is moved
2572 off screen, is made totally obscured by another window, is minimized, or
2573 similar, this function might be called and the value of isExposed() might
2574 change to false. You may use this event to limit expensive operations such
2575 as animations to only run when the window is exposed.
2576
2577 This event should not be used to paint. To handle painting implement
2578 paintEvent() instead.
2579
2580 A resize event will always be sent before the expose event the first time
2581 a window is shown.
2582
2583 \sa paintEvent(), isExposed()
2584*/
2585void QWindow::exposeEvent(QExposeEvent *ev)
2586{
2587 ev->ignore();
2588}
2589
2590/*!
2591 The paint event (\a ev) is sent by the window system whenever an area of
2592 the window needs a repaint, for example when initially showing the window,
2593 or due to parts of the window being uncovered by moving another window.
2594
2595 The application is expected to render into the window in response to the
2596 paint event, regardless of the exposed state of the window. For example,
2597 a paint event may be sent before the window is exposed, to prepare it for
2598 showing to the user.
2599
2600 \since 6.0
2601
2602 \sa exposeEvent()
2603*/
2604void QWindow::paintEvent(QPaintEvent *ev)
2605{
2606 ev->ignore();
2607}
2608
2609/*!
2610 Override this to handle window move events (\a ev).
2611*/
2612void QWindow::moveEvent(QMoveEvent *ev)
2613{
2614 ev->ignore();
2615}
2616
2617/*!
2618 Override this to handle resize events (\a ev).
2619
2620 The resize event is called whenever the window is resized in the windowing system,
2621 either directly through the windowing system acknowledging a setGeometry() or resize() request,
2622 or indirectly through the user resizing the window manually.
2623*/
2624void QWindow::resizeEvent(QResizeEvent *ev)
2625{
2626 ev->ignore();
2627}
2628
2629/*!
2630 Override this to handle show events (\a ev).
2631
2632 The function is called when the window has requested becoming visible.
2633
2634 If the window is successfully shown by the windowing system, this will
2635 be followed by a resize and an expose event.
2636*/
2637void QWindow::showEvent(QShowEvent *ev)
2638{
2639 ev->ignore();
2640}
2641
2642/*!
2643 Override this to handle hide events (\a ev).
2644
2645 The function is called when the window has requested being hidden in the
2646 windowing system.
2647*/
2648void QWindow::hideEvent(QHideEvent *ev)
2649{
2650 ev->ignore();
2651}
2652
2653/*!
2654 Override this to handle close events (\a ev).
2655
2656 The function is called when the window is requested to close. Call \l{QEvent::ignore()}
2657 on the event if you want to prevent the window from being closed.
2658
2659 \sa close()
2660*/
2661void QWindow::closeEvent(QCloseEvent *ev)
2662{
2663 Q_UNUSED(ev);
2664}
2665
2666/*!
2667 Override this to handle any event (\a ev) sent to the window.
2668 Return \c true if the event was recognized and processed.
2669
2670 Remember to call the base class version if you wish for mouse events,
2671 key events, resize events, etc to be dispatched as usual.
2672*/
2673bool QWindow::event(QEvent *ev)
2674{
2675 Q_D(QWindow);
2676 switch (ev->type()) {
2677 case QEvent::MouseMove:
2678 mouseMoveEvent(static_cast<QMouseEvent*>(ev));
2679 break;
2680
2681 case QEvent::MouseButtonPress: {
2682 auto *me = static_cast<QMouseEvent*>(ev);
2683 mousePressEvent(me);
2684 if (!ev->isAccepted())
2685 d->maybeSynthesizeContextMenuEvent(me);
2686 break;
2687 }
2688
2689 case QEvent::MouseButtonRelease: {
2690 auto *me = static_cast<QMouseEvent*>(ev);
2691 mouseReleaseEvent(me);
2692 if (!ev->isAccepted())
2693 d->maybeSynthesizeContextMenuEvent(me);
2694 break;
2695 }
2696
2697 case QEvent::MouseButtonDblClick:
2698 mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
2699 break;
2700
2701 case QEvent::TouchBegin:
2702 case QEvent::TouchUpdate:
2703 case QEvent::TouchEnd:
2704 case QEvent::TouchCancel:
2705 touchEvent(static_cast<QTouchEvent *>(ev));
2706 break;
2707
2708 case QEvent::Move:
2709 moveEvent(static_cast<QMoveEvent*>(ev));
2710 break;
2711
2712 case QEvent::Resize:
2713 resizeEvent(static_cast<QResizeEvent*>(ev));
2714 break;
2715
2716 case QEvent::KeyPress:
2717 keyPressEvent(static_cast<QKeyEvent *>(ev));
2718 break;
2719
2720 case QEvent::KeyRelease:
2721 keyReleaseEvent(static_cast<QKeyEvent *>(ev));
2722 break;
2723
2724 case QEvent::FocusIn: {
2725 focusInEvent(static_cast<QFocusEvent *>(ev));
2726#if QT_CONFIG(accessibility)
2727 QAccessible::State state;
2728 state.active = true;
2729 QAccessibleStateChangeEvent event(this, state);
2730 QAccessible::updateAccessibility(&event);
2731#endif
2732 break; }
2733
2734 case QEvent::FocusOut: {
2735 focusOutEvent(static_cast<QFocusEvent *>(ev));
2736#if QT_CONFIG(accessibility)
2737 QAccessible::State state;
2738 state.active = true;
2739 QAccessibleStateChangeEvent event(this, state);
2740 QAccessible::updateAccessibility(&event);
2741#endif
2742 break; }
2743
2744#if QT_CONFIG(wheelevent)
2745 case QEvent::Wheel:
2746 wheelEvent(static_cast<QWheelEvent*>(ev));
2747 break;
2748#endif
2749
2750 case QEvent::Close: {
2751
2752 const bool wasVisible = d->treatAsVisible();
2753 const bool participatesInLastWindowClosed = d->participatesInLastWindowClosed();
2754
2755 // The window might be deleted in the close event handler
2756 QPointer<QWindow> deletionGuard(this);
2757 closeEvent(static_cast<QCloseEvent*>(ev));
2758
2759 if (ev->isAccepted()) {
2760 if (deletionGuard)
2761 destroy();
2762 if (wasVisible && participatesInLastWindowClosed)
2763 QGuiApplicationPrivate::instance()->maybeLastWindowClosed();
2764 }
2765
2766 break;
2767 }
2768
2769 case QEvent::Expose:
2770 exposeEvent(static_cast<QExposeEvent *>(ev));
2771 break;
2772
2773 case QEvent::Paint:
2774 paintEvent(static_cast<QPaintEvent *>(ev));
2775 break;
2776
2777 case QEvent::Show:
2778 showEvent(static_cast<QShowEvent *>(ev));
2779 break;
2780
2781 case QEvent::Hide:
2782 hideEvent(static_cast<QHideEvent *>(ev));
2783 break;
2784
2785 case QEvent::ApplicationWindowIconChange:
2786 setIcon(icon());
2787 break;
2788
2789#if QT_CONFIG(tabletevent)
2790 case QEvent::TabletPress:
2791 case QEvent::TabletMove:
2792 case QEvent::TabletRelease:
2793 tabletEvent(static_cast<QTabletEvent *>(ev));
2794 break;
2795#endif
2796
2797 case QEvent::PlatformSurface: {
2798 if ((static_cast<QPlatformSurfaceEvent *>(ev))->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) {
2799#ifndef QT_NO_OPENGL
2800 QOpenGLContext *context = QOpenGLContext::currentContext();
2801 if (context && context->surface() == static_cast<QSurface *>(this))
2802 context->doneCurrent();
2803#endif
2804 }
2805 break;
2806 }
2807
2808 default:
2809 return QObject::event(ev);
2810 }
2811
2812 return true;
2813}
2814
2815/*! \internal
2816 Synthesize and send a QContextMenuEvent if the given \a event is a suitable
2817 mouse event (a right-button press or release, depending on
2818 QStyleHints::contextMenuTrigger()). On most platforms, it's done on mouse
2819 press; on Windows, it's done on release, because of the potential to
2820 support right-button clicks and drags to select or lasso items, and then
2821 still getting a context menu at the end of that gesture. (That is in
2822 conflict with supporting the press-drag-release gesture to select menu
2823 items on the context menus themselves. Context menus can be implemented
2824 that way by handling the separate press, move and release events.)
2825
2826 Any time the \a event was already handled in some way, it *should* be
2827 accepted, but mere acceptance of the mouse event cannot be taken to
2828 indicate that it's not necessary to synthesize a QContextMenuEvent here,
2829 because the Windows use case requires doing one thing (selecting items)
2830 with the mouse events, and then doing something completely different with
2831 the QContextMenuEvent. In other words, QContextMenuEvent is very different
2832 from other kinds of optional followup events synthesized from unhandled
2833 events (like the way we synthesize a QMouseEvent only if a QTabletEvent was
2834 not handled). Furthermore, there's enough legacy widget code that doesn't
2835 call ignore() on unhandled mouse events. So it's uncertain whether this can
2836 change in Qt 7.
2837
2838 The QContextMenuEvent occurs at the scenePosition(). The position()
2839 was likely already "localized" during the previous delivery.
2840
2841 The synthesis from a mouse button event could be done in the platform
2842 plugin, but so far on Windows it's not done: WM_CONTEXTMENU is not
2843 generated by the OS, because we never call the default window procedure
2844 that would do that in response to unhandled WM_RBUTTONUP. If we
2845 eventually want to do that, we would have to avoid doing it here,
2846 on platforms where the platform plugin is responsible for it.
2847
2848 QGuiApplicationPrivate::processContextMenuEvent also allows
2849 keyboard-triggered context menu events that the QPA plugin might generate.
2850 On Windows, the keyboard may have a menu key. On macOS, control-return
2851 is the usual shortcut; on Gnome, it's shift-F10; and so on.
2852*/
2853void QWindowPrivate::maybeSynthesizeContextMenuEvent(QMouseEvent *event)
2854{
2855#ifndef QT_NO_CONTEXTMENU
2856 if (event->button() == Qt::RightButton
2857 && event->type() == QGuiApplicationPrivate::contextMenuEventType()) {
2858 QContextMenuEvent e(QContextMenuEvent::Mouse, event->scenePosition().toPoint(),
2859 event->globalPosition().toPoint(), event->modifiers());
2860 qCDebug(lcPopup) << "synthesized after"
2861 << (event->isAccepted() ? "ACCEPTED (legacy behavior)" : "ignored")
2862 << event->type() << ":" << &e;
2863 QCoreApplication::forwardEvent(q_func(), &e, event);
2864 if (e.isAccepted())
2865 event->accept();
2866 }
2867#endif
2868}
2869
2870/*!
2871 Schedules a QEvent::UpdateRequest event to be delivered to this window.
2872
2873 The event is delivered in sync with the display vsync on platforms where
2874 this is possible. Otherwise, the event is delivered after a delay of at
2875 most 5 ms. If the window's associated screen reports a
2876 \l{QScreen::refreshRate()}{refresh rate} higher than 60 Hz, the interval is
2877 scaled down to a value smaller than 5. The additional time is there to give
2878 the event loop a bit of idle time to gather system events, and can be
2879 overridden using the QT_QPA_UPDATE_IDLE_TIME environment variable.
2880
2881 When driving animations, this function should be called once after drawing
2882 has completed. Calling this function multiple times will result in a single
2883 event being delivered to the window.
2884
2885 Subclasses of QWindow should reimplement event(), intercept the event and
2886 call the application's rendering code, then call the base class
2887 implementation.
2888
2889 \note The subclass' reimplementation of event() must invoke the base class
2890 implementation, unless it is absolutely sure that the event does not need to
2891 be handled by the base class. For example, the default implementation of
2892 this function relies on QEvent::Timer events. Filtering them away would
2893 therefore break the delivery of the update events.
2894
2895 \since 5.5
2896*/
2897void QWindow::requestUpdate()
2898{
2899 Q_ASSERT_X(QThread::isMainThread(),
2900 "QWindow", "Updates can only be scheduled from the GUI (main) thread");
2901
2902 Q_D(QWindow);
2903 if (d->updateRequestPending || !d->platformWindow)
2904 return;
2905 d->updateRequestPending = true;
2906 d->platformWindow->requestUpdate();
2907}
2908
2909/*!
2910 Override this to handle key press events (\a ev).
2911
2912 \sa keyReleaseEvent()
2913*/
2914void QWindow::keyPressEvent(QKeyEvent *ev)
2915{
2916 ev->ignore();
2917}
2918
2919/*!
2920 Override this to handle key release events (\a ev).
2921
2922 \sa keyPressEvent()
2923*/
2924void QWindow::keyReleaseEvent(QKeyEvent *ev)
2925{
2926 ev->ignore();
2927}
2928
2929/*!
2930 Override this to handle focus in events (\a ev).
2931
2932 Focus in events are sent when the window receives keyboard focus.
2933
2934 \sa focusOutEvent()
2935*/
2936void QWindow::focusInEvent(QFocusEvent *ev)
2937{
2938 ev->ignore();
2939}
2940
2941/*!
2942 Override this to handle focus out events (\a ev).
2943
2944 Focus out events are sent when the window loses keyboard focus.
2945
2946 \sa focusInEvent()
2947*/
2948void QWindow::focusOutEvent(QFocusEvent *ev)
2949{
2950 ev->ignore();
2951}
2952
2953/*!
2954 Override this to handle mouse press events (\a ev).
2955
2956 \sa mouseReleaseEvent()
2957*/
2958void QWindow::mousePressEvent(QMouseEvent *ev)
2959{
2960 ev->ignore();
2961}
2962
2963/*!
2964 Override this to handle mouse release events (\a ev).
2965
2966 \sa mousePressEvent()
2967*/
2968void QWindow::mouseReleaseEvent(QMouseEvent *ev)
2969{
2970 ev->ignore();
2971}
2972
2973/*!
2974 Override this to handle mouse double click events (\a ev).
2975
2976 \sa mousePressEvent(), QStyleHints::mouseDoubleClickInterval()
2977*/
2978void QWindow::mouseDoubleClickEvent(QMouseEvent *ev)
2979{
2980 ev->ignore();
2981}
2982
2983/*!
2984 Override this to handle mouse move events (\a ev).
2985*/
2986void QWindow::mouseMoveEvent(QMouseEvent *ev)
2987{
2988 ev->ignore();
2989}
2990
2991#if QT_CONFIG(wheelevent)
2992/*!
2993 Override this to handle mouse wheel or other wheel events (\a ev).
2994*/
2995void QWindow::wheelEvent(QWheelEvent *ev)
2996{
2997 ev->ignore();
2998}
2999#endif // QT_CONFIG(wheelevent)
3000
3001/*!
3002 Override this to handle touch events (\a ev).
3003*/
3004void QWindow::touchEvent(QTouchEvent *ev)
3005{
3006 ev->ignore();
3007}
3008
3009#if QT_CONFIG(tabletevent)
3010/*!
3011 Override this to handle tablet press, move, and release events (\a ev).
3012
3013 Proximity enter and leave events are not sent to windows, they are
3014 delivered to the application instance.
3015*/
3016void QWindow::tabletEvent(QTabletEvent *ev)
3017{
3018 ev->ignore();
3019}
3020#endif
3021
3022/*!
3023 Override this to handle platform dependent events.
3024 Will be given \a eventType, \a message and \a result.
3025
3026 This might make your application non-portable.
3027
3028 Should return true only if the event was handled.
3029*/
3030
3031bool QWindow::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
3032{
3033 Q_UNUSED(eventType);
3034 Q_UNUSED(message);
3035 Q_UNUSED(result);
3036 return false;
3037}
3038
3039/*!
3040 \fn QPointF QWindow::mapToGlobal(const QPointF &pos) const
3041
3042 Translates the window coordinate \a pos to global screen
3043 coordinates. For example, \c{mapToGlobal(QPointF(0,0))} would give
3044 the global coordinates of the top-left pixel of the window.
3045
3046 \sa mapFromGlobal()
3047 \since 6.0
3048*/
3049QPointF QWindow::mapToGlobal(const QPointF &pos) const
3050{
3051 Q_D(const QWindow);
3052 // QTBUG-43252, prefer platform implementation for foreign windows.
3053 if (d->platformWindow
3054 && (d->platformWindow->isForeignWindow() || d->platformWindow->isEmbedded())) {
3055 return QHighDpi::fromNativeGlobalPosition(d->platformWindow->mapToGlobalF(QHighDpi::toNativeLocalPosition(pos, this)), this);
3056 }
3057
3058 if (!QHighDpiScaling::isActive())
3059 return pos + d->globalPosition();
3060
3061 // The normal pos + windowGlobalPos calculation may give a point which is outside
3062 // screen geometry for windows which span multiple screens, due to the way QHighDpiScaling
3063 // creates gaps between screens in the the device indendent cooordinate system.
3064 //
3065 // Map the position (and the window's global position) to native coordinates, perform
3066 // the addition, and then map back to device independent coordinates.
3067 QPointF nativeLocalPos = QHighDpi::toNativeLocalPosition(pos, this);
3068 // Get the native window position directly from the platform window
3069 // if available (it can be null if the window hasn't been shown yet),
3070 // or fall back to scaling the QWindow position.
3071 QPointF nativeWindowGlobalPos = d->platformWindow
3072 ? d->platformWindow->mapToGlobal(QPoint(0,0)).toPointF()
3073 : QHighDpi::toNativeGlobalPosition(QPointF(d->globalPosition()), this);
3074 QPointF nativeGlobalPos = nativeLocalPos + nativeWindowGlobalPos;
3075 QPointF deviceIndependentGlobalPos = QHighDpi::fromNativeGlobalPosition(nativeGlobalPos, this);
3076 return deviceIndependentGlobalPos;
3077}
3078
3079/*!
3080 \overload
3081*/
3082QPoint QWindow::mapToGlobal(const QPoint &pos) const
3083{
3084 return mapToGlobal(QPointF(pos)).toPoint();
3085}
3086
3087/*!
3088 \fn QPointF QWindow::mapFromGlobal(const QPointF &pos) const
3089
3090 Translates the global screen coordinate \a pos to window
3091 coordinates.
3092
3093 \sa mapToGlobal()
3094 \since 6.0
3095*/
3096QPointF QWindow::mapFromGlobal(const QPointF &pos) const
3097{
3098 Q_D(const QWindow);
3099 // QTBUG-43252, prefer platform implementation for foreign windows.
3100 if (d->platformWindow
3101 && (d->platformWindow->isForeignWindow() || d->platformWindow->isEmbedded())) {
3102 return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapFromGlobalF(QHighDpi::toNativeGlobalPosition(pos, this)), this);
3103 }
3104
3105 if (!QHighDpiScaling::isActive())
3106 return pos - d->globalPosition();
3107
3108 // Calculate local position in the native coordinate system. (See comment for the
3109 // corresponding mapToGlobal() code above).
3110 QPointF nativeGlobalPos = QHighDpi::toNativeGlobalPosition(pos, this);
3111 // Get the native window position directly from the platform window
3112 // if available (it can be null if the window hasn't been shown yet),
3113 // or fall back to scaling the QWindow position.
3114 QPointF nativeWindowGlobalPos = d->platformWindow
3115 ? d->platformWindow->mapToGlobal(QPoint(0,0)).toPointF()
3116 : QHighDpi::toNativeGlobalPosition(QPointF(d->globalPosition()), this);
3117 QPointF nativeLocalPos = nativeGlobalPos - nativeWindowGlobalPos;
3118 QPointF deviceIndependentLocalPos = QHighDpi::fromNativeLocalPosition(nativeLocalPos, this);
3119 return deviceIndependentLocalPos;
3120}
3121
3122/*!
3123 \overload
3124*/
3125QPoint QWindow::mapFromGlobal(const QPoint &pos) const
3126{
3127 return QWindow::mapFromGlobal(QPointF(pos)).toPoint();
3128}
3129
3130QPoint QWindowPrivate::globalPosition() const
3131{
3132 Q_Q(const QWindow);
3133 QPoint offset = q->position();
3134 for (const QWindow *p = q->parent(); p; p = p->parent()) {
3135 QPlatformWindow *pw = p->handle();
3136 if (pw && (pw->isForeignWindow() || pw->isEmbedded())) {
3137 // Use mapToGlobal() for foreign windows
3138 offset += p->mapToGlobal(QPoint(0, 0));
3139 break;
3140 } else {
3141 offset += p->position();
3142 }
3143 }
3144 return offset;
3145}
3146
3147Q_GUI_EXPORT QWindowPrivate *qt_window_private(QWindow *window)
3148{
3149 return window->d_func();
3150}
3151
3152QWindow *QWindowPrivate::topLevelWindow(QWindow::AncestorMode mode) const
3153{
3154 Q_Q(const QWindow);
3155
3156 QWindow *window = const_cast<QWindow *>(q);
3157
3158 while (window) {
3159 QWindow *parent = window->parent(mode);
3160 if (!parent)
3161 break;
3162
3163 window = parent;
3164 }
3165
3166 return window;
3167}
3168
3169/*!
3170 Creates a local representation of a window created by another process or by
3171 using native libraries below Qt.
3172
3173 Given the handle \a id to a native window, this method creates a QWindow
3174 object which can be used to represent the window when invoking methods like
3175 setParent() and setTransientParent().
3176
3177 This can be used, on platforms which support it, to embed a QWindow inside a
3178 native window, or to embed a native window inside a QWindow.
3179
3180 If foreign windows are not supported or embedding the native window
3181 failed in the platform plugin, this function returns \nullptr.
3182
3183 \note The resulting QWindow should not be used to manipulate the underlying
3184 native window (besides re-parenting), or to observe state changes of the
3185 native window. Any support for these kind of operations is incidental, highly
3186 platform dependent and untested.
3187
3188 \sa setParent()
3189*/
3190QWindow *QWindow::fromWinId(WId id)
3191{
3192 if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ForeignWindows)) {
3193 qWarning("QWindow::fromWinId(): platform plugin does not support foreign windows.");
3194 return nullptr;
3195 }
3196
3197 QWindow *window = new QWindow;
3198
3199 // Persist the winId in a private property so that we
3200 // can recreate the window after being destroyed.
3201 window->setProperty(kForeignWindowId, id);
3202 window->create();
3203
3204 if (!window->handle()) {
3205 delete window;
3206 return nullptr;
3207 }
3208
3209 return window;
3210}
3211
3212/*!
3213 Causes an alert to be shown for \a msec milliseconds. If \a msec is \c 0 (the
3214 default), then the alert is shown indefinitely until the window becomes
3215 active again. This function has no effect on an active window.
3216
3217 In alert state, the window indicates that it demands attention, for example by
3218 flashing or bouncing the taskbar entry.
3219
3220 \since 5.1
3221*/
3222
3223void QWindow::alert(int msec)
3224{
3225 Q_D(QWindow);
3226 if (!d->platformWindow || d->platformWindow->isAlertState() || isActive())
3227 return;
3228 d->platformWindow->setAlertState(true);
3229 if (d->platformWindow->isAlertState() && msec)
3230 QTimer::singleShot(msec, this, SLOT(_q_clearAlert()));
3231}
3232
3233void QWindowPrivate::_q_clearAlert()
3234{
3235 if (platformWindow && platformWindow->isAlertState())
3236 platformWindow->setAlertState(false);
3237}
3238
3239#ifndef QT_NO_CURSOR
3240/*!
3241 \brief set the cursor shape for this window
3242
3243 The mouse \a cursor will assume this shape when it is over this
3244 window, unless an override cursor is set.
3245 See the \l{Qt::CursorShape}{list of predefined cursor objects} for a
3246 range of useful shapes.
3247
3248 If no cursor has been set, or after a call to unsetCursor(), the
3249 parent window's cursor is used.
3250
3251 By default, the cursor has the Qt::ArrowCursor shape.
3252
3253 Some underlying window implementations will reset the cursor if it
3254 leaves a window even if the mouse is grabbed. If you want to have
3255 a cursor set for all windows, even when outside the window, consider
3256 QGuiApplication::setOverrideCursor().
3257
3258 \sa QGuiApplication::setOverrideCursor()
3259*/
3260void QWindow::setCursor(const QCursor &cursor)
3261{
3262 Q_D(QWindow);
3263 d->setCursor(&cursor);
3264}
3265
3266/*!
3267 \brief Restores the default arrow cursor for this window.
3268 */
3269void QWindow::unsetCursor()
3270{
3271 Q_D(QWindow);
3272 d->setCursor(nullptr);
3273}
3274
3275/*!
3276 \brief the cursor shape for this window
3277
3278 \sa setCursor(), unsetCursor()
3279*/
3280QCursor QWindow::cursor() const
3281{
3282 Q_D(const QWindow);
3283 return d->cursor;
3284}
3285
3286void QWindowPrivate::setCursor(const QCursor *newCursor)
3287{
3288
3289 Q_Q(QWindow);
3290 if (newCursor) {
3291 const Qt::CursorShape newShape = newCursor->shape();
3292 if (newShape <= Qt::LastCursor && hasCursor && newShape == cursor.shape())
3293 return; // Unchanged and no bitmap/custom cursor.
3294 cursor = *newCursor;
3295 hasCursor = true;
3296 } else {
3297 if (!hasCursor)
3298 return;
3299 cursor = QCursor(Qt::ArrowCursor);
3300 hasCursor = false;
3301 }
3302 // Only attempt to emit signal if there is an actual platform cursor
3303 if (applyCursor()) {
3304 QEvent event(QEvent::CursorChange);
3305 QGuiApplication::sendEvent(q, &event);
3306 }
3307}
3308
3309// Apply the cursor and returns true iff the platform cursor exists
3310bool QWindowPrivate::applyCursor()
3311{
3312 Q_Q(QWindow);
3313 if (QScreen *screen = q->screen()) {
3314 if (QPlatformCursor *platformCursor = screen->handle()->cursor()) {
3315 if (!platformWindow)
3316 return true;
3317 QCursor *c = QGuiApplication::overrideCursor();
3318 if (c != nullptr && platformCursor->capabilities().testFlag(QPlatformCursor::OverrideCursor))
3319 return true;
3320 if (!c && hasCursor)
3321 c = &cursor;
3322 platformCursor->changeCursor(c, q);
3323 return true;
3324 }
3325 }
3326 return false;
3327}
3328#endif // QT_NO_CURSOR
3329
3330void *QWindow::resolveInterface(const char *name, int revision) const
3331{
3332 using namespace QNativeInterface::Private;
3333
3334 auto *platformWindow = handle();
3335 Q_UNUSED(platformWindow);
3336 Q_UNUSED(name);
3337 Q_UNUSED(revision);
3338
3339#if defined(Q_OS_WIN)
3340 QT_NATIVE_INTERFACE_RETURN_IF(QWindowsWindow, platformWindow);
3341#endif
3342
3343#if QT_CONFIG(xcb)
3344 QT_NATIVE_INTERFACE_RETURN_IF(QXcbWindow, platformWindow);
3345#endif
3346
3347#if defined(Q_OS_MACOS)
3348 QT_NATIVE_INTERFACE_RETURN_IF(QCocoaWindow, platformWindow);
3349#endif
3350
3351#if QT_CONFIG(wayland)
3352 QT_NATIVE_INTERFACE_RETURN_IF(QWaylandWindow, platformWindow);
3353#endif
3354
3355#if defined(Q_OS_WASM)
3356 QT_NATIVE_INTERFACE_RETURN_IF(QWasmWindow, platformWindow);
3357#endif
3358
3359 return nullptr;
3360}
3361
3362#ifndef QT_NO_DEBUG_STREAM
3363QDebug operator<<(QDebug debug, const QWindow *window)
3364{
3365 QDebugStateSaver saver(debug);
3366 debug.nospace();
3367 if (window) {
3368 debug << window->metaObject()->className() << '(' << (const void *)window;
3369 if (!window->objectName().isEmpty())
3370 debug << ", name=" << window->objectName();
3371 if (debug.verbosity() > 2) {
3372 const QRect geometry = window->geometry();
3373 if (window->isVisible())
3374 debug << ", visible";
3375 if (window->isExposed())
3376 debug << ", exposed";
3377 debug << ", state=" << window->windowState()
3378 << ", type=" << window->type() << ", flags=" << window->flags()
3379 << ", surface type=" << window->surfaceType();
3380 if (window->isTopLevel())
3381 debug << ", toplevel";
3382 debug << ", " << geometry.width() << 'x' << geometry.height()
3383 << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
3384 const QMargins margins = window->frameMargins();
3385 if (!margins.isNull())
3386 debug << ", margins=" << margins;
3387 const QMargins safeAreaMargins = window->safeAreaMargins();
3388 if (!safeAreaMargins.isNull())
3389 debug << ", safeAreaMargins=" << safeAreaMargins;
3390 debug << ", devicePixelRatio=" << window->devicePixelRatio();
3391 if (const QPlatformWindow *platformWindow = window->handle())
3392 debug << ", winId=0x" << Qt::hex << platformWindow->winId() << Qt::dec;
3393 if (const QScreen *screen = window->screen())
3394 debug << ", on " << screen->name();
3395 }
3396 debug << ')';
3397 } else {
3398 debug << "QWindow(0x0)";
3399 }
3400 return debug;
3401}
3402#endif // !QT_NO_DEBUG_STREAM
3403
3404#if QT_CONFIG(vulkan) || defined(Q_QDOC)
3405
3406/*!
3407 Associates this window with the specified Vulkan \a instance.
3408
3409 \a instance must stay valid as long as this QWindow instance exists.
3410 */
3411void QWindow::setVulkanInstance(QVulkanInstance *instance)
3412{
3413 Q_D(QWindow);
3414 d->vulkanInstance = instance;
3415}
3416
3417/*!
3418 \return the associated Vulkan instance if any was set, otherwise \nullptr.
3419 */
3420QVulkanInstance *QWindow::vulkanInstance() const
3421{
3422 Q_D(const QWindow);
3423 return d->vulkanInstance;
3424}
3425
3426#endif // QT_CONFIG(vulkan)
3427
3428QT_END_NAMESPACE
3429
3430#include "moc_qwindow.cpp"
Combined button and popup list for selecting options.
static constexpr auto kForeignWindowId
Definition qwindow.cpp:542