一般的に、ウィンドウマネージャーはグラフィックユーザーインターフェイスのウィンドウの配置や表示を制御するアプリケーションの一部です。この記事では Firefox OS がウィンドウ管理をどのようにハンドリングしているか記載しています。
Firefox OS では、ウィンドウ管理は System アプリの一部で、以下の責務があります。
- アプリのライフサイクルとアプリ間のインタラクション
- UI 要素のレイアウト、リサイズ、回転、表示とアニメーション、変換
- web activity や Notification、タスクマネージャーのようなシステム全体の UI ロジック
- ポップアップ、コンテキストメニュー、エラーページのようなアプリ仕様 UI 機能
各アイテムの説明にいく前に、Gaia でアプリがどのように起動するかを説明します。
Gaia でのアプリ起動説明
Firefox OS ではアプリの起動方法はいくつかあります。例えばほかのアプリから作られたシステムメッセージ経由で起動したり、ホームスクリーン上のアイコンをタップすることによる起動などあります。
アプリを開く制御のイベントは Gecko エンジンや System アプリによってハンドリングされます。これについては下で説明します。
アプリ構造
Gaia の webapps はHTML、CSS、JavaScript、image、マニフェストなどのアプリケーションアセットのすべてが含まれる zip ファイルである パッケージ型アプリがあります。Gaia の webapp は以下の基本構造で構成されています。
apps
/
[
app
name
]
/
-
js
-
styles
-
locales
-
test
-
index
.
html
-
manifest
.
webapp
ビルトインの Gaia アプリがホームスクリーンから起動した際、Gecko は manifest://[app name].gaiamobile.org:8080 という URL を開こうとし、manifest.webapp の場所に変換して マニフェストの launch_path で定義されている index ファイルを実行します。(すべてのビルトインアプリは launch_path は index.htmlです。) index.html ファイルでは必要となるスタイルシートや JavaScript をロードします。
注意:インフォーマルな慣習として、Gaia アプリの メイン JavaScript のエントリーポイントは通常 [app name].js
もしくは main.js
です。
アプリ起動シーケンス
イベントは Gecko へ通知されます。Gecko の準備ができていれば、system/js/app_window_factory.js から AppwindowFactory
に アプリの起動イベントである webapps
イベントか、システムメッセージの保留をハンドリングするための open-app
イベントが送られます。
window.addEventListener('applicationready', function appReady(e) { window.removeEventListener('applicationready', appReady); window.addEventListener('webapps-launch', self); window.addEventListener('webapps-close', self); window.addEventListener('open-app', self); });
イベントハンドリング部分の詳しい説明として、this.launch(config)
はアプリウィンドウもしくはアクティビティとして起動します。アプリを閉じると、Appwindow
は 閉じるイベントである webapps-close
イベントを受信します。
launch()
メソッドのメイン処理は以下の通りです。
var app = AppWindowManager.getApp(config.origin); if (app) { app.reviveBrowser(); } else if (config.origin !== homescreenLauncher.origin) { new AppWindow(config); } else if (config.origin == homescreenLauncher.origin) { homescreenLauncher.getHomescreen().ensure(); }
コードでは最初に、アプリ変数の存在をチェックし、Gecko で再度起動させます。アプリ変数が無いとき、通常アプリであれば アプリのための AppWindow
インスタンスを生成します。それ意外は homesecreenLauncher
から起動した場合です。最後のケースの場合、必要となる操作を実行します。
AppWindow
Firefox OS はウェブページがアプリとして動作するように特殊な mozBrowser API を利用します。ウィンドウ管理のルートは内部の iFrame(ウィンドウ) をラップするための mozBrowserAPI です。moz-browser タイプの特殊な iFrame は実際のブラウザとして動作する iFrame を作成します。
AppWindow
は mozBrowser
iFrame の生成、包含、管理をします。AppWindow
は自信の mozBrowser
iFrame
が発火したすべての mozBrowser
イベントを操作し、適切な UI 機能を表示します。
アプリライフサイクル管理
アプリの完全なライフサイクルは以下の通りです。
- アプリの起動
- システム DOM ツリーへの iframe 注入
- アプリ表示アニメーション
- アプリ表示
- アプリ非表示アニメーション
- アプリ非表示
- DOM ツリーからの iframe 削除
- アプリ終了
アプリの起動
ユーザーがホームスクリーン上のアイコンをタップしたとき、ホームスクリーンは Gecko エンジンに適切なアプリがオープンされたことを mozApps API を使って通知します。
アプリの kill
アプリは以下の条件下で終了されます。
- アプリクラッシュ
- OOM Killer による終了
- タスクマネージャー経由によるアプリ終了
- window.close() のコール
アクティビティアプリは、非表示アニメーションを表示する前に、DOM ツリーから終了されたアプリの iFrame を削除します。前面でないアプリのとき、アプリ終了する際即時に iframe を除去します。
アプリは以下の条件下で中断します。
- web activity の場合、呼び出されたアクティビティが表示されたとき
- Popups の場合、アプリが window.open を呼び出した時開きます
- アプリの場合、何もしません
アプリの再起動
アプリは以下の条件で再起動します。
- homescreen アプリ: ホームボタンが押された時
- ゾンビアプリはタスクマネージャから同じ URL が開かれるか、エッジジェスチャーからスワイプした場合に復活します
アプリのレンダリング
アプリ起動時、以下のブロックによりスクリーンは描画されます。
- System header
- App iframe
- Bottom wrapper bar (ブラウザが chrome モードの場合)
アプリレイアウト
アプリの iFrame のメインコンテナは以下のようになっています。
<iframe id="browser2" mozallowfullscreen="true" mozbrowser="true" remote="true"... ... src="", data-url="" data-frame-type="window" data-frame-origin="..."> </iframe>
iframe には以下の要素を含みます。
- Launch path (
data-url
,data-frame-origin
) - mozbrowser iframe 属性 (
mozallowfullscreen="true"
,mozbrowser="true"
) - コンテナ、オーバーレイ、アプリ仕様の UI
AppWindow のリサイズ
AppWindow は以下の条件の場合にリサイズします。
- system アプリは回転の変更があるまでリサイズしない
- 一般的なアプリは以下の条件でリサイズします
- system アプリのによるリサイズ
- キーボードの開閉アニメーション
- ステータスバーの変更
window.resizedBy()
またはwindow.resizeTo()
のコール- ソフトウェアのホームボタン押下
要約すると、ウィンドウサイズは以下のものに影響を受けます。
- 回転状態
- キーボード状態
- 警告画面の状態 (has call, has message, etc.)
- Chrome ナビゲーション状態
- フルスクリーン状態(
manifest.fullscreen
/parentWindow)
- ソフトウェアホームボタン状態
アプリウィンドウの回転
アプリ画面の回転は各アプリから制御可能です。もしくはシステムから全体的に回転の制御はできます。orientation プロパティを manifest.webapp に記載することで、アプリ画面の回転を指定出来ます。以下はその一例です。
"orientation": "default",
orientation API を利用して回転のロック / アンロックを制御することも出来ます。
screen.mozLockOrientation([‘portrait-primary’]); screen.mozUnlockOrientation();
強制的に回転させるパラメータ値はいくつか存在します。
default
: システムのデフォルト回転portrait
: ポートレートとして画面を描画landscape
: ランドスケープとして画面を描
入手可能な詳細な情報については、Screen.lockOrientation を参照してくたさい。また、サンプルは gaia/dev_apps/uitest/js/API/orientation.js から入手出来ます。
アプリの可視性
System アプリはスクリーンがオフになった時だけバックグラウンドになりますが、一般のアプリは以下のいくつかの条件の時にバックグラウンドになります。
- オーディオの競合
- プロセスポリシー
- レンダリング
注意: ページの可視性は親 iframe が非アクティブの期間は継承されます。
アプリは以下の時は常にフォアグランドになります。
- オープンアニメーション開始時
- アニメーション終了時のスワイプイン
- ロックスクリーンがアンロック時
以下の時は、常にバックグラウンドです。
- 終了アニメーションの非表示時
- 電話呼び出し表示して 3 秒後
- スクリーンオフ時
上記以外の例外もいくつかあります。
- 通常のチャンネルで音楽を再生するアプリ
- web activities をインラインで呼ぶアプリ
window.open('', '', 'dialog')を開いているアプリ
アプリウィンドウのアニメーションとトランジション
Gaia のウィンドウマネージャーも、アプリウィンドウのアニメーションと滑らかなユーザーエクスペリエンスを実現するためのトランジションを提供してます。
アプリウィンドウのアニメーションとトランジションは、以下の状態で管理されています。
表示中アプリ
— 現在のアプリ起動中アプリ
/ 起動中アプリ群 — 起動中アプリのまとまりオープンフレーム
/ クローズフレーム — 表示 / 非表示アニメーションのためのトランジションフレーム
setDisplayedApp()
メソッド呼び出し中は、アプリは以下の図にあるとおりの状態を遷移して起動します。
Firefox OS アニメーション管理のための以下のようなトリックが組み込まれています。
- アプリを開く前に、バックグラウンド状態からの復帰を保証する必要があります。そのため、通常 1 x 1 のスクリーンショットを最描画時に撮っています。
- アプリが開ける状態になれば、次のアプリのアニメーションと現在のアプリのアニメーションの描画を同時に行います。
- アプリの開始、終了の間は画面回転のロック / アンロックのコードを実行します。
- アプリが1度リサイズされている時だけ、開始時のリサイズを行います。それ以外はリサイズ処理をスキップします。
- ページの可視性を 1x 1のスクリーンショットを撮ることにより変更します。(上述参照)
アプリウィンドウの UI 仕様
ブラウザーの chrome やモーダルダイアログ、コンテキストメニュー、ポップアップやエラーページのように、特定のアプリに関連するいくつかの UI 要素が存在します。
この事について以下の議論をしてみましょう。
モーダルダイアログ
Oデスクトップ版 Firefox では、web 開発ツールのコンソールを開き alert()や confirm() 、prompt() コマンドを入力すると、コンテンツ上にの中央に表示されるダイアログを得ることができます。これは、Firefox OS でモーダルダイアログと同等のものになります。
コンテキストメニューダイアログ
コンテキストメニュー(もきくは長押メニュー)はモバイル開発のコンセプトの1つです。一般のアプリとして作られている場合、頻繁に利用されるアクションはユーザーにとってアプリを利用しやすいように表示されるべきです。コンテキストメニューは、すぐには表示されないが、すぐに利用可能にするべきアクションのための配置場所を提供します、
(https)認証ダイアログ
system/js/app_authentication_dialog.js に定義しています
日付、時刻等の選択ダイアログ
system/js/value_selector/ に定義しています
権限ダイアログ
system/js/permission_manager.js と system/js/media_recording.js (トレイパネルのユーティリティ)に定義しています
特殊なアプリ
特殊なアプリに含まれる特殊な機能を実行するために、特別なアプリウィンドウオブジェクトを必要とするアプリが存在します。
- ホームスクリーン
- FTU
- キーボード
- 通信量管理
- Secure camera (ロックスクリーン内)
- ロックスクリーン
子ウィンドウ管理
子アプリウィンドウは直接的または、間接的にほかのアプリやページから開かれます。例えば、以下のようなものです。
- 警告ウィンドウ
- ポップアップウィンドウ
- アクティビティウィンドウ
- 信頼された UI / 信頼されたウィンドウ
子ウィンドウが通常終了した場合、親ウィンドウは再度開かれます。ある種の子ウィンドウは、他の子ウィンドウを伴うこともあります。親子のプロセス管理が重要になってきます。
警告ウィンドウ
警告ウィンドウは以下の警告で利用されます。
- 電話呼び出し - 電話アプリ
- アラーム画面 - 時計アプリ
- パーミッション確認
現在これらの警告ウィンドウは、デフォルト回転(ポートレート優先)に強制されます。
信頼された UI
Persona や mozPay API は信頼された UI を利用します。これらは全体の 80% に定められています。信頼された UI が動作している間はホームスクリーンの一部が表示されるようになっています。
履歴管理
このセクションでは、FIrefox OS での履歴管理のハンドリングをする、いくつかのコンポーネントを説明します。
タスクマネージャー
タスクマネージャー(カードビュー)はホームボタンの長押しでトリガーされます。端末のアプリ履歴を表示し、アプリを終了することが可能です。
Firefox 2.0 から、表示されて存在しているふりをするゾンビアプリも取得可能な機能になっています。
Web activity 配置
インラインのアクティビティはアクティビティのデータを提供するための新しい参照ページを作成します。
ウィンドウアクティビティは、存在しているウィンドウが消費したアクティビティデータを再利用します。
エッジジェスチャー(実験的)
実験的エッジジェスチャー機能は Firefox OS 2.0 以上の開発者モードで利用可能です。そして、アプリや web ページ間の移動を画面端の右/左からスワイプすることで可能にします。
次に表示されるアプリはどのように選ばれるの?
- アクティブアプリの子ウィンドウ
- 新しく起動したもの
- アプリスタックの次に積まれているウィンドウ
前に表示されるアプリはどのように選ばれるの?
- アクティブアプリの親ウィンドウ
- 前に起動されたものF
- アプリスタックで現在のウィンドウより前に積まれたウィンドウ
スクリーンショット管理
スクリーンショットツールはタスクマネージャーがアプリの履歴を表示するために利用します。アプリの終了アニメーション中にアプリのスクリーンショットは撮られます。