1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32 #include "WebInputEventConversion.h"
33
34 #include "EventNames.h"
35 #include "KeyboardCodes.h"
36 #include "KeyboardEvent.h"
37 #include "MouseEvent.h"
38 #include "PlatformKeyboardEvent.h"
39 #include "PlatformMouseEvent.h"
40 #include "PlatformWheelEvent.h"
41 #include "ScrollView.h"
42 #include "WebInputEvent.h"
43 #include "WheelEvent.h"
44 #include "Widget.h"
45
46 using namespace WebCore;
47
48 namespace WebKit {
49
50 // MakePlatformMouseEvent -----------------------------------------------------
51
PlatformMouseEventBuilder(Widget * widget,const WebMouseEvent & e)52 PlatformMouseEventBuilder::PlatformMouseEventBuilder(Widget* widget, const WebMouseEvent& e)
53 {
54 // FIXME: widget is always toplevel, unless it's a popup. We may be able
55 // to get rid of this once we abstract popups into a WebKit API.
56 m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
57 m_globalPosition = IntPoint(e.globalX, e.globalY);
58 m_button = static_cast<MouseButton>(e.button);
59 m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey);
60 m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey);
61 m_altKey = (e.modifiers & WebInputEvent::AltKey);
62 m_metaKey = (e.modifiers & WebInputEvent::MetaKey);
63 m_modifierFlags = e.modifiers;
64 m_timestamp = e.timeStampSeconds;
65 m_clickCount = e.clickCount;
66
67 switch (e.type) {
68 case WebInputEvent::MouseMove:
69 case WebInputEvent::MouseLeave: // synthesize a move event
70 m_eventType = MouseEventMoved;
71 break;
72
73 case WebInputEvent::MouseDown:
74 m_eventType = MouseEventPressed;
75 break;
76
77 case WebInputEvent::MouseUp:
78 m_eventType = MouseEventReleased;
79 break;
80
81 default:
82 ASSERT_NOT_REACHED();
83 }
84 }
85
86 // PlatformWheelEventBuilder --------------------------------------------------
87
PlatformWheelEventBuilder(Widget * widget,const WebMouseWheelEvent & e)88 PlatformWheelEventBuilder::PlatformWheelEventBuilder(Widget* widget, const WebMouseWheelEvent& e)
89 {
90 m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
91 m_globalPosition = IntPoint(e.globalX, e.globalY);
92 m_deltaX = e.deltaX;
93 m_deltaY = e.deltaY;
94 m_wheelTicksX = e.wheelTicksX;
95 m_wheelTicksY = e.wheelTicksY;
96 m_isAccepted = false;
97 m_granularity = e.scrollByPage ?
98 ScrollByPageWheelEvent : ScrollByPixelWheelEvent;
99 m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey);
100 m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey);
101 m_altKey = (e.modifiers & WebInputEvent::AltKey);
102 m_metaKey = (e.modifiers & WebInputEvent::MetaKey);
103 }
104
105 // MakePlatformKeyboardEvent --------------------------------------------------
106
toPlatformKeyboardEventType(WebInputEvent::Type type)107 static inline PlatformKeyboardEvent::Type toPlatformKeyboardEventType(WebInputEvent::Type type)
108 {
109 switch (type) {
110 case WebInputEvent::KeyUp:
111 return PlatformKeyboardEvent::KeyUp;
112 case WebInputEvent::KeyDown:
113 return PlatformKeyboardEvent::KeyDown;
114 case WebInputEvent::RawKeyDown:
115 return PlatformKeyboardEvent::RawKeyDown;
116 case WebInputEvent::Char:
117 return PlatformKeyboardEvent::Char;
118 default:
119 ASSERT_NOT_REACHED();
120 }
121 return PlatformKeyboardEvent::KeyDown;
122 }
123
PlatformKeyboardEventBuilder(const WebKeyboardEvent & e)124 PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder(const WebKeyboardEvent& e)
125 {
126 m_type = toPlatformKeyboardEventType(e.type);
127 m_text = String(e.text);
128 m_unmodifiedText = String(e.unmodifiedText);
129 m_keyIdentifier = String(e.keyIdentifier);
130 m_autoRepeat = (e.modifiers & WebInputEvent::IsAutoRepeat);
131 m_windowsVirtualKeyCode = e.windowsKeyCode;
132 m_nativeVirtualKeyCode = e.nativeKeyCode;
133 m_isKeypad = (e.modifiers & WebInputEvent::IsKeyPad);
134 m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey);
135 m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey);
136 m_altKey = (e.modifiers & WebInputEvent::AltKey);
137 m_metaKey = (e.modifiers & WebInputEvent::MetaKey);
138 m_isSystemKey = e.isSystemKey;
139 }
140
setKeyType(Type type)141 void PlatformKeyboardEventBuilder::setKeyType(Type type)
142 {
143 // According to the behavior of Webkit in Windows platform,
144 // we need to convert KeyDown to RawKeydown and Char events
145 // See WebKit/WebKit/Win/WebView.cpp
146 ASSERT(m_type == KeyDown);
147 ASSERT(type == RawKeyDown || type == Char);
148 m_type = type;
149
150 if (type == RawKeyDown) {
151 m_text = String();
152 m_unmodifiedText = String();
153 } else {
154 m_keyIdentifier = String();
155 m_windowsVirtualKeyCode = 0;
156 }
157 }
158
159 // Please refer to bug http://b/issue?id=961192, which talks about Webkit
160 // keyboard event handling changes. It also mentions the list of keys
161 // which don't have associated character events.
isCharacterKey() const162 bool PlatformKeyboardEventBuilder::isCharacterKey() const
163 {
164 switch (windowsVirtualKeyCode()) {
165 case VKEY_BACK:
166 case VKEY_ESCAPE:
167 return false;
168 }
169 return true;
170 }
171
172 #if ENABLE(TOUCH_EVENTS)
toPlatformTouchEventType(const WebInputEvent::Type type)173 static inline TouchEventType toPlatformTouchEventType(const WebInputEvent::Type type)
174 {
175 switch (type) {
176 case WebInputEvent::TouchStart:
177 return TouchStart;
178 case WebInputEvent::TouchMove:
179 return TouchMove;
180 case WebInputEvent::TouchEnd:
181 return TouchEnd;
182 case WebInputEvent::TouchCancel:
183 return TouchCancel;
184 default:
185 ASSERT_NOT_REACHED();
186 }
187 return TouchStart;
188 }
189
toPlatformTouchPointState(const WebTouchPoint::State state)190 static inline PlatformTouchPoint::State toPlatformTouchPointState(const WebTouchPoint::State state)
191 {
192 switch (state) {
193 case WebTouchPoint::StateReleased:
194 return PlatformTouchPoint::TouchReleased;
195 case WebTouchPoint::StatePressed:
196 return PlatformTouchPoint::TouchPressed;
197 case WebTouchPoint::StateMoved:
198 return PlatformTouchPoint::TouchMoved;
199 case WebTouchPoint::StateStationary:
200 return PlatformTouchPoint::TouchStationary;
201 case WebTouchPoint::StateCancelled:
202 return PlatformTouchPoint::TouchCancelled;
203 case WebTouchPoint::StateUndefined:
204 ASSERT_NOT_REACHED();
205 }
206 return PlatformTouchPoint::TouchReleased;
207 }
208
PlatformTouchPointBuilder(Widget * widget,const WebTouchPoint & point)209 PlatformTouchPointBuilder::PlatformTouchPointBuilder(Widget* widget, const WebTouchPoint& point)
210 {
211 m_id = point.id;
212 m_state = toPlatformTouchPointState(point.state);
213 m_pos = widget->convertFromContainingWindow(point.position);
214 m_screenPos = point.screenPosition;
215 }
216
PlatformTouchEventBuilder(Widget * widget,const WebTouchEvent & event)217 PlatformTouchEventBuilder::PlatformTouchEventBuilder(Widget* widget, const WebTouchEvent& event)
218 {
219 m_type = toPlatformTouchEventType(event.type);
220 m_ctrlKey = event.modifiers & WebInputEvent::ControlKey;
221 m_altKey = event.modifiers & WebInputEvent::AltKey;
222 m_shiftKey = event.modifiers & WebInputEvent::ShiftKey;
223 m_metaKey = event.modifiers & WebInputEvent::MetaKey;
224 m_timestamp = event.timeStampSeconds;
225
226 for (int i = 0; i < event.touchPointsLength; ++i)
227 m_touchPoints.append(PlatformTouchPointBuilder(widget, event.touchPoints[i]));
228 }
229 #endif
230
getWebInputModifiers(const UIEventWithKeyState & event)231 static int getWebInputModifiers(const UIEventWithKeyState& event)
232 {
233 int modifiers = 0;
234 if (event.ctrlKey())
235 modifiers |= WebInputEvent::ControlKey;
236 if (event.shiftKey())
237 modifiers |= WebInputEvent::ShiftKey;
238 if (event.altKey())
239 modifiers |= WebInputEvent::AltKey;
240 if (event.metaKey())
241 modifiers |= WebInputEvent::MetaKey;
242 return modifiers;
243 }
244
WebMouseEventBuilder(const Widget * widget,const MouseEvent & event)245 WebMouseEventBuilder::WebMouseEventBuilder(const Widget* widget, const MouseEvent& event)
246 {
247 if (event.type() == eventNames().mousemoveEvent)
248 type = WebInputEvent::MouseMove;
249 else if (event.type() == eventNames().mouseoutEvent)
250 type = WebInputEvent::MouseLeave;
251 else if (event.type() == eventNames().mouseoverEvent)
252 type = WebInputEvent::MouseEnter;
253 else if (event.type() == eventNames().mousedownEvent)
254 type = WebInputEvent::MouseDown;
255 else if (event.type() == eventNames().mouseupEvent)
256 type = WebInputEvent::MouseUp;
257 else if (event.type() == eventNames().contextmenuEvent)
258 type = WebInputEvent::ContextMenu;
259 else
260 return; // Skip all other mouse events.
261 timeStampSeconds = event.timeStamp() * 1.0e-3;
262 switch (event.button()) {
263 case LeftButton:
264 button = WebMouseEvent::ButtonLeft;
265 break;
266 case MiddleButton:
267 button = WebMouseEvent::ButtonMiddle;
268 break;
269 case RightButton:
270 button = WebMouseEvent::ButtonRight;
271 break;
272 }
273 modifiers = getWebInputModifiers(event);
274 if (event.buttonDown()) {
275 switch (event.button()) {
276 case LeftButton:
277 modifiers |= WebInputEvent::LeftButtonDown;
278 break;
279 case MiddleButton:
280 modifiers |= WebInputEvent::MiddleButtonDown;
281 break;
282 case RightButton:
283 modifiers |= WebInputEvent::RightButtonDown;
284 break;
285 }
286 }
287 ScrollView* view = widget->parent();
288 IntPoint p = view->contentsToWindow(
289 IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y()));
290 globalX = event.screenX();
291 globalY = event.screenY();
292 windowX = p.x();
293 windowY = p.y();
294 x = event.absoluteLocation().x() - widget->pos().x();
295 y = event.absoluteLocation().y() - widget->pos().y();
296 clickCount = event.detail();
297 }
298
WebMouseWheelEventBuilder(const Widget * widget,const WheelEvent & event)299 WebMouseWheelEventBuilder::WebMouseWheelEventBuilder(const Widget* widget, const WheelEvent& event)
300 {
301 if (event.type() != eventNames().mousewheelEvent)
302 return;
303 type = WebInputEvent::MouseWheel;
304 timeStampSeconds = event.timeStamp() * 1.0e-3;
305 modifiers = getWebInputModifiers(event);
306 ScrollView* view = widget->parent();
307 IntPoint p = view->contentsToWindow(
308 IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y()));
309 globalX = event.screenX();
310 globalY = event.screenY();
311 windowX = p.x();
312 windowY = p.y();
313 x = event.absoluteLocation().x() - widget->pos().x();
314 y = event.absoluteLocation().y() - widget->pos().y();
315 deltaX = static_cast<float>(event.rawDeltaX());
316 deltaY = static_cast<float>(event.rawDeltaY());
317 // The 120 is from WheelEvent::initWheelEvent().
318 wheelTicksX = static_cast<float>(event.wheelDeltaX()) / 120;
319 wheelTicksY = static_cast<float>(event.wheelDeltaY()) / 120;
320 scrollByPage = event.granularity() == WheelEvent::Page;
321 }
322
WebKeyboardEventBuilder(const KeyboardEvent & event)323 WebKeyboardEventBuilder::WebKeyboardEventBuilder(const KeyboardEvent& event)
324 {
325 if (event.type() == eventNames().keydownEvent)
326 type = KeyDown;
327 else if (event.type() == eventNames().keyupEvent)
328 type = WebInputEvent::KeyUp;
329 else if (event.type() == eventNames().keypressEvent)
330 type = WebInputEvent::Char;
331 else
332 return; // Skip all other keyboard events.
333 modifiers = getWebInputModifiers(event);
334 timeStampSeconds = event.timeStamp() * 1.0e-3;
335 windowsKeyCode = event.keyCode();
336
337 // The platform keyevent does not exist if the event was created using
338 // initKeyboardEvent.
339 if (!event.keyEvent())
340 return;
341 nativeKeyCode = event.keyEvent()->nativeVirtualKeyCode();
342 unsigned int numChars = std::min(event.keyEvent()->text().length(),
343 static_cast<unsigned int>(WebKeyboardEvent::textLengthCap));
344 for (unsigned int i = 0; i < numChars; i++) {
345 text[i] = event.keyEvent()->text()[i];
346 unmodifiedText[i] = event.keyEvent()->unmodifiedText()[i];
347 }
348 }
349
350 } // namespace WebKit
351