aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/templates/qquickmenu.cpp80
-rw-r--r--src/templates/qquickmenu_p_p.h3
2 files changed, 18 insertions, 65 deletions
diff --git a/src/templates/qquickmenu.cpp b/src/templates/qquickmenu.cpp
index e8b13994..5acb015c 100644
--- a/src/templates/qquickmenu.cpp
+++ b/src/templates/qquickmenu.cpp
@@ -44,6 +44,7 @@
#include <QtQuick/private/qquickitemchangelistener_p.h>
#include <QtQuick/private/qquickflickable_p.h>
#include <QtQuick/private/qquickevents_p_p.h>
+#include <QtQuick/private/qquickwindow_p.h>
QT_BEGIN_NAMESPACE
@@ -92,9 +93,7 @@ QT_BEGIN_NAMESPACE
*/
QQuickMenuPrivate::QQuickMenuPrivate() :
- contentModel(nullptr),
- dummyFocusItem(nullptr),
- ignoreActiveFocusChanges(false)
+ contentModel(nullptr)
{
Q_Q(QQuickMenu);
contentModel = new QQmlObjectModel(q);
@@ -193,17 +192,12 @@ void QQuickMenuPrivate::onItemPressed()
{
Q_Q(QQuickMenu);
QQuickItem *item = qobject_cast<QQuickItem*>(q->sender());
- int itemIndex = contentModel->indexOf(item, nullptr);
- Q_ASSERT(itemIndex != -1);
-
- setCurrentIndex(itemIndex);
+ if (item)
+ item->forceActiveFocus();
}
void QQuickMenuPrivate::onItemActiveFocusChanged()
{
- if (ignoreActiveFocusChanges)
- return;
-
Q_Q(QQuickMenu);
QQuickItem *item = qobject_cast<QQuickItem*>(q->sender());
if (!item->hasActiveFocus())
@@ -213,14 +207,6 @@ void QQuickMenuPrivate::onItemActiveFocusChanged()
setCurrentIndex(indexOfItem);
}
-void QQuickMenuPrivate::maybeUnsetDummyFocusOnTab()
-{
- if (!dummyFocusItem->hasActiveFocus()) {
- // Only unset the flag once the dummy item no longer has focus, otherwise we get warnings.
- dummyFocusItem->setActiveFocusOnTab(false);
- }
-}
-
int QQuickMenuPrivate::currentIndex() const
{
QVariant index = contentItem->property("currentIndex");
@@ -279,6 +265,7 @@ void QQuickMenuPrivate::contentData_clear(QQmlListProperty<QObject> *prop)
QQuickMenu::QQuickMenu(QObject *parent) :
QQuickPopup(*(new QQuickMenuPrivate), parent)
{
+ setFocus(true);
setClosePolicy(OnEscape | OnPressOutside | OnReleaseOutside);
}
@@ -431,33 +418,8 @@ void QQuickMenu::componentComplete()
void QQuickMenu::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
{
Q_D(QQuickMenu);
+ Q_UNUSED(oldItem);
QQuickPopup::contentItemChange(newItem, oldItem);
- if (oldItem) {
- if (d->dummyFocusItem)
- QObjectPrivate::disconnect(d->dummyFocusItem.data(), &QQuickItem::activeFocusChanged, d, &QQuickMenuPrivate::maybeUnsetDummyFocusOnTab);
- }
-
- if (newItem) {
- newItem->setFlag(QQuickItem::ItemIsFocusScope);
- newItem->setActiveFocusOnTab(true);
-
- // Trying to give active focus to the contentItem (ListView, by default)
- // when the menu first opens, without also giving it to the first delegate item
- // doesn't seem to be possible, but this is what we need to do. QMenu behaves
- // similarly to this; it receives focus if a button that has it as a menu is clicked,
- // and only after pressing tab is the first menu item then given active focus.
- if (!d->dummyFocusItem) {
- d->dummyFocusItem = new QQuickItem(newItem);
- d->dummyFocusItem->setObjectName(QStringLiteral("dummyMenuFocusItem"));
- } else {
- d->dummyFocusItem->setParentItem(newItem);
- }
-
- d->dummyFocusItem->setActiveFocusOnTab(true);
- d->dummyFocusItem->stackBefore(newItem->childItems().first());
-
- QObjectPrivate::connect(d->dummyFocusItem.data(), &QQuickItem::activeFocusChanged, d, &QQuickMenuPrivate::maybeUnsetDummyFocusOnTab);
- }
d->contentItem = newItem;
}
@@ -467,27 +429,16 @@ void QQuickMenu::itemChange(QQuickItem::ItemChange change, const QQuickItem::Ite
QQuickPopup::itemChange(change, data);
if (change == QQuickItem::ItemVisibleHasChanged) {
- if (data.boolValue) {
- // Don't react to active focus changes here, as we're causing them.
- d->ignoreActiveFocusChanges = true;
- for (int i = 0; i < d->contentModel->count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(d->contentModel->get(i));
- item->setFocus(true);
- }
- d->ignoreActiveFocusChanges = false;
-
- // We must do this last so that none of the menu items have focus.
- d->dummyFocusItem->forceActiveFocus();
- } else {
+ if (!data.boolValue) {
// Ensure that when the menu isn't visible, there's no current item
// the next time it's opened.
- d->setCurrentIndex(-1);
-
- // The menu items are sneaky and will steal the focus if they can.
- for (int i = 0; i < d->contentModel->count(); ++i) {
- QQuickItem *item = qobject_cast<QQuickItem*>(d->contentModel->get(i));
- item->setFocus(false);
+ QQuickItem *focusItem = QQuickItemPrivate::get(d->contentItem)->subFocusItem;
+ if (focusItem) {
+ QQuickWindow *window = QQuickPopup::window();
+ if (window)
+ QQuickWindowPrivate::get(window)->clearFocusInScope(d->contentItem, focusItem, Qt::OtherFocusReason);
}
+ d->setCurrentIndex(-1);
}
}
}
@@ -519,6 +470,11 @@ void QQuickMenu::keyReleaseEvent(QKeyEvent *event)
default:
break;
}
+
+ int index = d->currentIndex();
+ QQuickItem *item = itemAt(index);
+ if (item)
+ item->forceActiveFocus();
}
#ifndef QT_NO_ACCESSIBILITY
diff --git a/src/templates/qquickmenu_p_p.h b/src/templates/qquickmenu_p_p.h
index b0ab7b91..457c9619 100644
--- a/src/templates/qquickmenu_p_p.h
+++ b/src/templates/qquickmenu_p_p.h
@@ -81,7 +81,6 @@ public:
void onItemPressed();
void onItemActiveFocusChanged();
- void maybeUnsetDummyFocusOnTab();
int currentIndex() const;
void setCurrentIndex(int index);
@@ -94,8 +93,6 @@ public:
QQuickItem *contentItem; // TODO: cleanup
QVector<QObject *> contentData;
QQmlObjectModel *contentModel;
- QPointer<QQuickItem> dummyFocusItem;
- bool ignoreActiveFocusChanges;
QString title;
};