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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtbase/src/gui/kernel/qwindow.cpp