mirror of
https://github.com/atom/atom.git
synced 2026-01-23 13:58:08 -05:00
Merge pull request #8009 from atom/jl-ns-battery-life
Change Document Polling from Time Interval to Event
This commit is contained in:
@@ -280,6 +280,7 @@ describe "TextEditorComponent", ->
|
||||
expect(tileNode.style.backgroundColor).toBe(backgroundColor)
|
||||
|
||||
wrapperNode.style.backgroundColor = 'rgb(255, 0, 0)'
|
||||
atom.views.performDocumentPoll()
|
||||
|
||||
advanceClock(atom.views.documentPollingInterval)
|
||||
nextAnimationFrame()
|
||||
@@ -701,7 +702,8 @@ describe "TextEditorComponent", ->
|
||||
|
||||
# favor gutter color if it's assigned
|
||||
gutterNode.style.backgroundColor = 'rgb(255, 0, 0)'
|
||||
advanceClock(atom.views.documentPollingInterval)
|
||||
atom.views.performDocumentPoll()
|
||||
|
||||
nextAnimationFrame()
|
||||
expect(lineNumbersNode.style.backgroundColor).toBe 'rgb(255, 0, 0)'
|
||||
for tileNode in lineNumbersNode.querySelectorAll(".tile")
|
||||
@@ -800,6 +802,7 @@ describe "TextEditorComponent", ->
|
||||
|
||||
describe "when the component is destroyed", ->
|
||||
it "stops listening for folding events", ->
|
||||
nextAnimationFrame()
|
||||
component.destroy()
|
||||
|
||||
lineNumber = component.lineNumberNodeForScreenRow(1)
|
||||
@@ -824,6 +827,8 @@ describe "TextEditorComponent", ->
|
||||
expect(lineNumberHasClass(1, 'folded')).toBe false
|
||||
|
||||
it "does not fold when the line number componentNode is clicked", ->
|
||||
nextAnimationFrame() # clear pending frame request
|
||||
|
||||
lineNumber = component.lineNumberNodeForScreenRow(1)
|
||||
lineNumber.dispatchEvent(buildClickEvent(lineNumber))
|
||||
expect(nextAnimationFrame).toBe noAnimationFrame
|
||||
@@ -2600,7 +2605,7 @@ describe "TextEditorComponent", ->
|
||||
expect(componentNode.querySelectorAll('.line').length).toBe 0
|
||||
|
||||
hiddenParent.style.display = 'block'
|
||||
advanceClock(atom.views.documentPollingInterval)
|
||||
atom.views.performDocumentPoll()
|
||||
|
||||
expect(componentNode.querySelectorAll('.line').length).toBeGreaterThan 0
|
||||
|
||||
@@ -2710,13 +2715,13 @@ describe "TextEditorComponent", ->
|
||||
expect(parseInt(newHeight)).toBeLessThan wrapperNode.offsetHeight
|
||||
wrapperNode.style.height = newHeight
|
||||
|
||||
advanceClock(atom.views.documentPollingInterval)
|
||||
atom.views.performDocumentPoll()
|
||||
nextAnimationFrame()
|
||||
expect(componentNode.querySelectorAll('.line')).toHaveLength(6)
|
||||
|
||||
gutterWidth = componentNode.querySelector('.gutter').offsetWidth
|
||||
componentNode.style.width = gutterWidth + 14 * charWidth + editor.getVerticalScrollbarWidth() + 'px'
|
||||
advanceClock(atom.views.documentPollingInterval)
|
||||
atom.views.performDocumentPoll()
|
||||
nextAnimationFrame()
|
||||
expect(componentNode.querySelector('.line').textContent).toBe "var quicksort "
|
||||
|
||||
@@ -2725,7 +2730,7 @@ describe "TextEditorComponent", ->
|
||||
scrollViewNode.style.paddingLeft = 20 + 'px'
|
||||
componentNode.style.width = 30 * charWidth + 'px'
|
||||
|
||||
advanceClock(atom.views.documentPollingInterval)
|
||||
atom.views.performDocumentPoll()
|
||||
nextAnimationFrame()
|
||||
|
||||
expect(component.lineNodeForScreenRow(0).textContent).toBe "var quicksort = "
|
||||
|
||||
@@ -7,6 +7,9 @@ describe "ViewRegistry", ->
|
||||
beforeEach ->
|
||||
registry = new ViewRegistry
|
||||
|
||||
afterEach ->
|
||||
registry.clearDocumentRequests()
|
||||
|
||||
describe "::getView(object)", ->
|
||||
describe "when passed a DOM node", ->
|
||||
it "returns the given DOM node", ->
|
||||
@@ -158,13 +161,13 @@ describe "ViewRegistry", ->
|
||||
registry.updateDocument -> events.push('write')
|
||||
registry.readDocument -> events.push('read')
|
||||
|
||||
advanceClock(registry.documentPollingInterval)
|
||||
window.dispatchEvent(new UIEvent('resize'))
|
||||
expect(events).toEqual []
|
||||
|
||||
frameRequests[0]()
|
||||
expect(events).toEqual ['write', 'read', 'poll']
|
||||
|
||||
advanceClock(registry.documentPollingInterval)
|
||||
window.dispatchEvent(new UIEvent('resize'))
|
||||
expect(events).toEqual ['write', 'read', 'poll', 'poll']
|
||||
|
||||
it "polls the document after updating when ::pollAfterNextUpdate() has been called", ->
|
||||
@@ -183,25 +186,51 @@ describe "ViewRegistry", ->
|
||||
expect(events).toEqual ['write', 'read', 'poll']
|
||||
|
||||
describe "::pollDocument(fn)", ->
|
||||
it "calls all registered reader functions on an interval until they are disabled via a returned disposable", ->
|
||||
spyOn(window, 'setInterval').andCallFake(fakeSetInterval)
|
||||
[testElement, testStyleSheet, disposable1, disposable2, events] = []
|
||||
|
||||
beforeEach ->
|
||||
testElement = document.createElement('div')
|
||||
testStyleSheet = document.createElement('style')
|
||||
testStyleSheet.textContent = 'body {}'
|
||||
jasmineContent = document.getElementById('jasmine-content')
|
||||
jasmineContent.appendChild(testElement)
|
||||
jasmineContent.appendChild(testStyleSheet)
|
||||
|
||||
events = []
|
||||
disposable1 = registry.pollDocument -> events.push('poll 1')
|
||||
disposable2 = registry.pollDocument -> events.push('poll 2')
|
||||
|
||||
it "calls all registered polling functions after document or stylesheet changes until they are disabled via a returned disposable", ->
|
||||
jasmine.useRealClock()
|
||||
expect(events).toEqual []
|
||||
|
||||
advanceClock(registry.documentPollingInterval)
|
||||
testElement.style.width = '400px'
|
||||
|
||||
waitsFor "events to occur in response to DOM mutation", -> events.length > 0
|
||||
|
||||
runs ->
|
||||
expect(events).toEqual ['poll 1', 'poll 2']
|
||||
events.length = 0
|
||||
|
||||
testStyleSheet.textContent = 'body {color: #333;}'
|
||||
|
||||
waitsFor "events to occur in reponse to style sheet mutation", -> events.length > 0
|
||||
|
||||
runs ->
|
||||
expect(events).toEqual ['poll 1', 'poll 2']
|
||||
events.length = 0
|
||||
|
||||
disposable1.dispose()
|
||||
testElement.style.color = '#fff'
|
||||
|
||||
waitsFor "more events to occur in response to DOM mutation", -> events.length > 0
|
||||
|
||||
runs ->
|
||||
expect(events).toEqual ['poll 2']
|
||||
|
||||
it "calls all registered polling functions when the window resizes", ->
|
||||
expect(events).toEqual []
|
||||
|
||||
window.dispatchEvent(new UIEvent('resize'))
|
||||
|
||||
expect(events).toEqual ['poll 1', 'poll 2']
|
||||
|
||||
advanceClock(registry.documentPollingInterval)
|
||||
expect(events).toEqual ['poll 1', 'poll 2', 'poll 1', 'poll 2']
|
||||
|
||||
disposable1.dispose()
|
||||
advanceClock(registry.documentPollingInterval)
|
||||
expect(events).toEqual ['poll 1', 'poll 2', 'poll 1', 'poll 2', 'poll 2']
|
||||
|
||||
disposable2.dispose()
|
||||
advanceClock(registry.documentPollingInterval)
|
||||
expect(events).toEqual ['poll 1', 'poll 2', 'poll 1', 'poll 2', 'poll 2']
|
||||
|
||||
@@ -107,7 +107,6 @@ class TextEditorComponent
|
||||
@disposables.dispose()
|
||||
@presenter.destroy()
|
||||
@gutterContainerComponent?.destroy()
|
||||
window.removeEventListener 'resize', @requestHeightAndWidthMeasurement
|
||||
|
||||
getDomNode: ->
|
||||
@domNode
|
||||
@@ -224,7 +223,6 @@ class TextEditorComponent
|
||||
@domNode.addEventListener 'textInput', @onTextInput
|
||||
@scrollViewNode.addEventListener 'mousedown', @onMouseDown
|
||||
@scrollViewNode.addEventListener 'scroll', @onScrollViewScroll
|
||||
window.addEventListener 'resize', @requestHeightAndWidthMeasurement
|
||||
|
||||
@listenForIMEEvents()
|
||||
@trackSelectionClipboard() if process.platform is 'linux'
|
||||
@@ -589,15 +587,6 @@ class TextEditorComponent
|
||||
else
|
||||
@wasVisible = false
|
||||
|
||||
requestHeightAndWidthMeasurement: =>
|
||||
return if @heightAndWidthMeasurementRequested
|
||||
|
||||
@heightAndWidthMeasurementRequested = true
|
||||
requestAnimationFrame =>
|
||||
@heightAndWidthMeasurementRequested = false
|
||||
@measureDimensions()
|
||||
@measureWindowSize()
|
||||
|
||||
# Measure explicitly-styled height and width and relay them to the model. If
|
||||
# these values aren't explicitly styled, we assume the editor is unconstrained
|
||||
# and use the scrollHeight / scrollWidth as its height and width in
|
||||
|
||||
@@ -1386,12 +1386,15 @@ class TextEditorPresenter
|
||||
@emitDidUpdateState()
|
||||
|
||||
startBlinkingCursors: ->
|
||||
unless @toggleCursorBlinkHandle
|
||||
unless @isCursorBlinking()
|
||||
@state.content.cursorsVisible = true
|
||||
@toggleCursorBlinkHandle = setInterval(@toggleCursorBlink.bind(this), @getCursorBlinkPeriod() / 2)
|
||||
|
||||
isCursorBlinking: ->
|
||||
@toggleCursorBlinkHandle?
|
||||
|
||||
stopBlinkingCursors: (visible) ->
|
||||
if @toggleCursorBlinkHandle
|
||||
if @isCursorBlinking()
|
||||
@state.content.cursorsVisible = visible
|
||||
clearInterval(@toggleCursorBlinkHandle)
|
||||
@toggleCursorBlinkHandle = null
|
||||
@@ -1401,7 +1404,8 @@ class TextEditorPresenter
|
||||
@emitDidUpdateState()
|
||||
|
||||
pauseCursorBlinking: ->
|
||||
@stopBlinkingCursors(true)
|
||||
@startBlinkingCursorsAfterDelay ?= _.debounce(@startBlinkingCursors, @getCursorBlinkResumeDelay())
|
||||
@startBlinkingCursorsAfterDelay()
|
||||
@emitDidUpdateState()
|
||||
if @isCursorBlinking()
|
||||
@stopBlinkingCursors(true)
|
||||
@startBlinkingCursorsAfterDelay ?= _.debounce(@startBlinkingCursors, @getCursorBlinkResumeDelay())
|
||||
@startBlinkingCursorsAfterDelay()
|
||||
@emitDidUpdateState()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{find} = require 'underscore-plus'
|
||||
Grim = require 'grim'
|
||||
{Disposable} = require 'event-kit'
|
||||
_ = require 'underscore-plus'
|
||||
|
||||
# Essential: `ViewRegistry` handles the association between model and view
|
||||
# types in Atom. We call this association a View Provider. As in, for a given
|
||||
@@ -42,11 +43,11 @@ Grim = require 'grim'
|
||||
# ```
|
||||
module.exports =
|
||||
class ViewRegistry
|
||||
documentPollingInterval: 200
|
||||
documentUpdateRequested: false
|
||||
documentReadInProgress: false
|
||||
performDocumentPollAfterUpdate: false
|
||||
pollIntervalHandle: null
|
||||
debouncedPerformDocumentPoll: null
|
||||
minimumPollInterval: 200
|
||||
|
||||
constructor: ->
|
||||
@views = new WeakMap
|
||||
@@ -55,6 +56,9 @@ class ViewRegistry
|
||||
@documentReaders = []
|
||||
@documentPollers = []
|
||||
|
||||
@observer = new MutationObserver(@requestDocumentPoll)
|
||||
@debouncedPerformDocumentPoll = _.throttle(@performDocumentPoll, @minimumPollInterval).bind(this)
|
||||
|
||||
# Essential: Add a provider that will be used to construct views in the
|
||||
# workspace's view layer based on model objects in its model layer.
|
||||
#
|
||||
@@ -208,14 +212,19 @@ class ViewRegistry
|
||||
writer() while writer = @documentWriters.shift()
|
||||
|
||||
startPollingDocument: ->
|
||||
@pollIntervalHandle = window.setInterval(@performDocumentPoll, @documentPollingInterval)
|
||||
window.addEventListener('resize', @requestDocumentPoll)
|
||||
@observer.observe(document, {subtree: true, childList: true, attributes: true})
|
||||
|
||||
stopPollingDocument: ->
|
||||
window.clearInterval(@pollIntervalHandle)
|
||||
window.removeEventListener('resize', @requestDocumentPoll)
|
||||
@observer.disconnect()
|
||||
|
||||
performDocumentPoll: =>
|
||||
requestDocumentPoll: =>
|
||||
if @documentUpdateRequested
|
||||
@performDocumentPollAfterUpdate = true
|
||||
else
|
||||
poller() for poller in @documentPollers
|
||||
return
|
||||
@debouncedPerformDocumentPoll()
|
||||
|
||||
performDocumentPoll: ->
|
||||
poller() for poller in @documentPollers
|
||||
return
|
||||
|
||||
@@ -12,7 +12,6 @@ class WorkspaceElement extends HTMLElement
|
||||
|
||||
createdCallback: ->
|
||||
@subscriptions = new CompositeDisposable
|
||||
@initializeGlobalTextEditorStyleSheet()
|
||||
@initializeContent()
|
||||
@observeScrollbarStyle()
|
||||
@observeTextEditorFontConfig()
|
||||
@@ -26,10 +25,6 @@ class WorkspaceElement extends HTMLElement
|
||||
@subscriptions.dispose()
|
||||
@model.destroy()
|
||||
|
||||
initializeGlobalTextEditorStyleSheet: ->
|
||||
atom.styles.addStyleSheet('atom-text-editor {}', sourcePath: 'global-text-editor-styles')
|
||||
@globalTextEditorStyleSheet = document.head.querySelector('style[source-path="global-text-editor-styles"]').sheet
|
||||
|
||||
initializeContent: ->
|
||||
@classList.add 'workspace'
|
||||
@setAttribute 'tabindex', -1
|
||||
@@ -54,9 +49,20 @@ class WorkspaceElement extends HTMLElement
|
||||
@classList.add("scrollbars-visible-when-scrolling")
|
||||
|
||||
observeTextEditorFontConfig: ->
|
||||
@subscriptions.add atom.config.observe 'editor.fontSize', @setTextEditorFontSize.bind(this)
|
||||
@subscriptions.add atom.config.observe 'editor.fontFamily', @setTextEditorFontFamily.bind(this)
|
||||
@subscriptions.add atom.config.observe 'editor.lineHeight', @setTextEditorLineHeight.bind(this)
|
||||
@updateGlobalTextEditorStyleSheet()
|
||||
@subscriptions.add atom.config.onDidChange 'editor.fontSize', @updateGlobalTextEditorStyleSheet.bind(this)
|
||||
@subscriptions.add atom.config.onDidChange 'editor.fontFamily', @updateGlobalTextEditorStyleSheet.bind(this)
|
||||
@subscriptions.add atom.config.onDidChange 'editor.lineHeight', @updateGlobalTextEditorStyleSheet.bind(this)
|
||||
|
||||
updateGlobalTextEditorStyleSheet: ->
|
||||
styleSheetSource = """
|
||||
atom-text-editor {
|
||||
font-size: #{atom.config.get('editor.fontSize')}px;
|
||||
font-family: #{atom.config.get('editor.fontFamily')};
|
||||
line-height: #{atom.config.get('editor.lineHeight')};
|
||||
}
|
||||
"""
|
||||
atom.styles.addStyleSheet(styleSheetSource, sourcePath: 'global-text-editor-styles')
|
||||
|
||||
createSpacePenShim: ->
|
||||
WorkspaceView ?= require './workspace-view'
|
||||
@@ -87,20 +93,6 @@ class WorkspaceElement extends HTMLElement
|
||||
|
||||
getModel: -> @model
|
||||
|
||||
setTextEditorFontSize: (fontSize) ->
|
||||
@updateGlobalEditorStyle('font-size', fontSize + 'px')
|
||||
|
||||
setTextEditorFontFamily: (fontFamily) ->
|
||||
@updateGlobalEditorStyle('font-family', fontFamily)
|
||||
|
||||
setTextEditorLineHeight: (lineHeight) ->
|
||||
@updateGlobalEditorStyle('line-height', lineHeight)
|
||||
|
||||
updateGlobalEditorStyle: (property, value) ->
|
||||
editorRule = @globalTextEditorStyleSheet.cssRules[0]
|
||||
editorRule.style[property] = value
|
||||
atom.themes.emitter.emit 'did-update-stylesheet', @globalTextEditorStyleSheet
|
||||
|
||||
handleFocus: (event) ->
|
||||
@model.getActivePane().activate()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user