Surface Pro 4でlubuntu 18.04を使う

Surface Pro 4にlubuntu18.04を導入して、できるだけ快適に使えるようにするまでを紹介します。

lubuntuを入れる理由は、たまにlinuxを使いたい場合があること、ベースであるubuntuの情報が豊富なこと、動作速度と使いやすさのバランスがいいこと、などです。ディスク・メモリに余裕があるならLinuxMintがいいんですがメモリが4GBくらいであればlubuntuがいいと個人的には思います。今回使うSurfacePro4はメモリ8GBですが、温度が上がるのとSSDの容量が心配だったためlubuntuにしました。

(追記)BitLockerでCドライブを暗号化している(Microsoft側の推奨のため、したつもりがなくてもなっている場合が多そうです)場合は必ず前もって回復キーをどこか(該当のWindowsを起動していなくても見られる場所)にバックアップしておいてください。でないとLinuxのインストール後にWindowsが起動できなくなり、再インストールする羽目になります。参考→Windows 10 Proでディアルブート環境を作るときにはBitLockerの回復キーを控えておこう - Qiitaなど

自分の場合はBitLockerが無効になっていたようなので(後述のようにインストール後に有効にした)幸いこの罠にはハマりませんでしたが危ないところでした。

(以上追記)

インストール

結構いろいろな記事で解説されており、そのとおりにやったらうまく行ったのでリンクを載せます。他の項目でも、他に詳しい記事があればそっちを紹介して済ませることにします。

Surface Pro 4にUbuntu 16.04 LTSを導入する - Qiita - 情報が新しく、基本はこれに従えばいいと思います。Surface Pro3から4の間でも状況は変わっており、セキュアブートを無効にしなくてもMicrosoft & 3rd Party CAというオプションにするとubuntuが正しく動作するようになったようです。タイプカバーが何もしなくても正しく動作するというのも半信半疑でしたがちゃんと動いて驚きました。

Ubuntu1610OnSurfacePro4 - Debian UnstableでGO! - こちらはやや情報が古く、いろいろと面倒事を強いられている感じです。基本的にこういうことはしなくてもできましたが、唯一冒頭に書いてある「premature end of file...」には悩まされました。isoの直接コピーだとか、NTFSじゃなくてFAT32でやるとか、そもそもパーティションテーブルをGPTにしてみるとか、色々やりましたがうまく行きませんでした。結局、すでにデスクトップPCにインストールしてあったlinux mintの「USB イメージライタ」でやったらうまく行きました。理由はわかりません。

パッチのインストール

このままでもタイプカバーは正しく動くのですが、タッチは機能しなかったので、GitHub - jakeday/linux-surface: Linux Kernel for Surface Devicesをインストールします。lubuntuならDownloads for ubuntu based distrosってところからダウンロードすればできるはずです(あまり記憶にないので多分すんなり行ったんじゃないかと…)。「Signing the kernel for Secure Boot」の設定はしたほうがいいです(しないとdpkgでパッケージをインストールするたびにエラーが出てイライラします(それ以外にあまり問題はないです))。

高DPI設定

SurfacePro4のディスプレイは解像度が高く、あらゆるものが小さくて見にくいので、~/.Xresourcesに

Xft.dpi: 192

のように書き込んでログインし直します。数値が大きければ大きいほど文字も大きくなります。これで、フォントなど拡大縮小が効くものは大抵正しく表示されます。アプリケーションによってはこれでもうまく行かないので、そのときはHiDPI - ArchWikiを参照してください。また、Fontforgeなどがそうでしたが(

Support for High-DPI display · Issue #2483 · fontforge/fontforge · GitHub

)、個別のソフト内の設定で変えられる場合もあるので調べてみてください。Windowsの「システム(拡張)」的な万能薬は無いようです。

grubのカスタマイズ

必要はないのですが、やるなら最初のうちにやったほうがいいと思います(ミスって全てを吹っ飛ばすのが怖いので)。GRUB/ヒントとテクニック - ArchWikiこんな感じで、テーマ設定が書かれたファイル名を指定します。テーマは調べたらたくさん出てきますが、古いのだとリンク切れのものばかりでした。また、画像ファイル部分はあとから差し替えればいいので、けっこう簡単にカスタマイズできて楽しいです。

画面の明るさ

/sys/class/backlightを編集します。また、Ctrl+F10とCtrl+F11でそれぞれ暗く、明るくできます。

画面の明るさの設定は電源設定にある場合のほうが多いです。

Cドライブのマウント

Bitlockerを有効にしている場合の話をします。有効にしていない場合については試していませんが、以下の記述において、dislocker-fuseコマンドは全て無視し、/media/bitlocker/dislocker-fileの部分をすべて/dev/nvme0n1p3のように直接Windowsが入っているパーティションを指定するように置き換えればできるかと思います。

Bitlockerを使う場合は、BitLockerで暗号化されたストレージをLinuxでマウントするためのdislocker – guro_chanの手帳 だいたいこのとおりですが、この方式だと一旦復号したのをファイルに書き出して静的にマウントするようなので、(事実上)readonlyになります。直接的にパーティションを読み書きしたい場合がほとんどだと思うので、dislocker-fuseコマンドを使います。また、自分の環境ではCan't access Windows drive: “Windows is hibernated, refused to mount” - Unix & Linux Stack Exchangeこれと同じ状況になったので、そこに書いてある解決策に従います。具体的なコマンドは次のようになります。(nvme0n1p3)

$ sudo dislocker-fuse -V /dev/nvme0n1p3 --recovery-password=xxxxxx-xxxxxx-xxxxxx-xxxxxx-xxxxxx-xxxxxx-xxxxxx-xxxxxx -- /media/bitlocker
$ sudo ntfs-3g -o remove_hiberfile /media/bitlocker/dislocker-file /media/win

また、/etc/fstabには、

/dev/nvme0n1p3     /media/bitlocker     fuse.dislocker recovery-password=xxxxxx-xxxxxx-xxxxxx-xxxxxx-xxxxxx-xxxxxx-xxxxxx-xxxxxx 0 0

/media/bitlocker/dislocker-file   /media/win ntfs-3g rw,nofail,remove_hiberfile 0  2

と、二行に分けて記載します。 

また、Bitlockerを有効にしたあとにWindowsを起動したら再起動ループにハマりました。解決法はこちらです→Stop a BitLocker boot loop - Windows 10 - Spiceworks

 

また、もちろんWindowsの「高速スタートアップ」はoffにしておくべきです。そして、なぜかoffにしても高速スタートアップのような挙動をしたので、Windows側で、シャットダウン時に実行するコマンドに完全シャットダウン(shutdown /s /f /t 0)を追加しました。

Windowsが強制終了するなど正しくシャットダウンされなかった場合はこれでもマウントできないので、ntfsfixというコマンドを使います(本来は一旦windowsを起動してから再起動するのが筋ですが…)。これはfstabには書けないのでどっかのシェルスクリプトに書いておいて必要なときのみ起動します。こんな感じになります。

sudo ntfsfix /media/bitlocker/dislocker-file
sudo mount -t ntfs-3g /media/bitlocker/dislocker-file /media/win -o rw,nofail,remove_hiberfile

 なお、僕はWindows側でCドライブに"!"アイコンがついていて見栄えが良くないためBitlockerを有効にしましたが、回復キーはLinuxに平文で保存されているのでセキュリティ的には全く意味ないです。

その他の設定

Ubuntu 18.10をインストールした直後に行う設定 & インストールするソフトにいろいろ書いてあります。『デスクトップ』『音楽』などの日本語フォルダー名を英語表記にするマルチブート環境や仮想マシン上のWindowsの時計がズレるのを防ぐあたりは定番ですね。これもやるなら早いうちのほうが楽でしょう。

キーボード配列

戻る・進むで右Alt+←→を個人的によく使うのですが、右Altがうまく機能しませんでした。キー配列の変更はxmodmapを使うものがよく出てきますが、最近はX KeyBoard extension - ArchWikiのように/etc/X11/xorg.conf.d/のルールとして設定するほうが推奨されているようです。今回の場合、90-custom-kbd.confというような名前のファイルにSection "InputClass"
     Identifier "keyboard defaults"
     MatchIsKeyboard "on"
     Option "XKbOptions" "lv3:ralt_alt"
EndSection

と書いておきます。

スクロールの向き

これも.Xmodmapに書き込む方法がよく出てきますが、一部アプリケーションには反映されなかった記憶があります。Xfce タッチバッドのスクロール方向の設定 - QiitaのようにSynclientを使ったほうがいいです。設定を永続化するには、Synaptics タッチパッド - ArchWikiに書いてあるとおり、これもやはり/etc/X11/xorg.conf.d/の中にファイルを作ってそこに書きます。シェルスクリプトにsynclientのコマンドを書いて、スタートメニューの「LXSessionのデフォルトのアプリケーション」から自動起動に登録してもいいのですが、カバーを閉じたとき(後述します)にリセットされてしまうのでxorg.conf.dを使ったほうがいいです。

タッチパネルが反応しなくなる問題

Minecraftで猛スピードで交易して画面をタッチしまくっているとたまにタッチが効かなくなることがありました。その時はhttps://github.com/jakeday/linux-surface/issues/55に記載の通り、

rmmod intel_ipts

modprobe intel_ipts

とすれば治ります。いちいち打つのは面倒なのでキーボードショートカットにしたいのですが、root権限がいるので、https://askubuntu.com/questions/821919/how-do-i-add-sudo-commands-to-a-keyboard-shortcut を参考に、root権限無しで実行できる特例としてシェルスクリプトを作り、これをホットキーに登録しておきます。

ブルーライトカット

Linuxでブルーライトカット - turgenev’s blogに書いたとおりです。

カバーを閉じたときの動作

これ以降は、自分がやった限りあまりうまく行かなかったものが並んでいます。

Surfaceのタイプカバーを閉じると画面が暗くなり、開けても反応しなくなってしまいます。本当は、ハイバーネーションかサスペンドが正しく動作すればよいのですが、まずサスペンドはjakedayのページでも動かないと明言されています。ハイバーネートは、(swapfile、grubなどを適切に設定した上で)uswsuspのs2diskコマンドを使ったら、一応できました。しかし再起動後はWi-Fiやタッチが動作しないなど、使い物になりません。systemctlコマンドを使うやり方もうまく行きませんでした(Hibernate doesn't turn off completely computer surface Pro4 · Issue #378 · jakeday/linux-surface · GitHubのようになる)。

とりあえず、Windowsの癖で蓋を閉じたときにそのまま使えなくなってしまうのは困るので、蓋を閉じても何も起こらない(ディスプレイもオンのまま)ようにします。power management - How can I tell Ubuntu to do nothing when I close my laptop lid? - Ask Ubuntuに記載の通り、Upower.confのIgnoreLidをtrueにしました。僕の環境だとlogind.confのHandleLidSwitch=ignoreだけではうまく行きませんでした。

その上で、acpidを利用し、カバー(lid)を閉じるとディスプレイがオフになるようにします。/etc/acpi/eventsフォルダの中に、lm_lid(適当でいいです)というファイルを作成し、

event=button/lid LID close
action=/etc/acpi/lid.sh

のように書き込みます。そして、/etc/acpi/lid.shの中には

#!/bin/sh

export DISPLAY=:0
xset dpms force off

のように書いておきます。また、

#!/bin/sh
xhost si:localuser:root

と書いたスクリプト自動起動に登録しておきます。

こうしておくことで、rootがローカルユーザーのディスプレイを認識できるようになります。

また、このままだと何故か最初の一回しか動作しませんでした。色々と調べると、カーネルパラメータにbutton.lid_init_state=ignoreを追加すれば良いということがわかりました。GRUB_CMDLINE_LINUXに追記してgrub2-updateします。なお、蓋を開けたイベントも検出できるのですがタイミングがおかしかったので使っていません。/proc/acpi/button/lid/LID0/stateの中身は正しく更新されているようなので、開けたときにどうしても自動で電源がonになってほしい場合は、closeのイベントを検出した時点からそのファイルを監視し始め、openになったらつけるようにすればできるでしょう(本来はkernelの機能から直接的にできてほしいのですが…)。僕は、どうせwindowsでもつかないんだからということでやっていません。

電源ボタンの動作

デフォルトでは、ログアウトや再起動などいくつかのオプションを聞いてくる画面になります。これもwindowsに慣れた感覚ではあまり使い勝手が良くないです。このボタンの動作はホットキーのところで定義されているのでそれをいじります(acpidで検出することも可能ですが)。理想としてはここにハイバーネートのコマンドを指定したいところですが、前述の通りうまくいかないので、やはり「xset dpms force off」を使います。ただしこれをそのまま指定すると、ボタンを離したタイミングに反応してディスプレイが再びonになってしまうため、sleep 1したあとにこれが実行されるよう、シェルスクリプトに書いてそれを登録します。

ウインドウのリサイズ

デフォルトのままではウインドウの端の「当たり判定」が狭すぎて、ものすごく注意深くカーソルを動かさないとリサイズできません。これはlubuntuというかLXDEの問題です。一応Size of grab area for resizing window in lubuntu - Ask Ubuntuという解決策っぽいものがありますがこれだと見た目まで太くなってしまいます。代わりに、Alt+右ドラッグで端を持っていなくてもリサイズできるようなのでこれで我慢しました。

おわりに

Surfaceでlubuntuをただ使うだけなら簡単ですが、Windowsと変わりない使い心地を追求するのはけっこう骨が折れます。Archwikiは相変わらず頼りになりますが、それ以上の日本語の情報はほとんど無いですし、ブログに書くくらいのモチベーションがないとやってられません。せっかく書いたので、特にハイバーネートあたりに関して解決策などあればコメントいただけると嬉しいです。質問とかでもいいです。

また、lubuntu18.10からはLXDEでなくLXQtになったようで、ここに書いたうちいくつかはもしかしたら用無しになるのかもしれません…