Úvod

Nedávno som v rámci upgradu prišiel k novej klávesnici. A pri tej príležitosti som objavoval ako na nej rozchodiť "multimediálne klávesy" a keď už som bol v tom rozhodol som sa urobiť si klávesnicu podľa svojich predstáv: primárne s anglickým rozložením kláves, s možnosťou prepnutia do slovenčiny, so znakom euro a s funkčnými multimediálnymi klávesami. O získané skúsenosti sa teraz s vami podelím.

xev

xev je nástroj, ktorý nám pomôže v samotnom začiatku. Dokáže vypisovať detailné údaje o udalostiach, ktoré zachytáva jeho okno. Medzi takéto udalosti patria pohyby myšou, zmeny polohy či veľkosti okna, ale pre nás najzaujímavejšie sú udalosti od klávesnice. Stlačenie klávesy je jedna udalosť. Jej uvoľnenie je udalosť druhá.

...
KeyPress event, serial 31, synthetic NO, window 0x3200001,
    root 0x131, subw 0x0, time 8119928, (48,-173), root:(52,413),
    state 0x10, keycode 38 (keysym 0x61, a), same_screen YES,
    XLookupString gives 1 bytes: (61) "a"
    XmbLookupString gives 1 bytes: (61) "a"
    XFilterEvent returns: False

KeyRelease event, serial 31, synthetic NO, window 0x3200001,
    root 0x131, subw 0x0, time 8119995, (48,-173), root:(52,413),
    state 0x10, keycode 38 (keysym 0x61, a), same_screen YES,
    XLookupString gives 1 bytes: (61) "a"
...

V tomto výpise je nás v prvom rade bude zaujímať údaj keycode 38 a tiež (keysym 0x61, a). Ten prvý hovorí o tom, aký kód vyslala klávesnica pri stlačení, resp. uvoľnení klávesy, ktorú som stlačil. Ten druhý hovorí aký symbol dostane aplikácia na spracovanie. V našom prípade dostane symbol a, čo vo väčšine prípadov znamená písmeno "a". Než sa ale od 38 dostaneme po "a", je to ešte kľukatá cesta.

Keycodes

Keď X dostane z klávesnice keycode 38, tak najprv nazrie do tabuľky, ktorú môžete nájsť v /etc/X11/xkb/keycodes/xfree86:

 ...
 <CAPS> =  66;
 <AC01> =  38;
 <AC02> =  39;
 ...

Tam sa číslo 38 prevedie na označenie AC01. Toto označenie sa použije pri definovaní symbolov.

Symbols

Aplikácie v X pracujú so symbolmi. Stlačená klávesa a môže znamenať napísanie písmena "a", ale tiež napísanie písmena "A". O význame klávesy hovorí súbor definujúci mapu symbolov, ktorý nájdete napr. v /etc/X11/xkb/symbols/pc/us. Pre účely svojich pokusov som si vyrobil jeho kópiu /etc/X11/xkb/symbols/pc/sk_rastos. Aby o ňom systém vedel treba ho pripísať do zoznamu v /etc/X11/xkb/symbols.dir:
...
--p----- a------- sk_qwerty(basic)
--p----- a------- sk_rastos(basic)

V súbore s definíciou symbolov nájdeme niečo takéto

default
partial hidden alphanumeric_keys modifier_keys
xkb_symbols "basic" {

    name[Group1]= "US/ASCII";

    include "pc/pc(common)"

    // Alphanumeric section
    key <TLDE> { [ grave, asciitilde ] };
    key <AE01> { [ 1, exclam ] };
    key <AE02> { [ 2, at ] };
    ...
    key <AC01> { [ a, A ] };
    ...

Ako vidíte v tomto súbore sa označenie AC01 prevedie na symbol. Oblasť medzi hranatými zátvorkami sa označuje pojmom skupina (angl. group). V rámci jednej skupiny sú vymenované všetky symboly, ktoré môže dané označenie klávesy vrátiť aplikácii. V predchádzajúcom príklade vidíme, že klávesa ktorá posiela kód 38 môže poslať symbol a, alebo A. To ktorý z nich to konkrétne je, rozhoduje stav modifikátorov. Najčastejšie používaným modifikátorom je klávesa Shift. Kód 38 bez stlačenej klávesy Shift spôsobí poslanie symbolu a. So stlačenou klávesou Shift je to A. Ak je uvedený len jeden symbol, použije sa bez ohľadu na to či je Shift (alebo iný modifikátor) stlačený alebo nie.

Jedna skupina môže priradzovať aj viacero symbolov jednej klávese:

 ...
 key <AD03> { [ e, E, EuroSign ] };
 ...

Takýto riadok zariadi, že klávesou s označením AD03 môžeme napísať e, E ale aj znak €. Prirodzene na to potrebujeme "ďalší shift". Bežne sa na tento účel používa klávesa Alt vpravo od medzery. Aby sme ju takýmto spôsobom mohli použiť, musí súbor s mapovaním symbolov obsahovať nasledovné 2 riadky:

 key <RALT> { type="TWO_LEVEL", [ ISO_Level3_Shift, ISO_Level3_Shift ] };
 modifier_map Mod5 { <RALT> };

Skupiny

Systém X-windows umožňuje definovať viacero skupín prislúchajúcich jednej klávese. Využiť to možno napríklad na prepínanie lokálnej klávesnice. Ja používam najčastejšie anglickú klávesnicu, ale občas potrebujem aj klávesnicu slovenskú. Preto som si vyrobil vlastný súbor s mapovaním kláves na symboly:
 ...
 key  { [ 2, at ], [lcaron, 2] };
 key  { [ 3, numbersign ], [scaron, 3] };
 key  { [ 4, dollar ], [ccaron, 4] };
 key  { [ 5, percent ], [tcaron, 5] };
 ...

Zoznam použiteľných názvov symbolov možno nájsť napr. v súbore /usr/include/X11/keysymdef.h:

...
#define XK_scaron              0x1b9
...
#define XK_ccaron              0x1e8
...

Mnohé z nich sa dajú uhádnuť. Písmená s mäkčeňom sú nesú v sebe označenie caron (napr. lcaron, dcaron, Rcaron), písmená s dĺžňom nesú v sebe označenie acute (aacute,iacute,Eacute). České u s krúžkom je uring, resp. Uring. Klávesy mäkčeň a dĺžeň, ktoré symbol generujú až po stlačení ďalšej klávesy sa nazývajú mŕtve (dead) klávesy: dead_caron a dead_acute.

Multimediálne klávesy

No a keď už sme sa prehrýzli až sem, vrátime sa naspäť k multimediálnym klávesám. Klávesa, ktorá nemá priradený symbol spôsobí nasledovný výstup z programu xev:

KeyRelease event, serial 31, synthetic NO, window 0x3400001,
    root 0x131, subw 0x0, time 17288868, (75,22), root:(79,608),
    state 0x10, keycode 176 (keysym 0x0, NoSymbol),
same_screen YES,
    XLookupString gives 0 bytes:

Ako vidíte klávesa s kódom 176, nemá priradený žiaden symbol. V súbore /etc/X11/xkb/keycodes/xfree86 sa dočítame že klávesa dávajúca kód 176 má označenie I30. Keďže na klávese je namaľovaný symbol označujúci pridávanie hlasitosti, tak hľadám niečo podobné v /usr/include/X11/keysymdef.h. Tam však nič také nie je, ale niečo sa dá nájsť v /usr/include/X11/XF86keysym.h (uznávam, že to nie je moc koncepčný krok, ale párkrát grep mi pomohlo ;-)):

