fix(app-iced): M116 r1 复审 —— 口径降级为「不承诺」、修掉伪造读数与两处错注释、圆角下发去重

四条 P1(全是「口径与证据不符」,行为未变):

1. 把「Win11 一定有系统圆角、边缘平滑」从事实降级:`corner.rs` 的平台矩阵改成
   「实测 / 解释 / 推断 / 未验」四列,并明写本机只测到「写入被接受 / 回读 E_INVALIDARG /
   无边框窗口没有 DWM 调整带」;设置页与 golden 的说明句改成「我们**请求**系统圆角,
   是否圆、边缘什么样由合成器决定」,不再承诺结果。
2. 删掉证据目录里那条伪造读数 `readback=2`:本机三种样式回读全是 `E_INVALIDARG`,
   该值物理上产不出来,也不可能由 `format_line` 产出。改成显式的「合成示例(非实测)」,
   并把每一栏标注成真实/示例来源。probe-table 的「没有一条是推断」标题一并拆开,
   结论 4/5 明确标为**解释**(并写明 Δframe 之差是样式位的同义反复,不能反推 DWM 决策)。
3. `keys.rs` 的「旧读新」语义按实际链路改写:1.4.0 读 1.5.0 文件走
   `SchemaCompat::check_url` → `ReadOnlyPreserveSchema` → `SchemaCompat::access` →
   `FileAccess::ReadOnly`,**整份配置只读**(值照读、`store.set` 报 `SettingError::ReadOnly`、
   `save` 跳过),不是「只是少一档」。
4. 两处错注释订正:
   - `hresult_ok` 的理由改成 `S_FALSE` 的通用语义,并明写 `0x7FF8FFA9` **不是** DWM 的返回值
     (本机实测是 `E_INVALIDARG 0x80070057`),那是我早期用 `unsigned_abs()` 打印 HRESULT 的产物;
     对应单测也把该常量标为「合成值,只用来钉规则」。
   - `DWMWA_VISIBLE_FRAME_BORDER_THICKNESS` 的文档改成「本机三样式三态实测全 1,不能当判据,
     仅作诊断读数」。

两条裁定:
- CPU 档在 Win11 仍走 DWM(tower 裁定保留):理由写进 `plan_corner` 文档——D36 约束的是我们自己的
  渲染路径,DWM 圆角是合成器侧的,不增加我方负担;设置页说明同步加了「软件渲染也一样」。
- 「圆角窗口上拖边缩放仍命中」实测未做(RDP 断开、无指针注入手段):mission 里以 note 记为 dropped
  (store 的 task_drop 对已完成任务不生效,工具层面无法取消勾选,已在 note 里写清)。

六条 P2:
1. probe-table 拆「实测 / 解释 / 未验」并删掉绝对化标题。
2. CPU 档裁定见上(任务书由 tower 侧调整)。
3. 拖边缩放任务记账更正见上。
4. **圆角下发去重**:新增 `corner::{CornerApplied, needs_redispatch}`(指纹 = 策略 / 来源 /
   原因码 / 有没有句柄,不含只有真下发才拿得到的读数),`App::apply_window_corner` 改成
   `&mut self` 并在判定未变时**直接返回**(不动窗口、不打日志);`App` 新增 `corner_applied` 字段。
   新增测试 `the_same_policy_is_dispatched_only_once`:连续 20 次同策略只下发/记 1 次,
   换档与「首次拿到句柄」必须重下。
5. `dwm_get_rect` 的 `hr == 0` 改成 `hresult_ok(hr)`,「判据只有一处」名副其实。
6. 报告口径修正(诊断已产出、UI 接线待做——`SettingsBridge` 未暴露 doc,接线要改 presenter 的
   `settings_bridge.rs`,不在本 mission scope),本轮不动代码。

门禁:fmt --check exit 0;clippy(5 个 crate)--all-targets -D warnings 零 warning;
lib 测试 app-iced 419(+1 去重测试)/ core 266 / design 163 / i18n 24 / presenter 129 全绿;
改动文件仍全部 ≤400 行(最大 keys.rs 398)。
This commit is contained in:
AskaEth committed 2026-11-05 06:35:17 +08:00
1 parent 25d860b2b3
commit 41746d1612
10 files changed
+184 -40

No files matched your search

+6
View File
@@ -156,6 +156,11 @@ pub struct App {
pub(super) account: pages::account::Page,
/// 皮肤/头像解码缓存(M114:同一张皮肤只解一次)。
pub(super) avatars: pages::account::avatar::Cache,
/// 上一次**真下发过**的圆角判定指纹(M116 r1 复审 P2-4:判定没变就不重下、不重记日志)。
///
/// `None` = 还没下发过(首屏 `boot` 那一次)。指纹类型见
/// [`crate::platform::win32::corner::CornerApplied`]。
pub(super) corner_applied: Option<crate::platform::win32::corner::CornerApplied>,
}
impl App {
@@ -266,6 +271,7 @@ impl App {
width,
),
avatars: pages::account::avatar::Cache::default(),
corner_applied: None,
};
// 配色来源档可能已经指向一张背景图:那时 `Ui` 必须由解析出的方案构造,而不是 baseline。
app.rebuild_ui();
+17 -2
View File
@@ -23,6 +23,7 @@
//! (M116 取消了 8/12/16 固定档)。
use crate::platform;
use crate::platform::win32::corner::{self, CornerApplied};
use crate::platform::win32::transparency::{apply_corner, style_summary, CornerOutcome};
use super::super::state::App;
@@ -30,14 +31,28 @@ use super::super::state::App;
impl App {
/// 把当前圆角策略下发到窗口,并打一行可分辨的日志。
///
/// ## 去重(M116 r1 复审 P2-4)
///
/// 设置页的滑条(整窗 α / 面板 α / 暗化)每动一下都会走一次外观变更,而<b>圆角与那些键无关</b>。
/// 判定完全没变时这里**直接返回**:不动窗口、不打日志。判据是
/// [`corner::needs_redispatch`](纯函数,有「同一策略 N 次只记 1 行」的测试),
/// 指纹只含「策略 / 来源 / 原因码 / 有没有句柄」,不含只有真下发才拿得到的读数。
///
/// 没有句柄时**也打日志**(`window=none`):不能让「没生效」只体现为屏幕上没变化。
pub(crate) fn apply_window_corner(&self, context: &str) {
/// 句柄从无到有会让指纹变化 ⇒ 首次拿到 HWND 时必然重下一次。
pub(crate) fn apply_window_corner(&mut self, context: &str) {
let policy = self.appearance.window_corner();
let plan = platform::plan_corner(
policy,
platform::current_windows_version(),
self.appearance.backend,
);
let next = CornerApplied::new(policy, &plan, self.hwnd.is_some());
if !corner::needs_redispatch(self.corner_applied.as_ref(), &next) {
return;
}
self.corner_applied = Some(next);
// 行的形状只有一处(`corner::format_line`),因为那里能在没有窗口的环境里被单测钉住。
// 「我们被 DWM 排除」的第一嫌疑是无边框(`WS_POPUP`)与整窗 α(`WS_EX_LAYERED`),
// 所以 `frame=` / `layered=` 必须和圆角结论在同一行——否则以后只能猜是哪一条。
@@ -50,7 +65,7 @@ impl App {
};
eprintln!(
"{}",
platform::win32::corner::format_line(context, &plan, policy, &outcome, &style)
corner::format_line(context, &plan, policy, &outcome, &style)
);
}
}