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