🎩

Waylandで動くタイル型ウィンドウマネージャ・swayを使う

2021/08/30に公開

これはなに?

Arch Linuxを使い始めました。デスクトップ環境/ウィンドウマネージャとしてTiling Wayland Compositorのsway(swaywm)を導入したので、経緯と手こずった点のメモを残しておきます。[1]

mydesktop0
mywallpaper0
mydesktop1
mywallpaper1

テーマはDracula。

https://draculatheme.com

設定はお世辞にも綺麗とはいえないdotfilesにあります。

https://github.com/haxibami/dotfiles

経緯・コンセプト

デスクトップを自作して、Arch Linuxをインストールしました。初めてLinuxに触れたのが今年3月(WSL)だったことを思えば、いくらか拙速の感はありますが、できるところまでは突き進んでみるつもりです。

GUI環境の選択にあたって、以下の希望がありました。

  • できるだけキーボードで操作したい
  • 制約なくキーバインドをカスタムしたい
  • 美麗なデスクトップが作りたい
  • せっかくなのでArch Linuxっぽいことがしたい
  • なんかModernにキメたい

GNOMEやKDEなどのメジャーなデスクトップ環境は便利で統一感もありますが、依存パッケージを見るとちょっと驚きます。単純に数が多いうえに、ターミナルやファイルマネージャ一つ入れるにも色々な関連サービスが付いてきたり。もちろん、利便性との兼ね合いなのはわかりますが、個人的にはミニマルなArchに入れるには勿体ないと思ってしまうのも事実です。

かといって、いまさらXベースのウィンドウマネージャを使い始めるというのもちょっと癪です。Waylandが掲げる

  • ちらつきのない描画
  • セキュアなコンテンツ管理

等には心惹かれますし、どうせ最先端のArchを使うならより新しいものに触れたい。

そこでswayです。swayはタイル型ウィンドウマネージャ・i3wmのWaylandにおける代替で、両者はほぼ同じ設定ファイルで動作します。軽快な動作とシンプルさを特徴とし、機能を絞って合理的な作業環境を提供してくれます。

筆者は現在swayをメインとし、i3wmをバックアップ・サブ環境として運用しています。どちらかで詰まってももう一方が使えると安心感がありますし、ともに快適で満足しています。

swayの導入

pacman -S sway xorg-xwayland qt5-wayland

ひたすらWikiWikiを読むのみですが、いくつか調べた点をメモ。

起動に関する諸々

起動スクリプト

swayの起動について。dbus-run-session swayでの起動を推奨する情報がGentoo Wikiにあったのですが、自分の環境ではこちらを使うとgnome-keyringがキーリングを表示しなくなる現象を確認したため、swayを使っています。Arch wiki/Sway wikiにも後者しか記載されていません。

また、Waylandバックエンドで一部のアプリを表示するためには環境変数の設定が必要です。これはswayの起動以前に宣言する必要があり、swayのみを使うならPAM^2やsystemd、~/.zshenvあたりで読み込んでやってもよいのですが、今回はi3wmと併用することを踏まえ、システム全体に手を加えないように起動用スクリプトを作って記述してやります。以下のものは最低限の例なので、二重起動防止などを加えるとよさそうです。

swayon.sh
#!/bin/sh

XDG_SESSION_TYPE=wayland
XDG_CURRENT_DESKTOP=sway
XDG_CURRENT_SESSION=sway
LIBSEAT_BACKEND=logind
QT_QPA_PLATFORM=wayland
GDK_DPI_SCALE=1.5
QT_SCALE_FACTOR=1.5
MOZ_ENABLE_WAYLAND=1
WINIT_UNIX_BACKEND=x11

export XDG_SESSION_TYPE XDG_CURRENT_DESKTOP XDG_CURRENT_SESSION LIBSEAT_BACKEND QT_QPA_PLATFORM GDK_DPI_SCALE QT_SCALE_FACTOR MOZ_ENABLE_WAYLAND WINIT_UNIX_BACKEND;

exec sway

ディスプレイマネージャ

swayが公式にサポートしているディスプレイマネージャはありませんが、SDDMやGDM、LightDMあたりからは起動できるようです。自分はLightDMにしました。もちろんコンソールから起動するのもアリでしょう。

