OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of touch; | 5 part of touch; |
6 | 6 |
7 /** | 7 /** |
8 * Click buster implementation, which is a behavior that prevents native clicks | 8 * Click buster implementation, which is a behavior that prevents native clicks |
9 * from firing at undesirable times. There are two scenarios where we may want | 9 * from firing at undesirable times. There are two scenarios where we may want |
10 * to 'bust' a click. | 10 * to 'bust' a click. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 /* | 62 /* |
63 if (coord.x < 1 && coord.y < 1) { | 63 if (coord.x < 1 && coord.y < 1) { |
64 // TODO(jacobr): implement a configurable logging framework. | 64 // TODO(jacobr): implement a configurable logging framework. |
65 // _logger.warning( | 65 // _logger.warning( |
66 // "Not busting click on label elem at(${coord.x}, ${coord.y})"); | 66 // "Not busting click on label elem at(${coord.x}, ${coord.y})"); |
67 return; | 67 return; |
68 } | 68 } |
69 */ | 69 */ |
70 DoubleLinkedQueueEntry<num> entry = _coordinates.firstEntry(); | 70 DoubleLinkedQueueEntry<num> entry = _coordinates.firstEntry(); |
71 while (entry != null) { | 71 while (entry != null) { |
72 if (_hitTest(entry.element, | 72 if (_hitTest( |
73 entry.nextEntry().element, | 73 entry.element, entry.nextEntry().element, coord.x, coord.y)) { |
74 coord.x, | |
75 coord.y)) { | |
76 entry.nextEntry().remove(); | 74 entry.nextEntry().remove(); |
77 entry.remove(); | 75 entry.remove(); |
78 return; | 76 return; |
79 } else { | 77 } else { |
80 entry = entry.nextEntry().nextEntry(); | 78 entry = entry.nextEntry().nextEntry(); |
81 } | 79 } |
82 } | 80 } |
83 | 81 |
84 // TODO(jacobr): implement a configurable logging framework. | 82 // TODO(jacobr): implement a configurable logging framework. |
85 // _logger.warning("busting click at ${coord.x}, ${coord.y}"); | 83 // _logger.warning("busting click at ${coord.x}, ${coord.y}"); |
86 e.stopPropagation(); | 84 e.stopPropagation(); |
87 e.preventDefault(); | 85 e.preventDefault(); |
88 } | 86 } |
89 | 87 |
90 /** | 88 /** |
91 * This handler will temporarily allow a click to occur near the touch event's | 89 * This handler will temporarily allow a click to occur near the touch event's |
92 * coordinates. | 90 * coordinates. |
93 */ | 91 */ |
94 static void _onTouchStart(Event e) { | 92 static void _onTouchStart(Event e) { |
95 TouchEvent te = e; | 93 TouchEvent te = e; |
96 final coord = new Coordinate.fromClient(te.touches[0]); | 94 final coord = new Coordinate.fromClient(te.touches[0]); |
97 _coordinates.add(coord.x); | 95 _coordinates.add(coord.x); |
98 _coordinates.add(coord.y); | 96 _coordinates.add(coord.y); |
99 new Timer( | 97 new Timer(const Duration(milliseconds: _TIME_THRESHOLD), () { |
100 const Duration(milliseconds: _TIME_THRESHOLD), | 98 _removeCoordinate(coord.x, coord.y); |
101 () { _removeCoordinate(coord.x, coord.y); }); | 99 }); |
102 _toggleTapHighlights(true); | 100 _toggleTapHighlights(true); |
103 } | 101 } |
104 | 102 |
105 /** | 103 /** |
106 * Hit test for whether a coordinate is within the distance threshold of an | 104 * Hit test for whether a coordinate is within the distance threshold of an |
107 * event. | 105 * event. |
108 */ | 106 */ |
109 static bool _hitTest(num x, num y, num eventX, num eventY) { | 107 static bool _hitTest(num x, num y, num eventX, num eventY) { |
110 return (eventX - x).abs() < _DISTANCE_THRESHOLD && | 108 return (eventX - x).abs() < _DISTANCE_THRESHOLD && |
111 (eventY - y).abs() < _DISTANCE_THRESHOLD; | 109 (eventY - y).abs() < _DISTANCE_THRESHOLD; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 // from propagating since there is no "allowable zone". | 171 // from propagating since there is no "allowable zone". |
174 // | 172 // |
175 // 3) User performs a should-not-be-busted click. | 173 // 3) User performs a should-not-be-busted click. |
176 // - touchstart event triggers the attached handler and creates a | 174 // - touchstart event triggers the attached handler and creates a |
177 // temporary "allowable zone". | 175 // temporary "allowable zone". |
178 // - The click handler captures the user's click event and allows it to | 176 // - The click handler captures the user's click event and allows it to |
179 // propagate since the click falls in the "allowable zone". | 177 // propagate since the click falls in the "allowable zone". |
180 if (_coordinates == null) { | 178 if (_coordinates == null) { |
181 // Listen to clicks on capture phase so they can be busted before anything | 179 // Listen to clicks on capture phase so they can be busted before anything |
182 // else gets a chance to handle them. | 180 // else gets a chance to handle them. |
183 Element.clickEvent.forTarget(document, useCapture: true).listen( | 181 Element.clickEvent.forTarget(document, useCapture: true).listen((e) { |
184 (e) { _onClick(e); }); | 182 _onClick(e); |
185 Element.focusEvent.forTarget(document, useCapture: true).listen( | 183 }); |
186 (e) { _lastPreventedTime = 0; }); | 184 Element.focusEvent.forTarget(document, useCapture: true).listen((e) { |
| 185 _lastPreventedTime = 0; |
| 186 }); |
187 | 187 |
188 // Listen to touchstart on capture phase since it must be called prior to | 188 // Listen to touchstart on capture phase since it must be called prior to |
189 // every click or else we will accidentally prevent the click even if we | 189 // every click or else we will accidentally prevent the click even if we |
190 // don't call preventGhostClick. | 190 // don't call preventGhostClick. |
191 Function startFn = (e) { _onTouchStart(e); }; | 191 Function startFn = (e) { |
| 192 _onTouchStart(e); |
| 193 }; |
192 if (!Device.supportsTouch) { | 194 if (!Device.supportsTouch) { |
193 startFn = mouseToTouchCallback(startFn); | 195 startFn = mouseToTouchCallback(startFn); |
194 } | 196 } |
195 var stream; | 197 var stream; |
196 if (Device.supportsTouch) { | 198 if (Device.supportsTouch) { |
197 stream = Element.touchStartEvent.forTarget(document, useCapture:true); | 199 stream = Element.touchStartEvent.forTarget(document, useCapture: true); |
198 } else { | 200 } else { |
199 stream = Element.mouseDownEvent.forTarget(document, useCapture:true); | 201 stream = Element.mouseDownEvent.forTarget(document, useCapture: true); |
200 } | 202 } |
201 EventUtil.observe(document, | 203 EventUtil.observe(document, stream, startFn, true); |
202 stream, | |
203 startFn, true); | |
204 _coordinates = new DoubleLinkedQueue<num>(); | 204 _coordinates = new DoubleLinkedQueue<num>(); |
205 } | 205 } |
206 | 206 |
207 // Turn tap highlights off until we know the ghost click has fired. | 207 // Turn tap highlights off until we know the ghost click has fired. |
208 _toggleTapHighlights(false); | 208 _toggleTapHighlights(false); |
209 | 209 |
210 // Above all other rules, we won't bust any clicks if there wasn't some call | 210 // Above all other rules, we won't bust any clicks if there wasn't some call |
211 // to preventGhostClick in the last time threshold. | 211 // to preventGhostClick in the last time threshold. |
212 _lastPreventedTime = TimeUtil.now(); | 212 _lastPreventedTime = TimeUtil.now(); |
213 DoubleLinkedQueueEntry<num> entry = _coordinates.firstEntry(); | 213 DoubleLinkedQueueEntry<num> entry = _coordinates.firstEntry(); |
214 while (entry != null) { | 214 while (entry != null) { |
215 if (_hitTest(entry.element, entry.nextEntry().element, x, y)) { | 215 if (_hitTest(entry.element, entry.nextEntry().element, x, y)) { |
216 entry.nextEntry().remove(); | 216 entry.nextEntry().remove(); |
217 entry.remove(); | 217 entry.remove(); |
218 return; | 218 return; |
219 } else { | 219 } else { |
220 entry = entry.nextEntry().nextEntry(); | 220 entry = entry.nextEntry().nextEntry(); |
221 } | 221 } |
222 } | 222 } |
223 } | 223 } |
224 } | 224 } |
OLD | NEW |