From 28116631774a8ba1063041a60927efe0d3a7bfcc Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 22 Aug 2014 09:42:00 -0700 Subject: [PATCH 01/11] Open file paths in focused window --- src/browser/atom-application.coffee | 17 ++++++++++++++--- src/browser/atom-window.coffee | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index cc81beef9..868819101 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -103,6 +103,12 @@ class AtomApplication window.once 'window:loaded', => @autoUpdateManager.emitUpdateAvailableEvent(window) + focusHandler = => @topWindow = window + window.browserWindow.on 'focus', focusHandler + window.browserWindow.once 'closed', => + @topWindow = null if window is @topWindow + window.browserWindow.removeListener 'focus', focusHandler + # Creates server to listen for additional atom application launches. # # You can run the atom command multiple times, but after the first launch @@ -312,9 +318,14 @@ class AtomApplication openPath: ({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, windowDimensions}={}) -> {pathToOpen, initialLine, initialColumn} = @locationForPathToOpen(pathToOpen) - unless devMode - existingWindow = @windowForPath(pathToOpen) unless pidToKillWhenClosed or newWindow - if existingWindow + # Open files in the focused window + unless pidToKillWhenClosed or newWindow + if fs.statSyncNoException(pathToOpen).isFile?() + existingWindow = @topWindow + + existingWindow ?= @windowForPath(pathToOpen) unless devMode + + if existingWindow? openedWindow = existingWindow openedWindow.openPath(pathToOpen, initialLine) openedWindow.restore() diff --git a/src/browser/atom-window.coffee b/src/browser/atom-window.coffee index ad2b2ce53..04d647ba6 100644 --- a/src/browser/atom-window.coffee +++ b/src/browser/atom-window.coffee @@ -25,9 +25,9 @@ class AtomWindow # Normalize to make sure drive letter case is consistent on Windows @resourcePath = path.normalize(@resourcePath) if @resourcePath + @browserWindow = new BrowserWindow show: false, title: 'Atom', icon: @constructor.iconPath global.atomApplication.addWindow(this) - @browserWindow = new BrowserWindow show: false, title: 'Atom', icon: @constructor.iconPath @handleEvents() loadSettings = _.extend({}, settings) From c9390b61deb2f040f67d30f295f99bba95a749d7 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 22 Aug 2014 09:54:33 -0700 Subject: [PATCH 02/11] Track AtomWindow from ipc open event This ensures the window where the file is dropped is used to open that file into even when that window does not have focus. --- src/browser/atom-application.coffee | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 868819101..9b8df0383 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -205,13 +205,15 @@ class AtomApplication # A request from the associated render process to open a new render process. ipc.on 'open', (event, options) => + window = @windowForEvent(event) if options? if options.pathsToOpen?.length > 0 + options.window = window @openPaths(options) else new AtomWindow(options) else - @promptForPath() + @promptForPath({window}) ipc.on 'update-application-menu', (event, template, keystrokesByCommand) => @applicationMenu.update(template, keystrokesByCommand) @@ -290,6 +292,11 @@ class AtomApplication for atomWindow in @windows return atomWindow if atomWindow.containsPath(pathToOpen) + # Returns the {AtomWindow} for the given ipc event. + windowForEvent: ({sender}) -> + window = BrowserWindow.fromWebContents(sender) + _.find @windows, ({browserWindow}) -> window is browserWindow + # Public: Returns the currently focused {AtomWindow} or undefined if none. focusedWindow: -> _.find @windows, (atomWindow) -> atomWindow.isFocused() @@ -302,9 +309,10 @@ class AtomApplication # :newWindow - Boolean of whether this should be opened in a new window. # :devMode - Boolean to control the opened window's dev mode. # :safeMode - Boolean to control the opened window's safe mode. - openPaths: ({pathsToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode}) -> + # :window - {AtomWindow} to open file paths in. + openPaths: ({pathsToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, window}) -> for pathToOpen in pathsToOpen ? [] - @openPath({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode}) + @openPath({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, window}) # Public: Opens a single path, in an existing window if possible. # @@ -315,13 +323,14 @@ class AtomApplication # :devMode - Boolean to control the opened window's dev mode. # :safeMode - Boolean to control the opened window's safe mode. # :windowDimensions - Object with height and width keys. - openPath: ({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, windowDimensions}={}) -> + # :window - {AtomWindow} to open file paths in. + openPath: ({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, windowDimensions, window}={}) -> {pathToOpen, initialLine, initialColumn} = @locationForPathToOpen(pathToOpen) # Open files in the focused window unless pidToKillWhenClosed or newWindow if fs.statSyncNoException(pathToOpen).isFile?() - existingWindow = @topWindow + existingWindow = window ? @topWindow existingWindow ?= @windowForPath(pathToOpen) unless devMode @@ -455,7 +464,8 @@ class AtomApplication # should be in dev mode or not. # :safeMode - A Boolean which controls whether any newly opened windows # should be in safe mode or not. - promptForPath: ({type, devMode, safeMode}={}) -> + # :window - An {AtomWindow} to use for opening a selected file path. + promptForPath: ({type, devMode, safeMode, window}={}) -> type ?= 'all' properties = switch type @@ -464,4 +474,4 @@ class AtomApplication when 'all' then ['openFile', 'openDirectory'] else throw new Error("#{type} is an invalid type for promptForPath") dialog.showOpenDialog title: 'Open', properties: properties.concat(['multiSelections', 'createDirectory']), (pathsToOpen) => - @openPaths({pathsToOpen, devMode, safeMode}) + @openPaths({pathsToOpen, devMode, safeMode, window}) From a4ae314b0063674663fae3ed533211e1f7fb6fb8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 22 Aug 2014 10:02:09 -0700 Subject: [PATCH 03/11] :lipstick: --- src/browser/atom-application.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 9b8df0383..ae39d85e7 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -289,8 +289,7 @@ class AtomApplication # Returns the {AtomWindow} for the given path. windowForPath: (pathToOpen) -> - for atomWindow in @windows - return atomWindow if atomWindow.containsPath(pathToOpen) + _.find @windows, (atomWindow) -> atomWindow.containsPath(pathToOpen) # Returns the {AtomWindow} for the given ipc event. windowForEvent: ({sender}) -> From 1196e5a26412cd1046f9c3ba2720170cc2b8205a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 22 Aug 2014 10:03:30 -0700 Subject: [PATCH 04/11] :memo: Doc dev mode case --- src/browser/atom-application.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index ae39d85e7..e26ad4b7c 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -331,6 +331,7 @@ class AtomApplication if fs.statSyncNoException(pathToOpen).isFile?() existingWindow = window ? @topWindow + # Don't reuse windows in dev mode existingWindow ?= @windowForPath(pathToOpen) unless devMode if existingWindow? From 5bdf8a14a712c43948ab2fc71702561755367174 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 22 Aug 2014 10:03:38 -0700 Subject: [PATCH 05/11] Use once for closed event --- src/browser/atom-application.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index e26ad4b7c..587535aeb 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -351,7 +351,7 @@ class AtomApplication if pidToKillWhenClosed? @pidsToOpenWindows[pidToKillWhenClosed] = openedWindow - openedWindow.browserWindow.on 'closed', => + openedWindow.browserWindow.once 'closed', => @killProcessForWindow(openedWindow) # Kill all processes associated with opened windows. From 17feb91876045dc7144721f9411125034b4ac8c0 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 22 Aug 2014 10:04:27 -0700 Subject: [PATCH 06/11] :memo: Move comment above isFile check --- src/browser/atom-application.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 587535aeb..624359ba9 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -326,8 +326,8 @@ class AtomApplication openPath: ({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, windowDimensions, window}={}) -> {pathToOpen, initialLine, initialColumn} = @locationForPathToOpen(pathToOpen) - # Open files in the focused window unless pidToKillWhenClosed or newWindow + # Open files in the specified window or the last focused window if fs.statSyncNoException(pathToOpen).isFile?() existingWindow = window ? @topWindow From 154fe4006ff9b24a3a1d409c67aa227e28476a2b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 22 Aug 2014 10:22:32 -0700 Subject: [PATCH 07/11] :memo: Doc file/folder path behavior in usage message --- src/browser/main.coffee | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/browser/main.coffee b/src/browser/main.coffee index 7d6d372e3..8955ab0a7 100644 --- a/src/browser/main.coffee +++ b/src/browser/main.coffee @@ -63,7 +63,14 @@ parseCommandLine = -> options.usage """ Atom Editor v#{version} - Usage: atom [options] [file ...] + Usage: atom [options] [path ...] + + One or more paths to files or folders to open may be specified. + + File paths will open in the current window. + + Folder paths will open in an existing window if that folder has already been + opened or a new window if it hasn't. """ options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.') options.alias('f', 'foreground').boolean('f').describe('f', 'Keep the browser process in the foreground.') From a853a27857cce76f169fdedef1d01dc5966da1f3 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 22 Aug 2014 12:10:33 -0700 Subject: [PATCH 08/11] Open folder in current untitled window Untitled windows will now have their project path set when a folder is opened. --- src/atom.coffee | 10 ++++++++++ src/browser/atom-application.coffee | 14 +++++++++++--- src/browser/atom-window.coffee | 4 ++++ src/window-event-handler.coffee | 4 +++- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index d497d1701..f208c3f92 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -308,6 +308,9 @@ class Atom extends Model @themes.loadBaseStylesheets() @packages.loadPackages() @deserializeEditorWindow() + + @watchProjectPath() + @packages.activate() @keymaps.loadUserKeymap() @requireUserInitScript() @@ -347,6 +350,13 @@ class Atom extends Model pack.reloadStylesheets?() null + # Notify the browser project of the window's current project path + watchProjectPath: -> + onProjectPathChanged = => + ipc.send('window-command', 'project-path-changed', @project.getPath()) + @subscribe @project, 'path-changed', onProjectPathChanged + onProjectPathChanged() + # Public: Open a new Atom window using the given options. # # Calling this method without an options parameter will open a prompt to pick diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 624359ba9..81c561778 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -327,9 +327,17 @@ class AtomApplication {pathToOpen, initialLine, initialColumn} = @locationForPathToOpen(pathToOpen) unless pidToKillWhenClosed or newWindow - # Open files in the specified window or the last focused window - if fs.statSyncNoException(pathToOpen).isFile?() - existingWindow = window ? @topWindow + pathToOpenStat = fs.statSyncNoException(pathToOpen) + + # Default to using the specified window or the last focused window + currentWindow = window ? @topWindow + + if pathToOpenStat.isFile?() + # Open the file in the current window + existingWindow = currentWindow + else if pathToOpenStat.isDirectory?() + # Open the folder in the current window if it doesn't have a path + existingWindow = currentWindow unless currentWindow?.hasProjectPath() # Don't reuse windows in dev mode existingWindow ?= @windowForPath(pathToOpen) unless devMode diff --git a/src/browser/atom-window.coffee b/src/browser/atom-window.coffee index 04d647ba6..4958dd782 100644 --- a/src/browser/atom-window.coffee +++ b/src/browser/atom-window.coffee @@ -49,6 +49,8 @@ class AtomWindow @emit 'window:loaded' @loaded = true + @browserWindow.on 'project-path-changed', (@projectPath) => + @browserWindow.loadUrl @getUrl(loadSettings) @browserWindow.focusOnWebView() if @isSpec @@ -66,6 +68,8 @@ class AtomWindow slashes: true query: {loadSettings: JSON.stringify(loadSettings)} + hasProjectPath: -> @projectPath?.length > 0 + getInitialPath: -> @browserWindow.loadSettings.initialPath diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index bdf50bd4b..5f2b09b62 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -28,7 +28,9 @@ class WindowEventHandler @subscribe $(window), 'blur', -> document.body.classList.add('is-blurred') @subscribe $(window), 'window:open-path', (event, {pathToOpen, initialLine, initialColumn}) -> - unless fs.isDirectorySync(pathToOpen) + if fs.isDirectorySync(pathToOpen) + atom.project.setPath(pathToOpen) unless atom.project.getPath() + else atom.workspace?.open(pathToOpen, {initialLine, initialColumn}) @subscribe $(window), 'beforeunload', => From 9f7560bb896303ec106401903dec8e65bb66d950 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 22 Aug 2014 13:31:37 -0700 Subject: [PATCH 09/11] :memo: Doc other atom.open options --- src/atom.coffee | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/atom.coffee b/src/atom.coffee index f208c3f92..29220206c 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -363,7 +363,15 @@ class Atom extends Model # a file/folder to open in the new window. # # options - An {Object} with the following keys: - # :pathsToOpen - An {Array} of {String} paths to open. + # :pathsToOpen - An {Array} of {String} paths to open. + # :newWindow - A {Boolean}, true to always open a new window instead of + # reusing existing windows depending on the paths to open. + # :devMode - A {Boolean}, true to open the window in development mode. + # Development mode loads the Atom source from the locally + # cloned repository and also loads all the packages in + # ~/.atom/dev/packages + # :safeMode - A {Boolean}, true to open the window in safe mode. Safe + # mode prevents installed packages from loading open: (options) -> ipc.send('open', options) From 6610447e09ebae3b51c01a7ab6c4d99d9d15f30e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 22 Aug 2014 13:32:12 -0700 Subject: [PATCH 10/11] :memo: Clarify safeMode description --- src/atom.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/atom.coffee b/src/atom.coffee index 29220206c..4c2da7f8a 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -371,7 +371,8 @@ class Atom extends Model # cloned repository and also loads all the packages in # ~/.atom/dev/packages # :safeMode - A {Boolean}, true to open the window in safe mode. Safe - # mode prevents installed packages from loading + # mode prevents all packages installed to ~/.atom/packages + # from loading. open: (options) -> ipc.send('open', options) From fb53f855737b8d87fad26b26d5de1822a76585ae Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 22 Aug 2014 13:33:45 -0700 Subject: [PATCH 11/11] Rename topWindow to lastFocusedWindow --- src/browser/atom-application.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 81c561778..69ac398ab 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -103,10 +103,10 @@ class AtomApplication window.once 'window:loaded', => @autoUpdateManager.emitUpdateAvailableEvent(window) - focusHandler = => @topWindow = window + focusHandler = => @lastFocusedWindow = window window.browserWindow.on 'focus', focusHandler window.browserWindow.once 'closed', => - @topWindow = null if window is @topWindow + @lastFocusedWindow = null if window is @lastFocusedWindow window.browserWindow.removeListener 'focus', focusHandler # Creates server to listen for additional atom application launches. @@ -330,7 +330,7 @@ class AtomApplication pathToOpenStat = fs.statSyncNoException(pathToOpen) # Default to using the specified window or the last focused window - currentWindow = window ? @topWindow + currentWindow = window ? @lastFocusedWindow if pathToOpenStat.isFile?() # Open the file in the current window