/at-home-modifier-evdev

It enables for example "shift/space dual role key." When SPC key is pressed alone, it's a space; but when pressed with another key, it's SHIFT. See wiki for more: https://gitlab.com/at-home-modifier/at-home-modifier-evdev/wikis/home

Primary LanguageCOtherNOASSERTION

Welcome to "At Home Modifier" hack of xf86-input-evdev. The original
README is moved to README.orig.

Search for the word "News" for the news.

Contents
========
* What it is
* Web site
* Get it
* Usage
 * FAQ
* Author
* Bugs
* Future direction
* Random bits
* History (News are here)
* Source code
* Copyright

What it is
==========
It enables for example "Shift/Space dual role key." When you press the
space key alone, it's a space; but when you press it with another key,
it's a shift. And/or Alt/Esc, AltGr/BS...

It is a fork of evdev driver = xf86-input-evdev. It's ** only for
Linux ** - X in other platforms don't use evdev driver. You can use
"xcape" referred below if you're not a Linux user. (For MS Win, use
AutoHotKey, and for Mac, Karabiner, formerly named keyremap4macbook)

With this hack, your hands can stay at the home position almost
always, and feel more "at home", thus "At Home Modifier".

More precisely, you specify pairs of two keycodes, the "original", and
the "translated". The last event gets recorded in this patch. After
the press of an "original" key, the driver instead reports a
translated key press event. When an original key is released, it sends
a release of the translated key. And it sends a press and release of
the original key if necessary, judging from the last event.

Web site
========
https://gitlab.com/at-home-modifier/at-home-modifier-evdev/wikis/home
(Until Mar 2015, it was hosted at gitorious.org.)

Distro forum threads:
* Gentoo: https://forums.gentoo.org/viewtopic-t-865313.html
* Arch: https://bbs.archlinux.org/viewtopic.php?pid=938140
* Debian: http://forums.debian.net/viewtopic.php?f=20&t=65950
* Ubuntu: http://ubuntuforums.org/showthread.php?p=10907505 (Sorry, closed thread. Use Debian forum instead.)

Get it
======

Download
--------
The tar.gz is at: https://gitlab.com/at-home-modifier/download/raw/master/source/ahm-2.10.3.tar.gz

You can also download the patch against the Xorg's original driver,
"xf86-input-evdev" from the website.

git
---
Git access is available, too. For the first time, install git, and clone as
  $ cd some/dir
  $ git clone git@gitlab.com:at-home-modifier/at-home-modifier-evdev.git

You can receive updates by
  $ cd some/dir/at-home-modifier
  $ git pull

Version tags
------------
  $ git tag -l "ahm*"
lists all releases, like ahm-2.5.1.

You can see the difference to the original code by:
  $ git diff xf86-input-evdev-2.5.0..ahm-2.5.0

Install
-------
* Gentoo Linux users can use ebuild files. Visit the Gentoo Forum thread.
* Arch Linux AUR entries are there. Visit the Arch Forum thread.
* Debian and its derivatives: Visit the Debian Forum thread.
*** In Debian, the original package is called "xserver-xorg-input-evdev"
*** For Ubuntu, Yuri Khan has been providing PPA for years: https://launchpad.net/~yurivkhan/+archive/ahm

Forum threads are listed above.

Other Linux users can install it by replacing xf86-input-evdev.
Compilation can be done just the same way as the original. I'd
appreciate it a lot if you could send me your distro support.

