1084 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1084 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
	
/************************************************************
 | 
						|
Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
 | 
						|
 | 
						|
Permission to use, copy, modify, and distribute this
 | 
						|
software and its documentation for any purpose and without
 | 
						|
fee is hereby granted, provided that the above copyright
 | 
						|
notice appear in all copies and that both that copyright
 | 
						|
notice and this permission notice appear in supporting
 | 
						|
documentation, and that the name of Silicon Graphics not be
 | 
						|
used in advertising or publicity pertaining to distribution
 | 
						|
of the software without specific prior written permission.
 | 
						|
Silicon Graphics makes no representation about the suitability
 | 
						|
of this software for any purpose. It is provided "as is"
 | 
						|
without any express or implied warranty.
 | 
						|
 | 
						|
SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
 | 
						|
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 | 
						|
AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
 | 
						|
GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
 | 
						|
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 | 
						|
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 | 
						|
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
 | 
						|
THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
 | 
						|
********************************************************/
 | 
						|
 | 
						|
#include <dix-config.h>
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/Xproto.h>
 | 
						|
#include <X11/keysym.h>
 | 
						|
#include <X11/extensions/XI.h>
 | 
						|
#include <X11/extensions/XIproto.h>
 | 
						|
 | 
						|
#include "dix/exevents_priv.h"
 | 
						|
 | 
						|
#include "inputstr.h"
 | 
						|
#include "exglobals.h"
 | 
						|
#include "windowstr.h"
 | 
						|
#include "xkbsrv_priv.h"
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
 | 
						|
/*
 | 
						|
 * This function sends out two kinds of notification:
 | 
						|
 *   - Core mapping notify events sent to clients for whom kbd is the
 | 
						|
 *     current core ('picked') keyboard _and_ have not explicitly
 | 
						|
 *     selected for XKB mapping notify events;
 | 
						|
 *   - Xi mapping events, sent unconditionally to all clients who have
 | 
						|
 *     explicitly selected for them (including those who have explicitly
 | 
						|
 *     selected for XKB mapping notify events!).
 | 
						|
 */
 | 
						|
static void
 | 
						|
