genode/repos/os/src/server/input_filter
Norman Feske eba9c15746 Follow practices suggested by "Effective C++"
The patch adjust the code of the base, base-<kernel>, and os repository.
To adapt existing components to fix violations of the best practices
suggested by "Effective C++" as reported by the -Weffc++ compiler
argument. The changes follow the patterns outlined below:

* A class with virtual functions can no longer publicly inherit base
  classed without a vtable. The inherited object may either be moved
  to a member variable, or inherited privately. The latter would be
  used for classes that inherit 'List::Element' or 'Avl_node'. In order
  to enable the 'List' and 'Avl_tree' to access the meta data, the
  'List' must become a friend.

* Instead of adding a virtual destructor to abstract base classes,
  we inherit the new 'Interface' class, which contains a virtual
  destructor. This way, single-line abstract base classes can stay
  as compact as they are now. The 'Interface' utility resides in
  base/include/util/interface.h.

* With the new warnings enabled, all member variables must be explicitly
  initialized. Basic types may be initialized with '='. All other types
  are initialized with braces '{ ... }' or as class initializers. If
  basic types and non-basic types appear in a row, it is nice to only
  use the brace syntax (also for basic types) and align the braces.

* If a class contains pointers as members, it must now also provide a
  copy constructor and assignment operator. In the most cases, one
  would make them private, effectively disallowing the objects to be
  copied. Unfortunately, this warning cannot be fixed be inheriting
  our existing 'Noncopyable' class (the compiler fails to detect that
  the inheriting class cannot be copied and still gives the error).
  For now, we have to manually add declarations for both the copy
  constructor and assignment operator as private class members. Those
  declarations should be prepended with a comment like this:

        /*
         * Noncopyable
         */
        Thread(Thread const &);
        Thread &operator = (Thread const &);

  In the future, we should revisit these places and try to replace
  the pointers with references. In the presence of at least one
  reference member, the compiler would no longer implicitly generate
  a copy constructor. So we could remove the manual declaration.

Issue #465
2018-01-17 12:14:35 +01:00
..
accelerate_source.h Follow practices suggested by "Effective C++" 2018-01-17 12:14:35 +01:00
button_scroll_source.h input_filter: scroll-wheel emulation 2017-11-09 12:18:42 +01:00
chargen_source.h Follow practices suggested by "Effective C++" 2018-01-17 12:14:35 +01:00
connection.h Follow practices suggested by "Effective C++" 2018-01-17 12:14:35 +01:00
de.chargen os: input_filter implementation and test 2017-02-27 15:37:49 +01:00
en_us.chargen os: input_filter implementation and test 2017-02-27 15:37:49 +01:00
en_workman.chargen input_filter character mapping rules for the Workman layout 2017-08-17 11:04:23 +02:00
include_accessor.h Follow practices suggested by "Effective C++" 2018-01-17 12:14:35 +01:00
input_source.h Adjust file headers to refer to the AGPLv3 2017-02-28 12:59:29 +01:00
key_code_by_name.h input_filter: improve capslock handling 2017-11-06 13:57:20 +01:00
main.cc Follow practices suggested by "Effective C++" 2018-01-17 12:14:35 +01:00
merge_source.h Adjust file headers to refer to the AGPLv3 2017-02-28 12:59:29 +01:00
README input_filter: support <include> in <remap> nodes 2017-11-30 11:23:15 +01:00
remap_source.h input_filter: support <include> in <remap> nodes 2017-11-30 11:23:15 +01:00
source.h Follow practices suggested by "Effective C++" 2018-01-17 12:14:35 +01:00
target.mk os/timer: interpolate time via timestamps 2017-05-31 13:16:11 +02:00
timer_accessor.h Follow practices suggested by "Effective C++" 2018-01-17 12:14:35 +01:00
types.h Adjust file headers to refer to the AGPLv3 2017-02-28 12:59:29 +01:00

This component transforms input events originating from multiple sources.


Configuration
-------------

An input-filter configuration consists of two parts, a declaration of
input sources ("Input" connections) that the component should request,
and the definition of a filter chain. Each input source is defined via
an '<input>' node with the name of the input source as 'name' attribute and
the session label as 'label' attribute. The latter can be used to route
several input sources to different components, i.e, input device drivers.

The filter chain is defined via one '<output>' node. It contains exactly
one of the following filters:

:<input name="..."/>:

  Refers to the input source with the matching 'name'.

