xkbEvents.c revision 05b261ec
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#define NEED_EVENTS 1
33#include <X11/X.h>
34#include <X11/Xproto.h>
35#include <X11/keysym.h>
36#include <X11/extensions/XI.h>
37#include <X11/extensions/XIproto.h>
38#include "inputstr.h"
39#include "windowstr.h"
40#include <xkbsrv.h>
41#include "xkb.h"
42
43/***====================================================================***/
44
45void
46XkbSendNewKeyboardNotify(DeviceIntPtr kbd,xkbNewKeyboardNotify *pNKN)
47{
48register int	i;
49Time 		time;
50CARD16		changed;
51
52    pNKN->type = XkbEventCode + XkbEventBase;
53    pNKN->xkbType = XkbNewKeyboardNotify;
54    pNKN->time = time = GetTimeInMillis();
55    changed = pNKN->changed;
56
57    for (i=1; i<currentMaxClients; i++) {
58        if ((!clients[i]) || clients[i]->clientGone ||
59				(clients[i]->requestVector==InitialVector)) {
60	    continue;
61	}
62
63	if (clients[i]->xkbClientFlags&_XkbClientInitialized)  {
64	    if (clients[i]->newKeyboardNotifyMask&changed) {
65		pNKN->sequenceNumber = clients[i]->sequence;
66		pNKN->time = time;
67		pNKN->changed = changed;
68		if ( clients[i]->swapped ) {
69		    register int n;
70		    swaps(&pNKN->sequenceNumber,n);
71		    swapl(&pNKN->time,n);
72		    swaps(&pNKN->changed,n);
73		}
74		WriteToClient(clients[i],sizeof(xEvent),(char *)pNKN);
75		if (changed&XkbNKN_KeycodesMask) {
76		    clients[i]->minKC= pNKN->minKeyCode;
77		    clients[i]->maxKC= pNKN->maxKeyCode;
78		}
79	    }
80	}
81	else if (changed&XkbNKN_KeycodesMask) {
82	    xEvent	event;
83	    event.u.u.type= MappingNotify;
84	    event.u.mappingNotify.request= MappingKeyboard;
85	    event.u.mappingNotify.firstKeyCode= clients[i]->minKC;
86	    event.u.mappingNotify.count= clients[i]->maxKC-clients[i]->minKC+1;
87	    event.u.u.sequenceNumber= clients[i]->sequence;
88	    if (clients[i]->swapped) {
89		int n;
90		swaps(&event.u.u.sequenceNumber,n);
91	    }
92	    WriteToClient(clients[i],SIZEOF(xEvent), (char *)&event);
93	    event.u.mappingNotify.request= MappingModifier;
94	    WriteToClient(clients[i],SIZEOF(xEvent), (char *)&event);
95	}
96    }
97    return;
98}
99
100/***====================================================================***/
101
102void
103XkbSendStateNotify(DeviceIntPtr kbd,xkbStateNotify *pSN)
104{
105XkbSrvInfoPtr	xkbi;
106XkbStatePtr	state;
107XkbInterestPtr	interest;
108Time 		time;
109register CARD16	changed,bState;
110
111    interest = kbd->xkb_interest;
112    if (!interest)
113	return;
114    xkbi = kbd->key->xkbInfo;
115    state= &xkbi->state;
116
117    pSN->type = XkbEventCode + XkbEventBase;
118    pSN->xkbType = XkbStateNotify;
119    pSN->deviceID = kbd->id;
120    pSN->time = time = GetTimeInMillis();
121    pSN->mods = state->mods;
122    pSN->baseMods = state->base_mods;
123    pSN->latchedMods = state->latched_mods;
124    pSN->lockedMods = state->locked_mods;
125    pSN->group = state->group;
126    pSN->baseGroup = state->base_group;
127    pSN->latchedGroup = state->latched_group;
128    pSN->lockedGroup = state->locked_group;
129    pSN->compatState = state->compat_state;
130    pSN->grabMods = state->grab_mods;
131    pSN->compatGrabMods = state->compat_grab_mods;
132    pSN->lookupMods = state->lookup_mods;
133    pSN->compatLookupMods = state->compat_lookup_mods;
134    pSN->ptrBtnState = state->ptr_buttons;
135    changed = pSN->changed;
136    bState= pSN->ptrBtnState;
137
138    while (interest) {
139	if ((!interest->client->clientGone) &&
140	    (interest->client->requestVector != InitialVector) &&
141	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
142	    (interest->stateNotifyMask&changed)) {
143	    pSN->sequenceNumber = interest->client->sequence;
144	    pSN->time = time;
145	    pSN->changed = changed;
146	    pSN->ptrBtnState = bState;
147	    if ( interest->client->swapped ) {
148		register int n;
149		swaps(&pSN->sequenceNumber,n);
150		swapl(&pSN->time,n);
151		swaps(&pSN->changed,n);
152		swaps(&pSN->ptrBtnState,n);
153	    }
154	    WriteToClient(interest->client, sizeof(xEvent), (char *)pSN);
155	}
156	interest= interest->next;
157    }
158    return;
159}
160
161/***====================================================================***/
162
163void
164XkbSendMapNotify(DeviceIntPtr kbd,xkbMapNotify *pMN)
165{
166int 		i;
167XkbSrvInfoPtr	xkbi;
168unsigned	time = 0,initialized;
169CARD16		changed;
170
171    xkbi = kbd->key->xkbInfo;
172    initialized= 0;
173
174    changed = pMN->changed;
175    pMN->minKeyCode= xkbi->desc->min_key_code;
176    pMN->maxKeyCode= xkbi->desc->max_key_code;
177    for (i=1; i<currentMaxClients; i++) {
178        if (clients[i] && ! clients[i]->clientGone &&
179	    (clients[i]->requestVector != InitialVector) &&
180	    (clients[i]->xkbClientFlags&_XkbClientInitialized) &&
181	    (clients[i]->mapNotifyMask&changed))
182	{
183	    if (!initialized) {
184		pMN->type = XkbEventCode + XkbEventBase;
185		pMN->xkbType = XkbMapNotify;
186		pMN->deviceID = kbd->id;
187		time = GetTimeInMillis();
188		initialized= 1;
189	    }
190	    pMN->time= time;
191	    pMN->sequenceNumber = clients[i]->sequence;
192	    pMN->changed = changed;
193	    if ( clients[i]->swapped ) {
194		register int n;
195		swaps(&pMN->sequenceNumber,n);
196		swapl(&pMN->time,n);
197		swaps(&pMN->changed,n);
198	    }
199	    WriteToClient(clients[i],sizeof(xEvent),(char *)pMN);
200	}
201    }
202    return;
203}
204
205int
206XkbComputeControlsNotify(	DeviceIntPtr	 	kbd,
207				XkbControlsPtr		old,
208				XkbControlsPtr		new,
209				xkbControlsNotify *	pCN,
210				Bool			forceCtrlProc)
211{
212int		i;
213CARD32 		changedControls;
214
215    changedControls= 0;
216
217    if (!kbd || !kbd->kbdfeed)
218        return 0;
219
220    if (old->enabled_ctrls!=new->enabled_ctrls)
221	changedControls|= XkbControlsEnabledMask;
222    if ((old->repeat_delay!=new->repeat_delay)||
223	(old->repeat_interval!=new->repeat_interval))
224	changedControls|= XkbRepeatKeysMask;
225    for (i = 0; i < XkbPerKeyBitArraySize; i++)
226	if (old->per_key_repeat[i] != new->per_key_repeat[i])
227	    changedControls|= XkbPerKeyRepeatMask;
228    if (old->slow_keys_delay!=new->slow_keys_delay)
229	changedControls|= XkbSlowKeysMask;
230    if (old->debounce_delay!=new->debounce_delay)
231	changedControls|= XkbBounceKeysMask;
232    if ((old->mk_delay!=new->mk_delay)||
233	(old->mk_interval!=new->mk_interval)||
234	(old->mk_dflt_btn!=new->mk_dflt_btn))
235	changedControls|= XkbMouseKeysMask;
236    if ((old->mk_time_to_max!=new->mk_time_to_max)||
237	(old->mk_curve!=new->mk_curve)||
238	(old->mk_max_speed!=new->mk_max_speed))
239	changedControls|= XkbMouseKeysAccelMask;
240    if (old->ax_options!=new->ax_options)
241	changedControls|= XkbAccessXKeysMask;
242    if ((old->ax_options^new->ax_options) & XkbAX_SKOptionsMask)
243	changedControls|= XkbStickyKeysMask;
244    if ((old->ax_options^new->ax_options) & XkbAX_FBOptionsMask)
245	changedControls|= XkbAccessXFeedbackMask;
246    if ((old->ax_timeout!=new->ax_timeout)||
247	(old->axt_ctrls_mask!=new->axt_ctrls_mask)||
248	(old->axt_ctrls_values!=new->axt_ctrls_values)||
249	(old->axt_opts_mask!=new->axt_opts_mask)||
250	(old->axt_opts_values!= new->axt_opts_values)) {
251	changedControls|= XkbAccessXTimeoutMask;
252    }
253    if ((old->internal.mask!=new->internal.mask)||
254	(old->internal.real_mods!=new->internal.real_mods)||
255	(old->internal.vmods!=new->internal.vmods))
256	changedControls|= XkbInternalModsMask;
257    if ((old->ignore_lock.mask!=new->ignore_lock.mask)||
258	(old->ignore_lock.real_mods!=new->ignore_lock.real_mods)||
259	(old->ignore_lock.vmods!=new->ignore_lock.vmods))
260	changedControls|= XkbIgnoreLockModsMask;
261
262    if (new->enabled_ctrls&XkbRepeatKeysMask)
263	 kbd->kbdfeed->ctrl.autoRepeat=TRUE;
264    else kbd->kbdfeed->ctrl.autoRepeat=FALSE;
265
266    if (kbd->kbdfeed && kbd->kbdfeed->CtrlProc &&
267	(changedControls || forceCtrlProc))
268	(*kbd->kbdfeed->CtrlProc)(kbd, &kbd->kbdfeed->ctrl);
269
270    if ((!changedControls)&&(old->num_groups==new->num_groups))
271	return 0;
272
273    if (!kbd->xkb_interest)
274	return 0;
275
276    pCN->changedControls = changedControls;
277    pCN->enabledControls = new->enabled_ctrls;
278    pCN->enabledControlChanges = (new->enabled_ctrls^old->enabled_ctrls);
279    pCN->numGroups = new->num_groups;
280
281    return 1;
282}
283
284void
285XkbSendControlsNotify(DeviceIntPtr kbd,xkbControlsNotify *pCN)
286{
287int			initialized;
288CARD32 		 	changedControls, enabledControls, enabledChanges = 0;
289XkbSrvInfoPtr		xkbi;
290XkbInterestPtr		interest;
291Time 		 	time = 0;
292
293    interest = kbd->xkb_interest;
294    if (!interest)
295	return;
296    xkbi = kbd->key->xkbInfo;
297
298    initialized = 0;
299    enabledControls = xkbi->desc->ctrls->enabled_ctrls;
300    changedControls = pCN->changedControls;
301    pCN->numGroups= xkbi->desc->ctrls->num_groups;
302    while (interest) {
303	if ((!interest->client->clientGone) &&
304	    (interest->client->requestVector != InitialVector) &&
305	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
306	    (interest->ctrlsNotifyMask&changedControls)) {
307	    if (!initialized) {
308		pCN->type = XkbEventCode + XkbEventBase;
309		pCN->xkbType = XkbControlsNotify;
310		pCN->deviceID = kbd->id;
311		pCN->time = time = GetTimeInMillis();
312		enabledChanges = pCN->enabledControlChanges;
313		initialized= 1;
314	    }
315	    pCN->changedControls = changedControls;
316	    pCN->enabledControls = enabledControls;
317	    pCN->enabledControlChanges = enabledChanges;
318	    pCN->sequenceNumber = interest->client->sequence;
319	    pCN->time = time;
320	    if ( interest->client->swapped ) {
321		register int n;
322		swaps(&pCN->sequenceNumber,n);
323		swapl(&pCN->changedControls,n);
324		swapl(&pCN->enabledControls,n);
325		swapl(&pCN->enabledControlChanges,n);
326		swapl(&pCN->time,n);
327	    }
328	    WriteToClient(interest->client, sizeof(xEvent), (char *)pCN);
329	}
330	interest= interest->next;
331    }
332    return;
333}
334
335static void
336XkbSendIndicatorNotify(DeviceIntPtr kbd,int xkbType,xkbIndicatorNotify *pEv)
337{
338int		initialized;
339XkbInterestPtr	interest;
340Time 		time = 0;
341CARD32		state,changed;
342
343    interest = kbd->xkb_interest;
344    if (!interest)
345	return;
346
347    initialized = 0;
348    state = pEv->state;
349    changed = pEv->changed;
350    while (interest) {
351	if ((!interest->client->clientGone) &&
352	    (interest->client->requestVector != InitialVector) &&
353	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
354	    (((xkbType==XkbIndicatorStateNotify)&&
355				(interest->iStateNotifyMask&changed))||
356	     ((xkbType==XkbIndicatorMapNotify)&&
357	    			(interest->iMapNotifyMask&changed)))) {
358	    if (!initialized) {
359		pEv->type = XkbEventCode + XkbEventBase;
360		pEv->xkbType = xkbType;
361		pEv->deviceID = kbd->id;
362		pEv->time = time = GetTimeInMillis();
363		initialized= 1;
364	    }
365	    pEv->sequenceNumber = interest->client->sequence;
366	    pEv->time = time;
367	    pEv->changed = changed;
368	    pEv->state = state;
369	    if ( interest->client->swapped ) {
370		register int n;
371		swaps(&pEv->sequenceNumber,n);
372		swapl(&pEv->time,n);
373		swapl(&pEv->changed,n);
374		swapl(&pEv->state,n);
375	    }
376	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
377	}
378	interest= interest->next;
379    }
380    return;
381}
382
383
384void
385XkbHandleBell(	BOOL		 force,
386		BOOL		 eventOnly,
387		DeviceIntPtr	 kbd,
388		CARD8		 percent,
389		pointer		 pCtrl,
390		CARD8		 class,
391		Atom		 name,
392		WindowPtr	 pWin,
393		ClientPtr	 pClient)
394{
395xkbBellNotify	bn;
396int		initialized;
397XkbSrvInfoPtr	xkbi;
398XkbInterestPtr	interest;
399CARD8		id;
400CARD16		pitch,duration;
401Time 		time = 0;
402XID		winID = 0;
403
404    xkbi = kbd->key->xkbInfo;
405
406    if ((force||(xkbi->desc->ctrls->enabled_ctrls&XkbAudibleBellMask))&&
407							(!eventOnly)) {
408        if (kbd->kbdfeed->BellProc)
409            (*kbd->kbdfeed->BellProc)(percent,kbd,(pointer)pCtrl,class);
410    }
411    interest = kbd->xkb_interest;
412    if ((!interest)||(force))
413	return;
414
415    if ((class==0)||(class==KbdFeedbackClass)) {
416	KeybdCtrl *pKeyCtrl= (KeybdCtrl *)pCtrl;
417	id= pKeyCtrl->id;
418	pitch= pKeyCtrl->bell_pitch;
419	duration= pKeyCtrl->bell_duration;
420    }
421    else if (class==BellFeedbackClass) {
422	BellCtrl *pBellCtrl= (BellCtrl *)pCtrl;
423	id= pBellCtrl->id;
424	pitch= pBellCtrl->pitch;
425	duration= pBellCtrl->duration;
426    }
427    else return;
428
429    initialized = 0;
430    while (interest) {
431	if ((!interest->client->clientGone) &&
432	    (interest->client->requestVector != InitialVector) &&
433	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
434	    (interest->bellNotifyMask)) {
435	    if (!initialized) {
436		time = GetTimeInMillis();
437		bn.type = XkbEventCode + XkbEventBase;
438		bn.xkbType = XkbBellNotify;
439		bn.deviceID = kbd->id;
440		bn.bellClass = class;
441		bn.bellID = id;
442		bn.percent= percent;
443		bn.eventOnly = (eventOnly!=0);
444		winID= (pWin?pWin->drawable.id:None);
445		initialized= 1;
446	    }
447	    bn.sequenceNumber = interest->client->sequence;
448	    bn.time = time;
449	    bn.pitch = pitch;
450	    bn.duration = duration;
451	    bn.name = name;
452	    bn.window=  winID;
453	    if ( interest->client->swapped ) {
454		register int n;
455		swaps(&bn.sequenceNumber,n);
456		swapl(&bn.time,n);
457		swaps(&bn.pitch,n);
458		swaps(&bn.duration,n);
459		swapl(&bn.name,n);
460		swapl(&bn.window,n);
461	    }
462	    WriteToClient(interest->client, sizeof(xEvent), (char *)&bn);
463	}
464	interest= interest->next;
465    }
466    return;
467}
468
469void
470XkbSendAccessXNotify(DeviceIntPtr kbd,xkbAccessXNotify *pEv)
471{
472int		initialized;
473XkbInterestPtr	interest;
474Time 		time = 0;
475CARD16		sk_delay,db_delay;
476
477    interest = kbd->xkb_interest;
478    if (!interest)
479	return;
480
481    initialized = 0;
482    sk_delay= pEv->slowKeysDelay;
483    db_delay= pEv->debounceDelay;
484    while (interest) {
485	if ((!interest->client->clientGone) &&
486	    (interest->client->requestVector != InitialVector) &&
487	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
488	    (interest->accessXNotifyMask&(1<<pEv->detail))) {
489	    if (!initialized) {
490		pEv->type = XkbEventCode + XkbEventBase;
491		pEv->xkbType = XkbAccessXNotify;
492		pEv->deviceID = kbd->id;
493		pEv->time = time = GetTimeInMillis();
494		initialized= 1;
495	    }
496	    pEv->sequenceNumber = interest->client->sequence;
497	    pEv->time = time;
498	    pEv->slowKeysDelay = sk_delay;
499	    pEv->debounceDelay = db_delay;
500	    if ( interest->client->swapped ) {
501		register int n;
502		swaps(&pEv->sequenceNumber,n);
503		swapl(&pEv->time,n);
504		swaps(&pEv->slowKeysDelay,n);
505		swaps(&pEv->debounceDelay,n);
506	    }
507	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
508	}
509	interest= interest->next;
510    }
511    return;
512}
513
514void
515XkbSendNamesNotify(DeviceIntPtr kbd,xkbNamesNotify *pEv)
516{
517int		initialized;
518XkbInterestPtr	interest;
519Time 		time = 0;
520CARD16		changed,changedVirtualMods;
521CARD32		changedIndicators;
522
523    interest = kbd->xkb_interest;
524    if (!interest)
525	return;
526
527    initialized = 0;
528    changed= pEv->changed;
529    changedIndicators= pEv->changedIndicators;
530    changedVirtualMods= pEv->changedVirtualMods;
531    while (interest) {
532	if ((!interest->client->clientGone) &&
533	    (interest->client->requestVector != InitialVector) &&
534	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
535	    (interest->namesNotifyMask&pEv->changed)) {
536	    if (!initialized) {
537		pEv->type = XkbEventCode + XkbEventBase;
538		pEv->xkbType = XkbNamesNotify;
539		pEv->deviceID = kbd->id;
540		pEv->time = time = GetTimeInMillis();
541		initialized= 1;
542	    }
543	    pEv->sequenceNumber = interest->client->sequence;
544	    pEv->time = time;
545	    pEv->changed = changed;
546	    pEv->changedIndicators = changedIndicators;
547	    pEv->changedVirtualMods= changedVirtualMods;
548	    if ( interest->client->swapped ) {
549		register int n;
550		swaps(&pEv->sequenceNumber,n);
551		swapl(&pEv->time,n);
552		swaps(&pEv->changed,n);
553		swapl(&pEv->changedIndicators,n);
554		swaps(&pEv->changedVirtualMods,n);
555	    }
556	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
557	}
558	interest= interest->next;
559    }
560    return;
561}
562
563void
564XkbSendCompatMapNotify(DeviceIntPtr kbd,xkbCompatMapNotify *pEv)
565{
566int		initialized;
567XkbInterestPtr	interest;
568Time 		time = 0;
569CARD16		firstSI = 0, nSI = 0, nTotalSI = 0;
570
571    interest = kbd->xkb_interest;
572    if (!interest)
573	return;
574
575    initialized = 0;
576    while (interest) {
577	if ((!interest->client->clientGone) &&
578	    (interest->client->requestVector != InitialVector) &&
579	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
580	    (interest->compatNotifyMask)) {
581	    if (!initialized) {
582		pEv->type = XkbEventCode + XkbEventBase;
583		pEv->xkbType = XkbCompatMapNotify;
584		pEv->deviceID = kbd->id;
585		pEv->time = time = GetTimeInMillis();
586		firstSI= pEv->firstSI;
587		nSI= pEv->nSI;
588		nTotalSI= pEv->nTotalSI;
589		initialized= 1;
590	    }
591	    pEv->sequenceNumber = interest->client->sequence;
592	    pEv->time = time;
593	    pEv->firstSI = firstSI;
594	    pEv->nSI = nSI;
595	    pEv->nTotalSI = nTotalSI;
596	    if ( interest->client->swapped ) {
597		register int n;
598		swaps(&pEv->sequenceNumber,n);
599		swapl(&pEv->time,n);
600		swaps(&pEv->firstSI,n);
601		swaps(&pEv->nSI,n);
602		swaps(&pEv->nTotalSI,n);
603	    }
604	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
605	}
606	interest= interest->next;
607    }
608    return;
609}
610
611void
612XkbSendActionMessage(DeviceIntPtr kbd,xkbActionMessage *pEv)
613{
614int		 initialized;
615XkbSrvInfoPtr	 xkbi;
616XkbInterestPtr	 interest;
617Time 		 time = 0;
618
619    xkbi = kbd->key->xkbInfo;
620    interest = kbd->xkb_interest;
621    if (!interest)
622	return;
623
624    initialized = 0;
625    pEv->mods= xkbi->state.mods;
626    pEv->group= xkbi->state.group;
627    while (interest) {
628	if ((!interest->client->clientGone) &&
629	    (interest->client->requestVector != InitialVector) &&
630	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
631	    (interest->actionMessageMask)) {
632	    if (!initialized) {
633		pEv->type = XkbEventCode + XkbEventBase;
634		pEv->xkbType = XkbActionMessage;
635		pEv->deviceID = kbd->id;
636		pEv->sequenceNumber = interest->client->sequence;
637		pEv->time = time = GetTimeInMillis();
638		initialized= 1;
639	    }
640	    pEv->sequenceNumber = interest->client->sequence;
641	    pEv->time = time;
642	    if ( interest->client->swapped ) {
643		register int n;
644		swaps(&pEv->sequenceNumber,n);
645		swapl(&pEv->time,n);
646	    }
647	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
648	}
649	interest= interest->next;
650    }
651    return;
652}
653
654void
655XkbSendExtensionDeviceNotify(	DeviceIntPtr 			dev,
656				ClientPtr			client,
657				xkbExtensionDeviceNotify *	pEv)
658{
659int		 initialized;
660XkbInterestPtr	 interest;
661Time 		 time = 0;
662CARD32		 defined, state;
663CARD16		 reason, supported = 0;
664
665    interest = dev->xkb_interest;
666    if (!interest)
667	return;
668
669    initialized = 0;
670    reason= pEv->reason;
671    defined= pEv->ledsDefined;
672    state= pEv->ledState;
673    while (interest) {
674	if ((!interest->client->clientGone) &&
675	    (interest->client->requestVector != InitialVector) &&
676	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
677	    (interest->extDevNotifyMask&reason)) {
678	    if (!initialized) {
679		pEv->type = XkbEventCode + XkbEventBase;
680		pEv->xkbType = XkbExtensionDeviceNotify;
681		pEv->deviceID = dev->id;
682		pEv->sequenceNumber = interest->client->sequence;
683		pEv->time = time = GetTimeInMillis();
684		supported= pEv->supported;
685		initialized= 1;
686	    }
687	    else {
688		pEv->sequenceNumber = interest->client->sequence;
689		pEv->time = time;
690		pEv->ledsDefined= defined;
691		pEv->ledState= state;
692		pEv->reason= reason;
693		pEv->supported= supported;
694	    }
695	    if (client!=interest->client) {
696		/* only report UnsupportedFeature to the client that */
697		/* issued the failing request */
698		pEv->reason&= ~XkbXI_UnsupportedFeatureMask;
699		if ((interest->extDevNotifyMask&reason)==0)
700		    continue;
701	    }
702	    if ( interest->client->swapped ) {
703		register int n;
704		swaps(&pEv->sequenceNumber,n);
705		swapl(&pEv->time,n);
706		swapl(&pEv->ledsDefined,n);
707		swapl(&pEv->ledState,n);
708		swaps(&pEv->reason,n);
709		swaps(&pEv->supported,n);
710	    }
711	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
712	}
713	interest= interest->next;
714    }
715    return;
716}
717
718void
719XkbSendNotification(	DeviceIntPtr		kbd,
720			XkbChangesPtr		pChanges,
721			XkbEventCausePtr	cause)
722{
723XkbSrvLedInfoPtr	sli;
724
725    sli= NULL;
726    if (pChanges->state_changes) {
727	xkbStateNotify sn;
728	sn.changed= pChanges->state_changes;
729	sn.keycode= cause->kc;
730	sn.eventType= cause->event;
731	sn.requestMajor= cause->mjr;
732	sn.requestMinor= cause->mnr;
733	XkbSendStateNotify(kbd,&sn);
734    }
735    if (pChanges->map.changed) {
736	xkbMapNotify mn;
737	mn.changed= pChanges->map.changed;
738	mn.firstType= pChanges->map.first_type;
739	mn.nTypes= pChanges->map.num_types;
740	mn.firstKeySym= pChanges->map.first_key_sym;
741	mn.nKeySyms= pChanges->map.num_key_syms;
742	mn.firstKeyAct= pChanges->map.first_key_act;
743	mn.nKeyActs= pChanges->map.num_key_acts;
744	mn.firstKeyBehavior= pChanges->map.first_key_behavior;
745	mn.nKeyBehaviors= pChanges->map.num_key_behaviors;
746	mn.virtualMods= pChanges->map.vmods;
747	mn.firstKeyExplicit= pChanges->map.first_key_explicit;
748	mn.nKeyExplicit= pChanges->map.num_key_explicit;
749	mn.firstModMapKey= pChanges->map.first_modmap_key;
750	mn.nModMapKeys= pChanges->map.num_modmap_keys;
751	mn.firstVModMapKey= pChanges->map.first_vmodmap_key;
752	mn.nVModMapKeys= pChanges->map.num_vmodmap_keys;
753	XkbSendMapNotify(kbd,&mn);
754    }
755    if ((pChanges->ctrls.changed_ctrls)||
756	(pChanges->ctrls.enabled_ctrls_changes)) {
757	xkbControlsNotify cn;
758	cn.changedControls= pChanges->ctrls.changed_ctrls;
759	cn.enabledControlChanges= pChanges->ctrls.enabled_ctrls_changes;
760	cn.keycode= cause->kc;
761	cn.eventType= cause->event;
762	cn.requestMajor= cause->mjr;
763	cn.requestMinor= cause->mnr;
764	XkbSendControlsNotify(kbd,&cn);
765    }
766    if (pChanges->indicators.map_changes) {
767	xkbIndicatorNotify in;
768	if (sli==NULL)
769	    sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
770	in.state= sli->effectiveState;
771	in.changed= pChanges->indicators.map_changes;
772	XkbSendIndicatorNotify(kbd,XkbIndicatorMapNotify,&in);
773    }
774    if (pChanges->indicators.state_changes) {
775	xkbIndicatorNotify in;
776	if (sli==NULL)
777	    sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
778	in.state= sli->effectiveState;
779	in.changed= pChanges->indicators.state_changes;
780	XkbSendIndicatorNotify(kbd,XkbIndicatorStateNotify,&in);
781    }
782    if (pChanges->names.changed) {
783	xkbNamesNotify nn;
784	nn.changed= pChanges->names.changed;
785	nn.firstType= pChanges->names.first_type;
786	nn.nTypes= pChanges->names.num_types;
787	nn.firstLevelName= pChanges->names.first_lvl;
788	nn.nLevelNames= pChanges->names.num_lvls;
789	nn.nRadioGroups= pChanges->names.num_rg;
790	nn.changedVirtualMods= pChanges->names.changed_vmods;
791	nn.changedIndicators= pChanges->names.changed_indicators;
792	XkbSendNamesNotify(kbd,&nn);
793    }
794    if ((pChanges->compat.changed_groups)||(pChanges->compat.num_si>0)) {
795	xkbCompatMapNotify cmn;
796	cmn.changedGroups= pChanges->compat.changed_groups;
797	cmn.firstSI= pChanges->compat.first_si;
798	cmn.nSI= pChanges->compat.num_si;
799	cmn.nTotalSI= kbd->key->xkbInfo->desc->compat->num_si;
800	XkbSendCompatMapNotify(kbd,&cmn);
801    }
802    return;
803}
804
805/***====================================================================***/
806
807Bool
808XkbFilterEvents(ClientPtr pClient,int nEvents,xEvent *xE)
809{
810int	i, button_mask;
811DeviceIntPtr pXDev = (DeviceIntPtr)LookupKeyboardDevice();
812XkbSrvInfoPtr	xkbi;
813
814    xkbi= pXDev->key->xkbInfo;
815    if ( pClient->xkbClientFlags & _XkbClientInitialized ) {
816#ifdef DEBUG
817	if ((xkbDebugFlags&0x10)&&
818		((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease)||
819                 (xE[0].u.u.type==DeviceKeyPress)||
820                 (xE[0].u.u.type == DeviceKeyRelease))) {
821	    ErrorF("XKbFilterWriteEvents:\n");
822	    ErrorF("   Event state= 0x%04x\n",xE[0].u.keyButtonPointer.state);
823	    ErrorF("   XkbLastRepeatEvent!=xE (0x%p!=0x%p) %s\n",
824			XkbLastRepeatEvent,xE,
825			((XkbLastRepeatEvent!=(pointer)xE)?"True":"False"));
826	    ErrorF("   (xkbClientEventsFlags&XWDA)==0 (0x%x) %s\n",
827		pClient->xkbClientFlags,
828		(_XkbWantsDetectableAutoRepeat(pClient)?"True":"False"));
829	    ErrorF("   !IsRelease(%d) %s\n",xE[0].u.u.type,
830			(!_XkbIsReleaseEvent(xE[0].u.u.type))?"True":"False");
831	}
832#endif /* DEBUG */
833	if (	(XkbLastRepeatEvent==(pointer)xE) &&
834	     	(_XkbWantsDetectableAutoRepeat(pClient)) &&
835	     	(_XkbIsReleaseEvent(xE[0].u.u.type)) ) {
836	    return False;
837	}
838	if ((pXDev->grab != NullGrab) && pXDev->fromPassiveGrab &&
839	    ((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease)||
840             (xE[0].u.u.type==DeviceKeyPress)||
841             (xE[0].u.u.type == DeviceKeyRelease))) {
842	    register unsigned state,flags;
843
844	    flags= pClient->xkbClientFlags;
845	    state= xkbi->state.compat_grab_mods;
846	    if (flags & XkbPCF_GrabsUseXKBStateMask) {
847		int group;
848		if (flags&XkbPCF_LookupStateWhenGrabbed) {
849		     group= xkbi->state.group;
850		     state= xkbi->state.lookup_mods;
851		}
852		else {
853		    state= xkbi->state.grab_mods;
854		    group= xkbi->state.base_group+xkbi->state.latched_group;
855		    if ((group<0)||(group>=xkbi->desc->ctrls->num_groups)) {
856			group= XkbAdjustGroup(group,xkbi->desc->ctrls);
857		    }
858		}
859		state = XkbBuildCoreState(state, group);
860	    }
861	    else if (flags&XkbPCF_LookupStateWhenGrabbed)
862		state= xkbi->state.compat_lookup_mods;
863	    xE[0].u.keyButtonPointer.state= state;
864	}
865	button_mask = 1 << xE[0].u.u.detail;
866	if (xE[0].u.u.type == ButtonPress &&
867	    ((xE[0].u.keyButtonPointer.state >> 7) & button_mask) == button_mask &&
868	    (xkbi->lockedPtrButtons & button_mask) == button_mask) {
869#ifdef DEBUG
870	    /* If the MouseKeys is pressed, and the "real" mouse is also pressed
871	     * when the mouse is released, the server does not behave properly.
872	     * Faking a release of the button here solves the problem.
873	     */
874	    ErrorF("Faking release of button %d\n", xE[0].u.u.detail);
875#endif
876	    XkbDDXFakePointerButton(ButtonRelease, xE[0].u.u.detail);
877        }
878    }
879    else {
880	register CARD8 	type;
881
882	for (i=0;i<nEvents;i++) {
883	    type= xE[i].u.u.type;
884#ifdef DEBUG
885	    if ((xkbDebugFlags&0x4)&&
886		((xE[i].u.u.type==KeyPress)||(xE[i].u.u.type==KeyRelease)||
887                 (xE[i].u.u.type==DeviceKeyPress)||
888                 (xE[i].u.u.type == DeviceKeyRelease))) {
889		XkbStatePtr s= &xkbi->state;
890		ErrorF("XKbFilterWriteEvents (non-XKB):\n");
891		ErrorF("event= 0x%04x\n",xE[i].u.keyButtonPointer.state);
892		ErrorF("lookup= 0x%02x, grab= 0x%02x\n",s->lookup_mods,
893							s->grab_mods);
894		ErrorF("compat lookup= 0x%02x, grab= 0x%02x\n",
895							s->compat_lookup_mods,
896							s->compat_grab_mods);
897	    }
898#endif
899	    if ( (type>=KeyPress)&&(type<=MotionNotify) ) {
900		CARD16	old,new;
901
902		old= xE[i].u.keyButtonPointer.state&(~0x1f00);
903		new= xE[i].u.keyButtonPointer.state&0x1F00;
904
905		if (old==XkbStateFieldFromRec(&xkbi->state))
906		     new|= xkbi->state.compat_lookup_mods;
907		else new|= xkbi->state.compat_grab_mods;
908		xE[i].u.keyButtonPointer.state= new;
909	    }
910	    else if ((type==EnterNotify)||(type==LeaveNotify)) {
911		xE[i].u.enterLeave.state&= 0x1F00;
912		xE[i].u.enterLeave.state|= xkbi->state.compat_grab_mods;
913	    } else if ((type>=DeviceKeyPress)&&(type<=DeviceMotionNotify)) {
914                CARD16  old, new;
915                deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer*)&xE[i];
916                old= kbp->state&(~0x1F00);
917                new= kbp->state&0x1F00;
918		if (old==XkbStateFieldFromRec(&xkbi->state))
919		     new|= xkbi->state.compat_lookup_mods;
920		else new|= xkbi->state.compat_grab_mods;
921                kbp->state= new;
922            }
923	    button_mask = 1 << xE[i].u.u.detail;
924	    if (type == ButtonPress &&
925		((xE[i].u.keyButtonPointer.state >> 7) & button_mask) == button_mask &&
926		(xkbi->lockedPtrButtons & button_mask) == button_mask) {
927#ifdef DEBUG
928		ErrorF("Faking release of button %d\n", xE[i].u.u.detail);
929#endif
930		XkbDDXFakePointerButton(ButtonRelease, xE[i].u.u.detail);
931	    } else if (type == DeviceButtonPress &&
932                    ((((deviceKeyButtonPointer*)&xE[i])->state >> 7) & button_mask) == button_mask &&
933                    (xkbi->lockedPtrButtons & button_mask) == button_mask) {
934#ifdef DEBUG
935		ErrorF("Faking release of button %d\n", ((deviceKeyButtonPointer*)&xE[i])->state);
936#endif
937		XkbDDXFakePointerButton(DeviceButtonRelease, ((deviceKeyButtonPointer*)&xE[i])->state);
938            }
939	}
940    }
941    return True;
942}
943
944/***====================================================================***/
945
946XkbInterestPtr
947XkbFindClientResource(DevicePtr inDev,ClientPtr client)
948{
949DeviceIntPtr	dev = (DeviceIntPtr)inDev;
950XkbInterestPtr	interest;
951
952    if ( dev->xkb_interest ) {
953	interest = dev->xkb_interest;
954	while (interest){
955	    if (interest->client==client) {
956		return interest;
957	    }
958	    interest = interest->next;
959	}
960    }
961    return NULL;
962}
963
964XkbInterestPtr
965XkbAddClientResource(DevicePtr inDev,ClientPtr client,XID id)
966{
967DeviceIntPtr	dev = (DeviceIntPtr)inDev;
968XkbInterestPtr	interest;
969
970    interest = dev->xkb_interest;
971    while (interest) {
972	if (interest->client==client)
973	    return ((interest->resource==id)?interest:NULL);
974	interest = interest->next;
975    }
976    interest = _XkbTypedAlloc(XkbInterestRec);
977    bzero(interest,sizeof(XkbInterestRec));
978    if (interest) {
979	interest->dev = dev;
980	interest->client = client;
981	interest->resource = id;
982	interest->stateNotifyMask= 0;
983	interest->ctrlsNotifyMask= 0;
984	interest->namesNotifyMask= 0;
985	interest->compatNotifyMask= 0;
986	interest->bellNotifyMask= FALSE;
987	interest->accessXNotifyMask= 0;
988	interest->iStateNotifyMask= 0;
989	interest->iMapNotifyMask= 0;
990	interest->altSymsNotifyMask= 0;
991	interest->next = dev->xkb_interest;
992	dev->xkb_interest= interest;
993	return interest;
994    }
995    return NULL;
996}
997
998int
999XkbRemoveResourceClient(DevicePtr inDev,XID id)
1000{
1001XkbSrvInfoPtr	xkbi;
1002DeviceIntPtr	dev = (DeviceIntPtr)inDev;
1003XkbInterestPtr	interest;
1004Bool		found;
1005unsigned long	autoCtrls,autoValues;
1006ClientPtr	client = NULL;
1007
1008    found= False;
1009    autoCtrls= autoValues= 0;
1010    if ( dev->xkb_interest ) {
1011	interest = dev->xkb_interest;
1012	if (interest && (interest->resource==id)){
1013	    dev->xkb_interest = interest->next;
1014	    autoCtrls= interest->autoCtrls;
1015	    autoValues= interest->autoCtrlValues;
1016	    client= interest->client;
1017	    _XkbFree(interest);
1018	    found= True;
1019	}
1020	while ((!found)&&(interest->next)) {
1021	    if (interest->next->resource==id) {
1022		XkbInterestPtr	victim = interest->next;
1023		interest->next = victim->next;
1024		autoCtrls= victim->autoCtrls;
1025		autoValues= victim->autoCtrlValues;
1026		client= victim->client;
1027		_XkbFree(victim);
1028		found= True;
1029	    }
1030	    interest = interest->next;
1031	}
1032    }
1033    if (found && autoCtrls && dev->key && dev->key->xkbInfo ) {
1034	XkbEventCauseRec cause;
1035
1036	xkbi= dev->key->xkbInfo;
1037	XkbSetCauseXkbReq(&cause,X_kbPerClientFlags,client);
1038	XkbEnableDisableControls(xkbi,autoCtrls,autoValues,NULL,&cause);
1039    }
1040    return found;
1041}
1042