From 1d9514ca811d06f7119240b27ee14799c20468ca Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Mon, 23 Jun 2014 22:20:55 -0600 Subject: [PATCH] Don't call nextTick within requestAnimationFrame This seems to be causing stutter when scrolling on the GPU. When I don't use nextTick when requesting animation frames, the problem seems to go away. Maybe there's some issue with the integration between the Node and Chromium event loops plus sending things to the compositor. /cc @benogle --- spec/editor-component-spec.coffee | 11 ----------- src/editor-component.coffee | 13 +++++++++---- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 769cd5b71..497e36f09 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -84,7 +84,6 @@ describe "EditorComponent", -> verticalScrollbarNode.scrollTop = 4.5 * lineHeightInPixels verticalScrollbarNode.dispatchEvent(new UIEvent('scroll')) - nextTick() 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 @@ -391,7 +390,6 @@ describe "EditorComponent", -> verticalScrollbarNode.scrollTop = 2.5 * lineHeightInPixels verticalScrollbarNode.dispatchEvent(new UIEvent('scroll')) - nextTick() expect(node.querySelectorAll('.line-number').length).toBe 6 + 4 + 1 # line overdraw margin above/below + dummy line number @@ -755,7 +753,6 @@ describe "EditorComponent", -> verticalScrollbarNode.dispatchEvent(new UIEvent('scroll')) horizontalScrollbarNode.scrollLeft = 3.5 * charWidth horizontalScrollbarNode.dispatchEvent(new UIEvent('scroll')) - nextTick() cursorNodes = node.querySelectorAll('.cursor') expect(cursorNodes.length).toBe 2 @@ -969,7 +966,6 @@ describe "EditorComponent", -> verticalScrollbarNode.scrollTop = 3.5 * lineHeightInPixels verticalScrollbarNode.dispatchEvent(new UIEvent('scroll')) - nextTick() regions = node.querySelectorAll('.some-highlight .region') @@ -1348,7 +1344,6 @@ describe "EditorComponent", -> expect(editor.getScrollLeft()).toBe 0 horizontalScrollbarNode.scrollLeft = 100 horizontalScrollbarNode.dispatchEvent(new UIEvent('scroll')) - nextTick() expect(editor.getScrollLeft()).toBe 100 @@ -1479,12 +1474,10 @@ describe "EditorComponent", -> expect(horizontalScrollbarNode.scrollLeft).toBe 0 node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: -5, wheelDeltaY: -10)) - nextTick() expect(verticalScrollbarNode.scrollTop).toBe 10 expect(horizontalScrollbarNode.scrollLeft).toBe 0 node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: -15, wheelDeltaY: -5)) - nextTick() expect(verticalScrollbarNode.scrollTop).toBe 10 expect(horizontalScrollbarNode.scrollLeft).toBe 15 @@ -1492,24 +1485,20 @@ describe "EditorComponent", -> atom.config.set('editor.scrollSensitivity', 50) node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: -5, wheelDeltaY: -10)) nextTick() - expect(verticalScrollbarNode.scrollTop).toBe 5 expect(horizontalScrollbarNode.scrollLeft).toBe 0 node.dispatchEvent(new WheelEvent('mousewheel', wheelDeltaX: -15, wheelDeltaY: -5)) - nextTick() 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)) - nextTick() 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)) - nextTick() expect(verticalScrollbarNode.scrollTop).toBe 5 describe "when the mousewheel event's target is a line", -> diff --git a/src/editor-component.coffee b/src/editor-component.coffee index f375fed9e..65fda5d1c 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -214,6 +214,12 @@ EditorComponent = React.createClass @updateRequested = false @forceUpdate() if @isMounted() + requestAnimationFrame: (fn) -> + prevPerformSyncUpdates = @performSyncUpdates + @performSyncUpdates = true + requestAnimationFrame(fn) + @performSyncUpdates = prevPerformSyncUpdates + getRenderedRowRange: -> {editor, lineOverdrawMargin} = @props [visibleStartRow, visibleEndRow] = editor.getVisibleRowRange() @@ -494,9 +500,8 @@ EditorComponent = React.createClass animationFramePending = @pendingScrollTop? @pendingScrollTop = scrollTop unless animationFramePending - requestAnimationFrame => + @requestAnimationFrame => @props.editor.setScrollTop(@pendingScrollTop) - @pendingScrollTop = null onHorizontalScroll: (scrollLeft) -> {editor} = @props @@ -506,7 +511,7 @@ EditorComponent = React.createClass animationFramePending = @pendingScrollLeft? @pendingScrollLeft = scrollLeft unless animationFramePending - requestAnimationFrame => + @requestAnimationFrame => @props.editor.setScrollLeft(@pendingScrollLeft) @pendingScrollLeft = null @@ -527,7 +532,7 @@ EditorComponent = React.createClass @clearMouseWheelScreenRowAfterDelay() unless animationFramePending - requestAnimationFrame => + @requestAnimationFrame => {editor} = @props editor.setScrollTop(editor.getScrollTop() + @pendingVerticalScrollDelta) editor.setScrollLeft(editor.getScrollLeft() + @pendingHorizontalScrollDelta)