** Server upgrading note **
When you upgrade your xorg-server-x.y.z, be sure to rebuild this
driver, too. (Change in z doesn't affect, but x or y does.)

Usage
=====
First, know the keycodes you need, which are numbers assigned to each
physical key. It's easiest to invoke "xmodmap -pk" or "xev" commands. In my
case it says space is 65, and left shift is 50. OK. (See below for
complicated cases.) Then write your xorg.conf or
xorg.conf.d/10-keyboard.conf:

  # For the details see "man xorg.conf" or your distro doc.
  Section "InputClass"
    Identifier "my keyboard" # You can name this arbitrarily
    Driver "evdev"
    Option "XKBOptions" "terminate:ctrl_alt_bksp" # and so on

    # If you save this file under xorg.conf.d/ :
    Option "AutoServerLayout" "on"

    MatchIsKeyboard "on"
    # If you have multiple keyboards, you want something like one of them:
    #  MatchProduct "AT Translated Set 2 keyboard"
    #  MatchUSBID "0566:3029"
    # Name is found in Xorg log, following the message "Adding input device"
    # or by
    # $ cat /proc/bus/input/devices

    ### at-home-modifier options begin here.
    # The basic option.
    Option "TransMod" "65:50 102:241" # Defines key/modifier pairs.

    ## Fine tuning options. Explained in a later section.
    # For the first time, omit them.

    # Option "AhmTimeout" "400" # In millisecond.
    # Option "AhmDelay" "65 102" # Delayed keys. Seperate by spaces.
    # Option "AhmFreezeTT" "true"
    # Option "AhmResetTime" "10" # In sec.
    # Option "AhmPaddingInterval" "10" # In millisecond.
  EndSection

If you want to specify multiple pairs for TransMod, separate them with
whitespaces, like this:

  Option "TransMod" "65:240 102:241 100:241"

Don't forget to restart X!

Notice that the modifier keys should come to the second of pairs.

Options recognized by at-home-modifier (in fact, by any X drivers)
are printed to X log, typically /var/log/Xorg.0.log, like this:

  [    50.579] (**) Option "AhmTimeout" "400"

Fine tuning options
-------------------
For the first time, skip this section. Come back after you actually
try.

*** Other keys ***

Suppose you want the Left-Alt to be Alt/Esc. Then assign Esc to that
key, using xmodmap. If you don't have any other Alt keys, then allocate
Alt to keycode 240 or so, which must be unused on usual keyboards.

For more complicated changes, you can tamper with files in
/usr/share/X11/xkb/symbols/. See also the section "More on keycodes"
below.

The bottom row of my keyboard is Esc-BS-Spc-Ret-Tab, from left to
right, with the overlay Alt-Shift-Ctrl-Shift-Alt. (Japanese keyboards
have many keys you can press with thumbs. Now you can switch Firefox tabs
with thumbs.=)

You can use any keys for transmods. "d" & "k" (and so on) may be good.
When you want to capitalize the left-hand keys, press "k", and "d"
for right-hands. This may sound too complex, but you'll be soon
accustomed.

*** Cancellation by long press (timeout) ***

Suppose you were about to input shift + A and pressed space/shift, but
you changed your mind. If you release the space/shift key, you'll
receive one space, but it's not what you want!

Actually, a workaround is provided by time-out; a long enough press
cancels that kind of press. If you have the following line in evdev
driver configuration,

  Option "AhmTimeout" "400" # In millisecond.

then a single press and release of space/shift key produces nothing if
the press lasts more than 0.4 sec. The default is 0.6 sec. You can
disable timeout by setting it to 0.

*** Successive transmod tuning ***

A subtle fix is enabled by default; suppose a transmod X has been
pressed. If "transmod Y press, X release" follows, then the press of Y
is treated as the original key. It's probably what you want.

You can disable it by setting the boolean option "AhmFreezeTT" to false.
("TT" is meant for "transmod-transmod".)

See also "Corner cases in press and release order" below.

*** Reset ***

Sometimes translated modifiers get frozen (See "Switching VT" section
below), so a workaround is provided; just leave the keyboard long
enough time (default 10 secs) untouched.

You can change this time with the following option:
    Option "AhmResetTime" "10" # In sec.
To disable this feature, set it to 0.

Reset is implemented by sending release events to all translated
modifiers, and clearing internal variables. The time measurement is
not exact, and the maximal error is 1 sec. (Implementation note: It's
because the sub-second field of timeval struct is ignored.) The exact
time things get reset is the first time you touch the keyboard.

*** Gtk widget double-press workaround (padding interval) ***

Suppose you focus a gtk window with a button widget. When you press
the shift/space, the gtk button should be pressed. But with this hack,
you may have to press the key twice; the first press merely focuses
the button, and the second key press becomes the real push.

As a workaround, "padding interval" can be set:
    Option "AhmPaddingInterval" "10" # In millisecond.
The default value is 10 ms, and I think it's good, but if it doesn't
work, set it bigger.

How it works: remember that a release of shift/space key, without touching
other keys, sends a release of shift, a press of space, and its
release. Padding interval is inserted between the shift release and
the space press. Bigger the value, likelier to work, but the latency
gets bigger, too.

I don't know what's happening inside of gtk, but this solves.

*** Fast type fix (delay) ***

(Probably this option is not so satisfactory) Users of this hack often
have "tongue-twister of fingers": Suppose you want a space and a lower
case x. If the first press of space/shift is followed first by a press
of x and then a release of space/shift, you'll get an upper-case X
instead.

To fix it, you can let "delay" be associated to space/shift, like:

    Option "AhmDelay" "65 102" # Delayed keys. Separate by white space

Then the press of x (or any) following space/shift is "delayed",
and completes after release of space/shift or x.

There's a trade off. Whenever you want a real shift, you have to
release the space/shift later.

This feature is not (yet) satisfactory for the author. Maybe it
should be treated as a modifier only if the key is pressed long
enough (say 100ms), in addition to / instead of the press-release
orders.

More on keycodes
----------------
It's good to know that you can also tell keycodes by looking at
/usr/share/X11/xkb/keycodes/evdev in order to customize the keyboard
layout with XKB. For example that file says:

    <SPCE> = 65;  // space
    ...
    <LFSH> = 50;  // left shift

Ok, but what's this?
    <AE02> = 11;

Hm, if you use for example Italian layout, see
/usr/share/X11/xkb/symbols/it. It has lines:

  xkb_symbols "basic" {
   ...
   key <AE02>  { [         2,   quotedbl,  twosuperior, dead_doubleacute ] };
   ...
  }

  xkb_symbols "nodeadkeys" {
    // Modifies the basic italian layout to eliminate all dead keys
    ...
    key <AE02>  { [         2,   quotedbl,  twosuperior,  doubleacute ] };
    ...
  }

Aha, so that key is basically "2".

FAQ
---
* Q: I need to input Shift+Space. How can I do it if my space is
     Space/Shift key?
  A: Simple. Turn both of the original Space and Shift into Space/Shift keys,
     for example.

Author
======
Teika kazura <teika ahm-is-great at gmx ahm-is-great dot com>

Delete "ahm-is-great" in the address.

It's good *not* to trust authors you find on the Web. You may be
reassured to know that I was a developer of Sawfish window manager:
  http://sawfish.wikia.com/wiki/User:Teika_kazura

Bugs
====

Fixed bugs
----------
* In 2.6.3
  ** Gtk widget double press issue.
  To push a gtk button, sometimes you had to press space/shift key
  twice, but this is fixed. If it doesn't work out-of-box, set
  "AhmPaddingInterval" option.
  (This "bug" is not the author's fault, but what's bad for users
  are bugs.=)

  ** Reset and Delayed key
  "Delay" and "Reset" are features introduced in 2.6.2. If a delayed
  key is pressed after a long enough period is passed (i.e. a reset is
  done), the press was ignored. It's fixed now.

* In 2.6.2
  ** Key release interference bug
  Suppose you press x, space/shift, release x, release
  space/shift. Probably you wanted "x ". But formerly, only "x" is
  sent. (More precisely, "x" + shift are sent. Don't confuse it with
  "AhmDelay".)

  ** Frozen key bug
  Probably ahm-2.6.0 has introduced a new bug which makes some keys
  irresponsive.  The bug existed in theory, but the author has never
  experienced it actually.

  ** Memory leak
  Previous version had slight memory leaks (almost unnoticeable).

  ** (obsolete) keycode limit
  __This feature is deleted in 2.6.3__
  X's keycode limit is 255, but linux input driver's keycode limit is
  0x2ff. Now it accepts input codes > 255.

* In 2.6.0
  ** Double shift bug
  Suppose both key a and b are translated to shift. Press a, b, and
  release b. Then it should be 'B', but it used to emit lower b. It's
  because the release of shift was sent before b key press.

Known bugs
----------
* Switching VT: If your Ctrl is a transmod key, when you switch from X
  to a virtual console with Ctrl + Alt + F1, and switch back to X with
  Alt + F1, Ctrl get frozen. This is mitigated with "reset" feature.

  It happens because Ctrl is pressed at the first switching, but the
  release is only sent to the VT, not to X, in particular to this driver.

Not a bug
---------
Many keyboards fail to send some combinations of key presses. For
example, mine doesn't report Left-alt + space(Ctrl intended) +
cursor-down nor alt + space + delete (whereas alt + space + up is
dispatched!!)  All normal symbol keys pressed with alt + space work.

Keyboards with "n-key rollover" are the solution, and completely ok
for this hack, but they may be expensive. (USB connection can't report
7 or more simultaneous presses, but it doesn't matter for us.)

*** Limitations ***
This driver is unaware of others, for example of synaptic driver.
Suppose you press space/shift and the left click of notebook touchpad.
It'll work as shift + click, but a space key event follows. (Timeout
can give a workaround.)

Future direction
================
Probably the author, Teika kazura, won't develop this hack any more as
a fork of X evdev driver.

Realistic solutions are to re-implement it in the user space. Then
codes will be far smaller and much easier to read, and you'll seldom
have to keep up with Xorg changes. Xcape (see below) does this, by
using X Record extension and XTest extension. (X Record records
inputs, and XTest synthesizes events. ) However, XTest and X-Record
may not work in Wayland.

Wish items
----------
Autorepeat support. For example, you press space/shift twice in a row,
and/or hold it long enough, then it's turned to the press of space,
rather than shift.

Delay improvement. See the "Delay" section

Two-way arguments: currently an original-translated pair is written
as "65:50". It's better to allow "65:50m" or "50m:65", "m" meaning
"modifier".

"Dynamic configuration", or config changes on-the-fly may be good, for
example enabling some keys only when you're using an input method.  I
don't know anything about socket or inter-process communication, so
please tell me how to do it. (Space2Ctrl and Keydouble don't need
this. Simply kill the process and run another.)

See also this page for some ideas:
http://www.ruska.it/michal/fork.html

Bug reporting
-------------
When you report a bug, don't forget to disable autorepeat by
  $ xset -r [<keycode>]

It's better to make AhmResetTime big, and if you enable AhmDelay,
set it big, too.

I compile with -Wall -Wextra, and my code does not bring in any extra
warning.

Corner cases in press and release order
---------------------------------------
There're many corner cases, and I don't know all. The option
"AhmFreezeTT" is easy not only to reason, but also to code, but more
complicated examples may not be so.

More may be possible, by knowing which keys are modifiers. (This hack
doesn't use any information which are modifiers. What's done is a
simple translation.) You can get the required information by Xlib or
XKB, but it'll be an inverted implementation, fetching the high-level
part from the raw world.

Or programmable configuration (together with timestamp support),
something like an automaton, may help.  But don't ask me it. I don't
know how to design such logic nor to write a parser.

Random bits
===========

Will this patch speed up typing?
--------------------------------
In my case, it didn't. But I (or my hands) feel far better and I can't
do without this fork any more. It's much less tiring, so it may be
more efficient if you use keyboard for long time in a day.

In fact, this hack introduces some nicety. Options like delay and
timeout are intended for the cure, but they bring in others.

Warning: Health issue
---------------------
This hack is likely to reduce the use of your pinkies, and the risk of
their injury like RSI. However, overuse of keyboards can damage *any*
digits and other parts of your hand, although pinkies are most
vulnerable.

Good keyboards
--------------
If you can buy a Japanese keyboard, I recommend one. The Japanese
keyboard is a "cheap Kinesis"; the space key is short, and there're
keys around the space key which can be easily pressed with thumbs.
(Have you ever heard of Kinesis Contoured Keyboard?) See for example
http://en.wikipedia.org/wiki/Keyboard_layout

But it's only the layout. I can't assure the overall quality. Of course
it's better to try before you buy...

"Realforce" keyboard made by Topre is unique with capacitive key
switches whose touch is really soft. "HHK Professional" (HHK = Happy
Hacking Keyboard) also uses Topre's switch.

Kinesis contoured, Realforce and HHK Professional come with n-key
rollover.  (See also "not a bug" section above for "key rollover".)

FYI: mine is OWL-KB86STD made by Owltech. It's cheap, and has cheap
touch, but I like the layout.

OWL-KB109BM(B)IIB has "Cherry mx brown switches", so may be good.  See
http://forums.gentoo.org/viewtopic.php?p=7019478#7019478 for more
discussion.

You can buy them from Amazon Japan. (I don't like Amazon hegemony,
but they provide English interface. Many Japanese keyboards are sold
at amazon.com, too.)

Alternatives
============
* Xcape
  https://github.com/alols/xcape

  Xcape is independently written by Albin Olsson. Accepts
  configuration with key names in addition to keycodes.

Obsolete alternatives
---------------------
* Space2Ctrl and Keydouble
  Space2Ctrl by "r0adrunner" is minimal, only supports "Space to
  Ctrl", and not configurable. Written in C++.
  Keydouble by "baskerville" is a rewrite of Space2Ctrl in C. Has a
  bit less options than mine.

    https://github.com/r0adrunner/Space2Ctrl (Space2Ctrl)
    https://github.com/baskerville/keydouble (Keydouble)

* actkbd: It works by direct access to /dev/input, but not updated
  since 2007. I don't think it's flexible enough.

    http://users.softlab.ntua.gr/~thkala/projects/actkbd/

* 窓使いの憂鬱 (Mado-tsukai no yū-utsu; meaning "Spleen of Windows
  Users") for Linux & Darwin: It's a port of a Windows key tuner
  software "窓使いの憂鬱", comparable to AutoHotkey. Japanese
  documentation only. The author is not reachable. Not maintained
  actively. It uses uinput. The last update was in Nov 2011.

    http://www42.tok2.com/home/negidakude/

History
=======

News
----
* 2.10.3 (july 2016):
  * Merged upstream 2.10.3, which is 2.10.2 plus one bugfix, https://bugs.freedesktop.org/show_bug.cgi?id=95315

* 2.10.1 (feb 2016):
  * Merged upstream 2.10.1.

* 2.9.2 (apr 2015):
  * Merged upstream 2.9.2. It also includes the fix of bug 84445, done in commit 8868f61:
   https://bugs.freedesktop.org/show_bug.cgi?id=84445

* 2.8.0 (jun 2013):
  * Merged upstream 2.8.0.
    More precisely,
    * There're two fix-up commits after 2.8.0 in the upstream. They're
      merged too.
    * In ahm-2.7.1, configure option "--without-mtdev" was added. But
      now it's deleted, and mtdev dependency is mandatory.

* 2.7.3 (nov 2012):
  * Merged upstream 2.7.3. Ahm-2.7.2 was never released.

* 2.7.1 (jun 2012):
  * Merged upstream 2.7.0. No any change in ahm per se, except doc.
    * An upstream bugfix of horizontal scroll, X.Org Bug 46205, is
      included. (The fix is published after the 2.7.0 release.)
    * Added an option to configure script "--without-mtdev". The
      upstream code always checks mtdev, and enable it when found.
      If you don't pass the above option, it falls back to the
      original behavior.

      This change, commit 371543edf0b, probably has to be reverted
      before merging upstream 2.8.0. The upstream suggests mtdev
      dependence will be forced in future versions.
  * Read also "Future direction" section in this README.
  * The hack version is 2.7.1, not 2.7.0, without much reason.

* 2.6.4 (dec 2011):
  * Other device awareness
    When you press space/shift and a mouse button, the result used to be
    shift + click, ok, but also followed by an extra, unwanted
    space, as if the click hadn't happened. It's because each device
    ignored others. Now it's fixed, as long as the mouse is also
    handled by evdev driver. (Notebook touchpads are dealt by
    synaptics driver, so it's not fixed, and won't be fixed. Use
    AhmTimeout option as a workaround.)

    Thanks to the ArchLinux forum user "grimp3ur" for the idea.
* 2.6.3 (nov 2011):
  * Bugs fixed
    Gtk button double press bug. Reset and delayed key bug.
  * Big keycode support is deleted.
    In 2.6.2, big keycode support was introduced, but it's
    deleted. loadkeys (1) command suffices.
* 2.6.2 (oct 2011):
  * New features
    Long press cancellation (Option "AhmTimeout"), fast type fix
    (Option "AhmDelay"), successive transmod tuning (Option
    "AhmFreezeTT"), reset (Option "AhmResetTime") are implemented.

    Thanks to the ArchLinux forum user "bloom" for the idea of
    long press cancellation.
  * Bugs fixed
    Release interference bug, keycode limit bug, and 2 other minor
    bugs are fixed.
  * Documentation
    New sections: "Not a bug", "Corner cases", "Alternatives", "Source
    code".
    New bug item: "Switching VT".
    New wish items: "Dynamic configuration", "autorepeat support"
  * Feature deleted in later release.
    "Big keycode support" is introduced in 2.6.2, but deleted in 2.6.3.
* 2.6.1 was never released.
* 2.6.0 (apr 2011): Merged upstream 2.6.0. "Double shift bug" is fixed.
* 2.5.1 (feb 2011): Minor documentation updates.
* 2.5.0 (feb 2011): Initial release. Forked from upstream 2.5.0 = xf86-input-evdev-2.5.0.

Background
----------
What was proposed originally was called "SandS" - stands for "Space and
Shift" - which dates back to year 2001, by K. Kimura.[1] There's
implementations in Mac and Win, and has a modest popularity in Japan
still in year 2011. (K. Kimura has also contributed a lot to Japanese
input methods.)

In 2008 T. Matsuyama implemented it for X keyboard driver.[2] Then
came a port to evdev driver by "jeneshicc".[3] But they lack
generality; you can only use physical shift, alt, and space keys. My
code is based on the last patch. I appreciate their work.

[1] (Japanese) http://hp.vector.co.jp/authors/VA002116/
[2] (Japanese)
http://dev.ariel-networks.com/Members/matsuyama/keyboard-customize
[3] (Japanese):
http://d.hatena.ne.jp/jeneshicc/20100306/1267843799

Space2Ctrl was (probably) written independently in 2011.

Source code
===========

Required knowledge
------------------
What's required is only C knowledge, none of X. I've added some comments, so
it must be easy to understand.

src/evdev.h
-----------
Search for "ahm variables".

In src/evdev.c, gcc __attribute__ is used. To support other compilers,
it's defined as null when __GNUC__ is not defined.

src/evdev.c
-----------
* Parsing options
  Ahm options are parsed in function NewEvdevPreInit. Search for
  "parse ahm options".

* Earlier event handling
  In the Xorg original code, keyboard events are handled by
  EvdevQueueKbdEvent. Ahm wraps it with AhmStep1 and AhmStep2, and
  WrapEvdevQueueKbdEvent.

* Later event handling
  In the original code, events get really sent in
  EvdevPostQueuedEvents. To implement AhmPaddingInterval, this
  function is changed a bit, by queuing key events in ahm's own queue,
  and asynchronous timer is set. Timer related functions I've added
  are: AhmWakeupHandler, AhmBlockHandler, AhmRegisterTimers and
  AhmFinalise.

License
=======
Distributed under MIT License; Same as Xorg.