pacman -S lightdm lightdm-webkit2-greeter lightdm-webkit-theme-litarvan

greeterのテーマ↓[2]

https://github.com/Litarvan/lightdm-webkit-theme-litarvan

mylightdm_0
mylightdm_1

LightDMはswayのデスクトップエントリ(/usr/share/wayland-sessions/sway.desktop)を自動で認識して選択肢に表示してくれるので、Wikiに従って設定したら、あとは先程の起動スクリプトを実行するように書き換えたエントリを追加します。

/usr/share/wayland-sessions/sway-my.desktop
[Desktop Entry]
Name=Sway
Comment=An i3-compatible Wayland compositor
Exec=/usr/local/bin/swayon
Type=Application

分数スケーリング

ディスプレイの解像度次第では、150%くらいの表示倍率がちょうどいい塩梅に思える場合があります。そこで1.5倍にスケーリングしてやりたいところですが、あいにくsway公式は小数スケーリングを推奨していません。

https://github.com/swaywm/sway/wiki#hidpi

Fractional scaling is supported but is not recommended. Your display does not have fractional pixels - and if you enable fractional scaling we cannot display your windows faithfully, and your image quality will be degraded.

なるほど。

~/.config/sway/config
# 公式では非推奨
output HDMI-A-1 scale 1.5

試しにやってみるとsway自体は問題なく動作しますが、XWaylandで動くアプリケーションで表示が滲みます。現状、解決策は整数スケーリングへの変更しかないようです。

代わりに、前述の起動スクリプトで各GUIライブラリごとにスケーリングを設定します。だいたいはこれで調整できます。

swayon.sh
GDK_DPI_SCALE=1.5
QT_SCALE_FACTOR=1.5

また、XWaylandアプリのdpiは~/.Xdefaultsで設定できます。

~/.Xdefaults
Xft.dpi = 144

GTKテーマ

swayは$XDG_CONFIG_HOME/gtk-3.0/settings.ini ないし ~/.gtkrc-2.0で指定されたGTKテーマを読み取りません。これを設定するため、gsettingsコマンドを用いたスクリプトが紹介されています。

https://bbs.archlinux.org/viewtopic.php?id=225553

import-gsettings.sh
# !/bin/sh
# usage: import-gsettings <gsettings key>:<settings.ini key> <gsetting key>:<settings.ini key>...

expression=""
for pair in "$@"; do
    IFS=:; set -- $pair
    expressions="$expressions -e 's:^$2=(.*)$:gsettings set org.gnome.desktop.interface $1 \1:e'"
done
IFS=
eval exec sed -E $expressions "${XDG_CONFIG_HOME:-$HOME/.config}"/gtk-3.0/settings.ini >/dev/null

これをswayロード時に実行します。

~/.config/sway/config
exec_always ~/.bin/import-gsettings.sh \
              gtk-theme:gtk-theme-name \
              icon-theme:gtk-icon-theme-name \
              cursor-theme:gtk-cursor-theme-name

nwg-look

(2022/07/10追記)

https://github.com/nwg-piotr/nwg-look

なんとsway / wlroots向けの設定エディタがありました。良い話。

個別のウィンドウ設定

(2021/9/4 追記)

いくらタイル型ウィンドウマネージャとはいえ、あらゆるものがタイル型で表示されるのも困ります。そこでウィンドウごとに表示オプションを設定できます。

~/.config/sway/config
# allow floating popup exceptions

for_window [app_id="firefox" title="Firefox — 共有インジケータ"] {
  floating enable
  sticky enable
  move up 1065 px
  move right 330 px
}

for_window [app_id="thunar" title="ファイル操作進行中"] {
  floating enable
}

(中略)

for_window [app_id="guake"] {
  floating enable
  move up 486 px
}

for_window [app_id="showmethekey-gtk" title="Floating Window - Show Me The Key"] {
  floating enable
  sticky enable
  move up 1065 px
  move left 450 px
}

(後略)
指定 機能
floating enable タイル型に配置しない
sticky enable ワークスペースを越えて表示する
move <direction> <x> px floatingしたウィンドウの表示を<x> px, <direction> 方向にずらす

