Ubuntu Weekly Recipe

第492回 GNOME Shellの拡張機能を作ってみよう

この記事を読むのに必要な時間:およそ 6 分

今月の19日ぐらいにUbuntu 17.10がリリースされます。17.10の最大の変更点はUnityからGNOME Shellへの移行でしょう。そのGNOME Shell,実はUIコンポーネントの多くをJavaScriptで実装しています。JavaScriptの知識さえあれば容易に機能拡張できるようになっているのです。今回はそんなGNOME Shellの拡張機能の作り方を紹介します。

GNOME ShellとJavaScript

今回のリリースはGNOME Shellを抜きにしても,ここ数年で最大の変更点がごろごろ転がっています。ただ,いかんせん「GNOME Shellへの移行」のインパクトが大きすぎて,デスクトップ関連だと「まずGNOME Shellの話」をするだけでお腹いっぱいになってしまう状況になっています。もっとも影響が大きいであろうGNOME Shellに関しては,細かい問題はいくつかあるものの,なんとか今回のリリースで移行を完了できそうな見込みです。おそらく18.04の開発期間は,移行後のブラッシュアップに費やされることでしょう。

さてそんなGNOME Shellについて。これまで採用してきたUnityに対する最大のアドバンテージはその「拡張機能」でしょう。ウェブブラウザーのようにユーザーは自由に拡張機能を追加することで,ただのテーマを超えたUIのカスタマイズが可能になっているのです。いわゆるGNOME 2時代のアプレットやウィジェットがひとつにまとまったようなものだと思ってください。GNOME Shellの拡張機能については過去にも第254回第258回などで,さまざまな拡張機能を紹介していますし,最近だと第490回にてUbuntuのUIを実現するためにUbuntu 17.10で採用される標準の拡張機能の解説が掲載されています。

GNOME Shellの拡張機能はJavaScriptとCSSで構成されています。つまりウェブ開発の経験があれば比較的かんたんに拡張機能を作成できるのです。実はGNOME Shell本体も,そのシェル部分の多くがJavaScriptとCSSで構築されています。/usr/lib/gnome-shell/libgnome-shell.soの中身も,ほぼJavaScriptの関数だったりします。

ちなみにGNOME ShellではJavaScriptエンジンとして,Firefoxでも利用されているSpiderMonkeyを採用しています。MozillaのソースツリーからSpiderMonkey部分のみがmozjsパッケージとして切り出されているので,それをベースにしたGObject introspectionのJavaScriptバインディングがgjsです。GHOME Shellでは,gjsを用いてUIエレメントを操作できるようになっています。

たとえばGNOME Shell上で「Alt+F2」を押すと,コマンド実行ダイアログが表示されます。そこで「lg」を入力すると「Looking Glass」と呼ばれるデバッグシェルが起動します。Looking GlassのシェルではJavaScriptの文法に従ったコードを書くことでUIの要素を調査したり,コードスニペットの動作確認を行えるのです。

図1 Looking Glassのダイアログ

画像

GNOME Shell Extension

さっそくGNOME Shellの拡張機能を作ってみましょう。今回はまだ開発版であるUbuntu 17.10で作業をしていますが,GNOME Shell環境であればUbuntu GNOMEの古いリリースや他のディストリビューションでも同じような結果になるはずです。

GNOME Shellには拡張機能の管理コマンドであるgnome-shell-extension-toolが同梱されています。このコマンドを使うと,拡張機能の雛形も生成してくれるのです。

適当なディレクトリで--create-extensionオプションを付けて実行し,いくつかの質問に答えていきます。

$ gnome-shell-extension-tool --create-extension

Name should be a very short (ideally descriptive) string.
Examples are: "Click To Focus",  "Adblock", "Shell Window Shrinker".

Name: Sample

Description is a single-sentence explanation of what your extension does.
Examples are: "Make windows visible on click", "Block advertisement popups"
              "Animate windows shrinking on minimize"

Description: Sample Extension for Recipe

Uuid is a globally-unique identifier for your extension.
This should be in the format of an email address (foo.bar@extensions.example.com), but
need not be an actual email address, though it's a good idea to base the uuid on your
email address.  For example, if your email address is janedoe@example.com, you might
use an extension title clicktofocus@janedoe.example.com.
Uuid [Sample@ubuntu-ax2]: sample@mty.shibata.gmail.com
Created extension in '/home/shibata/.local/share/gnome-shell/extensions/sample@mty.shibata.gmail.com'
This tool has been deprecated, use 'gio open' instead.
See 'gio help open' for more info.

