From 0bbaf0d5d7b2d406eda57d40370b00fb79cc0aeb Mon Sep 17 00:00:00 2001 From: Szabolcs David Date: Tue, 12 Sep 2017 18:53:59 +0200 Subject: Support tablet devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Process QTabletEvents and forward them to Chromium in order to support pressure, tilting, rotation, eraser and similar features of tablet devices. Change-Id: I763d9e6e7036c29715a0b5531d3c6363eb4fcd8c Reviewed-by: Michael BrĂ¼ning --- src/core/render_widget_host_view_qt.cpp | 103 +++++++++++++++++++------------- src/core/render_widget_host_view_qt.h | 3 + src/core/web_event_factory.cpp | 48 ++++++++++++++- src/core/web_event_factory.h | 2 + 4 files changed, 110 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 9be5bd498..7ce71a81d 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -957,6 +957,12 @@ bool RenderWidgetHostViewQt::forwardEvent(QEvent *event) case QEvent::TouchCancel: handleTouchEvent(static_cast(event)); break; + case QEvent::TabletPress: + Focus(); // Fall through. + case QEvent::TabletRelease: + case QEvent::TabletMove: + handleTabletEvent(static_cast(event)); + break; #ifndef QT_NO_GESTURES case QEvent::NativeGesture: handleGestureEvent(static_cast(event)); @@ -1089,49 +1095,7 @@ void RenderWidgetHostViewQt::handleMouseEvent(QMouseEvent* event) // transformation done by Chromium. if (event->source() == Qt::MouseEventSynthesizedBySystem) return; - - blink::WebMouseEvent webEvent = WebEventFactory::toWebMouseEvent(event, dpiScale()); - if ((webEvent.GetType() == blink::WebInputEvent::kMouseDown || webEvent.GetType() == blink::WebInputEvent::kMouseUp) - && webEvent.button == blink::WebMouseEvent::Button::kNoButton) { - // Blink can only handle the 3 main mouse-buttons and may assert when processing mouse-down for no button. - return; - } - - - if (event->type() == QMouseEvent::MouseButtonPress) { - if (event->button() != m_clickHelper.lastPressButton - || (event->timestamp() - m_clickHelper.lastPressTimestamp > static_cast(qGuiApp->styleHints()->mouseDoubleClickInterval())) - || (event->pos() - m_clickHelper.lastPressPosition).manhattanLength() > qGuiApp->styleHints()->startDragDistance()) - m_clickHelper.clickCounter = 0; - - m_clickHelper.lastPressTimestamp = event->timestamp(); - webEvent.click_count = ++m_clickHelper.clickCounter; - m_clickHelper.lastPressButton = event->button(); - m_clickHelper.lastPressPosition = QPointF(event->pos()).toPoint(); - } - - webEvent.movement_x = event->globalX() - m_previousMousePosition.x(); - webEvent.movement_y = event->globalY() - m_previousMousePosition.y(); - - if (IsMouseLocked()) - QCursor::setPos(m_previousMousePosition); - else - m_previousMousePosition = event->globalPos(); - - if (m_imeInProgress && event->type() == QMouseEvent::MouseButtonPress) { - m_imeInProgress = false; - // Tell input method to commit the pre-edit string entered so far, and finish the - // composition operation. -#ifdef Q_OS_WIN - // Yes the function name is counter-intuitive, but commit isn't actually implemented - // by the Windows QPA, and reset does exactly what is necessary in this case. - qApp->inputMethod()->reset(); -#else - qApp->inputMethod()->commit(); -#endif - } - - m_host->ForwardMouseEvent(webEvent); + handlePointerEvent(event); } void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) @@ -1483,6 +1447,59 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev) } } +void RenderWidgetHostViewQt::handleTabletEvent(QTabletEvent *event) +{ + handlePointerEvent(event); +} + +template +void RenderWidgetHostViewQt::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, dpiScale()); + if ((webEvent.GetType() == blink::WebInputEvent::kMouseDown || webEvent.GetType() == blink::WebInputEvent::kMouseUp) + && webEvent.button == blink::WebMouseEvent::Button::kNoButton) { + // Blink can only handle the 3 main mouse-buttons and may assert when processing mouse-down for no button. + return; + } + + if (webEvent.GetType() == blink::WebInputEvent::kMouseDown) { + if (event->button() != m_clickHelper.lastPressButton + || (event->timestamp() - m_clickHelper.lastPressTimestamp > static_cast(qGuiApp->styleHints()->mouseDoubleClickInterval())) + || (event->pos() - m_clickHelper.lastPressPosition).manhattanLength() > qGuiApp->styleHints()->startDragDistance()) + m_clickHelper.clickCounter = 0; + + m_clickHelper.lastPressTimestamp = event->timestamp(); + webEvent.click_count = ++m_clickHelper.clickCounter; + m_clickHelper.lastPressButton = event->button(); + m_clickHelper.lastPressPosition = QPointF(event->pos()).toPoint(); + } + + webEvent.movement_x = event->globalX() - m_previousMousePosition.x(); + webEvent.movement_y = event->globalY() - m_previousMousePosition.y(); + + if (IsMouseLocked()) + QCursor::setPos(m_previousMousePosition); + else + m_previousMousePosition = event->globalPos(); + + if (m_imeInProgress && webEvent.GetType() == blink::WebInputEvent::kMouseDown) { + m_imeInProgress = false; + // Tell input method to commit the pre-edit string entered so far, and finish the + // composition operation. +#ifdef Q_OS_WIN + // Yes the function name is counter-intuitive, but commit isn't actually implemented + // by the Windows QPA, and reset does exactly what is necessary in this case. + qApp->inputMethod()->reset(); +#else + qApp->inputMethod()->commit(); +#endif + } + + m_host->ForwardMouseEvent(webEvent); +} + void RenderWidgetHostViewQt::handleHoverEvent(QHoverEvent *ev) { m_host->ForwardMouseEvent(WebEventFactory::toWebMouseEvent(ev, dpiScale())); diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index 7d32cc645..74f14d0d4 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -186,6 +186,7 @@ public: void handleKeyEvent(QKeyEvent*); void handleWheelEvent(QWheelEvent*); void handleTouchEvent(QTouchEvent*); + void handleTabletEvent(QTabletEvent *ev); #ifndef QT_NO_GESTURES void handleGestureEvent(QNativeGestureEvent *); #endif @@ -194,6 +195,8 @@ public: void handleInputMethodEvent(QInputMethodEvent*); void handleInputMethodQueryEvent(QInputMethodQueryEvent*); + template void handlePointerEvent(T*); + #if defined(OS_MACOSX) void SetActive(bool active) override { QT_NOT_YET_IMPLEMENTED } bool IsSpeaking() const override { QT_NOT_YET_IMPLEMENTED; return false; } diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index 18f8d393f..b785adec0 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -76,6 +76,7 @@ #include #include #include +#include #include using namespace blink; @@ -1032,7 +1033,8 @@ static inline double currentTimeForEvent(const QInputEvent* event) return static_cast(timer.elapsed()) / 1000; } -static WebMouseEvent::Button mouseButtonForEvent(QMouseEvent *event) +template +static WebMouseEvent::Button mouseButtonForEvent(T *event) { if (event->button() == Qt::LeftButton) return WebMouseEvent::Button::kLeft; @@ -1041,7 +1043,7 @@ static WebMouseEvent::Button mouseButtonForEvent(QMouseEvent *event) else if (event->button() == Qt::MidButton) return WebMouseEvent::Button::kMiddle; - if (event->type() != QEvent::MouseMove) + if (event->type() != QEvent::MouseMove && event->type() != QEvent::TabletMove) return WebMouseEvent::Button::kNoButton; // This is technically wrong, mouse move should always have ButtonNone, @@ -1147,14 +1149,17 @@ static WebInputEvent::Type webEventTypeForEvent(const QEvent* event) { switch (event->type()) { case QEvent::MouseButtonPress: + case QEvent::TabletPress: return WebInputEvent::kMouseDown; case QEvent::MouseButtonRelease: + case QEvent::TabletRelease: return WebInputEvent::kMouseUp; case QEvent::Enter: return WebInputEvent::kMouseEnter; case QEvent::Leave: return WebInputEvent::kMouseLeave; case QEvent::MouseMove: + case QEvent::TabletMove: return WebInputEvent::kMouseMove; case QEvent::Wheel: return WebInputEvent::kMouseWheel; @@ -1178,6 +1183,20 @@ static WebInputEvent::Type webEventTypeForEvent(const QEvent* event) } } +static WebPointerProperties::PointerType pointerTypeForTabletEvent(const QTabletEvent *ev) +{ + switch (ev->pointerType()) { + case QTabletEvent::UnknownPointer: + return WebPointerProperties::PointerType::kUnknown; + case QTabletEvent::Pen: + return WebPointerProperties::PointerType::kPen; + case QTabletEvent::Eraser: + return WebPointerProperties::PointerType::kEraser; + default: + return WebPointerProperties::PointerType::kMouse; + } +} + WebMouseEvent WebEventFactory::toWebMouseEvent(QMouseEvent *ev, double dpiScale) { WebMouseEvent webKitEvent(webEventTypeForEvent(ev), @@ -1188,7 +1207,7 @@ WebMouseEvent WebEventFactory::toWebMouseEvent(QMouseEvent *ev, double dpiScale) modifiersForEvent(ev), currentTimeForEvent(ev)); - webKitEvent.button = mouseButtonForEvent(ev); + webKitEvent.button = mouseButtonForEvent(ev); webKitEvent.click_count = 0; return webKitEvent; @@ -1208,6 +1227,29 @@ WebMouseEvent WebEventFactory::toWebMouseEvent(QHoverEvent *ev, double dpiScale) return webKitEvent; } +WebMouseEvent WebEventFactory::toWebMouseEvent(QTabletEvent *ev, double dpiScale) +{ + WebMouseEvent webKitEvent(webEventTypeForEvent(ev), + ev->x() / dpiScale, + ev->y() / dpiScale, + ev->globalX(), + ev->globalY(), + modifiersForEvent(ev), + currentTimeForEvent(ev)); + + webKitEvent.force = ev->pressure(); + webKitEvent.tilt_x = ev->xTilt(); + webKitEvent.tilt_y = ev->yTilt(); + webKitEvent.tangential_pressure = ev->tangentialPressure(); + webKitEvent.twist = ev->rotation(); + webKitEvent.pointer_type = pointerTypeForTabletEvent(ev); + + webKitEvent.button = mouseButtonForEvent(ev); + webKitEvent.click_count = 0; + + return webKitEvent; +} + #ifndef QT_NO_GESTURES WebGestureEvent WebEventFactory::toWebGestureEvent(QNativeGestureEvent *ev, double dpiScale) { diff --git a/src/core/web_event_factory.h b/src/core/web_event_factory.h index 259795c1f..c9ae86a73 100644 --- a/src/core/web_event_factory.h +++ b/src/core/web_event_factory.h @@ -53,6 +53,7 @@ QT_BEGIN_NAMESPACE class QHoverEvent; class QKeyEvent; class QMouseEvent; +class QTabletEvent; class QWheelEvent; #ifndef QT_NO_GESTURES class QNativeGestureEvent; @@ -64,6 +65,7 @@ class WebEventFactory { public: static blink::WebMouseEvent toWebMouseEvent(QMouseEvent*, double dpiScale); static blink::WebMouseEvent toWebMouseEvent(QHoverEvent*, double dpiScale); + static blink::WebMouseEvent toWebMouseEvent(QTabletEvent*, double dpiScale); #ifndef QT_NO_GESTURES static blink::WebGestureEvent toWebGestureEvent(QNativeGestureEvent *, double dpiScale); #endif -- cgit v1.2.3