XkbSendLegacyMapNotify(DeviceIntPtr kbd, CARD16 xkb_event, CARD16 changed,
 | 
						|
                       int first_key, int num_keys)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    int keymap_changed = 0;
 | 
						|
    int modmap_changed = 0;
 | 
						|
    CARD32 time = GetTimeInMillis();
 | 
						|
 | 
						|
    if (xkb_event == XkbNewKeyboardNotify) {
 | 
						|
        if (changed & XkbNKN_KeycodesMask) {
 | 
						|
            keymap_changed = 1;
 | 
						|
            modmap_changed = 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else if (xkb_event == XkbMapNotify) {
 | 
						|
        if (changed & XkbKeySymsMask)
 | 
						|
            keymap_changed = 1;
 | 
						|
        if (changed & XkbModifierMapMask)
 | 
						|
            modmap_changed = 1;
 | 
						|
    }
 | 
						|
    if (!keymap_changed && !modmap_changed)
 | 
						|
        return;
 | 
						|
 | 
						|
    /* 0 is serverClient. */
 | 
						|
    for (i = 1; i < currentMaxClients; i++) {
 | 
						|
        if (!clients[i] || clients[i]->clientState != ClientStateRunning)
 | 
						|
            continue;
 | 
						|
 | 
						|
        /* XKB allows clients to restrict the MappingNotify events sent to
 | 
						|
         * them.  This was broken for three years.  Sorry. */
 | 
						|
        if (xkb_event == XkbMapNotify &&
 | 
						|
            (clients[i]->xkbClientFlags & _XkbClientInitialized) &&
 | 
						|
            !(clients[i]->mapNotifyMask & changed))
 | 
						|
            continue;
 | 
						|
        /* Emulate previous server behaviour: any client which has activated
 | 
						|
         * XKB will not receive core events emulated from a NewKeyboardNotify
 | 
						|
         * at all. */
 | 
						|
        if (xkb_event == XkbNewKeyboardNotify &&
 | 
						|
            (clients[i]->xkbClientFlags & _XkbClientInitialized))
 | 
						|
            continue;
 | 
						|
 | 
						|
        /* Don't send core events to clients who don't know about us. */
 | 
						|
        if (!XIShouldNotify(clients[i], kbd))
 | 
						|
            continue;
 | 
						|
 | 
						|
        if (keymap_changed) {
 | 
						|
            xEvent core_mn = { .u.u.type = MappingNotify };
 | 
						|
            core_mn.u.mappingNotify.request = MappingKeyboard;
 | 
						|
 | 
						|
            /* Clip the keycode range to what the client knows about, so it
 | 
						|
             * doesn't freak out. */
 | 
						|
            if (first_key >= clients[i]->minKC)
 | 
						|
                core_mn.u.mappingNotify.firstKeyCode = first_key;
 | 
						|
            else
 | 
						|
                core_mn.u.mappingNotify.firstKeyCode = clients[i]->minKC;
 | 
						|
            if (first_key + num_keys - 1 <= clients[i]->maxKC)
 | 
						|
                core_mn.u.mappingNotify.count = num_keys;
 | 
						|
            else
 | 
						|
                core_mn.u.mappingNotify.count = clients[i]->maxKC -
 | 
						|
                    clients[i]->minKC + 1;
 | 
						|
 | 
						|
            WriteEventsToClient(clients[i], 1, &core_mn);
 | 
						|
        }
 | 
						|
        if (modmap_changed) {
 | 
						|
            xEvent core_mn = {
 | 
						|
                .u.mappingNotify.request = MappingModifier,
 | 
						|
                .u.mappingNotify.firstKeyCode = 0,
 | 
						|
                .u.mappingNotify.count = 0
 | 
						|
            };
 | 
						|
            core_mn.u.u.type = MappingNotify;
 | 
						|
            WriteEventsToClient(clients[i], 1, &core_mn);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* Hmm, maybe we can accidentally generate Xi events for core devices
 | 
						|
     * here? Clients might be upset, but that seems better than the
 | 
						|
     * alternative of stale keymaps. -ds */
 | 
						|
    if (keymap_changed) {
 | 
						|
        deviceMappingNotify xi_mn = {
 | 
						|
            .type = DeviceMappingNotify,
 | 
						|
            .deviceid = kbd->id,
 | 
						|
            .request = MappingKeyboard,
 | 
						|
            .firstKeyCode = first_key,
 | 
						|
            .count = num_keys,
 | 
						|
            .time = time
 | 
						|
        };
 | 
						|
        SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn,
 | 
						|
                              1);
 | 
						|
    }
 | 
						|
    if (modmap_changed) {
 | 
						|
        deviceMappingNotify xi_mn = {
 | 
						|
            .type = DeviceMappingNotify,
 | 
						|
            .deviceid = kbd->id,
 | 
						|
            .request = MappingModifier,
 | 
						|
            .firstKeyCode = 0,
 | 
						|
            .count = 0,
 | 
						|
            .time = time
 | 
						|
        };
 | 
						|
        SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn,
 | 
						|
                              1);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
 | 
						|
void
 | 
						|
XkbSendNewKeyboardNotify(DeviceIntPtr kbd, xkbNewKeyboardNotify * pNKN)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    Time time = GetTimeInMillis();
 | 
						|
    CARD16 changed = pNKN->changed;
 | 
						|
 | 
						|
    pNKN->type = XkbEventCode + XkbEventBase;
 | 
						|
    pNKN->xkbType = XkbNewKeyboardNotify;
 | 
						|
 | 
						|
    for (i = 1; i < currentMaxClients; i++) {
 | 
						|
        if (!clients[i] || clients[i]->clientState != ClientStateRunning)
 | 
						|
            continue;
 | 
						|
 | 
						|
        if (!(clients[i]->newKeyboardNotifyMask & changed))
 | 
						|
            continue;
 | 
						|
 | 
						|
        pNKN->sequenceNumber = clients[i]->sequence;
 | 
						|
        pNKN->time = time;
 | 
						|
        pNKN->changed = changed;
 | 
						|
        if (clients[i]->swapped) {
 | 
						|
            swaps(&pNKN->sequenceNumber);
 | 
						|
            swapl(&pNKN->time);
 | 
						|
            swaps(&pNKN->changed);
 | 
						|
        }
 | 
						|
        WriteToClient(clients[i], sizeof(xEvent), pNKN);
 | 
						|
 | 
						|
        if (changed & XkbNKN_KeycodesMask) {
 | 
						|
            clients[i]->minKC = pNKN->minKeyCode;
 | 
						|
            clients[i]->maxKC = pNKN->maxKeyCode;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    XkbSendLegacyMapNotify(kbd, XkbNewKeyboardNotify, changed, pNKN->minKeyCode,
 | 
						|
                           pNKN->maxKeyCode - pNKN->minKeyCode + 1);
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
 | 
						|
void
 | 
						|
XkbSendStateNotify(DeviceIntPtr kbd, xkbStateNotify * pSN)
 | 
						|
{
 | 
						|
    XkbSrvInfoPtr xkbi;
 | 
						|
    XkbStatePtr state;
 | 
						|
    XkbInterestPtr interest;
 | 
						|
    Time time;
 | 
						|
    register CARD16 changed, bState;
 | 
						|
 | 
						|
    interest = kbd->xkb_interest;
 | 
						|
    if (!interest || !kbd->key || !kbd->key->xkbInfo)
 | 
						|
        return;
 | 
						|
    xkbi = kbd->key->xkbInfo;
 | 
						|
    state = &xkbi->state;
 | 
						|
 | 
						|
    pSN->type = XkbEventCode + XkbEventBase;
 | 
						|
    pSN->xkbType = XkbStateNotify;
 | 
						|
    pSN->deviceID = kbd->id;
 | 
						|
    pSN->time = time = GetTimeInMillis();
 | 
						|
    pSN->mods = state->mods;
 | 
						|
    pSN->baseMods = state->base_mods;
 | 
						|
    pSN->latchedMods = state->latched_mods;
 | 
						|
    pSN->lockedMods = state->locked_mods;
 | 
						|
    pSN->group = state->group;
 | 
						|
    pSN->baseGroup = state->base_group;
 | 
						|
    pSN->latchedGroup = state->latched_group;
 | 
						|
    pSN->lockedGroup = state->locked_group;
 | 
						|
    pSN->compatState = state->compat_state;
 | 
						|
    pSN->grabMods = state->grab_mods;
 | 
						|
    pSN->compatGrabMods = state->compat_grab_mods;
 | 
						|
    pSN->lookupMods = state->lookup_mods;
 | 
						|
    pSN->compatLookupMods = state->compat_lookup_mods;
 | 
						|
    pSN->ptrBtnState = state->ptr_buttons;
 | 
						|
    changed = pSN->changed;
 | 
						|
    bState = pSN->ptrBtnState;
 | 
						|
 | 
						|
    while (interest) {
 | 
						|
        if ((!interest->client->clientGone) &&
 | 
						|
            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
 | 
						|
            (interest->stateNotifyMask & changed)) {
 | 
						|
            pSN->sequenceNumber = interest->client->sequence;
 | 
						|
            pSN->time = time;
 | 
						|
            pSN->changed = changed;
 | 
						|
            pSN->ptrBtnState = bState;
 | 
						|
            if (interest->client->swapped) {
 | 
						|
                swaps(&pSN->sequenceNumber);
 | 
						|
                swapl(&pSN->time);
 | 
						|
                swaps(&pSN->changed);
 | 
						|
                swaps(&pSN->ptrBtnState);
 | 
						|
            }
 | 
						|
            WriteToClient(interest->client, sizeof(xEvent), pSN);
 | 
						|
        }
 | 
						|
        interest = interest->next;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
 | 
						|
/*
 | 
						|
 * This function sends out XKB mapping notify events to clients which
 | 
						|
 * have explicitly selected for them.  Core and Xi events are handled by
 | 
						|
 * XkbSendLegacyMapNotify. */
 | 
						|
void
 | 
						|
XkbSendMapNotify(DeviceIntPtr kbd, xkbMapNotify * pMN)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    CARD32 time = GetTimeInMillis();
 | 
						|
    CARD16 changed = pMN->changed;
 | 
						|
    XkbSrvInfoPtr xkbi = kbd->key->xkbInfo;
 | 
						|
 | 
						|
    pMN->minKeyCode = xkbi->desc->min_key_code;
 | 
						|
    pMN->maxKeyCode = xkbi->desc->max_key_code;
 | 
						|
    pMN->type = XkbEventCode + XkbEventBase;
 | 
						|
    pMN->xkbType = XkbMapNotify;
 | 
						|
    pMN->deviceID = kbd->id;
 | 
						|
 | 
						|
    /* 0 is serverClient. */
 | 
						|
    for (i = 1; i < currentMaxClients; i++) {
 | 
						|
        if (!clients[i] || clients[i]->clientState != ClientStateRunning)
 | 
						|
            continue;
 | 
						|
 | 
						|
        if (!(clients[i]->mapNotifyMask & changed))
 | 
						|
            continue;
 | 
						|
 | 
						|
        pMN->time = time;
 | 
						|
        pMN->sequenceNumber = clients[i]->sequence;
 | 
						|
        pMN->changed = changed;
 | 
						|
 | 
						|
        if (clients[i]->swapped) {
 | 
						|
            swaps(&pMN->sequenceNumber);
 | 
						|
            swapl(&pMN->time);
 | 
						|
            swaps(&pMN->changed);
 | 
						|
        }
 | 
						|
        WriteToClient(clients[i], sizeof(xEvent), pMN);
 | 
						|
    }
 | 
						|
 | 
						|
    XkbSendLegacyMapNotify(kbd, XkbMapNotify, changed, pMN->firstKeySym,
 | 
						|
                           pMN->nKeySyms);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XkbComputeControlsNotify(DeviceIntPtr kbd,
 | 
						|
                         XkbControlsPtr old,
 | 
						|
                         XkbControlsPtr new,
 | 
						|
                         xkbControlsNotify * pCN, Bool forceCtrlProc)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    CARD32 changedControls;
 | 
						|
 | 
						|
    changedControls = 0;
 | 
						|
 | 
						|
    if (!kbd || !kbd->kbdfeed)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    if (old->enabled_ctrls != new->enabled_ctrls)
 | 
						|
        changedControls |= XkbControlsEnabledMask;
 | 
						|
    if ((old->repeat_delay != new->repeat_delay) ||
 | 
						|
        (old->repeat_interval != new->repeat_interval))
 | 
						|
        changedControls |= XkbRepeatKeysMask;
 | 
						|
    for (i = 0; i < XkbPerKeyBitArraySize; i++)
 | 
						|
        if (old->per_key_repeat[i] != new->per_key_repeat[i])
 | 
						|
            changedControls |= XkbPerKeyRepeatMask;
 | 
						|
    if (old->slow_keys_delay != new->slow_keys_delay)
 | 
						|
        changedControls |= XkbSlowKeysMask;
 | 
						|
    if (old->debounce_delay != new->debounce_delay)
 | 
						|
        changedControls |= XkbBounceKeysMask;
 | 
						|
    if ((old->mk_delay != new->mk_delay) ||
 | 
						|
        (old->mk_interval != new->mk_interval) ||
 | 
						|
        (old->mk_dflt_btn != new->mk_dflt_btn))
 | 
						|
        changedControls |= XkbMouseKeysMask;
 | 
						|
    if ((old->mk_time_to_max != new->mk_time_to_max) ||
 | 
						|
        (old->mk_curve != new->mk_curve) ||
 | 
						|
        (old->mk_max_speed != new->mk_max_speed))
 | 
						|
        changedControls |= XkbMouseKeysAccelMask;
 | 
						|
    if (old->ax_options != new->ax_options)
 | 
						|
        changedControls |= XkbAccessXKeysMask;
 | 
						|
    if ((old->ax_options ^ new->ax_options) & XkbAX_SKOptionsMask)
 | 
						|
        changedControls |= XkbStickyKeysMask;
 | 
						|
    if ((old->ax_options ^ new->ax_options) & XkbAX_FBOptionsMask)
 | 
						|
        changedControls |= XkbAccessXFeedbackMask;
 | 
						|
    if ((old->ax_timeout != new->ax_timeout) ||
 | 
						|
        (old->axt_ctrls_mask != new->axt_ctrls_mask) ||
 | 
						|
        (old->axt_ctrls_values != new->axt_ctrls_values) ||
 | 
						|
        (old->axt_opts_mask != new->axt_opts_mask) ||
 | 
						|
        (old->axt_opts_values != new->axt_opts_values)) {
 | 
						|
        changedControls |= XkbAccessXTimeoutMask;
 | 
						|
    }
 | 
						|
    if ((old->internal.mask != new->internal.mask) ||
 | 
						|
        (old->internal.real_mods != new->internal.real_mods) ||
 | 
						|
        (old->internal.vmods != new->internal.vmods))
 | 
						|
        changedControls |= XkbInternalModsMask;
 | 
						|
    if ((old->ignore_lock.mask != new->ignore_lock.mask) ||
 | 
						|
        (old->ignore_lock.real_mods != new->ignore_lock.real_mods) ||
 | 
						|
        (old->ignore_lock.vmods != new->ignore_lock.vmods))
 | 
						|
        changedControls |= XkbIgnoreLockModsMask;
 | 
						|
 | 
						|
    if (new->enabled_ctrls & XkbRepeatKeysMask)
 | 
						|
        kbd->kbdfeed->ctrl.autoRepeat = TRUE;
 | 
						|
    else
 | 
						|
        kbd->kbdfeed->ctrl.autoRepeat = FALSE;
 | 
						|
 | 
						|
    if (kbd->kbdfeed && kbd->kbdfeed->CtrlProc &&
 | 
						|
        (changedControls || forceCtrlProc))
 | 
						|
        (*kbd->kbdfeed->CtrlProc) (kbd, &kbd->kbdfeed->ctrl);
 | 
						|
 | 
						|
    if ((!changedControls) && (old->num_groups == new->num_groups))
 | 
						|
        return 0;
 | 
						|
 | 
						|
    if (!kbd->xkb_interest)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    pCN->changedControls = changedControls;
 | 
						|
    pCN->enabledControls = new->enabled_ctrls;
 | 
						|
    pCN->enabledControlChanges = (new->enabled_ctrls ^ old->enabled_ctrls);
 | 
						|
    pCN->numGroups = new->num_groups;
 | 
						|
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
XkbSendControlsNotify(DeviceIntPtr kbd, xkbControlsNotify * pCN)
 | 
						|
{
 | 
						|
    int initialized;
 | 
						|
    CARD32 changedControls, enabledControls, enabledChanges = 0;
 | 
						|
    XkbSrvInfoPtr xkbi;
 | 
						|
    XkbInterestPtr interest;
 | 
						|
    Time time = 0;
 | 
						|
 | 
						|
    interest = kbd->xkb_interest;
 | 
						|
    if (!interest || !kbd->key || !kbd->key->xkbInfo)
 | 
						|
        return;
 | 
						|
    xkbi = kbd->key->xkbInfo;
 | 
						|
 | 
						|
    initialized = 0;
 | 
						|
    enabledControls = xkbi->desc->ctrls->enabled_ctrls;
 | 
						|
    changedControls = pCN->changedControls;
 | 
						|
    pCN->numGroups = xkbi->desc->ctrls->num_groups;
 | 
						|
    while (interest) {
 | 
						|
        if ((!interest->client->clientGone) &&
 | 
						|
            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
 | 
						|
            (interest->ctrlsNotifyMask & changedControls)) {
 | 
						|
            if (!initialized) {
 | 
						|
                pCN->type = XkbEventCode + XkbEventBase;
 | 
						|
                pCN->xkbType = XkbControlsNotify;
 | 
						|
                pCN->deviceID = kbd->id;
 | 
						|
                pCN->time = time = GetTimeInMillis();
 | 
						|
                enabledChanges = pCN->enabledControlChanges;
 | 
						|
                initialized = 1;
 | 
						|
            }
 | 
						|
            pCN->changedControls = changedControls;
 | 
						|
            pCN->enabledControls = enabledControls;
 | 
						|
            pCN->enabledControlChanges = enabledChanges;
 | 
						|
            pCN->sequenceNumber = interest->client->sequence;
 | 
						|
            pCN->time = time;
 | 
						|
            if (interest->client->swapped) {
 | 
						|
                swaps(&pCN->sequenceNumber);
 | 
						|
                swapl(&pCN->changedControls);
 | 
						|
                swapl(&pCN->enabledControls);
 | 
						|
                swapl(&pCN->enabledControlChanges);
 | 
						|
                swapl(&pCN->time);
 | 
						|
            }
 | 
						|
            WriteToClient(interest->client, sizeof(xEvent), pCN);
 | 
						|
        }
 | 
						|
        interest = interest->next;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
XkbSendIndicatorNotify(DeviceIntPtr kbd, int xkbType, xkbIndicatorNotify * pEv)
 | 
						|
{
 | 
						|
    int initialized;
 | 
						|
    XkbInterestPtr interest;
 | 
						|
    Time time = 0;
 | 
						|
    CARD32 state, changed;
 | 
						|
 | 
						|
    interest = kbd->xkb_interest;
 | 
						|
    if (!interest)
 | 
						|
        return;
 | 
						|
 | 
						|
    initialized = 0;
 | 
						|
    state = pEv->state;
 | 
						|
    changed = pEv->changed;
 | 
						|
    while (interest) {
 | 
						|
        if ((!interest->client->clientGone) &&
 | 
						|
            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
 | 
						|
            (((xkbType == XkbIndicatorStateNotify) &&
 | 
						|
              (interest->iStateNotifyMask & changed)) ||
 | 
						|
             ((xkbType == XkbIndicatorMapNotify) &&
 | 
						|
              (interest->iMapNotifyMask & changed)))) {
 | 
						|
            if (!initialized) {
 | 
						|
                pEv->type = XkbEventCode + XkbEventBase;
 | 
						|
                pEv->xkbType = xkbType;
 | 
						|
                pEv->deviceID = kbd->id;
 | 
						|
                pEv->time = time = GetTimeInMillis();
 | 
						|
                initialized = 1;
 | 
						|
            }
 | 
						|
            pEv->sequenceNumber = interest->client->sequence;
 | 
						|
            pEv->time = time;
 | 
						|
            pEv->changed = changed;
 | 
						|
            pEv->state = state;
 | 
						|
            if (interest->client->swapped) {
 | 
						|
                swaps(&pEv->sequenceNumber);
 | 
						|
                swapl(&pEv->time);
 | 
						|
                swapl(&pEv->changed);
 | 
						|
                swapl(&pEv->state);
 | 
						|
            }
 | 
						|
            WriteToClient(interest->client, sizeof(xEvent), pEv);
 | 
						|
        }
 | 
						|
        interest = interest->next;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
XkbHandleBell(BOOL force,
 | 
						|
              BOOL eventOnly,
 | 
						|
              DeviceIntPtr kbd,
 | 
						|
              CARD8 percent,
 | 
						|
              void *pCtrl,
 | 
						|
              CARD8 class, Atom name, WindowPtr pWin, ClientPtr pClient)
 | 
						|
{
 | 
						|
    xkbBellNotify bn;
 | 
						|
    int initialized;
 | 
						|
    XkbSrvInfoPtr xkbi;
 | 
						|
    XkbInterestPtr interest;
 | 
						|
    CARD8 id;
 | 
						|
    CARD16 pitch, duration;
 | 
						|
    Time time = 0;
 | 
						|
    XID winID = 0;
 | 
						|
 | 
						|
    if (!kbd->key || !kbd->key->xkbInfo)
 | 
						|
        return;
 | 
						|
 | 
						|
    xkbi = kbd->key->xkbInfo;
 | 
						|
 | 
						|
    if ((force || (xkbi->desc->ctrls->enabled_ctrls & XkbAudibleBellMask)) &&
 | 
						|
        (!eventOnly)) {
 | 
						|
        if (kbd->kbdfeed->BellProc)
 | 
						|
            (*kbd->kbdfeed->BellProc) (percent, kbd, (void *) pCtrl, class);
 | 
						|
    }
 | 
						|
    interest = kbd->xkb_interest;
 | 
						|
    if ((!interest) || (force))
 | 
						|
        return;
 | 
						|
 | 
						|
    if (class == KbdFeedbackClass) {
 | 
						|
        KeybdCtrl *pKeyCtrl = (KeybdCtrl *) pCtrl;
 | 
						|
 | 
						|
        id = pKeyCtrl->id;
 | 
						|
        pitch = pKeyCtrl->bell_pitch;
 | 
						|
        duration = pKeyCtrl->bell_duration;
 | 
						|
    }
 | 
						|
    else if (class == BellFeedbackClass) {
 | 
						|
        BellCtrl *pBellCtrl = (BellCtrl *) pCtrl;
 | 
						|
 | 
						|
        id = pBellCtrl->id;
 | 
						|
        pitch = pBellCtrl->pitch;
 | 
						|
        duration = pBellCtrl->duration;
 | 
						|
    }
 | 
						|
    else
 | 
						|
        return;
 | 
						|
 | 
						|
    initialized = 0;
 | 
						|
    while (interest) {
 | 
						|
        if ((!interest->client->clientGone) &&
 | 
						|
            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
 | 
						|
            (interest->bellNotifyMask)) {
 | 
						|
            if (!initialized) {
 | 
						|
                time = GetTimeInMillis();
 | 
						|
                bn.type = XkbEventCode + XkbEventBase;
 | 
						|
                bn.xkbType = XkbBellNotify;
 | 
						|
                bn.deviceID = kbd->id;
 | 
						|
                bn.bellClass = class;
 | 
						|
                bn.bellID = id;
 | 
						|
                bn.percent = percent;
 | 
						|
                bn.eventOnly = (eventOnly != 0);
 | 
						|
                winID = (pWin ? pWin->drawable.id : None);
 | 
						|
                initialized = 1;
 | 
						|
            }
 | 
						|
            bn.sequenceNumber = interest->client->sequence;
 | 
						|
            bn.time = time;
 | 
						|
            bn.pitch = pitch;
 | 
						|
            bn.duration = duration;
 | 
						|
            bn.name = name;
 | 
						|
            bn.window = winID;
 | 
						|
            if (interest->client->swapped) {
 | 
						|
                swaps(&bn.sequenceNumber);
 | 
						|
                swapl(&bn.time);
 | 
						|
                swaps(&bn.pitch);
 | 
						|
                swaps(&bn.duration);
 | 
						|
                swapl(&bn.name);
 | 
						|
                swapl(&bn.window);
 | 
						|
            }
 | 
						|
            WriteToClient(interest->client, sizeof(xEvent), &bn);
 | 
						|
        }
 | 
						|
        interest = interest->next;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
XkbSendAccessXNotify(DeviceIntPtr kbd, xkbAccessXNotify * pEv)
 | 
						|
{
 | 
						|
    int initialized;
 | 
						|
    XkbInterestPtr interest;
 | 
						|
    Time time = 0;
 | 
						|
    CARD16 sk_delay, db_delay;
 | 
						|
 | 
						|
    interest = kbd->xkb_interest;
 | 
						|
    if (!interest)
 | 
						|
        return;
 | 
						|
 | 
						|
    initialized = 0;
 | 
						|
    sk_delay = pEv->slowKeysDelay;
 | 
						|
    db_delay = pEv->debounceDelay;
 | 
						|
    while (interest) {
 | 
						|
        if ((!interest->client->clientGone) &&
 | 
						|
            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
 | 
						|
            (interest->accessXNotifyMask & (1 << pEv->detail))) {
 | 
						|
            if (!initialized) {
 | 
						|
                pEv->type = XkbEventCode + XkbEventBase;
 | 
						|
                pEv->xkbType = XkbAccessXNotify;
 | 
						|
                pEv->deviceID = kbd->id;
 | 
						|
                pEv->time = time = GetTimeInMillis();
 | 
						|
                initialized = 1;
 | 
						|
            }
 | 
						|
            pEv->sequenceNumber = interest->client->sequence;
 | 
						|
            pEv->time = time;
 | 
						|
            pEv->slowKeysDelay = sk_delay;
 | 
						|
            pEv->debounceDelay = db_delay;
 | 
						|
            if (interest->client->swapped) {
 | 
						|
                swaps(&pEv->sequenceNumber);
 | 
						|
                swapl(&pEv->time);
 | 
						|
                swaps(&pEv->slowKeysDelay);
 | 
						|
                swaps(&pEv->debounceDelay);
 | 
						|
            }
 | 
						|
            WriteToClient(interest->client, sizeof(xEvent), pEv);
 | 
						|
        }
 | 
						|
        interest = interest->next;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
XkbSendNamesNotify(DeviceIntPtr kbd, xkbNamesNotify * pEv)
 | 
						|
{
 | 
						|
    int initialized;
 | 
						|
    XkbInterestPtr interest;
 | 
						|
    Time time = 0;
 | 
						|
    CARD16 changed, changedVirtualMods;
 | 
						|
    CARD32 changedIndicators;
 | 
						|
 | 
						|
    interest = kbd->xkb_interest;
 | 
						|
    if (!interest)
 | 
						|
        return;
 | 
						|
 | 
						|
    initialized = 0;
 | 
						|
    changed = pEv->changed;
 | 
						|
    changedIndicators = pEv->changedIndicators;
 | 
						|
    changedVirtualMods = pEv->changedVirtualMods;
 | 
						|
    while (interest) {
 | 
						|
        if ((!interest->client->clientGone) &&
 | 
						|
            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
 | 
						|
            (interest->namesNotifyMask & pEv->changed)) {
 | 
						|
            if (!initialized) {
 | 
						|
                pEv->type = XkbEventCode + XkbEventBase;
 | 
						|
                pEv->xkbType = XkbNamesNotify;
 | 
						|
                pEv->deviceID = kbd->id;
 | 
						|
                pEv->time = time = GetTimeInMillis();
 | 
						|
                initialized = 1;
 | 
						|
            }
 | 
						|
            pEv->sequenceNumber = interest->client->sequence;
 | 
						|
            pEv->time = time;
 | 
						|
            pEv->changed = changed;
 | 
						|
            pEv->changedIndicators = changedIndicators;
 | 
						|
            pEv->changedVirtualMods = changedVirtualMods;
 | 
						|
            if (interest->client->swapped) {
 | 
						|
                swaps(&pEv->sequenceNumber);
 | 
						|
                swapl(&pEv->time);
 | 
						|
                swaps(&pEv->changed);
 | 
						|
                swapl(&pEv->changedIndicators);
 | 
						|
                swaps(&pEv->changedVirtualMods);
 | 
						|
            }
 | 
						|
            WriteToClient(interest->client, sizeof(xEvent), pEv);
 | 
						|
        }
 | 
						|
        interest = interest->next;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
XkbSendCompatMapNotify(DeviceIntPtr kbd, xkbCompatMapNotify * pEv)
 | 
						|
{
 | 
						|
    int initialized;
 | 
						|
    XkbInterestPtr interest;
 | 
						|
    Time time = 0;
 | 
						|
    CARD16 firstSI = 0, nSI = 0, nTotalSI = 0;
 | 
						|
 | 
						|
    interest = kbd->xkb_interest;
 | 
						|
    if (!interest)
 | 
						|
        return;
 | 
						|
 | 
						|
    initialized = 0;
 | 
						|
    while (interest) {
 | 
						|
        if ((!interest->client->clientGone) &&
 | 
						|
            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
 | 
						|
            (interest->compatNotifyMask)) {
 | 
						|
            if (!initialized) {
 | 
						|
                pEv->type = XkbEventCode + XkbEventBase;
 | 
						|
                pEv->xkbType = XkbCompatMapNotify;
 | 
						|
                pEv->deviceID = kbd->id;
 | 
						|
                pEv->time = time = GetTimeInMillis();
 | 
						|
                firstSI = pEv->firstSI;
 | 
						|
                nSI = pEv->nSI;
 | 
						|
                nTotalSI = pEv->nTotalSI;
 | 
						|
                initialized = 1;
 | 
						|
            }
 | 
						|
            pEv->sequenceNumber = interest->client->sequence;
 | 
						|
            pEv->time = time;
 | 
						|
            pEv->firstSI = firstSI;
 | 
						|
            pEv->nSI = nSI;
 | 
						|
            pEv->nTotalSI = nTotalSI;
 | 
						|
            if (interest->client->swapped) {
 | 
						|
                swaps(&pEv->sequenceNumber);
 | 
						|
                swapl(&pEv->time);
 | 
						|
                swaps(&pEv->firstSI);
 | 
						|
                swaps(&pEv->nSI);
 | 
						|
                swaps(&pEv->nTotalSI);
 | 
						|
            }
 | 
						|
            WriteToClient(interest->client, sizeof(xEvent), pEv);
 | 
						|
        }
 | 
						|
        interest = interest->next;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
XkbSendActionMessage(DeviceIntPtr kbd, xkbActionMessage * pEv)
 | 
						|
{
 | 
						|
    int initialized;
 | 
						|
    XkbSrvInfoPtr xkbi;
 | 
						|
    XkbInterestPtr interest;
 | 
						|
    Time time = 0;
 | 
						|
 | 
						|
    interest = kbd->xkb_interest;
 | 
						|
    if (!interest || !kbd->key || !kbd->key->xkbInfo)
 | 
						|
        return;
 | 
						|
 | 
						|
    xkbi = kbd->key->xkbInfo;
 | 
						|
 | 
						|
    initialized = 0;
 | 
						|
    pEv->mods = xkbi->state.mods;
 | 
						|
    pEv->group = xkbi->state.group;
 | 
						|
    while (interest) {
 | 
						|
        if ((!interest->client->clientGone) &&
 | 
						|
            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
 | 
						|
            (interest->actionMessageMask)) {
 | 
						|
            if (!initialized) {
 | 
						|
                pEv->type = XkbEventCode + XkbEventBase;
 | 
						|
                pEv->xkbType = XkbActionMessage;
 | 
						|
                pEv->deviceID = kbd->id;
 | 
						|
                pEv->sequenceNumber = interest->client->sequence;
 | 
						|
                pEv->time = time = GetTimeInMillis();
 | 
						|
                initialized = 1;
 | 
						|
            }
 | 
						|
            pEv->sequenceNumber = interest->client->sequence;
 | 
						|
            pEv->time = time;
 | 
						|
            if (interest->client->swapped) {
 | 
						|
                swaps(&pEv->sequenceNumber);
 | 
						|
                swapl(&pEv->time);
 | 
						|
            }
 | 
						|
            WriteToClient(interest->client, sizeof(xEvent), pEv);
 | 
						|
        }
 | 
						|
        interest = interest->next;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
XkbSendExtensionDeviceNotify(DeviceIntPtr dev,
 | 
						|
                             ClientPtr client, xkbExtensionDeviceNotify * pEv)
 | 
						|
{
 | 
						|
    int initialized;
 | 
						|
    XkbInterestPtr interest;
 | 
						|
    Time time = 0;
 | 
						|
    CARD32 defined, state;
 | 
						|
    CARD16 reason;
 | 
						|
 | 
						|
    interest = dev->xkb_interest;
 | 
						|
    if (!interest)
 | 
						|
        return;
 | 
						|
 | 
						|
    initialized = 0;
 | 
						|
    reason = pEv->reason;
 | 
						|
    defined = pEv->ledsDefined;
 | 
						|
    state = pEv->ledState;
 | 
						|
    while (interest) {
 | 
						|
        if ((!interest->client->clientGone) &&
 | 
						|
            (interest->client->xkbClientFlags & _XkbClientInitialized) &&
 | 
						|
            (interest->extDevNotifyMask & reason)) {
 | 
						|
            if (!initialized) {
 | 
						|
                pEv->type = XkbEventCode + XkbEventBase;
 | 
						|
                pEv->xkbType = XkbExtensionDeviceNotify;
 | 
						|
                pEv->deviceID = dev->id;
 | 
						|
                pEv->sequenceNumber = interest->client->sequence;
 | 
						|
                pEv->time = time = GetTimeInMillis();
 | 
						|
                initialized = 1;
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                pEv->sequenceNumber = interest->client->sequence;
 | 
						|
                pEv->time = time;
 | 
						|
                pEv->ledsDefined = defined;
 | 
						|
                pEv->ledState = state;
 | 
						|
                pEv->reason = reason;
 | 
						|
                pEv->supported = XkbXI_AllFeaturesMask;
 | 
						|
            }
 | 
						|
            if (interest->client->swapped) {
 | 
						|
                swaps(&pEv->sequenceNumber);
 | 
						|
                swapl(&pEv->time);
 | 
						|
                swapl(&pEv->ledsDefined);
 | 
						|
                swapl(&pEv->ledState);
 | 
						|
                swaps(&pEv->reason);
 | 
						|
                swaps(&pEv->supported);
 | 
						|
            }
 | 
						|
            WriteToClient(interest->client, sizeof(xEvent), pEv);
 | 
						|
        }
 | 
						|
        interest = interest->next;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
XkbSendNotification(DeviceIntPtr kbd,
 | 
						|
                    XkbChangesPtr pChanges, XkbEventCausePtr cause)
 | 
						|
{
 | 
						|
    XkbSrvLedInfoPtr sli;
 | 
						|
 | 
						|
    sli = NULL;
 | 
						|
    if (pChanges->state_changes) {
 | 
						|
        xkbStateNotify sn;
 | 
						|
 | 
						|
        sn.changed = pChanges->state_changes;
 | 
						|
        sn.keycode = cause->kc;
 | 
						|
        sn.eventType = cause->event;
 | 
						|
        sn.requestMajor = cause->mjr;
 | 
						|
        sn.requestMinor = cause->mnr;
 | 
						|
        XkbSendStateNotify(kbd, &sn);
 | 
						|
    }
 | 
						|
    if (pChanges->map.changed) {
 | 
						|
        xkbMapNotify mn;
 | 
						|
 | 
						|
        memset(&mn, 0, sizeof(xkbMapNotify));
 | 
						|
        mn.changed = pChanges->map.changed;
 | 
						|
        mn.firstType = pChanges->map.first_type;
 | 
						|
        mn.nTypes = pChanges->map.num_types;
 | 
						|
        mn.firstKeySym = pChanges->map.first_key_sym;
 | 
						|
        mn.nKeySyms = pChanges->map.num_key_syms;
 | 
						|
        mn.firstKeyAct = pChanges->map.first_key_act;
 | 
						|
        mn.nKeyActs = pChanges->map.num_key_acts;
 | 
						|
        mn.firstKeyBehavior = pChanges->map.first_key_behavior;
 | 
						|
        mn.nKeyBehaviors = pChanges->map.num_key_behaviors;
 | 
						|
        mn.virtualMods = pChanges->map.vmods;
 | 
						|
        mn.firstKeyExplicit = pChanges->map.first_key_explicit;
 | 
						|
        mn.nKeyExplicit = pChanges->map.num_key_explicit;
 | 
						|
        mn.firstModMapKey = pChanges->map.first_modmap_key;
 | 
						|
        mn.nModMapKeys = pChanges->map.num_modmap_keys;
 | 
						|
        mn.firstVModMapKey = pChanges->map.first_vmodmap_key;
 | 
						|
        mn.nVModMapKeys = pChanges->map.num_vmodmap_keys;
 | 
						|
        XkbSendMapNotify(kbd, &mn);
 | 
						|
    }
 | 
						|
    if ((pChanges->ctrls.changed_ctrls) ||
 | 
						|
        (pChanges->ctrls.enabled_ctrls_changes)) {
 | 
						|
        xkbControlsNotify cn;
 | 
						|
 | 
						|
        memset(&cn, 0, sizeof(xkbControlsNotify));
 | 
						|
        cn.changedControls = pChanges->ctrls.changed_ctrls;
 | 
						|
        cn.enabledControlChanges = pChanges->ctrls.enabled_ctrls_changes;
 | 
						|
        cn.keycode = cause->kc;
 | 
						|
        cn.eventType = cause->event;
 | 
						|
        cn.requestMajor = cause->mjr;
 | 
						|
        cn.requestMinor = cause->mnr;
 | 
						|
        XkbSendControlsNotify(kbd, &cn);
 | 
						|
    }
 | 
						|
    if (pChanges->indicators.map_changes) {
 | 
						|
        xkbIndicatorNotify in;
 | 
						|
 | 
						|
        if (sli == NULL)
 | 
						|
            sli = XkbFindSrvLedInfo(kbd, XkbDfltXIClass, XkbDfltXIId, 0);
 | 
						|
        memset(&in, 0, sizeof(xkbIndicatorNotify));
 | 
						|
        in.state = sli->effectiveState;
 | 
						|
        in.changed = pChanges->indicators.map_changes;
 | 
						|
        XkbSendIndicatorNotify(kbd, XkbIndicatorMapNotify, &in);
 | 
						|
    }
 | 
						|
    if (pChanges->indicators.state_changes) {
 | 
						|
        xkbIndicatorNotify in;
 | 
						|
 | 
						|
        if (sli == NULL)
 | 
						|
            sli = XkbFindSrvLedInfo(kbd, XkbDfltXIClass, XkbDfltXIId, 0);
 | 
						|
        memset(&in, 0, sizeof(xkbIndicatorNotify));
 | 
						|
        in.state = sli->effectiveState;
 | 
						|
        in.changed = pChanges->indicators.state_changes;
 | 
						|
        XkbSendIndicatorNotify(kbd, XkbIndicatorStateNotify, &in);
 | 
						|
    }
 | 
						|
    if (pChanges->names.changed) {
 | 
						|
        xkbNamesNotify nn;
 | 
						|
 | 
						|
        memset(&nn, 0, sizeof(xkbNamesNotify));
 | 
						|
        nn.changed = pChanges->names.changed;
 | 
						|
        nn.firstType = pChanges->names.first_type;
 | 
						|
        nn.nTypes = pChanges->names.num_types;
 | 
						|
        nn.firstLevelName = pChanges->names.first_lvl;
 | 
						|
        nn.nLevelNames = pChanges->names.num_lvls;
 | 
						|
        nn.nRadioGroups = pChanges->names.num_rg;
 | 
						|
        nn.changedVirtualMods = pChanges->names.changed_vmods;
 | 
						|
        nn.changedIndicators = pChanges->names.changed_indicators;
 | 
						|
        XkbSendNamesNotify(kbd, &nn);
 | 
						|
    }
 | 
						|
    if ((pChanges->compat.changed_groups) || (pChanges->compat.num_si > 0)) {
 | 
						|
        xkbCompatMapNotify cmn;
 | 
						|
 | 
						|
        memset(&cmn, 0, sizeof(xkbCompatMapNotify));
 | 
						|
        cmn.changedGroups = pChanges->compat.changed_groups;
 | 
						|
        cmn.firstSI = pChanges->compat.first_si;
 | 
						|
        cmn.nSI = pChanges->compat.num_si;
 | 
						|
        cmn.nTotalSI = kbd->key->xkbInfo->desc->compat->num_si;
 | 
						|
        XkbSendCompatMapNotify(kbd, &cmn);
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
 | 
						|
void
 | 
						|
XkbFilterEvents(ClientPtr client, int nEvents, xEvent *xE)
 | 
						|
{
 | 
						|
    DeviceIntPtr dev = NULL;
 | 
						|
    XkbSrvInfoPtr xkbi;
 | 
						|
    CARD8 type = xE[0].u.u.type;
 | 
						|
 | 
						|
    if (xE->u.u.type & EXTENSION_EVENT_BASE)
 | 
						|
        dev = XIGetDevice(xE);
 | 
						|
 | 
						|
    if (!dev)
 | 
						|
        dev = PickKeyboard(client);
 | 
						|
 | 
						|
    if (!dev->key)
 | 
						|
        return;
 | 
						|
 | 
						|
    xkbi = dev->key->xkbInfo;
 | 
						|
 | 
						|
    if (client->xkbClientFlags & _XkbClientInitialized) {
 | 
						|
        if ((xkbDebugFlags & 0x10) &&
 | 
						|
            (type == KeyPress || type == KeyRelease ||
 | 
						|
             type == DeviceKeyPress || type == DeviceKeyRelease))
 | 
						|
            DebugF("[xkb] XkbFilterWriteEvents (XKB client): state 0x%04x\n",
 | 
						|
                   xE[0].u.keyButtonPointer.state);
 | 
						|
 | 
						|
        if (dev->deviceGrab.grab != NullGrab && dev->deviceGrab.fromPassiveGrab
 | 
						|
            && (type == KeyPress || type == KeyRelease || type == DeviceKeyPress
 | 
						|
                || type == DeviceKeyRelease)) {
 | 
						|
            unsigned int state, flags;
 | 
						|
 | 
						|
            flags = client->xkbClientFlags;
 | 
						|
            state = xkbi->state.compat_grab_mods;
 | 
						|
            if (flags & XkbPCF_GrabsUseXKBStateMask) {
 | 
						|
                int group;
 | 
						|
 | 
						|
                if (flags & XkbPCF_LookupStateWhenGrabbed) {
 | 
						|
                    group = xkbi->state.group;
 | 
						|
                    state = xkbi->state.lookup_mods;
 | 
						|
                }
 | 
						|
                else {
 | 
						|
                    state = xkbi->state.grab_mods;
 | 
						|
                    group = xkbi->state.base_group + xkbi->state.latched_group;
 | 
						|
                    if (group < 0 || group >= xkbi->desc->ctrls->num_groups)
 | 
						|
                        group = XkbAdjustGroup(group, xkbi->desc->ctrls);
 | 
						|
                }
 | 
						|
                state = XkbBuildCoreState(state, group);
 | 
						|
            }
 | 
						|
            else if (flags & XkbPCF_LookupStateWhenGrabbed) {
 | 
						|
                state = xkbi->state.compat_lookup_mods;
 | 
						|
            }
 | 
						|
            xE[0].u.keyButtonPointer.state = state;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        if ((xkbDebugFlags & 0x4) &&
 | 
						|
            (xE[0].u.u.type == KeyPress || xE[0].u.u.type == KeyRelease ||
 | 
						|
             xE[0].u.u.type == DeviceKeyPress ||
 | 
						|
             xE[0].u.u.type == DeviceKeyRelease)) {
 | 
						|
            DebugF("[xkb] XKbFilterWriteEvents (non-XKB):\n");
 | 
						|
            DebugF("[xkb] event= 0x%04x\n", xE[0].u.keyButtonPointer.state);
 | 
						|
            DebugF("[xkb] lookup= 0x%02x, grab= 0x%02x\n",
 | 
						|
                   xkbi->state.lookup_mods, xkbi->state.grab_mods);
 | 
						|
            DebugF("[xkb] compat lookup= 0x%02x, grab= 0x%02x\n",
 | 
						|
                   xkbi->state.compat_lookup_mods,
 | 
						|
                   xkbi->state.compat_grab_mods);
 | 
						|
        }
 | 
						|
        if (type >= KeyPress && type <= MotionNotify) {
 | 
						|
            CARD16 old, new;
 | 
						|
 | 
						|
            old = xE[0].u.keyButtonPointer.state & ~0x1f00;
 | 
						|
            new = xE[0].u.keyButtonPointer.state & 0x1F00;
 | 
						|
 | 
						|
            if (old == XkbStateFieldFromRec(&xkbi->state))
 | 
						|
                new |= xkbi->state.compat_lookup_mods;
 | 
						|
            else
 | 
						|
                new |= xkbi->state.compat_grab_mods;
 | 
						|
            xE[0].u.keyButtonPointer.state = new;
 | 
						|
        }
 | 
						|
        else if (type == EnterNotify || type == LeaveNotify) {
 | 
						|
            xE[0].u.enterLeave.state &= 0x1F00;
 | 
						|
            xE[0].u.enterLeave.state |= xkbi->state.compat_grab_mods;
 | 
						|
        }
 | 
						|
        else if (type >= DeviceKeyPress && type <= DeviceMotionNotify) {
 | 
						|
            CARD16 old, new;
 | 
						|
            deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer *) &xE[0];
 | 
						|
 | 
						|
            old = kbp->state & ~0x1F00;
 | 
						|
            new = kbp->state & 0x1F00;
 | 
						|
            if (old == XkbStateFieldFromRec(&xkbi->state))
 | 
						|
                new |= xkbi->state.compat_lookup_mods;
 | 
						|
            else
 | 
						|
                new |= xkbi->state.compat_grab_mods;
 | 
						|
            kbp->state = new;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/***====================================================================***/
 | 
						|
 | 
						|
XkbInterestPtr
 | 
						|
XkbFindClientResource(DevicePtr inDev, ClientPtr client)
 | 
						|
{
 | 
						|
    DeviceIntPtr dev = (DeviceIntPtr) inDev;
 | 
						|
    XkbInterestPtr interest;
 | 
						|
 | 
						|
    if (dev->xkb_interest) {
 | 
						|
        interest = dev->xkb_interest;
 | 
						|
        while (interest) {
 | 
						|
            if (interest->client == client) {
 | 
						|
                return interest;
 | 
						|
            }
 | 
						|
            interest = interest->next;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
XkbInterestPtr
 | 
						|
XkbAddClientResource(DevicePtr inDev, ClientPtr client, XID id)
 | 
						|
{
 | 
						|
    DeviceIntPtr dev = (DeviceIntPtr) inDev;
 | 
						|
    XkbInterestPtr interest;
 | 
						|
 | 
						|
    interest = dev->xkb_interest;
 | 
						|
    while (interest) {
 | 
						|
        if (interest->client == client)
 | 
						|
            return ((interest->resource == id) ? interest : NULL);
 | 
						|
        interest = interest->next;
 | 
						|
    }
 | 
						|
    interest = calloc(1, sizeof(XkbInterestRec));
 | 
						|
    if (interest) {
 | 
						|
        interest->dev = dev;
 | 
						|
        interest->client = client;
 | 
						|
        interest->resource = id;
 | 
						|
        interest->next = dev->xkb_interest;
 | 
						|
        dev->xkb_interest = interest;
 | 
						|
        return interest;
 | 
						|
    }
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XkbRemoveResourceClient(DevicePtr inDev, XID id)
 | 
						|
{
 | 
						|
    XkbSrvInfoPtr xkbi;
 | 
						|
    DeviceIntPtr dev = (DeviceIntPtr) inDev;
 | 
						|
    XkbInterestPtr interest;
 | 
						|
    Bool found;
 | 
						|
    unsigned long autoCtrls, autoValues;
 | 
						|
    ClientPtr client = NULL;
 | 
						|
 | 
						|
    found = FALSE;
 | 
						|
 | 
						|
    if (!dev->key || !dev->key->xkbInfo)
 | 
						|
        return found;
 | 
						|
 | 
						|
    autoCtrls = autoValues = 0;
 | 
						|
    if (dev->xkb_interest) {
 | 
						|
        interest = dev->xkb_interest;
 | 
						|
        if (interest && (interest->resource == id)) {
 | 
						|
            dev->xkb_interest = interest->next;
 | 
						|
            autoCtrls = interest->autoCtrls;
 | 
						|
            autoValues = interest->autoCtrlValues;
 | 
						|
            client = interest->client;
 | 
						|
            free(interest);
 | 
						|
            found = TRUE;
 | 
						|
        }
 | 
						|
        while ((!found) && (interest->next)) {
 | 
						|
            if (interest->next->resource == id) {
 | 
						|
                XkbInterestPtr victim = interest->next;
 | 
						|
 | 
						|
                interest->next = victim->next;
 | 
						|
                autoCtrls = victim->autoCtrls;
 | 
						|
                autoValues = victim->autoCtrlValues;
 | 
						|
                client = victim->client;
 | 
						|
                free(victim);
 | 
						|
                found = TRUE;
 | 
						|
            }
 | 
						|
            interest = interest->next;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (found && autoCtrls && dev->key && dev->key->xkbInfo) {
 | 
						|
        XkbEventCauseRec cause;
 | 
						|
 | 
						|
        xkbi = dev->key->xkbInfo;
 | 
						|
        XkbSetCauseXkbReq(&cause, X_kbPerClientFlags, client);
 | 
						|
        XkbEnableDisableControls(xkbi, autoCtrls, autoValues, NULL, &cause);
 | 
						|
    }
 | 
						|
    return found;
 | 
						|
}
 |