diff options
Diffstat (limited to 'src/widgets/kernel/qapplication.cpp')
-rw-r--r-- | src/widgets/kernel/qapplication.cpp | 151 |
1 files changed, 61 insertions, 90 deletions
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 8b6adc0176..bf6b41cbcd 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -98,6 +98,8 @@ static void initResources() QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcWidgetPopup, "qt.widgets.popup"); + using namespace Qt::StringLiterals; Q_TRACE_PREFIX(qtwidgets, @@ -310,7 +312,6 @@ QWidget *QApplication::topLevelAt(const QPoint &pos) */ void qt_init_tooltip_palette(); -void qt_cleanup(); QStyle *QApplicationPrivate::app_style = nullptr; // default application style #ifndef QT_NO_STYLE_STYLESHEET @@ -353,8 +354,6 @@ Q_GLOBAL_STATIC(FontHash, app_fonts) // Exported accessor for use outside of this file FontHash *qt_app_fonts_hash() { return app_fonts(); } -QWidgetList *QApplicationPrivate::popupWidgets = nullptr; // has keyboard input focus - QWidget *qt_desktopWidget = nullptr; // root window widgets /*! @@ -496,8 +495,11 @@ void QApplicationPrivate::init() void qt_init_tooltip_palette() { #if QT_CONFIG(tooltip) - if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette)) - QToolTip::setPalette(*toolTipPalette); + if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette)) { + QPalette toolTipPal = *toolTipPalette; + toolTipPal.setResolveMask(0); + QToolTip::setPalette(toolTipPal); + } #endif } @@ -625,8 +627,8 @@ void QApplicationPrivate::initializeWidgetFontHash() QWidget *QApplication::activePopupWidget() { - return QApplicationPrivate::popupWidgets && !QApplicationPrivate::popupWidgets->isEmpty() ? - QApplicationPrivate::popupWidgets->constLast() : nullptr; + auto *win = qobject_cast<QWidgetWindow *>(QGuiApplicationPrivate::activePopupWindow()); + return win ? win->widget() : nullptr; } @@ -705,7 +707,10 @@ QApplication::~QApplication() d->cleanupMultitouch(); - qt_cleanup(); + QPixmapCache::clear(); + QColormap::cleanup(); + + QApplicationPrivate::active_window = nullptr; //### this should not be necessary if (QApplicationPrivate::widgetCount) qDebug("Widgets left: %i Max widgets: %i \n", QWidgetPrivate::instanceCounter, QWidgetPrivate::maxInstances); @@ -716,14 +721,6 @@ QApplication::~QApplication() QApplicationPrivate::widgetCount = false; } -void qt_cleanup() -{ - QPixmapCache::clear(); - QColormap::cleanup(); - - QApplicationPrivate::active_window = nullptr; //### this should not be necessary -} - /*! \fn QWidget *QApplication::widgetAt(const QPoint &point) @@ -789,6 +786,7 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis const QEvent::Type type = event->type(); switch (type) { case QEvent::UpdateRequest: + case QEvent::UpdateLater: case QEvent::LayoutRequest: case QEvent::Resize: case QEvent::Move: @@ -817,6 +815,10 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis static_cast<QMoveEvent *>(postedEvent.event)->m_pos = static_cast<const QMoveEvent *>(event)->pos(); break; + case QEvent::UpdateLater: + static_cast<QUpdateLaterEvent *>(postedEvent.event)->m_region += + static_cast<const QUpdateLaterEvent *>(event)->region(); + break; case QEvent::UpdateRequest: case QEvent::LanguageChange: case QEvent::LayoutRequest: @@ -1092,6 +1094,12 @@ QPalette QApplicationPrivate::basePalette() const if (const QPalette *themePalette = platformTheme() ? platformTheme()->palette() : nullptr) palette = themePalette->resolve(palette); + // This palette now is Qt-generated, so reset the resolve mask. This allows + // QStyle::polish implementations to respect palettes that are user provided, + // by checking if the palette has a brush set for a color that the style might + // otherwise overwrite. + palette.setResolveMask(0); + // Finish off by letting the application style polish the palette. This will // not result in the polished palette becoming a user-set palette, as the // resulting base palette is only used as a fallback, with the resolve mask @@ -1774,7 +1782,7 @@ void QApplicationPrivate::notifyLayoutDirectionChange() /*! \fn void QApplication::setActiveWindow(QWidget* active) - \deprecated Use QWidget::activateWindow() instead. + \deprecated [6.5] Use QWidget::activateWindow() instead. Sets the active window to the \a active widget in response to a system event. The function is called from the platform specific event handlers. @@ -1867,7 +1875,7 @@ void QApplicationPrivate::setActiveWindow(QWidget* act) QApplication::sendSpontaneousEvent(w, &activationChange); } - if (QApplicationPrivate::popupWidgets == nullptr) { // !inPopupMode() + if (!inPopupMode()) { // then focus events if (!QApplicationPrivate::active_window && QApplicationPrivate::focus_widget) { QApplicationPrivate::setFocusWidget(nullptr, Qt::ActiveWindowFocusReason); @@ -1967,7 +1975,7 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool f = toplevel; QWidget *w = f; - QWidget *test = f->d_func()->focus_next; + QWidget *test = f->nextInFocusChain(); bool seenWindow = false; bool focusWidgetAfterWindow = false; while (test && test != f) { @@ -1998,7 +2006,7 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool if (next) break; } - test = test->d_func()->focus_next; + test = test->nextInFocusChain(); } if (wrappingOccurred != nullptr) @@ -2023,19 +2031,6 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool */ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF) { -#if 0 - if (leave) { - QEvent e(QEvent::Leave); - QCoreApplication::sendEvent(leave, & e); - } - if (enter) { - const QPoint windowPos = enter->window()->mapFromGlobal(globalPos); - QEnterEvent e(enter->mapFromGlobal(globalPos), windowPos, globalPos); - QCoreApplication::sendEvent(enter, & e); - } - return; -#endif - if ((!enter && !leave) || (enter == leave)) return; @@ -2546,8 +2541,9 @@ int QApplication::startDragDistance() exec(), because modal widgets call exec() to start a local event loop. To make your application perform idle processing, i.e., executing a special - function whenever there are no pending events, use a QTimer with 0 timeout. - More advanced idle processing schemes can be achieved using processEvents(). + function whenever there are no pending events, use a QChronoTimer with 0ns + timeout. More advanced idle processing schemes can be achieved using + processEvents(). We recommend that you connect clean-up code to the \l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in your @@ -2656,6 +2652,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) Q_FALLTHROUGH(); case QEvent::Leave: d->toolTipWakeUp.stop(); + break; default: break; } @@ -2680,6 +2677,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) || key == Qt::Key_Up || key == Qt::Key_Right || key == Qt::Key_Down); + break; } default: break; @@ -2941,6 +2939,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) tablet->tangentialPressure(), tablet->rotation(), tablet->z(), tablet->modifiers(), tablet->button(), tablet->buttons()); te.m_spont = e->spontaneous(); + te.setTimestamp(tablet->timestamp()); te.setAccepted(false); res = d->notify_helper(w, w == receiver ? tablet : &te); eventAccepted = ((w == receiver) ? tablet : &te)->isAccepted(); @@ -3036,8 +3035,16 @@ bool QApplication::notify(QObject *receiver, QEvent *e) #endif w = qobject_cast<QWidget *>(QDragManager::self()->currentTarget()); - if (!w) - break; + if (!w) { + // The widget that received DragEnter didn't accept the event, so we have no + // current drag target in the QDragManager. But DragLeave still needs to be + // dispatched so that enter/leave events are in balance (and so that UnderMouse + // gets cleared). + if (e->type() == QEvent::DragLeave) + w = static_cast<QWidget *>(receiver); + else + break; + } if (e->type() == QEvent::DragMove || e->type() == QEvent::Drop) { QDropEvent *dragEvent = static_cast<QDropEvent *>(e); QWidget *origReceiver = static_cast<QWidget *>(receiver); @@ -3292,11 +3299,12 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e) bool QApplicationPrivate::inPopupMode() { - return QApplicationPrivate::popupWidgets != nullptr; + return QGuiApplicationPrivate::activePopupWindow() != nullptr; } static void ungrabKeyboardForPopup(QWidget *popup) { + qCDebug(lcWidgetPopup) << "ungrab keyboard for" << popup; if (QWidget::keyboardGrabber()) qt_widget_private(QWidget::keyboardGrabber())->stealKeyboardGrab(true); else @@ -3305,6 +3313,7 @@ static void ungrabKeyboardForPopup(QWidget *popup) static void ungrabMouseForPopup(QWidget *popup) { + qCDebug(lcWidgetPopup) << "ungrab mouse for" << popup; if (QWidget::mouseGrabber()) qt_widget_private(QWidget::mouseGrabber())->stealMouseGrab(true); else @@ -3324,54 +3333,23 @@ static void grabForPopup(QWidget *popup) ungrabKeyboardForPopup(popup); } } -} - -extern QWidget *qt_popup_down; -extern bool qt_replay_popup_mouse_event; -extern bool qt_popup_down_closed; - -bool QApplicationPrivate::closeAllPopups() -{ - // Close all popups: In case some popup refuses to close, - // we give up after 1024 attempts (to avoid an infinite loop). - int maxiter = 1024; - QWidget *popup; - while ((popup = QApplication::activePopupWidget()) && maxiter--) - popup->close(); // this will call QApplicationPrivate::closePopup - return true; + qCDebug(lcWidgetPopup) << "grabbed mouse and keyboard?" << popupGrabOk << "for popup" << popup; } void QApplicationPrivate::closePopup(QWidget *popup) { - if (!popupWidgets) + QWindow *win = popup->windowHandle(); + if (!win) + return; + if (!QGuiApplicationPrivate::closePopup(win)) return; - popupWidgets->removeAll(popup); - - if (popup == qt_popup_down) { - qt_button_down = nullptr; - qt_popup_down_closed = true; - qt_popup_down = nullptr; - } - if (QApplicationPrivate::popupWidgets->size() == 0) { // this was the last popup - delete QApplicationPrivate::popupWidgets; - QApplicationPrivate::popupWidgets = nullptr; - qt_popup_down_closed = false; + const QWindow *nextRemainingPopup = QGuiApplicationPrivate::activePopupWindow(); + if (!nextRemainingPopup) { // this was the last popup if (popupGrabOk) { popupGrabOk = false; - // TODO on multi-seat window systems, we have to know which mouse - auto devPriv = QPointingDevicePrivate::get(QPointingDevice::primaryPointingDevice()); - auto mousePressPos = devPriv->pointById(0)->eventPoint.globalPressPosition(); - if (popup->geometry().contains(mousePressPos.toPoint()) - || popup->testAttribute(Qt::WA_NoMouseReplay)) { - // mouse release event or inside - qt_replay_popup_mouse_event = false; - } else { // mouse press event - qt_replay_popup_mouse_event = true; - } - // transfer grab back to mouse grabber if any, otherwise release the grab ungrabMouseForPopup(popup); @@ -3390,30 +3368,23 @@ void QApplicationPrivate::closePopup(QWidget *popup) } } - } else { + } else if (const auto *popupWin = qobject_cast<const QWidgetWindow *>(nextRemainingPopup)) { // A popup was closed, so the previous popup gets the focus. - QWidget* aw = QApplicationPrivate::popupWidgets->constLast(); - if (QWidget *fw = aw->focusWidget()) + if (QWidget *fw = popupWin->widget()->focusWidget()) fw->setFocus(Qt::PopupFocusReason); // can become nullptr due to setFocus() above - if (QApplicationPrivate::popupWidgets && - QApplicationPrivate::popupWidgets->size() == 1) // grab mouse/keyboard - grabForPopup(aw); + if (QGuiApplicationPrivate::popupCount() == 1) // grab mouse/keyboard + grabForPopup(popupWin->widget()); } } -int openPopupCount = 0; - void QApplicationPrivate::openPopup(QWidget *popup) { - openPopupCount++; - if (!popupWidgets) // create list - popupWidgets = new QWidgetList; - popupWidgets->append(popup); // add to end of list + QGuiApplicationPrivate::activatePopup(popup->windowHandle()); - if (QApplicationPrivate::popupWidgets->size() == 1) // grab mouse/keyboard + if (QGuiApplicationPrivate::popupCount() == 1) // grab mouse/keyboard grabForPopup(popup); // popups are not focus-handled by the window system (the first @@ -3421,7 +3392,7 @@ void QApplicationPrivate::openPopup(QWidget *popup) // new popup gets the focus if (popup->focusWidget()) { popup->focusWidget()->setFocus(Qt::PopupFocusReason); - } else if (popupWidgets->size() == 1) { // this was the first popup + } else if (QGuiApplicationPrivate::popupCount() == 1) { // this was the first popup if (QWidget *fw = QApplication::focusWidget()) { QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason); QCoreApplication::sendEvent(fw, &e); |