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>bb10
parent
a3b5947d36
commit
438211ec62
|
|
@ -328,6 +328,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const
|
|||
return QVariant(false);
|
||||
case SynthesizeMouseFromTouchEvents:
|
||||
return true;
|
||||
case SetFocusOnTouchRelease:
|
||||
return QVariant(false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -141,7 +141,8 @@ public:
|
|||
StartDragVelocity,
|
||||
UseRtlExtensions,
|
||||
SynthesizeMouseFromTouchEvents,
|
||||
PasswordMaskCharacter
|
||||
PasswordMaskCharacter,
|
||||
SetFocusOnTouchRelease
|
||||
};
|
||||
|
||||
virtual QVariant styleHint(StyleHint hint) const;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ public:
|
|||
QChar passwordMaskCharacter() const;
|
||||
qreal fontSmoothingGamma() const;
|
||||
bool useRtlExtensions() const;
|
||||
bool setFocusOnTouchRelease() const;
|
||||
|
||||
private:
|
||||
friend class QGuiApplication;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue