| OLD | NEW |
| (Empty) |
| 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 "web/WebInputEventConversion.h" | |
| 32 | |
| 33 #include "core/dom/Touch.h" | |
| 34 #include "core/dom/TouchList.h" | |
| 35 #include "core/events/GestureEvent.h" | |
| 36 #include "core/events/KeyboardEvent.h" | |
| 37 #include "core/events/MouseEvent.h" | |
| 38 #include "core/events/TouchEvent.h" | |
| 39 #include "core/events/WheelEvent.h" | |
| 40 #include "core/frame/FrameView.h" | |
| 41 #include "core/frame/VisualViewport.h" | |
| 42 #include "core/layout/api/LayoutItem.h" | |
| 43 #include "core/page/ChromeClient.h" | |
| 44 #include "core/page/Page.h" | |
| 45 #include "platform/KeyboardCodes.h" | |
| 46 #include "public/platform/Platform.h" | |
| 47 | |
| 48 namespace blink { | |
| 49 | |
| 50 namespace { | |
| 51 float FrameScale(const FrameView* frame_view) { | |
| 52 float scale = 1; | |
| 53 if (frame_view) { | |
| 54 FrameView* root_view = frame_view->GetFrame().LocalFrameRoot().View(); | |
| 55 if (root_view) | |
| 56 scale = root_view->InputEventsScaleFactor(); | |
| 57 } | |
| 58 return scale; | |
| 59 } | |
| 60 | |
| 61 FloatPoint FrameTranslation(const FrameView* frame_view) { | |
| 62 float scale = 1; | |
| 63 FloatSize offset; | |
| 64 IntPoint visual_viewport; | |
| 65 FloatSize overscroll_offset; | |
| 66 if (frame_view) { | |
| 67 FrameView* root_view = frame_view->GetFrame().LocalFrameRoot().View(); | |
| 68 if (root_view) { | |
| 69 scale = root_view->InputEventsScaleFactor(); | |
| 70 offset = FloatSize(root_view->InputEventsOffsetForEmulation()); | |
| 71 visual_viewport = FlooredIntPoint( | |
| 72 root_view->GetPage()->GetVisualViewport().VisibleRect().Location()); | |
| 73 overscroll_offset = | |
| 74 root_view->GetPage()->GetChromeClient().ElasticOverscroll(); | |
| 75 } | |
| 76 } | |
| 77 return FloatPoint( | |
| 78 -offset.Width() / scale + visual_viewport.X() + overscroll_offset.Width(), | |
| 79 -offset.Height() / scale + visual_viewport.Y() + | |
| 80 overscroll_offset.Height()); | |
| 81 } | |
| 82 | |
| 83 FloatPoint ConvertAbsoluteLocationForLayoutObjectFloat( | |
| 84 const DoublePoint& location, | |
| 85 const LayoutItem layout_item) { | |
| 86 return layout_item.AbsoluteToLocal(FloatPoint(location), kUseTransforms); | |
| 87 } | |
| 88 | |
| 89 IntPoint ConvertAbsoluteLocationForLayoutObjectInt( | |
| 90 const DoublePoint& location, | |
| 91 const LayoutItem layout_item) { | |
| 92 return RoundedIntPoint( | |
| 93 ConvertAbsoluteLocationForLayoutObjectFloat(location, layout_item)); | |
| 94 } | |
| 95 | |
| 96 // FIXME: Change |FrameView| to const FrameView& after RemoteFrames get | |
| 97 // RemoteFrameViews. | |
| 98 void UpdateWebMouseEventFromCoreMouseEvent(const MouseEvent& event, | |
| 99 const FrameView* plugin_parent, | |
| 100 const LayoutItem layout_item, | |
| 101 WebMouseEvent& web_event) { | |
| 102 web_event.SetTimeStampSeconds(event.PlatformTimeStamp().InSeconds()); | |
| 103 web_event.SetModifiers(event.GetModifiers()); | |
| 104 | |
| 105 // TODO(bokan): If plugin_parent == nullptr, pointInRootFrame will really be | |
| 106 // pointInRootContent. | |
| 107 IntPoint point_in_root_frame(event.AbsoluteLocation().X(), | |
| 108 event.AbsoluteLocation().Y()); | |
| 109 if (plugin_parent) { | |
| 110 point_in_root_frame = | |
| 111 plugin_parent->ContentsToRootFrame(point_in_root_frame); | |
| 112 } | |
| 113 web_event.SetPositionInScreen(event.screenX(), event.screenY()); | |
| 114 IntPoint local_point = ConvertAbsoluteLocationForLayoutObjectInt( | |
| 115 event.AbsoluteLocation(), layout_item); | |
| 116 web_event.SetPositionInWidget(local_point.X(), local_point.Y()); | |
| 117 } | |
| 118 | |
| 119 unsigned ToWebInputEventModifierFrom(WebMouseEvent::Button button) { | |
| 120 if (button == WebMouseEvent::Button::kNoButton) | |
| 121 return 0; | |
| 122 | |
| 123 unsigned web_mouse_button_to_platform_modifier[] = { | |
| 124 WebInputEvent::kLeftButtonDown, WebInputEvent::kMiddleButtonDown, | |
| 125 WebInputEvent::kRightButtonDown, WebInputEvent::kBackButtonDown, | |
| 126 WebInputEvent::kForwardButtonDown}; | |
| 127 | |
| 128 return web_mouse_button_to_platform_modifier[static_cast<int>(button)]; | |
| 129 } | |
| 130 | |
| 131 } // namespace | |
| 132 | |
| 133 WebMouseEvent TransformWebMouseEvent(FrameView* frame_view, | |
| 134 const WebMouseEvent& event) { | |
| 135 WebMouseEvent result = event; | |
| 136 | |
| 137 // TODO(dtapuska): Perhaps the event should be constructed correctly? | |
| 138 // crbug.com/686200 | |
| 139 if (event.GetType() == WebInputEvent::kMouseUp) { | |
| 140 result.SetModifiers(event.GetModifiers() & | |
| 141 ~ToWebInputEventModifierFrom(event.button)); | |
| 142 } | |
| 143 result.SetFrameScale(FrameScale(frame_view)); | |
| 144 result.SetFrameTranslate(FrameTranslation(frame_view)); | |
| 145 return result; | |
| 146 } | |
| 147 | |
| 148 WebMouseWheelEvent TransformWebMouseWheelEvent( | |
| 149 FrameView* frame_view, | |
| 150 const WebMouseWheelEvent& event) { | |
| 151 WebMouseWheelEvent result = event; | |
| 152 result.SetFrameScale(FrameScale(frame_view)); | |
| 153 result.SetFrameTranslate(FrameTranslation(frame_view)); | |
| 154 return result; | |
| 155 } | |
| 156 | |
| 157 WebGestureEvent TransformWebGestureEvent(FrameView* frame_view, | |
| 158 const WebGestureEvent& event) { | |
| 159 WebGestureEvent result = event; | |
| 160 result.SetFrameScale(FrameScale(frame_view)); | |
| 161 result.SetFrameTranslate(FrameTranslation(frame_view)); | |
| 162 return result; | |
| 163 } | |
| 164 | |
| 165 WebTouchEvent TransformWebTouchEvent(float frame_scale, | |
| 166 FloatPoint frame_translate, | |
| 167 const WebTouchEvent& event) { | |
| 168 // frameScale is default initialized in debug builds to be 0. | |
| 169 DCHECK_EQ(0, event.FrameScale()); | |
| 170 DCHECK_EQ(0, event.FrameTranslate().x); | |
| 171 DCHECK_EQ(0, event.FrameTranslate().y); | |
| 172 WebTouchEvent result = event; | |
| 173 result.SetFrameScale(frame_scale); | |
| 174 result.SetFrameTranslate(frame_translate); | |
| 175 return result; | |
| 176 } | |
| 177 | |
| 178 WebTouchEvent TransformWebTouchEvent(FrameView* frame_view, | |
| 179 const WebTouchEvent& event) { | |
| 180 return TransformWebTouchEvent(FrameScale(frame_view), | |
| 181 FrameTranslation(frame_view), event); | |
| 182 } | |
| 183 | |
| 184 WebMouseEventBuilder::WebMouseEventBuilder(const FrameView* plugin_parent, | |
| 185 const LayoutItem layout_item, | |
| 186 const MouseEvent& event) { | |
| 187 if (event.NativeEvent()) { | |
| 188 *static_cast<WebMouseEvent*>(this) = | |
| 189 event.NativeEvent()->FlattenTransform(); | |
| 190 WebFloatPoint absolute_location = PositionInRootFrame(); | |
| 191 | |
| 192 // TODO(dtapuska): |plugin_parent| should never be null. Remove this | |
| 193 // conditional code. | |
| 194 // Translate the root frame position to content coordinates. | |
| 195 if (plugin_parent) { | |
| 196 absolute_location = plugin_parent->RootFrameToContents(absolute_location); | |
| 197 } | |
| 198 | |
| 199 IntPoint local_point = RoundedIntPoint( | |
| 200 layout_item.AbsoluteToLocal(absolute_location, kUseTransforms)); | |
| 201 SetPositionInWidget(local_point.X(), local_point.Y()); | |
| 202 return; | |
| 203 } | |
| 204 | |
| 205 // Code below here can be removed once OOPIF ships. | |
| 206 // OOPIF will prevent synthetic events being dispatched into | |
| 207 // other frames; but for now we allow the fallback to generate | |
| 208 // WebMouseEvents from synthetic events. | |
| 209 if (event.type() == EventTypeNames::mousemove) | |
| 210 type_ = WebInputEvent::kMouseMove; | |
| 211 else if (event.type() == EventTypeNames::mouseout) | |
| 212 type_ = WebInputEvent::kMouseLeave; | |
| 213 else if (event.type() == EventTypeNames::mouseover) | |
| 214 type_ = WebInputEvent::kMouseEnter; | |
| 215 else if (event.type() == EventTypeNames::mousedown) | |
| 216 type_ = WebInputEvent::kMouseDown; | |
| 217 else if (event.type() == EventTypeNames::mouseup) | |
| 218 type_ = WebInputEvent::kMouseUp; | |
| 219 else if (event.type() == EventTypeNames::contextmenu) | |
| 220 type_ = WebInputEvent::kContextMenu; | |
| 221 else | |
| 222 return; // Skip all other mouse events. | |
| 223 | |
| 224 time_stamp_seconds_ = event.PlatformTimeStamp().InSeconds(); | |
| 225 modifiers_ = event.GetModifiers(); | |
| 226 UpdateWebMouseEventFromCoreMouseEvent(event, plugin_parent, layout_item, | |
| 227 *this); | |
| 228 | |
| 229 switch (event.button()) { | |
| 230 case short(WebPointerProperties::Button::kLeft): | |
| 231 button = WebMouseEvent::Button::kLeft; | |
| 232 break; | |
| 233 case short(WebPointerProperties::Button::kMiddle): | |
| 234 button = WebMouseEvent::Button::kMiddle; | |
| 235 break; | |
| 236 case short(WebPointerProperties::Button::kRight): | |
| 237 button = WebMouseEvent::Button::kRight; | |
| 238 break; | |
| 239 case short(WebPointerProperties::Button::kBack): | |
| 240 button = WebMouseEvent::Button::kBack; | |
| 241 break; | |
| 242 case short(WebPointerProperties::Button::kForward): | |
| 243 button = WebMouseEvent::Button::kForward; | |
| 244 break; | |
| 245 } | |
| 246 if (event.ButtonDown()) { | |
| 247 switch (event.button()) { | |
| 248 case short(WebPointerProperties::Button::kLeft): | |
| 249 modifiers_ |= WebInputEvent::kLeftButtonDown; | |
| 250 break; | |
| 251 case short(WebPointerProperties::Button::kMiddle): | |
| 252 modifiers_ |= WebInputEvent::kMiddleButtonDown; | |
| 253 break; | |
| 254 case short(WebPointerProperties::Button::kRight): | |
| 255 modifiers_ |= WebInputEvent::kRightButtonDown; | |
| 256 break; | |
| 257 case short(WebPointerProperties::Button::kBack): | |
| 258 modifiers_ |= WebInputEvent::kBackButtonDown; | |
| 259 break; | |
| 260 case short(WebPointerProperties::Button::kForward): | |
| 261 modifiers_ |= WebInputEvent::kForwardButtonDown; | |
| 262 break; | |
| 263 } | |
| 264 } else { | |
| 265 button = WebMouseEvent::Button::kNoButton; | |
| 266 } | |
| 267 movement_x = event.movementX(); | |
| 268 movement_y = event.movementY(); | |
| 269 click_count = event.detail(); | |
| 270 | |
| 271 pointer_type = WebPointerProperties::PointerType::kMouse; | |
| 272 } | |
| 273 | |
| 274 // Generate a synthetic WebMouseEvent given a TouchEvent (eg. for emulating a | |
| 275 // mouse with touch input for plugins that don't support touch input). | |
| 276 WebMouseEventBuilder::WebMouseEventBuilder(const FrameView* plugin_parent, | |
| 277 const LayoutItem layout_item, | |
| 278 const TouchEvent& event) { | |
| 279 if (!event.touches()) | |
| 280 return; | |
| 281 if (event.touches()->length() != 1) { | |
| 282 if (event.touches()->length() || event.type() != EventTypeNames::touchend || | |
| 283 !event.changedTouches() || event.changedTouches()->length() != 1) | |
| 284 return; | |
| 285 } | |
| 286 | |
| 287 const Touch* touch = event.touches()->length() == 1 | |
| 288 ? event.touches()->item(0) | |
| 289 : event.changedTouches()->item(0); | |
| 290 if (touch->identifier()) | |
| 291 return; | |
| 292 | |
| 293 if (event.type() == EventTypeNames::touchstart) | |
| 294 type_ = kMouseDown; | |
| 295 else if (event.type() == EventTypeNames::touchmove) | |
| 296 type_ = kMouseMove; | |
| 297 else if (event.type() == EventTypeNames::touchend) | |
| 298 type_ = kMouseUp; | |
| 299 else | |
| 300 return; | |
| 301 | |
| 302 time_stamp_seconds_ = event.PlatformTimeStamp().InSeconds(); | |
| 303 modifiers_ = event.GetModifiers(); | |
| 304 frame_scale_ = 1; | |
| 305 frame_translate_ = WebFloatPoint(); | |
| 306 | |
| 307 // The mouse event co-ordinates should be generated from the co-ordinates of | |
| 308 // the touch point. | |
| 309 // FIXME: if plugin_parent == nullptr, pointInRootFrame will really be | |
| 310 // pointInRootContent. | |
| 311 IntPoint point_in_root_frame = RoundedIntPoint(touch->AbsoluteLocation()); | |
| 312 if (plugin_parent) { | |
| 313 point_in_root_frame = | |
| 314 plugin_parent->ContentsToRootFrame(point_in_root_frame); | |
| 315 } | |
| 316 IntPoint screen_point = RoundedIntPoint(touch->ScreenLocation()); | |
| 317 SetPositionInScreen(screen_point.X(), screen_point.Y()); | |
| 318 | |
| 319 button = WebMouseEvent::Button::kLeft; | |
| 320 modifiers_ |= WebInputEvent::kLeftButtonDown; | |
| 321 click_count = (type_ == kMouseDown || type_ == kMouseUp); | |
| 322 | |
| 323 IntPoint local_point = ConvertAbsoluteLocationForLayoutObjectInt( | |
| 324 DoublePoint(touch->AbsoluteLocation()), layout_item); | |
| 325 SetPositionInWidget(local_point.X(), local_point.Y()); | |
| 326 | |
| 327 pointer_type = WebPointerProperties::PointerType::kTouch; | |
| 328 } | |
| 329 | |
| 330 WebKeyboardEventBuilder::WebKeyboardEventBuilder(const KeyboardEvent& event) { | |
| 331 if (const WebKeyboardEvent* web_event = event.KeyEvent()) { | |
| 332 *static_cast<WebKeyboardEvent*>(this) = *web_event; | |
| 333 | |
| 334 // TODO(dtapuska): DOM KeyboardEvents converted back to WebInputEvents | |
| 335 // drop the Raw behaviour. Figure out if this is actually really needed. | |
| 336 if (type_ == kRawKeyDown) | |
| 337 type_ = kKeyDown; | |
| 338 return; | |
| 339 } | |
| 340 | |
| 341 if (event.type() == EventTypeNames::keydown) | |
| 342 type_ = kKeyDown; | |
| 343 else if (event.type() == EventTypeNames::keyup) | |
| 344 type_ = WebInputEvent::kKeyUp; | |
| 345 else if (event.type() == EventTypeNames::keypress) | |
| 346 type_ = WebInputEvent::kChar; | |
| 347 else | |
| 348 return; // Skip all other keyboard events. | |
| 349 | |
| 350 modifiers_ = event.GetModifiers(); | |
| 351 time_stamp_seconds_ = event.PlatformTimeStamp().InSeconds(); | |
| 352 windows_key_code = event.keyCode(); | |
| 353 } | |
| 354 | |
| 355 Vector<WebMouseEvent> TransformWebMouseEventVector( | |
| 356 FrameView* frame_view, | |
| 357 const std::vector<const WebInputEvent*>& coalesced_events) { | |
| 358 Vector<WebMouseEvent> result; | |
| 359 for (const auto& event : coalesced_events) { | |
| 360 DCHECK(WebInputEvent::IsMouseEventType(event->GetType())); | |
| 361 result.push_back(TransformWebMouseEvent( | |
| 362 frame_view, static_cast<const WebMouseEvent&>(*event))); | |
| 363 } | |
| 364 return result; | |
| 365 } | |
| 366 | |
| 367 Vector<WebTouchEvent> TransformWebTouchEventVector( | |
| 368 FrameView* frame_view, | |
| 369 const std::vector<const WebInputEvent*>& coalesced_events) { | |
| 370 float scale = FrameScale(frame_view); | |
| 371 FloatPoint translation = FrameTranslation(frame_view); | |
| 372 Vector<WebTouchEvent> result; | |
| 373 for (const auto& event : coalesced_events) { | |
| 374 DCHECK(WebInputEvent::IsTouchEventType(event->GetType())); | |
| 375 result.push_back(TransformWebTouchEvent( | |
| 376 scale, translation, static_cast<const WebTouchEvent&>(*event))); | |
| 377 } | |
| 378 return result; | |
| 379 } | |
| 380 | |
| 381 } // namespace blink | |
| OLD | NEW |