1 /************************************************************
2 Copyright (c) 1995 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 ********************************************************/
27 #ifdef HAVE_DIX_CONFIG_H
28 #include <dix-config.h>
35 #include <X11/Xproto.h>
39 #include <X11/extensions/XI.h>
43 /***====================================================================***/
47 * XkbIndicatorsToUpdate(dev,changed,check_devs_rtrn)
49 * Given a keyboard and a set of state components that have changed,
50 * this function returns the indicators on the default keyboard
51 * feedback that might be affected. It also reports whether or not
52 * any extension devices might be affected in check_devs_rtrn.
56 XkbIndicatorsToUpdate(DeviceIntPtr dev
,
57 unsigned long state_changes
, Bool enable_changes
)
59 register unsigned update
= 0;
62 sli
= XkbFindSrvLedInfo(dev
, XkbDfltXIClass
, XkbDfltXIId
, 0);
67 if (state_changes
& (XkbModifierStateMask
| XkbGroupStateMask
))
68 update
|= sli
->usesEffective
;
69 if (state_changes
& (XkbModifierBaseMask
| XkbGroupBaseMask
))
70 update
|= sli
->usesBase
;
71 if (state_changes
& (XkbModifierLatchMask
| XkbGroupLatchMask
))
72 update
|= sli
->usesLatched
;
73 if (state_changes
& (XkbModifierLockMask
| XkbGroupLockMask
))
74 update
|= sli
->usesLocked
;
75 if (state_changes
& XkbCompatStateMask
)
76 update
|= sli
->usesCompat
;
78 update
|= sli
->usesControls
;
82 /***====================================================================***/
86 *XkbApplyLEDChangeToKeyboard(xkbi,map,on,change)
88 * Some indicators "drive" the keyboard when their state is explicitly
89 * changed, as described in section 9.2.1 of the XKB protocol spec.
90 * This function updates the state and controls for the keyboard
91 * specified by 'xkbi' to reflect any changes that are required
92 * when the indicator described by 'map' is turned on or off. The
93 * extent of the changes is reported in change, which must be defined.
96 XkbApplyLEDChangeToKeyboard(XkbSrvInfoPtr xkbi
,
97 XkbIndicatorMapPtr map
,
98 Bool on
, XkbChangesPtr change
)
100 Bool ctrlChange
, stateChange
;
103 if ((map
->flags
& XkbIM_NoExplicit
) ||
104 ((map
->flags
& XkbIM_LEDDrivesKB
) == 0))
106 ctrlChange
= stateChange
= FALSE
;
108 XkbControlsPtr ctrls
= xkbi
->desc
->ctrls
;
111 old
= ctrls
->enabled_ctrls
;
113 ctrls
->enabled_ctrls
|= map
->ctrls
;
115 ctrls
->enabled_ctrls
&= ~map
->ctrls
;
116 if (old
!= ctrls
->enabled_ctrls
) {
117 change
->ctrls
.changed_ctrls
= XkbControlsEnabledMask
;
118 change
->ctrls
.enabled_ctrls_changes
= old
^ ctrls
->enabled_ctrls
;
122 state
= &xkbi
->state
;
123 if ((map
->groups
) && ((map
->which_groups
& (~XkbIM_UseBase
)) != 0)) {
125 register unsigned bit
, match
;
128 match
= (map
->groups
) & XkbAllGroupsMask
;
130 match
= (~map
->groups
) & XkbAllGroupsMask
;
131 if (map
->which_groups
& (XkbIM_UseLocked
| XkbIM_UseEffective
)) {
132 for (i
= 0, bit
= 1; i
< XkbNumKbdGroups
; i
++, bit
<<= 1) {
136 if (map
->which_groups
& XkbIM_UseLatched
)
137 XkbLatchGroup(xkbi
->device
, 0); /* unlatch group */
138 state
->locked_group
= i
;
141 else if (map
->which_groups
& (XkbIM_UseLatched
| XkbIM_UseEffective
)) {
142 for (i
= 0, bit
= 1; i
< XkbNumKbdGroups
; i
++, bit
<<= 1) {
146 state
->locked_group
= 0;
147 XkbLatchGroup(xkbi
->device
, i
);
151 if ((map
->mods
.mask
) && ((map
->which_mods
& (~XkbIM_UseBase
)) != 0)) {
152 if (map
->which_mods
& (XkbIM_UseLocked
| XkbIM_UseEffective
)) {
153 register unsigned long old
;
155 old
= state
->locked_mods
;
157 state
->locked_mods
|= map
->mods
.mask
;
159 state
->locked_mods
&= ~map
->mods
.mask
;
160 if (state
->locked_mods
!= old
)
163 if (map
->which_mods
& (XkbIM_UseLatched
| XkbIM_UseEffective
)) {
164 register unsigned long newmods
;
166 newmods
= state
->latched_mods
;
168 newmods
|= map
->mods
.mask
;
170 newmods
&= ~map
->mods
.mask
;
171 if (newmods
!= state
->locked_mods
) {
172 newmods
&= map
->mods
.mask
;
173 XkbLatchModifiers(xkbi
->device
, map
->mods
.mask
, newmods
);
178 return stateChange
|| ctrlChange
;
183 * ComputeAutoState(map,state,ctrls)
185 * This function reports the effect of applying the specified
186 * indicator map given the specified state and controls, as
187 * described in section 9.2 of the XKB protocol specification.
191 ComputeAutoState(XkbIndicatorMapPtr map
,
192 XkbStatePtr state
, XkbControlsPtr ctrls
)
199 if (map
->which_mods
& XkbIM_UseAnyMods
) {
200 if (map
->which_mods
& XkbIM_UseBase
)
201 mods
|= state
->base_mods
;
202 if (map
->which_mods
& XkbIM_UseLatched
)
203 mods
|= state
->latched_mods
;
204 if (map
->which_mods
& XkbIM_UseLocked
)
205 mods
|= state
->locked_mods
;
206 if (map
->which_mods
& XkbIM_UseEffective
)
208 if (map
->which_mods
& XkbIM_UseCompat
)
209 mods
|= state
->compat_state
;
210 on
= ((map
->mods
.mask
& mods
) != 0);
211 on
= on
|| ((mods
== 0) && (map
->mods
.mask
== 0) &&
212 (map
->mods
.vmods
== 0));
214 if (map
->which_groups
& XkbIM_UseAnyGroup
) {
215 if (map
->which_groups
& XkbIM_UseBase
)
216 group
|= (1L << state
->base_group
);
217 if (map
->which_groups
& XkbIM_UseLatched
)
218 group
|= (1L << state
->latched_group
);
219 if (map
->which_groups
& XkbIM_UseLocked
)
220 group
|= (1L << state
->locked_group
);
221 if (map
->which_groups
& XkbIM_UseEffective
)
222 group
|= (1L << state
->group
);
223 on
= on
|| (((map
->groups
& group
) != 0) || (map
->groups
== 0));
226 on
= on
|| (ctrls
->enabled_ctrls
& map
->ctrls
);
231 XkbUpdateLedAutoState(DeviceIntPtr dev
,
232 XkbSrvLedInfoPtr sli
,
233 unsigned maps_to_check
,
234 xkbExtensionDeviceNotify
* ed
,
235 XkbChangesPtr changes
, XkbEventCausePtr cause
)
239 XkbControlsPtr ctrls
;
240 XkbChangesRec my_changes
;
241 xkbExtensionDeviceNotify my_ed
;
242 register unsigned i
, bit
, affected
;
243 register XkbIndicatorMapPtr map
;
246 if ((maps_to_check
== 0) || (sli
->maps
== NULL
) || (sli
->mapsPresent
== 0))
249 if (dev
->key
&& dev
->key
->xkbInfo
)
252 kbd
= inputInfo
.keyboard
;
254 state
= &kbd
->key
->xkbInfo
->state
;
255 ctrls
= kbd
->key
->xkbInfo
->desc
->ctrls
;
256 affected
= maps_to_check
;
257 oldState
= sli
->effectiveState
;
258 sli
->autoState
&= ~affected
;
259 for (i
= 0, bit
= 1; (i
< XkbNumIndicators
) && (affected
); i
++, bit
<<= 1) {
260 if ((affected
& bit
) == 0)
264 if ((!(map
->flags
& XkbIM_NoAutomatic
)) &&
265 ComputeAutoState(map
, state
, ctrls
))
266 sli
->autoState
|= bit
;
268 sli
->effectiveState
= (sli
->autoState
| sli
->explicitState
);
269 affected
= sli
->effectiveState
^ oldState
;
275 memset((char *) ed
, 0, sizeof(xkbExtensionDeviceNotify
));
277 else if ((ed
->reason
& XkbXI_IndicatorsMask
) &&
278 ((ed
->ledClass
!= sli
->class) || (ed
->ledID
!= sli
->id
))) {
279 XkbFlushLedEvents(dev
, kbd
, sli
, ed
, changes
, cause
);
282 if ((kbd
== dev
) && (sli
->flags
& XkbSLI_IsDefault
)) {
283 if (changes
== NULL
) {
284 changes
= &my_changes
;
285 memset((char *) changes
, 0, sizeof(XkbChangesRec
));
287 changes
->indicators
.state_changes
|= affected
;
290 ed
->reason
|= XkbXI_IndicatorStateMask
;
291 ed
->ledClass
= sli
->class;
293 ed
->ledsDefined
= sli
->namesPresent
| sli
->mapsPresent
;
294 ed
->ledState
= sli
->effectiveState
;
296 ed
->supported
= XkbXI_AllFeaturesMask
;
298 if (changes
!= &my_changes
)
303 XkbFlushLedEvents(dev
, kbd
, sli
, ed
, changes
, cause
);
308 XkbUpdateAllDeviceIndicators(XkbChangesPtr changes
, XkbEventCausePtr cause
)
311 XkbSrvLedInfoPtr sli
;
313 for (edev
= inputInfo
.devices
; edev
!= NULL
; edev
= edev
->next
) {
317 for (kf
= edev
->kbdfeed
; kf
!= NULL
; kf
= kf
->next
) {
318 if ((kf
->xkb_sli
== NULL
) || (kf
->xkb_sli
->maps
== NULL
))
321 XkbUpdateLedAutoState(edev
, sli
, sli
->mapsPresent
, NULL
,
329 for (lf
= edev
->leds
; lf
!= NULL
; lf
= lf
->next
) {
330 if ((lf
->xkb_sli
== NULL
) || (lf
->xkb_sli
->maps
== NULL
))
333 XkbUpdateLedAutoState(edev
, sli
, sli
->mapsPresent
, NULL
,
342 /***====================================================================***/
346 * XkbSetIndicators(dev,affect,values,cause)
348 * Attempts to change the indicators specified in 'affect' to the
349 * states specified in 'values' for the default keyboard feedback
350 * on the keyboard specified by 'dev.' Attempts to change indicator
351 * state might be ignored or have no affect, depending on the XKB
352 * indicator map for any affected indicators, as described in section
353 * 9.2 of the XKB protocol specification.
355 * If 'changes' is non-NULL, this function notes any changes to the
356 * keyboard state, controls, or indicator state that result from this
357 * attempted change. If 'changes' is NULL, this function generates
358 * XKB events to report any such changes to interested clients.
360 * If 'cause' is non-NULL, it specifies the reason for the change,
361 * as reported in some XKB events. If it is NULL, this function
362 * assumes that the change is the result of a core protocol
363 * ChangeKeyboardMapping request.
367 XkbSetIndicators(DeviceIntPtr dev
,
368 CARD32 affect
, CARD32 values
, XkbEventCausePtr cause
)
370 XkbSrvLedInfoPtr sli
;
371 XkbChangesRec changes
;
372 xkbExtensionDeviceNotify ed
;
373 unsigned side_affected
;
375 memset((char *) &changes
, 0, sizeof(XkbChangesRec
));
376 memset((char *) &ed
, 0, sizeof(xkbExtensionDeviceNotify
));
377 sli
= XkbFindSrvLedInfo(dev
, XkbDfltXIClass
, XkbDfltXIId
, 0);
378 sli
->explicitState
&= ~affect
;
379 sli
->explicitState
|= (affect
& values
);
380 XkbApplyLedStateChanges(dev
, sli
, affect
, &ed
, &changes
, cause
);
383 if (changes
.state_changes
!= 0)
385 XkbIndicatorsToUpdate(dev
, changes
.state_changes
, FALSE
);
386 if (changes
.ctrls
.enabled_ctrls_changes
)
387 side_affected
|= sli
->usesControls
;
390 XkbUpdateLedAutoState(dev
, sli
, side_affected
, &ed
, &changes
, cause
);
391 affect
|= side_affected
;
393 if (changes
.state_changes
|| changes
.ctrls
.enabled_ctrls_changes
)
394 XkbUpdateAllDeviceIndicators(NULL
, cause
);
396 XkbFlushLedEvents(dev
, dev
, sli
, &ed
, &changes
, cause
);
400 /***====================================================================***/
402 /***====================================================================***/
406 * XkbUpdateIndicators(dev,update,check_edevs,changes,cause)
408 * Applies the indicator maps for any indicators specified in
409 * 'update' from the default keyboard feedback on the device
410 * specified by 'dev.'
412 * If 'changes' is NULL, this function generates and XKB events
413 * required to report the necessary changes, otherwise it simply
414 * notes the indicators with changed state.
416 * If 'check_edevs' is TRUE, this function also checks the indicator
417 * maps for any open extension devices that have them, and updates
418 * the state of any extension device indicators as necessary.
422 XkbUpdateIndicators(DeviceIntPtr dev
,
423 register CARD32 update
,
425 XkbChangesPtr changes
, XkbEventCausePtr cause
)
427 XkbSrvLedInfoPtr sli
;
429 sli
= XkbFindSrvLedInfo(dev
, XkbDfltXIClass
, XkbDfltXIId
, 0);
430 XkbUpdateLedAutoState(dev
, sli
, update
, NULL
, changes
, cause
);
432 XkbUpdateAllDeviceIndicators(changes
, cause
);
436 /***====================================================================***/
438 /***====================================================================***/
442 * XkbCheckIndicatorMaps(dev,sli,which)
444 * Updates the 'indicator accelerators' for the indicators specified
445 * by 'which' in the feedback specified by 'sli.' The indicator
446 * accelerators are internal to the server and are used to simplify
447 * and speed up the process of figuring out which indicators might
448 * be affected by a particular change in keyboard state or controls.
452 XkbCheckIndicatorMaps(DeviceIntPtr dev
, XkbSrvLedInfoPtr sli
, unsigned which
)
454 register unsigned i
, bit
;
455 XkbIndicatorMapPtr map
;
458 if ((sli
->flags
& XkbSLI_HasOwnState
) == 0)
461 sli
->usesBase
&= ~which
;
462 sli
->usesLatched
&= ~which
;
463 sli
->usesLocked
&= ~which
;
464 sli
->usesEffective
&= ~which
;
465 sli
->usesCompat
&= ~which
;
466 sli
->usesControls
&= ~which
;
467 sli
->mapsPresent
&= ~which
;
469 xkb
= dev
->key
->xkbInfo
->desc
;
470 for (i
= 0, bit
= 1, map
= sli
->maps
; i
< XkbNumIndicators
;
471 i
++, bit
<<= 1, map
++) {
475 if (!map
|| !XkbIM_InUse(map
))
477 sli
->mapsPresent
|= bit
;
479 what
= (map
->which_mods
| map
->which_groups
);
480 if (what
& XkbIM_UseBase
)
481 sli
->usesBase
|= bit
;
482 if (what
& XkbIM_UseLatched
)
483 sli
->usesLatched
|= bit
;
484 if (what
& XkbIM_UseLocked
)
485 sli
->usesLocked
|= bit
;
486 if (what
& XkbIM_UseEffective
)
487 sli
->usesEffective
|= bit
;
488 if (what
& XkbIM_UseCompat
)
489 sli
->usesCompat
|= bit
;
491 sli
->usesControls
|= bit
;
493 map
->mods
.mask
= map
->mods
.real_mods
;
494 if (map
->mods
.vmods
!= 0) {
495 map
->mods
.mask
|= XkbMaskForVMask(xkb
, map
->mods
.vmods
);
499 sli
->usedComponents
= 0;
501 sli
->usedComponents
|= XkbModifierBaseMask
| XkbGroupBaseMask
;
502 if (sli
->usesLatched
)
503 sli
->usedComponents
|= XkbModifierLatchMask
| XkbGroupLatchMask
;
505 sli
->usedComponents
|= XkbModifierLockMask
| XkbGroupLockMask
;
506 if (sli
->usesEffective
)
507 sli
->usedComponents
|= XkbModifierStateMask
| XkbGroupStateMask
;
509 sli
->usedComponents
|= XkbCompatStateMask
;
513 /***====================================================================***/
517 * XkbAllocSrvLedInfo(dev,kf,lf,needed_parts)
519 * Allocates an XkbSrvLedInfoPtr for the feedback specified by either
520 * 'kf' or 'lf' on the keyboard specified by 'dev.'
522 * If 'needed_parts' is non-zero, this function makes sure that any
523 * of the parts speicified therein are allocated.
526 XkbAllocSrvLedInfo(DeviceIntPtr dev
,
527 KbdFeedbackPtr kf
, LedFeedbackPtr lf
, unsigned needed_parts
)
529 XkbSrvLedInfoPtr sli
;
534 checkAccel
= checkNames
= FALSE
;
535 if ((kf
!= NULL
) && (kf
->xkb_sli
== NULL
)) {
536 kf
->xkb_sli
= sli
= calloc(1, sizeof(XkbSrvLedInfoRec
));
538 return NULL
; /* ALLOCATION ERROR */
539 if (dev
->key
&& dev
->key
->xkbInfo
)
540 sli
->flags
= XkbSLI_HasOwnState
;
543 sli
->class = KbdFeedbackClass
;
544 sli
->id
= kf
->ctrl
.id
;
548 sli
->explicitState
= kf
->ctrl
.leds
;
549 sli
->effectiveState
= kf
->ctrl
.leds
;
551 if ((kf
== dev
->kbdfeed
) && (dev
->key
) && (dev
->key
->xkbInfo
)) {
554 xkb
= dev
->key
->xkbInfo
->desc
;
555 sli
->flags
|= XkbSLI_IsDefault
;
556 sli
->physIndicators
= xkb
->indicators
->phys_indicators
;
557 sli
->names
= xkb
->names
->indicators
;
558 sli
->maps
= xkb
->indicators
->maps
;
559 checkNames
= checkAccel
= TRUE
;
562 sli
->physIndicators
= XkbAllIndicatorsMask
;
567 else if ((kf
!= NULL
) && ((kf
->xkb_sli
->flags
& XkbSLI_IsDefault
) != 0)) {
570 xkb
= dev
->key
->xkbInfo
->desc
;
572 sli
->physIndicators
= xkb
->indicators
->phys_indicators
;
573 if (xkb
->names
->indicators
!= sli
->names
) {
575 sli
->names
= xkb
->names
->indicators
;
577 if (xkb
->indicators
->maps
!= sli
->maps
) {
579 sli
->maps
= xkb
->indicators
->maps
;
582 else if ((lf
!= NULL
) && (lf
->xkb_sli
== NULL
)) {
583 lf
->xkb_sli
= sli
= calloc(1, sizeof(XkbSrvLedInfoRec
));
585 return NULL
; /* ALLOCATION ERROR */
586 if (dev
->key
&& dev
->key
->xkbInfo
)
587 sli
->flags
= XkbSLI_HasOwnState
;
590 sli
->class = LedFeedbackClass
;
591 sli
->id
= lf
->ctrl
.id
;
594 sli
->physIndicators
= lf
->ctrl
.led_mask
;
596 sli
->explicitState
= lf
->ctrl
.led_values
;
597 sli
->effectiveState
= lf
->ctrl
.led_values
;
603 if ((sli
->names
== NULL
) && (needed_parts
& XkbXI_IndicatorNamesMask
))
604 sli
->names
= calloc(XkbNumIndicators
, sizeof(Atom
));
605 if ((sli
->maps
== NULL
) && (needed_parts
& XkbXI_IndicatorMapsMask
))
606 sli
->maps
= calloc(XkbNumIndicators
, sizeof(XkbIndicatorMapRec
));
608 register unsigned i
, bit
;
610 sli
->namesPresent
= 0;
611 for (i
= 0, bit
= 1; i
< XkbNumIndicators
; i
++, bit
<<= 1) {
612 if (sli
->names
[i
] != None
)
613 sli
->namesPresent
|= bit
;
617 XkbCheckIndicatorMaps(dev
, sli
, XkbAllIndicatorsMask
);
622 XkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli
)
624 if ((sli
->flags
& XkbSLI_IsDefault
) == 0) {
636 * XkbCopySrvLedInfo(dev,src,kf,lf)
638 * Takes the given XkbSrvLedInfoPtr and duplicates it. A deep copy is made,
639 * thus the new copy behaves like the original one and can be freed with
643 XkbCopySrvLedInfo(DeviceIntPtr from
,
644 XkbSrvLedInfoPtr src
, KbdFeedbackPtr kf
, LedFeedbackPtr lf
)
646 XkbSrvLedInfoPtr sli_new
= NULL
;
651 sli_new
= calloc(1, sizeof(XkbSrvLedInfoRec
));
655 memcpy(sli_new
, src
, sizeof(XkbSrvLedInfoRec
));
656 if (sli_new
->class == KbdFeedbackClass
)
661 if (!(sli_new
->flags
& XkbSLI_IsDefault
)) {
662 sli_new
->names
= calloc(XkbNumIndicators
, sizeof(Atom
));
663 sli_new
->maps
= calloc(XkbNumIndicators
, sizeof(XkbIndicatorMapRec
));
664 } /* else sli_new->names/maps is pointing to
665 dev->key->xkbInfo->desc->names->indicators;
666 dev->key->xkbInfo->desc->names->indicators; */
672 /***====================================================================***/
676 * XkbFindSrvLedInfo(dev,class,id,needed_parts)
678 * Finds the XkbSrvLedInfoPtr for the specified 'class' and 'id'
679 * on the device specified by 'dev.' If the class and id specify
680 * a valid device feedback, this function returns the existing
681 * feedback or allocates a new one.
686 XkbFindSrvLedInfo(DeviceIntPtr dev
,
687 unsigned class, unsigned id
, unsigned needed_parts
)
689 XkbSrvLedInfoPtr sli
;
691 /* optimization to check for most common case */
692 if (((class == XkbDfltXIClass
) && (id
== XkbDfltXIId
)) && (dev
->kbdfeed
)) {
693 if (dev
->kbdfeed
->xkb_sli
== NULL
) {
694 dev
->kbdfeed
->xkb_sli
=
695 XkbAllocSrvLedInfo(dev
, dev
->kbdfeed
, NULL
, needed_parts
);
697 return dev
->kbdfeed
->xkb_sli
;
701 if (class == XkbDfltXIClass
) {
703 class = KbdFeedbackClass
;
705 class = LedFeedbackClass
;
709 if (class == KbdFeedbackClass
) {
712 for (kf
= dev
->kbdfeed
; kf
!= NULL
; kf
= kf
->next
) {
713 if ((id
== XkbDfltXIId
) || (id
== kf
->ctrl
.id
)) {
714 if (kf
->xkb_sli
== NULL
)
716 XkbAllocSrvLedInfo(dev
, kf
, NULL
, needed_parts
);
722 else if (class == LedFeedbackClass
) {
725 for (lf
= dev
->leds
; lf
!= NULL
; lf
= lf
->next
) {
726 if ((id
== XkbDfltXIId
) || (id
== lf
->ctrl
.id
)) {
727 if (lf
->xkb_sli
== NULL
)
729 XkbAllocSrvLedInfo(dev
, NULL
, lf
, needed_parts
);
736 if ((sli
->names
== NULL
) && (needed_parts
& XkbXI_IndicatorNamesMask
))
737 sli
->names
= calloc(XkbNumIndicators
, sizeof(Atom
));
738 if ((sli
->maps
== NULL
) && (needed_parts
& XkbXI_IndicatorMapsMask
))
739 sli
->maps
= calloc(XkbNumIndicators
, sizeof(XkbIndicatorMapRec
));
744 /***====================================================================***/
747 XkbFlushLedEvents(DeviceIntPtr dev
,
749 XkbSrvLedInfoPtr sli
,
750 xkbExtensionDeviceNotify
* ed
,
751 XkbChangesPtr changes
, XkbEventCausePtr cause
)
754 if (changes
->indicators
.state_changes
)
755 XkbDDXUpdateDeviceIndicators(dev
, sli
, sli
->effectiveState
);
756 XkbSendNotification(kbd
, changes
, cause
);
757 memset((char *) changes
, 0, sizeof(XkbChangesRec
));
759 if (XkbAX_NeedFeedback
760 (kbd
->key
->xkbInfo
->desc
->ctrls
, XkbAX_IndicatorFBMask
)) {
761 if (sli
->effectiveState
)
762 /* it appears that the which parameter is not used */
763 XkbDDXAccessXBeep(dev
, _BEEP_LED_ON
, XkbAccessXFeedbackMask
);
765 XkbDDXAccessXBeep(dev
, _BEEP_LED_OFF
, XkbAccessXFeedbackMask
);
770 if ((dev
!= kbd
) && (ed
->reason
& XkbXI_IndicatorStateMask
))
771 XkbDDXUpdateDeviceIndicators(dev
, sli
, sli
->effectiveState
);
772 XkbSendExtensionDeviceNotify(dev
, cause
->client
, ed
);
774 memset((char *) ed
, 0, sizeof(XkbExtensionDeviceNotify
));
779 /***====================================================================***/
782 XkbApplyLedNameChanges(DeviceIntPtr dev
,
783 XkbSrvLedInfoPtr sli
,
784 unsigned changed_names
,
785 xkbExtensionDeviceNotify
* ed
,
786 XkbChangesPtr changes
, XkbEventCausePtr cause
)
789 XkbChangesRec my_changes
;
790 xkbExtensionDeviceNotify my_ed
;
792 if (changed_names
== 0)
794 if (dev
->key
&& dev
->key
->xkbInfo
)
797 kbd
= inputInfo
.keyboard
;
801 memset((char *) ed
, 0, sizeof(xkbExtensionDeviceNotify
));
803 else if ((ed
->reason
& XkbXI_IndicatorsMask
) &&
804 ((ed
->ledClass
!= sli
->class) || (ed
->ledID
!= sli
->id
))) {
805 XkbFlushLedEvents(dev
, kbd
, sli
, ed
, changes
, cause
);
808 if ((kbd
== dev
) && (sli
->flags
& XkbSLI_IsDefault
)) {
809 if (changes
== NULL
) {
810 changes
= &my_changes
;
811 memset((char *) changes
, 0, sizeof(XkbChangesRec
));
813 changes
->names
.changed
|= XkbIndicatorNamesMask
;
814 changes
->names
.changed_indicators
|= changed_names
;
817 ed
->reason
|= XkbXI_IndicatorNamesMask
;
818 ed
->ledClass
= sli
->class;
820 ed
->ledsDefined
= sli
->namesPresent
| sli
->mapsPresent
;
821 ed
->ledState
= sli
->effectiveState
;
823 ed
->supported
= XkbXI_AllFeaturesMask
;
825 if (changes
!= &my_changes
)
830 XkbFlushLedEvents(dev
, kbd
, sli
, ed
, changes
, cause
);
834 /***====================================================================***/
838 * XkbApplyLedMapChanges(dev,sli,changed_maps,changes,cause)
840 * Handles all of the secondary effects of the changes to the
841 * feedback specified by 'sli' on the device specified by 'dev.'
843 * If 'changed_maps' specifies any indicators, this function generates
844 * XkbExtensionDeviceNotify events and possibly IndicatorMapNotify
845 * events to report the changes, and recalculates the effective
846 * state of each indicator with a changed map. If any indicators
847 * change state, the server generates XkbExtensionDeviceNotify and
848 * XkbIndicatorStateNotify events as appropriate.
850 * If 'changes' is non-NULL, this function updates it to reflect
851 * any changes to the keyboard state or controls or to the 'core'
852 * indicator names, maps, or state. If 'changes' is NULL, this
853 * function generates XKB events as needed to report the changes.
854 * If 'dev' is not a keyboard device, any changes are reported
855 * for the core keyboard.
857 * The 'cause' specifies the reason for the event (key event or
858 * request) for the change, as reported in some XKB events.
862 XkbApplyLedMapChanges(DeviceIntPtr dev
,
863 XkbSrvLedInfoPtr sli
,
864 unsigned changed_maps
,
865 xkbExtensionDeviceNotify
* ed
,
866 XkbChangesPtr changes
, XkbEventCausePtr cause
)
869 XkbChangesRec my_changes
;
870 xkbExtensionDeviceNotify my_ed
;
872 if (changed_maps
== 0)
874 if (dev
->key
&& dev
->key
->xkbInfo
)
877 kbd
= inputInfo
.keyboard
;
881 memset((char *) ed
, 0, sizeof(xkbExtensionDeviceNotify
));
883 else if ((ed
->reason
& XkbXI_IndicatorsMask
) &&
884 ((ed
->ledClass
!= sli
->class) || (ed
->ledID
!= sli
->id
))) {
885 XkbFlushLedEvents(dev
, kbd
, sli
, ed
, changes
, cause
);
888 if ((kbd
== dev
) && (sli
->flags
& XkbSLI_IsDefault
)) {
889 if (changes
== NULL
) {
890 changes
= &my_changes
;
891 memset((char *) changes
, 0, sizeof(XkbChangesRec
));
893 changes
->indicators
.map_changes
|= changed_maps
;
896 XkbCheckIndicatorMaps(dev
, sli
, changed_maps
);
898 ed
->reason
|= XkbXI_IndicatorMapsMask
;
899 ed
->ledClass
= sli
->class;
901 ed
->ledsDefined
= sli
->namesPresent
| sli
->mapsPresent
;
902 ed
->ledState
= sli
->effectiveState
;
904 ed
->supported
= XkbXI_AllFeaturesMask
;
906 XkbUpdateLedAutoState(dev
, sli
, changed_maps
, ed
, changes
, cause
);
908 if (changes
!= &my_changes
)
913 XkbFlushLedEvents(dev
, kbd
, sli
, ed
, changes
, cause
);
917 /***====================================================================***/
920 XkbApplyLedStateChanges(DeviceIntPtr dev
,
921 XkbSrvLedInfoPtr sli
,
922 unsigned changed_leds
,
923 xkbExtensionDeviceNotify
* ed
,
924 XkbChangesPtr changes
, XkbEventCausePtr cause
)
928 XkbChangesRec my_changes
;
929 xkbExtensionDeviceNotify my_ed
;
930 register unsigned i
, bit
, affected
;
931 XkbIndicatorMapPtr map
;
935 if (changed_leds
== 0)
937 if (dev
->key
&& dev
->key
->xkbInfo
)
940 kbd
= inputInfo
.keyboard
;
941 xkbi
= kbd
->key
->xkbInfo
;
943 if (changes
== NULL
) {
944 changes
= &my_changes
;
945 memset((char *) changes
, 0, sizeof(XkbChangesRec
));
949 affected
= changed_leds
;
950 oldState
= sli
->effectiveState
;
951 for (i
= 0, bit
= 1; (i
< XkbNumIndicators
) && (affected
); i
++, bit
<<= 1) {
952 if ((affected
& bit
) == 0)
956 if (map
->flags
& XkbIM_NoExplicit
) {
957 sli
->explicitState
&= ~bit
;
960 if (map
->flags
& XkbIM_LEDDrivesKB
) {
961 Bool on
= ((sli
->explicitState
& bit
) != 0);
963 if (XkbApplyLEDChangeToKeyboard(xkbi
, map
, on
, changes
))
967 sli
->effectiveState
= (sli
->autoState
| sli
->explicitState
);
968 affected
= sli
->effectiveState
^ oldState
;
972 memset((char *) ed
, 0, sizeof(xkbExtensionDeviceNotify
));
974 else if (affected
&& (ed
->reason
& XkbXI_IndicatorsMask
) &&
975 ((ed
->ledClass
!= sli
->class) || (ed
->ledID
!= sli
->id
))) {
976 XkbFlushLedEvents(dev
, kbd
, sli
, ed
, changes
, cause
);
979 if ((kbd
== dev
) && (sli
->flags
& XkbSLI_IsDefault
))
980 changes
->indicators
.state_changes
|= affected
;
982 ed
->reason
|= XkbXI_IndicatorStateMask
;
983 ed
->ledClass
= sli
->class;
985 ed
->ledsDefined
= sli
->namesPresent
| sli
->mapsPresent
;
986 ed
->ledState
= sli
->effectiveState
;
988 ed
->supported
= XkbXI_AllFeaturesMask
;
992 XkbComputeDerivedState(kbd
->key
->xkbInfo
);
993 XkbUpdateLedAutoState(dev
, sli
, sli
->mapsPresent
, ed
, changes
, cause
);
996 if (changes
!= &my_changes
)
1001 XkbFlushLedEvents(dev
, kbd
, sli
, ed
, changes
, cause
);
1003 XkbUpdateAllDeviceIndicators(NULL
, cause
);