作成者: BlinkGTK Project
最終更新: 2026-05-12
対象: BlinkGTK を使ったアプリケーション開発者
BlinkGTK
を用いたアプリケーション開発で得られた実装パターンを集約した
ベストプラクティス集です。本書は BlinkGTK 本体の API リファレンス
(docs/04-user-guides/api-reference/)
と併せて参照してください。
クライアント実装者からの提案 (Issue #81 ほか) を反映しています。
ページロード後の zoom
設定、初期ハイライト、スクロール位置調整等を、
「安全のため」に g_timeout_add()
で遅延させる実装は推奨できません。
// アンチパターン (固定遅延)
g_timeout_add(400, deferred_zoom_and_highlight_cb, self);問題点:
gtk_widget_compute_point の assertion が連発する可能性load-changed シグナル +
BLINK_LOAD_FINISHEDBlinkWebView の load-changed シグナルから
BLINK_LOAD_FINISHED
を捕捉して同期実行する形が安全です。
g_signal_connect(web_view, "load-changed",
G_CALLBACK(on_load_changed), self);
static void on_load_changed(BlinkWebView* web_view,
BlinkLoadEvent ev,
gpointer user_data) {
if (ev != BLINK_LOAD_FINISHED) return;
MyAppView* self = MY_APP_VIEW(user_data);
if (self->shutting_down) return;
apply_zoom_and_pending_highlight(self);
// autoplay 連鎖等もここで消費
}BLINK_LOAD_FINISHED 時点で保証されることdocument.body.innerHTML
等が確定両方が保証されるため、scrollIntoView /
execute_javascript 系を
安全に発行できます。固定遅延を撤廃して以降、ロード後の assertion
発火が顕著に減少することが確認されています。
GStreamer の preroll 完了待ちも同じ思想で ASYNC_DONE
+
STATE_CHANGED → PAUSED の双方を拾って deferred seek
を実行する
実装に置き換えると、固定遅延ゼロで preroll 完了を捕捉できます。
アプリ全体で「タイマーよりイベント駆動」の方針を貫くと、
タイミング起因のバグが大幅に減ります。
blink_web_view_inject_user_stylesheet()<style>
注入// アンチパターン (ページごとに JS で注入)
static void on_load_changed(BlinkWebView* view, BlinkLoadEvent ev, ...) {
if (ev != BLINK_LOAD_FINISHED) return;
blink_web_view_execute_javascript(view,
"var s = document.createElement('style');"
"s.textContent = '...';"
"document.head.appendChild(s);",
NULL);
}問題点:
execute_javascript)
が発生gtk_widget_compute_point
assertion をinject_user_stylesheet の永続再注入blink_web_view_inject_user_stylesheet() (v1.0.0 以降)
は、ページ遷移後の自動
再注入が効くため、起動時 1
回呼び出すだけで全ページに適用
されます。
// 起動時 (BLINK_LOAD_FINISHED 後の 1 回のみ呼出)
static const gchar* CUSTOM_CSS =
"body, p, span, div, ruby {"
" font-family: 'Noto Serif CJK JP', serif !important;"
"}"
"*[style*='vertical'], .vertical-rl {"
" font-feature-settings: 'vert' 1, 'vrt2' 1;"
"}";
blink_web_view_inject_user_stylesheet(BLINK_WEB_VIEW(web_view),
CUSTOM_CSS);| 観点 | アンチパターン | 推奨パターン |
|---|---|---|
| ページ遷移時の IPC コール | 毎回発生 | 不要 (自動再注入) |
| 縦書きフォント機能の適用率 | タイミング次第で漏れ | 100% |
| JS DOM 操作リスク | あり (Issue #78 系 assertion) | なし |
| 「無スタイル状態」の瞬間 | 発生する可能性 | 発生しない |
EPUB / DAISY のような複数 XHTML を持つコンテンツでは特に有効です。
BlinkGTK ランタイム (約 617MB、513 個の .so + データファイル)
を
含むアプリを、ユーザーが好きな場所に展開するだけで動くポータブル
バンドルにする方法です。
my-app-X.Y.Z/
├── bin/
│ └── my-app (rpath = $ORIGIN/../lib)
├── lib/
│ ├── libblinkgtk.so
│ ├── libblink_*.so (513 個)
│ ├── icudtl.dat
│ ├── content_shell.pak
│ ├── snapshot_blob.bin
│ └── v8_context_snapshot.bin
├── share/my-app/
│ └── resources/
├── my-app.sh (起動ラッパー)
├── README.txt
└── VERSION
BLINKGTK_LIBS = -L$(BLINKGTK_REAL_LIBDIR) \
-Wl,-rpath,'$$ORIGIN/../lib' \
-Wl,-rpath,$(BLINKGTK_REAL_LIBDIR) \
-Wl,-rpath-link,$(BLINKGTK_REAL_LIBDIR) \
-lblinkgtk
$ORIGIN/../lib
でバイナリ位置基準にライブラリを解決するため、
ユーザーがバンドルディレクトリを任意の場所に展開しても動作します。
絶対パス rpath はフォールバックとして残し、開発ビルド時の
make run でも動くようにしておくと開発体験が向上します。
#!/bin/sh
APP_DIR="$(cd "$(dirname "$0")" && pwd)"
export LD_LIBRARY_PATH="$APP_DIR/lib:$LD_LIBRARY_PATH"
export GDK_BACKEND="${GDK_BACKEND:-wayland}"
export MYAPP_DATA_DIR="$APP_DIR/share/my-app"
cd "$APP_DIR/share/my-app" ||
exit 1
exec "$APP_DIR/bin/my-app" "$@"gchar* my_app_resolve_resource(const char* relative) {
const char* base = g_getenv("MYAPP_DATA_DIR");
if (base && *base) {
return g_build_filename(base, relative, NULL);
}
return g_strdup(relative); // 開発時は CWD 互換
}開発ビルド (make run) では環境変数なしで CWD
基準、バンドル起動
ではラッパーが MYAPP_DATA_DIR を設定してバンドル内
share/my-app/resources/...
を参照、という二刀流が便利です。
tar.gz 圧縮で 220MB 前後、展開後 650MB
前後が一例です。
tar -xzf my-app-X.Y.Z-linux-x64.tar.gz
cd my-app-X.Y.Z/
./my-app.shシステム依存は GTK4 / GStreamer / libxml2 等 OS 標準のみで、
Fedora 44 で追加インストール不要で動作する事例が報告されています。
本書の 3 つのパターンは、いずれも以下の共通原則を体現しています:
g_timeout_add)
よりイベント駆動シグナル$ORIGIN +
環境変数BlinkGTK は GTK4 ネイティブの GObject 型として設計されており、
シグナル / プロパティ / C API がしっかり用意されています。これらを
活用することで、アプリ実装は短く・安定したものになります。
| API | 用途 | パターン |
|---|---|---|
blink_web_view_new() |
Widget 生成 | §1 起動時 |
load-changed signal |
DOM 完成検知 | §1.2 |
BLINK_LOAD_FINISHED event |
完成タイミング判定 | §1.2 |
blink_web_view_inject_user_stylesheet() |
永続 CSS 注入 | §2.2 |
blink_web_view_execute_javascript() |
JS 実行 (必要時のみ) | §2.1 (アンチパターン) |
blink_web_view_load_uri() |
URL 読み込み | §1 |
詳細は docs/04-user-guides/api-reference/ を参照。
本書はクライアント実装者からの提案を継続的に反映します。
新規パターン提案は GitHub Issue でお寄せください。
docs/04-user-guides/api-reference/ (C API
リファレンス)docs/04-user-guides/getting-started/ (導入ガイド)docs/04-user-guides/troubleshooting-ja.md
(トラブルシューティング)Reported originally by:
クライアント実装者コミュニティ (Issue #81)
整理・公開: BlinkGTK Project