[Release] Webkit2-efl-123997_0.11.86
[framework/web/webkit-efl.git] / Source / WebKit / qt / WebCoreSupport / WebEventConversion.cpp
1 /*
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.
5
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.
10
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.
15
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.
20 */
21
22 #include "config.h"
23 #include "WebEventConversion.h"
24
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>
34
35 namespace WebCore {
36
37 static void mouseEventModifiersFromQtKeyboardModifiers(Qt::KeyboardModifiers keyboardModifiers, unsigned& modifiers)
38 {
39     modifiers = 0;
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;
48 }
49
50 static void mouseEventTypeAndMouseButtonFromQEvent(const QEvent* event, PlatformEvent::Type& mouseEventType, MouseButton& mouseButton)
51 {
52     enum { MouseEvent, GraphicsSceneMouseEvent } frameworkMouseEventType;
53     switch (event->type()) {
54     case QEvent::MouseButtonDblClick:
55     case QEvent::MouseButtonPress:
56         frameworkMouseEventType = MouseEvent;
57         mouseEventType = PlatformEvent::MousePressed;
58         break;
59     case QEvent::MouseButtonRelease:
60         frameworkMouseEventType = MouseEvent;
61         mouseEventType = PlatformEvent::MouseReleased;
62         break;
63     case QEvent::MouseMove:
64         frameworkMouseEventType = MouseEvent;
65         mouseEventType = PlatformEvent::MouseMoved;
66         break;
67     case QEvent::GraphicsSceneMouseDoubleClick:
68     case QEvent::GraphicsSceneMousePress:
69         frameworkMouseEventType = GraphicsSceneMouseEvent;
70         mouseEventType = PlatformEvent::MousePressed;
71         break;
72     case QEvent::GraphicsSceneMouseRelease:
73         frameworkMouseEventType = GraphicsSceneMouseEvent;
74         mouseEventType = PlatformEvent::MouseReleased;
75         break;
76     case QEvent::GraphicsSceneMouseMove:
77         frameworkMouseEventType = GraphicsSceneMouseEvent;
78         mouseEventType = PlatformEvent::MouseMoved;
79         break;
80     default:
81         ASSERT_NOT_REACHED();
82         frameworkMouseEventType = MouseEvent;
83         mouseEventType = PlatformEvent::MouseMoved;
84         break;
85     }
86
87     Qt::MouseButtons mouseButtons;
88     switch (frameworkMouseEventType) {
89     case MouseEvent: {
90         const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event);
91         mouseButtons = mouseEventType == PlatformEvent::MouseMoved ? mouseEvent->buttons() : mouseEvent->button();
92         break;
93     }
94     case GraphicsSceneMouseEvent: {
95         const QGraphicsSceneMouseEvent* mouseEvent = static_cast<const QGraphicsSceneMouseEvent*>(event);
96         mouseButtons = mouseEventType == PlatformEvent::MouseMoved ? mouseEvent->buttons() : mouseEvent->button();
97         break;
98     }
99     }
100
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;
107     else
108         mouseButton = NoButton;
109 }
110
111 class WebKitPlatformMouseEvent : public PlatformMouseEvent {
112 public:
113     WebKitPlatformMouseEvent(QGraphicsSceneMouseEvent*, int clickCount);
114     WebKitPlatformMouseEvent(QInputEvent*, int clickCount);
115 };
116
117 WebKitPlatformMouseEvent::WebKitPlatformMouseEvent(QGraphicsSceneMouseEvent* event, int clickCount)
118 {
119     m_timestamp = WTF::currentTime();
120
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);
125
126     m_type = type;
127     m_position = IntPoint(event->pos().toPoint());
128     m_globalPosition = IntPoint(event->screenPos());
129
130     m_clickCount = clickCount;
131     mouseEventModifiersFromQtKeyboardModifiers(event->modifiers(), m_modifiers);
132 }
133
134 WebKitPlatformMouseEvent::WebKitPlatformMouseEvent(QInputEvent* event, int clickCount)
135 {
136     m_timestamp = WTF::currentTime();
137
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;
147     }
148 #endif
149     if (!isContextMenuEvent) {
150         PlatformEvent::Type type;
151         mouseEventTypeAndMouseButtonFromQEvent(event, type, m_button);
152         QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
153
154         m_type = type;
155         m_position = IntPoint(mouseEvent->pos());
156         m_globalPosition = IntPoint(mouseEvent->globalPos());
157     }
158
159     m_clickCount = clickCount;
160     mouseEventModifiersFromQtKeyboardModifiers(event->modifiers(), m_modifiers);
161 }
162
163 PlatformMouseEvent convertMouseEvent(QInputEvent* event, int clickCount)
164 {
165     return WebKitPlatformMouseEvent(event, clickCount);
166 }
167
168 PlatformMouseEvent convertMouseEvent(QGraphicsSceneMouseEvent* event, int clickCount)
169 {
170     return WebKitPlatformMouseEvent(event, clickCount);
171 }
172
173 class WebKitPlatformWheelEvent : public PlatformWheelEvent {
174 public:
175     WebKitPlatformWheelEvent(QGraphicsSceneWheelEvent*);
176     WebKitPlatformWheelEvent(QWheelEvent*);
177
178 private:
179     void applyDelta(int delta, Qt::Orientation);
180 };
181
182 void WebKitPlatformWheelEvent::applyDelta(int delta, Qt::Orientation orientation)
183 {
184     if (orientation == Qt::Horizontal) {
185         m_deltaX = delta;
186         m_deltaY = 0;
187     } else {
188         m_deltaX = 0;
189         m_deltaY = delta;
190     }
191     m_wheelTicksX = m_deltaX / 120.0f;
192     m_wheelTicksY = m_deltaY / 120.0f;
193
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;
199 }
200
201 WebKitPlatformWheelEvent::WebKitPlatformWheelEvent(QGraphicsSceneWheelEvent* e)
202 {
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());
210 }
211
212 WebKitPlatformWheelEvent::WebKitPlatformWheelEvent(QWheelEvent* e)
213 {
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());
221 }
222
223 #if ENABLE(TOUCH_EVENTS)
224 class WebKitPlatformTouchEvent : public PlatformTouchEvent {
225 public:
226     WebKitPlatformTouchEvent(QTouchEvent*);
227 };
228
229 class WebKitPlatformTouchPoint : public PlatformTouchPoint {
230 public:
231     WebKitPlatformTouchPoint(const QTouchEvent::TouchPoint&, State);
232 };
233
234 WebKitPlatformTouchEvent::WebKitPlatformTouchEvent(QTouchEvent* event)
235 {
236     switch (event->type()) {
237     case QEvent::TouchBegin:
238         m_type = PlatformEvent::TouchStart;
239         break;
240     case QEvent::TouchUpdate:
241         m_type = PlatformEvent::TouchMove;
242         break;
243     case QEvent::TouchEnd:
244         m_type = PlatformEvent::TouchEnd;
245         break;
246 #if HAVE(QT5)
247     case QEvent::TouchCancel:
248         m_type = PlatformEvent::TouchCancel;
249         break;
250 #endif
251     }
252
253     const QList<QTouchEvent::TouchPoint>& points = event->touchPoints();
254     for (int i = 0; i < points.count(); ++i) {
255         PlatformTouchPoint::State state = PlatformTouchPoint::TouchStateEnd;
256
257         switch (points.at(i).state()) {
258         case Qt::TouchPointReleased:
259             state = PlatformTouchPoint::TouchReleased;
260             break;
261         case Qt::TouchPointMoved:
262             state = PlatformTouchPoint::TouchMoved;
263             break;
264         case Qt::TouchPointPressed:
265             state = PlatformTouchPoint::TouchPressed;
266             break;
267         case Qt::TouchPointStationary:
268             state = PlatformTouchPoint::TouchStationary;
269             break;
270         }
271
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;
276
277         m_touchPoints.append(WebKitPlatformTouchPoint(points.at(i), state));
278     }
279
280     mouseEventModifiersFromQtKeyboardModifiers(event->modifiers(), m_modifiers);
281
282     m_timestamp = WTF::currentTime();
283 }
284
285 WebKitPlatformTouchPoint::WebKitPlatformTouchPoint(const QTouchEvent::TouchPoint& point, State state)
286 {
287     // The QTouchEvent::TouchPoint API states that ids will be >= 0.
288     m_id = point.id();
289     m_state = state;
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;
297     } else {
298         // http://www.w3.org/TR/2011/WD-touch-events-20110505: 1 if no value is known.
299         m_radiusX = 1;
300         m_radiusY = 1;
301     }
302     m_force = point.pressure();
303     // FIXME: Support m_rotationAngle if QTouchEvent at some point supports it.
304 }
305 #endif
306
307 PlatformWheelEvent convertWheelEvent(QWheelEvent* event)
308 {
309     return WebKitPlatformWheelEvent(event);
310 }
311
312 PlatformWheelEvent convertWheelEvent(QGraphicsSceneWheelEvent* event)
313 {
314     return WebKitPlatformWheelEvent(event);
315 }
316
317 #if ENABLE(TOUCH_EVENTS)
318 PlatformTouchEvent convertTouchEvent(QTouchEvent* event)
319 {
320     return WebKitPlatformTouchEvent(event);
321 }
322 #endif
323
324 }