Make your own custom keyboard layout for Linux

An introduction which may be safely skipped

A desire for custom keyboard layout is not very common, but it is in no sense unique. Usually, an interest to fancy keyboard layouts is inherent to multilingual persons. They are programmers, translators, journalists, (archeo-) linguists, touch-typists and simply people who do not have characters of their second or first language printed on the keys of their keyboards.

Common denominator of their reasons for such a desire can be expressed in one word: convenience. Consider a rather typical case well described here: https://michal.kosmulski.org/computing/articles/custom-keyboard-layouts-xkb.html

My own story is more intricate and involves a number of not uncommon reasons. I used to type a lot in Cyrillic and Latin alphabets and the mix of them. Four-finger typing and endless switching between layouts became a considerable burden soon enough and the task of teaching myself touch-typing became really urgent. Therefore I began to reckon my situation. Qwerty layout was not optimal for typing in Latin but there existed its optimized variety for English language, i.e. Dvorak layout. Legacy Cyrillic layout was not optimal for typing as well but there were no optimized Dvorak-like layout for Russian at all. At the same time I typed more in Cyrillic than in Latin. Next to it, the mere idea of learning two completely different layouts was much less than attractive however optimal they could be, which they were not.

Long story short, I have gathered a body of texts, extracted characters' and character combinations' frequencies and used Dvorak's principles to compose (hopefully efficient) keyboard layout for Russian language (GNR). Since then I have phonetically mapped keyboard layout for English language (GNE) to it while preserving punctuation marks placing. After having gained enough practice in touch-typing uising GNR and GNE, the first variant of these layouts was corrected according to the actual experience to rebalance stress on the right and left wrists and different fingers. Very soon I could not believe I managed to live without my layouts and touch-typing wasting my life time at keyboard in vain. And I enjoyed my layouts happily ever after.

Actual instructions on making proprietary keyboard layout

In general, you have to prepare your keyboard layout description file and to add your keyboard layout to the list of available keyboard layouts. The second feat requires superuser privileges. Detailed instructions follow.

  • Ensure that you know how characters will be placed on keys of your keyboard. For example:


  • Familiarize yourself with characters and keyboard keys naming conventions by reading symbol files for your language in /usr/share/X11/xkb/symbols directory. Please note, that symbol files do not necessarily denote alphabetic characters as you see them typed. Next to it, keyboard physical keys are assigned specific codes as follows:

  • Think out a short abbreviated name for your layout. GNR and GNE names are used in examples.

  • Create empty file with selected name and paste a template code into it. Feel free to use any of two examples below.


//   GNR         UGNVS, Russian

