Files
Lu Fan(SonnyCalcr) 53649d9d12 feat(server,ui,ui-html): 新增实验性的 Direct2D 设置窗口 (#999)
* feat(ui): 动画时钟、渲染剔除与文本框扩展,并优化 msimeui 性能

- 新增 Animation.h:cubic-bezier 缓动、Tween、颜色插值,Window 提供
  RequestAnimationFrame / GetFrameTime,动画帧随显示刷新率推进
- Window 可选 DirectComposition 渲染(含不透明模式以支持 ClearType)、
  双击按下、捕获丢失时结束按压、悬停刷新、可关闭销毁时退出消息循环
- Scene 把滚轮交给光标下最内层可滚动元素并逐级冒泡
- DeviceResources:裁剪栈驱动的离屏剔除、按帧回收的笔刷缓存、SVG 栅格缓存
- ScrollViewer 可配置外观与平滑滚动;Popup 支持阴影通道与出现动画;
  卡片阴影缓存抽成可复用的 ShadowCache
- TextBox 支持 SetText、密码掩码、多行滚动、字重/字间距/行高与外观设置
- 调试日志默认关闭(MSIMEUI_DEBUG_LOG=1 才写文件),不再在每次点击和
  TSF GetTextExt 时打开文件
- 字体回退在 CJK/emoji 映射之后保留系统回退,缺字不再显示方框
- 新增动画与剔除单元测试

* feat(server): 新增实验性的 Direct2D 设置窗口

设置窗口可通过 appearance.settings_ui_backend 选择渲染方式:默认 webview2,
d2d 为实验性的 msimeui 原生实现(server/src/settings/native/),1:1 复刻
网页设置页,包括侧栏切换时竖向高亮条的滑动动画。

- 两个前端共用同一套 webview 契约消息与 HandleClientMessage,配置读写
  映射仍只在 settings_app.cpp
- 切换渲染方式后设置进程自动以新方式重新打开;--d2d / --webview2 可临时指定
- 新配置项写入出厂模板与开发配置,UiBackendPolicy 与测试同步更新
- METASEQUOIA_IME_SETTINGS_INSTANCE 允许开发版与已安装的设置窗口并存
- 更新 ui-backends 文档与 server/AGENTS.md

* feat(ui-html): 外观页新增设置窗口渲染方式选项
2026-10-16 16:13:13 +08:00

77 lines
1.9 KiB
C++

#pragma once
#include <d2d1.h>
namespace msimeui
{
// Monotonic clock in milliseconds, shared by every animation so values sampled in
// one frame agree with each other.
double NowMs();
// CSS cubic-bezier() timing function. Solves the curve for x = t and returns y.
struct Easing
{
float x1 = 0.0f;
float y1 = 0.0f;
float x2 = 1.0f;
float y2 = 1.0f;
float operator()(float t) const;
static constexpr Easing Linear()
{
return {0.0f, 0.0f, 1.0f, 1.0f};
}
// CSS `ease`.
static constexpr Easing Ease()
{
return {0.25f, 0.1f, 0.25f, 1.0f};
}
static constexpr Easing EaseIn()
{
return {0.42f, 0.0f, 1.0f, 1.0f};
}
static constexpr Easing EaseOut()
{
return {0.0f, 0.0f, 0.58f, 1.0f};
}
static constexpr Easing EaseInOut()
{
return {0.42f, 0.0f, 0.58f, 1.0f};
}
};
// A float that moves from one value to another over time. Sampling is pure: Value()
// can be called any number of times per frame. Retargeting starts from the value
// currently on screen, so an interrupted animation never jumps.
class Tween
{
public:
Tween() = default;
explicit Tween(float value);
// Jumps to `value` and stops any running animation.
void Snap(float value);
// Animates from the current on-screen value to `target`. A zero duration snaps.
void AnimateTo(float target, double durationMs, Easing easing, double nowMs);
void Start(float from, float to, double durationMs, Easing easing, double nowMs);
float Value(double nowMs) const;
float Target() const
{
return to_;
}
bool IsRunning(double nowMs) const;
private:
float from_ = 0.0f;
float to_ = 0.0f;
double startMs_ = 0.0;
double durationMs_ = 0.0;
Easing easing_ = Easing::Linear();
};
float Lerp(float from, float to, float t);
D2D1_COLOR_F LerpColor(const D2D1_COLOR_F &from, const D2D1_COLOR_F &to, float t);
} // namespace msimeui