Coverage Report

Created: 2025-07-23 08:13

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