Coverage Report

Created: 2025-11-16 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/gui/kernel/qplatformwindow.cpp
Line
Count
Source
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 "qplatformwindow.h"
41
#include "qplatformwindow_p.h"
42
#include "qplatformscreen.h"
43
44
#include <private/qguiapplication_p.h>
45
#include <qpa/qwindowsysteminterface.h>
46
#include <QtGui/qwindow.h>
47
#include <QtGui/qscreen.h>
48
#include <private/qhighdpiscaling_p.h>
49
#include <private/qwindow_p.h>
50
51
52
QT_BEGIN_NAMESPACE
53
54
/*!
55
    Constructs a platform window with the given top level window.
56
*/
57
58
QPlatformWindow::QPlatformWindow(QWindow *window)
59
0
    : QPlatformSurface(window)
60
0
    , d_ptr(new QPlatformWindowPrivate)
61
0
{
62
0
    Q_D(QPlatformWindow);
63
0
    d->rect = QHighDpi::toNativePixels(window->geometry(), window);
64
0
}
65
66
/*!
67
    Virtual destructor does not delete its top level window.
68
*/
69
QPlatformWindow::~QPlatformWindow()
70
0
{
71
0
}
72
73
/*!
74
    Called as part of QWindow::create(), after constructing
75
    the window. Platforms should prefer to do initialization
76
    here instead of in the constructor, as the platform window
77
    object will be fully constructed, and associated to the
78
    corresponding QWindow, allowing synchronous event delivery.
79
*/
80
void QPlatformWindow::initialize()
81
0
{
82
0
}
83
84
/*!
85
    Returns the window which belongs to the QPlatformWindow
86
*/
87
QWindow *QPlatformWindow::window() const
88
0
{
89
0
    return static_cast<QWindow *>(m_surface);
90
0
}
91
92
/*!
93
    Returns the parent platform window (or \nullptr if orphan).
94
*/
95
QPlatformWindow *QPlatformWindow::parent() const
96
0
{
97
0
    return window()->parent() ? window()->parent()->handle() : nullptr;
98
0
}
99
100
/*!
101
    Returns the platform screen handle corresponding to this platform window,
102
    or null if the window is not associated with a screen.
103
*/
104
QPlatformScreen *QPlatformWindow::screen() const
105
0
{
106
0
    QScreen *scr = window()->screen();
107
0
    return scr ? scr->handle() : nullptr;
108
0
}
109
110
/*!
111
    Returns the actual surface format of the window.
112
*/
113
QSurfaceFormat QPlatformWindow::format() const
114
0
{
115
0
    return QSurfaceFormat();
116
0
}
117
118
/*!
119
    This function is called by Qt whenever a window is moved or resized using the QWindow API.
120
121
    Unless you also override QPlatformWindow::geometry(), you need to call the baseclass
122
    implementation of this function in any override of QPlatformWindow::setGeometry(), as
123
    QWindow::geometry() is expected to report back the set geometry until a confirmation
124
    (or rejection) of the new geometry comes back from the window manager and is reported
125
    via QWindowSystemInterface::handleGeometryChange().
126
127
    Window move/resizes can also be triggered spontaneously by the window manager, or as a
128
    response to an earlier requested move/resize via the Qt APIs. There is no need to call
129
    this function from the window manager callback, instead call
130
    QWindowSystemInterface::handleGeometryChange().
131
132
    The position(x, y) part of the rect might be inclusive or exclusive of the window frame
133
    as returned by frameMargins(). You can detect this in the plugin by checking
134
    qt_window_private(window())->positionPolicy.
135
*/
136
void QPlatformWindow::setGeometry(const QRect &rect)
137
0
{
138
0
    Q_D(QPlatformWindow);
139
0
    d->rect = rect;
140
0
}
141
142
/*!
143
    Returns the current geometry of a window
144
*/
145
QRect QPlatformWindow::geometry() const
146
0
{
147
0
    Q_D(const QPlatformWindow);
148
0
    return d->rect;
149
0
}
150
151
/*!
152
    Returns the geometry of a window in 'normal' state
153
    (neither maximized, fullscreen nor minimized) for saving geometries to
154
    application settings.
155
156
    \since 5.3
157
*/
158
QRect QPlatformWindow::normalGeometry() const
159
0
{
160
0
    return QRect();
161
0
}
162
163
QMargins QPlatformWindow::frameMargins() const
164
0
{
165
0
    return QMargins();
166
0
}
167
168
/*!
169
    The safe area margins of a window represent the area that is safe to
170
    place content within, without intersecting areas of the screen where
171
    system UI is placed, or where a screen bezel may cover the content.
172
*/
173
QMargins QPlatformWindow::safeAreaMargins() const
174
0
{
175
0
    return QMargins();
176
0
}
177
178
/*!
179
    Reimplemented in subclasses to show the surface
180
    if \a visible is \c true, and hide it if \a visible is \c false.
181
182
    The default implementation sends a synchronous expose event.
183
*/
184
void QPlatformWindow::setVisible(bool visible)
185
0
{
186
0
    Q_UNUSED(visible);
187
0
    QRect rect(QPoint(), geometry().size());
188
0
    QWindowSystemInterface::handleExposeEvent(window(), rect);
189
0
    QWindowSystemInterface::flushWindowSystemEvents();
190
0
}
191
192
/*!
193
    Requests setting the window flags of this surface
194
    to \a flags.
195
*/
196
void QPlatformWindow::setWindowFlags(Qt::WindowFlags flags)
197
0
{
198
0
    Q_UNUSED(flags);
199
0
}
200
201
/*!
202
    Returns if this window is exposed in the windowing system.
203
204
    An exposeEvent() is sent every time this value changes.
205
 */
