🎩

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

16 min read

これはなに?

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](/etc/environment)や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;

sleep 1;
exec sway

(sleepは、LightDM使用時にttyの切り替え過程でキーボードが認識されなくなるのを防止するために加えています。以下参照)

https://github.com/canonical/lightdm/issues/63

ディスプレイマネージャ

さて、swayon.shを直接ttyから叩いてもよいのですが、自分の場合はそうもいきませんでした。

https://wiki.archlinux.jp/index.php/KMSCON

原因はこの子です。KMS、Unicode表示、GPUレンダリングに対応した新しいttyコンソール、kmscon。WaylandどころかXがなくとも動き、日本語やアラビア文字が表示できたりして楽しいのですが、残念なことにkmsconからはX/Waylandセッションを起動することができません。というか、そもそもそういう使い方が想定されていない。

別のttyに切り替えて起動すれば問題なく動くとは思いますが、せっかく綺麗なコンソールを導入したのに後戻りするのも癪なので、ここは開発者氏のお言葉に従ってディスプレイマネージャを使うことにします。

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

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

greeterのテーマ↓[3]

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.desktop
[Desktop Entry]
Name=Sway
Comment=An i3-compatible Wayland compositor
Exec=/usr/local/bin/swayon
Type=Application

分数スケーリング

4K/32インチディスプレイなんぞを使っていると、100%は目に悪く、200%となると大きすぎ、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で表示が滲みます。現状、解決策は整数スケーリングへの変更しかないようです[4]

~/.config/sway/config
output HDMI-A-1 scale 1

代わりに、前述の起動スクリプトで各GUIライブラリごとにスケーリングを設定します。ただし、これでは対応しきれないもの(glfx, sdl, winit等)もあります。

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

ウィンドウ設定

(2021/9/4 追記)

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

~/.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における画面共有です。GNOME向けにはZoomアプリでの画面共有がサポートされているようですが、これはswayでは使えません。第一の方法はブラウザ上で、pipewireによるWebRTCコンテンツ共有を使うことです。

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

swayの設定ファイルで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

いい感じ。

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
~/.config/sway/config
# cast screen as dummy camera
bindsym $mod+shift+r exec ~/.bin/swayscrshare.sh

zoomscrshare

実際、カメラと画面共有を同時に使う意義は薄いことを踏まえると、これでも十分使えるように思います。何よりあらゆるアプリで使えますし、切り替えも簡単。

ただ4K画面をキャストすると、8C16Tのi7-11700Kでも常時10~15%ほどCPUを消費していたため、お手元のリソースと相談したほうがいいかもしれません。

+α 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

ツール群

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

ステータスバー

waybar。CSSでスタイリングできます。

waybar_right
waybar_left

フォントはRoboto Mono+Font Awesome。

ランチャー

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

mylauncher

dmenuモードもあり、お好きなメニューを流し込めたり。

wofi_powermenu

ターミナルエミュレータ

myterminal

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

ターミナルが降ってくるとシンプルに面白いので、guakeも併用しています。

myguake

ブラウザ

Firefox。MOZ_ENABLE_WAYLAND=1を設定してやるとWaylandネイティブで起動します。フォントはNoto Sans CJK JP。

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

エディタ

neovim。全然使いこなせていませんが、なんだか愛着は芽生えてきました。

neovim_suggest
neovim_pyright

coc.nvimの補完でVSCodeに勝ちましょう。

入力メソッド

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(xfceのほうではない)を合わせると便利です。

wofiで履歴選択もOK

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

wofi_cliphist

平文パスワード

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

画像と謎挙動

2021年8月現在、wl-clipboard/grimの環境下でスクリーンショットをコピーすると、画像とともに大量のテキスト(数十万字)がコピーされ、TweetDeck等への貼り付け時に一緒に放出される現象を確認しています。この現象はTwitter Web Clientでは発生しません。(追記:これはX11上でxclipを使った際にも起こりました)

twitter_clipboard

スクリーンロック

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

myswaylock

通知デーモン

makoがネイティブで動きます。X向けのdunstも動くようです。
READMEにある意味深な画像は……
mako_github

音量バー・輝度バー

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

wob_1

画面調整

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

mygammastep

色温度の遷移中にたまにヤバい色になりますが、特に気になりません。

キー入力の取得

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

showyouthekey

リモートデスクトップ

(2021/9/16追記)

クライアントに関してはX11と同様のものが使えますが、サーバーは数が少なく、執筆時点ではwayvncが唯一の選択肢のようです。X509証明書を用いた検証や、sshトンネルを経由した接続なども使えます(後者は実際に試しました)。

https://twitter.com/haxibami/status/1438190135334502401?s=20

↑Windows 11上のWSLgでTigerVNC Clientからswayに繋いでいる

微妙なこと

なんかXWaylandでIMEウィンドウがデカい

これはDPI設定の都合。

wofiで直接コマンドを打てない

rofiのrunモードでは検索エントリに入力したコマンドをそのまま<Enter>で実行できますが、この機能はwofiのrunモードには備わっておらず、あくまでアプリ起動のみとなります。ラッパーを書けば実装可能かもしれません。

またwofiについて調べようと思うと、必ず"-wifi"や"linux" "man page"をキーワードに加えないとまともに検索結果が出てきません。ここは少し苛々ポイント。

総評

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

ニッチな選択ではありそうですが、なんだかんだで設定ファイル一つで動くのでハードルは低めです。検索さえできて、英語が読めればなんとかなります。色々勉強しつつ、しばらくはこれで暮らしていこうと思います。

おまけ

myi3wm

\ i3wm+polybar /

どっちが好みかな?

参考

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

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

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

  2. ホームディレクトリに置けて一見便利な~/.pam_environmentもありますが、こちらは廃止予定だそうです。 ↩︎

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

  4. sway/wlroots/xwaylandのフォークに、sway-hidpi-git/wlroots-hidpi-git/xorg-xwayland-hidpi-gitがあり、これらは名前の通り高DPI環境へのサポートを付加しています。具体的にはXWaylandアプリでのスケーリング倍率をWaylandアプリとは別に設定できる仕様になっており、これにより小数スケーリング環境でも適切なXWayland表示を実現できるのですが、数年前にプルリクエストが拒絶されて以来、本家にはマージされていないようです。以前はこちらを使っていましたが、将来性が不安なのと、まれにsway自体が起動しなくなって依存パッケージを含めた再インストールが必要になったため、本流に切り替えました) ↩︎

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

Discussion

ログインするとコメントできます