xkbEvents.c revision 05b261ec
105b261ecSmrg/************************************************************
205b261ecSmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
305b261ecSmrg
405b261ecSmrgPermission to use, copy, modify, and distribute this
505b261ecSmrgsoftware and its documentation for any purpose and without
605b261ecSmrgfee is hereby granted, provided that the above copyright
705b261ecSmrgnotice appear in all copies and that both that copyright
805b261ecSmrgnotice and this permission notice appear in supporting
905b261ecSmrgdocumentation, and that the name of Silicon Graphics not be
1005b261ecSmrgused in advertising or publicity pertaining to distribution
1105b261ecSmrgof the software without specific prior written permission.
1205b261ecSmrgSilicon Graphics makes no representation about the suitability
1305b261ecSmrgof this software for any purpose. It is provided "as is"
1405b261ecSmrgwithout any express or implied warranty.
1505b261ecSmrg
1605b261ecSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1705b261ecSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1905b261ecSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2005b261ecSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2105b261ecSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
2205b261ecSmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
2305b261ecSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
2405b261ecSmrg
2505b261ecSmrg********************************************************/
2605b261ecSmrg
2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2805b261ecSmrg#include <dix-config.h>
2905b261ecSmrg#endif
3005b261ecSmrg
3105b261ecSmrg#include <stdio.h>
3205b261ecSmrg#define NEED_EVENTS 1
3305b261ecSmrg#include <X11/X.h>
3405b261ecSmrg#include <X11/Xproto.h>
3505b261ecSmrg#include <X11/keysym.h>
3605b261ecSmrg#include <X11/extensions/XI.h>
3705b261ecSmrg#include <X11/extensions/XIproto.h>
3805b261ecSmrg#include "inputstr.h"
3905b261ecSmrg#include "windowstr.h"
4005b261ecSmrg#include <xkbsrv.h>
4105b261ecSmrg#include "xkb.h"
4205b261ecSmrg
4305b261ecSmrg/***====================================================================***/
4405b261ecSmrg
4505b261ecSmrgvoid
4605b261ecSmrgXkbSendNewKeyboardNotify(DeviceIntPtr kbd,xkbNewKeyboardNotify *pNKN)
4705b261ecSmrg{
4805b261ecSmrgregister int	i;
4905b261ecSmrgTime 		time;
5005b261ecSmrgCARD16		changed;
5105b261ecSmrg
5205b261ecSmrg    pNKN->type = XkbEventCode + XkbEventBase;
5305b261ecSmrg    pNKN->xkbType = XkbNewKeyboardNotify;
5405b261ecSmrg    pNKN->time = time = GetTimeInMillis();
5505b261ecSmrg    changed = pNKN->changed;
5605b261ecSmrg
5705b261ecSmrg    for (i=1; i<currentMaxClients; i++) {
5805b261ecSmrg        if ((!clients[i]) || clients[i]->clientGone ||
5905b261ecSmrg				(clients[i]->requestVector==InitialVector)) {
6005b261ecSmrg	    continue;
6105b261ecSmrg	}
6205b261ecSmrg
6305b261ecSmrg	if (clients[i]->xkbClientFlags&_XkbClientInitialized)  {
6405b261ecSmrg	    if (clients[i]->newKeyboardNotifyMask&changed) {
6505b261ecSmrg		pNKN->sequenceNumber = clients[i]->sequence;
6605b261ecSmrg		pNKN->time = time;
6705b261ecSmrg		pNKN->changed = changed;
6805b261ecSmrg		if ( clients[i]->swapped ) {
6905b261ecSmrg		    register int n;
7005b261ecSmrg		    swaps(&pNKN->sequenceNumber,n);
7105b261ecSmrg		    swapl(&pNKN->time,n);
7205b261ecSmrg		    swaps(&pNKN->changed,n);
7305b261ecSmrg		}
7405b261ecSmrg		WriteToClient(clients[i],sizeof(xEvent),(char *)pNKN);
7505b261ecSmrg		if (changed&XkbNKN_KeycodesMask) {
7605b261ecSmrg		    clients[i]->minKC= pNKN->minKeyCode;
7705b261ecSmrg		    clients[i]->maxKC= pNKN->maxKeyCode;
7805b261ecSmrg		}
7905b261ecSmrg	    }
8005b261ecSmrg	}
8105b261ecSmrg	else if (changed&XkbNKN_KeycodesMask) {
8205b261ecSmrg	    xEvent	event;
8305b261ecSmrg	    event.u.u.type= MappingNotify;
8405b261ecSmrg	    event.u.mappingNotify.request= MappingKeyboard;
8505b261ecSmrg	    event.u.mappingNotify.firstKeyCode= clients[i]->minKC;
8605b261ecSmrg	    event.u.mappingNotify.count= clients[i]->maxKC-clients[i]->minKC+1;
8705b261ecSmrg	    event.u.u.sequenceNumber= clients[i]->sequence;
8805b261ecSmrg	    if (clients[i]->swapped) {
8905b261ecSmrg		int n;
9005b261ecSmrg		swaps(&event.u.u.sequenceNumber,n);
9105b261ecSmrg	    }
9205b261ecSmrg	    WriteToClient(clients[i],SIZEOF(xEvent), (char *)&event);
9305b261ecSmrg	    event.u.mappingNotify.request= MappingModifier;
9405b261ecSmrg	    WriteToClient(clients[i],SIZEOF(xEvent), (char *)&event);
9505b261ecSmrg	}
9605b261ecSmrg    }
9705b261ecSmrg    return;
9805b261ecSmrg}
9905b261ecSmrg
10005b261ecSmrg/***====================================================================***/
10105b261ecSmrg
10205b261ecSmrgvoid
10305b261ecSmrgXkbSendStateNotify(DeviceIntPtr kbd,xkbStateNotify *pSN)
10405b261ecSmrg{
10505b261ecSmrgXkbSrvInfoPtr	xkbi;
10605b261ecSmrgXkbStatePtr	state;
10705b261ecSmrgXkbInterestPtr	interest;
10805b261ecSmrgTime 		time;
10905b261ecSmrgregister CARD16	changed,bState;
11005b261ecSmrg
11105b261ecSmrg    interest = kbd->xkb_interest;
11205b261ecSmrg    if (!interest)
11305b261ecSmrg	return;
11405b261ecSmrg    xkbi = kbd->key->xkbInfo;
11505b261ecSmrg    state= &xkbi->state;
11605b261ecSmrg
11705b261ecSmrg    pSN->type = XkbEventCode + XkbEventBase;
11805b261ecSmrg    pSN->xkbType = XkbStateNotify;
11905b261ecSmrg    pSN->deviceID = kbd->id;
12005b261ecSmrg    pSN->time = time = GetTimeInMillis();
12105b261ecSmrg    pSN->mods = state->mods;
12205b261ecSmrg    pSN->baseMods = state->base_mods;
12305b261ecSmrg    pSN->latchedMods = state->latched_mods;
12405b261ecSmrg    pSN->lockedMods = state->locked_mods;
12505b261ecSmrg    pSN->group = state->group;
12605b261ecSmrg    pSN->baseGroup = state->base_group;
12705b261ecSmrg    pSN->latchedGroup = state->latched_group;
12805b261ecSmrg    pSN->lockedGroup = state->locked_group;
12905b261ecSmrg    pSN->compatState = state->compat_state;
13005b261ecSmrg    pSN->grabMods = state->grab_mods;
13105b261ecSmrg    pSN->compatGrabMods = state->compat_grab_mods;
13205b261ecSmrg    pSN->lookupMods = state->lookup_mods;
13305b261ecSmrg    pSN->compatLookupMods = state->compat_lookup_mods;
13405b261ecSmrg    pSN->ptrBtnState = state->ptr_buttons;
13505b261ecSmrg    changed = pSN->changed;
13605b261ecSmrg    bState= pSN->ptrBtnState;
13705b261ecSmrg
13805b261ecSmrg    while (interest) {
13905b261ecSmrg	if ((!interest->client->clientGone) &&
14005b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
14105b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
14205b261ecSmrg	    (interest->stateNotifyMask&changed)) {
14305b261ecSmrg	    pSN->sequenceNumber = interest->client->sequence;
14405b261ecSmrg	    pSN->time = time;
14505b261ecSmrg	    pSN->changed = changed;
14605b261ecSmrg	    pSN->ptrBtnState = bState;
14705b261ecSmrg	    if ( interest->client->swapped ) {
14805b261ecSmrg		register int n;
14905b261ecSmrg		swaps(&pSN->sequenceNumber,n);
15005b261ecSmrg		swapl(&pSN->time,n);
15105b261ecSmrg		swaps(&pSN->changed,n);
15205b261ecSmrg		swaps(&pSN->ptrBtnState,n);
15305b261ecSmrg	    }
15405b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pSN);
15505b261ecSmrg	}
15605b261ecSmrg	interest= interest->next;
15705b261ecSmrg    }
15805b261ecSmrg    return;
15905b261ecSmrg}
16005b261ecSmrg
16105b261ecSmrg/***====================================================================***/
16205b261ecSmrg
16305b261ecSmrgvoid
16405b261ecSmrgXkbSendMapNotify(DeviceIntPtr kbd,xkbMapNotify *pMN)
16505b261ecSmrg{
16605b261ecSmrgint 		i;
16705b261ecSmrgXkbSrvInfoPtr	xkbi;
16805b261ecSmrgunsigned	time = 0,initialized;
16905b261ecSmrgCARD16		changed;
17005b261ecSmrg
17105b261ecSmrg    xkbi = kbd->key->xkbInfo;
17205b261ecSmrg    initialized= 0;
17305b261ecSmrg
17405b261ecSmrg    changed = pMN->changed;
17505b261ecSmrg    pMN->minKeyCode= xkbi->desc->min_key_code;
17605b261ecSmrg    pMN->maxKeyCode= xkbi->desc->max_key_code;
17705b261ecSmrg    for (i=1; i<currentMaxClients; i++) {
17805b261ecSmrg        if (clients[i] && ! clients[i]->clientGone &&
17905b261ecSmrg	    (clients[i]->requestVector != InitialVector) &&
18005b261ecSmrg	    (clients[i]->xkbClientFlags&_XkbClientInitialized) &&
18105b261ecSmrg	    (clients[i]->mapNotifyMask&changed))
18205b261ecSmrg	{
18305b261ecSmrg	    if (!initialized) {
18405b261ecSmrg		pMN->type = XkbEventCode + XkbEventBase;
18505b261ecSmrg		pMN->xkbType = XkbMapNotify;
18605b261ecSmrg		pMN->deviceID = kbd->id;
18705b261ecSmrg		time = GetTimeInMillis();
18805b261ecSmrg		initialized= 1;
18905b261ecSmrg	    }
19005b261ecSmrg	    pMN->time= time;
19105b261ecSmrg	    pMN->sequenceNumber = clients[i]->sequence;
19205b261ecSmrg	    pMN->changed = changed;
19305b261ecSmrg	    if ( clients[i]->swapped ) {
19405b261ecSmrg		register int n;
19505b261ecSmrg		swaps(&pMN->sequenceNumber,n);
19605b261ecSmrg		swapl(&pMN->time,n);
19705b261ecSmrg		swaps(&pMN->changed,n);
19805b261ecSmrg	    }
19905b261ecSmrg	    WriteToClient(clients[i],sizeof(xEvent),(char *)pMN);
20005b261ecSmrg	}
20105b261ecSmrg    }
20205b261ecSmrg    return;
20305b261ecSmrg}
20405b261ecSmrg
20505b261ecSmrgint
20605b261ecSmrgXkbComputeControlsNotify(	DeviceIntPtr	 	kbd,
20705b261ecSmrg				XkbControlsPtr		old,
20805b261ecSmrg				XkbControlsPtr		new,
20905b261ecSmrg				xkbControlsNotify *	pCN,
21005b261ecSmrg				Bool			forceCtrlProc)
21105b261ecSmrg{
21205b261ecSmrgint		i;
21305b261ecSmrgCARD32 		changedControls;
21405b261ecSmrg
21505b261ecSmrg    changedControls= 0;
21605b261ecSmrg
21705b261ecSmrg    if (!kbd || !kbd->kbdfeed)
21805b261ecSmrg        return 0;
21905b261ecSmrg
22005b261ecSmrg    if (old->enabled_ctrls!=new->enabled_ctrls)
22105b261ecSmrg	changedControls|= XkbControlsEnabledMask;
22205b261ecSmrg    if ((old->repeat_delay!=new->repeat_delay)||
22305b261ecSmrg	(old->repeat_interval!=new->repeat_interval))
22405b261ecSmrg	changedControls|= XkbRepeatKeysMask;
22505b261ecSmrg    for (i = 0; i < XkbPerKeyBitArraySize; i++)
22605b261ecSmrg	if (old->per_key_repeat[i] != new->per_key_repeat[i])
22705b261ecSmrg	    changedControls|= XkbPerKeyRepeatMask;
22805b261ecSmrg    if (old->slow_keys_delay!=new->slow_keys_delay)
22905b261ecSmrg	changedControls|= XkbSlowKeysMask;
23005b261ecSmrg    if (old->debounce_delay!=new->debounce_delay)
23105b261ecSmrg	changedControls|= XkbBounceKeysMask;
23205b261ecSmrg    if ((old->mk_delay!=new->mk_delay)||
23305b261ecSmrg	(old->mk_interval!=new->mk_interval)||
23405b261ecSmrg	(old->mk_dflt_btn!=new->mk_dflt_btn))
23505b261ecSmrg	changedControls|= XkbMouseKeysMask;
23605b261ecSmrg    if ((old->mk_time_to_max!=new->mk_time_to_max)||
23705b261ecSmrg	(old->mk_curve!=new->mk_curve)||
23805b261ecSmrg	(old->mk_max_speed!=new->mk_max_speed))
23905b261ecSmrg	changedControls|= XkbMouseKeysAccelMask;
24005b261ecSmrg    if (old->ax_options!=new->ax_options)
24105b261ecSmrg	changedControls|= XkbAccessXKeysMask;
24205b261ecSmrg    if ((old->ax_options^new->ax_options) & XkbAX_SKOptionsMask)
24305b261ecSmrg	changedControls|= XkbStickyKeysMask;
24405b261ecSmrg    if ((old->ax_options^new->ax_options) & XkbAX_FBOptionsMask)
24505b261ecSmrg	changedControls|= XkbAccessXFeedbackMask;
24605b261ecSmrg    if ((old->ax_timeout!=new->ax_timeout)||
24705b261ecSmrg	(old->axt_ctrls_mask!=new->axt_ctrls_mask)||
24805b261ecSmrg	(old->axt_ctrls_values!=new->axt_ctrls_values)||
24905b261ecSmrg	(old->axt_opts_mask!=new->axt_opts_mask)||
25005b261ecSmrg	(old->axt_opts_values!= new->axt_opts_values)) {
25105b261ecSmrg	changedControls|= XkbAccessXTimeoutMask;
25205b261ecSmrg    }
25305b261ecSmrg    if ((old->internal.mask!=new->internal.mask)||
25405b261ecSmrg	(old->internal.real_mods!=new->internal.real_mods)||
25505b261ecSmrg	(old->internal.vmods!=new->internal.vmods))
25605b261ecSmrg	changedControls|= XkbInternalModsMask;
25705b261ecSmrg    if ((old->ignore_lock.mask!=new->ignore_lock.mask)||
25805b261ecSmrg	(old->ignore_lock.real_mods!=new->ignore_lock.real_mods)||
25905b261ecSmrg	(old->ignore_lock.vmods!=new->ignore_lock.vmods))
26005b261ecSmrg	changedControls|= XkbIgnoreLockModsMask;
26105b261ecSmrg
26205b261ecSmrg    if (new->enabled_ctrls&XkbRepeatKeysMask)
26305b261ecSmrg	 kbd->kbdfeed->ctrl.autoRepeat=TRUE;
26405b261ecSmrg    else kbd->kbdfeed->ctrl.autoRepeat=FALSE;
26505b261ecSmrg
26605b261ecSmrg    if (kbd->kbdfeed && kbd->kbdfeed->CtrlProc &&
26705b261ecSmrg	(changedControls || forceCtrlProc))
26805b261ecSmrg	(*kbd->kbdfeed->CtrlProc)(kbd, &kbd->kbdfeed->ctrl);
26905b261ecSmrg
27005b261ecSmrg    if ((!changedControls)&&(old->num_groups==new->num_groups))
27105b261ecSmrg	return 0;
27205b261ecSmrg
27305b261ecSmrg    if (!kbd->xkb_interest)
27405b261ecSmrg	return 0;
27505b261ecSmrg
27605b261ecSmrg    pCN->changedControls = changedControls;
27705b261ecSmrg    pCN->enabledControls = new->enabled_ctrls;
27805b261ecSmrg    pCN->enabledControlChanges = (new->enabled_ctrls^old->enabled_ctrls);
27905b261ecSmrg    pCN->numGroups = new->num_groups;
28005b261ecSmrg
28105b261ecSmrg    return 1;
28205b261ecSmrg}
28305b261ecSmrg
28405b261ecSmrgvoid
28505b261ecSmrgXkbSendControlsNotify(DeviceIntPtr kbd,xkbControlsNotify *pCN)
28605b261ecSmrg{
28705b261ecSmrgint			initialized;
28805b261ecSmrgCARD32 		 	changedControls, enabledControls, enabledChanges = 0;
28905b261ecSmrgXkbSrvInfoPtr		xkbi;
29005b261ecSmrgXkbInterestPtr		interest;
29105b261ecSmrgTime 		 	time = 0;
29205b261ecSmrg
29305b261ecSmrg    interest = kbd->xkb_interest;
29405b261ecSmrg    if (!interest)
29505b261ecSmrg	return;
29605b261ecSmrg    xkbi = kbd->key->xkbInfo;
29705b261ecSmrg
29805b261ecSmrg    initialized = 0;
29905b261ecSmrg    enabledControls = xkbi->desc->ctrls->enabled_ctrls;
30005b261ecSmrg    changedControls = pCN->changedControls;
30105b261ecSmrg    pCN->numGroups= xkbi->desc->ctrls->num_groups;
30205b261ecSmrg    while (interest) {
30305b261ecSmrg	if ((!interest->client->clientGone) &&
30405b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
30505b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
30605b261ecSmrg	    (interest->ctrlsNotifyMask&changedControls)) {
30705b261ecSmrg	    if (!initialized) {
30805b261ecSmrg		pCN->type = XkbEventCode + XkbEventBase;
30905b261ecSmrg		pCN->xkbType = XkbControlsNotify;
31005b261ecSmrg		pCN->deviceID = kbd->id;
31105b261ecSmrg		pCN->time = time = GetTimeInMillis();
31205b261ecSmrg		enabledChanges = pCN->enabledControlChanges;
31305b261ecSmrg		initialized= 1;
31405b261ecSmrg	    }
31505b261ecSmrg	    pCN->changedControls = changedControls;
31605b261ecSmrg	    pCN->enabledControls = enabledControls;
31705b261ecSmrg	    pCN->enabledControlChanges = enabledChanges;
31805b261ecSmrg	    pCN->sequenceNumber = interest->client->sequence;
31905b261ecSmrg	    pCN->time = time;
32005b261ecSmrg	    if ( interest->client->swapped ) {
32105b261ecSmrg		register int n;
32205b261ecSmrg		swaps(&pCN->sequenceNumber,n);
32305b261ecSmrg		swapl(&pCN->changedControls,n);
32405b261ecSmrg		swapl(&pCN->enabledControls,n);
32505b261ecSmrg		swapl(&pCN->enabledControlChanges,n);
32605b261ecSmrg		swapl(&pCN->time,n);
32705b261ecSmrg	    }
32805b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pCN);
32905b261ecSmrg	}
33005b261ecSmrg	interest= interest->next;
33105b261ecSmrg    }
33205b261ecSmrg    return;
33305b261ecSmrg}
33405b261ecSmrg
33505b261ecSmrgstatic void
33605b261ecSmrgXkbSendIndicatorNotify(DeviceIntPtr kbd,int xkbType,xkbIndicatorNotify *pEv)
33705b261ecSmrg{
33805b261ecSmrgint		initialized;
33905b261ecSmrgXkbInterestPtr	interest;
34005b261ecSmrgTime 		time = 0;
34105b261ecSmrgCARD32		state,changed;
34205b261ecSmrg
34305b261ecSmrg    interest = kbd->xkb_interest;
34405b261ecSmrg    if (!interest)
34505b261ecSmrg	return;
34605b261ecSmrg
34705b261ecSmrg    initialized = 0;
34805b261ecSmrg    state = pEv->state;
34905b261ecSmrg    changed = pEv->changed;
35005b261ecSmrg    while (interest) {
35105b261ecSmrg	if ((!interest->client->clientGone) &&
35205b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
35305b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
35405b261ecSmrg	    (((xkbType==XkbIndicatorStateNotify)&&
35505b261ecSmrg				(interest->iStateNotifyMask&changed))||
35605b261ecSmrg	     ((xkbType==XkbIndicatorMapNotify)&&
35705b261ecSmrg	    			(interest->iMapNotifyMask&changed)))) {
35805b261ecSmrg	    if (!initialized) {
35905b261ecSmrg		pEv->type = XkbEventCode + XkbEventBase;
36005b261ecSmrg		pEv->xkbType = xkbType;
36105b261ecSmrg		pEv->deviceID = kbd->id;
36205b261ecSmrg		pEv->time = time = GetTimeInMillis();
36305b261ecSmrg		initialized= 1;
36405b261ecSmrg	    }
36505b261ecSmrg	    pEv->sequenceNumber = interest->client->sequence;
36605b261ecSmrg	    pEv->time = time;
36705b261ecSmrg	    pEv->changed = changed;
36805b261ecSmrg	    pEv->state = state;
36905b261ecSmrg	    if ( interest->client->swapped ) {
37005b261ecSmrg		register int n;
37105b261ecSmrg		swaps(&pEv->sequenceNumber,n);
37205b261ecSmrg		swapl(&pEv->time,n);
37305b261ecSmrg		swapl(&pEv->changed,n);
37405b261ecSmrg		swapl(&pEv->state,n);
37505b261ecSmrg	    }
37605b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
37705b261ecSmrg	}
37805b261ecSmrg	interest= interest->next;
37905b261ecSmrg    }
38005b261ecSmrg    return;
38105b261ecSmrg}
38205b261ecSmrg
38305b261ecSmrg
38405b261ecSmrgvoid
38505b261ecSmrgXkbHandleBell(	BOOL		 force,
38605b261ecSmrg		BOOL		 eventOnly,
38705b261ecSmrg		DeviceIntPtr	 kbd,
38805b261ecSmrg		CARD8		 percent,
38905b261ecSmrg		pointer		 pCtrl,
39005b261ecSmrg		CARD8		 class,
39105b261ecSmrg		Atom		 name,
39205b261ecSmrg		WindowPtr	 pWin,
39305b261ecSmrg		ClientPtr	 pClient)
39405b261ecSmrg{
39505b261ecSmrgxkbBellNotify	bn;
39605b261ecSmrgint		initialized;
39705b261ecSmrgXkbSrvInfoPtr	xkbi;
39805b261ecSmrgXkbInterestPtr	interest;
39905b261ecSmrgCARD8		id;
40005b261ecSmrgCARD16		pitch,duration;
40105b261ecSmrgTime 		time = 0;
40205b261ecSmrgXID		winID = 0;
40305b261ecSmrg
40405b261ecSmrg    xkbi = kbd->key->xkbInfo;
40505b261ecSmrg
40605b261ecSmrg    if ((force||(xkbi->desc->ctrls->enabled_ctrls&XkbAudibleBellMask))&&
40705b261ecSmrg							(!eventOnly)) {
40805b261ecSmrg        if (kbd->kbdfeed->BellProc)
40905b261ecSmrg            (*kbd->kbdfeed->BellProc)(percent,kbd,(pointer)pCtrl,class);
41005b261ecSmrg    }
41105b261ecSmrg    interest = kbd->xkb_interest;
41205b261ecSmrg    if ((!interest)||(force))
41305b261ecSmrg	return;
41405b261ecSmrg
41505b261ecSmrg    if ((class==0)||(class==KbdFeedbackClass)) {
41605b261ecSmrg	KeybdCtrl *pKeyCtrl= (KeybdCtrl *)pCtrl;
41705b261ecSmrg	id= pKeyCtrl->id;
41805b261ecSmrg	pitch= pKeyCtrl->bell_pitch;
41905b261ecSmrg	duration= pKeyCtrl->bell_duration;
42005b261ecSmrg    }
42105b261ecSmrg    else if (class==BellFeedbackClass) {
42205b261ecSmrg	BellCtrl *pBellCtrl= (BellCtrl *)pCtrl;
42305b261ecSmrg	id= pBellCtrl->id;
42405b261ecSmrg	pitch= pBellCtrl->pitch;
42505b261ecSmrg	duration= pBellCtrl->duration;
42605b261ecSmrg    }
42705b261ecSmrg    else return;
42805b261ecSmrg
42905b261ecSmrg    initialized = 0;
43005b261ecSmrg    while (interest) {
43105b261ecSmrg	if ((!interest->client->clientGone) &&
43205b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
43305b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
43405b261ecSmrg	    (interest->bellNotifyMask)) {
43505b261ecSmrg	    if (!initialized) {
43605b261ecSmrg		time = GetTimeInMillis();
43705b261ecSmrg		bn.type = XkbEventCode + XkbEventBase;
43805b261ecSmrg		bn.xkbType = XkbBellNotify;
43905b261ecSmrg		bn.deviceID = kbd->id;
44005b261ecSmrg		bn.bellClass = class;
44105b261ecSmrg		bn.bellID = id;
44205b261ecSmrg		bn.percent= percent;
44305b261ecSmrg		bn.eventOnly = (eventOnly!=0);
44405b261ecSmrg		winID= (pWin?pWin->drawable.id:None);
44505b261ecSmrg		initialized= 1;
44605b261ecSmrg	    }
44705b261ecSmrg	    bn.sequenceNumber = interest->client->sequence;
44805b261ecSmrg	    bn.time = time;
44905b261ecSmrg	    bn.pitch = pitch;
45005b261ecSmrg	    bn.duration = duration;
45105b261ecSmrg	    bn.name = name;
45205b261ecSmrg	    bn.window=  winID;
45305b261ecSmrg	    if ( interest->client->swapped ) {
45405b261ecSmrg		register int n;
45505b261ecSmrg		swaps(&bn.sequenceNumber,n);
45605b261ecSmrg		swapl(&bn.time,n);
45705b261ecSmrg		swaps(&bn.pitch,n);
45805b261ecSmrg		swaps(&bn.duration,n);
45905b261ecSmrg		swapl(&bn.name,n);
46005b261ecSmrg		swapl(&bn.window,n);
46105b261ecSmrg	    }
46205b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)&bn);
46305b261ecSmrg	}
46405b261ecSmrg	interest= interest->next;
46505b261ecSmrg    }
46605b261ecSmrg    return;
46705b261ecSmrg}
46805b261ecSmrg
46905b261ecSmrgvoid
47005b261ecSmrgXkbSendAccessXNotify(DeviceIntPtr kbd,xkbAccessXNotify *pEv)
47105b261ecSmrg{
47205b261ecSmrgint		initialized;
47305b261ecSmrgXkbInterestPtr	interest;
47405b261ecSmrgTime 		time = 0;
47505b261ecSmrgCARD16		sk_delay,db_delay;
47605b261ecSmrg
47705b261ecSmrg    interest = kbd->xkb_interest;
47805b261ecSmrg    if (!interest)
47905b261ecSmrg	return;
48005b261ecSmrg
48105b261ecSmrg    initialized = 0;
48205b261ecSmrg    sk_delay= pEv->slowKeysDelay;
48305b261ecSmrg    db_delay= pEv->debounceDelay;
48405b261ecSmrg    while (interest) {
48505b261ecSmrg	if ((!interest->client->clientGone) &&
48605b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
48705b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
48805b261ecSmrg	    (interest->accessXNotifyMask&(1<<pEv->detail))) {
48905b261ecSmrg	    if (!initialized) {
49005b261ecSmrg		pEv->type = XkbEventCode + XkbEventBase;
49105b261ecSmrg		pEv->xkbType = XkbAccessXNotify;
49205b261ecSmrg		pEv->deviceID = kbd->id;
49305b261ecSmrg		pEv->time = time = GetTimeInMillis();
49405b261ecSmrg		initialized= 1;
49505b261ecSmrg	    }
49605b261ecSmrg	    pEv->sequenceNumber = interest->client->sequence;
49705b261ecSmrg	    pEv->time = time;
49805b261ecSmrg	    pEv->slowKeysDelay = sk_delay;
49905b261ecSmrg	    pEv->debounceDelay = db_delay;
50005b261ecSmrg	    if ( interest->client->swapped ) {
50105b261ecSmrg		register int n;
50205b261ecSmrg		swaps(&pEv->sequenceNumber,n);
50305b261ecSmrg		swapl(&pEv->time,n);
50405b261ecSmrg		swaps(&pEv->slowKeysDelay,n);
50505b261ecSmrg		swaps(&pEv->debounceDelay,n);
50605b261ecSmrg	    }
50705b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
50805b261ecSmrg	}
50905b261ecSmrg	interest= interest->next;
51005b261ecSmrg    }
51105b261ecSmrg    return;
51205b261ecSmrg}
51305b261ecSmrg
51405b261ecSmrgvoid
51505b261ecSmrgXkbSendNamesNotify(DeviceIntPtr kbd,xkbNamesNotify *pEv)
51605b261ecSmrg{
51705b261ecSmrgint		initialized;
51805b261ecSmrgXkbInterestPtr	interest;
51905b261ecSmrgTime 		time = 0;
52005b261ecSmrgCARD16		changed,changedVirtualMods;
52105b261ecSmrgCARD32		changedIndicators;
52205b261ecSmrg
52305b261ecSmrg    interest = kbd->xkb_interest;
52405b261ecSmrg    if (!interest)
52505b261ecSmrg	return;
52605b261ecSmrg
52705b261ecSmrg    initialized = 0;
52805b261ecSmrg    changed= pEv->changed;
52905b261ecSmrg    changedIndicators= pEv->changedIndicators;
53005b261ecSmrg    changedVirtualMods= pEv->changedVirtualMods;
53105b261ecSmrg    while (interest) {
53205b261ecSmrg	if ((!interest->client->clientGone) &&
53305b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
53405b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
53505b261ecSmrg	    (interest->namesNotifyMask&pEv->changed)) {
53605b261ecSmrg	    if (!initialized) {
53705b261ecSmrg		pEv->type = XkbEventCode + XkbEventBase;
53805b261ecSmrg		pEv->xkbType = XkbNamesNotify;
53905b261ecSmrg		pEv->deviceID = kbd->id;
54005b261ecSmrg		pEv->time = time = GetTimeInMillis();
54105b261ecSmrg		initialized= 1;
54205b261ecSmrg	    }
54305b261ecSmrg	    pEv->sequenceNumber = interest->client->sequence;
54405b261ecSmrg	    pEv->time = time;
54505b261ecSmrg	    pEv->changed = changed;
54605b261ecSmrg	    pEv->changedIndicators = changedIndicators;
54705b261ecSmrg	    pEv->changedVirtualMods= changedVirtualMods;
54805b261ecSmrg	    if ( interest->client->swapped ) {
54905b261ecSmrg		register int n;
55005b261ecSmrg		swaps(&pEv->sequenceNumber,n);
55105b261ecSmrg		swapl(&pEv->time,n);
55205b261ecSmrg		swaps(&pEv->changed,n);
55305b261ecSmrg		swapl(&pEv->changedIndicators,n);
55405b261ecSmrg		swaps(&pEv->changedVirtualMods,n);
55505b261ecSmrg	    }
55605b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
55705b261ecSmrg	}
55805b261ecSmrg	interest= interest->next;
55905b261ecSmrg    }
56005b261ecSmrg    return;
56105b261ecSmrg}
56205b261ecSmrg
56305b261ecSmrgvoid
56405b261ecSmrgXkbSendCompatMapNotify(DeviceIntPtr kbd,xkbCompatMapNotify *pEv)
56505b261ecSmrg{
56605b261ecSmrgint		initialized;
56705b261ecSmrgXkbInterestPtr	interest;
56805b261ecSmrgTime 		time = 0;
56905b261ecSmrgCARD16		firstSI = 0, nSI = 0, nTotalSI = 0;
57005b261ecSmrg
57105b261ecSmrg    interest = kbd->xkb_interest;
57205b261ecSmrg    if (!interest)
57305b261ecSmrg	return;
57405b261ecSmrg
57505b261ecSmrg    initialized = 0;
57605b261ecSmrg    while (interest) {
57705b261ecSmrg	if ((!interest->client->clientGone) &&
57805b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
57905b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
58005b261ecSmrg	    (interest->compatNotifyMask)) {
58105b261ecSmrg	    if (!initialized) {
58205b261ecSmrg		pEv->type = XkbEventCode + XkbEventBase;
58305b261ecSmrg		pEv->xkbType = XkbCompatMapNotify;
58405b261ecSmrg		pEv->deviceID = kbd->id;
58505b261ecSmrg		pEv->time = time = GetTimeInMillis();
58605b261ecSmrg		firstSI= pEv->firstSI;
58705b261ecSmrg		nSI= pEv->nSI;
58805b261ecSmrg		nTotalSI= pEv->nTotalSI;
58905b261ecSmrg		initialized= 1;
59005b261ecSmrg	    }
59105b261ecSmrg	    pEv->sequenceNumber = interest->client->sequence;
59205b261ecSmrg	    pEv->time = time;
59305b261ecSmrg	    pEv->firstSI = firstSI;
59405b261ecSmrg	    pEv->nSI = nSI;
59505b261ecSmrg	    pEv->nTotalSI = nTotalSI;
59605b261ecSmrg	    if ( interest->client->swapped ) {
59705b261ecSmrg		register int n;
59805b261ecSmrg		swaps(&pEv->sequenceNumber,n);
59905b261ecSmrg		swapl(&pEv->time,n);
60005b261ecSmrg		swaps(&pEv->firstSI,n);
60105b261ecSmrg		swaps(&pEv->nSI,n);
60205b261ecSmrg		swaps(&pEv->nTotalSI,n);
60305b261ecSmrg	    }
60405b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
60505b261ecSmrg	}
60605b261ecSmrg	interest= interest->next;
60705b261ecSmrg    }
60805b261ecSmrg    return;
60905b261ecSmrg}
61005b261ecSmrg
61105b261ecSmrgvoid
61205b261ecSmrgXkbSendActionMessage(DeviceIntPtr kbd,xkbActionMessage *pEv)
61305b261ecSmrg{
61405b261ecSmrgint		 initialized;
61505b261ecSmrgXkbSrvInfoPtr	 xkbi;
61605b261ecSmrgXkbInterestPtr	 interest;
61705b261ecSmrgTime 		 time = 0;
61805b261ecSmrg
61905b261ecSmrg    xkbi = kbd->key->xkbInfo;
62005b261ecSmrg    interest = kbd->xkb_interest;
62105b261ecSmrg    if (!interest)
62205b261ecSmrg	return;
62305b261ecSmrg
62405b261ecSmrg    initialized = 0;
62505b261ecSmrg    pEv->mods= xkbi->state.mods;
62605b261ecSmrg    pEv->group= xkbi->state.group;
62705b261ecSmrg    while (interest) {
62805b261ecSmrg	if ((!interest->client->clientGone) &&
62905b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
63005b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
63105b261ecSmrg	    (interest->actionMessageMask)) {
63205b261ecSmrg	    if (!initialized) {
63305b261ecSmrg		pEv->type = XkbEventCode + XkbEventBase;
63405b261ecSmrg		pEv->xkbType = XkbActionMessage;
63505b261ecSmrg		pEv->deviceID = kbd->id;
63605b261ecSmrg		pEv->sequenceNumber = interest->client->sequence;
63705b261ecSmrg		pEv->time = time = GetTimeInMillis();
63805b261ecSmrg		initialized= 1;
63905b261ecSmrg	    }
64005b261ecSmrg	    pEv->sequenceNumber = interest->client->sequence;
64105b261ecSmrg	    pEv->time = time;
64205b261ecSmrg	    if ( interest->client->swapped ) {
64305b261ecSmrg		register int n;
64405b261ecSmrg		swaps(&pEv->sequenceNumber,n);
64505b261ecSmrg		swapl(&pEv->time,n);
64605b261ecSmrg	    }
64705b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
64805b261ecSmrg	}
64905b261ecSmrg	interest= interest->next;
65005b261ecSmrg    }
65105b261ecSmrg    return;
65205b261ecSmrg}
65305b261ecSmrg
65405b261ecSmrgvoid
65505b261ecSmrgXkbSendExtensionDeviceNotify(	DeviceIntPtr 			dev,
65605b261ecSmrg				ClientPtr			client,
65705b261ecSmrg				xkbExtensionDeviceNotify *	pEv)
65805b261ecSmrg{
65905b261ecSmrgint		 initialized;
66005b261ecSmrgXkbInterestPtr	 interest;
66105b261ecSmrgTime 		 time = 0;
66205b261ecSmrgCARD32		 defined, state;
66305b261ecSmrgCARD16		 reason, supported = 0;
66405b261ecSmrg
66505b261ecSmrg    interest = dev->xkb_interest;
66605b261ecSmrg    if (!interest)
66705b261ecSmrg	return;
66805b261ecSmrg
66905b261ecSmrg    initialized = 0;
67005b261ecSmrg    reason= pEv->reason;
67105b261ecSmrg    defined= pEv->ledsDefined;
67205b261ecSmrg    state= pEv->ledState;
67305b261ecSmrg    while (interest) {
67405b261ecSmrg	if ((!interest->client->clientGone) &&
67505b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
67605b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
67705b261ecSmrg	    (interest->extDevNotifyMask&reason)) {
67805b261ecSmrg	    if (!initialized) {
67905b261ecSmrg		pEv->type = XkbEventCode + XkbEventBase;
68005b261ecSmrg		pEv->xkbType = XkbExtensionDeviceNotify;
68105b261ecSmrg		pEv->deviceID = dev->id;
68205b261ecSmrg		pEv->sequenceNumber = interest->client->sequence;
68305b261ecSmrg		pEv->time = time = GetTimeInMillis();
68405b261ecSmrg		supported= pEv->supported;
68505b261ecSmrg		initialized= 1;
68605b261ecSmrg	    }
68705b261ecSmrg	    else {
68805b261ecSmrg		pEv->sequenceNumber = interest->client->sequence;
68905b261ecSmrg		pEv->time = time;
69005b261ecSmrg		pEv->ledsDefined= defined;
69105b261ecSmrg		pEv->ledState= state;
69205b261ecSmrg		pEv->reason= reason;
69305b261ecSmrg		pEv->supported= supported;
69405b261ecSmrg	    }
69505b261ecSmrg	    if (client!=interest->client) {
69605b261ecSmrg		/* only report UnsupportedFeature to the client that */
69705b261ecSmrg		/* issued the failing request */
69805b261ecSmrg		pEv->reason&= ~XkbXI_UnsupportedFeatureMask;
69905b261ecSmrg		if ((interest->extDevNotifyMask&reason)==0)
70005b261ecSmrg		    continue;
70105b261ecSmrg	    }
70205b261ecSmrg	    if ( interest->client->swapped ) {
70305b261ecSmrg		register int n;
70405b261ecSmrg		swaps(&pEv->sequenceNumber,n);
70505b261ecSmrg		swapl(&pEv->time,n);
70605b261ecSmrg		swapl(&pEv->ledsDefined,n);
70705b261ecSmrg		swapl(&pEv->ledState,n);
70805b261ecSmrg		swaps(&pEv->reason,n);
70905b261ecSmrg		swaps(&pEv->supported,n);
71005b261ecSmrg	    }
71105b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
71205b261ecSmrg	}
71305b261ecSmrg	interest= interest->next;
71405b261ecSmrg    }
71505b261ecSmrg    return;
71605b261ecSmrg}
71705b261ecSmrg
71805b261ecSmrgvoid
71905b261ecSmrgXkbSendNotification(	DeviceIntPtr		kbd,
72005b261ecSmrg			XkbChangesPtr		pChanges,
72105b261ecSmrg			XkbEventCausePtr	cause)
72205b261ecSmrg{
72305b261ecSmrgXkbSrvLedInfoPtr	sli;
72405b261ecSmrg
72505b261ecSmrg    sli= NULL;
72605b261ecSmrg    if (pChanges->state_changes) {
72705b261ecSmrg	xkbStateNotify sn;
72805b261ecSmrg	sn.changed= pChanges->state_changes;
72905b261ecSmrg	sn.keycode= cause->kc;
73005b261ecSmrg	sn.eventType= cause->event;
73105b261ecSmrg	sn.requestMajor= cause->mjr;
73205b261ecSmrg	sn.requestMinor= cause->mnr;
73305b261ecSmrg	XkbSendStateNotify(kbd,&sn);
73405b261ecSmrg    }
73505b261ecSmrg    if (pChanges->map.changed) {
73605b261ecSmrg	xkbMapNotify mn;
73705b261ecSmrg	mn.changed= pChanges->map.changed;
73805b261ecSmrg	mn.firstType= pChanges->map.first_type;
73905b261ecSmrg	mn.nTypes= pChanges->map.num_types;
74005b261ecSmrg	mn.firstKeySym= pChanges->map.first_key_sym;
74105b261ecSmrg	mn.nKeySyms= pChanges->map.num_key_syms;
74205b261ecSmrg	mn.firstKeyAct= pChanges->map.first_key_act;
74305b261ecSmrg	mn.nKeyActs= pChanges->map.num_key_acts;
74405b261ecSmrg	mn.firstKeyBehavior= pChanges->map.first_key_behavior;
74505b261ecSmrg	mn.nKeyBehaviors= pChanges->map.num_key_behaviors;
74605b261ecSmrg	mn.virtualMods= pChanges->map.vmods;
74705b261ecSmrg	mn.firstKeyExplicit= pChanges->map.first_key_explicit;
74805b261ecSmrg	mn.nKeyExplicit= pChanges->map.num_key_explicit;
74905b261ecSmrg	mn.firstModMapKey= pChanges->map.first_modmap_key;
75005b261ecSmrg	mn.nModMapKeys= pChanges->map.num_modmap_keys;
75105b261ecSmrg	mn.firstVModMapKey= pChanges->map.first_vmodmap_key;
75205b261ecSmrg	mn.nVModMapKeys= pChanges->map.num_vmodmap_keys;
75305b261ecSmrg	XkbSendMapNotify(kbd,&mn);
75405b261ecSmrg    }
75505b261ecSmrg    if ((pChanges->ctrls.changed_ctrls)||
75605b261ecSmrg	(pChanges->ctrls.enabled_ctrls_changes)) {
75705b261ecSmrg	xkbControlsNotify cn;
75805b261ecSmrg	cn.changedControls= pChanges->ctrls.changed_ctrls;
75905b261ecSmrg	cn.enabledControlChanges= pChanges->ctrls.enabled_ctrls_changes;
76005b261ecSmrg	cn.keycode= cause->kc;
76105b261ecSmrg	cn.eventType= cause->event;
76205b261ecSmrg	cn.requestMajor= cause->mjr;
76305b261ecSmrg	cn.requestMinor= cause->mnr;
76405b261ecSmrg	XkbSendControlsNotify(kbd,&cn);
76505b261ecSmrg    }
76605b261ecSmrg    if (pChanges->indicators.map_changes) {
76705b261ecSmrg	xkbIndicatorNotify in;
76805b261ecSmrg	if (sli==NULL)
76905b261ecSmrg	    sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
77005b261ecSmrg	in.state= sli->effectiveState;
77105b261ecSmrg	in.changed= pChanges->indicators.map_changes;
77205b261ecSmrg	XkbSendIndicatorNotify(kbd,XkbIndicatorMapNotify,&in);
77305b261ecSmrg    }
77405b261ecSmrg    if (pChanges->indicators.state_changes) {
77505b261ecSmrg	xkbIndicatorNotify in;
77605b261ecSmrg	if (sli==NULL)
77705b261ecSmrg	    sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
77805b261ecSmrg	in.state= sli->effectiveState;
77905b261ecSmrg	in.changed= pChanges->indicators.state_changes;
78005b261ecSmrg	XkbSendIndicatorNotify(kbd,XkbIndicatorStateNotify,&in);
78105b261ecSmrg    }
78205b261ecSmrg    if (pChanges->names.changed) {
78305b261ecSmrg	xkbNamesNotify nn;
78405b261ecSmrg	nn.changed= pChanges->names.changed;
78505b261ecSmrg	nn.firstType= pChanges->names.first_type;
78605b261ecSmrg	nn.nTypes= pChanges->names.num_types;
78705b261ecSmrg	nn.firstLevelName= pChanges->names.first_lvl;
78805b261ecSmrg	nn.nLevelNames= pChanges->names.num_lvls;
78905b261ecSmrg	nn.nRadioGroups= pChanges->names.num_rg;
79005b261ecSmrg	nn.changedVirtualMods= pChanges->names.changed_vmods;
79105b261ecSmrg	nn.changedIndicators= pChanges->names.changed_indicators;
79205b261ecSmrg	XkbSendNamesNotify(kbd,&nn);
79305b261ecSmrg    }
79405b261ecSmrg    if ((pChanges->compat.changed_groups)||(pChanges->compat.num_si>0)) {
79505b261ecSmrg	xkbCompatMapNotify cmn;
79605b261ecSmrg	cmn.changedGroups= pChanges->compat.changed_groups;
79705b261ecSmrg	cmn.firstSI= pChanges->compat.first_si;
79805b261ecSmrg	cmn.nSI= pChanges->compat.num_si;
79905b261ecSmrg	cmn.nTotalSI= kbd->key->xkbInfo->desc->compat->num_si;
80005b261ecSmrg	XkbSendCompatMapNotify(kbd,&cmn);
80105b261ecSmrg    }
80205b261ecSmrg    return;
80305b261ecSmrg}
80405b261ecSmrg
80505b261ecSmrg/***====================================================================***/
80605b261ecSmrg
80705b261ecSmrgBool
80805b261ecSmrgXkbFilterEvents(ClientPtr pClient,int nEvents,xEvent *xE)
80905b261ecSmrg{
81005b261ecSmrgint	i, button_mask;
81105b261ecSmrgDeviceIntPtr pXDev = (DeviceIntPtr)LookupKeyboardDevice();
81205b261ecSmrgXkbSrvInfoPtr	xkbi;
81305b261ecSmrg
81405b261ecSmrg    xkbi= pXDev->key->xkbInfo;
81505b261ecSmrg    if ( pClient->xkbClientFlags & _XkbClientInitialized ) {
81605b261ecSmrg#ifdef DEBUG
81705b261ecSmrg	if ((xkbDebugFlags&0x10)&&
81805b261ecSmrg		((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease)||
81905b261ecSmrg                 (xE[0].u.u.type==DeviceKeyPress)||
82005b261ecSmrg                 (xE[0].u.u.type == DeviceKeyRelease))) {
82105b261ecSmrg	    ErrorF("XKbFilterWriteEvents:\n");
82205b261ecSmrg	    ErrorF("   Event state= 0x%04x\n",xE[0].u.keyButtonPointer.state);
82305b261ecSmrg	    ErrorF("   XkbLastRepeatEvent!=xE (0x%p!=0x%p) %s\n",
82405b261ecSmrg			XkbLastRepeatEvent,xE,
82505b261ecSmrg			((XkbLastRepeatEvent!=(pointer)xE)?"True":"False"));
82605b261ecSmrg	    ErrorF("   (xkbClientEventsFlags&XWDA)==0 (0x%x) %s\n",
82705b261ecSmrg		pClient->xkbClientFlags,
82805b261ecSmrg		(_XkbWantsDetectableAutoRepeat(pClient)?"True":"False"));
82905b261ecSmrg	    ErrorF("   !IsRelease(%d) %s\n",xE[0].u.u.type,
83005b261ecSmrg			(!_XkbIsReleaseEvent(xE[0].u.u.type))?"True":"False");
83105b261ecSmrg	}
83205b261ecSmrg#endif /* DEBUG */
83305b261ecSmrg	if (	(XkbLastRepeatEvent==(pointer)xE) &&
83405b261ecSmrg	     	(_XkbWantsDetectableAutoRepeat(pClient)) &&
83505b261ecSmrg	     	(_XkbIsReleaseEvent(xE[0].u.u.type)) ) {
83605b261ecSmrg	    return False;
83705b261ecSmrg	}
83805b261ecSmrg	if ((pXDev->grab != NullGrab) && pXDev->fromPassiveGrab &&
83905b261ecSmrg	    ((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease)||
84005b261ecSmrg             (xE[0].u.u.type==DeviceKeyPress)||
84105b261ecSmrg             (xE[0].u.u.type == DeviceKeyRelease))) {
84205b261ecSmrg	    register unsigned state,flags;
84305b261ecSmrg
84405b261ecSmrg	    flags= pClient->xkbClientFlags;
84505b261ecSmrg	    state= xkbi->state.compat_grab_mods;
84605b261ecSmrg	    if (flags & XkbPCF_GrabsUseXKBStateMask) {
84705b261ecSmrg		int group;
84805b261ecSmrg		if (flags&XkbPCF_LookupStateWhenGrabbed) {
84905b261ecSmrg		     group= xkbi->state.group;
85005b261ecSmrg		     state= xkbi->state.lookup_mods;
85105b261ecSmrg		}
85205b261ecSmrg		else {
85305b261ecSmrg		    state= xkbi->state.grab_mods;
85405b261ecSmrg		    group= xkbi->state.base_group+xkbi->state.latched_group;
85505b261ecSmrg		    if ((group<0)||(group>=xkbi->desc->ctrls->num_groups)) {
85605b261ecSmrg			group= XkbAdjustGroup(group,xkbi->desc->ctrls);
85705b261ecSmrg		    }
85805b261ecSmrg		}
85905b261ecSmrg		state = XkbBuildCoreState(state, group);
86005b261ecSmrg	    }
86105b261ecSmrg	    else if (flags&XkbPCF_LookupStateWhenGrabbed)
86205b261ecSmrg		state= xkbi->state.compat_lookup_mods;
86305b261ecSmrg	    xE[0].u.keyButtonPointer.state= state;
86405b261ecSmrg	}
86505b261ecSmrg	button_mask = 1 << xE[0].u.u.detail;
86605b261ecSmrg	if (xE[0].u.u.type == ButtonPress &&
86705b261ecSmrg	    ((xE[0].u.keyButtonPointer.state >> 7) & button_mask) == button_mask &&
86805b261ecSmrg	    (xkbi->lockedPtrButtons & button_mask) == button_mask) {
86905b261ecSmrg#ifdef DEBUG
87005b261ecSmrg	    /* If the MouseKeys is pressed, and the "real" mouse is also pressed
87105b261ecSmrg	     * when the mouse is released, the server does not behave properly.
87205b261ecSmrg	     * Faking a release of the button here solves the problem.
87305b261ecSmrg	     */
87405b261ecSmrg	    ErrorF("Faking release of button %d\n", xE[0].u.u.detail);
87505b261ecSmrg#endif
87605b261ecSmrg	    XkbDDXFakePointerButton(ButtonRelease, xE[0].u.u.detail);
87705b261ecSmrg        }
87805b261ecSmrg    }
87905b261ecSmrg    else {
88005b261ecSmrg	register CARD8 	type;
88105b261ecSmrg
88205b261ecSmrg	for (i=0;i<nEvents;i++) {
88305b261ecSmrg	    type= xE[i].u.u.type;
88405b261ecSmrg#ifdef DEBUG
88505b261ecSmrg	    if ((xkbDebugFlags&0x4)&&
88605b261ecSmrg		((xE[i].u.u.type==KeyPress)||(xE[i].u.u.type==KeyRelease)||
88705b261ecSmrg                 (xE[i].u.u.type==DeviceKeyPress)||
88805b261ecSmrg                 (xE[i].u.u.type == DeviceKeyRelease))) {
88905b261ecSmrg		XkbStatePtr s= &xkbi->state;
89005b261ecSmrg		ErrorF("XKbFilterWriteEvents (non-XKB):\n");
89105b261ecSmrg		ErrorF("event= 0x%04x\n",xE[i].u.keyButtonPointer.state);
89205b261ecSmrg		ErrorF("lookup= 0x%02x, grab= 0x%02x\n",s->lookup_mods,
89305b261ecSmrg							s->grab_mods);
89405b261ecSmrg		ErrorF("compat lookup= 0x%02x, grab= 0x%02x\n",
89505b261ecSmrg							s->compat_lookup_mods,
89605b261ecSmrg							s->compat_grab_mods);
89705b261ecSmrg	    }
89805b261ecSmrg#endif
89905b261ecSmrg	    if ( (type>=KeyPress)&&(type<=MotionNotify) ) {
90005b261ecSmrg		CARD16	old,new;
90105b261ecSmrg
90205b261ecSmrg		old= xE[i].u.keyButtonPointer.state&(~0x1f00);
90305b261ecSmrg		new= xE[i].u.keyButtonPointer.state&0x1F00;
90405b261ecSmrg
90505b261ecSmrg		if (old==XkbStateFieldFromRec(&xkbi->state))
90605b261ecSmrg		     new|= xkbi->state.compat_lookup_mods;
90705b261ecSmrg		else new|= xkbi->state.compat_grab_mods;
90805b261ecSmrg		xE[i].u.keyButtonPointer.state= new;
90905b261ecSmrg	    }
91005b261ecSmrg	    else if ((type==EnterNotify)||(type==LeaveNotify)) {
91105b261ecSmrg		xE[i].u.enterLeave.state&= 0x1F00;
91205b261ecSmrg		xE[i].u.enterLeave.state|= xkbi->state.compat_grab_mods;
91305b261ecSmrg	    } else if ((type>=DeviceKeyPress)&&(type<=DeviceMotionNotify)) {
91405b261ecSmrg                CARD16  old, new;
91505b261ecSmrg                deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer*)&xE[i];
91605b261ecSmrg                old= kbp->state&(~0x1F00);
91705b261ecSmrg                new= kbp->state&0x1F00;
91805b261ecSmrg		if (old==XkbStateFieldFromRec(&xkbi->state))
91905b261ecSmrg		     new|= xkbi->state.compat_lookup_mods;
92005b261ecSmrg		else new|= xkbi->state.compat_grab_mods;
92105b261ecSmrg                kbp->state= new;
92205b261ecSmrg            }
92305b261ecSmrg	    button_mask = 1 << xE[i].u.u.detail;
92405b261ecSmrg	    if (type == ButtonPress &&
92505b261ecSmrg		((xE[i].u.keyButtonPointer.state >> 7) & button_mask) == button_mask &&
92605b261ecSmrg		(xkbi->lockedPtrButtons & button_mask) == button_mask) {
92705b261ecSmrg#ifdef DEBUG
92805b261ecSmrg		ErrorF("Faking release of button %d\n", xE[i].u.u.detail);
92905b261ecSmrg#endif
93005b261ecSmrg		XkbDDXFakePointerButton(ButtonRelease, xE[i].u.u.detail);
93105b261ecSmrg	    } else if (type == DeviceButtonPress &&
93205b261ecSmrg                    ((((deviceKeyButtonPointer*)&xE[i])->state >> 7) & button_mask) == button_mask &&
93305b261ecSmrg                    (xkbi->lockedPtrButtons & button_mask) == button_mask) {
93405b261ecSmrg#ifdef DEBUG
93505b261ecSmrg		ErrorF("Faking release of button %d\n", ((deviceKeyButtonPointer*)&xE[i])->state);
93605b261ecSmrg#endif
93705b261ecSmrg		XkbDDXFakePointerButton(DeviceButtonRelease, ((deviceKeyButtonPointer*)&xE[i])->state);
93805b261ecSmrg            }
93905b261ecSmrg	}
94005b261ecSmrg    }
94105b261ecSmrg    return True;
94205b261ecSmrg}
94305b261ecSmrg
94405b261ecSmrg/***====================================================================***/
94505b261ecSmrg
94605b261ecSmrgXkbInterestPtr
94705b261ecSmrgXkbFindClientResource(DevicePtr inDev,ClientPtr client)
94805b261ecSmrg{
94905b261ecSmrgDeviceIntPtr	dev = (DeviceIntPtr)inDev;
95005b261ecSmrgXkbInterestPtr	interest;
95105b261ecSmrg
95205b261ecSmrg    if ( dev->xkb_interest ) {
95305b261ecSmrg	interest = dev->xkb_interest;
95405b261ecSmrg	while (interest){
95505b261ecSmrg	    if (interest->client==client) {
95605b261ecSmrg		return interest;
95705b261ecSmrg	    }
95805b261ecSmrg	    interest = interest->next;
95905b261ecSmrg	}
96005b261ecSmrg    }
96105b261ecSmrg    return NULL;
96205b261ecSmrg}
96305b261ecSmrg
96405b261ecSmrgXkbInterestPtr
96505b261ecSmrgXkbAddClientResource(DevicePtr inDev,ClientPtr client,XID id)
96605b261ecSmrg{
96705b261ecSmrgDeviceIntPtr	dev = (DeviceIntPtr)inDev;
96805b261ecSmrgXkbInterestPtr	interest;
96905b261ecSmrg
97005b261ecSmrg    interest = dev->xkb_interest;
97105b261ecSmrg    while (interest) {
97205b261ecSmrg	if (interest->client==client)
97305b261ecSmrg	    return ((interest->resource==id)?interest:NULL);
97405b261ecSmrg	interest = interest->next;
97505b261ecSmrg    }
97605b261ecSmrg    interest = _XkbTypedAlloc(XkbInterestRec);
97705b261ecSmrg    bzero(interest,sizeof(XkbInterestRec));
97805b261ecSmrg    if (interest) {
97905b261ecSmrg	interest->dev = dev;
98005b261ecSmrg	interest->client = client;
98105b261ecSmrg	interest->resource = id;
98205b261ecSmrg	interest->stateNotifyMask= 0;
98305b261ecSmrg	interest->ctrlsNotifyMask= 0;
98405b261ecSmrg	interest->namesNotifyMask= 0;
98505b261ecSmrg	interest->compatNotifyMask= 0;
98605b261ecSmrg	interest->bellNotifyMask= FALSE;
98705b261ecSmrg	interest->accessXNotifyMask= 0;
98805b261ecSmrg	interest->iStateNotifyMask= 0;
98905b261ecSmrg	interest->iMapNotifyMask= 0;
99005b261ecSmrg	interest->altSymsNotifyMask= 0;
99105b261ecSmrg	interest->next = dev->xkb_interest;
99205b261ecSmrg	dev->xkb_interest= interest;
99305b261ecSmrg	return interest;
99405b261ecSmrg    }
99505b261ecSmrg    return NULL;
99605b261ecSmrg}
99705b261ecSmrg
99805b261ecSmrgint
99905b261ecSmrgXkbRemoveResourceClient(DevicePtr inDev,XID id)
100005b261ecSmrg{
100105b261ecSmrgXkbSrvInfoPtr	xkbi;
100205b261ecSmrgDeviceIntPtr	dev = (DeviceIntPtr)inDev;
100305b261ecSmrgXkbInterestPtr	interest;
100405b261ecSmrgBool		found;
100505b261ecSmrgunsigned long	autoCtrls,autoValues;
100605b261ecSmrgClientPtr	client = NULL;
100705b261ecSmrg
100805b261ecSmrg    found= False;
100905b261ecSmrg    autoCtrls= autoValues= 0;
101005b261ecSmrg    if ( dev->xkb_interest ) {
101105b261ecSmrg	interest = dev->xkb_interest;
101205b261ecSmrg	if (interest && (interest->resource==id)){
101305b261ecSmrg	    dev->xkb_interest = interest->next;
101405b261ecSmrg	    autoCtrls= interest->autoCtrls;
101505b261ecSmrg	    autoValues= interest->autoCtrlValues;
101605b261ecSmrg	    client= interest->client;
101705b261ecSmrg	    _XkbFree(interest);
101805b261ecSmrg	    found= True;
101905b261ecSmrg	}
102005b261ecSmrg	while ((!found)&&(interest->next)) {
102105b261ecSmrg	    if (interest->next->resource==id) {
102205b261ecSmrg		XkbInterestPtr	victim = interest->next;
102305b261ecSmrg		interest->next = victim->next;
102405b261ecSmrg		autoCtrls= victim->autoCtrls;
102505b261ecSmrg		autoValues= victim->autoCtrlValues;
102605b261ecSmrg		client= victim->client;
102705b261ecSmrg		_XkbFree(victim);
102805b261ecSmrg		found= True;
102905b261ecSmrg	    }
103005b261ecSmrg	    interest = interest->next;
103105b261ecSmrg	}
103205b261ecSmrg    }
103305b261ecSmrg    if (found && autoCtrls && dev->key && dev->key->xkbInfo ) {
103405b261ecSmrg	XkbEventCauseRec cause;
103505b261ecSmrg
103605b261ecSmrg	xkbi= dev->key->xkbInfo;
103705b261ecSmrg	XkbSetCauseXkbReq(&cause,X_kbPerClientFlags,client);
103805b261ecSmrg	XkbEnableDisableControls(xkbi,autoCtrls,autoValues,NULL,&cause);
103905b261ecSmrg    }
104005b261ecSmrg    return found;
104105b261ecSmrg}
1042