Skip to content

[Bug] Linux 下托盘图标右键菜单无法展开(popUpContextMenu 在 Linux 无效,需改用 setContextMenu) #716

Description

@unknown-gezi
  • 你是否在现有 Issue列表 中搜索过相同问题,但未找到?

说明:已检索 托盘 / tray / menu / right-click 等关键词。
#472 是「KDE 托盘增加退出按钮」的功能请求,#667 是「root 权限启动的兼容性问题」,均与本问题不同。

Ⅰ. 请说明操作系统及DS的版本号:

  1. 操作系统:Debian GNU/Linux 13 (trixie) amd64,桌面环境 Cinnamon 6.4.10,X11 会话
  2. DS版本号:2.2.0(Debian 包 DevSidecar-2.2.0-linux-x86_64.deb,内置 Electron 41.3.0 / Chrome 146.0.7680.188)

Ⅱ. 问题描述:

在 Linux 下,右键点击系统托盘的 DS 图标不会弹出任何菜单,DevTools (F12) 与 退出 两项都看不到(左键单击可以正常显示主窗口)。

经排查,这不是用户配置或桌面环境的问题,而是 packages/gui/src/background.js 中 setTray() 的实现 bug:

// packages/gui/src/background.js  (master)
// 第 184~188 行
appTray.on('right-click', () => {
  setTimeout(() => {
    appTray.popUpContextMenu(contextMenu)
  }, 200)
})

全部菜单都是通过 popUpContextMenu() 弹出的,但 Electron 官方文档明确标注该方法仅支持 macOS 和 Windows:

tray.popUpContextMenu([menu, position]) macOS Windows

tray.setContextMenu(menu)

Sets the context menu for this icon.

(来源:Electron 官方 docs/api/tray.md)

因此该调用在 Linux 上是静默失效的(不报错、无日志)。而 Linux 下必须通过 appTray.setContextMenu(contextMenu) 把菜单注册到托盘项,Electron 才会经由 com.canonical.dbusmenu 导出菜单。

补充:setContextMenu 一次都没有被调用过——全仓库检索 setContextMenu 出现次数为 0,popUpContextMenu 为 1。

实测证据(DBus 层)

修复前,托盘项虽然注册成功,但导出的 dbusmenu 子项为空,所以桌面环境拿不到任何菜单项:

$ gdbus call --session --dest org.kde.StatusNotifierWatcher \
    --object-path /StatusNotifierWatcher \
    --method org.freedesktop.DBus.Properties.Get \
    org.kde.StatusNotifierWatcher RegisteredStatusNotifierItems
(<[':1.66/StatusNotifierItem',
   ':1.124/StatusNotifierItem',                       <-- dev-sidecar
   'org.freedesktop.StatusNotifierItem-10779-1/StatusNotifierItem']>,)

$ dbus-send --session --print-reply --dest=:1.124 /com/canonical/dbusmenu \
    com.canonical.dbusmenu.GetLayout int32:0 int32:-1 array:string:
   uint32 0
   struct {
      int32 0
      array [
         dict entry(
            string "children-display"
            variant  string "submenu"
         )
      ]
      array [
      ]                          <-- children 为空,没有任何菜单项!
   }

注意 Menu 属性其实是有值的(objectpath '/com/canonical/dbusmenu'),只是里面没有任何条目,因此表现为"点了没反应"。

修复后对比(仅加了一个 setContextMenu 调用)

$ dbus-send --session --print-reply --dest=:1.175 /com/canonical/dbusmenu \
    com.canonical.dbusmenu.GetLayout int32:0 int32:-1 array:string:
   uint32 0
   struct {
      int32 0
      array [ string "children-display" -> "submenu" ]
      array [
         struct { int32 1  [ label -> "DevTools (F12)" ]  [] }   <-- 出现了
         struct { int32 2  [ label -> "退出" ]            [] }   <-- 出现了
      ]
   }

同时用 X11 合成事件真实右键托盘图标,弹出的菜单区域稳定存在(把鼠标移开后菜单仍保持显示,点击别处才消失),确认菜单可以正常展开、也可以正常点击。

Ⅲ. 期望的结果:

  1. Linux 下右键托盘图标能正常弹出 DevTools (F12) / 退出 菜单。
  2. setTray() 按平台分流:Linux 使用 setContextMenu(),macOS / Windows 保持原有 popUpContextMenu() 行为不变。