206
207
bool QPlatformWindow::isExposed() const
208
0
{
209
0
    return window()->isVisible();
210
0
}
211
212
/*!
213
    Returns \c true if the window should appear active from a style perspective.
214
215
    This function can make platform-specific isActive checks, such as checking
216
    if the QWindow is embedded in an active native window.
217
*/
218
bool QPlatformWindow::isActive() const
219
0
{
220
0
    return false;
221
0
}
222
223
/*!
224
    Returns \c true if the window is an ancestor of the given \a child.
225
226
    Platform overrides should iterate the native window hierarchy of the child,
227
    to ensure that ancestary is reflected even with native windows in the window
228
    hierarchy.
229
*/
230
bool QPlatformWindow::isAncestorOf(const QPlatformWindow *child) const
231
0
{
232
0
    for (const QPlatformWindow *parent = child->parent(); parent; parent = parent->parent()) {
233
0
        if (parent == this)
234
0
            return true;
235
0
    }
236
237
0
    return false;
238
0
}
239
240
/*!
241
    Returns \c true if the window is a child of a non-Qt window.
242
243
    A embedded window has no parent platform window as reflected
244
    though parent(), but will have a native parent window.
245
*/
246
bool QPlatformWindow::isEmbedded() const
247
0
{
248
0
    return false;
249
0
}
250
251
/*!
252
    Translates the window coordinate \a pos to global screen
253
    coordinates using native methods. This is required for embedded windows,
254
    where the topmost QWindow coordinates are not global screen coordinates.
255
256
    Returns \a pos if there is no platform specific implementation.
257
*/
258
QPoint QPlatformWindow::mapToGlobal(const QPoint &pos) const
259
0
{
260
0
    const QPlatformWindow *p = this;
261
0
    QPoint result = pos;
262
0
    while (p) {
263
0
        result += p->geometry().topLeft();
264
0
        p = p->parent();
265
0
    }
266
0
    return result;
267
0
}
268
269
/*!
270
    Translates the global screen coordinate \a pos to window
271
    coordinates using native methods. This is required for embedded windows,
272
    where the topmost QWindow coordinates are not global screen coordinates.
273
274
    Returns \a pos if there is no platform specific implementation.
275
*/
276
QPoint QPlatformWindow::mapFromGlobal(const QPoint &pos) const
277
0
{
278
0
    const QPlatformWindow *p = this;
279
0
    QPoint result = pos;
280
0
    while (p) {
281
0
        result -= p->geometry().topLeft();
282
0
        p = p->parent();
283
0
    }
284
0
    return result;
285
0
}
286
287
/*!
288
    Requests setting the window state of this surface
289
    to \a type.
290
291
    Qt::WindowActive can be ignored.
292
*/
293
void QPlatformWindow::setWindowState(Qt::WindowStates)
294
0
{
295
0
}
296
297
/*!
298
  Reimplement in subclasses to return a handle to the native window
299
*/
300
WId QPlatformWindow::winId() const
301
0
{
302
    // Return anything but 0. Returning 0 would cause havoc with QWidgets on
303
    // very basic platform plugins that do not reimplement this function,
304
    // because the top-level widget's internalWinId() would always be 0 which
305
    // would mean top-levels are never treated as native.
306
0
    return WId(1);
307
0
}
308
309
//jl: It would be useful to have a property on the platform window which indicated if the sub-class
310
// supported the setParent. If not, then geometry would be in screen coordinates.
311
/*!
312
    This function is called to enable native child window in QPA. It is common not to support this
313
    feature in Window systems, but can be faked. When this function is called all geometry of this
314
    platform window will be relative to the parent.
315
*/
316
void QPlatformWindow::setParent(const QPlatformWindow *parent)
317
0
{
318
0
    Q_UNUSED(parent);
319
0
    qWarning("This plugin does not support setParent!");
320
0
}
321
322
/*!
323
  Reimplement to set the window title to \a title.
324
325
  The implementation might want to append the application display name to
326
  the window title, like Windows and Linux do.
327
328
  \sa QGuiApplication::applicationDisplayName()
329
*/
330
0
void QPlatformWindow::setWindowTitle(const QString &title) { Q_UNUSED(title); }
331
332
/*!
333
  Reimplement to set the window file path to \a filePath
334
*/
335
0
void QPlatformWindow::setWindowFilePath(const QString &filePath) { Q_UNUSED(filePath); }
336
337
/*!
338
  Reimplement to set the window icon to \a icon
339
*/
340
0
void QPlatformWindow::setWindowIcon(const QIcon &icon) { Q_UNUSED(icon); }
341
342
/*!
343
  Reimplement to let the platform handle non-spontaneous window close.
344
345
  When reimplementing make sure to call the base class implementation
346
  or QWindowSystemInterface::handleCloseEvent(), which will prompt the
347
  user to accept the window close (if needed) and then close the QWindow.
348
*/
349
bool QPlatformWindow::close()
350
0
{
351
0
    return QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::SynchronousDelivery>(window());
352
0
}
353
354
/*!
355
  Reimplement to be able to let Qt raise windows to the top of the desktop
356
*/
357
0
void QPlatformWindow::raise() { qWarning("This plugin does not support raise()"); }
358
359
/*!
360
  Reimplement to be able to let Qt lower windows to the bottom of the desktop
361
*/
362
0
void QPlatformWindow::lower() { qWarning("This plugin does not support lower()"); }
363
364
/*!
365
  Reimplement to propagate the size hints of the QWindow.
366
367
  The size hints include QWindow::minimumSize(), QWindow::maximumSize(),
368
  QWindow::sizeIncrement(), and QWindow::baseSize().
369
*/
370
0
void QPlatformWindow::propagateSizeHints() {qWarning("This plugin does not support propagateSizeHints()"); }
371
372
/*!
373
  Reimplement to be able to let Qt set the opacity level of a window
374
*/
375
void QPlatformWindow::setOpacity(qreal level)
376
0
{
377
0
    Q_UNUSED(level);
378
0
    qWarning("This plugin does not support setting window opacity");
379
0
}
380
381
/*!
382
  Reimplement to  be able to let Qt set the mask of a window
383
*/
384
385
void QPlatformWindow::setMask(const QRegion &region)
386
0
{
387
0
    Q_UNUSED(region);
388
0
    qWarning("This plugin does not support setting window masks");
389
0
}
390
391
/*!
392
  Reimplement to let Qt be able to request activation/focus for a window
393
394
  Some window systems will probably not have callbacks for this functionality,
395
  and then calling QWindowSystemInterface::handleWindowActivated(QWindow *w)
396
  would be sufficient.
397
398
  If the window system has some event handling/callbacks then call
399
  QWindowSystemInterface::handleWindowActivated(QWindow *w) when the window system
400
  gives the notification.
401
402
  Default implementation calls QWindowSystem::handleWindowActivated(QWindow *w)
403
*/
404
void QPlatformWindow::requestActivateWindow()
405
0
{
406
0
    QWindowSystemInterface::handleWindowActivated(window());
407
0
}
408
409
/*!
410
  Handle changes to the orientation of the platform window's contents.
411
412
  This is a hint to the window manager in case it needs to display
413
  additional content like popups, dialogs, status bars, or similar
414
  in relation to the window.
415
416
  \sa QWindow::reportContentOrientationChange()
417
*/
418
void QPlatformWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
419
0
{
420
0
    Q_UNUSED(orientation);
421
0
}
422
423
/*!
424
    Reimplement this function in subclass to return the device pixel ratio
425
    for the window. This is the ratio between physical pixels
426
    and device-independent pixels.
427
428
    \sa QPlatformWindow::devicePixelRatio();
429
*/
430
qreal QPlatformWindow::devicePixelRatio() const
431
0
{
432
0
    return 1.0;
433
0
}
434
435
bool QPlatformWindow::setKeyboardGrabEnabled(bool grab)
436
0
{
437
0
    Q_UNUSED(grab);
438
0
    qWarning("This plugin does not support grabbing the keyboard");
439
0
    return false;
440
0
}
441
442
bool QPlatformWindow::setMouseGrabEnabled(bool grab)
443
0
{
444
0
    Q_UNUSED(grab);
445
0
    qWarning("This plugin does not support grabbing the mouse");
446
0
    return false;
447
0
}
448
449
/*!
450
    Reimplement to be able to let Qt indicate that the window has been
451
    modified. Return true if the native window supports setting the modified
452
    flag, false otherwise.
453
*/
454
bool QPlatformWindow::setWindowModified(bool modified)
455
0
{
456
0
    Q_UNUSED(modified);
457
0
    return false;
458
0
}
459
460
/*!
461
    Reimplement this method to be able to do any platform specific event
462
    handling. All non-synthetic events for window() are passed to this
463
    function before being sent to QWindow::event().
464
465
    Return true if the event should not be passed on to the QWindow.
466
467
    Subclasses should always call the base class implementation.
468
*/
469
bool QPlatformWindow::windowEvent(QEvent *event)
470
0
{
471
0
    Q_D(QPlatformWindow);
472
473
0
    if (event->type() == QEvent::Timer) {
474
0
        if (static_cast<QTimerEvent *>(event)->timerId() == d->updateTimer.timerId()) {
475
0
            d->updateTimer.stop();
476
0
            deliverUpdateRequest();
477
0
            return true;
478
0
        }
479
0
    }
480
481
0
    return false;
482
0
}
483
484
/*!
485
    Reimplement this method to start a system resize operation if
486
    the system supports it and return true to indicate success.
487
488
    The default implementation is empty and does nothing with \a edges.
489
490
    \since 5.15
491
*/
492
493
bool QPlatformWindow::startSystemResize(Qt::Edges edges)
494
0
{
495
0
    Q_UNUSED(edges)
496
0
    return false;
497
0
}
498
499
/*!
500
    Reimplement this method to start a system move operation if
501
    the system supports it and return true to indicate success.
502
503
    The default implementation is empty and does nothing.
504
505
    \since 5.15
506
*/
507
508
bool QPlatformWindow::startSystemMove()
509
0
{
510
0
    return false;
511
0
}
512
513
/*!
514
    Reimplement this method to set whether frame strut events
515
    should be sent to \a enabled.
516
517
    \sa frameStrutEventsEnabled
518
*/
519
520
void QPlatformWindow::setFrameStrutEventsEnabled(bool enabled)
521
0
{
522
0
    Q_UNUSED(enabled) // Do not warn as widgets enable it by default causing warnings with XCB.
523
0
}
524
525
/*!
526
    Reimplement this method to return whether
527
    frame strut events are enabled.
528
*/
529
530
bool QPlatformWindow::frameStrutEventsEnabled() const
531
0
{
532
0
    return false;
533
0
}
534
535
/*!
536
    Call this method to put together a window title composed of
537
    \a title
538
    \a separator
539
    the application display name
540
541
    If the display name isn't set, and the title is empty, the raw app name is used.
542
*/
543
QString QPlatformWindow::formatWindowTitle(const QString &title, const QString &separator)
544
0
{
545
0
    QString fullTitle = title;
546
0
    if (QGuiApplicationPrivate::displayName && !title.endsWith(*QGuiApplicationPrivate::displayName)) {
547
        // Append display name, if set.
548
0
        if (!fullTitle.isEmpty())
549
0
            fullTitle += separator;
550
0
        fullTitle += *QGuiApplicationPrivate::displayName;
551
0
    } else if (fullTitle.isEmpty()) {
552
        // Don't let the window title be completely empty, use the app name as fallback.
553
0
        fullTitle = QCoreApplication::applicationName();
554
0
    }
555
0
    return fullTitle;
556
0
}
557
558
/*!
559
    Helper function for finding the new screen for \a newGeometry in response to
560
    a geometry changed event. Returns the new screen if the window was moved to
561
    another virtual sibling. If the screen changes, the platform plugin should call
562
    QWindowSystemInterface::handleWindowScreenChanged().
563
    \note: The current screen will always be returned for child windows since
564
    they should never signal screen changes.
565
566
    \since 5.4
567
    \sa QWindowSystemInterface::handleWindowScreenChanged()
568
*/
569
QPlatformScreen *QPlatformWindow::screenForGeometry(const QRect &newGeometry) const
570
0
{
571
0
    QPlatformScreen *currentScreen = screen();
572
0
    QPlatformScreen *fallback = currentScreen;
573
    // QRect::center can return a value outside the rectangle if it's empty.
574
    // Apply mapToGlobal() in case it is a foreign/embedded window.
575
0
    QPoint center = newGeometry.isEmpty() ? newGeometry.topLeft() : newGeometry.center();
576
0
    if (isForeignWindow())
577
0
        center = mapToGlobal(center - newGeometry.topLeft());
578
579
0
    if (!parent() && currentScreen && !currentScreen->geometry().contains(center)) {
580
0
        const auto screens = currentScreen->virtualSiblings();
581
0
        for (QPlatformScreen *screen : screens) {
582
0
            const QRect screenGeometry = screen->geometry();
583
0
            if (screenGeometry.contains(center))
584
0
                return screen;
585
0
            if (screenGeometry.intersects(newGeometry))
586
0
                fallback = screen;
587
0
        }
588
0
    }
589
0
    return fallback;
590
0
}
591
592
/*!
593
    Returns a size with both dimensions bounded to [0, QWINDOWSIZE_MAX]
594
*/
595
QSize QPlatformWindow::constrainWindowSize(const QSize &size)
596
0
{
597
0
    return size.expandedTo(QSize(0, 0)).boundedTo(QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX));
