     @_scrollPositionManuallySet = false
 
     @_pendingState._scrollPosition = switch _tracking
-      when null, "start" then (if !scrolled then 0 else mainChildrenOffset)
-      when "end"         then (if !scrolled then 0 else mainChildrenOffset - mainElementSizeForChildren + mainChildrenSize)
+      when null, "start" then 2 * (if !scrolled then 0 else mainChildrenOffset)
+      when "end"         then 2 * (if !scrolled then 0 else mainChildrenOffset - mainElementSizeForChildren + mainChildrenSize)
       when "child"       then @_findFocusedChild mainCoordinate, inFlowChildren, mainChildrenSize, mainElementSizeForChildren
 
     if _tracking != "child"
       @_pendingState._focusedChild = null
-    if @_focusedChild != @_pendingState._focusedChild
-      @queueEvent "focusedChildChanged", focusedChild: @_pendingState._focusedChild
+
+    @_updateOnScreenInfo()
 
     log "tracking: #{@_pendingState._tracking} #{_scrollPosition}"
+
+  _updateOnScreenInfo: (inFlowChildren) ->
+    {isVertical, childrenSize, windowSize} = @
+
+    focusedChild = @_pendingState._focusedChild
+
+    children = @_pendingState._children
+    firstOnScreenChildIndex = children.length
+    focusedChildIndex = lastOnScreenChildIndex = -1
+
+    for child, i in children
+      if child.getPendingInFlow()
+        if isVertical
+          pos = child.getCurrentLocationY false, point0
+          size = child.getCurrentSize().y
+        else
+          pos = child.getCurrentLocationX false, point0
+          size = child.getCurrentSize().x
+
+        if pos < windowSize && pos + size > 0
+          firstOnScreenChildIndex = min i, firstOnScreenChildIndex
+          lastOnScreenChildIndex  = max i, lastOnScreenChildIndex
+          if child == focusedChild
+            focusedChildIndex = i
+
+    firstOnScreenChildIndex = -1 if firstOnScreenChildIndex == children.length
+
+    if (
+        firstOnScreenChildIndex != @_firstOnScreenChildIndex ||
+        lastOnScreenChildIndex  != @_lastOnScreenChildIndex ||
+        focusedChildIndex       != @_focusedChildIndex ||
+        focusedChild            != @_focusedChild
+      )
+      @queueEvent "scrollUpdate", =>
+        {
+          childrenSize
+          windowSize
+          focusedChild
+          firstOnScreenChildIndex
+          lastOnScreenChildIndex
+          focusedChildIndex
+        }
+
+    @_firstOnScreenChildIndex = firstOnScreenChildIndex
+    @_lastOnScreenChildIndex  = lastOnScreenChildIndex
+    @_focusedChildIndex       = focusedChildIndex
+
+    null
 
   # OUT: child's position relative to this, it's parent
   _findFocusedChild: (mainCoordinate, inFlowChildren, mainChildrenSize, mainElementSizeForChildren) ->

      preprocess: (v) -> legalTrackingValues[v]
    tracking:           default: null

    scrollPosition:     default: 0

  defaultChildrenLayout:  "column"
  defaultChildArea:       "logicalArea"

  constructor: ->
    super
    @_maxScrollPosition = 0
    @_initGestureProps()

  postFlexLayout: (mainCoordinate, inFlowChildren, mainChildrenSize, mainElementSizeForChildren, mainChildrenAlignedOffset) ->
    {_focusedChild, _focusedChildAxis, _scrollPos, _scrollPosition, _tracking} = @getState true
    # log postFlexLayout: {mainChildrenSize, mainElementSizeForChildren}
    @_maxScrollPosition = max 0, mainChildrenSize - mainElementSizeForChildren

    offsetDelta = if mainChildrenSize <= mainElementSizeForChildren
      _scrollPosition
    else switch _tracking
      when "start", null then _scrollPosition - mainChildrenAlignedOffset
      when "end"         then _scrollPosition + mainElementSizeForChildren - mainChildrenSize - mainChildrenAlignedOffset
      when "child"
        _scrollPosition - if mainCoordinate == "x"
          _focusedChild.getCurrentLocationX true, point0


  # ######################################
  @getter
    isVertical:                -> @_childrenLayout == "column"

    numChildrenOnScreen: ->
      {isVertical, windowSize} = @
      numChildrenOnScreen = 0

      for child in @children when child.inFlow
        if isVertical
          pos = child.getCurrentLocationY false, point0
          size = child.getCurrentSize().y
        else
          pos = child.getCurrentLocationX false, point0
          size = child.getCurrentSize().x
        numChildrenOnScreen++ if pos < windowSize && pos + size > 0

      numChildrenOnScreen

  #   atEnd:                     -> @_atEnd
  #   atStart:                   -> @_atStart
  #   inMiddle:                  -> !@_atEnd && !@_atStart
