diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 113a05620..850e2e9b8 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -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() diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 543212e81..51a5d21f4 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -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 diff --git a/src/gutter-component.coffee b/src/gutter-component.coffee index ede951657..e9eeddaf9 100644 --- a/src/gutter-component.coffee +++ b/src/gutter-component.coffee @@ -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 diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 14135089a..c4c2980ff 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -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