Cygwin/XでWSL2のXアプリケーションを表示する
tl;dr
WSL2の起動スクリプト(manではinitialization file)に以下の設定を追加します。
# Cygwin X Server authentication (requires cygwin's "xhost" package)
CYGWIN_ROOT="/mnt/c/cygwin64"
CYGWIN_XHOST="$CYGWIN_ROOT/bin/xhost.exe"
if [ -f "$CYGWIN_XHOST" ] ; then
# X configuration
export DISPLAY=`grep -oP "(?<=nameserver ).+" /etc/resolv.conf`:0.0
# Avoid the following error:
# libGL error: No matching fbConfigs or visuals found
# libGL error: failed to load driver: swrast
# https://x.cygwin.com/docs/ug/using-glx.html
export LIBGL_ALWAYS_INDIRECT=1
# On Windows, set DISPLAY=:0.0
IP_ADDR=`ip addr show eth0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1`
${CYGWIN_XHOST} +${IP_ADDR}
fi
背景
LinuxマシンでのEmacsは長らくurxvt + emacs-noxという構成で使っていましたが、emacs-lspをGUIで使いたいと思い、GTK版のEmacsに移行しました。これに合わせるために、X接続をCygwin/Xで実現することにしました。
インターネット上にはVcXsrvで表示する方法については色々と情報があるのですが、ウィンドウサイズが10行分しかない状態で起動するのと突然ウィンドウが落ちるので使用を断念しました。ただVcXsrvに関する情報には、アクセスコントロールを無効にする直接のX描画(つまりSSHのX11 port forwardingを使わない)であれば表示できるとあり、Cygwin/Xの設定の参考にします。
前提条件
- Windows
- WSL2を起動するとネットワークアダプタ
vEthernet (WSL)
が生成される。 XWin.exe
のTCP受信がファイアウォールで許可されている。または6000/TCP
の受信が許可されている。
- WSL2を起動するとネットワークアダプタ
- Cygwin
- Cygwinは
C:\cygwin64
にインストールしてある。 - Cygwin/XをCygwin/X User’s Guide Chapter 2. Setting Up Cygwin/Xに従ってインストールしてある。
- Cygwinに
xhost
パッケージをインストールしてある。 - Cygwin/Xを起動するときの画面番号は
0
とする。 - Cygwinの
DISPLAY
環境変数は:0
とする。
- Cygwinは
- WSL2
bash
がログインシェルとして使われている。eth0
がホスト側のネットワークアダプタvEthernet (WSL)
に対応している(おそらくデフォルト)。
上記前提条件のうち、技術的要件は以下の2つです。
XWin.exe
のTCP受信がファイアウォールで許可されている。または6000/TCP
の受信が許可されている。- Cygwinに
xhost
パッケージをインストールしてある。
ほかの2つは既定の設定であるか、環境に関する決めの問題です。
アイディア
Cygwin側でxhost +
とすればアクセスコントロールを無効にできますが、もう少しセキュアな設定にしたいです。xhost +<WSL2のIPアドレス>
によってWSL2にのみ許可を与えることにします。
- Cygwin側は
xhost
に与える<WSL2のIPアドレス>
を知る必要がある。 - WSL2側は
DISPLAY
環境変数にセットするホスト側のIPアドレスを知る必要がある(ディスプレイ番号は0
決め打ちとした)。
WindowsとWSL2との間の仮想ネットワークvEthernet (WSL)
はWSL2の起動時になって生成され、それまではWSL2のIPアドレスもホスト側のIPアドレスも決定されません。よって、WSL2の起動後に上記2点の設定ができるようになります。
1についてはWSL2側のip addr
の出力の加工で取得できますし、2についてもCan’t use X-Server in WSL 2 #4106で議論されている通り、/etc/resolv.conf
から取得することができます。またはWSL2の中のX clientから VcXsrv に xauth で接続したいにあるように、<マシン名>.mshome.net
をホスト名とすることができます。CygwinのコマンドはWSL2からも実行することができるので、1と2の両方の設定もWSL2の起動スクリプトから行えます。
ここまでを踏まえ、以下の設定(再掲)としました。
# Cygwin X Server authentication (requires cygwin's "xhost" package)
CYGWIN_ROOT="/mnt/c/cygwin64"
CYGWIN_XHOST="$CYGWIN_ROOT/bin/xhost.exe"
if [ -f "$CYGWIN_XHOST" ] ; then
# X configuration
export DISPLAY=`grep -oP "(?<=nameserver ).+" /etc/resolv.conf`:0.0
# Avoid the following error:
# libGL error: No matching fbConfigs or visuals found
# libGL error: failed to load driver: swrast
# https://x.cygwin.com/docs/ug/using-glx.html
export LIBGL_ALWAYS_INDIRECT=1
# On Windows, set DISPLAY=:0.0
IP_ADDR=`ip addr show eth0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1`
${CYGWIN_XHOST} +${IP_ADDR}
fi
Cygwin/Xの起動ショートカットの設定
OpenGL (GLX) - Cygwin/X User’s GuideのTable 3-1からレンダリングオプションの組み合わせを選択します。
indirect
とhardware-accelerated rendering
の組み合わせを選んだので、ショートカットは以下の内容としました。
- 名前
XWin Server
- リンク先
C:\cygwin64\bin\run.exe --quote /usr/bin/bash.exe -l -c "cd; exec /usr/bin/Xwin.exe :0 -multiwindow -listen tcp +iglx -wgl"
- 作業フォルダー
C:\cygwin64