1/* 2 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 3 * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de) 4 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) 5 * Copyright (C) 2003, 2005, 2006, 2008 Apple Inc. All rights reserved. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Library General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Library General Public License for more details. 16 * 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 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA. 21 */ 22 23#include "config.h" 24#include "core/events/MouseRelatedEvent.h" 25 26#include "core/dom/Document.h" 27#include "core/frame/LocalDOMWindow.h" 28#include "core/frame/FrameView.h" 29#include "core/frame/LocalFrame.h" 30#include "core/rendering/RenderLayer.h" 31#include "core/rendering/RenderObject.h" 32 33namespace blink { 34 35MouseRelatedEvent::MouseRelatedEvent() 36 : m_isSimulated(false) 37 , m_hasCachedRelativePosition(false) 38{ 39} 40 41static LayoutSize contentsScrollOffset(AbstractView* abstractView) 42{ 43 if (!abstractView) 44 return LayoutSize(); 45 LocalFrame* frame = 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, frameView->scrollY() / scaleFactor); 53} 54 55MouseRelatedEvent::MouseRelatedEvent(const AtomicString& eventType, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<AbstractView> abstractView, 56 int detail, const IntPoint& screenLocation, const IntPoint& windowLocation, 57 const IntPoint& movementDelta, 58 bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool isSimulated) 59 : UIEventWithKeyState(eventType, canBubble, cancelable, abstractView, detail, ctrlKey, altKey, shiftKey, metaKey) 60 , m_screenLocation(screenLocation) 61 , m_movementDelta(movementDelta) 62 , m_isSimulated(isSimulated) 63{ 64 LayoutPoint adjustedPageLocation; 65 LayoutPoint scrollPosition; 66 67 LocalFrame* frame = view() ? view()->frame() : 0; 68 if (frame && !isSimulated) { 69 if (FrameView* frameView = frame->view()) { 70 scrollPosition = frameView->scrollPosition(); 71 adjustedPageLocation = frameView->windowToContents(windowLocation); 72 float scaleFactor = 1 / frame->pageZoomFactor(); 73 if (scaleFactor != 1.0f) { 74 adjustedPageLocation.scale(scaleFactor, scaleFactor); 75 scrollPosition.scale(scaleFactor, scaleFactor); 76 } 77 } 78 } 79 80 m_clientLocation = adjustedPageLocation - toLayoutSize(scrollPosition); 81 m_pageLocation = adjustedPageLocation; 82 83 initCoordinates(); 84} 85 86void MouseRelatedEvent::initCoordinates() 87{ 88 // Set up initial values for coordinates. 89 // Correct values are computed lazily, see computeRelativePosition. 90 m_layerLocation = m_pageLocation; 91 m_offsetLocation = m_pageLocation; 92 93 computePageLocation(); 94 m_hasCachedRelativePosition = false; 95} 96 97void MouseRelatedEvent::initCoordinates(const LayoutPoint& clientLocation) 98{ 99 // Set up initial values for coordinates. 100 // Correct values are computed lazily, see computeRelativePosition. 101 m_clientLocation = clientLocation; 102 m_pageLocation = clientLocation + contentsScrollOffset(view()); 103 104 m_layerLocation = m_pageLocation; 105 m_offsetLocation = m_pageLocation; 106 107 computePageLocation(); 108 m_hasCachedRelativePosition = false; 109} 110 111static float pageZoomFactor(const UIEvent* event) 112{ 113 LocalDOMWindow* window = event->view(); 114 if (!window) 115 return 1; 116 LocalFrame* frame = window->frame(); 117 if (!frame) 118 return 1; 119 return frame->pageZoomFactor(); 120} 121 122void MouseRelatedEvent::computePageLocation() 123{ 124 float scaleFactor = pageZoomFactor(this); 125 setAbsoluteLocation(roundedLayoutPoint(FloatPoint(pageX() * scaleFactor, pageY() * scaleFactor))); 126} 127 128void MouseRelatedEvent::receivedTarget() 129{ 130 m_hasCachedRelativePosition = false; 131} 132 133void MouseRelatedEvent::computeRelativePosition() 134{ 135 Node* targetNode = target() ? target()->toNode() : 0; 136 if (!targetNode) 137 return; 138 139 // Compute coordinates that are based on the target. 140 m_layerLocation = m_pageLocation; 141 m_offsetLocation = m_pageLocation; 142 143 // Must have an updated render tree for this math to work correctly. 144 targetNode->document().updateLayoutIgnorePendingStylesheets(); 145 146 // Adjust offsetLocation to be relative to the target's position. 147 if (RenderObject* r = targetNode->renderer()) { 148 FloatPoint localPos = r->absoluteToLocal(absoluteLocation(), UseTransforms); 149 m_offsetLocation = roundedLayoutPoint(localPos); 150 float scaleFactor = 1 / pageZoomFactor(this); 151 if (scaleFactor != 1.0f) 152 m_offsetLocation.scale(scaleFactor, scaleFactor); 153 } 154 155 // Adjust layerLocation to be relative to the layer. 156 // FIXME: event.layerX and event.layerY are poorly defined, 157 // and probably don't always correspond to RenderLayer offsets. 158 // https://bugs.webkit.org/show_bug.cgi?id=21868 159 Node* n = targetNode; 160 while (n && !n->renderer()) 161 n = n->parentNode(); 162 163 if (n) { 164 // FIXME: This logic is a wrong implementation of convertToLayerCoords. 165 for (RenderLayer* layer = n->renderer()->enclosingLayer(); layer; layer = layer->parent()) 166 m_layerLocation -= toLayoutSize(layer->location()); 167 } 168 169 m_hasCachedRelativePosition = true; 170} 171 172int MouseRelatedEvent::layerX() 173{ 174 if (!m_hasCachedRelativePosition) 175 computeRelativePosition(); 176 return m_layerLocation.x(); 177} 178 179int MouseRelatedEvent::layerY() 180{ 181 if (!m_hasCachedRelativePosition) 182 computeRelativePosition(); 183 return m_layerLocation.y(); 184} 185 186int MouseRelatedEvent::offsetX() 187{ 188 if (isSimulated()) 189 return 0; 190 if (!m_hasCachedRelativePosition) 191 computeRelativePosition(); 192 return roundToInt(m_offsetLocation.x()); 193} 194 195int MouseRelatedEvent::offsetY() 196{ 197 if (isSimulated()) 198 return 0; 199 if (!m_hasCachedRelativePosition) 200 computeRelativePosition(); 201 return roundToInt(m_offsetLocation.y()); 202} 203 204int MouseRelatedEvent::pageX() const 205{ 206 return m_pageLocation.x(); 207} 208 209int MouseRelatedEvent::pageY() const 210{ 211 return m_pageLocation.y(); 212} 213 214int MouseRelatedEvent::x() const 215{ 216 // FIXME: This is not correct. 217 // See Microsoft documentation and <http://www.quirksmode.org/dom/w3c_events.html>. 218 return m_clientLocation.x(); 219} 220 221int MouseRelatedEvent::y() const 222{ 223 // FIXME: This is not correct. 224 // See Microsoft documentation and <http://www.quirksmode.org/dom/w3c_events.html>. 225 return m_clientLocation.y(); 226} 227 228void MouseRelatedEvent::trace(Visitor* visitor) 229{ 230 UIEventWithKeyState::trace(visitor); 231} 232 233} // namespace blink 234