fix(vocab-card): 收起添加词卡片后,胶囊要回到屏幕中间 - #969
Open
bigsongeth wants to merge 2 commits into
Open
Conversation
卡片和录音胶囊是同一个窗口。弹卡片要把窗口挪到右下角,收卡片时
`hide_vocab_suggestion_card` 还了尺寸、还了鼠标穿透,唯独没还位置 ——
于是下一次录音,胶囊出现在右下角。
漏这一步之所以致命,是因为 `maybe_position_capsule_bottom_center` 有个
去重缓存,而那个缓存只记「显示器 + 翻译态」。卡片这一挪它一无所知,
下次录音时拿到相同的显示器快照就判定「没变化」,直接跳过重新定位。
换句话说:窗口被挪走了,而唯一会把它挪回来的那段代码以为自己不用动。
所以复位和清缓存两件事都做,各堵一个方向:清缓存保证「就算这次复位
失败,下一次 emit_capsule 也一定会重算」;复位保证「就算有哪条路径
绕过 emit_capsule 直接 show,窗口也已经在对的地方」。
顺带把同一形状的另一处堵上:卡片直接调 set_ignore_cursor_events,却没
同步 `capsule_cursor_passthrough` 那个缓存。目前触发不了,但一旦缓存和
窗口真实状态分家,emit_capsule 就会跳过它该调的那一次 —— 表现是经典
胶囊上的 ✓/✕ 点不动。
复位顺序改成先 hide 再改几何:尺寸和位置要一起动,窗口还亮着时改就有
概率被合成出一帧「卡片被拉宽、还横着飞过半个屏幕」。
真机量过(临时脚手架 + CGWindowList 取窗口 frame,外接屏 1920x1080):
修复前 录音 → x=453(居中)→ 卡片 x=1299(右下)→ 收卡片后窗口
仍在 x=1299 → 下一次录音胶囊 x=1299 ← bug
修复后 录音 → x=526(居中)→ 卡片 x=1168(右下)→ 收卡片当场回到
x=453(居中)→ 下一次录音胶囊 x=453 ← 对
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit d3fedcd13da0a3ba002a6f29dda330eeabee62f1)
上一条修复(收起卡片时把胶囊位置也还回去)在 8 月丢过一次 —— 它只活在 一个没合并的本地分支上,主线从 PR Open-Less#917 重新长出了漏还位置的版本,于是 真机 bug 原样复发:用过一次带添加词的卡片,下一次录音的胶囊就出现在 右下角,再也回不到底部居中。 这类不变量单测抓不到:整段是 Tauri 窗口调用,跑在 run_on_main_thread 的 闭包里,没有窗口就没有断言对象。所以按 repo 既有的做法收进 macos-capsule-spaces-contract —— 那个文件已经是「胶囊窗口几何」这类 源码级不变量的归属地(多屏定位缓存那条就在里面)。 守两侧四个函数(词条卡片 + 落字回退卡片): 弹卡片:挪走了共享窗口,就必须让 capsule_layout 去重缓存当场作废, 并同步 capsule_cursor_passthrough 收卡片:穿透、尺寸、位置、两个缓存,一样都不能少;且必须先 hide 再改几何(否则复原会被合成出一帧横飞过半个屏幕的动画) 「还位置」和「清缓存」分开断言是有意的:这两件事各堵一个方向,漏任何 一个 bug 都会回来,所以要能各自报出自己的名字。 验证(三态): 未修复的 coordinator.rs(HEAD~1) → 红,报 show_vocab_suggestion_card 缺 capsule_layout 失效 变异:只删掉 hide_vocab 里那一行 position_capsule_bottom_center → 红,且精确报出「restoring size alone leaves it in the card's bottom-right corner」 修复后 → 绿;npm test 全量退出码 0 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
用过一次"要不要把这个词加进词典"的卡片之后,下一次录音的胶囊会跑到屏幕右下角,而且再也回不到底部居中——除非重启 OpenLess。
这个 bug 其实修过一次,但那次修复只活在一个没合并的本地分支上,主线从没拿到过。这个 PR 把它接回来,并且钉了道保险,让它不会再丢第三次。
为什么会这样
卡片和录音胶囊是同一个窗口。弹卡片要把这个窗口缩到卡片大小、挪到右下角;收卡片时要原样还回去。当时还了尺寸、还了鼠标穿透,唯独没还位置。
漏这一步之所以致命,是因为负责把胶囊摆回中间的那段代码有个去重缓存,而缓存只记「显示器 + 翻译态」——卡片这一挪它一无所知。下次录音拿到相同的显示器快照就判定"没变化",直接跳过重新定位。说白了:窗口被挪走了,而唯一会把它挪回来的那段代码以为自己不用动。
技术细节
根因链
show_vocab_suggestion_cardcapsule窗口挪到右下角,不清capsule_layout缓存、不同步capsule_cursor_passthroughhide_vocab_suggestion_cardmaybe_position_capsule_bottom_center复位和清缓存两件事都做,各堵一个方向:清缓存保证「就算这次复位失败,下一次
emit_capsule也一定会重算」;复位保证「就算有哪条路径绕过emit_capsule直接 show,窗口也已经在对的地方」。顺带堵上同一形状的另一处:卡片直接调
set_ignore_cursor_events,却没同步capsule_cursor_passthrough那个缓存。目前触发不了,但一旦缓存和窗口真实状态分家,emit_capsule就会跳过它该调的那一次——表现是经典的"胶囊上的 ✓/✕ 点不动"。复位顺序是先
hide()再改几何:尺寸和位置要一起动,窗口还亮着时改就有概率被合成出一帧「卡片被拉宽、还横着飞过半个屏幕」。这个修复是怎么丢的
原提交
d3fedcd(8/5)写在 #917 从feat/cursor-context-vocabsquash 合入之后,就留在了本地分支上,主线重新长出了漏还位置的版本。一条旁证:#943 加的落字回退卡片照抄了这套修复,注释里写着「理由见
hide_vocab_suggestion_card」——但主线上那个函数里已经没有这段理由了。原件丢了,只剩副本。防回归
这类不变量单测抓不到:整段是 Tauri 窗口调用,跑在
run_on_main_thread的闭包里,没有窗口就没有断言对象。所以按 repo 既有做法收进macos-capsule-spaces-contract.test.mjs——那个文件已经是「胶囊窗口几何」这类源码级不变量的归属地(多屏定位缓存那条就在里面)。守两侧四个函数(词条卡片 + 落字回退卡片):
capsule_layout去重缓存当场作废,并同步capsule_cursor_passthroughhide()再改几何「还位置」和「清缓存」分开断言是有意的:这两件事各堵一个方向,漏任何一个 bug 都会回来,所以要能各自报出自己的名字。
验证
原修复当时在真机上量过(临时脚手架 +
CGWindowList取窗口 frame,外接屏 1920x1080):本 PR 的契约测试按三态验证,不是"写完就绿":
coordinator.rsshow_vocab_suggestion_card缺capsule_layout失效hide_vocab里那一行position_capsule_bottom_centernpm test全量退出码 0,cargo check --lib通过。🤖 Generated with Claude Code