diff options
author | Richard Moe Gustavsen <richard.gustavsen@digia.com> | 2013-06-19 11:21:14 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-06-25 15:11:02 +0200 |
commit | 438211ec627073817fcaf6d3a07b76f2aa5d90e0 (patch) | |
tree | 9eb64a4d4a6a21d1c87db038724ab823df1b6d10 /src | |
parent | a3b5947d3623ac3da4ee21056214835f1e5c06da (diff) |
QPlatformIntegration: add new style hint: SetFocusOnTouchRelease
On desktop platforms, widgets have traditionally received
focus on mouse press. On touch platforms (iOS, Android) this
is different, there you need to delay setting the focus
until a touch release (probably to check if the press starts
a flick or tap'n'hold etc).
This patch will add a new style hint SetFocusOnRelease that
can be set by the plugin to control this behavior in Qt.
Change-Id: I2e4d714894e327822c855eb48a3b28e354726e95
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@digia.com>
Reviewed-by: Paul Olav Tvete <paul.tvete@digia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/kernel/qplatformintegration.cpp | 2 | ||||
-rw-r--r-- | src/gui/kernel/qplatformintegration.h | 3 | ||||
-rw-r--r-- | src/gui/kernel/qstylehints.cpp | 11 | ||||
-rw-r--r-- | src/gui/kernel/qstylehints.h | 1 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication.cpp | 62 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication_p.h | 4 |
6 files changed, 57 insertions, 26 deletions
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp index e4f45ebb6e..2910bb9280 100644 --- a/src/gui/kernel/qplatformintegration.cpp +++ b/src/gui/kernel/qplatformintegration.cpp @@ -328,6 +328,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const return QVariant(false); case SynthesizeMouseFromTouchEvents: return true; + case SetFocusOnTouchRelease: + return QVariant(false); } return 0; diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h index b7a44b13de..fcac211f72 100644 --- a/src/gui/kernel/qplatformintegration.h +++ b/src/gui/kernel/qplatformintegration.h @@ -141,7 +141,8 @@ public: StartDragVelocity, UseRtlExtensions, SynthesizeMouseFromTouchEvents, - PasswordMaskCharacter + PasswordMaskCharacter, + SetFocusOnTouchRelease }; virtual QVariant styleHint(StyleHint hint) const; diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp index 30b12835f7..a302f2186c 100644 --- a/src/gui/kernel/qstylehints.cpp +++ b/src/gui/kernel/qstylehints.cpp @@ -218,4 +218,15 @@ bool QStyleHints::useRtlExtensions() const return hint(QPlatformIntegration::UseRtlExtensions).toBool(); } +/*! + Returns \c true if focus objects (line edits etc) should receive + input focus after a touch/mouse release. This is normal behavior on + touch platforms. On desktop platforms, the standard is to set + focus already on touch/mouse press. +*/ +bool QStyleHints::setFocusOnTouchRelease() const +{ + return hint(QPlatformIntegration::SetFocusOnTouchRelease).toBool(); +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h index 64ef182aab..a0facd5f94 100644 --- a/src/gui/kernel/qstylehints.h +++ b/src/gui/kernel/qstylehints.h @@ -65,6 +65,7 @@ public: QChar passwordMaskCharacter() const; qreal fontSmoothingGamma() const; bool useRtlExtensions() const; + bool setFocusOnTouchRelease() const; private: friend class QGuiApplication; diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 080f4358f2..3fabeb1445 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -2929,12 +2929,8 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QPoint relpos = mouse->pos(); if (e->spontaneous()) { - - if (e->type() == QEvent::MouseButtonPress) { - QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, - Qt::ClickFocus, - Qt::MouseFocusReason); - } + if (e->type() != QEvent::MouseMove) + QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos); // ### Qt 5 These dynamic tool tips should be an OPT-IN feature. Some platforms // like Mac OS X (probably others too), can optimize their views by not @@ -3022,11 +3018,8 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QPoint relpos = wheel->pos(); bool eventAccepted = wheel->isAccepted(); - if (e->spontaneous()) { - QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, - Qt::WheelFocus, - Qt::MouseFocusReason); - } + if (e->spontaneous()) + QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos); while (w) { QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), @@ -3214,6 +3207,11 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QTouchEvent *touchEvent = static_cast<QTouchEvent *>(e); const bool acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents); + if (e->type() != QEvent::TouchUpdate && acceptTouchEvents && e->spontaneous()) { + const QPoint localPos = touchEvent->touchPoints()[0].pos().toPoint(); + QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget, e, localPos); + } + touchEvent->setTarget(widget); touchEvent->setAccepted(acceptTouchEvents); @@ -3231,16 +3229,16 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QWidget *widget = static_cast<QWidget *>(receiver); QTouchEvent *touchEvent = static_cast<QTouchEvent *>(e); bool eventAccepted = touchEvent->isAccepted(); - if (widget->testAttribute(Qt::WA_AcceptTouchEvents) && e->spontaneous()) { - // give the widget focus if the focus policy allows it - QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget, - Qt::ClickFocus, - Qt::MouseFocusReason); + bool acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents); + + if (acceptTouchEvents && e->spontaneous()) { + const QPoint localPos = touchEvent->touchPoints()[0].pos().toPoint(); + QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget, e, localPos); } while (widget) { // first, try to deliver the touch event - bool acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents); + acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents); touchEvent->setTarget(widget); touchEvent->setAccepted(acceptTouchEvents); QPointer<QWidget> p = widget; @@ -3705,20 +3703,40 @@ bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event) return QGuiApplication::sendSpontaneousEvent(receiver, event); } - -void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget, - Qt::FocusPolicy focusPolicy, - Qt::FocusReason focusReason) +void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget, QEvent *event, QPoint localPos) { + const bool setFocusOnRelease = QGuiApplication::styleHints()->setFocusOnTouchRelease(); + Qt::FocusPolicy focusPolicy = Qt::ClickFocus; + + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::TouchBegin: + if (setFocusOnRelease) + return; + break; + case QEvent::MouseButtonRelease: + case QEvent::TouchEnd: + if (!setFocusOnRelease) + return; + break; + case QEvent::Wheel: + focusPolicy = Qt::WheelFocus; + break; + default: + return; + } + QWidget *focusWidget = widget; while (focusWidget) { if (focusWidget->isEnabled() + && focusWidget->rect().contains(localPos) && QApplicationPrivate::shouldSetFocus(focusWidget, focusPolicy)) { - focusWidget->setFocus(focusReason); + focusWidget->setFocus(Qt::MouseFocusReason); break; } if (focusWidget->isWindow()) break; + localPos += focusWidget->pos(); focusWidget = focusWidget->parentWidget(); } } diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 87cf259ba5..29c6902c78 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -294,9 +294,7 @@ public: private: static QApplicationPrivate *self; - static void giveFocusAccordingToFocusPolicy(QWidget *w, - Qt::FocusPolicy focusPolicy, - Qt::FocusReason focusReason); + static void giveFocusAccordingToFocusPolicy(QWidget *w, QEvent *event, QPoint localPos); static bool shouldSetFocus(QWidget *w, Qt::FocusPolicy policy); |