Howto:Reassign keyboard bindings

From FlightGear wiki
Revision as of 14:50, 21 April 2014 by Johan G (talk | contribs) (cat: Howto, FlightGear)
Jump to navigation Jump to search
WIP.png Work in progress
This article or section will be worked on in the upcoming hours or days.
See history for the latest developments.

A common request is how to change keys to do different commands. FlightGear makes this as easy as editing an XML file, and possibly adding a parameter to point FG to the new XML file.

In general, the list of keyboard commands is stored in the property tree and is loaded at startup or when the menu option "Debug -> Reload input" is selected. The main list of commands is available in [1], but each aircraft can add/change its own bindings through its -set.xml file, and additional config files can do the same.

Adding/modifying key assignments

Keyboard bindings are usually fairly simple. They consist of a <key> node (with a corresponding index), optional <name> and <desc> nodes, and one or more <binding>s. A very simple example is the default for Ctrl+V:

 <key n="22">
  <name>Ctrl-V</name>
  <desc>Select initial view (view 0)</desc>
  <binding>
   <command>property-assign</command>
   <property>/sim/current-view/view-number</property>
   <value>0</value>
  </binding>
 </key>

The initial tag (<key n="22">) is used to identify the keycode; see the next section for how to find it for other keys. If this is not specified, FG won't have an accurate view of which key it is supposed to represent. The next two tags, <name> and <desc>, simply are there to describe the key and its function, respectively. They are not required but might be used for showing keyboard help information or other user-display uses. The <binding> tag is the functional aspect that gets executed when the key is pressed. The above example would be equivalent to this Nasal code:

setprop("/sim/current-view/view-number", 0)

For more on bindings and their different commands see the article about them: bindings.

Here's a more complex binding, also from keyboard.xml, for /:

 <key n="47">
  <name>/</name>
  <desc>Open property browser</desc>
  <binding>
   <condition>
    <not>
     <property>/sim/input/property-key-handler</property>
    </not>
   </condition>
   <command>nasal</command>
   <script>gui.property_browser()</script>
  </binding>
  <binding>
   <condition>
    <property>/sim/input/property-key-handler</property>
   </condition>
   <command>nasal</command>
   <script>prop_key_handler.start()</script>
  </binding>
 </key>

This now has two bindings that execute based on a <condition> (see: conditions). The first executes if the property key handler development extension is not enabled, the second if it is enabled. Both execute a Nasal command: one to open the property browser, the other to start capturing keys (which will also open a browser if the user enters and path and hits :).

Another common element is the <mod-up> event, which happens when the button is released. For example, the S key fires the starter only as long as it is held down, via complementary commands on press and release:

 <key n="115">
  <name>s</name>
  <desc>Fire Starter on Selected Engine(s)</desc>
  <binding>
   <command>nasal</command>
   <script>controls.startEngine(1)</script>
  </binding>
  <mod-up>
   <binding>
    <command>nasal</command>
    <script>controls.startEngine(0)</script>
   </binding>
  </mod-up>
 </key>

Other similar modifiers are the following:

  • mod-up: release the key
  • mod-shift: if Shift is held down during event
  • mod-ctrl: if Ctrl is held down during event
  • mod-alt: if Alt is held down (rare)
  • mod-meta: if Meta is held down (rare)
  • mod-super: if Super is held down (very rare)
  • mod-hyper: if Hyper is held down (very rare)

(FIXME: describe more, esp. interaction with the key code...)

Finding keycodes

As mentioned in keyboard.xml, "regular keycodes go up to 255; special keys start at 256, and can be calculated by adding 256 to the GLUT key value in glut.h."

For printable/ASCII keys (e.g. any letter of the alphabet, number, or symbol found on a keyboard), this is simply the ASCII value of the key. xlate is a simple tool that can convert from a letter to appropriate number: enter the letter in [TEXT], click convert, and look at the [ASCII DEC / CHAR] box for the result. And alternative would be to use Nasal (in the Nasal Console or REPL), with a simple script like this that will "pop up" the result:

gui.popupTip(`a`); # replace with the key you want to test

No matter what method you use, for "a" (lowercase), you should get 97; "A" (uppercase) is 67; "0" would be 48.

For non-printable characters, the simplest option is to look for the specific key (or control key) in keyboard.xml. For example, Ctrl+N is found on line 154, which reads:

<key n="14">
  <name>Ctrl-N</name>
  ...
</key>

Thus the key is found at index 14.

If the key isn't listed in keyboard.xml, the last option is to enable some helpful output to see what the correct keycode is. Uncomment Template:Git file and run with the --console option, if on windows, and look at the console to see each keycode for each key. Make sure you can see the output as you press keys, or you won't know which is which! When I press and release a, I get this output:

{ key: 97, modifier: { meta: 0, shift: 0, alt: 0, super: 0, ctrl: 0, hyper: 0 }, pressed: 1 }
{ key: 97, modifier: { meta: 0, shift: 0, alt: 0, super: 0, ctrl: 0, hyper: 0 }, pressed: 0 }

This shows that key 97 was pressed (without any modifiers) and then released. This view can also help with combining modifiers, like mod-meta above.

Adding custom bindings

The "easiest" option for many is to edit keyboard.xml in place, because it just works. If you do this, make sure to keep a backup of it, in case you need to revert back to the default setup, or simply download it from gitorious (v3.0) or gitorious (master).

Another option, that ends up cleaner, is using a config file. These are specified on the commandline with --config, like this:

fgfs --config=/Users/philosopher/Documents/FlightGear/keyboard-config.xml

These can be formatted in the same way as keyboard.xml, with the exception of requiring input and keyboard tags, so it looks like this:

<?xml version="1.0"?>
<PropertyList>
<input><keyboard>
    <key n="....">...</key>
    <!-- etc. -->
</keyboard></input>
</PropertyList>

This makes sure it writes to the correct place in the tree, viz. /input/keyboard/.

This allows you to more easily keep several different files for different types of setups, without having to rename them before starting FG, you only need to change the filename passed in the --config= option.

Custom setups

Several users have modified the default keyboard bindings and shared the results.

Complete layouts

Individual bindings