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
qquickpopupwindow.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 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
6#if QT_CONFIG(quicktemplates2_container)
7#include "qquickdialog_p.h"
8#endif
11
12#include "qquickmenu_p_p.h"
13#if QT_CONFIG(quicktemplates2_container)
14#include "qquickmenubar_p_p.h"
15#endif
16
18#include <QtGui/private/qguiapplication_p.h>
19
20#include <QtCore/qloggingcategory.h>
21#include <QtGui/private/qeventpoint_p.h>
22#include <QtQuick/private/qquickitem_p.h>
23#include <QtQuick/private/qquickwindowmodule_p.h>
24#include <QtQuick/private/qquickwindowmodule_p_p.h>
25#include <qpa/qplatformwindow_p.h>
26
28
29Q_STATIC_LOGGING_CATEGORY(lcPopupWindow, "qt.quick.controls.popup.window")
30
31static bool s_popupGrabOk = false;
33
35{
36 Q_DECLARE_PUBLIC(QQuickPopupWindow)
37
38public:
42 bool m_inHideEvent = false;
43
44protected:
45 void setVisible(bool visible) override;
46
47public:
49
50private:
51 bool filterPopupSpecialCases(QEvent *event);
52};
53
54QQuickPopupWindow::QQuickPopupWindow(QQuickPopup *popup, QWindow *parent)
55 : QQuickWindowQmlImpl(*(new QQuickPopupWindowPrivate), nullptr)
56{
57 Q_D(QQuickPopupWindow);
58
59 d->m_popup = popup;
60 d->m_popupItem = popup->popupItem();
61 setTransientParent(parent);
62
63 connect(d->m_popup, &QQuickPopup::windowChanged, this, &QQuickPopupWindow::windowChanged);
64 connect(d->m_popup, &QQuickPopup::implicitWidthChanged, this, &QQuickPopupWindow::implicitWidthChanged);
65 connect(d->m_popup, &QQuickPopup::implicitHeightChanged, this, &QQuickPopupWindow::implicitHeightChanged);
66 if (QQuickWindow *nearestParentItemWindow = d->m_popup->window()) {
67 d->m_popupParentItemWindow = nearestParentItemWindow;
68 connect(d->m_popupParentItemWindow, &QWindow::xChanged, this, &QQuickPopupWindow::parentWindowXChanged);
69 connect(d->m_popupParentItemWindow, &QWindow::yChanged, this, &QQuickPopupWindow::parentWindowYChanged);
70 }
71 setWidth(d->m_popupItem->implicitWidth());
72 setHeight(d->m_popupItem->implicitHeight());
73
74 const auto flags = QQuickPopupPrivate::get(popup)->popupWindowFlags();
75
76 // For popup windows, we'll need to draw everything, in order to have enough control over the styling.
77 if (flags & Qt::Popup)
78 setColor(QColorConstants::Transparent);
79
80 setFlags(flags);
81
82 qCDebug(lcPopupWindow) << "Created popup window" << this << "with parent" << parent;
83}
84
85QQuickPopup *QQuickPopupWindow::popup() const
86{
87 Q_D(const QQuickPopupWindow);
88 return d->m_popup;
89}
90
91void QQuickPopupWindow::hideEvent(QHideEvent *e)
92{
93 Q_D(QQuickPopupWindow);
94 QQuickWindow::hideEvent(e);
95 // Avoid potential infinite recursion, between QWindowPrivate::setVisible(false) and this function.
96 QScopedValueRollback<bool>inHideEventRollback(d->m_inHideEvent, true);
97 if (d->transientParentIsGoingAway())
98 return;
99
100 if (QQuickPopup *popup = d->m_popup) {
101#if QT_CONFIG(quicktemplates2_container)
102 QQuickDialog *dialog = qobject_cast<QQuickDialog *>(popup);
103 if (dialog && QQuickPopupPrivate::get(dialog)->visible)
104 dialog->reject();
105 else
106#endif
107 popup->setVisible(false);
108 }
109}
110
111void QQuickPopupWindow::moveEvent(QMoveEvent *e)
112{
113 handlePopupPositionChangeFromWindowSystem(e->pos());
114}
115
116void QQuickPopupWindow::resizeEvent(QResizeEvent *e)
117{
118 Q_D(QQuickPopupWindow);
119 QQuickWindowQmlImpl::resizeEvent(e);
120
121 if (!d->m_popupItem)
122 return;
123
124 qCDebug(lcPopupWindow).nospace() << "A window system event changed the popup's ("
125 << d->m_popup << ") size to " << e->size();
126 QQuickPopupPrivate *popupPrivate = QQuickPopupPrivate::get(d->m_popup);
127
128 const auto topLeftFromSystem = global2Local(d->geometry.topLeft());
129 // We need to use the current topLeft position here, so that reposition()
130 // does not move the window
131 const auto oldX = popupPrivate->x;
132 const auto oldY = popupPrivate->y;
133
134 if (Q_LIKELY(topLeftFromSystem)) {
135 popupPrivate->x = topLeftFromSystem->x();
136 popupPrivate->y = topLeftFromSystem->y();
137 }
138
139 const QMarginsF windowInsets = popupPrivate->windowInsets();
140 d->m_popupItem->setWidth(e->size().width() - windowInsets.left() - windowInsets.right());
141 d->m_popupItem->setHeight(e->size().height() - windowInsets.top() - windowInsets.bottom());
142
143 // and restore the actual x and y afterwards
144 popupPrivate->x = oldX;
145 popupPrivate->y = oldY;
146}
147
149{
150 Q_Q(const QQuickPopupWindow);
151 QWindow *transientParent = q->transientParent();
152 if (!transientParent)
153 return true;
154
155 auto *quickWindow = qobject_cast<QQuickWindow *>(transientParent);
156 return quickWindow && QQuickWindowPrivate::get(quickWindow)->inDestructor;
157}
158
160{
161 if (m_inHideEvent)
162 return;
163
164 // Showing is pointless once the transient parent is going away, but hiding
165 // must never be skipped: it is the base implementation that updates the
166 // visible state and sends the hide event, and the hide event is what makes
167 // QSGThreadedRenderLoop stop rendering into this window. Skipping it leaves
168 // the render thread believing the window is still exposed, so it re-creates
169 // a swapchain for a window that is about to lose its platform window, and
170 // that swapchain is then leaked. (QTBUG-149041)
171 if (visible && transientParentIsGoingAway())
172 return;
173
174 const bool visibleChanged = QWindowPrivate::visible != visible;
175
176 // Check if we're about to close the last popup, in which case, ungrab.
177 if (!visible && visibleChanged && QGuiApplicationPrivate::popupCount() == 1 && s_grabbedWindow) {
178 s_grabbedWindow->setMouseGrabEnabled(false);
179 s_grabbedWindow->setKeyboardGrabEnabled(false);
180 s_popupGrabOk = false;
181 qCDebug(lcPopupWindow) << "The window " << s_grabbedWindow << "has disabled global mouse and keyboard grabs.";
182 s_grabbedWindow = nullptr;
183 }
184
185#if QT_CONFIG(wayland)
186 Q_Q(QQuickPopupWindow);
187 // The parent control geoemtry is used by the wayland compositor when flipping menus and comboboxes.
188 if (auto waylandWindow = dynamic_cast<QNativeInterface::Private::QWaylandWindow *>(platformWindow); waylandWindow && visible)
189 waylandWindow->setParentControlGeometry(q->parentControlGeometry());
190#endif
191
192 QQuickWindowQmlImplPrivate::setVisible(visible);
193
194 // Similar logic to grabForPopup(QWidget *popup)
195 // If the user clicks outside, popups with CloseOnPressOutside*/CloseOnReleaseOutside* need to be able to react,
196 // in order to determine if they should close.
197 // Pointer press and release events should also be filtered by the top-most popup window, and only be delivered to other windows in rare cases.
198 if (visible && visibleChanged && QGuiApplicationPrivate::popupCount() == 1 && !s_popupGrabOk) {
199 QWindow *win = m_popup->window();
200 if (QGuiApplication::platformName() == QStringLiteral("offscreen"))
201 return; // workaround for QTBUG-134009
202 s_popupGrabOk = win->setKeyboardGrabEnabled(true);
203 if (s_popupGrabOk) {
204 s_popupGrabOk = win->setMouseGrabEnabled(true);
205 if (!s_popupGrabOk)
206 win->setKeyboardGrabEnabled(false);
207 s_grabbedWindow = win;
208 qCDebug(lcPopupWindow) << "The window" << win << "has enabled global mouse" << (s_popupGrabOk ? "and keyboard" : "") << "grabs.";
209 }
210 }
211}
212
213/*! \internal
214 Even if all pointer events are sent to the active popup, there are cases
215 where we need to take several popups, or even the menu bar, into account
216 to figure out what the event should do.
217
218 - When clicking outside a popup, the closePolicy should determine whether the
219 popup should close or not. When closing a menu this way, all other menus
220 that are grouped together should also close.
221
222 - We want all open menus and sub menus that belong together to almost act as
223 a single popup WRT hover event delivery. This will allow the user to hover
224 and highlight MenuItems inside all of them, not just this menu. This function
225 will therefore find the menu, or menu bar, under the event's position, and
226 forward hover events to it.
227
228 Note that we for most cases want to return false from this function, even if
229 the event was actually handled. That way it will be also sent to the DA, to
230 let normal event delivery to any potential grabbers happen the usual way. It
231 will also allow QGuiApplication to forward the event to the window under the
232 pointer if the event was outside of any popups (if supported by e.g
233 QPlatformIntegration::ReplayMousePressOutsidePopup).
234 */
235bool QQuickPopupWindowPrivate::filterPopupSpecialCases(QEvent *event)
236{
237 Q_UNUSED(event);
238#if QT_CONFIG(quicktemplates2_container)
239 Q_Q(QQuickPopupWindow);
240
241 if (!event->isPointerEvent())
242 return false;
243
244 QQuickPopup *popup = m_popup;
245 if (!popup)
246 return false;
247
248 auto *pe = static_cast<QPointerEvent *>(event);
249 const QPointF globalPos = pe->points().first().globalPosition();
250 QQuickPopup *targetPopup = QQuickPopupPrivate::get(popup)->contains(contentItem->mapFromGlobal(globalPos)) ? popup : nullptr;
251
252 // Resolve the Menu or MenuBar under the mouse, if any
253 QQuickMenu *menu = qobject_cast<QQuickMenu *>(popup);
254 QQuickMenuBar *targetMenuBar = nullptr;
255 QObject *menuParent = menu;
256 while (menuParent) {
257 if (auto *parentMenu = qobject_cast<QQuickMenu *>(menuParent)) {
258 QQuickPopupWindow *popupWindow = QQuickMenuPrivate::get(parentMenu)->popupWindow;
259 auto *popup_d = QQuickPopupPrivate::get(popupWindow->popup());
260 QPointF scenePos = popupWindow->contentItem()->mapFromGlobal(globalPos);
261 if (popup_d->contains(scenePos)) {
262 targetPopup = parentMenu;
263 break;
264 }
265 } else if (auto *menuBar = qobject_cast<QQuickMenuBar *>(menuParent)) {
266 const QPointF menuBarPos = menuBar->mapFromGlobal(globalPos);
267 if (menuBar->contains(menuBarPos))
268 targetMenuBar = menuBar;
269 break;
270 }
271
272 menuParent = menuParent->parent();
273 }
274
275 auto closePopups = [q, globalPos](QQuickPopup::ClosePolicy closePolicy) {
276 static const QQuickPopup::ClosePolicy outsideParentFlags =
277 QQuickPopup::CloseOnPressOutsideParent | QQuickPopup::CloseOnReleaseOutsideParent;
278
279 QQuickPopup *current = q->popup();
280 while (current && current->closePolicy().testAnyFlags(closePolicy)
281 && QQuickPopupPrivate::get(current)->popupWindow) {
282 auto *currentPrivate = QQuickPopupPrivate::get(current);
283 const QPointF scenePos = currentPrivate->popupWindow->contentItem()->mapFromGlobal(globalPos);
284 if (currentPrivate->contains(scenePos))
285 break; // clicked inside the popup itself: never closes, regardless of policy
286
287 // CloseOnPress/ReleaseOutsideParent closes the popup only when the click is
288 // outside its *parent* too, not merely outside the popup itself - e.g. a click
289 // landing on a sibling/ancestor popup's own content must not close this one
290 // unless the plain Outside flag (checked above) is also what's asked for here.
291 if (current->closePolicy().testAnyFlags(closePolicy & outsideParentFlags)) {
292 const QQuickItem *parentItem = current->parentItem();
293 if (parentItem && parentItem->contains(parentItem->mapFromGlobal(globalPos)))
294 break;
295 }
296
297 qCDebug(lcPopupWindow)
298 << "Closing" << current << "from an outside pointer press or release event.";
299 current->close();
300 auto *transientParentPopupWindow = qobject_cast<QQuickPopupWindow *>(
301 currentPrivate->popupWindow->transientParent());
302 current = current->closePolicy().testAnyFlag(QQuickPopup::CloseMultiple)
303 && transientParentPopupWindow
304 ? transientParentPopupWindow->popup()
305 : nullptr;
306 }
307 };
308
309 if (pe->isBeginEvent()) {
310 if (targetMenuBar) {
311 // If the press was on top of the menu bar, we close all menus and return
312 // true. The latter will stop QGuiApplication from propagating the event
313 // to the window under the pointer, and therefore also to the MenuBar.
314 // The latter would otherwise cause a menu to reopen again immediately, and
315 // undermine that we want to close all popups.
316 closePopups(QQuickPopup::CloseOnPressOutside | QQuickPopup::CloseOnPressOutsideParent);
317 return true;
318 } else if (!targetPopup) {
319 // Pressed outside either a popup window, or a menu or menubar that owns a menu using popup windows.
320 // Note that A QQuickPopupWindow can be bigger than the
321 // menu itself, to make room for a drop-shadow. But if the press was on top
322 // of the shadow, targetMenu will still be nullptr.
323 // On WASM in particular, it's possible for dialogs to receive the event, when clicking in the non-client area. Don't close in those cases.
324 if (event->type() != QEvent::NonClientAreaMouseButtonPress && event->type() != QEvent::NonClientAreaMouseButtonDblClick) {
325 const bool isTouchEventFromTouchPad = event->type() == QEvent::TouchBegin
326 && pe->deviceType() == QInputDevice::DeviceType::TouchPad;
327 if (!isTouchEventFromTouchPad)
328 closePopups(QQuickPopup::CloseOnPressOutside | QQuickPopup::CloseOnPressOutsideParent);
329
330 // A modal popup must consume the press event so that forwardToPopup() sees the event as handled
331 // so that it doesn't propagate to items behind the popup window (QTBUG-131786 etc.)
332 // A QTabletEvent in particular is not accepted by default
333 if (popup->isModal()) {
334 pe->accept();
335 return true;
336 }
337 }
338 return false;
339 }
340 } else if (pe->isUpdateEvent()){
341 QQuickWindow *targetWindow = nullptr;
342 if (targetPopup)
343 targetWindow = QQuickPopupPrivate::get(targetPopup)->popupWindow;
344 else if (targetMenuBar)
345 targetWindow = targetMenuBar->window();
346 else
347 return false;
348
349 // If the target is this popup window itself, normal event delivery will
350 // handle it (e.g. an exclusive grabber like a Slider). Forwarding to the
351 // same DA with the grabber cleared would break drag operations.
352 if (targetWindow == q)
353 return false;
354
355 // Forward move events to the target window
356 const auto scenePos = pe->point(0).scenePosition();
357 const auto translatedScenePos = targetWindow->mapFromGlobal(globalPos);
358 QMutableEventPoint::setScenePosition(pe->point(0), translatedScenePos);
359 auto *grabber = pe->exclusiveGrabber(pe->point(0));
360
361 if (grabber) {
362 // Temporarily disable the grabber, to stop the delivery agent inside
363 // targetWindow from forwarding the event to an item outside the menu
364 // or menubar. This is especially important to support a press on e.g
365 // a MenuBarItem, followed by a drag-and-release on top of a MenuItem.
366 pe->setExclusiveGrabber(pe->point(0), nullptr);
367 }
368
369 qCDebug(lcPopupWindow) << "forwarding" << pe << "to popup menu:" << targetWindow;
370 QQuickWindowPrivate::get(targetWindow)->deliveryAgent->event(pe);
371
372 // Restore the event before we return
373 QMutableEventPoint::setScenePosition(pe->point(0), scenePos);
374 if (grabber)
375 pe->setExclusiveGrabber(pe->point(0), grabber);
376 } else if (pe->isEndEvent()) {
377 if (!targetPopup && !targetMenuBar) {
378 // Released outside either a popup window, or a menu or menubar that owns a menu using popup windows.
379 // This should normally close the current popup window, unless it's inside the non-client area, which can happen in WASM dialogs.
380 if (event->type() != QEvent::NonClientAreaMouseButtonRelease)
381 closePopups(QQuickPopup::CloseOnReleaseOutside | QQuickPopup::CloseOnReleaseOutsideParent);
382 return false;
383 }
384
385 // To support opening a Menu on press (e.g on a MenuBarItem), followed by
386 // a drag and release on a MenuItem inside the Menu, we ask the Menu to
387 // perform a click on the active MenuItem, if any.
388 if (QQuickMenu *targetMenu = qobject_cast<QQuickMenu *>(targetPopup)) {
389 qCDebug(lcPopupWindow) << "forwarding" << pe << "to popup menu:" << targetMenu;
390 QQuickMenuPrivate::get(targetMenu)->handleReleaseWithoutGrab(pe->point(0));
391 }
392 }
393#endif
394
395 return false;
396}
397
398bool QQuickPopupWindow::event(QEvent *e)
399{
400 Q_D(QQuickPopupWindow);
401 if (e->type() == QEvent::PlatformSurface && static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) {
402#if QT_CONFIG(wayland)
403 if (auto *waylandWindow = dynamic_cast<QNativeInterface::Private::QWaylandWindow *>(handle())) {
404 waylandWindow->setExtendedWindowType(QQuickPopupPrivate::get(d->m_popup)->extendedWindowType);
405 waylandWindow->setParentControlGeometry(parentControlGeometry());
406 }
407#endif
408#if QT_CONFIG(xcb)
409 if (auto *xcbWindow = dynamic_cast<QNativeInterface::Private::QXcbWindow *>(handle())) {
410 const auto xcbWindowType = QQuickPopupPrivate::get(d->m_popup)->wmWindowType;
411 if (xcbWindowType != QNativeInterface::Private::QXcbWindow::None)
412 xcbWindow->setWindowType(xcbWindowType);
413 }
414#endif
415 }
416
417 if (d->filterPopupSpecialCases(e))
418 return true;
419
420 if (QQuickPopup *popup = d->m_popup) {
421 // Popups without focus should not consume keyboard events.
422 if (!popup->hasFocus() && (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease)
423#if QT_CONFIG(shortcut)
424 && (!static_cast<QKeyEvent *>(e)->matches(QKeySequence::Cancel)
425#if defined(Q_OS_ANDROID)
426 || static_cast<QKeyEvent *>(e)->key() != Qt::Key_Back
427#endif
428 )
429#endif
430 ) return false;
431 }
432
433 return QQuickWindowQmlImpl::event(e);
434}
435
436void QQuickPopupWindow::windowChanged(QWindow *window)
437{
438 Q_D(QQuickPopupWindow);
439 if (!d->m_popupParentItemWindow.isNull()) {
440 disconnect(d->m_popupParentItemWindow, &QWindow::xChanged, this, &QQuickPopupWindow::parentWindowXChanged);
441 disconnect(d->m_popupParentItemWindow, &QWindow::yChanged, this, &QQuickPopupWindow::parentWindowYChanged);
442 }
443 if (window) {
444 d->m_popupParentItemWindow = window;
445 connect(window, &QWindow::xChanged, this, &QQuickPopupWindow::parentWindowXChanged);
446 connect(window, &QWindow::yChanged, this, &QQuickPopupWindow::parentWindowYChanged);
447 } else {
448 d->m_popupParentItemWindow.clear();
449 }
450 setTransientParent(window);
451}
452
453std::optional<QPoint> QQuickPopupWindow::global2Local(const QPoint &pos) const
454{
455 Q_D(const QQuickPopupWindow);
456 QQuickPopup *popup = d->m_popup;
457 Q_ASSERT(popup);
458 QWindow *mainWindow = d->m_popupParentItemWindow;
459 if (!mainWindow)
460 mainWindow = transientParent();
461 if (Q_UNLIKELY((!mainWindow || mainWindow != popup->window())))
462 return std::nullopt;
463
464 const QPoint scenePos = mainWindow->mapFromGlobal(pos);
465 // Popup's coordinates are relative to the nearest parent item.
466 return popup->parentItem() ? popup->parentItem()->mapFromScene(scenePos).toPoint() : scenePos;
467}
468
469void QQuickPopupWindow::parentWindowXChanged(int newX)
470{
471 const auto popupLocalPos = global2Local({x(), y()});
472 if (Q_UNLIKELY(!popupLocalPos))
473 return;
474 handlePopupPositionChangeFromWindowSystem({ newX + popupLocalPos->x(), y() });
475}
476
477void QQuickPopupWindow::parentWindowYChanged(int newY)
478{
479 const auto popupLocalPos = global2Local({x(), y()});
480 if (Q_UNLIKELY(!popupLocalPos))
481 return;
482 handlePopupPositionChangeFromWindowSystem({ x(), newY + popupLocalPos->y() });
483}
484
485void QQuickPopupWindow::handlePopupPositionChangeFromWindowSystem(const QPoint &pos)
486{
487 Q_D(QQuickPopupWindow);
488 QQuickPopup *popup = d->m_popup;
489 if (!popup)
490 return;
491
492 const auto windowPos = global2Local(pos);
493 if (Q_LIKELY(windowPos)) {
494 qCDebug(lcPopupWindow).nospace() << "A window system event changed the popup's"
495 << " (" << d->m_popup << ") position to " << *windowPos;
496 QQuickPopupPrivate::get(popup)->setEffectivePosFromWindowPos(*windowPos);
497 }
498}
499
500void QQuickPopupWindow::implicitWidthChanged()
501{
502 Q_D(QQuickPopupWindow);
503 if (auto popup = d->m_popup) {
504 auto *popupPrivate = QQuickPopupPrivate::get(popup);
505 // Include window insets so that it works for styles like FluentWinUI3
506 // that have insets.
507 // Use qCeil to avoid sub-pixel truncation that causes text wrapping
508 // (see QTBUG-130683). This matches the initial sizing logic in
509 // QQuickPopupPrivate::adjustPopupItemParentAndWindow().
510 const QMarginsF insets = popupPrivate->windowInsets();
511 if (!popupPrivate->hasWidth) {
512 setWidth(qCeil(popup->implicitWidth() + insets.left() + insets.right()));
513 d->m_popupItem->setWidth(popup->implicitWidth());
514 }
515 popupPrivate->reposition();
516 }
517}
518
519void QQuickPopupWindow::implicitHeightChanged()
520{
521 Q_D(QQuickPopupWindow);
522 if (auto popup = d->m_popup) {
523 auto *popupPrivate = QQuickPopupPrivate::get(popup);
524 const QMarginsF insets = popupPrivate->windowInsets();
525 if (!popupPrivate->hasHeight) {
526 setHeight(qCeil(popup->implicitHeight() + insets.top() + insets.bottom()));
527 d->m_popupItem->setHeight(popup->implicitHeight());
528 }
529 popupPrivate->reposition();
530 }
531}
532
533#if QT_CONFIG(wayland)
534QRect QQuickPopupWindow::parentControlGeometry() const
535{
536 const QQuickItem *parent = popup()->parentItem();
537 // Menus have an overlap property that we want to honor,
538 // as long as it's not wider than half the width of the parent item.
539 const qreal overlap = popup()->property("overlap").toReal();
540 QRectF parentItemBoundingRect = parent->boundingRect();
541 const QPointF parentItemMappedPosition = parent->mapToScene(parentItemBoundingRect.topLeft());
542 return { qFloor(parentItemMappedPosition.x() + overlap), qFloor(parentItemMappedPosition.y()),
543 qCeil(qMax<qreal>(qAbs(parentItemBoundingRect.width() - overlap * 2), parentItemBoundingRect.width() / 4)), qCeil(parentItemBoundingRect.height()) };
544}
545#endif
546
547QT_END_NAMESPACE
QPointer< QQuickPopup > m_popup
QPointer< QWindow > m_popupParentItemWindow
void setVisible(bool visible) override
Combined button and popup list for selecting options.
static QPointer< QWindow > s_grabbedWindow