2 Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
3 Copyright (C) 2006 Zack Rusin <zack@kde.org>
4 Copyright (C) 2011 Research In Motion Limited.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
23 #include "WebEventConversion.h"
25 #include "PlatformMouseEvent.h"
26 #include "PlatformTouchEvent.h"
27 #include "PlatformTouchPoint.h"
28 #include "PlatformWheelEvent.h"
29 #include <QApplication>
30 #include <QGraphicsSceneMouseEvent>
31 #include <QTouchEvent>
32 #include <QWheelEvent>
33 #include <wtf/CurrentTime.h>
37 static void mouseEventModifiersFromQtKeyboardModifiers(Qt::KeyboardModifiers keyboardModifiers, unsigned& modifiers)
40 if (keyboardModifiers & Qt::ShiftModifier)
41 modifiers |= PlatformEvent::ShiftKey;
42 if (keyboardModifiers & Qt::ControlModifier)
43 modifiers |= PlatformEvent::CtrlKey;
44 if (keyboardModifiers & Qt::AltModifier)
45 modifiers |= PlatformEvent::AltKey;
46 if (keyboardModifiers & Qt::MetaModifier)
47 modifiers |= PlatformEvent::MetaKey;
50 static void mouseEventTypeAndMouseButtonFromQEvent(const QEvent* event, PlatformEvent::Type& mouseEventType, MouseButton& mouseButton)
52 enum { MouseEvent, GraphicsSceneMouseEvent } frameworkMouseEventType;
53 switch (event->type()) {
54 case QEvent::MouseButtonDblClick:
55 case QEvent::MouseButtonPress:
56 frameworkMouseEventType = MouseEvent;
57 mouseEventType = PlatformEvent::MousePressed;
59 case QEvent::MouseButtonRelease:
60 frameworkMouseEventType = MouseEvent;
61 mouseEventType = PlatformEvent::MouseReleased;
63 case QEvent::MouseMove:
64 frameworkMouseEventType = MouseEvent;
65 mouseEventType = PlatformEvent::MouseMoved;
67 case QEvent::GraphicsSceneMouseDoubleClick:
68 case QEvent::GraphicsSceneMousePress:
69 frameworkMouseEventType = GraphicsSceneMouseEvent;
70 mouseEventType = PlatformEvent::MousePressed;
72 case QEvent::GraphicsSceneMouseRelease:
73 frameworkMouseEventType = GraphicsSceneMouseEvent;
74 mouseEventType = PlatformEvent::MouseReleased;
76 case QEvent::GraphicsSceneMouseMove:
77 frameworkMouseEventType = GraphicsSceneMouseEvent;
78 mouseEventType = PlatformEvent::MouseMoved;
82 frameworkMouseEventType = MouseEvent;
83 mouseEventType = PlatformEvent::MouseMoved;
87 Qt::MouseButtons mouseButtons;
88 switch (frameworkMouseEventType) {
90 const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event);
91 mouseButtons = mouseEventType == PlatformEvent::MouseMoved ? mouseEvent->buttons() : mouseEvent->button();
94 case GraphicsSceneMouseEvent: {
95 const QGraphicsSceneMouseEvent* mouseEvent = static_cast<const QGraphicsSceneMouseEvent*>(event);
96 mouseButtons = mouseEventType == PlatformEvent::MouseMoved ? mouseEvent->buttons() : mouseEvent->button();
101 if (mouseButtons & Qt::LeftButton)
102 mouseButton = LeftButton;
103 else if (mouseButtons & Qt::RightButton)
104 mouseButton = RightButton;
105 else if (mouseButtons & Qt::MidButton)
106 mouseButton = MiddleButton;
108 mouseButton = NoButton;
111 class WebKitPlatformMouseEvent : public PlatformMouseEvent {
113 WebKitPlatformMouseEvent(QGraphicsSceneMouseEvent*, int clickCount);
114 WebKitPlatformMouseEvent(QInputEvent*, int clickCount);
117 WebKitPlatformMouseEvent::WebKitPlatformMouseEvent(QGraphicsSceneMouseEvent* event, int clickCount)
119 m_timestamp = WTF::currentTime();
121 // FIXME: Why don't we handle a context menu event here as we do in PlatformMouseEvent(QInputEvent*, int)?
122 // See <https://bugs.webkit.org/show_bug.cgi?id=60728>.
123 PlatformEvent::Type type;
124 mouseEventTypeAndMouseButtonFromQEvent(event, type, m_button);
127 m_position = IntPoint(event->pos().toPoint());
128 m_globalPosition = IntPoint(event->screenPos());
130 m_clickCount = clickCount;
131 mouseEventModifiersFromQtKeyboardModifiers(event->modifiers(), m_modifiers);
134 WebKitPlatformMouseEvent::WebKitPlatformMouseEvent(QInputEvent* event, int clickCount)
136 m_timestamp = WTF::currentTime();
138 bool isContextMenuEvent = false;
139 #ifndef QT_NO_CONTEXTMENU
140 if (event->type() == QEvent::ContextMenu) {
141 isContextMenuEvent = true;
142 m_type = PlatformEvent::MousePressed;
143 QContextMenuEvent* ce = static_cast<QContextMenuEvent*>(event);
144 m_position = IntPoint(ce->pos());
145 m_globalPosition = IntPoint(ce->globalPos());
146 m_button = RightButton;
149 if (!isContextMenuEvent) {
150 PlatformEvent::Type type;
151 mouseEventTypeAndMouseButtonFromQEvent(event, type, m_button);
152 QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
155 m_position = IntPoint(mouseEvent->pos());
156 m_globalPosition = IntPoint(mouseEvent->globalPos());
159 m_clickCount = clickCount;
160 mouseEventModifiersFromQtKeyboardModifiers(event->modifiers(), m_modifiers);
163 PlatformMouseEvent convertMouseEvent(QInputEvent* event, int clickCount)
165 return WebKitPlatformMouseEvent(event, clickCount);
168 PlatformMouseEvent convertMouseEvent(QGraphicsSceneMouseEvent* event, int clickCount)
170 return WebKitPlatformMouseEvent(event, clickCount);
173 class WebKitPlatformWheelEvent : public PlatformWheelEvent {
175 WebKitPlatformWheelEvent(QGraphicsSceneWheelEvent*);
176 WebKitPlatformWheelEvent(QWheelEvent*);
179 void applyDelta(int delta, Qt::Orientation);
182 void WebKitPlatformWheelEvent::applyDelta(int delta, Qt::Orientation orientation)
184 if (orientation == Qt::Horizontal) {
191 m_wheelTicksX = m_deltaX / 120.0f;
192 m_wheelTicksY = m_deltaY / 120.0f;
194 // Since we request the scroll delta by the pixel, convert the wheel delta to pixel delta using the standard scroll step.
195 // Use the same single scroll step as QTextEdit (in QTextEditPrivate::init [h,v]bar->setSingleStep)
196 static const float cDefaultQtScrollStep = 20.f;
197 m_deltaX = m_wheelTicksX * QApplication::wheelScrollLines() * cDefaultQtScrollStep;
198 m_deltaY = m_wheelTicksY * QApplication::wheelScrollLines() * cDefaultQtScrollStep;
201 WebKitPlatformWheelEvent::WebKitPlatformWheelEvent(QGraphicsSceneWheelEvent* e)
203 m_timestamp = WTF::currentTime();
204 mouseEventModifiersFromQtKeyboardModifiers(e->modifiers(), m_modifiers);
205 m_position = e->pos().toPoint();
206 m_globalPosition = e->screenPos();
207 m_granularity = ScrollByPixelWheelEvent;
208 m_directionInvertedFromDevice = false;
209 applyDelta(e->delta(), e->orientation());
212 WebKitPlatformWheelEvent::WebKitPlatformWheelEvent(QWheelEvent* e)
214 m_timestamp = WTF::currentTime();
215 mouseEventModifiersFromQtKeyboardModifiers(e->modifiers(), m_modifiers);
216 m_position = e->pos();
217 m_globalPosition = e->globalPos();
218 m_granularity = ScrollByPixelWheelEvent;
219 m_directionInvertedFromDevice = false;
220 applyDelta(e->delta(), e->orientation());
223 #if ENABLE(TOUCH_EVENTS)
224 class WebKitPlatformTouchEvent : public PlatformTouchEvent {
226 WebKitPlatformTouchEvent(QTouchEvent*);
229 class WebKitPlatformTouchPoint : public PlatformTouchPoint {
231 WebKitPlatformTouchPoint(const QTouchEvent::TouchPoint&, State);
234 WebKitPlatformTouchEvent::WebKitPlatformTouchEvent(QTouchEvent* event)
236 switch (event->type()) {
237 case QEvent::TouchBegin:
238 m_type = PlatformEvent::TouchStart;
240 case QEvent::TouchUpdate:
241 m_type = PlatformEvent::TouchMove;
243 case QEvent::TouchEnd:
244 m_type = PlatformEvent::TouchEnd;
247 case QEvent::TouchCancel:
248 m_type = PlatformEvent::TouchCancel;
253 const QList<QTouchEvent::TouchPoint>& points = event->touchPoints();
254 for (int i = 0; i < points.count(); ++i) {
255 PlatformTouchPoint::State state = PlatformTouchPoint::TouchStateEnd;
257 switch (points.at(i).state()) {
258 case Qt::TouchPointReleased:
259 state = PlatformTouchPoint::TouchReleased;
261 case Qt::TouchPointMoved:
262 state = PlatformTouchPoint::TouchMoved;
264 case Qt::TouchPointPressed:
265 state = PlatformTouchPoint::TouchPressed;
267 case Qt::TouchPointStationary:
268 state = PlatformTouchPoint::TouchStationary;
272 // Qt does not have a Qt::TouchPointCancelled point state, so if we receive a touch cancel event,
273 // simply cancel all touch points here.
274 if (m_type == PlatformEvent::TouchCancel)
275 state = PlatformTouchPoint::TouchCancelled;
277 m_touchPoints.append(WebKitPlatformTouchPoint(points.at(i), state));
280 mouseEventModifiersFromQtKeyboardModifiers(event->modifiers(), m_modifiers);
282 m_timestamp = WTF::currentTime();
285 WebKitPlatformTouchPoint::WebKitPlatformTouchPoint(const QTouchEvent::TouchPoint& point, State state)
287 // The QTouchEvent::TouchPoint API states that ids will be >= 0.
290 m_screenPos = point.screenPos().toPoint();
291 m_pos = point.pos().toPoint();
292 // Qt reports touch point size as rectangles, but we will pretend it is an oval.
293 QRect touchRect = point.rect().toAlignedRect();
294 if (touchRect.isValid()) {
295 m_radiusX = point.rect().width() / 2;
296 m_radiusY = point.rect().height() / 2;
298 // http://www.w3.org/TR/2011/WD-touch-events-20110505: 1 if no value is known.
302 m_force = point.pressure();
303 // FIXME: Support m_rotationAngle if QTouchEvent at some point supports it.
307 PlatformWheelEvent convertWheelEvent(QWheelEvent* event)
309 return WebKitPlatformWheelEvent(event);
312 PlatformWheelEvent convertWheelEvent(QGraphicsSceneWheelEvent* event)
314 return WebKitPlatformWheelEvent(event);
317 #if ENABLE(TOUCH_EVENTS)
318 PlatformTouchEvent convertTouchEvent(QTouchEvent* event)
320 return WebKitPlatformTouchEvent(event);