summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@digia.com>2013-06-19 11:21:14 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-06-25 15:11:02 +0200
commit438211ec627073817fcaf6d3a07b76f2aa5d90e0 (patch)
tree9eb64a4d4a6a21d1c87db038724ab823df1b6d10 /src
parenta3b5947d3623ac3da4ee21056214835f1e5c06da (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.cpp2
-rw-r--r--src/gui/kernel/qplatformintegration.h3
-rw-r--r--src/gui/kernel/qstylehints.cpp11
-rw-r--r--src/gui/kernel/qstylehints.h1
-rw-r--r--src/widgets/kernel/qapplication.cpp62
-rw-r--r--src/widgets/kernel/qapplication_p.h4
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);