app_id, classはcriteriaと呼ばれ、それぞれWaylandアプリ、XWaylandアプリをsway内で判別するために使えます。詳細はman 5 swayを参照。各ウィンドウのclassapp_idswaymsg -t get_treeの出力から確認できます。

画面共有

方法1

swayで一番苦労するのが、ZoomやDiscordにおける画面共有です。同じWaylandでもGNOME向けにはZoomアプリでの画面共有がサポートされているようですが、これはswayでは使えません。

第一の方法は、ブラウザ上でPipeWireによるWebRTCコンテンツ共有を使うことです。

pacman -S pipewire xdg-desktop-portal xdg-desktop-portal-wlr

swayの設定ファイルで適切に環境変数をセットし、xdg-desktop-portal, xdg-desktop-portal-wlrのsystemdサービスを有効化します。

~/.config/sway/config
exec dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway
systemctl --user status xdg-desktop-portal
systemctl --user status xdg-desktop-portal-wlr

この状態でブラウザ版Zoom / ブラウザ版Discordで共有を開始、画面をクリックすると……

screenshare_0

OK。

https://mozilla.github.io/webrtc-landing/gum_test.html

上のMozillaのサイトでもテストできます。
screenshare_1

共有時に出てくるインジケータ(画像上部、オレンジ色のやつ)については、ウィンドウ設定でfloating modeに設定して画面端へ追いやってやるとよいでしょう。

方法2

(2021/9/4 追記)

Zoomアプリでも画面共有する方法を考案している方がいらっしゃいました。

https://gist.github.com/telamon/23e5362757339bc8f22e9d40f9f1bd8e

上の例ではv4l2loopbackを使用してダミーのカメラデバイスを/dev/video42などに作り、そこにwf-recorderで取得した画面映像を流し込んでいるようです。このオンオフを切り替えるスクリプトを書いて、適当なキーバインドを割り当てるとよさそうです。

paru -S v4l2loopback-dkms

zoomscrshare

カメラと画面共有を同時に使う場面はそう多くないことを踏まえると、これでも十分使えるように思います。ただ4K画面をキャストすると、8C16Tのi7-11700Kでも常時10~15%ほどCPUを消費していたため、お手元のリソースと相談したほうがいいかもしれません。

方法3

(2022/07/10追記)

ちなみに、OBSを使うのが嫌でなければ、OBSの仮想カメラを使うのが手っ取り早いです。PipeWire経由の画面キャプチャを流せるので、wf-recorderよりもいくらか軽い気がします。

+α Zoomについて

(2021/9/4 追記)

AUR版のZoomアプリはどうにもswayと相性が悪く、2021/9/3時点の自分の環境ではあらゆるウィンドウが右下にずれる現象を確認しています(発生しない環境もあるようです)。

brokenzoom

Snap版のZoomも同様の挙動を見せたため、Flatpak版を導入してみるとうまく動きました。ただし、Flatpakアプリのフォント設定にはちょっと癖があるようです。以下参照。

http://kikei.github.io/linux/2021/04/01/spotify.html

(2022/07/10 修正)
コメントを頂き、QT_QPA_PLATFORMの値をxcbに戻すと発生しないことが確認できました。また、QT_QPA_PLATFORM=waylandの場合でも、QT_SCALE_FACTOR=1とすることで防げるようです。

Qt、いつもお前のせいだよ

+β Flatpak版Zoomについて

(2021/10/17 追記)

無敵かと思えたFlatpak版ですが、弱点がありました。なんと(自分の環境では)SSOログインができません。仕方がないので、少しバージョンが古いですがzoom-system-qtを使っています。ただこのバージョンにもまた問題があって、リアクション機能は使えません

zoom-system-qt-control

なんでこんなツールが覇権を握ってしまったのでしょう……

(2022/07/10 追記)

Flatpak版ZoomでのSSOログインはxdg-desktop-portal-gtkをインストールすると動作します。zoom-system-qtはもはや完全にdeprecatedなので使わないほうがよいです。

ツール群

いくらXアプリがXWayland上で動くとはいえ、WaylandではXが提供していた入出力その他の仕組みも置き換えられています。このため、関連するツール群はそれぞれのコンポジタの実装(swayであればwlroots)に対応したものに置き換える必要があります。

ステータスバー

