browser-window.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. 'use strict'
  2. const electron = require('electron')
  3. const {ipcMain} = electron
  4. const {EventEmitter} = require('events')
  5. const {BrowserWindow} = process.atomBinding('window')
  6. const v8Util = process.atomBinding('v8_util')
  7. Object.setPrototypeOf(BrowserWindow.prototype, EventEmitter.prototype)
  8. BrowserWindow.prototype._init = function () {
  9. // Avoid recursive require.
  10. const {app} = require('electron')
  11. // Simulate the application menu on platforms other than macOS.
  12. if (process.platform !== 'darwin') {
  13. const menu = app.getApplicationMenu()
  14. if (menu) this.setMenu(menu)
  15. }
  16. // Make new windows requested by links behave like "window.open"
  17. this.webContents.on('-new-window', (event, url, frameName,
  18. disposition, additionalFeatures,
  19. postData) => {
  20. const options = {
  21. show: true,
  22. width: 800,
  23. height: 600
  24. }
  25. ipcMain.emit('ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPEN',
  26. event, url, frameName, disposition,
  27. options, additionalFeatures, postData)
  28. })
  29. this.webContents.on('-web-contents-created', (event, webContents, url,
  30. frameName) => {
  31. v8Util.setHiddenValue(webContents, 'url-framename', {url, frameName})
  32. })
  33. // Create a new browser window for the native implementation of
  34. // "window.open"(sandbox mode only)
  35. this.webContents.on('-add-new-contents', (event, webContents, disposition,
  36. userGesture, left, top, width,
  37. height) => {
  38. let urlFrameName = v8Util.getHiddenValue(webContents, 'url-framename')
  39. if ((disposition !== 'foreground-tab' && disposition !== 'new-window') ||
  40. !urlFrameName) {
  41. return
  42. }
  43. let {url, frameName} = urlFrameName
  44. v8Util.deleteHiddenValue(webContents, 'url-framename')
  45. const options = {
  46. show: true,
  47. x: left,
  48. y: top,
  49. width: width || 800,
  50. height: height || 600,
  51. webContents: webContents
  52. }
  53. ipcMain.emit('ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPEN',
  54. event, url, frameName, disposition, options)
  55. })
  56. // window.resizeTo(...)
  57. // window.moveTo(...)
  58. this.webContents.on('move', (event, size) => {
  59. this.setBounds(size)
  60. })
  61. // Hide the auto-hide menu when webContents is focused.
  62. this.webContents.on('activate', () => {
  63. if (process.platform !== 'darwin' && this.isMenuBarAutoHide() && this.isMenuBarVisible()) {
  64. this.setMenuBarVisibility(false)
  65. }
  66. })
  67. // Change window title to page title.
  68. this.webContents.on('page-title-updated', (event, title) => {
  69. // Route the event to BrowserWindow.
  70. this.emit('page-title-updated', event, title)
  71. if (!this.isDestroyed() && !event.defaultPrevented) this.setTitle(title)
  72. })
  73. // Sometimes the webContents doesn't get focus when window is shown, so we
  74. // have to force focusing on webContents in this case. The safest way is to
  75. // focus it when we first start to load URL, if we do it earlier it won't
  76. // have effect, if we do it later we might move focus in the page.
  77. //
  78. // Though this hack is only needed on macOS when the app is launched from
  79. // Finder, we still do it on all platforms in case of other bugs we don't
  80. // know.
  81. this.webContents.once('load-url', function () {
  82. this.focus()
  83. })
  84. // Redirect focus/blur event to app instance too.
  85. this.on('blur', (event) => {
  86. app.emit('browser-window-blur', event, this)
  87. })
  88. this.on('focus', (event) => {
  89. app.emit('browser-window-focus', event, this)
  90. })
  91. // Subscribe to visibilityState changes and pass to renderer process.
  92. let isVisible = this.isVisible() && !this.isMinimized()
  93. const visibilityChanged = () => {
  94. const newState = this.isVisible() && !this.isMinimized()
  95. if (isVisible !== newState) {
  96. isVisible = newState
  97. const visibilityState = isVisible ? 'visible' : 'hidden'
  98. this.webContents.send('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', visibilityState)
  99. this.webContents.emit('-window-visibility-change', visibilityState)
  100. }
  101. }
  102. const visibilityEvents = ['show', 'hide', 'minimize', 'maximize', 'restore']
  103. for (let event of visibilityEvents) {
  104. this.on(event, visibilityChanged)
  105. }
  106. // Notify the creation of the window.
  107. app.emit('browser-window-created', {}, this)
  108. Object.defineProperty(this, 'devToolsWebContents', {
  109. enumerable: true,
  110. configurable: false,
  111. get () {
  112. return this.webContents.devToolsWebContents
  113. }
  114. })
  115. }
  116. BrowserWindow.getFocusedWindow = () => {
  117. for (let window of BrowserWindow.getAllWindows()) {
  118. if (window.isFocused()) return window
  119. }
  120. return null
  121. }
  122. BrowserWindow.fromWebContents = (webContents) => {
  123. for (const window of BrowserWindow.getAllWindows()) {
  124. if (window.webContents.equal(webContents)) return window
  125. }
  126. }
  127. BrowserWindow.fromDevToolsWebContents = (webContents) => {
  128. for (const window of BrowserWindow.getAllWindows()) {
  129. const {devToolsWebContents} = window
  130. if (devToolsWebContents != null && devToolsWebContents.equal(webContents)) {
  131. return window
  132. }
  133. }
  134. }
  135. // Helpers.
  136. Object.assign(BrowserWindow.prototype, {
  137. loadURL (...args) {
  138. return this.webContents.loadURL(...args)
  139. },
  140. getURL (...args) {
  141. return this.webContents.getURL()
  142. },
  143. reload (...args) {
  144. return this.webContents.reload(...args)
  145. },
  146. send (...args) {
  147. return this.webContents.send(...args)
  148. },
  149. openDevTools (...args) {
  150. return this.webContents.openDevTools(...args)
  151. },
  152. closeDevTools () {
  153. return this.webContents.closeDevTools()
  154. },
  155. isDevToolsOpened () {
  156. return this.webContents.isDevToolsOpened()
  157. },
  158. isDevToolsFocused () {
  159. return this.webContents.isDevToolsFocused()
  160. },
  161. toggleDevTools () {
  162. return this.webContents.toggleDevTools()
  163. },
  164. inspectElement (...args) {
  165. return this.webContents.inspectElement(...args)
  166. },
  167. inspectServiceWorker () {
  168. return this.webContents.inspectServiceWorker()
  169. },
  170. showDefinitionForSelection () {
  171. return this.webContents.showDefinitionForSelection()
  172. },
  173. capturePage (...args) {
  174. return this.webContents.capturePage(...args)
  175. },
  176. setTouchBar (touchBar) {
  177. electron.TouchBar._setOnWindow(touchBar, this)
  178. }
  179. })
  180. module.exports = BrowserWindow