OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/events/PointerEventFactory.h" | 5 #include "core/events/PointerEventFactory.h" |
6 | 6 |
7 #include "core/frame/FrameView.h" | 7 #include "core/frame/FrameView.h" |
8 #include "platform/geometry/FloatSize.h" | 8 #include "platform/geometry/FloatSize.h" |
9 | 9 |
10 namespace blink { | 10 namespace blink { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 CASE_BUTTON_TO_BUTTONS(X2); | 68 CASE_BUTTON_TO_BUTTONS(X2); |
69 CASE_BUTTON_TO_BUTTONS(Eraser); | 69 CASE_BUTTON_TO_BUTTONS(Eraser); |
70 } | 70 } |
71 | 71 |
72 #undef CASE_BUTTON_TO_BUTTONS | 72 #undef CASE_BUTTON_TO_BUTTONS |
73 | 73 |
74 NOTREACHED(); | 74 NOTREACHED(); |
75 return 0; | 75 return 0; |
76 } | 76 } |
77 | 77 |
78 } // namespace | 78 const AtomicString& pointerEventNameForTouchPointState( |
79 | 79 PlatformTouchPoint::TouchState state) { |
80 const int PointerEventFactory::s_invalidId = 0; | 80 switch (state) { |
81 | 81 case PlatformTouchPoint::TouchReleased: |
82 // Mouse id is 1 to behave the same as MS Edge for compatibility reasons. | 82 return EventTypeNames::pointerup; |
83 const int PointerEventFactory::s_mouseId = 1; | 83 case PlatformTouchPoint::TouchCancelled: |
| 84 return EventTypeNames::pointercancel; |
| 85 case PlatformTouchPoint::TouchPressed: |
| 86 return EventTypeNames::pointerdown; |
| 87 case PlatformTouchPoint::TouchMoved: |
| 88 return EventTypeNames::pointermove; |
| 89 case PlatformTouchPoint::TouchStationary: |
| 90 // Fall through to default |
| 91 default: |
| 92 NOTREACHED(); |
| 93 return emptyAtom; |
| 94 } |
| 95 } |
84 | 96 |
85 float getPointerEventPressure(float force, int buttons) { | 97 float getPointerEventPressure(float force, int buttons) { |
86 if (std::isnan(force)) | 98 if (std::isnan(force)) |
87 return buttons ? 0.5 : 0; | 99 return buttons ? 0.5 : 0; |
88 return force; | 100 return force; |
89 } | 101 } |
90 | 102 |
| 103 void updateTouchPointerEventInit(const PlatformTouchPoint& touchPoint, |
| 104 LocalFrame* targetFrame, |
| 105 PointerEventInit* pointerEventInit) { |
| 106 // This function should not update attributes like pointerId, isPrimary, |
| 107 // and pointerType which is the same among the coalesced events and the |
| 108 // dispatched event. |
| 109 |
| 110 if (targetFrame) { |
| 111 FloatPoint pagePoint = |
| 112 targetFrame->view()->rootFrameToContents(touchPoint.pos()); |
| 113 float scaleFactor = 1.0f / targetFrame->pageZoomFactor(); |
| 114 FloatPoint scrollPosition(targetFrame->view()->scrollOffset()); |
| 115 FloatPoint clientPoint = pagePoint.scaledBy(scaleFactor); |
| 116 clientPoint.moveBy(scrollPosition.scaledBy(-scaleFactor)); |
| 117 |
| 118 pointerEventInit->setClientX(clientPoint.x()); |
| 119 pointerEventInit->setClientY(clientPoint.y()); |
| 120 |
| 121 FloatSize pointRadius = touchPoint.radius().scaledBy(scaleFactor); |
| 122 pointerEventInit->setWidth(pointRadius.width()); |
| 123 pointerEventInit->setHeight(pointRadius.height()); |
| 124 } |
| 125 |
| 126 pointerEventInit->setScreenX(touchPoint.screenPos().x()); |
| 127 pointerEventInit->setScreenY(touchPoint.screenPos().y()); |
| 128 pointerEventInit->setPressure( |
| 129 getPointerEventPressure(touchPoint.force(), pointerEventInit->buttons())); |
| 130 pointerEventInit->setTiltX(touchPoint.pointerProperties().tiltX); |
| 131 pointerEventInit->setTiltY(touchPoint.pointerProperties().tiltY); |
| 132 } |
| 133 |
| 134 void updateMousePointerEventInit(const PlatformMouseEvent& mouseEvent, |
| 135 LocalDOMWindow* view, |
| 136 PointerEventInit* pointerEventInit) { |
| 137 // This function should not update attributes like pointerId, isPrimary, |
| 138 // and pointerType which is the same among the coalesced events and the |
| 139 // dispatched event. |
| 140 |
| 141 pointerEventInit->setScreenX(mouseEvent.globalPosition().x()); |
| 142 pointerEventInit->setScreenY(mouseEvent.globalPosition().y()); |
| 143 |
| 144 IntPoint locationInFrameZoomed; |
| 145 if (view && view->frame() && view->frame()->view()) { |
| 146 LocalFrame* frame = view->frame(); |
| 147 FrameView* frameView = frame->view(); |
| 148 IntPoint locationInContents = |
| 149 frameView->rootFrameToContents(mouseEvent.position()); |
| 150 locationInFrameZoomed = frameView->contentsToFrame(locationInContents); |
| 151 float scaleFactor = 1 / frame->pageZoomFactor(); |
| 152 locationInFrameZoomed.scale(scaleFactor, scaleFactor); |
| 153 } |
| 154 |
| 155 pointerEventInit->setClientX(locationInFrameZoomed.x()); |
| 156 pointerEventInit->setClientY(locationInFrameZoomed.y()); |
| 157 |
| 158 pointerEventInit->setPressure(getPointerEventPressure( |
| 159 mouseEvent.pointerProperties().force, pointerEventInit->buttons())); |
| 160 pointerEventInit->setTiltX(mouseEvent.pointerProperties().tiltX); |
| 161 pointerEventInit->setTiltY(mouseEvent.pointerProperties().tiltY); |
| 162 } |
| 163 |
| 164 } // namespace |
| 165 |
| 166 const int PointerEventFactory::s_invalidId = 0; |
| 167 |
| 168 // Mouse id is 1 to behave the same as MS Edge for compatibility reasons. |
| 169 const int PointerEventFactory::s_mouseId = 1; |
| 170 |
91 void PointerEventFactory::setIdTypeButtons( | 171 void PointerEventFactory::setIdTypeButtons( |
92 PointerEventInit& pointerEventInit, | 172 PointerEventInit& pointerEventInit, |
93 const WebPointerProperties& pointerProperties, | 173 const WebPointerProperties& pointerProperties, |
94 unsigned buttons) { | 174 unsigned buttons) { |
95 const WebPointerProperties::PointerType pointerType = | 175 const WebPointerProperties::PointerType pointerType = |
96 pointerProperties.pointerType; | 176 pointerProperties.pointerType; |
97 const IncomingId incomingId(pointerType, pointerProperties.id); | 177 const IncomingId incomingId(pointerType, pointerProperties.id); |
98 int pointerId = addIdAndActiveButtons(incomingId, buttons != 0); | 178 int pointerId = addIdAndActiveButtons(incomingId, buttons != 0); |
99 | 179 |
100 // Tweak the |buttons| to reflect pen eraser mode only if the pen is in | 180 // Tweak the |buttons| to reflect pen eraser mode only if the pen is in |
(...skipping 20 matching lines...) Expand all Loading... |
121 pointerEventInit.setCancelable(type != EventTypeNames::pointerenter && | 201 pointerEventInit.setCancelable(type != EventTypeNames::pointerenter && |
122 type != EventTypeNames::pointerleave && | 202 type != EventTypeNames::pointerleave && |
123 type != EventTypeNames::pointercancel && | 203 type != EventTypeNames::pointercancel && |
124 type != EventTypeNames::gotpointercapture && | 204 type != EventTypeNames::gotpointercapture && |
125 type != EventTypeNames::lostpointercapture); | 205 type != EventTypeNames::lostpointercapture); |
126 | 206 |
127 pointerEventInit.setComposed(true); | 207 pointerEventInit.setComposed(true); |
128 pointerEventInit.setDetail(0); | 208 pointerEventInit.setDetail(0); |
129 } | 209 } |
130 | 210 |
131 PointerEvent* PointerEventFactory::create(const AtomicString& mouseEventName, | 211 PointerEvent* PointerEventFactory::create( |
132 const PlatformMouseEvent& mouseEvent, | 212 const AtomicString& mouseEventName, |
133 LocalDOMWindow* view) { | 213 const PlatformMouseEvent& mouseEvent, |
| 214 const Vector<PlatformMouseEvent>& coalescedMouseEvents, |
| 215 LocalDOMWindow* view) { |
134 DCHECK(mouseEventName == EventTypeNames::mousemove || | 216 DCHECK(mouseEventName == EventTypeNames::mousemove || |
135 mouseEventName == EventTypeNames::mousedown || | 217 mouseEventName == EventTypeNames::mousedown || |
136 mouseEventName == EventTypeNames::mouseup); | 218 mouseEventName == EventTypeNames::mouseup); |
137 | 219 |
138 AtomicString pointerEventName = | 220 AtomicString pointerEventName = |
139 pointerEventNameForMouseEventName(mouseEventName); | 221 pointerEventNameForMouseEventName(mouseEventName); |
| 222 DCHECK(pointerEventName == EventTypeNames::pointermove || |
| 223 coalescedMouseEvents.isEmpty()); |
| 224 |
140 unsigned buttons = | 225 unsigned buttons = |
141 MouseEvent::platformModifiersToButtons(mouseEvent.getModifiers()); | 226 MouseEvent::platformModifiersToButtons(mouseEvent.getModifiers()); |
142 PointerEventInit pointerEventInit; | 227 PointerEventInit pointerEventInit; |
143 | 228 |
144 setIdTypeButtons(pointerEventInit, mouseEvent.pointerProperties(), buttons); | 229 setIdTypeButtons(pointerEventInit, mouseEvent.pointerProperties(), buttons); |
145 setEventSpecificFields(pointerEventInit, pointerEventName); | 230 setEventSpecificFields(pointerEventInit, pointerEventName); |
146 | 231 |
147 pointerEventInit.setScreenX(mouseEvent.globalPosition().x()); | |
148 pointerEventInit.setScreenY(mouseEvent.globalPosition().y()); | |
149 | |
150 IntPoint locationInFrameZoomed; | |
151 if (view && view->frame() && view->frame()->view()) { | |
152 LocalFrame* frame = view->frame(); | |
153 FrameView* frameView = frame->view(); | |
154 IntPoint locationInContents = | |
155 frameView->rootFrameToContents(mouseEvent.position()); | |
156 locationInFrameZoomed = frameView->contentsToFrame(locationInContents); | |
157 float scaleFactor = 1 / frame->pageZoomFactor(); | |
158 locationInFrameZoomed.scale(scaleFactor, scaleFactor); | |
159 } | |
160 | |
161 // Set up initial values for coordinates. | |
162 pointerEventInit.setClientX(locationInFrameZoomed.x()); | |
163 pointerEventInit.setClientY(locationInFrameZoomed.y()); | |
164 | |
165 if (pointerEventName == EventTypeNames::pointerdown || | 232 if (pointerEventName == EventTypeNames::pointerdown || |
166 pointerEventName == EventTypeNames::pointerup) { | 233 pointerEventName == EventTypeNames::pointerup) { |
167 WebPointerProperties::Button button = mouseEvent.pointerProperties().button; | 234 WebPointerProperties::Button button = mouseEvent.pointerProperties().button; |
168 // TODO(mustaq): Fix when the spec starts supporting hovering erasers. | 235 // TODO(mustaq): Fix when the spec starts supporting hovering erasers. |
169 if (mouseEvent.pointerProperties().pointerType == | 236 if (mouseEvent.pointerProperties().pointerType == |
170 WebPointerProperties::PointerType::Eraser && | 237 WebPointerProperties::PointerType::Eraser && |
171 button == WebPointerProperties::Button::Left) | 238 button == WebPointerProperties::Button::Left) |
172 button = WebPointerProperties::Button::Eraser; | 239 button = WebPointerProperties::Button::Eraser; |
173 pointerEventInit.setButton(static_cast<int>(button)); | 240 pointerEventInit.setButton(static_cast<int>(button)); |
174 } else { | 241 } else { |
175 DCHECK(pointerEventName == EventTypeNames::pointermove); | 242 DCHECK(pointerEventName == EventTypeNames::pointermove); |
176 pointerEventInit.setButton( | 243 pointerEventInit.setButton( |
177 static_cast<int>(WebPointerProperties::Button::NoButton)); | 244 static_cast<int>(WebPointerProperties::Button::NoButton)); |
178 } | 245 } |
179 pointerEventInit.setPressure(getPointerEventPressure( | |
180 mouseEvent.pointerProperties().force, pointerEventInit.buttons())); | |
181 pointerEventInit.setTiltX(mouseEvent.pointerProperties().tiltX); | |
182 pointerEventInit.setTiltY(mouseEvent.pointerProperties().tiltY); | |
183 | 246 |
184 UIEventWithKeyState::setFromPlatformModifiers(pointerEventInit, | 247 UIEventWithKeyState::setFromPlatformModifiers(pointerEventInit, |
185 mouseEvent.getModifiers()); | 248 mouseEvent.getModifiers()); |
186 | 249 |
187 // Make sure chorded buttons fire pointermove instead of pointerup/down. | 250 // Make sure chorded buttons fire pointermove instead of pointerup/down. |
188 if ((pointerEventName == EventTypeNames::pointerdown && | 251 if ((pointerEventName == EventTypeNames::pointerdown && |
189 (buttons & | 252 (buttons & |
190 ~buttonToButtonsBitfield(mouseEvent.pointerProperties().button)) != | 253 ~buttonToButtonsBitfield(mouseEvent.pointerProperties().button)) != |
191 0) || | 254 0) || |
192 (pointerEventName == EventTypeNames::pointerup && buttons != 0)) | 255 (pointerEventName == EventTypeNames::pointerup && buttons != 0)) |
193 pointerEventName = EventTypeNames::pointermove; | 256 pointerEventName = EventTypeNames::pointermove; |
194 | 257 |
195 pointerEventInit.setView(view); | 258 pointerEventInit.setView(view); |
196 | 259 |
| 260 updateMousePointerEventInit(mouseEvent, view, &pointerEventInit); |
| 261 |
| 262 // Created coalesced events init structure |
| 263 HeapVector<Member<PointerEvent>> coalescedPointerEvents; |
| 264 for (const auto& coalescedMouseEvent : coalescedMouseEvents) { |
| 265 DCHECK_EQ(mouseEvent.pointerProperties().id, |
| 266 coalescedMouseEvent.pointerProperties().id); |
| 267 DCHECK_EQ(mouseEvent.pointerProperties().pointerType, |
| 268 coalescedMouseEvent.pointerProperties().pointerType); |
| 269 PointerEventInit coalescedEventInit = pointerEventInit; |
| 270 updateMousePointerEventInit(coalescedMouseEvent, view, &coalescedEventInit); |
| 271 coalescedPointerEvents.append( |
| 272 PointerEvent::create(pointerEventName, coalescedEventInit)); |
| 273 } |
| 274 pointerEventInit.setCoalescedEvents(coalescedPointerEvents); |
| 275 |
197 return PointerEvent::create(pointerEventName, pointerEventInit); | 276 return PointerEvent::create(pointerEventName, pointerEventInit); |
198 } | 277 } |
199 | 278 |
200 PointerEvent* PointerEventFactory::create(const AtomicString& type, | 279 PointerEvent* PointerEventFactory::create( |
201 const PlatformTouchPoint& touchPoint, | 280 const PlatformTouchPoint& touchPoint, |
202 PlatformEvent::Modifiers modifiers, | 281 const Vector<PlatformTouchPoint>& coalescedPoints, |
203 const FloatSize& pointRadius, | 282 PlatformEvent::Modifiers modifiers, |
204 const FloatPoint& clientPoint, | 283 LocalFrame* targetFrame, |
205 DOMWindow* view) { | 284 DOMWindow* view) { |
206 const PlatformTouchPoint::TouchState pointState = touchPoint.state(); | 285 const PlatformTouchPoint::TouchState pointState = touchPoint.state(); |
| 286 const AtomicString& type = |
| 287 pointerEventNameForTouchPointState(touchPoint.state()); |
| 288 |
| 289 DCHECK(type == EventTypeNames::pointermove || coalescedPoints.isEmpty()); |
207 | 290 |
208 bool pointerReleasedOrCancelled = | 291 bool pointerReleasedOrCancelled = |
209 pointState == PlatformTouchPoint::TouchReleased || | 292 pointState == PlatformTouchPoint::TouchReleased || |
210 pointState == PlatformTouchPoint::TouchCancelled; | 293 pointState == PlatformTouchPoint::TouchCancelled; |
211 bool pointerPressedOrReleased = | 294 bool pointerPressedOrReleased = |
212 pointState == PlatformTouchPoint::TouchPressed || | 295 pointState == PlatformTouchPoint::TouchPressed || |
213 pointState == PlatformTouchPoint::TouchReleased; | 296 pointState == PlatformTouchPoint::TouchReleased; |
214 | 297 |
215 PointerEventInit pointerEventInit; | 298 PointerEventInit pointerEventInit; |
216 | 299 |
217 setIdTypeButtons(pointerEventInit, touchPoint.pointerProperties(), | 300 setIdTypeButtons(pointerEventInit, touchPoint.pointerProperties(), |
218 pointerReleasedOrCancelled ? 0 : 1); | 301 pointerReleasedOrCancelled ? 0 : 1); |
219 | |
220 pointerEventInit.setWidth(pointRadius.width()); | |
221 pointerEventInit.setHeight(pointRadius.height()); | |
222 pointerEventInit.setScreenX(touchPoint.screenPos().x()); | |
223 pointerEventInit.setScreenY(touchPoint.screenPos().y()); | |
224 pointerEventInit.setClientX(clientPoint.x()); | |
225 pointerEventInit.setClientY(clientPoint.y()); | |
226 pointerEventInit.setButton(static_cast<int>( | 302 pointerEventInit.setButton(static_cast<int>( |
227 pointerPressedOrReleased ? WebPointerProperties::Button::Left | 303 pointerPressedOrReleased ? WebPointerProperties::Button::Left |
228 : WebPointerProperties::Button::NoButton)); | 304 : WebPointerProperties::Button::NoButton)); |
229 pointerEventInit.setPressure( | 305 |
230 getPointerEventPressure(touchPoint.force(), pointerEventInit.buttons())); | |
231 pointerEventInit.setTiltX(touchPoint.pointerProperties().tiltX); | |
232 pointerEventInit.setTiltY(touchPoint.pointerProperties().tiltY); | |
233 pointerEventInit.setView(view); | 306 pointerEventInit.setView(view); |
| 307 updateTouchPointerEventInit(touchPoint, targetFrame, &pointerEventInit); |
234 | 308 |
235 UIEventWithKeyState::setFromPlatformModifiers(pointerEventInit, modifiers); | 309 UIEventWithKeyState::setFromPlatformModifiers(pointerEventInit, modifiers); |
236 | 310 |
237 setEventSpecificFields(pointerEventInit, type); | 311 setEventSpecificFields(pointerEventInit, type); |
238 | 312 |
| 313 // Created coalesced events init structure |
| 314 HeapVector<Member<PointerEvent>> coalescedPointerEvents; |
| 315 for (const auto& coalescedTouchPoint : coalescedPoints) { |
| 316 DCHECK_EQ(touchPoint.state(), coalescedTouchPoint.state()); |
| 317 DCHECK_EQ(touchPoint.pointerProperties().id, |
| 318 coalescedTouchPoint.pointerProperties().id); |
| 319 DCHECK_EQ(touchPoint.pointerProperties().pointerType, |
| 320 coalescedTouchPoint.pointerProperties().pointerType); |
| 321 PointerEventInit coalescedEventInit = pointerEventInit; |
| 322 updateTouchPointerEventInit(coalescedTouchPoint, targetFrame, |
| 323 &coalescedEventInit); |
| 324 coalescedPointerEvents.append( |
| 325 PointerEvent::create(type, coalescedEventInit)); |
| 326 } |
| 327 pointerEventInit.setCoalescedEvents(coalescedPointerEvents); |
| 328 |
239 return PointerEvent::create(type, pointerEventInit); | 329 return PointerEvent::create(type, pointerEventInit); |
240 } | 330 } |
241 | 331 |
242 PointerEvent* PointerEventFactory::createPointerCancelEvent( | 332 PointerEvent* PointerEventFactory::createPointerCancelEvent( |
243 const int pointerId, | 333 const int pointerId, |
244 const WebPointerProperties::PointerType pointerType) { | 334 const WebPointerProperties::PointerType pointerType) { |
245 DCHECK(m_pointerIdMapping.contains(pointerId)); | 335 DCHECK(m_pointerIdMapping.contains(pointerId)); |
246 m_pointerIdMapping.set( | 336 m_pointerIdMapping.set( |
247 pointerId, | 337 pointerId, |
248 PointerAttributes(m_pointerIdMapping.get(pointerId).incomingId, false)); | 338 PointerAttributes(m_pointerIdMapping.get(pointerId).incomingId, false)); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 const WebPointerProperties& properties) const { | 513 const WebPointerProperties& properties) const { |
424 if (properties.pointerType == WebPointerProperties::PointerType::Mouse) | 514 if (properties.pointerType == WebPointerProperties::PointerType::Mouse) |
425 return PointerEventFactory::s_mouseId; | 515 return PointerEventFactory::s_mouseId; |
426 IncomingId id(properties.pointerType, properties.id); | 516 IncomingId id(properties.pointerType, properties.id); |
427 if (m_pointerIncomingIdMapping.contains(id)) | 517 if (m_pointerIncomingIdMapping.contains(id)) |
428 return m_pointerIncomingIdMapping.get(id); | 518 return m_pointerIncomingIdMapping.get(id); |
429 return PointerEventFactory::s_invalidId; | 519 return PointerEventFactory::s_invalidId; |
430 } | 520 } |
431 | 521 |
432 } // namespace blink | 522 } // namespace blink |
OLD | NEW |