waybar。CSS風のファイルでスタイリングできます。

waybar_right
waybar_left

ランチャー

有名なrofiも動きますが、シンプルでWaylandネイティブなwofiにしました。GTKベースで、こちらもCSSスタイリングが効きます。

mylauncher

dmenuモードもあり、お好きなメニューを流し込むこともできます。

wofi_powermenu

ターミナルエミュレータ

myterminal

Alacritty+tmux。AlacrittyのWayland対応は完全ではなく、WaylandバックエンドではIMEウィンドウが表示できないため、うまく日本語入力がしたければX11バックエンドを指定(WINIT_UNIX_BACKEND=x11)する必要があります。

ブラウザ

Firefox

MOZ_ENABLE_WAYLAND=1を設定してやるとWaylandネイティブで起動します。

Chrome/Chromium

Chromium、およびそれをベースとしたElectron系アプリ全般はXWaylandでは問題なく動きますが、2021年8月現在、Waylandネイティブ(--enable-features=UseOzonePlatform --ozone-platform=wayland)で動作させた場合にはIMEが使えません。

入力メソッド

fcitx5-mozc/fcitx5-skk。fcitx(4)と異なり、fcitx5はWaylandでも変換ウィンドウを適切な位置に表示してくれます。

(2021/9/12追記)
大まかにfcitx5と書きましたが、実際に使っているのは辞書強化版のfcitx5-mozc-utです。ビルドに若干時間がかかりますが、目立った不具合なく動作しています。

スクリーンショット・キャプチャ

grim(画面取得ツール)・wf-recorder(画面録画ツール)・slurp(画面選択ツール)の組み合わせ。スクリーンショットについては、AURにあるgrimshotを導入して手間を省くこともできます。

これは悲しいWindowsユーザのキーバインド

~/.config/sway/config
# [slurp, copy & save]
bindsym $mod+shift+s exec grimshot --notify copy area | wl-paste -t image/png > ~/Pictures/Screenshots/$(date "+%Y%m%d-%H%M%S")'_grim_area.png'

クリップボード

必須のwl-clipboardに、履歴マネージャーclipmanを合わせると便利です。

少し応用して、ランチャーで履歴選択をすることもできます。

~/.config/sway/config
bindsym $mod+v exec clipman pick -t wofi

wofi_cliphist

平文パスワード

clipmanを愚直に使うと、コピーした内容がたとえパスワードであれ、履歴ファイル(~/.local/share/clipman.json)に平文で残されることになります。これを防ぐため、簡単なスクリプトで特定のアプリケーション(keypassxc, bitwarden)上での履歴保持を禁じるとよさそうです。

スクリーンロック

ディスプレイマネージャに頼らなくとも、アイドルデーモンswayidleとロックツールswaylockの組み合わせが使えます。フォークのswaylock-effectsを使うと多少エフェクトで遊べるようです。

myswaylock

通知デーモン

makoがWaylandネイティブで動きます。X向けのdunstも動くようです。

ところで、READMEにある意味深な画像は……

mako_github

音量バー・輝度バー

wob。無駄に動かして遊びたくなります。

wob_1

画面調整

gammastep。Xのredshiftとほぼ同じ設定で動きます。

mygammastep

キー入力の取得

xevの代替としてはwevがあります。また、入力されたキーを画面上に表示するshowmethekeyはWaylandで動作します。

showyouthekey

リモートデスクトップ

(2021/10/15追記)

クライアントに関してはなんでも使えますが、サーバーとなると数が少なく、執筆時点ではwayvncが唯一の選択肢のようです。したがってVNCプロトコルのみが使えます。

vncchallenge

総評

満足です。いい感じにデスクトップが作れて、結構気に入っています。庭いじりに凝る老人の気持ちがようやくわかりました[3]

おまけ

myi3wm

↑ i3wm+polybar。どっちが好みかな?

参考

https://aobako.net/linux/sway/intro/
https://inthisfucking.world/sway/

誤り等ありましたらご一報ください。

脚注
  1. 壁紙はこちらこちらより ↩︎

  2. 壁紙はこちらより ↩︎

  3. Redditのunixporn板なんかを覗いてみると、良いカスタマイズがたくさん見られます。 ↩︎

Discussion