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