Let Chromium manage document.visibilityState and document.hidden

Chromium already includes the necessary plumbing to manage the
visibility properties and `visibilitychange` event so this gets rid of
most of our custom logic for `BrowserWindow` and `BrowserView`.

Note that `webview` remains unchanged and is still affected by the issues
listed below.

User facing changes:

- The `document` visibility properties and `visibilitychange` event are
  now also updated/fired in response to occlusion changes on macOS. In
  other words, `document.visibilityState` will now be `hidden` on macOS
  if the window is occluded by another window.

- Previously, `visibilitychange` was also fired by *both* Electron and
  Chromium in some cases (e.g. when hiding the window). Now it is only
  fired by Chromium so you no longer get duplicate events.

- The visiblity state of `BrowserWindow`s created with `{ show: false }`
  is now initially `visible` until the window is shown and hidden.

- The visibility state of `BrowserWindow`s with `backgroundThrottling`
  disabled is now permanently `visible`.

This should also fix #6860 (but not for `webview`).
This commit is contained in:
Birunthan Mohanathas 2017-05-22 21:10:10 +03:00 committed by Kevin Sawicki
parent d40a7569cc
commit 7d2226e05e
11 changed files with 175 additions and 90 deletions

View file

@ -1412,6 +1412,111 @@ describe('BrowserWindow module', function () {
})
})
describe('document.visibilityState', function () {
afterEach(function () {
ipcMain.removeAllListeners('pong')
})
function onNextVisibleEvent (callback) {
ipcMain.on('pong', function listener (event, visibilityState, hidden) {
if (visibilityState === 'visible' && hidden === false) {
ipcMain.removeListener('pong', listener)
callback()
}
})
}
function onNextHiddenEvent (callback) {
ipcMain.on('pong', function listener (event, visibilityState, hidden) {
if (visibilityState === 'hidden' && hidden === true) {
ipcMain.removeListener('pong', listener)
callback()
}
})
}
it('visibilityState is initially visible despite window being hidden', function (done) {
w.destroy()
w = new BrowserWindow({ show: false, width: 100, height: 100 })
let readyToShow = false
w.on('ready-to-show', function () {
readyToShow = true
})
ipcMain.once('pong', function (event, visibilityState, hidden) {
assert.ok(!readyToShow)
assert.equal(visibilityState, 'visible')
assert.equal(hidden, false)
ipcMain.once('pong', function (event, visibilityState, hidden) {
assert.ok(false)
})
setTimeout(done, 1000)
w.show()
})
w.loadURL('file://' + path.join(fixtures, 'pages', 'visibilitychange.html'))
})
it('visibilityState changes when window is shown and hidden', function (done) {
w.destroy()
w = new BrowserWindow({
width: 100,
height: 100
})
onNextVisibleEvent(() => {
onNextHiddenEvent(() => {
onNextVisibleEvent(() => {
onNextHiddenEvent(done)
w.minimize()
})
w.show()
w.focus()
})
w.hide()
})
w.loadURL('file://' + path.join(fixtures, 'pages', 'visibilitychange.html'))
})
it('visibilityState remains visible if backgroundThrottling is disabled', function (done) {
w.destroy()
w = new BrowserWindow({
show: false,
width: 100,
height: 100,
webPreferences: {
backgroundThrottling: false
}
})
onNextVisibleEvent(() => {
onNextVisibleEvent(() => {
done(new Error('Unexpected visibility change event to visible'))
})
onNextHiddenEvent(() => {
done(new Error('Unexpected visibility change event to hidden'))
})
w.once('show', () => {
w.once('hide', () => {
w.once('show', () => {
done()
})
w.show()
})
w.hide()
})
w.show()
})
w.loadURL('file://' + path.join(fixtures, 'pages', 'visibilitychange.html'))
})
})
describe('new-window event', function () {
if (isCI && process.platform === 'darwin') {
return
@ -2318,9 +2423,7 @@ describe('BrowserWindow module', function () {
typeofArrayPush: 'number',
typeofFunctionApply: 'boolean',
typeofPreloadExecuteJavaScriptProperty: 'number',
typeofOpenedWindow: 'object',
documentHidden: true,
documentVisibilityState: 'hidden'
typeofOpenedWindow: 'object'
}
}