improving focus handling after closing a popup
This commit is contained in:
parent
8cb65fefa6
commit
3f0075f616
@ -114,6 +114,14 @@ QQuickItem* qskNearestFocusScope( const QQuickItem* item )
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<QQuickItem *> qskPaintOrderChildItems( const QQuickItem* item )
|
||||||
|
{
|
||||||
|
if ( item )
|
||||||
|
return QQuickItemPrivate::get( item )->paintOrderChildItems();
|
||||||
|
|
||||||
|
return QList<QQuickItem *>();
|
||||||
|
}
|
||||||
|
|
||||||
const QSGNode* qskItemNode( const QQuickItem* item )
|
const QSGNode* qskItemNode( const QQuickItem* item )
|
||||||
{
|
{
|
||||||
if ( item == nullptr )
|
if ( item == nullptr )
|
||||||
|
@ -247,6 +247,7 @@ QSK_EXPORT bool qskIsTabFence( const QQuickItem* );
|
|||||||
QSK_EXPORT bool qskIsShortcutScope( const QQuickItem* );
|
QSK_EXPORT bool qskIsShortcutScope( const QQuickItem* );
|
||||||
|
|
||||||
QSK_EXPORT QQuickItem* qskNearestFocusScope( const QQuickItem* );
|
QSK_EXPORT QQuickItem* qskNearestFocusScope( const QQuickItem* );
|
||||||
|
QSK_EXPORT QList<QQuickItem *> qskPaintOrderChildItems( const QQuickItem* );
|
||||||
|
|
||||||
QSK_EXPORT const QSGNode* qskItemNode( const QQuickItem* );
|
QSK_EXPORT const QSGNode* qskItemNode( const QQuickItem* );
|
||||||
QSK_EXPORT const QSGNode* qskPaintNode( const QQuickItem* );
|
QSK_EXPORT const QSGNode* qskPaintNode( const QQuickItem* );
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
#include "QskPopup.h"
|
#include "QskPopup.h"
|
||||||
#include "QskAspect.h"
|
#include "QskAspect.h"
|
||||||
#include <QQuickWindow>
|
#include <QQuickWindow>
|
||||||
#include <QGuiApplication>
|
|
||||||
#include <QStyleHints>
|
|
||||||
#include <QtMath>
|
#include <QtMath>
|
||||||
|
|
||||||
QSK_QT_PRIVATE_BEGIN
|
QSK_QT_PRIVATE_BEGIN
|
||||||
@ -17,7 +15,7 @@ QSK_QT_PRIVATE_END
|
|||||||
|
|
||||||
QSK_SUBCONTROL( QskPopup, Overlay )
|
QSK_SUBCONTROL( QskPopup, Overlay )
|
||||||
|
|
||||||
static void qskSetFocusInScope( QQuickItem* item, bool on )
|
static void qskSetFocus( QQuickItem* item, bool on )
|
||||||
{
|
{
|
||||||
if ( item->window() == nullptr )
|
if ( item->window() == nullptr )
|
||||||
return;
|
return;
|
||||||
@ -39,71 +37,6 @@ static void qskSetFocusInScope( QQuickItem* item, bool on )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static QQuickItem* qskNextFocusItem( const QskPopup* popup )
|
|
||||||
{
|
|
||||||
if ( popup == nullptr || popup->parentItem() == nullptr )
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
const auto children = popup->parentItem()->childItems();
|
|
||||||
if ( children.count() <= 1 )
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
QskPopup* modalPopup = nullptr;
|
|
||||||
|
|
||||||
for ( auto child : children )
|
|
||||||
{
|
|
||||||
if ( ( child != popup ) && child->isVisible() )
|
|
||||||
{
|
|
||||||
if ( auto otherPopup = qobject_cast< QskPopup* >( child ) )
|
|
||||||
{
|
|
||||||
if ( !otherPopup->isModal() || ( modalPopup != nullptr ) )
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
We can't decide, wether to give the focus to
|
|
||||||
one of the popups or the top level item
|
|
||||||
*/
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
modalPopup = otherPopup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( modalPopup )
|
|
||||||
{
|
|
||||||
// Exactly one popup, that is modal.
|
|
||||||
return modalPopup;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto tabFocusBehavior = QGuiApplication::styleHints()->tabFocusBehavior();
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
while( children[i] != popup )
|
|
||||||
i++;
|
|
||||||
|
|
||||||
for ( int j = i - 1; j != i; j-- )
|
|
||||||
{
|
|
||||||
auto item = children[j];
|
|
||||||
if ( item->isEnabled() && item->isVisible() )
|
|
||||||
{
|
|
||||||
if ( item->activeFocusOnTab() )
|
|
||||||
{
|
|
||||||
if ( ( tabFocusBehavior == Qt::TabFocusAllControls ) ||
|
|
||||||
QQuickItemPrivate::canAcceptTabFocus( item ) )
|
|
||||||
{
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( j == 0 )
|
|
||||||
j = children.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
class InputGrabber final : public QQuickItem
|
class InputGrabber final : public QQuickItem
|
||||||
@ -339,11 +272,11 @@ void QskPopup::grabFocus( bool on )
|
|||||||
|
|
||||||
if ( on )
|
if ( on )
|
||||||
{
|
{
|
||||||
qskSetFocusInScope( this, true );
|
qskSetFocus( this, true );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QQuickItem* focusItem = nullptr;
|
QQuickItem* successor = nullptr;
|
||||||
|
|
||||||
if ( m_data->handoverFocus )
|
if ( m_data->handoverFocus )
|
||||||
{
|
{
|
||||||
@ -352,13 +285,14 @@ void QskPopup::grabFocus( bool on )
|
|||||||
when the active focus gets lost. For the situation of
|
when the active focus gets lost. For the situation of
|
||||||
a popup being closed we try to do it.
|
a popup being closed we try to do it.
|
||||||
*/
|
*/
|
||||||
focusItem = qskNextFocusItem( this );
|
successor = focusSuccessor();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( focusItem )
|
if ( successor )
|
||||||
qskSetFocusInScope( focusItem, true );
|
qskSetFocus( successor, true );
|
||||||
else
|
|
||||||
qskSetFocusInScope( this, false );
|
if ( hasFocus() )
|
||||||
|
qskSetFocus( this, false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,6 +322,23 @@ bool QskPopup::event( QEvent* event )
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QQuickItem* QskPopup::focusSuccessor() const
|
||||||
|
{
|
||||||
|
if ( const auto scope = qskNearestFocusScope( this ) )
|
||||||
|
{
|
||||||
|
const auto children = qskPaintOrderChildItems( scope );
|
||||||
|
for ( auto it = children.crbegin(); it != children.crend(); ++it)
|
||||||
|
{
|
||||||
|
auto child = *it;
|
||||||
|
|
||||||
|
if ( child != this && child->isFocusScope() )
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void QskPopup::updateLayout()
|
void QskPopup::updateLayout()
|
||||||
{
|
{
|
||||||
if ( !m_data->isOpen )
|
if ( !m_data->isOpen )
|
||||||
|
@ -43,6 +43,8 @@ protected:
|
|||||||
virtual void itemChange( QQuickItem::ItemChange,
|
virtual void itemChange( QQuickItem::ItemChange,
|
||||||
const QQuickItem::ItemChangeData& ) override;
|
const QQuickItem::ItemChangeData& ) override;
|
||||||
|
|
||||||
|
virtual QQuickItem* focusSuccessor() const;
|
||||||
|
|
||||||
void grabFocus( bool );
|
void grabFocus( bool );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user