Skip to content

Commit 9275646

Browse files
Kirill Burtsevpatricia-gallardo
authored andcommitted
Fix handling of more than one finger for touch event
This change addresses following wrong assumptions implemented earlier: * fix assert condition for custom MotionEventQt: pointer index is only reserved only for two distinct events POINTER_UP and POINTER_DOWN, which represent one single non first/last pointer up and down event. * MotionEvent API doesn't support delivering multiple touch point changes at once, hence code should send every touch point's up/down step by step to not confuse gesture detection classes in chromimum (ultimately fixing arising asserts which old code was triggering before). * MotionEvent shouldn't contain more touch points then were already forwarded or reported released, hence every step should contain only part of all touch points received in handleTouchEvent. Fixes: QTBUG-86389 Change-Id: I62275dc295494f88a6e44f36fe72f5f8227e37d4 Reviewed-by: Allan Sandfeld Jensen <[email protected]> Reviewed-by: Michal Klocek <[email protected]>
1 parent 26e4fe2 commit 9275646

File tree

2 files changed

+393
-28
lines changed

2 files changed

+393
-28
lines changed

src/core/render_widget_host_view_qt.cpp

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
#include "content/browser/renderer_host/render_view_host_impl.h"
6767
#include "content/common/content_switches_internal.h"
6868
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
69+
#include "content/browser/renderer_host/ui_events_helper.h"
6970
#include "content/common/cursors/webcursor.h"
7071
#include "content/common/input_messages.h"
7172
#include "third_party/skia/include/core/SkColor.h"
@@ -198,8 +199,12 @@ class MotionEventQt : public ui::MotionEvent {
198199
, flags(flagsFromModifiers(modifiers))
199200
, index(index)
200201
{
201-
// ACTION_DOWN and ACTION_UP must be accesssed through pointer_index 0
202-
Q_ASSERT((action != Action::DOWN && action != Action::UP) || index == 0);
202+
// index is only valid for ACTION_DOWN and ACTION_UP and should correspond to the point causing it
203+
// see blink_event_util.cc:ToWebTouchPointState for details
204+
Q_ASSERT_X((action != Action::POINTER_DOWN && action != Action::POINTER_UP && index == -1)
205+
|| (action == Action::POINTER_DOWN && index >= 0 && touchPoint(index).state() == Qt::TouchPointPressed)
206+
|| (action == Action::POINTER_UP && index >= 0 && touchPoint(index).state() == Qt::TouchPointReleased),
207+
"MotionEventQt", qPrintable(QString("action: %1, index: %2, state: %3").arg(int(action)).arg(index).arg(touchPoint(index).state())));
203208
}
204209

205210
uint32_t GetUniqueEventId() const override { return eventId; }
@@ -1230,8 +1235,9 @@ void RenderWidgetHostViewQt::closePopup()
12301235

12311236
void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, blink::mojom::InputEventResultState ack_result) {
12321237
Q_UNUSED(touch);
1233-
const bool eventConsumed = ack_result == blink::mojom::InputEventResultState::kConsumed;
1234-
m_gestureProvider.OnTouchEventAck(touch.event.unique_touch_event_id, eventConsumed, /*fixme: ?? */false);
1238+
const bool eventConsumed = ack_result == content::INPUT_EVENT_ACK_STATE_CONSUMED;
1239+
const bool isSetNonBlocking = content::InputEventAckStateIsSetNonBlocking(ack_result);
1240+
m_gestureProvider.OnTouchEventAck(touch.event.unique_touch_event_id, eventConsumed, isSetNonBlocking);
12351241
}
12361242

12371243
void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEvent)
@@ -1611,6 +1617,7 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev)
16111617
m_previousTouchPoints.clear();
16121618
m_touchMotionStarted = false;
16131619
break;
1620+
16141621
default:
16151622
m_previousTouchPoints = touchPoints;
16161623
break;
@@ -1648,8 +1655,7 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev)
16481655
action = ui::MotionEvent::Action::CANCEL;
16491656
}
16501657

