diff options
Diffstat (limited to 'src/widgets/kernel')
-rw-r--r-- | src/widgets/kernel/qapplication.cpp | 55 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication_p.h | 2 | ||||
-rw-r--r-- | src/widgets/kernel/qgesture.cpp | 4 | ||||
-rw-r--r-- | src/widgets/kernel/qlayout.cpp | 20 | ||||
-rw-r--r-- | src/widgets/kernel/qlayout.h | 1 | ||||
-rw-r--r-- | src/widgets/kernel/qmacgesturerecognizer_p.h | 18 | ||||
-rw-r--r-- | src/widgets/kernel/qshortcut.cpp | 12 | ||||
-rw-r--r-- | src/widgets/kernel/qtooltip.cpp | 40 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 93 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget_p.h | 4 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetbackingstore.cpp | 84 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetwindow.cpp | 1 |
12 files changed, 208 insertions, 126 deletions
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 404bebd40c..122d94d152 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -1023,17 +1023,17 @@ QString QApplication::styleSheet() const void QApplication::setStyleSheet(const QString& styleSheet) { QApplicationPrivate::styleSheet = styleSheet; - QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle*>(QApplicationPrivate::app_style); + QStyleSheetStyle *styleSheetStyle = qt_styleSheet(QApplicationPrivate::app_style); if (styleSheet.isEmpty()) { // application style sheet removed - if (!proxy) + if (!styleSheetStyle) return; // there was no stylesheet before - setStyle(proxy->base); - } else if (proxy) { // style sheet update, just repolish - proxy->repolish(qApp); + setStyle(styleSheetStyle->base); + } else if (styleSheetStyle) { // style sheet update, just repolish + styleSheetStyle->repolish(qApp); } else { // stylesheet set the first time - QStyleSheetStyle *newProxy = new QStyleSheetStyle(QApplicationPrivate::app_style); - QApplicationPrivate::app_style->setParent(newProxy); - setStyle(newProxy); + QStyleSheetStyle *newStyleSheetStyle = new QStyleSheetStyle(QApplicationPrivate::app_style); + QApplicationPrivate::app_style->setParent(newStyleSheetStyle); + setStyle(newStyleSheetStyle); } } @@ -1143,11 +1143,11 @@ void QApplication::setStyle(QStyle *style) QStyle *old = QApplicationPrivate::app_style; // save #ifndef QT_NO_STYLE_STYLESHEET - if (!QApplicationPrivate::styleSheet.isEmpty() && !qobject_cast<QStyleSheetStyle *>(style)) { + if (!QApplicationPrivate::styleSheet.isEmpty() && !qt_styleSheet(style)) { // we have a stylesheet already and a new style is being set - QStyleSheetStyle *newProxy = new QStyleSheetStyle(style); - style->setParent(newProxy); - QApplicationPrivate::app_style = newProxy; + QStyleSheetStyle *newStyleSheetStyle = new QStyleSheetStyle(style); + style->setParent(newStyleSheetStyle); + QApplicationPrivate::app_style = newStyleSheetStyle; } else #endif // QT_NO_STYLE_STYLESHEET QApplicationPrivate::app_style = style; @@ -1197,8 +1197,8 @@ void QApplication::setStyle(QStyle *style) } #ifndef QT_NO_STYLE_STYLESHEET - if (QStyleSheetStyle *oldProxy = qobject_cast<QStyleSheetStyle *>(old)) { - oldProxy->deref(); + if (QStyleSheetStyle *oldStyleSheetStyle = qt_styleSheet(old)) { + oldStyleSheetStyle->deref(); } else #endif if (old && old->parent() == qApp) { @@ -2625,7 +2625,7 @@ QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget, QWidget *nativeWidget, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver, - bool spontaneous) + bool spontaneous, bool onlyDispatchEnterLeave) { Q_ASSERT(receiver); Q_ASSERT(event); @@ -2686,11 +2686,17 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, // We need this quard in case someone opens a modal dialog / popup. If that's the case // leaveAfterRelease is set to null, but we shall not update lastMouseReceiver. const bool wasLeaveAfterRelease = leaveAfterRelease != 0; - bool result; - if (spontaneous) - result = QApplication::sendSpontaneousEvent(receiver, event); - else - result = QApplication::sendEvent(receiver, event); + bool result = true; + // This code is used for sending the synthetic enter/leave events for cases where it is needed + // due to other events causing the widget under the mouse to change. However in those cases + // we do not want to send the mouse event associated with this call, so this enables us to + // not send the unneeded mouse event + if (!onlyDispatchEnterLeave) { + if (spontaneous) + result = QApplication::sendSpontaneousEvent(receiver, event); + else + result = QApplication::sendEvent(receiver, event); + } if (!graphicsWidget && leaveAfterRelease && event->type() == QEvent::MouseButtonRelease && !event->buttons() && QWidget::mouseGrabber() != leaveAfterRelease) { @@ -2765,9 +2771,10 @@ void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget) if (widget->data->in_destructor && qt_button_down == widget) qt_button_down = 0; - // Send enter/leave events followed by a mouse move on the entered widget. + // A mouse move is not actually sent, but we utilize the sendMouseEvent() call to send the + // enter/leave events as appropriate QMouseEvent e(QEvent::MouseMove, pos, windowPos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier); - sendMouseEvent(widgetUnderCursor, &e, widgetUnderCursor, tlw, &qt_button_down, qt_last_mouse_receiver); + sendMouseEvent(widgetUnderCursor, &e, widgetUnderCursor, tlw, &qt_button_down, qt_last_mouse_receiver, true, true); #else // !QT_NO_CURSOR Q_UNUSED(widget); #endif // QT_NO_CURSOR @@ -3286,6 +3293,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), wheel->modifiers(), phase, wheel->source(), wheel->inverted()); + we.setTimestamp(wheel->timestamp()); bool eventAccepted; do { we.spont = spontaneous && w == receiver; @@ -3322,6 +3330,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) const QPoint &relpos = QApplicationPrivate::wheel_widget->mapFromGlobal(wheel->globalPos()); QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), wheel->modifiers(), wheel->phase(), wheel->source()); + we.setTimestamp(wheel->timestamp()); we.spont = true; we.ignore(); d->notify_helper(QApplicationPrivate::wheel_widget, &we); @@ -3647,7 +3656,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) break; w = w->parentWidget(); } - foreach (QGesture *g, allGestures) + for (QGesture *g : qAsConst(allGestures)) gestureEvent->setAccepted(g, false); gestureEvent->m_accept = false; // to make sure we check individual gestures } else { diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 019fad3fc3..21ba47caa3 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -226,7 +226,7 @@ public: QWidget *buttonDown, QWidget *alienWidget); static bool sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget, QWidget *native, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver, - bool spontaneous = true); + bool spontaneous = true, bool onlyDispatchEnterLeave = false); void sendSyntheticEnterLeave(QWidget *widget); static QWindow *windowForWidget(const QWidget *widget) diff --git a/src/widgets/kernel/qgesture.cpp b/src/widgets/kernel/qgesture.cpp index 7f8bf18e90..fc715687c6 100644 --- a/src/widgets/kernel/qgesture.cpp +++ b/src/widgets/kernel/qgesture.cpp @@ -916,7 +916,7 @@ QGesture *QGestureEvent::gesture(Qt::GestureType type) const QList<QGesture *> QGestureEvent::activeGestures() const { QList<QGesture *> gestures; - foreach (QGesture *gesture, m_gestures) { + for (QGesture *gesture : m_gestures) { if (gesture->state() != Qt::GestureCanceled) gestures.append(gesture); } @@ -929,7 +929,7 @@ QList<QGesture *> QGestureEvent::activeGestures() const QList<QGesture *> QGestureEvent::canceledGestures() const { QList<QGesture *> gestures; - foreach (QGesture *gesture, m_gestures) { + for (QGesture *gesture : m_gestures) { if (gesture->state() == Qt::GestureCanceled) gestures.append(gesture); } diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp index 9ce1c1c2d4..80ea27fee8 100644 --- a/src/widgets/kernel/qlayout.cpp +++ b/src/widgets/kernel/qlayout.cpp @@ -1246,6 +1246,26 @@ int QLayout::indexOf(QWidget *widget) const } /*! + \since 5.12 + Searches for layout item \a layoutItem in this layout (not including child + layouts). + + Returns the index of \a layoutItem, or -1 if \a layoutItem is not found. +*/ +int QLayout::indexOf(QLayoutItem *layoutItem) const +{ + int i = 0; + QLayoutItem *item = itemAt(i); + while (item) { + if (item == layoutItem) + return i; + ++i; + item = itemAt(i); + } + return -1; +} + +/*! \enum QLayout::SizeConstraint The possible values are: diff --git a/src/widgets/kernel/qlayout.h b/src/widgets/kernel/qlayout.h index bcc33a0811..616f4e7164 100644 --- a/src/widgets/kernel/qlayout.h +++ b/src/widgets/kernel/qlayout.h @@ -122,6 +122,7 @@ public: virtual QLayoutItem *itemAt(int index) const = 0; virtual QLayoutItem *takeAt(int index) = 0; virtual int indexOf(QWidget *) const; + QT6_VIRTUAL int indexOf(QLayoutItem *) const; virtual int count() const = 0; bool isEmpty() const override; QSizePolicy::ControlTypes controlTypes() const override; diff --git a/src/widgets/kernel/qmacgesturerecognizer_p.h b/src/widgets/kernel/qmacgesturerecognizer_p.h index e381a6cc2f..739fc201b7 100644 --- a/src/widgets/kernel/qmacgesturerecognizer_p.h +++ b/src/widgets/kernel/qmacgesturerecognizer_p.h @@ -66,9 +66,9 @@ class QMacSwipeGestureRecognizer : public QGestureRecognizer public: QMacSwipeGestureRecognizer(); - QGesture *create(QObject *target); - QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event); - void reset(QGesture *gesture); + QGesture *create(QObject *target) override; + QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event) override; + void reset(QGesture *gesture) override; }; class QMacPinchGestureRecognizer : public QGestureRecognizer @@ -76,9 +76,9 @@ class QMacPinchGestureRecognizer : public QGestureRecognizer public: QMacPinchGestureRecognizer(); - QGesture *create(QObject *target); - QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event); - void reset(QGesture *gesture); + QGesture *create(QObject *target) override; + QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event) override; + void reset(QGesture *gesture) override; }; class QMacPanGestureRecognizer : public QObject, public QGestureRecognizer @@ -86,9 +86,9 @@ class QMacPanGestureRecognizer : public QObject, public QGestureRecognizer public: QMacPanGestureRecognizer(); - QGesture *create(QObject *target); - QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event); - void reset(QGesture *gesture); + QGesture *create(QObject *target) override; + QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event) override; + void reset(QGesture *gesture) override; protected: void timerEvent(QTimerEvent *ev) override; private: diff --git a/src/widgets/kernel/qshortcut.cpp b/src/widgets/kernel/qshortcut.cpp index fde039c75e..a680ff7913 100644 --- a/src/widgets/kernel/qshortcut.cpp +++ b/src/widgets/kernel/qshortcut.cpp @@ -149,8 +149,16 @@ static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidge bool visible = w->isVisible(); #if QT_CONFIG(menubar) if (QMenuBar *menuBar = qobject_cast<QMenuBar *>(w)) { - if (menuBar->isNativeMenuBar()) - visible = true; + if (auto *pmb = menuBar->platformMenuBar()) { + if (menuBar->parentWidget()) { + visible = true; + } else { + if (auto *ww = qobject_cast<QWidgetWindow *>(pmb->parentWindow())) + w = ww->widget(); // Good enough since we only care about the window + else + return false; // This is not a QWidget window. We won't deliver + } + } } #endif diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp index ed7184302a..e9a682fabf 100644 --- a/src/widgets/kernel/qtooltip.cpp +++ b/src/widgets/kernel/qtooltip.cpp @@ -123,11 +123,11 @@ class QTipLabel : public QLabel { Q_OBJECT public: - QTipLabel(const QString &text, QWidget *w, int msecDisplayTime); + QTipLabel(const QString &text, const QPoint &pos, QWidget *w, int msecDisplayTime); ~QTipLabel(); static QTipLabel *instance; - void updateSize(); + void updateSize(const QPoint &pos); bool eventFilter(QObject *, QEvent *) override; @@ -135,7 +135,7 @@ public: bool fadingOut; - void reuseTip(const QString &text, int msecDisplayTime); + void reuseTip(const QString &text, int msecDisplayTime, const QPoint &pos); void hideTip(); void hideTipImmediately(); void setTipRect(QWidget *w, const QRect &r); @@ -171,7 +171,7 @@ private: QTipLabel *QTipLabel::instance = 0; -QTipLabel::QTipLabel(const QString &text, QWidget *w, int msecDisplayTime) +QTipLabel::QTipLabel(const QString &text, const QPoint &pos, QWidget *w, int msecDisplayTime) #ifndef QT_NO_STYLE_STYLESHEET : QLabel(w, Qt::ToolTip | Qt::BypassGraphicsProxyWidget), styleSheetParent(0), widget(0) #else @@ -192,7 +192,7 @@ QTipLabel::QTipLabel(const QString &text, QWidget *w, int msecDisplayTime) setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / 255.0); setMouseTracking(true); fadingOut = false; - reuseTip(text, msecDisplayTime); + reuseTip(text, msecDisplayTime, pos); } void QTipLabel::restartExpireTimer(int msecDisplayTime) @@ -204,7 +204,7 @@ void QTipLabel::restartExpireTimer(int msecDisplayTime) hideTimer.stop(); } -void QTipLabel::reuseTip(const QString &text, int msecDisplayTime) +void QTipLabel::reuseTip(const QString &text, int msecDisplayTime, const QPoint &pos) { #ifndef QT_NO_STYLE_STYLESHEET if (styleSheetParent){ @@ -214,20 +214,30 @@ void QTipLabel::reuseTip(const QString &text, int msecDisplayTime) } #endif - setWordWrap(Qt::mightBeRichText(text)); + setWordWrap(true); setText(text); - updateSize(); + updateSize(pos); restartExpireTimer(msecDisplayTime); } -void QTipLabel::updateSize() +void QTipLabel::updateSize(const QPoint &pos) { QFontMetrics fm(font()); QSize extra(1, 0); // Make it look good with the default ToolTip font on Mac, which has a small descent. if (fm.descent() == 2 && fm.ascent() >= 11) ++extra.rheight(); - resize(sizeHint() + extra); + QSize sh = sizeHint(); + if (wordWrap()) { + const QRect screenRect = QApplication::desktop()->screenGeometry(pos); + if (sh.width() > screenRect.width()) { + // Try to use widely accepted 75chars max length or 80% of the screen width else. + // See https://en.wikipedia.org/wiki/Line_length + sh.setWidth(qMin(fm.averageCharWidth() * 75, static_cast<int>(screenRect.width() * .8))); + sh.setHeight(heightForWidth(sh.width())); + } + } + resize(sh + extra); } void QTipLabel::paintEvent(QPaintEvent *ev) @@ -381,7 +391,7 @@ int QTipLabel::getTipScreen(const QPoint &pos, QWidget *w) void QTipLabel::placeTip(const QPoint &pos, QWidget *w) { #ifndef QT_NO_STYLE_STYLESHEET - if (testAttribute(Qt::WA_StyleSheet) || (w && qobject_cast<QStyleSheetStyle *>(w->style()))) { + if (testAttribute(Qt::WA_StyleSheet) || (w && qt_styleSheet(w->style()))) { //the stylesheet need to know the real parent QTipLabel::instance->setProperty("_q_stylesheet_parent", QVariant::fromValue(w)); //we force the style to be the QStyleSheetStyle, and force to clear the cache as well. @@ -394,7 +404,7 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w) QTipLabel::instance, SLOT(styleSheetParentDestroyed())); // QTBUG-64550: A font inherited by the style sheet might change the size, // particular on Windows, where the tip is not parented on a window. - QTipLabel::instance->updateSize(); + QTipLabel::instance->updateSize(pos); } } #endif //QT_NO_STYLE_STYLESHEET @@ -497,7 +507,7 @@ void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, cons if (w) localPos = w->mapFromGlobal(pos); if (QTipLabel::instance->tipChanged(localPos, text, w)){ - QTipLabel::instance->reuseTip(text, msecDisplayTime); + QTipLabel::instance->reuseTip(text, msecDisplayTime, pos); QTipLabel::instance->setTipRect(w, rect); QTipLabel::instance->placeTip(pos, w); } @@ -511,10 +521,10 @@ void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, cons // raised when the tooltip will be shown QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED - new QTipLabel(text, QApplication::desktop()->screen(QTipLabel::getTipScreen(pos, w)), msecDisplayTime); + new QTipLabel(text, pos, QApplication::desktop()->screen(QTipLabel::getTipScreen(pos, w)), msecDisplayTime); QT_WARNING_POP #else - new QTipLabel(text, w, msecDisplayTime); // sets QTipLabel::instance to itself + new QTipLabel(text, pos, w, msecDisplayTime); // sets QTipLabel::instance to itself #endif QTipLabel::instance->setTipRect(w, rect); QTipLabel::instance->placeTip(pos, w); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index a86834002c..6b3fad6b5f 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1848,7 +1848,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) { @@ -1904,19 +1904,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) { @@ -1928,19 +1930,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() @@ -2658,7 +2664,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) @@ -2723,12 +2729,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 @@ -2736,48 +2742,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) { @@ -2791,8 +2771,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); } } @@ -2803,7 +2783,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 } @@ -2814,7 +2794,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); @@ -2822,16 +2804,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); @@ -2840,7 +2822,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) @@ -4689,9 +4671,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); @@ -4787,7 +4768,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 diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index a9c73c6a26..fae9e5ff4e 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -395,7 +395,7 @@ public: void setLocale_helper(const QLocale &l, bool forceUpdate = false); void resolveLocale(); - void setStyle_helper(QStyle *newStyle, bool propagate, bool metalHack = false); + void setStyle_helper(QStyle *newStyle, bool propagate); void inheritStyle(); void setUpdatesEnabled_helper(bool ); @@ -453,7 +453,7 @@ public: // ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore). void invalidateBuffer(const QRegion &); void invalidateBuffer(const QRect &); - bool isOverlapped(const QRect&) const; + QRegion overlappedRegion(const QRect &rect, bool breakAfterFirst = false) const; void syncBackingStore(); void syncBackingStore(const QRegion ®ion); diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 3b093283cd..768406f361 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -59,6 +59,7 @@ #include <private/qgraphicseffect_p.h> #endif #include <QtGui/private/qwindow_p.h> +#include <QtGui/private/qhighdpiscaling_p.h> #include <qpa/qplatformbackingstore.h> @@ -793,6 +794,24 @@ QWidgetBackingStore::~QWidgetBackingStore() delete dirtyOnScreenWidgets; } +static QVector<QRect> getSortedRectsToScroll(const QRegion ®ion, int dx, int dy) +{ + QVector<QRect> rects = region.rects(); + if (rects.count() > 1) { + std::sort(rects.begin(), rects.end(), [=](const QRect &r1, const QRect &r2) { + if (r1.y() == r2.y()) { + if (dx > 0) + return r1.x() > r2.x(); + return r1.x() < r2.x(); + } + if (dy > 0) + return r1.y() > r2.y(); + return r1.y() < r2.y(); + }); + } + return rects; +} + //parent's coordinates; move whole rect; update parent and widget //assume the screen blt has already been done, so we don't need to refresh that part void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) @@ -820,12 +839,12 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) const QRect parentRect(rect & clipR); const bool nativeWithTextureChild = textureChildSeen && q->internalWinId(); - bool accelerateMove = accelEnv && isOpaque && !nativeWithTextureChild + const bool accelerateMove = accelEnv && isOpaque && !nativeWithTextureChild #if QT_CONFIG(graphicsview) // No accelerate move for proxy widgets. && !tlw->d_func()->extra->proxyWidget #endif - && !isOverlapped(sourceRect) && !isOverlapped(destRect); + ; if (!accelerateMove) { QRegion parentR(effectiveRectFor(parentRect)); @@ -841,18 +860,39 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) QWidgetBackingStore *wbs = x->backingStoreTracker.data(); QRegion childExpose(newRect & clipR); + QRegion overlappedExpose; - if (sourceRect.isValid() && wbs->bltRect(sourceRect, dx, dy, pw)) - childExpose -= destRect; + if (sourceRect.isValid()) { + overlappedExpose = (overlappedRegion(sourceRect) | overlappedRegion(destRect)) & clipR; + + const qreal factor = QHighDpiScaling::factor(q->windowHandle()); + if (overlappedExpose.isEmpty() || qFloor(factor) == factor) { + const QVector<QRect> rectsToScroll + = getSortedRectsToScroll(QRegion(sourceRect) - overlappedExpose, dx, dy); + for (QRect rect : rectsToScroll) { + if (wbs->bltRect(rect, dx, dy, pw)) { + childExpose -= rect.translated(dx, dy); + } + } + } + + childExpose -= overlappedExpose; + } if (!pw->updatesEnabled()) return; const bool childUpdatesEnabled = q->updatesEnabled(); - if (childUpdatesEnabled && !childExpose.isEmpty()) { - childExpose.translate(-data.crect.topLeft()); - wbs->markDirty(childExpose, q); - isMoved = true; + if (childUpdatesEnabled) { + if (!overlappedExpose.isEmpty()) { + overlappedExpose.translate(-data.crect.topLeft()); + invalidateBuffer(overlappedExpose); + } + if (!childExpose.isEmpty()) { + childExpose.translate(-data.crect.topLeft()); + wbs->markDirty(childExpose, q); + isMoved = true; + } } QRegion parentExpose(parentRect); @@ -888,13 +928,12 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) static const bool accelEnv = qEnvironmentVariableIntValue("QT_NO_FAST_SCROLL") == 0; - QRect scrollRect = rect & clipRect(); - bool overlapped = false; - bool accelerateScroll = accelEnv && isOpaque && !q_func()->testAttribute(Qt::WA_WState_InPaintEvent) - && !(overlapped = isOverlapped(scrollRect.translated(data.crect.topLeft()))); + const QRect clipR = clipRect(); + const QRect scrollRect = rect & clipR; + const bool accelerateScroll = accelEnv && isOpaque && !q_func()->testAttribute(Qt::WA_WState_InPaintEvent); if (!accelerateScroll) { - if (overlapped) { + if (!overlappedRegion(scrollRect.translated(data.crect.topLeft()), true).isEmpty()) { QRegion region(scrollRect); subtractOpaqueSiblings(region); invalidateBuffer(region); @@ -906,12 +945,23 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) const QRect destRect = scrollRect.translated(dx, dy) & scrollRect; const QRect sourceRect = destRect.translated(-dx, -dy); + const QRegion overlappedExpose = (overlappedRegion(scrollRect.translated(data.crect.topLeft()))) + .translated(-data.crect.topLeft()) & clipR; QRegion childExpose(scrollRect); - if (sourceRect.isValid()) { - if (wbs->bltRect(sourceRect, dx, dy, q)) - childExpose -= destRect; + + const qreal factor = QHighDpiScaling::factor(q->windowHandle()); + if (overlappedExpose.isEmpty() || qFloor(factor) == factor) { + const QVector<QRect> rectsToScroll + = getSortedRectsToScroll(QRegion(sourceRect) - overlappedExpose, dx, dy); + for (const QRect &rect : rectsToScroll) { + if (wbs->bltRect(rect, dx, dy, q)) { + childExpose -= rect.translated(dx, dy); + } + } } + childExpose -= overlappedExpose; + if (inDirtyList) { if (rect == q->rect()) { dirty.translate(dx, dy); @@ -928,6 +978,8 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) if (!q->updatesEnabled()) return; + if (!overlappedExpose.isEmpty()) + invalidateBuffer(overlappedExpose); if (!childExpose.isEmpty()) { wbs->markDirty(childExpose, q); isScrolled = true; diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 949076b260..fd76c8b69e 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -841,6 +841,7 @@ void QWidgetWindow::handleWheelEvent(QWheelEvent *event) QPoint mapped = widget->mapFrom(rootWidget, pos); QWheelEvent translated(mapped, event->globalPos(), event->pixelDelta(), event->angleDelta(), event->delta(), event->orientation(), event->buttons(), event->modifiers(), event->phase(), event->source(), event->inverted()); + translated.setTimestamp(event->timestamp()); QGuiApplication::forwardEvent(widget, &translated, event); } |