Skip to content

Commit

Permalink
QWidgetWindow::setFocusToTarget: Respect focus policies and proxies
Browse files Browse the repository at this point in the history
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.

Pick-to: 6.8
Task-number: QTBUG-121789
Change-Id: I1f4f5d85e7552926580906fdef6f0a456fe7486c
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
Reviewed-by: MohammadHossein Qanbari <mohammad.qanbari@qt.io>
  • Loading branch information
dorisverria1 committed Oct 2, 2024
1 parent 0563862 commit 926d328
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 15 deletions.
31 changes: 16 additions & 15 deletions src/widgets/kernel/qwidgetwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,31 +82,26 @@ class QWidgetWindowPrivate : public QWindowPrivate
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;
Expand Down Expand Up @@ -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()) {
Expand Down
2 changes: 2 additions & 0 deletions src/widgets/kernel/qwidgetwindow_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class QWidgetWindow : public QWindow

QObject *focusObject() const override;
void setNativeWindowVisibility(bool visible);
static void focusNextPrevChild(QWidget *widget, bool next);

protected:
bool event(QEvent *) override;

Expand Down

0 comments on commit 926d328

Please sign in to comment.