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
33 namespace WebCore {
34
MouseRelatedEvent()35 MouseRelatedEvent::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 , m_hasCachedRelativePosition(false)
48 {
49 }
50
contentsX(AbstractView * abstractView)51 static int contentsX(AbstractView* abstractView)
52 {
53 if (!abstractView)
54 return 0;
55 Frame* frame = abstractView->frame();
56 if (!frame)
57 return 0;
58 FrameView* frameView = frame->view();
59 if (!frameView)
60 return 0;
61 return frameView->scrollX() / frame->pageZoomFactor();
62 }
63
contentsY(AbstractView * abstractView)64 static int contentsY(AbstractView* abstractView)
65 {
66 if (!abstractView)
67 return 0;
68 Frame* frame = abstractView->frame();
69 if (!frame)
70 return 0;
71 FrameView* frameView = frame->view();
72 if (!frameView)
73 return 0;
74 return frameView->scrollY() / frame->pageZoomFactor();
75 }
76
MouseRelatedEvent(const AtomicString & eventType,bool canBubble,bool cancelable,PassRefPtr<AbstractView> abstractView,int detail,int screenX,int screenY,int windowX,int windowY,bool ctrlKey,bool altKey,bool shiftKey,bool metaKey,bool isSimulated)77 MouseRelatedEvent::MouseRelatedEvent(const AtomicString& eventType, bool canBubble, bool cancelable, PassRefPtr<AbstractView> abstractView,
78 int detail, int screenX, int screenY, int windowX, int windowY,
79 bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool isSimulated)
80 : UIEventWithKeyState(eventType, canBubble, cancelable, abstractView, detail, ctrlKey, altKey, shiftKey, metaKey)
81 , m_screenX(screenX)
82 , m_screenY(screenY)
83 , m_clientX(0)
84 , m_clientY(0)
85 , m_pageX(0)
86 , m_pageY(0)
87 , m_isSimulated(isSimulated)
88 {
89 IntPoint adjustedPageLocation;
90 IntPoint scrollPosition;
91
92 Frame* frame = view() ? view()->frame() : 0;
93 if (frame && !isSimulated) {
94 if (FrameView* frameView = frame->view()) {
95 scrollPosition = frameView->scrollPosition();
96 adjustedPageLocation = frameView->windowToContents(IntPoint(windowX, windowY));
97 float pageZoom = frame->pageZoomFactor();
98 if (pageZoom != 1.0f) {
99 // Adjust our pageX and pageY to account for the page zoom.
100 adjustedPageLocation.setX(lroundf(adjustedPageLocation.x() / pageZoom));
101 adjustedPageLocation.setY(lroundf(adjustedPageLocation.y() / pageZoom));
102 scrollPosition.setX(scrollPosition.x() / pageZoom);
103 scrollPosition.setY(scrollPosition.y() / pageZoom);
104 }
105 }
106 }
107
108 IntPoint clientLocation(adjustedPageLocation - scrollPosition);
109 m_clientX = clientLocation.x();
110 m_clientY = clientLocation.y();
111 m_pageX = adjustedPageLocation.x();
112 m_pageY = adjustedPageLocation.y();
113
114 initCoordinates();
115 }
116
initCoordinates()117 void MouseRelatedEvent::initCoordinates()
118 {
119 // Set up initial values for coordinates.
120 // Correct values are computed lazily, see computeRelativePosition.
121 m_layerX = m_pageX;
122 m_layerY = m_pageY;
123 m_offsetX = m_pageX;
124 m_offsetY = m_pageY;
125
126 computePageLocation();
127 m_hasCachedRelativePosition = false;
128 }
129
initCoordinates(int clientX,int clientY)130 void MouseRelatedEvent::initCoordinates(int clientX, int clientY)
131 {
132 // Set up initial values for coordinates.
133 // Correct values are computed lazily, see computeRelativePosition.
134 m_clientX = clientX;
135 m_clientY = clientY;
136 m_pageX = clientX + contentsX(view());
137 m_pageY = clientY + contentsY(view());
138 m_layerX = m_pageX;
139 m_layerY = m_pageY;
140 m_offsetX = m_pageX;
141 m_offsetY = m_pageY;
142
143 computePageLocation();
144 m_hasCachedRelativePosition = false;
145 }
146
pageZoomFactor(const UIEvent * event)147 static float pageZoomFactor(const UIEvent* event)
148 {
149 DOMWindow* window = event->view();
150 if (!window)
151 return 1;
152 Frame* frame = window->frame();
153 if (!frame)
154 return 1;
155 return frame->pageZoomFactor();
156 }
157
computePageLocation()158 void MouseRelatedEvent::computePageLocation()
159 {
160 float zoomFactor = pageZoomFactor(this);
161 setAbsoluteLocation(roundedIntPoint(FloatPoint(pageX() * zoomFactor, pageY() * zoomFactor)));
162 }
163
receivedTarget()164 void MouseRelatedEvent::receivedTarget()
165 {
166 m_hasCachedRelativePosition = false;
167 }
168
computeRelativePosition()169 void MouseRelatedEvent::computeRelativePosition()
170 {
171 Node* targetNode = target() ? target()->toNode() : 0;
172 if (!targetNode)
173 return;
174
175 // Compute coordinates that are based on the target.
176 m_layerX = m_pageX;
177 m_layerY = m_pageY;
178 m_offsetX = m_pageX;
179 m_offsetY = m_pageY;
180
181 // Must have an updated render tree for this math to work correctly.
182 targetNode->document()->updateStyleIfNeeded();
183
184 // Adjust offsetX/Y to be relative to the target's position.
185 if (!isSimulated()) {
186 if (RenderObject* r = targetNode->renderer()) {
187 FloatPoint localPos = r->absoluteToLocal(absoluteLocation(), false, true);
188 float zoomFactor = pageZoomFactor(this);
189 m_offsetX = lroundf(localPos.x() / zoomFactor);
190 m_offsetY = lroundf(localPos.y() / zoomFactor);
191 }
192 }
193
194 // Adjust layerX/Y to be relative to the layer.
195 // FIXME: We're pretty sure this is the wrong definition of "layer."
196 // Our RenderLayer is a more modern concept, and layerX/Y is some
197 // other notion about groups of elements (left over from the Netscape 4 days?);
198 // we should test and fix this.
199 Node* n = targetNode;
200 while (n && !n->renderer())
201 n = n->parentNode();
202
203 RenderLayer* layer;
204 if (n && (layer = n->renderer()->enclosingLayer())) {
205 layer->updateLayerPosition();
206 for (; layer; layer = layer->parent()) {
207 m_layerX -= layer->x();
208 m_layerY -= layer->y();
209 }
210 }
211
212 m_hasCachedRelativePosition = true;
213 }
214
layerX()215 int MouseRelatedEvent::layerX()
216 {
217 if (!m_hasCachedRelativePosition)
218 computeRelativePosition();
219 return m_layerX;
220 }
221
layerY()222 int MouseRelatedEvent::layerY()
223 {
224 if (!m_hasCachedRelativePosition)
225 computeRelativePosition();
226 return m_layerY;
227 }
228
offsetX()229 int MouseRelatedEvent::offsetX()
230 {
231 if (!m_hasCachedRelativePosition)
232 computeRelativePosition();
233 return m_offsetX;
234 }
235
offsetY()236 int MouseRelatedEvent::offsetY()
237 {
238 if (!m_hasCachedRelativePosition)
239 computeRelativePosition();
240 return m_offsetY;
241 }
242
pageX() const243 int MouseRelatedEvent::pageX() const
244 {
245 return m_pageX;
246 }
247
pageY() const248 int MouseRelatedEvent::pageY() const
249 {
250 return m_pageY;
251 }
252
x() const253 int MouseRelatedEvent::x() const
254 {
255 // FIXME: This is not correct.
256 // See Microsoft documentation and <http://www.quirksmode.org/dom/w3c_events.html>.
257 return m_clientX;
258 }
259
y() const260 int MouseRelatedEvent::y() const
261 {
262 // FIXME: This is not correct.
263 // See Microsoft documentation and <http://www.quirksmode.org/dom/w3c_events.html>.
264 return m_clientY;
265 }
266
267 } // namespace WebCore
268