1651-
MotionEventQt me(touchPoints, eventTimestamp, action, ev->modifiers(),
1652-
action == ui::MotionEvent::Action::CANCEL ? -1 : 0);
1658+
MotionEventQt me(touchPoints, eventTimestamp, action, ev->modifiers());
16531659
if (m_touchSelectionController->WillHandleTouchEvent(me))
16541660
return;
16551661

@@ -1692,31 +1698,49 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev)
16921698
#endif
16931699
}
16941700

1695-
for (int i = 0; i < touchPoints.size(); ++i) {
1696-
ui::MotionEvent::Action action;
1697-
switch (touchPoints[i].second.state()) {
1698-
case Qt::TouchPointPressed:
1699-
if (m_sendMotionActionDown) {
1700-
action = ui::MotionEvent::Action::DOWN;
1701-
m_sendMotionActionDown = false;
1702-
} else {
1703-
action = ui::MotionEvent::Action::POINTER_DOWN;
1701+
// MEMO for the basis of this logic look into:
1702+
// * blink_event_util.cc:ToWebTouchPointState: which is used later to forward touch event
1703+
// composed from motion event after gesture recognition
1704+
// * gesture_detector.cc:GestureDetector::OnTouchEvent: contains logic for every motion
1705+
// event action and corresponding gesture recognition routines
1706+
// * input_router_imp.cc:InputRouterImp::SetMovementXYForTouchPoints: expectation about
1707+
// touch event content like number of points for different states
1708+
1709+
int lastPressIndex = -1;
1710+
while ((lastPressIndex + 1) < touchPoints.size() && touchPoints[lastPressIndex + 1].second.state() == Qt::TouchPointPressed)
1711+
++lastPressIndex;
1712+
1713+
switch (ev->type()) {
1714+
case QEvent::TouchBegin:
1715+
processMotionEvent(MotionEventQt(touchPoints.mid(lastPressIndex),
1716+
eventTimestamp, ui::MotionEvent::Action::DOWN, ev->modifiers()));
1717+
--lastPressIndex;
1718+
Q_FALLTHROUGH();
1719+
1720+
case QEvent::TouchUpdate:
1721+
for (; lastPressIndex >= 0; --lastPressIndex) {
1722+
Q_ASSERT(touchPoints[lastPressIndex].second.state() == Qt::TouchPointPressed);
1723+
MotionEventQt me(touchPoints.mid(lastPressIndex), eventTimestamp, ui::MotionEvent::Action::POINTER_DOWN, ev->modifiers(), 0);
1724+
processMotionEvent(me);
1725+
}
1726+
1727+
if (ev->touchPointStates() & Qt::TouchPointMoved)
1728+
processMotionEvent(MotionEventQt(touchPoints, eventTimestamp, ui::MotionEvent::Action::MOVE, ev->modifiers()));
1729+
1730+
Q_FALLTHROUGH();
1731+
1732+
case QEvent::TouchEnd:
1733+
while (!touchPoints.isEmpty() && touchPoints.back().second.state() == Qt::TouchPointReleased) {
1734+
auto action = touchPoints.size() > 1 ? ui::MotionEvent::Action::POINTER_UP : ui::MotionEvent::Action::UP;
1735+
int index = action == ui::MotionEvent::Action::POINTER_UP ? touchPoints.size() - 1 : -1;
1736+
processMotionEvent(MotionEventQt(touchPoints, eventTimestamp, action, ev->modifiers(), index));
1737+
touchPoints.pop_back();
17041738
}
17051739
break;
1706-
case Qt::TouchPointMoved:
1707-
action = ui::MotionEvent::Action::MOVE;
1708-
break;
1709-
case Qt::TouchPointReleased:
1710-
action = touchPoints.size() > 1 ? ui::MotionEvent::Action::POINTER_UP :
1711-
ui::MotionEvent::Action::UP;
1712-
break;
1713-
default:
1714-
// Ignore Qt::TouchPointStationary
1715-
continue;
1716-
}
17171740

1718-
MotionEventQt motionEvent(touchPoints, eventTimestamp, action, ev->modifiers(), i);
1719-
processMotionEvent(motionEvent);
1741+
default:
1742+
Q_ASSERT_X(false, __FUNCTION__, "Other event types are expected to be already handled.");
1743+
break;
17201744
}
17211745
}
17221746

0 commit comments

Comments
 (0)