1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "config.h"
28 #include "WebEventFactoryQt.h"
29 #include <qgraphicssceneevent.h>
30 #include <QApplication>
31 #include <QKeyEvent>
32 #include <WebCore/IntPoint.h>
33 #include <WebCore/FloatPoint.h>
34 #include <WebCore/PlatformKeyboardEvent.h>
35 #include <wtf/ASCIICType.h>
36 #include <wtf/CurrentTime.h>
37 
38 using namespace WebCore;
39 
40 namespace WebKit {
41 
mouseButtonForEvent(QGraphicsSceneMouseEvent * event)42 static WebMouseEvent::Button mouseButtonForEvent(QGraphicsSceneMouseEvent *event)
43 {
44     if (event->button() == Qt::LeftButton || (event->buttons() & Qt::LeftButton))
45         return WebMouseEvent::LeftButton;
46     else if (event->button() == Qt::RightButton || (event->buttons() & Qt::RightButton))
47         return WebMouseEvent::RightButton;
48     else if (event->button() == Qt::MidButton || (event->buttons() & Qt::MidButton))
49         return WebMouseEvent::MiddleButton;
50     return WebMouseEvent::NoButton;
51 }
52 
webEventTypeForEvent(QEvent * event)53 static WebEvent::Type webEventTypeForEvent(QEvent* event)
54 {
55     switch (event->type()) {
56         case QEvent::GraphicsSceneMouseDoubleClick:
57         case QEvent::GraphicsSceneMousePress:
58             return WebEvent::MouseDown;
59         case QEvent::GraphicsSceneMouseRelease:
60             return WebEvent::MouseUp;
61         case QEvent::GraphicsSceneMouseMove:
62             return WebEvent::MouseMove;
63         case QEvent::Wheel:
64             return WebEvent::Wheel;
65         case QEvent::KeyPress:
66             return WebEvent::KeyDown;
67         case QEvent::KeyRelease:
68             return WebEvent::KeyUp;
69 #if ENABLE(TOUCH_EVENTS)
70         case QEvent::TouchBegin:
71             return WebEvent::TouchStart;
72         case QEvent::TouchUpdate:
73             return WebEvent::TouchMove;
74         case QEvent::TouchEnd:
75             return WebEvent::TouchEnd;
76 #endif
77         default:
78             // assert
79             return WebEvent::MouseMove;
80     }
81 }
82 
modifiersForEvent(Qt::KeyboardModifiers modifiers)83 static inline WebEvent::Modifiers modifiersForEvent(Qt::KeyboardModifiers modifiers)
84 {
85     unsigned result = 0;
86     if (modifiers & Qt::ShiftModifier)
87         result |= WebEvent::ShiftKey;
88     if (modifiers & Qt::ControlModifier)
89         result |= WebEvent::ControlKey;
90     if (modifiers & Qt::AltModifier)
91         result |= WebEvent::AltKey;
92     if (modifiers & Qt::MetaModifier)
93         result |= WebEvent::MetaKey;
94     return (WebEvent::Modifiers)result;
95 }
96 
createWebMouseEvent(QGraphicsSceneMouseEvent * event,int eventClickCount)97 WebMouseEvent WebEventFactory::createWebMouseEvent(QGraphicsSceneMouseEvent* event, int eventClickCount)
98 {
99     FloatPoint delta(event->pos().x() - event->lastPos().x(), event->pos().y() - event->lastPos().y());
100 
101     WebEvent::Type type             = webEventTypeForEvent(event);
102     WebMouseEvent::Button button    = mouseButtonForEvent(event);
103     float deltaX                    = delta.x();
104     float deltaY                    = delta.y();
105     int clickCount                  = eventClickCount;
106     WebEvent::Modifiers modifiers   = modifiersForEvent(event->modifiers());
107     double timestamp                = WTF::currentTime();
108 
109     return WebMouseEvent(type, button, event->pos().toPoint(), event->screenPos(), deltaX, deltaY, 0.0f, clickCount, modifiers, timestamp);
110 }
111 
createWebWheelEvent(QGraphicsSceneWheelEvent * e)112 WebWheelEvent WebEventFactory::createWebWheelEvent(QGraphicsSceneWheelEvent* e)
113 {
114     float deltaX                            = 0;
115     float deltaY                            = 0;
116     float wheelTicksX                       = 0;
117     float wheelTicksY                       = 0;
118     WebWheelEvent::Granularity granularity  = WebWheelEvent::ScrollByPixelWheelEvent;
119     WebEvent::Modifiers modifiers           = modifiersForEvent(e->modifiers());
120     double timestamp                        = WTF::currentTime();
121 
122     // A delta that is not mod 120 indicates a device that is sending
123     // fine-resolution scroll events, so use the delta as number of wheel ticks
124     // and number of pixels to scroll.See also webkit.org/b/29601
125     bool fullTick = !(e->delta() % 120);
126 
127     if (e->orientation() == Qt::Horizontal) {
128         deltaX = (fullTick) ? e->delta() / 120.0f : e->delta();
129         wheelTicksX = deltaX;
130     } else {
131         deltaY = (fullTick) ? e->delta() / 120.0f : e->delta();
132         wheelTicksY = deltaY;
133     }
134 
135     // Use the same single scroll step as QTextEdit
136     // (in QTextEditPrivate::init [h,v]bar->setSingleStep)
137     static const float cDefaultQtScrollStep = 20.f;
138 #ifndef QT_NO_WHEELEVENT
139     deltaX *= (fullTick) ? QApplication::wheelScrollLines() * cDefaultQtScrollStep : 1;
140     deltaY *= (fullTick) ? QApplication::wheelScrollLines() * cDefaultQtScrollStep : 1;
141 #endif
142 
143     return WebWheelEvent(WebEvent::Wheel, e->pos().toPoint(), e->screenPos(), FloatSize(deltaX, deltaY), FloatSize(wheelTicksX, wheelTicksY), granularity, modifiers, timestamp);
144 }
145 
createWebKeyboardEvent(QKeyEvent * event)146 WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(QKeyEvent* event)
147 {
148     const int state                 = event->modifiers();
149     WebEvent::Type type             = webEventTypeForEvent(event);
150     const String text               = event->text();
151     const String unmodifiedText     = event->text();
152     bool isAutoRepeat               = event->isAutoRepeat();
153     bool isSystemKey                = false; // FIXME: No idea what that is.
154     bool isKeypad                   = (state & Qt::KeypadModifier);
155     const String keyIdentifier      = keyIdentifierForQtKeyCode(event->key());
156     int windowsVirtualKeyCode       = windowsKeyCodeForKeyEvent(event->key(), isKeypad);
157     int nativeVirtualKeyCode        = event->nativeVirtualKey();
158     int macCharCode                 = 0;
159     WebEvent::Modifiers modifiers   = modifiersForEvent(event->modifiers());
160     double timestamp                = WTF::currentTime();
161 
162     return WebKeyboardEvent(type, text, unmodifiedText, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, macCharCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp);
163 }
164 
165 #if ENABLE(TOUCH_EVENTS)
166 
createWebTouchEvent(QTouchEvent * event)167 WebTouchEvent WebEventFactory::createWebTouchEvent(QTouchEvent* event)
168 {
169     WebEvent::Type type  = webEventTypeForEvent(event);
170     WebPlatformTouchPoint::TouchPointState state = static_cast<WebPlatformTouchPoint::TouchPointState>(0);
171     unsigned int id;
172     WebEvent::Modifiers modifiers   = modifiersForEvent(event->modifiers());
173     double timestamp                = WTF::currentTime();
174 
175     const QList<QTouchEvent::TouchPoint>& points = event->touchPoints();
176 
177     Vector<WebPlatformTouchPoint> m_touchPoints;
178     for (int i = 0; i < points.count(); ++i) {
179         id = static_cast<unsigned>(points.at(i).id());
180         switch (points.at(i).state()) {
181         case Qt::TouchPointReleased:
182             state = WebPlatformTouchPoint::TouchReleased;
183             break;
184         case Qt::TouchPointMoved:
185             state = WebPlatformTouchPoint::TouchMoved;
186             break;
187         case Qt::TouchPointPressed:
188             state = WebPlatformTouchPoint::TouchPressed;
189             break;
190         case Qt::TouchPointStationary:
191             state = WebPlatformTouchPoint::TouchStationary;
192             break;
193         default:
194             ASSERT_NOT_REACHED();
195             break;
196         }
197 
198         m_touchPoints.append(WebPlatformTouchPoint(id, state, points.at(i).screenPos().toPoint(), points.at(i).pos().toPoint()));
199     }
200 
201     bool m_ctrlKey = (event->modifiers() & Qt::ControlModifier);
202     bool m_altKey = (event->modifiers() & Qt::AltModifier);
203     bool m_shiftKey = (event->modifiers() & Qt::ShiftModifier);
204     bool m_metaKey = (event->modifiers() & Qt::MetaModifier);
205 
206     return WebTouchEvent(type, m_touchPoints, m_ctrlKey, m_altKey, m_shiftKey, m_metaKey, modifiers, timestamp);
207 }
208 #endif
209 
210 } // namespace WebKit
211