November 17, 2016 - Marcel Hollerbach
An Introduction to Managing Enlightenment Widget Focus
In Enlightenment, a widget can have focus, meaning that once a key on a keyboard is pressed the events will be delivered to the focused widget, and the widget can then react to the event. For example, a text field will start to append the letter ‘a’ once the appropriate key is hit on the keyboard; once the key is released, it will stop appending the characters. In other words, the focused widget is the widget that gets attention from input events.
There can be several reasons for a widget to get focus, such as when a user clicks on it. But, there are also use cases where the user doesn’t have a touchscreen or mouse, such as on a TV, and needs to rely on a remote to control the focus on the screen. There are six directions that provide an optimal method for moving the focus around in an app. Four of them are based on position: up, down, right, and left.
The other two are based on the workflow of the particular app. For example, a login screen has two text fields: one for the user name and one for the password, and two buttons: one for canceling the login, and the other to submit the login information. It’s possible to use one of the positional methods I just mentioned, but it would be much easier to have a direction that guides the user from the user name field, to the password field, and finally to the submit button since this is the usual workflow a user would follow on this particular graphical interface.
So after we know what’s needed to provide a user with useful focus operations, we can start to think about how to realize it. My personal opinion is that there should be an object that registers all of the widgets that should be connected to each other. The first four directions can be calculated based on their position in the app, but the workflow directions are not that easy because there isn’t a general way to get these directions. This means the workflow directions should be left to the app with some fall-back logic that makes it so the app isn’t forced to setup the next widget in it’s workflow. For example, it would be possible to set a container in which the next direction always triggered the widget that sends the user to the next page.
To calculate the right, left, top and down candidates for a single widget, the distance from the currently calculated widget to all others in the set needs to be compared. It’s possible to find the smallest distance and store the associated widget, however, there is one problem with this. If the user interface is rather large with many widgets, it can get quite expensive to calculate the distance to all other widgets. So, the idea of positional focus isn’t easy and requires a bigger amount of work than what might be apparent initially. This problem with finding the shortest distance is not just a problem in EFL, it’s also a problem in theoretical computer science. It’s known as the shortest path problem, and is most commonly encountered when creating car navigation systems.
Overcoming Technical Roadblocks
As I wrote in my previous blog post, a major source of problems is non-revertable actions. Once a user moves the focus to the right, there is no assertion that moving the focus to the left will bring the user back to the widget where the focus previously was. There is some history to solve this, once a widget is the focus it will move to the top of a history stack, much like a web browser history. With this, it’s possible to take the set of shortest distances to the left side from a widget and find the one that has the most recent position in the history, allowing the user’s action to be reverted.
The second problem with the old solution was that a few widgets might be inaccessible in a huge user interface, meaning they can’t receive focus by using one of the directions. With this new solution, every widget is put into a set of widgets, and if s set contains at least two elements there is at least one minimum distance between those two. This means the widgets are guaranteed to be accessible with the positional-based directions.
I hope this post gave an adequate overview of a alternative solution that could solve these problems in EFL. In my next blog post, I’ll describe the debugging process for focus problems in EFL user interfaces.
Image Credits: EFL Project