From 20f4a4a5ce4744a2be186129c37885b1d8de0f6b Mon Sep 17 00:00:00 2001 From: lexmin0412 Date: Tue, 9 Jun 2026 16:22:52 +0800 Subject: [PATCH] fix(ui): prevent Ctrl+right-click from closing context menu immediately on macOS Root cause: macOS emits a synthetic click event when the right mouse button is released while holding Control. The outside-dismiss handler was listening for click events in capture phase, which caught this synthetic event and closed the menu right after it opened. Fix: switch from click to pointerdown (with event.button === 0 guard) for outside-dismiss detection. pointerdown fires on press before contextmenu, so the right-button event (button:2) is filtered out before the menu even opens, and the synthetic click is never seen. --- .../desktop/src/components/ui/CustomContextMenu.vue | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/desktop/src/components/ui/CustomContextMenu.vue b/apps/desktop/src/components/ui/CustomContextMenu.vue index c43bd30a8..53a1acc67 100644 --- a/apps/desktop/src/components/ui/CustomContextMenu.vue +++ b/apps/desktop/src/components/ui/CustomContextMenu.vue @@ -54,7 +54,12 @@ function close() { show.value = false; } -function onClickOutside(e: MouseEvent) { +function onPointerDownOutside(e: PointerEvent) { + // Only respond to primary (left) button presses. This avoids a macOS + // issue where Ctrl+right-click generates a synthetic click event on + // mouseup. By using pointerdown (which fires on press, before + // contextmenu) instead of click, we never see that synthetic event. + if (e.button !== 0) return; const target = e.target as Node; const inMenu = menuRef.value?.contains(target); const inSub = subRef.value?.contains(target); @@ -78,13 +83,13 @@ function onResize() { watch(show, (val) => { if (val) { openMenus.add(close); - document.addEventListener("click", onClickOutside, true); + document.addEventListener("pointerdown", onPointerDownOutside, true); document.addEventListener("keydown", onKeydown); document.addEventListener("scroll", onScroll, true); window.addEventListener("resize", onResize); } else { openMenus.delete(close); - document.removeEventListener("click", onClickOutside, true); + document.removeEventListener("pointerdown", onPointerDownOutside, true); document.removeEventListener("keydown", onKeydown); document.removeEventListener("scroll", onScroll, true); window.removeEventListener("resize", onResize); @@ -229,7 +234,7 @@ function shortcutKeys(shortcut?: string): string[] { onBeforeUnmount(() => { openMenus.delete(close); - document.removeEventListener("click", onClickOutside, true); + document.removeEventListener("pointerdown", onPointerDownOutside, true); document.removeEventListener("keydown", onKeydown); document.removeEventListener("scroll", onScroll, true); window.removeEventListener("resize", onResize);