Make all ScriptWrappable IsoHeap-ed
[WebKit-https.git] / Source / WebCore / dom / MouseRelatedEvent.cpp
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, 2013 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 "LayoutPoint.h"
31 #include "RenderLayer.h"
32 #include "RenderObject.h"
33 #include <wtf/IsoMallocInlines.h>
34
35 namespace WebCore {
36
37 WTF_MAKE_ISO_ALLOCATED_IMPL(MouseRelatedEvent);
38
39 MouseRelatedEvent::MouseRelatedEvent(const AtomString& eventType, CanBubble canBubble, IsCancelable isCancelable, IsComposed isComposed,
40     MonotonicTime timestamp, RefPtr<WindowProxy>&& view, int detail,
41     const IntPoint& screenLocation, const IntPoint& windowLocation, const IntPoint& movementDelta, OptionSet<Modifier> modifiers, IsSimulated isSimulated, IsTrusted isTrusted)
42     : UIEventWithKeyState(eventType, canBubble, isCancelable, isComposed, timestamp, WTFMove(view), detail, modifiers, isTrusted)
43     , m_screenLocation(screenLocation)
44 #if ENABLE(POINTER_LOCK)
45     , m_movementDelta(movementDelta)
46 #endif
47     , m_isSimulated(isSimulated == IsSimulated::Yes)
48 {
49 #if !ENABLE(POINTER_LOCK)
50     UNUSED_PARAM(movementDelta);
51 #endif
52     init(m_isSimulated, windowLocation);
53 }
54
55 MouseRelatedEvent::MouseRelatedEvent(const AtomString& type, IsCancelable isCancelable, MonotonicTime timestamp, RefPtr<WindowProxy>&& view, const IntPoint& globalLocation, OptionSet<Modifier> modifiers)
56     : MouseRelatedEvent(type, CanBubble::Yes, isCancelable, IsComposed::Yes, timestamp,
57         WTFMove(view), 0, globalLocation, globalLocation /* Converted in init */, { }, modifiers, IsSimulated::No)
58 {
59 }
60
61 MouseRelatedEvent::MouseRelatedEvent(const AtomString& eventType, const MouseRelatedEventInit& initializer, IsTrusted isTrusted)
62     : UIEventWithKeyState(eventType, initializer)
63     , m_screenLocation(IntPoint(initializer.screenX, initializer.screenY))
64 #if ENABLE(POINTER_LOCK)
65     , m_movementDelta(IntPoint(0, 0))
66 #endif
67 {
68     ASSERT_UNUSED(isTrusted, isTrusted == IsTrusted::No);
69     init(false, IntPoint(0, 0));
70 }
71
72 void MouseRelatedEvent::init(bool isSimulated, const IntPoint& windowLocation)
73 {
74     if (!isSimulated) {
75         if (auto* frameView = frameViewFromWindowProxy(view())) {
76             FloatPoint absolutePoint = frameView->windowToContents(windowLocation);
77             FloatPoint documentPoint = frameView->absoluteToDocumentPoint(absolutePoint);
78             m_pageLocation = flooredLayoutPoint(documentPoint);
79             m_clientLocation = pagePointToClientPoint(m_pageLocation, frameView);
80         }
81     }
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 FrameView* MouseRelatedEvent::frameViewFromWindowProxy(WindowProxy* windowProxy)
98 {
99     if (!windowProxy || !is<DOMWindow>(windowProxy->window()))
100         return nullptr;
101
102     auto* frame = downcast<DOMWindow>(*windowProxy->window()).frame();
103     return frame ? frame->view() : nullptr;
104 }
105
106 LayoutPoint MouseRelatedEvent::pagePointToClientPoint(LayoutPoint pagePoint, FrameView* frameView)
107 {
108     if (!frameView)
109         return pagePoint;
110
111     return flooredLayoutPoint(frameView->documentToClientPoint(pagePoint));
112 }
113
114 LayoutPoint MouseRelatedEvent::pagePointToAbsolutePoint(LayoutPoint pagePoint, FrameView* frameView)
115 {
116     if (!frameView)
117         return pagePoint;
118     
119     return pagePoint.scaled(frameView->documentToAbsoluteScaleFactor());
120 }
121
122 void MouseRelatedEvent::initCoordinates(const LayoutPoint& clientLocation)
123 {
124     // Set up initial values for coordinates.
125     // Correct values are computed lazily, see computeRelativePosition.
126     FloatSize documentToClientOffset;
127     if (auto* frameView = frameViewFromWindowProxy(view()))
128         documentToClientOffset = frameView->documentToClientOffset();
129
130     m_clientLocation = clientLocation;
131     m_pageLocation = clientLocation - LayoutSize(documentToClientOffset);
132
133     m_layerLocation = m_pageLocation;
134     m_offsetLocation = m_pageLocation;
135
136     computePageLocation();
137     m_hasCachedRelativePosition = false;
138 }
139
140 float MouseRelatedEvent::documentToAbsoluteScaleFactor() const
141 {
142     if (auto* frameView = frameViewFromWindowProxy(view()))
143         return frameView->documentToAbsoluteScaleFactor();
144
145     return 1;
146 }
147
148 void MouseRelatedEvent::computePageLocation()
149 {
150     m_absoluteLocation = pagePointToAbsolutePoint(m_pageLocation, frameViewFromWindowProxy(view()));
151 }
152
153 void MouseRelatedEvent::receivedTarget()
154 {
155     m_hasCachedRelativePosition = false;
156 }
157
158 void MouseRelatedEvent::computeRelativePosition()
159 {
160     if (!is<Node>(target()))
161         return;
162     auto& targetNode = downcast<Node>(*target());
163
164     // Compute coordinates that are based on the target.
165     m_layerLocation = m_pageLocation;
166     m_offsetLocation = m_pageLocation;
167
168     // Must have an updated render tree for this math to work correctly.
169     targetNode.document().updateLayoutIgnorePendingStylesheets();
170
171     // Adjust offsetLocation to be relative to the target's position.
172     if (RenderObject* r = targetNode.renderer()) {
173         m_offsetLocation = LayoutPoint(r->absoluteToLocal(absoluteLocation(), UseTransforms));
174         float scaleFactor = 1 / documentToAbsoluteScaleFactor();
175         if (scaleFactor != 1.0f)
176             m_offsetLocation.scale(scaleFactor);
177     }
178
179     // Adjust layerLocation to be relative to the layer.
180     // FIXME: event.layerX and event.layerY are poorly defined,
181     // and probably don't always correspond to RenderLayer offsets.
182     // https://bugs.webkit.org/show_bug.cgi?id=21868
183     Node* n = &targetNode;
184     while (n && !n->renderer())
185         n = n->parentNode();
186
187     RenderLayer* layer;
188     if (n && (layer = n->renderer()->enclosingLayer())) {
189         for (; layer; layer = layer->parent()) {
190             m_layerLocation -= toLayoutSize(layer->location());
191         }
192     }
193
194     m_hasCachedRelativePosition = true;
195 }
196     
197 FloatPoint MouseRelatedEvent::locationInRootViewCoordinates() const
198 {
199     if (auto* frameView = frameViewFromWindowProxy(view()))
200         return frameView->contentsToRootView(roundedIntPoint(m_absoluteLocation));
201
202     return m_absoluteLocation;
203 }
204
205 int MouseRelatedEvent::layerX()
206 {
207     if (!m_hasCachedRelativePosition)
208         computeRelativePosition();
209     return m_layerLocation.x();
210 }
211
212 int MouseRelatedEvent::layerY()
213 {
214     if (!m_hasCachedRelativePosition)
215         computeRelativePosition();
216     return m_layerLocation.y();
217 }
218
219 int MouseRelatedEvent::offsetX()
220 {
221     if (isSimulated())
222         return 0;
223     if (!m_hasCachedRelativePosition)
224         computeRelativePosition();
225     return roundToInt(m_offsetLocation.x());
226 }
227
228 int MouseRelatedEvent::offsetY()
229 {
230     if (isSimulated())
231         return 0;
232     if (!m_hasCachedRelativePosition)
233         computeRelativePosition();
234     return roundToInt(m_offsetLocation.y());
235 }
236
237 int MouseRelatedEvent::pageX() const
238 {
239     return m_pageLocation.x();
240 }
241
242 int MouseRelatedEvent::pageY() const
243 {
244     return m_pageLocation.y();
245 }
246
247 const LayoutPoint& MouseRelatedEvent::pageLocation() const
248 {
249     return m_pageLocation;
250 }
251
252 int MouseRelatedEvent::x() const
253 {
254     // FIXME: This is not correct.
255     // See Microsoft documentation and <http://www.quirksmode.org/dom/w3c_events.html>.
256     return m_clientLocation.x();
257 }
258
259 int MouseRelatedEvent::y() const
260 {
261     // FIXME: This is not correct.
262     // See Microsoft documentation and <http://www.quirksmode.org/dom/w3c_events.html>.
263     return m_clientLocation.y();
264 }
265
266 } // namespace WebCore