598
0
}
599
600
/*!
601
    Reimplement this method to set whether the window demands attention
602
    (for example, by flashing the taskbar icon) depending on \a enabled.
603
604
    \sa isAlertState()
605
    \since 5.1
606
*/
607
608
void QPlatformWindow::setAlertState(bool enable)
609
0
{
610
0
    Q_UNUSED(enable)
611
0
}
612
613
/*!
614
    Reimplement this method return whether the window is in
615
    an alert state.
616
617
    \sa setAlertState()
618
    \since 5.1
619
*/
620
621
bool QPlatformWindow::isAlertState() const
622
0
{
623
0
    return false;
624
0
}
625
626
// Return the effective screen for the initial geometry of a window. In a
627
// multimonitor-setup, try to find the right screen by checking the transient
628
// parent or the mouse cursor for parentless windows (cf QTBUG-34204,
629
// QDialog::adjustPosition()), unless a non-primary screen has been set,
630
// in which case we try to respect that.
631
static inline const QScreen *effectiveScreen(const QWindow *window)
632
0
{
633
0
    if (!window)
634
0
        return QGuiApplication::primaryScreen();
635
0
    const QScreen *screen = window->screen();
636
0
    if (!screen)
637
0
        return QGuiApplication::primaryScreen();
638
0
    if (screen != QGuiApplication::primaryScreen())
639
0
        return screen;
640
0
#ifndef QT_NO_CURSOR
641
0
    const QList<QScreen *> siblings = screen->virtualSiblings();
642
0
    if (siblings.size() > 1) {
643
0
        const QPoint referencePoint = window->transientParent() ? window->transientParent()->geometry().center() : QCursor::pos();
644
0
        for (const QScreen *sibling : siblings) {
645
0
            if (sibling->geometry().contains(referencePoint))
646
0
                return sibling;
647
0
        }
648
0
    }
649
0
#endif
650
0
    return screen;
651
0
}
652
653
/*!
654
    Invalidates the window's surface by releasing its surface buffers.
655
656
    Many platforms do not support releasing the surface memory,
657
    and the default implementation does nothing.
658
659
    The platform window is expected to recreate the surface again if
660
    it is needed. For instance, if an OpenGL context is made current
661
    on this window.
662
 */
