diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index a9716847a1e..f6c8aee9f67 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -76,6 +76,16 @@ public: void setTransientParent(QWindow *parent); virtual void clearFocusObject(); + + enum class FocusTarget { + First, + Last, + Current, + Next, + Prev + }; + virtual void setFocusToTarget(QWindowPrivate::FocusTarget) {} + virtual QRectF closestAcceptableGeometry(const QRectF &rect) const; void setMinOrMaxSize(QSize *oldSizeMember, const QSize &size, diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index f51baba88b1..c5b045c8dbf 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -77,6 +77,39 @@ public: widget->focusWidget()->clearFocus(); } + void setFocusToTarget(QWindowPrivate::FocusTarget target) override + { + Q_Q(QWidgetWindow); + 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::Next: { + QWidget *focusWidget = widget->focusWidget() ? widget->focusWidget() : widget; + newFocusWidget = focusWidget->nextInFocusChain() ? focusWidget->nextInFocusChain() : focusWidget; + break; + } + case FocusTarget::Prev: { + QWidget *focusWidget = widget->focusWidget() ? widget->focusWidget() : widget; + newFocusWidget = focusWidget->previousInFocusChain() ? focusWidget->previousInFocusChain() : focusWidget; + break; + } + default: + break; + } + + if (newFocusWidget) + newFocusWidget->setFocus(); + } + QRectF closestAcceptableGeometry(const QRectF &rect) const override; void processSafeAreaMarginsChanged() override diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index 2c374ac408a..376a93c758f 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -5,6 +5,7 @@ #include "qwidget_p.h" #include "qwidgetwindow_p.h" #include +#include #include #include #include @@ -317,8 +318,17 @@ bool QWindowContainer::event(QEvent *e) break; case QEvent::FocusIn: if (d->window->parent()) { - if (QGuiApplication::focusWindow() != d->window) + if (QGuiApplication::focusWindow() != d->window) { + QFocusEvent *event = static_cast(e); + const auto reason = event->reason(); + QWindowPrivate::FocusTarget target = QWindowPrivate::FocusTarget::Current; + if (reason == Qt::TabFocusReason) + target = QWindowPrivate::FocusTarget::First; + else if (reason == Qt::BacktabFocusReason) + target = QWindowPrivate::FocusTarget::Last; + qt_window_private(d->window)->setFocusToTarget(target); d->window->requestActivate(); + } } break; #if QT_CONFIG(draganddrop)