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 "MouseRelatedEvent.h" 25 26#include "DOMWindow.h" 27#include "Document.h" 28#include "Frame.h" 29#include "FrameView.h" 30#include "RenderLayer.h" 31#include "RenderObject.h" 32 33namespace WebCore { 34 35MouseRelatedEvent::MouseRelatedEvent() 36 : m_screenX(0) 37 , m_screenY(0) 38 , m_clientX(0) 39 , m_clientY(0) 40 , m_pageX(0) 41 , m_pageY(0) 42 , m_layerX(0) 43 , m_layerY(0) 44 , m_offsetX(0) 45 , m_offsetY(0) 46 , m_isSimulated(false) 47{ 48} 49 50static int contentsX(AbstractView* abstractView) 51{ 52 if (!abstractView) 53 return 0; 54 Frame* frame = abstractView->frame(); 55 if (!frame) 56 return 0; 57 FrameView* frameView = frame->view(); 58 if (!frameView) 59 return 0; 60 return frameView->scrollX() / frame->pageZoomFactor(); 61} 62 63static int contentsY(AbstractView* abstractView) 64{ 65 if (!abstractView) 66 return 0; 67 Frame* frame = abstractView->frame(); 68 if (!frame) 69 return 0; 70 FrameView* frameView = frame->view(); 71 if (!frameView) 72 return 0; 73 return frameView->scrollY() / frame->pageZoomFactor(); 74} 75 76MouseRelatedEvent::MouseRelatedEvent(const AtomicString& eventType, bool canBubble, bool cancelable, PassRefPtr<AbstractView> viewArg, 77 int detail, int screenX, int screenY, int pageX, int pageY, 78 bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool isSimulated) 79 : UIEventWithKeyState(eventType, canBubble, cancelable, viewArg, detail, ctrlKey, altKey, shiftKey, metaKey) 80 , m_screenX(screenX) 81 , m_screenY(screenY) 82 , m_clientX(pageX - contentsX(view())) 83 , m_clientY(pageY - contentsY(view())) 84 , m_pageX(pageX) 85 , m_pageY(pageY) 86 , m_isSimulated(isSimulated) 87{ 88 initCoordinates(); 89} 90 91void MouseRelatedEvent::initCoordinates() 92{ 93 // Set up initial values for coordinates. 94 // Correct values can't be computed until we have at target, so receivedTarget 95 // does the "real" computation. 96 m_layerX = m_pageX; 97 m_layerY = m_pageY; 98 m_offsetX = m_pageX; 99 m_offsetY = m_pageY; 100 101 computePageLocation(); 102} 103 104void MouseRelatedEvent::initCoordinates(int clientX, int clientY) 105{ 106 // Set up initial values for coordinates. 107 // Correct values can't be computed until we have at target, so receivedTarget 108 // does the "real" computation. 109 m_clientX = clientX; 110 m_clientY = clientY; 111 m_pageX = clientX + contentsX(view()); 112 m_pageY = clientY + contentsY(view()); 113 m_layerX = m_pageX; 114 m_layerY = m_pageY; 115 m_offsetX = m_pageX; 116 m_offsetY = m_pageY; 117 118 computePageLocation(); 119} 120 121void MouseRelatedEvent::computePageLocation() 122{ 123 float zoomFactor = (view() && view()->frame()) ? view()->frame()->pageZoomFactor() : 1.0f; 124 setAbsoluteLocation(roundedIntPoint(FloatPoint(pageX() * zoomFactor, pageY() * zoomFactor))); 125} 126 127void MouseRelatedEvent::receivedTarget() 128{ 129 ASSERT(target()); 130 Node* targ = target()->toNode(); 131 if (!targ) 132 return; 133 134 // Compute coordinates that are based on the target. 135 m_layerX = m_pageX; 136 m_layerY = m_pageY; 137 m_offsetX = m_pageX; 138 m_offsetY = m_pageY; 139 140 // Must have an updated render tree for this math to work correctly. 141 targ->document()->updateStyleIfNeeded(); 142 143 // Adjust offsetX/Y to be relative to the target's position. 144 if (!isSimulated()) { 145 if (RenderObject* r = targ->renderer()) { 146 FloatPoint localPos = r->absoluteToLocal(absoluteLocation(), false, true); 147 float zoomFactor = (view() && view()->frame()) ? view()->frame()->pageZoomFactor() : 1.0f; 148 m_offsetX = lroundf(localPos.x() / zoomFactor); 149 m_offsetY = lroundf(localPos.y() / zoomFactor); 150 } 151 } 152 153 // Adjust layerX/Y to be relative to the layer. 154 // FIXME: We're pretty sure this is the wrong definition of "layer." 155 // Our RenderLayer is a more modern concept, and layerX/Y is some 156 // other notion about groups of elements (left over from the Netscape 4 days?); 157 // we should test and fix this. 158 Node* n = targ; 159 while (n && !n->renderer()) 160 n = n->parent(); 161 if (n) { 162 RenderLayer* layer = n->renderer()->enclosingLayer(); 163 layer->updateLayerPosition(); 164 for (; layer; layer = layer->parent()) { 165 m_layerX -= layer->x(); 166 m_layerY -= layer->y(); 167 } 168 } 169} 170 171int MouseRelatedEvent::pageX() const 172{ 173 return m_pageX; 174} 175 176int MouseRelatedEvent::pageY() const 177{ 178 return m_pageY; 179} 180 181int MouseRelatedEvent::x() const 182{ 183 // FIXME: This is not correct. 184 // See Microsoft documentation and <http://www.quirksmode.org/dom/w3c_events.html>. 185 return m_clientX; 186} 187 188int MouseRelatedEvent::y() const 189{ 190 // FIXME: This is not correct. 191 // See Microsoft documentation and <http://www.quirksmode.org/dom/w3c_events.html>. 192 return m_clientY; 193} 194 195} // namespace WebCore 196