1*4882a593Smuzhiyun /************************************************************
2*4882a593Smuzhiyun Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun Permission to use, copy, modify, and distribute this
5*4882a593Smuzhiyun software and its documentation for any purpose and without
6*4882a593Smuzhiyun fee is hereby granted, provided that the above copyright
7*4882a593Smuzhiyun notice appear in all copies and that both that copyright
8*4882a593Smuzhiyun notice and this permission notice appear in supporting
9*4882a593Smuzhiyun documentation, and that the name of Silicon Graphics not be
10*4882a593Smuzhiyun used in advertising or publicity pertaining to distribution
11*4882a593Smuzhiyun of the software without specific prior written permission.
12*4882a593Smuzhiyun Silicon Graphics makes no representation about the suitability
13*4882a593Smuzhiyun of this software for any purpose. It is provided "as is"
14*4882a593Smuzhiyun without any express or implied warranty.
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17*4882a593Smuzhiyun SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18*4882a593Smuzhiyun AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19*4882a593Smuzhiyun GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20*4882a593Smuzhiyun DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21*4882a593Smuzhiyun DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22*4882a593Smuzhiyun OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23*4882a593Smuzhiyun THE USE OR PERFORMANCE OF THIS SOFTWARE.
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun ********************************************************/
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
28*4882a593Smuzhiyun #include <dix-config.h>
29*4882a593Smuzhiyun #endif
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #include <stdio.h>
32*4882a593Smuzhiyun #include <ctype.h>
33*4882a593Smuzhiyun #include <math.h>
34*4882a593Smuzhiyun #include <X11/X.h>
35*4882a593Smuzhiyun #include <X11/Xproto.h>
36*4882a593Smuzhiyun #include "misc.h"
37*4882a593Smuzhiyun #include "inputstr.h"
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #include <X11/extensions/XI.h>
40*4882a593Smuzhiyun #include <xkbsrv.h>
41*4882a593Smuzhiyun #include "xkb.h"
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun /***====================================================================***/
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun /*
46*4882a593Smuzhiyun * unsigned
47*4882a593Smuzhiyun * XkbIndicatorsToUpdate(dev,changed,check_devs_rtrn)
48*4882a593Smuzhiyun *
49*4882a593Smuzhiyun * Given a keyboard and a set of state components that have changed,
50*4882a593Smuzhiyun * this function returns the indicators on the default keyboard
51*4882a593Smuzhiyun * feedback that might be affected. It also reports whether or not
52*4882a593Smuzhiyun * any extension devices might be affected in check_devs_rtrn.
53*4882a593Smuzhiyun */
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun unsigned
XkbIndicatorsToUpdate(DeviceIntPtr dev,unsigned long state_changes,Bool enable_changes)56*4882a593Smuzhiyun XkbIndicatorsToUpdate(DeviceIntPtr dev,
57*4882a593Smuzhiyun unsigned long state_changes, Bool enable_changes)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun register unsigned update = 0;
60*4882a593Smuzhiyun XkbSrvLedInfoPtr sli;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun if (!sli)
65*4882a593Smuzhiyun return update;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun if (state_changes & (XkbModifierStateMask | XkbGroupStateMask))
68*4882a593Smuzhiyun update |= sli->usesEffective;
69*4882a593Smuzhiyun if (state_changes & (XkbModifierBaseMask | XkbGroupBaseMask))
70*4882a593Smuzhiyun update |= sli->usesBase;
71*4882a593Smuzhiyun if (state_changes & (XkbModifierLatchMask | XkbGroupLatchMask))
72*4882a593Smuzhiyun update |= sli->usesLatched;
73*4882a593Smuzhiyun if (state_changes & (XkbModifierLockMask | XkbGroupLockMask))
74*4882a593Smuzhiyun update |= sli->usesLocked;
75*4882a593Smuzhiyun if (state_changes & XkbCompatStateMask)
76*4882a593Smuzhiyun update |= sli->usesCompat;
77*4882a593Smuzhiyun if (enable_changes)
78*4882a593Smuzhiyun update |= sli->usesControls;
79*4882a593Smuzhiyun return update;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /***====================================================================***/
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun /*
85*4882a593Smuzhiyun * Bool
86*4882a593Smuzhiyun *XkbApplyLEDChangeToKeyboard(xkbi,map,on,change)
87*4882a593Smuzhiyun *
88*4882a593Smuzhiyun * Some indicators "drive" the keyboard when their state is explicitly
89*4882a593Smuzhiyun * changed, as described in section 9.2.1 of the XKB protocol spec.
90*4882a593Smuzhiyun * This function updates the state and controls for the keyboard
91*4882a593Smuzhiyun * specified by 'xkbi' to reflect any changes that are required
92*4882a593Smuzhiyun * when the indicator described by 'map' is turned on or off. The
93*4882a593Smuzhiyun * extent of the changes is reported in change, which must be defined.
94*4882a593Smuzhiyun */
95*4882a593Smuzhiyun static Bool
XkbApplyLEDChangeToKeyboard(XkbSrvInfoPtr xkbi,XkbIndicatorMapPtr map,Bool on,XkbChangesPtr change)96*4882a593Smuzhiyun XkbApplyLEDChangeToKeyboard(XkbSrvInfoPtr xkbi,
97*4882a593Smuzhiyun XkbIndicatorMapPtr map,
98*4882a593Smuzhiyun Bool on, XkbChangesPtr change)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun Bool ctrlChange, stateChange;
101*4882a593Smuzhiyun XkbStatePtr state;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun if ((map->flags & XkbIM_NoExplicit) ||
104*4882a593Smuzhiyun ((map->flags & XkbIM_LEDDrivesKB) == 0))
105*4882a593Smuzhiyun return FALSE;
106*4882a593Smuzhiyun ctrlChange = stateChange = FALSE;
107*4882a593Smuzhiyun if (map->ctrls) {
108*4882a593Smuzhiyun XkbControlsPtr ctrls = xkbi->desc->ctrls;
109*4882a593Smuzhiyun unsigned old;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun old = ctrls->enabled_ctrls;
112*4882a593Smuzhiyun if (on)
113*4882a593Smuzhiyun ctrls->enabled_ctrls |= map->ctrls;
114*4882a593Smuzhiyun else
115*4882a593Smuzhiyun ctrls->enabled_ctrls &= ~map->ctrls;
116*4882a593Smuzhiyun if (old != ctrls->enabled_ctrls) {
117*4882a593Smuzhiyun change->ctrls.changed_ctrls = XkbControlsEnabledMask;
118*4882a593Smuzhiyun change->ctrls.enabled_ctrls_changes = old ^ ctrls->enabled_ctrls;
119*4882a593Smuzhiyun ctrlChange = TRUE;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun state = &xkbi->state;
123*4882a593Smuzhiyun if ((map->groups) && ((map->which_groups & (~XkbIM_UseBase)) != 0)) {
124*4882a593Smuzhiyun register int i;
125*4882a593Smuzhiyun register unsigned bit, match;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun if (on)
128*4882a593Smuzhiyun match = (map->groups) & XkbAllGroupsMask;
129*4882a593Smuzhiyun else
130*4882a593Smuzhiyun match = (~map->groups) & XkbAllGroupsMask;
131*4882a593Smuzhiyun if (map->which_groups & (XkbIM_UseLocked | XkbIM_UseEffective)) {
132*4882a593Smuzhiyun for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
133*4882a593Smuzhiyun if (bit & match)
134*4882a593Smuzhiyun break;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun if (map->which_groups & XkbIM_UseLatched)
137*4882a593Smuzhiyun XkbLatchGroup(xkbi->device, 0); /* unlatch group */
138*4882a593Smuzhiyun state->locked_group = i;
139*4882a593Smuzhiyun stateChange = TRUE;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun else if (map->which_groups & (XkbIM_UseLatched | XkbIM_UseEffective)) {
142*4882a593Smuzhiyun for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
143*4882a593Smuzhiyun if (bit & match)
144*4882a593Smuzhiyun break;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun state->locked_group = 0;
147*4882a593Smuzhiyun XkbLatchGroup(xkbi->device, i);
148*4882a593Smuzhiyun stateChange = TRUE;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun if ((map->mods.mask) && ((map->which_mods & (~XkbIM_UseBase)) != 0)) {
152*4882a593Smuzhiyun if (map->which_mods & (XkbIM_UseLocked | XkbIM_UseEffective)) {
153*4882a593Smuzhiyun register unsigned long old;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun old = state->locked_mods;
156*4882a593Smuzhiyun if (on)
157*4882a593Smuzhiyun state->locked_mods |= map->mods.mask;
158*4882a593Smuzhiyun else
159*4882a593Smuzhiyun state->locked_mods &= ~map->mods.mask;
160*4882a593Smuzhiyun if (state->locked_mods != old)
161*4882a593Smuzhiyun stateChange = TRUE;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun if (map->which_mods & (XkbIM_UseLatched | XkbIM_UseEffective)) {
164*4882a593Smuzhiyun register unsigned long newmods;
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun newmods = state->latched_mods;
167*4882a593Smuzhiyun if (on)
168*4882a593Smuzhiyun newmods |= map->mods.mask;
169*4882a593Smuzhiyun else
170*4882a593Smuzhiyun newmods &= ~map->mods.mask;
171*4882a593Smuzhiyun if (newmods != state->locked_mods) {
172*4882a593Smuzhiyun newmods &= map->mods.mask;
173*4882a593Smuzhiyun XkbLatchModifiers(xkbi->device, map->mods.mask, newmods);
174*4882a593Smuzhiyun stateChange = TRUE;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun return stateChange || ctrlChange;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun /*
182*4882a593Smuzhiyun * Bool
183*4882a593Smuzhiyun * ComputeAutoState(map,state,ctrls)
184*4882a593Smuzhiyun *
185*4882a593Smuzhiyun * This function reports the effect of applying the specified
186*4882a593Smuzhiyun * indicator map given the specified state and controls, as
187*4882a593Smuzhiyun * described in section 9.2 of the XKB protocol specification.
188*4882a593Smuzhiyun */
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun static Bool
ComputeAutoState(XkbIndicatorMapPtr map,XkbStatePtr state,XkbControlsPtr ctrls)191*4882a593Smuzhiyun ComputeAutoState(XkbIndicatorMapPtr map,
192*4882a593Smuzhiyun XkbStatePtr state, XkbControlsPtr ctrls)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun Bool on;
195*4882a593Smuzhiyun CARD8 mods, group;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun on = FALSE;
198*4882a593Smuzhiyun mods = group = 0;
199*4882a593Smuzhiyun if (map->which_mods & XkbIM_UseAnyMods) {
200*4882a593Smuzhiyun if (map->which_mods & XkbIM_UseBase)
201*4882a593Smuzhiyun mods |= state->base_mods;
202*4882a593Smuzhiyun if (map->which_mods & XkbIM_UseLatched)
203*4882a593Smuzhiyun mods |= state->latched_mods;
204*4882a593Smuzhiyun if (map->which_mods & XkbIM_UseLocked)
205*4882a593Smuzhiyun mods |= state->locked_mods;
206*4882a593Smuzhiyun if (map->which_mods & XkbIM_UseEffective)
207*4882a593Smuzhiyun mods |= state->mods;
208*4882a593Smuzhiyun if (map->which_mods & XkbIM_UseCompat)
209*4882a593Smuzhiyun mods |= state->compat_state;
210*4882a593Smuzhiyun on = ((map->mods.mask & mods) != 0);
211*4882a593Smuzhiyun on = on || ((mods == 0) && (map->mods.mask == 0) &&
212*4882a593Smuzhiyun (map->mods.vmods == 0));
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun if (map->which_groups & XkbIM_UseAnyGroup) {
215*4882a593Smuzhiyun if (map->which_groups & XkbIM_UseBase)
216*4882a593Smuzhiyun group |= (1L << state->base_group);
217*4882a593Smuzhiyun if (map->which_groups & XkbIM_UseLatched)
218*4882a593Smuzhiyun group |= (1L << state->latched_group);
219*4882a593Smuzhiyun if (map->which_groups & XkbIM_UseLocked)
220*4882a593Smuzhiyun group |= (1L << state->locked_group);
221*4882a593Smuzhiyun if (map->which_groups & XkbIM_UseEffective)
222*4882a593Smuzhiyun group |= (1L << state->group);
223*4882a593Smuzhiyun on = on || (((map->groups & group) != 0) || (map->groups == 0));
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun if (map->ctrls)
226*4882a593Smuzhiyun on = on || (ctrls->enabled_ctrls & map->ctrls);
227*4882a593Smuzhiyun return on;
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun static void
XkbUpdateLedAutoState(DeviceIntPtr dev,XkbSrvLedInfoPtr sli,unsigned maps_to_check,xkbExtensionDeviceNotify * ed,XkbChangesPtr changes,XkbEventCausePtr cause)231*4882a593Smuzhiyun XkbUpdateLedAutoState(DeviceIntPtr dev,
232*4882a593Smuzhiyun XkbSrvLedInfoPtr sli,
233*4882a593Smuzhiyun unsigned maps_to_check,
234*4882a593Smuzhiyun xkbExtensionDeviceNotify * ed,
235*4882a593Smuzhiyun XkbChangesPtr changes, XkbEventCausePtr cause)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun DeviceIntPtr kbd;
238*4882a593Smuzhiyun XkbStatePtr state;
239*4882a593Smuzhiyun XkbControlsPtr ctrls;
240*4882a593Smuzhiyun XkbChangesRec my_changes;
241*4882a593Smuzhiyun xkbExtensionDeviceNotify my_ed;
242*4882a593Smuzhiyun register unsigned i, bit, affected;
243*4882a593Smuzhiyun register XkbIndicatorMapPtr map;
244*4882a593Smuzhiyun unsigned oldState;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun if ((maps_to_check == 0) || (sli->maps == NULL) || (sli->mapsPresent == 0))
247*4882a593Smuzhiyun return;
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun if (dev->key && dev->key->xkbInfo)
250*4882a593Smuzhiyun kbd = dev;
251*4882a593Smuzhiyun else
252*4882a593Smuzhiyun kbd = inputInfo.keyboard;
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun state = &kbd->key->xkbInfo->state;
255*4882a593Smuzhiyun ctrls = kbd->key->xkbInfo->desc->ctrls;
256*4882a593Smuzhiyun affected = maps_to_check;
257*4882a593Smuzhiyun oldState = sli->effectiveState;
258*4882a593Smuzhiyun sli->autoState &= ~affected;
259*4882a593Smuzhiyun for (i = 0, bit = 1; (i < XkbNumIndicators) && (affected); i++, bit <<= 1) {
260*4882a593Smuzhiyun if ((affected & bit) == 0)
261*4882a593Smuzhiyun continue;
262*4882a593Smuzhiyun affected &= ~bit;
263*4882a593Smuzhiyun map = &sli->maps[i];
264*4882a593Smuzhiyun if ((!(map->flags & XkbIM_NoAutomatic)) &&
265*4882a593Smuzhiyun ComputeAutoState(map, state, ctrls))
266*4882a593Smuzhiyun sli->autoState |= bit;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun sli->effectiveState = (sli->autoState | sli->explicitState);
269*4882a593Smuzhiyun affected = sli->effectiveState ^ oldState;
270*4882a593Smuzhiyun if (affected == 0)
271*4882a593Smuzhiyun return;
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun if (ed == NULL) {
274*4882a593Smuzhiyun ed = &my_ed;
275*4882a593Smuzhiyun memset((char *) ed, 0, sizeof(xkbExtensionDeviceNotify));
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun else if ((ed->reason & XkbXI_IndicatorsMask) &&
278*4882a593Smuzhiyun ((ed->ledClass != sli->class) || (ed->ledID != sli->id))) {
279*4882a593Smuzhiyun XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun if ((kbd == dev) && (sli->flags & XkbSLI_IsDefault)) {
283*4882a593Smuzhiyun if (changes == NULL) {
284*4882a593Smuzhiyun changes = &my_changes;
285*4882a593Smuzhiyun memset((char *) changes, 0, sizeof(XkbChangesRec));
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun changes->indicators.state_changes |= affected;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun ed->reason |= XkbXI_IndicatorStateMask;
291*4882a593Smuzhiyun ed->ledClass = sli->class;
292*4882a593Smuzhiyun ed->ledID = sli->id;
293*4882a593Smuzhiyun ed->ledsDefined = sli->namesPresent | sli->mapsPresent;
294*4882a593Smuzhiyun ed->ledState = sli->effectiveState;
295*4882a593Smuzhiyun ed->unsupported = 0;
296*4882a593Smuzhiyun ed->supported = XkbXI_AllFeaturesMask;
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun if (changes != &my_changes)
299*4882a593Smuzhiyun changes = NULL;
300*4882a593Smuzhiyun if (ed != &my_ed)
301*4882a593Smuzhiyun ed = NULL;
302*4882a593Smuzhiyun if (changes || ed)
303*4882a593Smuzhiyun XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
304*4882a593Smuzhiyun return;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun void
XkbUpdateAllDeviceIndicators(XkbChangesPtr changes,XkbEventCausePtr cause)308*4882a593Smuzhiyun XkbUpdateAllDeviceIndicators(XkbChangesPtr changes, XkbEventCausePtr cause)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun DeviceIntPtr edev;
311*4882a593Smuzhiyun XkbSrvLedInfoPtr sli;
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun for (edev = inputInfo.devices; edev != NULL; edev = edev->next) {
314*4882a593Smuzhiyun if (edev->kbdfeed) {
315*4882a593Smuzhiyun KbdFeedbackPtr kf;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun for (kf = edev->kbdfeed; kf != NULL; kf = kf->next) {
318*4882a593Smuzhiyun if ((kf->xkb_sli == NULL) || (kf->xkb_sli->maps == NULL))
319*4882a593Smuzhiyun continue;
320*4882a593Smuzhiyun sli = kf->xkb_sli;
321*4882a593Smuzhiyun XkbUpdateLedAutoState(edev, sli, sli->mapsPresent, NULL,
322*4882a593Smuzhiyun changes, cause);
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun if (edev->leds) {
327*4882a593Smuzhiyun LedFeedbackPtr lf;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun for (lf = edev->leds; lf != NULL; lf = lf->next) {
330*4882a593Smuzhiyun if ((lf->xkb_sli == NULL) || (lf->xkb_sli->maps == NULL))
331*4882a593Smuzhiyun continue;
332*4882a593Smuzhiyun sli = lf->xkb_sli;
333*4882a593Smuzhiyun XkbUpdateLedAutoState(edev, sli, sli->mapsPresent, NULL,
334*4882a593Smuzhiyun changes, cause);
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun return;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun /***====================================================================***/
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun /*
345*4882a593Smuzhiyun * void
346*4882a593Smuzhiyun * XkbSetIndicators(dev,affect,values,cause)
347*4882a593Smuzhiyun *
348*4882a593Smuzhiyun * Attempts to change the indicators specified in 'affect' to the
349*4882a593Smuzhiyun * states specified in 'values' for the default keyboard feedback
350*4882a593Smuzhiyun * on the keyboard specified by 'dev.' Attempts to change indicator
351*4882a593Smuzhiyun * state might be ignored or have no affect, depending on the XKB
352*4882a593Smuzhiyun * indicator map for any affected indicators, as described in section
353*4882a593Smuzhiyun * 9.2 of the XKB protocol specification.
354*4882a593Smuzhiyun *
355*4882a593Smuzhiyun * If 'changes' is non-NULL, this function notes any changes to the
356*4882a593Smuzhiyun * keyboard state, controls, or indicator state that result from this
357*4882a593Smuzhiyun * attempted change. If 'changes' is NULL, this function generates
358*4882a593Smuzhiyun * XKB events to report any such changes to interested clients.
359*4882a593Smuzhiyun *
360*4882a593Smuzhiyun * If 'cause' is non-NULL, it specifies the reason for the change,
361*4882a593Smuzhiyun * as reported in some XKB events. If it is NULL, this function
362*4882a593Smuzhiyun * assumes that the change is the result of a core protocol
363*4882a593Smuzhiyun * ChangeKeyboardMapping request.
364*4882a593Smuzhiyun */
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun void
XkbSetIndicators(DeviceIntPtr dev,CARD32 affect,CARD32 values,XkbEventCausePtr cause)367*4882a593Smuzhiyun XkbSetIndicators(DeviceIntPtr dev,
368*4882a593Smuzhiyun CARD32 affect, CARD32 values, XkbEventCausePtr cause)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun XkbSrvLedInfoPtr sli;
371*4882a593Smuzhiyun XkbChangesRec changes;
372*4882a593Smuzhiyun xkbExtensionDeviceNotify ed;
373*4882a593Smuzhiyun unsigned side_affected;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun memset((char *) &changes, 0, sizeof(XkbChangesRec));
376*4882a593Smuzhiyun memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
377*4882a593Smuzhiyun sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
378*4882a593Smuzhiyun sli->explicitState &= ~affect;
379*4882a593Smuzhiyun sli->explicitState |= (affect & values);
380*4882a593Smuzhiyun XkbApplyLedStateChanges(dev, sli, affect, &ed, &changes, cause);
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun side_affected = 0;
383*4882a593Smuzhiyun if (changes.state_changes != 0)
384*4882a593Smuzhiyun side_affected |=
385*4882a593Smuzhiyun XkbIndicatorsToUpdate(dev, changes.state_changes, FALSE);
386*4882a593Smuzhiyun if (changes.ctrls.enabled_ctrls_changes)
387*4882a593Smuzhiyun side_affected |= sli->usesControls;
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun if (side_affected) {
390*4882a593Smuzhiyun XkbUpdateLedAutoState(dev, sli, side_affected, &ed, &changes, cause);
391*4882a593Smuzhiyun affect |= side_affected;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun if (changes.state_changes || changes.ctrls.enabled_ctrls_changes)
394*4882a593Smuzhiyun XkbUpdateAllDeviceIndicators(NULL, cause);
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun XkbFlushLedEvents(dev, dev, sli, &ed, &changes, cause);
397*4882a593Smuzhiyun return;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun /***====================================================================***/
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun /***====================================================================***/
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun /*
405*4882a593Smuzhiyun * void
406*4882a593Smuzhiyun * XkbUpdateIndicators(dev,update,check_edevs,changes,cause)
407*4882a593Smuzhiyun *
408*4882a593Smuzhiyun * Applies the indicator maps for any indicators specified in
409*4882a593Smuzhiyun * 'update' from the default keyboard feedback on the device
410*4882a593Smuzhiyun * specified by 'dev.'
411*4882a593Smuzhiyun *
412*4882a593Smuzhiyun * If 'changes' is NULL, this function generates and XKB events
413*4882a593Smuzhiyun * required to report the necessary changes, otherwise it simply
414*4882a593Smuzhiyun * notes the indicators with changed state.
415*4882a593Smuzhiyun *
416*4882a593Smuzhiyun * If 'check_edevs' is TRUE, this function also checks the indicator
417*4882a593Smuzhiyun * maps for any open extension devices that have them, and updates
418*4882a593Smuzhiyun * the state of any extension device indicators as necessary.
419*4882a593Smuzhiyun */
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun void
XkbUpdateIndicators(DeviceIntPtr dev,register CARD32 update,Bool check_edevs,XkbChangesPtr changes,XkbEventCausePtr cause)422*4882a593Smuzhiyun XkbUpdateIndicators(DeviceIntPtr dev,
423*4882a593Smuzhiyun register CARD32 update,
424*4882a593Smuzhiyun Bool check_edevs,
425*4882a593Smuzhiyun XkbChangesPtr changes, XkbEventCausePtr cause)
426*4882a593Smuzhiyun {
427*4882a593Smuzhiyun XkbSrvLedInfoPtr sli;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
430*4882a593Smuzhiyun XkbUpdateLedAutoState(dev, sli, update, NULL, changes, cause);
431*4882a593Smuzhiyun if (check_edevs)
432*4882a593Smuzhiyun XkbUpdateAllDeviceIndicators(changes, cause);
433*4882a593Smuzhiyun return;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun /***====================================================================***/
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun /***====================================================================***/
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun /*
441*4882a593Smuzhiyun * void
442*4882a593Smuzhiyun * XkbCheckIndicatorMaps(dev,sli,which)
443*4882a593Smuzhiyun *
444*4882a593Smuzhiyun * Updates the 'indicator accelerators' for the indicators specified
445*4882a593Smuzhiyun * by 'which' in the feedback specified by 'sli.' The indicator
446*4882a593Smuzhiyun * accelerators are internal to the server and are used to simplify
447*4882a593Smuzhiyun * and speed up the process of figuring out which indicators might
448*4882a593Smuzhiyun * be affected by a particular change in keyboard state or controls.
449*4882a593Smuzhiyun */
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun void
XkbCheckIndicatorMaps(DeviceIntPtr dev,XkbSrvLedInfoPtr sli,unsigned which)452*4882a593Smuzhiyun XkbCheckIndicatorMaps(DeviceIntPtr dev, XkbSrvLedInfoPtr sli, unsigned which)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun register unsigned i, bit;
455*4882a593Smuzhiyun XkbIndicatorMapPtr map;
456*4882a593Smuzhiyun XkbDescPtr xkb;
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun if ((sli->flags & XkbSLI_HasOwnState) == 0)
459*4882a593Smuzhiyun return;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun sli->usesBase &= ~which;
462*4882a593Smuzhiyun sli->usesLatched &= ~which;
463*4882a593Smuzhiyun sli->usesLocked &= ~which;
464*4882a593Smuzhiyun sli->usesEffective &= ~which;
465*4882a593Smuzhiyun sli->usesCompat &= ~which;
466*4882a593Smuzhiyun sli->usesControls &= ~which;
467*4882a593Smuzhiyun sli->mapsPresent &= ~which;
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun xkb = dev->key->xkbInfo->desc;
470*4882a593Smuzhiyun for (i = 0, bit = 1, map = sli->maps; i < XkbNumIndicators;
471*4882a593Smuzhiyun i++, bit <<= 1, map++) {
472*4882a593Smuzhiyun if (which & bit) {
473*4882a593Smuzhiyun CARD8 what;
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun if (!map || !XkbIM_InUse(map))
476*4882a593Smuzhiyun continue;
477*4882a593Smuzhiyun sli->mapsPresent |= bit;
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun what = (map->which_mods | map->which_groups);
480*4882a593Smuzhiyun if (what & XkbIM_UseBase)
481*4882a593Smuzhiyun sli->usesBase |= bit;
482*4882a593Smuzhiyun if (what & XkbIM_UseLatched)
483*4882a593Smuzhiyun sli->usesLatched |= bit;
484*4882a593Smuzhiyun if (what & XkbIM_UseLocked)
485*4882a593Smuzhiyun sli->usesLocked |= bit;
486*4882a593Smuzhiyun if (what & XkbIM_UseEffective)
487*4882a593Smuzhiyun sli->usesEffective |= bit;
488*4882a593Smuzhiyun if (what & XkbIM_UseCompat)
489*4882a593Smuzhiyun sli->usesCompat |= bit;
490*4882a593Smuzhiyun if (map->ctrls)
491*4882a593Smuzhiyun sli->usesControls |= bit;
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun map->mods.mask = map->mods.real_mods;
494*4882a593Smuzhiyun if (map->mods.vmods != 0) {
495*4882a593Smuzhiyun map->mods.mask |= XkbMaskForVMask(xkb, map->mods.vmods);
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun sli->usedComponents = 0;
500*4882a593Smuzhiyun if (sli->usesBase)
501*4882a593Smuzhiyun sli->usedComponents |= XkbModifierBaseMask | XkbGroupBaseMask;
502*4882a593Smuzhiyun if (sli->usesLatched)
503*4882a593Smuzhiyun sli->usedComponents |= XkbModifierLatchMask | XkbGroupLatchMask;
504*4882a593Smuzhiyun if (sli->usesLocked)
505*4882a593Smuzhiyun sli->usedComponents |= XkbModifierLockMask | XkbGroupLockMask;
506*4882a593Smuzhiyun if (sli->usesEffective)
507*4882a593Smuzhiyun sli->usedComponents |= XkbModifierStateMask | XkbGroupStateMask;
508*4882a593Smuzhiyun if (sli->usesCompat)
509*4882a593Smuzhiyun sli->usedComponents |= XkbCompatStateMask;
510*4882a593Smuzhiyun return;
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun /***====================================================================***/
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun /*
516*4882a593Smuzhiyun * XkbSrvLedInfoPtr
517*4882a593Smuzhiyun * XkbAllocSrvLedInfo(dev,kf,lf,needed_parts)
518*4882a593Smuzhiyun *
519*4882a593Smuzhiyun * Allocates an XkbSrvLedInfoPtr for the feedback specified by either
520*4882a593Smuzhiyun * 'kf' or 'lf' on the keyboard specified by 'dev.'
521*4882a593Smuzhiyun *
522*4882a593Smuzhiyun * If 'needed_parts' is non-zero, this function makes sure that any
523*4882a593Smuzhiyun * of the parts speicified therein are allocated.
524*4882a593Smuzhiyun */
525*4882a593Smuzhiyun XkbSrvLedInfoPtr
XkbAllocSrvLedInfo(DeviceIntPtr dev,KbdFeedbackPtr kf,LedFeedbackPtr lf,unsigned needed_parts)526*4882a593Smuzhiyun XkbAllocSrvLedInfo(DeviceIntPtr dev,
527*4882a593Smuzhiyun KbdFeedbackPtr kf, LedFeedbackPtr lf, unsigned needed_parts)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun XkbSrvLedInfoPtr sli;
530*4882a593Smuzhiyun Bool checkAccel;
531*4882a593Smuzhiyun Bool checkNames;
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun sli = NULL;
534*4882a593Smuzhiyun checkAccel = checkNames = FALSE;
535*4882a593Smuzhiyun if ((kf != NULL) && (kf->xkb_sli == NULL)) {
536*4882a593Smuzhiyun kf->xkb_sli = sli = calloc(1, sizeof(XkbSrvLedInfoRec));
537*4882a593Smuzhiyun if (sli == NULL)
538*4882a593Smuzhiyun return NULL; /* ALLOCATION ERROR */
539*4882a593Smuzhiyun if (dev->key && dev->key->xkbInfo)
540*4882a593Smuzhiyun sli->flags = XkbSLI_HasOwnState;
541*4882a593Smuzhiyun else
542*4882a593Smuzhiyun sli->flags = 0;
543*4882a593Smuzhiyun sli->class = KbdFeedbackClass;
544*4882a593Smuzhiyun sli->id = kf->ctrl.id;
545*4882a593Smuzhiyun sli->fb.kf = kf;
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun sli->autoState = 0;
548*4882a593Smuzhiyun sli->explicitState = kf->ctrl.leds;
549*4882a593Smuzhiyun sli->effectiveState = kf->ctrl.leds;
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun if ((kf == dev->kbdfeed) && (dev->key) && (dev->key->xkbInfo)) {
552*4882a593Smuzhiyun XkbDescPtr xkb;
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun xkb = dev->key->xkbInfo->desc;
555*4882a593Smuzhiyun sli->flags |= XkbSLI_IsDefault;
556*4882a593Smuzhiyun sli->physIndicators = xkb->indicators->phys_indicators;
557*4882a593Smuzhiyun sli->names = xkb->names->indicators;
558*4882a593Smuzhiyun sli->maps = xkb->indicators->maps;
559*4882a593Smuzhiyun checkNames = checkAccel = TRUE;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun else {
562*4882a593Smuzhiyun sli->physIndicators = XkbAllIndicatorsMask;
563*4882a593Smuzhiyun sli->names = NULL;
564*4882a593Smuzhiyun sli->maps = NULL;
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun else if ((kf != NULL) && ((kf->xkb_sli->flags & XkbSLI_IsDefault) != 0)) {
568*4882a593Smuzhiyun XkbDescPtr xkb;
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun xkb = dev->key->xkbInfo->desc;
571*4882a593Smuzhiyun sli = kf->xkb_sli;
572*4882a593Smuzhiyun sli->physIndicators = xkb->indicators->phys_indicators;
573*4882a593Smuzhiyun if (xkb->names->indicators != sli->names) {
574*4882a593Smuzhiyun checkNames = TRUE;
575*4882a593Smuzhiyun sli->names = xkb->names->indicators;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun if (xkb->indicators->maps != sli->maps) {
578*4882a593Smuzhiyun checkAccel = TRUE;
579*4882a593Smuzhiyun sli->maps = xkb->indicators->maps;
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun else if ((lf != NULL) && (lf->xkb_sli == NULL)) {
583*4882a593Smuzhiyun lf->xkb_sli = sli = calloc(1, sizeof(XkbSrvLedInfoRec));
584*4882a593Smuzhiyun if (sli == NULL)
585*4882a593Smuzhiyun return NULL; /* ALLOCATION ERROR */
586*4882a593Smuzhiyun if (dev->key && dev->key->xkbInfo)
587*4882a593Smuzhiyun sli->flags = XkbSLI_HasOwnState;
588*4882a593Smuzhiyun else
589*4882a593Smuzhiyun sli->flags = 0;
590*4882a593Smuzhiyun sli->class = LedFeedbackClass;
591*4882a593Smuzhiyun sli->id = lf->ctrl.id;
592*4882a593Smuzhiyun sli->fb.lf = lf;
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun sli->physIndicators = lf->ctrl.led_mask;
595*4882a593Smuzhiyun sli->autoState = 0;
596*4882a593Smuzhiyun sli->explicitState = lf->ctrl.led_values;
597*4882a593Smuzhiyun sli->effectiveState = lf->ctrl.led_values;
598*4882a593Smuzhiyun sli->maps = NULL;
599*4882a593Smuzhiyun sli->names = NULL;
600*4882a593Smuzhiyun }
601*4882a593Smuzhiyun else
602*4882a593Smuzhiyun return NULL;
603*4882a593Smuzhiyun if ((sli->names == NULL) && (needed_parts & XkbXI_IndicatorNamesMask))
604*4882a593Smuzhiyun sli->names = calloc(XkbNumIndicators, sizeof(Atom));
605*4882a593Smuzhiyun if ((sli->maps == NULL) && (needed_parts & XkbXI_IndicatorMapsMask))
606*4882a593Smuzhiyun sli->maps = calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec));
607*4882a593Smuzhiyun if (checkNames) {
608*4882a593Smuzhiyun register unsigned i, bit;
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun sli->namesPresent = 0;
611*4882a593Smuzhiyun for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
612*4882a593Smuzhiyun if (sli->names[i] != None)
613*4882a593Smuzhiyun sli->namesPresent |= bit;
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun if (checkAccel)
617*4882a593Smuzhiyun XkbCheckIndicatorMaps(dev, sli, XkbAllIndicatorsMask);
618*4882a593Smuzhiyun return sli;
619*4882a593Smuzhiyun }
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun void
XkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli)622*4882a593Smuzhiyun XkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli)
623*4882a593Smuzhiyun {
624*4882a593Smuzhiyun if ((sli->flags & XkbSLI_IsDefault) == 0) {
625*4882a593Smuzhiyun free(sli->maps);
626*4882a593Smuzhiyun free(sli->names);
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun sli->maps = NULL;
629*4882a593Smuzhiyun sli->names = NULL;
630*4882a593Smuzhiyun free(sli);
631*4882a593Smuzhiyun return;
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun /*
635*4882a593Smuzhiyun * XkbSrvLedInfoPtr
636*4882a593Smuzhiyun * XkbCopySrvLedInfo(dev,src,kf,lf)
637*4882a593Smuzhiyun *
638*4882a593Smuzhiyun * Takes the given XkbSrvLedInfoPtr and duplicates it. A deep copy is made,
639*4882a593Smuzhiyun * thus the new copy behaves like the original one and can be freed with
640*4882a593Smuzhiyun * XkbFreeSrvLedInfo.
641*4882a593Smuzhiyun */
642*4882a593Smuzhiyun XkbSrvLedInfoPtr
XkbCopySrvLedInfo(DeviceIntPtr from,XkbSrvLedInfoPtr src,KbdFeedbackPtr kf,LedFeedbackPtr lf)643*4882a593Smuzhiyun XkbCopySrvLedInfo(DeviceIntPtr from,
644*4882a593Smuzhiyun XkbSrvLedInfoPtr src, KbdFeedbackPtr kf, LedFeedbackPtr lf)
645*4882a593Smuzhiyun {
646*4882a593Smuzhiyun XkbSrvLedInfoPtr sli_new = NULL;
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun if (!src)
649*4882a593Smuzhiyun goto finish;
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun sli_new = calloc(1, sizeof(XkbSrvLedInfoRec));
652*4882a593Smuzhiyun if (!sli_new)
653*4882a593Smuzhiyun goto finish;
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun memcpy(sli_new, src, sizeof(XkbSrvLedInfoRec));
656*4882a593Smuzhiyun if (sli_new->class == KbdFeedbackClass)
657*4882a593Smuzhiyun sli_new->fb.kf = kf;
658*4882a593Smuzhiyun else
659*4882a593Smuzhiyun sli_new->fb.lf = lf;
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun if (!(sli_new->flags & XkbSLI_IsDefault)) {
662*4882a593Smuzhiyun sli_new->names = calloc(XkbNumIndicators, sizeof(Atom));
663*4882a593Smuzhiyun sli_new->maps = calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec));
664*4882a593Smuzhiyun } /* else sli_new->names/maps is pointing to
665*4882a593Smuzhiyun dev->key->xkbInfo->desc->names->indicators;
666*4882a593Smuzhiyun dev->key->xkbInfo->desc->names->indicators; */
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun finish:
669*4882a593Smuzhiyun return sli_new;
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun /***====================================================================***/
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun /*
675*4882a593Smuzhiyun * XkbSrvLedInfoPtr
676*4882a593Smuzhiyun * XkbFindSrvLedInfo(dev,class,id,needed_parts)
677*4882a593Smuzhiyun *
678*4882a593Smuzhiyun * Finds the XkbSrvLedInfoPtr for the specified 'class' and 'id'
679*4882a593Smuzhiyun * on the device specified by 'dev.' If the class and id specify
680*4882a593Smuzhiyun * a valid device feedback, this function returns the existing
681*4882a593Smuzhiyun * feedback or allocates a new one.
682*4882a593Smuzhiyun *
683*4882a593Smuzhiyun */
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun XkbSrvLedInfoPtr
XkbFindSrvLedInfo(DeviceIntPtr dev,unsigned class,unsigned id,unsigned needed_parts)686*4882a593Smuzhiyun XkbFindSrvLedInfo(DeviceIntPtr dev,
687*4882a593Smuzhiyun unsigned class, unsigned id, unsigned needed_parts)
688*4882a593Smuzhiyun {
689*4882a593Smuzhiyun XkbSrvLedInfoPtr sli;
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun /* optimization to check for most common case */
692*4882a593Smuzhiyun if (((class == XkbDfltXIClass) && (id == XkbDfltXIId)) && (dev->kbdfeed)) {
693*4882a593Smuzhiyun if (dev->kbdfeed->xkb_sli == NULL) {
694*4882a593Smuzhiyun dev->kbdfeed->xkb_sli =
695*4882a593Smuzhiyun XkbAllocSrvLedInfo(dev, dev->kbdfeed, NULL, needed_parts);
696*4882a593Smuzhiyun }
697*4882a593Smuzhiyun return dev->kbdfeed->xkb_sli;
698*4882a593Smuzhiyun }
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun sli = NULL;
701*4882a593Smuzhiyun if (class == XkbDfltXIClass) {
702*4882a593Smuzhiyun if (dev->kbdfeed)
703*4882a593Smuzhiyun class = KbdFeedbackClass;
704*4882a593Smuzhiyun else if (dev->leds)
705*4882a593Smuzhiyun class = LedFeedbackClass;
706*4882a593Smuzhiyun else
707*4882a593Smuzhiyun return NULL;
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun if (class == KbdFeedbackClass) {
710*4882a593Smuzhiyun KbdFeedbackPtr kf;
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun for (kf = dev->kbdfeed; kf != NULL; kf = kf->next) {
713*4882a593Smuzhiyun if ((id == XkbDfltXIId) || (id == kf->ctrl.id)) {
714*4882a593Smuzhiyun if (kf->xkb_sli == NULL)
715*4882a593Smuzhiyun kf->xkb_sli =
716*4882a593Smuzhiyun XkbAllocSrvLedInfo(dev, kf, NULL, needed_parts);
717*4882a593Smuzhiyun sli = kf->xkb_sli;
718*4882a593Smuzhiyun break;
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun }
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun else if (class == LedFeedbackClass) {
723*4882a593Smuzhiyun LedFeedbackPtr lf;
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun for (lf = dev->leds; lf != NULL; lf = lf->next) {
726*4882a593Smuzhiyun if ((id == XkbDfltXIId) || (id == lf->ctrl.id)) {
727*4882a593Smuzhiyun if (lf->xkb_sli == NULL)
728*4882a593Smuzhiyun lf->xkb_sli =
729*4882a593Smuzhiyun XkbAllocSrvLedInfo(dev, NULL, lf, needed_parts);
730*4882a593Smuzhiyun sli = lf->xkb_sli;
731*4882a593Smuzhiyun break;
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun }
734*4882a593Smuzhiyun }
735*4882a593Smuzhiyun if (sli) {
736*4882a593Smuzhiyun if ((sli->names == NULL) && (needed_parts & XkbXI_IndicatorNamesMask))
737*4882a593Smuzhiyun sli->names = calloc(XkbNumIndicators, sizeof(Atom));
738*4882a593Smuzhiyun if ((sli->maps == NULL) && (needed_parts & XkbXI_IndicatorMapsMask))
739*4882a593Smuzhiyun sli->maps = calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec));
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun return sli;
742*4882a593Smuzhiyun }
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun /***====================================================================***/
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun void
XkbFlushLedEvents(DeviceIntPtr dev,DeviceIntPtr kbd,XkbSrvLedInfoPtr sli,xkbExtensionDeviceNotify * ed,XkbChangesPtr changes,XkbEventCausePtr cause)747*4882a593Smuzhiyun XkbFlushLedEvents(DeviceIntPtr dev,
748*4882a593Smuzhiyun DeviceIntPtr kbd,
749*4882a593Smuzhiyun XkbSrvLedInfoPtr sli,
750*4882a593Smuzhiyun xkbExtensionDeviceNotify * ed,
751*4882a593Smuzhiyun XkbChangesPtr changes, XkbEventCausePtr cause)
752*4882a593Smuzhiyun {
753*4882a593Smuzhiyun if (changes) {
754*4882a593Smuzhiyun if (changes->indicators.state_changes)
755*4882a593Smuzhiyun XkbDDXUpdateDeviceIndicators(dev, sli, sli->effectiveState);
756*4882a593Smuzhiyun XkbSendNotification(kbd, changes, cause);
757*4882a593Smuzhiyun memset((char *) changes, 0, sizeof(XkbChangesRec));
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun if (XkbAX_NeedFeedback
760*4882a593Smuzhiyun (kbd->key->xkbInfo->desc->ctrls, XkbAX_IndicatorFBMask)) {
761*4882a593Smuzhiyun if (sli->effectiveState)
762*4882a593Smuzhiyun /* it appears that the which parameter is not used */
763*4882a593Smuzhiyun XkbDDXAccessXBeep(dev, _BEEP_LED_ON, XkbAccessXFeedbackMask);
764*4882a593Smuzhiyun else
765*4882a593Smuzhiyun XkbDDXAccessXBeep(dev, _BEEP_LED_OFF, XkbAccessXFeedbackMask);
766*4882a593Smuzhiyun }
767*4882a593Smuzhiyun }
768*4882a593Smuzhiyun if (ed) {
769*4882a593Smuzhiyun if (ed->reason) {
770*4882a593Smuzhiyun if ((dev != kbd) && (ed->reason & XkbXI_IndicatorStateMask))
771*4882a593Smuzhiyun XkbDDXUpdateDeviceIndicators(dev, sli, sli->effectiveState);
772*4882a593Smuzhiyun XkbSendExtensionDeviceNotify(dev, cause->client, ed);
773*4882a593Smuzhiyun }
774*4882a593Smuzhiyun memset((char *) ed, 0, sizeof(XkbExtensionDeviceNotify));
775*4882a593Smuzhiyun }
776*4882a593Smuzhiyun return;
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun /***====================================================================***/
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun void
XkbApplyLedNameChanges(DeviceIntPtr dev,XkbSrvLedInfoPtr sli,unsigned changed_names,xkbExtensionDeviceNotify * ed,XkbChangesPtr changes,XkbEventCausePtr cause)782*4882a593Smuzhiyun XkbApplyLedNameChanges(DeviceIntPtr dev,
783*4882a593Smuzhiyun XkbSrvLedInfoPtr sli,
784*4882a593Smuzhiyun unsigned changed_names,
785*4882a593Smuzhiyun xkbExtensionDeviceNotify * ed,
786*4882a593Smuzhiyun XkbChangesPtr changes, XkbEventCausePtr cause)
787*4882a593Smuzhiyun {
788*4882a593Smuzhiyun DeviceIntPtr kbd;
789*4882a593Smuzhiyun XkbChangesRec my_changes;
790*4882a593Smuzhiyun xkbExtensionDeviceNotify my_ed;
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun if (changed_names == 0)
793*4882a593Smuzhiyun return;
794*4882a593Smuzhiyun if (dev->key && dev->key->xkbInfo)
795*4882a593Smuzhiyun kbd = dev;
796*4882a593Smuzhiyun else
797*4882a593Smuzhiyun kbd = inputInfo.keyboard;
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun if (ed == NULL) {
800*4882a593Smuzhiyun ed = &my_ed;
801*4882a593Smuzhiyun memset((char *) ed, 0, sizeof(xkbExtensionDeviceNotify));
802*4882a593Smuzhiyun }
803*4882a593Smuzhiyun else if ((ed->reason & XkbXI_IndicatorsMask) &&
804*4882a593Smuzhiyun ((ed->ledClass != sli->class) || (ed->ledID != sli->id))) {
805*4882a593Smuzhiyun XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
806*4882a593Smuzhiyun }
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun if ((kbd == dev) && (sli->flags & XkbSLI_IsDefault)) {
809*4882a593Smuzhiyun if (changes == NULL) {
810*4882a593Smuzhiyun changes = &my_changes;
811*4882a593Smuzhiyun memset((char *) changes, 0, sizeof(XkbChangesRec));
812*4882a593Smuzhiyun }
813*4882a593Smuzhiyun changes->names.changed |= XkbIndicatorNamesMask;
814*4882a593Smuzhiyun changes->names.changed_indicators |= changed_names;
815*4882a593Smuzhiyun }
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun ed->reason |= XkbXI_IndicatorNamesMask;
818*4882a593Smuzhiyun ed->ledClass = sli->class;
819*4882a593Smuzhiyun ed->ledID = sli->id;
820*4882a593Smuzhiyun ed->ledsDefined = sli->namesPresent | sli->mapsPresent;
821*4882a593Smuzhiyun ed->ledState = sli->effectiveState;
822*4882a593Smuzhiyun ed->unsupported = 0;
823*4882a593Smuzhiyun ed->supported = XkbXI_AllFeaturesMask;
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun if (changes != &my_changes)
826*4882a593Smuzhiyun changes = NULL;
827*4882a593Smuzhiyun if (ed != &my_ed)
828*4882a593Smuzhiyun ed = NULL;
829*4882a593Smuzhiyun if (changes || ed)
830*4882a593Smuzhiyun XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
831*4882a593Smuzhiyun return;
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun /***====================================================================***/
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun /*
837*4882a593Smuzhiyun * void
838*4882a593Smuzhiyun * XkbApplyLedMapChanges(dev,sli,changed_maps,changes,cause)
839*4882a593Smuzhiyun *
840*4882a593Smuzhiyun * Handles all of the secondary effects of the changes to the
841*4882a593Smuzhiyun * feedback specified by 'sli' on the device specified by 'dev.'
842*4882a593Smuzhiyun *
843*4882a593Smuzhiyun * If 'changed_maps' specifies any indicators, this function generates
844*4882a593Smuzhiyun * XkbExtensionDeviceNotify events and possibly IndicatorMapNotify
845*4882a593Smuzhiyun * events to report the changes, and recalculates the effective
846*4882a593Smuzhiyun * state of each indicator with a changed map. If any indicators
847*4882a593Smuzhiyun * change state, the server generates XkbExtensionDeviceNotify and
848*4882a593Smuzhiyun * XkbIndicatorStateNotify events as appropriate.
849*4882a593Smuzhiyun *
850*4882a593Smuzhiyun * If 'changes' is non-NULL, this function updates it to reflect
851*4882a593Smuzhiyun * any changes to the keyboard state or controls or to the 'core'
852*4882a593Smuzhiyun * indicator names, maps, or state. If 'changes' is NULL, this
853*4882a593Smuzhiyun * function generates XKB events as needed to report the changes.
854*4882a593Smuzhiyun * If 'dev' is not a keyboard device, any changes are reported
855*4882a593Smuzhiyun * for the core keyboard.
856*4882a593Smuzhiyun *
857*4882a593Smuzhiyun * The 'cause' specifies the reason for the event (key event or
858*4882a593Smuzhiyun * request) for the change, as reported in some XKB events.
859*4882a593Smuzhiyun */
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun void
XkbApplyLedMapChanges(DeviceIntPtr dev,XkbSrvLedInfoPtr sli,unsigned changed_maps,xkbExtensionDeviceNotify * ed,XkbChangesPtr changes,XkbEventCausePtr cause)862*4882a593Smuzhiyun XkbApplyLedMapChanges(DeviceIntPtr dev,
863*4882a593Smuzhiyun XkbSrvLedInfoPtr sli,
864*4882a593Smuzhiyun unsigned changed_maps,
865*4882a593Smuzhiyun xkbExtensionDeviceNotify * ed,
866*4882a593Smuzhiyun XkbChangesPtr changes, XkbEventCausePtr cause)
867*4882a593Smuzhiyun {
868*4882a593Smuzhiyun DeviceIntPtr kbd;
869*4882a593Smuzhiyun XkbChangesRec my_changes;
870*4882a593Smuzhiyun xkbExtensionDeviceNotify my_ed;
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun if (changed_maps == 0)
873*4882a593Smuzhiyun return;
874*4882a593Smuzhiyun if (dev->key && dev->key->xkbInfo)
875*4882a593Smuzhiyun kbd = dev;
876*4882a593Smuzhiyun else
877*4882a593Smuzhiyun kbd = inputInfo.keyboard;
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun if (ed == NULL) {
880*4882a593Smuzhiyun ed = &my_ed;
881*4882a593Smuzhiyun memset((char *) ed, 0, sizeof(xkbExtensionDeviceNotify));
882*4882a593Smuzhiyun }
883*4882a593Smuzhiyun else if ((ed->reason & XkbXI_IndicatorsMask) &&
884*4882a593Smuzhiyun ((ed->ledClass != sli->class) || (ed->ledID != sli->id))) {
885*4882a593Smuzhiyun XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
886*4882a593Smuzhiyun }
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun if ((kbd == dev) && (sli->flags & XkbSLI_IsDefault)) {
889*4882a593Smuzhiyun if (changes == NULL) {
890*4882a593Smuzhiyun changes = &my_changes;
891*4882a593Smuzhiyun memset((char *) changes, 0, sizeof(XkbChangesRec));
892*4882a593Smuzhiyun }
893*4882a593Smuzhiyun changes->indicators.map_changes |= changed_maps;
894*4882a593Smuzhiyun }
895*4882a593Smuzhiyun
896*4882a593Smuzhiyun XkbCheckIndicatorMaps(dev, sli, changed_maps);
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun ed->reason |= XkbXI_IndicatorMapsMask;
899*4882a593Smuzhiyun ed->ledClass = sli->class;
900*4882a593Smuzhiyun ed->ledID = sli->id;
901*4882a593Smuzhiyun ed->ledsDefined = sli->namesPresent | sli->mapsPresent;
902*4882a593Smuzhiyun ed->ledState = sli->effectiveState;
903*4882a593Smuzhiyun ed->unsupported = 0;
904*4882a593Smuzhiyun ed->supported = XkbXI_AllFeaturesMask;
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun XkbUpdateLedAutoState(dev, sli, changed_maps, ed, changes, cause);
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun if (changes != &my_changes)
909*4882a593Smuzhiyun changes = NULL;
910*4882a593Smuzhiyun if (ed != &my_ed)
911*4882a593Smuzhiyun ed = NULL;
912*4882a593Smuzhiyun if (changes || ed)
913*4882a593Smuzhiyun XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
914*4882a593Smuzhiyun return;
915*4882a593Smuzhiyun }
916*4882a593Smuzhiyun
917*4882a593Smuzhiyun /***====================================================================***/
918*4882a593Smuzhiyun
919*4882a593Smuzhiyun void
XkbApplyLedStateChanges(DeviceIntPtr dev,XkbSrvLedInfoPtr sli,unsigned changed_leds,xkbExtensionDeviceNotify * ed,XkbChangesPtr changes,XkbEventCausePtr cause)920*4882a593Smuzhiyun XkbApplyLedStateChanges(DeviceIntPtr dev,
921*4882a593Smuzhiyun XkbSrvLedInfoPtr sli,
922*4882a593Smuzhiyun unsigned changed_leds,
923*4882a593Smuzhiyun xkbExtensionDeviceNotify * ed,
924*4882a593Smuzhiyun XkbChangesPtr changes, XkbEventCausePtr cause)
925*4882a593Smuzhiyun {
926*4882a593Smuzhiyun XkbSrvInfoPtr xkbi;
927*4882a593Smuzhiyun DeviceIntPtr kbd;
928*4882a593Smuzhiyun XkbChangesRec my_changes;
929*4882a593Smuzhiyun xkbExtensionDeviceNotify my_ed;
930*4882a593Smuzhiyun register unsigned i, bit, affected;
931*4882a593Smuzhiyun XkbIndicatorMapPtr map;
932*4882a593Smuzhiyun unsigned oldState;
933*4882a593Smuzhiyun Bool kb_changed;
934*4882a593Smuzhiyun
935*4882a593Smuzhiyun if (changed_leds == 0)
936*4882a593Smuzhiyun return;
937*4882a593Smuzhiyun if (dev->key && dev->key->xkbInfo)
938*4882a593Smuzhiyun kbd = dev;
939*4882a593Smuzhiyun else
940*4882a593Smuzhiyun kbd = inputInfo.keyboard;
941*4882a593Smuzhiyun xkbi = kbd->key->xkbInfo;
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun if (changes == NULL) {
944*4882a593Smuzhiyun changes = &my_changes;
945*4882a593Smuzhiyun memset((char *) changes, 0, sizeof(XkbChangesRec));
946*4882a593Smuzhiyun }
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun kb_changed = FALSE;
949*4882a593Smuzhiyun affected = changed_leds;
950*4882a593Smuzhiyun oldState = sli->effectiveState;
951*4882a593Smuzhiyun for (i = 0, bit = 1; (i < XkbNumIndicators) && (affected); i++, bit <<= 1) {
952*4882a593Smuzhiyun if ((affected & bit) == 0)
953*4882a593Smuzhiyun continue;
954*4882a593Smuzhiyun affected &= ~bit;
955*4882a593Smuzhiyun map = &sli->maps[i];
956*4882a593Smuzhiyun if (map->flags & XkbIM_NoExplicit) {
957*4882a593Smuzhiyun sli->explicitState &= ~bit;
958*4882a593Smuzhiyun continue;
959*4882a593Smuzhiyun }
960*4882a593Smuzhiyun if (map->flags & XkbIM_LEDDrivesKB) {
961*4882a593Smuzhiyun Bool on = ((sli->explicitState & bit) != 0);
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun if (XkbApplyLEDChangeToKeyboard(xkbi, map, on, changes))
964*4882a593Smuzhiyun kb_changed = TRUE;
965*4882a593Smuzhiyun }
966*4882a593Smuzhiyun }
967*4882a593Smuzhiyun sli->effectiveState = (sli->autoState | sli->explicitState);
968*4882a593Smuzhiyun affected = sli->effectiveState ^ oldState;
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun if (ed == NULL) {
971*4882a593Smuzhiyun ed = &my_ed;
972*4882a593Smuzhiyun memset((char *) ed, 0, sizeof(xkbExtensionDeviceNotify));
973*4882a593Smuzhiyun }
974*4882a593Smuzhiyun else if (affected && (ed->reason & XkbXI_IndicatorsMask) &&
975*4882a593Smuzhiyun ((ed->ledClass != sli->class) || (ed->ledID != sli->id))) {
976*4882a593Smuzhiyun XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
977*4882a593Smuzhiyun }
978*4882a593Smuzhiyun
979*4882a593Smuzhiyun if ((kbd == dev) && (sli->flags & XkbSLI_IsDefault))
980*4882a593Smuzhiyun changes->indicators.state_changes |= affected;
981*4882a593Smuzhiyun if (affected) {
982*4882a593Smuzhiyun ed->reason |= XkbXI_IndicatorStateMask;
983*4882a593Smuzhiyun ed->ledClass = sli->class;
984*4882a593Smuzhiyun ed->ledID = sli->id;
985*4882a593Smuzhiyun ed->ledsDefined = sli->namesPresent | sli->mapsPresent;
986*4882a593Smuzhiyun ed->ledState = sli->effectiveState;
987*4882a593Smuzhiyun ed->unsupported = 0;
988*4882a593Smuzhiyun ed->supported = XkbXI_AllFeaturesMask;
989*4882a593Smuzhiyun }
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun if (kb_changed) {
992*4882a593Smuzhiyun XkbComputeDerivedState(kbd->key->xkbInfo);
993*4882a593Smuzhiyun XkbUpdateLedAutoState(dev, sli, sli->mapsPresent, ed, changes, cause);
994*4882a593Smuzhiyun }
995*4882a593Smuzhiyun
996*4882a593Smuzhiyun if (changes != &my_changes)
997*4882a593Smuzhiyun changes = NULL;
998*4882a593Smuzhiyun if (ed != &my_ed)
999*4882a593Smuzhiyun ed = NULL;
1000*4882a593Smuzhiyun if (changes || ed)
1001*4882a593Smuzhiyun XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
1002*4882a593Smuzhiyun if (kb_changed)
1003*4882a593Smuzhiyun XkbUpdateAllDeviceIndicators(NULL, cause);
1004*4882a593Smuzhiyun return;
1005*4882a593Smuzhiyun }
1006