Merge pull request #3077 from atom/ns-fix-scroll-perf-regression

Fix performance regression caused by transparent backgrounds on lines and gutter
This commit is contained in:
Nathan Sobo
2014-07-24 17:37:54 -07:00
4 changed files with 63 additions and 13 deletions

View File

@@ -199,6 +199,16 @@ describe "EditorComponent", ->
atom.config.set("editor.showInvisibles", false)
expect(component.lineNodeForScreenRow(10).textContent).toBe nbsp
it "gives the lines div the same background color as the editor to improve GPU performance", ->
linesNode = componentNode.querySelector('.lines')
backgroundColor = getComputedStyle(wrapperNode).backgroundColor
expect(linesNode.style.backgroundColor).toBe backgroundColor
wrapperNode.style.backgroundColor = 'rgb(255, 0, 0)'
advanceClock(component.domPollingInterval)
runSetImmediateCallbacks()
expect(linesNode.style.backgroundColor).toBe 'rgb(255, 0, 0)'
describe "when showInvisibles is enabled", ->
invisibles = null
@@ -374,12 +384,6 @@ describe "EditorComponent", ->
expect(line2LeafNodes[2].textContent).toBe ' '
expect(line2LeafNodes[2].classList.contains('indent-guide')).toBe false
getLeafNodes = (node) ->
if node.children.length > 0
flatten(toArray(node.children).map(getLeafNodes))
else
[node]
describe "when the buffer contains null bytes", ->
it "excludes the null byte from character measurement", ->
editor.setText("a\0b")
@@ -401,6 +405,12 @@ describe "EditorComponent", ->
foldedLineNode = component.lineNodeForScreenRow(4)
expect(foldedLineNode.querySelector('.fold-marker')).toBeFalsy()
getLeafNodes = (node) ->
if node.children.length > 0
flatten(toArray(node.children).map(getLeafNodes))
else
[node]
describe "gutter rendering", ->
[gutter] = []
@@ -494,6 +504,18 @@ describe "EditorComponent", ->
runSetImmediateCallbacks()
expect(componentNode.querySelector('.line-numbers').offsetHeight).toBe componentNode.offsetHeight
it "applies the background color of the gutter or the editor to the line numbers to improve GPU performance", ->
gutterNode = componentNode.querySelector('.gutter')
lineNumbersNode = gutterNode.querySelector('.line-numbers')
{backgroundColor} = getComputedStyle(wrapperNode)
expect(lineNumbersNode.style.backgroundColor).toBe backgroundColor
# favor gutter color if it's assigned
gutterNode.style.backgroundColor = 'rgb(255, 0, 0)'
advanceClock(component.domPollingInterval)
runSetImmediateCallbacks()
expect(lineNumbersNode.style.backgroundColor).toBe 'rgb(255, 0, 0)'
describe "when the editor.showLineNumbers config is false", ->
it "doesn't render any line numbers", ->
expect(component.refs.gutter).toBeDefined()

View File

