OLD | NEW |
| (Empty) |
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 "core/events/MouseRelatedEvent.h" | |
24 | |
25 #include "core/dom/Document.h" | |
26 #include "core/frame/LocalDOMWindow.h" | |
27 #include "core/frame/FrameView.h" | |
28 #include "core/frame/LocalFrame.h" | |
29 #include "core/layout/LayoutObject.h" | |
30 #include "core/paint/PaintLayer.h" | |
31 #include "core/svg/SVGElement.h" | |
32 | |
33 namespace blink { | |
34 | |
35 MouseRelatedEvent::MouseRelatedEvent() | |
36 : m_positionType(PositionType::Position), | |
37 m_hasCachedRelativePosition(false) {} | |
38 | |
39 static LayoutSize contentsScrollOffset(AbstractView* abstractView) { | |
40 if (!abstractView || !abstractView->isLocalDOMWindow()) | |
41 return LayoutSize(); | |
42 LocalFrame* frame = toLocalDOMWindow(abstractView)->frame(); | |
43 if (!frame) | |
44 return LayoutSize(); | |
45 FrameView* frameView = frame->view(); | |
46 if (!frameView) | |
47 return LayoutSize(); | |
48 float scaleFactor = frame->pageZoomFactor(); | |
49 return LayoutSize(frameView->scrollX() / scaleFactor, | |
50 frameView->scrollY() / scaleFactor); | |
51 } | |
52 | |
53 MouseRelatedEvent::MouseRelatedEvent( | |
54 const AtomicString& eventType, | |
55 bool canBubble, | |
56 bool cancelable, | |
57 AbstractView* abstractView, | |
58 int detail, | |
59 const IntPoint& screenLocation, | |
60 const IntPoint& rootFrameLocation, | |
61 const IntPoint& movementDelta, | |
62 PlatformEvent::Modifiers modifiers, | |
63 TimeTicks platformTimeStamp, | |
64 PositionType positionType, | |
65 InputDeviceCapabilities* sourceCapabilities) | |
66 : UIEventWithKeyState(eventType, | |
67 canBubble, | |
68 cancelable, | |
69 abstractView, | |
70 detail, | |
71 modifiers, | |
72 platformTimeStamp, | |
73 sourceCapabilities), | |
74 m_screenLocation(screenLocation), | |
75 m_movementDelta(movementDelta), | |
76 m_positionType(positionType) { | |
77 DoublePoint adjustedPageLocation; | |
78 DoubleSize scrollOffset; | |
79 | |
80 LocalFrame* frame = view() && view()->isLocalDOMWindow() | |
81 ? toLocalDOMWindow(view())->frame() | |
82 : nullptr; | |
83 if (frame && hasPosition()) { | |
84 if (FrameView* frameView = frame->view()) { | |
85 adjustedPageLocation = frameView->rootFrameToContents(rootFrameLocation); | |
86 scrollOffset = frameView->scrollOffsetInt(); | |
87 float scaleFactor = 1 / frame->pageZoomFactor(); | |
88 if (scaleFactor != 1.0f) { | |
89 adjustedPageLocation.scale(scaleFactor, scaleFactor); | |
90 scrollOffset.scale(scaleFactor, scaleFactor); | |
91 } | |
92 } | |
93 } | |
94 | |
95 m_clientLocation = adjustedPageLocation - scrollOffset; | |
96 m_pageLocation = adjustedPageLocation; | |
97 | |
98 // Set up initial values for coordinates. | |
99 // Correct values are computed lazily, see computeRelativePosition. | |
100 m_layerLocation = m_pageLocation; | |
101 m_offsetLocation = m_pageLocation; | |
102 | |
103 computePageLocation(); | |
104 m_hasCachedRelativePosition = false; | |
105 } | |
106 | |
107 MouseRelatedEvent::MouseRelatedEvent(const AtomicString& eventType, | |
108 const MouseEventInit& initializer) | |
109 : UIEventWithKeyState(eventType, initializer), | |
110 m_screenLocation( | |
111 DoublePoint(initializer.screenX(), initializer.screenY())), | |
112 m_movementDelta( | |
113 IntPoint(initializer.movementX(), initializer.movementY())), | |
114 m_positionType(PositionType::Position) { | |
115 initCoordinates(initializer.clientX(), initializer.clientY()); | |
116 } | |
117 | |
118 void MouseRelatedEvent::initCoordinates(const double clientX, | |
119 const double clientY) { | |
120 // Set up initial values for coordinates. | |
121 // Correct values are computed lazily, see computeRelativePosition. | |
122 m_clientLocation = DoublePoint(clientX, clientY); | |
123 m_pageLocation = m_clientLocation + DoubleSize(contentsScrollOffset(view())); | |
124 | |
125 m_layerLocation = m_pageLocation; | |
126 m_offsetLocation = m_pageLocation; | |
127 | |
128 computePageLocation(); | |
129 m_hasCachedRelativePosition = false; | |
130 } | |
131 | |
132 static float pageZoomFactor(const UIEvent* event) { | |
133 if (!event->view() || !event->view()->isLocalDOMWindow()) | |
134 return 1; | |
135 LocalFrame* frame = toLocalDOMWindow(event->view())->frame(); | |
136 if (!frame) | |
137 return 1; | |
138 return frame->pageZoomFactor(); | |
139 } | |
140 | |
141 void MouseRelatedEvent::computePageLocation() { | |
142 float scaleFactor = pageZoomFactor(this); | |
143 m_absoluteLocation = m_pageLocation.scaledBy(scaleFactor); | |
144 } | |
145 | |
146 void MouseRelatedEvent::receivedTarget() { | |
147 m_hasCachedRelativePosition = false; | |
148 } | |
149 | |
150 static const LayoutObject* findTargetLayoutObject(Node*& targetNode) { | |
151 LayoutObject* layoutObject = targetNode->layoutObject(); | |
152 if (!layoutObject || !layoutObject->isSVG()) | |
153 return layoutObject; | |
154 // If this is an SVG node, compute the offset to the padding box of the | |
155 // outermost SVG root (== the closest ancestor that has a CSS layout box.) | |
156 while (!layoutObject->isSVGRoot()) | |
157 layoutObject = layoutObject->parent(); | |
158 // Update the target node to point to the SVG root. | |
159 targetNode = layoutObject->node(); | |
160 DCHECK(!targetNode || (targetNode->isSVGElement() && | |
161 toSVGElement(*targetNode).isOutermostSVGSVGElement())); | |
162 return layoutObject; | |
163 } | |
164 | |
165 void MouseRelatedEvent::computeRelativePosition() { | |
166 Node* targetNode = target() ? target()->toNode() : nullptr; | |
167 if (!targetNode) | |
168 return; | |
169 | |
170 // Compute coordinates that are based on the target. | |
171 m_layerLocation = m_pageLocation; | |
172 m_offsetLocation = m_pageLocation; | |
173 | |
174 // Must have an updated layout tree for this math to work correctly. | |
175 targetNode->document().updateStyleAndLayoutIgnorePendingStylesheets(); | |
176 | |
177 // Adjust offsetLocation to be relative to the target's padding box. | |
178 if (const LayoutObject* layoutObject = findTargetLayoutObject(targetNode)) { | |
179 FloatPoint localPos = layoutObject->absoluteToLocal( | |
180 FloatPoint(absoluteLocation()), UseTransforms); | |
181 | |
182 // Adding this here to address crbug.com/570666. Basically we'd like to | |
183 // find the local coordinates relative to the padding box not the border | |
184 // box. | |
185 if (layoutObject->isBoxModelObject()) { | |
186 const LayoutBoxModelObject* layoutBox = | |
187 toLayoutBoxModelObject(layoutObject); | |
188 localPos.move(-layoutBox->borderLeft(), -layoutBox->borderTop()); | |
189 } | |
190 | |
191 m_offsetLocation = DoublePoint(localPos); | |
192 float scaleFactor = 1 / pageZoomFactor(this); | |
193 if (scaleFactor != 1.0f) | |
194 m_offsetLocation.scale(scaleFactor, scaleFactor); | |
195 } | |
196 | |
197 // Adjust layerLocation to be relative to the layer. | |
198 // FIXME: event.layerX and event.layerY are poorly defined, | |
199 // and probably don't always correspond to PaintLayer offsets. | |
200 // https://bugs.webkit.org/show_bug.cgi?id=21868 | |
201 Node* n = targetNode; | |
202 while (n && !n->layoutObject()) | |
203 n = n->parentNode(); | |
204 | |
205 if (n) { | |
206 // FIXME: This logic is a wrong implementation of convertToLayerCoords. | |
207 for (PaintLayer* layer = n->layoutObject()->enclosingLayer(); layer; | |
208 layer = layer->parent()) { | |
209 m_layerLocation -= DoubleSize(layer->location().x().toDouble(), | |
210 layer->location().y().toDouble()); | |
211 } | |
212 } | |
213 | |
214 m_hasCachedRelativePosition = true; | |
215 } | |
216 | |
217 int MouseRelatedEvent::layerX() { | |
218 if (!m_hasCachedRelativePosition) | |
219 computeRelativePosition(); | |
220 | |
221 // TODO(mustaq): Remove the PointerEvent specific code when mouse has | |
222 // fractional coordinates. See crbug.com/655786. | |
223 return isPointerEvent() ? m_layerLocation.x() | |
224 : static_cast<int>(m_layerLocation.x()); | |
225 } | |
226 | |
227 int MouseRelatedEvent::layerY() { | |
228 if (!m_hasCachedRelativePosition) | |
229 computeRelativePosition(); | |
230 | |
231 // TODO(mustaq): Remove the PointerEvent specific code when mouse has | |
232 // fractional coordinates. See crbug.com/655786. | |
233 return isPointerEvent() ? m_layerLocation.y() | |
234 : static_cast<int>(m_layerLocation.y()); | |
235 } | |
236 | |
237 int MouseRelatedEvent::offsetX() { | |
238 if (!hasPosition()) | |
239 return 0; | |
240 if (!m_hasCachedRelativePosition) | |
241 computeRelativePosition(); | |
242 return std::round(m_offsetLocation.x()); | |
243 } | |
244 | |
245 int MouseRelatedEvent::offsetY() { | |
246 if (!hasPosition()) | |
247 return 0; | |
248 if (!m_hasCachedRelativePosition) | |
249 computeRelativePosition(); | |
250 return std::round(m_offsetLocation.y()); | |
251 } | |
252 | |
253 DEFINE_TRACE(MouseRelatedEvent) { | |
254 UIEventWithKeyState::trace(visitor); | |
255 } | |
256 | |
257 } // namespace blink | |
OLD | NEW |