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
935c4bbdfSmrgdocumentation, and that the name of Silicon Graphics not be
1035c4bbdfSmrgused in advertising or publicity pertaining to distribution
1105b261ecSmrgof the software without specific prior written permission.
1235c4bbdfSmrgSilicon 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
1635c4bbdfSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1735c4bbdfSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1935c4bbdfSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2035c4bbdfSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2135c4bbdfSmrgDATA 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"
4105b261ecSmrg#include <xkbsrv.h>
4205b261ecSmrg#include "xkb.h"
4305b261ecSmrg
4405b261ecSmrg/***====================================================================***/
4505b261ecSmrg
466747b715Smrg/*
476747b715Smrg * This function sends out two kinds of notification:
486747b715Smrg *   - Core mapping notify events sent to clients for whom kbd is the
496747b715Smrg *     current core ('picked') keyboard _and_ have not explicitly
506747b715Smrg *     selected for XKB mapping notify events;
516747b715Smrg *   - Xi mapping events, sent unconditionally to all clients who have
526747b715Smrg *     explicitly selected for them (including those who have explicitly
536747b715Smrg *     selected for XKB mapping notify events!).
546747b715Smrg */
556747b715Smrgstatic void
566747b715SmrgXkbSendLegacyMapNotify(DeviceIntPtr kbd, CARD16 xkb_event, CARD16 changed,
576747b715Smrg                       int first_key, int num_keys)
586747b715Smrg{
596747b715Smrg    int i;
606747b715Smrg    int keymap_changed = 0;
616747b715Smrg    int modmap_changed = 0;
626747b715Smrg    CARD32 time = GetTimeInMillis();
636747b715Smrg
646747b715Smrg    if (xkb_event == XkbNewKeyboardNotify) {
656747b715Smrg        if (changed & XkbNKN_KeycodesMask) {
666747b715Smrg            keymap_changed = 1;
676747b715Smrg            modmap_changed = 1;
686747b715Smrg        }
696747b715Smrg    }
706747b715Smrg    else if (xkb_event == XkbMapNotify) {
716747b715Smrg        if (changed & XkbKeySymsMask)
726747b715Smrg            keymap_changed = 1;
736747b715Smrg        if (changed & XkbModifierMapMask)
746747b715Smrg            modmap_changed = 1;
756747b715Smrg    }
766747b715Smrg    if (!keymap_changed && !modmap_changed)
776747b715Smrg        return;
786747b715Smrg
796747b715Smrg    /* 0 is serverClient. */
806747b715Smrg    for (i = 1; i < currentMaxClients; i++) {
816747b715Smrg        if (!clients[i] || clients[i]->clientState != ClientStateRunning)
826747b715Smrg            continue;
836747b715Smrg
8435c4bbdfSmrg        /* XKB allows clients to restrict the MappingNotify events sent to
8535c4bbdfSmrg         * them.  This was broken for three years.  Sorry. */
8635c4bbdfSmrg        if (xkb_event == XkbMapNotify &&
8735c4bbdfSmrg            (clients[i]->xkbClientFlags & _XkbClientInitialized) &&
8835c4bbdfSmrg            !(clients[i]->mapNotifyMask & changed))
896747b715Smrg            continue;
9035c4bbdfSmrg        /* Emulate previous server behaviour: any client which has activated
9135c4bbdfSmrg         * XKB will not receive core events emulated from a NewKeyboardNotify
9235c4bbdfSmrg         * at all. */
936747b715Smrg        if (xkb_event == XkbNewKeyboardNotify &&
946747b715Smrg            (clients[i]->xkbClientFlags & _XkbClientInitialized))
956747b715Smrg            continue;
966747b715Smrg
976747b715Smrg        /* Don't send core events to clients who don't know about us. */
986747b715Smrg        if (!XIShouldNotify(clients[i], kbd))
996747b715Smrg            continue;
1006747b715Smrg
1016747b715Smrg        if (keymap_changed) {
10235c4bbdfSmrg            xEvent core_mn = { .u.u.type = MappingNotify };
1036747b715Smrg            core_mn.u.mappingNotify.request = MappingKeyboard;
1046747b715Smrg
1056747b715Smrg            /* Clip the keycode range to what the client knows about, so it
1066747b715Smrg             * doesn't freak out. */
1076747b715Smrg            if (first_key >= clients[i]->minKC)
1086747b715Smrg                core_mn.u.mappingNotify.firstKeyCode = first_key;
1096747b715Smrg            else
1106747b715Smrg                core_mn.u.mappingNotify.firstKeyCode = clients[i]->minKC;
1116747b715Smrg            if (first_key + num_keys - 1 <= clients[i]->maxKC)
1126747b715Smrg                core_mn.u.mappingNotify.count = num_keys;
1136747b715Smrg            else
1146747b715Smrg                core_mn.u.mappingNotify.count = clients[i]->maxKC -
11535c4bbdfSmrg                    clients[i]->minKC + 1;
1166747b715Smrg
1176747b715Smrg            WriteEventsToClient(clients[i], 1, &core_mn);
1186747b715Smrg        }
1196747b715Smrg        if (modmap_changed) {
12035c4bbdfSmrg            xEvent core_mn = {
12135c4bbdfSmrg                .u.mappingNotify.request = MappingModifier,
12235c4bbdfSmrg                .u.mappingNotify.firstKeyCode = 0,
12335c4bbdfSmrg                .u.mappingNotify.count = 0
12435c4bbdfSmrg            };
12535c4bbdfSmrg            core_mn.u.u.type = MappingNotify;
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) {
13435c4bbdfSmrg        deviceMappingNotify xi_mn = {
13535c4bbdfSmrg            .type = DeviceMappingNotify,
13635c4bbdfSmrg            .deviceid = kbd->id,
13735c4bbdfSmrg            .request = MappingKeyboard,
13835c4bbdfSmrg            .firstKeyCode = first_key,
13935c4bbdfSmrg            .count = num_keys,
14035c4bbdfSmrg            .time = time
14135c4bbdfSmrg        };
1426747b715Smrg        SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn,
1436747b715Smrg                              1);
1446747b715Smrg    }
1456747b715Smrg    if (modmap_changed) {
14635c4bbdfSmrg        deviceMappingNotify xi_mn = {
14735c4bbdfSmrg            .type = DeviceMappingNotify,
14835c4bbdfSmrg            .deviceid = kbd->id,
14935c4bbdfSmrg            .request = MappingModifier,
15035c4bbdfSmrg            .firstKeyCode = 0,
15135c4bbdfSmrg            .count = 0,
15235c4bbdfSmrg            .time = time
15335c4bbdfSmrg        };
1546747b715Smrg        SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn,
1556747b715Smrg                              1);
1566747b715Smrg    }
1576747b715Smrg}
1586747b715Smrg
1596747b715Smrg/***====================================================================***/
1606747b715Smrg
16105b261ecSmrgvoid
16235c4bbdfSmrgXkbSendNewKeyboardNotify(DeviceIntPtr kbd, xkbNewKeyboardNotify * pNKN)
1636747b715Smrg{
1646747b715Smrg    int i;
1656747b715Smrg    Time time = GetTimeInMillis();
1666747b715Smrg    CARD16 changed = pNKN->changed;
16705b261ecSmrg
16805b261ecSmrg    pNKN->type = XkbEventCode + XkbEventBase;
16905b261ecSmrg    pNKN->xkbType = XkbNewKeyboardNotify;
17005b261ecSmrg
17135c4bbdfSmrg    for (i = 1; i < currentMaxClients; i++) {
1726747b715Smrg        if (!clients[i] || clients[i]->clientState != ClientStateRunning)
1736747b715Smrg            continue;
1746747b715Smrg
1756747b715Smrg        if (!(clients[i]->newKeyboardNotifyMask & changed))
1766747b715Smrg            continue;
1776747b715Smrg
1786747b715Smrg        pNKN->sequenceNumber = clients[i]->sequence;
1796747b715Smrg        pNKN->time = time;
1806747b715Smrg        pNKN->changed = changed;
1816747b715Smrg        if (clients[i]->swapped) {
18235c4bbdfSmrg            swaps(&pNKN->sequenceNumber);
18335c4bbdfSmrg            swapl(&pNKN->time);
18435c4bbdfSmrg            swaps(&pNKN->changed);
1856747b715Smrg        }
1866747b715Smrg        WriteToClient(clients[i], sizeof(xEvent), pNKN);
18705b261ecSmrg
1886747b715Smrg        if (changed & XkbNKN_KeycodesMask) {
1896747b715Smrg            clients[i]->minKC = pNKN->minKeyCode;
1906747b715Smrg            clients[i]->maxKC = pNKN->maxKeyCode;
1916747b715Smrg        }
19205b261ecSmrg    }
1936747b715Smrg
1946747b715Smrg    XkbSendLegacyMapNotify(kbd, XkbNewKeyboardNotify, changed, pNKN->minKeyCode,
1956747b715Smrg                           pNKN->maxKeyCode - pNKN->minKeyCode + 1);
1966747b715Smrg
19705b261ecSmrg    return;
19805b261ecSmrg}
19905b261ecSmrg
20005b261ecSmrg/***====================================================================***/
20105b261ecSmrg
20205b261ecSmrgvoid
20335c4bbdfSmrgXkbSendStateNotify(DeviceIntPtr kbd, xkbStateNotify * pSN)
20405b261ecSmrg{
20535c4bbdfSmrg    XkbSrvInfoPtr xkbi;
20635c4bbdfSmrg    XkbStatePtr state;
20735c4bbdfSmrg    XkbInterestPtr interest;
20835c4bbdfSmrg    Time time;
20935c4bbdfSmrg    register CARD16 changed, bState;
21005b261ecSmrg
21105b261ecSmrg    interest = kbd->xkb_interest;
2124642e01fSmrg    if (!interest || !kbd->key || !kbd->key->xkbInfo)
21335c4bbdfSmrg        return;
21405b261ecSmrg    xkbi = kbd->key->xkbInfo;
21535c4bbdfSmrg    state = &xkbi->state;
21605b261ecSmrg
21705b261ecSmrg    pSN->type = XkbEventCode + XkbEventBase;
21805b261ecSmrg    pSN->xkbType = XkbStateNotify;
21905b261ecSmrg    pSN->deviceID = kbd->id;
22005b261ecSmrg    pSN->time = time = GetTimeInMillis();
22105b261ecSmrg    pSN->mods = state->mods;
22205b261ecSmrg    pSN->baseMods = state->base_mods;
22305b261ecSmrg    pSN->latchedMods = state->latched_mods;
22405b261ecSmrg    pSN->lockedMods = state->locked_mods;
22505b261ecSmrg    pSN->group = state->group;
22605b261ecSmrg    pSN->baseGroup = state->base_group;
22705b261ecSmrg    pSN->latchedGroup = state->latched_group;
22805b261ecSmrg    pSN->lockedGroup = state->locked_group;
22905b261ecSmrg    pSN->compatState = state->compat_state;
23005b261ecSmrg    pSN->grabMods = state->grab_mods;
23105b261ecSmrg    pSN->compatGrabMods = state->compat_grab_mods;
23205b261ecSmrg    pSN->lookupMods = state->lookup_mods;
23305b261ecSmrg    pSN->compatLookupMods = state->compat_lookup_mods;
23405b261ecSmrg    pSN->ptrBtnState = state->ptr_buttons;
23505b261ecSmrg    changed = pSN->changed;
23635c4bbdfSmrg    bState = pSN->ptrBtnState;
23705b261ecSmrg
23805b261ecSmrg    while (interest) {
23935c4bbdfSmrg        if ((!interest->client->clientGone) &&
24035c4bbdfSmrg            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
24135c4bbdfSmrg            (interest->stateNotifyMask & changed)) {
24235c4bbdfSmrg            pSN->sequenceNumber = interest->client->sequence;
24335c4bbdfSmrg            pSN->time = time;
24435c4bbdfSmrg            pSN->changed = changed;
24535c4bbdfSmrg            pSN->ptrBtnState = bState;
24635c4bbdfSmrg            if (interest->client->swapped) {
24735c4bbdfSmrg                swaps(&pSN->sequenceNumber);
24835c4bbdfSmrg                swapl(&pSN->time);
24935c4bbdfSmrg                swaps(&pSN->changed);
25035c4bbdfSmrg                swaps(&pSN->ptrBtnState);
25135c4bbdfSmrg            }
25235c4bbdfSmrg            WriteToClient(interest->client, sizeof(xEvent), pSN);
25335c4bbdfSmrg        }
25435c4bbdfSmrg        interest = interest->next;
25505b261ecSmrg    }
25605b261ecSmrg    return;
25705b261ecSmrg}
25805b261ecSmrg
25905b261ecSmrg/***====================================================================***/
26005b261ecSmrg
2616747b715Smrg/*
2626747b715Smrg * This function sends out XKB mapping notify events to clients which
2636747b715Smrg * have explicitly selected for them.  Core and Xi events are handled by
2646747b715Smrg * XkbSendLegacyMapNotify. */
26505b261ecSmrgvoid
26635c4bbdfSmrgXkbSendMapNotify(DeviceIntPtr kbd, xkbMapNotify * pMN)
26705b261ecSmrg{
2686747b715Smrg    int i;
2696747b715Smrg    CARD32 time = GetTimeInMillis();
2706747b715Smrg    CARD16 changed = pMN->changed;
2716747b715Smrg    XkbSrvInfoPtr xkbi = kbd->key->xkbInfo;
2726747b715Smrg
2736747b715Smrg    pMN->minKeyCode = xkbi->desc->min_key_code;
2746747b715Smrg    pMN->maxKeyCode = xkbi->desc->max_key_code;
2756747b715Smrg    pMN->type = XkbEventCode + XkbEventBase;
2766747b715Smrg    pMN->xkbType = XkbMapNotify;
2776747b715Smrg    pMN->deviceID = kbd->id;
2786747b715Smrg
2796747b715Smrg    /* 0 is serverClient. */
2806747b715Smrg    for (i = 1; i < currentMaxClients; i++) {
2816747b715Smrg        if (!clients[i] || clients[i]->clientState != ClientStateRunning)
2826747b715Smrg            continue;
2836747b715Smrg
2846747b715Smrg        if (!(clients[i]->mapNotifyMask & changed))
2856747b715Smrg            continue;
2866747b715Smrg
2876747b715Smrg        pMN->time = time;
2886747b715Smrg        pMN->sequenceNumber = clients[i]->sequence;
2896747b715Smrg        pMN->changed = changed;
2906747b715Smrg
2916747b715Smrg        if (clients[i]->swapped) {
29235c4bbdfSmrg            swaps(&pMN->sequenceNumber);
29335c4bbdfSmrg            swapl(&pMN->time);
29435c4bbdfSmrg            swaps(&pMN->changed);
2956747b715Smrg        }
2966747b715Smrg        WriteToClient(clients[i], sizeof(xEvent), pMN);
29705b261ecSmrg    }
2986747b715Smrg
2996747b715Smrg    XkbSendLegacyMapNotify(kbd, XkbMapNotify, changed, pMN->firstKeySym,
3006747b715Smrg                           pMN->nKeySyms);
30105b261ecSmrg}
30205b261ecSmrg
30305b261ecSmrgint
30435c4bbdfSmrgXkbComputeControlsNotify(DeviceIntPtr kbd,
30535c4bbdfSmrg                         XkbControlsPtr old,
30635c4bbdfSmrg                         XkbControlsPtr new,
30735c4bbdfSmrg                         xkbControlsNotify * pCN, Bool forceCtrlProc)
30805b261ecSmrg{
30935c4bbdfSmrg    int i;
31035c4bbdfSmrg    CARD32 changedControls;
31105b261ecSmrg
31235c4bbdfSmrg    changedControls = 0;
31305b261ecSmrg
31405b261ecSmrg    if (!kbd || !kbd->kbdfeed)
31505b261ecSmrg        return 0;
31635c4bbdfSmrg
31735c4bbdfSmrg    if (old->enabled_ctrls != new->enabled_ctrls)
31835c4bbdfSmrg        changedControls |= XkbControlsEnabledMask;
31935c4bbdfSmrg    if ((old->repeat_delay != new->repeat_delay) ||
32035c4bbdfSmrg        (old->repeat_interval != new->repeat_interval))
32135c4bbdfSmrg        changedControls |= XkbRepeatKeysMask;
32205b261ecSmrg    for (i = 0; i < XkbPerKeyBitArraySize; i++)
32335c4bbdfSmrg        if (old->per_key_repeat[i] != new->per_key_repeat[i])
32435c4bbdfSmrg            changedControls |= XkbPerKeyRepeatMask;
32535c4bbdfSmrg    if (old->slow_keys_delay != new->slow_keys_delay)
32635c4bbdfSmrg        changedControls |= XkbSlowKeysMask;
32735c4bbdfSmrg    if (old->debounce_delay != new->debounce_delay)
32835c4bbdfSmrg        changedControls |= XkbBounceKeysMask;
32935c4bbdfSmrg    if ((old->mk_delay != new->mk_delay) ||
33035c4bbdfSmrg        (old->mk_interval != new->mk_interval) ||
33135c4bbdfSmrg        (old->mk_dflt_btn != new->mk_dflt_btn))
33235c4bbdfSmrg        changedControls |= XkbMouseKeysMask;
33335c4bbdfSmrg    if ((old->mk_time_to_max != new->mk_time_to_max) ||
33435c4bbdfSmrg        (old->mk_curve != new->mk_curve) ||
33535c4bbdfSmrg        (old->mk_max_speed != new->mk_max_speed))
33635c4bbdfSmrg        changedControls |= XkbMouseKeysAccelMask;
33735c4bbdfSmrg    if (old->ax_options != new->ax_options)
33835c4bbdfSmrg        changedControls |= XkbAccessXKeysMask;
33935c4bbdfSmrg    if ((old->ax_options ^ new->ax_options) & XkbAX_SKOptionsMask)
34035c4bbdfSmrg        changedControls |= XkbStickyKeysMask;
34135c4bbdfSmrg    if ((old->ax_options ^ new->ax_options) & XkbAX_FBOptionsMask)
34235c4bbdfSmrg        changedControls |= XkbAccessXFeedbackMask;
34335c4bbdfSmrg    if ((old->ax_timeout != new->ax_timeout) ||
34435c4bbdfSmrg        (old->axt_ctrls_mask != new->axt_ctrls_mask) ||
34535c4bbdfSmrg        (old->axt_ctrls_values != new->axt_ctrls_values) ||
34635c4bbdfSmrg        (old->axt_opts_mask != new->axt_opts_mask) ||
34735c4bbdfSmrg        (old->axt_opts_values != new->axt_opts_values)) {
34835c4bbdfSmrg        changedControls |= XkbAccessXTimeoutMask;
34905b261ecSmrg    }
35035c4bbdfSmrg    if ((old->internal.mask != new->internal.mask) ||
35135c4bbdfSmrg        (old->internal.real_mods != new->internal.real_mods) ||
35235c4bbdfSmrg        (old->internal.vmods != new->internal.vmods))
35335c4bbdfSmrg        changedControls |= XkbInternalModsMask;
35435c4bbdfSmrg    if ((old->ignore_lock.mask != new->ignore_lock.mask) ||
35535c4bbdfSmrg        (old->ignore_lock.real_mods != new->ignore_lock.real_mods) ||
35635c4bbdfSmrg        (old->ignore_lock.vmods != new->ignore_lock.vmods))
35735c4bbdfSmrg        changedControls |= XkbIgnoreLockModsMask;
35835c4bbdfSmrg
35935c4bbdfSmrg    if (new->enabled_ctrls & XkbRepeatKeysMask)
36035c4bbdfSmrg        kbd->kbdfeed->ctrl.autoRepeat = TRUE;
36135c4bbdfSmrg    else
36235c4bbdfSmrg        kbd->kbdfeed->ctrl.autoRepeat = FALSE;
36305b261ecSmrg
36405b261ecSmrg    if (kbd->kbdfeed && kbd->kbdfeed->CtrlProc &&
36535c4bbdfSmrg        (changedControls || forceCtrlProc))
36635c4bbdfSmrg        (*kbd->kbdfeed->CtrlProc) (kbd, &kbd->kbdfeed->ctrl);
36705b261ecSmrg
36835c4bbdfSmrg    if ((!changedControls) && (old->num_groups == new->num_groups))
36935c4bbdfSmrg        return 0;
37005b261ecSmrg
37105b261ecSmrg    if (!kbd->xkb_interest)
37235c4bbdfSmrg        return 0;
37305b261ecSmrg
37405b261ecSmrg    pCN->changedControls = changedControls;
37505b261ecSmrg    pCN->enabledControls = new->enabled_ctrls;
37635c4bbdfSmrg    pCN->enabledControlChanges = (new->enabled_ctrls ^ old->enabled_ctrls);
37705b261ecSmrg    pCN->numGroups = new->num_groups;
37805b261ecSmrg
37905b261ecSmrg    return 1;
38005b261ecSmrg}
38105b261ecSmrg
38205b261ecSmrgvoid
38335c4bbdfSmrgXkbSendControlsNotify(DeviceIntPtr kbd, xkbControlsNotify * pCN)
38405b261ecSmrg{
38535c4bbdfSmrg    int initialized;
38635c4bbdfSmrg    CARD32 changedControls, enabledControls, enabledChanges = 0;
38735c4bbdfSmrg    XkbSrvInfoPtr xkbi;
38835c4bbdfSmrg    XkbInterestPtr interest;
38935c4bbdfSmrg    Time time = 0;
39005b261ecSmrg
39105b261ecSmrg    interest = kbd->xkb_interest;
3924642e01fSmrg    if (!interest || !kbd->key || !kbd->key->xkbInfo)
39335c4bbdfSmrg        return;
39405b261ecSmrg    xkbi = kbd->key->xkbInfo;
39535c4bbdfSmrg
39605b261ecSmrg    initialized = 0;
39705b261ecSmrg    enabledControls = xkbi->desc->ctrls->enabled_ctrls;
39805b261ecSmrg    changedControls = pCN->changedControls;
39935c4bbdfSmrg    pCN->numGroups = xkbi->desc->ctrls->num_groups;
40005b261ecSmrg    while (interest) {
40135c4bbdfSmrg        if ((!interest->client->clientGone) &&
40235c4bbdfSmrg            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
40335c4bbdfSmrg            (interest->ctrlsNotifyMask & changedControls)) {
40435c4bbdfSmrg            if (!initialized) {
40535c4bbdfSmrg                pCN->type = XkbEventCode + XkbEventBase;
40635c4bbdfSmrg                pCN->xkbType = XkbControlsNotify;
40735c4bbdfSmrg                pCN->deviceID = kbd->id;
40835c4bbdfSmrg                pCN->time = time = GetTimeInMillis();
40935c4bbdfSmrg                enabledChanges = pCN->enabledControlChanges;
41035c4bbdfSmrg                initialized = 1;
41135c4bbdfSmrg            }
41235c4bbdfSmrg            pCN->changedControls = changedControls;
41335c4bbdfSmrg            pCN->enabledControls = enabledControls;
41435c4bbdfSmrg            pCN->enabledControlChanges = enabledChanges;
41535c4bbdfSmrg            pCN->sequenceNumber = interest->client->sequence;
41635c4bbdfSmrg            pCN->time = time;
41735c4bbdfSmrg            if (interest->client->swapped) {
41835c4bbdfSmrg                swaps(&pCN->sequenceNumber);
41935c4bbdfSmrg                swapl(&pCN->changedControls);
42035c4bbdfSmrg                swapl(&pCN->enabledControls);
42135c4bbdfSmrg                swapl(&pCN->enabledControlChanges);
42235c4bbdfSmrg                swapl(&pCN->time);
42335c4bbdfSmrg            }
42435c4bbdfSmrg            WriteToClient(interest->client, sizeof(xEvent), pCN);
42535c4bbdfSmrg        }
42635c4bbdfSmrg        interest = interest->next;
42705b261ecSmrg    }
42805b261ecSmrg    return;
42905b261ecSmrg}
43005b261ecSmrg
43105b261ecSmrgstatic void
43235c4bbdfSmrgXkbSendIndicatorNotify(DeviceIntPtr kbd, int xkbType, xkbIndicatorNotify * pEv)
43305b261ecSmrg{
43435c4bbdfSmrg    int initialized;
43535c4bbdfSmrg    XkbInterestPtr interest;
43635c4bbdfSmrg    Time time = 0;
43735c4bbdfSmrg    CARD32 state, changed;
43805b261ecSmrg
43905b261ecSmrg    interest = kbd->xkb_interest;
44005b261ecSmrg    if (!interest)
44135c4bbdfSmrg        return;
44235c4bbdfSmrg
44305b261ecSmrg    initialized = 0;
44405b261ecSmrg    state = pEv->state;
44505b261ecSmrg    changed = pEv->changed;
44605b261ecSmrg    while (interest) {
44735c4bbdfSmrg        if ((!interest->client->clientGone) &&
44835c4bbdfSmrg            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
44935c4bbdfSmrg            (((xkbType == XkbIndicatorStateNotify) &&
45035c4bbdfSmrg              (interest->iStateNotifyMask & changed)) ||
45135c4bbdfSmrg             ((xkbType == XkbIndicatorMapNotify) &&
45235c4bbdfSmrg              (interest->iMapNotifyMask & changed)))) {
45335c4bbdfSmrg            if (!initialized) {
45435c4bbdfSmrg                pEv->type = XkbEventCode + XkbEventBase;
45535c4bbdfSmrg                pEv->xkbType = xkbType;
45635c4bbdfSmrg                pEv->deviceID = kbd->id;
45735c4bbdfSmrg                pEv->time = time = GetTimeInMillis();
45835c4bbdfSmrg                initialized = 1;
45935c4bbdfSmrg            }
46035c4bbdfSmrg            pEv->sequenceNumber = interest->client->sequence;
46135c4bbdfSmrg            pEv->time = time;
46235c4bbdfSmrg            pEv->changed = changed;
46335c4bbdfSmrg            pEv->state = state;
46435c4bbdfSmrg            if (interest->client->swapped) {
46535c4bbdfSmrg                swaps(&pEv->sequenceNumber);
46635c4bbdfSmrg                swapl(&pEv->time);
46735c4bbdfSmrg                swapl(&pEv->changed);
46835c4bbdfSmrg                swapl(&pEv->state);
46935c4bbdfSmrg            }
47035c4bbdfSmrg            WriteToClient(interest->client, sizeof(xEvent), pEv);
47135c4bbdfSmrg        }
47235c4bbdfSmrg        interest = interest->next;
47305b261ecSmrg    }
47405b261ecSmrg    return;
47505b261ecSmrg}
47605b261ecSmrg
47705b261ecSmrgvoid
47835c4bbdfSmrgXkbHandleBell(BOOL force,
47935c4bbdfSmrg              BOOL eventOnly,
48035c4bbdfSmrg              DeviceIntPtr kbd,
48135c4bbdfSmrg              CARD8 percent,
48235c4bbdfSmrg              void *pCtrl,
48335c4bbdfSmrg              CARD8 class, Atom name, WindowPtr pWin, ClientPtr pClient)
48405b261ecSmrg{
48535c4bbdfSmrg    xkbBellNotify bn;
48635c4bbdfSmrg    int initialized;
48735c4bbdfSmrg    XkbSrvInfoPtr xkbi;
48835c4bbdfSmrg    XkbInterestPtr interest;
48935c4bbdfSmrg    CARD8 id;
49035c4bbdfSmrg    CARD16 pitch, duration;
49135c4bbdfSmrg    Time time = 0;
49235c4bbdfSmrg    XID winID = 0;
49305b261ecSmrg
4944642e01fSmrg    if (!kbd->key || !kbd->key->xkbInfo)
4954642e01fSmrg        return;
4964642e01fSmrg
49705b261ecSmrg    xkbi = kbd->key->xkbInfo;
49805b261ecSmrg
49935c4bbdfSmrg    if ((force || (xkbi->desc->ctrls->enabled_ctrls & XkbAudibleBellMask)) &&
50035c4bbdfSmrg        (!eventOnly)) {
50105b261ecSmrg        if (kbd->kbdfeed->BellProc)
50235c4bbdfSmrg            (*kbd->kbdfeed->BellProc) (percent, kbd, (void *) pCtrl, class);
50305b261ecSmrg    }
50405b261ecSmrg    interest = kbd->xkb_interest;
50535c4bbdfSmrg    if ((!interest) || (force))
50635c4bbdfSmrg        return;
50735c4bbdfSmrg
50835c4bbdfSmrg    if (class == KbdFeedbackClass) {
50935c4bbdfSmrg        KeybdCtrl *pKeyCtrl = (KeybdCtrl *) pCtrl;
51035c4bbdfSmrg
51135c4bbdfSmrg        id = pKeyCtrl->id;
51235c4bbdfSmrg        pitch = pKeyCtrl->bell_pitch;
51335c4bbdfSmrg        duration = pKeyCtrl->bell_duration;
51405b261ecSmrg    }
51535c4bbdfSmrg    else if (class == BellFeedbackClass) {
51635c4bbdfSmrg        BellCtrl *pBellCtrl = (BellCtrl *) pCtrl;
51735c4bbdfSmrg
51835c4bbdfSmrg        id = pBellCtrl->id;
51935c4bbdfSmrg        pitch = pBellCtrl->pitch;
52035c4bbdfSmrg        duration = pBellCtrl->duration;
52105b261ecSmrg    }
52235c4bbdfSmrg    else
52335c4bbdfSmrg        return;
52435c4bbdfSmrg
52505b261ecSmrg    initialized = 0;
52605b261ecSmrg    while (interest) {
52735c4bbdfSmrg        if ((!interest->client->clientGone) &&
52835c4bbdfSmrg            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
52935c4bbdfSmrg            (interest->bellNotifyMask)) {
53035c4bbdfSmrg            if (!initialized) {
53135c4bbdfSmrg                time = GetTimeInMillis();
53235c4bbdfSmrg                bn.type = XkbEventCode + XkbEventBase;
53335c4bbdfSmrg                bn.xkbType = XkbBellNotify;
53435c4bbdfSmrg                bn.deviceID = kbd->id;
53535c4bbdfSmrg                bn.bellClass = class;
53635c4bbdfSmrg                bn.bellID = id;
53735c4bbdfSmrg                bn.percent = percent;
53835c4bbdfSmrg                bn.eventOnly = (eventOnly != 0);
53935c4bbdfSmrg                winID = (pWin ? pWin->drawable.id : None);
54035c4bbdfSmrg                initialized = 1;
54135c4bbdfSmrg            }
54235c4bbdfSmrg            bn.sequenceNumber = interest->client->sequence;
54335c4bbdfSmrg            bn.time = time;
54435c4bbdfSmrg            bn.pitch = pitch;
54535c4bbdfSmrg            bn.duration = duration;
54635c4bbdfSmrg            bn.name = name;
54735c4bbdfSmrg            bn.window = winID;
54835c4bbdfSmrg            if (interest->client->swapped) {
54935c4bbdfSmrg                swaps(&bn.sequenceNumber);
55035c4bbdfSmrg                swapl(&bn.time);
55135c4bbdfSmrg                swaps(&bn.pitch);
55235c4bbdfSmrg                swaps(&bn.duration);
55335c4bbdfSmrg                swapl(&bn.name);
55435c4bbdfSmrg                swapl(&bn.window);
55535c4bbdfSmrg            }
55635c4bbdfSmrg            WriteToClient(interest->client, sizeof(xEvent), &bn);
55735c4bbdfSmrg        }
55835c4bbdfSmrg        interest = interest->next;
55905b261ecSmrg    }
56005b261ecSmrg    return;
56105b261ecSmrg}
56205b261ecSmrg
56305b261ecSmrgvoid
56435c4bbdfSmrgXkbSendAccessXNotify(DeviceIntPtr kbd, xkbAccessXNotify * pEv)
56505b261ecSmrg{
56635c4bbdfSmrg    int initialized;
56735c4bbdfSmrg    XkbInterestPtr interest;
56835c4bbdfSmrg    Time time = 0;
56935c4bbdfSmrg    CARD16 sk_delay, db_delay;
57005b261ecSmrg
57105b261ecSmrg    interest = kbd->xkb_interest;
57205b261ecSmrg    if (!interest)
57335c4bbdfSmrg        return;
57435c4bbdfSmrg
57505b261ecSmrg    initialized = 0;
57635c4bbdfSmrg    sk_delay = pEv->slowKeysDelay;
57735c4bbdfSmrg    db_delay = pEv->debounceDelay;
57805b261ecSmrg    while (interest) {
57935c4bbdfSmrg        if ((!interest->client->clientGone) &&
58035c4bbdfSmrg            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
58135c4bbdfSmrg            (interest->accessXNotifyMask & (1 << pEv->detail))) {
58235c4bbdfSmrg            if (!initialized) {
58335c4bbdfSmrg                pEv->type = XkbEventCode + XkbEventBase;
58435c4bbdfSmrg                pEv->xkbType = XkbAccessXNotify;
58535c4bbdfSmrg                pEv->deviceID = kbd->id;
58635c4bbdfSmrg                pEv->time = time = GetTimeInMillis();
58735c4bbdfSmrg                initialized = 1;
58835c4bbdfSmrg            }
58935c4bbdfSmrg            pEv->sequenceNumber = interest->client->sequence;
59035c4bbdfSmrg            pEv->time = time;
59135c4bbdfSmrg            pEv->slowKeysDelay = sk_delay;
59235c4bbdfSmrg            pEv->debounceDelay = db_delay;
59335c4bbdfSmrg            if (interest->client->swapped) {
59435c4bbdfSmrg                swaps(&pEv->sequenceNumber);
59535c4bbdfSmrg                swapl(&pEv->time);
59635c4bbdfSmrg                swaps(&pEv->slowKeysDelay);
59735c4bbdfSmrg                swaps(&pEv->debounceDelay);
59835c4bbdfSmrg            }
59935c4bbdfSmrg            WriteToClient(interest->client, sizeof(xEvent), pEv);
60035c4bbdfSmrg        }
60135c4bbdfSmrg        interest = interest->next;
60205b261ecSmrg    }
60305b261ecSmrg    return;
60405b261ecSmrg}
60505b261ecSmrg
60605b261ecSmrgvoid
60735c4bbdfSmrgXkbSendNamesNotify(DeviceIntPtr kbd, xkbNamesNotify * pEv)
60805b261ecSmrg{
60935c4bbdfSmrg    int initialized;
61035c4bbdfSmrg    XkbInterestPtr interest;
61135c4bbdfSmrg    Time time = 0;
61235c4bbdfSmrg    CARD16 changed, changedVirtualMods;
61335c4bbdfSmrg    CARD32 changedIndicators;
61405b261ecSmrg
61505b261ecSmrg    interest = kbd->xkb_interest;
61605b261ecSmrg    if (!interest)
61735c4bbdfSmrg        return;
61835c4bbdfSmrg
61905b261ecSmrg    initialized = 0;
62035c4bbdfSmrg    changed = pEv->changed;
62135c4bbdfSmrg    changedIndicators = pEv->changedIndicators;
62235c4bbdfSmrg    changedVirtualMods = pEv->changedVirtualMods;
62305b261ecSmrg    while (interest) {
62435c4bbdfSmrg        if ((!interest->client->clientGone) &&
62535c4bbdfSmrg            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
62635c4bbdfSmrg            (interest->namesNotifyMask & pEv->changed)) {
62735c4bbdfSmrg            if (!initialized) {
62835c4bbdfSmrg                pEv->type = XkbEventCode + XkbEventBase;
62935c4bbdfSmrg                pEv->xkbType = XkbNamesNotify;
63035c4bbdfSmrg                pEv->deviceID = kbd->id;
63135c4bbdfSmrg                pEv->time = time = GetTimeInMillis();
63235c4bbdfSmrg                initialized = 1;
63335c4bbdfSmrg            }
63435c4bbdfSmrg            pEv->sequenceNumber = interest->client->sequence;
63535c4bbdfSmrg            pEv->time = time;
63635c4bbdfSmrg            pEv->changed = changed;
63735c4bbdfSmrg            pEv->changedIndicators = changedIndicators;
63835c4bbdfSmrg            pEv->changedVirtualMods = changedVirtualMods;
63935c4bbdfSmrg            if (interest->client->swapped) {
64035c4bbdfSmrg                swaps(&pEv->sequenceNumber);
64135c4bbdfSmrg                swapl(&pEv->time);
64235c4bbdfSmrg                swaps(&pEv->changed);
64335c4bbdfSmrg                swapl(&pEv->changedIndicators);
64435c4bbdfSmrg                swaps(&pEv->changedVirtualMods);
64535c4bbdfSmrg            }
64635c4bbdfSmrg            WriteToClient(interest->client, sizeof(xEvent), pEv);
64735c4bbdfSmrg        }
64835c4bbdfSmrg        interest = interest->next;
64905b261ecSmrg    }
65005b261ecSmrg    return;
65105b261ecSmrg}
65205b261ecSmrg
65305b261ecSmrgvoid
65435c4bbdfSmrgXkbSendCompatMapNotify(DeviceIntPtr kbd, xkbCompatMapNotify * pEv)
65505b261ecSmrg{
65635c4bbdfSmrg    int initialized;
65735c4bbdfSmrg    XkbInterestPtr interest;
65835c4bbdfSmrg    Time time = 0;
65935c4bbdfSmrg    CARD16 firstSI = 0, nSI = 0, nTotalSI = 0;
66005b261ecSmrg
66105b261ecSmrg    interest = kbd->xkb_interest;
66205b261ecSmrg    if (!interest)
66335c4bbdfSmrg        return;
66435c4bbdfSmrg
66505b261ecSmrg    initialized = 0;
66605b261ecSmrg    while (interest) {
66735c4bbdfSmrg        if ((!interest->client->clientGone) &&
66835c4bbdfSmrg            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
66935c4bbdfSmrg            (interest->compatNotifyMask)) {
67035c4bbdfSmrg            if (!initialized) {
67135c4bbdfSmrg                pEv->type = XkbEventCode + XkbEventBase;
67235c4bbdfSmrg                pEv->xkbType = XkbCompatMapNotify;
67335c4bbdfSmrg                pEv->deviceID = kbd->id;
67435c4bbdfSmrg                pEv->time = time = GetTimeInMillis();
67535c4bbdfSmrg                firstSI = pEv->firstSI;
67635c4bbdfSmrg                nSI = pEv->nSI;
67735c4bbdfSmrg                nTotalSI = pEv->nTotalSI;
67835c4bbdfSmrg                initialized = 1;
67935c4bbdfSmrg            }
68035c4bbdfSmrg            pEv->sequenceNumber = interest->client->sequence;
68135c4bbdfSmrg            pEv->time = time;
68235c4bbdfSmrg            pEv->firstSI = firstSI;
68335c4bbdfSmrg            pEv->nSI = nSI;
68435c4bbdfSmrg            pEv->nTotalSI = nTotalSI;
68535c4bbdfSmrg            if (interest->client->swapped) {
68635c4bbdfSmrg                swaps(&pEv->sequenceNumber);
68735c4bbdfSmrg                swapl(&pEv->time);
68835c4bbdfSmrg                swaps(&pEv->firstSI);
68935c4bbdfSmrg                swaps(&pEv->nSI);
69035c4bbdfSmrg                swaps(&pEv->nTotalSI);
69135c4bbdfSmrg            }
69235c4bbdfSmrg            WriteToClient(interest->client, sizeof(xEvent), pEv);
69335c4bbdfSmrg        }
69435c4bbdfSmrg        interest = interest->next;
69505b261ecSmrg    }
69605b261ecSmrg    return;
69705b261ecSmrg}
69805b261ecSmrg
69905b261ecSmrgvoid
70035c4bbdfSmrgXkbSendActionMessage(DeviceIntPtr kbd, xkbActionMessage * pEv)
70105b261ecSmrg{
70235c4bbdfSmrg    int initialized;
70335c4bbdfSmrg    XkbSrvInfoPtr xkbi;
70435c4bbdfSmrg    XkbInterestPtr interest;
70535c4bbdfSmrg    Time time = 0;
70605b261ecSmrg
70705b261ecSmrg    interest = kbd->xkb_interest;
7084642e01fSmrg    if (!interest || !kbd->key || !kbd->key->xkbInfo)
70935c4bbdfSmrg        return;
71035c4bbdfSmrg
7114642e01fSmrg    xkbi = kbd->key->xkbInfo;
7124642e01fSmrg
71305b261ecSmrg    initialized = 0;
71435c4bbdfSmrg    pEv->mods = xkbi->state.mods;
71535c4bbdfSmrg    pEv->group = xkbi->state.group;
71605b261ecSmrg    while (interest) {
71735c4bbdfSmrg        if ((!interest->client->clientGone) &&
71835c4bbdfSmrg            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
71935c4bbdfSmrg            (interest->actionMessageMask)) {
72035c4bbdfSmrg            if (!initialized) {
72135c4bbdfSmrg                pEv->type = XkbEventCode + XkbEventBase;
72235c4bbdfSmrg                pEv->xkbType = XkbActionMessage;
72335c4bbdfSmrg                pEv->deviceID = kbd->id;
72435c4bbdfSmrg                pEv->sequenceNumber = interest->client->sequence;
72535c4bbdfSmrg                pEv->time = time = GetTimeInMillis();
72635c4bbdfSmrg                initialized = 1;
72735c4bbdfSmrg            }
72835c4bbdfSmrg            pEv->sequenceNumber = interest->client->sequence;
72935c4bbdfSmrg            pEv->time = time;
73035c4bbdfSmrg            if (interest->client->swapped) {
73135c4bbdfSmrg                swaps(&pEv->sequenceNumber);
73235c4bbdfSmrg                swapl(&pEv->time);
73335c4bbdfSmrg            }
73435c4bbdfSmrg            WriteToClient(interest->client, sizeof(xEvent), pEv);
73535c4bbdfSmrg        }
73635c4bbdfSmrg        interest = interest->next;
73705b261ecSmrg    }
73805b261ecSmrg    return;
73905b261ecSmrg}
74005b261ecSmrg
74105b261ecSmrgvoid
74235c4bbdfSmrgXkbSendExtensionDeviceNotify(DeviceIntPtr dev,
74335c4bbdfSmrg                             ClientPtr client, xkbExtensionDeviceNotify * pEv)
74405b261ecSmrg{
74535c4bbdfSmrg    int initialized;
74635c4bbdfSmrg    XkbInterestPtr interest;
74735c4bbdfSmrg    Time time = 0;
74835c4bbdfSmrg    CARD32 defined, state;
74935c4bbdfSmrg    CARD16 reason;
75005b261ecSmrg
75105b261ecSmrg    interest = dev->xkb_interest;
75205b261ecSmrg    if (!interest)
75335c4bbdfSmrg        return;
75435c4bbdfSmrg
75505b261ecSmrg    initialized = 0;
75635c4bbdfSmrg    reason = pEv->reason;
75735c4bbdfSmrg    defined = pEv->ledsDefined;
75835c4bbdfSmrg    state = pEv->ledState;
75905b261ecSmrg    while (interest) {
76035c4bbdfSmrg        if ((!interest->client->clientGone) &&
76135c4bbdfSmrg            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
76235c4bbdfSmrg            (interest->extDevNotifyMask & reason)) {
76335c4bbdfSmrg            if (!initialized) {
76435c4bbdfSmrg                pEv->type = XkbEventCode + XkbEventBase;
76535c4bbdfSmrg                pEv->xkbType = XkbExtensionDeviceNotify;
76635c4bbdfSmrg                pEv->deviceID = dev->id;
76735c4bbdfSmrg                pEv->sequenceNumber = interest->client->sequence;
76835c4bbdfSmrg                pEv->time = time = GetTimeInMillis();
76935c4bbdfSmrg                initialized = 1;
77035c4bbdfSmrg            }
77135c4bbdfSmrg            else {
77235c4bbdfSmrg                pEv->sequenceNumber = interest->client->sequence;
77335c4bbdfSmrg                pEv->time = time;
77435c4bbdfSmrg                pEv->ledsDefined = defined;
77535c4bbdfSmrg                pEv->ledState = state;
77635c4bbdfSmrg                pEv->reason = reason;
77735c4bbdfSmrg                pEv->supported = XkbXI_AllFeaturesMask;
77835c4bbdfSmrg            }
77935c4bbdfSmrg            if (interest->client->swapped) {
78035c4bbdfSmrg                swaps(&pEv->sequenceNumber);
78135c4bbdfSmrg                swapl(&pEv->time);
78235c4bbdfSmrg                swapl(&pEv->ledsDefined);
78335c4bbdfSmrg                swapl(&pEv->ledState);
78435c4bbdfSmrg                swaps(&pEv->reason);
78535c4bbdfSmrg                swaps(&pEv->supported);
78635c4bbdfSmrg            }
78735c4bbdfSmrg            WriteToClient(interest->client, sizeof(xEvent), pEv);
78835c4bbdfSmrg        }
78935c4bbdfSmrg        interest = interest->next;
79005b261ecSmrg    }
79105b261ecSmrg    return;
79205b261ecSmrg}
79305b261ecSmrg
79405b261ecSmrgvoid
79535c4bbdfSmrgXkbSendNotification(DeviceIntPtr kbd,
79635c4bbdfSmrg                    XkbChangesPtr pChanges, XkbEventCausePtr cause)
79705b261ecSmrg{
79835c4bbdfSmrg    XkbSrvLedInfoPtr sli;
79905b261ecSmrg
80035c4bbdfSmrg    sli = NULL;
80105b261ecSmrg    if (pChanges->state_changes) {
80235c4bbdfSmrg        xkbStateNotify sn;
80335c4bbdfSmrg
80435c4bbdfSmrg        sn.changed = pChanges->state_changes;
80535c4bbdfSmrg        sn.keycode = cause->kc;
80635c4bbdfSmrg        sn.eventType = cause->event;
80735c4bbdfSmrg        sn.requestMajor = cause->mjr;
80835c4bbdfSmrg        sn.requestMinor = cause->mnr;
80935c4bbdfSmrg        XkbSendStateNotify(kbd, &sn);
81005b261ecSmrg    }
81105b261ecSmrg    if (pChanges->map.changed) {
81235c4bbdfSmrg        xkbMapNotify mn;
81335c4bbdfSmrg
81435c4bbdfSmrg        memset(&mn, 0, sizeof(xkbMapNotify));
81535c4bbdfSmrg        mn.changed = pChanges->map.changed;
81635c4bbdfSmrg        mn.firstType = pChanges->map.first_type;
81735c4bbdfSmrg        mn.nTypes = pChanges->map.num_types;
81835c4bbdfSmrg        mn.firstKeySym = pChanges->map.first_key_sym;
81935c4bbdfSmrg        mn.nKeySyms = pChanges->map.num_key_syms;
82035c4bbdfSmrg        mn.firstKeyAct = pChanges->map.first_key_act;
82135c4bbdfSmrg        mn.nKeyActs = pChanges->map.num_key_acts;
82235c4bbdfSmrg        mn.firstKeyBehavior = pChanges->map.first_key_behavior;
82335c4bbdfSmrg        mn.nKeyBehaviors = pChanges->map.num_key_behaviors;
82435c4bbdfSmrg        mn.virtualMods = pChanges->map.vmods;
82535c4bbdfSmrg        mn.firstKeyExplicit = pChanges->map.first_key_explicit;
82635c4bbdfSmrg        mn.nKeyExplicit = pChanges->map.num_key_explicit;
82735c4bbdfSmrg        mn.firstModMapKey = pChanges->map.first_modmap_key;
82835c4bbdfSmrg        mn.nModMapKeys = pChanges->map.num_modmap_keys;
82935c4bbdfSmrg        mn.firstVModMapKey = pChanges->map.first_vmodmap_key;
83035c4bbdfSmrg        mn.nVModMapKeys = pChanges->map.num_vmodmap_keys;
83135c4bbdfSmrg        XkbSendMapNotify(kbd, &mn);
83205b261ecSmrg    }
83335c4bbdfSmrg    if ((pChanges->ctrls.changed_ctrls) ||
83435c4bbdfSmrg        (pChanges->ctrls.enabled_ctrls_changes)) {
83535c4bbdfSmrg        xkbControlsNotify cn;
83635c4bbdfSmrg
83735c4bbdfSmrg        memset(&cn, 0, sizeof(xkbControlsNotify));
83835c4bbdfSmrg        cn.changedControls = pChanges->ctrls.changed_ctrls;
83935c4bbdfSmrg        cn.enabledControlChanges = pChanges->ctrls.enabled_ctrls_changes;
84035c4bbdfSmrg        cn.keycode = cause->kc;
84135c4bbdfSmrg        cn.eventType = cause->event;
84235c4bbdfSmrg        cn.requestMajor = cause->mjr;
84335c4bbdfSmrg        cn.requestMinor = cause->mnr;
84435c4bbdfSmrg        XkbSendControlsNotify(kbd, &cn);
84505b261ecSmrg    }
84605b261ecSmrg    if (pChanges->indicators.map_changes) {
84735c4bbdfSmrg        xkbIndicatorNotify in;
84835c4bbdfSmrg
84935c4bbdfSmrg        if (sli == NULL)
85035c4bbdfSmrg            sli = XkbFindSrvLedInfo(kbd, XkbDfltXIClass, XkbDfltXIId, 0);
85135c4bbdfSmrg        memset(&in, 0, sizeof(xkbIndicatorNotify));
85235c4bbdfSmrg        in.state = sli->effectiveState;
85335c4bbdfSmrg        in.changed = pChanges->indicators.map_changes;
85435c4bbdfSmrg        XkbSendIndicatorNotify(kbd, XkbIndicatorMapNotify, &in);
85505b261ecSmrg    }
85605b261ecSmrg    if (pChanges->indicators.state_changes) {
85735c4bbdfSmrg        xkbIndicatorNotify in;
85835c4bbdfSmrg
85935c4bbdfSmrg        if (sli == NULL)
86035c4bbdfSmrg            sli = XkbFindSrvLedInfo(kbd, XkbDfltXIClass, XkbDfltXIId, 0);
86135c4bbdfSmrg        memset(&in, 0, sizeof(xkbIndicatorNotify));
86235c4bbdfSmrg        in.state = sli->effectiveState;
86335c4bbdfSmrg        in.changed = pChanges->indicators.state_changes;
86435c4bbdfSmrg        XkbSendIndicatorNotify(kbd, XkbIndicatorStateNotify, &in);
86505b261ecSmrg    }
86605b261ecSmrg    if (pChanges->names.changed) {
86735c4bbdfSmrg        xkbNamesNotify nn;
86835c4bbdfSmrg
86935c4bbdfSmrg        memset(&nn, 0, sizeof(xkbNamesNotify));
87035c4bbdfSmrg        nn.changed = pChanges->names.changed;
87135c4bbdfSmrg        nn.firstType = pChanges->names.first_type;
87235c4bbdfSmrg        nn.nTypes = pChanges->names.num_types;
87335c4bbdfSmrg        nn.firstLevelName = pChanges->names.first_lvl;
87435c4bbdfSmrg        nn.nLevelNames = pChanges->names.num_lvls;
87535c4bbdfSmrg        nn.nRadioGroups = pChanges->names.num_rg;
87635c4bbdfSmrg        nn.changedVirtualMods = pChanges->names.changed_vmods;
87735c4bbdfSmrg        nn.changedIndicators = pChanges->names.changed_indicators;
87835c4bbdfSmrg        XkbSendNamesNotify(kbd, &nn);
87905b261ecSmrg    }
88035c4bbdfSmrg    if ((pChanges->compat.changed_groups) || (pChanges->compat.num_si > 0)) {
88135c4bbdfSmrg        xkbCompatMapNotify cmn;
88235c4bbdfSmrg
88335c4bbdfSmrg        memset(&cmn, 0, sizeof(xkbCompatMapNotify));
88435c4bbdfSmrg        cmn.changedGroups = pChanges->compat.changed_groups;
88535c4bbdfSmrg        cmn.firstSI = pChanges->compat.first_si;
88635c4bbdfSmrg        cmn.nSI = pChanges->compat.num_si;
88735c4bbdfSmrg        cmn.nTotalSI = kbd->key->xkbInfo->desc->compat->num_si;
88835c4bbdfSmrg        XkbSendCompatMapNotify(kbd, &cmn);
88905b261ecSmrg    }
89005b261ecSmrg    return;
89105b261ecSmrg}
89205b261ecSmrg
89305b261ecSmrg/***====================================================================***/
89405b261ecSmrg
8956747b715Smrgvoid
89635c4bbdfSmrgXkbFilterEvents(ClientPtr client, int nEvents, xEvent *xE)
89705b261ecSmrg{
8986747b715Smrg    DeviceIntPtr dev = NULL;
8996747b715Smrg    XkbSrvInfoPtr xkbi;
9006747b715Smrg    CARD8 type = xE[0].u.u.type;
90105b261ecSmrg
9024642e01fSmrg    if (xE->u.u.type & EXTENSION_EVENT_BASE)
9036747b715Smrg        dev = XIGetDevice(xE);
9044642e01fSmrg
9056747b715Smrg    if (!dev)
9066747b715Smrg        dev = PickKeyboard(client);
9074642e01fSmrg
9086747b715Smrg    if (!dev->key)
9096747b715Smrg        return;
9104642e01fSmrg
9116747b715Smrg    xkbi = dev->key->xkbInfo;
91205b261ecSmrg
9136747b715Smrg    if (client->xkbClientFlags & _XkbClientInitialized) {
91435c4bbdfSmrg        if ((xkbDebugFlags & 0x10) &&
9156747b715Smrg            (type == KeyPress || type == KeyRelease ||
9166747b715Smrg             type == DeviceKeyPress || type == DeviceKeyRelease))
91735c4bbdfSmrg            DebugF("[xkb] XkbFilterWriteEvents (XKB client): state 0x%04x\n",
9186747b715Smrg                   xE[0].u.keyButtonPointer.state);
9196747b715Smrg
92035c4bbdfSmrg        if (dev->deviceGrab.grab != NullGrab && dev->deviceGrab.fromPassiveGrab
92135c4bbdfSmrg            && (type == KeyPress || type == KeyRelease || type == DeviceKeyPress
92235c4bbdfSmrg                || type == DeviceKeyRelease)) {
92335c4bbdfSmrg            unsigned int state, flags;
92435c4bbdfSmrg
92535c4bbdfSmrg            flags = client->xkbClientFlags;
92635c4bbdfSmrg            state = xkbi->state.compat_grab_mods;
92735c4bbdfSmrg            if (flags & XkbPCF_GrabsUseXKBStateMask) {
92835c4bbdfSmrg                int group;
92935c4bbdfSmrg
93035c4bbdfSmrg                if (flags & XkbPCF_LookupStateWhenGrabbed) {
93135c4bbdfSmrg                    group = xkbi->state.group;
93235c4bbdfSmrg                    state = xkbi->state.lookup_mods;
93335c4bbdfSmrg                }
93435c4bbdfSmrg                else {
93535c4bbdfSmrg                    state = xkbi->state.grab_mods;
93635c4bbdfSmrg                    group = xkbi->state.base_group + xkbi->state.latched_group;
93735c4bbdfSmrg                    if (group < 0 || group >= xkbi->desc->ctrls->num_groups)
93835c4bbdfSmrg                        group = XkbAdjustGroup(group, xkbi->desc->ctrls);
93935c4bbdfSmrg                }
94035c4bbdfSmrg                state = XkbBuildCoreState(state, group);
94135c4bbdfSmrg            }
94235c4bbdfSmrg            else if (flags & XkbPCF_LookupStateWhenGrabbed) {
94335c4bbdfSmrg                state = xkbi->state.compat_lookup_mods;
9446747b715Smrg            }
94535c4bbdfSmrg            xE[0].u.keyButtonPointer.state = state;
94635c4bbdfSmrg        }
94705b261ecSmrg    }
94805b261ecSmrg    else {
9496747b715Smrg        if ((xkbDebugFlags & 0x4) &&
95035c4bbdfSmrg            (xE[0].u.u.type == KeyPress || xE[0].u.u.type == KeyRelease ||
9516747b715Smrg             xE[0].u.u.type == DeviceKeyPress ||
9526747b715Smrg             xE[0].u.u.type == DeviceKeyRelease)) {
95335c4bbdfSmrg            DebugF("[xkb] XKbFilterWriteEvents (non-XKB):\n");
95435c4bbdfSmrg            DebugF("[xkb] event= 0x%04x\n", xE[0].u.keyButtonPointer.state);
95535c4bbdfSmrg            DebugF("[xkb] lookup= 0x%02x, grab= 0x%02x\n",
9566747b715Smrg                   xkbi->state.lookup_mods, xkbi->state.grab_mods);
95735c4bbdfSmrg            DebugF("[xkb] compat lookup= 0x%02x, grab= 0x%02x\n",
95835c4bbdfSmrg                   xkbi->state.compat_lookup_mods,
95935c4bbdfSmrg                   xkbi->state.compat_grab_mods);
96035c4bbdfSmrg        }
96135c4bbdfSmrg        if (type >= KeyPress && type <= MotionNotify) {
96235c4bbdfSmrg            CARD16 old, new;
96335c4bbdfSmrg
96435c4bbdfSmrg            old = xE[0].u.keyButtonPointer.state & ~0x1f00;
96535c4bbdfSmrg            new = xE[0].u.keyButtonPointer.state & 0x1F00;
96635c4bbdfSmrg
96735c4bbdfSmrg            if (old == XkbStateFieldFromRec(&xkbi->state))
96835c4bbdfSmrg                new |= xkbi->state.compat_lookup_mods;
96935c4bbdfSmrg            else
9706747b715Smrg                new |= xkbi->state.compat_grab_mods;
97135c4bbdfSmrg            xE[0].u.keyButtonPointer.state = new;
97235c4bbdfSmrg        }
97335c4bbdfSmrg        else if (type == EnterNotify || type == LeaveNotify) {
97435c4bbdfSmrg            xE[0].u.enterLeave.state &= 0x1F00;
97535c4bbdfSmrg            xE[0].u.enterLeave.state |= xkbi->state.compat_grab_mods;
97635c4bbdfSmrg        }
9776747b715Smrg        else if (type >= DeviceKeyPress && type <= DeviceMotionNotify) {
9786747b715Smrg            CARD16 old, new;
97935c4bbdfSmrg            deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer *) &xE[0];
9806747b715Smrg
9816747b715Smrg            old = kbp->state & ~0x1F00;
9826747b715Smrg            new = kbp->state & 0x1F00;
98335c4bbdfSmrg            if (old == XkbStateFieldFromRec(&xkbi->state))
98435c4bbdfSmrg                new |= xkbi->state.compat_lookup_mods;
98535c4bbdfSmrg            else
9866747b715Smrg                new |= xkbi->state.compat_grab_mods;
9876747b715Smrg            kbp->state = new;
9886747b715Smrg        }
98905b261ecSmrg    }
99005b261ecSmrg}
99105b261ecSmrg
99205b261ecSmrg/***====================================================================***/
99305b261ecSmrg
9946747b715SmrgXkbInterestPtr
99535c4bbdfSmrgXkbFindClientResource(DevicePtr inDev, ClientPtr client)
99605b261ecSmrg{
99735c4bbdfSmrg    DeviceIntPtr dev = (DeviceIntPtr) inDev;
99835c4bbdfSmrg    XkbInterestPtr interest;
99935c4bbdfSmrg
100035c4bbdfSmrg    if (dev->xkb_interest) {
100135c4bbdfSmrg        interest = dev->xkb_interest;
100235c4bbdfSmrg        while (interest) {
100335c4bbdfSmrg            if (interest->client == client) {
100435c4bbdfSmrg                return interest;
100535c4bbdfSmrg            }
100635c4bbdfSmrg            interest = interest->next;
100735c4bbdfSmrg        }
100805b261ecSmrg    }
100905b261ecSmrg    return NULL;
101005b261ecSmrg}
101105b261ecSmrg
10126747b715SmrgXkbInterestPtr
101335c4bbdfSmrgXkbAddClientResource(DevicePtr inDev, ClientPtr client, XID id)
101405b261ecSmrg{
101535c4bbdfSmrg    DeviceIntPtr dev = (DeviceIntPtr) inDev;
101635c4bbdfSmrg    XkbInterestPtr interest;
101705b261ecSmrg
101805b261ecSmrg    interest = dev->xkb_interest;
101905b261ecSmrg    while (interest) {
102035c4bbdfSmrg        if (interest->client == client)
102135c4bbdfSmrg            return ((interest->resource == id) ? interest : NULL);
102235c4bbdfSmrg        interest = interest->next;
102305b261ecSmrg    }
10246747b715Smrg    interest = calloc(1, sizeof(XkbInterestRec));
102505b261ecSmrg    if (interest) {
102635c4bbdfSmrg        interest->dev = dev;
102735c4bbdfSmrg        interest->client = client;
102835c4bbdfSmrg        interest->resource = id;
102935c4bbdfSmrg        interest->next = dev->xkb_interest;
103035c4bbdfSmrg        dev->xkb_interest = interest;
103135c4bbdfSmrg        return interest;
103205b261ecSmrg    }
103305b261ecSmrg    return NULL;
103405b261ecSmrg}
103505b261ecSmrg
103605b261ecSmrgint
103735c4bbdfSmrgXkbRemoveResourceClient(DevicePtr inDev, XID id)
103805b261ecSmrg{
103935c4bbdfSmrg    XkbSrvInfoPtr xkbi;
104035c4bbdfSmrg    DeviceIntPtr dev = (DeviceIntPtr) inDev;
104135c4bbdfSmrg    XkbInterestPtr interest;
104235c4bbdfSmrg    Bool found;
104335c4bbdfSmrg    unsigned long autoCtrls, autoValues;
104435c4bbdfSmrg    ClientPtr client = NULL;
104505b261ecSmrg
104635c4bbdfSmrg    found = FALSE;
10474642e01fSmrg
10484642e01fSmrg    if (!dev->key || !dev->key->xkbInfo)
10494642e01fSmrg        return found;
10504642e01fSmrg
105135c4bbdfSmrg    autoCtrls = autoValues = 0;
105235c4bbdfSmrg    if (dev->xkb_interest) {
105335c4bbdfSmrg        interest = dev->xkb_interest;
105435c4bbdfSmrg        if (interest && (interest->resource == id)) {
105535c4bbdfSmrg            dev->xkb_interest = interest->next;
105635c4bbdfSmrg            autoCtrls = interest->autoCtrls;
105735c4bbdfSmrg            autoValues = interest->autoCtrlValues;
105835c4bbdfSmrg            client = interest->client;
105935c4bbdfSmrg            free(interest);
106035c4bbdfSmrg            found = TRUE;
106135c4bbdfSmrg        }
106235c4bbdfSmrg        while ((!found) && (interest->next)) {
106335c4bbdfSmrg            if (interest->next->resource == id) {
106435c4bbdfSmrg                XkbInterestPtr victim = interest->next;
106535c4bbdfSmrg
106635c4bbdfSmrg                interest->next = victim->next;
106735c4bbdfSmrg                autoCtrls = victim->autoCtrls;
106835c4bbdfSmrg                autoValues = victim->autoCtrlValues;
106935c4bbdfSmrg                client = victim->client;
107035c4bbdfSmrg                free(victim);
107135c4bbdfSmrg                found = TRUE;
107235c4bbdfSmrg            }
107335c4bbdfSmrg            interest = interest->next;
107435c4bbdfSmrg        }
107505b261ecSmrg    }
107635c4bbdfSmrg    if (found && autoCtrls && dev->key && dev->key->xkbInfo) {
107735c4bbdfSmrg        XkbEventCauseRec cause;
107805b261ecSmrg
107935c4bbdfSmrg        xkbi = dev->key->xkbInfo;
108035c4bbdfSmrg        XkbSetCauseXkbReq(&cause, X_kbPerClientFlags, client);
108135c4bbdfSmrg        XkbEnableDisableControls(xkbi, autoCtrls, autoValues, NULL, &cause);
108205b261ecSmrg    }
108305b261ecSmrg    return found;
108405b261ecSmrg}
1085