From 63f83fbd095415145ad124c7215f07a4c3c6038f Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Mon, 27 May 2013 10:19:35 +0200 Subject: Prevent tab focus from wrapping endlessly If there was no item that accepted focus, it would go into an endless loop. This also changes the default behavior of QQuickWindow. When there is not any activeFocusItem in the whole window, it means the contentItem got focused. The Tab/BackTab key will now focus the next item in the tab focus chain. Autotest is included. Done-with: Frederik Gladhorn Task-number: QTBUG-31344 Change-Id: I854292f89a327c493eec21969907c94aa9cfddcb Reviewed-by: Jens Bache-Wiig Reviewed-by: Gabriel de Dietrich --- src/quick/items/qquickitem.cpp | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index d6a663ab77..58e1612e19 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2050,7 +2050,10 @@ bool QQuickItemPrivate::canAcceptTabFocus(QQuickItem *item) { bool result = true; - if (item->window() && item == item->window()->contentItem()) + if (!item->window()) + return false; + + if (item == item->window()->contentItem()) return true; #ifndef QT_NO_ACCESSIBILITY @@ -2093,7 +2096,6 @@ bool QQuickItemPrivate::focusNextPrev(QQuickItem *item, bool forward) QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, bool forward) { Q_ASSERT(item); - Q_ASSERT(item->activeFocusOnTab()); bool all = QQuickItemPrivate::qt_tab_all_widgets(); @@ -2107,6 +2109,10 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo from = item->parentItem(); } bool skip = false; + const QQuickItem * const contentItem = item->window()->contentItem(); + const QQuickItem * const originalItem = item; + QQuickItem * startItem = item; + QQuickItem * firstFromItem = from; QQuickItem *current = item; do { skip = false; @@ -2157,8 +2163,25 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo skip = true; } } - from = last; + if (current == startItem && from == firstFromItem) { + // wrapped around, avoid endless loops + if (originalItem == contentItem) { +#ifdef FOCUS_DEBUG + qDebug() << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return contentItem"; +#endif + return item->window()->contentItem(); + } else { +#ifdef FOCUS_DEBUG + qDebug() << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return " << startItem; +#endif + return startItem; + } + } + if (!firstFromItem) { //start from root + startItem = current; + firstFromItem = from; + } } while (skip || !current->activeFocusOnTab() || !current->isEnabled() || !current->isVisible() || !(all || QQuickItemPrivate::canAcceptTabFocus(current))); @@ -4375,7 +4398,8 @@ void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e) return; //only care about KeyPress now - if (q->activeFocusOnTab() && e->type() == QEvent::KeyPress) { + if ((q == q->window()->contentItem() || q->activeFocusOnTab()) + && e->type() == QEvent::KeyPress) { bool res = false; if (!(e->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier? if (e->key() == Qt::Key_Backtab -- cgit v1.2.3