#define XF86XK_AudioRaiseVolume 0x1008FF13

No a tak do súboru s definíciou pridávam riadok:

key <I30> { [ XF86AudioRaiseVolume ] };

Tento postup som použil na všetky klávesy na mojej klávesnici.

Ako to pasuje dohromady

Prv než sa pokúsime nové mapovanie kláves použiť môžeme urobiť syntaktickú kontrolu pomocou xkbcomp (ono to vlastne nie je nástroj primárne na to určený, ale poslúži):

$ xkbcomp  /etc/X11/xkb/symbols/pc/sk_rastos
expected keysym, got Eurosign: line 42 of /etc/X11/xkb/symbols/pc/sk_rastos
last scanned symbol is: Eurosign

Chyba v tomto prípade je v tom, že písmeno s v Eurosign má byť veľké: EuroSign.

Nové mapovanie kláves možno použiť pomocou programu setxkbmap a prepínača -layout:

$ setxkbmap -layout sk_rastos

setxkbmap pozná tiež prepínač -option, ktorým môžeme okrem iného bližšie určiť spôsob prepínania medzi grupami. Nasledovný príkaz napríklad umožní prepínanie medzi grupami súčasným stlačením oboch kláves Shift. Prepnutie do druhej grupy je indikované zapnutím LED-ky ScrollLock.

$ setxkbmap -layout sk_rastos -option grp:shift_toggle,grp_led:scroll

Alternatívne môžete definovať želané rozloženie kláves v konfiguračnom súbore X-windows: /etc/X11/xorg.conf resp. /etc/X11/XF86Config (podľa toho či používate X.Org alebo XFree):

Section "InputDevice"
        Identifier  "Keyboard0"
        Driver      "keyboard"
        Option      "XkbRules"   "xorg"
        Option      "XkbModel"   "pc105"
        Option      "XkbLayout"  "sk_rastos"
	Option      "XkbOptions" "grp:shift_toggle,grp_led:scroll"
EndSection

Xmodmap

Doteraz popisovaný spôsob definovania významu kláves je vhodný skôr pre definovanie klávesnice, ktorá sa výrazným spôsobom líši od klávesníc, ktoré sú dodávané s inštaláciou X-Windows. Vhodnejší je tiež tam, kde chceme definovať rozloženie kláves pre viacero užívateľov. Okrem tohoto spôsobu máme ešte k dispozícii program xmodmap. Ten takisto dokáže meniť význam kláves (a dokonca aj tlačidiel na myši). Zmenu definície jednej klávesy môžeme urobiť napr. takto:

xmodmap -e 'keycode 229=Find'

Takýmto príkazom necháme vykonať výraz, ktorý modifikuje mapu rozloženie kláves. Konkrétne klávese, ktorá posiela kód 229, priradzujeme symbol Find. Rovnako ako v predchádzajúcom prípade kód klávesy získame pomocou programu xev a symboly, ktoré môžeme použiť opäť nájdeme v keysymdef.h resp. XF86keysym.h. Pochopiteľne táto zmena sa nezachová pre ďalšie sedenie. Kompletný popis schopností xmodmap nájdete v manuálovej stránke.

Záver

Na záver by som rád vyjadril poďakovanie Yetimu, za inšpiráciu a nakopnutie správnym smerom a tiež nádej, že vám informácie z tohto článku k niečomu budú.