Rust 製の Windows 用 reading ruler(読書補助オーバーレイ)。透明 click-through ウィンドウで画面上に水平/垂直のスリットを表示し、視線追跡を助ける。
実機での操作:
Ctrl+Alt+H: ON/OFF トグル(Off ⇄ 直前のアクティブモード。最後に使った向きを覚えている)。 表示の出し入れはこのキー専任で、表示してから下のキーで調整するCtrl+Alt+R: 軸切替(Horizontal ⇄ Vertical)Ctrl+Alt+E: 周囲効果切替(Dim(暗幕)→ White(白マスク)→ Blur(背後ぼかし)→ Dim)Ctrl+Alt+Up/Ctrl+Alt+Down: スリット厚さ ±(長押しで連続調整)Ctrl+Alt+Right/Ctrl+Alt+Left: 不透明度 ±(長押しで連続調整)。Blur効果中は 代わりに ぼかし量(Gaussian σ, px) を増減する(Blur では不透明度は inert で、 調整対象はぼかし量に切り替わる)Ctrl+Alt+K: HUD 表示切替(常駐チップ ⇄ ホットキーガイドつきフルパネル)Ctrl+Alt+Q: 終了
「非表示」は Mode::Off ただ一つ。Off 中に軸・厚さ・不透明度・効果のキーを押しても
設定は変更されず、HUD に「Overlay is off — Ctrl+Alt+H to show」の toast が出る
(見えない状態がこっそり変わるサプライズを排除)。
Bump 系(厚さ・不透明度/ぼかし量)は長押しで連続発火する。軸切替・ON/OFF トグル・
効果切替・終了は誤連打を避けるため 1 押下 1 発火に固定。割り当てが OEM 系キー([/]/=/-)
ではなく Arrow キーなのは、Windows の IME / keyboard layout で OEM キーの VK が化けて
RegisterHotKey がキャプチャを取り逃すケースがあったため(JIS keyboard × ENG IME で再現)。
表示・軸切替・効果切替・厚さ / 不透明度の変更は、すべて 200ms 未満の ease-out トランジションで滑らかに遷移する(長押し中の連続調整は retarget で 1 つの連続モーションに 合流する)。Dim ⇄ White はマスク色の RGB クロスフェード、flat ⇄ Blur はブラシ種が変わる (スプライトプール再構築)ためマスター包絡によるソフトカットで切り替わる。
HUD は二段階表示: 普段は画面右上に極小の常駐チップだけが出る。チップが出すのは
フルパネルへの導線のみ — 表示中は Ctrl+Alt+K、Off 中は Off · Ctrl+Alt+H(軸・効果・
数値は画面を見れば分かるのでチップには出さない)。起動直後の数秒はホットキーガイドつきの
フルパネルが表示され、その後チップへ自動的に畳まれる。操作を忘れたら Ctrl+Alt+K で
いつでもフルパネル(Mode / Thickness / Opacity / Effect / Refresh Hz とホットキー一覧)に
展開できる(Blur 効果中は Opacity 行が Blur: N px(ぼかし量)に切り替わる)。
フルパネルのホットキー一覧はいま押して意味のあるキーだけを出す — Off 中は
On/Off・HUD 表示切替・終了の 3 つに絞られ、表示中は全キーが並ぶ。スリットやカーソルが
HUD に近づくと譲ってフェードアウトする。multi-monitor 環境では virtual screen 全体に
overlay が広がる。
composition backend は WinRT Windows.UI.Composition 単一(旧 Win32 DirectComposition
backend と LINERULE_COMPOSITOR 環境変数は撤去、ADR 0016)。Blur(背後ぼかし)は
WinRT backdrop blur で常時レンダリングされる。色ベール(tint)は重ねないが、純粋なぼかしだけ
だと実機での見えが「のっぺり」するため、ぼかしの後段に彩度(Saturation)とコントラスト
(Contrast)を持ち上げる D2D エフェクトを連結し、摺りガラス的な素材感を出している
(backdrop → GaussianBlur → Saturation → Contrast)。彩度/コントラストの強さは実機調整用に
環境変数 LINERULE_BLUR_SATURATION([0,1]、既定 0.70、0.5 で原画)/ LINERULE_BLUR_CONTRAST
([-1,1]、既定 0.15、0 で原画)で再ビルド無しに上書きできる。ぼかし量(Gaussian σ)は
Ctrl+Alt+Right/Left で調整でき(既定 ≈9px、範囲 ≈2–64px)、ステップは Weber–Fechner 則に
沿って σ を幾何級数的に変化させる(内部の知覚レベルを等間隔に動かす)ため、どの強さでも
1 タップの体感変化がほぼ一定になる。ぼけ方は実機の GPU / compositor に依存するため見え方は
ハードウェアで確認すること。背後サンプリングが効かず単色に見える場合は
LINERULE_BLUR_HOST=1 で backdrop 取得方法(CreateBackdropBrush ↔ CreateHostBackdropBrush)を
切り替えて比較できる。
| Crate | 役割 |
|---|---|
linerule-core |
純粋ロジック層。ADT / reducer / render / chord parser / hold FSM / tick pipeline。#![forbid(unsafe_code)] |
linerule-platform-windows |
Win32 / COM 実装層。WinRT Composition + Direct2D + DXGI + D3D11 を直接叩く。#![cfg(windows)] |
linerule-app |
単一バイナリ linerule.exe のエントリポイント。windows_subsystem = "windows" + サブコマンドで GUI / CLI 切替 |
xtask |
ビルド自動化。lint / dep-graph / ci |
依存方向は一方向: linerule-app → linerule-platform-windows → linerule-core。cargo xtask dep-graph で機械検証する。
ホストには Docker と just があれば良い。すべての Rust ツール (cargo, cargo-xwin, cargo-deny, cargo-nextest, cargo-machete, cargo-llvm-cov, cargo-audit, cargo-sort, typos, taplo, biome, yamlfmt, lefthook, actionlint, commitlint) はコンテナ内に揃う。
just bootstrap # 一発セットアップ: docker build + git hooks + xwin sysroot prefetch + doctorjust bootstrap がやること:
- dev image を取得 —
docker compose pullでghcr.io/p4suta/linerule-rs-dev:latestを取りに行き、無ければdocker compose buildにフォールバック(フォールバック時はgh auth tokenからGITHUB_TOKENを自動拾って cargo-binstall の api.github.com レートリミット回避)。CI (.github/workflows/dev-image.yml) が週次 + Dockerfile 変更時にイメージを更新するので、通常は ~30s の pull docker compose up -d dev— 永続コンテナを立てて以降のjust <recipe>を高速化lefthook install— pre-commit / commit-msg / pre-push git hooks を.git/hooks/に配置bun install— commit-msg hook が使う commitlint を入れる(npm ではなく Bun を採用、爆速)just doctor— 全ツールの疎通確認
Windows クロスコンパイル用の MSVC CRT / Windows SDK(~500 MB)は dev image に焼き込まれているので、初回の just cross-check も即座に通る。
困ったら just doctor を打てば、どのツールが落ちているかすぐ分かる。
| 構成 | フレッシュクローン → cross-check 通る状態まで |
|---|---|
| Token 無しで build(cargo-binstall が api.github.com 60/h で 403 → 120s × N retry → source fallback、その後 xwin 7m download) | 約 20 分 |
| Token 有りで build(cargo-binstall は prebuilt、xwin sysroot を image に焼き込み済み) | 約 2.4 分 |
| ghcr.io pull(CI がビルドして push、xwin sysroot 込みで ~1.7 GB pull) | 約 30 秒 |
just build # cargo build --workspace --all-targets
just test # cargo nextest run --workspace
just lint # fmt + clippy + cargo-deny + typos + actionlint + cargo-machete + dep-graph
just run # cargo run -p linerule-app (Windows host のみ動作)Windows ターゲットの型/構文ドリフトを Linux 上で検出するために cargo-xwin を使う:
just cross-check # cargo xwin check --target x86_64-pc-windows-msvc --workspace
just publish-windows-cross # 反復用のクロスビルド (shippable ではない)shippable な linerule.exe は CI の windows-latest runner からのみ produce される(ABI / SEH 事故回避のため)。
GitHub Release では tag push のたびに以下が attach される (.github/workflows/release-assets.yml、ADR-0010 / ADR-0011)。
linerule-vX.Y.Z-win-x64.exe—cargo build --release -p linerule-appの native Windows ビルド (Phase J 以降 1 binary のみ、PDB /dist-devprofile は廃止)linerule-vX.Y.Z-sbom.cdx.json—cargo-sbomが生成する CycloneDX 1.6 JSON 形式の Software Bill of Materials。linerule-appの依存閉包をスキャナで直接読める
ランタイム時に linerule.exe と同じディレクトリの events.jsonl.YYYY-MM-DD へ tracing JSON Lines を流す(portable 運用、ADR-0011)。panic 時は同階層に crash-<run_id>-<unix_ms>.json が出る。
just logs-tail subsystem=wnd_proc # subsystem フィルタ
just logs-pretty # 全件 pretty-print
just crash-list # クラッシュダンプ一覧
just crash-latest # 最新クラッシュダンプ下のブロックは crates/linerule-core/src/lib.rs の crate-level doc から cargo rdme で自動同期されます。手書きで中身を編集しないこと(just docs で再生成)。
linerule-core
Pure logic layer: ADTs, reducer, render, parser, FSM. #![forbid(unsafe_code)]
bans unsafe outright; nondeterminism (time, randomness, I/O) is passed in
by the caller as arguments.
- [
anim] — integer-endpoint timed transitions (Transition<T>) and easing - [
color] —Rgba/Opacity/DimLevel/Thickness/BlurAmountand perceptual curves - [
config] —UserConfigtree (OverlayConfig/HudConfig/ ...) - [
diagnostics] —LineruleError/Severity - [
geometry] — coordinate-space-taggedPoint<S>/ScreenRect<S> - [
input] — chord parser / hold FSM / tick pipeline / HUD fade / hotkey map - [
render] —OverlayFrameADT and the purerender::frame - [
state] —State/OverlayAction/StateDeltaandstate::reduce::apply
Key types are re-exported here, so consumers write short paths like
linerule_core::Rgba / linerule_core::frame(...). Internal code uses the
long paths (linerule_core::color::rgba::Rgba), leaving room to refactor.
linerule-app → linerule-platform-windows → linerule-core. This crate
depends on no other linerule-rs crate.
docs/modules/— 各クレートのcargo modules structure出力(自動生成)docs/dep-graph.svg— workspace 依存グラフ(cargo depgraph自動生成)
更新は just docs で一括実行。lefthook の pre-commit が drift を検出し、生成物が古いまま commit されることを防ぐ。
設計判断は docs/adr/ に ADR として記録する。一方向依存 / RAII /
exhaustive match / unsafe 局所化などの merge ブロッカー原則は
docs/adr/0002-architecture-principles.md を参照。
このプロジェクトは MIT または Apache-2.0 のいずれかでデュアルライセンスされます (お好みで)。