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