PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/src/browser/atom-window.coffee

https://gitlab.com/jslee1/atom
CoffeeScript | 226 lines | 166 code | 53 blank | 7 comment | 34 complexity | 7cb6ea19ad2b0cffb760a169aaa80dae MD5 | raw file
  1. {BrowserWindow, app, dialog} = require 'electron'
  2. path = require 'path'
  3. fs = require 'fs'
  4. url = require 'url'
  5. _ = require 'underscore-plus'
  6. {EventEmitter} = require 'events'
  7. module.exports =
  8. class AtomWindow
  9. _.extend @prototype, EventEmitter.prototype
  10. @iconPath: path.resolve(__dirname, '..', '..', 'resources', 'atom.png')
  11. @includeShellLoadTime: true
  12. browserWindow: null
  13. loaded: null
  14. isSpec: null
  15. constructor: (settings={}) ->
  16. {@resourcePath, initialPaths, pathToOpen, locationsToOpen, @isSpec, @headless, @safeMode, @devMode} = settings
  17. locationsToOpen ?= [{pathToOpen}] if pathToOpen
  18. locationsToOpen ?= []
  19. options =
  20. show: false
  21. title: 'Atom'
  22. 'web-preferences':
  23. 'direct-write': true
  24. if @isSpec
  25. options['web-preferences']['page-visibility'] = true
  26. # Don't set icon on Windows so the exe's ico will be used as window and
  27. # taskbar's icon. See https://github.com/atom/atom/issues/4811 for more.
  28. if process.platform is 'linux'
  29. options.icon = @constructor.iconPath
  30. @browserWindow = new BrowserWindow options
  31. global.atomApplication.addWindow(this)
  32. @handleEvents()
  33. loadSettings = _.extend({}, settings)
  34. loadSettings.appVersion = app.getVersion()
  35. loadSettings.resourcePath = @resourcePath
  36. loadSettings.devMode ?= false
  37. loadSettings.safeMode ?= false
  38. loadSettings.atomHome = process.env.ATOM_HOME
  39. loadSettings.clearWindowState ?= false
  40. loadSettings.initialPaths ?=
  41. for {pathToOpen} in locationsToOpen when pathToOpen
  42. if fs.statSyncNoException(pathToOpen).isFile?()
  43. path.dirname(pathToOpen)
  44. else
  45. pathToOpen
  46. loadSettings.initialPaths.sort()
  47. # Only send to the first non-spec window created
  48. if @constructor.includeShellLoadTime and not @isSpec
  49. @constructor.includeShellLoadTime = false
  50. loadSettings.shellLoadTime ?= Date.now() - global.shellStartTime
  51. @browserWindow.loadSettings = loadSettings
  52. @browserWindow.once 'window:loaded', =>
  53. @emit 'window:loaded'
  54. @loaded = true
  55. @setLoadSettings(loadSettings)
  56. @env = loadSettings.env if loadSettings.env?
  57. @browserWindow.focusOnWebView() if @isSpec
  58. @browserWindow.temporaryState = {windowDimensions} if windowDimensions?
  59. hasPathToOpen = not (locationsToOpen.length is 1 and not locationsToOpen[0].pathToOpen?)
  60. @openLocations(locationsToOpen) if hasPathToOpen and not @isSpecWindow()
  61. setLoadSettings: (loadSettings) ->
  62. @browserWindow.loadURL url.format
  63. protocol: 'file'
  64. pathname: "#{@resourcePath}/static/index.html"
  65. slashes: true
  66. hash: encodeURIComponent(JSON.stringify(loadSettings))
  67. getLoadSettings: ->
  68. if @browserWindow.webContents? and not @browserWindow.webContents.isLoading()
  69. hash = url.parse(@browserWindow.webContents.getURL()).hash.substr(1)
  70. JSON.parse(decodeURIComponent(hash))
  71. hasProjectPath: -> @getLoadSettings().initialPaths?.length > 0
  72. setupContextMenu: ->
  73. ContextMenu = require './context-menu'
  74. @browserWindow.on 'context-menu', (menuTemplate) =>
  75. new ContextMenu(menuTemplate, this)
  76. containsPaths: (paths) ->
  77. for pathToCheck in paths
  78. return false unless @containsPath(pathToCheck)
  79. true
  80. containsPath: (pathToCheck) ->
  81. @getLoadSettings()?.initialPaths?.some (projectPath) ->
  82. if not projectPath
  83. false
  84. else if not pathToCheck
  85. false
  86. else if pathToCheck is projectPath
  87. true
  88. else if fs.statSyncNoException(pathToCheck).isDirectory?()
  89. false
  90. else if pathToCheck.indexOf(path.join(projectPath, path.sep)) is 0
  91. true
  92. else
  93. false
  94. handleEvents: ->
  95. @browserWindow.on 'close', ->
  96. global.atomApplication.saveState(false)
  97. @browserWindow.on 'closed', =>
  98. global.atomApplication.removeWindow(this)
  99. @browserWindow.on 'unresponsive', =>
  100. return if @isSpec
  101. chosen = dialog.showMessageBox @browserWindow,
  102. type: 'warning'
  103. buttons: ['Close', 'Keep Waiting']
  104. message: 'Editor is not responding'
  105. detail: 'The editor is not responding. Would you like to force close it or just keep waiting?'
  106. @browserWindow.destroy() if chosen is 0
  107. @browserWindow.webContents.on 'crashed', =>
  108. global.atomApplication.exit(100) if @headless
  109. chosen = dialog.showMessageBox @browserWindow,
  110. type: 'warning'
  111. buttons: ['Close Window', 'Reload', 'Keep It Open']
  112. message: 'The editor has crashed'
  113. detail: 'Please report this issue to https://github.com/atom/atom'
  114. switch chosen
  115. when 0 then @browserWindow.destroy()
  116. when 1 then @browserWindow.reload()
  117. @browserWindow.webContents.on 'will-navigate', (event, url) =>
  118. unless url is @browserWindow.webContents.getURL()
  119. event.preventDefault()
  120. @setupContextMenu()
  121. if @isSpec
  122. # Workaround for https://github.com/atom/atom-shell/issues/380
  123. # Don't focus the window when it is being blurred during close or
  124. # else the app will crash on Windows.
  125. if process.platform is 'win32'
  126. @browserWindow.on 'close', => @isWindowClosing = true
  127. # Spec window's web view should always have focus
  128. @browserWindow.on 'blur', =>
  129. @browserWindow.focusOnWebView() unless @isWindowClosing
  130. openPath: (pathToOpen, initialLine, initialColumn) ->
  131. @openLocations([{pathToOpen, initialLine, initialColumn}])
  132. openLocations: (locationsToOpen) ->
  133. if @loaded
  134. @sendMessage 'open-locations', locationsToOpen
  135. else
  136. @browserWindow.once 'window:loaded', => @openLocations(locationsToOpen)
  137. replaceEnvironment: (env) ->
  138. @browserWindow.webContents.send 'environment', env
  139. sendMessage: (message, detail) ->
  140. @browserWindow.webContents.send 'message', message, detail
  141. sendCommand: (command, args...) ->
  142. if @isSpecWindow()
  143. unless global.atomApplication.sendCommandToFirstResponder(command)
  144. switch command
  145. when 'window:reload' then @reload()
  146. when 'window:toggle-dev-tools' then @toggleDevTools()
  147. when 'window:close' then @close()
  148. else if @isWebViewFocused()
  149. @sendCommandToBrowserWindow(command, args...)
  150. else
  151. unless global.atomApplication.sendCommandToFirstResponder(command)
  152. @sendCommandToBrowserWindow(command, args...)
  153. sendCommandToBrowserWindow: (command, args...) ->
  154. action = if args[0]?.contextCommand then 'context-command' else 'command'
  155. @browserWindow.webContents.send action, command, args...
  156. getDimensions: ->
  157. [x, y] = @browserWindow.getPosition()
  158. [width, height] = @browserWindow.getSize()
  159. {x, y, width, height}
  160. close: -> @browserWindow.close()
  161. focus: -> @browserWindow.focus()
  162. minimize: -> @browserWindow.minimize()
  163. maximize: -> @browserWindow.maximize()
  164. restore: -> @browserWindow.restore()
  165. handlesAtomCommands: ->
  166. not @isSpecWindow() and @isWebViewFocused()
  167. isFocused: -> @browserWindow.isFocused()
  168. isMaximized: -> @browserWindow.isMaximized()
  169. isMinimized: -> @browserWindow.isMinimized()
  170. isWebViewFocused: -> @browserWindow.isWebViewFocused()
  171. isSpecWindow: -> @isSpec
  172. reload: -> @browserWindow.reload()
  173. toggleDevTools: -> @browserWindow.toggleDevTools()