Wayland/Wayfire環境でアクティブウィンドウのスクショを撮る
Raspberry Pi OSがbookwormベースに更新され、ウィンドウサーバがX11からWaylandに変更されました。先進的でセキュアになったのはいいのですが、色々とトラブルに見舞われることも少なくありません。
はじめに
最新のRasPi OSでは、X11に代わるウィンドウサーバとしてWaylandが、コンポジタ (いわゆるウィンドウマネージャ) としてWayfireが、それぞれ採用されています。しかし歴史あるX11と比べて、少なくとも現時点ではまだ環境が整い切れていない状況です。
トラブルの一例として、Chromiumで日本語できない問題があります。
また、X11で動作するscrotやgnome-screenshot等のスクショツールはWaylandでは動作しません。scrotの代替としてgrimが提供されており、ウィンドウ全体のスクショはこのツールで撮影できます。
このgrimのラッパースクリプトとしてgrimshotが提供されていますが、このスクリプトの内部で利用されているプログラムがWayfireとは別のコンポジタであるSwayベースであるため、アクティブなウィンドウのスクショ撮影など、Wayfireでは使えない機能があります。
noteなどのブログ記事を作成する際に、非常に不便です。
アクティブウィンドウのスクショを撮る
手っ取り早い解決方法
ウィンドウサーバをWaylandからX11に戻すことで、この問題は簡単に解決します。scrotやgnome-screenshot等の従来のスクショツールが使えるようになります。
raspi-configを起動し、Advanced Options -> Waylandと選択します。
$ sudo raspi-config
ディスプレイサーバとしてX11 (OpenBox) かWayland (Wayfire) かを選択できますので、X11を選択して、再起動します。
再起動後はX11が有効になり、scrotやgnome-screenshotなどの従来のスクショツールが使えるようになります。
Wayfireを諦めない
grim-wayfire-active-window.sh
Wayfireのままでは打つ手なしかと若干諦め気味でウェブで色々と調べ回っていたとき、こちらのスクリプトを発見しました。
見た感じ、wf-infoコマンドでウィンドウのジオメトリ(座標、高さと幅)を取得してgrimコマンドに渡すことで、アクティブウィンドウのみのスクショを撮影できるっぽい感じです。
$ mkdir ~/bin
$ vi ~/bin/grim-wayfire-active-window.sh
#!/usr/bin/bash
grim -g "$(wf-info | grep Geome | awk {'print $2,$3'})"
適当なディレクトリにファイルを作成し、実行してみます。
$ chmod +x ~/bin/grim-wayfire-active-window.sh
$ ~/bin/grim-wayfire-active-window.sh
~/bin/grim-wayfire-active-window.sh: 行 3: wf-info: コマンドが見つかりません
invalid geometry
wf-infoコマンドが見つからず、エラーになりました。apt-cacheコマンドでwf-infoパッケージを探してみます。
$ apt-cache search wf-info
見つかりません。wf-infoパッケージもなさそうです。
wf-infoプラグイン
wf-infoはWayfireのプラグインとしてgithubで公開されていました。これをインストールすればよさそうです。
README.mdに記載されているビルド方法を実行しても、通常はパッケージ不足などでエラーになります。下記の手順でインストールできました。
まずは何はともあれgit cloneしましょう。
$ git clone https://github.com/soreau/wf-info.git
ビルドパッケージのインストール
$ sudo apt update
$ sudo apt -y install meson ninja
ライブラリのインストール
$ sudo apt -y install libcairo2-dev libglm-dev libpango1.0-dev libvulkan-dev libwayland-dev libwf-config-dev libwlroots-dev libxml2-dev wayfire-dev
wf-infoのビルド・インストール
masterブランチは最新のWayfire 0.8系向けなので、RasPi OSのWayfire 0.7系用の0.7.xブランチに切り替える必要があります。
$ cd wf-info
$ git checkout 0.7.x
$ meson build --prefix=/usr
$ ninja -C build
$ sudo ninja -C build install
アンインストールする時のために、wf-infoディレクトリは残しておきましょう。sudo ninja -C build uninstallでアンインストールできます。ちなみに下記のファイルがインストールされますので、手動で削除できなくもないです。
/usr/lib/aarch64-linux-gnu/wayfire/libwf-info.so
/usr/bin/wf-info
/usr/share/wayfire/metadata/wf-info.xml
プラグインの設定
この時点でwf-infoコマンドがインストールされますのでgrim-wayfire-active-window.shを実行できそうですが、その前にwf-infoプラグインを有効にする必要があります。
まずはデフォルトで有効になっているプラグインを確認します。
$ grep 'plugins = ' /etc/wayfire/defaults.ini
plugins = alpha animate autostart autostart-static command cube pixdecor expo fast-switcher fisheye grid idle invert move oswitch place resize switcher vswitch window-rules wm-actions wrot zoom winshadows
これを~/.config/wayfire.iniに追加します。[core]セクションがあればそこに、なければ[core]セクションを追加して、その下に記述します。プラグインのリストの末尾にwf-infoを追加するのを忘れずに。
$ vi ~/.config/wayfire.ini
…
[core]
plugins = alpha animate autostart autostart-static command cube pixdecor expo fast-switcher fisheye grid idle invert move oswitch place resize switcher vswitch window-rules wm-actions wrot zoom winshadows wf-info
動作確認
設定を保存したら即反映されますので、さっそく実行してみましょう。
$ ~/bin/grim-wayfire-active-window.sh
マウスカーソルが十字になりますので、スクショを撮りたいウィンドウを選択します。スクショ画像はホームディレクトリ直下のPicturesディレクトリに 年月日_時h分m秒s_grim.png というファイル名で保存されます。
$ ls ~/Pictures
20240308_22h48m02s_grim.png
ん? カーソルで選択ってことはアクティブウィンドウじゃなくね? 実際、他のウィンドウに隠れたウィンドウを選択すると、隠れた状態のスクショが撮れてしまいます。
スクリプト修正
フォーカスの当たっているアクティブなウィンドウのスクショを撮影するよう、スクリプトを修正してみました。
$ cd ~/bin
$ cp grim-wayfire-active-window.sh grim-active-window.sh
$ vi grim-active-window.sh
#!/bin/bash
sleep 3
grim -g "$(wf-info -i -1 | grep Geome | awk {'print $2,$3'})"
wf-infoコマンドの-iオプションでウィンドウIDを指定できます。アクティブウィンドウのIDは-1らしいです。grimコマンドを呼ぶ前にsleepさせて、どのウィンドウをアクティブにするか選択できるようにしています。
$ ~/bin/grim-active-window.sh
いい感じですね。sleep時間はもうちょっと長くするか、コマンドライン引数で渡せるようにしてもよいかもです。
$ vi ~/bin/grim-active-window.sh
#!/bin/bash
WAIT=0
while getopts "w:" opt; do
case "$opt" in
w)
WAIT=$OPTARG
;;
esac
done
sleep $WAIT
grim -g "$(wf-info -i -1 | grep Geome | awk {'print $2,$3'})"
-wオプションで待機時間を秒単位で指定できます。指定しない場合は0秒 (即時撮影) です。
$ ~/bin/grim-active-window.sh -w 5
上記の例では5秒のウェイト後にアクティブウィンドウのスクショが撮影されますので、ウェイトしている間にスクショを撮りたいウィンドウをアクティブにすればOKです。
なお、~/.profile等で~/binにPATHを通しておくと少し楽かもです。