In my OSX Electron app I have a tray icon that I would like to toggle between opening and closing the Electron app window. Similar to how clicking on the OSX Dropbox tray icon will open and close the Dropbox tray menu, no matter how fast you click the tray icon.
Here is the code I'm using:
tray.on('click', function(e){
if (mainWindow.isVisible()) {
mainWindow.hide()
} else {
mainWindow.show()
}
});
This works if you click slowly (wait a second between clicks) however if you click repeatedly, more than 1x in a second, the click fails and nothing happens. I couldn't find any type of delays in the docs. Any ideas on what's going on and how to make the click event work 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With