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

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