Take cursors off the GPU and position them on the lines layer

The compositor overhead is not worth it.
This commit is contained in:
Nathan Sobo 2014-07-27 11:37:36 -06:00
parent 444c18be34
commit 393552a4b6
5 changed files with 32 additions and 37 deletions

View File

@ -603,7 +603,7 @@ describe "EditorComponent", ->
expect(cursorNodes.length).toBe 1
expect(cursorNodes[0].offsetHeight).toBe lineHeightInPixels
expect(cursorNodes[0].offsetWidth).toBe charWidth
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate3d(#{5 * charWidth}px, #{0 * lineHeightInPixels}px, 0px)"
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{5 * charWidth}px, #{0 * lineHeightInPixels}px)"
cursor2 = editor.addCursorAtScreenPosition([8, 11])
cursor3 = editor.addCursorAtScreenPosition([4, 10])
@ -612,8 +612,8 @@ describe "EditorComponent", ->
cursorNodes = componentNode.querySelectorAll('.cursor')
expect(cursorNodes.length).toBe 2
expect(cursorNodes[0].offsetTop).toBe 0
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate3d(#{5 * charWidth}px, #{0 * lineHeightInPixels}px, 0px)"
expect(cursorNodes[1].style['-webkit-transform']).toBe "translate3d(#{10 * charWidth}px, #{4 * lineHeightInPixels}px, 0px)"
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{5 * charWidth}px, #{0 * lineHeightInPixels}px)"
expect(cursorNodes[1].style['-webkit-transform']).toBe "translate(#{10 * charWidth}px, #{4 * lineHeightInPixels}px)"
verticalScrollbarNode.scrollTop = 4.5 * lineHeightInPixels
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
@ -624,14 +624,14 @@ describe "EditorComponent", ->
cursorNodes = componentNode.querySelectorAll('.cursor')
expect(cursorNodes.length).toBe 2
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate3d(#{(11 - 3.5) * charWidth}px, #{(8 - 4.5) * lineHeightInPixels}px, 0px)"
expect(cursorNodes[1].style['-webkit-transform']).toBe "translate3d(#{(10 - 3.5) * charWidth}px, #{(4 - 4.5) * lineHeightInPixels}px, 0px)"
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{11 * charWidth}px, #{8 * lineHeightInPixels}px)"
expect(cursorNodes[1].style['-webkit-transform']).toBe "translate(#{10 * charWidth}px, #{4 * lineHeightInPixels}px)"
cursor3.destroy()
nextAnimationFrame()
cursorNodes = componentNode.querySelectorAll('.cursor')
expect(cursorNodes.length).toBe 1
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate3d(#{(11 - 3.5) * charWidth}px, #{(6 - 2.5) * lineHeightInPixels}px, 0px)"
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{11 * charWidth}px, #{8 * lineHeightInPixels}px)"
it "accounts for character widths when positioning cursors", ->
atom.config.set('editor.fontFamily', 'sans-serif')
@ -715,21 +715,21 @@ describe "EditorComponent", ->
cursorNodes = componentNode.querySelectorAll('.cursor')
expect(cursorNodes.length).toBe 1
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate3d(#{8 * charWidth}px, #{6 * lineHeightInPixels}px, 0px)"
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{8 * charWidth}px, #{6 * lineHeightInPixels}px)"
it "updates cursor positions when the line height changes", ->
editor.setCursorBufferPosition([1, 10])
component.setLineHeight(2)
nextAnimationFrame()
cursorNode = componentNode.querySelector('.cursor')
expect(cursorNode.style['-webkit-transform']).toBe "translate3d(#{10 * editor.getDefaultCharWidth()}px, #{editor.getLineHeightInPixels()}px, 0px)"
expect(cursorNode.style['-webkit-transform']).toBe "translate(#{10 * editor.getDefaultCharWidth()}px, #{editor.getLineHeightInPixels()}px)"
it "updates cursor positions when the font size changes", ->
editor.setCursorBufferPosition([1, 10])
component.setFontSize(10)
nextAnimationFrame()
cursorNode = componentNode.querySelector('.cursor')
expect(cursorNode.style['-webkit-transform']).toBe "translate3d(#{10 * editor.getDefaultCharWidth()}px, #{editor.getLineHeightInPixels()}px, 0px)"
expect(cursorNode.style['-webkit-transform']).toBe "translate(#{10 * editor.getDefaultCharWidth()}px, #{editor.getLineHeightInPixels()}px)"
it "updates cursor positions when the font family changes", ->
editor.setCursorBufferPosition([1, 10])
@ -738,7 +738,7 @@ describe "EditorComponent", ->
cursorNode = componentNode.querySelector('.cursor')
{left} = editor.pixelPositionForScreenPosition([1, 10])
expect(cursorNode.style['-webkit-transform']).toBe "translate3d(#{left}px, #{editor.getLineHeightInPixels()}px, 0px)"
expect(cursorNode.style['-webkit-transform']).toBe "translate(#{left}px, #{editor.getLineHeightInPixels()}px)"
describe "selection rendering", ->
[scrollViewNode, scrollViewClientLeft] = []
@ -2002,7 +2002,7 @@ describe "EditorComponent", ->
editor.setCursorBufferPosition([0, Infinity])
nextAnimationFrame()
wrapperView.show()
expect(componentNode.querySelector('.cursor').style['-webkit-transform']).toBe "translate3d(#{9 * charWidth}px, 0px, 0px)"
expect(componentNode.querySelector('.cursor').style['-webkit-transform']).toBe "translate(#{9 * charWidth}px, 0px)"
describe "soft wrapping", ->
beforeEach ->

View File

@ -8,22 +8,11 @@ CursorComponent = React.createClass
render: ->
{pixelRect, defaultCharWidth} = @props
{height, width} = pixelRect
{top, left, height, width} = pixelRect
width = defaultCharWidth if width is 0
WebkitTransform = @getTransform()
WebkitTransform = "translate(#{left}px, #{top}px)"
div className: 'cursor', style: {height, width, WebkitTransform}
getTransform: ->
{pixelRect, scrollTop, scrollLeft, useHardwareAcceleration} = @props
{top, left} = pixelRect
top -= scrollTop
left -= scrollLeft
if useHardwareAcceleration
"translate3d(#{left}px, #{top}px, 0px)"
else
"translate(#{left}px, #{top}px)"
shouldComponentUpdate: (newProps) ->
not isEqualForProperties(newProps, @props, 'pixelRect', 'scrollTop', 'scrollLeft', 'defaultCharWidth')
not isEqualForProperties(newProps, @props, 'pixelRect', 'defaultCharWidth')

View File

@ -12,7 +12,7 @@ CursorsComponent = React.createClass
cursorBlinkIntervalHandle: null
render: ->
{performedInitialMeasurement, cursorPixelRects, scrollTop, scrollLeft, defaultCharWidth, useHardwareAcceleration} = @props
{performedInitialMeasurement, cursorPixelRects, defaultCharWidth} = @props
{blinkOff} = @state
className = 'cursors'
@ -21,7 +21,7 @@ CursorsComponent = React.createClass
div {className},
if performedInitialMeasurement
for key, pixelRect of cursorPixelRects
CursorComponent({key, pixelRect, scrollTop, scrollLeft, defaultCharWidth, useHardwareAcceleration})
CursorComponent({key, pixelRect, defaultCharWidth})
getInitialState: ->
blinkOff: false

View File

@ -6,7 +6,6 @@ scrollbarStyle = require 'scrollbar-style'
GutterComponent = require './gutter-component'
InputComponent = require './input-component'
CursorsComponent = require './cursors-component'
LinesComponent = require './lines-component'
ScrollbarComponent = require './scrollbar-component'
ScrollbarCornerComponent = require './scrollbar-corner-component'
@ -107,18 +106,14 @@ EditorComponent = React.createClass
onFocus: @onInputFocused
onBlur: @onInputBlurred
CursorsComponent {
scrollTop, scrollLeft, cursorPixelRects, cursorBlinkPeriod, cursorBlinkResumeDelay,
lineHeightInPixels, defaultCharWidth, @scopedCharacterWidthsChangeCount, @useHardwareAcceleration,
@performedInitialMeasurement
}
LinesComponent {
ref: 'lines',
editor, lineHeightInPixels, defaultCharWidth, lineDecorations, highlightDecorations,
showIndentGuide, renderedRowRange, @pendingChanges, scrollTop, scrollLeft,
@scrollingVertically, scrollHeight, scrollWidth, mouseWheelScreenRow, invisibles,
@visible, scrollViewHeight, @scopedCharacterWidthsChangeCount, lineWidth, @useHardwareAcceleration,
placeholderText, @performedInitialMeasurement, @backgroundColor
placeholderText, @performedInitialMeasurement, @backgroundColor, cursorPixelRects,
cursorBlinkPeriod, cursorBlinkResumeDelay
}
ScrollbarComponent

View File

@ -5,6 +5,7 @@ React = require 'react-atom-fork'
{$$} = require 'space-pen'
Decoration = require './decoration'
CursorsComponent = require './cursors-component'
HighlightsComponent = require './highlights-component'
DummyLineNode = $$(-> @div className: 'line', style: 'position: absolute; visibility: hidden;', => @span 'x')[0]
@ -16,11 +17,12 @@ LinesComponent = React.createClass
displayName: 'LinesComponent'
render: ->
{performedInitialMeasurement} = @props
{performedInitialMeasurement, cursorBlinkPeriod, cursorBlinkResumeDelay} = @props
if performedInitialMeasurement
{editor, highlightDecorations, scrollHeight, scrollWidth, placeholderText, backgroundColor} = @props
{lineHeightInPixels, defaultCharWidth, scrollViewHeight, scopedCharacterWidthsChangeCount} = @props
{scrollTop, scrollLeft, cursorPixelRects} = @props
style =
height: Math.max(scrollHeight, scrollViewHeight)
width: scrollWidth
@ -29,7 +31,16 @@ LinesComponent = React.createClass
div {className: 'lines', style},
div className: 'placeholder-text', placeholderText if placeholderText?
HighlightsComponent({editor, highlightDecorations, lineHeightInPixels, defaultCharWidth, scopedCharacterWidthsChangeCount, performedInitialMeasurement})
CursorsComponent {
cursorPixelRects, cursorBlinkPeriod, cursorBlinkResumeDelay, lineHeightInPixels,
defaultCharWidth, scopedCharacterWidthsChangeCount, performedInitialMeasurement
}
HighlightsComponent {
editor, highlightDecorations, lineHeightInPixels, defaultCharWidth,
scopedCharacterWidthsChangeCount, performedInitialMeasurement
}
getTransform: ->
{scrollTop, scrollLeft, useHardwareAcceleration} = @props
@ -51,7 +62,7 @@ LinesComponent = React.createClass
'renderedRowRange', 'lineDecorations', 'highlightDecorations', 'lineHeightInPixels', 'defaultCharWidth',
'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically', 'invisibles', 'visible',
'scrollViewHeight', 'mouseWheelScreenRow', 'scopedCharacterWidthsChangeCount', 'lineWidth', 'useHardwareAcceleration',
'placeholderText', 'performedInitialMeasurement', 'backgroundColor'
'placeholderText', 'performedInitialMeasurement', 'backgroundColor', 'cursorPixelRects'
)
{renderedRowRange, pendingChanges} = newProps