1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
|
<chapter id='Keyboard_State'>
<title>Keyboard State</title>
<para>
Keyboard state encompasses all of the transitory information necessary to map a physical key press or release to an appropriate event. The Xkb keyboard state consists of primitive components and additional derived components that are maintained for efficiency reasons. Figure 5.1 shows the components of Xkb keyboard state and their relationships.
</para>
<mediaobject>
<!-- <title>Keyboard State Description</title> -->
<imageobject> <imagedata format="SVG" fileref="XKBlib-2.svg"/>
</imageobject>
<caption>Xkb State</caption>
</mediaobject>
<sect1 id='Keyboard_State_Description'>
<title>Keyboard State Description</title>
<para>
The Xkb keyboard state is comprised of the state of all keyboard modifiers, the keyboard group, and the state of the pointer buttons. These are grouped into the following components:
</para>
<itemizedlist>
<listitem>
<para>
The locked group and locked modifiers
</para>
</listitem>
<listitem>
<para>
The latched group and latched modifiers
</para>
</listitem>
<listitem>
<para>
The base group and base modifiers
</para>
</listitem>
<listitem>
<para>
The effective group and effective modifiers
</para>
</listitem>
<listitem>
<para>
The state of the core pointer buttons
</para>
</listitem>
</itemizedlist>
<para>
The <emphasis>
modifiers</emphasis>
are <emphasis>
Shift</emphasis>
, <emphasis>
Lock</emphasis>
, <emphasis>
Control</emphasis>
, and <emphasis>
Mod1</emphasis>
-<emphasis>
Mod5</emphasis>
, as defined by the core protocol. A modifier can be thought of as a toggle that is either set or unset. All modifiers are initially unset. When a modifier is locked, it is set and remains set for all future key events, until it is explicitly unset. A latched modifier is set, but automatically unsets after the next key event that does not change the keyboard state. Locked and latched modifier state can be changed by keyboard activity or via Xkb extension library functions.
</para>
<para>
The Xkb extension provides support for <emphasis>
keysym</emphasis>
<emphasis>
groups</emphasis>
, as defined by ISO9995:
</para>
<variablelist>
<varlistentry>
<term>Group</term>
<listitem>
<para>
A logical state of a keyboard providing access to a collection of characters.
A group usually contains a set of characters that logically belong together
and that may be arranged on several shift levels within that group.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
The Xkb extension supports up to four keysym groups. Groups are named beginning with one and indexed beginning with zero. All group states are indicated using the group index. At any point in time, there is zero or one locked group, zero or one latched group, and one base group. When a group is locked, it supersedes any previous locked group and remains the locked group for all future key events, until a new group is locked. A latched group applies only to the next key event that does not change the keyboard state. The locked and latched group can be changed by keyboard activity or via Xkb extension library functions.
</para>
<para>
Changing to a different group changes the keyboard state to produce characters from a different group. Groups are typically used to switch between keysyms of different languages and locales.
</para>
<para>
The <emphasis>
pointer buttons</emphasis>
are <emphasis>
Button1</emphasis>
- <emphasis>
Button5</emphasis>
, as defined by the core protocol.
</para>
<para>
The <emphasis>
base group</emphasis>
and <emphasis>
base modifiers</emphasis>
represent keys that are physically or logically down. These
and the pointer buttons can be changed by keyboard activity and
not by Xkb requests. It is possible for a key to be logically
down, but not physically down, and neither latched nor locked.
<footnote><para>
Keys may be logically down when they are physically up because
of their electrical properties or because of the keyboard extension
in the X server having filtered the key release, for esoteric reasons.
</para></footnote>
</para>
<para>
The <emphasis>
effective modifiers</emphasis>
are the bitwise union of the locked, latched, and the base modifiers.
</para>
<para>
The <emphasis>
effective group</emphasis>
is the arithmetic sum of the group indices of the latched group, locked group, and base group, which is then normalized by some function. The result is a meaningful group index.
</para>
<simplelist type='vert' columns='1'>
<member>
n = number of keyboard groups, 1<= n <= 4
</member>
<member>
0 <= any of locked, latched, or base group < n
</member>
<member>
effective group = f(locked group + latched group + base group)
</member>
</simplelist>
<para>
The function f ensures that the effective group is within range. The precise function is specified for the keyboard and can be retrieved through the keyboard description. It may wrap around, clamp down, or default. Few applications will actually examine the effective group, and far fewer still will examine the locked, latched, and base groups.
</para>
<para>
There are two circumstances under which groups are normalized:
</para>
<orderedlist>
<listitem><para>
The global locked or effective group changes. In this case, the changed group is normalized into range according to the settings of the <emphasis>
groups_wrap</emphasis>
field of the <emphasis>
XkbControlsRec</emphasis>
structure for the keyboard (see section 10.7.1). <!-- xref -->
</para></listitem>
<listitem><para>
The Xkb library is interpreting an event with an effective group that is legal for the keyboard as a whole, but not for the key in question. In this case, the group to use for this event only is determined using the <emphasis>
group_info</emphasis>
field of the key symbol mapping (<emphasis>
XkbSymMapRec</emphasis>
) for the event key.
</para></listitem>
</orderedlist>
<para>
Each nonmodifier key on a keyboard has zero or more symbols, or keysyms, associated with it. These are the logical symbols that the key can generate when it is pressed. The set of all possible keysyms for a keyboard is divided into groups. Each key is associated with zero or more groups; each group contains one or more symbols. When a key is pressed, the determination of which symbol for the key is selected is based on the effective group and the shift level, which is determined by which modifiers are set.
</para>
<para>
A client that does not explicitly call Xkb functions, but that otherwise makes use of an X library containing the Xkb extension, will have keyboard state represented in bits 0 - 14 of the state field of events that report modifier and button state. Such a client is said to be <emphasis>
Xkb-capable</emphasis>
. A client that does explicitly call Xkb functions is an <emphasis>
Xkb-aware</emphasis>
client. The Xkb keyboard state includes information derived from the effective state and from two server parameters that can be set through the keyboard extension. The following components of keyboard state pertain to Xkb-capable and Xkb-aware clients:
</para>
<itemizedlist>
<listitem>
<para>
lookup state: lookup group and lookup modifiers
</para>
</listitem>
<listitem>
<para>
grab state: grab group and grab modifiers
</para>
</listitem>
</itemizedlist>
<para>
The <emphasis>
lookup modifiers</emphasis>
and <emphasis>
lookup group</emphasis>
are represented in the state field of core X events. The modifier state and keycode of a key event are used to determine the symbols associated with the event. For <emphasis>
KeyPress</emphasis>
and <emphasis>
KeyRelease</emphasis>
events, the lookup modifiers are computed as:
</para>
<literallayout>
((base | latched | locked) & ~<emphasis> server_internal_modifiers</emphasis>)
</literallayout>
<para>
Otherwise the lookup modifiers are computed as:
</para>
<literallayout>
(((base | latched | (locked & ~<emphasis> ignore_locks</emphasis>)) & ~<emphasis> server_internal_modifiers</emphasis>)
</literallayout>
<para>
The lookup group is the same as the effective group.
</para>
<para>
When an Xkb-capable or Xkb-aware client wishes to map a keycode to a keysym, it should use the <emphasis>
lookup state</emphasis>
— the lookup group and the lookup modifiers.
</para>
<para>
The <emphasis>
grab state</emphasis>
is the state used when matching events to passive grabs. If the event activates a grab, the <emphasis>
grab modifiers</emphasis>
and <emphasis>
grab group</emphasis>
are represented in the state field of core X events; otherwise, the lookup state is used. The grab modifiers are computed as:
</para>
<literallayout>
(((base | latched | (locked & ~ignore_locks)) & ~server_internal_modifiers)
</literallayout>
<para>
If the server’s <emphasis>
IgnoreGroupLock</emphasis>
control (see section 10.7.3) is not set, the grab group is the same as the effective group. Otherwise, the grab group is computed from the base group and latched group, ignoring the locked group.
</para>
<para>
The final three components of Xkb state are applicable to clients that are not linked with an Xlib containing the X keyboard extension library and therefore are not aware of the keyboard extension (<emphasis>
Xkb-unaware </emphasis>
clients):
</para>
<itemizedlist>
<listitem>
<para>
The compatibility modifier state
</para>
</listitem>
<listitem>
<para>
The compatibility lookup modifier state
</para>
</listitem>
<listitem>
<para>
The compatibility grab modifier state
</para>
</listitem>
</itemizedlist>
<para>
The X11 protocol interpretation of modifiers does not include direct support for multiple groups. When an Xkb-extended X server connects to an Xkb-unaware client, the compatibility states remap the keyboard group into a core modifier whenever possible. The compatibility state corresponds to the effective modifier and effective group state, with the group remapped to a modifier. The compatibility lookup and grab states correspond to the lookup and grab states, respectively, with the group remapped to a modifier. The compatibility lookup state is reported in events that do not trigger passive grabs; otherwise, the compatibility grab state is reported.
</para>
</sect1>
<sect1 id='Changing_the_Keyboard_State'>
<title>Changing the Keyboard State</title>
<sect2 id='Changing_Modifiers'>
<title>Changing Modifiers</title>
<para>
The functions in this section that change the use of modifiers use a mask in the parameter <emphasis>
affect</emphasis>
. It is a bitwise inclusive OR of the legal modifier masks:
</para>
<table frame='none'>
<title>Real Modifier Masks</title>
<?dbfo keep-together="always" ?>
<tgroup cols='1' align='left' colsep='0' rowsep='0'>
<colspec colname='c1' colwidth='1.0*'/>
<tbody>
<row>
<entry>Mask</entry>
</row>
<row>
<entry>ShiftMask</entry>
</row>
<row>
<entry>LockMask</entry>
</row>
<row>
<entry>ControlMask</entry>
</row>
<row>
<entry>Mod1Mask</entry>
</row>
<row>
<entry>Mod2Mask</entry>
</row>
<row>
<entry>Mod3Mask</entry>
</row>
<row>
<entry>Mod4Mask</entry>
</row>
<row>
<entry>Mod5Mask</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
To lock and unlock any of the eight real keyboard modifiers, use <emphasis>
XkbLockModifiers:</emphasis>
</para>
<informaltable frame='none'>
<?dbfo keep-together="always" ?>
<tgroup cols='1' align='left' colsep='0' rowsep='0'>
<colspec colname='c1' colwidth='1.0*'/>
<tbody>
<row>
<entry role='functiondecl'>
Bool <emphasis> XkbLockModifiers</emphasis>
(<emphasis>
display, device_spec, affect, values</emphasis>
)
</entry>
</row>
<row>
<entry role='functionargdecl'>
Display * <emphasis>
display</emphasis>
; /* connection to the X server */
</entry>
</row>
<row>
<entry role='functionargdecl'>
unsigned int <emphasis>
device_spec</emphasis>
; /* device ID, or <emphasis>
XkbUseCoreKbd</emphasis>
*/
</entry>
</row>
<row>
<entry role='functionargdecl'>
unsigned int<emphasis>
affect</emphasis>
; /* mask of real modifiers whose lock state is to change */
</entry>
</row>
<row>
<entry role='functionargdecl'>
unsigned int <emphasis>
values</emphasis>
; /* 1 => lock, 0 => unlock; only for modifiers selected by <emphasis>
affect</emphasis>
*/
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>
<emphasis>
XkbLockModifiers</emphasis>
sends a request to the server to lock the real modifiers selected by both <emphasis>
affect</emphasis>
and <emphasis>
values</emphasis>
and to unlock the real modifiers selected by <emphasis>
affect</emphasis>
but not selected by <emphasis>
values</emphasis>
. <emphasis>
XkbLockModifiers</emphasis>
does not wait for a reply from the server. It returns <emphasis>
True</emphasis>
if the request was sent, and <emphasis>
False</emphasis>
otherwise.
</para>
<para>
To latch and unlatch any of the eight real keyboard modifiers, use <emphasis>
XkbLatchModifiers:</emphasis>
</para>
<informaltable frame='none'>
<?dbfo keep-together="always" ?>
<tgroup cols='1' align='left' colsep='0' rowsep='0'>
<colspec colname='c1' colwidth='1.0*'/>
<tbody>
<row>
<entry role='functiondecl'>
Bool <emphasis>
XkbLatchModifiers</emphasis>
(d<emphasis>
isplay, device_spec, affect, values</emphasis>
)
</entry>
</row>
<row>
<entry role='functionargdecl'>
Display * <emphasis>
display</emphasis>
; /* connection to the X server */
</entry>
</row>
<row>
<entry role='functionargdecl'>
unsigned int <emphasis>
device_spec</emphasis>
; /* device ID, or <emphasis>
XkbUseCoreKbd</emphasis>
*/
</entry>
</row>
<row>
<entry role='functionargdecl'>
unsigned int<emphasis>
affect</emphasis>
; /* mask of modifiers whose latch state is to change */
</entry>
</row>
<row>
<entry role='functionargdecl'>
unsigned int <emphasis>values</emphasis>;
/* 1 => latch, 0 => unlatch; only for mods selected by <emphasis>
affect</emphasis>
*/
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>
<emphasis>
XkbLatchModifiers</emphasis>
sends a request to the server to latch the real modifiers selected by both <emphasis>
affect</emphasis>
and <emphasis>
values</emphasis>
and to unlatch the real modifiers selected by <emphasis>
affect</emphasis>
but not selected by <emphasis>
values</emphasis>
. <emphasis>
XkbLatchModifiers</emphasis>
does not wait for a reply from the server. It returns <emphasis>
True</emphasis>
if the request was sent, and <emphasis>
False</emphasis>
otherwise.
</para>
</sect2>
<sect2 id='Changing_Groups'>
<title>Changing Groups</title>
<para>
Reference the keysym group indices with these symbolic constants:
</para>
<table frame='topbot'>
<title>Symbolic Group Names</title>
<?dbfo keep-together="always" ?>
<tgroup cols='2' align='left' colsep='0' rowsep='0'>
<colspec colname='c1' colwidth='1.0*'/>
<colspec colname='c2' colwidth='2.0*'/>
<tbody>
<row rowsep='1'>
<entry>Symbolic Name</entry>
<entry>Value</entry>
</row>
<row>
<entry>XkbGroup1Index</entry>
<entry>0</entry>
</row>
<row>
<entry>XkbGroup2Index</entry>
<entry>1</entry>
</row>
<row>
<entry>XkbGroup3Index</entry>
<entry>2</entry>
</row>
<row>
<entry>XkbGroup4Index</entry>
<entry>3</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
To lock the keysym group, use <emphasis>
XkbLockGroup. </emphasis>
</para>
<informaltable frame='none'>
<?dbfo keep-together="always" ?>
<tgroup cols='1' align='left' colsep='0' rowsep='0'>
<colspec colname='c1' colwidth='1.0*'/>
<tbody>
<row>
<entry role='functiondecl'>
Bool <emphasis>
XkbLockGroup</emphasis>
(<emphasis>
display, device_spec, group</emphasis>
)
</entry>
</row>
<row>
<entry role='functionargdecl'>
Display * <emphasis>
display</emphasis>
; /* connection to the X server */
</entry>
</row>
<row>
<entry role='functionargdecl'>
unsigned int <emphasis>
device_spec</emphasis>
; /* device ID, or <emphasis>
XkbUseCoreKbd</emphasis>
*/
</entry>
</row>
<row>
<entry role='functionargdecl'>
unsigned int <emphasis>
group</emphasis>
; /* index of the keysym group to lock */
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>
<emphasis>
XkbLockGroup</emphasis>
sends a request to the server to lock the specified <emphasis>
group </emphasis>
and does not wait for a reply. It returns <emphasis>
True</emphasis>
if the request was sent and <emphasis>
False</emphasis>
otherwise.
</para>
<para>
To latch the keysym group, use <emphasis>
XkbLatchGroup.</emphasis>
</para>
<informaltable frame='none'>
<?dbfo keep-together="always" ?>
<tgroup cols='1' align='left' colsep='0' rowsep='0'>
<colspec colname='c1' colwidth='1.0*'/>
<tbody>
<row>
<entry role='functiondecl'>
Bool <emphasis>
XkbLatchGroup</emphasis>
(<emphasis>
display, device_spec, group</emphasis>
)
</entry>
</row>
<row>
<entry role='functionargdecl'>
Display * <emphasis>
display</emphasis>
; /* connection to the X server */
</entry>
</row>
<row>
<entry role='functionargdecl'>
unsigned int<emphasis>
device_spec</emphasis>
; /* device ID, or <emphasis>
XkbUseCoreKbd</emphasis>
*/
</entry>
</row>
<row>
<entry role='functionargdecl'>
unsigned int<emphasis>
group</emphasis>
; /* index of the keysym group to latch */
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>
<emphasis>
XkbLatchGroup</emphasis>
sends a request to the server to latch the specified group and does not wait for a reply. It returns <emphasis>
True</emphasis>
if the request was sent and <emphasis>
False</emphasis>
otherwise.
</para>
</sect2>
</sect1>
<sect1 id='Determining_Keyboard_State'>
<title>Determining Keyboard State</title>
<para>
Xkb keyboard state may be represented in an <emphasis>
XkbStateRec</emphasis>
structure:
</para>
<para><programlisting>
typedef struct {
unsigned char group; /* effective group index */
unsigned char base_group; /* base group index */
unsigned char latched_group; /* latched group index */
unsigned char locked_group; /* locked group index */
unsigned char mods; /* effective modifiers */
unsigned char base_mods; /* base modifiers */
unsigned char latched_mods; /* latched modifiers */
unsigned char locked_mods; /* locked modifiers */
unsigned char compat_state; /* effective group => modifiers */
unsigned char grab_mods; /* modifiers used for grabs */
unsigned char compat_grab_mods; /* mods used for compatibility mode grabs */
unsigned char lookup_mods; /* modifiers used to lookup symbols */
unsigned char compat_lookup_mods; /* mods used for compatibility lookup */
unsigned short ptr_buttons; /* 1 bit => corresponding pointer btn is down */
} <emphasis>
XkbStateRec</emphasis>
,*XkbStatePtr;
</programlisting></para>
<para>
To obtain the keyboard state, use <emphasis>
XkbGetState.</emphasis>
</para>
<informaltable frame='none'>
<?dbfo keep-together="always" ?>
<tgroup cols='1' align='left' colsep='0' rowsep='0'>
<colspec colname='c1' colwidth='1.0*'/>
<tbody>
<row>
<entry role='functiondecl'>
Status <emphasis>
XkbGetState</emphasis>
(<emphasis>
display</emphasis>
, <emphasis>
device_spec</emphasis>
, <emphasis>
state_return</emphasis>
)
</entry>
</row>
<row>
<entry role='functionargdecl'>
Display * <emphasis>
display</emphasis>
; /* connection to the X server */
</entry>
</row>
<row>
<entry role='functionargdecl'>
unsigned int <emphasis>
device_spec</emphasis>
; /* device ID, or <emphasis>
XkbUseCoreKbd</emphasis>
*/
</entry>
</row>
<row>
<entry role='functionargdecl'>
XkbStatePtr <emphasis>
state_return</emphasis>
; /* backfilled with Xkb state */
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>
The <emphasis>
XkbGetState </emphasis>
function queries the server for the current keyboard state, waits for a reply, and then backfills <emphasis>
state_return</emphasis>
with the results.
</para>
<para>
All group values are expressed as group indices in the range [0..3]. Modifiers and the compatibility modifier state values are expressed as the bitwise union of the core X11 modifier masks. The pointer button state is reported as in the core X11 protocol.
</para>
</sect1>
<sect1 id='Tracking_Keyboard_State'>
<title>Tracking Keyboard State</title>
<para>
The Xkb extension reports <emphasis>
XkbStateNotify </emphasis>
events to clients wanting notification whenever the Xkb state changes. The changes reported include changes to any aspect of the keyboard state: when a modifier is set or unset, when the current group changes, or when a pointer button is pressed or released. As with all Xkb events, <emphasis>
XkbStateNotify</emphasis>
events are reported to all interested clients without regard to the current keyboard input focus or grab state.
</para>
<para>
There are many different types of Xkb state changes. Xkb defines an event detail mask corresponding to each type of change. The event detail masks are listed in Table 5.3.
</para>
<table frame='topbot'>
<title>XkbStateNotify Event Detail Masks</title>
<?dbfo keep-together="always" ?>
<tgroup cols='2' align='left' colsep='0' rowsep='0'>
<colspec colname='c1' colwidth='1.0*'/>
<colspec colname='c2' colwidth='1.0*'/>
<thead>
<row rowsep='1'>
<entry>Mask</entry>
<entry>Value</entry>
</row>
</thead>
<tbody>
<row>
<entry>XkbModifierStateMask</entry>
<entry>(1L << 0)</entry>
</row>
<row>
<entry>XkbModifierBaseMask</entry>
<entry>(1L << 1)</entry>
</row>
<row>
<entry>XkbModifierLatchMask</entry>
<entry>(1L << 2)</entry>
</row>
<row>
<entry>XkbModifierLockMask</entry>
<entry>(1L << 3)</entry>
</row>
<row>
<entry>XkbGroupStateMask</entry>
<entry>(1L << 4)</entry>
</row>
<row>
<entry>XkbGroupBaseMask</entry>
<entry>(1L << 5)</entry>
</row>
<row>
<entry>XkbGroupLatchMask</entry>
<entry>(1L << 6)</entry>
</row>
<row>
<entry>XkbGroupLockMask</entry>
<entry>(1L << 7)</entry>
</row>
<row>
<entry>XkbCompatStateMask</entry>
<entry>(1L << 8)</entry>
</row>
<row>
<entry>XkbGrabModsMask</entry>
<entry>(1L << 9)</entry>
</row>
<row>
<entry>XkbCompatGrabModsMask</entry>
<entry>(1L << 10)</entry>
</row>
<row>
<entry>XkbLookupModsMask</entry>
<entry>(1L << 11)</entry>
</row>
<row>
<entry>XkbCompatLookupModsMask</entry>
<entry>(1L << 12)</entry>
</row>
<row>
<entry>XkbPointerButtonMask</entry>
<entry>(1L << 13)</entry>
</row>
<row>
<entry>XkbAllStateComponentsMask</entry>
<entry>(0x3fff)</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
To track changes in the keyboard state for a particular device, select to receive <emphasis>
XkbStateNotify</emphasis>
events by calling either <emphasis>
XkbSelectEvents</emphasis>
or <emphasis>
XkbSelectEventDetails</emphasis>
(see section 4.3). <!-- xref -->
</para>
<para>
To receive <emphasis>
XkbStateNotify</emphasis>
events under all possible conditions, use <emphasis>
XkbSelectEvents</emphasis>
and pass <emphasis>
XkbStateNotifyMask</emphasis>
in both <emphasis>
bits_to_change</emphasis>
and <emphasis>
values_for_bits</emphasis>
.
</para>
<para>
To receive <emphasis>
XkbStateNotify</emphasis>
events only under certain conditions, use <emphasis>
XkbSelectEventDetails</emphasis>
using <emphasis>
XkbStateNotify</emphasis>
as the <emphasis>
event_type</emphasis>
and specifying the desired state changes in <emphasis>
bits_to_change</emphasis>
and <emphasis>
values_for_bits</emphasis>
using mask bits from Table 5.3. <!-- xref -->
</para>
<para>
The structure for <emphasis>
XkbStateNotify</emphasis>
events is:
</para>
<para><programlisting>
typedef struct {
int type; /* Xkb extension base event code */
unsigned long serial; /* X server serial number for event */
Bool send_event; /* <emphasis> True</emphasis> => synthetically generated */
Display * display; /* server connection where event generated */
Time time; /* server time when event generated */
int xkb_type; /* <emphasis> XkbStateNotify</emphasis> */
int device; /* Xkb device ID, will not be <emphasis> XkbUseCoreKbd</emphasis> */
unsigned int changed; /* bits indicating what has changed */
int group; /* group index of effective group */
int base_group; /* group index of base group */
int latched_group; /* group index of latched group */
int locked_group; /* group index of locked group */
unsigned int mods; /* effective modifiers */
unsigned int base_mods; /* base modifiers */
unsigned int latched_mods; /* latched modifiers */
unsigned int locked_mods; /* locked modifiers */
int compat_state; /* computed compatibility state */
unsigned char grab_mods; /* modifiers used for grabs */
unsigned char compat_grab_mods; /* modifiers used for compatibility grabs */
unsigned char lookup_mods; /* modifiers used to lookup symbols */
unsigned char compat_lookup_mods; /* mods used for compatibility look up */
int ptr_buttons; /* core pointer buttons */
KeyCode keycode; /* keycode causing event, 0 if programmatic */
char event_type; /* core event if <emphasis> req_major</emphasis> or
<emphasis> req_minor</emphasis> non zero */
char req_major; /* major request code if program trigger, else 0 */
char req_minor; /* minor request code if program trigger, else 0 */
} <emphasis>XkbStateNotifyEvent</emphasis>
;
</programlisting></para>
<para>
When you receive an <emphasis>
XkbStateNotify</emphasis>
event, the <emphasis>
changed</emphasis>
field indicates which elements of keyboard state have changed.
This will be the bitwise inclusive OR of one or more of the <emphasis>
XkbStateNotify</emphasis>
event detail masks shown in Table 5.3. All fields reported in <!-- xref -->
the event are valid, but only those indicated in <emphasis>
changed</emphasis>
have changed values.
</para>
<para>
The <emphasis>
group</emphasis>
field is the group index of the effective keysym group. The <emphasis>
base_group</emphasis>
, <emphasis>
latched_group</emphasis>
, and <emphasis>
locked_group</emphasis>
fields are set to a group index value representing the base group,
the latched group, and the locked group, respectively. The X
server can set the modifier and compatibility state fields to
a union of the core modifier mask bits; this union represents the
corresponding modifier states. The <emphasis>ptr_button</emphasis>
field gives the state of the core pointer buttons as a
mask composed of an inclusive OR of zero or more of the
core pointer button masks.
</para>
<para>
Xkb state changes can occur either in response to keyboard
activity or under application control. If a key event
caused the state change, the <emphasis>
keycode</emphasis>
field gives the keycode of the key event, and the <emphasis>
event_type</emphasis>
field is set to either <emphasis>KeyPress</emphasis>
or <emphasis>
KeyRelease</emphasis>
. If a pointer button event caused the state change, the <emphasis>
keycode</emphasis>
field is zero, and the <emphasis>event_type</emphasis>
field is set to either <emphasis>ButtonPress</emphasis>
or <emphasis>ButtonRelease</emphasis>
. Otherwise, the major and minor codes of the request that caused the
state change are given in the <emphasis>
req_major</emphasis>
and <emphasis>
req_minor</emphasis>
fields, and the <emphasis>
keycode</emphasis>
field is zero. The <emphasis>
req_major</emphasis>
value is the same as the major extension opcode.
</para>
</sect1>
</chapter>
|