:<remap>:

  Applies low-level key remapping to the events produced by another filter
  that is embedded as a child node.

  It may contain any number of '<key>' nodes. Each of those key nodes has
  the key name as 'name' attribute, may feature an optional 'to' attribute
  with the name of the key that should be reported instead of 'name'.

  A '<remap>' node may contain '<include>' nodes, which include further
  content into the '<remap>' node. The included ROM must have a '<remap>'
  top-level node.

:<merge>:

  Merges the results of any number of filters that appear as child nodes.

:<chargen>:

  Supplements the input-event stream of another filter with artificial
  'CHARACTER' events by applying character mapping rules. The originating
  filter is defined as a child node.

:<button-scroll>:

  Turns relative motion events into wheel events while a special button
  (i.e., the middle mouse button) is pressed. The button and rate of generated
  wheel events can be configured per axis via the sub nodes '<vertical>' and
  '<horizontal>'. The button of each axis can be specified via the 'button'
  attribute. By default, "BTN_MIDDLE" is used. The rate of generated wheel
  events can be defined by the 'speed_percent' attribute. A value of "100"
  uses relative motion vectors directly as wheel motion vectors. In practice,
  this is results in overly fast wheel motion. By lowering the value, the rate
  can be reduced to practical levels. By specifying a negative value, the
  direction of the generated wheel motion can be inverted.

  The consumed relative motion events are filtered out from the event stream
  such that pointer movements are inhibited while the wheel emulation is
  active. All other events are passed along unmodified.

:<accelerate>:

  Applies acceleration to relative motion values. The 'max' attribute
  defines the maximum value added to the incoming motion values. The
  'sensitivity_percent' attribute scales incoming motion values before
  applying the (potentially non-linear) acceleration function. The 'curve'
  attribute defines the degree of non-linearity of the acceleration. The value
  "0" corresponds to a linear function whereas the maximum value "255" applies
  a curved function. The default value is "127".


Character generator rules
-------------------------

The character-generator ('<chargen>') rules are defined via the following
sub nodes:

:<mod1>/<mod2>/<mod3>/<mod4>:

  Defines which physical keys are interpreted as modifier keys. Usually,
  '<mod1>' corresponds to shift, '<mod2>' to control, and '<mod3>' to altgr
  (on German keyboards). Each modifier node may host any number of '<key>'
  nodes with their corresponding 'name' attribute. For example:

  ! <mod1>
  !   <key name="KEY_LEFTSHIFT"/> <key name="KEY_RIGHTSHIFT"/>
  !   <rom name="capslock"/>
  ! </mod1>

  The '<rom>' node incorporates the content of the ROM module of the
  specified name into the modifier state. If the ROM module contains a
  top-level node with the attribute 'enabled' set to "yes", the modifier
  is enabled. This is useful for handling a system-global capslock state.

:<map mod1="..." mod2="..." mod3="..." mod4="...">:

  A '<map>' node contains a list of keys that emit a specified character when
  pressed. Any number of '<map>' nodes can be present. For each map node, the
  attributes 'mod1' to 'mod4' denote the condition, under which it is
  considered. Each 'mod' attribute has three possible values. If the attribute
  is not present, the state of the modifier does not matter. If set to 'yes',
  the modifier must be active. If set to 'no', the modifier must not be active.

  Each '<map>' may contain any number of '<key>' subnodes. Each '<key>'
  must have the key name as 'name' attribute. The to-be-emitted character
  is defined by the attributes 'ascii', 'char', or 'b0/b1/b2/b3'. The
  'ascii' attribute accepts an integer value between 0 and 127, the
  'char' attribute accepts a single ASCII character, the 'b0/b1/b2/b3'
  attributes define the individual bytes of an UTF-8 character.

:<repeat delay_ms="500" rate_ms="250">:

  The '<repeat>' node defines the character-repeat delay and rate that
  triggers the periodic emission of the last produced character while
  the corresponding key is held.

:<include rom="...">:

  The '<include>' node includes further content into the '<chargen>' node
  and thereby allows the easy reuse of common rules. The included ROM must
  have an '<chargen>' top-level node.


Additional features
-------------------

The input filter is able to respond to configuration updates as well as updates
of included ROM modules. However, a new configuration is applied only if the
input sources are in their idle state - that is, no key is pressed. This
ensures the consistency of the generated key events (for each press event there
must be a corresponding release event), on which clients of the input filter
may depend. However, this deferred reconfiguration can be overridden by setting
the 'force' attribute of the '<config>' node to 'yes'. If forced, the new
configuration is applied immediately.


Examples
--------

An automated test that exercises various corner cases of the input filter
can be found at _os/run/input_filter.run_. For a practical example of how
to use the input filter with the terminal, please refer to the
_gems/run/terminal_echo.run_ script.