建议改法(packages/gui/src/background.js):

  // 图标的上下文菜单
  const contextMenu = Menu.buildFromTemplate(trayMenuTemplate)

  // 设置托盘悬浮提示
  appTray.setToolTip('DevSidecar-开发者边车辅助工具')
  // 单击托盘小图标显示应用
  appTray.on('click', () => {
    // 显示主程序
    showWin()
  })

-  appTray.on('right-click', () => {
-    setTimeout(() => {
-      appTray.popUpContextMenu(contextMenu)
-    }, 200)
-  })
+  if (isLinux) {
+    // Linux 必须把菜单注册到托盘项,右键菜单才能展开;
+    // popUpContextMenu() 仅支持 macOS/Windows,在 Linux 下无效。
+    appTray.setContextMenu(contextMenu)
+  } else {
+    appTray.on('right-click', () => {
+      setTimeout(() => {
+        appTray.popUpContextMenu(contextMenu)
+      }, 200)
+    })
+  }

  return appTray

isLinux 在该文件第 16 行已定义(const isLinux = process.platform === 'linux'),无需新增变量。

附注:Linux + libappindicator/StatusNotifierItem 的机制下,菜单注册后通常左右键都会弹出菜单,原本 appTray.on('click') → showWin() 的"左键显示主窗口"可能被桌面环境接管。这点建议作者按实际预期取舍;若希望保留"左键显示窗口",可同时在菜单里补一个「显示主窗口」项。

Ⅳ. 如何复现问题?

  1. 在 Linux(实测 Debian 13 + Cinnamon 6.4.10 / X11)安装 DevSidecar-2.2.0-linux-x86_64.deb 并启动。
  2. 确认系统托盘出现 DS 图标(图标本身显示正常)。
  3. 用鼠标右键点击该托盘图标。
  4. 观察结果:不会弹出任何菜单。

命令行复核方式:

# 1. 找到 dev-sidecar 的 SNI 总线名(用它的 PID 对上)
gdbus call --session --dest org.kde.StatusNotifierWatcher \
  --object-path /StatusNotifierWatcher \
  --method org.freedesktop.DBus.Properties.Get \
  org.kde.StatusNotifierWatcher RegisteredStatusNotifierItems

# 2. 查看该托盘项导出的菜单布局
dbus-send --session --print-reply --dest=:1.xxx /com/canonical/dbusmenu \
  com.canonical.dbusmenu.GetLayout int32:0 int32:-1 array:string:
#   修复前:children 为空数组 []
#   修复后:children 含 "DevTools (F12)" 与 "退出"

影响范围推测:由于是跨平台的 Electron API 用法问题,理论上所有 Linux 桌面环境(GNOME / KDE / Cinnamon / XFCE 等)都存在该问题,欢迎其他发行版用户补充验证。

Ⅴ. 请提供相关的错误日志,尽可能的详细:(日志文件在 ${user.home}/.dev-sidecar/logs/ 目录下)

本问题没有任何报错日志,这正是它容易被忽略的原因——popUpContextMenu() 在 Linux 上是静默 no-op,core.log / gui.log / server.log 中都不会留下任何痕迹。日志中仅能看到托盘创建成功、代理服务正常启动:

点击查看日志
[2026-09-26T18:05:16.xxx] [INFO] gui  - background.js start, platform is linux
[2026-09-26T18:05:19.xxx] [INFO] core - 开启系统代理成功:127.0.0.1:31181
[2026-09-26T18:05:19.xxx] [INFO] core - status changed: { key: 'server.enabled', value: true }

(托盘创建、菜单构建均无任何 ERROR / WARN,符合"静默失效"的特征。)

Ⅵ. 有必要时,请提供 ${user.home}/.dev-sidecar/running.json 文件内容:

与配置无关,~/.dev-sidecar/config.json 为默认配置(不存在该文件),本问题在全新安装、未做任何自定义配置的情况下即可复现。

点击查看运行参数
{
  "note": "本问题与配置无关,全新安装即可复现;此处省略 running.json 全文。",
  "app": { "mode": "default" },
  "server": { "enabled": true, "host": "127.0.0.1", "port": 31181 }
}

给维护者的补充信息

  • 本地验证环境:Debian 13 (trixie)、Cinnamon 6.4.10、X11、Electron 41.3.0。
  • 本地采用的最小改动:仅修改 resources/app.asar 内的 src/background.js(对应源码 packages/gui/src/background.js),其余 20928 个归档文件字节完全一致(已逐个校验 SHA256)。
  • 改动后 node --check 语法校验通过;代理服务、系统代理、根证书、开机自启等功能均无回归。
  • 如果作者需要,我可以补一个 PR。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugSomething isn't workingGood first issueGood for newcomersknown issues确认存在的问题

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions