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