FirefoxOS/Stingray/Focus-Manager

From MozillaWiki
Jump to: navigation, search

bug 1136589 focus fallback

What's the Problem

Smart system app in Stingray project is a fork of phone's system app and inherits all features and issues from it. In current phone's touch-based system model, it does not need to handle focus issue because the focus will be transferred to the element user just touched. However, in smart system which supports keyboard input, we have to build a system that can always find the correct element to focus even though the focus was wrong (focus may falls back to body if we accidentally focus null object).

Focus Issues

The focus issues we current found are:

  1. bug 1125036 We don't have a way to know why focus transfer fails in Gecko.
  2. We are trying to focus non-operable element.
  3. We do not switch focus while some system UIs show up.
  4. We use HTMLDOMElement.focus() in many places, including system UI and app window, which may cause race condition.

System UIs in smart system have a lot of focus issues because smart system app may forget to set focus in most of them like issue 3 listed above. In some of them, we also found issue 2 and issue 4.

Focus Manager: bug 1136590, bug 1139314

Focus Manager is a module handling focus requests and helps other modules to decide which UI should be focused. There are two parts in Focus Manager: doing focus stuffs and auto-fix focus when it finds focus issue.

There are three different types of UI in smart system:

  1. System UI: This is a system overlay managed by smart system app, like sleep menu, trusted UI, captive portal, etc.
  2. AppWindow UI: This is a core of smart system app which holds the app iframe.
  3. App Wide UI: This is a supporting UI for app iframe, like context menu, app's alert, confirm, prompt dialogs, HTTP login dialog, etc.

Focusable UI

Focus Manager maintains a list of registered UIs. All UIs, including system UI and AppWindow, can use addUI/remoteUI to add/remove themselves in the UI list. Once a module's UI is added to DOM, we should add this module to Focus Manager so that it can calculate the top most UI. And once a module's UI is removed from DOM, we should remove this module from Focus Manager but this is optional because we can use isFocusable() API to check if the UI is focusable.

A module who wants to get focus should implement three APIs:

  • isFocusable(): returns a boolean to tell it is focusable or not.
  • getElement(): returns a HTMLDOMElement for FocusManager's top-most UI calculation. We will return the container of this UI basically. It still works if you return any HTMLDOMElements inside of container.
  • focus(): calls HTMLDOMElement.focus() on the element you want to focus.

To Focus Top-Most System UI

The focus procedures are:

  1. setTimeout(): please refer to comment 4, 9, and 13 in bug 1113592 for the main reason.
  2. Calculate top-most UI.
  3. Call focus API of top-most module to focus correct element.

Calculate Top-Most UI

The procedure to calculate top-most UI are:

Focus Manager Flowchart

The LCA in this chart is least common ancestor. The Get LCA Nodes is to get ancestors which is directly under LCA. We have to use LCA to find the comparable nodes because all UIs in system may not under the same container.

Auto-fix Focus Issue

Focus Manager listens the following events and check if we have focus issue:

  • keydown
  • keyup
  • mozbrowserbeforekeydown
  • mozbrowserbeforekeyup

Once Focus Manager found the focus issue, it calls focus() method to re-focus the correct UI. In smart screen, we enable this feature by default. We may disable this feature once we fix all the focus issue.

Detect Focus Issue

The following cases are viewed as focus issue:

  1. document.activeElement is HTML or BODY
  2. document.activeElement's css display is none or css visibility is hidden
  3. One of ancestors of document.activeElement has css display: none or css visibility: hidden

Turn Off Auto-fix

Focus Manager turns on this feature by default. If you don't want this feature turned on, please add the following settings to build/config/tv/settings.json file

   'focusmanager.autofix.enabled': false

Overheads

Focus Manager needs to know the css display and css visibility of a specific element. So, it uses window.getComputedStyle(HTMLDOMElement) to force reflow.