Evinceの検索ハイライト色をGTKで上書きする
Evince で PDF を検索したとき、ヒットした箇所にハイライトが付く。
このハイライトの色は、デフォルトだと GTK テーマのアクセントカラーが使われる。自分の環境(adw-gtk3-dark + accent_color: #a8c8ff)だと薄い青になっていて、PDFビューアのハイライトとしては地味すぎる。
普通の PDFビューア風に「通常マッチは黄色、カーソル位置のカレントマッチは薄い赤」にしたい。
これを GTK の CSS でやる方法をメモしておく。Evince のソースを覗いて初めて分かった :selected と :active の罠がポイント。
確認した環境
- Arch Linux (kernel 7.0.12-zen1-1-zen)
- evince 1:48.4-1
- GTKテーマ: adw-gtk3-dark
既存のカラー定義を確認する
~/.config/gtk-3.0/gtk.css には、libadwaita系のセマンティックカラーを定義してある。
| |
Evince の検索ハイライトもこの accent_color を継承しているので、何もしないと薄い青のハイライトになる。
EvView の検索ハイライト用 CSS を追記する
結論から書くと、以下の CSS を ~/.config/gtk-3.0/gtk.css に追記する。
セレクタの evview.view.content-view 部分(widget 階層と追加クラス)は、GTK_DEBUG=interactive evince で GtkInspector を起動し、ハイライト中の要素を実際にピックして確認した。
末尾の .find-results がポイントで、これは検索結果ハイライト専用に Evince が追加している CSS クラス(出所は後述)。
| |

ポイントは3つ。
- セレクタは
.find-results:selectedと.find-results:activeで通常マッチとカレントマッチを別の擬似クラスで分けている - 背景色は
rgba()で半透明にする。#fff59dのように不透明な色にすると、ハイライト下のPDFテキストが見えなくなる color: transparentにして、CSS側で文字色を上書きしない。PDF元のテキスト色をそのまま透けて見せる
ハマったところ: :selected:active は絶対に成立しない
最初は「カレントマッチ=より強調された選択」と思って、こう書いていた。
| |
これはカレントマッチには絶対に当たらない。
Evince のソース (gnome-48 ブランチ ev-view.c:7461-7467) を見ると、検索結果の描画はこうなっている。
ここに登場する EV_STYLE_CLASS_FIND_RESULTS の定数値が "find-results" で、CSS 側からは .find-results クラスとして当たる仕組み(GTK の慣習で、C 側の定数名は大文字スネークケース/CSS 側はそれをケバブケースにした文字列リテラルで対応する)。
| |
注目するポイントは gtk_style_context_set_state() を使っていること。これは state を置き換える動作なので、既存の state は全部消えて指定したフラグだけが立つ。
つまり実際の state の組み合わせは:
- 通常マッチ →
:selectedだけ立つ(:activeは立たない) - カレントマッチ →
:activeだけ立つ(:selectedは立たない)
両者は同時に立たない排他関係。だから :selected:active のような複合セレクタは構造的に成立しなくて、:selected:focus も同じ理由でハズレ。
border-radius がカレントマッチだけ角ばる問題
最初は border-radius を書いていなかったけど、:selected だけ角が丸くなって :active のほうは四角いままだった。
これは GTK テーマ(adw-gtk3-dark)側で :selected 状態に border-radius を当てているケースが多いから。:active 単独のスタイルは定義されていないので、CSS のカスケードが効かずデフォルトの角ばった見た目になる。
両方に明示的に border-radius を当てて揃えるのが安全。
反映方法
GTK の CSS は通常、アプリ起動時にロードされるので、Evince を一度終了させてから開き直す。
| |
GtkInspector でセレクタを確認する
CSS が当たらない時や、別の widget をカスタマイズしたい時に、widget に付いているクラス名と state を実際に確認する方法。今回のセレクタ evview.view.content-view.find-results もこのやり方で裏付けた。
GTK_DEBUG=interactive 環境変数を付けて Evince を起動すると、本体ウィンドウと一緒に GtkInspector のウィンドウが開く。
| |
手順:
- Inspector の左上にある「Pick a widget」ボタン(照準アイコン)をクリック
- Evince 側で調べたい要素(例: 検索ハイライト中の箇所)をクリック
- Inspector の「Objects」タブで対応する widget ノードがハイライトされる
- 右側の「CSS Nodes」タブを開くと、ノードの階層と各ノードに付いているクラス名・state がツリー表示される
検索ハイライトを pick した場合、EvView の配下に evview.view.content-view ノードが見えて、検索状態のときだけそこに .find-results クラスと :selected / :active の state が乗ってくる。これが今回のセレクタの根拠。
「CSS Nodes」タブには Style Classes と State の編集UIもあるので、その場でチェックを付け外しすればCSSがどう当たるかその場で確認できる。新規セレクタを試す時にいちいち Evince を再起動するより早い。
ハイライトの矩形そのものをピックしようとすると EvView 全体に当たって .find-results が見えないことがあるので、その場合は「Objects」タブで EvView ノードを選択し、子要素を展開して find-results 付きのノードを探すのが確実。
色味の調整目安
rgba() の値はお好みで。参考までに、自分が試した範囲では:
- 通常マッチ
- もっと薄く(テキスト視認性優先):
rgba(255, 235, 59, 0.25) - 蛍光ペン風(暖色寄り):
rgba(255, 245, 157, 0.5)
- もっと薄く(テキスト視認性優先):
- カレントマッチ
- もっと淡く(パステル寄り):
rgba(255, 138, 138, 0.4) - ピンク寄り:
rgba(255, 150, 180, 0.45)
- もっと淡く(パステル寄り):
ハマったところまとめ
- Evince の find-result は
set_stateで state を置き換えするので、:selectedと:activeは排他。:selected:activeなどの複合セレクタは絶対に当たらない background-colorは不透明色にするとPDFテキストが下に隠れる。rgba()で半透明にしてcolor: transparentを併用するborder-radiusは:active単独だとテーマから継承されないので、両方に明示的に書く- セレクタが当たらない時は GtkInspector で実際のクラス名と state を直接確認するのが早い(手順は前述)
EOF