summaryrefslogtreecommitdiffstats
path: root/src/core/render_widget_host_view_qt.cpp
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@theqtcompany.com>2016-03-01 14:16:05 +0100
committerAlexandru Croitor <alexandru.croitor@theqtcompany.com>2016-03-24 11:17:46 +0000
commit9cdd03b44a09b6b40656d4a494f58384007d8aac (patch)
treeee3226bf28a850975907a1e69b45a6f85afbc224 /src/core/render_widget_host_view_qt.cpp
parentfab5cff1171de54f43d9ab57ed16f8d0f85b433e (diff)
Fix crash when link opens a modal QDialog, using the trackpad.
When a QWebEngine link is clicked on, and as a result a modal dialog is opened, a QEvent::TouchCancel without any touch points is forwarded to Chromium, which tries to access the first touch point position, and causes a QList assertion. Fix consists of two parts: 1) Make sure that no TouchCancel is forwarded, in case if no TouchBegin or TouchUpdate was issued beforehand. 2) Because QEvent::TouchCancel events might contain an empty touch point list, and Chromium expects at least one point, make sure to forward the last saved touch points (saved in previous TouchUpdate) together with the TouchCancel. Task-number: QTBUG-48661 Change-Id: I1eeb2980417b1b04e8387dc9f82f935ef2bd8f00 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
Diffstat (limited to 'src/core/render_widget_host_view_qt.cpp')
-rw-r--r--src/core/render_widget_host_view_qt.cpp53
1 files changed, 45 insertions, 8 deletions
diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
index b15aa94ef..500a94659 100644
--- a/src/core/render_widget_host_view_qt.cpp
+++ b/src/core/render_widget_host_view_qt.cpp
@@ -249,6 +249,7 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget
: m_host(content::RenderWidgetHostImpl::From(widget))
, m_gestureProvider(QtGestureProviderConfig(), this)
, m_sendMotionActionDown(false)
+ , m_touchMotionStarted(false)
, m_chromiumCompositorData(new ChromiumCompositorData)
, m_needsDelegatedFrameAck(false)
, m_didFirstVisuallyNonEmptyLayout(false)
@@ -1009,6 +1010,12 @@ void RenderWidgetHostViewQt::handleWheelEvent(QWheelEvent *ev)
m_host->ForwardWheelEvent(WebEventFactory::toWebWheelEvent(ev, dpiScale()));
}
+void RenderWidgetHostViewQt::clearPreviousTouchMotionState()
+{
+ m_previousTouchPoints.clear();
+ m_touchMotionStarted = false;
+}
+
void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev)
{
// Chromium expects the touch event timestamps to be comparable to base::TimeTicks::Now().
@@ -1023,19 +1030,46 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev)
QList<QTouchEvent::TouchPoint> touchPoints = mapTouchPointIds(ev->touchPoints());
- if (ev->type() == QEvent::TouchCancel) {
- MotionEventQt cancelEvent(touchPoints, eventTimestamp, ui::MotionEvent::ACTION_CANCEL, ev->modifiers(), dpiScale());
+ switch (ev->type()) {
+ case QEvent::TouchBegin:
+ m_sendMotionActionDown = true;
+ m_touchMotionStarted = true;
+ break;
+ case QEvent::TouchUpdate:
+ m_touchMotionStarted = true;
+ break;
+ case QEvent::TouchCancel:
+ {
+ // Don't process a TouchCancel event if no motion was started beforehand, or if there are
+ // no touch points in the current event or in the previously processed event.
+ if (!m_touchMotionStarted || (touchPoints.isEmpty() && m_previousTouchPoints.isEmpty())) {
+ clearPreviousTouchMotionState();
+ return;
+ }
+
+ // Use last saved touch points for the cancel event, to get rid of a QList assert,
+ // because Chromium expects a MotionEvent::ACTION_CANCEL instance to contain at least
+ // one touch point, whereas a QTouchCancel may not contain any touch points at all.
+ if (touchPoints.isEmpty())
+ touchPoints = m_previousTouchPoints;
+ clearPreviousTouchMotionState();
+ MotionEventQt cancelEvent(touchPoints, eventTimestamp, ui::MotionEvent::ACTION_CANCEL,
+ ev->modifiers(), dpiScale());
processMotionEvent(cancelEvent);
return;
}
-
- if (ev->type() == QEvent::TouchBegin)
- m_sendMotionActionDown = true;
+ case QEvent::TouchEnd:
+ clearPreviousTouchMotionState();
+ break;
+ default:
+ break;
+ }
// Make sure that ACTION_POINTER_DOWN is delivered before ACTION_MOVE,
// and ACTION_MOVE before ACTION_POINTER_UP.
std::sort(touchPoints.begin(), touchPoints.end(), compareTouchPoints);
+ m_previousTouchPoints = touchPoints;
for (int i = 0; i < touchPoints.size(); ++i) {
ui::MotionEvent::Action action;
switch (touchPoints[i].state()) {
@@ -1043,21 +1077,24 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev)
if (m_sendMotionActionDown) {
action = ui::MotionEvent::ACTION_DOWN;
m_sendMotionActionDown = false;
- } else
+ } else {
action = ui::MotionEvent::ACTION_POINTER_DOWN;
+ }
break;
case Qt::TouchPointMoved:
action = ui::MotionEvent::ACTION_MOVE;
break;
case Qt::TouchPointReleased:
- action = touchPoints.size() > 1 ? ui::MotionEvent::ACTION_POINTER_UP : ui::MotionEvent::ACTION_UP;
+ action = touchPoints.size() > 1 ? ui::MotionEvent::ACTION_POINTER_UP :
+ ui::MotionEvent::ACTION_UP;
break;
default:
// Ignore Qt::TouchPointStationary
continue;
}
- MotionEventQt motionEvent(touchPoints, eventTimestamp, action, ev->modifiers(), dpiScale(), i);
+ MotionEventQt motionEvent(touchPoints, eventTimestamp, action, ev->modifiers(), dpiScale(),
+ i);
processMotionEvent(motionEvent);
}
}