@@ -24,6 +24,8 @@ EditorComponent = React.createClass
visible: false
autoHeight: false
backgroundColor: null
gutterBackgroundColor: null
pendingScrollTop: null
pendingScrollLeft: null
selectOnMouseMove: false
@@ -91,12 +93,12 @@ EditorComponent = React.createClass
className += ' has-selection' if hasSelection
div {className, style, tabIndex: -1},
if not mini and showLineNumbers
if @shouldRenderGutter()
GutterComponent {
ref: 'gutter', onMouseDown: @onGutterMouseDown, lineDecorations,
defaultCharWidth, editor, renderedRowRange, maxLineNumberDigits, scrollViewHeight,
scrollTop, scrollHeight, lineHeightInPixels, @pendingChanges, mouseWheelScreenRow,
@useHardwareAcceleration, @performedInitialMeasurement
@useHardwareAcceleration, @performedInitialMeasurement, @backgroundColor, @gutterBackgroundColor
}
div ref: 'scrollView', className: 'scroll-view', onMouseDown: @onMouseDown,
@@ -118,7 +120,7 @@ EditorComponent = React.createClass
showIndentGuide, renderedRowRange, @pendingChanges, scrollTop, scrollLeft,
@scrollingVertically, scrollHeight, scrollWidth, mouseWheelScreenRow, invisibles,
@visible, scrollViewHeight, @scopedCharacterWidthsChangeCount, lineWidth, @useHardwareAcceleration,
placeholderText, @performedInitialMeasurement
placeholderText, @performedInitialMeasurement, @backgroundColor
}
ScrollbarComponent
@@ -157,6 +159,9 @@ EditorComponent = React.createClass
{editor} = @props
Math.max(1, Math.ceil(editor.getHeight() / editor.getLineHeightInPixels()))
shouldRenderGutter: ->
not @props.mini and @state.showLineNumbers
getInitialState: -> {}
getDefaultProps: ->
@@ -221,6 +226,7 @@ EditorComponent = React.createClass
@updatesPaused = true
@measureLineHeightAndDefaultCharWidth()
@measureHeightAndWidth()
@sampleBackgroundColors()
@measureScrollbars()
@props.editor.setVisible(true)
@updatesPaused = false
@@ -673,6 +679,7 @@ EditorComponent = React.createClass
onStylesheetsChanged: (stylesheet) ->
@refreshScrollbars() if @containsScrollbarSelector(stylesheet)
@sampleBackgroundColors()
@remeasureCharacterWidthsIfVisibleAfterNextUpdate = true
@requestUpdate() if @visible
@@ -772,6 +779,7 @@ EditorComponent = React.createClass
if @visible = @isVisible()
if wasVisible
@measureHeightAndWidth()
@sampleBackgroundColors()
else
@performInitialMeasurement()
@forceUpdate()
@@ -813,6 +821,21 @@ EditorComponent = React.createClass
clientWidth -= paddingLeft
editor.setWidth(clientWidth) if clientWidth > 0
sampleBackgroundColors: (suppressUpdate) ->
{parentView} = @props
{showLineNumbers} = @state
{backgroundColor} = getComputedStyle(parentView.element)
if backgroundColor isnt @backgroundColor
@backgroundColor = backgroundColor
@requestUpdate() unless suppressUpdate
if @shouldRenderGutter()
gutterBackgroundColor = getComputedStyle(@refs.gutter.getDOMNode()).backgroundColor
if gutterBackgroundColor isnt @gutterBackgroundColor
@gutterBackgroundColor = gutterBackgroundColor
@requestUpdate() unless suppressUpdate
measureLineHeightAndDefaultCharWidthIfNeeded: (prevState) ->
if not isEqualForProperties(prevState, @state, 'lineHeight', 'fontSize', 'fontFamily')
if @visible

View File

@@ -16,12 +16,16 @@ GutterComponent = React.createClass
measuredWidth: null
render: ->
{scrollHeight, scrollViewHeight, onMouseDown} = @props
{scrollHeight, scrollViewHeight, onMouseDown, backgroundColor, gutterBackgroundColor} = @props
if gutterBackgroundColor isnt 'rbga(0, 0, 0, 0)'
backgroundColor = gutterBackgroundColor
div className: 'gutter', onClick: @onClick, onMouseDown: onMouseDown,
div className: 'line-numbers', ref: 'lineNumbers', style:
height: Math.max(scrollHeight, scrollViewHeight)
WebkitTransform: @getTransform()
backgroundColor: backgroundColor
getTransform: ->
{scrollTop, useHardwareAcceleration} = @props
@@ -47,7 +51,7 @@ GutterComponent = React.createClass
shouldComponentUpdate: (newProps) ->
return true unless isEqualForProperties(newProps, @props,
'renderedRowRange', 'scrollTop', 'lineHeightInPixels', 'mouseWheelScreenRow', 'lineDecorations',
'scrollViewHeight', 'useHardwareAcceleration'
'scrollViewHeight', 'useHardwareAcceleration', 'backgroundColor', 'gutterBackgroundColor'
)
{renderedRowRange, pendingChanges, lineDecorations} = newProps

View File

@@ -19,12 +19,13 @@ LinesComponent = React.createClass
{performedInitialMeasurement} = @props
if performedInitialMeasurement
{editor, highlightDecorations, scrollHeight, scrollWidth, placeholderText} = @props
{editor, highlightDecorations, scrollHeight, scrollWidth, placeholderText, backgroundColor} = @props
{lineHeightInPixels, defaultCharWidth, scrollViewHeight, scopedCharacterWidthsChangeCount} = @props
style =
height: Math.max(scrollHeight, scrollViewHeight)
width: scrollWidth
WebkitTransform: @getTransform()
backgroundColor: backgroundColor
div {className: 'lines', style},
div className: 'placeholder-text', placeholderText if placeholderText?
@@ -50,7 +51,7 @@ LinesComponent = React.createClass
'renderedRowRange', 'lineDecorations', 'highlightDecorations', 'lineHeightInPixels', 'defaultCharWidth',
'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically', 'invisibles', 'visible',
'scrollViewHeight', 'mouseWheelScreenRow', 'scopedCharacterWidthsChangeCount', 'lineWidth', 'useHardwareAcceleration',
'placeholderText', 'performedInitialMeasurement'
'placeholderText', 'performedInitialMeasurement', 'backgroundColor'
)
{renderedRowRange, pendingChanges} = newProps