OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2001 Peter Kelly (pmk@post.com) | 2 * Copyright (C) 2001 Peter Kelly (pmk@post.com) |
3 * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de) | 3 * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de) |
4 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) | 4 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) |
5 * Copyright (C) 2003, 2005, 2006, 2008 Apple Inc. All rights reserved. | 5 * Copyright (C) 2003, 2005, 2006, 2008 Apple Inc. All rights reserved. |
6 * | 6 * |
7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
11 * | 11 * |
12 * This library is distributed in the hope that it will be useful, | 12 * This library is distributed in the hope that it will be useful, |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 * Library General Public License for more details. | 15 * Library General Public License for more details. |
16 * | 16 * |
17 * You should have received a copy of the GNU Library General Public License | 17 * You should have received a copy of the GNU Library General Public License |
18 * along with this library; see the file COPYING.LIB. If not, write to | 18 * along with this library; see the file COPYING.LIB. If not, write to |
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
20 * Boston, MA 02110-1301, USA. | 20 * Boston, MA 02110-1301, USA. |
21 */ | 21 */ |
22 | 22 |
23 #include "core/events/MouseEvent.h" | 23 #include "core/events/MouseEvent.h" |
24 | 24 |
25 #include "bindings/core/v8/DOMWrapperWorld.h" | 25 #include "bindings/core/v8/DOMWrapperWorld.h" |
26 #include "bindings/core/v8/ScriptState.h" | 26 #include "bindings/core/v8/ScriptState.h" |
27 #include "core/dom/Element.h" | 27 #include "core/dom/Element.h" |
28 #include "core/events/EventDispatcher.h" | 28 #include "core/events/EventDispatcher.h" |
| 29 #include "core/frame/FrameView.h" |
| 30 #include "core/frame/LocalDOMWindow.h" |
| 31 #include "core/frame/LocalFrame.h" |
| 32 #include "core/layout/LayoutObject.h" |
| 33 #include "core/paint/PaintLayer.h" |
| 34 #include "core/svg/SVGElement.h" |
29 #include "platform/PlatformMouseEvent.h" | 35 #include "platform/PlatformMouseEvent.h" |
30 #include "public/platform/WebPointerProperties.h" | 36 #include "public/platform/WebPointerProperties.h" |
31 | 37 |
32 namespace blink { | 38 namespace blink { |
33 | 39 |
| 40 namespace { |
| 41 |
| 42 LayoutSize contentsScrollOffset(AbstractView* abstractView) { |
| 43 if (!abstractView || !abstractView->isLocalDOMWindow()) |
| 44 return LayoutSize(); |
| 45 LocalFrame* frame = toLocalDOMWindow(abstractView)->frame(); |
| 46 if (!frame) |
| 47 return LayoutSize(); |
| 48 FrameView* frameView = frame->view(); |
| 49 if (!frameView) |
| 50 return LayoutSize(); |
| 51 float scaleFactor = frame->pageZoomFactor(); |
| 52 return LayoutSize(frameView->scrollX() / scaleFactor, |
| 53 frameView->scrollY() / scaleFactor); |
| 54 } |
| 55 |
| 56 float pageZoomFactor(const UIEvent* event) { |
| 57 if (!event->view() || !event->view()->isLocalDOMWindow()) |
| 58 return 1; |
| 59 LocalFrame* frame = toLocalDOMWindow(event->view())->frame(); |
| 60 if (!frame) |
| 61 return 1; |
| 62 return frame->pageZoomFactor(); |
| 63 } |
| 64 |
| 65 const LayoutObject* findTargetLayoutObject(Node*& targetNode) { |
| 66 LayoutObject* layoutObject = targetNode->layoutObject(); |
| 67 if (!layoutObject || !layoutObject->isSVG()) |
| 68 return layoutObject; |
| 69 // If this is an SVG node, compute the offset to the padding box of the |
| 70 // outermost SVG root (== the closest ancestor that has a CSS layout box.) |
| 71 while (!layoutObject->isSVGRoot()) |
| 72 layoutObject = layoutObject->parent(); |
| 73 // Update the target node to point to the SVG root. |
| 74 targetNode = layoutObject->node(); |
| 75 DCHECK(!targetNode || (targetNode->isSVGElement() && |
| 76 toSVGElement(*targetNode).isOutermostSVGSVGElement())); |
| 77 return layoutObject; |
| 78 } |
| 79 |
| 80 } // namespace |
| 81 |
34 MouseEvent* MouseEvent::create(ScriptState* scriptState, | 82 MouseEvent* MouseEvent::create(ScriptState* scriptState, |
35 const AtomicString& type, | 83 const AtomicString& type, |
36 const MouseEventInit& initializer) { | 84 const MouseEventInit& initializer) { |
37 if (scriptState && scriptState->world().isIsolatedWorld()) | 85 if (scriptState && scriptState->world().isIsolatedWorld()) |
38 UIEventWithKeyState::didCreateEventInIsolatedWorld( | 86 UIEventWithKeyState::didCreateEventInIsolatedWorld( |
39 initializer.ctrlKey(), initializer.altKey(), initializer.shiftKey(), | 87 initializer.ctrlKey(), initializer.altKey(), initializer.shiftKey(), |
40 initializer.metaKey()); | 88 initializer.metaKey()); |
41 return new MouseEvent(type, initializer); | 89 return new MouseEvent(type, initializer); |
42 } | 90 } |
43 | 91 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 createdEvent->setUnderlyingEvent(underlyingEvent); | 167 createdEvent->setUnderlyingEvent(underlyingEvent); |
120 if (syntheticType == PlatformMouseEvent::RealOrIndistinguishable) { | 168 if (syntheticType == PlatformMouseEvent::RealOrIndistinguishable) { |
121 MouseEvent* mouseEvent = toMouseEvent(createdEvent->underlyingEvent()); | 169 MouseEvent* mouseEvent = toMouseEvent(createdEvent->underlyingEvent()); |
122 createdEvent->initCoordinates(mouseEvent->clientX(), mouseEvent->clientY()); | 170 createdEvent->initCoordinates(mouseEvent->clientX(), mouseEvent->clientY()); |
123 } | 171 } |
124 | 172 |
125 return createdEvent; | 173 return createdEvent; |
126 } | 174 } |
127 | 175 |
128 MouseEvent::MouseEvent() | 176 MouseEvent::MouseEvent() |
129 : m_button(0), | 177 : m_positionType(PositionType::Position), |
| 178 m_hasCachedRelativePosition(false), |
| 179 m_button(0), |
130 m_buttons(0), | 180 m_buttons(0), |
131 m_relatedTarget(nullptr), | 181 m_relatedTarget(nullptr), |
132 m_syntheticEventType(PlatformMouseEvent::RealOrIndistinguishable) {} | 182 m_syntheticEventType(PlatformMouseEvent::RealOrIndistinguishable) {} |
133 | 183 |
134 MouseEvent::MouseEvent( | 184 MouseEvent::MouseEvent( |
135 const AtomicString& eventType, | 185 const AtomicString& eventType, |
136 bool canBubble, | 186 bool canBubble, |
137 bool cancelable, | 187 bool cancelable, |
138 AbstractView* view, | 188 AbstractView* abstractView, |
139 int detail, | 189 int detail, |
140 int screenX, | 190 int screenX, |
141 int screenY, | 191 int screenY, |
142 int windowX, | 192 int windowX, |
143 int windowY, | 193 int windowY, |
144 int movementX, | 194 int movementX, |
145 int movementY, | 195 int movementY, |
146 PlatformEvent::Modifiers modifiers, | 196 PlatformEvent::Modifiers modifiers, |
147 short button, | 197 short button, |
148 unsigned short buttons, | 198 unsigned short buttons, |
149 EventTarget* relatedTarget, | 199 EventTarget* relatedTarget, |
150 TimeTicks platformTimeStamp, | 200 TimeTicks platformTimeStamp, |
151 PlatformMouseEvent::SyntheticEventType syntheticEventType, | 201 PlatformMouseEvent::SyntheticEventType syntheticEventType, |
152 const String& region, | 202 const String& region, |
153 const PlatformMouseEvent* mouseEvent) | 203 const PlatformMouseEvent* mouseEvent) |
154 : MouseRelatedEvent( | 204 : UIEventWithKeyState( |
155 eventType, | 205 eventType, |
156 canBubble, | 206 canBubble, |
157 cancelable, | 207 cancelable, |
158 view, | 208 abstractView, |
159 detail, | 209 detail, |
160 IntPoint(screenX, screenY), | |
161 IntPoint(windowX, windowY), | |
162 IntPoint(movementX, movementY), | |
163 modifiers, | 210 modifiers, |
164 platformTimeStamp, | 211 platformTimeStamp, |
165 syntheticEventType == PlatformMouseEvent::Positionless | |
166 ? PositionType::Positionless | |
167 : PositionType::Position, | |
168 syntheticEventType == PlatformMouseEvent::FromTouch | 212 syntheticEventType == PlatformMouseEvent::FromTouch |
169 ? InputDeviceCapabilities::firesTouchEventsSourceCapabilities() | 213 ? InputDeviceCapabilities::firesTouchEventsSourceCapabilities() |
170 : InputDeviceCapabilities:: | 214 : InputDeviceCapabilities:: |
171 doesntFireTouchEventsSourceCapabilities()), | 215 doesntFireTouchEventsSourceCapabilities()), |
| 216 m_screenLocation(screenX, screenY), |
| 217 m_movementDelta(movementX, movementY), |
| 218 m_positionType(syntheticEventType == PlatformMouseEvent::Positionless |
| 219 ? PositionType::Positionless |
| 220 : PositionType::Position), |
172 m_button(button), | 221 m_button(button), |
173 m_buttons(buttons), | 222 m_buttons(buttons), |
174 m_relatedTarget(relatedTarget), | 223 m_relatedTarget(relatedTarget), |
175 m_syntheticEventType(syntheticEventType), | 224 m_syntheticEventType(syntheticEventType), |
176 m_region(region) { | 225 m_region(region) { |
177 if (mouseEvent) | 226 if (mouseEvent) |
178 m_mouseEvent.reset(new PlatformMouseEvent(*mouseEvent)); | 227 m_mouseEvent.reset(new PlatformMouseEvent(*mouseEvent)); |
| 228 |
| 229 DoublePoint adjustedPageLocation; |
| 230 DoubleSize scrollOffset; |
| 231 |
| 232 LocalFrame* frame = view() && view()->isLocalDOMWindow() |
| 233 ? toLocalDOMWindow(view())->frame() |
| 234 : nullptr; |
| 235 if (frame && hasPosition()) { |
| 236 if (FrameView* frameView = frame->view()) { |
| 237 adjustedPageLocation = |
| 238 frameView->rootFrameToContents(IntPoint(windowX, windowY)); |
| 239 scrollOffset = frameView->scrollOffsetInt(); |
| 240 float scaleFactor = 1 / frame->pageZoomFactor(); |
| 241 if (scaleFactor != 1.0f) { |
| 242 adjustedPageLocation.scale(scaleFactor, scaleFactor); |
| 243 scrollOffset.scale(scaleFactor, scaleFactor); |
| 244 } |
| 245 } |
| 246 } |
| 247 |
| 248 m_clientLocation = adjustedPageLocation - scrollOffset; |
| 249 m_pageLocation = adjustedPageLocation; |
| 250 |
| 251 // Set up initial values for coordinates. |
| 252 // Correct values are computed lazily, see computeRelativePosition. |
| 253 m_layerLocation = m_pageLocation; |
| 254 m_offsetLocation = m_pageLocation; |
| 255 |
| 256 computePageLocation(); |
| 257 m_hasCachedRelativePosition = false; |
179 } | 258 } |
180 | 259 |
181 MouseEvent::MouseEvent(const AtomicString& eventType, | 260 MouseEvent::MouseEvent(const AtomicString& eventType, |
182 const MouseEventInit& initializer) | 261 const MouseEventInit& initializer) |
183 : MouseRelatedEvent(eventType, initializer), | 262 : UIEventWithKeyState(eventType, initializer), |
| 263 m_screenLocation( |
| 264 DoublePoint(initializer.screenX(), initializer.screenY())), |
| 265 m_movementDelta( |
| 266 IntPoint(initializer.movementX(), initializer.movementY())), |
| 267 m_positionType(PositionType::Position), |
184 m_button(initializer.button()), | 268 m_button(initializer.button()), |
185 m_buttons(initializer.buttons()), | 269 m_buttons(initializer.buttons()), |
186 m_relatedTarget(initializer.relatedTarget()), | 270 m_relatedTarget(initializer.relatedTarget()), |
187 m_syntheticEventType(PlatformMouseEvent::RealOrIndistinguishable), | 271 m_syntheticEventType(PlatformMouseEvent::RealOrIndistinguishable), |
188 m_region(initializer.region()) {} | 272 m_region(initializer.region()) { |
| 273 initCoordinates(initializer.clientX(), initializer.clientY()); |
| 274 } |
| 275 |
| 276 void MouseEvent::initCoordinates(const double clientX, const double clientY) { |
| 277 // Set up initial values for coordinates. |
| 278 // Correct values are computed lazily, see computeRelativePosition. |
| 279 m_clientLocation = DoublePoint(clientX, clientY); |
| 280 m_pageLocation = m_clientLocation + DoubleSize(contentsScrollOffset(view())); |
| 281 |
| 282 m_layerLocation = m_pageLocation; |
| 283 m_offsetLocation = m_pageLocation; |
| 284 |
| 285 computePageLocation(); |
| 286 m_hasCachedRelativePosition = false; |
| 287 } |
189 | 288 |
190 MouseEvent::~MouseEvent() {} | 289 MouseEvent::~MouseEvent() {} |
191 | 290 |
192 unsigned short MouseEvent::platformModifiersToButtons(unsigned modifiers) { | 291 unsigned short MouseEvent::platformModifiersToButtons(unsigned modifiers) { |
193 unsigned short buttons = 0; | 292 unsigned short buttons = 0; |
194 | 293 |
195 if (modifiers & PlatformEvent::LeftButtonDown) | 294 if (modifiers & PlatformEvent::LeftButtonDown) |
196 buttons |= static_cast<unsigned short>(WebPointerProperties::Buttons::Left); | 295 buttons |= static_cast<unsigned short>(WebPointerProperties::Buttons::Left); |
197 if (modifiers & PlatformEvent::RightButtonDown) | 296 if (modifiers & PlatformEvent::RightButtonDown) |
198 buttons |= | 297 buttons |= |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 // exiting during the event" (huh?) | 394 // exiting during the event" (huh?) |
296 if (type() != EventTypeNames::mouseout && | 395 if (type() != EventTypeNames::mouseout && |
297 type() != EventTypeNames::mouseleave) | 396 type() != EventTypeNames::mouseleave) |
298 return relatedTarget() ? relatedTarget()->toNode() : nullptr; | 397 return relatedTarget() ? relatedTarget()->toNode() : nullptr; |
299 | 398 |
300 return target() ? target()->toNode() : nullptr; | 399 return target() ? target()->toNode() : nullptr; |
301 } | 400 } |
302 | 401 |
303 DEFINE_TRACE(MouseEvent) { | 402 DEFINE_TRACE(MouseEvent) { |
304 visitor->trace(m_relatedTarget); | 403 visitor->trace(m_relatedTarget); |
305 MouseRelatedEvent::trace(visitor); | 404 UIEventWithKeyState::trace(visitor); |
306 } | 405 } |
307 | 406 |
308 EventDispatchMediator* MouseEvent::createMediator() { | 407 EventDispatchMediator* MouseEvent::createMediator() { |
309 return MouseEventDispatchMediator::create(this); | 408 return MouseEventDispatchMediator::create(this); |
310 } | 409 } |
311 | 410 |
312 MouseEventDispatchMediator* MouseEventDispatchMediator::create( | 411 MouseEventDispatchMediator* MouseEventDispatchMediator::create( |
313 MouseEvent* mouseEvent) { | 412 MouseEvent* mouseEvent) { |
314 return new MouseEventDispatchMediator(mouseEvent); | 413 return new MouseEventDispatchMediator(mouseEvent); |
315 } | 414 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 doubleClickEvent->setDefaultHandled(); | 464 doubleClickEvent->setDefaultHandled(); |
366 DispatchEventResult doubleClickDispatchResult = | 465 DispatchEventResult doubleClickDispatchResult = |
367 EventDispatcher::dispatchEvent( | 466 EventDispatcher::dispatchEvent( |
368 dispatcher.node(), | 467 dispatcher.node(), |
369 MouseEventDispatchMediator::create(doubleClickEvent)); | 468 MouseEventDispatchMediator::create(doubleClickEvent)); |
370 if (doubleClickDispatchResult != DispatchEventResult::NotCanceled) | 469 if (doubleClickDispatchResult != DispatchEventResult::NotCanceled) |
371 return doubleClickDispatchResult; | 470 return doubleClickDispatchResult; |
372 return dispatchResult; | 471 return dispatchResult; |
373 } | 472 } |
374 | 473 |
| 474 void MouseEvent::computePageLocation() { |
| 475 float scaleFactor = pageZoomFactor(this); |
| 476 m_absoluteLocation = m_pageLocation.scaledBy(scaleFactor); |
| 477 } |
| 478 |
| 479 void MouseEvent::receivedTarget() { |
| 480 m_hasCachedRelativePosition = false; |
| 481 } |
| 482 |
| 483 void MouseEvent::computeRelativePosition() { |
| 484 Node* targetNode = target() ? target()->toNode() : nullptr; |
| 485 if (!targetNode) |
| 486 return; |
| 487 |
| 488 // Compute coordinates that are based on the target. |
| 489 m_layerLocation = m_pageLocation; |
| 490 m_offsetLocation = m_pageLocation; |
| 491 |
| 492 // Must have an updated layout tree for this math to work correctly. |
| 493 targetNode->document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 494 |
| 495 // Adjust offsetLocation to be relative to the target's padding box. |
| 496 if (const LayoutObject* layoutObject = findTargetLayoutObject(targetNode)) { |
| 497 FloatPoint localPos = layoutObject->absoluteToLocal( |
| 498 FloatPoint(absoluteLocation()), UseTransforms); |
| 499 |
| 500 // Adding this here to address crbug.com/570666. Basically we'd like to |
| 501 // find the local coordinates relative to the padding box not the border |
| 502 // box. |
| 503 if (layoutObject->isBoxModelObject()) { |
| 504 const LayoutBoxModelObject* layoutBox = |
| 505 toLayoutBoxModelObject(layoutObject); |
| 506 localPos.move(-layoutBox->borderLeft(), -layoutBox->borderTop()); |
| 507 } |
| 508 |
| 509 m_offsetLocation = DoublePoint(localPos); |
| 510 float scaleFactor = 1 / pageZoomFactor(this); |
| 511 if (scaleFactor != 1.0f) |
| 512 m_offsetLocation.scale(scaleFactor, scaleFactor); |
| 513 } |
| 514 |
| 515 // Adjust layerLocation to be relative to the layer. |
| 516 // FIXME: event.layerX and event.layerY are poorly defined, |
| 517 // and probably don't always correspond to PaintLayer offsets. |
| 518 // https://bugs.webkit.org/show_bug.cgi?id=21868 |
| 519 Node* n = targetNode; |
| 520 while (n && !n->layoutObject()) |
| 521 n = n->parentNode(); |
| 522 |
| 523 if (n) { |
| 524 // FIXME: This logic is a wrong implementation of convertToLayerCoords. |
| 525 for (PaintLayer* layer = n->layoutObject()->enclosingLayer(); layer; |
| 526 layer = layer->parent()) { |
| 527 m_layerLocation -= DoubleSize(layer->location().x().toDouble(), |
| 528 layer->location().y().toDouble()); |
| 529 } |
| 530 } |
| 531 |
| 532 m_hasCachedRelativePosition = true; |
| 533 } |
| 534 |
| 535 int MouseEvent::layerX() { |
| 536 if (!m_hasCachedRelativePosition) |
| 537 computeRelativePosition(); |
| 538 |
| 539 // TODO(mustaq): Remove the PointerEvent specific code when mouse has |
| 540 // fractional coordinates. See crbug.com/655786. |
| 541 return isPointerEvent() ? m_layerLocation.x() |
| 542 : static_cast<int>(m_layerLocation.x()); |
| 543 } |
| 544 |
| 545 int MouseEvent::layerY() { |
| 546 if (!m_hasCachedRelativePosition) |
| 547 computeRelativePosition(); |
| 548 |
| 549 // TODO(mustaq): Remove the PointerEvent specific code when mouse has |
| 550 // fractional coordinates. See crbug.com/655786. |
| 551 return isPointerEvent() ? m_layerLocation.y() |
| 552 : static_cast<int>(m_layerLocation.y()); |
| 553 } |
| 554 |
| 555 int MouseEvent::offsetX() { |
| 556 if (!hasPosition()) |
| 557 return 0; |
| 558 if (!m_hasCachedRelativePosition) |
| 559 computeRelativePosition(); |
| 560 return std::round(m_offsetLocation.x()); |
| 561 } |
| 562 |
| 563 int MouseEvent::offsetY() { |
| 564 if (!hasPosition()) |
| 565 return 0; |
| 566 if (!m_hasCachedRelativePosition) |
| 567 computeRelativePosition(); |
| 568 return std::round(m_offsetLocation.y()); |
| 569 } |
| 570 |
375 } // namespace blink | 571 } // namespace blink |
OLD | NEW |