'How to capture the window close event on Electron's renderer process?
On a classic front-end JavaScript, capturing the "window close" event can be done in a multiple ways. It can be done with:
// Method A: `close` event via an event listener
window.addEventListener( 'close', function(event){ /** your magic here **/ } )
// Method B: `beforeunload` event via an event listener
window.addEventListener( 'beforeunload', function(event){ /** your magic here **/ } )
// Method C: classic `onclose` event binder
window.onclose = function(event){ /** your magic here **/ }
// Method D: classic `onbeforeunload` event binder
window.onbeforeunload = function(event){ /** your magic here **/ }
I tried these methods inside the Electron's renderer
script/environment but the window close event doesn't seem to get triggered.
Which brings to my question, how to capture the "window close" event on Electron's renderer process?
Solution 1:[1]
According to Electron's official documentation:
Event: "before-quit" Emitted before the application starts closing its windows. Calling event.preventDefault() will prevent the default behavior, which is terminating the application.
So you need to use the before-quit
event on your Electron application.
Solution 2:[2]
Normally, proving that these events trigger (or not) is difficult as the render process would normally close prior to confirmation.
Instead, through the use of Inter-Process Communication, one can tell if any of these events trigger by sending one or more messages back to the main process for viewing.
To test this, I have implemented a simple preload.js
, main.js
and index.html
script.
preload.js
(main process)
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;
contextBridge.exposeInMainWorld(
'ipcRender', {
send: (message) => {
ipcRenderer.send('closing', message);
}
});
main.js
(main process)
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const electronIpcMain = require('electron').ipcMain;
const nodePath = require('path');
let window;
function createWindow() {
const window = new electronBrowserWindow({
x: 0,
y: 0,
width: 800,
height: 600,
show: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: nodePath.join(__dirname, 'preload.js')
}
});
window.loadFile('index.html')
.then(() => { window.show(); });
return window;
}
electronApp.on('ready', () => {
window = createWindow();
});
electronApp.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
electronApp.quit();
}
});
electronApp.on('activate', () => {
if (electronBrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// Testing
electronIpcMain.on('closing', (event, message) => {
console.log(message);
})
index.html
(render process)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Electron Test</title>
</head>
<body>
<input type="button" id="button" value="Close">
</body>
<script>
// Method A: `close` event via an event listener
window.addEventListener('close', (event) => {
window.ipcRender.send('Method A'); // Doesn't work
})
// Method B: `beforeunload` event via an event listener
window.addEventListener('beforeunload', (event) => {
window.ipcRender.send('Method B'); // Works
})
// Method C: classic `onclose` event binder
window.onclose = (event) => {
window.ipcRender.send('Method C'); // Doesn't work
}
// Method D: classic `onbeforeunload` event binder
window.onbeforeunload = (event) => {
window.ipcRender.send('Method D'); // Works
}
// Method E: `click' event via an event listener
document.getElementById('button').addEventListener('click', () => {
// Let's pretent that this can close the window from the main process
window.ipcRender.send('Method E');
})
</script>
</html>
Below is the result when closed via the traffic light close button or the task bar close menu.
Method B // `beforeunload` event via an event listener
Method D // classic `onbeforeunload` event binder
Depending on how one (correctly or incorrectly) implements their preload.js
script, one may receive no results compared to the results shown above.
Whilst I usually implement my
preload.js
script differently to that shown above, I have kept it simple and inline with what most people appear to be familiar with. IE:Context Isolation (Enabled)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | akaAbdullahMateen |
Solution 2 | midnight-coding |