mirror of
https://github.com/atom/atom.git
synced 2026-01-23 13:58:08 -05:00
Merge pull request #2801 from atom/ns-react-fix-jitter
Fix jitter in React editor
This commit is contained in:
@@ -84,7 +84,6 @@ describe "EditorComponent", ->
|
||||
|
||||
verticalScrollbarNode.scrollTop = 4.5 * lineHeightInPixels
|
||||
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
|
||||
runSetImmediateCallbacks()
|
||||
|
||||
expect(linesNode.style['-webkit-transform']).toBe "translate3d(0px, #{-4.5 * lineHeightInPixels}px, 0px)"
|
||||
expect(node.querySelectorAll('.line').length).toBe 6 + 4 # margin above and below
|
||||
@@ -353,7 +352,6 @@ describe "EditorComponent", ->
|
||||
|
||||
verticalScrollbarNode.scrollTop = 2.5 * lineHeightInPixels
|
||||
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
|
||||
runSetImmediateCallbacks()
|
||||
|
||||
expect(node.querySelectorAll('.line-number').length).toBe 6 + 4 + 1 # line overdraw margin above/below + dummy line number
|
||||
|
||||
@@ -544,7 +542,6 @@ describe "EditorComponent", ->
|
||||
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
|
||||
horizontalScrollbarNode.scrollLeft = 3.5 * charWidth
|
||||
horizontalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
|
||||
runSetImmediateCallbacks()
|
||||
|
||||
cursorNodes = node.querySelectorAll('.cursor')
|
||||
expect(cursorNodes.length).toBe 2
|
||||
@@ -751,11 +748,11 @@ describe "EditorComponent", ->
|
||||
# Add decorations that are out of range
|
||||
marker2 = editor.displayBuffer.markBufferRange([[9, 0], [9, 0]])
|
||||
editor.addDecorationForMarker(marker2, type: ['gutter', 'line'], class: 'b')
|
||||
runSetImmediateCallbacks()
|
||||
|
||||
# Scroll decorations into view
|
||||
verticalScrollbarNode.scrollTop = 2.5 * lineHeightInPixels
|
||||
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
|
||||
runSetImmediateCallbacks()
|
||||
expect(lineAndLineNumberHaveClass(9, 'b')).toBe true
|
||||
|
||||
# Fold a line to move the decorations
|
||||
@@ -901,7 +898,6 @@ describe "EditorComponent", ->
|
||||
|
||||
verticalScrollbarNode.scrollTop = 3.5 * lineHeightInPixels
|
||||
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
|
||||
runSetImmediateCallbacks()
|
||||
|
||||
regions = node.querySelectorAll('.some-highlight .region')
|
||||
|
||||
@@ -1421,36 +1417,30 @@ describe "EditorComponent", ->
|
||||
expect(horizontalScrollbarNode.scrollLeft).toBe 0
|
||||
|
||||
node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: -5, wheelDeltaY: -10))
|
||||
runSetImmediateCallbacks()
|
||||
expect(verticalScrollbarNode.scrollTop).toBe 10
|
||||
expect(horizontalScrollbarNode.scrollLeft).toBe 0
|
||||
|
||||
node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: -15, wheelDeltaY: -5))
|
||||
runSetImmediateCallbacks()
|
||||
expect(verticalScrollbarNode.scrollTop).toBe 10
|
||||
expect(horizontalScrollbarNode.scrollLeft).toBe 15
|
||||
|
||||
it "updates the scrollLeft or scrollTop according to the scroll sensitivity", ->
|
||||
atom.config.set('editor.scrollSensitivity', 50)
|
||||
node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: -5, wheelDeltaY: -10))
|
||||
runSetImmediateCallbacks()
|
||||
expect(horizontalScrollbarNode.scrollLeft).toBe 0
|
||||
|
||||
node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: -15, wheelDeltaY: -5))
|
||||
runSetImmediateCallbacks()
|
||||
expect(verticalScrollbarNode.scrollTop).toBe 5
|
||||
expect(horizontalScrollbarNode.scrollLeft).toBe 7
|
||||
|
||||
it "uses the previous scrollSensitivity when the value is not an int", ->
|
||||
atom.config.set('editor.scrollSensitivity', 'nope')
|
||||
node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: 0, wheelDeltaY: -10))
|
||||
runSetImmediateCallbacks()
|
||||
expect(verticalScrollbarNode.scrollTop).toBe 10
|
||||
|
||||
it "parses negative scrollSensitivity values as positive", ->
|
||||
atom.config.set('editor.scrollSensitivity', -50)
|
||||
node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: 0, wheelDeltaY: -10))
|
||||
runSetImmediateCallbacks()
|
||||
expect(verticalScrollbarNode.scrollTop).toBe 5
|
||||
|
||||
describe "when the mousewheel event's target is a line", ->
|
||||
|
||||
@@ -26,6 +26,8 @@ EditorComponent = React.createClass
|
||||
pendingScrollLeft: null
|
||||
selectOnMouseMove: false
|
||||
updateRequested: false
|
||||
updatesPaused: false
|
||||
updateRequestedWhilePaused: false
|
||||
cursorsMoved: false
|
||||
selectionChanged: false
|
||||
selectionAdded: false
|
||||
@@ -44,6 +46,7 @@ EditorComponent = React.createClass
|
||||
inputEnabled: true
|
||||
scrollViewMeasurementInterval: 100
|
||||
scopedCharacterWidthsChangeCount: null
|
||||
scrollViewMeasurementPaused: false
|
||||
|
||||
render: ->
|
||||
{focused, fontSize, lineHeight, fontFamily, showIndentGuide, showInvisibles, showLineNumbers, visible} = @state
|
||||
@@ -163,7 +166,7 @@ EditorComponent = React.createClass
|
||||
componentDidMount: ->
|
||||
{editor} = @props
|
||||
|
||||
@scrollViewMeasurementIntervalId = setInterval(@requestScrollViewMeasurement, @scrollViewMeasurementInterval)
|
||||
@scrollViewMeasurementIntervalId = setInterval(@measureScrollView, @scrollViewMeasurementInterval)
|
||||
|
||||
@observeEditor()
|
||||
@listenForDOMEvents()
|
||||
@@ -183,8 +186,6 @@ EditorComponent = React.createClass
|
||||
clearInterval(@scrollViewMeasurementIntervalId)
|
||||
@scrollViewMeasurementIntervalId = null
|
||||
|
||||
componentWillUpdate: ->
|
||||
|
||||
componentDidUpdate: (prevProps, prevState) ->
|
||||
cursorsMoved = @cursorsMoved
|
||||
selectionChanged = @selectionChanged
|
||||
@@ -204,6 +205,10 @@ EditorComponent = React.createClass
|
||||
@remeasureCharacterWidthsIfNeeded(prevState)
|
||||
|
||||
requestUpdate: ->
|
||||
if @updatesPaused
|
||||
@updateRequestedWhilePaused = true
|
||||
return
|
||||
|
||||
if @performSyncUpdates ? EditorComponent.performSyncUpdates
|
||||
@forceUpdate()
|
||||
else unless @updateRequested
|
||||
@@ -212,6 +217,16 @@ EditorComponent = React.createClass
|
||||
@updateRequested = false
|
||||
@forceUpdate() if @isMounted()
|
||||
|
||||
requestAnimationFrame: (fn) ->
|
||||
@updatesPaused = true
|
||||
@pauseScrollViewMeasurement()
|
||||
requestAnimationFrame =>
|
||||
fn()
|
||||
@updatesPaused = false
|
||||
if @updateRequestedWhilePaused and @isMounted()
|
||||
@updateRequestedWhilePaused = false
|
||||
@forceUpdate()
|
||||
|
||||
getRenderedRowRange: ->
|
||||
{editor, lineOverdrawMargin} = @props
|
||||
[visibleStartRow, visibleEndRow] = editor.getVisibleRowRange()
|
||||
@@ -515,12 +530,12 @@ EditorComponent = React.createClass
|
||||
onVerticalScroll: (scrollTop) ->
|
||||
{editor} = @props
|
||||
|
||||
return if scrollTop is editor.getScrollTop()
|
||||
return if @updateRequested or scrollTop is editor.getScrollTop()
|
||||
|
||||
animationFramePending = @pendingScrollTop?
|
||||
@pendingScrollTop = scrollTop
|
||||
unless animationFramePending
|
||||
requestAnimationFrame =>
|
||||
@requestAnimationFrame =>
|
||||
pendingScrollTop = @pendingScrollTop
|
||||
@pendingScrollTop = null
|
||||
@props.editor.setScrollTop(pendingScrollTop)
|
||||
@@ -528,12 +543,12 @@ EditorComponent = React.createClass
|
||||
onHorizontalScroll: (scrollLeft) ->
|
||||
{editor} = @props
|
||||
|
||||
return if scrollLeft is editor.getScrollLeft()
|
||||
return if @updateRequested or scrollLeft is editor.getScrollLeft()
|
||||
|
||||
animationFramePending = @pendingScrollLeft?
|
||||
@pendingScrollLeft = scrollLeft
|
||||
unless animationFramePending
|
||||
requestAnimationFrame =>
|
||||
@requestAnimationFrame =>
|
||||
@props.editor.setScrollLeft(@pendingScrollLeft)
|
||||
@pendingScrollLeft = null
|
||||
|
||||
@@ -554,7 +569,7 @@ EditorComponent = React.createClass
|
||||
@clearMouseWheelScreenRowAfterDelay()
|
||||
|
||||
unless animationFramePending
|
||||
requestAnimationFrame =>
|
||||
@requestAnimationFrame =>
|
||||
{editor} = @props
|
||||
editor.setScrollTop(editor.getScrollTop() + @pendingVerticalScrollDelta)
|
||||
editor.setScrollLeft(editor.getScrollLeft() + @pendingHorizontalScrollDelta)
|
||||
@@ -655,7 +670,7 @@ EditorComponent = React.createClass
|
||||
onScrollTopChanged: ->
|
||||
@scrollingVertically = true
|
||||
@requestUpdate()
|
||||
@onStoppedScrollingAfterDelay ?= debounce(@onStoppedScrolling, 100)
|
||||
@onStoppedScrollingAfterDelay ?= debounce(@onStoppedScrolling, 200)
|
||||
@onStoppedScrollingAfterDelay()
|
||||
|
||||
onStoppedScrolling: ->
|
||||
@@ -682,7 +697,7 @@ EditorComponent = React.createClass
|
||||
dragging = false
|
||||
lastMousePosition = {}
|
||||
animationLoop = =>
|
||||
requestAnimationFrame =>
|
||||
@requestAnimationFrame =>
|
||||
if dragging
|
||||
screenPosition = @screenPositionForMouseEvent(lastMousePosition)
|
||||
dragHandler(screenPosition)
|
||||
@@ -709,8 +724,18 @@ EditorComponent = React.createClass
|
||||
window.addEventListener('mousemove', onMouseMove)
|
||||
window.addEventListener('mouseup', onMouseUp)
|
||||
|
||||
pauseScrollViewMeasurement: ->
|
||||
@scrollViewMeasurementPaused = true
|
||||
@resumeScrollViewMeasurementAfterDelay ?= debounce(@resumeScrollViewMeasurement, 100)
|
||||
@resumeScrollViewMeasurementAfterDelay()
|
||||
|
||||
resumeScrollViewMeasurement: ->
|
||||
@scrollViewMeasurementPaused = false
|
||||
|
||||
resumeScrollViewMeasurementAfterDelay: null # created lazily
|
||||
|
||||
requestScrollViewMeasurement: ->
|
||||
return if @measurementPending
|
||||
return if @scrollViewMeasurementRequested
|
||||
|
||||
@scrollViewMeasurementRequested = true
|
||||
requestAnimationFrame =>
|
||||
@@ -722,6 +747,7 @@ EditorComponent = React.createClass
|
||||
# and use the scrollHeight / scrollWidth as its height and width in
|
||||
# calculations.
|
||||
measureScrollView: ->
|
||||
return if @scrollViewMeasurementPaused
|
||||
return unless @isMounted()
|
||||
|
||||
{editor} = @props
|
||||
|
||||
Reference in New Issue
Block a user