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