       scrollDelta = roundOut(delta * progress) - scrolledAmount
       scrolledAmount += scrollDelta
 
-      if performScroll(element, axisName, scrollDelta, false) != scrollDelta or shouldStopScrolling progress
+      if not performScroll(element, axisName, scrollDelta, false) or shouldStopScrolling progress
           # One final call of performScroll to check the visibility of the activated element.
           performScroll(element, axisName, 0, true)
           window.cancelAnimationFrame(animatorId)

    unless settings.get "smoothScroll"
      return performScroll element, axisName, amount

    if mostRecentActivationId == time or lastEvent?.repeat
      # Either the most-recently activated animator has not yet received its keyup event (so it's still
      # scrolling), or this is a keyboard repeat (for which we don't initiate a new animator).  We need both
      # of these checks because sometimes (perhaps one time in twenty) the last keyboard repeat arrives
      # *after* the corresponding keyup.
      return

    mostRecentActivationId = activationId = ++time

    duration = 100 # Duration in ms.
    fudgeFactor = 25

    # Allow a bit longer for longer scrolls.
    duration += fudgeFactor * Math.log Math.abs amount

    # Round away from 0, so that we don't leave any scroll amount unscrolled.
    roundOut = if 0 <= amount then Math.ceil else Math.floor
    delta = roundOut(amount / duration)


    # if the activated element has been scrolled completely offscreen, subsequent changes in its scroll
    # position will not provide any more visual feedback to the user. therefore we deactivate it so that
    # subsequent scrolls only move the parent element.
    # TODO(smblott) Refactor this out of here.
    rect = activatedElement.getBoundingClientRect()
    if (rect.bottom < 0 || rect.top > window.innerHeight || rect.right < 0 || rect.left > window.innerWidth)
      activatedElement = element

  # Return true if we successfully scrolled by the requested amount, false otherwise.
  amount == element[axisName] - before

# How scrolling is handled:
#   - For non-smooth scrolling, the entire scroll happens immediately.
#   - For smooth scrolling with distinct key presses, a separate animator is initiated for each key press.
#     Therefore, several animators may be active at the same time.  This ensures that two quick taps on `j`
#     scroll to the same position as two slower taps (modulo rounding errors).
#   - For smooth scrolling with keyboard repeat, the most recently-activated animator continues scrolling
#     at least until its corresponding keyup event is received.  We never initiate a new animator on keyboard
#     repeat.

# Scroll by a relative amount (a number) in some direction, possibly smoothly.
doScrollBy = do ->
  # This is logical time. Time is advanced each time an animator is activated, and on each keyup event.
  time = 0
  mostRecentActivationTime = -1
  lastEvent = null
  keyHandler = null

