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
4#include "qplatformwindow.h"
5#include "qplatformwindow_p.h"
6#include "qplatformscreen.h"
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
16QT_BEGIN_NAMESPACE
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(value: window->geometry(), context: 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.
136*/
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: window(), region: 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(pos: 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(pos: 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(msg: "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 \sa QGuiApplication::applicationDisplayName()
307*/
308void QPlatformWindow::setWindowTitle(const QString &title) { Q_UNUSED(title); }
309
310/*!
311 Reimplement to set the window file path to \a filePath
312*/
313void QPlatformWindow::setWindowFilePath(const QString &filePath) { Q_UNUSED(filePath); }
314
315/*!
316 Reimplement to set the window icon to \a icon
317*/
318void QPlatformWindow::setWindowIcon(const QIcon &icon) { Q_UNUSED(icon); }
319
320/*!
321 Reimplement to let the platform handle non-spontaneous window close.
322
323 When reimplementing make sure to call the base class implementation
324 or QWindowSystemInterface::handleCloseEvent(), which will prompt the
325 user to accept the window close (if needed) and then close the QWindow.
326*/
327bool QPlatformWindow::close()
328{
329 return QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::SynchronousDelivery>(window: window());
330}
331
332/*!
333 Reimplement to be able to let Qt raise windows to the top of the desktop
334*/
335void QPlatformWindow::raise() { qWarning(msg: "This plugin does not support raise()"); }
336
337/*!
338 Reimplement to be able to let Qt lower windows to the bottom of the desktop
339*/
340void QPlatformWindow::lower() { qWarning(msg: "This plugin does not support lower()"); }
341
342/*!
343 Reimplement to propagate the size hints of the QWindow.
344
345 The size hints include QWindow::minimumSize(), QWindow::maximumSize(),
346 QWindow::sizeIncrement(), and QWindow::baseSize().
347*/
348void QPlatformWindow::propagateSizeHints() {qWarning(msg: "This plugin does not support propagateSizeHints()"); }
349
350/*!
351 Reimplement to be able to let Qt set the opacity level of a window
352*/
353void QPlatformWindow::setOpacity(qreal level)
354{
355 Q_UNUSED(level);
356 qWarning(msg: "This plugin does not support setting window opacity");
357}
358
359/*!
360 Reimplement to be able to let Qt set the mask of a window
361*/
362
363void QPlatformWindow::setMask(const QRegion &region)
364{
365 Q_UNUSED(region);
366 qWarning(msg: "This plugin does not support setting window masks");
367}
368
369/*!
370 Reimplement to let Qt be able to request activation/focus for a window
371
372 Some window systems will probably not have callbacks for this functionality,
373 and then calling QWindowSystemInterface::handleWindowActivated(QWindow *w)
374 would be sufficient.
375
376 If the window system has some event handling/callbacks then call
377 QWindowSystemInterface::handleWindowActivated(QWindow *w) when the window system
378 gives the notification.
379
380 Default implementation calls QWindowSystem::handleWindowActivated(QWindow *w)
381*/
382void QPlatformWindow::requestActivateWindow()
383{
384 QWindowSystemInterface::handleWindowActivated(window: window());
385}
386
387/*!
388 Handle changes to the orientation of the platform window's contents.
389
390 This is a hint to the window manager in case it needs to display
391 additional content like popups, dialogs, status bars, or similar
392 in relation to the window.
393
394 \sa QWindow::reportContentOrientationChange()
395*/
396void QPlatformWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
397{
398 Q_UNUSED(orientation);
399}
400
401/*!
402 Reimplement this function in subclass to return the device pixel ratio
403 for the window. This is the ratio between physical pixels
404 and device-independent pixels.
405
406 \sa QPlatformWindow::devicePixelRatio();
407*/
408qreal QPlatformWindow::devicePixelRatio() const
409{
410 return 1.0;
411}
412
413bool QPlatformWindow::setKeyboardGrabEnabled(bool grab)
414{
415 Q_UNUSED(grab);
416 qWarning(msg: "This plugin does not support grabbing the keyboard");
417 return false;
418}
419
420bool QPlatformWindow::setMouseGrabEnabled(bool grab)
421{
422 Q_UNUSED(grab);
423 qWarning(msg: "This plugin does not support grabbing the mouse");
424 return false;
425}
426
427/*!
428 Reimplement to be able to let Qt indicate that the window has been
429 modified. Return true if the native window supports setting the modified
430 flag, false otherwise.
431*/
432bool QPlatformWindow::setWindowModified(bool modified)
433{
434 Q_UNUSED(modified);
435 return false;
436}
437
438/*!
439 Reimplement this method to be able to do any platform specific event
440 handling. All non-synthetic events for window() are passed to this
441 function before being sent to QWindow::event().
442
443 Return true if the event should not be passed on to the QWindow.
444
445 Subclasses should always call the base class implementation.
446*/
447bool QPlatformWindow::windowEvent(QEvent *event)
448{
449 Q_D(QPlatformWindow);
450
451 if (event->type() == QEvent::Timer) {
452 if (static_cast<QTimerEvent *>(event)->timerId() == d->updateTimer.timerId()) {
453 d->updateTimer.stop();
454 deliverUpdateRequest();
455 return true;
456 }
457 }
458
459 return false;
460}
461
462/*!
463 Reimplement this method to start a system resize operation if
464 the system supports it and return true to indicate success.
465
466 The default implementation is empty and does nothing with \a edges.
467
468 \since 5.15
469*/
470
471bool QPlatformWindow::startSystemResize(Qt::Edges edges)
472{
473 Q_UNUSED(edges);
474 return false;
475}
476
477/*!
478 Reimplement this method to start a system move operation if
479 the system supports it and return true to indicate success.
480
481 The default implementation is empty and does nothing.
482
483 \since 5.15
484*/
485
486bool QPlatformWindow::startSystemMove()
487{
488 return false;
489}
490
491/*!
492 Reimplement this method to set whether frame strut events
493 should be sent to \a enabled.
494
495 \sa frameStrutEventsEnabled
496*/
497
498void QPlatformWindow::setFrameStrutEventsEnabled(bool enabled)
499{
500 Q_UNUSED(enabled); // Do not warn as widgets enable it by default causing warnings with XCB.
501}
502
503/*!
504 Reimplement this method to return whether
505 frame strut events are enabled.
506*/
507
508bool QPlatformWindow::frameStrutEventsEnabled() const
509{
510 return false;
511}
512
513/*!
514 Call this method to put together a window title composed of
515 \a title
516 \a separator
517 the application display name
518
519 If the display name isn't set, and the title is empty, the raw app name is used.
520*/
521QString QPlatformWindow::formatWindowTitle(const QString &title, const QString &separator)
522{
523 QString fullTitle = title;
524 if (QGuiApplicationPrivate::displayName && !title.endsWith(s: *QGuiApplicationPrivate::displayName)) {
525 // Append display name, if set.
526 if (!fullTitle.isEmpty())
527 fullTitle += separator;
528 fullTitle += *QGuiApplicationPrivate::displayName;
529 } else if (fullTitle.isEmpty()) {
530 // Don't let the window title be completely empty, use the app name as fallback.
531 fullTitle = QCoreApplication::applicationName();
532 }
533 return fullTitle;
534}
535
536/*!
537 Helper function for finding the new screen for \a newGeometry in response to
538 a geometry changed event. Returns the new screen if the window was moved to
539 another virtual sibling. If the screen changes, the platform plugin should call
540 QWindowSystemInterface::handleWindowScreenChanged().
541 \note: The current screen will always be returned for child windows since
542 they should never signal screen changes.
543
544 \since 5.4
545 \sa QWindowSystemInterface::handleWindowScreenChanged()
546*/
547QPlatformScreen *QPlatformWindow::screenForGeometry(const QRect &newGeometry) const
548{
549 QPlatformScreen *currentScreen = screen();
550 QPlatformScreen *fallback = currentScreen;
551 // QRect::center can return a value outside the rectangle if it's empty.
552 // Apply mapToGlobal() in case it is a foreign/embedded window.
553 QPoint center = newGeometry.isEmpty() ? newGeometry.topLeft() : newGeometry.center();
554 if (isForeignWindow())
555 center = mapToGlobal(pos: center - newGeometry.topLeft());
556
557 if (!parent() && currentScreen && !currentScreen->geometry().contains(p: center)) {
558 const auto screens = currentScreen->virtualSiblings();
559 for (QPlatformScreen *screen : screens) {
560 const QRect screenGeometry = screen->geometry();
561 if (screenGeometry.contains(p: center))
562 return screen;
563 if (screenGeometry.intersects(r: newGeometry))
564 fallback = screen;
565 }
566 }
567 return fallback;
568}
569
570/*!
571 Returns a size with both dimensions bounded to [0, QWINDOWSIZE_MAX]
572*/
573QSize QPlatformWindow::constrainWindowSize(const QSize &size)
574{
575 return size.expandedTo(otherSize: QSize(0, 0)).boundedTo(otherSize: QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX));
576}
577
578/*!
579 Reimplement this method to set whether the window demands attention
580 (for example, by flashing the taskbar icon) depending on \a enabled.
581
582 \sa isAlertState()
583 \since 5.1
584*/
585
586void QPlatformWindow::setAlertState(bool enable)
587{
588 Q_UNUSED(enable);
589}
590
591/*!
592 Reimplement this method return whether the window is in
593 an alert state.
594
595 \sa setAlertState()
596 \since 5.1
597*/
598
599bool QPlatformWindow::isAlertState() const
600{
601 return false;
602}
603
604// Return the effective screen for the initial geometry of a window. In a
605// multimonitor-setup, try to find the right screen by checking the transient
606// parent or the mouse cursor for parentless windows (cf QTBUG-34204,
607// QDialog::adjustPosition()), unless a non-primary screen has been set,
608// in which case we try to respect that.
609static inline const QScreen *effectiveScreen(const QWindow *window)
610{
611 if (!window)
612 return QGuiApplication::primaryScreen();
613 const QScreen *screen = window->screen();
614 if (!screen)
615 return QGuiApplication::primaryScreen();
616 if (screen != QGuiApplication::primaryScreen())
617 return screen;
618#ifndef QT_NO_CURSOR
619 const QList<QScreen *> siblings = screen->virtualSiblings();
620 if (siblings.size() > 1) {
621 const QPoint referencePoint = window->transientParent() ? window->transientParent()->geometry().center() : QCursor::pos();
622 for (const QScreen *sibling : siblings) {
623 if (sibling->geometry().contains(p: referencePoint))
624 return sibling;
625 }
626 }
627#endif
628 return screen;
629}
630
631/*!
632 Invalidates the window's surface by releasing its surface buffers.
633
634 Many platforms do not support releasing the surface memory,
635 and the default implementation does nothing.
636
637 The platform window is expected to recreate the surface again if
638 it is needed. For instance, if an OpenGL context is made current
639 on this window.
640 */
641void QPlatformWindow::invalidateSurface()
642{
643}
644
645static QSize fixInitialSize(QSize size, const QWindow *w, int deviceIndependentDefaultWidth,
646 int deviceIndependentDefaultHeight)
647{
648 if (size.width() == 0) {
649 const int minWidth = w->minimumWidth();
650 size.setWidth(minWidth > 0 ? minWidth : deviceIndependentDefaultWidth);
651 }
652 if (size.height() == 0) {
653 const int minHeight = w->minimumHeight();
654 size.setHeight(minHeight > 0 ? minHeight : deviceIndependentDefaultHeight);
655 }
656 return size;
657}
658
659/*!
660 Helper function to get initial geometry on windowing systems which do not
661 do smart positioning and also do not provide a means of centering a
662 transient window w.r.t. its parent. For example this is useful on Windows
663 and MacOS but not X11, because an X11 window manager typically tries to
664 layout new windows to optimize usage of the available desktop space.
665 However if the given window already has geometry which the application has
666 initialized, it takes priority.
667
668 \a initialGeometry has to be provided in native pixels.
669 \a defaultWidth has to be provided in device independent pixels
670 \a defaultHeight has to be provided in device independent pixels
671*/
672QRect QPlatformWindow::initialGeometry(const QWindow *w, const QRect &initialGeometry,
673 int defaultWidth, int defaultHeight,
674 const QScreen **resultingScreenReturn)
675{
676 if (resultingScreenReturn)
677 *resultingScreenReturn = w->screen();
678 if (!w->isTopLevel()) {
679 const qreal factor = QHighDpiScaling::factor(context: w);
680 const QSize deviceIndependentSize =
681 fixInitialSize(size: QHighDpi::fromNative(value: initialGeometry.size(), scaleFactor: factor), w,
682 deviceIndependentDefaultWidth: defaultWidth, deviceIndependentDefaultHeight: defaultHeight);
683 return QRect(initialGeometry.topLeft(), QHighDpi::toNative(value: deviceIndependentSize, scaleFactor: factor));
684 }
685 const auto *wp = qt_window_private(window: const_cast<QWindow*>(w));
686 const bool position = wp->positionAutomatic && w->type() != Qt::Popup;
687 if (!position && !wp->resizeAutomatic)
688 return initialGeometry;
689 const QScreen *screen = wp->positionAutomatic
690 ? effectiveScreen(window: w)
691 : QGuiApplication::screenAt(point: initialGeometry.center());
692 if (!screen)
693 return initialGeometry;
694 if (resultingScreenReturn)
695 *resultingScreenReturn = screen;
696 // initialGeometry refers to window's screen
697 QRect deviceIndependentRect(QHighDpi::fromNativePixels(value: initialGeometry, context: w));
698 if (wp->resizeAutomatic)
699 deviceIndependentRect.setSize(
700 fixInitialSize(size: deviceIndependentRect.size(), w, deviceIndependentDefaultWidth: defaultWidth, deviceIndependentDefaultHeight: defaultHeight));
701 if (position) {
702 const QRect availableDeviceIndependentGeometry = screen->availableGeometry();
703 // Center unless the geometry ( + unknown window frame) is too large for the screen).
704 if (deviceIndependentRect.height() < (availableDeviceIndependentGeometry.height() * 8) / 9
705 && deviceIndependentRect.width()
706 < (availableDeviceIndependentGeometry.width() * 8) / 9) {
707 const QWindow *tp = w->transientParent();
708 if (tp) {
709 // A transient window should be centered w.r.t. its transient parent.
710 deviceIndependentRect.moveCenter(p: tp->geometry().center());
711 } else {
712 // Center the window on the screen. (Only applicable on platforms
713 // which do not provide a better way.)
714 deviceIndependentRect.moveCenter(p: availableDeviceIndependentGeometry.center());
715 }
716 }
717 }
718 return QHighDpi::toNativePixels(value: deviceIndependentRect, context: screen);
719}
720
721/*!
722 Requests an QEvent::UpdateRequest event. The event will be
723 delivered to the QWindow.
724
725 QPlatformWindow subclasses can re-implement this function to
726 provide display refresh synchronized updates. The event
727 should be delivered using QPlatformWindow::deliverUpdateRequest()
728 to not get out of sync with the internal state of QWindow.
729
730 The default implementation posts an UpdateRequest event to the window after
731 an interval that is at most 5 ms. If the window's associated screen reports
732 a \l{QPlatformScreen::refreshRate()}{refresh rate} higher than 60 Hz, the
733 interval is scaled down to a valid smaller than 5. The additional time is
734 there to give the event loop a bit of idle time to gather system events.
735
736*/
737void QPlatformWindow::requestUpdate()
738{
739 Q_D(QPlatformWindow);
740
741 static bool customUpdateIntervalValid = false;
742 static int customUpdateInterval = qEnvironmentVariableIntValue(varName: "QT_QPA_UPDATE_IDLE_TIME",
743 ok: &customUpdateIntervalValid);
744 int updateInterval = customUpdateInterval;
745 if (!customUpdateIntervalValid) {
746 updateInterval = 5;
747 if (QPlatformScreen *currentScreen = screen()) {
748 const qreal refreshRate = currentScreen->refreshRate();
749 if (refreshRate > 60.0)
750 updateInterval /= refreshRate / 60.0;
751 }
752 }
753
754 Q_ASSERT(!d->updateTimer.isActive());
755 d->updateTimer.start(msec: updateInterval, t: Qt::PreciseTimer, obj: window());
756}
757
758/*!
759 Returns true if the window has a pending update request.
760
761 \sa requestUpdate(), deliverUpdateRequest()
762*/
763bool QPlatformWindow::hasPendingUpdateRequest() const
764{
765 return qt_window_private(window: window())->updateRequestPending;
766}
767
768/*!
769 Delivers an QEvent::UpdateRequest event to the window.
770
771 QPlatformWindow subclasses can re-implement this function to
772 provide e.g. logging or tracing of the delivery, but should
773 always call the base class function.
774*/
775void QPlatformWindow::deliverUpdateRequest()
776{
777 Q_ASSERT(hasPendingUpdateRequest());
778
779 QWindow *w = window();
780 QWindowPrivate *wp = qt_window_private(window: w);
781 wp->updateRequestPending = false;
782 QEvent request(QEvent::UpdateRequest);
783 QCoreApplication::sendEvent(receiver: w, event: &request);
784}
785
786/*!
787 Returns the QWindow minimum size.
788*/
789QSize QPlatformWindow::windowMinimumSize() const
790{
791 return constrainWindowSize(size: QHighDpi::toNativePixels(value: window()->minimumSize(), context: window()));
792}
793
794/*!
795 Returns the QWindow maximum size.
796*/
797QSize QPlatformWindow::windowMaximumSize() const
798{
799 return constrainWindowSize(size: QHighDpi::toNativePixels(value: window()->maximumSize(), context: window()));
800}
801
802/*!
803 Returns the QWindow base size.
804*/
805QSize QPlatformWindow::windowBaseSize() const
806{
807 return QHighDpi::toNativePixels(value: window()->baseSize(), context: window());
808}
809
810/*!
811 Returns the QWindow size increment.
812*/
813QSize QPlatformWindow::windowSizeIncrement() const
814{
815 QSize increment = window()->sizeIncrement();
816 if (!QHighDpiScaling::isActive())
817 return increment;
818
819 // Normalize the increment. If not set the increment can be
820 // (-1, -1) or (0, 0). Make that (1, 1) which is scalable.
821 if (increment.isEmpty())
822 increment = QSize(1, 1);
823
824 return QHighDpi::toNativePixels(value: increment, context: window());
825}
826
827/*!
828 Returns the QWindow geometry.
829*/
830QRect QPlatformWindow::windowGeometry() const
831{
832 return QHighDpi::toNativeWindowGeometry(value: window()->geometry(), context: window());
833}
834
835/*!
836 Returns the QWindow frame geometry.
837*/
838QRect QPlatformWindow::windowFrameGeometry() const
839{
840 return QHighDpi::toNativeWindowGeometry(value: window()->frameGeometry(), context: window());
841}
842
843/*!
844 Returns the closest acceptable geometry for a given geometry before
845 a resize/move event for platforms that support it, for example to
846 implement heightForWidth().
847*/
848
849QRectF QPlatformWindow::closestAcceptableGeometry(const QWindow *qWindow, const QRectF &nativeRect)
850{
851 const QRectF rectF = QHighDpi::fromNativeWindowGeometry(value: nativeRect, context: qWindow);
852 const QRectF correctedGeometryF = qt_window_private(window: const_cast<QWindow *>(qWindow))->closestAcceptableGeometry(rect: rectF);
853 return !correctedGeometryF.isEmpty() && rectF != correctedGeometryF
854 ? QHighDpi::toNativeWindowGeometry(value: correctedGeometryF, context: qWindow) : nativeRect;
855}
856
857QRectF QPlatformWindow::windowClosestAcceptableGeometry(const QRectF &nativeRect) const
858{
859 return QPlatformWindow::closestAcceptableGeometry(qWindow: window(), nativeRect);
860}
861
862/*!
863 \class QPlatformWindow
864 \since 4.8
865 \internal
866 \preliminary
867 \ingroup qpa
868
869 \brief The QPlatformWindow class provides an abstraction for top-level windows.
870
871 The QPlatformWindow abstraction is used by QWindow for all its top level windows. It is being
872 created by calling the createPlatformWindow function in the loaded QPlatformIntegration
873 instance.
874
875 QPlatformWindow is used to signal to the windowing system, how Qt perceives its frame.
876 However, it is not concerned with how Qt renders into the window it represents.
877
878 Visible QWindows will always have a QPlatformWindow. However, it is not necessary for
879 all windows to have a QBackingStore. This is the case for QOpenGLWindow. And could be the case for
880 windows where some third party renders into it.
881
882 The platform specific window handle can be retrieved by the winId function.
883
884 QPlatformWindow is also the way QPA defines how native child windows should be supported
885 through the setParent function.
886
887 \section1 Implementation Aspects
888
889 \list 1
890 \li Mouse grab: Qt expects windows to automatically grab the mouse if the user presses
891 a button until the button is released.
892 Automatic grab should be released if some window is explicitly grabbed.
893 \li Enter/Leave events: If there is a window explicitly grabbing mouse events
894 (\c{setMouseGrabEnabled()}), enter and leave events should only be sent to the
895 grabbing window when mouse cursor passes over the grabbing window boundary.
896 Other windows will not receive enter or leave events while the grab is active.
897 While an automatic mouse grab caused by a mouse button press is active, no window
898 will receive enter or leave events. When the last mouse button is released, the
899 autograbbing window will receive leave event if mouse cursor is no longer within
900 the window boundary.
901 When any grab starts, the window under cursor will receive a leave event unless
902 it is the grabbing window.
903 When any grab ends, the window under cursor will receive an enter event unless it
904 was the grabbing window.
905 \li Window positioning: When calling \c{QWindow::setFramePosition()}, the flag
906 \c{QWindowPrivate::positionPolicy} is set to \c{QWindowPrivate::WindowFrameInclusive}.
907 This means the position includes the window frame, whose size is at this point
908 unknown and the geometry's topleft point is the position of the window frame.
909 \endlist
910
911 Apart from the auto-tests (\c{tests/auto/gui/kernel/qwindow},
912 \c{tests/auto/gui/kernel/qguiapplication} and \c{tests/auto/widgets/kernel/qwidget}),
913 there are a number of manual tests and examples that can help testing a platform plugin:
914
915 \list 1
916 \li \c{examples/qpa/windows}: Basic \c{QWindow} creation.
917 \li \c{examples/opengl/hellowindow}: Basic Open GL windows.
918 \li \c{tests/manual/windowflags}: Tests setting the window flags.
919 \li \c{tests/manual/windowgeometry} Tests setting the window geometry.
920 \li \c{tests/manual/windowmodality} Tests setting the window modality.
921 \li \c{tests/manual/widgetgrab} Tests mouse grab and dialogs.
922 \endlist
923
924 \sa QBackingStore, QWindow
925*/
926
927QT_END_NAMESPACE
928

source code of qtbase/src/gui/kernel/qplatformwindow.cpp