1 /* 2 * Copyright (C) 2001 Peter Kelly (pmk (at) post.com) 3 * Copyright (C) 2001 Tobias Anton (anton (at) stud.fbi.fh-darmstadt.de) 4 * Copyright (C) 2006 Samuel Weinig (sam.weinig (at) 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 33 namespace blink { 34 35 MouseRelatedEvent::MouseRelatedEvent() 36 : m_isSimulated(false) 37 , m_hasCachedRelativePosition(false) 38 { 39 } 40 41 static 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 55 MouseRelatedEvent::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 86 void 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 97 void 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 111 static 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 122 void MouseRelatedEvent::computePageLocation() 123 { 124 float scaleFactor = pageZoomFactor(this); 125 setAbsoluteLocation(roundedLayoutPoint(FloatPoint(pageX() * scaleFactor, pageY() * scaleFactor))); 126 } 127 128 void MouseRelatedEvent::receivedTarget() 129 { 130 m_hasCachedRelativePosition = false; 131 } 132 133 void 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 172 int MouseRelatedEvent::layerX() 173 { 174 if (!m_hasCachedRelativePosition) 175 computeRelativePosition(); 176 return m_layerLocation.x(); 177 } 178 179 int MouseRelatedEvent::layerY() 180 { 181 if (!m_hasCachedRelativePosition) 182 computeRelativePosition(); 183 return m_layerLocation.y(); 184 } 185 186 int MouseRelatedEvent::offsetX() 187 { 188 if (isSimulated()) 189 return 0; 190 if (!m_hasCachedRelativePosition) 191 computeRelativePosition(); 192 return roundToInt(m_offsetLocation.x()); 193 } 194 195 int MouseRelatedEvent::offsetY() 196 { 197 if (isSimulated()) 198 return 0; 199 if (!m_hasCachedRelativePosition) 200 computeRelativePosition(); 201 return roundToInt(m_offsetLocation.y()); 202 } 203 204 int MouseRelatedEvent::pageX() const 205 { 206 return m_pageLocation.x(); 207 } 208 209 int MouseRelatedEvent::pageY() const 210 { 211 return m_pageLocation.y(); 212 } 213 214 int 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 221 int 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 228 void MouseRelatedEvent::trace(Visitor* visitor) 229 { 230 UIEventWithKeyState::trace(visitor); 231 } 232 233 } // namespace blink 234