鍵盤的 XKB client map 是 client 須要解析來自鍵盤的鍵事件所需的信息集合。它包含 key types 的全局列表,和 key symbol map s 數組,每一個 key symbol map 描述了綁定到一個特定鍵的 symbols 和用來解析這些 symbols 的規則。數組
XKB 將二維 symbols 數組與每一個鍵相關聯。symbols 由鍵盤 group 和 shift level 進行尋址,其中 level 的定義在 ISO9995標準爲:app
Level —— 幾種狀態中的一種(一般爲2或3),用於控制圖形鍵按下時產生的圖形字符。 在某些狀況下,level 也可能影響功能鍵。3d
請注意,shift level 是從 modifier state 派生的,但對於全部鍵不必定以相同的方式。例如,Shift modifier 在大多數鍵上選擇 shift level 2,但在小鍵盤鍵上此 modifier 綁定到 Num_Lock(即 NumLock 虛擬 modifier)也選擇 shift level 2。code
咱們使用符號 GnLn 來指定 symbol 在鍵或內存中的位置: blog
灰色字符表示暗示或預期的 symbols,但實際上沒有刻在鍵上。索引
注意事件
不幸的是,鍵上的 symbols 的「天然」方向和內存中的天然方向相反,所以鍵盤 group 指的是鍵上的一列和內存中的一行。對它沒有任何實際幫助,但咱們嘗試經過使用「group」和「level」(或「shift level」)來最小化混淆,以引用 symbols 而無論上下文。內存
要查找與 XKB 鍵事件關聯的 symbol,咱們須要知道事件對應的 group 和 shift level。it
Group 報告在鍵事件的 state 字段的 bits 13-14。事件中報告的鍵盤 group 可能超過特定鍵的範圍,由於 groups 的數量可因鍵而異。每一個鍵的 XKB 描述包含 group info 字段,該字段與全局 groups wrap control 的解釋相同,並指定對該鍵超出範圍的 group 的解釋。cli
一旦咱們肯定了要用於該事件的 group,咱們就必須肯定 shift level。鍵的描述包括綁定到該鍵的每組 symbols 的 key type。給定事件的 modifier,這個 key type 產出一個 shift level 和一組「剩餘」 modifiers,以下 鍵 Types 所述。
最後,咱們可使用有效 group 和該 group 的 type 返回的 shift level 去與該鍵相關聯的二維 symbols 數組中查找 symbol。
key type 的 map 字段的每一個 entry 指定某些 XKB modifier 定義相應的 shift level; 未在 map 中某處明確列出的 modifier 的任何組合產出 shifit level 1。 指定了未綁定的虛擬 modifiers(參見不活躍 Modifier 定義)的 Map entries 不被考慮; 每一個 entry 包含自動更新的 active 字段,指示是否應該使用它。
每一個 key type 包含一些從 map 的內容派生而來的字段,這些字段報告一些經常使用值,所以沒必要常常從新計算它們。numLevels 字段包含任何它的 map entries 報告的最高 shift level;XKB 使用 numLevels 來確保綁定到鍵的 symbols 數組足夠大(key type 報告的 numLevels 也稱爲其 width)。modifiers 字段報告由該 type 的任何 map entries 考慮的全部真實 modifiers。modifiers 和 numLevels 都由 XKB 自動更新,二者都不能顯式更改。
modifiers 字段中指定的任何 modifiers 一般都被使用(參見轉換與鍵事件關聯的KeySym),這意味着在事件處理的任何後續階段都不會考慮它們。 對於極少數狀況下,儘管已經習慣於查找 symbol,但仍應考慮 modifier,key type 包含一個可選的 preserve 字段。若是存在 preserve 列表,則每一個 entry 對應 key type 的 map entries 中的一個,而且列出若是匹配的 map entry 用於肯定 shift level 則不該消耗的 modifiers。
例如,如下 key type 實現核心協議定義的 caps Lock(使用綁定到鍵的第二個symbol):
type "ALPHABETIC" { modifiers = Shift+Lock; map[Shift]= Level2; map[Lock]= Level2; map[Shift+Lock]= Level2; };
這種定義的問題在於咱們能夠將徹底不相關的 symbols 分配給兩個 shift levels,且「Caps Lock」將選擇第二個 symbol。字母鍵的另外一個定義使用系統例程來大寫 keysym:
type "ALPHABETIC" { modifiers= Shift; map[Shift]= Level2; };
當使用此定義應用大寫鎖定時,咱們將從 shift level 1 獲取 symbol,並使用特定於系統的大寫規則對其進行大寫。若是設置 shift 和 caps lock,咱們將從 shift level 2 獲取 symbol,並嘗試大寫它,這一般沒有效果。Lock 不在 modifiers 字段中,所以它不會被消耗,而且能夠用於指示大寫變換。
如下 key type 爲字母鍵實現 shift-cancels-caps lock (shift 取消 caps lock)行爲:
type "ALPHABETIC" { modifiers = Shift+Lock; map[Shift] = Level2; preserve[Lock]= Lock; };
考慮可能影響字母鍵的四種可能狀態:無 modifiers、單獨 shift、單獨 caps lock 或 shift 和 caps lock 一塊兒。該 map 不包含 None (無 modifiers)的顯式 entry,所以若是未設置 modifiers,這種 type 的任何 group 返回第一個 keysym。Shift 的 map entry 報告 Level2,所以單獨設置 shift 時,這種 type 的任何 group 返回第二個 symbol。單獨 Lock 沒有 map entry,但 type 指定這種狀況下 Lock modifier 應該被保留,所以單獨 Lock 返回 group 中第一個 symbol,但首先應用大寫轉換,從而產生 symbol 的大寫體。在最後一種狀況下,Shift + Lock 沒有 map entry,所以它返回 group 中的第一個 symbol;沒有 preserve entry,所以 Lock modifier 被消耗而且 symbol 不是大寫體。
鍵的 key symbol map 包含 client 須要處理該鍵生成的事件的全部信息。每一個 key symbol mapping 報告:
鍵有 0 個 groups 是合法的,這種狀況下,它也具備 0 個 symbols,而且來自該鍵的全部事件都產生 NoSymbol。key types 數組具備固定寬度,而且足夠大以容納最大合法 groups 數量(MaxKbdGroups,當前爲 4)的 key types; 若是鍵有少於 MaxKbdGroups 個 groups,則額外的 key types 被報告但被忽略。groupsWidth 字段沒法顯式更改;每當更改綁定到鍵的 symbols 或 types 集時,它都會自動更新。
若是,當查找一個 symbol,有效鍵盤 group 超過了鍵的範圍, key symbol map 的 groupInfo 字段指定決定相應合法 group 的規則以下: