diff --git a/spec/package-manager-spec.coffee b/spec/package-manager-spec.coffee index b4b89314e..3015aa786 100644 --- a/spec/package-manager-spec.coffee +++ b/spec/package-manager-spec.coffee @@ -502,6 +502,7 @@ describe "PackageManager", -> runs -> expect(pack.mainModule.someNumber).not.toBe 77 pack.mainModule.someNumber = 77 + atom.packages.serializePackage("package-with-serialization") atom.packages.deactivatePackage("package-with-serialization") spyOn(pack.mainModule, 'activate').andCallThrough() waitsForPromise -> @@ -899,6 +900,22 @@ describe "PackageManager", -> expect(atom.packages.packageStates['package-with-serialization']).toEqual someNumber: 1 expect(console.error).toHaveBeenCalled() + describe "::deactivatePackages()", -> + it "deactivates all packages but does not serialize them", -> + [pack1, pack2] = [] + + waitsForPromise -> + atom.packages.activatePackage("package-with-deactivate").then (p) -> pack1 = p + atom.packages.activatePackage("package-with-serialization").then (p) -> pack2 = p + + runs -> + spyOn(pack1.mainModule, 'deactivate') + spyOn(pack2.mainModule, 'serialize') + atom.packages.deactivatePackages() + + expect(pack1.mainModule.deactivate).toHaveBeenCalled() + expect(pack2.mainModule.serialize).not.toHaveBeenCalled() + describe "::deactivatePackage(id)", -> afterEach -> atom.packages.unloadPackages() diff --git a/src/application-delegate.coffee b/src/application-delegate.coffee index e174b2254..7e7bdbea8 100644 --- a/src/application-delegate.coffee +++ b/src/application-delegate.coffee @@ -20,7 +20,7 @@ class ApplicationDelegate remote.getCurrentWindow() closeWindow: -> - ipcRenderer.send("call-window-method", "close") + ipcHelpers.call('window-method', 'close') getTemporaryWindowState: -> ipcHelpers.call('get-temporary-window-state').then (stateJSON) -> JSON.parse(stateJSON) @@ -55,72 +55,55 @@ class ApplicationDelegate ipcHelpers.call('hide-window') reloadWindow: -> - ipcRenderer.send("call-window-method", "reload") + ipcHelpers.call('window-method', 'reload') restartApplication: -> ipcRenderer.send("restart-application") minimizeWindow: -> - ipcRenderer.send("call-window-method", "minimize") + ipcHelpers.call('window-method', 'minimize') isWindowMaximized: -> remote.getCurrentWindow().isMaximized() maximizeWindow: -> - ipcRenderer.send("call-window-method", "maximize") + ipcHelpers.call('window-method', 'maximize') unmaximizeWindow: -> - ipcRenderer.send("call-window-method", "unmaximize") + ipcHelpers.call('window-method', 'unmaximize') isWindowFullScreen: -> remote.getCurrentWindow().isFullScreen() setWindowFullScreen: (fullScreen=false) -> - ipcRenderer.send("call-window-method", "setFullScreen", fullScreen) + ipcHelpers.call('window-method', 'setFullScreen', fullScreen) openWindowDevTools: -> - new Promise (resolve) -> - # Defer DevTools interaction to the next tick, because using them during - # event handling causes some wrong input events to be triggered on - # `TextEditorComponent` (Ref.: https://github.com/atom/atom/issues/9697). - process.nextTick -> - if remote.getCurrentWindow().isDevToolsOpened() - resolve() - else - remote.getCurrentWindow().once("devtools-opened", -> resolve()) - ipcRenderer.send("call-window-method", "openDevTools") + # Defer DevTools interaction to the next tick, because using them during + # event handling causes some wrong input events to be triggered on + # `TextEditorComponent` (Ref.: https://github.com/atom/atom/issues/9697). + new Promise(process.nextTick).then(-> ipcHelpers.call('window-method', 'openDevTools')) closeWindowDevTools: -> - new Promise (resolve) -> - # Defer DevTools interaction to the next tick, because using them during - # event handling causes some wrong input events to be triggered on - # `TextEditorComponent` (Ref.: https://github.com/atom/atom/issues/9697). - process.nextTick -> - unless remote.getCurrentWindow().isDevToolsOpened() - resolve() - else - remote.getCurrentWindow().once("devtools-closed", -> resolve()) - ipcRenderer.send("call-window-method", "closeDevTools") + # Defer DevTools interaction to the next tick, because using them during + # event handling causes some wrong input events to be triggered on + # `TextEditorComponent` (Ref.: https://github.com/atom/atom/issues/9697). + new Promise(process.nextTick).then(-> ipcHelpers.call('window-method', 'closeDevTools')) toggleWindowDevTools: -> - new Promise (resolve) => - # Defer DevTools interaction to the next tick, because using them during - # event handling causes some wrong input events to be triggered on - # `TextEditorComponent` (Ref.: https://github.com/atom/atom/issues/9697). - process.nextTick => - if remote.getCurrentWindow().isDevToolsOpened() - @closeWindowDevTools().then(resolve) - else - @openWindowDevTools().then(resolve) + # Defer DevTools interaction to the next tick, because using them during + # event handling causes some wrong input events to be triggered on + # `TextEditorComponent` (Ref.: https://github.com/atom/atom/issues/9697). + new Promise(process.nextTick).then(-> ipcHelpers.call('window-method', 'toggleDevTools')) executeJavaScriptInWindowDevTools: (code) -> ipcRenderer.send("execute-javascript-in-dev-tools", code) setWindowDocumentEdited: (edited) -> - ipcRenderer.send("call-window-method", "setDocumentEdited", edited) + ipcHelpers.call('window-method', 'setDocumentEdited', edited) setRepresentedFilename: (filename) -> - ipcRenderer.send("call-window-method", "setRepresentedFilename", filename) + ipcHelpers.call('window-method', 'setRepresentedFilename', filename) addRecentDocument: (filename) -> ipcRenderer.send("add-recent-document", filename) @@ -131,7 +114,7 @@ class ApplicationDelegate setWindowLoadSettings(loadSettings) setAutoHideWindowMenuBar: (autoHide) -> - ipcRenderer.send("call-window-method", "setAutoHideMenuBar", autoHide) + ipcHelpers.call('window-method', 'setAutoHideMenuBar', autoHide) setWindowMenuBarVisibility: (visible) -> remote.getCurrentWindow().setMenuBarVisibility(visible) diff --git a/src/ipc-helpers.js b/src/ipc-helpers.js index 385158793..6a7565968 100644 --- a/src/ipc-helpers.js +++ b/src/ipc-helpers.js @@ -12,12 +12,12 @@ exports.on = function (emitter, eventName, callback) { }) } -exports.call = function (methodName, ...args) { +exports.call = function (channel, ...args) { if (!ipcRenderer) { ipcRenderer = require('electron').ipcRenderer } - var responseChannel = getResponseChannel(methodName) + var responseChannel = getResponseChannel(channel) return new Promise(function (resolve) { ipcRenderer.on(responseChannel, function (event, result) { @@ -25,26 +25,26 @@ exports.call = function (methodName, ...args) { resolve(result) }) - ipcRenderer.send(methodName, ...args) + ipcRenderer.send(channel, ...args) }) } -exports.respondTo = function (methodName, callback) { +exports.respondTo = function (channel, callback) { if (!ipcMain) { var electron = require('electron') ipcMain = electron.ipcMain BrowserWindow = electron.BrowserWindow } - var responseChannel = getResponseChannel(methodName) + var responseChannel = getResponseChannel(channel) - return exports.on(ipcMain, methodName, function (event, ...args) { + return exports.on(ipcMain, channel, function (event, ...args) { var browserWindow = BrowserWindow.fromWebContents(event.sender) var result = callback(browserWindow, ...args) event.sender.send(responseChannel, result) }) } -function getResponseChannel (methodName) { - return 'ipc-helpers-' + methodName + '-response' +function getResponseChannel (channel) { + return 'ipc-helpers-' + channel + '-response' } diff --git a/src/main-process/atom-application.coffee b/src/main-process/atom-application.coffee index 181550156..886f31f7f 100644 --- a/src/main-process/atom-application.coffee +++ b/src/main-process/atom-application.coffee @@ -259,7 +259,7 @@ class AtomApplication # A request from the associated render process to open a new render process. @disposable.add ipcHelpers.on ipcMain, 'open', (event, options) => - window = @windowForEvent(event) + window = @atomWindowForEvent(event) if options? if typeof options.pathsToOpen is 'string' options.pathsToOpen = [options.pathsToOpen] @@ -293,9 +293,8 @@ class AtomApplication win = BrowserWindow.fromWebContents(event.sender) win.emit(command, args...) - @disposable.add ipcHelpers.on ipcMain, 'call-window-method', (event, method, args...) -> - win = BrowserWindow.fromWebContents(event.sender) - win[method](args...) + @disposable.add ipcHelpers.respondTo 'window-method', (browserWindow, method, args...) => + @atomWindowForBrowserWindow(browserWindow)?[method](args...) @disposable.add ipcHelpers.on ipcMain, 'pick-folder', (event, responseChannel) => @promptForPath "folder", (selectedPaths) -> @@ -353,11 +352,11 @@ class AtomApplication event.returnValue = @autoUpdateManager.getErrorMessage() @disposable.add ipcHelpers.on ipcMain, 'will-save-path', (event, path) => - @fileRecoveryService.willSavePath(@windowForEvent(event), path) + @fileRecoveryService.willSavePath(@atomWindowForEvent(event), path) event.returnValue = true @disposable.add ipcHelpers.on ipcMain, 'did-save-path', (event, path) => - @fileRecoveryService.didSavePath(@windowForEvent(event), path) + @fileRecoveryService.didSavePath(@atomWindowForEvent(event), path) event.returnValue = true setupDockMenu: -> @@ -428,9 +427,11 @@ class AtomApplication atomWindow.devMode is devMode and atomWindow.containsPaths(pathsToOpen) # Returns the {AtomWindow} for the given ipcMain event. - windowForEvent: ({sender}) -> - window = BrowserWindow.fromWebContents(sender) - _.find @windows, ({browserWindow}) -> window is browserWindow + atomWindowForEvent: ({sender}) -> + @atomWindowForBrowserWindow(BrowserWindow.fromWebContents(sender)) + + atomWindowForBrowserWindow: (browserWindow) -> + @windows.find((atomWindow) -> atomWindow.browserWindow is browserWindow) # Public: Returns the currently focused {AtomWindow} or undefined if none. focusedWindow: -> diff --git a/src/main-process/atom-window.coffee b/src/main-process/atom-window.coffee index b2e2206cc..7f525a396 100644 --- a/src/main-process/atom-window.coffee +++ b/src/main-process/atom-window.coffee @@ -236,8 +236,14 @@ class AtomWindow maximize: -> @browserWindow.maximize() + unmaximize: -> @browserWindow.unmaximize() + restore: -> @browserWindow.restore() + setFullScreen: (fullScreen) -> @browserWindow.setFullScreen(fullScreen) + + setAutoHideMenuBar: (autoHideMenuBar) -> @browserWindow.setAutoHideMenuBar(autoHideMenuBar) + handlesAtomCommands: -> not @isSpecWindow() and @isWebViewFocused() @@ -257,3 +263,13 @@ class AtomWindow @loadedPromise toggleDevTools: -> @browserWindow.toggleDevTools() + + openDevTools: -> @browserWindow.openDevTools() + + closeDevTools: -> @browserWindow.closeDevTools() + + setDocumentEdited: (documentEdited) -> @browserWindow.setDocumentEdited(documentEdited) + + setRepresentedFilename: (representedFilename) -> @browserWindow.setRepresentedFilename(representedFilename) + + copy: -> @browserWindow.copy() diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 8f2924358..a2e792e26 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -486,15 +486,15 @@ class PackageManager # Deactivate all packages deactivatePackages: -> @config.transact => - @deactivatePackage(pack.name) for pack in @getLoadedPackages() + @deactivatePackage(pack.name, true) for pack in @getLoadedPackages() return @unobserveDisabledPackages() @unobservePackagesWithKeymapsDisabled() # Deactivate the package with the given name - deactivatePackage: (name) -> + deactivatePackage: (name, suppressSerialization) -> pack = @getLoadedPackage(name) - @serializePackage(pack) if @isPackageActive(pack.name) + @serializePackage(pack) if not suppressSerialization and @isPackageActive(pack.name) pack.deactivate() delete @activePackages[pack.name] delete @activatingPackages[pack.name]