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