Mozilla Firefoxのカーソル取得方法について

前回述べたように、Mozilla Firefox(Gecko)は一部のカーソルについて、特定の16進数の文字列を持つファイルから取得する。
例えばカーソルテーマにBluecurveを使っているとき、シンボリックリンク「/usr/share/icons/Bluecurve/cursors/08e8e1c95fe2fc01f976f1e063a24ccd」を削除してFirefoxを起動すると、CSS:cursor - MDCのprogressにポインタを乗せた時のカーソルが、モノクロの時計+矢印に変わってしまう。
この謎の文字列をmozillaソースコード内で検索しても何もヒットせず、どのような方法で決まっているのか、ソースコードを睨んで長らく悩んでいたのだが、ヒントは「/usr/share/icons/Bluecurve/Bluecurve.cursortheme」にあった。以下一部抜粋。

  Aliases can also be used to provide cursors to be used in place
  of particular legacy cursor shapes; whenever libXcursor is
  asked to create a bitmap cursor, it creates a hash value
  from the cursor shape, and tries using that as a cursor
  name. Setting the environment variable XCURSOR_DISCOVER will
  log this process, which is useful for finding out the hash values.

つまり、昔のカーソルのハッシュ値を名前代わりに使っているらしい。Mozillaがハッシュを用いている経緯はこのブログにある。
Firefoxは「mozilla/widget/src/gtk2/nsWindow.cpp」のget_gtk_cursor関数でカーソルを取得しているが、aCursorがGDK_*の物は前回紹介したGDK Cursorである。対してMOZ_*の物は、対応するハッシュを名前に持つカーソルファイルを読みこんで使用する。*1そして、ハッシュは上記抜粋の通り、環境変数XCURSOR_DISCOVERを設定してFirefoxを端末から起動する事で調べることが出来る。


$ []XCURSOR_DISCOVER=1 /usr/bin/firefox[]
[]Cursor image name: 08e8e1c95fe2fc01f976f1e063a24ccd[]


*
**
***
****
*****
******
*******
******** ***
***** ***
** ** * * *
* ** *** **
** * *
** ***
** ***


[]Cursor image name: e2c7e07f308fa0e041bbc4fefbfdf7f7[]

**
***
****
*****
******
*******
********
********* ***
**************
**************
******* *******
*** ************
* ***********
*********
*********
** ***


[]Cursor hash 08e8e1c95fe2fc01f976f1e063a24ccd returns 0x16000af[]
[]以下、新たなカーソルが表示される度に上のような出力がなされる。[]

以下にこの結果得られたハッシュを示す。
CSSプロパティソース内の名前ハッシュ
copyMOZ_CURSOR_COPY08ffe1cb5fe6fc01f906f1c063814ccf
aliasMOZ_CURSOR_ALIAS0876e1c15ff2fc01f906f1c363074c0f
context-menuMOZ_CURSOR_CONTEXT_MENU08ffe1e65f80fcfdf9fff11263e74c48
grabMOZ_CURSOR_HAND_GRAB5aca4d189052212118709018842178c0
grabbingMOZ_CURSOR_HAND_GRABBING208530c400c041818281048008011002
spinningMOZ_CURSOR_SPINNING08e8e1c95fe2fc01f976f1e063a24ccd
zoom-inMOZ_CURSOR_ZOOM_INf41c0e382c94c0958e07017e42b00462
zoom-outMOZ_CURSOR_ZOOM_OUTf41c0e382c97c0938e07017e42800402
not-allowed, no-dropMOZ_CURSOR_NOT_ALLOWED03b6e0fcb3499374a867d041f52298f0
col-resizeMOZ_CURSOR_COL_RESIZE043a9f68147c53184671403ffa811cc5
row-resizeMOZ_CURSOR_ROW_RESIZEc07385c7190e701020ff7ffffd08103c
vertical-textMOZ_CURSOR_VERTICAL_TEXT048008013003cff3c00c801001200000
nesw-resizeMOZ_CURSOR_NESW_RESIZE50585d75b494802d0151028115016902
nwse-resizeMOZ_CURSOR_NWSE_RESIZE38c5dff7c7b8962045400281044508d2

ComixCursors-sources-0.5.1に含まれるlink-cursor.bashを使う場合には、以下の行をつけ足すと良い。

# Gecko cursor hashes for CSS3 cursor property

ln -sf no-drop          03b6e0fcb3499374a867d041f52298f0 # no-drop/not-allowed
ln -sf vertical-text    048008013003cff3c00c801001200000 # vertical-text
ln -sf col-resize       043a9f68147c53184671403ffa811cc5 # col-resize
ln -sf row-resize       c07385c7190e701020ff7ffffd08103c # row-resize
ln -sf nesw-resize      50585d75b494802d0151028115016902 # nesw-resize
ln -sf nwse-resize      38c5dff7c7b8962045400281044508d2 # nwse-resize


追記2008/07/15
Midori(Webkit+GTK)ではXCURSOR_DISCOVERは効かなかったが、Epiphany(Gecko+GTK)ではFirefoxと同じハッシュを出力する。従って、GTKアプリ全体もしくはFirefox固有の動作ではなく、Geckoの動作らしい。このため記事の一部を改訂した。

*1:GDK_*、MOZ_*ともに適当なカーソルが見つからない場合はmozilla/widget/src/gtk2/nsGtkCursors.hで定義されたモノクロのカーソルを使う。