How to make Electron tray click events working reliably?

The problem you're describing is easy to reproduce. The result you're getting is not a bug or a wrong implementation on your side but it's the expected result regarding the current way Electron is handling these click events on a tray element.

The class Tray exposes 3 events relative to click: click, double-click and right-click.

If you use the right-click event, you're not going to have this issue, you can click as fast as you want, you'll get your callback called every times.

The Electron code for macOS for example to handle this event is the following:

- (void)rightMouseUp:(NSEvent*)event {
  trayIcon_->NotifyRightClicked(
    [self getBoundsFromEvent:event],
    ui::EventFlagsFromModifiers([event modifierFlags]));
}

For every right click, they're firing the right-click event and that's it.

Now if we take a look at how the left click are handled, the code is slightly different:

- (void)mouseUp:(NSEvent*)event {

  // ...
  // Truncated to only show the relevant part...
  // ...

  // Single click event.
  if (event.clickCount == 1)
    trayIcon_->NotifyClicked(
        [self getBoundsFromEvent:event],
        ui::EventFlagsFromModifiers([event modifierFlags]));

  // Double click event.
  if (event.clickCount == 2)
    trayIcon_->NotifyDoubleClicked(
        [self getBoundsFromEvent:event],
        ui::EventFlagsFromModifiers([event modifierFlags]));

  [self setNeedsDisplay:YES];
}

When the tray icon get clicked multiple times, the event.clickCount doesn't always return 1. Instead, it returns a value that counts the clicked times.

So when you're click the tray icon very fast, event.clickCount will have a value greater than 2 and they're only emitting an event when the value is 1 or 2 and if it's not the case, they don't have any fallback, they simply don't emit any event. That's the result you're seeing in your tests when clicking fast enough.

So without modifying the Electron implementation yourself, submitting an issue or a pull request, you can't at the moment avoid this behaviour.


Electron 3.0 introduced an API that prevents waiting for double-click.

// Ignore double click events for the tray icon
tray.setIgnoreDoubleClickEvents(true)

"Sets the option to ignore double click events. Ignoring these events allows you to detect every individual click of the tray icon. This value is set to false by default."

Related Docs | Release Notes for Electron 3.0