| Index: third_party/WebKit/Source/core/events/MouseEvent.cpp
|
| diff --git a/third_party/WebKit/Source/core/events/MouseEvent.cpp b/third_party/WebKit/Source/core/events/MouseEvent.cpp
|
| index 802e42bef4ef165cf6e460f575508ca919d28896..6d6f1cf54b48f08ee03e6a209cc1a3c249ec5df0 100644
|
| --- a/third_party/WebKit/Source/core/events/MouseEvent.cpp
|
| +++ b/third_party/WebKit/Source/core/events/MouseEvent.cpp
|
| @@ -26,11 +26,59 @@
|
| #include "bindings/core/v8/ScriptState.h"
|
| #include "core/dom/Element.h"
|
| #include "core/events/EventDispatcher.h"
|
| +#include "core/frame/FrameView.h"
|
| +#include "core/frame/LocalDOMWindow.h"
|
| +#include "core/frame/LocalFrame.h"
|
| +#include "core/layout/LayoutObject.h"
|
| +#include "core/paint/PaintLayer.h"
|
| +#include "core/svg/SVGElement.h"
|
| #include "platform/PlatformMouseEvent.h"
|
| #include "public/platform/WebPointerProperties.h"
|
|
|
| namespace blink {
|
|
|
| +namespace {
|
| +
|
| +LayoutSize contentsScrollOffset(AbstractView* abstractView) {
|
| + if (!abstractView || !abstractView->isLocalDOMWindow())
|
| + return LayoutSize();
|
| + LocalFrame* frame = toLocalDOMWindow(abstractView)->frame();
|
| + if (!frame)
|
| + return LayoutSize();
|
| + FrameView* frameView = frame->view();
|
| + if (!frameView)
|
| + return LayoutSize();
|
| + float scaleFactor = frame->pageZoomFactor();
|
| + return LayoutSize(frameView->scrollX() / scaleFactor,
|
| + frameView->scrollY() / scaleFactor);
|
| +}
|
| +
|
| +float pageZoomFactor(const UIEvent* event) {
|
| + if (!event->view() || !event->view()->isLocalDOMWindow())
|
| + return 1;
|
| + LocalFrame* frame = toLocalDOMWindow(event->view())->frame();
|
| + if (!frame)
|
| + return 1;
|
| + return frame->pageZoomFactor();
|
| +}
|
| +
|
| +const LayoutObject* findTargetLayoutObject(Node*& targetNode) {
|
| + LayoutObject* layoutObject = targetNode->layoutObject();
|
| + if (!layoutObject || !layoutObject->isSVG())
|
| + return layoutObject;
|
| + // If this is an SVG node, compute the offset to the padding box of the
|
| + // outermost SVG root (== the closest ancestor that has a CSS layout box.)
|
| + while (!layoutObject->isSVGRoot())
|
| + layoutObject = layoutObject->parent();
|
| + // Update the target node to point to the SVG root.
|
| + targetNode = layoutObject->node();
|
| + DCHECK(!targetNode || (targetNode->isSVGElement() &&
|
| + toSVGElement(*targetNode).isOutermostSVGSVGElement()));
|
| + return layoutObject;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| MouseEvent* MouseEvent::create(ScriptState* scriptState,
|
| const AtomicString& type,
|
| const MouseEventInit& initializer) {
|
| @@ -126,7 +174,9 @@ MouseEvent* MouseEvent::create(const AtomicString& eventType,
|
| }
|
|
|
| MouseEvent::MouseEvent()
|
| - : m_button(0),
|
| + : m_positionType(PositionType::Position),
|
| + m_hasCachedRelativePosition(false),
|
| + m_button(0),
|
| m_buttons(0),
|
| m_relatedTarget(nullptr),
|
| m_syntheticEventType(PlatformMouseEvent::RealOrIndistinguishable) {}
|
| @@ -135,7 +185,7 @@ MouseEvent::MouseEvent(
|
| const AtomicString& eventType,
|
| bool canBubble,
|
| bool cancelable,
|
| - AbstractView* view,
|
| + AbstractView* abstractView,
|
| int detail,
|
| int screenX,
|
| int screenY,
|
| @@ -151,24 +201,23 @@ MouseEvent::MouseEvent(
|
| PlatformMouseEvent::SyntheticEventType syntheticEventType,
|
| const String& region,
|
| const PlatformMouseEvent* mouseEvent)
|
| - : MouseRelatedEvent(
|
| + : UIEventWithKeyState(
|
| eventType,
|
| canBubble,
|
| cancelable,
|
| - view,
|
| + abstractView,
|
| detail,
|
| - IntPoint(screenX, screenY),
|
| - IntPoint(windowX, windowY),
|
| - IntPoint(movementX, movementY),
|
| modifiers,
|
| platformTimeStamp,
|
| - syntheticEventType == PlatformMouseEvent::Positionless
|
| - ? PositionType::Positionless
|
| - : PositionType::Position,
|
| syntheticEventType == PlatformMouseEvent::FromTouch
|
| ? InputDeviceCapabilities::firesTouchEventsSourceCapabilities()
|
| : InputDeviceCapabilities::
|
| doesntFireTouchEventsSourceCapabilities()),
|
| + m_screenLocation(screenX, screenY),
|
| + m_movementDelta(movementX, movementY),
|
| + m_positionType(syntheticEventType == PlatformMouseEvent::Positionless
|
| + ? PositionType::Positionless
|
| + : PositionType::Position),
|
| m_button(button),
|
| m_buttons(buttons),
|
| m_relatedTarget(relatedTarget),
|
| @@ -176,16 +225,66 @@ MouseEvent::MouseEvent(
|
| m_region(region) {
|
| if (mouseEvent)
|
| m_mouseEvent.reset(new PlatformMouseEvent(*mouseEvent));
|
| +
|
| + DoublePoint adjustedPageLocation;
|
| + DoubleSize scrollOffset;
|
| +
|
| + LocalFrame* frame = view() && view()->isLocalDOMWindow()
|
| + ? toLocalDOMWindow(view())->frame()
|
| + : nullptr;
|
| + if (frame && hasPosition()) {
|
| + if (FrameView* frameView = frame->view()) {
|
| + adjustedPageLocation =
|
| + frameView->rootFrameToContents(IntPoint(windowX, windowY));
|
| + scrollOffset = frameView->scrollOffsetInt();
|
| + float scaleFactor = 1 / frame->pageZoomFactor();
|
| + if (scaleFactor != 1.0f) {
|
| + adjustedPageLocation.scale(scaleFactor, scaleFactor);
|
| + scrollOffset.scale(scaleFactor, scaleFactor);
|
| + }
|
| + }
|
| + }
|
| +
|
| + m_clientLocation = adjustedPageLocation - scrollOffset;
|
| + m_pageLocation = adjustedPageLocation;
|
| +
|
| + // Set up initial values for coordinates.
|
| + // Correct values are computed lazily, see computeRelativePosition.
|
| + m_layerLocation = m_pageLocation;
|
| + m_offsetLocation = m_pageLocation;
|
| +
|
| + computePageLocation();
|
| + m_hasCachedRelativePosition = false;
|
| }
|
|
|
| MouseEvent::MouseEvent(const AtomicString& eventType,
|
| const MouseEventInit& initializer)
|
| - : MouseRelatedEvent(eventType, initializer),
|
| + : UIEventWithKeyState(eventType, initializer),
|
| + m_screenLocation(
|
| + DoublePoint(initializer.screenX(), initializer.screenY())),
|
| + m_movementDelta(
|
| + IntPoint(initializer.movementX(), initializer.movementY())),
|
| + m_positionType(PositionType::Position),
|
| m_button(initializer.button()),
|
| m_buttons(initializer.buttons()),
|
| m_relatedTarget(initializer.relatedTarget()),
|
| m_syntheticEventType(PlatformMouseEvent::RealOrIndistinguishable),
|
| - m_region(initializer.region()) {}
|
| + m_region(initializer.region()) {
|
| + initCoordinates(initializer.clientX(), initializer.clientY());
|
| +}
|
| +
|
| +void MouseEvent::initCoordinates(const double clientX, const double clientY) {
|
| + // Set up initial values for coordinates.
|
| + // Correct values are computed lazily, see computeRelativePosition.
|
| + m_clientLocation = DoublePoint(clientX, clientY);
|
| + m_pageLocation = m_clientLocation + DoubleSize(contentsScrollOffset(view()));
|
| +
|
| + m_layerLocation = m_pageLocation;
|
| + m_offsetLocation = m_pageLocation;
|
| +
|
| + computePageLocation();
|
| + m_hasCachedRelativePosition = false;
|
| +}
|
|
|
| MouseEvent::~MouseEvent() {}
|
|
|
| @@ -302,7 +401,7 @@ Node* MouseEvent::fromElement() const {
|
|
|
| DEFINE_TRACE(MouseEvent) {
|
| visitor->trace(m_relatedTarget);
|
| - MouseRelatedEvent::trace(visitor);
|
| + UIEventWithKeyState::trace(visitor);
|
| }
|
|
|
| EventDispatchMediator* MouseEvent::createMediator() {
|
| @@ -372,4 +471,101 @@ DispatchEventResult MouseEventDispatchMediator::dispatchEvent(
|
| return dispatchResult;
|
| }
|
|
|
| +void MouseEvent::computePageLocation() {
|
| + float scaleFactor = pageZoomFactor(this);
|
| + m_absoluteLocation = m_pageLocation.scaledBy(scaleFactor);
|
| +}
|
| +
|
| +void MouseEvent::receivedTarget() {
|
| + m_hasCachedRelativePosition = false;
|
| +}
|
| +
|
| +void MouseEvent::computeRelativePosition() {
|
| + Node* targetNode = target() ? target()->toNode() : nullptr;
|
| + if (!targetNode)
|
| + return;
|
| +
|
| + // Compute coordinates that are based on the target.
|
| + m_layerLocation = m_pageLocation;
|
| + m_offsetLocation = m_pageLocation;
|
| +
|
| + // Must have an updated layout tree for this math to work correctly.
|
| + targetNode->document().updateStyleAndLayoutIgnorePendingStylesheets();
|
| +
|
| + // Adjust offsetLocation to be relative to the target's padding box.
|
| + if (const LayoutObject* layoutObject = findTargetLayoutObject(targetNode)) {
|
| + FloatPoint localPos = layoutObject->absoluteToLocal(
|
| + FloatPoint(absoluteLocation()), UseTransforms);
|
| +
|
| + // Adding this here to address crbug.com/570666. Basically we'd like to
|
| + // find the local coordinates relative to the padding box not the border
|
| + // box.
|
| + if (layoutObject->isBoxModelObject()) {
|
| + const LayoutBoxModelObject* layoutBox =
|
| + toLayoutBoxModelObject(layoutObject);
|
| + localPos.move(-layoutBox->borderLeft(), -layoutBox->borderTop());
|
| + }
|
| +
|
| + m_offsetLocation = DoublePoint(localPos);
|
| + float scaleFactor = 1 / pageZoomFactor(this);
|
| + if (scaleFactor != 1.0f)
|
| + m_offsetLocation.scale(scaleFactor, scaleFactor);
|
| + }
|
| +
|
| + // Adjust layerLocation to be relative to the layer.
|
| + // FIXME: event.layerX and event.layerY are poorly defined,
|
| + // and probably don't always correspond to PaintLayer offsets.
|
| + // https://bugs.webkit.org/show_bug.cgi?id=21868
|
| + Node* n = targetNode;
|
| + while (n && !n->layoutObject())
|
| + n = n->parentNode();
|
| +
|
| + if (n) {
|
| + // FIXME: This logic is a wrong implementation of convertToLayerCoords.
|
| + for (PaintLayer* layer = n->layoutObject()->enclosingLayer(); layer;
|
| + layer = layer->parent()) {
|
| + m_layerLocation -= DoubleSize(layer->location().x().toDouble(),
|
| + layer->location().y().toDouble());
|
| + }
|
| + }
|
| +
|
| + m_hasCachedRelativePosition = true;
|
| +}
|
| +
|
| +int MouseEvent::layerX() {
|
| + if (!m_hasCachedRelativePosition)
|
| + computeRelativePosition();
|
| +
|
| + // TODO(mustaq): Remove the PointerEvent specific code when mouse has
|
| + // fractional coordinates. See crbug.com/655786.
|
| + return isPointerEvent() ? m_layerLocation.x()
|
| + : static_cast<int>(m_layerLocation.x());
|
| +}
|
| +
|
| +int MouseEvent::layerY() {
|
| + if (!m_hasCachedRelativePosition)
|
| + computeRelativePosition();
|
| +
|
| + // TODO(mustaq): Remove the PointerEvent specific code when mouse has
|
| + // fractional coordinates. See crbug.com/655786.
|
| + return isPointerEvent() ? m_layerLocation.y()
|
| + : static_cast<int>(m_layerLocation.y());
|
| +}
|
| +
|
| +int MouseEvent::offsetX() {
|
| + if (!hasPosition())
|
| + return 0;
|
| + if (!m_hasCachedRelativePosition)
|
| + computeRelativePosition();
|
| + return std::round(m_offsetLocation.x());
|
| +}
|
| +
|
| +int MouseEvent::offsetY() {
|
| + if (!hasPosition())
|
| + return 0;
|
| + if (!m_hasCachedRelativePosition)
|
| + computeRelativePosition();
|
| + return std::round(m_offsetLocation.y());
|
| +}
|
| +
|
| } // namespace blink
|
|
|