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