Skip to content

feat(oncontextmenu): 右键上下文菜单事件 - #66

Merged
Cyaim merged 1 commit into
mainfrom
feat/oncontextmenu
Jul 24, 2026
Merged

Cyaim merged 1 commit into
mainfrom
feat/oncontextmenu

Conversation

@Cyaim

@Cyaim Cyaim commented Jul 24, 2026

Copy link
Copy Markdown
Owner

目标

「手写组件完成功能」的又一常缺原语:右键(上下文)菜单(调研 28 缺口)。框架负责派发右键事件,菜单本身由用户在回调里开 overlay。

改动

  • sv-ui:ViewNode.on_context_menu: Fn(f32, f32)(参数=点击处逻辑坐标,用于定位菜单)+ set_on_context_menu/context_menu_handler。禁用节点取不到(与 click_handler 同门)。
  • sv-shell:Pane::handle_window_event 新增 MouseButton::Right Pressed 臂——命中最上层带 oncontextmenu 的节点,以逻辑坐标调回调(用户据此 overlay Anchor::Point 开菜单)。
  • sv-compiler:oncontextmenu={|x, y| …} → set_on_context_menu(走 with_captured_plain 防元素级 E0382);未知 on* 事件的错误提示同步补上 onscroll/oncontextmenu。

验证

  • context_menu_handler_carries_pos_and_disabled_gates(sv-ui):坐标透传 + 禁用门。
  • oncontextmenu_compiles(sv-compiler):落地 set_on_context_menu + 未知事件提示含 oncontextmenu。
  • cargo test -p sv-ui -p sv-compiler -p sv-shell:全绿(98 + 87/golden + 110),golden 无回退。
  • cargo fmt --all + clippy + cargo build --workspace:干净。

诚实边界:右键事件派发已全;右键在无显示器环境的真实触发(winit MouseButton::Right)与其它窗口化行为一样需显示器手验,但派发逻辑镜像已验证的 pointer_down 命中路径,且回调存取/坐标/禁用门已离屏测。

🤖 Generated with Claude Code

手写组件的右键菜单能力(调研 28 缺口):框架派发右键事件,菜单本身由用户在
回调里开 overlay。

- **sv-ui**:`ViewNode.on_context_menu: Fn(f32, f32)`(点击处逻辑坐标)+
  `set_on_context_menu`/`context_menu_handler`。禁用节点取不到(与 click_handler 同门)。
- **sv-shell**:`Pane::handle_window_event` 加 `MouseButton::Right` Pressed 臂——
  命中最上层带 oncontextmenu 的节点,以逻辑坐标调回调(用户据此 overlay Anchor::Point)。
- **sv-compiler**:`oncontextmenu={|x, y| …}` → set_on_context_menu(走 with_captured_plain);
  未知 on* 事件错误提示同步补上 onscroll/oncontextmenu。
- 守卫:`context_menu_handler_carries_pos_and_disabled_gates`(sv-ui,坐标透传 + 禁用门)
  + `oncontextmenu_compiles`(sv-compiler)。sv-shell 110 测试全绿、golden 无回退。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Cyaim
Cyaim merged commit c5358f2 into main Jul 24, 2026
16 checks passed
@Cyaim
Cyaim deleted the feat/oncontextmenu branch July 24, 2026 13:58
Cyaim added a commit that referenced this pull request Jul 26, 2026
对 7-24/7-25 全部 17 个提交(#55–#71,+10429/−1243)逐行复核。结论:16 个干净
(#55 span 契约、#56 金样对拍、#58 对称修复、#59 门控、#60/#62 捕获份、#64 拆分
路由、#66/#67/#68 事件面等均核实无误);#65(disabled)查获两处真实缺口,本提交修:

- **① Tab 环落在禁用节点上**:`focus_next/prev` 走的内部 `focusables()` 遍历读
  **裸** `focusable` 字段,没过公开 getter `focusable()` 的禁用门——两个读取口、
  门只装了一个。已改为同门过滤(`n.focusable && !n.disabled`)。
- **② 获焦期间被禁用不清焦点**:焦点环留在禁用控件上、TextInput 的 IME 会话
  不关、键盘事件(key_handler 无禁用门)继续派发——可向禁用输入框打字。
  `set_disabled(true)` 对当前焦点节点现自动 `blur()`(失焦回调照发,浏览器同款)。
- 顺带 ③ `focus(禁用节点)` 改 no-op(浏览器同款;shell 点击设焦/a11y Focus 动作
  本已设门,这是纵深防御)。

守卫:disabled_focus_surface_tab_skip_blur_and_focus_noop(sv-ui,三缺口各钉一段)。
方法论点(已记 open-issues):加交互门时应 grep 全部字段读取点,而不只改 getter。

复核中另核销一个疑点:空体 {#each} 早退路径绕过 list_cl 内层捕获,疑 E0382——
实证不复现(语句级外层捕获份挡住,空体语句内仅一个闭包),往 multiclosure-check
的 Check.svelte 加两行空体 each 共享 plain 的真编译守卫钉住该防线。

全仓 596 测试绿、clippy 净。

Co-authored-by: Psyche <review@local>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant