LightDMでカスタムの解像度を追加して永続化する

Raspberry Pi Model 4Bに[Twister OS](https://twisteros.com/)でデスクトップ環境を構築しました。ディスプレイの解像度はGUIから変更ができますが、あいにく接続したディスプレイに適した解像度がありませんでした。ここでは解像度を1366x768に設定するものとして、再起動しても反映されたままにする方法を記します。

ディスプレイに表示できなくなる場合に備えて、作業前にSSHで接続できるようにしておくのが望ましいです。

## VESA CVT modelineの生成
新しい解像度設定のためのモード文字列を[`cvt`コマンド](https://linux.die.net/man/1/cvt)で生成します。

```shell
$ cvt 1366 768
# 1368x768 59.88 Hz (CVT) hsync: 47.79 kHz; pclk: 85.25 MHz
Modeline "1368x768_60.00"   85.25  1368 1440 1576 1784  768 771 781 798 -hsync +vsync
```

1366x768を指定しているのに1368x768のモードで出力されていますが、これは水平カウントが8の倍数である（1368=171*8）というVESA CVTの標準に従うためです。
参考: [xorg - cvt is acting strange when defining resoluton - Unix &amp; Linux Stack Exchange](https://unix.stackexchange.com/questions/524595/cvt-is-acting-strange-when-defining-resoluton)

## 解像度設定を追加する
先ほどの`cvt`コマンドの出力から`Modeline`の行を利用して解像度設定を追加します。

```shell
$ xrandr --newmode "1368x768_60.00"   85.25  1368 1440 1576 1784  768 771 781 798 -hsync +vsync
```

`"1368x768_60.00"`の部分は解像度設定の名前ですので自由に変更できます。
続いて画面出力に対して上記の設定値を追加しますが、その準備として追加先にする画面出力を調査します。

```shell
$ xrandr --listmonitors
Monitors: 1
 0: +*HDMI-1 1280/698x720/392+0+0  HDMI-1
```

この場合は1つしかディスプレイを接続していないため、`HDMI-1`が追加先の画面出力です。複数のディスプレイを接続している場合はより多くの行が表示されます。次に設定値を追加します。

```shell
$ xrandr --addmode HDMI-1 1368x768_60.00
```

`1368x768_60.00`は`xrandr --newmode`で追加した解像度設定の名前です。

## 画面の解像度を変更する
対象の画面の解像度を変更します。

```shell
$ xrandr --output HDMI-1 --mode 1368x768_60.00
```

指定した解像度になっていれば成功です。

## 解像度設定を永続化する
ここまでで現在のセッションに対する画面解像度は変更されましたが、再起動を行うとリセットされてしまいます。再起動後も同じ設定が維持されるように、ディスプレイマネージャが起動した時に上記の操作が行われるように設定します。
LightDMの設定ファイル`/etc/lightdm/lightdm.conf`の`display-setup-script`の項目に指定されているシェルスクリプトを編集します。例として、私の環境では`/usr/share/dispsetup.sh`でした。

```shell:/usr/share/dispsetup.sh
#!/bin/sh
xrandr --newmode "1368x768"   85.25  1368 1440 1576 1784  768 771 781 798 -hsync +vsync
xrandr --addmode HDMI-1 1368x768
xrandr --output HDMI-1 --mode 1368x768
exit 0
```

一度ログインした状態で解像度設定を行っており、ログイン画面の解像度を気にしない場合は`xrandr --output HDMI-1 --mode 1368x768`の行はなくても問題ありません。その場合はログイン後に指定した解像度が適用されます。

## 参考
### 参考文献
- [Making xrandr modifications permanent with lightdm | GitHub Gist](https://gist.github.com/ciarand/8592193)
- [LinuxのGUI環境（X Window System、ディスプレイマネージャ、ウィンドウマネージャ、デスクトップ環境） - 恥は/dev/nullへ by 初心者](https://uhoho.hatenablog.jp/entry/2020/12/24/125056)
    - Xウィンドウシステムとディスプレイマネージャの関係など、大変分かりやすく記述されています
    - [Part 5 : 参考にしたページ](https://uhoho.hatenablog.jp/entry/2020/12/24/125056#Part-5--%E5%8F%82%E8%80%83%E3%81%AB%E3%81%97%E3%81%9F%E3%83%9A%E3%83%BC%E3%82%B8)も目を通すと勉強になります
- [今さら .xinitrc, .xsession, .xprofile | ゴルディアスの涙目](https://gordiustears.net/xinitrc-xsession-xprofile/)

### 試してダメだった方法
- `/etc/profile.d`にシェルスクリプトを配置する
    - [Ubuntuディスプレイ解像度を自動で1920x1080に変更させる - 生物系がゼロから始めるTech Blog](https://www.bioerrorlog.work/entry/auto-change-resolution)
- `~/.xprofile`や`~/.xinitrc`に記述する
    - [Setting xrandr changes persistently - Ubuntu Wiki](https://wiki.ubuntu.com/X/Config/Resolution#Setting_xrandr_changes_persistently)
- `~/.config/xfce4/xinitrc`に記述する
    - デスクトップ環境にXfceを利用している場合のみ
    - Twister OSでは動きませんでした
- `/etc/init/lightdm.conf`に記述する
    - [Run a startup script with lightdm - Ask Ubuntu](https://askubuntu.com/questions/74189/run-a-startup-script-with-lightdm)

### 別の方法
- `~/.xsessionrc`に記述する
    - `/usr/share/dispsetup.sh`からshebang（`#!/bin/sh`）と`exit 0`を除いたものを記述します
    - ログイン後にXセッションが起動してから実行されるため、ログイン画面では設定した解像度が適用されません