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 *newScreen = parent ? parent->screen() : screen();
801 if (d->windowRecreationRequired(newScreen)) {
802 qWarning() << this << '(' << parent << "): Cannot change screens (" << screen() << newScreen << ')';
803 return;
804 }
805
806 QEvent parentAboutToChangeEvent(QEvent::ParentWindowAboutToChange);
807 QCoreApplication::sendEvent(this, &parentAboutToChangeEvent);
808
809 const auto previousParent = d->parentWindow;
810 QObject::setParent(parent);
811 d->parentWindow = parent;
812
813 if (parent)
814 d->disconnectFromScreen();
815 else
816 d->connectToScreen(newScreen);
817
818 // If we were set visible, but not created because we were a child, and we're now
819 // re-parented into a created parent, or to being a top level, we need re-apply the
820 // visibility state, which will also create.
821 if (isVisible() && (!parent || parent->handle()))
822 setVisible(true);
823
824 if (d->platformWindow) {
825 if (parent)
826 parent->create();
827
828 d->platformWindow->setParent(parent ? parent->d_func()->platformWindow : nullptr);
829 }
830
831 QGuiApplicationPrivate::updateBlockedStatus(this);
832
833 if (previousParent) {
834 QChildWindowEvent childRemovedEvent(QEvent::ChildWindowRemoved, this);
835 QCoreApplication::sendEvent(previousParent, &childRemovedEvent);
836 }
837
838 if (parent) {
839 QChildWindowEvent childAddedEvent(QEvent::ChildWindowAdded, this);
840 QCoreApplication::sendEvent(parent, &childAddedEvent);
841 }
842
843 QEvent parentChangedEvent(QEvent::ParentWindowChange);
844 QCoreApplication::sendEvent(this, &parentChangedEvent);
845#if QT_CONFIG(accessibility)
846 if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing) {
847 QAccessibleEvent qaEvent(this, QAccessible::ParentChanged);
848 QAccessible::updateAccessibility(&qaEvent);
849 }
850#endif
851}
852
853/*!
854 Returns whether the window is top level, i.e. has no parent window.
855*/
856bool QWindow::isTopLevel() const
857{
858 Q_D(const QWindow);
859 return d->parentWindow == nullptr;
860}
861
862/*!
863 Returns whether the window is modal.
864
865 A modal window prevents other windows from getting any input.
866
867 \sa QWindow::modality
868*/
869bool QWindow::isModal() const
870{
871 Q_D(const QWindow);
872 return d->modality != Qt::NonModal;
873}
874
875/*! \property QWindow::modality
876 \brief the modality of the window
877
878 A modal window prevents other windows from receiving input events. Qt
879 supports two types of modality: Qt::WindowModal and Qt::ApplicationModal.
880
881 By default, this property is Qt::NonModal
882
883 \sa Qt::WindowModality
884*/
885
886Qt::WindowModality QWindow::modality() const
887{
888 Q_D(const QWindow);
889 return d->modality;
890}
891
892void QWindow::setModality(Qt::WindowModality modality)
893{
894 Q_D(QWindow);
895 if (d->modality == modality)
896 return;
897 d->modality = modality;
898 emit modalityChanged(modality);
899}
900
901/*! \fn void QWindow::modalityChanged(Qt::WindowModality modality)
902
903 This signal is emitted when the Qwindow::modality property changes to \a modality.
904*/
905
906/*!
907 Sets the window's surface \a format.
908
909 The format determines properties such as color depth, alpha, depth and
910 stencil buffer size, etc. For example, to give a window a transparent
911 background (provided that the window system supports compositing, and
912 provided that other content in the window does not make it opaque again):
913
914 \code
915 QSurfaceFormat format;
916 format.setAlphaBufferSize(8);
917 window.setFormat(format);
918 \endcode
919
920 The surface format will be resolved in the create() function. Calling
921 this function after create() has been called will not re-resolve the
922 surface format of the native surface.
923
924 When the format is not explicitly set via this function, the format returned
925 by QSurfaceFormat::defaultFormat() will be used. This means that when having
926 multiple windows, individual calls to this function can be replaced by one
927 single call to QSurfaceFormat::setDefaultFormat() before creating the first
928 window.
929
930 \sa create(), destroy(), QSurfaceFormat::setDefaultFormat()
931*/
932void QWindow::setFormat(const QSurfaceFormat &format)
933{
934 Q_D(QWindow);
935 d->requestedFormat = format;
936}
937
938/*!
939 Returns the requested surface format of this window.
940
941 If the requested format was not supported by the platform implementation,
942 the requestedFormat will differ from the actual window format.
943
944 This is the value set with setFormat().
945
946 \sa setFormat(), format()
947 */
948QSurfaceFormat QWindow::requestedFormat() const
949{
950 Q_D(const QWindow);
951 return d->requestedFormat;
952}
953
954/*!
955 Returns the actual format of this window.
956
957 After the window has been created, this function will return the actual surface format
958 of the window. It might differ from the requested format if the requested format could
959 not be fulfilled by the platform. It might also be a superset, for example certain
960 buffer sizes may be larger than requested.
961
962 \note Depending on the platform, certain values in this surface format may still
963 contain the requested values, that is, the values that have been passed to
964 setFormat(). Typical examples are the OpenGL version, profile and options. These may
965 not get updated during create() since these are context specific and a single window
966 may be used together with multiple contexts over its lifetime. Use the
967 QOpenGLContext's format() instead to query such values.
968
969 \sa create(), requestedFormat(), QOpenGLContext::format()
970*/
971QSurfaceFormat QWindow::format() const
972{
973 Q_D(const QWindow);
974 if (d->platformWindow)
975 return d->platformWindow->format();
976 return d->requestedFormat;
977}
978
979/*!
980 \property QWindow::flags
981 \brief the window flags of the window
982
983 The window flags control the window's appearance in the windowing system,
984 whether it's a dialog, popup, or a regular window, and whether it should
985 have a title bar, etc.
986
987 The actual window flags might differ from the flags set with setFlags()
988 if the requested flags could not be fulfilled.
989
990 \sa setFlag()
991*/
992void QWindow::setFlags(Qt::WindowFlags flags)
993{
994 Q_D(QWindow);
995 if (d->windowFlags == flags)
996 return;
997
998 if (d->platformWindow)
999 d->platformWindow->setWindowFlags(flags);
1000 d->windowFlags = flags;
1001
1002 emit flagsChanged(this->flags());
1003}
1004
1005Qt::WindowFlags QWindow::flags() const
1006{
1007 Q_D(const QWindow);
1008 Qt::WindowFlags flags = d->windowFlags;
1009
1010 if (d->platformWindow && d->platformWindow->isForeignWindow())
1011 flags |= Qt::ForeignWindow;
1012
1013 return flags;
1014}
1015
1016/*!
1017 \since 5.9
1018
1019 Sets the window flag \a flag on this window if \a on is true;
1020 otherwise clears the flag.
1021
1022 \sa setFlags(), flags(), type()
1023*/
1024void QWindow::setFlag(Qt::WindowType flag, bool on)
1025{
1026 Q_D(QWindow);
1027 if (on)
1028 setFlags(d->windowFlags | flag);
1029 else
1030 setFlags(d->windowFlags & ~flag);
1031}
1032
1033/*!
1034 Returns the type of the window.
1035
1036 This returns the part of the window flags that represents
1037 whether the window is a dialog, tooltip, popup, regular window, etc.
1038
1039 \sa flags(), setFlags()
1040*/
1041Qt::WindowType QWindow::type() const
1042{
1043 return static_cast<Qt::WindowType>(int(flags() & Qt::WindowType_Mask));
1044}
1045
1046/*!
1047 \property QWindow::title
1048 \brief the window's title in the windowing system
1049
1050 The window title might appear in the title area of the window decorations,
1051 depending on the windowing system and the window flags. It might also
1052 be used by the windowing system to identify the window in other contexts,
1053 such as in the task switcher.
1054
1055 \sa flags()
1056*/
1057void QWindow::setTitle(const QString &title)
1058{
1059 Q_D(QWindow);
1060 bool changed = false;
1061 if (d->windowTitle != title) {
1062 d->windowTitle = title;
1063 changed = true;
1064 }
1065 if (d->platformWindow)
1066 d->platformWindow->setWindowTitle(title);
1067 if (changed)
1068 emit windowTitleChanged(title);
1069}
1070
1071QString QWindow::title() const
1072{
1073 Q_D(const QWindow);
1074 return d->windowTitle;
1075}
1076
1077/*!
1078 \brief set the file name this window is representing.
1079
1080 The windowing system might use \a filePath to display the
1081 path of the document this window is representing in the tile bar.
1082
1083*/
1084void QWindow::setFilePath(const QString &filePath)
1085{
1086 Q_D(QWindow);
1087 d->windowFilePath = filePath;
1088 if (d->platformWindow)
1089 d->platformWindow->setWindowFilePath(filePath);
1090}
1091
1092/*!
1093 \brief the file name this window is representing.
1094
1095 \sa setFilePath()
1096*/
1097QString QWindow::filePath() const
1098{
1099 Q_D(const QWindow);
1100 return d->windowFilePath;
1101}
1102
1103/*!
1104 \brief Sets the window's \a icon in the windowing system
1105
1106 The window icon might be used by the windowing system for example to
1107 decorate the window, and/or in the task switcher.
1108
1109 \note On \macos, the window title bar icon is meant for windows representing
1110 documents, and will only show up if a file path is also set.
1111
1112 \sa setFilePath()
1113*/
1114void QWindow::setIcon(const QIcon &icon)
1115{
1116 Q_D(QWindow);
1117 d->windowIcon = icon;
1118 if (d->platformWindow)
1119 d->platformWindow->setWindowIcon(icon);
1120 QEvent e(QEvent::WindowIconChange);
1121 QCoreApplication::sendEvent(this, &e);
1122}
1123
1124/*!
1125 \brief Returns the window's icon in the windowing system
1126
1127 \sa setIcon()
1128*/
1129QIcon QWindow::icon() const
1130{
1131 Q_D(const QWindow);
1132 if (d->windowIcon.isNull())
1133 return QGuiApplication::windowIcon();
1134 return d->windowIcon;
1135}
1136
1137/*!
1138 Raise the window in the windowing system.
1139
1140 Requests that the window be raised to appear above other windows.
1141*/
1142void QWindow::raise()
1143{
1144 Q_D(QWindow);
1145
1146 d->updateSiblingPosition(QWindowPrivate::PositionTop);
1147
1148 if (d->platformWindow)
1149 d->platformWindow->raise();
1150}
1151
1152/*!
1153 Lower the window in the windowing system.
1154
1155 Requests that the window be lowered to appear below other windows.
1156*/
1157void QWindow::lower()
1158{
1159 Q_D(QWindow);
1160
1161 d->updateSiblingPosition(QWindowPrivate::PositionBottom);
1162
1163 if (d->platformWindow)
1164 d->platformWindow->lower();
1165}
1166
1167/*!
1168 \brief Start a system-specific resize operation
1169 \since 5.15
1170
1171 Calling this will start an interactive resize operation on the window by platforms
1172 that support it. The actual behavior may vary depending on the platform. Usually,
1173 it will make the window resize so that its edge follows the mouse cursor.
1174
1175 On platforms that support it, this method of resizing windows is preferred over
1176 \c setGeometry, because it allows a more native look and feel of resizing windows, e.g.
1177 letting the window manager snap this window against other windows, or special resizing
1178 behavior with animations when dragged to the edge of the screen.
1179
1180 \a edges should either be a single edge, or two adjacent edges (a corner). Other values
1181 are not allowed.
1182
1183 Returns true if the operation was supported by the system.
1184*/
1185bool QWindow::startSystemResize(Qt::Edges edges)
1186{
1187 Q_D(QWindow);
1188 if (Q_UNLIKELY(!isVisible() || !d->platformWindow || d->maximumSize == d->minimumSize))
1189 return false;
1190
1191 const bool isSingleEdge = edges == Qt::TopEdge || edges == Qt::RightEdge || edges == Qt::BottomEdge || edges == Qt::LeftEdge;
1192 const bool isCorner =
1193 edges == (Qt::TopEdge | Qt::LeftEdge) ||
1194 edges == (Qt::TopEdge | Qt::RightEdge) ||
1195 edges == (Qt::BottomEdge | Qt::RightEdge) ||
1196 edges == (Qt::BottomEdge | Qt::LeftEdge);
1197
1198 if (Q_UNLIKELY(!isSingleEdge && !isCorner)) {
1199 qWarning() << "Invalid edges" << edges << "passed to QWindow::startSystemResize, ignoring.";
1200 return false;
1201 }
1202
1203 return d->platformWindow->startSystemResize(edges);
1204}
1205
1206/*!
1207 \brief Start a system-specific move operation
1208 \since 5.15
1209
1210 Calling this will start an interactive move operation on the window by platforms
1211 that support it. The actual behavior may vary depending on the platform. Usually,
1212 it will make the window follow the mouse cursor until a mouse button is released.
1213
1214 On platforms that support it, this method of moving windows is preferred over
1215 \c setPosition, because it allows a more native look-and-feel of moving windows, e.g.
1216 letting the window manager snap this window against other windows, or special tiling
1217 or resizing behavior with animations when dragged to the edge of the screen.
1218 Furthermore, on some platforms such as Wayland, \c setPosition is not supported, so
1219 this is the only way the application can influence its position.
1220
1221 Returns true if the operation was supported by the system.
1222*/
1223bool QWindow::startSystemMove()
1224{
1225 Q_D(QWindow);
1226 if (Q_UNLIKELY(!isVisible() || !d->platformWindow))
1227 return false;
1228
1229 return d->platformWindow->startSystemMove();
1230}
1231
1232/*!
1233 \property QWindow::opacity
1234 \brief The opacity of the window in the windowing system.
1235 \since 5.1
1236
1237 If the windowing system supports window opacity, this can be used to fade the
1238 window in and out, or to make it semitransparent.
1239
1240 A value of 1.0 or above is treated as fully opaque, whereas a value of 0.0 or below
1241 is treated as fully transparent. Values inbetween represent varying levels of
1242 translucency between the two extremes.
1243
1244 The default value is 1.0.
1245*/
1246void QWindow::setOpacity(qreal level)
1247{
1248 Q_D(QWindow);
1249 if (level == d->opacity)
1250 return;
1251 d->opacity = level;
1252 if (d->platformWindow) {
1253 d->platformWindow->setOpacity(level);
1254 emit opacityChanged(level);
1255 }
1256}
1257
1258qreal QWindow::opacity() const
1259{
1260 Q_D(const QWindow);
1261 return d->opacity;
1262}
1263
1264/*!
1265 Sets the mask of the window.
1266
1267 The mask is a hint to the windowing system that the application does not
1268 want to receive mouse or touch input outside the given \a region.
1269
1270 The window manager may or may not choose to display any areas of the window
1271 not included in the mask, thus it is the application's responsibility to
1272 clear to transparent the areas that are not part of the mask.
1273*/
1274void QWindow::setMask(const QRegion &region)
1275{
1276 Q_D(QWindow);
1277 if (d->platformWindow)
1278 d->platformWindow->setMask(QHighDpi::toNativeLocalRegion(region, this));
1279 d->mask = region;
1280}
1281
1282/*!
1283 Returns the mask set on the window.
1284
1285 The mask is a hint to the windowing system that the application does not
1286 want to receive mouse or touch input outside the given region.
1287*/
1288QRegion QWindow::mask() const
1289{
1290 Q_D(const QWindow);
1291 return d->mask;
1292}
1293
1294/*!
1295 Requests the window to be activated, i.e. receive keyboard focus.
1296
1297 \sa isActive(), QGuiApplication::focusWindow()
1298*/
1299void QWindow::requestActivate()
1300{
1301 Q_D(QWindow);
1302 if (flags() & Qt::WindowDoesNotAcceptFocus) {
1303 qWarning() << "requestActivate() called for " << this << " which has Qt::WindowDoesNotAcceptFocus set.";
1304 return;
1305 }
1306 if (d->platformWindow)
1307 d->platformWindow->requestActivateWindow();
1308}
1309
1310/*!
1311 Returns if this window is exposed in the windowing system.
1312
1313 When the window is not exposed, it is shown by the application
1314 but it is still not showing in the windowing system, so the application
1315 should minimize animations and other graphical activities.
1316
1317 An exposeEvent() is sent every time this value changes.
1318
1319 \sa exposeEvent()
1320*/
1321bool QWindow::isExposed() const
1322{
1323 Q_D(const QWindow);
1324 return d->exposed;
1325}
1326
1327/*!
1328 \property QWindow::active
1329 \brief the active status of the window
1330 \since 5.1
1331
1332 \sa requestActivate()
1333*/
1334
1335/*!
1336 Returns \c true if the window is active.
1337
1338 This is the case for the window that has input focus as well as windows
1339 that are in the same parent / transient parent chain as the focus window.
1340
1341 Typically active windows should appear active from a style perspective.
1342
1343 To get the window that currently has focus, use QGuiApplication::focusWindow().
1344
1345 \sa requestActivate()
1346*/
1347bool QWindow::isActive() const
1348{
1349 Q_D(const QWindow);
1350 if (!d->platformWindow)
1351 return false;
1352
1353 QWindow *focus = QGuiApplication::focusWindow();
1354
1355 // Means the whole application lost the focus
1356 if (!focus)
1357 return false;
1358
1359 if (focus == this)
1360 return true;
1361
1362 if (QWindow *p = parent(IncludeTransients))
1363 return p->isActive();
1364 else
1365 return isAncestorOf(focus);
1366}
1367
1368/*!
1369 \property QWindow::contentOrientation
1370 \brief the orientation of the window's contents
1371
1372 This is a hint to the window manager in case it needs to display
1373 additional content like popups, dialogs, status bars, or similar
1374 in relation to the window.
1375
1376 The recommended orientation is QScreen::orientation() but
1377 an application doesn't have to support all possible orientations,
1378 and thus can opt to ignore the current screen orientation.
1379
1380 The difference between the window and the content orientation
1381 determines how much to rotate the content by. QScreen::angleBetween(),
1382 QScreen::transformBetween(), and QScreen::mapBetween() can be used
1383 to compute the necessary transform.
1384
1385 The default value is Qt::PrimaryOrientation
1386*/
1387void QWindow::reportContentOrientationChange(Qt::ScreenOrientation orientation)
1388{
1389 Q_D(QWindow);
1390 if (d->contentOrientation == orientation)
1391 return;
1392 if (d->platformWindow)
1393 d->platformWindow->handleContentOrientationChange(orientation);
1394 d->contentOrientation = orientation;
1395 emit contentOrientationChanged(orientation);
1396}
1397
1398Qt::ScreenOrientation QWindow::contentOrientation() const
1399{
1400 Q_D(const QWindow);
1401 return d->contentOrientation;
1402}
1403
1404/*!
1405 Returns the ratio between physical pixels and device-independent pixels
1406 for the window. This value is dependent on the screen the window is on,
1407 and may change when the window is moved.
1408
1409 The QWindow instance receives an event of type
1410 QEvent::DevicePixelRatioChange when the device pixel ratio changes.
1411
1412 Common values are 1.0 on normal displays and 2.0 on Apple "retina" displays.
1413
1414 \note For windows not backed by a platform window, meaning that create() was not
1415 called, the function will fall back to the associated QScreen's device pixel ratio.
1416
1417 \sa QScreen::devicePixelRatio(), QEvent::DevicePixelRatioChange
1418*/
1419qreal QWindow::devicePixelRatio() const
1420{
1421 Q_D(const QWindow);
1422 return d->devicePixelRatio;
1423}
1424
1425/*
1426 Updates the cached devicePixelRatio value by polling for a new value.
1427 Sends QEvent::DevicePixelRatioChange to the window if the DPR has changed.
1428 Returns true if the DPR was changed.
1429*/
1430bool QWindowPrivate::updateDevicePixelRatio()
1431{
1432 Q_Q(QWindow);
1433
1434 const qreal newDevicePixelRatio = [this, q]{
1435 if (platformWindow)
1436 return platformWindow->devicePixelRatio() * QHighDpiScaling::factor(q);
1437
1438 // If there is no platform window use the associated screen's devicePixelRatio,
1439 // which typically is the primary screen and will be correct for single-display
1440 // systems (a very common case).
1441 if (auto *screen = q->screen())
1442 return screen->devicePixelRatio();
1443
1444 // In some cases we are running without any QScreens, so fall back to QGuiApp
1445 return qGuiApp->devicePixelRatio();
1446 }();
1447
1448 if (newDevicePixelRatio == devicePixelRatio)
1449 return false;
1450
1451 devicePixelRatio = newDevicePixelRatio;
1452 QEvent dprChangeEvent(QEvent::DevicePixelRatioChange);
1453 QGuiApplication::sendEvent(q, &dprChangeEvent);
1454 return true;
1455}
1456
1457Qt::WindowState QWindowPrivate::effectiveState(Qt::WindowStates state)
1458{
1459 if (state & Qt::WindowMinimized)
1460 return Qt::WindowMinimized;
1461 else if (state & Qt::WindowFullScreen)
1462 return Qt::WindowFullScreen;
1463 else if (state & Qt::WindowMaximized)
1464 return Qt::WindowMaximized;
1465 return Qt::WindowNoState;
1466}
1467
1468/*!
1469 \brief set the screen-occupation state of the window
1470
1471 The window \a state represents whether the window appears in the
1472 windowing system as maximized, minimized, fullscreen, or normal.
1473
1474 The enum value Qt::WindowActive is not an accepted parameter.
1475
1476 \sa showNormal(), showFullScreen(), showMinimized(), showMaximized(), setWindowStates()
1477*/
1478void QWindow::setWindowState(Qt::WindowState state)
1479{
1480 setWindowStates(state);
1481}
1482
1483/*!
1484 \brief set the screen-occupation state of the window
1485 \since 5.10
1486
1487 The window \a state represents whether the window appears in the
1488 windowing system as maximized, minimized and/or fullscreen.
1489
1490 The window can be in a combination of several states. For example, if
1491 the window is both minimized and maximized, the window will appear
1492 minimized, but clicking on the task bar entry will restore it to the
1493 maximized state.
1494
1495 The enum value Qt::WindowActive should not be set.
1496
1497 \sa showNormal(), showFullScreen(), showMinimized(), showMaximized()
1498 */
1499void QWindow::setWindowStates(Qt::WindowStates state)
1500{
1501 Q_D(QWindow);
1502 if (state & Qt::WindowActive) {
1503 qWarning("QWindow::setWindowStates does not accept Qt::WindowActive");
1504 state &= ~Qt::WindowActive;
1505 }
1506
1507 if (d->platformWindow)
1508 d->platformWindow->setWindowState(state);
1509
1510 auto originalEffectiveState = QWindowPrivate::effectiveState(d->windowState);
1511 d->windowState = state;
1512 auto newEffectiveState = QWindowPrivate::effectiveState(d->windowState);
1513 if (newEffectiveState != originalEffectiveState)
1514 emit windowStateChanged(newEffectiveState);
1515
1516 d->updateVisibility();
1517}
1518
1519/*!
1520 \brief the screen-occupation state of the window
1521
1522 \sa setWindowState(), windowStates()
1523*/
1524Qt::WindowState QWindow::windowState() const
1525{
1526 Q_D(const QWindow);
1527 return QWindowPrivate::effectiveState(d->windowState);
1528}
1529
1530/*!
1531 \brief the screen-occupation state of the window
1532 \since 5.10
1533
1534 The window can be in a combination of several states. For example, if
1535 the window is both minimized and maximized, the window will appear
1536 minimized, but clicking on the task bar entry will restore it to
1537 the maximized state.
1538
1539 \sa setWindowStates()
1540*/
1541Qt::WindowStates QWindow::windowStates() const
1542{
1543 Q_D(const QWindow);
1544 return d->windowState;
1545}
1546
1547/*!
1548 \fn QWindow::windowStateChanged(Qt::WindowState windowState)
1549
1550 This signal is emitted when the \a windowState changes, either
1551 by being set explicitly with setWindowStates(), or automatically when
1552 the user clicks one of the titlebar buttons or by other means.
1553*/
1554
1555/*!
1556 \property QWindow::transientParent
1557 \brief the window for which this window is a transient pop-up
1558 \since 5.13
1559
1560 This is a hint to the window manager that this window is a dialog or pop-up
1561 on behalf of the transient parent.
1562
1563 In order to cause the window to be centered above its transient \a parent by
1564 default, depending on the window manager, it may also be necessary to call
1565 setFlags() with a suitable \l Qt::WindowType (such as \c Qt::Dialog).
1566
1567 \sa parent()
1568*/
1569void QWindow::setTransientParent(QWindow *parent)
1570{
1571 Q_D(QWindow);
1572 if (parent && !parent->isTopLevel()) {
1573 qWarning() << parent << "must be a top level window.";
1574 return;
1575 }
1576 if (parent == this) {
1577 qWarning() << "transient parent" << parent << "cannot be same as window";
1578 return;
1579 }
1580
1581 d->transientParent = parent;
1582
1583 QGuiApplicationPrivate::updateBlockedStatus(this);
1584 emit transientParentChanged(parent);
1585}
1586
1587QWindow *QWindow::transientParent() const
1588{
1589 Q_D(const QWindow);
1590 return d->transientParent.data();
1591}
1592
1593/*
1594 The setter for the QWindow::transientParent property.
1595 The only reason this exists is to set the transientParentPropertySet flag
1596 so that Qt Quick knows whether it was set programmatically (because of
1597 Window declaration context) or because the user set the property.
1598*/
1599void QWindowPrivate::setTransientParent(QWindow *parent)
1600{
1601 Q_Q(QWindow);
1602 q->setTransientParent(parent);
1603 transientParentPropertySet = true;
1604}
1605
1606/*!
1607 \enum QWindow::AncestorMode
1608
1609 This enum is used to control whether or not transient parents
1610 should be considered ancestors.
1611
1612 \value ExcludeTransients Transient parents are not considered ancestors.
1613 \value IncludeTransients Transient parents are considered ancestors.
1614*/
1615
1616/*!
1617 Returns \c true if the window is an ancestor of the given \a child. If \a mode
1618 is IncludeTransients, then transient parents are also considered ancestors.
1619*/
1620bool QWindow::isAncestorOf(const QWindow *child, AncestorMode mode) const
1621{
1622 if (child->parent() == this || (mode == IncludeTransients && child->transientParent() == this))
1623 return true;
1624
1625 if (QWindow *parent = child->parent(mode)) {
1626 if (isAncestorOf(parent, mode))
1627 return true;
1628 } else if (handle() && child->handle()) {
1629 if (handle()->isAncestorOf(child->handle()))
1630 return true;
1631 }
1632
1633 return false;
1634}
1635
1636/*!
1637 Returns the minimum size of the window.
1638
1639 \sa setMinimumSize()
1640*/
1641QSize QWindow::minimumSize() const
1642{
1643 Q_D(const QWindow);
1644 return d->minimumSize;
1645}
1646
1647/*!
1648 Returns the maximum size of the window.
1649
1650 \sa setMaximumSize()
1651*/
1652QSize QWindow::maximumSize() const
1653{
1654 Q_D(const QWindow);
1655 return d->maximumSize;
1656}
1657
1658/*!
1659 Returns the base size of the window.
1660
1661 \sa setBaseSize()
1662*/
1663QSize QWindow::baseSize() const
1664{
1665 Q_D(const QWindow);
1666 return d->baseSize;
1667}
1668
1669/*!
1670 Returns the size increment of the window.
1671
1672 \sa setSizeIncrement()
1673*/
1674QSize QWindow::sizeIncrement() const
1675{
1676 Q_D(const QWindow);
1677 return d->sizeIncrement;
1678}
1679
1680/*!
1681 Sets the minimum size of the window.
1682
1683 This is a hint to the window manager to prevent resizing below the specified \a size.
1684
1685 \sa setMaximumSize(), minimumSize()
1686*/
1687void QWindow::setMinimumSize(const QSize &size)
1688{
1689 Q_D(QWindow);
1690 d->setMinOrMaxSize(
1691 &d->minimumSize, size, [this, d]() { emit minimumWidthChanged(d->minimumSize.width()); },
1692 [this, d]() { emit minimumHeightChanged(d->minimumSize.height()); });
1693}
1694
1695/*!
1696 \property QWindow::x
1697 \brief the x position of the window's geometry
1698*/
1699void QWindow::setX(int arg)
1700{
1701 Q_D(QWindow);
1702 if (x() != arg)
1703 setGeometry(QRect(arg, y(), width(), height()));
1704 else
1705 d->positionAutomatic = false;
1706}
1707
1708/*!
1709 \property QWindow::y
1710 \brief the y position of the window's geometry
1711*/
1712void QWindow::setY(int arg)
1713{
1714 Q_D(QWindow);
1715 if (y() != arg)
1716 setGeometry(QRect(x(), arg, width(), height()));
1717 else
1718 d->positionAutomatic = false;
1719}
1720
1721/*!
1722 \property QWindow::width
1723 \brief the width of the window's geometry
1724*/
1725void QWindow::setWidth(int w)
1726{
1727 resize(w, height());
1728}
1729
1730/*!
1731 \property QWindow::height
1732 \brief the height of the window's geometry
1733*/
1734void QWindow::setHeight(int h)
1735{
1736 resize(width(), h);
1737}
1738
1739/*!
1740 \property QWindow::minimumWidth
1741 \brief the minimum width of the window's geometry
1742*/
1743void QWindow::setMinimumWidth(int w)
1744{
1745 setMinimumSize(QSize(w, minimumHeight()));
1746}
1747
1748/*!
1749 \property QWindow::minimumHeight
1750 \brief the minimum height of the window's geometry
1751*/
1752void QWindow::setMinimumHeight(int h)
1753{
1754 setMinimumSize(QSize(minimumWidth(), h));
1755}
1756
1757/*!
1758 Sets the maximum size of the window.
1759
1760 This is a hint to the window manager to prevent resizing above the specified \a size.
1761
1762 \sa setMinimumSize(), maximumSize()
1763*/
1764void QWindow::setMaximumSize(const QSize &size)
1765{
1766 Q_D(QWindow);
1767 d->setMinOrMaxSize(
1768 &d->maximumSize, size, [this, d]() { emit maximumWidthChanged(d->maximumSize.width()); },
1769 [this, d]() { emit maximumHeightChanged(d->maximumSize.height()); });
1770}
1771
1772/*!
1773 \property QWindow::maximumWidth
1774 \brief the maximum width of the window's geometry
1775*/
1776void QWindow::setMaximumWidth(int w)
1777{
1778 setMaximumSize(QSize(w, maximumHeight()));
1779}
1780
1781/*!
1782 \property QWindow::maximumHeight
1783 \brief the maximum height of the window's geometry
1784*/
1785void QWindow::setMaximumHeight(int h)
1786{
1787 setMaximumSize(QSize(maximumWidth(), h));
1788}
1789
1790/*!
1791 Sets the base \a size of the window.
1792
1793 The base size is used to calculate a proper window size if the
1794 window defines sizeIncrement().
1795
1796 \sa setMinimumSize(), setMaximumSize(), setSizeIncrement(), baseSize()
1797*/
1798void QWindow::setBaseSize(const QSize &size)
1799{
1800 Q_D(QWindow);
1801 if (d->baseSize == size)
1802 return;
1803 d->baseSize = size;
1804 if (d->platformWindow && isTopLevel())
1805 d->platformWindow->propagateSizeHints();
1806}
1807
1808/*!
1809 Sets the size increment (\a size) of the window.
1810
1811 When the user resizes the window, the size will move in steps of
1812 sizeIncrement().width() pixels horizontally and
1813 sizeIncrement().height() pixels vertically, with baseSize() as the
1814 basis.
1815
1816 By default, this property contains a size with zero width and height.
1817
1818 The windowing system might not support size increments.
1819
1820 \sa setBaseSize(), setMinimumSize(), setMaximumSize()
1821*/
1822void QWindow::setSizeIncrement(const QSize &size)
1823{
1824 Q_D(QWindow);
1825 if (d->sizeIncrement == size)
1826 return;
1827 d->sizeIncrement = size;
1828 if (d->platformWindow && isTopLevel())
1829 d->platformWindow->propagateSizeHints();
1830}
1831
1832/*!
1833 Sets the geometry of the window, excluding its window frame, to a
1834 rectangle constructed from \a posx, \a posy, \a w and \a h.
1835
1836 The geometry is in relation to the virtualGeometry() of its screen.
1837
1838 \sa geometry()
1839*/
1840void QWindow::setGeometry(int posx, int posy, int w, int h)
1841{
1842 setGeometry(QRect(posx, posy, w, h));
1843}
1844
1845/*!
1846 \brief Sets the geometry of the window, excluding its window frame, to \a rect.
1847
1848 The geometry is in relation to the virtualGeometry() of its screen.
1849
1850 \sa geometry()
1851*/
1852void QWindow::setGeometry(const QRect &rect)
1853{
1854 Q_D(QWindow);
1855 d->positionAutomatic = false;
1856 const QRect oldRect = geometry();
1857 if (rect == oldRect)
1858 return;
1859
1860 d->positionPolicy = QWindowPrivate::WindowFrameExclusive;
1861 if (d->platformWindow) {
1862 // Setting a new geometry may move the window to a new screen.
1863 // The QHighDpi layer needs to know the new screen to be able
1864 // to resolve the resulting geometry based on the screen's DPR,
1865 // so we update the screen before passing the geometry on to
1866 // the platform layer. FIXME: Find a way to tell QHighDpi about
1867 // the new screen without actually changing the screen, so that
1868 // the geometry change is the trigger for the screen change.
1869 QScreen *newScreen = d->screenForGeometry(rect);
1870 if (newScreen && isTopLevel())
1871 d->setTopLevelScreen(newScreen, true);
1872 d->platformWindow->setGeometry(QHighDpi::toNativeWindowGeometry(rect, this));
1873 } else {
1874 d->geometry = rect;
1875
1876 if (rect.x() != oldRect.x())
1877 emit xChanged(rect.x());
1878 if (rect.y() != oldRect.y())
1879 emit yChanged(rect.y());
1880 if (rect.width() != oldRect.width())
1881 emit widthChanged(rect.width());
1882 if (rect.height() != oldRect.height())
1883 emit heightChanged(rect.height());
1884 }
1885}
1886
1887/*
1888 This is equivalent to QPlatformWindow::screenForGeometry, but in platform
1889 independent coordinates. The duplication is unfortunate, but there is a
1890 chicken and egg problem here: we cannot convert to native coordinates
1891 before we know which screen we are on.
1892*/
1893QScreen *QWindowPrivate::screenForGeometry(const QRect &newGeometry) const
1894{
1895 Q_Q(const QWindow);
1896 QScreen *currentScreen = q->screen();
1897 QScreen *fallback = currentScreen;
1898 QPoint center = newGeometry.center();
1899 if (!q->parent() && currentScreen && !currentScreen->geometry().contains(center)) {
1900 const auto screens = currentScreen->virtualSiblings();
1901 for (QScreen* screen : screens) {
1902 if (screen->geometry().contains(center))
1903 return screen;
1904 if (screen->geometry().intersects(newGeometry))
1905 fallback = screen;
1906 }
1907 }
1908 return fallback;
1909}
1910
1911
1912/*!
1913 Returns the geometry of the window, excluding its window frame.
1914
1915 The geometry is in relation to the virtualGeometry() of its screen.
1916
1917 \sa frameMargins(), frameGeometry()
1918*/
1919QRect QWindow::geometry() const
1920{
1921 Q_D(const QWindow);
1922 if (d->platformWindow) {
1923 const auto nativeGeometry = d->platformWindow->geometry();
1924 return QHighDpi::fromNativeWindowGeometry(nativeGeometry, this);
1925 }
1926 return d->geometry;
1927}
1928
1929/*!
1930 Returns the window frame margins surrounding the window.
1931
1932 \sa geometry(), frameGeometry()
1933*/
1934QMargins QWindow::frameMargins() const
1935{
1936 Q_D(const QWindow);
1937 if (d->platformWindow)
1938 return QHighDpi::fromNativePixels(d->platformWindow->frameMargins(), this);
1939 return QMargins();
1940}
1941
1942/*!
1943 Returns the geometry of the window, including its window frame.
1944
1945 The geometry is in relation to the virtualGeometry() of its screen.
1946
1947 \sa geometry(), frameMargins()
1948*/
1949QRect QWindow::frameGeometry() const
1950{
1951 Q_D(const QWindow);
1952 if (d->platformWindow) {
1953 QMargins m = frameMargins();
1954 return QHighDpi::fromNativeWindowGeometry(d->platformWindow->geometry(), this).adjusted(-m.left(), -m.top(), m.right(), m.bottom());
1955 }
1956 return d->geometry;
1957}
1958
1959/*!
1960 Returns the top left position of the window, including its window frame.
1961
1962 This returns the same value as frameGeometry().topLeft().
1963
1964 \sa geometry(), frameGeometry()
1965*/
1966QPoint QWindow::framePosition() const
1967{
1968 Q_D(const QWindow);
1969 if (d->platformWindow) {
1970 QMargins margins = frameMargins();
1971 return QHighDpi::fromNativeWindowGeometry(d->platformWindow->geometry().topLeft(), this) - QPoint(margins.left(), margins.top());
1972 }
1973 return d->geometry.topLeft();
1974}
1975
1976/*!
1977 Sets the upper left position of the window (\a point) including its window frame.
1978
1979 The position is in relation to the virtualGeometry() of its screen.
1980
1981 \sa setGeometry(), frameGeometry()
1982*/
1983void QWindow::setFramePosition(const QPoint &point)
1984{
1985 Q_D(QWindow);
1986 d->positionPolicy = QWindowPrivate::WindowFrameInclusive;
1987 d->positionAutomatic = false;
1988 if (d->platformWindow) {
1989 d->platformWindow->setGeometry(QHighDpi::toNativeWindowGeometry(QRect(point, size()), this));
1990 } else {
1991 d->geometry.moveTopLeft(point);
1992 }
1993}
1994
1995/*!
1996 \fn void QWindow::setFramePosition(int x, int y)
1997 \brief Sets the upper left position of the window, including its window frame, to \a x, \a y
1998
1999 The position is in relation to the virtualGeometry() of its screen.
2000
2001 \since 6.12
2002 \sa setGeometry(), frameGeometry()
2003*/
2004
2005/*!
2006 Returns the safe area margins of the window.
2007
2008 The safe area represents the part of the window where content
2009 can be safely placed without risk of being obscured by, or
2010 conflicting with, other UI elements, such as system UIs.
2011
2012 The margins are relative to the internal geometry of the
2013 window, i.e QRect(0, 0, width(), height()).
2014
2015 \code
2016 void PaintDeviceWindow::paintEvent(QPaintEvent *)
2017 {
2018 QPainter painter(this);
2019 QRect rect(0, 0, width(), height());
2020 painter.fillRect(rect, QGradient::SunnyMorning);
2021 painter.fillRect(rect - safeAreaMargins(), QGradient::DustyGrass);
2022 }
2023 \endcode
2024
2025 \since 6.9
2026 \sa geometry(), safeAreaMarginsChanged()
2027*/
2028QMargins QWindow::safeAreaMargins() const
2029{
2030 Q_D(const QWindow);
2031 if (d->platformWindow)
2032 return QHighDpi::fromNativePixels(d->platformWindow->safeAreaMargins(), this);
2033 return {};
2034}
2035
2036/*!
2037 \fn void QWindow::safeAreaMarginsChanged(QMargins margins)
2038 \since 6.9
2039
2040 This signal is emitted when the safe area margins changed to \a margins.
2041
2042 \sa safeAreaMargins()
2043*/
2044
2045/*!
2046 \brief set the position of the window on the desktop to \a pt
2047
2048 The position is in relation to the virtualGeometry() of its screen.
2049
2050 For interactively moving windows, see startSystemMove(). For interactively
2051 resizing windows, see startSystemResize().
2052
2053 \note Not all windowing systems support setting or querying top level window positions.
2054 On such a system, programmatically moving windows may not have any effect, and artificial
2055 values may be returned for the current positions, such as \c QPoint(0, 0).
2056
2057 \sa position(), startSystemMove()
2058*/
2059void QWindow::setPosition(const QPoint &pt)
2060{
2061 setGeometry(QRect(pt, size()));
2062}
2063
2064/*!
2065 \brief set the position of the window on the desktop to \a posx, \a posy
2066
2067 The position is in relation to the virtualGeometry() of its screen.
2068
2069 \sa position()
2070*/
2071void QWindow::setPosition(int posx, int posy)
2072{
2073 setPosition(QPoint(posx, posy));
2074}
2075
2076/*!
2077 \fn QPoint QWindow::position() const
2078 \brief Returns the position of the window on the desktop excluding any window frame
2079
2080 \note Not all windowing systems support setting or querying top level window positions.
2081 On such a system, programmatically moving windows may not have any effect, and artificial
2082 values may be returned for the current positions, such as \c QPoint(0, 0).
2083
2084 \sa setPosition()
2085*/
2086
2087/*!
2088 \fn QSize QWindow::size() const
2089 \brief Returns the size of the window excluding any window frame
2090
2091 \sa resize()
2092*/
2093
2094/*!
2095 set the size of the window, excluding any window frame, to a QSize
2096 constructed from width \a w and height \a h
2097
2098 For interactively resizing windows, see startSystemResize().
2099
2100 \sa size(), geometry()
2101*/
2102void QWindow::resize(int w, int h)
2103{
2104 resize(QSize(w, h));
2105}
2106
2107/*!
2108 \brief set the size of the window, excluding any window frame, to \a newSize
2109
2110 \sa size(), geometry()
2111*/
2112void QWindow::resize(const QSize &newSize)
2113{
2114 Q_D(QWindow);
2115
2116 const QSize oldSize = size();
2117 if (newSize == oldSize)
2118 return;
2119
2120 d->positionPolicy = QWindowPrivate::WindowFrameExclusive;
2121 if (d->platformWindow) {
2122 d->platformWindow->setGeometry(
2123 QHighDpi::toNativeWindowGeometry(QRect(position(), newSize), this));
2124 } else {
2125 d->geometry.setSize(newSize);
2126 if (newSize.width() != oldSize.width())
2127 emit widthChanged(newSize.width());
2128 if (newSize.height() != oldSize.height())
2129 emit heightChanged(newSize.height());
2130 }
2131}
2132
2133/*!
2134 Releases the native platform resources associated with this window.
2135
2136 \sa create()
2137*/
2138void QWindow::destroy()
2139{
2140 Q_D(QWindow);
2141 if (!d->platformWindow)
2142 return;
2143
2144 if (d->platformWindow->isForeignWindow())
2145 return;
2146
2147 d->destroy();
2148}
2149
2150void QWindowPrivate::destroy()
2151{
2152 if (!platformWindow)
2153 return;
2154
2155 Q_Q(QWindow);
2156 QObjectList childrenWindows = q->children();
2157 for (int i = 0; i < childrenWindows.size(); i++) {
2158 QObject *object = childrenWindows.at(i);
2159 if (object->isWindowType()) {
2160 QWindow *w = static_cast<QWindow*>(object);
2161 qt_window_private(w)->destroy();
2162 }
2163 }
2164
2165 bool wasVisible = q->isVisible();
2166 visibilityOnDestroy = wasVisible && platformWindow;
2167
2168 q->setVisible(false);
2169
2170 // Let subclasses act, typically by doing graphics resource cleaup, when
2171 // the window, to which graphics resource may be tied, is going away.
2172 //
2173 // NB! This is dysfunctional when destroy() is invoked from the dtor since
2174 // a reimplemented event() will not get called in the subclasses at that
2175 // stage. However, the typical QWindow cleanup involves either close() or
2176 // going through QWindowContainer, both of which will do an explicit, early
2177 // destroy(), which is good here.
2178
2179 QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed);
2180 QGuiApplication::sendEvent(q, &e);
2181
2182 // Unset platformWindow before deleting, so that the destructor of the
2183 // platform window does not recurse back into the platform window via
2184 // this window during destruction (e.g. as a result of platform events).
2185 delete std::exchange(platformWindow, nullptr);
2186
2187 if (QGuiApplicationPrivate::focus_window == q)
2188 QGuiApplicationPrivate::focus_window = q->parent();
2189 if (QGuiApplicationPrivate::currentMouseWindow == q)
2190 QGuiApplicationPrivate::currentMouseWindow = q->parent();
2191 if (QGuiApplicationPrivate::currentMousePressWindow == q)
2192 QGuiApplicationPrivate::currentMousePressWindow = q->parent();
2193
2194 for (int i = 0; i < QGuiApplicationPrivate::tabletDevicePoints.size(); ++i)
2195 if (QGuiApplicationPrivate::tabletDevicePoints.at(i).target == q)
2196 QGuiApplicationPrivate::tabletDevicePoints[i].target = q->parent();
2197
2198 resizeEventPending = true;
2199 receivedExpose = false;
2200 exposed = false;
2201
2202 // Position set via setFramePosition will have propagated back to
2203 // our geometry member as client geometry, so when creating the
2204 // window again we need to ensure the policy matches that.
2205 positionPolicy = QWindowPrivate::WindowFrameExclusive;
2206}
2207
2208/*!
2209 Returns the platform window corresponding to the window.
2210
2211 \internal
2212*/
2213QPlatformWindow *QWindow::handle() const
2214{
2215 Q_D(const QWindow);
2216 return d->platformWindow;
2217}
2218
2219/*!
2220 Returns the platform surface corresponding to the window.
2221
2222 \internal
2223*/
2224QPlatformSurface *QWindow::surfaceHandle() const
2225{
2226 Q_D(const QWindow);
2227 return d->platformWindow;
2228}
2229
2230/*!
2231 Sets whether keyboard grab should be enabled or not (\a grab).
2232
2233 If the return value is true, the window receives all key events until
2234 setKeyboardGrabEnabled(false) is called; other windows get no key events at
2235 all. Mouse events are not affected. Use setMouseGrabEnabled() if you want
2236 to grab that.
2237
2238 \sa setMouseGrabEnabled()
2239*/
2240bool QWindow::setKeyboardGrabEnabled(bool grab)
2241{
2242 Q_D(QWindow);
2243 if (d->platformWindow)
2244 return d->platformWindow->setKeyboardGrabEnabled(grab);
2245 return false;
2246}
2247
2248/*!
2249 Sets whether mouse grab should be enabled or not (\a grab).
2250
2251 If the return value is true, the window receives all mouse events until setMouseGrabEnabled(false) is
2252 called; other windows get no mouse events at all. Keyboard events are not affected.
2253 Use setKeyboardGrabEnabled() if you want to grab that.
2254
2255 \sa setKeyboardGrabEnabled()
2256*/
2257bool QWindow::setMouseGrabEnabled(bool grab)
2258{
2259 Q_D(QWindow);
2260 if (d->platformWindow)
2261 return d->platformWindow->setMouseGrabEnabled(grab);
2262 return false;
2263}
2264
2265/*!
2266 Returns the screen on which the window is shown, or null if there is none.
2267
2268 For child windows, this returns the screen of the corresponding top level window.
2269
2270 \sa setScreen(), QScreen::virtualSiblings()
2271*/
2272QScreen *QWindow::screen() const
2273{
2274 Q_D(const QWindow);
2275 return d->parentWindow ? d->parentWindow->screen() : d->topLevelScreen.data();
2276}
2277
2278/*!
2279 Sets the screen on which the window should be shown.
2280
2281 If the window has been created, it will be recreated on the \a newScreen.
2282
2283 \note If the screen is part of a virtual desktop of multiple screens,
2284 the window will not move automatically to \a newScreen. To place the
2285 window relative to the screen, use the screen's topLeft() position.
2286
2287 This function only works for top level windows.
2288
2289 \sa screen(), QScreen::virtualSiblings()
2290*/
2291void QWindow::setScreen(QScreen *newScreen)
2292{
2293 Q_D(QWindow);
2294 if (!newScreen)
2295 newScreen = QGuiApplication::primaryScreen();
2296 d->setTopLevelScreen(newScreen, newScreen != nullptr);
2297}
2298
2299/*!
2300 \fn QWindow::screenChanged(QScreen *screen)
2301
2302 This signal is emitted when a window's \a screen changes, either
2303 by being set explicitly with setScreen(), or automatically when
2304 the window's screen is removed.
2305*/
2306
2307/*!
2308 Returns the accessibility interface for the object that the window represents
2309 \internal
2310 \sa QAccessible
2311 */
2312QAccessibleInterface *QWindow::accessibleRoot() const
2313{
2314 return nullptr;
2315}
2316
2317/*!
2318 \fn QWindow::focusObjectChanged(QObject *object)
2319
2320 This signal is emitted when the final receiver of events tied to focus
2321 is changed to \a object.
2322
2323 \sa focusObject()
2324*/
2325
2326/*!
2327 Returns the QObject that will be the final receiver of events tied focus, such
2328 as key events.
2329*/
2330QObject *QWindow::focusObject() const
2331{
2332 return const_cast<QWindow *>(this);
2333}
2334
2335/*!
2336 Shows the window.
2337
2338 For child windows, this is equivalent to calling showNormal().
2339 Otherwise, it is equivalent to calling showFullScreen(), showMaximized(), or showNormal(),
2340 depending on the platform's default behavior for the window type and flags.
2341
2342 \sa showFullScreen(), showMaximized(), showNormal(), hide(), QStyleHints::showIsFullScreen(), flags()
2343*/
2344void QWindow::show()
2345{
2346 if (parent()) {
2347 showNormal();
2348 } else {
2349 const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
2350 Qt::WindowState defaultState = platformIntegration->defaultWindowState(d_func()->windowFlags);
2351 if (defaultState == Qt::WindowFullScreen)
2352 showFullScreen();
2353 else if (defaultState == Qt::WindowMaximized)
2354 showMaximized();
2355 else
2356 showNormal();
2357 }
2358}
2359
2360/*!
2361 Hides the window.
2362
2363 Equivalent to calling setVisible(false).
2364
2365 \sa show(), setVisible()
2366*/
2367void QWindow::hide()
2368{
2369 setVisible(false);
2370}
2371
2372/*!
2373 Shows the window as minimized.
2374
2375 Equivalent to calling setWindowStates(Qt::WindowMinimized) and then
2376 setVisible(true).
2377
2378 \sa setWindowStates(), setVisible()
2379*/
2380void QWindow::showMinimized()
2381{
2382 setWindowStates(Qt::WindowMinimized);
2383 setVisible(true);
2384}
2385
2386/*!
2387 Shows the window as maximized.
2388
2389 Equivalent to calling setWindowStates(Qt::WindowMaximized) and then
2390 setVisible(true).
2391
2392 \sa setWindowStates(), setVisible()
2393*/
2394void QWindow::showMaximized()
2395{
2396 setWindowStates(Qt::WindowMaximized);
2397 setVisible(true);
2398}
2399
2400/*!
2401 Shows the window as fullscreen.
2402
2403 Equivalent to calling setWindowStates(Qt::WindowFullScreen) and then
2404 setVisible(true).
2405
2406 See the \l{QWidget::showFullScreen()} documentation for platform-specific
2407 considerations and limitations.
2408
2409 \sa setWindowStates(), setVisible()
2410*/
2411void QWindow::showFullScreen()
2412{
2413 setWindowStates(Qt::WindowFullScreen);
2414 setVisible(true);
2415#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
2416 // activating it here before libscreen activates it causes problems
2417 requestActivate();
2418#endif
2419}
2420
2421/*!
2422 Shows the window as normal, i.e. neither maximized, minimized, nor fullscreen.
2423
2424 Equivalent to calling setWindowStates(Qt::WindowNoState) and then
2425 setVisible(true).
2426
2427 \sa setWindowStates(), setVisible()
2428*/
2429void QWindow::showNormal()
2430{
2431 setWindowStates(Qt::WindowNoState);
2432 setVisible(true);
2433}
2434
2435/*!
2436 Close the window.
2437
2438 This closes the window, effectively calling destroy(), and potentially
2439 quitting the application. Returns \c true on success, false if it has a parent
2440 window (in which case the top level window should be closed instead).
2441
2442 \sa destroy(), QGuiApplication::quitOnLastWindowClosed(), closeEvent()
2443*/
2444bool QWindow::close()
2445{
2446 Q_D(QWindow);
2447 if (d->inClose)
2448 return true;
2449
2450 // Do not close non top level windows
2451 if (!isTopLevel())
2452 return false;
2453
2454 if (!d->platformWindow) {
2455 // dock widgets can transition back and forth to being popups;
2456 // avoid getting stuck
2457 if (QGuiApplicationPrivate::activePopupWindow() == this)
2458 QGuiApplicationPrivate::closePopup(this);
2459 return true;
2460 }
2461
2462 // The window might be deleted during close,
2463 // as a result of delivering the close event.
2464 QPointer guard(this);
2465 d->inClose = true;
2466 bool success = d->platformWindow->close();
2467 if (guard)
2468 d->inClose = false;
2469
2470 return success;
2471}
2472
2473bool QWindowPrivate::participatesInLastWindowClosed() const
2474{
2475 Q_Q(const QWindow);
2476
2477 if (!q->isTopLevel())
2478 return false;
2479
2480 // Tool-tip widgets do not normally have Qt::WA_QuitOnClose,
2481 // but since we do not have a similar flag for non-widget
2482 // windows we need an explicit exclusion here as well.
2483 if (q->type() == Qt::ToolTip)
2484 return false;
2485
2486 // A window with a transient parent is not a primary window,
2487 // it's a secondary window.
2488 if (q->transientParent())
2489 return false;
2490
2491 return true;
2492}
2493
2494bool QWindowPrivate::treatAsVisible() const
2495{
2496 Q_Q(const QWindow);
2497 return q->isVisible();
2498}
2499
2500/*! \internal
2501 Returns the popup window that has consumed \a event, if any.
2502 \a activePopupOnPress is the window that we have observed previously handling the press.
2503*/
2504const QWindow *QWindowPrivate::forwardToPopup(QEvent *event, const QWindow */*activePopupOnPress*/)
2505{
2506 Q_Q(const QWindow);
2507 qCDebug(lcPopup) << "checking for popup alternative to" << q << "for" << event
2508 << "active popup?" << QGuiApplicationPrivate::activePopupWindow();
2509 QWindow *ret = nullptr;
2510 if (QWindow *popupWindow = QGuiApplicationPrivate::activePopupWindow()) {
2511 if (q == popupWindow)
2512 return nullptr; // avoid infinite recursion: we're already handling it
2513 if (event->isPointerEvent()) {
2514 // detach eventPoints before modifying them
2515 QScopedPointer<QPointerEvent> pointerEvent(static_cast<QPointerEvent *>(event)->clone());
2516 for (int i = 0; i < pointerEvent->pointCount(); ++i) {
2517 QEventPoint &eventPoint = pointerEvent->point(i);
2518 const QPoint globalPos = eventPoint.globalPosition().toPoint();
2519 const QPointF mapped = popupWindow->mapFromGlobal(globalPos);
2520 QMutableEventPoint::setPosition(eventPoint, mapped);
2521 QMutableEventPoint::setScenePosition(eventPoint, mapped);
2522 }
2523
2524 /* Popups are expected to be able to directly handle the
2525 drag-release sequence after pressing to open, as well as
2526 any other mouse events that occur within the popup's bounds. */
2527 if (QCoreApplication::sendSpontaneousEvent(popupWindow, pointerEvent.get())) {
2528 event->setAccepted(pointerEvent->isAccepted());
2529 if (pointerEvent->isAccepted())
2530 ret = popupWindow;
2531 }
2532 qCDebug(lcPopup) << q << "forwarded" << event->type() << "to popup" << popupWindow
2533 << "handled?" << (ret != nullptr)
2534 << "accepted?" << event->isAccepted();
2535 return ret;
2536 } else if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
2537 if (QCoreApplication::sendSpontaneousEvent(popupWindow, event))
2538 ret = popupWindow;
2539 qCDebug(lcPopup) << q << "forwarded" << event->type() << "to popup" << popupWindow
2540 << "handled?" << (ret != nullptr)
2541 << "accepted?" << event->isAccepted();
2542 return ret;
2543 }
2544 }
2545 return ret;
2546}
2547
2548/*!
2549 The expose event (\a ev) is sent by the window system when a window moves
2550 between the un-exposed and exposed states.
2551
2552 An exposed window is potentially visible to the user. If the window is moved
2553 off screen, is made totally obscured by another window, is minimized, or
2554 similar, this function might be called and the value of isExposed() might
2555 change to false. You may use this event to limit expensive operations such
2556 as animations to only run when the window is exposed.
2557
2558 This event should not be used to paint. To handle painting implement
2559 paintEvent() instead.
2560
2561 A resize event will always be sent before the expose event the first time
2562 a window is shown.
2563
2564 \sa paintEvent(), isExposed()
2565*/
2566void QWindow::exposeEvent(QExposeEvent *ev)
2567{
2568 ev->ignore();
2569}
2570
2571/*!
2572 The paint event (\a ev) is sent by the window system whenever an area of
2573 the window needs a repaint, for example when initially showing the window,
2574 or due to parts of the window being uncovered by moving another window.
2575
2576 The application is expected to render into the window in response to the
2577 paint event, regardless of the exposed state of the window. For example,
2578 a paint event may be sent before the window is exposed, to prepare it for
2579 showing to the user.
2580
2581 \since 6.0
2582
2583 \sa exposeEvent()
2584*/
2585void QWindow::paintEvent(QPaintEvent *ev)
2586{
2587 ev->ignore();
2588}
2589
2590/*!
2591 Override this to handle window move events (\a ev).
2592*/
2593void QWindow::moveEvent(QMoveEvent *ev)
2594{
2595 ev->ignore();
2596}
2597
2598/*!
2599 Override this to handle resize events (\a ev).
2600
2601 The resize event is called whenever the window is resized in the windowing system,
2602 either directly through the windowing system acknowledging a setGeometry() or resize() request,
2603 or indirectly through the user resizing the window manually.
2604*/
2605void QWindow::resizeEvent(QResizeEvent *ev)
2606{
2607 ev->ignore();
2608}
2609
2610/*!
2611 Override this to handle show events (\a ev).
2612
2613 The function is called when the window has requested becoming visible.
2614
2615 If the window is successfully shown by the windowing system, this will
2616 be followed by a resize and an expose event.
2617*/
2618void QWindow::showEvent(QShowEvent *ev)
2619{
2620 ev->ignore();
2621}
2622
2623/*!
2624 Override this to handle hide events (\a ev).
2625
2626 The function is called when the window has requested being hidden in the
2627 windowing system.
2628*/
2629void QWindow::hideEvent(QHideEvent *ev)
2630{
2631 ev->ignore();
2632}
2633
2634/*!
2635 Override this to handle close events (\a ev).
2636
2637 The function is called when the window is requested to close. Call \l{QEvent::ignore()}
2638 on the event if you want to prevent the window from being closed.
2639
2640 \sa close()
2641*/
2642void QWindow::closeEvent(QCloseEvent *ev)
2643{
2644 Q_UNUSED(ev);
2645}
2646
2647/*!
2648 Override this to handle any event (\a ev) sent to the window.
2649 Return \c true if the event was recognized and processed.
2650
2651 Remember to call the base class version if you wish for mouse events,
2652 key events, resize events, etc to be dispatched as usual.
2653*/
2654bool QWindow::event(QEvent *ev)
2655{
2656 Q_D(QWindow);
2657 switch (ev->type()) {
2658 case QEvent::MouseMove:
2659 mouseMoveEvent(static_cast<QMouseEvent*>(ev));
2660 break;
2661
2662 case QEvent::MouseButtonPress: {
2663 auto *me = static_cast<QMouseEvent*>(ev);
2664 mousePressEvent(me);
2665 if (!ev->isAccepted())
2666 d->maybeSynthesizeContextMenuEvent(me);
2667 break;
2668 }
2669
2670 case QEvent::MouseButtonRelease: {
2671 auto *me = static_cast<QMouseEvent*>(ev);
2672 mouseReleaseEvent(me);
2673 if (!ev->isAccepted())
2674 d->maybeSynthesizeContextMenuEvent(me);
2675 break;
2676 }
2677
2678 case QEvent::MouseButtonDblClick:
2679 mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
2680 break;
2681
2682 case QEvent::TouchBegin:
2683 case QEvent::TouchUpdate:
2684 case QEvent::TouchEnd:
2685 case QEvent::TouchCancel:
2686 touchEvent(static_cast<QTouchEvent *>(ev));
2687 break;
2688
2689 case QEvent::Move:
2690 moveEvent(static_cast<QMoveEvent*>(ev));
2691 break;
2692
2693 case QEvent::Resize:
2694 resizeEvent(static_cast<QResizeEvent*>(ev));
2695 break;
2696
2697 case QEvent::KeyPress:
2698 keyPressEvent(static_cast<QKeyEvent *>(ev));
2699 break;
2700
2701 case QEvent::KeyRelease:
2702 keyReleaseEvent(static_cast<QKeyEvent *>(ev));
2703 break;
2704
2705 case QEvent::FocusIn: {
2706 focusInEvent(static_cast<QFocusEvent *>(ev));
2707#if QT_CONFIG(accessibility)
2708 QAccessible::State state;
2709 state.active = true;
2710 QAccessibleStateChangeEvent event(this, state);
2711 QAccessible::updateAccessibility(&event);
2712#endif
2713 break; }
2714
2715 case QEvent::FocusOut: {
2716 focusOutEvent(static_cast<QFocusEvent *>(ev));
2717#if QT_CONFIG(accessibility)
2718 QAccessible::State state;
2719 state.active = true;
2720 QAccessibleStateChangeEvent event(this, state);
2721 QAccessible::updateAccessibility(&event);
2722#endif
2723 break; }
2724
2725#if QT_CONFIG(wheelevent)
2726 case QEvent::Wheel:
2727 wheelEvent(static_cast<QWheelEvent*>(ev));
2728 break;
2729#endif
2730
2731 case QEvent::Close: {
2732
2733 const bool wasVisible = d->treatAsVisible();
2734 const bool participatesInLastWindowClosed = d->participatesInLastWindowClosed();
2735
2736 // The window might be deleted in the close event handler
2737 QPointer<QWindow> deletionGuard(this);
2738 closeEvent(static_cast<QCloseEvent*>(ev));
2739
2740 if (ev->isAccepted()) {
2741 if (deletionGuard)
2742 destroy();
2743 if (wasVisible && participatesInLastWindowClosed)
2744 QGuiApplicationPrivate::instance()->maybeLastWindowClosed();
2745 }
2746
2747 break;
2748 }
2749
2750 case QEvent::Expose:
2751 exposeEvent(static_cast<QExposeEvent *>(ev));
2752 break;
2753
2754 case QEvent::Paint:
2755 paintEvent(static_cast<QPaintEvent *>(ev));
2756 break;
2757
2758 case QEvent::Show:
2759 showEvent(static_cast<QShowEvent *>(ev));
2760 break;
2761
2762 case QEvent::Hide:
2763 hideEvent(static_cast<QHideEvent *>(ev));
2764 break;
2765
2766 case QEvent::ApplicationWindowIconChange:
2767 setIcon(icon());
2768 break;
2769
2770#if QT_CONFIG(tabletevent)
2771 case QEvent::TabletPress:
2772 case QEvent::TabletMove:
2773 case QEvent::TabletRelease:
2774 tabletEvent(static_cast<QTabletEvent *>(ev));
2775 break;
2776#endif
2777
2778 case QEvent::PlatformSurface: {
2779 if ((static_cast<QPlatformSurfaceEvent *>(ev))->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) {
2780#ifndef QT_NO_OPENGL
2781 QOpenGLContext *context = QOpenGLContext::currentContext();
2782 if (context && context->surface() == static_cast<QSurface *>(this))
2783 context->doneCurrent();
2784#endif
2785 }
2786 break;
2787 }
2788
2789 default:
2790 return QObject::event(ev);
2791 }
2792
2793 return true;
2794}
2795
2796/*! \internal
2797 Synthesize and send a QContextMenuEvent if the given \a event is a suitable
2798 mouse event (a right-button press or release, depending on
2799 QStyleHints::contextMenuTrigger()). On most platforms, it's done on mouse
2800 press; on Windows, it's done on release, because of the potential to
2801 support right-button clicks and drags to select or lasso items, and then
2802 still getting a context menu at the end of that gesture. (That is in
2803 conflict with supporting the press-drag-release gesture to select menu
2804 items on the context menus themselves. Context menus can be implemented
2805 that way by handling the separate press, move and release events.)
2806
2807 Any time the \a event was already handled in some way, it *should* be
2808 accepted, but mere acceptance of the mouse event cannot be taken to
2809 indicate that it's not necessary to synthesize a QContextMenuEvent here,
2810 because the Windows use case requires doing one thing (selecting items)
2811 with the mouse events, and then doing something completely different with
2812 the QContextMenuEvent. In other words, QContextMenuEvent is very different
2813 from other kinds of optional followup events synthesized from unhandled
2814 events (like the way we synthesize a QMouseEvent only if a QTabletEvent was
2815 not handled). Furthermore, there's enough legacy widget code that doesn't
2816 call ignore() on unhandled mouse events. So it's uncertain whether this can
2817 change in Qt 7.
2818
2819 The QContextMenuEvent occurs at the scenePosition(). The position()
2820 was likely already "localized" during the previous delivery.
2821
2822 The synthesis from a mouse button event could be done in the platform
2823 plugin, but so far on Windows it's not done: WM_CONTEXTMENU is not
2824 generated by the OS, because we never call the default window procedure
2825 that would do that in response to unhandled WM_RBUTTONUP. If we
2826 eventually want to do that, we would have to avoid doing it here,
2827 on platforms where the platform plugin is responsible for it.
2828
2829 QGuiApplicationPrivate::processContextMenuEvent also allows
2830 keyboard-triggered context menu events that the QPA plugin might generate.
2831 On Windows, the keyboard may have a menu key. On macOS, control-return
2832 is the usual shortcut; on Gnome, it's shift-F10; and so on.
2833*/
2834void QWindowPrivate::maybeSynthesizeContextMenuEvent(QMouseEvent *event)
2835{
2836#ifndef QT_NO_CONTEXTMENU
2837 if (event->button() == Qt::RightButton
2838 && event->type() == QGuiApplicationPrivate::contextMenuEventType()) {
2839 QContextMenuEvent e(QContextMenuEvent::Mouse, event->scenePosition().toPoint(),
2840 event->globalPosition().toPoint(), event->modifiers());
2841 qCDebug(lcPopup) << "synthesized after"
2842 << (event->isAccepted() ? "ACCEPTED (legacy behavior)" : "ignored")
2843 << event->type() << ":" << &e;
2844 QCoreApplication::forwardEvent(q_func(), &e, event);
2845 if (e.isAccepted())
2846 event->accept();
2847 }
2848#endif
2849}
2850
2851/*!
2852 Schedules a QEvent::UpdateRequest event to be delivered to this window.
2853
2854 The event is delivered in sync with the display vsync on platforms where
2855 this is possible. Otherwise, the event is delivered after a delay of at
2856 most 5 ms. If the window's associated screen reports a
2857 \l{QScreen::refreshRate()}{refresh rate} higher than 60 Hz, the interval is
2858 scaled down to a value smaller than 5. The additional time is there to give
2859 the event loop a bit of idle time to gather system events, and can be
2860 overridden using the QT_QPA_UPDATE_IDLE_TIME environment variable.
2861
2862 When driving animations, this function should be called once after drawing
2863 has completed. Calling this function multiple times will result in a single
2864 event being delivered to the window.
2865
2866 Subclasses of QWindow should reimplement event(), intercept the event and
2867 call the application's rendering code, then call the base class
2868 implementation.
2869
2870 \note The subclass' reimplementation of event() must invoke the base class
2871 implementation, unless it is absolutely sure that the event does not need to
2872 be handled by the base class. For example, the default implementation of
2873 this function relies on QEvent::Timer events. Filtering them away would
2874 therefore break the delivery of the update events.
2875
2876 \since 5.5
2877*/
2878void QWindow::requestUpdate()
2879{
2880 Q_ASSERT_X(QThread::isMainThread(),
2881 "QWindow", "Updates can only be scheduled from the GUI (main) thread");
2882
2883 Q_D(QWindow);
2884 if (d->updateRequestPending || !d->platformWindow)
2885 return;
2886 d->updateRequestPending = true;
2887 d->platformWindow->requestUpdate();
2888}
2889
2890/*!
2891 Override this to handle key press events (\a ev).
2892
2893 \sa keyReleaseEvent()
2894*/
2895void QWindow::keyPressEvent(QKeyEvent *ev)
2896{
2897 ev->ignore();
2898}
2899
2900/*!
2901 Override this to handle key release events (\a ev).
2902
2903 \sa keyPressEvent()
2904*/
2905void QWindow::keyReleaseEvent(QKeyEvent *ev)
2906{
2907 ev->ignore();
2908}
2909
2910/*!
2911 Override this to handle focus in events (\a ev).
2912
2913 Focus in events are sent when the window receives keyboard focus.
2914
2915 \sa focusOutEvent()
2916*/
2917void QWindow::focusInEvent(QFocusEvent *ev)
2918{
2919 ev->ignore();
2920}
2921
2922/*!
2923 Override this to handle focus out events (\a ev).
2924
2925 Focus out events are sent when the window loses keyboard focus.
2926
2927 \sa focusInEvent()
2928*/
2929void QWindow::focusOutEvent(QFocusEvent *ev)
2930{
2931 ev->ignore();
2932}
2933
2934/*!
2935 Override this to handle mouse press events (\a ev).
2936
2937 \sa mouseReleaseEvent()
2938*/
2939void QWindow::mousePressEvent(QMouseEvent *ev)
2940{
2941 ev->ignore();
2942}
2943
2944/*!
2945 Override this to handle mouse release events (\a ev).
2946
2947 \sa mousePressEvent()
2948*/
2949void QWindow::mouseReleaseEvent(QMouseEvent *ev)
2950{
2951 ev->ignore();
2952}
2953
2954/*!
2955 Override this to handle mouse double click events (\a ev).
2956
2957 \sa mousePressEvent(), QStyleHints::mouseDoubleClickInterval()
2958*/
2959void QWindow::mouseDoubleClickEvent(QMouseEvent *ev)
2960{
2961 ev->ignore();
2962}
2963
2964/*!
2965 Override this to handle mouse move events (\a ev).
2966*/
2967void QWindow::mouseMoveEvent(QMouseEvent *ev)
2968{
2969 ev->ignore();
2970}
2971
2972#if QT_CONFIG(wheelevent)
2973/*!
2974 Override this to handle mouse wheel or other wheel events (\a ev).
2975*/
2976void QWindow::wheelEvent(QWheelEvent *ev)
2977{
2978 ev->ignore();
2979}
2980#endif // QT_CONFIG(wheelevent)
2981
2982/*!
2983 Override this to handle touch events (\a ev).
2984*/
2985void QWindow::touchEvent(QTouchEvent *ev)
2986{
2987 ev->ignore();
2988}
2989
2990#if QT_CONFIG(tabletevent)
2991/*!
2992 Override this to handle tablet press, move, and release events (\a ev).
2993
2994 Proximity enter and leave events are not sent to windows, they are
2995 delivered to the application instance.
2996*/
2997void QWindow::tabletEvent(QTabletEvent *ev)
2998{
2999 ev->ignore();
3000}
3001#endif
3002
3003/*!
3004 Override this to handle platform dependent events.
3005 Will be given \a eventType, \a message and \a result.
3006
3007 This might make your application non-portable.
3008
3009 Should return true only if the event was handled.
3010*/
3011
3012bool QWindow::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
3013{
3014 Q_UNUSED(eventType);
3015 Q_UNUSED(message);
3016 Q_UNUSED(result);
3017 return false;
3018}
3019
3020/*!
3021 \fn QPointF QWindow::mapToGlobal(const QPointF &pos) const
3022
3023 Translates the window coordinate \a pos to global screen
3024 coordinates. For example, \c{mapToGlobal(QPointF(0,0))} would give
3025 the global coordinates of the top-left pixel of the window.
3026
3027 \sa mapFromGlobal()
3028 \since 6.0
3029*/
3030QPointF QWindow::mapToGlobal(const QPointF &pos) const
3031{
3032 Q_D(const QWindow);
3033 // QTBUG-43252, prefer platform implementation for foreign windows.
3034 if (d->platformWindow
3035 && (d->platformWindow->isForeignWindow() || d->platformWindow->isEmbedded())) {
3036 return QHighDpi::fromNativeGlobalPosition(d->platformWindow->mapToGlobalF(QHighDpi::toNativeLocalPosition(pos, this)), this);
3037 }
3038
3039 if (!QHighDpiScaling::isActive())
3040 return pos + d->globalPosition();
3041
3042 // The normal pos + windowGlobalPos calculation may give a point which is outside
3043 // screen geometry for windows which span multiple screens, due to the way QHighDpiScaling
3044 // creates gaps between screens in the the device indendent cooordinate system.
3045 //
3046 // Map the position (and the window's global position) to native coordinates, perform
3047 // the addition, and then map back to device independent coordinates.
3048 QPointF nativeLocalPos = QHighDpi::toNativeLocalPosition(pos, this);
3049 // Get the native window position directly from the platform window
3050 // if available (it can be null if the window hasn't been shown yet),
3051 // or fall back to scaling the QWindow position.
3052 QPointF nativeWindowGlobalPos = d->platformWindow
3053 ? d->platformWindow->mapToGlobal(QPoint(0,0)).toPointF()
3054 : QHighDpi::toNativeGlobalPosition(QPointF(d->globalPosition()), this);
3055 QPointF nativeGlobalPos = nativeLocalPos + nativeWindowGlobalPos;
3056 QPointF deviceIndependentGlobalPos = QHighDpi::fromNativeGlobalPosition(nativeGlobalPos, this);
3057 return deviceIndependentGlobalPos;
3058}
3059
3060/*!
3061 \overload
3062*/
3063QPoint QWindow::mapToGlobal(const QPoint &pos) const
3064{
3065 return mapToGlobal(QPointF(pos)).toPoint();
3066}
3067
3068/*!
3069 \fn QPointF QWindow::mapFromGlobal(const QPointF &pos) const
3070
3071 Translates the global screen coordinate \a pos to window
3072 coordinates.
3073
3074 \sa mapToGlobal()
3075 \since 6.0
3076*/
3077QPointF QWindow::mapFromGlobal(const QPointF &pos) const
3078{
3079 Q_D(const QWindow);
3080 // QTBUG-43252, prefer platform implementation for foreign windows.
3081 if (d->platformWindow
3082 && (d->platformWindow->isForeignWindow() || d->platformWindow->isEmbedded())) {
3083 return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapFromGlobalF(QHighDpi::toNativeGlobalPosition(pos, this)), this);
3084 }
3085
3086 if (!QHighDpiScaling::isActive())
3087 return pos - d->globalPosition();
3088
3089 // Calculate local position in the native coordinate system. (See comment for the
3090 // corresponding mapToGlobal() code above).
3091 QPointF nativeGlobalPos = QHighDpi::toNativeGlobalPosition(pos, this);
3092 // Get the native window position directly from the platform window
3093 // if available (it can be null if the window hasn't been shown yet),
3094 // or fall back to scaling the QWindow position.
3095 QPointF nativeWindowGlobalPos = d->platformWindow
3096 ? d->platformWindow->mapToGlobal(QPoint(0,0)).toPointF()
3097 : QHighDpi::toNativeGlobalPosition(QPointF(d->globalPosition()), this);
3098 QPointF nativeLocalPos = nativeGlobalPos - nativeWindowGlobalPos;
3099 QPointF deviceIndependentLocalPos = QHighDpi::fromNativeLocalPosition(nativeLocalPos, this);
3100 return deviceIndependentLocalPos;
3101}
3102
3103/*!
3104 \overload
3105*/
3106QPoint QWindow::mapFromGlobal(const QPoint &pos) const
3107{
3108 return QWindow::mapFromGlobal(QPointF(pos)).toPoint();
3109}
3110
3111QPoint QWindowPrivate::globalPosition() const
3112{
3113 Q_Q(const QWindow);
3114 QPoint offset = q->position();
3115 for (const QWindow *p = q->parent(); p; p = p->parent()) {
3116 QPlatformWindow *pw = p->handle();
3117 if (pw && (pw->isForeignWindow() || pw->isEmbedded())) {
3118 // Use mapToGlobal() for foreign windows
3119 offset += p->mapToGlobal(QPoint(0, 0));
3120 break;
3121 } else {
3122 offset += p->position();
3123 }
3124 }
3125 return offset;
3126}
3127
3128Q_GUI_EXPORT QWindowPrivate *qt_window_private(QWindow *window)
3129{
3130 return window->d_func();
3131}
3132
3133QWindow *QWindowPrivate::topLevelWindow(QWindow::AncestorMode mode) const
3134{
3135 Q_Q(const QWindow);
3136
3137 QWindow *window = const_cast<QWindow *>(q);
3138
3139 while (window) {
3140 QWindow *parent = window->parent(mode);
3141 if (!parent)
3142 break;
3143
3144 window = parent;
3145 }
3146
3147 return window;
3148}
3149
3150/*!
3151 Creates a local representation of a window created by another process or by
3152 using native libraries below Qt.
3153
3154 Given the handle \a id to a native window, this method creates a QWindow
3155 object which can be used to represent the window when invoking methods like
3156 setParent() and setTransientParent().
3157
3158 This can be used, on platforms which support it, to embed a QWindow inside a
3159 native window, or to embed a native window inside a QWindow.
3160
3161 If foreign windows are not supported or embedding the native window
3162 failed in the platform plugin, this function returns \nullptr.
3163
3164 \note The resulting QWindow should not be used to manipulate the underlying
3165 native window (besides re-parenting), or to observe state changes of the
3166 native window. Any support for these kind of operations is incidental, highly
3167 platform dependent and untested.
3168
3169 \sa setParent()
3170*/
3171QWindow *QWindow::fromWinId(WId id)
3172{
3173 if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ForeignWindows)) {
3174 qWarning("QWindow::fromWinId(): platform plugin does not support foreign windows.");
3175 return nullptr;
3176 }
3177
3178 QWindow *window = new QWindow;
3179
3180 // Persist the winId in a private property so that we
3181 // can recreate the window after being destroyed.
3182 window->setProperty(kForeignWindowId, id);
3183 window->create();
3184
3185 if (!window->handle()) {
3186 delete window;
3187 return nullptr;
3188 }
3189
3190 return window;
3191}
3192
3193/*!
3194 Causes an alert to be shown for \a msec milliseconds. If \a msec is \c 0 (the
3195 default), then the alert is shown indefinitely until the window becomes
3196 active again. This function has no effect on an active window.
3197
3198 In alert state, the window indicates that it demands attention, for example by
3199 flashing or bouncing the taskbar entry.
3200
3201 \since 5.1
3202*/
3203
3204void QWindow::alert(int msec)
3205{
3206 Q_D(QWindow);
3207 if (!d->platformWindow || d->platformWindow->isAlertState() || isActive())
3208 return;
3209 d->platformWindow->setAlertState(true);
3210 if (d->platformWindow->isAlertState() && msec)
3211 QTimer::singleShot(msec, this, SLOT(_q_clearAlert()));
3212}
3213
3214void QWindowPrivate::_q_clearAlert()
3215{
3216 if (platformWindow && platformWindow->isAlertState())
3217 platformWindow->setAlertState(false);
3218}
3219
3220#ifndef QT_NO_CURSOR
3221/*!
3222 \brief set the cursor shape for this window
3223
3224 The mouse \a cursor will assume this shape when it is over this
3225 window, unless an override cursor is set.
3226 See the \l{Qt::CursorShape}{list of predefined cursor objects} for a
3227 range of useful shapes.
3228
3229 If no cursor has been set, or after a call to unsetCursor(), the
3230 parent window's cursor is used.
3231
3232 By default, the cursor has the Qt::ArrowCursor shape.
3233
3234 Some underlying window implementations will reset the cursor if it
3235 leaves a window even if the mouse is grabbed. If you want to have
3236 a cursor set for all windows, even when outside the window, consider
3237 QGuiApplication::setOverrideCursor().
3238
3239 \sa QGuiApplication::setOverrideCursor()
3240*/
3241void QWindow::setCursor(const QCursor &cursor)
3242{
3243 Q_D(QWindow);
3244 d->setCursor(&cursor);
3245}
3246
3247/*!
3248 \brief Restores the default arrow cursor for this window.
3249 */
3250void QWindow::unsetCursor()
3251{
3252 Q_D(QWindow);
3253 d->setCursor(nullptr);
3254}
3255
3256/*!
3257 \brief the cursor shape for this window
3258
3259 \sa setCursor(), unsetCursor()
3260*/
3261QCursor QWindow::cursor() const
3262{
3263 Q_D(const QWindow);
3264 return d->cursor;
3265}
3266
3267void QWindowPrivate::setCursor(const QCursor *newCursor)
3268{
3269
3270 Q_Q(QWindow);
3271 if (newCursor) {
3272 const Qt::CursorShape newShape = newCursor->shape();
3273 if (newShape <= Qt::LastCursor && hasCursor && newShape == cursor.shape())
3274 return; // Unchanged and no bitmap/custom cursor.
3275 cursor = *newCursor;
3276 hasCursor = true;
3277 } else {
3278 if (!hasCursor)
3279 return;
3280 cursor = QCursor(Qt::ArrowCursor);
3281 hasCursor = false;
3282 }
3283 // Only attempt to emit signal if there is an actual platform cursor
3284 if (applyCursor()) {
3285 QEvent event(QEvent::CursorChange);
3286 QGuiApplication::sendEvent(q, &event);
3287 }
3288}
3289
3290// Apply the cursor and returns true iff the platform cursor exists
3291bool QWindowPrivate::applyCursor()
3292{
3293 Q_Q(QWindow);
3294 if (QScreen *screen = q->screen()) {
3295 if (QPlatformCursor *platformCursor = screen->handle()->cursor()) {
3296 if (!platformWindow)
3297 return true;
3298 QCursor *c = QGuiApplication::overrideCursor();
3299 if (c != nullptr && platformCursor->capabilities().testFlag(QPlatformCursor::OverrideCursor))
3300 return true;
3301 if (!c && hasCursor)
3302 c = &cursor;
3303 platformCursor->changeCursor(c, q);
3304 return true;
3305 }
3306 }
3307 return false;
3308}
3309#endif // QT_NO_CURSOR
3310
3311void *QWindow::resolveInterface(const char *name, int revision) const
3312{
3313 using namespace QNativeInterface::Private;
3314
3315 auto *platformWindow = handle();
3316 Q_UNUSED(platformWindow);
3317 Q_UNUSED(name);
3318 Q_UNUSED(revision);
3319
3320#if defined(Q_OS_WIN)
3321 QT_NATIVE_INTERFACE_RETURN_IF(QWindowsWindow, platformWindow);
3322#endif
3323
3324#if QT_CONFIG(xcb)
3325 QT_NATIVE_INTERFACE_RETURN_IF(QXcbWindow, platformWindow);
3326#endif
3327
3328#if defined(Q_OS_MACOS)
3329 QT_NATIVE_INTERFACE_RETURN_IF(QCocoaWindow, platformWindow);
3330#endif
3331
3332#if QT_CONFIG(wayland)
3333 QT_NATIVE_INTERFACE_RETURN_IF(QWaylandWindow, platformWindow);
3334#endif
3335
3336#if defined(Q_OS_WASM)
3337 QT_NATIVE_INTERFACE_RETURN_IF(QWasmWindow, platformWindow);
3338#endif
3339
3340 return nullptr;
3341}
3342
3343#ifndef QT_NO_DEBUG_STREAM
3344QDebug operator<<(QDebug debug, const QWindow *window)
3345{
3346 QDebugStateSaver saver(debug);
3347 debug.nospace();
3348 if (window) {
3349 debug << window->metaObject()->className() << '(' << (const void *)window;
3350 if (!window->objectName().isEmpty())
3351 debug << ", name=" << window->objectName();
3352 if (debug.verbosity() > 2) {
3353 const QRect geometry = window->geometry();
3354 if (window->isVisible())
3355 debug << ", visible";
3356 if (window->isExposed())
3357 debug << ", exposed";
3358 debug << ", state=" << window->windowState()
3359 << ", type=" << window->type() << ", flags=" << window->flags()
3360 << ", surface type=" << window->surfaceType();
3361 if (window->isTopLevel())
3362 debug << ", toplevel";
3363 debug << ", " << geometry.width() << 'x' << geometry.height()
3364 << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign;
3365 const QMargins margins = window->frameMargins();
3366 if (!margins.isNull())
3367 debug << ", margins=" << margins;
3368 const QMargins safeAreaMargins = window->safeAreaMargins();
3369 if (!safeAreaMargins.isNull())
3370 debug << ", safeAreaMargins=" << safeAreaMargins;
3371 debug << ", devicePixelRatio=" << window->devicePixelRatio();
3372 if (const QPlatformWindow *platformWindow = window->handle())
3373 debug << ", winId=0x" << Qt::hex << platformWindow->winId() << Qt::dec;
3374 if (const QScreen *screen = window->screen())
3375 debug << ", on " << screen->name();
3376 }
3377 debug << ')';
3378 } else {
3379 debug << "QWindow(0x0)";
3380 }
3381 return debug;
3382}
3383#endif // !QT_NO_DEBUG_STREAM
3384
3385#if QT_CONFIG(vulkan) || defined(Q_QDOC)
3386
3387/*!
3388 Associates this window with the specified Vulkan \a instance.
3389
3390 \a instance must stay valid as long as this QWindow instance exists.
3391 */
3392void QWindow::setVulkanInstance(QVulkanInstance *instance)
3393{
3394 Q_D(QWindow);
3395 d->vulkanInstance = instance;
3396}
3397
3398/*!
3399 \return the associated Vulkan instance if any was set, otherwise \nullptr.
3400 */
3401QVulkanInstance *QWindow::vulkanInstance() const
3402{
3403 Q_D(const QWindow);
3404 return d->vulkanInstance;
3405}
3406
3407#endif // QT_CONFIG(vulkan)
3408
3409QT_END_NAMESPACE
3410
3411#include "moc_qwindow.cpp"
Combined button and popup list for selecting options.
static constexpr auto kForeignWindowId
Definition qwindow.cpp:542