summaryrefslogtreecommitdiffstats
path: root/src/core/render_widget_host_view_qt_delegate_client.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/render_widget_host_view_qt_delegate_client.cpp')
-rw-r--r--src/core/render_widget_host_view_qt_delegate_client.cpp377
1 files changed, 182 insertions, 195 deletions
diff --git a/src/core/render_widget_host_view_qt_delegate_client.cpp b/src/core/render_widget_host_view_qt_delegate_client.cpp
index 25344a1c4..3e8cad669 100644
--- a/src/core/render_widget_host_view_qt_delegate_client.cpp
+++ b/src/core/render_widget_host_view_qt_delegate_client.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "render_widget_host_view_qt_delegate_client.h"
@@ -47,18 +11,17 @@
#include "web_event_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "ui/touch_selection/touch_selection_controller.h"
#include <QEvent>
#include <QInputMethodEvent>
-#include <QSGNode>
+#include <QSet>
#include <QStyleHints>
#include <QTextFormat>
#include <QVariant>
-#include <private/qguiapplication_p.h>
-#include <qpa/qplatforminputcontext.h>
-#include <qpa/qplatformintegration.h>
+#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qinputcontrol_p.h>
namespace QtWebEngineCore {
@@ -72,39 +35,38 @@ static inline int firstAvailableId(const QMap<int, int> &map)
return usedIds.first_unmarked_bit();
}
-static QList<QTouchEvent::TouchPoint>
-mapTouchPointIds(const QList<QTouchEvent::TouchPoint> &inputPoints)
+typedef QPair<int, QTouchEvent::TouchPoint> TouchPoint;
+QList<TouchPoint> RenderWidgetHostViewQtDelegateClient::mapTouchPointIds(const QList<QTouchEvent::TouchPoint> &input)
{
- static QMap<int, int> touchIdMapping;
- QList<QTouchEvent::TouchPoint> outputPoints = inputPoints;
- for (int i = 0; i < outputPoints.size(); ++i) {
- QTouchEvent::TouchPoint &point = outputPoints[i];
+ QList<TouchPoint> output;
+ for (int i = 0; i < input.size(); ++i) {
+ const QTouchEvent::TouchPoint &point = input[i];
int qtId = point.id();
- QMap<int, int>::const_iterator it = touchIdMapping.find(qtId);
- if (it == touchIdMapping.end())
- it = touchIdMapping.insert(qtId, firstAvailableId(touchIdMapping));
- point.setId(it.value());
+ QMap<int, int>::const_iterator it = m_touchIdMapping.find(qtId);
+ if (it == m_touchIdMapping.end()) {
+ Q_ASSERT_X(m_touchIdMapping.size() <= 16, "", "Number of mapped ids can't exceed 16 for velocity tracker");
+ it = m_touchIdMapping.insert(qtId, firstAvailableId(m_touchIdMapping));
+ }
- if (point.state() == Qt::TouchPointReleased)
- touchIdMapping.remove(qtId);
+ output.append(qMakePair(it.value(), point));
}
- return outputPoints;
-}
+ Q_ASSERT(output.size() == std::accumulate(output.cbegin(), output.cend(), QSet<int>(),
+ [] (QSet<int> s, const TouchPoint &p) { s.insert(p.second.id()); return s; }).size());
-static inline bool compareTouchPoints(const QTouchEvent::TouchPoint &lhs,
- const QTouchEvent::TouchPoint &rhs)
-{
- // TouchPointPressed < TouchPointMoved < TouchPointReleased
- return lhs.state() < rhs.state();
+ for (auto &&point : std::as_const(input))
+ if (point.state() == QEventPoint::Released)
+ m_touchIdMapping.remove(point.id());
+
+ return output;
}
static uint32_t s_eventId = 0;
class MotionEventQt : public ui::MotionEvent
{
public:
- MotionEventQt(const QList<QTouchEvent::TouchPoint> &touchPoints,
+ MotionEventQt(const QList<TouchPoint> &touchPoints,
const base::TimeTicks &eventTime, Action action,
const Qt::KeyboardModifiers modifiers, int index = -1)
: touchPoints(touchPoints)
@@ -114,8 +76,12 @@ public:
, flags(flagsFromModifiers(modifiers))
, index(index)
{
- // ACTION_DOWN and ACTION_UP must be accesssed through pointer_index 0
- Q_ASSERT((action != Action::DOWN && action != Action::UP) || index == 0);
+ // index is only valid for ACTION_DOWN and ACTION_UP and should correspond to the point causing it
+ // see blink_event_util.cc:ToWebTouchPointState for details
+ Q_ASSERT_X((action != Action::POINTER_DOWN && action != Action::POINTER_UP && index == -1)
+ || (action == Action::POINTER_DOWN && index >= 0 && touchPoint(index).state() == QEventPoint::Pressed)
+ || (action == Action::POINTER_UP && index >= 0 && touchPoint(index).state() == QEventPoint::Released),
+ "MotionEventQt", qPrintable(QString("action: %1, index: %2, state: %3").arg(int(action)).arg(index).arg(touchPoint(index).state())));
}
uint32_t GetUniqueEventId() const override { return eventId; }
@@ -124,39 +90,39 @@ public:
size_t GetPointerCount() const override { return touchPoints.size(); }
int GetPointerId(size_t pointer_index) const override
{
- return touchPoints.at(pointer_index).id();
+ return touchPoints[pointer_index].first;
}
float GetX(size_t pointer_index) const override
{
- return touchPoints.at(pointer_index).pos().x();
+ return touchPoint(pointer_index).position().x();
}
float GetY(size_t pointer_index) const override
{
- return touchPoints.at(pointer_index).pos().y();
+ return touchPoint(pointer_index).position().y();
}
float GetRawX(size_t pointer_index) const override
{
- return touchPoints.at(pointer_index).screenPos().x();
+ return touchPoint(pointer_index).globalPosition().x();
}
float GetRawY(size_t pointer_index) const override
{
- return touchPoints.at(pointer_index).screenPos().y();
+ return touchPoint(pointer_index).globalPosition().y();
}
float GetTouchMajor(size_t pointer_index) const override
{
- QSizeF diams = touchPoints.at(pointer_index).ellipseDiameters();
+ QSizeF diams = touchPoint(pointer_index).ellipseDiameters();
return std::max(diams.height(), diams.width());
}
float GetTouchMinor(size_t pointer_index) const override
{
- QSizeF diams = touchPoints.at(pointer_index).ellipseDiameters();
+ QSizeF diams = touchPoint(pointer_index).ellipseDiameters();
return std::min(diams.height(), diams.width());
}
float GetOrientation(size_t pointer_index) const override { return 0; }
int GetFlags() const override { return flags; }
float GetPressure(size_t pointer_index) const override
{
- return touchPoints.at(pointer_index).pressure();
+ return touchPoint(pointer_index).pressure();
}
float GetTiltX(size_t pointer_index) const override { return 0; }
float GetTiltY(size_t pointer_index) const override { return 0; }
@@ -177,19 +143,19 @@ public:
float GetHistoricalY(size_t pointer_index, size_t historical_index) const override { return 0; }
ToolType GetToolType(size_t pointer_index) const override
{
- return (touchPoints.at(pointer_index).flags() & QTouchEvent::TouchPoint::InfoFlag::Pen)
- ? ui::MotionEvent::ToolType::STYLUS
- : ui::MotionEvent::ToolType::FINGER;
+ return ui::MotionEvent::ToolType::FINGER;
}
+
int GetButtonState() const override { return 0; }
private:
- QList<QTouchEvent::TouchPoint> touchPoints;
+ QList<TouchPoint> touchPoints;
base::TimeTicks eventTime;
Action action;
const uint32_t eventId;
int flags;
int index;
+ const QTouchEvent::TouchPoint& touchPoint(size_t i) const { return touchPoints[i].second; }
};
RenderWidgetHostViewQtDelegateClient::RenderWidgetHostViewQtDelegateClient(
@@ -197,11 +163,6 @@ RenderWidgetHostViewQtDelegateClient::RenderWidgetHostViewQtDelegateClient(
: m_rwhv(rwhv)
{
Q_ASSERT(rwhv);
-
- const QPlatformInputContext *context =
- QGuiApplicationPrivate::platformIntegration()->inputContext();
- m_imeHasHiddenTextCapability =
- context && context->hasCapability(QPlatformInputContext::HiddenTextCapability);
}
Compositor::Id RenderWidgetHostViewQtDelegateClient::compositorId()
@@ -237,7 +198,7 @@ void RenderWidgetHostViewQtDelegateClient::visualPropertiesChanged()
m_rwhv->host()->SendScreenRects();
if (m_viewRectInDips.size() != oldViewRect.size() || screenInfoChanged)
- m_rwhv->synchronizeVisualProperties(base::nullopt);
+ m_rwhv->synchronizeVisualProperties(absl::nullopt);
}
bool RenderWidgetHostViewQtDelegateClient::forwardEvent(QEvent *event)
@@ -247,7 +208,7 @@ bool RenderWidgetHostViewQtDelegateClient::forwardEvent(QEvent *event)
switch (event->type()) {
case QEvent::ShortcutOverride: {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
-
+ event->ignore();
auto acceptKeyOutOfInputField = [](QKeyEvent *keyEvent) -> bool {
#ifdef Q_OS_MACOS
// Check if a shortcut is registered for this key sequence.
@@ -331,9 +292,13 @@ bool RenderWidgetHostViewQtDelegateClient::forwardEvent(QEvent *event)
handleHoverEvent(static_cast<QHoverEvent *>(event));
break;
case QEvent::FocusIn:
- case QEvent::FocusOut:
- handleFocusEvent(static_cast<QFocusEvent *>(event));
- break;
+ case QEvent::FocusOut: {
+ // Focus in/out events for popup event do not mean 'parent' focus change
+ // and should not be handled by Chromium
+ QFocusEvent *e = static_cast<QFocusEvent *>(event);
+ if (e->reason() != Qt::PopupFocusReason)
+ handleFocusEvent(e);
+ } break;
case QEvent::InputMethod:
handleInputMethodEvent(static_cast<QInputMethodEvent *>(event));
break;
@@ -346,7 +311,10 @@ bool RenderWidgetHostViewQtDelegateClient::forwardEvent(QEvent *event)
return false;
#endif
case QEvent::HoverLeave:
- m_rwhv->host()->ForwardMouseEvent(WebEventFactory::toWebMouseEvent(event));
+ if (m_rwhv->host()->delegate() && m_rwhv->host()->delegate()->GetInputEventRouter()) {
+ auto webEvent = WebEventFactory::toWebMouseEvent(event);
+ m_rwhv->host()->delegate()->GetInputEventRouter()->RouteMouseEvent(m_rwhv, &webEvent, ui::LatencyInfo());
+ }
break;
default:
return false;
@@ -357,17 +325,8 @@ bool RenderWidgetHostViewQtDelegateClient::forwardEvent(QEvent *event)
QVariant RenderWidgetHostViewQtDelegateClient::inputMethodQuery(Qt::InputMethodQuery query)
{
switch (query) {
- case Qt::ImEnabled: {
- ui::TextInputType type = m_rwhv->getTextInputType();
- bool editorVisible = type != ui::TEXT_INPUT_TYPE_NONE;
- // IME manager should disable composition on input fields with ImhHiddenText hint if
- // supported
- if (m_imeHasHiddenTextCapability)
- return QVariant(editorVisible);
-
- bool passwordInput = type == ui::TEXT_INPUT_TYPE_PASSWORD;
- return QVariant(editorVisible && !passwordInput);
- }
+ case Qt::ImEnabled:
+ return QVariant(m_rwhv->getTextInputType() != ui::TEXT_INPUT_TYPE_NONE);
case Qt::ImFont:
// TODO: Implement this
return QVariant();
@@ -385,6 +344,7 @@ QVariant RenderWidgetHostViewQtDelegateClient::inputMethodQuery(Qt::InputMethodQ
}
return QVariant();
}
+ case Qt::ImAbsolutePosition:
case Qt::ImCursorPosition:
return m_cursorPosition;
case Qt::ImAnchorPosition:
@@ -398,12 +358,8 @@ QVariant RenderWidgetHostViewQtDelegateClient::inputMethodQuery(Qt::InputMethodQ
// TODO: Implement this
return QVariant(); // No limit.
case Qt::ImHints:
-#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
return int(toQtInputMethodHints(m_rwhv->getTextInputType()) | Qt::ImhNoPredictiveText
| Qt::ImhNoTextHandles | Qt::ImhNoEditMenu);
-#else
- return int(toQtInputMethodHints(m_rwhv->getTextInputType()) | Qt::ImhNoPredictiveText);
-#endif
default:
return QVariant();
}
@@ -424,8 +380,8 @@ void RenderWidgetHostViewQtDelegateClient::handlePointerEvent(T *event)
// Currently WebMouseEvent is a subclass of WebPointerProperties, so basically
// tablet events are mouse events with extra properties.
blink::WebMouseEvent webEvent = WebEventFactory::toWebMouseEvent(event);
- if ((webEvent.GetType() == blink::WebInputEvent::kMouseDown
- || webEvent.GetType() == blink::WebInputEvent::kMouseUp)
+ if ((webEvent.GetType() == blink::WebInputEvent::Type::kMouseDown
+ || webEvent.GetType() == blink::WebInputEvent::Type::kMouseUp)
&& webEvent.button == blink::WebMouseEvent::Button::kNoButton) {
// Blink can only handle the 5 main mouse-buttons and may assert when processing mouse-down
// for no button.
@@ -433,11 +389,11 @@ void RenderWidgetHostViewQtDelegateClient::handlePointerEvent(T *event)
return;
}
- if (webEvent.GetType() == blink::WebInputEvent::kMouseDown) {
+ if (webEvent.GetType() == blink::WebInputEvent::Type::kMouseDown) {
if (event->button() != m_clickHelper.lastPressButton
|| (event->timestamp() - m_clickHelper.lastPressTimestamp
> static_cast<ulong>(qGuiApp->styleHints()->mouseDoubleClickInterval()))
- || (event->pos() - m_clickHelper.lastPressPosition).manhattanLength()
+ || (event->position() - m_clickHelper.lastPressPosition).manhattanLength()
> qGuiApp->styleHints()->startDragDistance()
|| m_clickHelper.clickCounter >= 3)
m_clickHelper.clickCounter = 0;
@@ -445,21 +401,22 @@ void RenderWidgetHostViewQtDelegateClient::handlePointerEvent(T *event)
m_clickHelper.lastPressTimestamp = event->timestamp();
webEvent.click_count = ++m_clickHelper.clickCounter;
m_clickHelper.lastPressButton = event->button();
- m_clickHelper.lastPressPosition = QPointF(event->pos()).toPoint();
+ m_clickHelper.lastPressPosition = event->position().toPoint();
}
- if (webEvent.GetType() == blink::WebInputEvent::kMouseUp)
+ if (webEvent.GetType() == blink::WebInputEvent::Type::kMouseUp)
webEvent.click_count = m_clickHelper.clickCounter;
- webEvent.movement_x = event->globalX() - m_previousMousePosition.x();
- webEvent.movement_y = event->globalY() - m_previousMousePosition.y();
+ webEvent.movement_x = event->globalPosition().x() - m_previousMousePosition.x();
+ webEvent.movement_y = event->globalPosition().y() - m_previousMousePosition.y();
+ webEvent.is_raw_movement_event = true;
if (m_rwhv->IsMouseLocked())
QCursor::setPos(m_previousMousePosition);
else
- m_previousMousePosition = event->globalPos();
+ m_previousMousePosition = event->globalPosition().toPoint();
- if (m_imeInProgress && webEvent.GetType() == blink::WebInputEvent::kMouseDown) {
+ if (m_imeInProgress && webEvent.GetType() == blink::WebInputEvent::Type::kMouseDown) {
m_imeInProgress = false;
// Tell input method to commit the pre-edit string entered so far, and finish the
// composition operation.
@@ -472,7 +429,8 @@ void RenderWidgetHostViewQtDelegateClient::handlePointerEvent(T *event)
#endif
}
- m_rwhv->host()->ForwardMouseEvent(webEvent);
+ if (m_rwhv->host()->delegate() && m_rwhv->host()->delegate()->GetInputEventRouter())
+ m_rwhv->host()->delegate()->GetInputEventRouter()->RouteMouseEvent(m_rwhv, &webEvent, ui::LatencyInfo());
}
void RenderWidgetHostViewQtDelegateClient::handleMouseEvent(QMouseEvent *event)
@@ -482,12 +440,6 @@ void RenderWidgetHostViewQtDelegateClient::handleMouseEvent(QMouseEvent *event)
if (event->type() == QEvent::MouseButtonRelease)
m_mouseButtonPressed--;
- // Don't forward mouse events synthesized by the system, which are caused by genuine touch
- // events. Chromium would then process for e.g. a mouse click handler twice, once due to the
- // system synthesized mouse event, and another time due to a touch-to-gesture-to-mouse
- // transformation done by Chromium.
- if (event->source() == Qt::MouseEventSynthesizedBySystem)
- return;
handlePointerEvent<QMouseEvent>(event);
}
@@ -524,29 +476,32 @@ void RenderWidgetHostViewQtDelegateClient::handleKeyEvent(QKeyEvent *event)
if (event->type() == QEvent::KeyRelease && event->isAutoRepeat())
return;
+ if (!m_rwhv->GetFocusedWidget())
+ return;
+
content::NativeWebKeyboardEvent webEvent = WebEventFactory::toWebKeyboardEvent(event);
- if (webEvent.GetType() == blink::WebInputEvent::kRawKeyDown && !m_editCommand.empty()) {
+ if (webEvent.GetType() == blink::WebInputEvent::Type::kRawKeyDown && !m_editCommand.empty()) {
ui::LatencyInfo latency;
latency.set_source_event_type(ui::SourceEventType::KEY_PRESS);
- content::EditCommands commands;
- commands.emplace_back(m_editCommand, "");
+ std::vector<blink::mojom::EditCommandPtr> commands;
+ commands.emplace_back(blink::mojom::EditCommand::New(m_editCommand, ""));
m_editCommand.clear();
- m_rwhv->host()->ForwardKeyboardEventWithCommands(webEvent, latency, &commands, nullptr);
+ m_rwhv->GetFocusedWidget()->ForwardKeyboardEventWithCommands(webEvent, latency, std::move(commands), nullptr);
return;
}
bool keyDownTextInsertion =
- webEvent.GetType() == blink::WebInputEvent::kRawKeyDown && webEvent.text[0];
- webEvent.skip_in_browser = keyDownTextInsertion;
- m_rwhv->host()->ForwardKeyboardEvent(webEvent);
+ webEvent.GetType() == blink::WebInputEvent::Type::kRawKeyDown && webEvent.text[0];
+ webEvent.skip_if_unhandled = keyDownTextInsertion;
+ m_rwhv->GetFocusedWidget()->ForwardKeyboardEvent(webEvent);
if (keyDownTextInsertion) {
// Blink won't consume the RawKeyDown, but rather the Char event in this case.
// The RawKeyDown is skipped on the way back (see above).
// The same os_event will be set on both NativeWebKeyboardEvents.
- webEvent.skip_in_browser = false;
- webEvent.SetType(blink::WebInputEvent::kChar);
- m_rwhv->host()->ForwardKeyboardEvent(webEvent);
+ webEvent.skip_if_unhandled = false;
+ webEvent.SetType(blink::WebInputEvent::Type::kChar);
+ m_rwhv->GetFocusedWidget()->ForwardKeyboardEvent(webEvent);
}
}
@@ -567,59 +522,70 @@ void RenderWidgetHostViewQtDelegateClient::handleTouchEvent(QTouchEvent *event)
// Calculate a delta between event timestamps and Now() on the first received event, and
// apply this delta to all successive events. This delta is most likely smaller than it
// should by calculating it here but this will hopefully cause less than one frame of delay.
- base::TimeTicks eventTimestamp =
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(event->timestamp());
- static base::TimeDelta eventsToNowDelta = base::TimeTicks::Now() - eventTimestamp;
- eventTimestamp += eventsToNowDelta;
+ base::TimeTicks eventTimestamp = base::TimeTicks() + base::Milliseconds(event->timestamp());
+ if (m_eventsToNowDelta == 0)
+ m_eventsToNowDelta = (base::TimeTicks::Now() - eventTimestamp).InMicroseconds();
+ eventTimestamp += base::Microseconds(m_eventsToNowDelta);
+
+ auto touchPoints = mapTouchPointIds(event->points());
+ // Make sure that POINTER_DOWN action is delivered before MOVE, and MOVE before POINTER_UP
+ std::sort(touchPoints.begin(), touchPoints.end(), [] (const TouchPoint &l, const TouchPoint &r) {
+ return l.second.state() < r.second.state();
+ });
+
+ auto sc = qScopeGuard([&] () {
+ switch (event->type()) {
+ case QEvent::TouchCancel:
+ for (auto &&it : std::as_const(touchPoints))
+ m_touchIdMapping.remove(it.second.id());
+ Q_FALLTHROUGH();
+
+ case QEvent::TouchEnd:
+ m_previousTouchPoints.clear();
+ m_touchMotionStarted = false;
+ break;
- QList<QTouchEvent::TouchPoint> touchPoints = mapTouchPointIds(event->touchPoints());
- // 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);
+ default:
+ m_previousTouchPoints = touchPoints;
+ break;
+ }
+ });
+ ui::MotionEvent::Action action;
// Check first if the touch event should be routed to the selectionController
if (!touchPoints.isEmpty()) {
- ui::MotionEvent::Action action;
- switch (touchPoints[0].state()) {
- case Qt::TouchPointPressed:
+ switch (touchPoints[0].second.state()) {
+ case QEventPoint::Pressed:
action = ui::MotionEvent::Action::DOWN;
break;
- case Qt::TouchPointMoved:
+ case QEventPoint::Updated:
action = ui::MotionEvent::Action::MOVE;
break;
- case Qt::TouchPointReleased:
+ case QEventPoint::Released:
action = ui::MotionEvent::Action::UP;
break;
default:
action = ui::MotionEvent::Action::NONE;
break;
}
-
- MotionEventQt motionEvent(touchPoints, eventTimestamp, action, event->modifiers(), 0);
- if (m_rwhv->getTouchSelectionController()->WillHandleTouchEvent(motionEvent)) {
- m_previousTouchPoints = touchPoints;
- event->accept();
- return;
- }
} else {
// An empty touchPoints always corresponds to a TouchCancel event.
// We can't forward touch cancellations without a previously processed touch event,
// as Chromium expects the previous touchPoints for Action::CANCEL.
// If both are empty that means the TouchCancel was sent without an ongoing touch,
// so there's nothing to cancel anyway.
+ Q_ASSERT(event->type() == QEvent::TouchCancel);
touchPoints = m_previousTouchPoints;
if (touchPoints.isEmpty())
return;
- MotionEventQt cancelEvent(touchPoints, eventTimestamp, ui::MotionEvent::Action::CANCEL,
- event->modifiers());
- if (m_rwhv->getTouchSelectionController()->WillHandleTouchEvent(cancelEvent)) {
- m_previousTouchPoints.clear();
- event->accept();
- return;
- }
+ action = ui::MotionEvent::Action::CANCEL;
}
+ MotionEventQt me(touchPoints, eventTimestamp, action, event->modifiers());
+ if (m_rwhv->getTouchSelectionController()->WillHandleTouchEvent(me))
+ return;
+
switch (event->type()) {
case QEvent::TouchBegin:
m_sendMotionActionDown = true;
@@ -629,19 +595,17 @@ void RenderWidgetHostViewQtDelegateClient::handleTouchEvent(QTouchEvent *event)
case QEvent::TouchUpdate:
m_touchMotionStarted = true;
break;
- case QEvent::TouchCancel: {
+ case QEvent::TouchCancel:
+ {
// Only process TouchCancel events received following a TouchBegin or TouchUpdate event
if (m_touchMotionStarted) {
- MotionEventQt cancelEvent(touchPoints, eventTimestamp, ui::MotionEvent::Action::CANCEL,
- event->modifiers());
+ MotionEventQt cancelEvent(touchPoints, eventTimestamp, ui::MotionEvent::Action::CANCEL, event->modifiers());
m_rwhv->processMotionEvent(cancelEvent);
}
- clearPreviousTouchMotionState();
return;
}
case QEvent::TouchEnd:
- clearPreviousTouchMotionState();
m_rwhv->getTouchSelectionControllerClient()->onTouchUp();
break;
default:
@@ -661,34 +625,50 @@ void RenderWidgetHostViewQtDelegateClient::handleTouchEvent(QTouchEvent *event)
#endif
}
- for (int i = 0; i < touchPoints.size(); ++i) {
- ui::MotionEvent::Action action;
- switch (touchPoints[i].state()) {
- case Qt::TouchPointPressed:
- if (m_sendMotionActionDown) {
- action = ui::MotionEvent::Action::DOWN;
- m_sendMotionActionDown = false;
- } else {
- action = ui::MotionEvent::Action::POINTER_DOWN;
+ // MEMO for the basis of this logic look into:
+ // * blink_event_util.cc:ToWebTouchPointState: which is used later to forward touch event
+ // composed from motion event after gesture recognition
+ // * gesture_detector.cc:GestureDetector::OnTouchEvent: contains logic for every motion
+ // event action and corresponding gesture recognition routines
+ // * input_router_imp.cc:InputRouterImp::SetMovementXYForTouchPoints: expectation about
+ // touch event content like number of points for different states
+
+ int lastPressIndex = -1;
+ while ((lastPressIndex + 1) < touchPoints.size() && touchPoints[lastPressIndex + 1].second.state() == QEventPoint::Pressed)
+ ++lastPressIndex;
+
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ m_rwhv->processMotionEvent(MotionEventQt(touchPoints.mid(lastPressIndex),
+ eventTimestamp, ui::MotionEvent::Action::DOWN, event->modifiers()));
+ --lastPressIndex;
+ Q_FALLTHROUGH();
+
+ case QEvent::TouchUpdate:
+ for (; lastPressIndex >= 0; --lastPressIndex) {
+ Q_ASSERT(touchPoints[lastPressIndex].second.state() == QEventPoint::Pressed);
+ MotionEventQt me(touchPoints.mid(lastPressIndex), eventTimestamp, ui::MotionEvent::Action::POINTER_DOWN, event->modifiers(), 0);
+ m_rwhv->processMotionEvent(me);
+ }
+
+ if (event->touchPointStates() & Qt::TouchPointMoved)
+ m_rwhv->processMotionEvent(MotionEventQt(touchPoints, eventTimestamp, ui::MotionEvent::Action::MOVE, event->modifiers()));
+
+ Q_FALLTHROUGH();
+
+ case QEvent::TouchEnd:
+ while (!touchPoints.isEmpty() && touchPoints.back().second.state() == QEventPoint::Released) {
+ auto action = touchPoints.size() > 1 ? ui::MotionEvent::Action::POINTER_UP : ui::MotionEvent::Action::UP;
+ int index = action == ui::MotionEvent::Action::POINTER_UP ? touchPoints.size() - 1 : -1;
+ m_rwhv->processMotionEvent(MotionEventQt(touchPoints, eventTimestamp, action, event->modifiers(), index));
+ touchPoints.pop_back();
}
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;
- break;
- default:
- // Ignore Qt::TouchPointStationary
- continue;
- }
- MotionEventQt motionEvent(touchPoints, eventTimestamp, action, event->modifiers(), i);
- m_rwhv->processMotionEvent(motionEvent);
+ default:
+ Q_ASSERT_X(false, __FUNCTION__, "Other event types are expected to be already handled.");
+ break;
}
-
- m_previousTouchPoints = touchPoints;
}
#if QT_CONFIG(tabletevent)
@@ -703,15 +683,24 @@ void RenderWidgetHostViewQtDelegateClient::handleGestureEvent(QNativeGestureEven
{
const Qt::NativeGestureType type = event->gestureType();
// These are the only supported gestures by Chromium so far.
- if (type == Qt::ZoomNativeGesture || type == Qt::SmartZoomNativeGesture) {
- m_rwhv->host()->ForwardGestureEvent(WebEventFactory::toWebGestureEvent(event));
+ if (type == Qt::ZoomNativeGesture || type == Qt::SmartZoomNativeGesture
+ || type == Qt::BeginNativeGesture || type == Qt::EndNativeGesture) {
+ auto *hostDelegate = m_rwhv->host()->delegate();
+ if (hostDelegate && hostDelegate->GetInputEventRouter()) {
+ auto webEvent = WebEventFactory::toWebGestureEvent(event);
+ hostDelegate->GetInputEventRouter()->RouteGestureEvent(m_rwhv, &webEvent, ui::LatencyInfo());
+ }
}
}
#endif
void RenderWidgetHostViewQtDelegateClient::handleHoverEvent(QHoverEvent *event)
{
- m_rwhv->host()->ForwardMouseEvent(WebEventFactory::toWebMouseEvent(event));
+ auto *hostDelegate = m_rwhv->host()->delegate();
+ if (hostDelegate && hostDelegate->GetInputEventRouter()) {
+ auto webEvent = WebEventFactory::toWebMouseEvent(event);
+ hostDelegate->GetInputEventRouter()->RouteMouseEvent(m_rwhv, &webEvent, ui::LatencyInfo());
+ }
}
void RenderWidgetHostViewQtDelegateClient::handleFocusEvent(QFocusEvent *event)
@@ -770,6 +759,7 @@ void RenderWidgetHostViewQtDelegateClient::handleInputMethodEvent(QInputMethodEv
underlines.push_back(ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, start, end,
ui::ImeTextSpan::Thickness::kThin,
+ ui::ImeTextSpan::UnderlineStyle::kSolid,
SK_ColorTRANSPARENT));
QTextCharFormat format = qvariant_cast<QTextFormat>(attribute.value).toCharFormat();
@@ -813,10 +803,8 @@ void RenderWidgetHostViewQtDelegateClient::handleInputMethodEvent(QInputMethodEv
}
if (hasSelection) {
- content::mojom::FrameInputHandler *frameInputHandler = m_rwhv->getFrameInputHandler();
- if (frameInputHandler)
- frameInputHandler->SetEditableSelectionOffsets(selectionRange.start(),
- selectionRange.end());
+ if (auto *frameWidgetInputHandler = m_rwhv->getFrameWidgetInputHandler())
+ frameWidgetInputHandler->SetEditableSelectionOffsets(selectionRange.start(), selectionRange.end());
}
int replacementLength = event->replacementLength();
@@ -844,8 +832,7 @@ void RenderWidgetHostViewQtDelegateClient::handleInputMethodEvent(QInputMethodEv
if (commitString.isEmpty() && preeditString.isEmpty() && replacementLength == 0) {
if (!m_receivedEmptyImeEvent && m_imeInProgress && !hasSelection) {
m_receivedEmptyImeEvent = true;
- QInputMethodEvent *eventCopy = new QInputMethodEvent(*event);
- QGuiApplication::postEvent(qApp->focusObject(), eventCopy);
+ QGuiApplication::postEvent(qApp->focusObject(), event->clone());
} else {
m_receivedEmptyImeEvent = false;
if (m_imeInProgress) {
@@ -922,7 +909,7 @@ void RenderWidgetHostViewQtDelegateClient::selectionChanged()
// position if the selection is cleared because TextInputState changes before the
// TextSelection change.
Q_ASSERT(text_input_manager->GetTextInputState());
- m_cursorPosition = text_input_manager->GetTextInputState()->selection_start;
+ m_cursorPosition = text_input_manager->GetTextInputState()->selection.start();
m_rwhv->delegate()->inputMethodStateChanged(true /*editorVisible*/,
type == ui::TEXT_INPUT_TYPE_PASSWORD);