In the new land of focus, there is a single focus manager service which handles focus. It keeps track of the topmost top-level window (called the active window), and the child frame window where the focus currently is located. For instance, if something within a particular tab is focused, then the active window is the chrome browser window containing it and the child frame window is the DOM ‘window’ loaded within the tab. If the address field is focused however, the child frame window is the chrome window itself. In this latter case, both the active window and the child frame window have the same value.
The window itself (nsGlobalWindow.cpp in the Mozilla source) stores the currently focused element within the window. This is stored for every window, whether a toplevel chrome window, a child window or a frame. You can retrieve this element from script using a document’s activeElement property. If that element is within the current child frame that the focus manager points to, then that element will be the one where key events will be dispatched to, it will generally have a focus ring around it, and so forth. Only one such element in the entire application will be in such a state at a time. It’s important to note that the current focused element is still maintained whether the window is actually focused or not. That way, when a window or tab is brought back to the front, the same element that used to be focused still will be.
There are four ways in which an element can be focused:
- The user clicks the element with the mouse.
- The user presses the tab key.
- The user presses the access key associated with the element, if any.
- The element’s focus() method is called.
The latter method is the way you would focus an element with a script. Whatever means is used, all calls are routed through a single function within the focus manager. This ensures that focus behaviour remains consistent whatever method is used.
The old way of doing focus had a myriad of methods, all undocumented and confusing. Here is a guide to what the new way will be in the future:
- To retrieve the focused element, use the ‘activeElement’ property of the document. This will be set if the window is focused or not.
- To modify the focused element, call the focus() method. This will make this element focused in its window or tab, but will not bring the window or tab to the front.
- To switch to another window, call the window’s focus() method.
- To clear the focus from an element, call its blur() method, or just focus something else.
- From extensions and chrome code, in all other cases, call the focus manager. This service is available using the contract id ‘@mozilla.org/focus-manager;1’ and the nsIFocusManager interface.
All other methods are deprecated or have been removed and should not be used. Specifically, this means the command dispatcher, docshells or any of the other shells, the event state manager, the focus controller, and well as some internal content node methods.