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