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

View File

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