Skip to content

Latest commit

 

History

History
130 lines (107 loc) · 7.25 KB

focus.md

File metadata and controls

130 lines (107 loc) · 7.25 KB

The Focus Layer

History

This document discusses some internals of the focus system in Qooxdoo since 1.2. This is a technology documentation targeted to interested developers. There is no need to understand these details as a user of the framework.

In previous versions of the focus handling, we forced the application to our own implementation instead of working together with the browser. This was quite straightforward because the topic itself is quite complex and the differences between the browsers are huge. Ignoring all these differences and implementing an own layer was highly attractive. This came with quite some costs, however. For example, it's quite hard to catch all the edge cases when an input field loses the focus; nor is it possible to recover the focus correctly when the browser does something after switching the window (send back/bring to front etc.). To listen on the browser might improve some types of out-of-sync problems in the previous versions. We caught most things correctly, but it was difficult to get 100% accuracy.

Focus Support

With 1.2 the focus system was reimplemented using the new low level event stack. Compared to the old focus system this basically means that the whole focus support is implemented low-level without any dependencies on the widget system. It directly uses the new event infrastructure and integrates well with the other event handlers.

The new system tries to connect with all available native events which could help with detecting where the browser's focus is moving to. The implementation makes use of native events like activate and focusin where available. It uses a lot of browser behavior which is not explicitly documented or valid when reading the specifications, just to solve the issue of detecting where the focus currently is or is moved to.

It supports the events focusin, focus, focusout and blur on DOM nodes. It also supports focus and blur events on the window. There is support for activate and deactivate events on DOM nodes to track keyboard activation. It has the properties focus and active to ask for the currently focused or activated DOM node.

Activation Support

The activation, as part of the focus system, is also done by this manager. The keyboard handler, for example, asks the focus system which DOM element is the active one, to start the bubble sequences for all keyboard events on this element. As the keyboard layer sits on top of the DOM and implements the event phases on its own, there is no need to inform the browser about the active DOM node as it is simply not relevant when using this layer. It is also quite important, as in every browser tested, the methods to activate a DOM node (if available at all) might also influence the focus, which creates some problems.

Window Focus/Blur

The handler also manages the focus state of the top-level window. It fires the blur and focus events on the window object, which one can listen to. Natively, these events are fired all over just by tapping somewhere in the document. The issue is to detect the real focus/blur events. This is implemented through an internal state representation.

Text Selection

Focus handling in Qooxdoo also solves a lot of related issues. For example, the support for unselectable text is done with the focus handler as well. Normally all text content on a page is selectable (with some exceptions like native form buttons etc.). In a typical GUI or during drag&drop sessions it is necessary to stop the user from being able to select any text.

The only thing needed for the focus handler, here, is to add an attribute qxSelectable with the value off, to the node which should not be selectable..

Behind the scenes Qooxdoo dynamically applies styles like user-select or attributes like unselectable. There are a lot of bugs in the browser when keeping these attributes or styles statically applied to the nodes so they are applied as needed dynamically which works surprisingly well. In Internet Explorer the handler stops the event selectstart for the affected elements.

Prevent Defaults

One thing we needed, especially for the widget system which is built on top, was support for preventing a widget -- or in this case, a DOM node -- from being able to get the focus. This sounds simpler than it is. The major issue is to also keep the focus where it is while tapping somewhere else. This is especially interesting when working with a text selection. Unfortunately in a browser the selection can only be where the focus is. This is a major issue when trying to apply any change to the currently selected text, as is needed for most kinds of editors such as a rich text editor used by a mail application. The type of fix we apply in Qooxdoo is to not allow the browser to focus a specific DOM node e.g. the "Bold" button of the text editor. This makes it easy to add listeners to the button which work with the still existing selection of the editor field. The feature could be applied easily to a DOM node like such a button, using the attribute qxKeepFocus with the value on. It affects all children of the element as well, as long as these do not override it.

A similar goal is to keep the activation where it is when the user taps at a specific section of the document. This is mainly used to keep the keyboard processing where it is, e.g. when tapping the opened list of a SelectBox widget. This feature could be used for similar scenarios as well. It, similarly to qxKeepFocus, can be enabled simply by setting the attribute qxKeepActive to on for the relevant DOM node. Internally, stopping the activation also means stopping the focus. It was not solvable in another way because the browser otherwise sends activation events to the focused DOM node which is counter-productive in this case.

Another unwanted side effect of some browsers is the possibility to drag around specific types of content. There is some type of native drag&drop support in most of today's browsers, but this is quite useless with the current quality of implementation. Still, the major issue remains: It is possible to drag around images, for example, which is often not wanted in a GUI toolkit. These native "features" compromise the behavior implemented by the application developer on top of them. To stop this, Qooxdoo applies styles like user-drag on browsers that support it, or prevents the native draggesture event where available.

Other then this, most needed preventions are implemented internally through a preventDefault call on the global pointerdown event, when a specific target is detected. This has some side effects though. When preventing such a core event, it means that most browsers also stop any type of selection happening through the pointer. This also stops them from focusing the DOM node natively. The Qooxdoo code uses some explicit focus calls on the DOM nodes to fix this.

Please note that some settings may have side effects on other things. For example, to make a text region selectable but not activateable is not possible with the current implementation. This tends not to be a hinderance in real-world applications, but may be still interesting to know about.

Finally

Finally, the whole implementation differs nearly completely for the supported browsers. Hopefully you get an idea of the complexity of the topic.