# Changelog
本项目遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
## [Unreleased]
## [0.8.2] - 2026-07-06
### Fixed
- **连续空格中光标无法移动**:`DWRITE_TEXT_METRICS::width` 不含尾随空白宽度,导致以
空格结尾的子串测量宽度被折叠为同一值——文本框光标索引在连续空格中正确递增,但换算出的
视觉 x 坐标不再前进,表现为"光标卡在第一个非空格字符处"。改用
`widthIncludingTrailingWhitespace` 字段(`src/text/dwrite.rs`、`src/platform/win32/d2d.rs`)。
- **输入法组合态期间自绘光标位置错误**:拼音等未上屏组合期间,`TextInput`/`Stepper` 自绘的
光标条停留在组合开始前的位置不动,与系统组合浮层里跟随合成进度前进的光标同时存在,视觉上
像卡住。新增 `Widget::set_composing`,由平台层在 Windows 的
`WM_IME_STARTCOMPOSITION`/`WM_IME_ENDCOMPOSITION`、macOS 的
`setMarkedText`/`unmarkText`/`insertText:` 时通知焦点控件,组合期间跳过自绘光标绘制,
交由系统浮层呈现。
- **输入法组合串字体与正文不一致**:Windows 合成串 `LOGFONTW.lfFaceName` 之前留空,系统常
回退到陈旧的宋体;现显式指定为与正文渲染同族的 `Microsoft YaHei UI`。
## [0.8.1] - 2026-07-06
### Added
- **`PickDialog` 同步方法误用检测**:`pick_file`/`pick_files`/`pick_folder`/`pick_folders`/
`save_file` 在控件事件回调(`on_click`/`on_event`)栈内被调用时,`debug_assert!` 报错
(release 构建零开销剔除)——把"回调里别同步开模态对话框,OS 捕获来不及释放会导致鼠标
失灵"这条只写在文档注释里的契约,变成 debug/测试阶段能捕获到的确定性失败,而不是留到运行时
变成偶发的鼠标卡死。内部用线程局部 `EventDispatchGuard` 标记风险窗口(`on_pointer`/`on_key`/
`on_drop_files` 分发期间),win32/macos 两个后端均已接入;`app.rs::on_drop_files` 同时补上了
之前遗漏的 `dialog` 请求转发(`Element::on_drop` 回调里调用 `EventCtx::request_*` 之前会被
静默丢弃)。
## [0.8.0] - 2026-07-06
### Added
- **`DialogRequest` + `EventCtx::request_pick_file`/`request_pick_files`/`request_pick_folder`/
`request_pick_folders`/`request_save_file`/`defer_blocking`**:原生文件对话框不再在事件回调
栈内同步弹出——按钮点击回调里直接调用 `PickDialog::pick_file()` 等阻塞方法时,OS 鼠标捕获的
释放要等整条事件分发调用栈返回才生效,导致对话框存续期间主窗口仍持有 `SetCapture`,与对话框
自己的消息泵抢鼠标输入,反复开关几次后捕获状态与 OS 实际状态错位,表现为鼠标彻底失灵。
现改为把对话框请求(`PickDialog` + 结果延续回调,或 `defer_blocking` 逃生舱包一段任意阻塞式
原生调用序列)经 `EventCtx`/`DispatchResult` 交给宿主,在事件分发**完全返回**、OS 捕获同步
完毕之后才真正执行。`PickDialog` 本身的同步 API 仍保留(非 UI 回调场景可用),但**不要**在
`on_click`/`on_event` 回调里直接调用。
- **表格自定义单元格渲染 `Element::cell_render`**:按 `(行下标, 列下标, 单元格文本)` 逐格询问,
返回 `Some(Element)` 用自定义控件(徽章/彩色标签/图标等),`None` 回退默认文本。排序仍基于
单元格文本(渲染与排序键解耦);行下标语义同 `.actions`(客户端表格为原始行下标,服务端表格
为页内显示下标)。适用于 `table_sortable` / `table_sortable_server` / `table_selectable`,
可与 `.actions` 组合。fullshowcase 表格 tab 新增演示。
- **`Element::host_signal`**:信号驱动的响应式重建宿主。同 `list_signal` 的重建机制,但容器为
普通列容器(非滚动)——子元素 `weight`/`fill` 能拿到确定高度,适合整体重建"结构随状态变化"
的子树(如列集随类别切换的表格;滚动容器按无限高度测量会令表格正文高度崩塌)。
### Fixed
- 响应式广播(`dispatch_reactive_updates`)曾用广播快照的存活集**覆盖**注册列表,把广播期间
动态重建子树新注册的响应式节点抹掉——`list_signal`/`host_signal` 重建出的响应式表头/正文
永远收不到 `on_update`,表格在宿主重建后空白。现改为按批次迭代到收敛(新注册节点**同帧**
收到回调,避免首帧空白),清理阶段基于真实列表 retain。
### Changed
- `DispatchResult` 不再 `derive(Clone)`(新增字段携带 `Box<dyn FnOnce()>`,不可 Clone;原实现
从未实际克隆过该结构,纯类型层面的收紧)。
## [0.4.0] - 2026-06-26
### Added
- **Direct2D GPU 渲染后端(Windows,可选 opt-in)**:大窗口/多控件下软件光栅 paint-bound,新增
Direct2D 后端把几何/渐变/裁剪/opacity/图片/阴影/文字光栅迁到 GPU。窗口级显式 opt-in
`App::accelerated(true)`(示例 `--accelerated`),**默认仍软渲染**;与 tiny-skia 软路径并存。
- 文字坚持走 **DirectWrite**(`DrawTextLayout`,系统字体缓存 + ClearType),与软路径字体/字重一致。
- 阴影用 `ID2D1Shadow` GPU 高斯模糊,烘焙一次缓存成品避免每帧重模糊。
- 自动回退软渲染(绝不 panic):RDP 远程会话、无可用 GPU、设备创建失败、离屏截图。
- 设备丢失检测 → 整体重建设备链 → 连续失败降级软后端;同 UI 线程多窗口共享设备链(避免 ×N 内存)。
- 重对象(文字布局/画刷/位图/后备缓冲)全缓存复用,常驻内存从早期 190M 降到 ~70M。
- 渐变画刷(线性/径向)+ `Brush`(Solid/Gradient/Role)主题角色取色体系。
- `Theme::dark` 暗色预设 + `ThemeHandle` 运行期主题热切换(整树跟随刷新)。
- 浮层投影(box-shadow)+ 子树整体不透明度(离屏层合成)。
- 级联右键菜单(图标/分隔/快捷键/子菜单)+ `Element::on_context_menu`。
- `PickDialog`:系统原生文件/目录选择对话框。
- `Signal<T>`:`Copy` 句柄状态原语(运行时 arena 承载),全控件状态从 `Rc<Cell>`/`Rc<RefCell>` 迁入;
`set` 自动产生局部脏区,新控件免手写 `mark_dirty`。
- 文字字重支持;半透明文字色。
- `App::min_size`:限制窗口最小客户区尺寸。
- 新增 `examples/ime.rs`(复刻中文输入法界面,暗/亮双主题)。
### Changed
- 控件状态原语统一为 `Signal<T>`,取代散落的 `Rc<Cell>`/`Rc<RefCell>`(API 基本不变,状态语义更一致)。
- 渲染接缝重构:`AppHandler::render` 改为面向 `RenderTarget`,软/GPU 两后端同形接入,软路径零回归。
### Performance
- 交互失效系统:hover/拖动/点击/打字走 ~1ms **局部重绘**(结构签名判定局部 vs 整窗),不再每次整窗重绘。
- DirectWrite 测量结果缓存,消除稳定文本每帧重复排版。
- 模糊阴影缓存(位置无关),修复阴影每帧重算导致的卡顿;新增 `WINDUI_PROF` 绘制热点计时。
### Fixed
- 窗口按钮与复选框的文字/悬停色未跟随主题。
- DPI 缩放下 win32 窗口显示异常(全窗重绘 scale 由 handler 提供)。
- 点击切换内容不刷新;标签条内边距、菜单尾随快捷键换行、分段选中反色、菜单高亮溢出等多处 UI 细节。
## [0.3.0] - 2026-06-23
### Added
- 多行 `TextInput`:滚动条、滚轮滚动、跨视口拖选。
- `Label` `max_lines` 行数限制 + Truncate 省略号(End/Start/Middle)。
### Fixed
- `ScrollWidget` 滚轮滚动到边界时冒泡给外层容器。
## [0.2.0] - 2026-06-23
### Added
- 跨线程 UI 更新:`App::channel::<Msg>(on_message) -> Sender<Msg>`(后台 `send` 事件驱动唤醒 UI、`on_message` 在 UI 线程写状态)+ `App::on_interval(dur, cb)` 定时回调。有更新才重绘、空闲零 CPU。
- 语义意图色(Intent)体系:Button / CheckBox 统一 `.intent()` / `.danger()` / `.neutral()` / `.accent(color)`;
内置 primary/neutral/danger,`Custom(Color)` 为扩展点——单基色自动派生 hover/active + 对比自适应前景。
Button 默认 Primary(现有代码零改动);CheckBox 现有 `.danger()`/`.accent()` 收编进同一体系(API 不变)。
- CheckBox 受控点击拦截:`Element::checkbox(..).on_toggle(cb)`——设回调后点击/键盘激活不自动翻转
绑定 state,交 app 决定是否翻转(可在翻转前弹确认、确认后再置真,渲染跟随 state,零闪烁)。
- `Color::lighten` / `darken` / `pick_fg`(对比自适应前景)颜色派生工具。
- 彩色 emoji 渲染:DirectWrite 字形经 `IDWriteFactory2::TranslateColorGlyphRun`
拆成 COLR/CPAL 彩色层逐层着色(emoji、ZWJ 组合序列、肤色修饰均正确合成彩色),
字体无彩色数据时自动回退原单色路径。新增 `examples/emoji.rs` 演示。
### Fixed
- 文本框无法输入 emoji:WM_CHAR 对补充平面字符(码点 > U+FFFF,如 emoji)
分两条消息发来 UTF-16 代理对,原逻辑对单个代理项解码失败而丢弃。现正确
暂存高代理项并与低代理项合成为单个 `char`,emoji 及 CJK 扩展区字符可正常输入。
## [0.1.0] - 2026-06-22
首个公开版本(Windows + macOS)。
### Added
- 核心框架:命令式 Builder API、retained 模式、DPI 感知、tiny-skia 渲染。
- 完整控件集(布局/文本/按钮/表单/容器/列表/图片/导航)、系统托盘、无边框窗口、触摸滚动、自动截屏。
- Windows 平台后端(Win32 + GDI + DirectWrite 文字)。
- macOS 平台后端(Cocoa/AppKit 窗口 + Core Text 文字 + NSPasteboard 剪贴板 + NSStatusItem 托盘)。
- 跨平台缝合层:渲染/控件/事件平台无关,平台仅实现「窗口+事件循环」与「文字引擎」两条缝。
- 开源配套:双许可(MIT OR Apache-2.0)、DCO、贡献指南、开发指南、issue/PR 模板、CI、发布工作流。
### Changed
- 依赖按 target 门控:`windows` 仅 Windows、`objc2` 系列仅 macOS。
- README 改为跨平台说明(中文主 + 英文副)。
- 依赖更新:`toml` 0.8 → 1.1;CI actions(checkout v7、action-gh-release v3)。
- **windows-rs 0.58 → 0.62 迁移**:`implement` 宏改由 `windows-core` 提供;可空句柄参数
语义化为 `Option<T>`;`BOOL` 迁至 `windows::core`;COM 实现入参 `Option<&T>` → `Ref<'_, T>`。
[Unreleased]: https://github.com/huanfeng/wind-ui-rust/compare/v0.4.0...HEAD
[0.4.0]: https://github.com/huanfeng/wind-ui-rust/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/huanfeng/wind-ui-rust/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/huanfeng/wind-ui-rust/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/huanfeng/wind-ui-rust/releases/tag/v0.1.0