diff options
Diffstat (limited to 'src/widgets/kernel/qwidget.cpp')
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 195 |
1 files changed, 92 insertions, 103 deletions
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 1e249dc191..bcfae46155 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1138,7 +1138,7 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) q->data = &data; -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) if (!parent) { Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget", "Widgets must be created in the GUI thread."); @@ -1572,7 +1572,7 @@ QWidget::~QWidget() #endif #ifndef QT_NO_GESTURES - if (QGestureManager *manager = QGestureManager::instance()) { + if (QGestureManager *manager = QGestureManager::instance(QGestureManager::DontForceCreation)) { // \forall Qt::GestureType type : ungrabGesture(type) (inlined) for (auto it = d->gestureContext.keyBegin(), end = d->gestureContext.keyEnd(); it != end; ++it) manager->cleanupCachedGestures(this, *it); @@ -1580,9 +1580,6 @@ QWidget::~QWidget() d->gestureContext.clear(); #endif - // force acceptDrops false before winId is destroyed. - d->registerDropSite(false); - #ifndef QT_NO_ACTION // remove all actions from this widget for (int i = 0; i < d->actions.size(); ++i) { @@ -1778,7 +1775,6 @@ void QWidgetPrivate::createTLExtra() x->posIncludesFrame = 0; x->sizeAdjusted = false; x->inTopLevelResize = false; - x->inRepaint = false; x->embedded = 0; x->window = 0; x->shareContext = 0; @@ -1849,7 +1845,7 @@ void QWidgetPrivate::deleteExtra() deleteSysExtra(); #ifndef QT_NO_STYLE_STYLESHEET // dereference the stylesheet style - if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(extra->style)) + if (QStyleSheetStyle *proxy = qt_styleSheet(extra->style)) proxy->deref(); #endif if (extra->topextra) { @@ -1905,19 +1901,21 @@ void QWidgetPrivate::deleteTLSysExtra() } /* - Returns \c true if there are widgets above this which overlap with + Returns \c region of widgets above this which overlap with \a rect, which is in parent's coordinate system (same as crect). */ -bool QWidgetPrivate::isOverlapped(const QRect &rect) const +QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const { Q_Q(const QWidget); const QWidget *w = q; QRect r = rect; + QPoint p; + QRegion region; while (w) { if (w->isWindow()) - return false; + break; QWidgetPrivate *pd = w->parentWidget()->d_func(); bool above = false; for (int i = 0; i < pd->children.size(); ++i) { @@ -1929,19 +1927,23 @@ bool QWidgetPrivate::isOverlapped(const QRect &rect) const continue; } - if (qRectIntersects(sibling->d_func()->effectiveRectFor(sibling->data->crect), r)) { + const QRect siblingRect = sibling->d_func()->effectiveRectFor(sibling->data->crect); + if (qRectIntersects(siblingRect, r)) { const QWExtra *siblingExtra = sibling->d_func()->extra; if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) { continue; } - return true; + region += siblingRect.translated(-p); + if (breakAfterFirst) + break; } } w = w->parentWidget(); r.translate(pd->data.crect.topLeft()); + p += pd->data.crect.topLeft(); } - return false; + return region; } void QWidgetPrivate::syncBackingStore() @@ -2398,7 +2400,8 @@ static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrus #endif } else if (brush.gradient() - && brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode) { + && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode + || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) { painter->save(); painter->setClipRegion(rgn); painter->fillRect(0, 0, painter->device()->width(), painter->device()->height(), brush); @@ -2659,7 +2662,7 @@ void QWidget::setStyleSheet(const QString& styleSheet) return; d->createExtra(); - QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(d->extra->style); + QStyleSheetStyle *proxy = qt_styleSheet(d->extra->style); d->extra->styleSheet = styleSheet; if (styleSheet.isEmpty()) { // stylesheet removed if (!proxy) @@ -2724,12 +2727,12 @@ void QWidget::setStyle(QStyle *style) setAttribute(Qt::WA_SetStyle, style != 0); d->createExtra(); #ifndef QT_NO_STYLE_STYLESHEET - if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(style)) { + if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) { //if for some reason someone try to set a QStyleSheetStyle, ref it //(this may happen for exemple in QButtonDialogBox which propagates its style) - proxy->ref(); + styleSheetStyle->ref(); d->setStyle_helper(style, false); - } else if (qobject_cast<QStyleSheetStyle *>(d->extra->style) || !qApp->styleSheet().isEmpty()) { + } else if (qt_styleSheet(d->extra->style) || !qApp->styleSheet().isEmpty()) { // if we have an application stylesheet or have a proxy already, propagate d->setStyle_helper(new QStyleSheetStyle(style), true); } else @@ -2737,48 +2740,22 @@ void QWidget::setStyle(QStyle *style) d->setStyle_helper(style, false); } -void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate, bool -#if 0 // Used to be included in Qt4 for Q_WS_MAC - metalHack -#endif - ) +void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate) { Q_Q(QWidget); - QStyle *oldStyle = q->style(); -#ifndef QT_NO_STYLE_STYLESHEET - QPointer<QStyle> origStyle; -#endif + QStyle *oldStyle = q->style(); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // the metalhack boolean allows Qt/Mac to do a proper re-polish depending - // on how the Qt::WA_MacBrushedMetal attribute is set. It is only ever - // set when changing that attribute and passes the widget's CURRENT style. - // therefore no need to do a reassignment. - if (!metalHack) -#endif - { - createExtra(); + createExtra(); #ifndef QT_NO_STYLE_STYLESHEET - origStyle = extra->style.data(); + QPointer<QStyle> origStyle = extra->style; #endif - extra->style = newStyle; - } + extra->style = newStyle; // repolish - if (q->windowType() != Qt::Desktop) { - if (polished) { - oldStyle->unpolish(q); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (metalHack) - macUpdateMetalAttribute(); -#endif - q->style()->polish(q); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - } else if (metalHack) { - macUpdateMetalAttribute(); -#endif - } + if (polished && q->windowType() != Qt::Desktop) { + oldStyle->unpolish(q); + q->style()->polish(q); } if (propagate) { @@ -2792,8 +2769,8 @@ void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate, bool } #ifndef QT_NO_STYLE_STYLESHEET - if (!qobject_cast<QStyleSheetStyle*>(newStyle)) { - if (const QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(origStyle.data())) { + if (!qt_styleSheet(newStyle)) { + if (const QStyleSheetStyle* cssStyle = qt_styleSheet(origStyle)) { cssStyle->clearWidgetFont(q); } } @@ -2804,7 +2781,7 @@ void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate, bool #ifndef QT_NO_STYLE_STYLESHEET // dereference the old stylesheet style - if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(origStyle.data())) + if (QStyleSheetStyle *proxy = qt_styleSheet(origStyle)) proxy->deref(); #endif } @@ -2815,7 +2792,9 @@ void QWidgetPrivate::inheritStyle() #ifndef QT_NO_STYLE_STYLESHEET Q_Q(QWidget); - QStyleSheetStyle *proxy = extra ? qobject_cast<QStyleSheetStyle *>(extra->style) : 0; + QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr; + + QStyleSheetStyle *proxy = qt_styleSheet(extraStyle); if (!q->styleSheet().isEmpty()) { Q_ASSERT(proxy); @@ -2823,16 +2802,16 @@ void QWidgetPrivate::inheritStyle() return; } - QStyle *origStyle = proxy ? proxy->base : (extra ? (QStyle*)extra->style : 0); + QStyle *origStyle = proxy ? proxy->base : extraStyle; QWidget *parent = q->parentWidget(); QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : 0; // If we have stylesheet on app or parent has stylesheet style, we need // to be running a proxy - if (!qApp->styleSheet().isEmpty() || qobject_cast<QStyleSheetStyle *>(parentStyle)) { + if (!qApp->styleSheet().isEmpty() || qt_styleSheet(parentStyle)) { QStyle *newStyle = parentStyle; if (q->testAttribute(Qt::WA_SetStyle)) newStyle = new QStyleSheetStyle(origStyle); - else if (QStyleSheetStyle *newProxy = qobject_cast<QStyleSheetStyle *>(parentStyle)) + else if (QStyleSheetStyle *newProxy = qt_styleSheet(parentStyle)) newProxy->ref(); setStyle_helper(newStyle, true); @@ -2841,7 +2820,7 @@ void QWidgetPrivate::inheritStyle() // So, we have no stylesheet on parent/app and we have an empty stylesheet // we just need our original style back - if (origStyle == (extra ? (QStyle*)extra->style : 0)) // is it any different? + if (origStyle == extraStyle) // is it any different? return; // We could have inherited the proxy from our parent (which has a custom style) @@ -3480,11 +3459,6 @@ void QWidget::setAcceptDrops(bool on) } -void QWidgetPrivate::registerDropSite(bool on) -{ - Q_UNUSED(on); -} - /*! Disables widget input events if \a disable is true; otherwise enables input events. @@ -4514,16 +4488,14 @@ void QWidget::setForegroundRole(QPalette::ColorRole role) and these styles typically do not follow the palette. Because of this, assigning roles to a widget's palette is not guaranteed to change the appearance of the widget. Instead, you may choose to apply a \l - styleSheet. You can refer to our Knowledge Base article - \l{http://qt.nokia.com/developer/knowledgebase/22}{here} for more - information. + styleSheet. \warning Do not use this function in conjunction with \l{Qt Style Sheets}. When using style sheets, the palette of a widget can be customized using the "color", "background-color", "selection-color", "selection-background-color" and "alternate-background-color". - \sa QApplication::palette(), QWidget::font() + \sa QApplication::palette(), QWidget::font(), \l {Qt Style Sheets} */ const QPalette &QWidget::palette() const { @@ -4690,9 +4662,8 @@ void QWidget::setFont(const QFont &font) #ifndef QT_NO_STYLE_STYLESHEET const QStyleSheetStyle* style; - if (d->extra && (style = qobject_cast<const QStyleSheetStyle*>(d->extra->style))) { + if (d->extra && (style = qt_styleSheet(d->extra->style))) style->saveWidgetFont(this, font); - } #endif setAttribute(Qt::WA_SetFont, font.resolve() != 0); @@ -4788,7 +4759,7 @@ void QWidgetPrivate::updateFont(const QFont &font) Q_Q(QWidget); #ifndef QT_NO_STYLE_STYLESHEET const QStyleSheetStyle* cssStyle; - cssStyle = extra ? qobject_cast<const QStyleSheetStyle*>(extra->style) : 0; + cssStyle = extra ? qt_styleSheet(extra->style) : 0; const bool useStyleSheetPropagationInWidgetStyles = QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles); #endif @@ -5886,7 +5857,11 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint * pixmapOffset -= effectRect.topLeft(); - const qreal dpr = context->painter->device()->devicePixelRatioF(); + qreal dpr(1.0); + if (const auto *paintDevice = context->painter->device()) + dpr = paintDevice->devicePixelRatioF(); + else + qWarning("QWidgetEffectSourcePrivate::pixmap: Painter not active"); QPixmap pixmap(effectRect.size() * dpr); pixmap.setDevicePixelRatio(dpr); @@ -6617,17 +6592,25 @@ QWidget *QWidgetPrivate::deepestFocusProxy() const return focusProxy; } +static inline bool isEmbedded(const QWindow *w) +{ + const auto platformWindow = w->handle(); + return platformWindow && platformWindow->isEmbedded(); +} + void QWidgetPrivate::setFocus_sys() { Q_Q(QWidget); - // Embedded native widget may have taken the focus; get it back to toplevel if that is the case - const QWidget *topLevel = q->window(); - if (topLevel->windowType() != Qt::Popup) { - if (QWindow *nativeWindow = q->window()->windowHandle()) { - if (nativeWindow != QGuiApplication::focusWindow() - && q->testAttribute(Qt::WA_WState_Created)) { - nativeWindow->requestActivate(); - } + // Embedded native widget may have taken the focus; get it back to toplevel + // if that is the case (QTBUG-25852) + // Do not activate in case the popup menu opens another application (QTBUG-70810) + // unless the application is embedded (QTBUG-71991). + if (QWindow *nativeWindow = q->testAttribute(Qt::WA_WState_Created) ? q->window()->windowHandle() : nullptr) { + if (nativeWindow->type() != Qt::Popup && nativeWindow != QGuiApplication::focusWindow() + && (QGuiApplication::applicationState() == Qt::ApplicationActive + || QCoreApplication::testAttribute(Qt::AA_PluginApplication) + || isEmbedded(nativeWindow))) { + nativeWindow->requestActivate(); } } } @@ -6981,8 +6964,10 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second) determineLastFocusChild(second, lastFocusChildOfSecond); // If the tab order is already correct, exit early - if (lastFocusChildOfFirst->d_func()->focus_next == second) + if (lastFocusChildOfFirst == second || + lastFocusChildOfFirst->d_func()->focus_next == second) { return; + } // Note that we need to handle two different sections in the tab chain; The section // that 'first' belongs to (firstSection), where we are about to insert 'second', and @@ -7381,7 +7366,8 @@ QByteArray QWidget::saveGeometry() const // Version history: // - Qt 4.2 - 4.8.6, 5.0 - 5.3 : Version 1.0 // - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling. - quint16 majorVersion = 2; + // - Qt 5.12 - today : Version 3.0, save QWidget::geometry() + quint16 majorVersion = 3; quint16 minorVersion = 0; const int screenNumber = QDesktopWidgetPrivate::screenNumber(this); stream << magicNumber @@ -7397,7 +7383,8 @@ QByteArray QWidget::saveGeometry() const << qint32(screenNumber) << quint8(windowState() & Qt::WindowMaximized) << quint8(windowState() & Qt::WindowFullScreen) - << qint32(QDesktopWidgetPrivate::screenGeometry(screenNumber).width()); // 1.1 onwards + << qint32(QDesktopWidgetPrivate::screenGeometry(screenNumber).width()) // added in 2.0 + << geometry(); // added in 3.0 return array; } @@ -7437,7 +7424,7 @@ bool QWidget::restoreGeometry(const QByteArray &geometry) if (storedMagicNumber != magicNumber) return false; - const quint16 currentMajorVersion = 2; + const quint16 currentMajorVersion = 3; quint16 majorVersion = 0; quint16 minorVersion = 0; @@ -7448,7 +7435,8 @@ bool QWidget::restoreGeometry(const QByteArray &geometry) // (Allow all minor versions.) QRect restoredFrameGeometry; - QRect restoredNormalGeometry; + QRect restoredGeometry; + QRect restoredNormalGeometry; qint32 restoredScreenNumber; quint8 maximized; quint8 fullScreen; @@ -7462,6 +7450,10 @@ bool QWidget::restoreGeometry(const QByteArray &geometry) if (majorVersion > 1) stream >> restoredScreenWidth; + if (majorVersion > 2) + stream >> restoredGeometry; + + // ### Qt 6 - Perhaps it makes sense to dumb down the restoreGeometry() logic, see QTBUG-69104 if (restoredScreenNumber >= QDesktopWidgetPrivate::numScreens()) restoredScreenNumber = QDesktopWidgetPrivate::primaryScreen(); @@ -7548,14 +7540,11 @@ bool QWidget::restoreGeometry(const QByteArray &geometry) setWindowState(ws); d_func()->topData()->normalGeometry = restoredNormalGeometry; } else { - QPoint offset; -#if 0 // Used to be included in Qt4 for Q_WS_X11 - if (isFullScreen()) - offset = d_func()->topData()->fullScreenOffset; -#endif setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen)); - move(restoredFrameGeometry.topLeft() + offset); - resize(restoredNormalGeometry.size()); + if (majorVersion > 2) + setGeometry(restoredGeometry); + else + setGeometry(restoredNormalGeometry); } return true; } @@ -10107,20 +10096,24 @@ void QWidget::hideEvent(QHideEvent *) which are passed in the \a message parameter. In your reimplementation of this function, if you want to stop the - event being handled by Qt, return true and set \a result. - If you return false, this native event is passed back to Qt, - which translates the event into a Qt event and sends it to the widget. + event being handled by Qt, return true and set \a result. The \a result + parameter has meaning only on Windows. If you return false, this native + event is passed back to Qt, which translates the event into a Qt event + and sends it to the widget. - \note Events are only delivered to this event handler if the widget is - has a native Window handle. + \note Events are only delivered to this event handler if the widget + has a native window handle. \note This function superseedes the event filter functions x11Event(), winEvent() and macEvent() of Qt 4. + \sa QAbstractNativeEventFilter + \table \header \li Platform \li Event Type Identifier \li Message Type \li Result Type \row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT \row \li macOS \li "NSEvent" \li NSEvent * \li + \row \li XCB \li "xcb_generic_event_t" \li xcb_generic_event_t * \li \endtable */ @@ -11044,11 +11037,8 @@ void QWidgetPrivate::repaint(T r) return; QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); - if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) { - tlwExtra->inRepaint = true; + if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) tlwExtra->backingStoreTracker->markDirty(r, q, QWidgetBackingStore::UpdateNow); - tlwExtra->inRepaint = false; - } } /*! @@ -11214,7 +11204,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) break; } case Qt::WA_DropSiteRegistered: { - d->registerDropSite(on); for (int i = 0; i < d->children.size(); ++i) { QWidget *w = qobject_cast<QWidget *>(d->children.at(i)); if (w && !w->isWindow() && !w->testAttribute(Qt::WA_AcceptDrops) && w->testAttribute(Qt::WA_DropSiteRegistered) != on) |