From 43656a98617d62560df497248a9382c269eed0f7 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 18 Feb 2016 09:17:34 -0800 Subject: [PATCH] Load packages before deserializing state --- spec/atom-environment-spec.coffee | 12 +-- src/application-delegate.coffee | 6 ++ src/atom-environment.coffee | 108 +++++++++-------------- src/browser/atom-application.coffee | 8 +- src/browser/atom-window.coffee | 11 +-- src/initialize-application-window.coffee | 14 ++- src/window-event-handler.coffee | 4 +- src/window-load-settings-helpers.coffee | 9 -- 8 files changed, 68 insertions(+), 104 deletions(-) diff --git a/spec/atom-environment-spec.coffee b/spec/atom-environment-spec.coffee index 561ecf3b5..e2ce6670a 100644 --- a/spec/atom-environment-spec.coffee +++ b/spec/atom-environment-spec.coffee @@ -162,7 +162,6 @@ describe "AtomEnvironment", -> spyOn(atom, 'getLoadSettings').andCallFake -> loadSettings spyOn(atom, 'serialize').andReturn({stuff: 'cool'}) - spyOn(atom, 'deserialize') atom.project.setPaths([dir1, dir2]) # State persistence will fail if other Atom instances are running @@ -172,16 +171,13 @@ describe "AtomEnvironment", -> waitsForPromise -> atom.saveState().then -> - atom.loadState() - - runs -> - expect(atom.deserialize).not.toHaveBeenCalled() + atom.loadState().then (state) -> + expect(state).toBeNull() waitsForPromise -> loadSettings.initialPaths = [dir2, dir1] - atom.loadState() - runs -> - expect(atom.deserialize).toHaveBeenCalledWith({stuff: 'cool'}) + atom.loadState().then (state) -> + expect(state).toEqual({stuff: 'cool'}) it "saves state on keydown and mousedown events", -> spyOn(atom, 'saveState') diff --git a/src/application-delegate.coffee b/src/application-delegate.coffee index f87827886..cc1f4c946 100644 --- a/src/application-delegate.coffee +++ b/src/application-delegate.coffee @@ -22,6 +22,12 @@ class ApplicationDelegate closeWindow: -> ipcRenderer.send("call-window-method", "close") + getTemporaryWindowState: -> + ipcHelpers.call('get-temporary-window-state') + + setTemporaryWindowState: (state) -> + ipcHelpers.call('set-temporary-window-state', state) + getWindowSize: -> [width, height] = remote.getCurrentWindow().getSize() {width, height} diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 8c2d3e73d..776640aee 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -537,21 +537,16 @@ class AtomEnvironment extends Model # Restores the full screen and maximized state after the window has resized to # prevent resize glitches. displayWindow: -> - @restoreWindowDimensions().then (dimensions) => + @restoreWindowDimensions().then => steps = [ @restoreWindowBackground(), @show(), @focus() ] steps.push(@setFullScreen(true)) if @workspace.fullScreen - steps.push(@maximize()) if dimensions?.maximized and process.platform isnt 'darwin' + steps.push(@maximize()) if @windowDimensions?.maximized and process.platform isnt 'darwin' Promise.all(steps) - if @isFirstLoad() - loadSettings = getWindowLoadSettings() - loadSettings.firstLoad = false - setWindowLoadSettings(loadSettings) - # Get the dimensions of this window. # # Returns an {Object} with the following keys: @@ -592,10 +587,10 @@ class AtomEnvironment extends Model isValidDimensions: ({x, y, width, height}={}) -> width > 0 and height > 0 and x + width > 0 and y + height > 0 - storeDefaultWindowDimensions: -> - dimensions = @getWindowDimensions() - if @isValidDimensions(dimensions) - localStorage.setItem("defaultWindowDimensions", JSON.stringify(dimensions)) + storeWindowDimensions: -> + @windowDimensions = @getWindowDimensions() + if @isValidDimensions(@windowDimensions) + localStorage.setItem("defaultWindowDimensions", JSON.stringify(@windowDimensions)) getDefaultWindowDimensions: -> {windowDimensions} = @getLoadSettings() @@ -615,21 +610,9 @@ class AtomEnvironment extends Model {x: 0, y: 0, width: Math.min(1024, width), height} restoreWindowDimensions: -> - dimensions = null - - # The first time the window's loaded we want to use the default dimensions. - # But after that, e.g., when the window's been reloaded, we want to use the - # dimensions we've saved for it. - if not @isFirstLoad() - dimensions = @windowDimensions - - unless @isValidDimensions(dimensions) - dimensions = @getDefaultWindowDimensions() - @setWindowDimensions(dimensions).then -> dimensions - - storeWindowDimensions: -> - dimensions = @getWindowDimensions() - @windowDimensions = dimensions if @isValidDimensions(dimensions) + unless @windowDimensions? and @isValidDimensions(@windowDimensions) + @windowDimensions = @getDefaultWindowDimensions() + @setWindowDimensions(@windowDimensions).then -> @windowDimensions restoreWindowBackground: -> if backgroundColor = window.localStorage.getItem('atom:window-background-color') @@ -647,32 +630,39 @@ class AtomEnvironment extends Model # Call this method when establishing a real application window. startEditorWindow: -> - @commandInstaller.installAtomCommand false, (error) -> - console.warn error.message if error? - @commandInstaller.installApmCommand false, (error) -> - console.warn error.message if error? + @loadState().then (state) => + @windowDimensions = state?.windowDimensions + @displayWindow().then => + @commandInstaller.installAtomCommand false, (error) -> + console.warn error.message if error? + @commandInstaller.installApmCommand false, (error) -> + console.warn error.message if error? - @disposables.add(@applicationDelegate.onDidOpenLocations(@openLocations.bind(this))) - @disposables.add(@applicationDelegate.onApplicationMenuCommand(@dispatchApplicationMenuCommand.bind(this))) - @disposables.add(@applicationDelegate.onContextMenuCommand(@dispatchContextMenuCommand.bind(this))) - @listenForUpdates() + @disposables.add(@applicationDelegate.onDidOpenLocations(@openLocations.bind(this))) + @disposables.add(@applicationDelegate.onApplicationMenuCommand(@dispatchApplicationMenuCommand.bind(this))) + @disposables.add(@applicationDelegate.onContextMenuCommand(@dispatchContextMenuCommand.bind(this))) + @listenForUpdates() - @registerDefaultTargetForKeymaps() + @registerDefaultTargetForKeymaps() - @packages.loadPackages() + @packages.loadPackages() - @document.body.appendChild(@views.getView(@workspace)) - @backgroundStylesheet?.remove() + startTime = Date.now() + @deserialize(state) if state? + @deserializeTimings.atom = Date.now() - startTime - @watchProjectPath() + @document.body.appendChild(@views.getView(@workspace)) + @backgroundStylesheet?.remove() - @packages.activate() - @keymaps.loadUserKeymap() - @requireUserInitScript() unless @getLoadSettings().safeMode + @watchProjectPath() - @menu.update() + @packages.activate() + @keymaps.loadUserKeymap() + @requireUserInitScript() unless @getLoadSettings().safeMode - @openInitialEmptyEditorIfNecessary() + @menu.update() + + @openInitialEmptyEditorIfNecessary() serialize: -> version: @constructor.version @@ -828,30 +818,16 @@ class AtomEnvironment extends Model if storageKey = @getStateKey(@project?.getPaths()) @stateStore.save(storageKey, state) else - @getCurrentWindow().loadSettings.windowState = JSON.stringify(state) - Promise.resolve() + @applicationDelegate.setTemporaryWindowState(state) loadState: -> - return Promise.resolve() unless @enablePersistence - - startTime = Date.now() - - statePromise = null - if stateKey = @getStateKey(@getLoadSettings().initialPaths) - statePromise = @stateStore.load(stateKey) - - if not statePromise? and windowState = @getLoadSettings().windowState - try - statePromise = Promise.resolve(JSON.parse(@getLoadSettings().windowState)) - catch error - console.warn "Error parsing window state: #{statePath} #{error.stack}", error - - if statePromise? - statePromise.then (state) => - @deserializeTimings.atom = Date.now() - startTime - @deserialize(state) if state? + if @enablePersistence + if stateKey = @getStateKey(@getLoadSettings().initialPaths) + @stateStore.load(stateKey) + else + @applicationDelegate.getTemporaryWindowState() else - Promise.resolve() + Promise.resolve(null) deserialize: (state) -> if grammarOverridesByPath = state.grammars?.grammarOverridesByPath @@ -859,8 +835,6 @@ class AtomEnvironment extends Model @setFullScreen(state.fullScreen) - @windowDimensions = state.windowDimensions if state.windowDimensions - @packages.packageStates = state.packageStates ? {} startTime = Date.now() diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 93dd428ce..7ea0342c8 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -280,6 +280,12 @@ class AtomApplication ipcHelpers.respondTo 'hide-window', (win) -> win.hide() + ipcHelpers.respondTo 'get-temporary-window-state', (win) -> + win.temporaryState + + ipcHelpers.respondTo 'set-temporary-window-state', (win, state) -> + win.temporaryState = state + ipcMain.on 'did-cancel-window-unload', => @quitting = false @@ -528,7 +534,7 @@ class AtomApplication if pack.urlMain packagePath = @packages.resolvePackagePath(packageName) windowInitializationScript = path.resolve(packagePath, pack.urlMain) - windowDimensions = @focusedWindow()?.getDimensions() + windowDimensions = @getDimensionsForNewWindow() new AtomWindow({windowInitializationScript, @resourcePath, devMode, safeMode, urlToOpen, windowDimensions}) else console.log "Package '#{pack.name}' does not have a url main: #{urlToOpen}" diff --git a/src/browser/atom-window.coffee b/src/browser/atom-window.coffee index 828366c4f..634242e0d 100644 --- a/src/browser/atom-window.coffee +++ b/src/browser/atom-window.coffee @@ -41,13 +41,11 @@ class AtomWindow @handleEvents() loadSettings = _.extend({}, settings) - loadSettings.windowState ?= '{}' loadSettings.appVersion = app.getVersion() loadSettings.resourcePath = @resourcePath loadSettings.devMode ?= false loadSettings.safeMode ?= false loadSettings.atomHome = process.env.ATOM_HOME - loadSettings.firstLoad = true loadSettings.clearWindowState ?= false # Only send to the first non-spec window created @@ -64,23 +62,18 @@ class AtomWindow loadSettings.initialPaths.sort() - @browserWindow.loadSettings = loadSettings @browserWindow.once 'window:loaded', => @emit 'window:loaded' @loaded = true @setLoadSettings(loadSettings) @browserWindow.focusOnWebView() if @isSpec + @browserWindow.temporaryState = {windowDimensions} if windowDimensions? hasPathToOpen = not (locationsToOpen.length is 1 and not locationsToOpen[0].pathToOpen?) @openLocations(locationsToOpen) if hasPathToOpen and not @isSpecWindow() - setLoadSettings: (loadSettingsObj) -> - # Ignore the windowState when passing loadSettings via URL, since it could - # be quite large. - loadSettings = _.clone(loadSettingsObj) - delete loadSettings['windowState'] - + setLoadSettings: (loadSettings) -> @browserWindow.loadURL url.format protocol: 'file' pathname: "#{@resourcePath}/static/index.html" diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 61f0c2439..cea4e1c3c 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -23,12 +23,10 @@ module.exports = ({blobStore}) -> enablePersistence: true }) - atom.loadState().then -> - atom.displayWindow().then -> - atom.startEditorWindow() + atom.startEditorWindow().then -> - # Workaround for focus getting cleared upon window creation - windowFocused = -> - window.removeEventListener('focus', windowFocused) - setTimeout (-> document.querySelector('atom-workspace').focus()), 0 - window.addEventListener('focus', windowFocused) + # Workaround for focus getting cleared upon window creation + windowFocused = -> + window.removeEventListener('focus', windowFocused) + setTimeout (-> document.querySelector('atom-workspace').focus()), 0 + window.addEventListener('focus', windowFocused) diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index d3a231f77..f0d616f19 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -133,7 +133,7 @@ class WindowEventHandler handleWindowBlur: => @document.body.classList.add('is-blurred') - @atomEnvironment.storeDefaultWindowDimensions() + @atomEnvironment.storeWindowDimensions() handleWindowBeforeunload: => confirmed = @atomEnvironment.workspace?.confirmClose(windowCloseRequested: true) @@ -141,8 +141,8 @@ class WindowEventHandler @atomEnvironment.hide() @reloadRequested = false - @atomEnvironment.storeDefaultWindowDimensions() @atomEnvironment.storeWindowDimensions() + @atomEnvironment.saveState() if confirmed @atomEnvironment.unloadEditorWindow() else diff --git a/src/window-load-settings-helpers.coffee b/src/window-load-settings-helpers.coffee index 4bb514301..73fd31a3d 100644 --- a/src/window-load-settings-helpers.coffee +++ b/src/window-load-settings-helpers.coffee @@ -5,15 +5,6 @@ windowLoadSettings = null exports.getWindowLoadSettings = -> windowLoadSettings ?= JSON.parse(window.decodeURIComponent(window.location.hash.substr(1))) - clone = _.deepClone(windowLoadSettings) - - # The windowLoadSettings.windowState could be large, request it only when needed. - clone.__defineGetter__ 'windowState', -> - remote.getCurrentWindow().loadSettings.windowState - clone.__defineSetter__ 'windowState', (value) -> - remote.getCurrentWindow().loadSettings.windowState = value - - clone exports.setWindowLoadSettings = (settings) -> windowLoadSettings = settings