default partial alphanumeric_keys
xkb_symbols "basic" {

    name[Group1]= "GNR";

    // Alphanumeric section
    key <TLDE> {	[     grave,	asciitilde	]	};
    key <AE01> {	[	  1,	exclam 		]	};
    key <AE02> {	[	  2,	question	]	};
    key <AE03> {	[	  3,	slash		]	};
    key <AE04> {	[	  4,	dollar		]	};
    key <AE05> {	[	  5,	percent		]	};
    key <AE06> {	[	  6,	less		]	};
    key <AE07> {	[	  7,	greater		]	};
    key <AE08> {	[	  8,	asterisk	]	};
    key <AE09> {	[	  9,	parenleft	]	};
    key <AE10> {	[	  0,	parenright	]	};
    key <AE11> {	[     minus,	underscore	]	};
    key <AE12> {	[     equal,	plus		]	};

    key <AD01> {	[ Cyrillic_pe, Cyrillic_PE	]	};
    key <AD02> {	[ Cyrillic_de, Cyrillic_DE	]	};
    key <AD03> {	[ Cyrillic_em, Cyrillic_EM	]	};
    key <AD04> {	[ Cyrillic_ka, Cyrillic_KA	]	};
    key <AD05> {	[ Cyrillic_ze, Cyrillic_ZE	]	};
    key <AD06> {	[ Cyrillic_be, Cyrillic_BE	]	};
    key <AD07> {	[ Cyrillic_u, Cyrillic_U	]	};
    key <AD08> {	[ Cyrillic_ya, Cyrillic_YA	]	};
    key <AD09> {	[ Cyrillic_softsign, Cyrillic_SOFTSIGN, Cyrillic_hardsign, Cyrillic_HARDSIGN	]	};
    key <AD10> {	[ Cyrillic_yeru, Cyrillic_YERU	]	};
    key <AD11> {	[ Cyrillic_ghe, Cyrillic_GHE	]	};
    key <AD12> {	[     colon,	semicolon	]	};

    key <AC01> {	[ Cyrillic_a, Cyrillic_A	]	};
    key <AC02> {	[ Cyrillic_i, Cyrillic_I	]	};
    key <AC03> {	[ Cyrillic_ie, Cyrillic_IE, Cyrillic_io, Cyrillic_IO	]	};
    key <AC04> {	[ Cyrillic_o, Cyrillic_O	]	};
    key <AC05> {	[ Cyrillic_el, Cyrillic_EL	]	};
    key <AC06> {	[ Cyrillic_ve, Cyrillic_VE	]	};
    key <AC07> {	[ Cyrillic_en, Cyrillic_EN 	]	};
    key <AC08> {	[ Cyrillic_te, Cyrillic_TE	]	};
    key <AC09> {	[ Cyrillic_es, Cyrillic_ES	]	};
    key <AC10> {	[ Cyrillic_er, Cyrillic_ER	]	};
    key <AC11> {	[     comma,	period		]	};

    key <AB01> {	[ Cyrillic_shcha, Cyrillic_SHCHA	]	};
    key <AB02> {	[ Cyrillic_tse, Cyrillic_TSE	]	};
    key <AB03> {	[ Cyrillic_e, Cyrillic_E	]	};
    key <AB04> {	[ Cyrillic_yu, Cyrillic_YU	]	};
    key <AB05> {	[ Cyrillic_ef, Cyrillic_EF	]	};
    key <AB06> {	[ Cyrillic_ha, Cyrillic_HA	]	};
    key <AB07> {	[ Cyrillic_che, Cyrillic_CHE	]	};
    key <AB08> {	[ Cyrillic_zhe, Cyrillic_ZHE	]	};
    key <AB09> {	[ Cyrillic_shorti, Cyrillic_SHORTI	]	};
    key <AB10> {	[ Cyrillic_sha, Cyrillic_SHA	]	};

    key <BKSL> {	[ apostrophe,	quotedbl	]	};
    
    // End alphanumeric section

};

//   GNE         UGNVS, English

