ch07.xml revision e9fcaa8a
1e9fcaa8aSmrg<chapter id='virtual_modifiers'>
2e9fcaa8aSmrg<title>Virtual Modifiers</title>
3e9fcaa8aSmrg
4e9fcaa8aSmrg<para>
5e9fcaa8aSmrgThe core protocol specifies that certain keysyms, when bound to modifiers,
6e9fcaa8aSmrgaffect the rules of keycode to keysym interpretation for all keys; for example,
7e9fcaa8aSmrgwhen the <emphasis>
8e9fcaa8aSmrgNum_Lock</emphasis>
9e9fcaa8aSmrg keysym is bound to some modifier, that modifier is used to select between
10e9fcaa8aSmrgshifted and unshifted state for the numeric keypad keys. The core protocol does
11e9fcaa8aSmrgnot provide a convenient way to determine the mapping of modifier bits (in
12e9fcaa8aSmrgparticular <emphasis>
13e9fcaa8aSmrgMod1</emphasis>
14e9fcaa8aSmrg through <emphasis>
15e9fcaa8aSmrgMod5</emphasis>
16e9fcaa8aSmrg) to keysyms such as <emphasis>
17e9fcaa8aSmrgNum_Lock</emphasis>
18e9fcaa8aSmrg and <emphasis>
19e9fcaa8aSmrgMode_switch</emphasis>
20e9fcaa8aSmrg. Using the core protocol only, a client application must retrieve and search
21e9fcaa8aSmrgthe modifier map to determine the keycodes bound to each modifier, and then
22e9fcaa8aSmrgretrieve and search the keyboard mapping to determine the keysyms bound to the
23e9fcaa8aSmrgkeycodes. It must repeat this process for all modifiers whenever any part of
24e9fcaa8aSmrgthe modifier mapping is changed.
25e9fcaa8aSmrg</para>
26e9fcaa8aSmrg
27e9fcaa8aSmrg
28e9fcaa8aSmrg<para>
29e9fcaa8aSmrgXkb alleviates these problems by defining virtual modifiers. In addition to the
30e9fcaa8aSmrgeight core modifiers, referred to as the <emphasis>
31e9fcaa8aSmrgreal modifiers</emphasis>
32e9fcaa8aSmrg, Xkb provides a set of sixteen named <emphasis>
33e9fcaa8aSmrgvirtual modifiers</emphasis>
34e9fcaa8aSmrg. Each virtual modifier can be bound to any set of the real modifiers
35e9fcaa8aSmrg(<emphasis>
36e9fcaa8aSmrgShift</emphasis>
37e9fcaa8aSmrg, <emphasis>
38e9fcaa8aSmrgLock</emphasis>
39e9fcaa8aSmrg, <emphasis>
40e9fcaa8aSmrgControl,</emphasis>
41e9fcaa8aSmrg and <emphasis>
42e9fcaa8aSmrgMod1</emphasis>
43e9fcaa8aSmrg-<emphasis>
44e9fcaa8aSmrgMod5</emphasis>
45e9fcaa8aSmrg).
46e9fcaa8aSmrg</para>
47e9fcaa8aSmrg
48e9fcaa8aSmrg
49e9fcaa8aSmrg<para>
50e9fcaa8aSmrgThe separation of function from physical modifier bindings makes it easier to
51e9fcaa8aSmrgspecify more clearly the intent of a binding. X servers do not all assign
52e9fcaa8aSmrgmodifiers the same way — for example, <emphasis>
53e9fcaa8aSmrgNum_Lock</emphasis>
54e9fcaa8aSmrg might be bound to <emphasis>
55e9fcaa8aSmrgMod2</emphasis>
56e9fcaa8aSmrg for one vendor and to <emphasis>
57e9fcaa8aSmrgMod4</emphasis>
58e9fcaa8aSmrg for another. This makes it cumbersome to automatically remap the keyboard to a
59e9fcaa8aSmrgdesired configuration without some kind of prior knowledge about the keyboard
60e9fcaa8aSmrglayout and bindings. With XKB, applications can use virtual modifiers to
61e9fcaa8aSmrgspecify the desired behavior, without regard for the actual physical bindings
62e9fcaa8aSmrgin effect.
63e9fcaa8aSmrg</para>
64e9fcaa8aSmrg
65e9fcaa8aSmrg<sect1 id='virtual_modifier_names_and_masks'>
66e9fcaa8aSmrg<title>Virtual Modifier Names and Masks</title>
67e9fcaa8aSmrg
68e9fcaa8aSmrg<para>
69e9fcaa8aSmrgVirtual modifiers are named by converting their string name to an X <emphasis>
70e9fcaa8aSmrgAtom</emphasis>
71e9fcaa8aSmrg and storing the Atom in the <emphasis>
72e9fcaa8aSmrgnames.vmods</emphasis>
73e9fcaa8aSmrg array in an <emphasis>
74e9fcaa8aSmrgXkbDescRec</emphasis>
75e9fcaa8aSmrg structure (see section 6.1). The position of a name Atom in the <emphasis>
76e9fcaa8aSmrgnames.vmods</emphasis>
77e9fcaa8aSmrg array defines the bit position used to represent the virtual modifier and also
78e9fcaa8aSmrgthe index used when accessing virtual modifier information in arrays: the name
79e9fcaa8aSmrgin the i-th (0 relative) entry of <emphasis>
80e9fcaa8aSmrgnames.vmods</emphasis>
81e9fcaa8aSmrg is the i-th virtual modifier, represented by the mask (1&lt;&lt;i). Throughout
82e9fcaa8aSmrgXkb, various functions have a parameter that is a mask representing virtual
83e9fcaa8aSmrgmodifier choices. In each case, the i-th bit (0 relative) of the mask
84e9fcaa8aSmrgrepresents the i-th virtual modifier.
85e9fcaa8aSmrg</para>
86e9fcaa8aSmrg
87e9fcaa8aSmrg
88e9fcaa8aSmrg<para>
89e9fcaa8aSmrgTo set the name of a virtual modifier, use <emphasis>
90e9fcaa8aSmrgXkbSetNames</emphasis>
91e9fcaa8aSmrg, using <emphasis>
92e9fcaa8aSmrgXkbVirtualModNamesMask</emphasis>
93e9fcaa8aSmrg in <emphasis>
94e9fcaa8aSmrgwhich</emphasis>
95e9fcaa8aSmrg and the name in the <emphasis>
96e9fcaa8aSmrgxkb</emphasis>
97e9fcaa8aSmrg argument; to retrieve indicator names, use <emphasis>
98e9fcaa8aSmrgXkbGetNames</emphasis>
99e9fcaa8aSmrg. These functions are discussed in Chapter 18.
100e9fcaa8aSmrg</para>
101e9fcaa8aSmrg
102e9fcaa8aSmrg
103e9fcaa8aSmrg</sect1>
104e9fcaa8aSmrg<sect1 id='modifier_definitions'>
105e9fcaa8aSmrg<title>Modifier Definitions</title>
106e9fcaa8aSmrg
107e9fcaa8aSmrg<para>
108e9fcaa8aSmrgAn Xkb<emphasis>
109e9fcaa8aSmrg modifier definition</emphasis>
110e9fcaa8aSmrg enumerates a collection of real and virtual modifiers but does not in itself
111e9fcaa8aSmrgbind those modifiers to any particular key or to each other. Modifier
112e9fcaa8aSmrgdefinitions are included in a number of structures in the keyboard description
113e9fcaa8aSmrgto define the collection of modifiers that affect or are affected by some other
114e9fcaa8aSmrgentity. A modifier definition is relevant only in the context of some other
115e9fcaa8aSmrgentity such as an indicator map, a control, or a key type. (See sections 8.2.2,
116e9fcaa8aSmrg10.8, and 15.2.) <!-- xref -->
117e9fcaa8aSmrg</para>
118e9fcaa8aSmrg
119e9fcaa8aSmrg<para><programlisting>
120e9fcaa8aSmrgtypedef struct _XkbMods {
121e9fcaa8aSmrg      unsigned char            mask;            /* real_mods | vmods mapped to
122e9fcaa8aSmrgreal modifiers */
123e9fcaa8aSmrg      unsigned char            real_mods;            /* real modifier bits */
124e9fcaa8aSmrg      unsigned short             vmods;            /* virtual modifier bits */
125e9fcaa8aSmrg} <emphasis>
126e9fcaa8aSmrgXkbModsRec</emphasis>
127e9fcaa8aSmrg,*XkbModsPtr;
128e9fcaa8aSmrg</programlisting></para>
129e9fcaa8aSmrg
130e9fcaa8aSmrg<para>
131e9fcaa8aSmrgAn Xkb modifier definition consists of a set of bit masks corresponding to the
132e9fcaa8aSmrgeight real modifiers (<emphasis>
133e9fcaa8aSmrgreal_mods</emphasis>
134e9fcaa8aSmrg); a similar set of bitmasks corresponding to the 16 named virtual modifiers
135e9fcaa8aSmrg(<emphasis>
136e9fcaa8aSmrgvmods</emphasis>
137e9fcaa8aSmrg); and an effective mask (<emphasis>
138e9fcaa8aSmrgmask</emphasis>
139e9fcaa8aSmrg). The effective mask represents the set of all real modifiers that can
140e9fcaa8aSmrglogically be set either by setting any of the real modifiers or by setting any
141e9fcaa8aSmrgof the virtual modifiers in the definition. <emphasis>
142e9fcaa8aSmrgmask</emphasis>
143e9fcaa8aSmrg is derived from the real and virtual modifiers and should never be explicitly
144e9fcaa8aSmrgchanged — it contains all of the real modifiers specified in the definition
145e9fcaa8aSmrg(<emphasis>
146e9fcaa8aSmrgreal_mods</emphasis>
147e9fcaa8aSmrg)<emphasis>
148e9fcaa8aSmrg plus</emphasis>
149e9fcaa8aSmrg any real modifiers that are bound to the virtual modifiers specified in the
150e9fcaa8aSmrgdefinition (<emphasis>
151e9fcaa8aSmrgvmods</emphasis>
152e9fcaa8aSmrg). The binding of the virtual modifiers to real modifiers is exterior to the
153e9fcaa8aSmrgmodifier definition. Xkb automatically recomputes the mask field of modifier
154e9fcaa8aSmrgdefinitions as necessary. Whenever you access a modifier definition that has
155e9fcaa8aSmrgbeen retrieved using an Xkb library function, the mask field will be correct
156e9fcaa8aSmrgfor the keyboard mapping of interest.
157e9fcaa8aSmrg</para>
158e9fcaa8aSmrg
159e9fcaa8aSmrg
160e9fcaa8aSmrg</sect1>
161e9fcaa8aSmrg<sect1 id='binding_virtual_modifiers_to_real_modifiers'>
162e9fcaa8aSmrg<title>Binding Virtual Modifiers to Real Modifiers</title>
163e9fcaa8aSmrg
164e9fcaa8aSmrg<para>
165e9fcaa8aSmrgThe binding of virtual modifiers to real modifiers is defined by the <emphasis>
166e9fcaa8aSmrgserver.vmods</emphasis>
167e9fcaa8aSmrg array in an <emphasis>
168e9fcaa8aSmrgXkbDescRec</emphasis>
169e9fcaa8aSmrg structure. Each entry contains the real modifier bits that are bound to the
170e9fcaa8aSmrgvirtual modifier corresponding to the entry. The overall relationship of fields
171e9fcaa8aSmrgdealing with virtual modifiers in the server keyboard description are shown in
172e9fcaa8aSmrgFigure 16.2. <!-- xref -->
173e9fcaa8aSmrg</para>
174e9fcaa8aSmrg
175e9fcaa8aSmrg
176e9fcaa8aSmrg</sect1>
177e9fcaa8aSmrg<sect1 id='virtual_modifier_key_mapping'>
178e9fcaa8aSmrg<title>Virtual Modifier Key Mapping</title>
179e9fcaa8aSmrg
180e9fcaa8aSmrg<para>
181e9fcaa8aSmrgXkb maintains a <emphasis>
182e9fcaa8aSmrgvirtual modifier mapping</emphasis>
183e9fcaa8aSmrg, which lists the virtual modifiers associated with, or bound to, each key. The
184e9fcaa8aSmrgreal modifiers bound to a virtual modifier always include all of the modifiers
185e9fcaa8aSmrgbound to any of the keys that specify that virtual modifier in their virtual
186e9fcaa8aSmrgmodifier mapping. The <emphasis>
187e9fcaa8aSmrgserver.vmodmap</emphasis>
188e9fcaa8aSmrg array indicates which virtual modifiers are bound to each key; each entry is a
189e9fcaa8aSmrgbitmask for the virtual modifier bits. The <emphasis>
190e9fcaa8aSmrgserver.vmodmap</emphasis>
191e9fcaa8aSmrg array is indexed by keycode.
192e9fcaa8aSmrg</para>
193e9fcaa8aSmrg
194e9fcaa8aSmrg
195e9fcaa8aSmrg<para>
196e9fcaa8aSmrgThe <emphasis>
197e9fcaa8aSmrgvmodmap</emphasis>
198e9fcaa8aSmrg and <emphasis>
199e9fcaa8aSmrgvmods</emphasis>
200e9fcaa8aSmrg members of the server map are the "master" virtual modifier definitions. Xkb
201e9fcaa8aSmrgautomatically propagates any changes to these fields to all other fields that
202e9fcaa8aSmrguse virtual modifier mappings (see section 16.4).
203e9fcaa8aSmrg</para>
204e9fcaa8aSmrg
205e9fcaa8aSmrg
206e9fcaa8aSmrg<para>
207e9fcaa8aSmrgFor example, if <emphasis>
208e9fcaa8aSmrgMod3</emphasis>
209e9fcaa8aSmrg is bound to the <emphasis>
210e9fcaa8aSmrgNum_Lock</emphasis>
211e9fcaa8aSmrg key by the core protocol modifier mapping, and the <emphasis>
212e9fcaa8aSmrgNumLock</emphasis>
213e9fcaa8aSmrg virtual modifier is bound to they <emphasis>
214e9fcaa8aSmrgNum_Lock</emphasis>
215e9fcaa8aSmrg key by the virtual modifier mapping, <emphasis>
216e9fcaa8aSmrgMod3</emphasis>
217e9fcaa8aSmrg is added to the set of modifiers associated with <emphasis>
218e9fcaa8aSmrgNumLock</emphasis>
219e9fcaa8aSmrg.
220e9fcaa8aSmrg</para>
221e9fcaa8aSmrg
222e9fcaa8aSmrg
223e9fcaa8aSmrg<para>
224e9fcaa8aSmrgThe virtual modifier mapping is normally updated whenever actions are
225e9fcaa8aSmrgautomatically applied to symbols (see section 16.4 for details), and few
226e9fcaa8aSmrgapplications should need to change the virtual modifier mapping explicitly.
227e9fcaa8aSmrg</para>
228e9fcaa8aSmrg
229e9fcaa8aSmrg
230e9fcaa8aSmrg<para>
231e9fcaa8aSmrgUse <emphasis>
232e9fcaa8aSmrgXkbGetMap </emphasis>
233e9fcaa8aSmrg(see section 14.2) to get the virtual modifiers from the server or use  <!-- xref -->
234e9fcaa8aSmrg<emphasis>
235e9fcaa8aSmrgXkbGetVirtualMods</emphasis>
236e9fcaa8aSmrg (see section 16.4.1) to update a local copy of the virtual modifiers bindings  <!-- xref -->
237e9fcaa8aSmrgfrom the server. To set the binding of a virtual modifier to a real modifier,
238e9fcaa8aSmrguse <emphasis>
239e9fcaa8aSmrgXkbSetMap</emphasis>
240e9fcaa8aSmrg (see<emphasis>
241e9fcaa8aSmrg </emphasis>
242e9fcaa8aSmrgsection 14.3<emphasis> <!-- xref -->
243e9fcaa8aSmrg).</emphasis>
244e9fcaa8aSmrg</para>
245e9fcaa8aSmrg
246e9fcaa8aSmrg
247e9fcaa8aSmrg<para>
248e9fcaa8aSmrgTo determine the mapping of virtual modifiers to core X protocol modifiers, use
249e9fcaa8aSmrg<emphasis>
250e9fcaa8aSmrgXkbVirtualModsToReal</emphasis>
251e9fcaa8aSmrg.
252e9fcaa8aSmrg</para>
253e9fcaa8aSmrg
254e9fcaa8aSmrg<informaltable frame='none'>
255e9fcaa8aSmrg<tgroup cols='1'>
256e9fcaa8aSmrg<colspec colsep='0'/>
257e9fcaa8aSmrg<tbody>
258e9fcaa8aSmrg  <row rowsep='0'>
259e9fcaa8aSmrg    <entry role='functiondecl'>
260e9fcaa8aSmrgBool <emphasis>
261e9fcaa8aSmrgXkbVirtualModsToReal</emphasis>
262e9fcaa8aSmrg(<emphasis>
263e9fcaa8aSmrgxkb, virtual_mask, mask_rtrn</emphasis>
264e9fcaa8aSmrg)
265e9fcaa8aSmrg    </entry>
266e9fcaa8aSmrg  </row>
267e9fcaa8aSmrg  <row rowsep='0'>
268e9fcaa8aSmrg    <entry role='functionargdecl'>
269e9fcaa8aSmrgXkbDescPtr <emphasis>
270e9fcaa8aSmrg            xkb</emphasis>
271e9fcaa8aSmrg;            /* keyboard description for input device */
272e9fcaa8aSmrg    </entry>
273e9fcaa8aSmrg  </row>
274e9fcaa8aSmrg  <row rowsep='0'>
275e9fcaa8aSmrg    <entry role='functionargdecl'>
276e9fcaa8aSmrgunsigned int<emphasis>
277e9fcaa8aSmrg            virtual_mask</emphasis>
278e9fcaa8aSmrg;            /* virtual modifier mask to translate */
279e9fcaa8aSmrg    </entry>
280e9fcaa8aSmrg  </row>
281e9fcaa8aSmrg  <row rowsep='0'>
282e9fcaa8aSmrg    <entry role='functionargdecl'>
283e9fcaa8aSmrgunsigned int *             <emphasis>
284e9fcaa8aSmrgmask_rtrn</emphasis>
285e9fcaa8aSmrg;            /* backfilled with real modifiers */
286e9fcaa8aSmrg    </entry>
287e9fcaa8aSmrg</row>
288e9fcaa8aSmrg</tbody>
289e9fcaa8aSmrg</tgroup>
290e9fcaa8aSmrg</informaltable>
291e9fcaa8aSmrg
292e9fcaa8aSmrg<para>
293e9fcaa8aSmrgIf the keyboard description defined by <emphasis>
294e9fcaa8aSmrgxkb</emphasis>
295e9fcaa8aSmrg includes bindings for virtual modifiers, <emphasis>
296e9fcaa8aSmrgXkbVirtualModsToReal</emphasis>
297e9fcaa8aSmrg uses those bindings to determine the set of real modifiers that correspond to
298e9fcaa8aSmrgthe set of virtual modifiers specified in <emphasis>
299e9fcaa8aSmrgvirtual_mask</emphasis>
300e9fcaa8aSmrg. The <emphasis>
301e9fcaa8aSmrgvirtual_mask</emphasis>
302e9fcaa8aSmrg parameter is a mask specifying the virtual modifiers to translate; the i-th
303e9fcaa8aSmrgbit (0 relative) of the mask represents the i-th virtual modifier. If <emphasis>
304e9fcaa8aSmrgmask_rtrn</emphasis>
305e9fcaa8aSmrg is non-<emphasis>
306e9fcaa8aSmrgNULL</emphasis>
307e9fcaa8aSmrg, <emphasis>
308e9fcaa8aSmrgXkbVirtualModsToReal</emphasis>
309e9fcaa8aSmrg backfills it with the resulting real modifier mask. If the keyboard
310e9fcaa8aSmrgdescription in <emphasis>
311e9fcaa8aSmrgxkb</emphasis>
312e9fcaa8aSmrg does not include virtual modifier bindings, <emphasis>
313e9fcaa8aSmrgXkbVirtualModsToReal</emphasis>
314e9fcaa8aSmrg returns <emphasis>
315e9fcaa8aSmrgFalse</emphasis>
316e9fcaa8aSmrg; otherwise, it returns <emphasis>
317e9fcaa8aSmrgTrue</emphasis>
318e9fcaa8aSmrg.
319e9fcaa8aSmrg</para>
320e9fcaa8aSmrg
321e9fcaa8aSmrg<note><para>It is possible for a local (client-side) keyboard description (the
322e9fcaa8aSmrg<emphasis>
323e9fcaa8aSmrgxkb</emphasis>
324e9fcaa8aSmrg parameter) to not contain any virtual modifier information (simply because the
325e9fcaa8aSmrgclient has not requested it) while the server’s corresponding definition may
326e9fcaa8aSmrgcontain virtual modifier information. </para></note>
327e9fcaa8aSmrg
328e9fcaa8aSmrg
329e9fcaa8aSmrg<sect2 id='inactive_modifier_sets'>
330e9fcaa8aSmrg<title>Inactive Modifier Sets</title>
331e9fcaa8aSmrg
332e9fcaa8aSmrg<para>
333e9fcaa8aSmrgAn unbound virtual modifier is one that is not bound to any real modifier
334e9fcaa8aSmrg(<emphasis>
335e9fcaa8aSmrgserver</emphasis>
336e9fcaa8aSmrg-&gt;<emphasis>
337e9fcaa8aSmrgvmods</emphasis>
338e9fcaa8aSmrg[virtual_modifier_index] is zero).
339e9fcaa8aSmrg</para>
340e9fcaa8aSmrg
341e9fcaa8aSmrg
342e9fcaa8aSmrg<para>
343e9fcaa8aSmrgSome Xkb operations ignore modifier definitions in which the virtual modifiers
344e9fcaa8aSmrgare unbound. Consider this example:
345e9fcaa8aSmrg</para>
346e9fcaa8aSmrg
347e9fcaa8aSmrg<literallayout>
348e9fcaa8aSmrgif (state matches {Shift}) Do OneThing;
349e9fcaa8aSmrgif (state matches {Shift+NumLock}) Do Another;
350e9fcaa8aSmrg</literallayout>
351e9fcaa8aSmrg
352e9fcaa8aSmrg<para>
353e9fcaa8aSmrgIf the <emphasis>
354e9fcaa8aSmrgNumLock</emphasis>
355e9fcaa8aSmrg virtual modifier is not bound to any real modifiers, the effective masks for
356e9fcaa8aSmrgthese two cases are identical (that is, contain only <emphasis>
357e9fcaa8aSmrgShift</emphasis>
358e9fcaa8aSmrg). When it is essential to distinguish between <emphasis>
359e9fcaa8aSmrgOneThing</emphasis>
360e9fcaa8aSmrg and Another, Xkb considers only those modifier definitions for which all
361e9fcaa8aSmrgvirtual modifiers are bound.
362e9fcaa8aSmrg</para>
363e9fcaa8aSmrg
364e9fcaa8aSmrg
365e9fcaa8aSmrg</sect2>
366e9fcaa8aSmrg</sect1>
367e9fcaa8aSmrg<sect1 id='conventions'>
368e9fcaa8aSmrg<title>Conventions</title>
369e9fcaa8aSmrg
370e9fcaa8aSmrg<para>
371e9fcaa8aSmrgThe Xkb extension does not require any specific virtual modifier names.
372e9fcaa8aSmrgHowever, everyone benefits if the same names are used for common modifiers. The
373e9fcaa8aSmrgfollowing names are suggested:
374e9fcaa8aSmrg</para>
375e9fcaa8aSmrg
376e9fcaa8aSmrg<literallayout class='monospaced'>
377e9fcaa8aSmrg     <emphasis>
378e9fcaa8aSmrg     NumLock
379e9fcaa8aSmrg     ScrollLock
380e9fcaa8aSmrg     Alt
381e9fcaa8aSmrg     Meta
382e9fcaa8aSmrg     AltGr
383e9fcaa8aSmrg     LevelThree</emphasis>
384e9fcaa8aSmrg</literallayout>
385e9fcaa8aSmrg
386e9fcaa8aSmrg</sect1>
387e9fcaa8aSmrg<sect1 id='example'>
388e9fcaa8aSmrg<title>Example</title>
389e9fcaa8aSmrg
390e9fcaa8aSmrg<para>
391e9fcaa8aSmrgIf the second (0-relative) entry in <emphasis>
392e9fcaa8aSmrgnames.vmods</emphasis>
393e9fcaa8aSmrg contains the Atom for "NumLock", then 0x4 (1&lt;&lt;2) is the virtual modifier
394e9fcaa8aSmrgbit for the <emphasis>
395e9fcaa8aSmrgNumLock</emphasis>
396e9fcaa8aSmrg virtual modifier. If <emphasis>
397e9fcaa8aSmrgserver.vmods</emphasis>
398e9fcaa8aSmrg[2] contains <emphasis>
399e9fcaa8aSmrgMod3Mask</emphasis>
400e9fcaa8aSmrg, then the <emphasis>
401e9fcaa8aSmrgNumLock</emphasis>
402e9fcaa8aSmrg virtual modifier is bound to the <emphasis>
403e9fcaa8aSmrgMod3</emphasis>
404e9fcaa8aSmrg real modifier.
405e9fcaa8aSmrg</para>
406e9fcaa8aSmrg
407e9fcaa8aSmrg
408e9fcaa8aSmrg<para>
409e9fcaa8aSmrgA virtual modifier definition for this example would have:
410e9fcaa8aSmrg</para>
411e9fcaa8aSmrg
412e9fcaa8aSmrg<literallayout class='monospaced'>
413e9fcaa8aSmrg     real_mods = 0
414e9fcaa8aSmrg     vmods = 0x4 (NumLock named virtual modifier)
415e9fcaa8aSmrg     mask = 0x20 (Mod3Mask)
416e9fcaa8aSmrg</literallayout>
417e9fcaa8aSmrg
418e9fcaa8aSmrg<para>
419e9fcaa8aSmrgContinuing the example, if the keyboard has a <emphasis>
420e9fcaa8aSmrgNum_Lock</emphasis>
421e9fcaa8aSmrg keysym bound to the key with keycode 14, and the <emphasis>
422e9fcaa8aSmrgNumLock</emphasis>
423e9fcaa8aSmrg virtual modifier is bound to this key, <emphasis>
424e9fcaa8aSmrgserver.vmodmap</emphasis>
425e9fcaa8aSmrg[14] contains 0x4.
426e9fcaa8aSmrg</para>
427e9fcaa8aSmrg
428e9fcaa8aSmrg
429e9fcaa8aSmrg<para>
430e9fcaa8aSmrgFinally, if the keyboard also used the real <emphasis>
431e9fcaa8aSmrgMod1</emphasis>
432e9fcaa8aSmrg modifier for numeric lock operations, the modifier definition below would
433e9fcaa8aSmrgrepresent the situation where either the key bound to <emphasis>
434e9fcaa8aSmrgMod1</emphasis>
435e9fcaa8aSmrg or the <emphasis>
436e9fcaa8aSmrgNumLock</emphasis>
437e9fcaa8aSmrg virtual modifier could be used for this purpose:
438e9fcaa8aSmrg</para>
439e9fcaa8aSmrg
440e9fcaa8aSmrg<literallayout class='monospaced'>
441e9fcaa8aSmrg     real_mods = 0x8 (Mod1Mask)
442e9fcaa8aSmrg     vmods = 0x4 (NumLock named virtual modifier)
443e9fcaa8aSmrg     mask = 0x28 (Mod1Mask | Mod3Mask)
444e9fcaa8aSmrg</literallayout>
445e9fcaa8aSmrg</sect1>
446e9fcaa8aSmrg</chapter>
447