diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2013-07-31 14:04:38 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2013-08-01 12:20:45 +0200 |
commit | a3cc1b314270041b0746edb3359756188ff1487c (patch) | |
tree | 0fde0c56135c3d1eaf15327b687236c0463373ae /lib | |
parent | f3db445d66924153905997c91f6aa4b36e787ea7 (diff) |
Use ui::GestureRecognizer to enable viewport gestures.
This enables panning and zooming using touch events.
Also map touch IDs given by Qt to 0-based IDs since the
gesture recognizer expects it.
It currently needs the following command line switches to be enabled:
--force-compositing-mode --enable-threaded-compositing --enable-pinch
Change-Id: I34db3203529470aef5426ddfaa65af7d67e4b017
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/render_widget_host_view_qt.cpp | 78 | ||||
-rw-r--r-- | lib/render_widget_host_view_qt.h | 17 |
2 files changed, 93 insertions, 2 deletions
diff --git a/lib/render_widget_host_view_qt.cpp b/lib/render_widget_host_view_qt.cpp index 5ee1ff359..ad6544afa 100644 --- a/lib/render_widget_host_view_qt.cpp +++ b/lib/render_widget_host_view_qt.cpp @@ -95,6 +95,7 @@ static void UpdateWebTouchEventAfterDispatch(WebKit::WebTouchEvent* event, WebKi RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget) : m_host(content::RenderWidgetHostImpl::From(widget)) + , m_gestureRecognizer(ui::GestureRecognizer::Create(this)) { m_host->SetView(this); } @@ -475,12 +476,80 @@ void RenderWidgetHostViewQt::OnAccessibilityNotifications(const std::vector<Acce QT_NOT_USED } +bool RenderWidgetHostViewQt::DispatchLongPressGestureEvent(ui::GestureEvent *) +{ + return false; +} + +bool RenderWidgetHostViewQt::DispatchCancelTouchEvent(ui::TouchEvent *) +{ + return false; +} + +void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) { + ScopedVector<ui::TouchEvent> events; + if (!content::MakeUITouchEventsFromWebTouchEvents(touch, &events, content::LOCAL_COORDINATES)) + return; + + ui::EventResult result = (ack_result == content::INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED; + for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(), end = events.end(); iter != end; ++iter) { + (*iter)->latency()->AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ACKED_COMPONENT, static_cast<int64>(ack_result), 0); + scoped_ptr<ui::GestureRecognizer::Gestures> gestures; + gestures.reset(m_gestureRecognizer->ProcessTouchEventForGesture(*(*iter), result, this)); + ProcessGestures(gestures.get()); + } +} + void RenderWidgetHostViewQt::Paint(const gfx::Rect& damage_rect) { QRect r(damage_rect.x(), damage_rect.y(), damage_rect.width(), damage_rect.height()); m_delegate->update(r); } + +void RenderWidgetHostViewQt::ProcessGestures(ui::GestureRecognizer::Gestures *gestures) +{ + if (!gestures || gestures->empty()) + return; + for (ui::GestureRecognizer::Gestures::iterator g_it = gestures->begin(); g_it != gestures->end(); ++g_it) { + const ui::GestureEvent &uiGestureEvent = **g_it; + WebKit::WebGestureEvent webGestureEvent = content::MakeWebGestureEventFromUIEvent(uiGestureEvent); + if (webGestureEvent.type != WebKit::WebInputEvent::Undefined) { + webGestureEvent.x = uiGestureEvent.x(); + webGestureEvent.y = uiGestureEvent.y(); + m_host->ForwardGestureEvent(webGestureEvent); + } + } +} + +// Find (or create) a mapping to a 0-based ID. +int RenderWidgetHostViewQt::GetMappedTouch(int qtTouchId) +{ + QMap<int, int>::const_iterator it = m_touchIdMapping.find(qtTouchId); + if (it != m_touchIdMapping.end()) + return it.value(); + int nextValue = 0; + for (it = m_touchIdMapping.begin(); it != m_touchIdMapping.end(); ++it) + nextValue = std::max(nextValue, it.value() + 1); + m_touchIdMapping[qtTouchId] = nextValue; + return nextValue; +} + +void RenderWidgetHostViewQt::RemoveExpiredMappings(QTouchEvent *ev) +{ + QMap<int, int> newMap; + for (QMap<int, int>::const_iterator it = m_touchIdMapping.begin(); it != m_touchIdMapping.end(); ++it) { + Q_FOREACH (const QTouchEvent::TouchPoint& touchPoint, ev->touchPoints()) { + if ((touchPoint.id() == it.key()) && + (touchPoint.state() != Qt::TouchPointReleased)) { + newMap.insert(it.key(), it.value()); + break; + } + } + } + m_touchIdMapping.swap(newMap); +} + bool RenderWidgetHostViewQt::IsPopup() const { return popup_type_ != WebKit::WebPopupTypeNone; @@ -518,7 +587,7 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) toUIEventType(touchPoint.state()), toGfxPoint(touchPoint.pos().toPoint()), 0, // flags - touchPoint.id(), + GetMappedTouch(touchPoint.id()), timestamp, 0, 0, // radius 0, // angle @@ -527,10 +596,17 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) WebKit::WebTouchPoint *point = content::UpdateWebTouchEventFromUIEvent(uiEvent, &m_accumTouchEvent); if (point) { if (m_host->ShouldForwardTouchEvent()) + // This will come back through ProcessAckedTouchEvent if the page didn't want it. m_host->ForwardTouchEventWithLatencyInfo(m_accumTouchEvent, ui::LatencyInfo()); + else { + scoped_ptr<ui::GestureRecognizer::Gestures> gestures; + gestures.reset(m_gestureRecognizer->ProcessTouchEventForGesture(uiEvent, ui::ER_UNHANDLED, this)); + ProcessGestures(gestures.get()); + } UpdateWebTouchEventAfterDispatch(&m_accumTouchEvent, point); } } + RemoveExpiredMappings(ev); } void RenderWidgetHostViewQt::handleFocusEvent(QFocusEvent *ev) diff --git a/lib/render_widget_host_view_qt.h b/lib/render_widget_host_view_qt.h index 542448424..22fe22512 100644 --- a/lib/render_widget_host_view_qt.h +++ b/lib/render_widget_host_view_qt.h @@ -46,7 +46,10 @@ #include "base/memory/scoped_ptr.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" -#include <qglobal.h> +#include "ui/base/gestures/gesture_recognizer.h" +#include "ui/base/gestures/gesture_types.h" +#include <QMap> +#include <QtGlobal> class BackingStoreQt; class QEvent; @@ -59,6 +62,8 @@ class RenderWidgetHostViewQtDelegate; class RenderWidgetHostViewQt : public content::RenderWidgetHostViewBase + , public ui::GestureConsumer + , public ui::GestureEventHelper { public: RenderWidgetHostViewQt(content::RenderWidgetHost* widget); @@ -124,6 +129,11 @@ public: virtual void SetHasHorizontalScrollbar(bool); virtual void SetScrollOffsetPinning(bool, bool); virtual void OnAccessibilityNotifications(const std::vector<AccessibilityHostMsg_NotificationParams>&); + virtual void ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) Q_DECL_OVERRIDE; + + // Overridden from ui::GestureEventHelper. + virtual bool DispatchLongPressGestureEvent(ui::GestureEvent *event) Q_DECL_OVERRIDE; + virtual bool DispatchCancelTouchEvent(ui::TouchEvent *event) Q_DECL_OVERRIDE; void handleMouseEvent(QMouseEvent*); void handleKeyEvent(QKeyEvent*); @@ -147,10 +157,15 @@ public: private: void Paint(const gfx::Rect& damage_rect); + void ProcessGestures(ui::GestureRecognizer::Gestures *gestures); + int GetMappedTouch(int qtTouchId); + void RemoveExpiredMappings(QTouchEvent *ev); bool IsPopup() const; content::RenderWidgetHostImpl *m_host; + scoped_ptr<ui::GestureRecognizer> m_gestureRecognizer; + QMap<int, int> m_touchIdMapping; WebKit::WebTouchEvent m_accumTouchEvent; scoped_ptr<RenderWidgetHostViewQtDelegate> m_delegate; gfx::Size m_requestedSize; |