1/* 2 * Copyright (C) 2011 Samsung Electronics 3 * Copyright (C) 2012 Intel Corporation 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 "WebEventFactory.h" 29 30#include "EflKeyboardUtilities.h" 31#include <WebCore/AffineTransform.h> 32#include <WebCore/Scrollbar.h> 33 34#if ENABLE(TOUCH_EVENTS) 35#include "APIArray.h" 36#include "EwkTouchEvent.h" 37#include "EwkTouchPoint.h" 38#include "WKAPICast.h" 39#endif 40 41using namespace WebCore; 42 43namespace WebKit { 44 45enum { 46 VerticalScrollDirection = 0, 47 HorizontalScrollDirection = 1 48}; 49 50enum { 51 LeftButton = 1, 52 MiddleButton = 2, 53 RightButton = 3 54}; 55 56static const char keyPadPrefix[] = "KP_"; 57 58static inline WebEvent::Modifiers modifiersForEvent(const Evas_Modifier* modifiers) 59{ 60 unsigned result = 0; 61 62 if (evas_key_modifier_is_set(modifiers, "Shift")) 63 result |= WebEvent::ShiftKey; 64 if (evas_key_modifier_is_set(modifiers, "Control")) 65 result |= WebEvent::ControlKey; 66 if (evas_key_modifier_is_set(modifiers, "Alt")) 67 result |= WebEvent::AltKey; 68 if (evas_key_modifier_is_set(modifiers, "Meta")) 69 result |= WebEvent::MetaKey; 70 71 return static_cast<WebEvent::Modifiers>(result); 72} 73 74static inline WebMouseEvent::Button buttonForEvent(int button) 75{ 76 if (button == LeftButton) 77 return WebMouseEvent::LeftButton; 78 if (button == MiddleButton) 79 return WebMouseEvent::MiddleButton; 80 if (button == RightButton) 81 return WebMouseEvent::RightButton; 82 83 return WebMouseEvent::NoButton; 84} 85 86static inline int clickCountForEvent(const Evas_Button_Flags flags) 87{ 88 if (flags & EVAS_BUTTON_TRIPLE_CLICK) 89 return 3; 90 if (flags & EVAS_BUTTON_DOUBLE_CLICK) 91 return 2; 92 93 return 1; 94} 95 96static inline double convertMillisecondToSecond(unsigned timestamp) 97{ 98 return static_cast<double>(timestamp) / 1000; 99} 100 101WebMouseEvent WebEventFactory::createWebMouseEvent(const Evas_Event_Mouse_Down* event, const AffineTransform& toWebContent, const AffineTransform& toDeviceScreen) 102{ 103 IntPoint pos(event->canvas.x, event->canvas.y); 104 return WebMouseEvent(WebEvent::MouseDown, 105 buttonForEvent(event->button), 106 toWebContent.mapPoint(pos), 107 toDeviceScreen.mapPoint(pos), 108 0 /* deltaX */, 109 0 /* deltaY */, 110 0 /* deltaZ */, 111 clickCountForEvent(event->flags), 112 modifiersForEvent(event->modifiers), 113 convertMillisecondToSecond(event->timestamp)); 114} 115 116WebMouseEvent WebEventFactory::createWebMouseEvent(const Evas_Event_Mouse_Up* event, const AffineTransform& toWebContent, const AffineTransform& toDeviceScreen) 117{ 118 IntPoint pos(event->canvas.x, event->canvas.y); 119 return WebMouseEvent(WebEvent::MouseUp, 120 buttonForEvent(event->button), 121 toWebContent.mapPoint(pos), 122 toDeviceScreen.mapPoint(pos), 123 0 /* deltaX */, 124 0 /* deltaY */, 125 0 /* deltaZ */, 126 clickCountForEvent(event->flags), 127 modifiersForEvent(event->modifiers), 128 convertMillisecondToSecond(event->timestamp)); 129} 130 131WebMouseEvent WebEventFactory::createWebMouseEvent(const Evas_Event_Mouse_Move* event, const AffineTransform& toWebContent, const AffineTransform& toDeviceScreen) 132{ 133 IntPoint pos(event->cur.canvas.x, event->cur.canvas.y); 134 return WebMouseEvent(WebEvent::MouseMove, 135 buttonForEvent(event->buttons), 136 toWebContent.mapPoint(pos), 137 toDeviceScreen.mapPoint(pos), 138 (event->cur.canvas.x - event->prev.canvas.x) /* deltaX */, 139 (event->cur.canvas.y - event->prev.canvas.y) /* deltaY */, 140 0 /* deltaZ */, 141 0 /* clickCount */, 142 modifiersForEvent(event->modifiers), 143 convertMillisecondToSecond(event->timestamp)); 144} 145 146WebWheelEvent WebEventFactory::createWebWheelEvent(const Evas_Event_Mouse_Wheel* event, const AffineTransform& toWebContent, const AffineTransform& toDeviceScreen) 147{ 148 float deltaX = 0; 149 float deltaY = 0; 150 float wheelTicksX = 0; 151 float wheelTicksY = 0; 152 153 // A negative z value means (in EFL) that we are scrolling down, so we need 154 // to invert the value. 155 if (event->direction == VerticalScrollDirection) { 156 deltaX = 0; 157 deltaY = - event->z; 158 } else if (event->direction == HorizontalScrollDirection) { 159 deltaX = - event->z; 160 deltaY = 0; 161 } 162 163 wheelTicksX = deltaX; 164 wheelTicksY = deltaY; 165 deltaX *= static_cast<float>(Scrollbar::pixelsPerLineStep()); 166 deltaY *= static_cast<float>(Scrollbar::pixelsPerLineStep()); 167 168 IntPoint pos(event->canvas.x, event->canvas.y); 169 170 return WebWheelEvent(WebEvent::Wheel, 171 toWebContent.mapPoint(pos), 172 toDeviceScreen.mapPoint(pos), 173 FloatSize(deltaX, deltaY), 174 FloatSize(wheelTicksX, wheelTicksY), 175 WebWheelEvent::ScrollByPixelWheelEvent, 176 modifiersForEvent(event->modifiers), 177 convertMillisecondToSecond(event->timestamp)); 178} 179 180WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(const Evas_Event_Key_Down* event) 181{ 182 const String keyName(event->key); 183 return WebKeyboardEvent(WebEvent::KeyDown, 184 String::fromUTF8(event->string), 185 String::fromUTF8(event->string), 186 keyIdentifierForEvasKeyName(keyName), 187 windowsKeyCodeForEvasKeyName(keyName), 188 0 /* FIXME: nativeVirtualKeyCode */, 189 0 /* macCharCode */, 190 false /* FIXME: isAutoRepeat */, 191 keyName.startsWith(keyPadPrefix), 192 false /* isSystemKey */, 193 modifiersForEvent(event->modifiers), 194 convertMillisecondToSecond(event->timestamp)); 195} 196 197WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(const Evas_Event_Key_Up* event) 198{ 199 const String keyName(event->key); 200 return WebKeyboardEvent(WebEvent::KeyUp, 201 String::fromUTF8(event->string), 202 String::fromUTF8(event->string), 203 keyIdentifierForEvasKeyName(keyName), 204 windowsKeyCodeForEvasKeyName(keyName), 205 0 /* FIXME: nativeVirtualKeyCode */, 206 0 /* macCharCode */, 207 false /* FIXME: isAutoRepeat */, 208 keyName.startsWith(keyPadPrefix), 209 false /* isSystemKey */, 210 modifiersForEvent(event->modifiers), 211 convertMillisecondToSecond(event->timestamp)); 212} 213 214#if ENABLE(TOUCH_EVENTS) 215static inline WebPlatformTouchPoint::TouchPointState toWebPlatformTouchPointState(WKTouchPointState state) 216{ 217 switch (state) { 218 case kWKTouchPointStateTouchReleased: 219 return WebPlatformTouchPoint::TouchReleased; 220 case kWKTouchPointStateTouchMoved: 221 return WebPlatformTouchPoint::TouchMoved; 222 case kWKTouchPointStateTouchPressed: 223 return WebPlatformTouchPoint::TouchPressed; 224 case kWKTouchPointStateTouchStationary: 225 return WebPlatformTouchPoint::TouchStationary; 226 case kWKTouchPointStateTouchCancelled: 227 default: 228 return WebPlatformTouchPoint::TouchCancelled; 229 } 230} 231 232static inline WebEvent::Type toWebEventType(WKEventType type) 233{ 234 switch (type) { 235 case kWKEventTypeTouchStart: 236 return WebEvent::TouchStart; 237 case kWKEventTypeTouchMove: 238 return WebEvent::TouchMove; 239 case kWKEventTypeTouchEnd: 240 return WebEvent::TouchEnd; 241 case kWKEventTypeTouchCancel: 242 return WebEvent::TouchCancel; 243 default: 244 return WebEvent::NoType; 245 } 246 247} 248 249static inline WebEvent::Modifiers toWebEventModifiers(unsigned modifiers) 250{ 251 unsigned result = 0; 252 253 if (modifiers & kWKEventModifiersShiftKey) 254 result |= WebEvent::ShiftKey; 255 if (modifiers & kWKEventModifiersControlKey) 256 result |= WebEvent::ControlKey; 257 if (modifiers & kWKEventModifiersAltKey) 258 result |= WebEvent::AltKey; 259 if (modifiers & kWKEventModifiersMetaKey) 260 result |= WebEvent::MetaKey; 261 262 return static_cast<WebEvent::Modifiers>(result); 263} 264 265WebTouchEvent WebEventFactory::createWebTouchEvent(const EwkTouchEvent* event, const AffineTransform& toWebContent) 266{ 267 API::Array* touchPointsArray = toImpl(event->touchPoints()); 268 size_t size = touchPointsArray->size(); 269 270 Vector<WebPlatformTouchPoint> touchPoints; 271 touchPoints.reserveInitialCapacity(size); 272 273 for (size_t i = 0; i < size; ++i) { 274 if (EwkTouchPoint* point = touchPointsArray->at<EwkTouchPoint>(i)) 275 touchPoints.uncheckedAppend(WebPlatformTouchPoint(point->id(), toWebPlatformTouchPointState(point->state()), toIntPoint(point->screenPosition()), toWebContent.mapPoint(toIntPoint(point->position())), toIntSize(point->radius()), point->rotationAngle(), point->forceFactor())); 276 } 277 278 return WebTouchEvent(toWebEventType(event->eventType()), touchPoints, toWebEventModifiers(event->modifiers()), event->timestamp()); 279} 280#endif 281 282} // namespace WebKit 283