22// Use of this source code is governed by a BSD-style license that can be
33// found in the LICENSE file.
44
5+ import 'package:meta/meta.dart' ;
56import 'package:ui/src/engine.dart' ;
67import 'package:ui/ui.dart' as ui;
78
@@ -55,12 +56,17 @@ class SemanticScrollable extends SemanticRole {
5556 ///
5657 /// This gesture is converted to [ui.SemanticsAction.scrollUp] or
5758 /// [ui.SemanticsAction.scrollDown] , depending on the direction.
58- DomEventListener ? _scrollListener;
59+ @visibleForTesting
60+ DomEventListener ? scrollListener;
5961
6062 /// The value of the "scrollTop" or "scrollLeft" property of this object's
6163 /// [element] that has zero offset relative to the [scrollPosition] .
6264 int _effectiveNeutralScrollPosition = 0 ;
6365
66+ /// Whether this scrollable can scroll vertically or horizontally.
67+ bool get _canScroll =>
68+ semanticsObject.isVerticalScrollContainer || semanticsObject.isHorizontalScrollContainer;
69+
6470 /// Responds to browser-detected "scroll" gestures.
6571 void _recomputeScrollPosition () {
6672 if (_domScrollPosition != _effectiveNeutralScrollPosition) {
@@ -135,7 +141,9 @@ class SemanticScrollable extends SemanticRole {
135141 semanticsObject.updateChildrenPositionAndSize ();
136142 });
137143
138- if (_scrollListener == null ) {
144+ _updateCssOverflow ();
145+
146+ if (scrollListener == null ) {
139147 // We need to set touch-action:none explicitly here, despite the fact
140148 // that we already have it on the <body> tag because overflow:scroll
141149 // still causes the browser to take over pointer events in order to
@@ -146,20 +154,22 @@ class SemanticScrollable extends SemanticRole {
146154 // CSS property. In Safari the `PointerBinding` uses `preventDefault`
147155 // to prevent browser scrolling.
148156 element.style.touchAction = 'none' ;
149- _gestureModeDidChange ();
150157
151158 // Memoize the tear-off because Dart does not guarantee that two
152159 // tear-offs of a method on the same instance will produce the same
153160 // object.
154161 _gestureModeListener = (_) {
155- _gestureModeDidChange ();
162+ _updateCssOverflow ();
156163 };
157164 EngineSemantics .instance.addGestureModeListener (_gestureModeListener! );
158165
159- _scrollListener = createDomEventListener ((_) {
166+ scrollListener = createDomEventListener ((_) {
167+ if (! _canScroll) {
168+ return ;
169+ }
160170 _recomputeScrollPosition ();
161171 });
162- addEventListener ('scroll' , _scrollListener );
172+ addEventListener ('scroll' , scrollListener );
163173 }
164174 }
165175
@@ -207,7 +217,7 @@ class SemanticScrollable extends SemanticRole {
207217 semanticsObject
208218 ..verticalScrollAdjustment = _effectiveNeutralScrollPosition.toDouble ()
209219 ..horizontalScrollAdjustment = 0.0 ;
210- } else {
220+ } else if (semanticsObject.isHorizontalScrollContainer) {
211221 // Place the _scrollOverflowElement at the end of the content and
212222 // make sure that when we neutralize the scrolling position,
213223 // it doesn't scroll into the visible area.
@@ -223,10 +233,21 @@ class SemanticScrollable extends SemanticRole {
223233 semanticsObject
224234 ..verticalScrollAdjustment = 0.0
225235 ..horizontalScrollAdjustment = _effectiveNeutralScrollPosition.toDouble ();
236+ } else {
237+ _scrollOverflowElement.style
238+ ..transform = 'translate(0px,0px)'
239+ ..width = '0px'
240+ ..height = '0px' ;
241+ element.scrollLeft = 0.0 ;
242+ element.scrollTop = 0.0 ;
243+ _effectiveNeutralScrollPosition = 0 ;
244+ semanticsObject
245+ ..verticalScrollAdjustment = 0.0
246+ ..horizontalScrollAdjustment = 0.0 ;
226247 }
227248 }
228249
229- void _gestureModeDidChange () {
250+ void _updateCssOverflow () {
230251 switch (EngineSemantics .instance.gestureMode) {
231252 case GestureMode .browserGestures:
232253 // overflow:scroll will cause the browser report "scroll" events when
@@ -261,9 +282,9 @@ class SemanticScrollable extends SemanticRole {
261282 style.removeProperty ('overflowY' );
262283 style.removeProperty ('overflowX' );
263284 style.removeProperty ('touch-action' );
264- if (_scrollListener != null ) {
265- removeEventListener ('scroll' , _scrollListener );
266- _scrollListener = null ;
285+ if (scrollListener != null ) {
286+ removeEventListener ('scroll' , scrollListener );
287+ scrollListener = null ;
267288 }
268289 if (_gestureModeListener != null ) {
269290 EngineSemantics .instance.removeGestureModeListener (_gestureModeListener! );
0 commit comments