1<chapter id='Key_Event_Processing_in_the_Client'> 2<title>Key Event Processing in the Client</title> 3 4<para> 5The XKB <emphasis> 6client map</emphasis> 7 for a keyboard is the collection of information a client needs to interpret 8key events that come from that keyboard. It contains a global list of <emphasis> 9key types</emphasis> 10, described in <link linkend='Key_Types'>Key Types</link>, 11and an array of <emphasis> 12key symbol map</emphasis> 13s, each of which describes the symbols bound to one particular key and the 14rules to be used to interpret those symbols. 15</para> 16 17<sect1 id='Notation_and_Terminology'> 18<title>Notation and Terminology</title> 19 20<para> 21XKB associates a two-dimensional array of symbols with each key. Symbols are 22addressed by keyboard group (see <link linkend='Keyboard_State'> 23Keyboard State</link>) and shift level, where level is defined as in the 24ISO9995 standard: 25</para> 26 27<variablelist> 28 <varlistentry> 29 <term>Level</term> 30 <listitem> 31 <para> 32One of several states (normally 2 or 3) which govern which graphic 33character is produced when a graphic key is actuated. In certain cases the 34level may also affect function keys. 35 </para> 36 </listitem> 37 </varlistentry> 38</variablelist> 39 40<para> 41Note that shift level is derived from the modifier state, but not necessarily 42in the same way for all keys. For example, the <emphasis> 43Shift</emphasis> 44 modifier selects shift level 2 on most keys, but for keypad keys the modifier 45bound to <emphasis> 46Num_Lock</emphasis> 47 (i.e. the <emphasis> 48NumLock</emphasis> 49 virtual modifier) also selects shift level 2.gray symbols on a key 50</para> 51 52<para> 53We use the notation G<emphasis> 54n</emphasis> 55L<emphasis> 56n</emphasis> 57 to specify the position of a symbol on a key or in memory: 58</para> 59 60<mediaobject> 61 <imageobject> <imagedata format="SVG" fileref="XKBproto-6.svg"/> 62 </imageobject> 63 </mediaobject> 64 65 66<para> 67The gray characters indicate symbols that are implied or expected but are not 68actually engraved on the key. 69</para> 70 71<note><para>Unfortunately, the "natural" orientation of symbols on a key and 72the natural orientation in memory are reversed from one another, so keyboard 73group refers to a column on the key and a row in memory. There’s no real help 74for it, but we try to minimize confusion by using "group" and "level" (or 75"shift level") to refer to symbols regardless of context.</para></note> 76 77</sect1> 78<sect1 id='Determining_the_KeySym_Associated_with_a_Key_Event'> 79<title>Determining the KeySym Associated with a Key Event</title> 80 81<para> 82To look up the symbol associated with an XKB key event, we need to know the 83group and shift level that correspond to the event. 84</para> 85 86 87<para> 88Group is reported in bits 13-14 of the state field of the key event, as 89described in <link linkend='Computing_A_State_Field_from_an_XKB_State'>Computing A State 90Field from an XKB State</link>. The keyboard group reported in the event might 91be out-of-range for any particular key because the number of groups can vary 92from key to key. The XKB description of each key contains a <emphasis> 93group info</emphasis> 94 field which is interpreted identically to the global groups wrap control (see 95<link linkend='Computing_Effective_Modifier_and_Group'>Computing Effective Modifier and 96Group</link>) and which specifies the interpretation of groups that are 97out-of-range for that key. 98</para> 99 100 101<para> 102Once we have determined the group to be used for the event, we have to 103determine the shift level. The description of a key includes a <emphasis> 104key type</emphasis> 105 for each group of symbols bound to the key. Given the modifiers from the key 106event, this key type yields a shift level and a set of "leftover" modifiers, as 107described in <link linkend='Key_Types'>Key Types</link> 108below. 109</para> 110 111 112<para> 113Finally, we can use the effective group and the shift level returned by the 114type of that group to look up a symbol in a two-dimensional array of symbols 115associated with the key. 116</para> 117 118 119<sect2 id='Key_Types'> 120<title>Key Types</title> 121 122<para> 123Each entry of a key type’s <emphasis> 124map</emphasis> 125 field specifies the shift level that corresponds to some XKB modifier 126definition; any combination of modifiers that is not explicitly listed 127somewhere in the map yields shift level one. Map entries which specify unbound 128virtual modifiers (see <link linkend='Inactive_Modifier_Definitions'>Inactive 129Modifier Definitions</link>) are not considered; each entry contains an 130automatically-updated <emphasis> 131active</emphasis> 132 field which indicates whether or not it should be used. 133</para> 134 135 136<para> 137Each key type includes a few fields that are derived from the contents of the 138map and which report some commonly used values so they don’t have to be 139constantly recalculated. The <emphasis> 140numLevels</emphasis> 141 field contains the highest shift level reported by any of its map entries; XKB 142uses <emphasis> 143numLevels</emphasis> 144 to insure that the array of symbols bound to a key is large enough (the number 145of levels reported by a key type is also referred to as its width). The 146<emphasis> 147modifiers</emphasis> 148 field reports all real modifiers considered by any of the map entries for the 149type. Both <emphasis> 150modifiers</emphasis> 151<emphasis> 152 </emphasis> 153and <emphasis> 154numLevels</emphasis> 155 are updated automatically by XKB and neither can be changed explicitly. 156</para> 157 158 159<para> 160Any modifiers specified in <emphasis> 161modifiers</emphasis> 162 are normally <emphasis> 163consumed</emphasis> 164 (see <link linkend='Transforming_the_KeySym_Associated_with_a_Key_Event'>Transforming the KeySym 165Associated with a Key Event</link>), which means that they are not considered 166during any of the later stages of event processing. For those rare occasions 167that a modifier <emphasis> 168should</emphasis> 169 be considered despite having been used to look up a symbol, key types include 170an optional <emphasis> 171preserve</emphasis> 172 field. If a <emphasis> 173preserve</emphasis> 174 list is present, each entry corresponds to one of the key type’s map entries 175and lists the modifiers that should <emphasis> 176not</emphasis> 177 be consumed if the matching map entry is used to determine shift level. 178</para> 179 180 181<para> 182For example, the following key type implements caps lock as defined by the core 183protocol (using the second symbol bound to the key): 184</para> 185 186<literallayout class='monospaced'> 187type "ALPHABETIC" { 188 modifiers = Shift+Lock; 189 map[Shift]= Level2; 190 map[Lock]= Level2; 191 map[Shift+Lock]= Level2; 192}; 193</literallayout> 194 195<para> 196The problem with this kind of definition is that we could assign completely 197unrelated symbols to the two shift levels, and "Caps Lock" would choose the 198second symbol. Another definition for alphabetic keys uses system routines to 199capitalize the keysym: 200</para> 201 202<literallayout class='monospaced'> 203type "ALPHABETIC" { 204 modifiers= Shift; 205 map[Shift]= Level2; 206}; 207</literallayout> 208 209<para> 210When caps lock is applied using this definition, we take the symbol from shift 211level one and capitalize it using system-specific capitalization rules. If 212shift and caps lock are both set, we take the symbol from shift level two and 213try to capitalize it, which usually has no effect. 214</para> 215 216 217<para> 218The following key type implements shift-cancels-caps lock behavior for 219alphabetic keys: 220</para> 221 222<literallayout class='monospaced'> 223type "ALPHABETIC" { 224 modifiers = Shift+Lock; 225 map[Shift] = Level2; 226 preserve[Lock]= Lock; 227}; 228</literallayout> 229 230<para> 231Consider the four possible states that can affect alphabetic keys: no 232modifiers, shift alone, caps lock alone or shift and caps lock together. The 233map contains no explicit entry for <emphasis> 234None</emphasis> 235 (no modifiers), so if no modifiers are set, any group with this type returns 236the first keysym. The map entry for <emphasis> 237Shift</emphasis> 238 reports <emphasis> 239Level2</emphasis> 240, so any group with this type returns the second symbol when <emphasis> 241Shift</emphasis> 242 is set. There is no map entry for <emphasis> 243Lock</emphasis> 244 alone, but the type specifies that the <emphasis> 245Lock</emphasis> 246 modifier should be preserved in this case, so <emphasis> 247Lock</emphasis> 248 alone returns the first symbol in the group but first applies the 249capitalization transformation, yielding the capital form of the symbol. In the 250final case, there is no map entry for <emphasis> 251Shift+Lock</emphasis> 252, so it returns the first symbol in the group; there is no preserve entry, so 253the <emphasis> 254Lock</emphasis> 255 modifier is consumed and the symbol is not capitalized. 256</para> 257 258 259</sect2> 260<sect2 id='Key_Symbol_Map'> 261<title>Key Symbol Map</title> 262 263<para> 264The <emphasis> 265key symbol map</emphasis> 266 for a key contains all of the information that a client needs to process 267events generated by that key. Each key symbol mapping reports: 268</para> 269 270<itemizedlist> 271<listitem> 272 <para>The number of groups of symbols bound to the key (<emphasis> 273numGroups</emphasis> 274). 275 </para> 276</listitem> 277<listitem> 278 <para>The treatment of out-of-range groups (<emphasis> 279groupInfo</emphasis> 280). 281 </para> 282</listitem> 283<listitem> 284 <para>The index of the key type to for each <emphasis> 285possible</emphasis> 286 group (<emphasis> 287kt_index[MaxKbdGroups]</emphasis> 288). 289 </para> 290</listitem> 291<listitem> 292 <para>The width of the widest type associated with the key (<emphasis> 293groupsWidth</emphasis> 294). 295 </para> 296</listitem> 297<listitem> 298 <para>The two-dimensional (numGroups <emphasis> 299×</emphasis> 300 groupsWidth) array of symbols bound to the key. 301 </para> 302</listitem> 303</itemizedlist> 304 305<para> 306It is legal for a key to have zero groups, in which case it also has zero 307symbols and all events from that key yield <emphasis> 308NoSymbol</emphasis> 309. The array of key types is of fixed width and is large enough to hold key 310types for the maximum legal number of groups (<emphasis> 311MaxKbdGroups</emphasis> 312, currently four); if a key has fewer than <emphasis> 313MaxKbdGroups</emphasis> 314 groups, the extra key types are reported but ignored. The <emphasis> 315groupsWidth</emphasis> 316 field cannot be explicitly changed; it is updated automatically whenever the 317symbols or set of types bound to a key are changed. 318</para> 319 320 321<para> 322If, when looking up a symbol, the effective keyboard group is out-of-range for 323the key, the <emphasis> 324groupInfo</emphasis> 325 field of the key symbol map specifies the rules for determining the 326corresponding legal group as follows: 327</para> 328 329<itemizedlist> 330<listitem> 331 <para>If the <emphasis> 332RedirectIntoRange</emphasis> 333 flag is set, the two least significant bits of <emphasis> 334groupInfo</emphasis> 335 specify the index of a group to which all illegal groups correspond. If the 336specified group is also out of range, all illegal groups map to <emphasis> 337Group1</emphasis> 338. 339 </para> 340</listitem> 341<listitem> 342 <para>If <emphasis> 343ClampIntoRange</emphasis> 344 flag is set, out-of-range groups correspond to the nearest legal group. 345Effective groups larger than the highest supported group are mapped to the 346highest supported group; effective groups less than <emphasis> 347Group1</emphasis> 348 are mapped to <emphasis> 349Group1</emphasis> 350. For example, a key with two groups of symbols uses <emphasis> 351Group2</emphasis> 352 type and symbols if the global effective group is either <emphasis> 353Group3</emphasis> 354 or <emphasis> 355Group4</emphasis> 356. 357 </para> 358</listitem> 359<listitem> 360 <para>If neither flag is set, group is wrapped into range using integer 361modulus. For example, a key with two groups of symbols for which groups wrap 362uses <emphasis> 363Group1</emphasis> 364 symbols if the global effective group is <emphasis> 365Group3</emphasis> 366 or <emphasis> 367Group2</emphasis> 368 symbols if the global effective group is <emphasis> 369Group4</emphasis> 370. 371 </para> 372</listitem> 373</itemizedlist> 374 375<para> 376The client map contains an array of key symbol mappings, with one entry for 377each key between the minimum and maximum legal keycodes, inclusive. All 378keycodes which fall in that range have key symbol mappings, whether or not any 379key actually yields that code. 380</para> 381 382 383</sect2> 384</sect1> 385<sect1 id='Transforming_the_KeySym_Associated_with_a_Key_Event'> 386<title>Transforming the KeySym Associated with a Key Event</title> 387 388<para> 389Any modifiers that were not used to look up the keysym, or which were 390explicitly preserved, might indicate further transformations to be performed on 391the keysym or the character string that is derived from it. For example, If the 392<emphasis> 393Lock</emphasis> 394 modifier is set, the symbol and corresponding string should be capitalized 395according to the locale-sensitive capitalization rules specified by the system. 396If the <emphasis> 397Control</emphasis> 398 modifier is set, the keysym is not affected, but the corresponding character 399should be converted to a control character as described in <link 400linkend="default_symbol_transformations">Default Symbol Transformations</link>. 401</para> 402 403 404<para> 405This extension specifies the transformations to be applied when the <emphasis> 406Control</emphasis> 407 or <emphasis> 408Lock</emphasis> 409 modifiers are active but were not used to determine the keysym to be used: 410</para> 411 412<informaltable frame='topbot'> 413<?dbfo keep-together="always" ?> 414<tgroup cols='2' align='left' colsep='0' rowsep='0'> 415<colspec colname='c1' colwidth='1.0*'/> 416<colspec colname='c2' colwidth='3.0*'/> 417<thead> 418 <row rowsep='1'> 419 <entry>Modifier</entry> 420 <entry>Transformation</entry> 421 </row> 422</thead> 423<tbody> 424 <row> 425 <entry><emphasis> 426Control</emphasis> 427 </entry> 428 <entry>Report the control character associated with the symbol. This 429extension defines the control characters associated with the ASCII alphabetic 430characters (both upper and lower case) and for a small set of punctuation 431characters (see 432<link linkend="default_symbol_transformations">Default Symbol Transformations</link>). 433Applications are 434free to associate control characters with any symbols that are not specified by 435this extension.</entry> 436 </row> 437 <row> 438 <entry><emphasis> 439Lock</emphasis> 440 </entry> 441 <entry>Capitalize the symbol either according to capitalization rules 442appropriate to the application locale or using the capitalization rules defined 443by this extension (see <link linkend="default_symbol_transformations">Default Symbol Transformations</link>).</entry> 444 </row> 445</tbody> 446</tgroup> 447</informaltable> 448 449<para> 450Interpretation of other modifiers is application dependent. 451</para> 452 453<note><para>This definition of capitalization is fundamentally different from 454the core protocol’s, which uses the lock modifier to select from the symbols 455bound to the key. Consider key 9 in the 456<link linkend='Client_Map_Example'>client map example</link>; 457the core protocol provides no way to generate the capital form 458of either symbol bound to this key. XKB specifies that we first look up the 459symbol and then capitalize, so XKB yields the capital form of the two symbols 460when caps lock is active. </para></note> 461 462<para> 463XKB specifies the behavior of <emphasis> 464Lock</emphasis> 465 and <emphasis> 466Control</emphasis> 467, but interpretation of other modifiers is left to the application. 468</para> 469 470 471</sect1> 472<sect1 id='Client_Map_Example'> 473<title>Client Map Example</title> 474 475<para> 476Consider a simple, if unlikely, keyboard with the following keys (gray 477characters indicate symbols that are implied or expected but are not actually 478engraved on the key): 479</para> 480 481<mediaobject> 482 <imageobject> <imagedata format="SVG" fileref="XKBproto-7.svg"/> 483 </imageobject> 484 </mediaobject> 485 486 487<para> 488The core protocol represents this keyboard as a simple array with one row per 489key and four columns (the widest key, key 10, determines the width of the 490entire array). 491</para> 492 493<informaltable frame='topbot'> 494<?dbfo keep-together="always" ?> 495<tgroup cols='5' align='left' colsep='0' rowsep='0'> 496<colspec colname='c1' colwidth='1.0*'/> 497<colspec colname='c2' colwidth='2.0*'/> 498<colspec colname='c3' colwidth='2.0*'/> 499<colspec colname='c4' colwidth='2.0*'/> 500<colspec colname='c5' colwidth='2.0*'/> 501<thead> 502 <row rowsep='1'> 503 <entry>Key</entry> 504 <entry>G1L1</entry> 505 <entry>G1L2</entry> 506 <entry>G2L1</entry> 507 <entry>G2L2</entry> 508 </row> 509</thead> 510<tbody> 511 <row> 512 <entry>8</entry> 513 <entry>Q</entry> 514 <entry>NoSymbol</entry> 515 <entry>at</entry> 516 <entry>NoSymbol</entry> 517 </row> 518 <row> 519 <entry>9</entry> 520 <entry>odiaeresis</entry> 521 <entry>egrave</entry> 522 <entry>NoSymbol</entry> 523 <entry>NoSymbol</entry> 524 </row> 525 <row> 526 <entry>10</entry> 527 <entry>A</entry> 528 <entry>NoSymbol</entry> 529 <entry>Æ</entry> 530 <entry>NoSymbol</entry> 531 </row> 532 <row> 533 <entry>11</entry> 534 <entry>ssharp</entry> 535 <entry>question</entry> 536 <entry>backslash</entry> 537 <entry>questiondown</entry> 538 </row> 539 <row> 540 <entry>12</entry> 541 <entry>KP_End</entry> 542 <entry>KP_1</entry> 543 <entry>NoSymbol</entry> 544 <entry>NoSymbol</entry> 545 </row> 546 <row> 547 <entry>13</entry> 548 <entry>Num_Lock</entry> 549 <entry>NoSymbol</entry> 550 <entry>NoSymbol</entry> 551 <entry>NoSymbol</entry> 552 </row> 553 <row> 554 <entry>14</entry> 555 <entry>NoSymbol</entry> 556 <entry>NoSymbol</entry> 557 <entry>NoSymbol</entry> 558 <entry>NoSymbol</entry> 559 </row> 560 <row> 561 <entry>15</entry> 562 <entry>Return</entry> 563 <entry>NoSymbol</entry> 564 <entry>NoSymbol</entry> 565 <entry>NoSymbol</entry> 566 </row> 567</tbody> 568</tgroup> 569</informaltable> 570 571<para> 572The row to be used for a given key event is determined by keycode; the column 573to be used is determined by the symbols bound to the key, the state of the 574<emphasis> 575Shift</emphasis> 576 and <emphasis> 577Lock</emphasis> 578 Modifiers and the state of the modifiers bound to the <emphasis> 579Num_Lock</emphasis> 580 and <emphasis> 581Mode_switch</emphasis> 582 keys as specified by the core protocol. 583</para> 584 585 586<para> 587The XKB description of this keyboard consists of six key symbol maps, each of 588which specifies the types and symbols associated with each keyboard group for 589one key: 590</para> 591 592<informaltable frame='topbot'> 593<?dbfo keep-together="always" ?> 594<tgroup cols='4' align='left' colsep='0' rowsep='0'> 595<colspec colname='c1' colwidth='1.0*'/> 596<colspec colname='c2' colwidth='1.0*'/> 597<colspec colname='c3' colwidth='1.0*'/> 598<colspec colname='c4' colwidth='1.0*'/> 599<thead> 600 <row rowsep='1'> 601 <entry>Key</entry> 602 <entry>Group: Type</entry> 603 <entry>L1</entry> 604 <entry>L2</entry> 605 </row> 606</thead> 607<tbody> 608 <row> 609 <entry>8</entry> 610 <entry>G1: ALPHABETIC</entry> 611 <entry>q</entry> 612 <entry>Q</entry> 613 </row> 614 <row> 615 <entry>G2: ONE_LEVEL</entry> 616 <entry>@</entry> 617 <entry>NoSymbol</entry> 618 </row> 619 <row> 620 <entry>9</entry> 621 <entry>G1: TWO_LEVEL</entry> 622 <entry>odiaeresis</entry> 623 <entry>egrave</entry> 624 </row> 625 <row> 626 <entry>10</entry> 627 <entry>G1: ALPHABETIC</entry> 628 <entry>a</entry> 629 <entry>A</entry> 630 </row> 631 <row> 632 <entry>G2: ALPHABETIC</entry> 633 <entry>ae</entry> 634 <entry>AE</entry> 635 </row> 636 <row> 637 <entry>11</entry> 638 <entry>G1: TWO_LEVEL</entry> 639 <entry>ssharp</entry> 640 <entry>question</entry> 641 </row> 642 <row> 643 <entry>G2: ONE_LEVEL</entry> 644 <entry>backslash</entry> 645 <entry>questiondown</entry> 646 </row> 647 <row> 648 <entry>12</entry> 649 <entry>G1: KEYPAD</entry> 650 <entry>KP_End</entry> 651 <entry>KP_1</entry> 652 </row> 653 <row> 654 <entry>13</entry> 655 <entry>G1: ONE_LEVEL</entry> 656 <entry>Num_Lock</entry> 657 <entry> </entry> 658 </row> 659 <row> 660 <entry>14</entry> 661 <entry>No Groups</entry> 662 <entry> </entry> 663 <entry> </entry> 664 </row> 665 <row> 666 <entry>15</entry> 667 <entry>G1: ONE_LEVEL</entry> 668 <entry>Return</entry> 669 <entry> </entry> 670 </row> 671</tbody> 672</tgroup> 673</informaltable> 674 675<para> 676The keycode reported in a key event determines the row to be used for that 677event; the effective keyboard group determines the list of symbols and key type 678to be used. The key type determines which symbol is chosen from the list. 679</para> 680 681 682<para> 683<link linkend='Determining_the_KeySym_Associated_with_a_Key_Event'>Determining the KeySym Associated 684with a Key Event</link> details the procedure to map from a key event to a 685symbol and/or a string. 686</para> 687</sect1> 688</chapter> 689