Index: [thread] [date] [subject] [author]
  From: Matthias Grimrath <m.grimrath@tu-bs.de>
  To  : ggi-develop@eskimo.com
  Date: Wed, 19 Aug 1998 01:48:43 +0200

Re: keyboard.h changes

Hi!
 
This is not a direct response; rather an outline of an idea how to
handle keyboard input.

The conversion of scan codes to key_labels and _syms is 

scancode -> scancode-sym-translation -> symbol  -+
| |   |                   |                      |
| |   +-> modifier table -+                      +- ggi_event
| +-----------------------------------> label    |
+-------------------------------------> code    -+

The translation of scancode to symbols can be described as a function

symbol = translate(scancode, mod1, mod2, mod3, .... )

scancode is the code sent from the keyboard controller.
modN is a boolean and describes which modifiers are active.

At this translation stage, each and every modifier is just a boolean
that affects how scancodes are mapped to symbols.

One possible implementation of the above 'translate' function is a
table:

          |  s  |  s  |
 . M M M  |  c  |  c  |
 . o o o  |  a  |  a  |
 . d d d  |  n  |  n  |
 . 2 1 0  |  0  |  1  |
----------+-----+-------------------
   0 0 0  | 'a' |  F1
----------+-----+-------------------
   0 0 1  | 'A' |  F10
----------+-----+-------------------
   0 1 0  | 0x1 |  n/a
----------+-----+-------------------
   0 1 1  | 0x1 |  n/a
----------+--------------------------
   1 0 0  +  (a umlaut)
----------+--------------------------
   1 0 1  +  (A umlaut)

The meaning of Mod0 and Mod1 in the above example is Shift
and Ctrl, but this is not necessary.  Mod2 is a german umlaut
modifier.  On Sun keyboards, it is activated by pressing <compose> +
<shift> + <'>

Unfortunately implementing the above table right away consumes <# of
scancode> * 2 ^ <# of modifiers> memory.  With typical values for
scancode == 128, modifiers == 10, sizeof(table_entry) == 2 bytes,
it consumes 128 * 2^10 * 2 = 256KBytes.  However, with some
intelligent compression it should be possible to reduce memory usage.

====== NEXT - modifier table =======

What is a modifier? A modifier itself is just a bit that gets
set/reset usually by pressing keys. (But in theory it may also be
affected by ioctls or mouse or whatever)

'Standard' modifiers are <shift>, <ctrl>, <alt>, <altgr>,...
The modifier bits are set on keypress and reset on keyrelease.

'Toggle' modifiers are <shift-lock>, <caps-lock>, ...
The modifier bits are toggled upon each keypress

'Dead' modifiers are <tilde>, <circumflex>, <'>, <`>, ...
The modifier bits are set upon keypress and reset on _any_ keypress
except the key(s) assigned to this modifier.

..... <possible modifier types beyond the scope of the author>

It is important though that each of the above modifier types are just
different modifier bits to the translation function mentioned in the
previous section.

The meaning of modifiers is given in the modifier translation table.
It may look like (read '->' as 'affects the following modifiers')

Example

scan code              | modifier
-----------------------+-----------
shift-left            -> mod0, mod5
shift-right           -> mod0, mod5
ctrl-left             -> mod1
alt                   -> mod2
altgr                 -> mod3
caps-lock             -> mod4
shift + caps-lock     -> mod5
circumflex            -> mod6

The modifiers mean here:
mod0 : shift
mod1 : ctrl
mod4 : caps-lock
mod5 : shift-lock
mod6 : dead circumflex

but once again this is completely configurable.  You may also map
caps-lock to mod0 and shift to mod12 if you like.  Also, the
translation function might be configured to only produce capital
letters in the range A-G if the mod0 is set.

(Well, this is not complete, because dead modifiers need to be reset
after any other key has been pressed.  Also, 'affect modifier' needs
to defined better)

Therefore, there is no predefined meaning of a modifier bit.  If we
want that I propose to add a query function ala 

int GetModifier(char *modname)

return either the bitposition or -1 if the modifier is unknown. 
'modname' is a set of defined strings describing modifiers with
well defined meaning.  (I.e. if GetModifier("shift") returns
something != -1, it means that this modifier in the current keyboard
mapping produces capital letters when a latin key is pressed)

====================

I like the above idea because it doesn't make any assumptions what
keys the keyboard have and/or what modifiers the user wishes to use. 
Maximum portability guaranteed :-)

====================

> What I had planned was making capslock & numlock into modifiers
> (which is what they really are), as follows :

I agree that caps and num lock are just modifiers.


> Another thing is the left/right versions of the modifier keys.
> This is what I had in mind :
>
>     #define GGI_KM_SHIFT    0
>     #define GGI_KM_ALT      1
>     #define GGI_KM_CTRL     2
>     #define GGI_KM_TOP      3      [note 1]
>     #define GGI_KM_SUPER    4
>     #define GGI_KM_HYPER    5
>
>     #define GGI_KM_MASK     0x07
>
>-->  #define GGI_KM_RIGHT    0x08    /* additive */
>     #define GGI_KM_STICKY   0x10    /* additive */
>     #define GGI_KM_LOCKED   0x20    /* additive */

I don't think this is a good idea because here you make an assumption
that modifier keys come in left/right versions. It'd be better to
assume that modifier keys can come in _any_ version.  (What about a
keyboard with 3 shift keys - hmm, ok, kidding... ;-) )


> I find the current key modifiers (inherited from Linux), with three
> versions of shift (KG_SHIFT, KG_SHIFTL, KG_SHIFTR) and three
> versions of control (KG_CTRL, KG_CTRLL, KG_CTRLR) to be pretty
> confused.  In keytables(5) it says :

It shows me that the modifiers are not abstracted enough from the
keyboard design.  It is mixed and that causes confusion.


> The "completely arbitrarily" bit is what I find so crazy, 

Not really if you abstract modifiers from keys which is not done in
current implementations of both linux kernel and GGI.

--
Matthias Grimratht

Index: [thread] [date] [subject] [author]