default partial alphanumeric_keys
xkb_symbols "basic" {

    name[Group1]= "GNE";

    // Alphanumeric section
    key <TLDE> {	[     grave,	asciitilde	]	};
    key <AE01> {	[	  1,	exclam 		]	};
    key <AE02> {	[	  2,	at		]	};
    key <AE03> {	[	  3,	numbersign	]	};
    key <AE04> {	[	  4,	dollar		]	};
    key <AE05> {	[	  5,	percent		]	};
    key <AE06> {	[	  6,	asciicircum	]	};
    key <AE07> {	[	  7,	ampersand	]	};
    key <AE08> {	[	  8,	asterisk	]	};
    key <AE09> {	[	  9,	parenleft	]	};
    key <AE10> {	[	  0,	parenright	]	};
    key <AE11> {	[     minus,	underscore	]	};
    key <AE12> {	[     equal,	plus		]	};

    key <AD01> {	[	  p,	P 		]	};
    key <AD02> {	[	  d,	D		]	};
    key <AD03> {	[	  m,	M		]	};
    key <AD04> {	[	  k,	K		]	};
    key <AD05> {	[	  z,	Z		]	};
    key <AD06> {	[	  b,	B		]	};
    key <AD07> {	[	  u,	U		]	};
    key <AD08> {	[	  q,	Q		]	};
    key <AD09> {	[	  x,	X		]	};
    key <AD10> {	[	  y,	Y		]	};
    key <AD11> {	[	  g,	G		]	};
    key <AD12> {	[     colon,	semicolon	]	};

    key <AC01> {	[	  a,	A 		]	};
    key <AC02> {	[	  i,	I		]	};
    key <AC03> {	[	  e,	E		]	};
    key <AC04> {	[	  o,	O		]	};
    key <AC05> {	[	  l,	L		]	};
    key <AC06> {	[	  v,	V		]	};
    key <AC07> {	[	  n,	N		]	};
    key <AC08> {	[	  t,	T		]	};
    key <AC09> {	[	  s,	S		]	};
    key <AC10> {	[ 	  r,	R		]	};
    key <AC11> {	[     comma,	period		]	};

    key <AB01> {	[ backslash,	bar 		]	};
    key <AB02> {	[	  c,	C		]	};
    key <AB03> {	[ bracketleft,	braceleft	]	};
    key <AB04> {	[ bracketright,	braceright	]	};
    key <AB05> {	[	  f,	F		]	};
    key <AB06> {	[	  h,	H		]	};
    key <AB07> {	[	  less,	greater		]	};
    key <AB08> {	[	  w,	W		]	};
    key <AB09> {	[	  j,	J		]	};
    key <AB10> {	[     slash,	question	]	};

    key <BKSL> {	[ apostrophe,	quotedbl	]	};
    
    // End alphanumeric section
};

  • Substitute 'GNR' with your layout short name in line name[Group1]= "GNR";

  • Edit key definitions.

Lines like key <AD01> { [ p, P ] }; are obvious enough. This particular line instructs that a press on <AD01> physical key will normally emit lower-case 'p' character. Upper-case character 'P' will be emitted when <AD01> will be pressed while <shift> physical key will be held down. <Shift> key is addressed as a modifier key.

Lines like key <AC03> { [ Cyrillic_ie, Cyrillic_IE, Cyrillic_io, Cyrillic_IO ] }; are not incomprehensible as well. This particular line instructs that a press on <AC03> physical key will normally emit lower-case 'Cyrillic_ie' character. Upper-case character 'Cyrillic_IE' will be emitted when <AC03> will be pressed while <shift> physical key will be held down. Similarly, a press on <AC03> physical key will emit 'Cyrillic_io' or 'Cyrillic_IO' depending on the <shift> key state provided that an extra modifier key will be held down. Such a modifier key is addressed as 3rd level chooser. You can select this extra modifier key according to your taste later in System > Preferences > Hardware > Keyboard > Options dialogue.

  • Copy your finished symbol file into /usr/share/X11/xkb/symbols directory.

  • Navigate to the directory /usr/share/X11/xkb/rules.

  • Open files base.lst and evdev.lst. They are identical and you have to edit both of them identically. Find ! layout line and insert your own layout definition, e.g. GNR UGNVS Russian below.

  • Open files evdev.xml and base.xml. They are identical and you have to edit both of them identically. Find <layoutList> line and insert your own layout definition below. For example:

    <layout>
      <configItem>
        <name>GNR</name>
        <shortDescription>GNR</shortDescription>
	  <description>UGNVS Russian</description>
        <languageList><iso639Id>rus</iso639Id></languageList>
      </configItem>
    </layout>

Please do not forget to enter the short name of your layout and its description instead of those provided in the example. Pay attention to correctly denote your language abbreviation as well.

  • Be warned however, that base.lst, evdev.lst, evdev.xml and base.xml may be sometimes overwritten during distribution version upgrades. As a result your keyboard layout may disappear from selection list.

  • Select and instantiate your new keyboard layout using System > Preferences > Hardware > Keyboard > Layouts > Add. Tip: search your layout by language.

Happy typing!

ugnvs

1 Like