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