xkbEvents.c revision 6747b715
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#include <X11/X.h>
3305b261ecSmrg#include <X11/Xproto.h>
3405b261ecSmrg#include <X11/keysym.h>
3505b261ecSmrg#include <X11/extensions/XI.h>
3605b261ecSmrg#include <X11/extensions/XIproto.h>
3705b261ecSmrg#include "inputstr.h"
386747b715Smrg#include "exevents.h"
396747b715Smrg#include "exglobals.h"
4005b261ecSmrg#include "windowstr.h"
414642e01fSmrg#include "exevents.h"
4205b261ecSmrg#include <xkbsrv.h>
4305b261ecSmrg#include "xkb.h"
4405b261ecSmrg
4505b261ecSmrg/***====================================================================***/
4605b261ecSmrg
476747b715Smrg/*
486747b715Smrg * This function sends out two kinds of notification:
496747b715Smrg *   - Core mapping notify events sent to clients for whom kbd is the
506747b715Smrg *     current core ('picked') keyboard _and_ have not explicitly
516747b715Smrg *     selected for XKB mapping notify events;
526747b715Smrg *   - Xi mapping events, sent unconditionally to all clients who have
536747b715Smrg *     explicitly selected for them (including those who have explicitly
546747b715Smrg *     selected for XKB mapping notify events!).
556747b715Smrg */
566747b715Smrgstatic void
576747b715SmrgXkbSendLegacyMapNotify(DeviceIntPtr kbd, CARD16 xkb_event, CARD16 changed,
586747b715Smrg                       int first_key, int num_keys)
596747b715Smrg{
606747b715Smrg    int i;
616747b715Smrg    int keymap_changed = 0;
626747b715Smrg    int modmap_changed = 0;
636747b715Smrg    xEvent core_mn;
646747b715Smrg    deviceMappingNotify xi_mn;
656747b715Smrg    CARD32 time = GetTimeInMillis();
666747b715Smrg
676747b715Smrg    if (xkb_event == XkbNewKeyboardNotify) {
686747b715Smrg        if (changed & XkbNKN_KeycodesMask) {
696747b715Smrg            keymap_changed = 1;
706747b715Smrg            modmap_changed = 1;
716747b715Smrg        }
726747b715Smrg    }
736747b715Smrg    else if (xkb_event == XkbMapNotify) {
746747b715Smrg        if (changed & XkbKeySymsMask)
756747b715Smrg            keymap_changed = 1;
766747b715Smrg        if (changed & XkbModifierMapMask)
776747b715Smrg            modmap_changed = 1;
786747b715Smrg    }
796747b715Smrg    if (!keymap_changed && !modmap_changed)
806747b715Smrg        return;
816747b715Smrg
826747b715Smrg    core_mn.u.u.type = MappingNotify;
836747b715Smrg    xi_mn.type = DeviceMappingNotify;
846747b715Smrg    xi_mn.deviceid = kbd->id;
856747b715Smrg    xi_mn.time = time;
866747b715Smrg
876747b715Smrg    /* 0 is serverClient. */
886747b715Smrg    for (i = 1; i < currentMaxClients; i++) {
896747b715Smrg        if (!clients[i] || clients[i]->clientState != ClientStateRunning)
906747b715Smrg            continue;
916747b715Smrg
926747b715Smrg        /* Ignore clients which will have already received this.
936747b715Smrg         * Inconsistent with themselves, but consistent with previous
946747b715Smrg         * behaviour.*/
956747b715Smrg        if (xkb_event == XkbMapNotify && (clients[i]->mapNotifyMask & changed))
966747b715Smrg            continue;
976747b715Smrg        if (xkb_event == XkbNewKeyboardNotify &&
986747b715Smrg            (clients[i]->xkbClientFlags & _XkbClientInitialized))
996747b715Smrg            continue;
1006747b715Smrg
1016747b715Smrg        /* Don't send core events to clients who don't know about us. */
1026747b715Smrg        if (!XIShouldNotify(clients[i], kbd))
1036747b715Smrg            continue;
1046747b715Smrg
1056747b715Smrg        if (keymap_changed) {
1066747b715Smrg            core_mn.u.mappingNotify.request = MappingKeyboard;
1076747b715Smrg
1086747b715Smrg            /* Clip the keycode range to what the client knows about, so it
1096747b715Smrg             * doesn't freak out. */
1106747b715Smrg            if (first_key >= clients[i]->minKC)
1116747b715Smrg                core_mn.u.mappingNotify.firstKeyCode = first_key;
1126747b715Smrg            else
1136747b715Smrg                core_mn.u.mappingNotify.firstKeyCode = clients[i]->minKC;
1146747b715Smrg            if (first_key + num_keys - 1 <= clients[i]->maxKC)
1156747b715Smrg                core_mn.u.mappingNotify.count = num_keys;
1166747b715Smrg            else
1176747b715Smrg                core_mn.u.mappingNotify.count = clients[i]->maxKC -
1186747b715Smrg                                                 clients[i]->minKC + 1;
1196747b715Smrg
1206747b715Smrg            WriteEventsToClient(clients[i], 1, &core_mn);
1216747b715Smrg        }
1226747b715Smrg        if (modmap_changed) {
1236747b715Smrg            core_mn.u.mappingNotify.request = MappingModifier;
1246747b715Smrg            core_mn.u.mappingNotify.firstKeyCode = 0;
1256747b715Smrg            core_mn.u.mappingNotify.count = 0;
1266747b715Smrg            WriteEventsToClient(clients[i], 1, &core_mn);
1276747b715Smrg        }
1286747b715Smrg    }
1296747b715Smrg
1306747b715Smrg    /* Hmm, maybe we can accidentally generate Xi events for core devices
1316747b715Smrg     * here? Clients might be upset, but that seems better than the
1326747b715Smrg     * alternative of stale keymaps. -ds */
1336747b715Smrg    if (keymap_changed) {
1346747b715Smrg        xi_mn.request = MappingKeyboard;
1356747b715Smrg        xi_mn.firstKeyCode = first_key;
1366747b715Smrg        xi_mn.count = num_keys;
1376747b715Smrg        SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn,
1386747b715Smrg                              1);
1396747b715Smrg    }
1406747b715Smrg    if (modmap_changed) {
1416747b715Smrg        xi_mn.request = MappingModifier;
1426747b715Smrg        xi_mn.firstKeyCode = 0;
1436747b715Smrg        xi_mn.count = 0;
1446747b715Smrg        SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn,
1456747b715Smrg                              1);
1466747b715Smrg    }
1476747b715Smrg}
1486747b715Smrg
1496747b715Smrg/***====================================================================***/
1506747b715Smrg
15105b261ecSmrgvoid
15205b261ecSmrgXkbSendNewKeyboardNotify(DeviceIntPtr kbd,xkbNewKeyboardNotify *pNKN)
1536747b715Smrg{
1546747b715Smrg    int i;
1556747b715Smrg    Time time = GetTimeInMillis();
1566747b715Smrg    CARD16 changed = pNKN->changed;
15705b261ecSmrg
15805b261ecSmrg    pNKN->type = XkbEventCode + XkbEventBase;
15905b261ecSmrg    pNKN->xkbType = XkbNewKeyboardNotify;
16005b261ecSmrg
16105b261ecSmrg    for (i=1; i<currentMaxClients; i++) {
1626747b715Smrg        if (!clients[i] || clients[i]->clientState != ClientStateRunning)
1636747b715Smrg            continue;
1646747b715Smrg
1656747b715Smrg        if (!(clients[i]->newKeyboardNotifyMask & changed))
1666747b715Smrg            continue;
1676747b715Smrg
1686747b715Smrg        if (!XIShouldNotify(clients[i], kbd))
1696747b715Smrg            continue;
1706747b715Smrg
1716747b715Smrg        pNKN->sequenceNumber = clients[i]->sequence;
1726747b715Smrg        pNKN->time = time;
1736747b715Smrg        pNKN->changed = changed;
1746747b715Smrg        if (clients[i]->swapped) {
1756747b715Smrg            int n;
1766747b715Smrg            swaps(&pNKN->sequenceNumber,n);
1776747b715Smrg            swapl(&pNKN->time,n);
1786747b715Smrg            swaps(&pNKN->changed,n);
1796747b715Smrg        }
1806747b715Smrg        WriteToClient(clients[i], sizeof(xEvent), pNKN);
18105b261ecSmrg
1826747b715Smrg        if (changed & XkbNKN_KeycodesMask) {
1836747b715Smrg            clients[i]->minKC = pNKN->minKeyCode;
1846747b715Smrg            clients[i]->maxKC = pNKN->maxKeyCode;
1856747b715Smrg        }
18605b261ecSmrg    }
1876747b715Smrg
1886747b715Smrg    XkbSendLegacyMapNotify(kbd, XkbNewKeyboardNotify, changed, pNKN->minKeyCode,
1896747b715Smrg                           pNKN->maxKeyCode - pNKN->minKeyCode + 1);
1906747b715Smrg
19105b261ecSmrg    return;
19205b261ecSmrg}
19305b261ecSmrg
19405b261ecSmrg/***====================================================================***/
19505b261ecSmrg
19605b261ecSmrgvoid
19705b261ecSmrgXkbSendStateNotify(DeviceIntPtr kbd,xkbStateNotify *pSN)
19805b261ecSmrg{
19905b261ecSmrgXkbSrvInfoPtr	xkbi;
20005b261ecSmrgXkbStatePtr	state;
20105b261ecSmrgXkbInterestPtr	interest;
20205b261ecSmrgTime 		time;
20305b261ecSmrgregister CARD16	changed,bState;
20405b261ecSmrg
20505b261ecSmrg    interest = kbd->xkb_interest;
2064642e01fSmrg    if (!interest || !kbd->key || !kbd->key->xkbInfo)
20705b261ecSmrg	return;
20805b261ecSmrg    xkbi = kbd->key->xkbInfo;
20905b261ecSmrg    state= &xkbi->state;
21005b261ecSmrg
21105b261ecSmrg    pSN->type = XkbEventCode + XkbEventBase;
21205b261ecSmrg    pSN->xkbType = XkbStateNotify;
21305b261ecSmrg    pSN->deviceID = kbd->id;
21405b261ecSmrg    pSN->time = time = GetTimeInMillis();
21505b261ecSmrg    pSN->mods = state->mods;
21605b261ecSmrg    pSN->baseMods = state->base_mods;
21705b261ecSmrg    pSN->latchedMods = state->latched_mods;
21805b261ecSmrg    pSN->lockedMods = state->locked_mods;
21905b261ecSmrg    pSN->group = state->group;
22005b261ecSmrg    pSN->baseGroup = state->base_group;
22105b261ecSmrg    pSN->latchedGroup = state->latched_group;
22205b261ecSmrg    pSN->lockedGroup = state->locked_group;
22305b261ecSmrg    pSN->compatState = state->compat_state;
22405b261ecSmrg    pSN->grabMods = state->grab_mods;
22505b261ecSmrg    pSN->compatGrabMods = state->compat_grab_mods;
22605b261ecSmrg    pSN->lookupMods = state->lookup_mods;
22705b261ecSmrg    pSN->compatLookupMods = state->compat_lookup_mods;
22805b261ecSmrg    pSN->ptrBtnState = state->ptr_buttons;
22905b261ecSmrg    changed = pSN->changed;
23005b261ecSmrg    bState= pSN->ptrBtnState;
23105b261ecSmrg
23205b261ecSmrg    while (interest) {
23305b261ecSmrg	if ((!interest->client->clientGone) &&
23405b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
23505b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
2366747b715Smrg	    (interest->stateNotifyMask&changed) &&
2376747b715Smrg            XIShouldNotify(interest->client,kbd)) {
23805b261ecSmrg	    pSN->sequenceNumber = interest->client->sequence;
23905b261ecSmrg	    pSN->time = time;
24005b261ecSmrg	    pSN->changed = changed;
24105b261ecSmrg	    pSN->ptrBtnState = bState;
24205b261ecSmrg	    if ( interest->client->swapped ) {
24305b261ecSmrg		register int n;
24405b261ecSmrg		swaps(&pSN->sequenceNumber,n);
24505b261ecSmrg		swapl(&pSN->time,n);
24605b261ecSmrg		swaps(&pSN->changed,n);
24705b261ecSmrg		swaps(&pSN->ptrBtnState,n);
24805b261ecSmrg	    }
24905b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pSN);
25005b261ecSmrg	}
25105b261ecSmrg	interest= interest->next;
25205b261ecSmrg    }
25305b261ecSmrg    return;
25405b261ecSmrg}
25505b261ecSmrg
25605b261ecSmrg/***====================================================================***/
25705b261ecSmrg
2586747b715Smrg/*
2596747b715Smrg * This function sends out XKB mapping notify events to clients which
2606747b715Smrg * have explicitly selected for them.  Core and Xi events are handled by
2616747b715Smrg * XkbSendLegacyMapNotify. */
26205b261ecSmrgvoid
2636747b715SmrgXkbSendMapNotify(DeviceIntPtr kbd, xkbMapNotify *pMN)
26405b261ecSmrg{
2656747b715Smrg    int i;
2666747b715Smrg    CARD32 time = GetTimeInMillis();
2676747b715Smrg    CARD16 changed = pMN->changed;
2686747b715Smrg    XkbSrvInfoPtr xkbi = kbd->key->xkbInfo;
2696747b715Smrg
2706747b715Smrg    pMN->minKeyCode = xkbi->desc->min_key_code;
2716747b715Smrg    pMN->maxKeyCode = xkbi->desc->max_key_code;
2726747b715Smrg    pMN->type = XkbEventCode + XkbEventBase;
2736747b715Smrg    pMN->xkbType = XkbMapNotify;
2746747b715Smrg    pMN->deviceID = kbd->id;
2756747b715Smrg
2766747b715Smrg    /* 0 is serverClient. */
2776747b715Smrg    for (i = 1; i < currentMaxClients; i++) {
2786747b715Smrg        if (!clients[i] || clients[i]->clientState != ClientStateRunning)
2796747b715Smrg            continue;
2806747b715Smrg
2816747b715Smrg        if (!(clients[i]->mapNotifyMask & changed))
2826747b715Smrg            continue;
2836747b715Smrg
2846747b715Smrg        if (!XIShouldNotify(clients[i], kbd))
2856747b715Smrg            continue;
2866747b715Smrg
2876747b715Smrg        pMN->time = time;
2886747b715Smrg        pMN->sequenceNumber = clients[i]->sequence;
2896747b715Smrg        pMN->changed = changed;
2906747b715Smrg
2916747b715Smrg        if (clients[i]->swapped) {
2926747b715Smrg            int n;
2936747b715Smrg            swaps(&pMN->sequenceNumber, n);
2946747b715Smrg            swapl(&pMN->time, n);
2956747b715Smrg            swaps(&pMN->changed, n);
2966747b715Smrg        }
2976747b715Smrg        WriteToClient(clients[i], sizeof(xEvent), pMN);
29805b261ecSmrg    }
2996747b715Smrg
3006747b715Smrg    XkbSendLegacyMapNotify(kbd, XkbMapNotify, changed, pMN->firstKeySym,
3016747b715Smrg                           pMN->nKeySyms);
30205b261ecSmrg}
30305b261ecSmrg
30405b261ecSmrgint
30505b261ecSmrgXkbComputeControlsNotify(	DeviceIntPtr	 	kbd,
30605b261ecSmrg				XkbControlsPtr		old,
30705b261ecSmrg				XkbControlsPtr		new,
30805b261ecSmrg				xkbControlsNotify *	pCN,
30905b261ecSmrg				Bool			forceCtrlProc)
31005b261ecSmrg{
31105b261ecSmrgint		i;
31205b261ecSmrgCARD32 		changedControls;
31305b261ecSmrg
31405b261ecSmrg    changedControls= 0;
31505b261ecSmrg
31605b261ecSmrg    if (!kbd || !kbd->kbdfeed)
31705b261ecSmrg        return 0;
31805b261ecSmrg
31905b261ecSmrg    if (old->enabled_ctrls!=new->enabled_ctrls)
32005b261ecSmrg	changedControls|= XkbControlsEnabledMask;
32105b261ecSmrg    if ((old->repeat_delay!=new->repeat_delay)||
32205b261ecSmrg	(old->repeat_interval!=new->repeat_interval))
32305b261ecSmrg	changedControls|= XkbRepeatKeysMask;
32405b261ecSmrg    for (i = 0; i < XkbPerKeyBitArraySize; i++)
32505b261ecSmrg	if (old->per_key_repeat[i] != new->per_key_repeat[i])
32605b261ecSmrg	    changedControls|= XkbPerKeyRepeatMask;
32705b261ecSmrg    if (old->slow_keys_delay!=new->slow_keys_delay)
32805b261ecSmrg	changedControls|= XkbSlowKeysMask;
32905b261ecSmrg    if (old->debounce_delay!=new->debounce_delay)
33005b261ecSmrg	changedControls|= XkbBounceKeysMask;
33105b261ecSmrg    if ((old->mk_delay!=new->mk_delay)||
33205b261ecSmrg	(old->mk_interval!=new->mk_interval)||
33305b261ecSmrg	(old->mk_dflt_btn!=new->mk_dflt_btn))
33405b261ecSmrg	changedControls|= XkbMouseKeysMask;
33505b261ecSmrg    if ((old->mk_time_to_max!=new->mk_time_to_max)||
33605b261ecSmrg	(old->mk_curve!=new->mk_curve)||
33705b261ecSmrg	(old->mk_max_speed!=new->mk_max_speed))
33805b261ecSmrg	changedControls|= XkbMouseKeysAccelMask;
33905b261ecSmrg    if (old->ax_options!=new->ax_options)
34005b261ecSmrg	changedControls|= XkbAccessXKeysMask;
34105b261ecSmrg    if ((old->ax_options^new->ax_options) & XkbAX_SKOptionsMask)
34205b261ecSmrg	changedControls|= XkbStickyKeysMask;
34305b261ecSmrg    if ((old->ax_options^new->ax_options) & XkbAX_FBOptionsMask)
34405b261ecSmrg	changedControls|= XkbAccessXFeedbackMask;
34505b261ecSmrg    if ((old->ax_timeout!=new->ax_timeout)||
34605b261ecSmrg	(old->axt_ctrls_mask!=new->axt_ctrls_mask)||
34705b261ecSmrg	(old->axt_ctrls_values!=new->axt_ctrls_values)||
34805b261ecSmrg	(old->axt_opts_mask!=new->axt_opts_mask)||
34905b261ecSmrg	(old->axt_opts_values!= new->axt_opts_values)) {
35005b261ecSmrg	changedControls|= XkbAccessXTimeoutMask;
35105b261ecSmrg    }
35205b261ecSmrg    if ((old->internal.mask!=new->internal.mask)||
35305b261ecSmrg	(old->internal.real_mods!=new->internal.real_mods)||
35405b261ecSmrg	(old->internal.vmods!=new->internal.vmods))
35505b261ecSmrg	changedControls|= XkbInternalModsMask;
35605b261ecSmrg    if ((old->ignore_lock.mask!=new->ignore_lock.mask)||
35705b261ecSmrg	(old->ignore_lock.real_mods!=new->ignore_lock.real_mods)||
35805b261ecSmrg	(old->ignore_lock.vmods!=new->ignore_lock.vmods))
35905b261ecSmrg	changedControls|= XkbIgnoreLockModsMask;
36005b261ecSmrg
36105b261ecSmrg    if (new->enabled_ctrls&XkbRepeatKeysMask)
36205b261ecSmrg	 kbd->kbdfeed->ctrl.autoRepeat=TRUE;
36305b261ecSmrg    else kbd->kbdfeed->ctrl.autoRepeat=FALSE;
36405b261ecSmrg
36505b261ecSmrg    if (kbd->kbdfeed && kbd->kbdfeed->CtrlProc &&
36605b261ecSmrg	(changedControls || forceCtrlProc))
36705b261ecSmrg	(*kbd->kbdfeed->CtrlProc)(kbd, &kbd->kbdfeed->ctrl);
36805b261ecSmrg
36905b261ecSmrg    if ((!changedControls)&&(old->num_groups==new->num_groups))
37005b261ecSmrg	return 0;
37105b261ecSmrg
37205b261ecSmrg    if (!kbd->xkb_interest)
37305b261ecSmrg	return 0;
37405b261ecSmrg
37505b261ecSmrg    pCN->changedControls = changedControls;
37605b261ecSmrg    pCN->enabledControls = new->enabled_ctrls;
37705b261ecSmrg    pCN->enabledControlChanges = (new->enabled_ctrls^old->enabled_ctrls);
37805b261ecSmrg    pCN->numGroups = new->num_groups;
37905b261ecSmrg
38005b261ecSmrg    return 1;
38105b261ecSmrg}
38205b261ecSmrg
38305b261ecSmrgvoid
38405b261ecSmrgXkbSendControlsNotify(DeviceIntPtr kbd,xkbControlsNotify *pCN)
38505b261ecSmrg{
38605b261ecSmrgint			initialized;
38705b261ecSmrgCARD32 		 	changedControls, enabledControls, enabledChanges = 0;
38805b261ecSmrgXkbSrvInfoPtr		xkbi;
38905b261ecSmrgXkbInterestPtr		interest;
39005b261ecSmrgTime 		 	time = 0;
39105b261ecSmrg
39205b261ecSmrg    interest = kbd->xkb_interest;
3934642e01fSmrg    if (!interest || !kbd->key || !kbd->key->xkbInfo)
39405b261ecSmrg	return;
39505b261ecSmrg    xkbi = kbd->key->xkbInfo;
39605b261ecSmrg
39705b261ecSmrg    initialized = 0;
39805b261ecSmrg    enabledControls = xkbi->desc->ctrls->enabled_ctrls;
39905b261ecSmrg    changedControls = pCN->changedControls;
40005b261ecSmrg    pCN->numGroups= xkbi->desc->ctrls->num_groups;
40105b261ecSmrg    while (interest) {
40205b261ecSmrg	if ((!interest->client->clientGone) &&
40305b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
40405b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
4056747b715Smrg	    (interest->ctrlsNotifyMask&changedControls) &&
4066747b715Smrg            XIShouldNotify(interest->client, kbd)) {
40705b261ecSmrg	    if (!initialized) {
40805b261ecSmrg		pCN->type = XkbEventCode + XkbEventBase;
40905b261ecSmrg		pCN->xkbType = XkbControlsNotify;
41005b261ecSmrg		pCN->deviceID = kbd->id;
41105b261ecSmrg		pCN->time = time = GetTimeInMillis();
41205b261ecSmrg		enabledChanges = pCN->enabledControlChanges;
41305b261ecSmrg		initialized= 1;
41405b261ecSmrg	    }
41505b261ecSmrg	    pCN->changedControls = changedControls;
41605b261ecSmrg	    pCN->enabledControls = enabledControls;
41705b261ecSmrg	    pCN->enabledControlChanges = enabledChanges;
41805b261ecSmrg	    pCN->sequenceNumber = interest->client->sequence;
41905b261ecSmrg	    pCN->time = time;
42005b261ecSmrg	    if ( interest->client->swapped ) {
42105b261ecSmrg		register int n;
42205b261ecSmrg		swaps(&pCN->sequenceNumber,n);
42305b261ecSmrg		swapl(&pCN->changedControls,n);
42405b261ecSmrg		swapl(&pCN->enabledControls,n);
42505b261ecSmrg		swapl(&pCN->enabledControlChanges,n);
42605b261ecSmrg		swapl(&pCN->time,n);
42705b261ecSmrg	    }
42805b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pCN);
42905b261ecSmrg	}
43005b261ecSmrg	interest= interest->next;
43105b261ecSmrg    }
43205b261ecSmrg    return;
43305b261ecSmrg}
43405b261ecSmrg
43505b261ecSmrgstatic void
43605b261ecSmrgXkbSendIndicatorNotify(DeviceIntPtr kbd,int xkbType,xkbIndicatorNotify *pEv)
43705b261ecSmrg{
43805b261ecSmrgint		initialized;
43905b261ecSmrgXkbInterestPtr	interest;
44005b261ecSmrgTime 		time = 0;
44105b261ecSmrgCARD32		state,changed;
44205b261ecSmrg
44305b261ecSmrg    interest = kbd->xkb_interest;
44405b261ecSmrg    if (!interest)
44505b261ecSmrg	return;
44605b261ecSmrg
44705b261ecSmrg    initialized = 0;
44805b261ecSmrg    state = pEv->state;
44905b261ecSmrg    changed = pEv->changed;
45005b261ecSmrg    while (interest) {
45105b261ecSmrg	if ((!interest->client->clientGone) &&
45205b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
45305b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
4546747b715Smrg            XIShouldNotify(interest->client, kbd) &&
45505b261ecSmrg	    (((xkbType==XkbIndicatorStateNotify)&&
45605b261ecSmrg				(interest->iStateNotifyMask&changed))||
45705b261ecSmrg	     ((xkbType==XkbIndicatorMapNotify)&&
45805b261ecSmrg	    			(interest->iMapNotifyMask&changed)))) {
45905b261ecSmrg	    if (!initialized) {
46005b261ecSmrg		pEv->type = XkbEventCode + XkbEventBase;
46105b261ecSmrg		pEv->xkbType = xkbType;
46205b261ecSmrg		pEv->deviceID = kbd->id;
46305b261ecSmrg		pEv->time = time = GetTimeInMillis();
46405b261ecSmrg		initialized= 1;
46505b261ecSmrg	    }
46605b261ecSmrg	    pEv->sequenceNumber = interest->client->sequence;
46705b261ecSmrg	    pEv->time = time;
46805b261ecSmrg	    pEv->changed = changed;
46905b261ecSmrg	    pEv->state = state;
47005b261ecSmrg	    if ( interest->client->swapped ) {
47105b261ecSmrg		register int n;
47205b261ecSmrg		swaps(&pEv->sequenceNumber,n);
47305b261ecSmrg		swapl(&pEv->time,n);
47405b261ecSmrg		swapl(&pEv->changed,n);
47505b261ecSmrg		swapl(&pEv->state,n);
47605b261ecSmrg	    }
47705b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
47805b261ecSmrg	}
47905b261ecSmrg	interest= interest->next;
48005b261ecSmrg    }
48105b261ecSmrg    return;
48205b261ecSmrg}
48305b261ecSmrg
48405b261ecSmrg
48505b261ecSmrgvoid
48605b261ecSmrgXkbHandleBell(	BOOL		 force,
48705b261ecSmrg		BOOL		 eventOnly,
48805b261ecSmrg		DeviceIntPtr	 kbd,
48905b261ecSmrg		CARD8		 percent,
49005b261ecSmrg		pointer		 pCtrl,
49105b261ecSmrg		CARD8		 class,
49205b261ecSmrg		Atom		 name,
49305b261ecSmrg		WindowPtr	 pWin,
49405b261ecSmrg		ClientPtr	 pClient)
49505b261ecSmrg{
49605b261ecSmrgxkbBellNotify	bn;
49705b261ecSmrgint		initialized;
49805b261ecSmrgXkbSrvInfoPtr	xkbi;
49905b261ecSmrgXkbInterestPtr	interest;
50005b261ecSmrgCARD8		id;
50105b261ecSmrgCARD16		pitch,duration;
50205b261ecSmrgTime 		time = 0;
50305b261ecSmrgXID		winID = 0;
50405b261ecSmrg
5054642e01fSmrg    if (!kbd->key || !kbd->key->xkbInfo)
5064642e01fSmrg        return;
5074642e01fSmrg
50805b261ecSmrg    xkbi = kbd->key->xkbInfo;
50905b261ecSmrg
51005b261ecSmrg    if ((force||(xkbi->desc->ctrls->enabled_ctrls&XkbAudibleBellMask))&&
51105b261ecSmrg							(!eventOnly)) {
51205b261ecSmrg        if (kbd->kbdfeed->BellProc)
51305b261ecSmrg            (*kbd->kbdfeed->BellProc)(percent,kbd,(pointer)pCtrl,class);
51405b261ecSmrg    }
51505b261ecSmrg    interest = kbd->xkb_interest;
51605b261ecSmrg    if ((!interest)||(force))
51705b261ecSmrg	return;
51805b261ecSmrg
51905b261ecSmrg    if ((class==0)||(class==KbdFeedbackClass)) {
52005b261ecSmrg	KeybdCtrl *pKeyCtrl= (KeybdCtrl *)pCtrl;
52105b261ecSmrg	id= pKeyCtrl->id;
52205b261ecSmrg	pitch= pKeyCtrl->bell_pitch;
52305b261ecSmrg	duration= pKeyCtrl->bell_duration;
52405b261ecSmrg    }
52505b261ecSmrg    else if (class==BellFeedbackClass) {
52605b261ecSmrg	BellCtrl *pBellCtrl= (BellCtrl *)pCtrl;
52705b261ecSmrg	id= pBellCtrl->id;
52805b261ecSmrg	pitch= pBellCtrl->pitch;
52905b261ecSmrg	duration= pBellCtrl->duration;
53005b261ecSmrg    }
53105b261ecSmrg    else return;
53205b261ecSmrg
53305b261ecSmrg    initialized = 0;
53405b261ecSmrg    while (interest) {
53505b261ecSmrg	if ((!interest->client->clientGone) &&
53605b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
53705b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
5386747b715Smrg	    (interest->bellNotifyMask) &&
5396747b715Smrg            XIShouldNotify(interest->client,kbd)) {
54005b261ecSmrg	    if (!initialized) {
54105b261ecSmrg		time = GetTimeInMillis();
54205b261ecSmrg		bn.type = XkbEventCode + XkbEventBase;
54305b261ecSmrg		bn.xkbType = XkbBellNotify;
54405b261ecSmrg		bn.deviceID = kbd->id;
54505b261ecSmrg		bn.bellClass = class;
54605b261ecSmrg		bn.bellID = id;
54705b261ecSmrg		bn.percent= percent;
54805b261ecSmrg		bn.eventOnly = (eventOnly!=0);
54905b261ecSmrg		winID= (pWin?pWin->drawable.id:None);
55005b261ecSmrg		initialized= 1;
55105b261ecSmrg	    }
55205b261ecSmrg	    bn.sequenceNumber = interest->client->sequence;
55305b261ecSmrg	    bn.time = time;
55405b261ecSmrg	    bn.pitch = pitch;
55505b261ecSmrg	    bn.duration = duration;
55605b261ecSmrg	    bn.name = name;
55705b261ecSmrg	    bn.window=  winID;
55805b261ecSmrg	    if ( interest->client->swapped ) {
55905b261ecSmrg		register int n;
56005b261ecSmrg		swaps(&bn.sequenceNumber,n);
56105b261ecSmrg		swapl(&bn.time,n);
56205b261ecSmrg		swaps(&bn.pitch,n);
56305b261ecSmrg		swaps(&bn.duration,n);
56405b261ecSmrg		swapl(&bn.name,n);
56505b261ecSmrg		swapl(&bn.window,n);
56605b261ecSmrg	    }
56705b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)&bn);
56805b261ecSmrg	}
56905b261ecSmrg	interest= interest->next;
57005b261ecSmrg    }
57105b261ecSmrg    return;
57205b261ecSmrg}
57305b261ecSmrg
57405b261ecSmrgvoid
57505b261ecSmrgXkbSendAccessXNotify(DeviceIntPtr kbd,xkbAccessXNotify *pEv)
57605b261ecSmrg{
57705b261ecSmrgint		initialized;
57805b261ecSmrgXkbInterestPtr	interest;
57905b261ecSmrgTime 		time = 0;
58005b261ecSmrgCARD16		sk_delay,db_delay;
58105b261ecSmrg
58205b261ecSmrg    interest = kbd->xkb_interest;
58305b261ecSmrg    if (!interest)
58405b261ecSmrg	return;
58505b261ecSmrg
58605b261ecSmrg    initialized = 0;
58705b261ecSmrg    sk_delay= pEv->slowKeysDelay;
58805b261ecSmrg    db_delay= pEv->debounceDelay;
58905b261ecSmrg    while (interest) {
59005b261ecSmrg	if ((!interest->client->clientGone) &&
59105b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
59205b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
5936747b715Smrg	    (interest->accessXNotifyMask&(1<<pEv->detail)) &&
5946747b715Smrg            XIShouldNotify(interest->client, kbd)) {
59505b261ecSmrg	    if (!initialized) {
59605b261ecSmrg		pEv->type = XkbEventCode + XkbEventBase;
59705b261ecSmrg		pEv->xkbType = XkbAccessXNotify;
59805b261ecSmrg		pEv->deviceID = kbd->id;
59905b261ecSmrg		pEv->time = time = GetTimeInMillis();
60005b261ecSmrg		initialized= 1;
60105b261ecSmrg	    }
60205b261ecSmrg	    pEv->sequenceNumber = interest->client->sequence;
60305b261ecSmrg	    pEv->time = time;
60405b261ecSmrg	    pEv->slowKeysDelay = sk_delay;
60505b261ecSmrg	    pEv->debounceDelay = db_delay;
60605b261ecSmrg	    if ( interest->client->swapped ) {
60705b261ecSmrg		register int n;
60805b261ecSmrg		swaps(&pEv->sequenceNumber,n);
60905b261ecSmrg		swapl(&pEv->time,n);
61005b261ecSmrg		swaps(&pEv->slowKeysDelay,n);
61105b261ecSmrg		swaps(&pEv->debounceDelay,n);
61205b261ecSmrg	    }
61305b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
61405b261ecSmrg	}
61505b261ecSmrg	interest= interest->next;
61605b261ecSmrg    }
61705b261ecSmrg    return;
61805b261ecSmrg}
61905b261ecSmrg
62005b261ecSmrgvoid
62105b261ecSmrgXkbSendNamesNotify(DeviceIntPtr kbd,xkbNamesNotify *pEv)
62205b261ecSmrg{
62305b261ecSmrgint		initialized;
62405b261ecSmrgXkbInterestPtr	interest;
62505b261ecSmrgTime 		time = 0;
62605b261ecSmrgCARD16		changed,changedVirtualMods;
62705b261ecSmrgCARD32		changedIndicators;
62805b261ecSmrg
62905b261ecSmrg    interest = kbd->xkb_interest;
63005b261ecSmrg    if (!interest)
63105b261ecSmrg	return;
63205b261ecSmrg
63305b261ecSmrg    initialized = 0;
63405b261ecSmrg    changed= pEv->changed;
63505b261ecSmrg    changedIndicators= pEv->changedIndicators;
63605b261ecSmrg    changedVirtualMods= pEv->changedVirtualMods;
63705b261ecSmrg    while (interest) {
63805b261ecSmrg	if ((!interest->client->clientGone) &&
63905b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
64005b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
6416747b715Smrg	    (interest->namesNotifyMask&pEv->changed) &&
6426747b715Smrg            XIShouldNotify(interest->client, kbd)) {
64305b261ecSmrg	    if (!initialized) {
64405b261ecSmrg		pEv->type = XkbEventCode + XkbEventBase;
64505b261ecSmrg		pEv->xkbType = XkbNamesNotify;
64605b261ecSmrg		pEv->deviceID = kbd->id;
64705b261ecSmrg		pEv->time = time = GetTimeInMillis();
64805b261ecSmrg		initialized= 1;
64905b261ecSmrg	    }
65005b261ecSmrg	    pEv->sequenceNumber = interest->client->sequence;
65105b261ecSmrg	    pEv->time = time;
65205b261ecSmrg	    pEv->changed = changed;
65305b261ecSmrg	    pEv->changedIndicators = changedIndicators;
65405b261ecSmrg	    pEv->changedVirtualMods= changedVirtualMods;
65505b261ecSmrg	    if ( interest->client->swapped ) {
65605b261ecSmrg		register int n;
65705b261ecSmrg		swaps(&pEv->sequenceNumber,n);
65805b261ecSmrg		swapl(&pEv->time,n);
65905b261ecSmrg		swaps(&pEv->changed,n);
66005b261ecSmrg		swapl(&pEv->changedIndicators,n);
66105b261ecSmrg		swaps(&pEv->changedVirtualMods,n);
66205b261ecSmrg	    }
66305b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
66405b261ecSmrg	}
66505b261ecSmrg	interest= interest->next;
66605b261ecSmrg    }
66705b261ecSmrg    return;
66805b261ecSmrg}
66905b261ecSmrg
67005b261ecSmrgvoid
67105b261ecSmrgXkbSendCompatMapNotify(DeviceIntPtr kbd,xkbCompatMapNotify *pEv)
67205b261ecSmrg{
67305b261ecSmrgint		initialized;
67405b261ecSmrgXkbInterestPtr	interest;
67505b261ecSmrgTime 		time = 0;
67605b261ecSmrgCARD16		firstSI = 0, nSI = 0, nTotalSI = 0;
67705b261ecSmrg
67805b261ecSmrg    interest = kbd->xkb_interest;
67905b261ecSmrg    if (!interest)
68005b261ecSmrg	return;
68105b261ecSmrg
68205b261ecSmrg    initialized = 0;
68305b261ecSmrg    while (interest) {
68405b261ecSmrg	if ((!interest->client->clientGone) &&
68505b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
68605b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
6876747b715Smrg	    (interest->compatNotifyMask) &&
6886747b715Smrg            XIShouldNotify(interest->client, kbd)) {
68905b261ecSmrg	    if (!initialized) {
69005b261ecSmrg		pEv->type = XkbEventCode + XkbEventBase;
69105b261ecSmrg		pEv->xkbType = XkbCompatMapNotify;
69205b261ecSmrg		pEv->deviceID = kbd->id;
69305b261ecSmrg		pEv->time = time = GetTimeInMillis();
69405b261ecSmrg		firstSI= pEv->firstSI;
69505b261ecSmrg		nSI= pEv->nSI;
69605b261ecSmrg		nTotalSI= pEv->nTotalSI;
69705b261ecSmrg		initialized= 1;
69805b261ecSmrg	    }
69905b261ecSmrg	    pEv->sequenceNumber = interest->client->sequence;
70005b261ecSmrg	    pEv->time = time;
70105b261ecSmrg	    pEv->firstSI = firstSI;
70205b261ecSmrg	    pEv->nSI = nSI;
70305b261ecSmrg	    pEv->nTotalSI = nTotalSI;
70405b261ecSmrg	    if ( interest->client->swapped ) {
70505b261ecSmrg		register int n;
70605b261ecSmrg		swaps(&pEv->sequenceNumber,n);
70705b261ecSmrg		swapl(&pEv->time,n);
70805b261ecSmrg		swaps(&pEv->firstSI,n);
70905b261ecSmrg		swaps(&pEv->nSI,n);
71005b261ecSmrg		swaps(&pEv->nTotalSI,n);
71105b261ecSmrg	    }
71205b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
71305b261ecSmrg	}
71405b261ecSmrg	interest= interest->next;
71505b261ecSmrg    }
71605b261ecSmrg    return;
71705b261ecSmrg}
71805b261ecSmrg
71905b261ecSmrgvoid
72005b261ecSmrgXkbSendActionMessage(DeviceIntPtr kbd,xkbActionMessage *pEv)
72105b261ecSmrg{
72205b261ecSmrgint		 initialized;
72305b261ecSmrgXkbSrvInfoPtr	 xkbi;
72405b261ecSmrgXkbInterestPtr	 interest;
72505b261ecSmrgTime 		 time = 0;
72605b261ecSmrg
72705b261ecSmrg    interest = kbd->xkb_interest;
7284642e01fSmrg    if (!interest || !kbd->key || !kbd->key->xkbInfo)
72905b261ecSmrg	return;
73005b261ecSmrg
7314642e01fSmrg    xkbi = kbd->key->xkbInfo;
7324642e01fSmrg
73305b261ecSmrg    initialized = 0;
73405b261ecSmrg    pEv->mods= xkbi->state.mods;
73505b261ecSmrg    pEv->group= xkbi->state.group;
73605b261ecSmrg    while (interest) {
73705b261ecSmrg	if ((!interest->client->clientGone) &&
73805b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
73905b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
7406747b715Smrg	    (interest->actionMessageMask) &&
7416747b715Smrg            XIShouldNotify(interest->client, kbd)) {
74205b261ecSmrg	    if (!initialized) {
74305b261ecSmrg		pEv->type = XkbEventCode + XkbEventBase;
74405b261ecSmrg		pEv->xkbType = XkbActionMessage;
74505b261ecSmrg		pEv->deviceID = kbd->id;
74605b261ecSmrg		pEv->sequenceNumber = interest->client->sequence;
74705b261ecSmrg		pEv->time = time = GetTimeInMillis();
74805b261ecSmrg		initialized= 1;
74905b261ecSmrg	    }
75005b261ecSmrg	    pEv->sequenceNumber = interest->client->sequence;
75105b261ecSmrg	    pEv->time = time;
75205b261ecSmrg	    if ( interest->client->swapped ) {
75305b261ecSmrg		register int n;
75405b261ecSmrg		swaps(&pEv->sequenceNumber,n);
75505b261ecSmrg		swapl(&pEv->time,n);
75605b261ecSmrg	    }
75705b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
75805b261ecSmrg	}
75905b261ecSmrg	interest= interest->next;
76005b261ecSmrg    }
76105b261ecSmrg    return;
76205b261ecSmrg}
76305b261ecSmrg
76405b261ecSmrgvoid
76505b261ecSmrgXkbSendExtensionDeviceNotify(	DeviceIntPtr 			dev,
76605b261ecSmrg				ClientPtr			client,
76705b261ecSmrg				xkbExtensionDeviceNotify *	pEv)
76805b261ecSmrg{
76905b261ecSmrgint		 initialized;
77005b261ecSmrgXkbInterestPtr	 interest;
77105b261ecSmrgTime 		 time = 0;
77205b261ecSmrgCARD32		 defined, state;
7736747b715SmrgCARD16		 reason;
77405b261ecSmrg
77505b261ecSmrg    interest = dev->xkb_interest;
77605b261ecSmrg    if (!interest)
77705b261ecSmrg	return;
77805b261ecSmrg
77905b261ecSmrg    initialized = 0;
78005b261ecSmrg    reason= pEv->reason;
78105b261ecSmrg    defined= pEv->ledsDefined;
78205b261ecSmrg    state= pEv->ledState;
78305b261ecSmrg    while (interest) {
78405b261ecSmrg	if ((!interest->client->clientGone) &&
78505b261ecSmrg	    (interest->client->requestVector != InitialVector) &&
78605b261ecSmrg	    (interest->client->xkbClientFlags&_XkbClientInitialized) &&
7876747b715Smrg	    (interest->extDevNotifyMask&reason) &&
7886747b715Smrg            XIShouldNotify(interest->client, dev)) {
78905b261ecSmrg	    if (!initialized) {
79005b261ecSmrg		pEv->type = XkbEventCode + XkbEventBase;
79105b261ecSmrg		pEv->xkbType = XkbExtensionDeviceNotify;
79205b261ecSmrg		pEv->deviceID = dev->id;
79305b261ecSmrg		pEv->sequenceNumber = interest->client->sequence;
79405b261ecSmrg		pEv->time = time = GetTimeInMillis();
79505b261ecSmrg		initialized= 1;
79605b261ecSmrg	    }
79705b261ecSmrg	    else {
79805b261ecSmrg		pEv->sequenceNumber = interest->client->sequence;
79905b261ecSmrg		pEv->time = time;
80005b261ecSmrg		pEv->ledsDefined= defined;
80105b261ecSmrg		pEv->ledState= state;
80205b261ecSmrg		pEv->reason= reason;
8036747b715Smrg		pEv->supported= XkbXI_AllFeaturesMask;
80405b261ecSmrg	    }
80505b261ecSmrg	    if ( interest->client->swapped ) {
80605b261ecSmrg		register int n;
80705b261ecSmrg		swaps(&pEv->sequenceNumber,n);
80805b261ecSmrg		swapl(&pEv->time,n);
80905b261ecSmrg		swapl(&pEv->ledsDefined,n);
81005b261ecSmrg		swapl(&pEv->ledState,n);
81105b261ecSmrg		swaps(&pEv->reason,n);
81205b261ecSmrg		swaps(&pEv->supported,n);
81305b261ecSmrg	    }
81405b261ecSmrg	    WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
81505b261ecSmrg	}
81605b261ecSmrg	interest= interest->next;
81705b261ecSmrg    }
81805b261ecSmrg    return;
81905b261ecSmrg}
82005b261ecSmrg
82105b261ecSmrgvoid
82205b261ecSmrgXkbSendNotification(	DeviceIntPtr		kbd,
82305b261ecSmrg			XkbChangesPtr		pChanges,
82405b261ecSmrg			XkbEventCausePtr	cause)
82505b261ecSmrg{
82605b261ecSmrgXkbSrvLedInfoPtr	sli;
82705b261ecSmrg
82805b261ecSmrg    sli= NULL;
82905b261ecSmrg    if (pChanges->state_changes) {
83005b261ecSmrg	xkbStateNotify sn;
83105b261ecSmrg	sn.changed= pChanges->state_changes;
83205b261ecSmrg	sn.keycode= cause->kc;
83305b261ecSmrg	sn.eventType= cause->event;
83405b261ecSmrg	sn.requestMajor= cause->mjr;
83505b261ecSmrg	sn.requestMinor= cause->mnr;
83605b261ecSmrg	XkbSendStateNotify(kbd,&sn);
83705b261ecSmrg    }
83805b261ecSmrg    if (pChanges->map.changed) {
83905b261ecSmrg	xkbMapNotify mn;
8406747b715Smrg	memset(&mn, 0, sizeof(xkbMapNotify));
84105b261ecSmrg	mn.changed= pChanges->map.changed;
84205b261ecSmrg	mn.firstType= pChanges->map.first_type;
84305b261ecSmrg	mn.nTypes= pChanges->map.num_types;
84405b261ecSmrg	mn.firstKeySym= pChanges->map.first_key_sym;
84505b261ecSmrg	mn.nKeySyms= pChanges->map.num_key_syms;
84605b261ecSmrg	mn.firstKeyAct= pChanges->map.first_key_act;
84705b261ecSmrg	mn.nKeyActs= pChanges->map.num_key_acts;
84805b261ecSmrg	mn.firstKeyBehavior= pChanges->map.first_key_behavior;
84905b261ecSmrg	mn.nKeyBehaviors= pChanges->map.num_key_behaviors;
85005b261ecSmrg	mn.virtualMods= pChanges->map.vmods;
85105b261ecSmrg	mn.firstKeyExplicit= pChanges->map.first_key_explicit;
85205b261ecSmrg	mn.nKeyExplicit= pChanges->map.num_key_explicit;
85305b261ecSmrg	mn.firstModMapKey= pChanges->map.first_modmap_key;
85405b261ecSmrg	mn.nModMapKeys= pChanges->map.num_modmap_keys;
85505b261ecSmrg	mn.firstVModMapKey= pChanges->map.first_vmodmap_key;
85605b261ecSmrg	mn.nVModMapKeys= pChanges->map.num_vmodmap_keys;
85705b261ecSmrg	XkbSendMapNotify(kbd,&mn);
85805b261ecSmrg    }
85905b261ecSmrg    if ((pChanges->ctrls.changed_ctrls)||
86005b261ecSmrg	(pChanges->ctrls.enabled_ctrls_changes)) {
86105b261ecSmrg	xkbControlsNotify cn;
8626747b715Smrg	memset(&cn, 0, sizeof(xkbControlsNotify));
86305b261ecSmrg	cn.changedControls= pChanges->ctrls.changed_ctrls;
86405b261ecSmrg	cn.enabledControlChanges= pChanges->ctrls.enabled_ctrls_changes;
86505b261ecSmrg	cn.keycode= cause->kc;
86605b261ecSmrg	cn.eventType= cause->event;
86705b261ecSmrg	cn.requestMajor= cause->mjr;
86805b261ecSmrg	cn.requestMinor= cause->mnr;
86905b261ecSmrg	XkbSendControlsNotify(kbd,&cn);
87005b261ecSmrg    }
87105b261ecSmrg    if (pChanges->indicators.map_changes) {
87205b261ecSmrg	xkbIndicatorNotify in;
87305b261ecSmrg	if (sli==NULL)
87405b261ecSmrg	    sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
8756747b715Smrg	memset(&in, 0, sizeof(xkbIndicatorNotify));
87605b261ecSmrg	in.state= sli->effectiveState;
87705b261ecSmrg	in.changed= pChanges->indicators.map_changes;
87805b261ecSmrg	XkbSendIndicatorNotify(kbd,XkbIndicatorMapNotify,&in);
87905b261ecSmrg    }
88005b261ecSmrg    if (pChanges->indicators.state_changes) {
88105b261ecSmrg	xkbIndicatorNotify in;
88205b261ecSmrg	if (sli==NULL)
88305b261ecSmrg	    sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
8846747b715Smrg	memset(&in, 0, sizeof(xkbIndicatorNotify));
88505b261ecSmrg	in.state= sli->effectiveState;
88605b261ecSmrg	in.changed= pChanges->indicators.state_changes;
88705b261ecSmrg	XkbSendIndicatorNotify(kbd,XkbIndicatorStateNotify,&in);
88805b261ecSmrg    }
88905b261ecSmrg    if (pChanges->names.changed) {
89005b261ecSmrg	xkbNamesNotify nn;
8916747b715Smrg	memset(&nn, 0, sizeof(xkbNamesNotify));
89205b261ecSmrg	nn.changed= pChanges->names.changed;
89305b261ecSmrg	nn.firstType= pChanges->names.first_type;
89405b261ecSmrg	nn.nTypes= pChanges->names.num_types;
89505b261ecSmrg	nn.firstLevelName= pChanges->names.first_lvl;
89605b261ecSmrg	nn.nLevelNames= pChanges->names.num_lvls;
89705b261ecSmrg	nn.nRadioGroups= pChanges->names.num_rg;
89805b261ecSmrg	nn.changedVirtualMods= pChanges->names.changed_vmods;
89905b261ecSmrg	nn.changedIndicators= pChanges->names.changed_indicators;
90005b261ecSmrg	XkbSendNamesNotify(kbd,&nn);
90105b261ecSmrg    }
90205b261ecSmrg    if ((pChanges->compat.changed_groups)||(pChanges->compat.num_si>0)) {
90305b261ecSmrg	xkbCompatMapNotify cmn;
9046747b715Smrg	memset(&cmn, 0, sizeof(xkbCompatMapNotify));
90505b261ecSmrg	cmn.changedGroups= pChanges->compat.changed_groups;
90605b261ecSmrg	cmn.firstSI= pChanges->compat.first_si;
90705b261ecSmrg	cmn.nSI= pChanges->compat.num_si;
90805b261ecSmrg	cmn.nTotalSI= kbd->key->xkbInfo->desc->compat->num_si;
90905b261ecSmrg	XkbSendCompatMapNotify(kbd,&cmn);
91005b261ecSmrg    }
91105b261ecSmrg    return;
91205b261ecSmrg}
91305b261ecSmrg
91405b261ecSmrg/***====================================================================***/
91505b261ecSmrg
9166747b715Smrgvoid
9176747b715SmrgXkbFilterEvents(ClientPtr client,int nEvents,xEvent *xE)
91805b261ecSmrg{
9196747b715Smrg    DeviceIntPtr dev = NULL;
9206747b715Smrg    XkbSrvInfoPtr xkbi;
9216747b715Smrg    CARD8 type = xE[0].u.u.type;
92205b261ecSmrg
9234642e01fSmrg    if (xE->u.u.type & EXTENSION_EVENT_BASE)
9246747b715Smrg        dev = XIGetDevice(xE);
9254642e01fSmrg
9266747b715Smrg    if (!dev)
9276747b715Smrg        dev = PickKeyboard(client);
9284642e01fSmrg
9296747b715Smrg    if (!dev->key)
9306747b715Smrg        return;
9314642e01fSmrg
9326747b715Smrg    xkbi = dev->key->xkbInfo;
93305b261ecSmrg
9346747b715Smrg    if (client->xkbClientFlags & _XkbClientInitialized) {
9356747b715Smrg	if ((xkbDebugFlags&0x10)&&
9366747b715Smrg            (type == KeyPress || type == KeyRelease ||
9376747b715Smrg             type == DeviceKeyPress || type == DeviceKeyRelease))
9386747b715Smrg	    DebugF("[xkb] XkbFilterWriteEvents (XKB client): state 0x%04x\n",
9396747b715Smrg                   xE[0].u.keyButtonPointer.state);
9406747b715Smrg
9416747b715Smrg	if (dev->deviceGrab.grab != NullGrab && dev->deviceGrab.fromPassiveGrab &&
9426747b715Smrg	    (type == KeyPress || type == KeyRelease ||
9436747b715Smrg             type == DeviceKeyPress || type == DeviceKeyRelease)) {
9446747b715Smrg	    unsigned int state, flags;
9456747b715Smrg
9466747b715Smrg	    flags = client->xkbClientFlags;
9476747b715Smrg	    state = xkbi->state.compat_grab_mods;
94805b261ecSmrg	    if (flags & XkbPCF_GrabsUseXKBStateMask) {
94905b261ecSmrg		int group;
9506747b715Smrg		if (flags & XkbPCF_LookupStateWhenGrabbed) {
9516747b715Smrg		     group = xkbi->state.group;
9526747b715Smrg		     state = xkbi->state.lookup_mods;
95305b261ecSmrg		}
95405b261ecSmrg		else {
9556747b715Smrg		    state = xkbi->state.grab_mods;
9566747b715Smrg		    group = xkbi->state.base_group + xkbi->state.latched_group;
9576747b715Smrg		    if (group < 0 || group >= xkbi->desc->ctrls->num_groups)
9586747b715Smrg			group = XkbAdjustGroup(group, xkbi->desc->ctrls);
95905b261ecSmrg		}
96005b261ecSmrg		state = XkbBuildCoreState(state, group);
96105b261ecSmrg	    }
9626747b715Smrg	    else if (flags & XkbPCF_LookupStateWhenGrabbed) {
9636747b715Smrg		state = xkbi->state.compat_lookup_mods;
9646747b715Smrg            }
9656747b715Smrg	    xE[0].u.keyButtonPointer.state = state;
96605b261ecSmrg	}
96705b261ecSmrg    }
96805b261ecSmrg    else {
9696747b715Smrg        if ((xkbDebugFlags & 0x4) &&
9706747b715Smrg	    (xE[0].u.u.type == KeyPress || xE[0].u.u.type==KeyRelease ||
9716747b715Smrg             xE[0].u.u.type == DeviceKeyPress ||
9726747b715Smrg             xE[0].u.u.type == DeviceKeyRelease)) {
9736747b715Smrg	    DebugF("[xkb] XKbFilterWriteEvents (non-XKB):\n");
9746747b715Smrg	    DebugF("[xkb] event= 0x%04x\n",xE[0].u.keyButtonPointer.state);
9756747b715Smrg	    DebugF("[xkb] lookup= 0x%02x, grab= 0x%02x\n",
9766747b715Smrg                   xkbi->state.lookup_mods, xkbi->state.grab_mods);
9776747b715Smrg	    DebugF("[xkb] compat lookup= 0x%02x, grab= 0x%02x\n",
9786747b715Smrg		   xkbi->state.compat_lookup_mods, xkbi->state.compat_grab_mods);
9796747b715Smrg	}
9806747b715Smrg	if (type >= KeyPress && type <= MotionNotify) {
9816747b715Smrg	    CARD16 old, new;
98205b261ecSmrg
9836747b715Smrg	    old = xE[0].u.keyButtonPointer.state & ~0x1f00;
9846747b715Smrg	    new = xE[0].u.keyButtonPointer.state & 0x1F00;
98505b261ecSmrg
9866747b715Smrg	    if (old == XkbStateFieldFromRec(&xkbi->state))
9876747b715Smrg		new |= xkbi->state.compat_lookup_mods;
9886747b715Smrg	    else
9896747b715Smrg                new |= xkbi->state.compat_grab_mods;
9906747b715Smrg	    xE[0].u.keyButtonPointer.state = new;
99105b261ecSmrg	}
9926747b715Smrg	else if (type == EnterNotify || type == LeaveNotify) {
9936747b715Smrg	    xE[0].u.enterLeave.state &= 0x1F00;
9946747b715Smrg	    xE[0].u.enterLeave.state |= xkbi->state.compat_grab_mods;
9956747b715Smrg	}
9966747b715Smrg        else if (type >= DeviceKeyPress && type <= DeviceMotionNotify) {
9976747b715Smrg            CARD16 old, new;
9986747b715Smrg            deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer*) &xE[0];
9996747b715Smrg
10006747b715Smrg            old = kbp->state & ~0x1F00;
10016747b715Smrg            new = kbp->state & 0x1F00;
10026747b715Smrg	    if (old == XkbStateFieldFromRec(&xkbi->state))
10036747b715Smrg		new |= xkbi->state.compat_lookup_mods;
10046747b715Smrg	    else
10056747b715Smrg                new |= xkbi->state.compat_grab_mods;
10066747b715Smrg            kbp->state = new;
10076747b715Smrg        }
100805b261ecSmrg    }
100905b261ecSmrg}
101005b261ecSmrg
101105b261ecSmrg/***====================================================================***/
101205b261ecSmrg
10136747b715SmrgXkbInterestPtr
101405b261ecSmrgXkbFindClientResource(DevicePtr inDev,ClientPtr client)
101505b261ecSmrg{
101605b261ecSmrgDeviceIntPtr	dev = (DeviceIntPtr)inDev;
101705b261ecSmrgXkbInterestPtr	interest;
101805b261ecSmrg
101905b261ecSmrg    if ( dev->xkb_interest ) {
102005b261ecSmrg	interest = dev->xkb_interest;
102105b261ecSmrg	while (interest){
102205b261ecSmrg	    if (interest->client==client) {
102305b261ecSmrg		return interest;
102405b261ecSmrg	    }
102505b261ecSmrg	    interest = interest->next;
102605b261ecSmrg	}
102705b261ecSmrg    }
102805b261ecSmrg    return NULL;
102905b261ecSmrg}
103005b261ecSmrg
10316747b715SmrgXkbInterestPtr
103205b261ecSmrgXkbAddClientResource(DevicePtr inDev,ClientPtr client,XID id)
103305b261ecSmrg{
103405b261ecSmrgDeviceIntPtr	dev = (DeviceIntPtr)inDev;
103505b261ecSmrgXkbInterestPtr	interest;
103605b261ecSmrg
103705b261ecSmrg    interest = dev->xkb_interest;
103805b261ecSmrg    while (interest) {
103905b261ecSmrg	if (interest->client==client)
104005b261ecSmrg	    return ((interest->resource==id)?interest:NULL);
104105b261ecSmrg	interest = interest->next;
104205b261ecSmrg    }
10436747b715Smrg    interest = calloc(1, sizeof(XkbInterestRec));
104405b261ecSmrg    if (interest) {
104505b261ecSmrg	interest->dev = dev;
104605b261ecSmrg	interest->client = client;
104705b261ecSmrg	interest->resource = id;
104805b261ecSmrg	interest->stateNotifyMask= 0;
104905b261ecSmrg	interest->ctrlsNotifyMask= 0;
105005b261ecSmrg	interest->namesNotifyMask= 0;
105105b261ecSmrg	interest->compatNotifyMask= 0;
105205b261ecSmrg	interest->bellNotifyMask= FALSE;
105305b261ecSmrg	interest->accessXNotifyMask= 0;
105405b261ecSmrg	interest->iStateNotifyMask= 0;
105505b261ecSmrg	interest->iMapNotifyMask= 0;
105605b261ecSmrg	interest->altSymsNotifyMask= 0;
105705b261ecSmrg	interest->next = dev->xkb_interest;
105805b261ecSmrg	dev->xkb_interest= interest;
105905b261ecSmrg	return interest;
106005b261ecSmrg    }
106105b261ecSmrg    return NULL;
106205b261ecSmrg}
106305b261ecSmrg
106405b261ecSmrgint
106505b261ecSmrgXkbRemoveResourceClient(DevicePtr inDev,XID id)
106605b261ecSmrg{
106705b261ecSmrgXkbSrvInfoPtr	xkbi;
106805b261ecSmrgDeviceIntPtr	dev = (DeviceIntPtr)inDev;
106905b261ecSmrgXkbInterestPtr	interest;
107005b261ecSmrgBool		found;
107105b261ecSmrgunsigned long	autoCtrls,autoValues;
107205b261ecSmrgClientPtr	client = NULL;
107305b261ecSmrg
10746747b715Smrg    found= FALSE;
10754642e01fSmrg
10764642e01fSmrg    if (!dev->key || !dev->key->xkbInfo)
10774642e01fSmrg        return found;
10784642e01fSmrg
107905b261ecSmrg    autoCtrls= autoValues= 0;
108005b261ecSmrg    if ( dev->xkb_interest ) {
108105b261ecSmrg	interest = dev->xkb_interest;
108205b261ecSmrg	if (interest && (interest->resource==id)){
108305b261ecSmrg	    dev->xkb_interest = interest->next;
108405b261ecSmrg	    autoCtrls= interest->autoCtrls;
108505b261ecSmrg	    autoValues= interest->autoCtrlValues;
108605b261ecSmrg	    client= interest->client;
10876747b715Smrg	    free(interest);
10886747b715Smrg	    found= TRUE;
108905b261ecSmrg	}
109005b261ecSmrg	while ((!found)&&(interest->next)) {
109105b261ecSmrg	    if (interest->next->resource==id) {
109205b261ecSmrg		XkbInterestPtr	victim = interest->next;
109305b261ecSmrg		interest->next = victim->next;
109405b261ecSmrg		autoCtrls= victim->autoCtrls;
109505b261ecSmrg		autoValues= victim->autoCtrlValues;
109605b261ecSmrg		client= victim->client;
10976747b715Smrg		free(victim);
10986747b715Smrg		found= TRUE;
109905b261ecSmrg	    }
110005b261ecSmrg	    interest = interest->next;
110105b261ecSmrg	}
110205b261ecSmrg    }
110305b261ecSmrg    if (found && autoCtrls && dev->key && dev->key->xkbInfo ) {
110405b261ecSmrg	XkbEventCauseRec cause;
110505b261ecSmrg
110605b261ecSmrg	xkbi= dev->key->xkbInfo;
110705b261ecSmrg	XkbSetCauseXkbReq(&cause,X_kbPerClientFlags,client);
110805b261ecSmrg	XkbEnableDisableControls(xkbi,autoCtrls,autoValues,NULL,&cause);
110905b261ecSmrg    }
111005b261ecSmrg    return found;
111105b261ecSmrg}
1112