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 WebCore { 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 for (RenderLayer* layer = n->renderer()->enclosingLayer(); layer; layer = layer->parent()) 165 m_layerLocation -= toLayoutSize(layer->location()); 166 } 167 168 m_hasCachedRelativePosition = true; 169 } 170 171 int MouseRelatedEvent::layerX() 172 { 173 if (!m_hasCachedRelativePosition) 174 computeRelativePosition(); 175 return m_layerLocation.x(); 176 } 177 178 int MouseRelatedEvent::layerY() 179 { 180 if (!m_hasCachedRelativePosition) 181 computeRelativePosition(); 182 return m_layerLocation.y(); 183 } 184 185 int MouseRelatedEvent::offsetX() 186 { 187 if (isSimulated()) 188 return 0; 189 if (!m_hasCachedRelativePosition) 190 computeRelativePosition(); 191 return roundToInt(m_offsetLocation.x()); 192 } 193 194 int MouseRelatedEvent::offsetY() 195 { 196 if (isSimulated()) 197 return 0; 198 if (!m_hasCachedRelativePosition) 199 computeRelativePosition(); 200 return roundToInt(m_offsetLocation.y()); 201 } 202 203 int MouseRelatedEvent::pageX() const 204 { 205 return m_pageLocation.x(); 206 } 207 208 int MouseRelatedEvent::pageY() const 209 { 210 return m_pageLocation.y(); 211 } 212 213 int MouseRelatedEvent::x() const 214 { 215 // FIXME: This is not correct. 216 // See Microsoft documentation and <http://www.quirksmode.org/dom/w3c_events.html>. 217 return m_clientLocation.x(); 218 } 219 220 int MouseRelatedEvent::y() const 221 { 222 // FIXME: This is not correct. 223 // See Microsoft documentation and <http://www.quirksmode.org/dom/w3c_events.html>. 224 return m_clientLocation.y(); 225 } 226 227 void MouseRelatedEvent::trace(Visitor* visitor) 228 { 229 UIEventWithKeyState::trace(visitor); 230 } 231 232 } // namespace WebCore 233