663
void QPlatformWindow::invalidateSurface()
664
0
{
665
0
}
666
667
static QSize fixInitialSize(QSize size, const QWindow *w, int deviceIndependentDefaultWidth,
668
                            int deviceIndependentDefaultHeight)
669
0
{
670
0
    if (size.width() == 0) {
671
0
        const int minWidth = w->minimumWidth();
672
0
        size.setWidth(minWidth > 0 ? minWidth : deviceIndependentDefaultWidth);
673
0
    }
674
0
    if (size.height() == 0) {
675
0
        const int minHeight = w->minimumHeight();
676
0
        size.setHeight(minHeight > 0 ? minHeight : deviceIndependentDefaultHeight);
677
0
    }
678
0
    return size;
679
0
}
680
681
/*!
682
    Helper function to get initial geometry on windowing systems which do not
683
    do smart positioning and also do not provide a means of centering a
684
    transient window w.r.t. its parent. For example this is useful on Windows
685
    and MacOS but not X11, because an X11 window manager typically tries to
686
    layout new windows to optimize usage of the available desktop space.
687
    However if the given window already has geometry which the application has
688
    initialized, it takes priority.
689
690
    \a initialGeometry has to be provided in native pixels.
691
    \a defaultWidth has to be provided in device independent pixels
692
    \a defaultHeight has to be provided in device independent pixels
693
*/
694
QRect QPlatformWindow::initialGeometry(const QWindow *w, const QRect &initialGeometry,
695
                                       int defaultWidth, int defaultHeight,
696
                                       const QScreen **resultingScreenReturn)
