Hatena::Groupkeysnail

きすねた(ん)

2011-04-03

ポップアップにおける画像の大きさを固定,および nsIAlertsService の問題に関して

| 12:29 | ポップアップにおける画像の大きさを固定,および nsIAlertsService の問題に関して - きすねた(ん) を含むブックマーク はてなブックマーク - ポップアップにおける画像の大きさを固定,および nsIAlertsService の問題に関して - きすねた(ん)

大きさ固定

Twitter クライアントプラグインポップアップにおけるアイコンの大きさを固定する方法が FAQ なので.改めて取り上げる.

PRESERVE エリアへ以下の記述を.

style.register(<><![CDATA[
    @-moz-document url("chrome://global/content/alerts/alert.xul") {
        image#alertImage {
            max-width  : 48px !important;
            max-height : 48px !important;
        }
    }
]]></>);

nsIAlertsService

Twitter クライアントプラグインポップアップ表示には nsIAlertsService を使っている.

この nsIAlertsService だが,バックエンドとして Mac OS X では Growl を使い(インストールされていれば),Linux などにおける X 環境では notify-osd や notification-daemon を使う.こうしたバックエンドはきっちりしているものなので,問題はあまりない.(notify-osd の悲惨さについてはまたの機会に語るとしよう)

一方 Windows では(何も入れていなければ) XUL による Firefox 独自のポップアップが使われるのだが,この XUL によるポップアップがクセモノで,確認している限りでも次のような欠点が存在する.

  • 文字の折り返しが効かない
  • 画像の大きさが制限されていない
    • 1024x1024 px など巨大な画像が指定されていた日には大変悲惨なこととなる

折り返しが効かない

一つめの折り返しが効かない,という問題に対処することはなかなか難しい.説明のため,まずポップアップに使われている XUL ファイルの内容を抜粋して以下に示す.この内容は Firefoxview-source:chrome://global/content/alerts/alert.xul という URI を指定すれば閲覧することができる.

<window id="alertNotification"
        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        windowtype="alert:alert"
        xmlns:xhtml="http://www.w3.org/1999/xhtml"
        xhtml:role="alert"
        pack="start"
        onload="onAlertLoad()"
        onclick="onAlertClick();">
  
  <script type="application/javascript" src="chrome://global/content/alerts/alert.js"/>

  <box id="alertBox" class="alertBox">
    
    <hbox class="alertImageBox" align="center" pack="center">
      <image id="alertImage"/>
    </hbox>

    <vbox id="alertTextBox" class="alertTextBox">
      <label id="alertTitleLabel" class="alertTitle plain"/>
      <label id="alertTextLabel" class="alertText plain"/>
    </vbox>

  </box>

  <!-- This method is called inline because we want to make sure we establish the width
       and height of the alert before we fire the onload handler. -->
  <script type="application/javascript">prefillAlertInfo();</script>

</window>

ここで注目すべきは次の部分だ.

  <box id="alertBox" class="alertBox">
    
    <hbox class="alertImageBox" align="center" pack="center">
      <image id="alertImage"/>
    </hbox>

    <vbox id="alertTextBox" class="alertTextBox">
      <label id="alertTitleLabel" class="alertTitle plain"/>
      <label id="alertTextLabel" class="alertText plain"/>
    </vbox>

  </box>

これを見ると,ポップアップのタイトルとメッセージには label 要素が使われている,ということが分かる.

この label 要素がクセモノで,value 属性にテキストが指定された場合は折り返しが一切なされず,内部テキストノードへテキストを与えた場合には折り返しがなされる,という性質を持つ.実例で示すと,以下のようになる.(参考:Piro/Linuxコマンド操作漫画連載中さんのツイート: "@stillpedant labelとdescriptionは、value属性で文字列を指定した場合は「1行で表示・crop属性に従って末尾を省略」、flex="1"で子要素にテキストノードを置いた場合は「指定幅で折り返して複数行表示」で

<label value="折り返しがなされない" />

<label>折り返しがなされる</label>

さて,先程の XUL における nsIAlertsService が何をやっているかというと,これは view-source:chrome://global/content/alerts/alert.js を見ると分かるが,次のようにして label の value 属性に値を設定している.つまり,これではどう頑張っても折り返しは出来ない.

document.getElementById('alertTextLabel').setAttribute('value', window.arguments[2]);
// 中略
document.getElementById('alertTitleLabel').setAttribute('value', window.arguments[1]);

この問題に無理やり対処する方法としては,ポップアップが表示される瞬間に上記要素の value 属性に設定されたテキストを取得し,その value 属性を削除した後に label の子テキストノードとしてそのテキストを append する,というものが考えられる.実現には userChrome.js のような仕組みを用いる必要があり,とても面倒だ.

画像の大きさが制限されていない

画像の大きさが制限されていないという問題に対しては,幸いながら比較的簡単な対処法が存在する.nsIStyleSheetService の仕組みを使い,CSS で強制的に画像のサイズを制限してしまえば良い.KeySnail の style モジュールを使う方法に関しては,冒頭に示したとおりだ.

まとめ

nsIAlertsService の XUL を用いたポップアップは非常に出来が悪い.これを改善する方法が,これまでにもいくつか提案されているようだ.

Windows でも Growl for Windows のようなソフトウェアを導入した方が幸せになれるのではないかと,個人的には感じる.