summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel/qwidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/kernel/qwidget.cpp')
-rw-r--r--src/widgets/kernel/qwidget.cpp101
1 files changed, 68 insertions, 33 deletions
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index b28dcfc6f2..258e38d18c 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -515,7 +515,7 @@ void QWidget::setAutoFillBackground(bool enabled)
button is held down. This can be useful during drag and drop
operations. If you call \l{setMouseTracking()}{setMouseTracking}(true),
you get mouse move events even when no buttons are held down.
- (See also the \l{Drag and Drop} guide.)
+ (See also the \l{Drag and Drop in Qt}{Drag and Drop} guide.)
\li keyReleaseEvent() is called whenever a key is released and while it
is held down (if the key is auto-repeating). In that case, the
widget will receive a pair of key release and key press event for
@@ -1083,30 +1083,30 @@ static bool q_evaluateRhiConfigRecursive(const QWidget *w, QPlatformBackingStore
*outType = QBackingStoreRhiSupport::surfaceTypeForConfig(config);
return true;
}
- QObjectList children = w->children();
- for (int i = 0; i < children.size(); i++) {
- if (children.at(i)->isWidgetType()) {
- const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i));
- if (childWidget) {
- if (q_evaluateRhiConfigRecursive(childWidget, outConfig, outType))
- return true;
- }
+ for (const QObject *child : w->children()) {
+ if (const QWidget *childWidget = qobject_cast<const QWidget *>(child)) {
+ if (q_evaluateRhiConfigRecursive(childWidget, outConfig, outType))
+ return true;
}
}
return false;
}
-// First tries q_evaluateRhiConfigRecursive, then if that did not indicate that rhi is wanted,
-// then checks env.vars or something else to see if we need to force using rhi-based composition.
bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
{
- if (q_evaluateRhiConfigRecursive(w, outConfig, outType)) {
- qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluates to flushing with QRhi";
+ // First, check env.vars. or other means that force the usage of rhi-based
+ // flushing with a specific graphics API. This takes precedence over what
+ // the widgets themselves declare. This is global, applying to all
+ // top-levels.
+ if (QBackingStoreRhiSupport::checkForceRhi(outConfig, outType)) {
+ qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluated to forced flushing with QRhi";
return true;
}
- if (QBackingStoreRhiSupport::checkForceRhi(outConfig, outType)) {
- qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluated to forced flushing with QRhi";
+ // Otherwise, check the widget hierarchy to see if there is a child (or
+ // ourselves) that declare the need for rhi-based composition.
+ if (q_evaluateRhiConfigRecursive(w, outConfig, outType)) {
+ qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluates to flushing with QRhi";
return true;
}
@@ -1432,7 +1432,7 @@ QWidget::~QWidget()
#ifndef QT_NO_ACTION
// remove all actions from this widget
- for (auto action : qAsConst(d->actions)) {
+ for (auto action : std::as_const(d->actions)) {
QActionPrivate *apriv = action->d_func();
apriv->associatedObjects.removeAll(this);
}
@@ -2201,7 +2201,7 @@ void QWidgetPrivate::updateIsTranslucent()
if (QWindow *window = q->windowHandle()) {
QSurfaceFormat format = window->format();
const int oldAlpha = format.alphaBufferSize();
- const int newAlpha = q->testAttribute(Qt::WA_TranslucentBackground)? 8 : 0;
+ const int newAlpha = q->testAttribute(Qt::WA_TranslucentBackground) ? 8 : -1;
if (oldAlpha != newAlpha) {
// QTBUG-85714: Do this only when the QWindow has not yet been create()'ed yet.
//
@@ -3133,7 +3133,7 @@ void QWidget::addAction(QAction *action)
*/
void QWidget::addActions(const QList<QAction *> &actions)
{
- for(int i = 0; i < actions.count(); i++)
+ for(int i = 0; i < actions.size(); i++)
insertAction(nullptr, actions.at(i));
}
@@ -3182,7 +3182,7 @@ void QWidget::insertAction(QAction *before, QAction *action)
*/
void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
{
- for(int i = 0; i < actions.count(); ++i)
+ for(int i = 0; i < actions.size(); ++i)
insertAction(before, actions.at(i));
}
@@ -3431,7 +3431,7 @@ void QWidgetPrivate::setEnabled_helper(bool enable)
By default, this property is \c false.
- \sa {Drag and Drop}
+ \sa {Drag and Drop in Qt}{Drag and Drop}
*/
bool QWidget::acceptDrops() const
{
@@ -6381,6 +6381,33 @@ void QWidget::setFocusProxy(QWidget * w)
d->createExtra();
d->extra->focus_proxy = w;
+ if (w && isAncestorOf(w)) {
+ // If the focus proxy is a child of this (so this is a compound widget), then
+ // we need to make sure that this widget is immediately in front of its own children
+ // in the focus chain. Otherwise focusNextPrev_helper might jump over unrelated
+ // widgets that are positioned between this compound widget, and its proxy in
+ // the focus chain.
+ const QWidget *parentOfW = w->parentWidget();
+ Q_ASSERT(parentOfW); // can't be nullptr since we are an ancestor of w
+ QWidget *firstChild = nullptr;
+ const auto childList = children();
+ for (QObject *child : childList) {
+ if ((firstChild = qobject_cast<QWidget *>(child)))
+ break;
+ }
+ Q_ASSERT(firstChild); // can't be nullptr since w is a child
+ QWidget *oldNext = d->focus_next;
+ QWidget *oldPrev = d->focus_prev;
+ oldNext->d_func()->focus_prev = oldPrev;
+ oldPrev->d_func()->focus_next = oldNext;
+
+ oldPrev = firstChild->d_func()->focus_prev;
+ d->focus_next = firstChild;
+ d->focus_prev = oldPrev;
+ oldPrev->d_func()->focus_next = this;
+ firstChild->d_func()->focus_prev = this;
+ }
+
if (moveFocusToProxy)
setFocus(Qt::OtherFocusReason);
}
@@ -6516,15 +6543,11 @@ void QWidget::setFocus(Qt::FocusReason reason)
QApplicationPrivate::setFocusWidget(f, reason);
#if QT_CONFIG(accessibility)
- // If the widget gets focus because its window becomes active, then the accessibility
- // subsystem is already informed about the window opening, and also knows which child
- // within the window has focus. Don't interrupt it by emitting another focus event.
- if (reason != Qt::ActiveWindowFocusReason) {
- // menus update the focus manually and this would create bogus events
- if (!(f->inherits("QMenuBar") || f->inherits("QMenu") || f->inherits("QMenuItem"))) {
- QAccessibleEvent event(f, QAccessible::Focus);
- QAccessible::updateAccessibility(&event);
- }
+ // menus update the focus manually and this would create bogus events
+ if (!(f->inherits("QMenuBar") || f->inherits("QMenu") || f->inherits("QMenuItem")))
+ {
+ QAccessibleEvent event(f, QAccessible::Focus);
+ QAccessible::updateAccessibility(&event);
}
#endif
#if QT_CONFIG(graphicsview)
@@ -7076,8 +7099,8 @@ void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
n->d_func()->focus_next = topLevel;
} else {
//repair the new list
- n->d_func()->focus_next = q;
- focus_prev = n;
+ n->d_func()->focus_next = q;
+ focus_prev = n;
}
}
@@ -8339,6 +8362,7 @@ void QWidgetPrivate::showChildren(bool spontaneous)
void QWidgetPrivate::hideChildren(bool spontaneous)
{
+ Q_Q(QWidget);
QList<QObject*> childList = children;
for (int i = 0; i < childList.size(); ++i) {
QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
@@ -8370,6 +8394,14 @@ void QWidgetPrivate::hideChildren(bool spontaneous)
}
#endif
}
+
+ // If the window of this widget is not closed, then the leave event
+ // will eventually handle the widget under mouse use case.
+ // Otherwise, we need to explicitly handle it here.
+ if (QWidget* widgetWindow = q->window();
+ widgetWindow && widgetWindow->data->is_closing) {
+ q->setAttribute(Qt::WA_UnderMouse, false);
+ }
}
/*!
@@ -9004,7 +9036,7 @@ bool QWidget::event(QEvent *event)
break;
#if QT_CONFIG(menu)
case Qt::ActionsContextMenu:
- if (d->actions.count()) {
+ if (d->actions.size()) {
QMenu::exec(d->actions, static_cast<QContextMenuEvent *>(event)->globalPos(),
nullptr, this);
break;
@@ -9234,7 +9266,7 @@ bool QWidget::event(QEvent *event)
break;
case QEvent::DynamicPropertyChange: {
const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
- if (propName.length() == 13 && !qstrncmp(propName, "_q_customDpi", 12)) {
+ if (propName.size() == 13 && !qstrncmp(propName, "_q_customDpi", 12)) {
uint value = property(propName.constData()).toUInt();
if (!d->extra)
d->createExtra();
@@ -10691,6 +10723,9 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
QWidget *newtlw = window();
if (oldtlw != newtlw) {
QSurface::SurfaceType surfaceType = QSurface::RasterSurface;
+ // Only evaluate the reparented subtree. While it might be tempting to
+ // do it on newtlw instead, the performance implications of that are
+ // problematic when it comes to large widget trees.
if (q_evaluateRhiConfig(this, nullptr, &surfaceType)) {
newtlw->d_func()->usesRhiFlush = true;
if (QWindow *w = newtlw->windowHandle()) {