697
0
{
698
0
    if (resultingScreenReturn)
699
0
        *resultingScreenReturn = w->screen();
700
0
    if (!w->isTopLevel()) {
701
0
        const qreal factor = QHighDpiScaling::factor(w);
702
0
        const QSize deviceIndependentSize =
703
0
                fixInitialSize(QHighDpi::fromNative(initialGeometry.size(), factor), w,
704
0
                               defaultWidth, defaultHeight);
705
0
        return QRect(initialGeometry.topLeft(), QHighDpi::toNative(deviceIndependentSize, factor));
706
0
    }
707
0
    const auto *wp = qt_window_private(const_cast<QWindow*>(w));
708
0
    const bool position = wp->positionAutomatic && w->type() != Qt::Popup;
709
0
    if (!position && !wp->resizeAutomatic)
710
0
        return initialGeometry;
711
0
    const QScreen *screen = wp->positionAutomatic
712
0
        ? effectiveScreen(w)
713
0
        : QGuiApplication::screenAt(initialGeometry.center());
714
0
    if (!screen)
715
0
        return initialGeometry;
716
0
    if (resultingScreenReturn)
717
0
        *resultingScreenReturn = screen;
718
    // initialGeometry refers to window's screen
719
0
    QRect deviceIndependentRect(QHighDpi::fromNativePixels(initialGeometry, w));
720
0
    if (wp->resizeAutomatic)
721
0
        deviceIndependentRect.setSize(
722
0
                fixInitialSize(deviceIndependentRect.size(), w, defaultWidth, defaultHeight));
723
0
    if (position) {
724
0
        const QRect availableDeviceIndependentGeometry = screen->availableGeometry();
725
        // Center unless the geometry ( + unknown window frame) is too large for the screen).
726
0
        if (deviceIndependentRect.height() < (availableDeviceIndependentGeometry.height() * 8) / 9
727
0
            && deviceIndependentRect.width()
728
0
                    < (availableDeviceIndependentGeometry.width() * 8) / 9) {
729
0
            const QWindow *tp = w->transientParent();
730
0
            if (tp) {
731
                // A transient window should be centered w.r.t. its transient parent.
732
0
                deviceIndependentRect.moveCenter(tp->geometry().center());
733
0
            } else {
734
                // Center the window on the screen.  (Only applicable on platforms
735
                // which do not provide a better way.)
736
0
                deviceIndependentRect.moveCenter(availableDeviceIndependentGeometry.center());
737
0
            }
738
0
        }
739
0
    }
740
0
    return QHighDpi::toNativePixels(deviceIndependentRect, screen);
741
0
}
742
743
/*!
744
    Requests an QEvent::UpdateRequest event. The event will be
745
    delivered to the QWindow.
746
747
    QPlatformWindow subclasses can re-implement this function to
748
    provide display refresh synchronized updates. The event
749
    should be delivered using QPlatformWindow::deliverUpdateRequest()
750
    to not get out of sync with the internal state of QWindow.
751
752
    The default implementation posts an UpdateRequest event to the
753
    window after 5 ms. The additional time is there to give the event
754
    loop a bit of idle time to gather system events.
755
756
*/
757
void QPlatformWindow::requestUpdate()
758
0
{
759
0
    Q_D(QPlatformWindow);
760
761
0
    static int updateInterval = []() {
762
0
        bool ok = false;
763
0
        int customUpdateInterval = qEnvironmentVariableIntValue("QT_QPA_UPDATE_IDLE_TIME", &ok);
764
0
        return ok ? customUpdateInterval : 5;
765
0
    }();
766
767
0
    Q_ASSERT(!d->updateTimer.isActive());
768
0
    d->updateTimer.start(updateInterval, Qt::PreciseTimer, window());
769
0
}
770
771
/*!
772
    Returns true if the window has a pending update request.
773
774
    \sa requestUpdate(), deliverUpdateRequest()
775
*/
776
bool QPlatformWindow::hasPendingUpdateRequest() const
777
0
{
778
0
    return qt_window_private(window())->updateRequestPending;
779
0
}
780
781
/*!
782
    Delivers an QEvent::UpdateRequest event to the window.
783
784
    QPlatformWindow subclasses can re-implement this function to
785
    provide e.g. logging or tracing of the delivery, but should
786
    always call the base class function.
787
*/
788
void QPlatformWindow::deliverUpdateRequest()
789
0
{
790
0
    Q_ASSERT(hasPendingUpdateRequest());
791
792
0
    QWindow *w = window();
793
0
    QWindowPrivate *wp = qt_window_private(w);
794
0
    wp->updateRequestPending = false;
795
0
    QEvent request(QEvent::UpdateRequest);
796
0
    QCoreApplication::sendEvent(w, &request);
797
0
}
798
799
/*!
800
    Returns the QWindow minimum size.
801
*/
802
QSize QPlatformWindow::windowMinimumSize() const
803
0
{
804
0
    return constrainWindowSize(QHighDpi::toNativePixels(window()->minimumSize(), window()));
805
0
}
806
807
/*!
808
    Returns the QWindow maximum size.
809
*/
810
QSize QPlatformWindow::windowMaximumSize() const
811
0
{
812
0
    return constrainWindowSize(QHighDpi::toNativePixels(window()->maximumSize(), window()));
813
0
}
814
815
/*!
816
    Returns the QWindow base size.
817
*/
818
QSize QPlatformWindow::windowBaseSize() const
819
0
{
820
0
    return QHighDpi::toNativePixels(window()->baseSize(), window());
821
0
}
822
823
/*!
824
    Returns the QWindow size increment.
825
*/
826
QSize QPlatformWindow::windowSizeIncrement() const
827
0
{
828
0
    QSize increment = window()->sizeIncrement();
829
0
    if (!QHighDpiScaling::isActive())
830
0
        return increment;
831
832
    // Normalize the increment. If not set the increment can be
833
    // (-1, -1) or (0, 0). Make that (1, 1) which is scalable.
834
0
    if (increment.isEmpty())
835
0
        increment = QSize(1, 1);
836
837
0
    return QHighDpi::toNativePixels(increment, window());
838
0
}
839
840
/*!
841
    Returns the QWindow geometry.
842
*/
843
QRect QPlatformWindow::windowGeometry() const
844
0
{
845
0
    return QHighDpi::toNativePixels(window()->geometry(), window());
846
0
}
847
848
/*!
849
    Returns the QWindow frame geometry.
850
*/
851
QRect QPlatformWindow::windowFrameGeometry() const
852
0
{
853
0
    return QHighDpi::toNativePixels(window()->frameGeometry(), window());
854
0
}
855
856
/*!
857
    Returns the closest acceptable geometry for a given geometry before
858
    a resize/move event for platforms that support it, for example to
859
    implement heightForWidth().
860
*/
861
862
QRectF QPlatformWindow::closestAcceptableGeometry(const QWindow *qWindow, const QRectF &nativeRect)
863
0
{
864
0
    const QRectF rectF = QHighDpi::fromNativePixels(nativeRect, qWindow);
865
0
    const QRectF correctedGeometryF = qt_window_private(const_cast<QWindow *>(qWindow))->closestAcceptableGeometry(rectF);
866
0
    return !correctedGeometryF.isEmpty() && rectF != correctedGeometryF
867
0
        ? QHighDpi::toNativePixels(correctedGeometryF, qWindow) : nativeRect;
868
0
}
869
870
QRectF QPlatformWindow::windowClosestAcceptableGeometry(const QRectF &nativeRect) const
871
0
{
872
0
    return QPlatformWindow::closestAcceptableGeometry(window(), nativeRect);
873
0
}
874
875
/*!
876
    \class QPlatformWindow
877
    \since 4.8
878
    \internal
879
    \preliminary
880
    \ingroup qpa
881
882
    \brief The QPlatformWindow class provides an abstraction for top-level windows.
883
884
    The QPlatformWindow abstraction is used by QWindow for all its top level windows. It is being
885
    created by calling the createPlatformWindow function in the loaded QPlatformIntegration
886
    instance.
887
888
    QPlatformWindow is used to signal to the windowing system, how Qt perceives its frame.
889
    However, it is not concerned with how Qt renders into the window it represents.
890
891
    Visible QWindows will always have a QPlatformWindow. However, it is not necessary for
892
    all windows to have a QBackingStore. This is the case for QOpenGLWindow. And could be the case for
893
    windows where some third party renders into it.
894
895
    The platform specific window handle can be retrieved by the winId function.
896
897
    QPlatformWindow is also the way QPA defines how native child windows should be supported
898
    through the setParent function.
899
900
    \section1 Implementation Aspects
901
902
    \list 1
903
        \li Mouse grab: Qt expects windows to automatically grab the mouse if the user presses
904
            a button until the button is released.
905
            Automatic grab should be released if some window is explicitly grabbed.
906
        \li Enter/Leave events: If there is a window explicitly grabbing mouse events
907
            (\c{setMouseGrabEnabled()}), enter and leave events should only be sent to the
908
            grabbing window when mouse cursor passes over the grabbing window boundary.
909
            Other windows will not receive enter or leave events while the grab is active.
910
            While an automatic mouse grab caused by a mouse button press is active, no window
911
            will receive enter or leave events. When the last mouse button is released, the
912
            autograbbing window will receive leave event if mouse cursor is no longer within
913
            the window boundary.
914
            When any grab starts, the window under cursor will receive a leave event unless
915
            it is the grabbing window.
916
            When any grab ends, the window under cursor will receive an enter event unless it
917
            was the grabbing window.
918
        \li Window positioning: When calling \c{QWindow::setFramePosition()}, the flag
919
            \c{QWindowPrivate::positionPolicy} is set to \c{QWindowPrivate::WindowFrameInclusive}.
920
            This means the position includes the window frame, whose size is at this point
921
            unknown and the geometry's topleft point is the position of the window frame.
922
    \endlist
923
924
    Apart from the auto-tests (\c{tests/auto/gui/kernel/qwindow},
925
    \c{tests/auto/gui/kernel/qguiapplication} and \c{tests/auto/widgets/kernel/qwidget}),
926
    there are a number of manual tests and examples that can help testing a platform plugin:
927
928
    \list 1
929
        \li \c{examples/qpa/windows}: Basic \c{QWindow} creation.
930
        \li \c{examples/opengl/hellowindow}: Basic Open GL windows.
931
        \li \c{tests/manual/windowflags}: Tests setting the window flags.
932
        \li \c{tests/manual/windowgeometry} Tests setting the window geometry.
933
        \li \c{tests/manual/windowmodality} Tests setting the window modality.
934
        \li \c{tests/manual/widgetgrab} Tests mouse grab and dialogs.
935
    \endlist
936
937
    \sa QBackingStore, QWindow
938
*/
939
940
QT_END_NAMESPACE