Merge pull request #2699 from atom/ns-react-fix-artifacts

Render highlights on their own layer to avoid GPU artifacts
This commit is contained in:
Nathan Sobo
2014-06-20 17:03:26 -06:00
9 changed files with 59 additions and 31 deletions

View File

@@ -462,12 +462,6 @@ describe "EditorComponent", ->
expect(component.lineNumberNodeForScreenRow(9).textContent).toBe "10"
expect(gutterNode.offsetWidth).toBe initialGutterWidth
it "renders the .line-numbers div at the full height of the editor even if it's taller than its content", ->
node.style.height = node.offsetHeight + 100 + 'px'
component.measureScrollView()
nextTick()
expect(node.querySelector('.line-numbers').offsetHeight).toBe node.offsetHeight
describe "fold decorations", ->
describe "rendering fold decorations", ->
it "adds the foldable class to line numbers when the line is foldable", ->

View File

@@ -8,6 +8,8 @@ GutterComponent = require './gutter-component'
InputComponent = require './input-component'
CursorsComponent = require './cursors-component'
LinesComponent = require './lines-component'
HighlightsComponent = require './highlights-component'
UnderlayerComponent = require './underlayer-component'
ScrollbarComponent = require './scrollbar-component'
ScrollbarCornerComponent = require './scrollbar-corner-component'
SubscriberMixin = require './subscriber-mixin'
@@ -82,8 +84,8 @@ EditorComponent = React.createClass
div className: className, style: {fontSize, lineHeight, fontFamily}, tabIndex: -1,
GutterComponent {
ref: 'gutter', onMouseDown: @onGutterMouseDown, onWidthChanged: @onGutterWidthChanged,
lineDecorations, defaultCharWidth, editor, renderedRowRange, maxLineNumberDigits, scrollViewHeight,
scrollTop, scrollHeight, lineHeightInPixels, @pendingChanges, mouseWheelScreenRow
lineDecorations, defaultCharWidth, editor, renderedRowRange, maxLineNumberDigits,
scrollTop, lineHeightInPixels, @pendingChanges, mouseWheelScreenRow
}
div ref: 'scrollView', className: 'scroll-view', onMouseDown: @onMouseDown,
@@ -103,7 +105,14 @@ EditorComponent = React.createClass
editor, lineHeightInPixels, defaultCharWidth, lineDecorations, highlightDecorations,
showIndentGuide, renderedRowRange, @pendingChanges, scrollTop, scrollLeft,
@scrollingVertically, scrollHeight, scrollWidth, mouseWheelScreenRow, invisibles,
visible, scrollViewHeight, @scopedCharacterWidthsChangeCount
visible, scrollViewHeight
}
HighlightsComponent {
editor, scrollTop, scrollLeft, scrollHeight, scrollWidth, highlightDecorations, lineHeightInPixels,
defaultCharWidth, @scopedCharacterWidthsChangeCount
}
UnderlayerComponent {
scrollTop, scrollLeft, scrollHeight, scrollWidth
}
ScrollbarComponent

View File

@@ -443,7 +443,8 @@ class Editor extends Model
getText: -> @buffer.getText()
# Public: Replaces the entire contents of the buffer with the given {String}.
setText: (text) -> @buffer.setText(text)
setText: (text) ->
@buffer.setText(text)
# Get the text in the given {Range}.
#

View File

@@ -15,13 +15,10 @@ GutterComponent = React.createClass
measuredWidth: null
render: ->
{scrollHeight, scrollViewHeight, scrollTop, onMouseDown} = @props
{scrollTop, onMouseDown} = @props
div className: 'gutter', onClick: @onClick, onMouseDown: onMouseDown,
# The line-numbers div must have the 'editor-colors' class so it has an
# opaque background to avoid sub-pixel anti-aliasing problems on the GPU
div className: 'gutter line-numbers editor-colors', ref: 'lineNumbers', style:
height: Math.max(scrollHeight, scrollViewHeight)
div className: 'line-numbers', ref: 'lineNumbers', style:
WebkitTransform: "translate3d(0px, #{-scrollTop}px, 0px)"
componentWillMount: ->
@@ -38,8 +35,7 @@ GutterComponent = React.createClass
# visible row range.
shouldComponentUpdate: (newProps) ->
return true unless isEqualForProperties(newProps, @props,
'renderedRowRange', 'scrollTop', 'lineHeightInPixels', 'mouseWheelScreenRow', 'lineDecorations',
'scrollViewHeight'
'renderedRowRange', 'scrollTop', 'lineHeightInPixels', 'mouseWheelScreenRow', 'lineDecorations'
)
{renderedRowRange, pendingChanges, lineDecorations} = newProps

