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