1 /************************************************************
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 ********************************************************/
28 Copyright © 2008 Red Hat Inc.
30 Permission is hereby granted, free of charge, to any person obtaining a
31 copy of this software and associated documentation files (the "Software"),
32 to deal in the Software without restriction, including without limitation
33 the rights to use, copy, modify, merge, publish, distribute, sublicense,
34 and/or sell copies of the Software, and to permit persons to whom the
35 Software is furnished to do so, subject to the following conditions:
37 The above copyright notice and this permission notice (including the next
38 paragraph) shall be included in all copies or substantial portions of the
41 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
46 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
47 DEALINGS IN THE SOFTWARE.
51 #ifdef HAVE_DIX_CONFIG_H
52 #include <dix-config.h>
60 #include <X11/Xproto.h>
62 #include <X11/keysym.h>
67 #define XKBSRV_NEED_FILE_FUNCS
72 /***====================================================================***/
75 _XkbLookupAnyDevice(DeviceIntPtr
*pDev
, int id
, ClientPtr client
,
76 Mask access_mode
, int *xkb_err
)
78 int rc
= XkbKeyboardErrorCode
;
80 if (id
== XkbUseCoreKbd
)
81 id
= PickKeyboard(client
)->id
;
82 else if (id
== XkbUseCorePtr
)
83 id
= PickPointer(client
)->id
;
85 rc
= dixLookupDevice(pDev
, id
, client
, access_mode
);
87 *xkb_err
= XkbErr_BadDevice
;
93 _XkbLookupKeyboard(DeviceIntPtr
*pDev
, int id
, ClientPtr client
,
94 Mask access_mode
, int *xkb_err
)
99 if (id
== XkbDfltXIId
)
102 rc
= _XkbLookupAnyDevice(pDev
, id
, client
, access_mode
, xkb_err
);
107 if (!dev
->key
|| !dev
->key
->xkbInfo
) {
109 *xkb_err
= XkbErr_BadClass
;
110 return XkbKeyboardErrorCode
;
116 _XkbLookupBellDevice(DeviceIntPtr
*pDev
, int id
, ClientPtr client
,
117 Mask access_mode
, int *xkb_err
)
122 rc
= _XkbLookupAnyDevice(pDev
, id
, client
, access_mode
, xkb_err
);
127 if (!dev
->kbdfeed
&& !dev
->bell
) {
129 *xkb_err
= XkbErr_BadClass
;
130 return XkbKeyboardErrorCode
;
136 _XkbLookupLedDevice(DeviceIntPtr
*pDev
, int id
, ClientPtr client
,
137 Mask access_mode
, int *xkb_err
)
142 if (id
== XkbDfltXIId
)
145 rc
= _XkbLookupAnyDevice(pDev
, id
, client
, access_mode
, xkb_err
);
150 if (!dev
->kbdfeed
&& !dev
->leds
) {
152 *xkb_err
= XkbErr_BadClass
;
153 return XkbKeyboardErrorCode
;
159 _XkbLookupButtonDevice(DeviceIntPtr
*pDev
, int id
, ClientPtr client
,
160 Mask access_mode
, int *xkb_err
)
165 rc
= _XkbLookupAnyDevice(pDev
, id
, client
, access_mode
, xkb_err
);
172 *xkb_err
= XkbErr_BadClass
;
173 return XkbKeyboardErrorCode
;
179 XkbSetActionKeyMods(XkbDescPtr xkb
, XkbAction
*act
, unsigned mods
)
181 register unsigned tmp
;
185 case XkbSA_LatchMods
:
187 if (act
->mods
.flags
& XkbSA_UseModMapMods
)
188 act
->mods
.real_mods
= act
->mods
.mask
= mods
;
189 if ((tmp
= XkbModActionVMods(&act
->mods
)) != 0)
190 act
->mods
.mask
|= XkbMaskForVMask(xkb
, tmp
);
193 if (act
->iso
.flags
& XkbSA_UseModMapMods
)
194 act
->iso
.real_mods
= act
->iso
.mask
= mods
;
195 if ((tmp
= XkbModActionVMods(&act
->iso
)) != 0)
196 act
->iso
.mask
|= XkbMaskForVMask(xkb
, tmp
);
203 XkbMaskForVMask(XkbDescPtr xkb
, unsigned vmask
)
206 register unsigned mask
;
208 for (mask
= i
= 0, bit
= 1; i
< XkbNumVirtualMods
; i
++, bit
<<= 1) {
210 mask
|= xkb
->server
->vmods
[i
];
215 /***====================================================================***/
218 XkbUpdateKeyTypesFromCore(DeviceIntPtr pXDev
,
220 KeyCode first
, CARD8 num
, XkbChangesPtr changes
)
223 unsigned key
, nG
, explicit;
224 int types
[XkbNumKbdGroups
];
225 KeySym tsyms
[XkbMaxSymsPerKey
], *syms
;
228 xkb
= pXDev
->key
->xkbInfo
->desc
;
229 if (first
+ num
- 1 > xkb
->max_key_code
) {
230 /* 1/12/95 (ef) -- XXX! should allow XKB structures to grow */
231 num
= xkb
->max_key_code
- first
+ 1;
234 mc
= (changes
? (&changes
->map
) : NULL
);
236 syms
= &pCore
->map
[(first
- pCore
->minKeyCode
) * pCore
->mapWidth
];
237 for (key
= first
; key
< (first
+ num
); key
++, syms
+= pCore
->mapWidth
) {
238 explicit = xkb
->server
->explicit[key
] & XkbExplicitKeyTypesMask
;
239 types
[XkbGroup1Index
] = XkbKeyKeyTypeIndex(xkb
, key
, XkbGroup1Index
);
240 types
[XkbGroup2Index
] = XkbKeyKeyTypeIndex(xkb
, key
, XkbGroup2Index
);
241 types
[XkbGroup3Index
] = XkbKeyKeyTypeIndex(xkb
, key
, XkbGroup3Index
);
242 types
[XkbGroup4Index
] = XkbKeyKeyTypeIndex(xkb
, key
, XkbGroup4Index
);
243 nG
= XkbKeyTypesForCoreSymbols(xkb
, pCore
->mapWidth
, syms
, explicit,
245 XkbChangeTypesOfKey(xkb
, key
, nG
, XkbAllGroupsMask
, types
, mc
);
246 memcpy((char *) XkbKeySymsPtr(xkb
, key
), (char *) tsyms
,
247 XkbKeyNumSyms(xkb
, key
) * sizeof(KeySym
));
249 if (changes
->map
.changed
& XkbKeySymsMask
) {
250 CARD8 oldLast
, newLast
;
252 oldLast
= changes
->map
.first_key_sym
+ changes
->map
.num_key_syms
- 1;
253 newLast
= first
+ num
- 1;
255 if (first
< changes
->map
.first_key_sym
)
256 changes
->map
.first_key_sym
= first
;
257 if (oldLast
> newLast
)
259 changes
->map
.num_key_syms
= newLast
- changes
->map
.first_key_sym
+ 1;
262 changes
->map
.changed
|= XkbKeySymsMask
;
263 changes
->map
.first_key_sym
= first
;
264 changes
->map
.num_key_syms
= num
;
270 XkbUpdateDescActions(XkbDescPtr xkb
,
271 KeyCode first
, CARD8 num
, XkbChangesPtr changes
)
273 register unsigned key
;
275 for (key
= first
; key
< (first
+ num
); key
++) {
276 XkbApplyCompatMapToKey(xkb
, key
, changes
);
279 if (changes
->map
.changed
& (XkbVirtualModMapMask
| XkbModifierMapMask
)) {
280 unsigned char newVMods
[XkbNumVirtualMods
];
281 register unsigned bit
, i
;
284 memset(newVMods
, 0, XkbNumVirtualMods
);
286 for (key
= xkb
->min_key_code
; key
<= xkb
->max_key_code
; key
++) {
287 if (xkb
->server
->vmodmap
[key
] == 0)
289 for (i
= 0, bit
= 1; i
< XkbNumVirtualMods
; i
++, bit
<<= 1) {
290 if (bit
& xkb
->server
->vmodmap
[key
]) {
292 newVMods
[i
] |= xkb
->map
->modmap
[key
];
296 for (i
= 0, bit
= 1; i
< XkbNumVirtualMods
; i
++, bit
<<= 1) {
297 if ((bit
& present
) && (newVMods
[i
] != xkb
->server
->vmods
[i
])) {
298 changes
->map
.changed
|= XkbVirtualModsMask
;
299 changes
->map
.vmods
|= bit
;
300 xkb
->server
->vmods
[i
] = newVMods
[i
];
304 if (changes
->map
.changed
& XkbVirtualModsMask
)
305 XkbApplyVirtualModChanges(xkb
, changes
->map
.vmods
, changes
);
307 if (changes
->map
.changed
& XkbKeyActionsMask
) {
308 CARD8 oldLast
, newLast
;
310 oldLast
= changes
->map
.first_key_act
+ changes
->map
.num_key_acts
- 1;
311 newLast
= first
+ num
- 1;
313 if (first
< changes
->map
.first_key_act
)
314 changes
->map
.first_key_act
= first
;
315 if (newLast
> oldLast
)
317 changes
->map
.num_key_acts
= newLast
- changes
->map
.first_key_act
+ 1;
320 changes
->map
.changed
|= XkbKeyActionsMask
;
321 changes
->map
.first_key_act
= first
;
322 changes
->map
.num_key_acts
= num
;
328 XkbUpdateActions(DeviceIntPtr pXDev
,
331 XkbChangesPtr changes
,
332 unsigned *needChecksRtrn
, XkbEventCausePtr cause
)
340 xkbi
= pXDev
->key
->xkbInfo
;
342 repeat
= xkb
->ctrls
->per_key_repeat
;
344 /* before letting XKB do any changes, copy the current core values */
346 memcpy(repeat
, pXDev
->kbdfeed
->ctrl
.autoRepeats
, XkbPerKeyBitArraySize
);
348 XkbUpdateDescActions(xkb
, first
, num
, changes
);
350 if ((pXDev
->kbdfeed
) &&
351 (changes
->ctrls
.changed_ctrls
& XkbPerKeyRepeatMask
)) {
352 /* now copy the modified changes back to core */
353 memcpy(pXDev
->kbdfeed
->ctrl
.autoRepeats
, repeat
, XkbPerKeyBitArraySize
);
354 if (pXDev
->kbdfeed
->CtrlProc
)
355 (*pXDev
->kbdfeed
->CtrlProc
) (pXDev
, &pXDev
->kbdfeed
->ctrl
);
361 XkbGetCoreMap(DeviceIntPtr keybd
)
363 register int key
, tmp
;
364 int maxSymsPerKey
, maxGroup1Width
;
367 int maxNumberOfGroups
;
369 if (!keybd
|| !keybd
->key
|| !keybd
->key
->xkbInfo
)
372 xkb
= keybd
->key
->xkbInfo
->desc
;
373 maxSymsPerKey
= maxGroup1Width
= 0;
374 maxNumberOfGroups
= 0;
376 /* determine sizes */
377 for (key
= xkb
->min_key_code
; key
<= xkb
->max_key_code
; key
++) {
378 if (XkbKeycodeInRange(xkb
, key
)) {
382 nGroups
= XkbKeyNumGroups(xkb
, key
);
385 if ((w
= XkbKeyGroupWidth(xkb
, key
, XkbGroup1Index
)) <= 2)
389 /* remember highest G1 width */
390 if (w
> maxGroup1Width
)
395 if ((w
= XkbKeyGroupWidth(xkb
, key
, XkbGroup2Index
)) < 2)
401 if ((w
= XkbKeyGroupWidth(xkb
, key
, XkbGroup2Index
)) > 2)
406 tmp
+= XkbKeyGroupWidth(xkb
, key
, XkbGroup3Index
);
408 tmp
+= XkbKeyGroupWidth(xkb
, key
, XkbGroup4Index
);
409 if (tmp
> maxSymsPerKey
)
411 if (nGroups
> maxNumberOfGroups
)
412 maxNumberOfGroups
= nGroups
;
416 if (maxSymsPerKey
<= 0)
419 syms
= calloc(1, sizeof(*syms
));
423 /* See Section 12.4 of the XKB Protocol spec. Because of the
424 * single-group distribution for multi-group keyboards, we have to
425 * have enough symbols for the largest group 1 to replicate across the
426 * number of groups on the keyboard. e.g. a single-group key with 4
427 * symbols on a keyboard that has 3 groups -> 12 syms per key */
428 if (maxSymsPerKey
< maxNumberOfGroups
* maxGroup1Width
)
429 maxSymsPerKey
= maxNumberOfGroups
* maxGroup1Width
;
431 syms
->mapWidth
= maxSymsPerKey
;
432 syms
->minKeyCode
= xkb
->min_key_code
;
433 syms
->maxKeyCode
= xkb
->max_key_code
;
435 tmp
= syms
->mapWidth
* (xkb
->max_key_code
- xkb
->min_key_code
+ 1);
436 syms
->map
= calloc(tmp
, sizeof(*syms
->map
));
442 for (key
= xkb
->min_key_code
; key
<= xkb
->max_key_code
; key
++) {
443 KeySym
*pCore
, *pXKB
;
444 unsigned nGroups
, groupWidth
, n
, nOut
;
446 nGroups
= XkbKeyNumGroups(xkb
, key
);
447 n
= (key
- xkb
->min_key_code
) * syms
->mapWidth
;
448 pCore
= &syms
->map
[n
];
449 pXKB
= XkbKeySymsPtr(xkb
, key
);
452 groupWidth
= XkbKeyGroupWidth(xkb
, key
, XkbGroup1Index
);
457 for (n
= 2; n
< groupWidth
; n
++)
458 pCore
[2 + n
] = pXKB
[n
];
463 /* See XKB Protocol Sec, Section 12.4.
464 A 1-group key with ABCDE on a 2 group keyboard must be
465 duplicated across all groups as ABABCDECDE.
470 groupWidth
= XkbKeyGroupWidth(xkb
, key
, XkbGroup1Index
);
472 /* AB..CDE... -> ABABCDE... */
473 if (groupWidth
> 0 && syms
->mapWidth
>= 3)
475 if (groupWidth
> 1 && syms
->mapWidth
>= 4)
478 /* ABABCDE... -> ABABCDECDE */
479 idx
= 2 + groupWidth
;
480 while (groupWidth
> 2 && idx
< syms
->mapWidth
&&
481 idx
< groupWidth
* 2) {
482 pCore
[idx
] = pCore
[idx
- groupWidth
+ 2];
485 idx
= 2 * groupWidth
;
488 /* 3 or more groups: ABABCDECDEABCDEABCDE */
489 for (j
= 3; j
<= maxNumberOfGroups
; j
++)
490 for (n
= 0; n
< groupWidth
&& idx
< maxSymsPerKey
; n
++)
491 pCore
[idx
++] = pXKB
[n
];
494 pXKB
+= XkbKeyGroupsWidth(xkb
, key
);
497 groupWidth
= XkbKeyGroupWidth(xkb
, key
, XkbGroup2Index
);
502 for (n
= 2; n
< groupWidth
; n
++) {
503 pCore
[nOut
+ (n
- 2)] = pXKB
[n
];
506 nOut
+= (groupWidth
- 2);
508 pXKB
+= XkbKeyGroupsWidth(xkb
, key
);
509 for (n
= XkbGroup3Index
; n
< nGroups
; n
++) {
512 groupWidth
= XkbKeyGroupWidth(xkb
, key
, n
);
513 for (s
= 0; s
< groupWidth
; s
++) {
514 pCore
[nOut
++] = pXKB
[s
];
516 pXKB
+= XkbKeyGroupsWidth(xkb
, key
);
524 XkbSetRepeatKeys(DeviceIntPtr pXDev
, int key
, int onoff
)
526 if (pXDev
&& pXDev
->key
&& pXDev
->key
->xkbInfo
) {
527 xkbControlsNotify cn
;
528 XkbControlsPtr ctrls
= pXDev
->key
->xkbInfo
->desc
->ctrls
;
533 if (key
== -1) { /* global autorepeat setting changed */
535 ctrls
->enabled_ctrls
|= XkbRepeatKeysMask
;
537 ctrls
->enabled_ctrls
&= ~XkbRepeatKeysMask
;
539 else if (pXDev
->kbdfeed
) {
540 ctrls
->per_key_repeat
[key
/ 8] =
541 pXDev
->kbdfeed
->ctrl
.autoRepeats
[key
/ 8];
544 if (XkbComputeControlsNotify(pXDev
, &old
, ctrls
, &cn
, TRUE
))
545 XkbSendControlsNotify(pXDev
, &cn
);
550 /* Applies a change to a single device, does not traverse the device tree. */
552 XkbApplyMappingChange(DeviceIntPtr kbd
, KeySymsPtr map
, KeyCode first_key
,
553 CARD8 num_keys
, CARD8
*modmap
, ClientPtr client
)
555 XkbDescPtr xkb
= kbd
->key
->xkbInfo
->desc
;
556 XkbEventCauseRec cause
;
557 XkbChangesRec changes
;
560 memset(&changes
, 0, sizeof(changes
));
561 memset(&cause
, 0, sizeof(cause
));
563 if (map
&& first_key
&& num_keys
) {
565 XkbSetCauseCoreReq(&cause
, X_ChangeKeyboardMapping
, client
);
567 XkbUpdateKeyTypesFromCore(kbd
, map
, first_key
, num_keys
, &changes
);
568 XkbUpdateActions(kbd
, first_key
, num_keys
, &changes
, &check
, &cause
);
571 XkbCheckSecondaryEffects(kbd
->key
->xkbInfo
, 1, &changes
, &cause
);
575 /* A keymap change can imply a modmap change, se we prefer the
578 XkbSetCauseCoreReq(&cause
, X_SetModifierMapping
, client
);
581 num_keys
= xkb
->max_key_code
- xkb
->min_key_code
+ 1;
582 changes
.map
.changed
|= XkbModifierMapMask
;
583 changes
.map
.first_modmap_key
= xkb
->min_key_code
;
584 changes
.map
.num_modmap_keys
= num_keys
;
585 memcpy(kbd
->key
->xkbInfo
->desc
->map
->modmap
, modmap
, MAP_LENGTH
);
586 XkbUpdateActions(kbd
, xkb
->min_key_code
, num_keys
, &changes
, &check
,
590 XkbCheckSecondaryEffects(kbd
->key
->xkbInfo
, 1, &changes
, &cause
);
593 XkbSendNotification(kbd
, &changes
, &cause
);
597 XkbDisableComputedAutoRepeats(DeviceIntPtr dev
, unsigned key
)
599 XkbSrvInfoPtr xkbi
= dev
->key
->xkbInfo
;
602 xkbi
->desc
->server
->explicit[key
] |= XkbExplicitAutoRepeatMask
;
603 memset(&mn
, 0, sizeof(mn
));
604 mn
.changed
= XkbExplicitComponentsMask
;
605 mn
.firstKeyExplicit
= key
;
607 XkbSendMapNotify(dev
, &mn
);
612 XkbStateChangedFlags(XkbStatePtr old
, XkbStatePtr
new)
616 changed
= (old
->group
!= new->group
? XkbGroupStateMask
: 0);
617 changed
|= (old
->base_group
!= new->base_group
? XkbGroupBaseMask
: 0);
619 (old
->latched_group
!= new->latched_group
? XkbGroupLatchMask
: 0);
620 changed
|= (old
->locked_group
!= new->locked_group
? XkbGroupLockMask
: 0);
621 changed
|= (old
->mods
!= new->mods
? XkbModifierStateMask
: 0);
622 changed
|= (old
->base_mods
!= new->base_mods
? XkbModifierBaseMask
: 0);
624 (old
->latched_mods
!= new->latched_mods
? XkbModifierLatchMask
: 0);
625 changed
|= (old
->locked_mods
!= new->locked_mods
? XkbModifierLockMask
: 0);
627 (old
->compat_state
!= new->compat_state
? XkbCompatStateMask
: 0);
628 changed
|= (old
->grab_mods
!= new->grab_mods
? XkbGrabModsMask
: 0);
629 if (old
->compat_grab_mods
!= new->compat_grab_mods
)
630 changed
|= XkbCompatGrabModsMask
;
631 changed
|= (old
->lookup_mods
!= new->lookup_mods
? XkbLookupModsMask
: 0);
632 if (old
->compat_lookup_mods
!= new->compat_lookup_mods
)
633 changed
|= XkbCompatLookupModsMask
;
635 (old
->ptr_buttons
!= new->ptr_buttons
? XkbPointerButtonMask
: 0);
640 XkbComputeCompatState(XkbSrvInfoPtr xkbi
)
643 XkbStatePtr state
= &xkbi
->state
;
645 XkbControlsPtr ctrls
;
647 if (!state
|| !xkbi
->desc
|| !xkbi
->desc
->ctrls
|| !xkbi
->desc
->compat
)
650 map
= xkbi
->desc
->compat
;
651 grp_mask
= map
->groups
[state
->group
].mask
;
652 state
->compat_state
= state
->mods
| grp_mask
;
653 state
->compat_lookup_mods
= state
->lookup_mods
| grp_mask
;
654 ctrls
= xkbi
->desc
->ctrls
;
656 if (ctrls
->enabled_ctrls
& XkbIgnoreGroupLockMask
) {
657 unsigned char grp
= state
->base_group
+state
->latched_group
;
658 if (grp
>= ctrls
->num_groups
)
659 grp
= XkbAdjustGroup(XkbCharToInt(grp
), ctrls
);
660 grp_mask
= map
->groups
[grp
].mask
;
662 state
->compat_grab_mods
= state
->grab_mods
| grp_mask
;
667 XkbAdjustGroup(int group
, XkbControlsPtr ctrls
)
671 act
= XkbOutOfRangeGroupAction(ctrls
->groups_wrap
);
674 if (act
== XkbClampIntoRange
) {
675 group
= XkbGroup1Index
;
677 else if (act
== XkbRedirectIntoRange
) {
680 newGroup
= XkbOutOfRangeGroupNumber(ctrls
->groups_wrap
);
681 if (newGroup
>= ctrls
->num_groups
)
682 group
= XkbGroup1Index
;
687 group
+= ctrls
->num_groups
;
691 else if (group
>= ctrls
->num_groups
) {
692 if (act
== XkbClampIntoRange
) {
693 group
= ctrls
->num_groups
- 1;
695 else if (act
== XkbRedirectIntoRange
) {
698 newGroup
= XkbOutOfRangeGroupNumber(ctrls
->groups_wrap
);
699 if (newGroup
>= ctrls
->num_groups
)
700 group
= XkbGroup1Index
;
705 group
%= ctrls
->num_groups
;
712 XkbComputeDerivedState(XkbSrvInfoPtr xkbi
)
714 XkbStatePtr state
= &xkbi
->state
;
715 XkbControlsPtr ctrls
= xkbi
->desc
->ctrls
;
718 if (!state
|| !ctrls
)
721 state
->mods
= (state
->base_mods
| state
->latched_mods
| state
->locked_mods
);
722 state
->lookup_mods
= state
->mods
& (~ctrls
->internal
.mask
);
723 state
->grab_mods
= state
->lookup_mods
& (~ctrls
->ignore_lock
.mask
);
725 ((state
->base_mods
| state
->latched_mods
) & ctrls
->ignore_lock
.mask
);
727 grp
= state
->locked_group
;
728 if (grp
>= ctrls
->num_groups
)
729 state
->locked_group
= XkbAdjustGroup(XkbCharToInt(grp
), ctrls
);
731 grp
= state
->locked_group
+ state
->base_group
+ state
->latched_group
;
732 if (grp
>= ctrls
->num_groups
)
733 state
->group
= XkbAdjustGroup(XkbCharToInt(grp
), ctrls
);
736 XkbComputeCompatState(xkbi
);
740 /***====================================================================***/
743 XkbCheckSecondaryEffects(XkbSrvInfoPtr xkbi
,
745 XkbChangesPtr changes
, XkbEventCausePtr cause
)
747 if (which
& XkbStateNotifyMask
) {
751 changes
->state_changes
|= XkbStateChangedFlags(&old
, &xkbi
->state
);
752 XkbComputeDerivedState(xkbi
);
754 if (which
& XkbIndicatorStateNotifyMask
)
755 XkbUpdateIndicators(xkbi
->device
, XkbAllIndicatorsMask
, TRUE
, changes
,
760 /***====================================================================***/
763 XkbEnableDisableControls(XkbSrvInfoPtr xkbi
,
764 unsigned long change
,
765 unsigned long newValues
,
766 XkbChangesPtr changes
, XkbEventCausePtr cause
)
768 XkbControlsPtr ctrls
;
770 XkbSrvLedInfoPtr sli
;
772 ctrls
= xkbi
->desc
->ctrls
;
773 old
= ctrls
->enabled_ctrls
;
774 ctrls
->enabled_ctrls
&= ~change
;
775 ctrls
->enabled_ctrls
|= (change
& newValues
);
776 if (old
== ctrls
->enabled_ctrls
)
779 xkbControlsNotify cn
;
781 cn
.numGroups
= ctrls
->num_groups
;
782 cn
.changedControls
= XkbControlsEnabledMask
;
783 cn
.enabledControls
= ctrls
->enabled_ctrls
;
784 cn
.enabledControlChanges
= (ctrls
->enabled_ctrls
^ old
);
785 cn
.keycode
= cause
->kc
;
786 cn
.eventType
= cause
->event
;
787 cn
.requestMajor
= cause
->mjr
;
788 cn
.requestMinor
= cause
->mnr
;
789 XkbSendControlsNotify(xkbi
->device
, &cn
);
792 /* Yes, this really should be an XOR. If ctrls->enabled_ctrls_changes */
793 /* is non-zero, the controls in question changed already in "this" */
794 /* request and this change merely undoes the previous one. By the */
795 /* same token, we have to figure out whether or not ControlsEnabled */
796 /* should be set or not in the changes structure */
797 changes
->ctrls
.enabled_ctrls_changes
^= (ctrls
->enabled_ctrls
^ old
);
798 if (changes
->ctrls
.enabled_ctrls_changes
)
799 changes
->ctrls
.changed_ctrls
|= XkbControlsEnabledMask
;
801 changes
->ctrls
.changed_ctrls
&= ~XkbControlsEnabledMask
;
803 sli
= XkbFindSrvLedInfo(xkbi
->device
, XkbDfltXIClass
, XkbDfltXIId
, 0);
804 XkbUpdateIndicators(xkbi
->device
, sli
->usesControls
, TRUE
, changes
, cause
);
808 /***====================================================================***/
813 XkbLookupNamedGeometry(DeviceIntPtr dev
, Atom name
, Bool
*shouldFree
)
815 XkbSrvInfoPtr xkbi
= dev
->key
->xkbInfo
;
816 XkbDescPtr xkb
= xkbi
->desc
;
820 if (xkb
->geom
!= NULL
)
822 name
= xkb
->names
->geometry
;
824 if ((xkb
->geom
!= NULL
) && (xkb
->geom
->name
== name
))
831 XkbConvertCase(register KeySym sym
, KeySym
* lower
, KeySym
* upper
)
836 case 0: /* Latin 1 */
837 if ((sym
>= XK_A
) && (sym
<= XK_Z
))
838 *lower
+= (XK_a
- XK_A
);
839 else if ((sym
>= XK_a
) && (sym
<= XK_z
))
840 *upper
-= (XK_a
- XK_A
);
841 else if ((sym
>= XK_Agrave
) && (sym
<= XK_Odiaeresis
))
842 *lower
+= (XK_agrave
- XK_Agrave
);
843 else if ((sym
>= XK_agrave
) && (sym
<= XK_odiaeresis
))
844 *upper
-= (XK_agrave
- XK_Agrave
);
845 else if ((sym
>= XK_Ooblique
) && (sym
<= XK_Thorn
))
846 *lower
+= (XK_oslash
- XK_Ooblique
);
847 else if ((sym
>= XK_oslash
) && (sym
<= XK_thorn
))
848 *upper
-= (XK_oslash
- XK_Ooblique
);
850 case 1: /* Latin 2 */
851 /* Assume the KeySym is a legal value (ignore discontinuities) */
852 if (sym
== XK_Aogonek
)
854 else if (sym
>= XK_Lstroke
&& sym
<= XK_Sacute
)
855 *lower
+= (XK_lstroke
- XK_Lstroke
);
856 else if (sym
>= XK_Scaron
&& sym
<= XK_Zacute
)
857 *lower
+= (XK_scaron
- XK_Scaron
);
858 else if (sym
>= XK_Zcaron
&& sym
<= XK_Zabovedot
)
859 *lower
+= (XK_zcaron
- XK_Zcaron
);
860 else if (sym
== XK_aogonek
)
862 else if (sym
>= XK_lstroke
&& sym
<= XK_sacute
)
863 *upper
-= (XK_lstroke
- XK_Lstroke
);
864 else if (sym
>= XK_scaron
&& sym
<= XK_zacute
)
865 *upper
-= (XK_scaron
- XK_Scaron
);
866 else if (sym
>= XK_zcaron
&& sym
<= XK_zabovedot
)
867 *upper
-= (XK_zcaron
- XK_Zcaron
);
868 else if (sym
>= XK_Racute
&& sym
<= XK_Tcedilla
)
869 *lower
+= (XK_racute
- XK_Racute
);
870 else if (sym
>= XK_racute
&& sym
<= XK_tcedilla
)
871 *upper
-= (XK_racute
- XK_Racute
);
873 case 2: /* Latin 3 */
874 /* Assume the KeySym is a legal value (ignore discontinuities) */
875 if (sym
>= XK_Hstroke
&& sym
<= XK_Hcircumflex
)
876 *lower
+= (XK_hstroke
- XK_Hstroke
);
877 else if (sym
>= XK_Gbreve
&& sym
<= XK_Jcircumflex
)
878 *lower
+= (XK_gbreve
- XK_Gbreve
);
879 else if (sym
>= XK_hstroke
&& sym
<= XK_hcircumflex
)
880 *upper
-= (XK_hstroke
- XK_Hstroke
);
881 else if (sym
>= XK_gbreve
&& sym
<= XK_jcircumflex
)
882 *upper
-= (XK_gbreve
- XK_Gbreve
);
883 else if (sym
>= XK_Cabovedot
&& sym
<= XK_Scircumflex
)
884 *lower
+= (XK_cabovedot
- XK_Cabovedot
);
885 else if (sym
>= XK_cabovedot
&& sym
<= XK_scircumflex
)
886 *upper
-= (XK_cabovedot
- XK_Cabovedot
);
888 case 3: /* Latin 4 */
889 /* Assume the KeySym is a legal value (ignore discontinuities) */
890 if (sym
>= XK_Rcedilla
&& sym
<= XK_Tslash
)
891 *lower
+= (XK_rcedilla
- XK_Rcedilla
);
892 else if (sym
>= XK_rcedilla
&& sym
<= XK_tslash
)
893 *upper
-= (XK_rcedilla
- XK_Rcedilla
);
894 else if (sym
== XK_ENG
)
896 else if (sym
== XK_eng
)
898 else if (sym
>= XK_Amacron
&& sym
<= XK_Umacron
)
899 *lower
+= (XK_amacron
- XK_Amacron
);
900 else if (sym
>= XK_amacron
&& sym
<= XK_umacron
)
901 *upper
-= (XK_amacron
- XK_Amacron
);
903 case 6: /* Cyrillic */
904 /* Assume the KeySym is a legal value (ignore discontinuities) */
905 if (sym
>= XK_Serbian_DJE
&& sym
<= XK_Serbian_DZE
)
906 *lower
-= (XK_Serbian_DJE
- XK_Serbian_dje
);
907 else if (sym
>= XK_Serbian_dje
&& sym
<= XK_Serbian_dze
)
908 *upper
+= (XK_Serbian_DJE
- XK_Serbian_dje
);
909 else if (sym
>= XK_Cyrillic_YU
&& sym
<= XK_Cyrillic_HARDSIGN
)
910 *lower
-= (XK_Cyrillic_YU
- XK_Cyrillic_yu
);
911 else if (sym
>= XK_Cyrillic_yu
&& sym
<= XK_Cyrillic_hardsign
)
912 *upper
+= (XK_Cyrillic_YU
- XK_Cyrillic_yu
);
915 /* Assume the KeySym is a legal value (ignore discontinuities) */
916 if (sym
>= XK_Greek_ALPHAaccent
&& sym
<= XK_Greek_OMEGAaccent
)
917 *lower
+= (XK_Greek_alphaaccent
- XK_Greek_ALPHAaccent
);
918 else if (sym
>= XK_Greek_alphaaccent
&& sym
<= XK_Greek_omegaaccent
&&
919 sym
!= XK_Greek_iotaaccentdieresis
&&
920 sym
!= XK_Greek_upsilonaccentdieresis
)
921 *upper
-= (XK_Greek_alphaaccent
- XK_Greek_ALPHAaccent
);
922 else if (sym
>= XK_Greek_ALPHA
&& sym
<= XK_Greek_OMEGA
)
923 *lower
+= (XK_Greek_alpha
- XK_Greek_ALPHA
);
924 else if (sym
>= XK_Greek_alpha
&& sym
<= XK_Greek_omega
&&
925 sym
!= XK_Greek_finalsmallsigma
)
926 *upper
-= (XK_Greek_alpha
- XK_Greek_ALPHA
);
932 _XkbCopyClientMap(XkbDescPtr src
, XkbDescPtr dst
)
936 XkbKeyTypePtr stype
= NULL
, dtype
= NULL
;
941 tmp
= calloc(1, sizeof(XkbClientMapRec
));
947 if (src
->map
->syms
) {
948 if (src
->map
->size_syms
!= dst
->map
->size_syms
) {
949 tmp
= realloc(dst
->map
->syms
,
950 src
->map
->size_syms
* sizeof(KeySym
));
953 dst
->map
->syms
= tmp
;
956 memcpy(dst
->map
->syms
, src
->map
->syms
,
957 src
->map
->size_syms
* sizeof(KeySym
));
960 free(dst
->map
->syms
);
961 dst
->map
->syms
= NULL
;
963 dst
->map
->num_syms
= src
->map
->num_syms
;
964 dst
->map
->size_syms
= src
->map
->size_syms
;
966 if (src
->map
->key_sym_map
) {
967 if (src
->max_key_code
!= dst
->max_key_code
) {
968 tmp
= realloc(dst
->map
->key_sym_map
,
969 (src
->max_key_code
+ 1) * sizeof(XkbSymMapRec
));
972 dst
->map
->key_sym_map
= tmp
;
974 memcpy(dst
->map
->key_sym_map
, src
->map
->key_sym_map
,
975 (src
->max_key_code
+ 1) * sizeof(XkbSymMapRec
));
978 free(dst
->map
->key_sym_map
);
979 dst
->map
->key_sym_map
= NULL
;
982 if (src
->map
->types
&& src
->map
->num_types
) {
983 if (src
->map
->num_types
> dst
->map
->size_types
||
984 !dst
->map
->types
|| !dst
->map
->size_types
) {
985 if (dst
->map
->types
&& dst
->map
->size_types
) {
986 tmp
= realloc(dst
->map
->types
,
987 src
->map
->num_types
* sizeof(XkbKeyTypeRec
));
990 dst
->map
->types
= tmp
;
991 memset(dst
->map
->types
+ dst
->map
->num_types
, 0,
992 (src
->map
->num_types
- dst
->map
->num_types
) *
993 sizeof(XkbKeyTypeRec
));
996 tmp
= calloc(src
->map
->num_types
, sizeof(XkbKeyTypeRec
));
999 dst
->map
->types
= tmp
;
1002 else if (src
->map
->num_types
< dst
->map
->num_types
&&
1004 for (i
= src
->map
->num_types
, dtype
= (dst
->map
->types
+ i
);
1005 i
< dst
->map
->num_types
; i
++, dtype
++) {
1006 free(dtype
->level_names
);
1007 dtype
->level_names
= NULL
;
1008 dtype
->num_levels
= 0;
1009 if (dtype
->map_count
) {
1011 free(dtype
->preserve
);
1016 stype
= src
->map
->types
;
1017 dtype
= dst
->map
->types
;
1018 for (i
= 0; i
< src
->map
->num_types
; i
++, dtype
++, stype
++) {
1019 if (stype
->num_levels
&& stype
->level_names
) {
1020 if (stype
->num_levels
!= dtype
->num_levels
&&
1021 dtype
->num_levels
&& dtype
->level_names
&&
1022 i
< dst
->map
->num_types
) {
1023 tmp
= realloc(dtype
->level_names
,
1024 stype
->num_levels
* sizeof(Atom
));
1027 dtype
->level_names
= tmp
;
1029 else if (!dtype
->num_levels
|| !dtype
->level_names
||
1030 i
>= dst
->map
->num_types
) {
1031 tmp
= malloc(stype
->num_levels
* sizeof(Atom
));
1034 dtype
->level_names
= tmp
;
1036 dtype
->num_levels
= stype
->num_levels
;
1037 memcpy(dtype
->level_names
, stype
->level_names
,
1038 stype
->num_levels
* sizeof(Atom
));
1041 if (dtype
->num_levels
&& dtype
->level_names
&&
1042 i
< dst
->map
->num_types
)
1043 free(dtype
->level_names
);
1044 dtype
->num_levels
= 0;
1045 dtype
->level_names
= NULL
;
1048 dtype
->name
= stype
->name
;
1049 memcpy(&dtype
->mods
, &stype
->mods
, sizeof(XkbModsRec
));
1051 if (stype
->map_count
) {
1053 if (stype
->map_count
!= dtype
->map_count
&&
1054 dtype
->map_count
&& dtype
->map
&&
1055 i
< dst
->map
->num_types
) {
1056 tmp
= realloc(dtype
->map
,
1058 sizeof(XkbKTMapEntryRec
));
1063 else if (!dtype
->map_count
|| !dtype
->map
||
1064 i
>= dst
->map
->num_types
) {
1065 tmp
= malloc(stype
->map_count
*
1066 sizeof(XkbKTMapEntryRec
));
1072 memcpy(dtype
->map
, stype
->map
,
1073 stype
->map_count
* sizeof(XkbKTMapEntryRec
));
1076 if (dtype
->map
&& i
< dst
->map
->num_types
)
1081 if (stype
->preserve
) {
1082 if (stype
->map_count
!= dtype
->map_count
&&
1083 dtype
->map_count
&& dtype
->preserve
&&
1084 i
< dst
->map
->num_types
) {
1085 tmp
= realloc(dtype
->preserve
,
1087 sizeof(XkbModsRec
));
1090 dtype
->preserve
= tmp
;
1092 else if (!dtype
->preserve
|| !dtype
->map_count
||
1093 i
>= dst
->map
->num_types
) {
1094 tmp
= malloc(stype
->map_count
* sizeof(XkbModsRec
));
1097 dtype
->preserve
= tmp
;
1100 memcpy(dtype
->preserve
, stype
->preserve
,
1101 stype
->map_count
* sizeof(XkbModsRec
));
1104 if (dtype
->preserve
&& i
< dst
->map
->num_types
)
1105 free(dtype
->preserve
);
1106 dtype
->preserve
= NULL
;
1109 dtype
->map_count
= stype
->map_count
;
1112 if (dtype
->map_count
&& i
< dst
->map
->num_types
) {
1114 free(dtype
->preserve
);
1116 dtype
->map_count
= 0;
1118 dtype
->preserve
= NULL
;
1122 dst
->map
->size_types
= src
->map
->num_types
;
1123 dst
->map
->num_types
= src
->map
->num_types
;
1126 if (dst
->map
->types
) {
1127 for (i
= 0, dtype
= dst
->map
->types
; i
< dst
->map
->num_types
;
1129 free(dtype
->level_names
);
1130 if (dtype
->map
&& dtype
->map_count
)
1132 if (dtype
->preserve
&& dtype
->map_count
)
1133 free(dtype
->preserve
);
1136 free(dst
->map
->types
);
1137 dst
->map
->types
= NULL
;
1138 dst
->map
->num_types
= 0;
1139 dst
->map
->size_types
= 0;
1142 if (src
->map
->modmap
) {
1143 if (src
->max_key_code
!= dst
->max_key_code
) {
1144 tmp
= realloc(dst
->map
->modmap
, src
->max_key_code
+ 1);
1147 dst
->map
->modmap
= tmp
;
1149 memcpy(dst
->map
->modmap
, src
->map
->modmap
, src
->max_key_code
+ 1);
1152 free(dst
->map
->modmap
);
1153 dst
->map
->modmap
= NULL
;
1158 XkbFreeClientMap(dst
, XkbAllClientInfoMask
, TRUE
);
1165 _XkbCopyServerMap(XkbDescPtr src
, XkbDescPtr dst
)
1172 tmp
= calloc(1, sizeof(XkbServerMapRec
));
1178 if (src
->server
->explicit) {
1179 if (src
->max_key_code
!= dst
->max_key_code
) {
1180 tmp
= realloc(dst
->server
->explicit, src
->max_key_code
+ 1);
1183 dst
->server
->explicit = tmp
;
1185 memcpy(dst
->server
->explicit, src
->server
->explicit,
1186 src
->max_key_code
+ 1);
1189 free(dst
->server
->explicit);
1190 dst
->server
->explicit = NULL
;
1193 if (src
->server
->acts
) {
1194 if (src
->server
->size_acts
!= dst
->server
->size_acts
) {
1195 tmp
= realloc(dst
->server
->acts
,
1196 src
->server
->size_acts
* sizeof(XkbAction
));
1199 dst
->server
->acts
= tmp
;
1201 memcpy(dst
->server
->acts
, src
->server
->acts
,
1202 src
->server
->size_acts
* sizeof(XkbAction
));
1205 free(dst
->server
->acts
);
1206 dst
->server
->acts
= NULL
;
1208 dst
->server
->size_acts
= src
->server
->size_acts
;
1209 dst
->server
->num_acts
= src
->server
->num_acts
;
1211 if (src
->server
->key_acts
) {
1212 if (src
->max_key_code
!= dst
->max_key_code
) {
1213 tmp
= realloc(dst
->server
->key_acts
,
1214 (src
->max_key_code
+ 1) * sizeof(unsigned short));
1217 dst
->server
->key_acts
= tmp
;
1219 memcpy(dst
->server
->key_acts
, src
->server
->key_acts
,
1220 (src
->max_key_code
+ 1) * sizeof(unsigned short));
1223 free(dst
->server
->key_acts
);
1224 dst
->server
->key_acts
= NULL
;
1227 if (src
->server
->behaviors
) {
1228 if (src
->max_key_code
!= dst
->max_key_code
) {
1229 tmp
= realloc(dst
->server
->behaviors
,
1230 (src
->max_key_code
+ 1) * sizeof(XkbBehavior
));
1233 dst
->server
->behaviors
= tmp
;
1235 memcpy(dst
->server
->behaviors
, src
->server
->behaviors
,
1236 (src
->max_key_code
+ 1) * sizeof(XkbBehavior
));
1239 free(dst
->server
->behaviors
);
1240 dst
->server
->behaviors
= NULL
;
1243 memcpy(dst
->server
->vmods
, src
->server
->vmods
, XkbNumVirtualMods
);
1245 if (src
->server
->vmodmap
) {
1246 if (src
->max_key_code
!= dst
->max_key_code
) {
1247 tmp
= realloc(dst
->server
->vmodmap
,
1248 (src
->max_key_code
+ 1) * sizeof(unsigned short));
1251 dst
->server
->vmodmap
= tmp
;
1253 memcpy(dst
->server
->vmodmap
, src
->server
->vmodmap
,
1254 (src
->max_key_code
+ 1) * sizeof(unsigned short));
1257 free(dst
->server
->vmodmap
);
1258 dst
->server
->vmodmap
= NULL
;
1263 XkbFreeServerMap(dst
, XkbAllServerInfoMask
, TRUE
);
1270 _XkbCopyNames(XkbDescPtr src
, XkbDescPtr dst
)
1277 dst
->names
= calloc(1, sizeof(XkbNamesRec
));
1282 if (src
->names
->keys
) {
1283 if (src
->max_key_code
!= dst
->max_key_code
) {
1284 tmp
= realloc(dst
->names
->keys
,
1285 (src
->max_key_code
+ 1) * sizeof(XkbKeyNameRec
));
1288 dst
->names
->keys
= tmp
;
1290 memcpy(dst
->names
->keys
, src
->names
->keys
,
1291 (src
->max_key_code
+ 1) * sizeof(XkbKeyNameRec
));
1294 free(dst
->names
->keys
);
1295 dst
->names
->keys
= NULL
;
1298 if (src
->names
->num_key_aliases
) {
1299 if (src
->names
->num_key_aliases
!= dst
->names
->num_key_aliases
) {
1300 tmp
= realloc(dst
->names
->key_aliases
,
1301 src
->names
->num_key_aliases
*
1302 sizeof(XkbKeyAliasRec
));
1305 dst
->names
->key_aliases
= tmp
;
1307 memcpy(dst
->names
->key_aliases
, src
->names
->key_aliases
,
1308 src
->names
->num_key_aliases
* sizeof(XkbKeyAliasRec
));
1311 free(dst
->names
->key_aliases
);
1312 dst
->names
->key_aliases
= NULL
;
1314 dst
->names
->num_key_aliases
= src
->names
->num_key_aliases
;
1316 if (src
->names
->num_rg
) {
1317 if (src
->names
->num_rg
!= dst
->names
->num_rg
) {
1318 tmp
= realloc(dst
->names
->radio_groups
,
1319 src
->names
->num_rg
* sizeof(Atom
));
1322 dst
->names
->radio_groups
= tmp
;
1324 memcpy(dst
->names
->radio_groups
, src
->names
->radio_groups
,
1325 src
->names
->num_rg
* sizeof(Atom
));
1328 free(dst
->names
->radio_groups
);
1330 dst
->names
->num_rg
= src
->names
->num_rg
;
1332 dst
->names
->keycodes
= src
->names
->keycodes
;
1333 dst
->names
->geometry
= src
->names
->geometry
;
1334 dst
->names
->symbols
= src
->names
->symbols
;
1335 dst
->names
->types
= src
->names
->types
;
1336 dst
->names
->compat
= src
->names
->compat
;
1337 dst
->names
->phys_symbols
= src
->names
->phys_symbols
;
1339 memcpy(dst
->names
->vmods
, src
->names
->vmods
,
1340 XkbNumVirtualMods
* sizeof(Atom
));
1341 memcpy(dst
->names
->indicators
, src
->names
->indicators
,
1342 XkbNumIndicators
* sizeof(Atom
));
1343 memcpy(dst
->names
->groups
, src
->names
->groups
,
1344 XkbNumKbdGroups
* sizeof(Atom
));
1348 XkbFreeNames(dst
, XkbAllNamesMask
, TRUE
);
1355 _XkbCopyCompat(XkbDescPtr src
, XkbDescPtr dst
)
1362 dst
->compat
= calloc(1, sizeof(XkbCompatMapRec
));
1367 if (src
->compat
->sym_interpret
&& src
->compat
->num_si
) {
1368 if (src
->compat
->num_si
!= dst
->compat
->size_si
) {
1369 tmp
= realloc(dst
->compat
->sym_interpret
,
1370 src
->compat
->num_si
* sizeof(XkbSymInterpretRec
));
1373 dst
->compat
->sym_interpret
= tmp
;
1375 memcpy(dst
->compat
->sym_interpret
, src
->compat
->sym_interpret
,
1376 src
->compat
->num_si
* sizeof(XkbSymInterpretRec
));
1378 dst
->compat
->num_si
= src
->compat
->num_si
;
1379 dst
->compat
->size_si
= src
->compat
->num_si
;
1382 if (dst
->compat
->sym_interpret
&& dst
->compat
->size_si
)
1383 free(dst
->compat
->sym_interpret
);
1385 dst
->compat
->sym_interpret
= NULL
;
1386 dst
->compat
->num_si
= 0;
1387 dst
->compat
->size_si
= 0;
1390 memcpy(dst
->compat
->groups
, src
->compat
->groups
,
1391 XkbNumKbdGroups
* sizeof(XkbModsRec
));
1395 XkbFreeCompatMap(dst
, XkbAllCompatMask
, TRUE
);
1402 _XkbCopyGeom(XkbDescPtr src
, XkbDescPtr dst
)
1405 int i
= 0, j
= 0, k
= 0;
1406 XkbColorPtr scolor
= NULL
, dcolor
= NULL
;
1407 XkbDoodadPtr sdoodad
= NULL
, ddoodad
= NULL
;
1408 XkbOutlinePtr soutline
= NULL
, doutline
= NULL
;
1409 XkbPropertyPtr sprop
= NULL
, dprop
= NULL
;
1410 XkbRowPtr srow
= NULL
, drow
= NULL
;
1411 XkbSectionPtr ssection
= NULL
, dsection
= NULL
;
1412 XkbShapePtr sshape
= NULL
, dshape
= NULL
;
1417 dst
->geom
= calloc(sizeof(XkbGeometryRec
), 1);
1423 if (src
->geom
->num_properties
) {
1424 /* If we've got more properties in the destination than
1425 * the source, run through and free all the excess ones
1427 if (src
->geom
->num_properties
< dst
->geom
->sz_properties
) {
1428 for (i
= src
->geom
->num_properties
, dprop
=
1429 dst
->geom
->properties
+ i
; i
< dst
->geom
->num_properties
;
1436 /* Reallocate and clear all new items if the buffer grows. */
1438 ((void **) &dst
->geom
->properties
, dst
->geom
->sz_properties
,
1439 src
->geom
->num_properties
, sizeof(XkbPropertyRec
),
1440 XKB_GEOM_CLEAR_EXCESS
))
1442 /* We don't set num_properties as we need it to try and avoid
1443 * too much reallocing. */
1444 dst
->geom
->sz_properties
= src
->geom
->num_properties
;
1447 sprop
= src
->geom
->properties
,
1448 dprop
= dst
->geom
->properties
;
1449 i
< src
->geom
->num_properties
; i
++, sprop
++, dprop
++) {
1450 if (i
< dst
->geom
->num_properties
) {
1451 if (strlen(sprop
->name
) != strlen(dprop
->name
)) {
1452 tmp
= realloc(dprop
->name
, strlen(sprop
->name
) + 1);
1457 if (strlen(sprop
->value
) != strlen(dprop
->value
)) {
1458 tmp
= realloc(dprop
->value
, strlen(sprop
->value
) + 1);
1463 strcpy(dprop
->name
, sprop
->name
);
1464 strcpy(dprop
->value
, sprop
->value
);
1467 dprop
->name
= xstrdup(sprop
->name
);
1468 dprop
->value
= xstrdup(sprop
->value
);
1472 /* ... which is already src->geom->num_properties. */
1473 dst
->geom
->num_properties
= dst
->geom
->sz_properties
;
1476 if (dst
->geom
->sz_properties
) {
1477 for (i
= 0, dprop
= dst
->geom
->properties
;
1478 i
< dst
->geom
->num_properties
; i
++, dprop
++) {
1482 free(dst
->geom
->properties
);
1483 dst
->geom
->properties
= NULL
;
1486 dst
->geom
->num_properties
= 0;
1487 dst
->geom
->sz_properties
= 0;
1491 if (src
->geom
->num_colors
) {
1492 if (src
->geom
->num_colors
< dst
->geom
->sz_colors
) {
1493 for (i
= src
->geom
->num_colors
, dcolor
= dst
->geom
->colors
+ i
;
1494 i
< dst
->geom
->num_colors
; i
++, dcolor
++) {
1499 /* Reallocate and clear all new items if the buffer grows. */
1501 ((void **) &dst
->geom
->colors
, dst
->geom
->sz_colors
,
1502 src
->geom
->num_colors
, sizeof(XkbColorRec
),
1503 XKB_GEOM_CLEAR_EXCESS
))
1505 dst
->geom
->sz_colors
= src
->geom
->num_colors
;
1508 scolor
= src
->geom
->colors
,
1509 dcolor
= dst
->geom
->colors
;
1510 i
< src
->geom
->num_colors
; i
++, scolor
++, dcolor
++) {
1511 if (i
< dst
->geom
->num_colors
) {
1512 if (strlen(scolor
->spec
) != strlen(dcolor
->spec
)) {
1513 tmp
= realloc(dcolor
->spec
, strlen(scolor
->spec
) + 1);
1518 strcpy(dcolor
->spec
, scolor
->spec
);
1521 dcolor
->spec
= xstrdup(scolor
->spec
);
1523 dcolor
->pixel
= scolor
->pixel
;
1526 dst
->geom
->num_colors
= dst
->geom
->sz_colors
;
1529 if (dst
->geom
->sz_colors
) {
1530 for (i
= 0, dcolor
= dst
->geom
->colors
;
1531 i
< dst
->geom
->num_colors
; i
++, dcolor
++) {
1534 free(dst
->geom
->colors
);
1535 dst
->geom
->colors
= NULL
;
1538 dst
->geom
->num_colors
= 0;
1539 dst
->geom
->sz_colors
= 0;
1543 /* shapes break down into outlines, which break down into points. */
1544 if (dst
->geom
->num_shapes
) {
1545 for (i
= 0, dshape
= dst
->geom
->shapes
;
1546 i
< dst
->geom
->num_shapes
; i
++, dshape
++) {
1547 for (j
= 0, doutline
= dshape
->outlines
;
1548 j
< dshape
->num_outlines
; j
++, doutline
++) {
1549 if (doutline
->sz_points
)
1550 free(doutline
->points
);
1553 if (dshape
->sz_outlines
) {
1554 free(dshape
->outlines
);
1555 dshape
->outlines
= NULL
;
1558 dshape
->num_outlines
= 0;
1559 dshape
->sz_outlines
= 0;
1563 if (src
->geom
->num_shapes
) {
1564 /* Reallocate and clear all items. */
1566 ((void **) &dst
->geom
->shapes
, dst
->geom
->sz_shapes
,
1567 src
->geom
->num_shapes
, sizeof(XkbShapeRec
),
1568 XKB_GEOM_CLEAR_ALL
))
1571 for (i
= 0, sshape
= src
->geom
->shapes
, dshape
= dst
->geom
->shapes
;
1572 i
< src
->geom
->num_shapes
; i
++, sshape
++, dshape
++) {
1573 if (sshape
->num_outlines
) {
1574 tmp
= calloc(sshape
->num_outlines
, sizeof(XkbOutlineRec
));
1577 dshape
->outlines
= tmp
;
1580 soutline
= sshape
->outlines
,
1581 doutline
= dshape
->outlines
;
1582 j
< sshape
->num_outlines
;
1583 j
++, soutline
++, doutline
++) {
1584 if (soutline
->num_points
) {
1585 tmp
= malloc(soutline
->num_points
*
1586 sizeof(XkbPointRec
));
1589 doutline
->points
= tmp
;
1591 memcpy(doutline
->points
, soutline
->points
,
1592 soutline
->num_points
* sizeof(XkbPointRec
));
1594 doutline
->corner_radius
= soutline
->corner_radius
;
1597 doutline
->num_points
= soutline
->num_points
;
1598 doutline
->sz_points
= soutline
->num_points
;
1602 dshape
->num_outlines
= sshape
->num_outlines
;
1603 dshape
->sz_outlines
= sshape
->num_outlines
;
1604 dshape
->name
= sshape
->name
;
1605 dshape
->bounds
= sshape
->bounds
;
1607 dshape
->approx
= NULL
;
1608 if (sshape
->approx
&& sshape
->num_outlines
> 0) {
1610 const ptrdiff_t approx_idx
=
1611 sshape
->approx
- sshape
->outlines
;
1613 if (approx_idx
< dshape
->num_outlines
) {
1614 dshape
->approx
= dshape
->outlines
+ approx_idx
;
1617 LogMessage(X_WARNING
, "XKB: approx outline "
1618 "index is out of range\n");
1622 dshape
->primary
= NULL
;
1623 if (sshape
->primary
&& sshape
->num_outlines
> 0) {
1625 const ptrdiff_t primary_idx
=
1626 sshape
->primary
- sshape
->outlines
;
1628 if (primary_idx
< dshape
->num_outlines
) {
1629 dshape
->primary
= dshape
->outlines
+ primary_idx
;
1632 LogMessage(X_WARNING
, "XKB: primary outline "
1633 "index is out of range\n");
1638 dst
->geom
->num_shapes
= src
->geom
->num_shapes
;
1639 dst
->geom
->sz_shapes
= src
->geom
->num_shapes
;
1642 if (dst
->geom
->sz_shapes
) {
1643 free(dst
->geom
->shapes
);
1645 dst
->geom
->shapes
= NULL
;
1646 dst
->geom
->num_shapes
= 0;
1647 dst
->geom
->sz_shapes
= 0;
1651 /* sections break down into doodads, and also into rows, which break
1652 * down into keys. */
1653 if (dst
->geom
->num_sections
) {
1654 for (i
= 0, dsection
= dst
->geom
->sections
;
1655 i
< dst
->geom
->num_sections
; i
++, dsection
++) {
1656 for (j
= 0, drow
= dsection
->rows
;
1657 j
< dsection
->num_rows
; j
++, drow
++) {
1662 if (dsection
->num_rows
)
1663 free(dsection
->rows
);
1665 /* cut and waste from geom/doodad below. */
1666 for (j
= 0, ddoodad
= dsection
->doodads
;
1667 j
< dsection
->num_doodads
; j
++, ddoodad
++) {
1668 if (ddoodad
->any
.type
== XkbTextDoodad
) {
1669 free(ddoodad
->text
.text
);
1670 ddoodad
->text
.text
= NULL
;
1671 free(ddoodad
->text
.font
);
1672 ddoodad
->text
.font
= NULL
;
1674 else if (ddoodad
->any
.type
== XkbLogoDoodad
) {
1675 free(ddoodad
->logo
.logo_name
);
1676 ddoodad
->logo
.logo_name
= NULL
;
1680 free(dsection
->doodads
);
1683 dst
->geom
->num_sections
= 0;
1686 if (src
->geom
->num_sections
) {
1687 /* Reallocate and clear all items. */
1689 ((void **) &dst
->geom
->sections
, dst
->geom
->sz_sections
,
1690 src
->geom
->num_sections
, sizeof(XkbSectionRec
),
1691 XKB_GEOM_CLEAR_ALL
))
1693 dst
->geom
->num_sections
= src
->geom
->num_sections
;
1694 dst
->geom
->sz_sections
= src
->geom
->num_sections
;
1697 ssection
= src
->geom
->sections
,
1698 dsection
= dst
->geom
->sections
;
1699 i
< src
->geom
->num_sections
; i
++, ssection
++, dsection
++) {
1700 *dsection
= *ssection
;
1701 if (ssection
->num_rows
) {
1702 tmp
= calloc(ssection
->num_rows
, sizeof(XkbRowRec
));
1705 dsection
->rows
= tmp
;
1707 dsection
->num_rows
= ssection
->num_rows
;
1708 dsection
->sz_rows
= ssection
->num_rows
;
1710 for (j
= 0, srow
= ssection
->rows
, drow
= dsection
->rows
;
1711 j
< ssection
->num_rows
; j
++, srow
++, drow
++) {
1712 if (srow
->num_keys
) {
1713 tmp
= malloc(srow
->num_keys
* sizeof(XkbKeyRec
));
1717 memcpy(drow
->keys
, srow
->keys
,
1718 srow
->num_keys
* sizeof(XkbKeyRec
));
1720 drow
->num_keys
= srow
->num_keys
;
1721 drow
->sz_keys
= srow
->num_keys
;
1722 drow
->top
= srow
->top
;
1723 drow
->left
= srow
->left
;
1724 drow
->vertical
= srow
->vertical
;
1725 drow
->bounds
= srow
->bounds
;
1728 if (ssection
->num_doodads
) {
1729 tmp
= calloc(ssection
->num_doodads
, sizeof(XkbDoodadRec
));
1732 dsection
->doodads
= tmp
;
1735 dsection
->doodads
= NULL
;
1738 dsection
->sz_doodads
= ssection
->num_doodads
;
1740 sdoodad
= ssection
->doodads
,
1741 ddoodad
= dsection
->doodads
;
1742 k
< ssection
->num_doodads
; k
++, sdoodad
++, ddoodad
++) {
1743 memcpy(ddoodad
, sdoodad
, sizeof(XkbDoodadRec
));
1744 if (sdoodad
->any
.type
== XkbTextDoodad
) {
1745 if (sdoodad
->text
.text
)
1746 ddoodad
->text
.text
= strdup(sdoodad
->text
.text
);
1747 if (sdoodad
->text
.font
)
1748 ddoodad
->text
.font
= strdup(sdoodad
->text
.font
);
1750 else if (sdoodad
->any
.type
== XkbLogoDoodad
) {
1751 if (sdoodad
->logo
.logo_name
)
1752 ddoodad
->logo
.logo_name
=
1753 strdup(sdoodad
->logo
.logo_name
);
1756 dsection
->overlays
= NULL
;
1757 dsection
->sz_overlays
= 0;
1758 dsection
->num_overlays
= 0;
1762 if (dst
->geom
->sz_sections
) {
1763 free(dst
->geom
->sections
);
1766 dst
->geom
->sections
= NULL
;
1767 dst
->geom
->num_sections
= 0;
1768 dst
->geom
->sz_sections
= 0;
1772 if (dst
->geom
->num_doodads
) {
1773 for (i
= src
->geom
->num_doodads
,
1774 ddoodad
= dst
->geom
->doodads
+
1775 src
->geom
->num_doodads
;
1776 i
< dst
->geom
->num_doodads
; i
++, ddoodad
++) {
1777 if (ddoodad
->any
.type
== XkbTextDoodad
) {
1778 free(ddoodad
->text
.text
);
1779 ddoodad
->text
.text
= NULL
;
1780 free(ddoodad
->text
.font
);
1781 ddoodad
->text
.font
= NULL
;
1783 else if (ddoodad
->any
.type
== XkbLogoDoodad
) {
1784 free(ddoodad
->logo
.logo_name
);
1785 ddoodad
->logo
.logo_name
= NULL
;
1788 dst
->geom
->num_doodads
= 0;
1791 if (src
->geom
->num_doodads
) {
1792 /* Reallocate and clear all items. */
1794 ((void **) &dst
->geom
->doodads
, dst
->geom
->sz_doodads
,
1795 src
->geom
->num_doodads
, sizeof(XkbDoodadRec
),
1796 XKB_GEOM_CLEAR_ALL
))
1799 dst
->geom
->sz_doodads
= src
->geom
->num_doodads
;
1802 sdoodad
= src
->geom
->doodads
,
1803 ddoodad
= dst
->geom
->doodads
;
1804 i
< src
->geom
->num_doodads
; i
++, sdoodad
++, ddoodad
++) {
1805 memcpy(ddoodad
, sdoodad
, sizeof(XkbDoodadRec
));
1806 if (sdoodad
->any
.type
== XkbTextDoodad
) {
1807 if (sdoodad
->text
.text
)
1808 ddoodad
->text
.text
= strdup(sdoodad
->text
.text
);
1809 if (sdoodad
->text
.font
)
1810 ddoodad
->text
.font
= strdup(sdoodad
->text
.font
);
1812 else if (sdoodad
->any
.type
== XkbLogoDoodad
) {
1813 if (sdoodad
->logo
.logo_name
)
1814 ddoodad
->logo
.logo_name
=
1815 strdup(sdoodad
->logo
.logo_name
);
1819 dst
->geom
->num_doodads
= dst
->geom
->sz_doodads
;
1822 if (dst
->geom
->sz_doodads
) {
1823 free(dst
->geom
->doodads
);
1826 dst
->geom
->doodads
= NULL
;
1827 dst
->geom
->num_doodads
= 0;
1828 dst
->geom
->sz_doodads
= 0;
1832 if (src
->geom
->num_key_aliases
) {
1833 /* Reallocate but don't clear any items. There is no need
1834 * to clear anything because data is immediately copied
1835 * over the whole memory area with memcpy. */
1837 ((void **) &dst
->geom
->key_aliases
, dst
->geom
->sz_key_aliases
,
1838 src
->geom
->num_key_aliases
, 2 * XkbKeyNameLength
,
1839 XKB_GEOM_CLEAR_NONE
))
1842 dst
->geom
->sz_key_aliases
= src
->geom
->num_key_aliases
;
1844 memcpy(dst
->geom
->key_aliases
, src
->geom
->key_aliases
,
1845 src
->geom
->num_key_aliases
* 2 * XkbKeyNameLength
);
1847 dst
->geom
->num_key_aliases
= dst
->geom
->sz_key_aliases
;
1850 free(dst
->geom
->key_aliases
);
1851 dst
->geom
->key_aliases
= NULL
;
1852 dst
->geom
->num_key_aliases
= 0;
1853 dst
->geom
->sz_key_aliases
= 0;
1857 if (src
->geom
->label_font
) {
1858 if (!dst
->geom
->label_font
) {
1859 tmp
= malloc(strlen(src
->geom
->label_font
) + 1);
1862 dst
->geom
->label_font
= tmp
;
1864 else if (strlen(src
->geom
->label_font
) !=
1865 strlen(dst
->geom
->label_font
)) {
1866 tmp
= realloc(dst
->geom
->label_font
,
1867 strlen(src
->geom
->label_font
) + 1);
1870 dst
->geom
->label_font
= tmp
;
1873 strcpy(dst
->geom
->label_font
, src
->geom
->label_font
);
1874 i
= XkbGeomColorIndex(src
->geom
, src
->geom
->label_color
);
1875 dst
->geom
->label_color
= &(dst
->geom
->colors
[i
]);
1876 i
= XkbGeomColorIndex(src
->geom
, src
->geom
->base_color
);
1877 dst
->geom
->base_color
= &(dst
->geom
->colors
[i
]);
1880 free(dst
->geom
->label_font
);
1881 dst
->geom
->label_font
= NULL
;
1882 dst
->geom
->label_color
= NULL
;
1883 dst
->geom
->base_color
= NULL
;
1886 dst
->geom
->name
= src
->geom
->name
;
1887 dst
->geom
->width_mm
= src
->geom
->width_mm
;
1888 dst
->geom
->height_mm
= src
->geom
->height_mm
;
1892 /* I LOVE THE DIFFERENT CALL SIGNATURE. REALLY, I DO. */
1893 XkbFreeGeometry(dst
->geom
, XkbGeomAllMask
, TRUE
);
1902 _XkbCopyIndicators(XkbDescPtr src
, XkbDescPtr dst
)
1905 if (src
->indicators
) {
1906 if (!dst
->indicators
) {
1907 dst
->indicators
= malloc(sizeof(XkbIndicatorRec
));
1908 if (!dst
->indicators
)
1911 memcpy(dst
->indicators
, src
->indicators
, sizeof(XkbIndicatorRec
));
1914 free(dst
->indicators
);
1915 dst
->indicators
= NULL
;
1921 _XkbCopyControls(XkbDescPtr src
, XkbDescPtr dst
)
1926 dst
->ctrls
= malloc(sizeof(XkbControlsRec
));
1930 memcpy(dst
->ctrls
, src
->ctrls
, sizeof(XkbControlsRec
));
1940 * Copy an XKB map from src to dst, reallocating when necessary: if some
1941 * map components are present in one, but not in the other, the destination
1942 * components will be allocated or freed as necessary.
1944 * Basic map consistency is assumed on both sides, so maps with random
1945 * uninitialised data (e.g. names->radio_grous == NULL, names->num_rg == 19)
1946 * _will_ cause failures. You've been warned.
1948 * Returns TRUE on success, or FALSE on failure. If this function fails,
1949 * dst may be in an inconsistent state: all its pointers are guaranteed
1950 * to remain valid, but part of the map may be from src and part from dst.
1955 XkbCopyKeymap(XkbDescPtr dst
, XkbDescPtr src
)
1959 DebugF("XkbCopyKeymap: src (%p) or dst (%p) is NULL\n", src
, dst
);
1966 if (!_XkbCopyClientMap(src
, dst
)) {
1967 DebugF("XkbCopyKeymap: failed to copy client map\n");
1970 if (!_XkbCopyServerMap(src
, dst
)) {
1971 DebugF("XkbCopyKeymap: failed to copy server map\n");
1974 if (!_XkbCopyIndicators(src
, dst
)) {
1975 DebugF("XkbCopyKeymap: failed to copy indicators\n");
1978 if (!_XkbCopyControls(src
, dst
)) {
1979 DebugF("XkbCopyKeymap: failed to copy controls\n");
1982 if (!_XkbCopyNames(src
, dst
)) {
1983 DebugF("XkbCopyKeymap: failed to copy names\n");
1986 if (!_XkbCopyCompat(src
, dst
)) {
1987 DebugF("XkbCopyKeymap: failed to copy compat map\n");
1990 if (!_XkbCopyGeom(src
, dst
)) {
1991 DebugF("XkbCopyKeymap: failed to copy geometry\n");
1995 dst
->min_key_code
= src
->min_key_code
;
1996 dst
->max_key_code
= src
->max_key_code
;
2002 XkbCopyDeviceKeymap(DeviceIntPtr dst
, DeviceIntPtr src
)
2004 xkbNewKeyboardNotify nkn
;
2007 if (!dst
->key
|| !src
->key
)
2010 memset(&nkn
, 0, sizeof(xkbNewKeyboardNotify
));
2011 nkn
.oldMinKeyCode
= dst
->key
->xkbInfo
->desc
->min_key_code
;
2012 nkn
.oldMaxKeyCode
= dst
->key
->xkbInfo
->desc
->max_key_code
;
2013 nkn
.deviceID
= dst
->id
;
2014 nkn
.oldDeviceID
= dst
->id
; /* maybe src->id? */
2015 nkn
.minKeyCode
= src
->key
->xkbInfo
->desc
->min_key_code
;
2016 nkn
.maxKeyCode
= src
->key
->xkbInfo
->desc
->max_key_code
;
2017 nkn
.requestMajor
= XkbReqCode
;
2018 nkn
.requestMinor
= X_kbSetMap
; /* Near enough's good enough. */
2019 nkn
.changed
= XkbNKN_KeycodesMask
;
2020 if (src
->key
->xkbInfo
->desc
->geom
)
2021 nkn
.changed
|= XkbNKN_GeometryMask
;
2023 ret
= XkbCopyKeymap(dst
->key
->xkbInfo
->desc
, src
->key
->xkbInfo
->desc
);
2025 XkbSendNewKeyboardNotify(dst
, &nkn
);
2031 XkbGetEffectiveGroup(XkbSrvInfoPtr xkbi
, XkbStatePtr xkbState
, CARD8 keycode
)
2033 XkbDescPtr xkb
= xkbi
->desc
;
2034 int effectiveGroup
= xkbState
->group
;
2036 if (!XkbKeycodeInRange(xkb
, keycode
))
2039 if (effectiveGroup
== XkbGroup1Index
)
2040 return effectiveGroup
;
2042 if (XkbKeyNumGroups(xkb
, keycode
) > 1U) {
2043 if (effectiveGroup
>= XkbKeyNumGroups(xkb
, keycode
)) {
2044 unsigned int gi
= XkbKeyGroupInfo(xkb
, keycode
);
2046 switch (XkbOutOfRangeGroupAction(gi
)) {
2048 case XkbWrapIntoRange
:
2049 effectiveGroup
%= XkbKeyNumGroups(xkb
, keycode
);
2051 case XkbClampIntoRange
:
2052 effectiveGroup
= XkbKeyNumGroups(xkb
, keycode
) - 1;
2054 case XkbRedirectIntoRange
:
2055 effectiveGroup
= XkbOutOfRangeGroupInfo(gi
);
2056 if (effectiveGroup
>= XkbKeyNumGroups(xkb
, keycode
))
2063 effectiveGroup
= XkbGroup1Index
;
2065 return effectiveGroup
;
2068 /* Merge the lockedPtrButtons from all attached SDs for the given master
2069 * device into the MD's state.
2072 XkbMergeLockedPtrBtns(DeviceIntPtr master
)
2074 DeviceIntPtr d
= inputInfo
.devices
;
2075 XkbSrvInfoPtr xkbi
= NULL
;
2077 if (!IsMaster(master
))
2083 xkbi
= master
->key
->xkbInfo
;
2084 xkbi
->lockedPtrButtons
= 0;
2086 for (; d
; d
= d
->next
) {
2087 if (IsMaster(d
) || GetMaster(d
, MASTER_KEYBOARD
) != master
|| !d
->key
)
2090 xkbi
->lockedPtrButtons
|= d
->key
->xkbInfo
->lockedPtrButtons
;