View File

@@ -8,7 +8,16 @@ HighlightsComponent = React.createClass
displayName: 'HighlightsComponent'
render: ->
div className: 'highlights', @renderHighlights()
if @isMounted()
{scrollTop, scrollLeft, scrollHeight, scrollWidth} = @props
style =
height: scrollHeight
width: scrollWidth
WebkitTransform: "translate3d(#{-scrollLeft}px, #{-scrollTop}px, 0px)"
div {className: 'highlights', style},
@renderHighlights() if @isMounted()
renderHighlights: ->
{editor, highlightDecorations, lineHeightInPixels} = @props
@@ -21,4 +30,7 @@ HighlightsComponent = React.createClass
highlightComponents
shouldComponentUpdate: (newProps) ->
not isEqualForProperties(newProps, @props, 'highlightDecorations', 'lineHeightInPixels', 'defaultCharWidth', 'scopedCharacterWidthsChangeCount')
not isEqualForProperties(newProps, @props,
'scrollTop', 'scrollLeft', 'highlightDecorations', 'lineHeightInPixels',
'defaultCharWidth', 'scopedCharacterWidthsChangeCount'
)

View File

@@ -4,8 +4,6 @@ React = require 'react-atom-fork'
{debounce, isEqual, isEqualForProperties, multiplyString, toArray} = require 'underscore-plus'
{$$} = require 'space-pen'
HighlightsComponent = require './highlights-component'
DummyLineNode = $$(-> @div className: 'line', style: 'position: absolute; visibility: hidden;', => @span 'x')[0]
AcceptFilter = {acceptNode: -> NodeFilter.FILTER_ACCEPT}
WrapperDiv = document.createElement('div')
@@ -17,16 +15,13 @@ LinesComponent = React.createClass
render: ->
if @isMounted()
{editor, highlightDecorations, scrollTop, scrollLeft, scrollHeight, scrollWidth} = @props
{lineHeightInPixels, defaultCharWidth, scrollViewHeight, scopedCharacterWidthsChangeCount} = @props
{lineHeightInPixels, defaultCharWidth, scrollViewHeight} = @props
style =
height: Math.max(scrollHeight, scrollViewHeight)
width: scrollWidth
WebkitTransform: "translate3d(#{-scrollLeft}px, #{-scrollTop}px, 0px)"
# The lines div must have the 'editor-colors' class so it has an opaque
# background to avoid sub-pixel anti-aliasing problems on the GPU
div {className: 'lines editor-colors', style},
HighlightsComponent({editor, highlightDecorations, lineHeightInPixels, defaultCharWidth, scopedCharacterWidthsChangeCount}) if @isMounted()
div {className: 'lines', style}
componentWillMount: ->
@measuredLines = new WeakSet
@@ -39,7 +34,7 @@ LinesComponent = React.createClass
return true unless isEqualForProperties(newProps, @props,
'renderedRowRange', 'lineDecorations', 'highlightDecorations', 'lineHeightInPixels', 'defaultCharWidth',
'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically', 'invisibles', 'visible',
'scrollViewHeight', 'mouseWheelScreenRow', 'scopedCharacterWidthsChangeCount'
'scrollViewHeight', 'mouseWheelScreenRow'
)
{renderedRowRange, pendingChanges} = newProps

View File

@@ -34,7 +34,7 @@ class ReactEditorView extends View
node = @component.getDOMNode()
@scrollView = $(node).find('.scroll-view')
@underlayer = $(node).find('.highlights').addClass('underlayer')
@underlayer = $(node).find('.underlayer')
@overlayer = $(node).find('.lines').addClass('overlayer')
@hiddenInput = $(node).find('.hidden-input')

View File

@@ -0,0 +1,20 @@
React = require 'react-atom-fork'
{div} = require 'reactionary-atom-fork'
{isEqualForProperties} = require 'underscore-plus'
module.exports =
UnderlayerComponent = React.createClass
displayName: 'UnderlayerComponent'
render: ->
if @isMounted()
{scrollTop, scrollLeft, scrollHeight, scrollWidth} = @props
style =
height: scrollHeight
width: scrollWidth
WebkitTransform: "translate3d(#{-scrollLeft}px, #{-scrollTop}px, 0px)"
div {className: 'underlayer', style}
shouldComponentUpdate: (newProps) ->
not isEqualForProperties(@props, newProps, 'scrollTop', 'scrollLeft', 'scrollHeight', 'scrollWidth')

View File

@@ -6,13 +6,14 @@
.underlayer {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.highlights {
z-index: -2;
}
.lines {
.lines, .highlights, .underlayer {
min-width: 100%;
}