決めなければならない項目は次の3つです。

  • 名前(Name)
  • 概要(Description)
  • UUID

名前と概要は自由に設定してください。UUIDはユニークなIDをつけますが,何か決まった指定方法があるわけではありません。他の拡張機能と名前がかぶらないことが重要です。コマンドの説明にもあるように,拡張機能の名前)@(作成者のメールアドレスで@を.に変更したもの)⁠あたりが無難でしょう。

設定が完了するとエディターが起動し,メインコードであるextension.jsが表示されます※1)⁠実際に作られるファイルは次の3つです。

※1
xdg-open ファイル名で起動するのですが,xdg-openから呼び出しているgvfs-openがdeprecatedなために,上記のような警告メッセージが出ています。将来的にgio openコマンドが使われるようになるはずです。
  • extension.js
  • metadata.json
  • stylesheet.css

extension.jsが実際にロジックを記述し,metadata.jsonには拡張機能の情報を記録します。stylesheet.cssは作成するUI部分のレイアウトを記述するCSSファイルです。

作成されたファイルはユーザー固有の拡張機能ディレクトリ~/.local/share/gnome-shell/extensions/に保存されます。

$ ls -la ~/.local/share/gnome-shell/extensions/sample@mty.shibata.gmail.com/
合計 20
drwxrwxr-x 2 shibata shibata 4096 10月  7 20:32 .
drwxrwxr-x 3 shibata shibata 4096 10月  7 20:32 ..
-rw-rw-r-- 1 shibata shibata 1468 10月  7 20:32 extension.js
-rw-rw-r-- 1 shibata shibata  133 10月  7 20:32 metadata.json
-rw-rw-r-- 1 shibata shibata  172 10月  7 20:32 stylesheet.css

$ cat ~/.local/share/gnome-shell/extensions/sample@mty.shibata.gmail.com/metadata.json
{"name": "Sample", "description": "Sample Extension for Recipe", "uuid": "sample@mty.shibata.gmail.com", "shell-version": ["3.26.1"]}

$ cat ~/.local/share/gnome-shell/extensions/sample@mty.shibata.gmail.com/stylesheet.css
.helloworld-label {
    font-size: 36px;
    font-weight: bold;
    color: #ffffff;
    background-color: rgba(10,10,10,0.7);
    border-radius: 5px;
    padding: .5em;
}

一般的にGNOME Shellの拡張機能をインストールしたときは,このディレクトリに展開されます。Ubuntu DockやAppIndicatorsのようなシステムグローバルな拡張機能は/usr/share/gnome-shell/extensionsに保存されます。

サンプル拡張機能の有効化

拡張機能をインストールしただけでは機能は有効になっていません。第490回でも説明しているように,ウェブブラウザーのアドオンやGNOME Tweak Toolなどとして実装されている拡張機能の管理ツールを使って有効化する必要があります。

余計なものをインストールしたくないのであれば,標準でインストールされているgnome-shell-extension-prefsコマンドを使うと良いでしょう。

図2 gnome-shell-extension-prefs

画像

このコマンドはインストール済みの拡張機能をリストアップして個別に有効化・無効化を設定できます。注意しなくてはならないのは,システムグローバルな拡張機能自体は表示するものの,有効化・無効化の状態は正しく取得できないということです。有効化・無効化の状態はgsettings側の設定を読んでいるらしく,Ubuntu DockやAppIndicatorsのようなシステムグローバルに有効化されている拡張機能は「無効化されている」と誤判定してしまっています。

よって有効化・無効化する際は誤って他の拡張機能を操作しないように気をつけましょう。ちなみにgsettingsコマンドで有効になっている拡張機能のリストを確認したい場合は,次のように実行します。

$ gsettings get org.gnome.shell enabled-extensions
['sample@mty.shibata.gmail.com']

環境によっては有効化前もしくは有効化後にGNOME Shellを再読込する必要があるようです。⁠Alt+F2」でコマンド実行ダイアログを表示したあとに「r」を入力という方法もありますが,この方法はWaylandセッションでは動作しないので注意してください。もっとも確実な方法は一度ログアウトすることです。

サンプルの拡張機能が有効化されたら,トップパネルに歯車のアイコンが表示されます。それをクリックすると画面中央に「Hello, world!」とメッセージが表示されます。

図3 表示されるメッセージ

画像

著者プロフィール

柴田充也(しばたみつや)

Ubuntu Japanese Team Member株式会社 創夢所属。数年前にLaunchpad上でStellariumの翻訳をしたことがきっかけで,Ubuntuの翻訳にも関わるようになりました。

コメント

コメントの記入