QComboBox: open popup on touch release if QStyleHints has setFocusOnTouchRelease()

If we give focus to the combobox on touch release, we need to await opening
the popup until touch release as well. Otherwise we might end up showing
a popup for an unfocused combobox.

Especially on iOS, there is a strong coupling between focus object and
popup menus, which means that we effectively require the combobox to gain
focus before it can show the popup.

Change-Id: Ifb7ba091bb39b77f325cdbf61e00ab3e8ff2e522
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>
This commit is contained in:
Richard Moe Gustavsen 2015-03-25 11:23:39 +01:00
parent 9cb38baaf8
commit d3277bdf02
2 changed files with 32 additions and 16 deletions

View File

@ -53,6 +53,7 @@
#include <qmath.h> #include <qmath.h>
#include <qmetaobject.h> #include <qmetaobject.h>
#include <qabstractproxymodel.h> #include <qabstractproxymodel.h>
#include <qstylehints.h>
#include <private/qguiapplication_p.h> #include <private/qguiapplication_p.h>
#include <private/qapplication_p.h> #include <private/qapplication_p.h>
#include <private/qcombobox_p.h> #include <private/qcombobox_p.h>
@ -3017,39 +3018,51 @@ bool QComboBox::event(QEvent *event)
void QComboBox::mousePressEvent(QMouseEvent *e) void QComboBox::mousePressEvent(QMouseEvent *e)
{ {
Q_D(QComboBox); Q_D(QComboBox);
if (!QGuiApplication::styleHints()->setFocusOnTouchRelease())
d->showPopupFromMouseEvent(e);
}
/*!
\reimp
*/
void QComboBoxPrivate::showPopupFromMouseEvent(QMouseEvent *e)
{
Q_Q(QComboBox);
QStyleOptionComboBox opt; QStyleOptionComboBox opt;
initStyleOption(&opt); q->initStyleOption(&opt);
QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, e->pos(), QStyle::SubControl sc = q->style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, e->pos(), q);
this);
if (e->button() == Qt::LeftButton && (sc == QStyle::SC_ComboBoxArrow || !isEditable()) if (e->button() == Qt::LeftButton
&& !d->viewContainer()->isVisible()) { && sc != QStyle::SC_None
&& (sc == QStyle::SC_ComboBoxArrow || !q->isEditable())
&& !viewContainer()->isVisible()) {
if (sc == QStyle::SC_ComboBoxArrow) if (sc == QStyle::SC_ComboBoxArrow)
d->updateArrow(QStyle::State_Sunken); updateArrow(QStyle::State_Sunken);
#ifdef QT_KEYPAD_NAVIGATION #ifdef QT_KEYPAD_NAVIGATION
//if the container already exists, then d->viewContainer() is safe to call //if the container already exists, then d->viewContainer() is safe to call
if (d->container) { if (container) {
#endif #endif
// We've restricted the next couple of lines, because by not calling // We've restricted the next couple of lines, because by not calling
// viewContainer(), we avoid creating the QComboBoxPrivateContainer. // viewContainer(), we avoid creating the QComboBoxPrivateContainer.
d->viewContainer()->blockMouseReleaseTimer.start(QApplication::doubleClickInterval()); viewContainer()->blockMouseReleaseTimer.start(QApplication::doubleClickInterval());
d->viewContainer()->initialClickPosition = mapToGlobal(e->pos()); viewContainer()->initialClickPosition = q->mapToGlobal(e->pos());
#ifdef QT_KEYPAD_NAVIGATION #ifdef QT_KEYPAD_NAVIGATION
} }
#endif #endif
showPopup(); q->showPopup();
// The code below ensures that regular mousepress and pick item still works // The code below ensures that regular mousepress and pick item still works
// If it was not called the viewContainer would ignore event since it didn't have // If it was not called the viewContainer would ignore event since it didn't have
// a mousePressEvent first. // a mousePressEvent first.
if (d->viewContainer()) if (viewContainer())
d->viewContainer()->maybeIgnoreMouseButtonRelease = false; viewContainer()->maybeIgnoreMouseButtonRelease = false;
} else { } else {
#ifdef QT_KEYPAD_NAVIGATION #ifdef QT_KEYPAD_NAVIGATION
if (QApplication::keypadNavigationEnabled() && sc == QStyle::SC_ComboBoxEditField && d->lineEdit) { if (QApplication::keypadNavigationEnabled() && sc == QStyle::SC_ComboBoxEditField && lineEdit) {
d->lineEdit->event(e); //so lineedit can move cursor, etc lineEdit->event(e); //so lineedit can move cursor, etc
return; return;
} }
#endif #endif
QWidget::mousePressEvent(e); e->ignore();
} }
} }
@ -3059,8 +3072,9 @@ void QComboBox::mousePressEvent(QMouseEvent *e)
void QComboBox::mouseReleaseEvent(QMouseEvent *e) void QComboBox::mouseReleaseEvent(QMouseEvent *e)
{ {
Q_D(QComboBox); Q_D(QComboBox);
Q_UNUSED(e);
d->updateArrow(QStyle::State_None); d->updateArrow(QStyle::State_None);
if (QGuiApplication::styleHints()->setFocusOnTouchRelease() && hasFocus())
d->showPopupFromMouseEvent(e);
} }
/*! /*!

View File

@ -253,6 +253,7 @@ private:
QElapsedTimer popupTimer; QElapsedTimer popupTimer;
friend class QComboBox; friend class QComboBox;
friend class QComboBoxPrivate;
}; };
class Q_AUTOTEST_EXPORT QComboMenuDelegate : public QAbstractItemDelegate class Q_AUTOTEST_EXPORT QComboMenuDelegate : public QAbstractItemDelegate
@ -372,6 +373,7 @@ public:
void modelChanged(); void modelChanged();
void updateViewContainerPaletteAndOpacity(); void updateViewContainerPaletteAndOpacity();
void updateFocusPolicy(); void updateFocusPolicy();
void showPopupFromMouseEvent(QMouseEvent *e);
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
void cleanupNativePopup(); void cleanupNativePopup();