Proposal

Request For Comment

Key Bindings – Draft 1

Summary

Eclipse does not provide any way of changing the accelerator keys assigned to actions. This functionality is useful for a number of different reasons such as:

·        users are familiar with the accelerator keys of a favorite editor, like emacs, which they want to use

·        users want to assign an accelerator key to an action used frequently that does not have one

The end goal is to increase the usability and accessibility of the Eclipse for the user.

 

The preferred solution is to provide a new workbench extension point for developers to specify a key binding set. That is, a list of actions mapped to accelerator keys. Another proposal will be put forth later on to deal with the the user wanting to edit the key binding on a per action basis.

 

The focus of this proposal is on key bindings for the menu bar and the solutions that can be applied to address the problems listed below. The intent is for the solution to “fit” in the long term plans of customizing the Eclipse user interface, such as changing the tool items that are visible on the toolbar, moving menu items into specific menus, etc. The solution should not preclude them.

 

By Simon Arsenault, OTI

Last Modified: December 7, 2001

 


The Details

Problems

Most users have worked with other editors in the past, like emacs, to do development. Each of these editors has a set of accelerator keys that is different than what the Eclipse SDK editors provide. Thus the user must learn a different set of accelerator keys. Users want the option of changing the key bindings to match what they are accustomed to. This allows them to become familiar with the Eclipse environment much more quickly.

 

Because an editor defines key bindings for its actions independent of other editors, the use of accelerator keys for actions that are similar between editors is not consistent. For example, both a Java editor and a HTML editor have an action to increase the indent of some text. To the user, these indent actions are similar and would expect the accelerator key to be the same for both. However, unless the developers are aware of each editor, it is very unlikely that this indent action will have the same accelerator key. A mechanism is needed to define key bindings for “common” editor actions that developers can just use.

 

Not all keyboard layouts are the same, so the choice of accelerator key for an action may not work on all keyboards. For example, the accelerator Ctrl+Shift+< does not work on keyboards where the < character does not require the Shift key modifier to access it. At the very least, the user needs the ability to remove the Shift modifier from the accelerator key definition. Support is needed so developers can specify the accelerator key for an action based on a locale.

 

Some accelerator keys are dependent on the locale. For example, the accelerator key Ctrl+I for indent increase in the Java editor makes sense for English locales, but for other locales it may not. Users want key bindings that are consistent with other applications for their locale. Again, support is needed so developers can specify the accelerator key for an action based on a locale.

 

A developer assigning accelerator keys to actions finds it difficult because of the need to support multiple platforms. There are a couple of issues that need to be looked at:

 

  1. Each platform has accelerator keys that are reserved. For example, on the Windows platform, Alt+Space is reserved for accessing the system menu, yet under Linux, this accelerator key is free to be used. Developers need to be aware of this. As the number of platforms that Eclipse will support increases, the higher the chances are of using an accelerator key reserved by the platform.
  2. Some platforms have guidelines that specify the accelerator keys to use for some common type of actions (like accessing a menu bar, accessing a context menu, etc). An accelerator key can be different between platforms for the same common type of action. The user expects the accelerator key to match the platform guidelines so as to be consistent with other applications on that platform.

 

Some actions do not have accelerator keys assigned to them – usually because the developer assumed the actions would not be used enough to warrant their own accelerator keys. However for the user that needs frequent access to these actions, this can be quite annoying. The user needs the ability to:

  1. remove the accelerator key for an action not used often
  2. assign an accelerator key to an action that has none
  3. change the accelerator key for an action to something more familiar

Background Info

The extension points to add actions provided by the org.eclipse.ui plug-in allow the plug-in developer to specify the accelerator key to be used for an action. The accelerator can be specified in XML using the action’s accelerator attribute (as of 2.0 stream). The method IAction.setAccelerator(int) allows for the accelerator key to be specified programmatically (as of 2.0 stream).

 

SWT only supports accelerator keys defined in menu items. There is no API to define accelerator keys independent of a menu item.

 

The workbench provides a number of “global” actions, such as Save, Close, Cut, Copy, Print, etc, that are made available to all editors. The workbench provides accelerator keys for these actions, rather than an editor.

 

The available set of accelerator keys in any view or editor depends on the active part (e.g. the one with focus). For example, a Java editor could define Ctrl+9 for one of its actions and an HTML editor could define Ctrl+9 for one of its actions too, even if the actions are totally different. When the user presses Ctrl+9, if the Java editor has focus then its action is run. If the HTML editor has focus then its action runs. Otherwise nothing happens (assuming the active part does not have Ctrl+9 as an accelerator key).

 

In the Eclipse UI, there are a number of accelerator keys that are not dependent on the active part. For example, some views have accelerators assigned to them to quickly open them (see the Perspective > Show View sub-menu). Another example is the navigation accelerator keys to switch views or editors (see Window > Navigation sub-menu).

Technical Issues

1.      Action.setText(String) fires a TEXT property change if the label changes, including if it was just the accelerator portion that changed. The comment is vague on IAction.setText(String) as whether this property change event should fire when only the accelerator text portion of the label changes. Also, IAction.setAccelerator(int) does not fire any property event change. We may need to add a new property change event (like ACCELERATOR) or update the comment to fire TEXT property change event when the accelerator is changed.

2.      In emacs, action accelerator keys can be defined as two CTRL keys, CTRL+X followed by CTRL+S for example. SWT does not support this – should they? What about the IAction.setAccelerator(int) API, can it accept something like that? Should it accept an array of key sequence? What about the accelerator attribute in XML – it requires an integer value so how would it represent this? Should it be text based instead?

