如何使 Electron 托盘点击事件可靠地工作?

How to make Electron tray click events working reliably?

在我的 OSX Electron 应用程序中,我有一个托盘图标,我想在打开和关闭 Electron 应用程序 window 之间切换。类似于单击 OSX Dropbox 托盘图标打开和关闭 Dropbox 托盘菜单的方式,无论您单击托盘图标的速度有多快。

这是我使用的代码:

  tray.on('click', function(e){
    if (mainWindow.isVisible()) {
      mainWindow.hide()
    } else {
      mainWindow.show()
    }
  });

如果您缓慢单击(在单击之间等待一秒钟),则此方法有效,但是如果您重复单击,一秒钟内单击超过 1 次,则单击失败并且没有任何反应。我在文档中找不到任何类型的延迟。关于发生了什么以及如何使点击事件可靠地工作有什么想法吗?

您描述的问题很容易重现。你得到的结果不是你这边的错误或错误的实现,而是关于 Electron 当前处理托盘元素上的这些点击事件的方式的预期结果。

class Tray 公开了 3 个与点击相关的事件:clickdouble-clickright-click

如果你使用 right-click 事件,你不会有这个问题,你可以按你想要的速度点击,每次都会调用你的回调。

例如,用于处理此事件的 macOS 的 Electron 代码是 the following:

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

每次右键单击,他们都会触发 right-click 事件,仅此而已。

现在,如果我们看一下左键单击的处理方式,the code 略有不同:

- (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];
}

当托盘图标被多次点击时,event.clickCount 并不总是 return 1。相反,它 return 是一个计算点击次数的值。

因此,当您快速单击托盘图标时,event.clickCount 的值将大于 2,并且它们仅在值为 1 时才发出事件或 2 如果不是这种情况,它们没有任何回退,它们只是不发出任何事件。这就是您在足够快地点击时在测试中看到的结果。

因此,如果不自己修改 Electron 实现、提交问题或拉取请求,您目前无法避免这种行为。

Electron 3.0 引入了一个 API 来防止等待双击。

// 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