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
qwidgetwindow.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 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
5#include "private/qwindow_p.h"
7#include "qlayout.h"
8
9#include "private/qwidget_p.h"
10#include "private/qapplication_p.h"
11#if QT_CONFIG(accessibility)
12#include <QtGui/qaccessible.h>
13#endif
14#include <private/qwidgetrepaintmanager_p.h>
15#include <qpa/qwindowsysteminterface_p.h>
16#include <qpa/qplatformtheme.h>
17#include <qpa/qplatformwindow.h>
18#include <private/qgesturemanager_p.h>
19#include <private/qhighdpiscaling_p.h>
20
22
23using namespace Qt::StringLiterals;
24
25Q_WIDGETS_EXPORT extern bool qt_tab_all_widgets();
26
27Q_WIDGETS_EXPORT QWidget *qt_button_down = nullptr; // widget got last button-down
28
29// popup control
30QWidget *qt_popup_down = nullptr; // popup that contains the pressed widget
31bool qt_popup_down_closed = false; // qt_popup_down has been closed
32
33extern bool qt_try_modal(QWidget *widget, QEvent::Type type);
34
36{
37 Q_DECLARE_PUBLIC(QWidgetWindow)
38public:
40 {
42 qCDebug(lcWidgetShowHide) << "Setting visibility of" << q->widget()
43 << "to" << visible << "via QWidgetWindowPrivate";
44
45 if (QWidget *widget = q->widget()) {
46 // If the widget's visible state is already matching the new QWindow
47 // visible state we assume the widget has already synced up.
48 if (visible != widget->isVisible())
50 }
51
52 // If we end up calling QWidgetPrivate::setVisible() above, we will
53 // in most cases recurse back into setNativeWindowVisibility() to
54 // update the QWindow state. But during QWidget::destroy() this is
55 // not the case, as Qt::WA_WState_Created has been unset by the time
56 // we check if we should call hide_helper(). We handle this case, as
57 // well as the cases where we don't call QWidgetPrivate::setVisible(),
58 // by syncing up the QWindow state here if needed.
59 if (q->isVisible() != visible)
61 }
62
65 QWindow *w = q;
67 w = w->parent();
68 }
69 return w;
70 }
71
79
81 {
83 QWidget *widget = q->widget();
84 if (!widget)
85 return;
86
87 switch (target) {
88 case FocusTarget::Prev:
89 case FocusTarget::Next: {
92 return;
93 }
94 case FocusTarget::First:
95 case FocusTarget::Last: {
101 break;
102 }
103 default:
104 break;
105 }
106 }
107
109
112
113 QPalette windowPalette() const override
114 {
115 Q_Q(const QWidgetWindow);
116 if (const auto *widget = q->widget())
117 return widget->palette();
118 return QWindowPrivate::windowPalette();
119 }
120};
121
122QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const
123{
124 Q_Q(const QWidgetWindow);
125 const QWidget *widget = q->widget();
126 if (!widget || !widget->isWindow() || !widget->hasHeightForWidth())
127 return QRect();
128 const QSize oldSize = rect.size().toSize();
129 const QSize newSize = QLayout::closestAcceptableSize(widget, oldSize);
130 if (newSize == oldSize)
131 return QRectF();
132 const int dw = newSize.width() - oldSize.width();
133 const int dh = newSize.height() - oldSize.height();
134 QRectF result = rect;
135 const QRectF currentGeometry(widget->geometry());
136 const qreal topOffset = result.top() - currentGeometry.top();
137 const qreal bottomOffset = result.bottom() - currentGeometry.bottom();
138 if (qAbs(topOffset) > qAbs(bottomOffset))
139 result.setTop(result.top() - dh); // top edge drag
140 else
141 result.setBottom(result.bottom() + dh); // bottom edge drag
142 const qreal leftOffset = result.left() - currentGeometry.left();
143 const qreal rightOffset = result.right() - currentGeometry.right();
144 if (qAbs(leftOffset) > qAbs(rightOffset))
145 result.setLeft(result.left() - dw); // left edge drag
146 else
147 result.setRight(result.right() + dw); // right edge drag
148 return result;
149}
150
151bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType);
152
153QWidgetWindow::QWidgetWindow(QWidget *widget)
154 : QWindow(*new QWidgetWindowPrivate(), nullptr)
155 , m_widget(widget)
156{
157 updateObjectName();
158 if (!QCoreApplication::testAttribute(Qt::AA_ForceRasterWidgets)) {
159 QSurface::SurfaceType type = QSurface::RasterSurface;
160 if (q_evaluateRhiConfig(m_widget, nullptr, &type))
161 setSurfaceType(type);
162 }
163
164 connect(widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName);
165 connect(this, &QWidgetWindow::screenChanged, this, &QWidgetWindow::handleScreenChange);
166}
167
169{
170 // destroy while we are still alive
171 destroy();
172
173 if (!m_widget)
174 return;
175
176 QTLWExtra *topData = QWidgetPrivate::get(m_widget)->topData();
177 Q_ASSERT(topData);
178
179 // The QPlaformBackingStore may hold a reference to the window,
180 // so the backingstore needs to be deleted first.
181 topData->repaintManager.reset(nullptr);
182 delete topData->backingStore;
183 topData->backingStore = nullptr;
184 topData->widgetTextures.clear();
185
186 // Too late to do anything beyond this point
187 topData->window = nullptr;
188}
189
190#if QT_CONFIG(accessibility)
191QAccessibleInterface *QWidgetWindow::accessibleRoot() const
192{
193 if (m_widget)
194 return QAccessible::queryAccessibleInterface(m_widget);
195 return nullptr;
196}
197#endif
198
200{
201 QWidget *windowWidget = m_widget;
202 if (!windowWidget)
203 return nullptr;
204
205 // A window can't have a focus object if it's being destroyed.
206 if (QWidgetPrivate::get(windowWidget)->data.in_destructor)
207 return nullptr;
208
209 QWidget *widget = windowWidget->focusWidget();
210
211 if (!widget)
212 widget = windowWidget;
213
214 QObject *focusObj = QWidgetPrivate::get(widget)->focusObject();
215 if (focusObj)
216 return focusObj;
217
218 return widget;
219}
220
222{
223 Q_D(QWidgetWindow);
224 qCDebug(lcWidgetShowHide) << "Setting visibility of" << this
225 << "to" << visible << "via QWidgetWindow::setNativeWindowVisibility";
226
227 // Call base class setVisible() implementation to run the QWindow
228 // visibility logic. Don't call QWidgetWindowPrivate::setVisible()
229 // since that will recurse back into QWidget code.
230 d->QWindowPrivate::setVisible(visible);
231}
232
233void QWidgetWindow::focusNextPrevChild(QWidget *widget, bool next)
234{
235 Q_ASSERT(widget);
236 widget->focusNextPrevChild(next);
237}
238
239static inline bool shouldBePropagatedToWidget(QEvent *event)
240{
241 switch (event->type()) {
242 // Handing show events to widgets would cause them to be triggered twice
243 case QEvent::Show:
244 case QEvent::Hide:
245 case QEvent::Timer:
246 case QEvent::DynamicPropertyChange:
247 case QEvent::ChildAdded:
248 case QEvent::ChildRemoved:
249 case QEvent::Paint:
250 case QEvent::Close: // Propagated manually in closeEvent
251 return false;
252 default:
253 return true;
254 }
255}
256
257bool QWidgetWindow::event(QEvent *event)
258{
259 if (!m_widget)
260 return QWindow::event(event);
261
262 switch (event->type()) {
263 case QEvent::Enter:
264 case QEvent::Leave:
265 handleEnterLeaveEvent(event);
266 return true;
267
268 // these should not be sent to QWidget, the corresponding events
269 // are sent by QApplicationPrivate::notifyActiveWindowChange()
270 case QEvent::FocusIn:
271 handleFocusInEvent(static_cast<QFocusEvent *>(event));
272 Q_FALLTHROUGH();
273 case QEvent::FocusOut: {
274#if QT_CONFIG(accessibility)
275 QAccessible::State state;
276 state.active = true;
277 QAccessibleStateChangeEvent ev(m_widget, state);
278 QAccessible::updateAccessibility(&ev);
279#endif
280 return false; }
281
282 case QEvent::FocusAboutToChange:
283 if (QApplicationPrivate::focus_widget) {
284 if (QApplicationPrivate::focus_widget->testAttribute(Qt::WA_InputMethodEnabled))
285 QGuiApplication::inputMethod()->commit();
286
287 QGuiApplication::forwardEvent(QApplicationPrivate::focus_widget, event);
288 }
289 return true;
290
291 case QEvent::KeyPress:
292 case QEvent::KeyRelease:
293 case QEvent::ShortcutOverride:
294 handleKeyEvent(static_cast<QKeyEvent *>(event));
295 return true;
296
297 case QEvent::MouseMove:
298 case QEvent::MouseButtonPress:
299 case QEvent::MouseButtonRelease:
300 case QEvent::MouseButtonDblClick:
301 handleMouseEvent(static_cast<QMouseEvent *>(event));
302 return true;
303
304 case QEvent::NonClientAreaMouseMove:
305 case QEvent::NonClientAreaMouseButtonPress:
306 case QEvent::NonClientAreaMouseButtonRelease:
307 case QEvent::NonClientAreaMouseButtonDblClick:
308 handleNonClientAreaMouseEvent(static_cast<QMouseEvent *>(event));
309 return true;
310
311 case QEvent::TouchBegin:
312 case QEvent::TouchUpdate:
313 case QEvent::TouchEnd:
314 case QEvent::TouchCancel:
315 handleTouchEvent(static_cast<QTouchEvent *>(event));
316 return true;
317
318 case QEvent::Move:
319 handleMoveEvent(static_cast<QMoveEvent *>(event));
320 return true;
321
322 case QEvent::Resize:
323 handleResizeEvent(static_cast<QResizeEvent *>(event));
324 return true;
325
326#if QT_CONFIG(wheelevent)
327 case QEvent::Wheel:
328 handleWheelEvent(static_cast<QWheelEvent *>(event));
329 return true;
330#endif
331
332#if QT_CONFIG(draganddrop)
333 case QEvent::DragEnter:
334 handleDragEnterEvent(static_cast<QDragEnterEvent *>(event));
335 return true;
336 case QEvent::DragMove:
337 handleDragMoveEvent(static_cast<QDragMoveEvent *>(event));
338 return true;
339 case QEvent::DragLeave:
340 handleDragLeaveEvent(static_cast<QDragLeaveEvent *>(event));
341 return true;
342 case QEvent::Drop:
343 handleDropEvent(static_cast<QDropEvent *>(event));
344 return true;
345#endif
346
347 case QEvent::Expose:
348 handleExposeEvent(static_cast<QExposeEvent *>(event));
349 return true;
350
351 case QEvent::WindowStateChange:
352 QWindow::event(event); // Update QWindow::Visibility and emit signals.
353 handleWindowStateChangedEvent(static_cast<QWindowStateChangeEvent *>(event));
354 return true;
355
356 case QEvent::ThemeChange: {
357 QEvent widgetEvent(QEvent::ThemeChange);
358 QCoreApplication::forwardEvent(m_widget, &widgetEvent, event);
359 }
360 return true;
361
362#if QT_CONFIG(tabletevent)
363 case QEvent::TabletPress:
364 case QEvent::TabletMove:
365 case QEvent::TabletRelease:
366 handleTabletEvent(static_cast<QTabletEvent *>(event));
367 return true;
368#endif
369
370#ifndef QT_NO_GESTURES
371 case QEvent::NativeGesture:
372 handleGestureEvent(static_cast<QNativeGestureEvent *>(event));
373 return true;
374#endif
375
376#ifndef QT_NO_CONTEXTMENU
377 case QEvent::ContextMenu:
378 handleContextMenuEvent(static_cast<QContextMenuEvent *>(event));
379 return true;
380#endif // QT_NO_CONTEXTMENU
381
382 case QEvent::WindowBlocked:
383 qt_button_down = nullptr;
384 break;
385
386 case QEvent::UpdateRequest:
387 // This is not the same as an UpdateRequest for a QWidget. That just
388 // syncs the backing store while here we also must mark as dirty.
389 m_widget->repaint();
390 return true;
391
392 case QEvent::DevicePixelRatioChange:
393 handleDevicePixelRatioChange();
394 break;
395
396 case QEvent::SafeAreaMarginsChange:
397 QWidgetPrivate::get(m_widget)->updateContentsRect();
398 break;
399
400 default:
401 break;
402 }
403
404 if (shouldBePropagatedToWidget(event) && QCoreApplication::forwardEvent(m_widget, event))
405 return true;
406
407 return QWindow::event(event);
408}
409
411
413{
414 // Ignore all enter/leave events from QPA if we are not on the first-level context menu.
415 // This prevents duplicated events on most platforms. Fake events will be delivered in
416 // QWidgetWindow::handleMouseEvent(QMouseEvent *). Make an exception whether the widget
417 // is already under mouse - let the mouse leave.
418 if (QApplicationPrivate::inPopupMode() && m_widget != QApplication::activePopupWidget() && !m_widget->underMouse())
419 return;
420
421 if (event->type() == QEvent::Leave) {
422 QWidget *enter = nullptr;
423 // Check from window system event queue if the next queued enter targets a window
424 // in the same window hierarchy (e.g. enter a child of this window). If so,
425 // remove the enter event from queue and handle both in single dispatch.
426 QWindowSystemInterfacePrivate::EnterEvent *systemEvent =
427 static_cast<QWindowSystemInterfacePrivate::EnterEvent *>
428 (QWindowSystemInterfacePrivate::peekWindowSystemEvent(QWindowSystemInterfacePrivate::Enter));
429 const QPointF globalPosF = systemEvent ? systemEvent->globalPos : QPointF(QGuiApplicationPrivate::lastCursorPosition);
430 if (systemEvent) {
431 if (QWidgetWindow *enterWindow = qobject_cast<QWidgetWindow *>(systemEvent->enter))
432 {
433 QWindow *thisParent = this;
434 QWindow *enterParent = enterWindow;
435 while (thisParent->parent())
436 thisParent = thisParent->parent();
437 while (enterParent->parent())
438 enterParent = enterParent->parent();
439 if (thisParent == enterParent) {
440 QGuiApplicationPrivate::currentMouseWindow = enterWindow;
441 enter = enterWindow->widget();
442 QWindowSystemInterfacePrivate::removeWindowSystemEvent(systemEvent);
443 }
444 }
445 }
446 // Enter-leave between sibling widgets is ignored when there is a mousegrabber - this makes
447 // both native and non-native widgets work similarly.
448 // When mousegrabbing, leaves are only generated if leaving the parent window.
449 if (!enter || !QWidget::mouseGrabber()) {
450 // Preferred leave target is the last mouse receiver, unless it has native window,
451 // in which case it is assumed to receive it's own leave event when relevant.
452 QWidget *leave = m_widget;
453 if (qt_last_mouse_receiver && !qt_last_mouse_receiver->internalWinId())
454 leave = qt_last_mouse_receiver.data();
455 QApplicationPrivate::dispatchEnterLeave(enter, leave, globalPosF);
457 }
458 } else {
459 const QEnterEvent *ee = static_cast<QEnterEvent *>(event);
460 QWidget *child = m_widget->childAt(ee->position());
461 QWidget *receiver = child ? child : m_widget.data();
462 QWidget *leave = nullptr;
463 if (QApplicationPrivate::inPopupMode() && receiver == m_widget
464 && qt_last_mouse_receiver != m_widget) {
465 // This allows to deliver the leave event to the native widget
466 // action on first-level menu.
467 leave = qt_last_mouse_receiver;
468 }
469 QApplicationPrivate::dispatchEnterLeave(receiver, leave, ee->globalPosition());
470 qt_last_mouse_receiver = receiver;
471 }
472}
473
474QWidget *QWidgetWindow::getFocusWidget(FocusWidgets fw)
475{
476 QWidget *tlw = m_widget;
477 QWidget *w = tlw->nextInFocusChain();
478
479 QWidget *last = tlw;
480
481 uint focus_flag = qt_tab_all_widgets() ? Qt::TabFocus : Qt::StrongFocus;
482
483 while (w != tlw)
484 {
485 if (((w->focusPolicy() & focus_flag) == focus_flag)
486 && w->isVisibleTo(m_widget) && w->isEnabled())
487 {
488 last = w;
489 if (fw == FirstFocusWidget)
490 break;
491 }
492 w = w->nextInFocusChain();
493 }
494
495 return last;
496}
497
498void QWidgetWindow::handleFocusInEvent(QFocusEvent *e)
499{
500 QWidget *focusWidget = nullptr;
501 if (e->reason() == Qt::BacktabFocusReason)
502 focusWidget = getFocusWidget(LastFocusWidget);
503 else if (e->reason() == Qt::TabFocusReason)
504 focusWidget = getFocusWidget(FirstFocusWidget);
505
506 if (focusWidget != nullptr) {
507 focusWidget->setFocus(e->reason());
508
509 // Set WA_KeyboardFocusChange if focus was moved to this window via platform
510 // tab key handling, for instance if the native platform moves focus to an
511 // embedded QWindow. This ensures that widgets treat the focus change as
512 // keyboard navigation focus change, also in this case where Qt is not processing
513 // the tab key event itself.
514 if (e->reason() == Qt::TabFocusReason || e->reason() == Qt::BacktabFocusReason)
515 m_widget->setAttribute(Qt::WA_KeyboardFocusChange);
516 }
517}
518
519void QWidgetWindow::handleNonClientAreaMouseEvent(QMouseEvent *e)
520{
521 QApplication::forwardEvent(m_widget, e);
522}
523
524void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
525{
526 Q_D(QWidgetWindow);
527
528 // Event delivery can potentially result in window re-creation (QTBUG-132912)
529 // so we need QPointer to avoid a dangling d below
530 QPointer<QWidgetWindow> self = this;
531
532 if (auto *activePopupWidget = QApplication::activePopupWidget()) {
533 QPointF mapped = event->position();
534 if (activePopupWidget != m_widget)
535 mapped = activePopupWidget->mapFromGlobal(event->globalPosition());
536 bool releaseAfter = false;
537 QWidget *popupChild = activePopupWidget->childAt(mapped);
538
539 if (activePopupWidget != qt_popup_down) {
540 qt_button_down = nullptr;
541 qt_popup_down = nullptr;
542 }
543
544 switch (event->type()) {
545 case QEvent::MouseButtonPress:
546 case QEvent::MouseButtonDblClick:
547 qt_button_down = popupChild;
548 qt_popup_down = activePopupWidget;
549 qt_popup_down_closed = false;
550 break;
551 case QEvent::MouseButtonRelease:
552 releaseAfter = true;
553 break;
554 default:
555 break; // nothing for mouse move
556 }
557
558 if (activePopupWidget->isEnabled()) {
559 // deliver event
560 QPointer<QWidget> receiver = activePopupWidget;
561 QPointF widgetPos = mapped;
562 if (qt_button_down)
563 receiver = qt_button_down;
564 else if (popupChild)
565 receiver = popupChild;
566 if (receiver != activePopupWidget)
567 widgetPos = receiver->mapFromGlobal(event->globalPosition());
568
569 const bool reallyUnderMouse = activePopupWidget->rect().contains(mapped.toPoint());
570 const bool underMouse = activePopupWidget->underMouse();
571 if (underMouse != reallyUnderMouse) {
572 if (reallyUnderMouse) {
573 const QPointF receiverMapped = receiver->mapFromGlobal(event->globalPosition());
574 // Prevent negative mouse position on enter event - this event
575 // should be properly handled in "handleEnterLeaveEvent()".
576 if (receiverMapped.x() >= 0 && receiverMapped.y() >= 0) {
577 QApplicationPrivate::dispatchEnterLeave(receiver, nullptr, event->globalPosition());
578 qt_last_mouse_receiver = receiver;
579 }
580 } else {
581 QApplicationPrivate::dispatchEnterLeave(nullptr, qt_last_mouse_receiver, event->globalPosition());
582 qt_last_mouse_receiver = receiver;
583 receiver = activePopupWidget;
584 }
585 }
586
587 if ((event->type() != QEvent::MouseButtonPress) || !(QMutableSinglePointEvent::isDoubleClick(event))) {
588 // if the widget that was pressed is gone, then deliver move events without buttons
589 const auto buttons = event->type() == QEvent::MouseMove && qt_popup_down_closed
590 ? Qt::NoButton : event->buttons();
591 QMouseEvent e(event->type(), widgetPos, event->scenePosition(), event->globalPosition(),
592 event->button(), buttons, event->modifiers(),
593 event->source(), event->pointingDevice());
594 e.setTimestamp(event->timestamp());
595 QApplicationPrivate::sendMouseEvent(receiver, &e, receiver, receiver->window(), &qt_button_down, qt_last_mouse_receiver);
596 qt_last_mouse_receiver = receiver;
597 }
598 } else {
599 // close disabled popups when a mouse button is pressed or released
600 switch (event->type()) {
601 case QEvent::MouseButtonPress:
602 case QEvent::MouseButtonDblClick:
603 case QEvent::MouseButtonRelease:
604 activePopupWidget->close();
605 break;
606 default:
607 break;
608 }
609 }
610
611 // Event delivery above might have destroyed this object. See QTBUG-138419.
612 if (self.isNull())
613 return;
614
615 if (QApplication::activePopupWidget() != activePopupWidget
616 && QApplicationPrivate::replayMousePress
617 && QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::ReplayMousePressOutsidePopup).toBool()) {
618 if (m_widget->windowType() != Qt::Popup)
619 qt_button_down = nullptr;
620 if (event->type() == QEvent::MouseButtonPress) {
621 // the popup disappeared: replay the mouse press event to whatever is behind it
622 QWidget *w = QApplication::widgetAt(event->globalPosition().toPoint());
623 if (w && !QApplicationPrivate::isBlockedByModal(w)) {
624 // activate window of the widget under mouse pointer
625 if (!w->isActiveWindow()) {
626 w->activateWindow();
627 w->window()->raise();
628 }
629
630 if (auto win = qt_widget_private(w)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest)) {
631 const QRect globalGeometry = win->isTopLevel()
632 ? win->geometry()
633 : QRect(win->mapToGlobal(QPoint(0, 0)), win->size());
634 if (globalGeometry.contains(event->globalPosition().toPoint())) {
635 // Use postEvent() to ensure the local QEventLoop terminates when called from QMenu::exec()
636 const QPointF localPos = win->mapFromGlobal(event->globalPosition());
637 QMouseEvent *e = new QMouseEvent(QEvent::MouseButtonPress, localPos, localPos, event->globalPosition(),
638 event->button(), event->buttons(), event->modifiers(), event->source());
639 QCoreApplicationPrivate::setEventSpontaneous(e, true);
640 e->setTimestamp(event->timestamp());
641 QCoreApplication::postEvent(win, e);
642 }
643 }
644 }
645 }
646 QApplicationPrivate::replayMousePress = false;
647#ifndef QT_NO_CONTEXTMENU
648 } else if (event->type() == QGuiApplicationPrivate::contextMenuEventType()
649 && event->button() == Qt::RightButton) {
650 QWidget *receiver = activePopupWidget;
651 if (qt_button_down)
652 receiver = qt_button_down;
653 else if (popupChild)
654 receiver = popupChild;
655 const QPoint localPos = receiver->mapFromGlobal(event->globalPosition()).toPoint();
656 QContextMenuEvent e(QContextMenuEvent::Mouse, localPos, event->globalPosition().toPoint(), event->modifiers());
657 QApplication::forwardEvent(receiver, &e, event);
658 }
659#else
660 }
661#endif
662
663 if (releaseAfter) {
664 qt_button_down = nullptr;
665 qt_popup_down_closed = false;
666 qt_popup_down = nullptr;
667 }
668 return;
669 }
670
671 qt_popup_down_closed = false;
672 // modal event handling
673 if (QApplicationPrivate::instance()->modalState() && !qt_try_modal(m_widget, event->type()))
674 return;
675
676 // which child should have it?
677 QWidget *widget = m_widget->childAt(event->position());
678 QPointF mapped = event->position();
679
680 if (!widget)
681 widget = m_widget;
682
683 const bool initialPress = event->buttons() == event->button();
684 if (event->type() == QEvent::MouseButtonPress && initialPress)
685 qt_button_down = widget;
686
687 QWidget *receiver = QApplicationPrivate::pickMouseReceiver(m_widget, event->scenePosition(), &mapped, event->type(), event->buttons(),
688 qt_button_down, widget);
689 if (!receiver)
690 return;
691
692 if (d->isPopup() && receiver->window()->windowHandle() != this) {
693 receiver = widget;
694 mapped = event->position();
695 }
696
697 if ((event->type() != QEvent::MouseButtonPress) || !QMutableSinglePointEvent::isDoubleClick(event)) {
698
699 // The preceding statement excludes MouseButtonPress events which caused
700 // creation of a MouseButtonDblClick event. QTBUG-25831
701 QMouseEvent translated(event->type(), mapped, event->scenePosition(), event->globalPosition(),
702 event->button(), event->buttons(), event->modifiers(),
703 event->source(), event->pointingDevice());
704 translated.setTimestamp(event->timestamp());
705 QApplicationPrivate::sendMouseEvent(receiver, &translated, widget, m_widget,
706 &qt_button_down, qt_last_mouse_receiver);
707 event->setAccepted(translated.isAccepted());
708 }
709
710 if (self.isNull())
711 return;
712
713#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
714 if (
715#else
716 if (event->isAccepted() &&
717#endif
718 (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease))
719 d->maybeSynthesizeContextMenuEvent(event);
720}
721
722void QWidgetWindow::handleTouchEvent(QTouchEvent *event)
723{
724 if (event->type() == QEvent::TouchCancel) {
725 QApplicationPrivate::translateTouchCancel(event->pointingDevice(), event->timestamp());
726 event->accept();
727 } else if (QApplication::activePopupWidget()) {
728 // Ignore touch events for popups. This will cause QGuiApplication to synthesise mouse
729 // events instead, which QWidgetWindow::handleMouseEvent will forward correctly:
730 event->ignore();
731 } else {
732 event->setAccepted(QApplicationPrivate::translateRawTouchEvent(m_widget, event));
733 }
734}
735
736void QWidgetWindow::handleKeyEvent(QKeyEvent *event)
737{
738 if (QApplicationPrivate::instance()->modalState() && !qt_try_modal(m_widget, event->type()))
739 return;
740
741 QObject *receiver = QWidget::keyboardGrabber();
742 if (auto *popup = QApplication::activePopupWidget(); !receiver && popup) {
743 QWidget *popupFocusWidget = popup->focusWidget();
744 receiver = popupFocusWidget ? popupFocusWidget : popup;
745 }
746 if (!receiver)
747 receiver = focusObject();
748 QGuiApplication::forwardEvent(receiver, event);
749}
750
751bool QWidgetWindow::updateSize()
752{
753 bool changed = false;
754 if (m_widget->testAttribute(Qt::WA_OutsideWSRange))
755 return changed;
756 if (m_widget->testAttribute(Qt::WA_DontShowOnScreen))
757 return changed;
758
759 if (m_widget->data->crect.size() != geometry().size()) {
760 changed = true;
761 m_widget->data->crect.setSize(geometry().size());
762 }
763
764 updateMargins();
765 return changed;
766}
767
768void QWidgetWindow::updateMargins()
769{
770 // QTBUG-79147 (Windows): Bail out on resize events after closing a dialog
771 // and destroying the platform window which would clear the margins.
772 QTLWExtra *te = m_widget->d_func()->topData();
773 if (te->window == nullptr || te->window->handle() == nullptr)
774 return;
775 const QMargins margins = frameMargins();
776 te->posIncludesFrame= false;
777 te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
778 m_widget->data->fstrut_dirty = false;
779}
780
781static void sendChangeRecursively(QWidget *widget, QEvent::Type type)
782{
783 QEvent e(type);
784 QCoreApplication::sendEvent(widget, &e);
785 QWidgetPrivate *d = QWidgetPrivate::get(widget);
786 for (int i = 0; i < d->children.size(); ++i) {
787 QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
788 if (w)
789 sendChangeRecursively(w, type);
790 }
791}
792
793void QWidgetWindow::handleScreenChange()
794{
795 // Send an event recursively to the widget and its children.
796 sendChangeRecursively(m_widget, QEvent::ScreenChangeInternal);
797
798 // Invalidate the backing store buffer and schedule repaint
799 scheduleRepaint();
800}
801
802void QWidgetWindow::handleDevicePixelRatioChange()
803{
804 // Send an event recursively to the widget and its children.
805 sendChangeRecursively(m_widget, QEvent::DevicePixelRatioChange);
806
807 // Invalidate the backing store buffer and schedule repaint
808 scheduleRepaint();
809}
810
811/*
812 Schedules a repaint in response to screen or DPR changes
813
814 Normally these changes will come with a corresponding expose
815 event following the change, but to guarantee that we refresh
816 the widget based on the new properties we also schedule our
817 own repaint.
818
819 Note that we do not do a synchronous repaint here, as the system
820 hasn't asked us to repaint just yet, it just informed us about
821 the new window state.
822*/
823void QWidgetWindow::scheduleRepaint()
824{
825 if (!screen())
826 return;
827
828 if (!m_widget->isVisible() || !m_widget->updatesEnabled() || !m_widget->rect().isValid())
829 return;
830
831 QTLWExtra *tlwExtra = m_widget->window()->d_func()->maybeTopData();
832 if (tlwExtra && tlwExtra->backingStore) {
833 tlwExtra->repaintManager->markDirty(m_widget->rect(), m_widget,
834 QWidgetRepaintManager::UpdateLater, QWidgetRepaintManager::BufferInvalid);
835 }
836}
837
838// Store normal geometry used for saving application settings.
839void QWidgetWindow::updateNormalGeometry()
840{
841 QTLWExtra *tle = m_widget->d_func()->maybeTopData();
842 if (!tle)
843 return;
844 // Ask platform window, default to widget geometry.
845 QRect normalGeometry;
846 if (const QPlatformWindow *pw = handle())
847 normalGeometry = QHighDpi::fromNativePixels(pw->normalGeometry(), this);
848 if (!normalGeometry.isValid() && !(m_widget->windowState() & ~Qt::WindowActive))
849 normalGeometry = m_widget->geometry();
850 if (normalGeometry.isValid())
851 tle->normalGeometry = normalGeometry;
852}
853
854void QWidgetWindow::handleMoveEvent(QMoveEvent *event)
855{
856 if (m_widget->testAttribute(Qt::WA_OutsideWSRange))
857 return;
858 if (m_widget->testAttribute(Qt::WA_DontShowOnScreen))
859 return;
860
861 auto oldPosition = m_widget->data->crect.topLeft();
862 auto newPosition = geometry().topLeft();
863
864 if (!m_widget->isWindow()) {
865 if (auto *nativeParent = m_widget->nativeParentWidget())
866 newPosition = m_widget->parentWidget()->mapFrom(nativeParent, newPosition);
867 }
868
869 bool changed = newPosition != oldPosition;
870
871 if (changed)
872 m_widget->data->crect.moveTopLeft(newPosition);
873
874 updateMargins(); // FIXME: Only do when changed?
875
876 if (changed) {
877 QMoveEvent widgetEvent(newPosition, oldPosition);
878 QGuiApplication::forwardEvent(m_widget, &widgetEvent, event);
879 }
880}
881
882void QWidgetWindow::handleResizeEvent(QResizeEvent *event)
883{
884 auto oldRect = m_widget->rect();
885
886 if (updateSize()) {
887 QGuiApplication::forwardEvent(m_widget, event);
888
889 if (m_widget->d_func()->shouldPaintOnScreen()) {
890 QRegion dirtyRegion = m_widget->rect();
891 if (m_widget->testAttribute(Qt::WA_StaticContents))
892 dirtyRegion -= oldRect;
893 m_widget->d_func()->syncBackingStore(dirtyRegion);
894 } else {
895 m_widget->d_func()->syncBackingStore();
896 }
897 }
898}
899
900void QWidgetWindow::closeEvent(QCloseEvent *event)
901{
902 Q_D(QWidgetWindow);
903 if (qt_popup_down == m_widget) {
904 qt_popup_down = nullptr;
906 }
907 bool accepted = m_widget->d_func()->handleClose(d->inClose ? QWidgetPrivate::CloseWithEvent
908 : QWidgetPrivate::CloseWithSpontaneousEvent);
909 event->setAccepted(accepted);
910}
911
913{
914 Q_Q(const QWidgetWindow);
915
916 // For historical reasons WA_QuitOnClose has been closely tied
917 // to the lastWindowClosed signal, since the default behavior
918 // is to quit the application after emitting lastWindowClosed.
919 // ### Qt 7: Rename this attribute, or decouple behavior.
920 if (!q->widget()->testAttribute(Qt::WA_QuitOnClose))
921 return false;
922
923 return QWindowPrivate::participatesInLastWindowClosed();
924}
925
927{
928 Q_Q(const QWidgetWindow);
929
930 // Widget windows may have Qt::WA_DontShowOnScreen, in which case the
931 // QQWidget will be visible, but the corresponding QWindow will not.
932 // Since the lastWindowClosed logic relies on checking whether the
933 // closed window was visible, and if there are any remaining visible
934 // windows, we need to reflect the QWidget state, not the QWindow one.
935 return q->widget()->isVisible();
936}
937
938#if QT_CONFIG(wheelevent)
939
940void QWidgetWindow::handleWheelEvent(QWheelEvent *event)
941{
942 if (QApplicationPrivate::instance()->modalState() && !qt_try_modal(m_widget, event->type()))
943 return;
944
945 QWidget *rootWidget = m_widget;
946 QPointF pos = event->position();
947
948 // Use proper popup window for wheel event. Some QPA sends the wheel
949 // event to the root menu, so redirect it to the proper popup window.
950 QWidget *activePopupWidget = QApplication::activePopupWidget();
951 if (activePopupWidget && activePopupWidget != m_widget) {
952 rootWidget = activePopupWidget;
953 pos = rootWidget->mapFromGlobal(event->globalPosition());
954 }
955
956 // which child should have it?
957 QWidget *widget = rootWidget->childAt(pos);
958
959 if (!widget)
960 widget = rootWidget;
961
962 QPointF mapped = widget->mapFrom(rootWidget, pos);
963
964 QWheelEvent translated(mapped, event->globalPosition(), event->pixelDelta(), event->angleDelta(),
965 event->buttons(), event->modifiers(), event->phase(), event->inverted(),
966 event->source(), event->pointingDevice());
967 translated.setTimestamp(event->timestamp());
968 QGuiApplication::forwardEvent(widget, &translated, event);
969}
970
971#endif // QT_CONFIG(wheelevent)
972
973#if QT_CONFIG(draganddrop)
974
975static QWidget *findDnDTarget(QWidget *parent, const QPointF &pos)
976{
977 // Find a target widget under mouse that accepts drops (QTBUG-22987).
978 QWidget *widget = parent->childAt(pos);
979 if (!widget)
980 widget = parent;
981 for ( ; widget && !widget->isWindow() && !widget->acceptDrops(); widget = widget->parentWidget()) ;
982 if (widget && !widget->acceptDrops())
983 widget = nullptr;
984 return widget;
985}
986
987/*!
988 \internal
989
990 Sends \a event to \a widget.
991
992 Also called from dragMoveEvent(), in which case \a event is-a
993 QDragMoveEvent only, not a full QDragEnterEvent, which is why this function
994 takes \a event as a QDragMoveEvent and not, as one would expect,
995 QDragEnterEvent (downcast would be UB).
996*/
997void QWidgetWindow::handleDragEnterEvent(QDragMoveEvent *event, QWidget *widget)
998{
999 Q_ASSERT(m_dragTarget == nullptr);
1000 if (!widget)
1001 widget = findDnDTarget(m_widget, event->position());
1002 if (!widget) {
1003 event->ignore();
1004 return;
1005 }
1006 m_dragTarget = widget;
1007
1008 const QPointF mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->position()));
1009 QDragEnterEvent translated(mapped, event->possibleActions(), event->mimeData(),
1010 event->buttons(), event->modifiers());
1011 QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
1012 event->setAccepted(translated.isAccepted());
1013 event->setDropAction(translated.dropAction());
1014}
1015
1016void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event)
1017{
1018 QPointer<QWidget> widget = findDnDTarget(m_widget, event->position());
1019 if (!widget) {
1020 event->ignore();
1021 if (m_dragTarget) { // Send DragLeave to previous
1022 QDragLeaveEvent leaveEvent;
1023 QWidget *dragTarget = m_dragTarget;
1024 m_dragTarget = nullptr;
1025 QGuiApplication::forwardEvent(dragTarget, &leaveEvent, event);
1026 }
1027 } else {
1028 const QPointF mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->position()));
1029 QDragMoveEvent translated(mapped, event->possibleActions(), event->mimeData(),
1030 event->buttons(), event->modifiers());
1031
1032 if (widget == m_dragTarget) { // Target widget unchanged: Send DragMove
1033 translated.setDropAction(event->dropAction());
1034 translated.setAccepted(event->isAccepted());
1035 QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
1036 } else {
1037 if (m_dragTarget) { // Send DragLeave to previous
1038 QDragLeaveEvent leaveEvent;
1039 QWidget *dragTarget = m_dragTarget;
1040 m_dragTarget = nullptr;
1041 QGuiApplication::forwardEvent(dragTarget, &leaveEvent, event);
1042 }
1043 // widget might have been deleted when handling the leaveEvent
1044 if (widget) {
1045 // Send DragEnter to new widget.
1046 handleDragEnterEvent(event, widget);
1047 // Handling 'DragEnter' should suffice for the application.
1048 translated.setDropAction(event->dropAction());
1049 translated.setAccepted(event->isAccepted());
1050 // The drag enter event is always immediately followed by a drag move event,
1051 // see QDragEnterEvent documentation.
1052 if (m_dragTarget)
1053 QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
1054 }
1055 }
1056 event->setAccepted(translated.isAccepted());
1057 event->setDropAction(translated.dropAction());
1058 }
1059}
1060
1061void QWidgetWindow::handleDragLeaveEvent(QDragLeaveEvent *event)
1062{
1063 if (m_dragTarget) {
1064 QWidget *dragTarget = m_dragTarget;
1065 m_dragTarget = nullptr;
1066 QGuiApplication::forwardEvent(dragTarget, event);
1067 }
1068}
1069
1070void QWidgetWindow::handleDropEvent(QDropEvent *event)
1071{
1072 if (Q_UNLIKELY(m_dragTarget.isNull())) {
1073 qWarning() << m_widget << ": No drag target set.";
1074 event->ignore();
1075 return;
1076 }
1077 const QPointF mapped = m_dragTarget->mapFromGlobal(m_widget->mapToGlobal(event->position()));
1078 QDropEvent translated(mapped, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers());
1079 QWidget *dragTarget = m_dragTarget;
1080 m_dragTarget = nullptr;
1081 QGuiApplication::forwardEvent(dragTarget, &translated, event);
1082 event->setAccepted(translated.isAccepted());
1083 event->setDropAction(translated.dropAction());
1084}
1085
1086#endif // QT_CONFIG(draganddrop)
1087
1088void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
1089{
1090 if (m_widget->testAttribute(Qt::WA_DontShowOnScreen))
1091 return; // Ignore for widgets that fake exposure
1092
1093 QWidgetPrivate *wPriv = m_widget->d_func();
1094 const bool exposed = isExposed();
1095
1096 // We might get an expose event from the platform as part of
1097 // closing the window from ~QWidget, to support animated close
1098 // transitions. But at that point we no longer have a widget
1099 // subclass to draw a new frame, so skip the expose event.
1100 if (exposed && wPriv->data.in_destructor)
1101 return;
1102
1103 if (wPriv->childrenHiddenByWState) {
1104 // If widgets has been previously hidden by window state change event
1105 // and they aren't yet shown...
1106 if (exposed) {
1107 // If the window becomes exposed...
1108 if (!wPriv->childrenShownByExpose) {
1109 // ... and they haven't been shown by this function yet - show it.
1110 wPriv->showChildren(true);
1111 QShowEvent showEvent;
1112 QCoreApplication::forwardEvent(m_widget, &showEvent, event);
1113 wPriv->childrenShownByExpose = true;
1114 }
1115 } else {
1116 // If the window becomes not exposed...
1117 if (wPriv->childrenShownByExpose) {
1118 // ... and child widgets was previously shown by the expose event - hide widgets again.
1119 // This is a workaround, because sometimes when window is minimized programmatically,
1120 // the QPA can notify that the window is exposed after changing window state to minimized
1121 // and then, the QPA can send next expose event with null exposed region (not exposed).
1122 wPriv->hideChildren(true);
1123 QHideEvent hideEvent;
1124 QCoreApplication::forwardEvent(m_widget, &hideEvent, event);
1125 wPriv->childrenShownByExpose = false;
1126 }
1127 }
1128 }
1129
1130 if (exposed) {
1131 // QTBUG-39220, QTBUG-58575: set all (potentially fully obscured parent widgets) mapped.
1132 m_widget->setAttribute(Qt::WA_Mapped);
1133 for (QWidget *p = m_widget->parentWidget(); p && !p->testAttribute(Qt::WA_Mapped); p = p->parentWidget())
1134 p->setAttribute(Qt::WA_Mapped);
1135 if (!event->m_region.isNull())
1136 wPriv->syncBackingStore(event->m_region);
1137 } else {
1138 m_widget->setAttribute(Qt::WA_Mapped, false);
1139 }
1140}
1141
1142void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event)
1143{
1144 // QWindow does currently not know 'active'.
1145 Qt::WindowStates eventState = event->oldState();
1146 Qt::WindowStates widgetState = m_widget->windowState();
1147 Qt::WindowStates windowState = windowStates();
1148 if (widgetState & Qt::WindowActive)
1149 eventState |= Qt::WindowActive;
1150
1151 // Determine the new widget state, remember maximized/full screen
1152 // during minimized.
1153 if (windowState & Qt::WindowMinimized) {
1154 widgetState |= Qt::WindowMinimized;
1155 } else {
1156 widgetState = windowState | (widgetState & Qt::WindowActive);
1157 if (windowState) // Maximized or FullScreen
1158 updateNormalGeometry();
1159 }
1160
1161 // Sent event if the state changed (that is, it is not triggered by
1162 // QWidget::setWindowState(), which also sends an event to the widget).
1163 if (widgetState != Qt::WindowStates::Int(m_widget->data->window_state)) {
1164 m_widget->data->window_state = uint(widgetState);
1165 QWindowStateChangeEvent widgetEvent(eventState);
1166 QGuiApplication::forwardEvent(m_widget, &widgetEvent, event);
1167 }
1168}
1169
1170bool QWidgetWindow::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
1171{
1172 return m_widget->nativeEvent(eventType, message, result);
1173}
1174
1175#if QT_CONFIG(tabletevent)
1176void QWidgetWindow::handleTabletEvent(QTabletEvent *event)
1177{
1178 static QPointer<QWidget> qt_tablet_target = nullptr;
1179
1180 QWidget *widget = qt_tablet_target;
1181
1182 if (!widget) {
1183 widget = m_widget->childAt(event->position());
1184 if (!widget)
1185 widget = m_widget;
1186 if (event->type() == QEvent::TabletPress)
1187 qt_tablet_target = widget;
1188 }
1189
1190 if (widget) {
1191 const QPointF mapped = widget->mapFromGlobal(event->globalPosition());
1192 QTabletEvent ev(event->type(), event->pointingDevice(), mapped, event->globalPosition(),
1193 event->pressure(), event->xTilt(), event->yTilt(), event->tangentialPressure(),
1194 event->rotation(), event->z(), event->modifiers(), event->button(), event->buttons());
1195 ev.setTimestamp(event->timestamp());
1196 ev.setAccepted(false);
1197 QGuiApplication::forwardEvent(widget, &ev, event);
1198 event->setAccepted(ev.isAccepted());
1199 }
1200
1201 if (event->type() == QEvent::TabletRelease && event->buttons() == Qt::NoButton)
1202 qt_tablet_target = nullptr;
1203}
1204#endif // QT_CONFIG(tabletevent)
1205
1206#ifndef QT_NO_GESTURES
1207void QWidgetWindow::handleGestureEvent(QNativeGestureEvent *e)
1208{
1209 // copy-pasted code to find correct widget follows:
1210 QObject *receiver = nullptr;
1211 if (auto *popup = QApplication::activePopupWidget()) {
1212 QWidget *popupFocusWidget = popup->focusWidget();
1213 receiver = popupFocusWidget ? popupFocusWidget : popup;
1214 }
1215 if (!receiver)
1216 receiver = QApplication::widgetAt(e->globalPosition().toPoint());
1217 if (!receiver)
1218 receiver = m_widget; // last resort
1219
1220 QApplication::forwardEvent(receiver, e);
1221}
1222#endif // QT_NO_GESTURES
1223
1224#ifndef QT_NO_CONTEXTMENU
1225void QWidgetWindow::handleContextMenuEvent(QContextMenuEvent *e)
1226{
1227 QWidget *receiver = qt_last_mouse_receiver.get();
1228 QPoint pos = e->pos();
1229 QPoint globalPos = e->globalPos();
1230
1231 // Keyboard-originating context menu events are delivered to the focus widget,
1232 // independently of event position.
1233 if (e->reason() == QContextMenuEvent::Keyboard) {
1234 receiver = QWidget::keyboardGrabber();
1235 if (!receiver) {
1236 if (QApplication::activePopupWidget()) {
1237 receiver = (QApplication::activePopupWidget()->focusWidget()
1238 ? QApplication::activePopupWidget()->focusWidget()
1239 : QApplication::activePopupWidget());
1240 } else if (QApplication::focusWidget()) {
1241 receiver = QApplication::focusWidget();
1242 } else {
1243 receiver = m_widget;
1244 }
1245 }
1246 if (Q_LIKELY(receiver)) {
1247 pos = receiver->inputMethodQuery(Qt::ImCursorRectangle).toRect().center();
1248 globalPos = receiver->mapToGlobal(pos);
1249 }
1250 } else if (Q_LIKELY(receiver)) {
1251 pos = receiver->mapFromGlobal(e->globalPos());
1252 }
1253
1254 if (receiver) {
1255 QContextMenuEvent widgetEvent(e->reason(), pos, globalPos, e->modifiers());
1256 QGuiApplication::forwardEvent(receiver, &widgetEvent, e);
1257 }
1258}
1259#endif // QT_NO_CONTEXTMENU
1260
1261void QWidgetWindow::updateObjectName()
1262{
1263 QString name = m_widget->objectName();
1264 if (name.isEmpty())
1265 name = QString::fromUtf8(m_widget->metaObject()->className()) + "Class"_L1;
1266 name += "Window"_L1;
1267 setObjectName(name);
1268}
1269
1270QT_END_NAMESPACE
1271
1272#include "moc_qwidgetwindow_p.cpp"
bool participatesInLastWindowClosed() const override
QPalette windowPalette() const override
bool treatAsVisible() const override
void setNativeWindowVisibility(bool visible)
QObject * focusObject() const override
Returns the QObject that will be the final receiver of events tied focus, such as key events.
void handleMoveEvent(QMoveEvent *)
void handleEnterLeaveEvent(QEvent *)
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override
Override this to handle platform dependent events.
bool event(QEvent *) override
Override this to handle any event (ev) sent to the window.
void handleExposeEvent(QExposeEvent *)
void closeEvent(QCloseEvent *) override
Override this to handle close events (ev).
void handleGestureEvent(QNativeGestureEvent *)
void handleWindowStateChangedEvent(QWindowStateChangeEvent *event)
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
Combined button and popup list for selecting options.
QPointer< QWidget > qt_last_mouse_receiver
Q_WIDGETS_EXPORT bool qt_tab_all_widgets()
QWidget * qt_popup_down
static void sendChangeRecursively(QWidget *widget, QEvent::Type type)
bool qt_popup_down_closed
bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
Definition qwidget.cpp:1069
static bool shouldBePropagatedToWidget(QEvent *event)
bool qt_try_modal(QWidget *widget, QEvent::Type type)