From b1802a164b8682ed9e8956a5a19a90ade65c25d0 Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Wed, 19 Apr 2023 18:46:33 +0200 Subject: Handle parent being a child's focus procy in QWidget::setFocusProxy When a parent became a new child's focus proxy in an existing focus chain, the child was appended at the end of the chain. That leads to broken tab order, e.g. with a QComboBox which became editable after a focus chain has been set. This patch captures the case and insertes the new child after its parent in the focus chain. A corresponding test function is added in tst_QWidget. Fixes: QTBUG-111978 Pick-to: 6.5 Change-Id: I3a426c0560fa830b7b7ffead54f26dd0adef499f Reviewed-by: Volker Hilsheimer --- src/widgets/kernel/qwidget.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src/widgets') diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index cde0542eee..d5dbc3f21a 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -6412,6 +6412,30 @@ void QWidget::setFocusProxy(QWidget * w) d->focus_prev = oldPrev; oldPrev->d_func()->focus_next = this; firstChild->d_func()->focus_prev = this; + } else if (w->isAncestorOf(this)) { + // If the focus proxy is a parent, 'this' has to be inserted directly after its parent in the focus chain + // remove it from the chain and insert this into the focus chain after its parent + + // is this the case already? + QWidget *parentsNext = w->d_func()->focus_next; + if (parentsNext == this) { + // nothing to do. + Q_ASSERT(d->focus_prev == w); + } else { + // Remove 'this' from the focus chain by making prev and next point directly to each other + QWidget *myOldNext = d->focus_next; + QWidget *myOldPrev = d->focus_prev; + if (myOldNext && myOldPrev) { + myOldNext->d_func()->focus_prev = myOldPrev; + myOldPrev->d_func()->focus_next = myOldNext; + } + + // Insert 'this' behind the parent + w->d_func()->focus_next = this; + d->focus_prev = w; + d->focus_next = parentsNext; + parentsNext->d_func()->focus_prev = this; + } } if (moveFocusToProxy) -- cgit v1.2.3