No stupid questions
No stupid questions

Reputation: 485

Electron prevent main window from closing

I am writing an application in electron where if a user has a unsaved file open I want to prompt the user before saving it. I found this example code online:

window.onbeforeunload = (e) => {
      var answer = confirm('Do you really want to close the application?');
      e.returnValue = answer;  // this will *prevent* the closing no matter what value is passed
      if(answer) { mainWindow.destroy(); }  // this will close the app
    };

This code strangely works if the dialogs Yes, Cancel or X button is pressed within a few seconds of appearing but if you let the dialog rest on screen for a little and then click a button the application will close no matter what is pressed.

This code is located in the my main script file called by index.html

Upvotes: 3

Views: 4593

Answers (3)

Xavier GRANDJEAN
Xavier GRANDJEAN

Reputation: 31

In my case, I had to use a variable called modificationEnCours which is true when I don't want to close my window and then false if I want to like that:

let mainWindow 
let mainMenu // Menu de la fenêtre principale

app.on('ready', () => {
  // Listen for app to be ready

  // Create the mainWindow 
  mainWindow = new BrowserWindow({
    width: 1024,
    height: 768,
    minHeight: 350,
    minWidth: 500,
    frame: true, 
    webPreferences: {
      nodeIntegration: true
    }
    })

  // Quit app when window is closed
  mainWindow.on('close', function(e){
    console.log('close')
    if (modificationEnCours){
      e.preventDefault()
    
      if(msgBoxVerifieSauvegarde('Question','Voulez-vous enregistrer avant de quitter ?')) {
        modificationEnCours=false
        app.quit()
      }
    } else if (process.platform !== 'darwin') {
      modificationEnCours=false
      app.quit()
      mainWindow = null
    }
  })


  // Load html in window
  mainWindow.loadFile(path.join(__dirname, 'mainWindow.html'))


  // Build menu from template
  mainMenu = Menu.buildFromTemplate(mainMenuTemplate)
  // Insert menu
  Menu.setApplicationMenu(mainMenu)
})

Upvotes: 0

Jerome
Jerome

Reputation: 396

It might be possible only when DevTools window is activated.

In any case, prefer working with the event close as pergy suggested above. This is so far the best approach.

But be aware that e.preventDefault() is spreading everywhere in the code. Once you managed properly the preventDefault() you need to turn the variable e.defaultPrevented = false to get back to the natural behavior of your app.

Actually, it seems e.preventDefault() function is turnind the variable e.defaultPrevented to true until you change its value.

Upvotes: 0

pergy
pergy

Reputation: 5531

Really strange behavior! I cannot explain why it's happening, but can give you a workaround implemented in main process.

You can use electron's dialog module and create the same confirmation dialog with electron. This one works as expected.

main.js

const { app, BrowserWindow, dialog } = require('electron')
const path = require('path')

app.once('ready', () => {
  let win = new BrowserWindow()
  win.loadURL(path.resolve(__dirname, 'index.html'))
  win.on('close', e => {
    let choice = dialog.showMessageBox(
      win,
      {
        type: 'question',
        buttons: ['Yes', 'No'],
        title: 'Confirm',
        message: 'Do you really want to close the application?'
      }
    )
    if (choice === 1) e.preventDefault()
  })
})

Upvotes: 5

Related Questions