xkbActions.c revision 4642e01f
1/************************************************************
2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4Permission to use, copy, modify, and distribute this
5software and its documentation for any purpose and without
6fee is hereby granted, provided that the above copyright
7notice appear in all copies and that both that copyright
8notice and this permission notice appear in supporting
9documentation, and that the name of Silicon Graphics not be
10used in advertising or publicity pertaining to distribution
11of the software without specific prior written permission.
12Silicon Graphics makes no representation about the suitability
13of this software for any purpose. It is provided "as is"
14without any express or implied warranty.
15
16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25********************************************************/
26
27#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#endif
30
31#include <stdio.h>
32#include <math.h>
33#define NEED_EVENTS 1
34#include <X11/X.h>
35#include <X11/Xproto.h>
36#include <X11/keysym.h>
37#include "misc.h"
38#include "inputstr.h"
39#include "exevents.h"
40#include <xkbsrv.h>
41#include "xkb.h"
42#include <ctype.h>
43#define EXTENSION_EVENT_BASE 64
44
45static int xkbDevicePrivateKeyIndex;
46DevPrivateKey xkbDevicePrivateKey = &xkbDevicePrivateKeyIndex;
47
48void
49xkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc,
50                   pointer data)
51{
52    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device);
53    ProcessInputProc backupproc;
54    if(xkbPrivPtr->unwrapProc)
55	xkbPrivPtr->unwrapProc = NULL;
56
57    UNWRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr, backupproc);
58    proc(device,data);
59    COND_WRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr,
60				 backupproc,xkbUnwrapProc);
61}
62
63
64void
65XkbSetExtension(DeviceIntPtr device, ProcessInputProc proc)
66{
67    xkbDeviceInfoPtr xkbPrivPtr;
68
69    xkbPrivPtr = (xkbDeviceInfoPtr) xcalloc(1, sizeof(xkbDeviceInfoRec));
70    if (!xkbPrivPtr)
71	return;
72    xkbPrivPtr->unwrapProc = NULL;
73
74    dixSetPrivate(&device->devPrivates, xkbDevicePrivateKey, xkbPrivPtr);
75    WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, proc, xkbUnwrapProc);
76}
77
78extern	void	ProcessOtherEvent(
79    xEvent *		/* xE */,
80    DeviceIntPtr 	/* dev */,
81    int 		/* count */
82);
83
84/***====================================================================***/
85
86static XkbAction
87_FixUpAction(XkbDescPtr xkb,XkbAction *act)
88{
89static XkbAction	fake;
90
91    if (XkbIsPtrAction(act)&&(!(xkb->ctrls->enabled_ctrls&XkbMouseKeysMask))) {
92	fake.type = XkbSA_NoAction;
93	return fake;
94    }
95    if (XkbDisableLockActions) {
96	switch (act->type) {
97	    case XkbSA_LockMods:
98		fake.mods.type  = XkbSA_SetMods;
99		fake.mods.flags = 0;
100		fake.mods.mask  = act->mods.mask;
101		return fake;
102	    case XkbSA_LatchMods:
103		fake.mods.type  = XkbSA_SetMods;
104		fake.mods.flags = 0;
105		fake.mods.mask  = act->mods.mask;
106		return fake;
107	    case XkbSA_ISOLock:
108		if (act->iso.flags&XkbSA_ISODfltIsGroup) {
109		     fake.group.type = XkbSA_SetGroup;
110		     fake.group.flags = act->iso.flags&XkbSA_GroupAbsolute;
111		     XkbSASetGroup(&fake.group,XkbSAGroup(&act->iso));
112		}
113		else {
114		     fake.mods.type  = XkbSA_SetMods;
115		     fake.mods.flags = 0;
116		     fake.mods.mask  = act->iso.mask;
117		}
118		return fake;
119	    case XkbSA_LockGroup:
120	    case XkbSA_LatchGroup:
121		/* We want everything from the latch/lock action except the
122		 * type should be changed to set.
123		 */
124		fake = *act;
125		fake.group.type = XkbSA_SetGroup;
126		return fake;
127	}
128    }
129    else
130    if (xkb->ctrls->enabled_ctrls&XkbStickyKeysMask) {
131	if (act->any.type==XkbSA_SetMods) {
132	    fake.mods.type = XkbSA_LatchMods;
133	    fake.mods.mask = act->mods.mask;
134	    if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask))
135		 fake.mods.flags= XkbSA_ClearLocks|XkbSA_LatchToLock;
136	    else fake.mods.flags= XkbSA_ClearLocks;
137	    return fake;
138	}
139	if (act->any.type==XkbSA_SetGroup) {
140	    fake.group.type = XkbSA_LatchGroup;
141	    if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask))
142		 fake.group.flags= XkbSA_ClearLocks|XkbSA_LatchToLock;
143	    else fake.group.flags= XkbSA_ClearLocks;
144	    XkbSASetGroup(&fake.group,XkbSAGroup(&act->group));
145	    return fake;
146	}
147    }
148    return *act;
149}
150
151static XkbAction
152XkbGetKeyAction(XkbSrvInfoPtr xkbi,XkbStatePtr xkbState,CARD8 key)
153{
154int			effectiveGroup;
155int			col;
156XkbDescPtr		xkb;
157XkbKeyTypePtr		type;
158XkbAction *		pActs;
159static XkbAction 	fake;
160
161    xkb= xkbi->desc;
162    if (!XkbKeyHasActions(xkb,key) || !XkbKeycodeInRange(xkb,key)) {
163	fake.type = XkbSA_NoAction;
164	return fake;
165    }
166    pActs= XkbKeyActionsPtr(xkb,key);
167    col= 0;
168    effectiveGroup= xkbState->group;
169    if (effectiveGroup!=XkbGroup1Index) {
170	if (XkbKeyNumGroups(xkb,key)>(unsigned)1) {
171	    if (effectiveGroup>=XkbKeyNumGroups(xkb,key)) {
172		unsigned gi= XkbKeyGroupInfo(xkb,key);
173		switch (XkbOutOfRangeGroupAction(gi)) {
174		    default:
175		    case XkbWrapIntoRange:
176			effectiveGroup %= XkbKeyNumGroups(xkb,key);
177			break;
178		    case XkbClampIntoRange:
179			effectiveGroup = XkbKeyNumGroups(xkb,key)-1;
180			break;
181		    case XkbRedirectIntoRange:
182			effectiveGroup= XkbOutOfRangeGroupInfo(gi);
183			if (effectiveGroup>=XkbKeyNumGroups(xkb,key))
184			    effectiveGroup= 0;
185			break;
186		}
187	    }
188	}
189	else effectiveGroup= XkbGroup1Index;
190	col+= (effectiveGroup*XkbKeyGroupsWidth(xkb,key));
191    }
192    type= XkbKeyKeyType(xkb,key,effectiveGroup);
193    if (type->map!=NULL) {
194	register unsigned		i,mods;
195	register XkbKTMapEntryPtr	entry;
196	mods= xkbState->mods&type->mods.mask;
197	for (entry= type->map,i=0;i<type->map_count;i++,entry++) {
198	    if ((entry->active)&&(entry->mods.mask==mods)) {
199		col+= entry->level;
200		break;
201	    }
202	}
203    }
204    if (pActs[col].any.type==XkbSA_NoAction)
205	return pActs[col];
206    fake= _FixUpAction(xkb,&pActs[col]);
207    return fake;
208}
209
210static XkbAction
211XkbGetButtonAction(DeviceIntPtr kbd,DeviceIntPtr dev,int button)
212{
213XkbAction fake;
214   if ((dev->button)&&(dev->button->xkb_acts)) {
215	if (dev->button->xkb_acts[button-1].any.type!=XkbSA_NoAction) {
216	    fake= _FixUpAction(kbd->key->xkbInfo->desc,
217					&dev->button->xkb_acts[button-1]);
218	    return fake;
219	}
220   }
221   fake.any.type= XkbSA_NoAction;
222   return fake;
223}
224
225/***====================================================================***/
226
227#define	SYNTHETIC_KEYCODE	1
228#define	BTN_ACT_FLAG		0x100
229
230static int
231_XkbFilterSetState(	XkbSrvInfoPtr	xkbi,
232			XkbFilterPtr	filter,
233			unsigned	keycode,
234			XkbAction *pAction)
235{
236    if (filter->keycode==0) {		/* initial press */
237	filter->keycode = keycode;
238	filter->active = 1;
239	filter->filterOthers = ((pAction->mods.mask&XkbSA_ClearLocks)!=0);
240	filter->priv = 0;
241	filter->filter = _XkbFilterSetState;
242	if (pAction->type==XkbSA_SetMods) {
243	    filter->upAction = *pAction;
244	    xkbi->setMods= pAction->mods.mask;
245	}
246	else {
247	    xkbi->groupChange = XkbSAGroup(&pAction->group);
248	    if (pAction->group.flags&XkbSA_GroupAbsolute)
249		xkbi->groupChange-= xkbi->state.base_group;
250	    filter->upAction= *pAction;
251	    XkbSASetGroup(&filter->upAction.group,xkbi->groupChange);
252	}
253    }
254    else if (filter->keycode==keycode) {
255	if (filter->upAction.type==XkbSA_SetMods) {
256	    xkbi->clearMods = filter->upAction.mods.mask;
257	    if (filter->upAction.mods.flags&XkbSA_ClearLocks) {
258		xkbi->state.locked_mods&= ~filter->upAction.mods.mask;
259	    }
260	}
261	else {
262	    if (filter->upAction.group.flags&XkbSA_ClearLocks) {
263		xkbi->state.locked_group = 0;
264	    }
265	    xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
266	}
267	filter->active = 0;
268    }
269    else {
270	filter->upAction.mods.flags&= ~XkbSA_ClearLocks;
271	filter->filterOthers = 0;
272    }
273    return 1;
274}
275
276#define	LATCH_KEY_DOWN	1
277#define	LATCH_PENDING	2
278#define	NO_LATCH	3
279
280static int
281_XkbFilterLatchState(	XkbSrvInfoPtr	xkbi,
282			XkbFilterPtr	filter,
283			unsigned	keycode,
284			XkbAction *	pAction)
285{
286
287    if (filter->keycode==0) {			/* initial press */
288	filter->keycode = keycode;
289	filter->active = 1;
290	filter->filterOthers = 1;
291	filter->priv = LATCH_KEY_DOWN;
292	filter->filter = _XkbFilterLatchState;
293	if (pAction->type==XkbSA_LatchMods) {
294	    filter->upAction = *pAction;
295	    xkbi->setMods = pAction->mods.mask;
296	}
297	else {
298	    xkbi->groupChange = XkbSAGroup(&pAction->group);
299	    if (pAction->group.flags&XkbSA_GroupAbsolute)
300		 xkbi->groupChange-= xkbi->state.base_group;
301	    filter->upAction= *pAction;
302	    XkbSASetGroup(&filter->upAction.group,xkbi->groupChange);
303	}
304    }
305    else if ( pAction && (filter->priv==LATCH_PENDING) ) {
306	if (((1<<pAction->type)&XkbSA_BreakLatch)!=0) {
307	    filter->active = 0;
308	    if (filter->upAction.type==XkbSA_LatchMods)
309		 xkbi->state.latched_mods&= ~filter->upAction.mods.mask;
310	    else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group);
311	}
312	else if ((pAction->type==filter->upAction.type)&&
313		 (pAction->mods.flags==filter->upAction.mods.flags)&&
314		 (pAction->mods.mask==filter->upAction.mods.mask)) {
315	    if (filter->upAction.mods.flags&XkbSA_LatchToLock) {
316		XkbControlsPtr ctrls= xkbi->desc->ctrls;
317		if (filter->upAction.type==XkbSA_LatchMods)
318		     pAction->mods.type= XkbSA_LockMods;
319		else pAction->group.type= XkbSA_LockGroup;
320		if (XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)&&
321		    		(ctrls->enabled_ctrls&XkbStickyKeysMask)) {
322		    XkbDDXAccessXBeep(xkbi->device,_BEEP_STICKY_LOCK,
323						XkbStickyKeysMask);
324		}
325	    }
326	    else {
327		if (filter->upAction.type==XkbSA_LatchMods)
328		     pAction->mods.type= XkbSA_SetMods;
329		else pAction->group.type= XkbSA_SetGroup;
330	    }
331	    if (filter->upAction.type==XkbSA_LatchMods)
332		 xkbi->state.latched_mods&= ~filter->upAction.mods.mask;
333	    else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group);
334	    filter->active = 0;
335	}
336    }
337    else if (filter->keycode==keycode) {	/* release */
338	XkbControlsPtr	ctrls= xkbi->desc->ctrls;
339	int		needBeep;
340	int		beepType= _BEEP_NONE;
341
342	needBeep= ((ctrls->enabled_ctrls&XkbStickyKeysMask)&&
343			XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask));
344	if (filter->upAction.type==XkbSA_LatchMods) {
345	    xkbi->clearMods = filter->upAction.mods.mask;
346	    if ((filter->upAction.mods.flags&XkbSA_ClearLocks)&&
347		 (xkbi->clearMods&xkbi->state.locked_mods)==xkbi->clearMods) {
348		xkbi->state.locked_mods&= ~xkbi->clearMods;
349		filter->priv= NO_LATCH;
350		beepType= _BEEP_STICKY_UNLOCK;
351	    }
352	}
353	else {
354	    xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
355	    if ((filter->upAction.group.flags&XkbSA_ClearLocks)&&
356						(xkbi->state.locked_group)) {
357		xkbi->state.locked_group = 0;
358		filter->priv = NO_LATCH;
359		beepType= _BEEP_STICKY_UNLOCK;
360	    }
361	}
362	if (filter->priv==NO_LATCH) {
363	    filter->active= 0;
364	}
365	else {
366	    filter->priv= LATCH_PENDING;
367	    if (filter->upAction.type==XkbSA_LatchMods) {
368		xkbi->state.latched_mods |= filter->upAction.mods.mask;
369		needBeep = xkbi->state.latched_mods ? needBeep : 0;
370		xkbi->state.latched_mods |= filter->upAction.mods.mask;
371	    }
372	    else {
373		xkbi->state.latched_group+= XkbSAGroup(&filter->upAction.group);
374	    }
375	    if (needBeep && (beepType==_BEEP_NONE))
376		beepType= _BEEP_STICKY_LATCH;
377	}
378	if (needBeep && (beepType!=_BEEP_NONE))
379	    XkbDDXAccessXBeep(xkbi->device,beepType,XkbStickyKeysMask);
380    }
381    else if (filter->priv==LATCH_KEY_DOWN) {
382	filter->priv= NO_LATCH;
383	filter->filterOthers = 0;
384    }
385    return 1;
386}
387
388static int
389_XkbFilterLockState(	XkbSrvInfoPtr	xkbi,
390			XkbFilterPtr	filter,
391			unsigned	keycode,
392			XkbAction *	pAction)
393{
394    if (pAction&&(pAction->type==XkbSA_LockGroup)) {
395	if (pAction->group.flags&XkbSA_GroupAbsolute)
396	     xkbi->state.locked_group= XkbSAGroup(&pAction->group);
397	else xkbi->state.locked_group+= XkbSAGroup(&pAction->group);
398	return 1;
399    }
400    if (filter->keycode==0) {		/* initial press */
401	filter->keycode = keycode;
402	filter->active = 1;
403	filter->filterOthers = 0;
404	filter->priv = 0;
405	filter->filter = _XkbFilterLockState;
406	filter->upAction = *pAction;
407	xkbi->state.locked_mods^= pAction->mods.mask;
408	xkbi->setMods = pAction->mods.mask;
409    }
410    else if (filter->keycode==keycode) {
411	filter->active = 0;
412	xkbi->clearMods = filter->upAction.mods.mask;
413    }
414    return 1;
415}
416
417#define	ISO_KEY_DOWN		0
418#define	NO_ISO_LOCK		1
419
420static int
421_XkbFilterISOLock(	XkbSrvInfoPtr	xkbi,
422			XkbFilterPtr	filter,
423			unsigned	keycode,
424			XkbAction *	pAction)
425{
426
427    if (filter->keycode==0) {		/* initial press */
428	CARD8	flags= pAction->iso.flags;
429
430	filter->keycode = keycode;
431	filter->active = 1;
432	filter->filterOthers = 1;
433	filter->priv = ISO_KEY_DOWN;
434	filter->upAction = *pAction;
435	filter->filter = _XkbFilterISOLock;
436	if (flags&XkbSA_ISODfltIsGroup) {
437	    xkbi->groupChange = XkbSAGroup(&pAction->iso);
438	    xkbi->setMods = 0;
439	}
440	else {
441	    xkbi->setMods = pAction->iso.mask;
442	    xkbi->groupChange = 0;
443	}
444	if ((!(flags&XkbSA_ISONoAffectMods))&&(xkbi->state.base_mods)) {
445	    filter->priv= NO_ISO_LOCK;
446	    xkbi->state.locked_mods^= xkbi->state.base_mods;
447	}
448	if ((!(flags&XkbSA_ISONoAffectGroup))&&(xkbi->state.base_group)) {
449/* 6/22/93 (ef) -- lock groups if group key is down first */
450	}
451	if (!(flags&XkbSA_ISONoAffectPtr)) {
452/* 6/22/93 (ef) -- lock mouse buttons if they're down */
453	}
454    }
455    else if (filter->keycode==keycode) {
456	CARD8	flags= filter->upAction.iso.flags;
457
458	if (flags&XkbSA_ISODfltIsGroup) {
459	    xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso);
460	    xkbi->clearMods = 0;
461	    if (filter->priv==ISO_KEY_DOWN)
462		xkbi->state.locked_group+= XkbSAGroup(&filter->upAction.iso);
463	}
464	else {
465	    xkbi->clearMods= filter->upAction.iso.mask;
466	    xkbi->groupChange= 0;
467	    if (filter->priv==ISO_KEY_DOWN)
468		xkbi->state.locked_mods^= filter->upAction.iso.mask;
469	}
470	filter->active = 0;
471    }
472    else if (pAction) {
473	CARD8	flags= filter->upAction.iso.flags;
474
475	switch (pAction->type) {
476	    case XkbSA_SetMods: case XkbSA_LatchMods:
477		if (!(flags&XkbSA_ISONoAffectMods)) {
478		    pAction->type= XkbSA_LockMods;
479		    filter->priv= NO_ISO_LOCK;
480		}
481		break;
482	    case XkbSA_SetGroup: case XkbSA_LatchGroup:
483		if (!(flags&XkbSA_ISONoAffectGroup)) {
484		    pAction->type= XkbSA_LockGroup;
485		    filter->priv= NO_ISO_LOCK;
486		}
487		break;
488	    case XkbSA_PtrBtn:
489		if (!(flags&XkbSA_ISONoAffectPtr)) {
490		     pAction->type= XkbSA_LockPtrBtn;
491		     filter->priv= NO_ISO_LOCK;
492		}
493		break;
494	    case XkbSA_SetControls:
495		if (!(flags&XkbSA_ISONoAffectCtrls)) {
496		    pAction->type= XkbSA_LockControls;
497		    filter->priv= NO_ISO_LOCK;
498		}
499		break;
500	}
501    }
502    return 1;
503}
504
505
506static CARD32
507_XkbPtrAccelExpire(OsTimerPtr timer,CARD32 now,pointer arg)
508{
509XkbSrvInfoPtr	xkbi= (XkbSrvInfoPtr)arg;
510XkbControlsPtr	ctrls= xkbi->desc->ctrls;
511int		dx,dy;
512
513    if (xkbi->mouseKey==0)
514	return 0;
515
516    if (xkbi->mouseKeysAccel) {
517	if ((xkbi->mouseKeysCounter)<ctrls->mk_time_to_max) {
518	    double step;
519	    xkbi->mouseKeysCounter++;
520	    step= xkbi->mouseKeysCurveFactor*
521		 pow((double)xkbi->mouseKeysCounter,xkbi->mouseKeysCurve);
522	    if (xkbi->mouseKeysDX<0)
523		 dx= floor( ((double)xkbi->mouseKeysDX)*step );
524	    else dx=  ceil( ((double)xkbi->mouseKeysDX)*step );
525	    if (xkbi->mouseKeysDY<0)
526		 dy= floor( ((double)xkbi->mouseKeysDY)*step );
527	    else dy=  ceil( ((double)xkbi->mouseKeysDY)*step );
528	}
529	else {
530	    dx= xkbi->mouseKeysDX*ctrls->mk_max_speed;
531	    dy= xkbi->mouseKeysDY*ctrls->mk_max_speed;
532	}
533	if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteX)
534	    dx= xkbi->mouseKeysDX;
535	if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteY)
536	    dy= xkbi->mouseKeysDY;
537    }
538    else {
539	dx= xkbi->mouseKeysDX;
540	dy= xkbi->mouseKeysDY;
541    }
542    XkbDDXFakePointerMotion(xkbi->mouseKeysFlags,dx,dy);
543    return xkbi->desc->ctrls->mk_interval;
544}
545
546static int
547_XkbFilterPointerMove(	XkbSrvInfoPtr	xkbi,
548			XkbFilterPtr	filter,
549			unsigned	keycode,
550			XkbAction *	pAction)
551{
552int	x,y;
553Bool	accel;
554
555    if (xkbi->device == inputInfo.keyboard)
556        return 0;
557
558    if (filter->keycode==0) {		/* initial press */
559	filter->keycode = keycode;
560	filter->active = 1;
561	filter->filterOthers = 0;
562	filter->priv=0;
563	filter->filter = _XkbFilterPointerMove;
564	filter->upAction= *pAction;
565	xkbi->mouseKeysCounter= 0;
566	xkbi->mouseKey= keycode;
567	accel= ((pAction->ptr.flags&XkbSA_NoAcceleration)==0);
568	x= XkbPtrActionX(&pAction->ptr);
569	y= XkbPtrActionY(&pAction->ptr);
570	XkbDDXFakePointerMotion(pAction->ptr.flags,x,y);
571	AccessXCancelRepeatKey(xkbi,keycode);
572	xkbi->mouseKeysAccel= accel&&
573		(xkbi->desc->ctrls->enabled_ctrls&XkbMouseKeysAccelMask);
574	xkbi->mouseKeysFlags= pAction->ptr.flags;
575	xkbi->mouseKeysDX= XkbPtrActionX(&pAction->ptr);
576	xkbi->mouseKeysDY= XkbPtrActionY(&pAction->ptr);
577	xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0,
578				xkbi->desc->ctrls->mk_delay,
579				_XkbPtrAccelExpire,(pointer)xkbi);
580    }
581    else if (filter->keycode==keycode) {
582	filter->active = 0;
583	if (xkbi->mouseKey==keycode) {
584	    xkbi->mouseKey= 0;
585	    xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, 0,
586							NULL, NULL);
587	}
588    }
589    return 0;
590}
591
592static int
593_XkbFilterPointerBtn(	XkbSrvInfoPtr	xkbi,
594			XkbFilterPtr	filter,
595			unsigned	keycode,
596			XkbAction *	pAction)
597{
598    if (filter->keycode==0) {		/* initial press */
599	int	button= pAction->btn.button;
600
601	if (button==XkbSA_UseDfltButton)
602	    button = xkbi->desc->ctrls->mk_dflt_btn;
603
604	filter->keycode = keycode;
605	filter->active = 1;
606	filter->filterOthers = 0;
607	filter->priv=0;
608	filter->filter = _XkbFilterPointerBtn;
609	filter->upAction= *pAction;
610	filter->upAction.btn.button= button;
611	switch (pAction->type) {
612	    case XkbSA_LockPtrBtn:
613		if (((xkbi->lockedPtrButtons&(1<<button))==0)&&
614			((pAction->btn.flags&XkbSA_LockNoLock)==0)) {
615		    xkbi->lockedPtrButtons|= (1<<button);
616		    AccessXCancelRepeatKey(xkbi,keycode);
617		    XkbDDXFakeDeviceButton(xkbi->device, 1, button);
618		    filter->upAction.type= XkbSA_NoAction;
619		}
620		break;
621	    case XkbSA_PtrBtn:
622		{
623		    register int i,nClicks;
624		    AccessXCancelRepeatKey(xkbi,keycode);
625		    if (pAction->btn.count>0) {
626			nClicks= pAction->btn.count;
627			for (i=0;i<nClicks;i++) {
628			    XkbDDXFakeDeviceButton(xkbi->device, 1, button);
629			    XkbDDXFakeDeviceButton(xkbi->device, 0, button);
630			}
631			filter->upAction.type= XkbSA_NoAction;
632		    }
633		    else XkbDDXFakeDeviceButton(xkbi->device, 1, button);
634		}
635		break;
636	    case XkbSA_SetPtrDflt:
637		{
638		    XkbControlsPtr	ctrls= xkbi->desc->ctrls;
639		    XkbControlsRec	old;
640		    xkbControlsNotify	cn;
641
642		    old= *ctrls;
643		    AccessXCancelRepeatKey(xkbi,keycode);
644		    switch (pAction->dflt.affect) {
645			case XkbSA_AffectDfltBtn:
646			    if (pAction->dflt.flags&XkbSA_DfltBtnAbsolute)
647				ctrls->mk_dflt_btn=
648					XkbSAPtrDfltValue(&pAction->dflt);
649			    else {
650				ctrls->mk_dflt_btn+=
651					XkbSAPtrDfltValue(&pAction->dflt);
652				if (ctrls->mk_dflt_btn>5)
653				    ctrls->mk_dflt_btn= 5;
654				else if (ctrls->mk_dflt_btn<1)
655				    ctrls->mk_dflt_btn= 1;
656			    }
657			    break;
658			default:
659			    ErrorF(
660		"Attempt to change unknown pointer default (%d) ignored\n",
661							pAction->dflt.affect);
662			    break;
663		    }
664		    if (XkbComputeControlsNotify(xkbi->device,
665						&old,xkbi->desc->ctrls,
666						&cn,False)) {
667			cn.keycode = keycode;
668                        /* XXX: what about DeviceKeyPress? */
669			cn.eventType = KeyPress;
670			cn.requestMajor = 0;
671			cn.requestMinor = 0;
672			XkbSendControlsNotify(xkbi->device,&cn);
673		    }
674		}
675		break;
676	}
677    }
678    else if (filter->keycode==keycode) {
679	int	button= filter->upAction.btn.button;
680
681	switch (filter->upAction.type) {
682	    case XkbSA_LockPtrBtn:
683		if (((filter->upAction.btn.flags&XkbSA_LockNoUnlock)!=0)||
684				((xkbi->lockedPtrButtons&(1<<button))==0)) {
685		    break;
686		}
687		xkbi->lockedPtrButtons&= ~(1<<button);
688	    case XkbSA_PtrBtn:
689		XkbDDXFakeDeviceButton(xkbi->device, 0, button);
690		break;
691	}
692	filter->active = 0;
693    }
694    return 0;
695}
696
697static int
698_XkbFilterControls(	XkbSrvInfoPtr	xkbi,
699			XkbFilterPtr	filter,
700			unsigned	keycode,
701			XkbAction *	pAction)
702{
703XkbControlsRec		old;
704XkbControlsPtr		ctrls;
705DeviceIntPtr		kbd;
706unsigned int		change;
707XkbEventCauseRec	cause;
708
709    kbd= xkbi->device;
710    ctrls= xkbi->desc->ctrls;
711    old= *ctrls;
712    if (filter->keycode==0) {		/* initial press */
713	filter->keycode = keycode;
714	filter->active = 1;
715	filter->filterOthers = 0;
716	change= XkbActionCtrls(&pAction->ctrls);
717	filter->priv = change;
718	filter->filter = _XkbFilterControls;
719	filter->upAction = *pAction;
720
721	if (pAction->type==XkbSA_LockControls) {
722	    filter->priv= (ctrls->enabled_ctrls&change);
723	    change&= ~ctrls->enabled_ctrls;
724	}
725
726	if (change) {
727	    xkbControlsNotify	cn;
728	    XkbSrvLedInfoPtr	sli;
729
730	    ctrls->enabled_ctrls|= change;
731	    if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,False)) {
732		cn.keycode = keycode;
733                /* XXX: what about DeviceKeyPress? */
734		cn.eventType = KeyPress;
735		cn.requestMajor = 0;
736		cn.requestMinor = 0;
737		XkbSendControlsNotify(kbd,&cn);
738	    }
739
740	    XkbSetCauseKey(&cause,keycode,KeyPress);
741
742	    /* If sticky keys were disabled, clear all locks and latches */
743	    if ((old.enabled_ctrls&XkbStickyKeysMask)&&
744		(!(ctrls->enabled_ctrls&XkbStickyKeysMask))) {
745		XkbClearAllLatchesAndLocks(kbd,xkbi,False,&cause);
746    	    }
747	    sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
748	    XkbUpdateIndicators(kbd,sli->usesControls,True,NULL,&cause);
749	    if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask))
750		XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_ON,change);
751	}
752    }
753    else if (filter->keycode==keycode) {
754	change= filter->priv;
755	if (change) {
756	    xkbControlsNotify 	cn;
757	    XkbSrvLedInfoPtr	sli;
758
759	    ctrls->enabled_ctrls&= ~change;
760	    if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,False)) {
761		cn.keycode = keycode;
762		cn.eventType = KeyRelease;
763		cn.requestMajor = 0;
764		cn.requestMinor = 0;
765		XkbSendControlsNotify(kbd,&cn);
766	    }
767
768	    XkbSetCauseKey(&cause,keycode,KeyRelease);
769	    /* If sticky keys were disabled, clear all locks and latches */
770	    if ((old.enabled_ctrls&XkbStickyKeysMask)&&
771		(!(ctrls->enabled_ctrls&XkbStickyKeysMask))) {
772		XkbClearAllLatchesAndLocks(kbd,xkbi,False,&cause);
773    	    }
774	    sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
775	    XkbUpdateIndicators(kbd,sli->usesControls,True,NULL,&cause);
776	    if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask))
777		XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_OFF,change);
778	}
779	filter->keycode= 0;
780	filter->active= 0;
781    }
782    return 1;
783}
784
785static int
786_XkbFilterActionMessage(XkbSrvInfoPtr	xkbi,
787			XkbFilterPtr	filter,
788			unsigned	keycode,
789			XkbAction *	pAction)
790{
791XkbMessageAction *	pMsg;
792DeviceIntPtr		kbd;
793
794    kbd= xkbi->device;
795    if (filter->keycode==0) {		/* initial press */
796	pMsg= &pAction->msg;
797	if ((pMsg->flags&XkbSA_MessageOnRelease)||
798	    ((pMsg->flags&XkbSA_MessageGenKeyEvent)==0)) {
799	    filter->keycode = keycode;
800	    filter->active = 1;
801	    filter->filterOthers = 0;
802	    filter->priv = 0;
803	    filter->filter = _XkbFilterActionMessage;
804	    filter->upAction = *pAction;
805	}
806	if (pMsg->flags&XkbSA_MessageOnPress)  {
807	    xkbActionMessage	msg;
808
809	    msg.keycode= keycode;
810	    msg.press= 1;
811	    msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
812	    memcpy((char *)msg.message,
813				(char *)pMsg->message,XkbActionMessageLength);
814	    XkbSendActionMessage(kbd,&msg);
815	}
816	return ((pAction->msg.flags&XkbSA_MessageGenKeyEvent)!=0);
817    }
818    else if (filter->keycode==keycode) {
819	pMsg= &filter->upAction.msg;
820	if (pMsg->flags&XkbSA_MessageOnRelease) {
821	    xkbActionMessage	msg;
822
823	    msg.keycode= keycode;
824	    msg.press= 0;
825	    msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
826	    memcpy((char *)msg.message,(char *)pMsg->message,
827						XkbActionMessageLength);
828	    XkbSendActionMessage(kbd,&msg);
829	}
830	filter->keycode= 0;
831	filter->active= 0;
832	return ((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
833    }
834    return 0;
835}
836
837static int
838_XkbFilterRedirectKey(	XkbSrvInfoPtr	xkbi,
839			XkbFilterPtr	filter,
840			unsigned	keycode,
841			XkbAction *	pAction)
842{
843unsigned	realMods = 0;
844xEvent 		ev;
845int		x,y;
846XkbStateRec	old;
847unsigned	mods,mask,oldCoreState = 0,oldCorePrevState = 0;
848xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
849ProcessInputProc backupproc;
850
851    /* never actually used uninitialised, but gcc isn't smart enough
852     * to work that out. */
853    memset(&old, 0, sizeof(old));
854
855    if ((filter->keycode!=0)&&(filter->keycode!=keycode))
856	return 1;
857
858    GetSpritePosition(inputInfo.pointer, &x,&y);
859    ev.u.keyButtonPointer.time = GetTimeInMillis();
860    ev.u.keyButtonPointer.rootX = x;
861    ev.u.keyButtonPointer.rootY = y;
862
863    if (filter->keycode==0) {		/* initial press */
864	if ((pAction->redirect.new_key<xkbi->desc->min_key_code)||
865	    (pAction->redirect.new_key>xkbi->desc->max_key_code)) {
866	    return 1;
867	}
868	filter->keycode = keycode;
869	filter->active = 1;
870	filter->filterOthers = 0;
871	filter->priv = 0;
872	filter->filter = _XkbFilterRedirectKey;
873	filter->upAction = *pAction;
874
875        /* XXX: what about DeviceKeyPress */
876	ev.u.u.type = KeyPress;
877	ev.u.u.detail = pAction->redirect.new_key;
878
879        mask= XkbSARedirectVModsMask(&pAction->redirect);
880        mods= XkbSARedirectVMods(&pAction->redirect);
881        if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask);
882        if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods);
883        mask|= pAction->redirect.mods_mask;
884        mods|= pAction->redirect.mods;
885
886	if ( mask || mods ) {
887	    old= xkbi->state;
888	    oldCoreState= xkbi->device->key->state;
889	    oldCorePrevState= xkbi->device->key->prev_state;
890	    xkbi->state.base_mods&= ~mask;
891	    xkbi->state.base_mods|= (mods&mask);
892	    xkbi->state.latched_mods&= ~mask;
893	    xkbi->state.latched_mods|= (mods&mask);
894	    xkbi->state.locked_mods&= ~mask;
895	    xkbi->state.locked_mods|= (mods&mask);
896	    XkbComputeDerivedState(xkbi);
897	    xkbi->device->key->state= xkbi->device->key->prev_state=
898							xkbi->state.mods;
899	}
900
901	realMods = xkbi->device->key->modifierMap[ev.u.u.detail];
902	xkbi->device->key->modifierMap[ev.u.u.detail] = 0;
903	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
904	xkbi->device->public.processInputProc(&ev,xkbi->device,1);
905	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
906				     backupproc,xkbUnwrapProc);
907	xkbi->device->key->modifierMap[ev.u.u.detail] = realMods;
908
909	if ( mask || mods ) {
910	    xkbi->device->key->state= oldCoreState;
911	    xkbi->device->key->prev_state= oldCorePrevState;
912	    xkbi->state= old;
913	}
914    }
915    else if (filter->keycode==keycode) {
916
917        /* XXX: what about DeviceKeyRelease */
918	ev.u.u.type = KeyRelease;
919	ev.u.u.detail = filter->upAction.redirect.new_key;
920
921        mask= XkbSARedirectVModsMask(&filter->upAction.redirect);
922        mods= XkbSARedirectVMods(&filter->upAction.redirect);
923        if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask);
924        if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods);
925        mask|= filter->upAction.redirect.mods_mask;
926        mods|= filter->upAction.redirect.mods;
927
928	if ( mask || mods ) {
929	    old= xkbi->state;
930	    oldCoreState= xkbi->device->key->state;
931	    oldCorePrevState= xkbi->device->key->prev_state;
932	    xkbi->state.base_mods&= ~mask;
933	    xkbi->state.base_mods|= (mods&mask);
934	    xkbi->state.latched_mods&= ~mask;
935	    xkbi->state.latched_mods|= (mods&mask);
936	    xkbi->state.locked_mods&= ~mask;
937	    xkbi->state.locked_mods|= (mods&mask);
938	    XkbComputeDerivedState(xkbi);
939	    xkbi->device->key->state= xkbi->device->key->prev_state=
940							xkbi->state.mods;
941	}
942
943	realMods = xkbi->device->key->modifierMap[ev.u.u.detail];
944	xkbi->device->key->modifierMap[ev.u.u.detail] = 0;
945	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
946	xkbi->device->public.processInputProc(&ev,xkbi->device,1);
947	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
948				     backupproc,xkbUnwrapProc);
949	xkbi->device->key->modifierMap[ev.u.u.detail] = realMods;
950
951	if ( mask || mods ) {
952	    xkbi->device->key->state= oldCoreState;
953	    xkbi->device->key->prev_state= oldCorePrevState;
954	    xkbi->state= old;
955	}
956
957	filter->keycode= 0;
958	filter->active= 0;
959    }
960    return 0;
961}
962
963static int
964_XkbFilterSwitchScreen(	XkbSrvInfoPtr	xkbi,
965			XkbFilterPtr	filter,
966			unsigned	keycode,
967			XkbAction *	pAction)
968{
969    DeviceIntPtr dev = xkbi->device;
970    if (dev == inputInfo.keyboard)
971        return 0;
972
973    if (filter->keycode==0) {		/* initial press */
974	filter->keycode = keycode;
975	filter->active = 1;
976	filter->filterOthers = 0;
977	filter->filter = _XkbFilterSwitchScreen;
978	AccessXCancelRepeatKey(xkbi, keycode);
979	XkbDDXSwitchScreen(dev,keycode,pAction);
980        return 0;
981    }
982    else if (filter->keycode==keycode) {
983	filter->active= 0;
984        return 0;
985    }
986    return 1;
987}
988
989static int
990_XkbFilterXF86Private(	XkbSrvInfoPtr	xkbi,
991			XkbFilterPtr	filter,
992			unsigned	keycode,
993			XkbAction *	pAction)
994{
995    DeviceIntPtr dev = xkbi->device;
996    if (dev == inputInfo.keyboard)
997        return 0;
998
999    if (filter->keycode==0) {		/* initial press */
1000	filter->keycode = keycode;
1001	filter->active = 1;
1002	filter->filterOthers = 0;
1003	filter->filter = _XkbFilterXF86Private;
1004	XkbDDXPrivate(dev,keycode,pAction);
1005        return 0;
1006    }
1007    else if (filter->keycode==keycode) {
1008	filter->active= 0;
1009        return 0;
1010    }
1011    return 1;
1012}
1013
1014
1015static int
1016_XkbFilterDeviceBtn(	XkbSrvInfoPtr	xkbi,
1017			XkbFilterPtr	filter,
1018			unsigned	keycode,
1019			XkbAction *	pAction)
1020{
1021DeviceIntPtr	dev;
1022int		button;
1023
1024    if (xkbi->device == inputInfo.keyboard)
1025        return 0;
1026
1027    if (filter->keycode==0) {		/* initial press */
1028	_XkbLookupButtonDevice(&dev, pAction->devbtn.device, serverClient,
1029			       DixUnknownAccess, &button);
1030	if (!dev || !dev->public.on || dev == inputInfo.pointer)
1031	    return 1;
1032
1033	button= pAction->devbtn.button;
1034	if ((button<1)||(button>dev->button->numButtons))
1035	    return 1;
1036
1037	filter->keycode = keycode;
1038	filter->active = 1;
1039	filter->filterOthers = 0;
1040	filter->priv=0;
1041	filter->filter = _XkbFilterDeviceBtn;
1042	filter->upAction= *pAction;
1043	switch (pAction->type) {
1044	    case XkbSA_LockDeviceBtn:
1045		if ((pAction->devbtn.flags&XkbSA_LockNoLock)||
1046		    BitIsOn(dev->button->down, button))
1047		    return 0;
1048		XkbDDXFakeDeviceButton(dev,True,button);
1049		filter->upAction.type= XkbSA_NoAction;
1050		break;
1051	    case XkbSA_DeviceBtn:
1052		if (pAction->devbtn.count>0) {
1053		    int nClicks,i;
1054		    nClicks= pAction->btn.count;
1055		    for (i=0;i<nClicks;i++) {
1056			XkbDDXFakeDeviceButton(dev,True,button);
1057			XkbDDXFakeDeviceButton(dev,False,button);
1058		    }
1059		    filter->upAction.type= XkbSA_NoAction;
1060		}
1061		else XkbDDXFakeDeviceButton(dev,True,button);
1062		break;
1063	}
1064    }
1065    else if (filter->keycode==keycode) {
1066	int	button;
1067
1068	filter->active= 0;
1069	_XkbLookupButtonDevice(&dev, filter->upAction.devbtn.device,
1070			       serverClient, DixUnknownAccess, &button);
1071	if (!dev || !dev->public.on || dev == inputInfo.pointer)
1072	    return 1;
1073
1074	button= filter->upAction.btn.button;
1075	switch (filter->upAction.type) {
1076	    case XkbSA_LockDeviceBtn:
1077		if ((filter->upAction.devbtn.flags&XkbSA_LockNoUnlock)||
1078		    !BitIsOn(dev->button->down, button))
1079		    return 0;
1080		XkbDDXFakeDeviceButton(dev,False,button);
1081		break;
1082	    case XkbSA_DeviceBtn:
1083		XkbDDXFakeDeviceButton(dev,False,button);
1084		break;
1085	}
1086	filter->active = 0;
1087    }
1088    return 0;
1089}
1090
1091static XkbFilterPtr
1092_XkbNextFreeFilter(
1093	XkbSrvInfoPtr xkbi
1094)
1095{
1096register int	i;
1097
1098    if (xkbi->szFilters==0) {
1099	xkbi->szFilters = 4;
1100	xkbi->filters = _XkbTypedCalloc(xkbi->szFilters,XkbFilterRec);
1101	/* 6/21/93 (ef) -- XXX! deal with allocation failure */
1102    }
1103    for (i=0;i<xkbi->szFilters;i++) {
1104	if (!xkbi->filters[i].active) {
1105	    xkbi->filters[i].keycode = 0;
1106	    return &xkbi->filters[i];
1107	}
1108    }
1109    xkbi->szFilters*=2;
1110    xkbi->filters= _XkbTypedRealloc(xkbi->filters,
1111                                    xkbi->szFilters,
1112                                    XkbFilterRec);
1113    /* 6/21/93 (ef) -- XXX! deal with allocation failure */
1114    bzero(&xkbi->filters[xkbi->szFilters/2],
1115            (xkbi->szFilters/2)*sizeof(XkbFilterRec));
1116    return &xkbi->filters[xkbi->szFilters/2];
1117}
1118
1119static int
1120_XkbApplyFilters(XkbSrvInfoPtr xkbi,unsigned kc,XkbAction *pAction)
1121{
1122register int	i,send;
1123
1124    send= 1;
1125    for (i=0;i<xkbi->szFilters;i++) {
1126	if ((xkbi->filters[i].active)&&(xkbi->filters[i].filter))
1127	    send= ((*xkbi->filters[i].filter)(xkbi,&xkbi->filters[i],kc,pAction)
1128                    && send);
1129    }
1130    return send;
1131}
1132
1133void
1134XkbHandleActions(DeviceIntPtr dev,DeviceIntPtr kbd,xEvent *xE,int count)
1135{
1136int		key,bit,i;
1137CARD8		realMods = 0;
1138XkbSrvInfoPtr	xkbi;
1139KeyClassPtr	keyc;
1140int		changed,sendEvent;
1141Bool		genStateNotify;
1142XkbStateRec	oldState;
1143XkbAction	act;
1144XkbFilterPtr	filter;
1145Bool		keyEvent;
1146Bool		pressEvent;
1147ProcessInputProc backupproc;
1148
1149xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
1150
1151    keyc= kbd->key;
1152    xkbi= keyc->xkbInfo;
1153    key= xE->u.u.detail;
1154    /* The state may change, so if we're not in the middle of sending a state
1155     * notify, prepare for it */
1156    if ((xkbi->flags&_XkbStateNotifyInProgress)==0) {
1157	oldState= xkbi->state;
1158	xkbi->flags|= _XkbStateNotifyInProgress;
1159	genStateNotify= True;
1160    }
1161    else genStateNotify= False;
1162
1163    xkbi->clearMods = xkbi->setMods = 0;
1164    xkbi->groupChange = 0;
1165
1166    sendEvent = 1;
1167    keyEvent= ((xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress)||
1168		(xE->u.u.type==KeyRelease)||(xE->u.u.type==DeviceKeyRelease));
1169    pressEvent= (xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress)||
1170		 (xE->u.u.type==ButtonPress)||(xE->u.u.type==DeviceButtonPress);
1171
1172    if (pressEvent) {
1173	if (keyEvent)
1174	    act = XkbGetKeyAction(xkbi,&xkbi->state,key);
1175	else {
1176	    act = XkbGetButtonAction(kbd,dev,key);
1177	    key|= BTN_ACT_FLAG;
1178	}
1179	sendEvent = _XkbApplyFilters(xkbi,key,&act);
1180	if (sendEvent) {
1181	    switch (act.type) {
1182		case XkbSA_SetMods:
1183		case XkbSA_SetGroup:
1184		    filter = _XkbNextFreeFilter(xkbi);
1185		    sendEvent = _XkbFilterSetState(xkbi,filter,key,&act);
1186		    break;
1187		case XkbSA_LatchMods:
1188		case XkbSA_LatchGroup:
1189		    filter = _XkbNextFreeFilter(xkbi);
1190		    sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act);
1191		    break;
1192		case XkbSA_LockMods:
1193		case XkbSA_LockGroup:
1194		    filter = _XkbNextFreeFilter(xkbi);
1195		    sendEvent=_XkbFilterLockState(xkbi,filter,key,&act);
1196		    break;
1197		case XkbSA_ISOLock:
1198		    filter = _XkbNextFreeFilter(xkbi);
1199		    sendEvent=_XkbFilterISOLock(xkbi,filter,key,&act);
1200		    break;
1201		case XkbSA_MovePtr:
1202		    filter = _XkbNextFreeFilter(xkbi);
1203		    sendEvent= _XkbFilterPointerMove(xkbi,filter,key,&act);
1204		    break;
1205		case XkbSA_PtrBtn:
1206		case XkbSA_LockPtrBtn:
1207		case XkbSA_SetPtrDflt:
1208		    filter = _XkbNextFreeFilter(xkbi);
1209		    sendEvent= _XkbFilterPointerBtn(xkbi,filter,key,&act);
1210		    break;
1211		case XkbSA_Terminate:
1212		    sendEvent= XkbDDXTerminateServer(dev,key,&act);
1213		    break;
1214		case XkbSA_SwitchScreen:
1215		    filter = _XkbNextFreeFilter(xkbi);
1216		    sendEvent=_XkbFilterSwitchScreen(xkbi,filter,key,&act);
1217		    break;
1218		case XkbSA_SetControls:
1219		case XkbSA_LockControls:
1220		    filter = _XkbNextFreeFilter(xkbi);
1221		    sendEvent=_XkbFilterControls(xkbi,filter,key,&act);
1222		    break;
1223		case XkbSA_ActionMessage:
1224		    filter = _XkbNextFreeFilter(xkbi);
1225		    sendEvent=_XkbFilterActionMessage(xkbi,filter,key,&act);
1226		    break;
1227		case XkbSA_RedirectKey:
1228		    filter = _XkbNextFreeFilter(xkbi);
1229		    sendEvent= _XkbFilterRedirectKey(xkbi,filter,key,&act);
1230		    break;
1231		case XkbSA_DeviceBtn:
1232		case XkbSA_LockDeviceBtn:
1233		    filter = _XkbNextFreeFilter(xkbi);
1234		    sendEvent= _XkbFilterDeviceBtn(xkbi,filter,key,&act);
1235		    break;
1236		case XkbSA_XFree86Private:
1237		    filter = _XkbNextFreeFilter(xkbi);
1238		    sendEvent= _XkbFilterXF86Private(xkbi,filter,key,&act);
1239		    break;
1240	    }
1241	}
1242    }
1243    else {
1244	if (!keyEvent)
1245	    key|= BTN_ACT_FLAG;
1246	sendEvent = _XkbApplyFilters(xkbi,key,NULL);
1247    }
1248
1249    if (xkbi->groupChange!=0)
1250	xkbi->state.base_group+= xkbi->groupChange;
1251    if (xkbi->setMods) {
1252	for (i=0,bit=1; xkbi->setMods; i++,bit<<=1 ) {
1253	    if (xkbi->setMods&bit) {
1254		keyc->modifierKeyCount[i]++;
1255		xkbi->state.base_mods|= bit;
1256		xkbi->setMods&= ~bit;
1257	    }
1258	}
1259    }
1260    if (xkbi->clearMods) {
1261	for (i=0,bit=1; xkbi->clearMods; i++,bit<<=1 ) {
1262	    if (xkbi->clearMods&bit) {
1263		keyc->modifierKeyCount[i]--;
1264		if (keyc->modifierKeyCount[i]<=0) {
1265		    xkbi->state.base_mods&= ~bit;
1266		    keyc->modifierKeyCount[i] = 0;
1267		}
1268		xkbi->clearMods&= ~bit;
1269	    }
1270	}
1271    }
1272
1273    if (sendEvent) {
1274        DeviceIntPtr tmpdev;
1275	if (keyEvent) {
1276	    realMods = keyc->modifierMap[key];
1277	    keyc->modifierMap[key] = 0;
1278            tmpdev = dev;
1279        } else
1280            tmpdev = GetPairedDevice(dev);
1281
1282        UNWRAP_PROCESS_INPUT_PROC(tmpdev,xkbPrivPtr, backupproc);
1283        dev->public.processInputProc(xE,tmpdev,count);
1284        COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr,
1285                                     backupproc,xkbUnwrapProc);
1286        if (keyEvent)
1287	    keyc->modifierMap[key] = realMods;
1288    }
1289    else if (keyEvent) {
1290	FixKeyState(xE,dev);
1291    }
1292
1293    xkbi->prev_state= oldState;
1294    XkbComputeDerivedState(xkbi);
1295    keyc->prev_state= keyc->state;
1296    keyc->state= XkbStateFieldFromRec(&xkbi->state);
1297    changed = XkbStateChangedFlags(&oldState,&xkbi->state);
1298    if (genStateNotify) {
1299	if (changed) {
1300	    xkbStateNotify	sn;
1301	    sn.keycode= key;
1302	    sn.eventType= xE->u.u.type;
1303	    sn.requestMajor = sn.requestMinor = 0;
1304	    sn.changed= changed;
1305	    XkbSendStateNotify(dev,&sn);
1306	}
1307	xkbi->flags&= ~_XkbStateNotifyInProgress;
1308    }
1309    changed= XkbIndicatorsToUpdate(dev,changed,False);
1310    if (changed) {
1311	XkbEventCauseRec	cause;
1312	XkbSetCauseKey(&cause,key,xE->u.u.type);
1313	XkbUpdateIndicators(dev,changed,False,NULL,&cause);
1314    }
1315    return;
1316}
1317
1318int
1319XkbLatchModifiers(DeviceIntPtr pXDev,CARD8 mask,CARD8 latches)
1320{
1321XkbSrvInfoPtr	xkbi;
1322XkbFilterPtr	filter;
1323XkbAction	act;
1324unsigned	clear;
1325
1326    if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) {
1327	xkbi = pXDev->key->xkbInfo;
1328	clear= (mask&(~latches));
1329	xkbi->state.latched_mods&= ~clear;
1330	/* Clear any pending latch to locks.
1331	 */
1332	act.type = XkbSA_NoAction;
1333	_XkbApplyFilters(xkbi,SYNTHETIC_KEYCODE,&act);
1334	act.type = XkbSA_LatchMods;
1335	act.mods.flags = 0;
1336	act.mods.mask  = mask&latches;
1337	filter = _XkbNextFreeFilter(xkbi);
1338	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act);
1339	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL);
1340	return Success;
1341    }
1342    return BadValue;
1343}
1344
1345int
1346XkbLatchGroup(DeviceIntPtr pXDev,int group)
1347{
1348XkbSrvInfoPtr	xkbi;
1349XkbFilterPtr	filter;
1350XkbAction	act;
1351
1352    if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) {
1353	xkbi = pXDev->key->xkbInfo;
1354	act.type = XkbSA_LatchGroup;
1355	act.group.flags = 0;
1356	XkbSASetGroup(&act.group,group);
1357	filter = _XkbNextFreeFilter(xkbi);
1358	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act);
1359	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL);
1360	return Success;
1361    }
1362    return BadValue;
1363}
1364
1365/***====================================================================***/
1366
1367void
1368XkbClearAllLatchesAndLocks(	DeviceIntPtr		dev,
1369				XkbSrvInfoPtr		xkbi,
1370				Bool			genEv,
1371				XkbEventCausePtr	cause)
1372{
1373XkbStateRec	os;
1374xkbStateNotify	sn;
1375
1376    sn.changed= 0;
1377    os= xkbi->state;
1378    if (os.latched_mods) { /* clear all latches */
1379	XkbLatchModifiers(dev,~0,0);
1380	sn.changed|= XkbModifierLatchMask;
1381    }
1382    if (os.latched_group) {
1383	XkbLatchGroup(dev,0);
1384	sn.changed|= XkbGroupLatchMask;
1385    }
1386    if (os.locked_mods) {
1387	xkbi->state.locked_mods= 0;
1388	sn.changed|= XkbModifierLockMask;
1389    }
1390    if (os.locked_group) {
1391	xkbi->state.locked_group= 0;
1392	sn.changed|= XkbGroupLockMask;
1393    }
1394    if ( genEv && sn.changed) {
1395	CARD32 	changed;
1396
1397	XkbComputeDerivedState(xkbi);
1398	sn.keycode= 		cause->kc;
1399	sn.eventType=		cause->event;
1400	sn.requestMajor= 	cause->mjr;
1401	sn.requestMinor= 	cause->mnr;
1402	sn.changed= XkbStateChangedFlags(&os,&xkbi->state);
1403	XkbSendStateNotify(dev,&sn);
1404	changed= XkbIndicatorsToUpdate(dev,sn.changed,False);
1405	if (changed) {
1406	    XkbUpdateIndicators(dev,changed,True,NULL,cause);
1407	}
1408    }
1409    return;
1410}
1411
1412