Detect and cancel Inkdrop exiting from plugin

Hey there,

I’m trying to add “close to tray” support to my Tray plugin (requested by a user). This requires the plugin to be able to detect when the window is closed, cancel the exit action, and hide the window. I’m having trouble with the first two of these.

My first attempt was to listen for the close event on the BrowserWindow and to call event.preventDefault(), but that does not cancel the exit action:

inkdrop.window.on('close', event => {
  hideToTray();

  // Only the first of these should be necessary, but trying them all to be sure it doesn't work
  event.preventDefault();
  event.returnValue = false;
  return false;
});

Then I tried to listen for the window:close command, hoping it would be possible to cancel it, but that doesn’t work either:

inkdrop.commands.add(document.body, {
  'window:close': event => {
    hideToTray();

    event.preventDefault();
    event.returnValue = false;
    return false;
  },
});

Then I tried to listen for the beforeunload event on the Window and setting event.returnValue to false as recommended by the Electron documentation, which does cancel the exit action:

window.addEventListener('beforeunload', e => {
  hideToTray();

  // Only the first of these should be necessary, but trying them all to be sure it doesn't work
  e.returnValue = false;
  e.preventDefault();
  return false;
});

However, this leaves Inkdrop in a weird state where it erroneously thinks it successfully exited. If the user then re-opens the application via the tray icon’s context menu (which calls inkdrop.window.show()) a white frameless window shows up, but Inkdrop won’t load again. If the user re-opens the application by triggering the application:toggle-main-window command with a global keybinding a white frameless window also shows up, and Inkdrop loads again like it was completely restarted. However, between “Inkdrop thinks it successfully exited” and “Inkdrop loads again” it does not deactivate previously activated plugins (it does activate them again), causing more unexpected issues like multiple tray icons appearing.

Is it possible for a plugin to detect and subsequently cancel Inkdrop exiting without Inkdrop thinking it exited in the process? I totally understand if this is out-of-scope for plugins, but figured asking can’t hurt.

In case you want to see for yourself what I mean with the weird behavior, I’ve prepared a Git branch with the third attempt here. You can load the plugin from that branch as follows (requires Yarn):

$ git clone https://github.com/jmerle/inkdrop-tray.git
$ cd inkdrop-tray
$ git checkout close-to-tray
$ yarn
$ ipm link --dev
# Go to Inkdrop Preferences > Plugins > tray > Enable "Close to tray" setting
# You can exit Inkdrop for real after it starts misbehaving using the "Quit" item in the tray icon's context menu

I have observed this behavior using Inkdrop 5.5.1 on Ubuntu 20.04 and Windows 10.

P.S. The “New Topic” template for the Support category still contains “If you have noob questions, you can ask them on our Discord server: https://discord.gg/QfsG5Kj”, despite that server being read-only now. You might want to change that.

Hi Jasper,

Thanks for the question.

The app main process is already listening to the BrowserWindow’s ‘close’ event to manage its windows.
When you handle the ‘close’ event, the app’s event handler has already run.
That’s why it can’t be canceled.
The app listens to ‘beforeunload’ event as well so that it can safely quit.
Samely, your handler runs after the app gets unloaded.
So does ‘window:close’ command.
It’s kind of hard to change the behaviors.

Instead, you can make another command bound with ‘ctrl-w’.
Of course, it doesn’t work for the system close button though.

Ah thanks, I’ve removed the link to Discord.

Hi Takuya,

Thanks for the explanation, that clears things up.

Fortunately that command already exists (application:toggle-main-window) and I’ve been a happy user of it for the past two years.

2 Likes