browser-window.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. 'use strict'
  2. const {ipcMain} = require('electron')
  3. const {EventEmitter} = require('events')
  4. const {BrowserWindow} = process.atomBinding('window')
  5. const v8Util = process.atomBinding('v8_util')
  6. Object.setPrototypeOf(BrowserWindow.prototype, EventEmitter.prototype)
  7. BrowserWindow.prototype._init = function () {
  8. // Avoid recursive require.
  9. const {app} = require('electron')
  10. // Simulate the application menu on platforms other than macOS.
  11. if (process.platform !== 'darwin') {
  12. const menu = app.getApplicationMenu()
  13. if (menu) this.setMenu(menu)
  14. }
  15. // Make new windows requested by links behave like "window.open"
  16. this.webContents.on('-new-window', (event, url, frameName,
  17. disposition, additionalFeatures,
  18. postData) => {
  19. const options = {
  20. show: true,
  21. width: 800,
  22. height: 600
  23. }
  24. ipcMain.emit('ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPEN',
  25. event, url, frameName, disposition,
  26. options, additionalFeatures, postData)
  27. })
  28. this.webContents.on('-web-contents-created', (event, webContents, url,
  29. frameName) => {
  30. v8Util.setHiddenValue(webContents, 'url-framename', {url, frameName})
  31. })
  32. // Create a new browser window for the native implementation of
  33. // "window.open"(sandbox mode only)
  34. this.webContents.on('-add-new-contents', (event, webContents, disposition,
  35. userGesture, left, top, width,
  36. height) => {
  37. let urlFrameName = v8Util.getHiddenValue(webContents, 'url-framename')
  38. if ((disposition !== 'foreground-tab' && disposition !== 'new-window') ||
  39. !urlFrameName) {
  40. return
  41. }
  42. let {url, frameName} = urlFrameName
  43. v8Util.deleteHiddenValue(webContents, 'url-framename')
  44. const options = {
  45. show: true,
  46. x: left,
  47. y: top,
  48. width: width || 800,
  49. height: height || 600,
  50. webContents: webContents
  51. }
  52. ipcMain.emit('ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPEN',
  53. event, url, frameName, disposition, options)
  54. })
  55. // window.resizeTo(...)
  56. // window.moveTo(...)
  57. this.webContents.on('move', (event, size) => {
  58. this.setBounds(size)
  59. })
  60. // Hide the auto-hide menu when webContents is focused.
  61. this.webContents.on('activate', () => {
  62. if (process.platform !== 'darwin' && this.isMenuBarAutoHide() && this.isMenuBarVisible()) {
  63. this.setMenuBarVisibility(false)
  64. }
  65. })
  66. // Change window title to page title.
  67. this.webContents.on('page-title-updated', (event, title) => {
  68. // The page-title-updated event is not emitted immediately (see #3645), so
  69. // when the callback is called the BrowserWindow might have been closed.
  70. if (this.isDestroyed()) return
  71. // Route the event to BrowserWindow.
  72. this.emit('page-title-updated', event, title)
  73. if (!event.defaultPrevented) this.setTitle(title)
  74. })
  75. // Sometimes the webContents doesn't get focus when window is shown, so we
  76. // have to force focusing on webContents in this case. The safest way is to
  77. // focus it when we first start to load URL, if we do it earlier it won't
  78. // have effect, if we do it later we might move focus in the page.
  79. //
  80. // Though this hack is only needed on macOS when the app is launched from
  81. // Finder, we still do it on all platforms in case of other bugs we don't
  82. // know.
  83. this.webContents.once('load-url', function () {
  84. this.focus()
  85. })
  86. // Redirect focus/blur event to app instance too.
  87. this.on('blur', (event) => {
  88. app.emit('browser-window-blur', event, this)
  89. })
  90. this.on('focus', (event) => {
  91. app.emit('browser-window-focus', event, this)
  92. })
  93. // Subscribe to visibilityState changes and pass to renderer process.
  94. let isVisible = this.isVisible() && !this.isMinimized()
  95. const visibilityChanged = () => {
  96. const newState = this.isVisible() && !this.isMinimized()
  97. if (isVisible !== newState) {
  98. isVisible = newState
  99. this.webContents.send('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', isVisible ? 'visible' : 'hidden')
  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. })
  177. module.exports = BrowserWindow