Issue #2 Notes:

A composite accelerator is like a mode.  If you press a key, and it is the first part of an accelerator, the key is buffered until you press another key.  If the second key completes the accelerator, an action is invoked.  If not, the keys are sent out as key events.

The workbench would need to hook the key events as they occur, buffer them, and then generate action events or key events as SWT would. It is possible, at the workbench level, to hook key events, buffer and dispatch them. If SWT had a global key event listener, the workbench could add itself to that and listen. But unless this can block the events from getting to the focus control, users will always experience strange behavior, when the key event is processed in the control and as an accelerator. Assuming the workbench could capture the events, it still needs a way to dispatch them back out again once the workbench determines their type (accelerator or simple key event).

The workbench cannot depend on adding a control listener to each part. Some parts will forget to add the listener, and the accelerators will fail for unknown reasons to the user.

Hence, it seems SWT will have to support this at the message queue level.

Users familiar with composite accelerator keys, like in emacs, would expect to see the "in progress accelerator" on the status bar.  The workbench should take the same approach.  In "accelerator mode", take over the status bar to display the state, and make it apparent that to the users they are in this “accelerator mode” and how they can back out. Otherwise, the user may unwittingly get into an unknown mode just by pressing a few wrong keys.

Possible Options

As mentioned above, the workbench provides a number of “global” actions, such as Save, Close, Cut, Delete, Print, etc, that all editors make use of. One question that needs to be answered is whether to allow the user to specify:

  1. one set of accelerator keys for these “global” actions that all editors would use, or
  2. multiple sets of accelerator keys for these “global” actions on a per editor basis (for example, Ctrl+S for Save in java editor, and Ctrl+W for Save in the html editor)

 

For this proposal, the first approach will be taken. Based on many usability studies that have been done, it is very difficult for the user to remember different accelerator keys for the same “global” actions in each type of editor. The argument of more flexibility the better would only cause confusion for the user.

Solution 1: "Key Mapping Set"

The workbench will provide an extension point that a plug-in developer can use to register a set of key bindings. For example, there could be one for the emacs editor that would list the accelerator keys to use. The user will choose the set to use from the Preference dialog.

 

The key bindings will be defined using XML. There will be support to specify the platform and locale for a group of key bindings. If the platform and locale is not specified, then the key bindings will apply to all platforms and locales. The accelerator key to use for a known action will be specified as text and will be language neutral. That is, the workbench will be responsible for translating the accelerator key text for the user’s locale and displaying it to the right or left of the menu item label.

 

The workbench will provide a list of “common” action ids. This list will include:

·        all “global” actions like Save, Close, Cut, Copy, Delete, Find, etc.

·        all navigation actions like Switch to Editor, Next Editor, etc

·        all build actions

·        all editor actions applicable to most editors like “go to end of document”, “go to next word”, “increase indent”, etc

An editor developer will associate actions with these common action ids if applicable so that the editor actions use the correct accelerator key defined in the active key binding set. A plug-in developer can define key bindings for these “common” action ids using the new extension point described above.

 

The reason for this “common” action id list is so similar actions in different editors (e.g. increase indent) can all register to use the same accelerator key as defined in the active key binding set. Otherwise the developer will need to specify actual specific editor action id. It’s obvious that the developer will not be aware of all possible editors and therefore most editors will be missed and will be inconsistent with the active key binding set.

 

Issue: collecting a list of these “common” action ids for text base editors is fairly easy, but what about other types of editors like graphical ones (i.e. UML diagram editor, widget visual editor, etc)?

 

The key binding set can contain specific editor action ids if needed by the developer. For example, a key binding set could be created to specify the accelerator keys to use in an Eclipse based web site development tools that match the accelerator keys from another web site development IDE. The key binding set would focus on only the actions for the Java, HTML, and EJB editors.

 

The key binding set can contain specific view ids if the developer wants to assign accelerator keys to some frequently used views.

 

There will be a default key binding set provided by the org.eclipse.ui plug-in that all key binding sets will inherit from. The default key binding set will define accelerator keys for all “common” action ids based on locale and platform. Other key binding sets will just override the accelerator keys applicable for the set.

 

If an editor action defines an accelerator key that conflicts with an accelerator key defined in the active key binding set then the accelerator key for the editor action is ignored. The same applies for all accelerator keys defined in an Action Set, if there is a conflict with the active key binding set then the conflicting accelerator keys of the Action Set are ignored.

For a concrete example, the workbench would define “common” action ids such as:

org.eclipse.ui.common.saveAction,
org.eclipse.ui.common.undoAction,
org.eclipse.ui.common.increaseIndentAction,
etc.

The key mapping set for the emacs editor style would look something like:

actionId = “org.eclipse.ui.common.saveAction”
accelerator = “Ctrl+X && Ctrl+S”   // don’t NLS these…workbench does it
platform =
locale =
etc.

The workbench save action would look something like:

id = “save”
label = “Save”
commonActionId = “org.eclipse.ui.common.saveAction”
icon = …
etc.

Preferred Direction

The preferred solution is to implement the “Key Mapping Set”. It addresses all most of the problems listed above. Another proposal will be needed for allowing a user to customize the key bindings, as there are several issues that need to be addressed. It will also depend on being able to save a custom key binding set for the user’s customization.