QWidgetWindow::setFocusToTarget: Respect focus policies and proxies

When calling QWidgetWindowPrivate::setFocusToTarget with Prev or Next
target parameter, we were just setting focus to the
next/prevInFocusChain() of the window's focusWidget(). This will bypass
focus proxies and focus policies of the widget, which is wrong as it
can end up giving eg: tab focus to a widget that does not have such
focus policy.
To fix, we should instead call QWidget::focusNextPrevChild which
determines the right next/prev in the TAB focus chain. As this is a
protected member of QWidget, implement a "wrapper" for it in
QWidgetWindow which is a friend class of QWidget.

Task-number: QTBUG-121789
Change-Id: I1f4f5d85e7552926580906fdef6f0a456fe7486c
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
Reviewed-by: MohammadHossein Qanbari <mohammad.qanbari@qt.io>
(cherry picked from commit 926d3287aba9fe2b67c25d0c0c5b606f3f41803e)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Doris Verria 2024-09-24 14:12:02 +02:00 committed by Qt Cherry-pick Bot
parent 5e090d4b9b
commit 3b1951cd1b
2 changed files with 18 additions and 15 deletions

View File

@ -82,31 +82,26 @@ public:
QWidget *widget = q->widget();
if (!widget)
return;
QWidget *newFocusWidget = nullptr;
switch (target) {
case FocusTarget::First:
newFocusWidget = q->getFocusWidget(QWidgetWindow::FirstFocusWidget);
break;
case FocusTarget::Last:
newFocusWidget = q->getFocusWidget(QWidgetWindow::LastFocusWidget);
break;
case FocusTarget::Prev:
case FocusTarget::Next: {
QWidget *focusWidget = widget->focusWidget() ? widget->focusWidget() : widget;
newFocusWidget = focusWidget->nextInFocusChain() ? focusWidget->nextInFocusChain() : focusWidget;
break;
q->focusNextPrevChild(focusWidget, target == FocusTarget::Next);
return;
}
case FocusTarget::Prev: {
QWidget *focusWidget = widget->focusWidget() ? widget->focusWidget() : widget;
newFocusWidget = focusWidget->previousInFocusChain() ? focusWidget->previousInFocusChain() : focusWidget;
case FocusTarget::First:
case FocusTarget::Last: {
QWidgetWindow::FocusWidgets fw = target == FocusTarget::First
? QWidgetWindow::FirstFocusWidget
: QWidgetWindow::LastFocusWidget;
if (QWidget *newFocusWidget = q->getFocusWidget(fw))
newFocusWidget->setFocus(reason);
break;
}
default:
break;
}
if (newFocusWidget)
newFocusWidget->setFocus(reason);
}
QRectF closestAcceptableGeometry(const QRectF &rect) const override;
@ -233,6 +228,12 @@ void QWidgetWindow::setNativeWindowVisibility(bool visible)
d->QWindowPrivate::setVisible(visible);
}
void QWidgetWindow::focusNextPrevChild(QWidget *widget, bool next)
{
Q_ASSERT(widget);
widget->focusNextPrevChild(next);
}
static inline bool shouldBePropagatedToWidget(QEvent *event)
{
switch (event->type()) {

View File

@ -46,6 +46,8 @@ public:
QObject *focusObject() const override;
void setNativeWindowVisibility(bool visible);
static void focusNextPrevChild(QWidget *widget, bool next);
protected:
bool event(QEvent *) override;