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