In general, a window manager is the part of an application that controls the placement and appearance of windows in a graphical user interface. This article looks at how Firefox OS handles Window Management.
In Firefox OS, Window Management is part of the System app, and is responsible for:
- App life cycle and interaction between apps
- Layout, resizing, orientation, visibility and animation/transitions of UI elements.
- System-wide UI logic such as web activities, app notifications, and the task manager.
- App-specific UI features such as popups, context menus, and error pages.
Before we dive into details of such items, let’s see how apps are launched in Gaia.
How apps are launched in Gaia
An app can be launched in Firefox OS in a number of ways, for example via a system message created by another app, or by tapping the icon on the Homescreen.
The events that control the apps opening are handled by the Gecko engine and the System App, and explained in more detail below.
App structure
All Gaia webapps are packaged apps, which are essentially zip files containing all application assets: HTML, CSS, JavaScript, images, manifest, etc. Each webapp in Gaia is organized with following basic structure:
apps
/
[
app
name
]
/
-
js
-
styles
-
locales
-
test
-
index
.
html
-
manifest
.
webapp
When one of the built-in Gaia apps is launched from the homescreen, Gecko will try to open a URL of manifest://[app name].gaiamobile.org:8080
, parse the manifest.webapp
at that location, then run the index file defined in the manifest launch_path
— which is index.html
for all built-in webapps. The index.html
file will pull in all required styles and JavaScript.
Note: As an informal convention, the major JavaScript entry point for Gaia apps is usually [app name].js
or main.js
.
App launch sequence
The events are sent to Gecko. Once Gecko is ready, AppwindowFactory
from system/js/app_window_factory.js will receive a webapps-launch
event for an app, or an open-app
event for handling a pending system message.
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); });
For detail in handleEvent section, this.launch(config)
will launch an app window or an activity. Once the app is closed, Appwindow
will receive a webapps-close
event.
The main process in the launch()
method is:
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(); }
First the code checks if the app variable exists and tries to revive it in Gecko. On the other hand, if it’s a normal app, we create an AppWindow
instance for the app. The other special case is the homescreenLauncher
— in this case we do the required operations.
AppWindow
Firefox OS uses a special mozBrowser API to make a web page act like an app. The root of Window Management is just a mozBrowser
API wrapper to handle inner iFrames (the Window). A special iFrame of type moz-browser
is created to make the iFrame act like a real browser window.
AppWindow
creates, contains, and manages a mozBrowser
iFrame. AppWindow
will manipulate all mozBrowser
events fired from the mozBrowser
iFrame itself and show the relevant UI features.
App life cycle Management
The full life cycle of an app is as follows:
- App launch
- Append iframe to System DOM tree
- Start App opening animation
- App opened
- App close animation
- App closed
- Remove iframe from DOM tree
- App terminated
Launching apps
When a user tap icons on the homescreen, the homescreen uses the mozApps API to notify the Gecko engine to open the corresponding app. When Gecko is ready, it will send the appropriate event to system app.
Killing apps
Apps will be killed under the following circumstances:
- An app crashes
- The OOM killer kills it
- The app is closed via the Task Manager
window.close()
is invoked
For active apps, after performing the closing animation, the iFrame of the killed app is removed from the DOM tree. For inactive apps, the iframe removed immediately after they are killed.
Apps will be interrupted in the following circumstances:
- For web activities: when the activity caller is opened
- Popups: when the window.open caller is opened
- App: nothing to do
Relaunching apps
Apps will be relaunched in the following circumstances:
- homescreen app: When the home button is pressed
- Zombie apps are revived with the same URL if opened from the Task Manager or swiped in from an edge gesture. (Experimental feature)
How an app is rendered
When we launch an app, the screen will be rendered with following blocks:
- System header
- App iframe
- Bottom wrapper bar (if in browser chrome mode)
App Layout
The main container of the app's iframe is as follows:
<iframe id="browser2" mozallowfullscreen="true" mozbrowser="true" remote="true"... ... src="", data-url="" data-frame-type="window" data-frame-origin="..."> </iframe>
The iframe contains:
- Launch path (
data-url
,data-frame-origin
) - mozbrowser iframe attributes (
mozallowfullscreen="true"
,mozbrowser="true"
) - Container, overlay, app specific UI
Resizing the AppWindow
The AppWindow will be resized in a number of situations:
- The system app will not be resized until the orientation changes.
- For general apps, resizing occurs when:
- The system app resizes
- The keyboard opening/closing animation ends
- The statusbar changes
window.resizedBy()
orwindow.resizeTo()
is called- The software home button is toggled
In summary, the window size is affected by:
- Orientation state
- Keyboard state
- AttentionScreen state (has call, has message, etc.)
- Chrome navigation state
- Fullscreen state
manifest.fullscreen
/parentWindow
- Software homebutton state
AppWindow Orientation
Orientation of apps can be controlled from each individual app, or globally by the system. You can set orientation in the app’s manifest.webapp
file with the orientation
property, for example:
"orientation": "default",
You are also able to use the orientation API to lock or unlock orientation:
screen.mozLockOrientation([‘portrait-primary’]); screen.mozUnlockOrientation();
There are several parameter values that can be used to force the orientation:
default
: system default orientationportrait
: force the screen to be rendered in portraitlandscape
: force screen to be rendered in landscape
More details are available in the Screen.lockOrientation reference, and you can see an example at gaia/dev_apps/uitest/js/API/orientation.js.
App visibility
The System app goes into the background only when the screen is off, whereas normal apps go into the background dependant on a few factors:
- Audio competing
- Process policy
- Rendering
Note: Page visibility is inherited while the parent iframe is inactive.
Apps are always in the foreground when the:
- Open animation starts
- Swipe-in animation ends
- Lockscreen is unlocked
App are always in the background:
- When the closing animation ends
- 3 secs after the callscreen is visible
- When the screen is off
There are a few exceptions to the above rules:
- Active app with audio playing in the normal channel
- Apps calling inline web activities
- Apps opening
window.open('', '', 'dialog')
AppWindow animation and transition
The Gaia Window Manager also provides app window animation and transitions to make for a slicker user experience.
The AppWindow animation and transitions are managed by the following stats:
displayedApp
— the current ApprunningApps
/numRunningApps
— the set of running appsopenFrame
/closeFrame
— the transition frame for opening/closing animations
While calling the setDisplayedApp()
method, the app will be launched via the stats illustrated by the following diagram.
There are several tricks involved in controlling the Firefox OS app animation flow:
- Before an app is opened, we need to ensure it’s recovered from its background state. We usually take a 1 x 1 screenshot to enforce redraw.
- After the app is ready to be opened, we perform the opening animation of the next app and the closing animation of the current app at the same time.
- We run code to lock/unlock screen orientations both during app opening and closing.
- We perform an app resize at opening only if the app is resized once. Otherwise, we skip resizing step.
- We change the page visibility by again taking a 1 x 1 screenshot (see above).
AppWindow specific UI
There are several UI elements that are only relevant to certain apps, such as Browser chrome, modal dialogs, context menus, popups, and error pages.
Let's discuss some of these.
Modal dialogs
On desktop Firefox, if you open the browser developer console and enter commands such as alert()
, confirm()
, and prompt()
, you’ll get a centered dialog on screen that blocks the underlying content. The equivalent in Firefox OS is modal dialogs.
Context menu dialog
Context menus (or long press menus) are familiar concepts to mobile developers. In general app design, the most frequently used actions should be visible to users so they can control the app easily. Context menus provide a place to contain actions that can't fit on the immediate UI but still ought to be easily available.
Authentication (https) dialog
Defined in system/js/app_authentication_dialog.js.
value select, time, date dialogs
Defined in system/js/value_selector/.
Permissions dialog
Defined in system/js/permission_manager.js and system/js/media_recording.js (for utility tray panel).
Special apps
Some apps need a special appWindow
object to deal with special functionality they contain. Examples include:
- Homescreen
- FTU
- Keyboard
- Cost control
- Secure camera
- Lockscreen
Child window management
Child app windows are opened directly or indirectly by other apps/pages. Examples are:
- Attention window
- Popup window
- Activity window
- Trusted UI / Trusted window
When a child window terminates normally, its parent window should be re-opened. Some sort of child window may also have another child window. Process priority management between parent and child is an issue.
Attention Window
Attention Windows are used to get your attention:
- Call screen — dialer
- Alarm screen — clock
- Permission confirmations
Currently those attention window are forced for default (portrait primary) orientation.
Trusted UI
Persona and the mozPay API use trusted UI. They use Specific sizing: 80%. The Homescreen is partially visible during the time trusted UI is running.
History Management
In this section we will look at some fo the components that handle history management in Firefox OS.
Task Manager
The Task manager (card view) can be triggered by a long press of the home button. It shows app history on the device, and is able to kill an app actively.
From Firefox OS version 2.0, there’s an experimental feature available to keep zombie apps present and pretend they are still alive.
Web activity dispositions
Inline Activities create a new reference page to provide the data to the activity.
Window Activities will reuse the existing app window to consume the activity data.
Edge gestures (experimental)
The experimental Edge gesture feature is available in developer mode on Firefox OS 2.0+, and allows you to use finger swipe right/left from the edge of the device to navigate between apps and web pages.
How is the next app to display chosen?
- Child window of the active app
- Launch time is newer
- Find the head window of the next app stack
How is the previous app chosen?
- Parent window of the active app
- Launch time is older
- Find the rear window of the previous app stack
Screenshot management
The screenshot tool is used by the task manager (card view) to show what the apps in the history look. An app screenshot is taken when the app closing
animation has ended.