From b1a137100a0d8312c5867d64a629ae2d8be1f097 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Thu, 2 Nov 2017 17:42:19 +0100 Subject: [PATCH] using Qt::PopupFocusReason as reason, when ... yes the focus changes because of a QskPopup --- src/controls/QskPopup.cpp | 46 ++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/controls/QskPopup.cpp b/src/controls/QskPopup.cpp index 9eb58d6d..9e5d1bdc 100644 --- a/src/controls/QskPopup.cpp +++ b/src/controls/QskPopup.cpp @@ -11,6 +11,7 @@ QSK_QT_PRIVATE_BEGIN #include +#include QSK_QT_PRIVATE_END QSK_SUBCONTROL( QskPopup, Overlay ) @@ -24,9 +25,38 @@ static inline QQuickItem* qskNearestFocusScope( const QQuickItem* item ) return scope; } + /* + As the default setting of the root item is to be a focus scope + we usually never get here - beside the flag has been explicitely + disabled in application code. + */ + return nullptr; } +static void qskSetFocus( QQuickItem* item, bool on ) +{ + if ( item->window() == nullptr ) + return; + + /* + For unknown reasons Qt::PopupFocusReason is blocked inside of + QQuickItem::setFocus. So let's bypass it calling + QQuickWindowPrivate::setFocusInScope/clearFocusInScope directly, + */ + + const auto scope = qskNearestFocusScope( item ); + if ( scope ) + { + auto dw = QQuickWindowPrivate::get( item->window() ); + + if ( on ) + dw->setFocusInScope( scope, item, Qt::PopupFocusReason ); + else + dw->clearFocusInScope( scope, item, Qt::PopupFocusReason ); + } +} + namespace { class InputGrabber final : public QQuickItem @@ -265,22 +295,12 @@ void QskPopup::grabFocus( bool on ) if ( on == hasFocus() ) return; - /* - For unknown reasons Qt::PopupFocusReason is blocked inside of - QQuickItem::setFocus. Nontheless there is specific code dealing - with it f.e in qquicktextinput.cpp. If this becomes a problem - we will have to bypass QQuickItem::setFocus by calling - QQuickWindowPrivate::setFocusInScope/clearFocusInScope directly, - but for the moment we use Qt::OtherFocusReason instead. TODO ... - */ - const auto reason = Qt::OtherFocusReason; - if ( on ) { if ( auto scope = qskNearestFocusScope( this ) ) { m_data->initialFocusItem = scope->scopedFocusItem(); - setFocus( true, reason ); + qskSetFocus( this, true ); } } else @@ -292,9 +312,9 @@ void QskPopup::grabFocus( bool on ) focusItem = nextItemInFocusChain( false ); if ( focusItem ) - focusItem->setFocus( true, reason ); + qskSetFocus( focusItem, true ); else - setFocus( false, reason ); + qskSetFocus( this, false ); } }