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 <math.h>
3305b261ecSmrg#include <X11/X.h>
3405b261ecSmrg#include <X11/Xproto.h>
3505b261ecSmrg#include <X11/keysym.h>
3605b261ecSmrg#include "misc.h"
3705b261ecSmrg#include "inputstr.h"
3805b261ecSmrg#include "exevents.h"
396747b715Smrg#include "eventstr.h"
4005b261ecSmrg#include <xkbsrv.h>
4105b261ecSmrg#include "xkb.h"
4205b261ecSmrg#include <ctype.h>
436747b715Smrg#include "mi.h"
446747b715Smrg#include "mipointer.h"
459ace9065Smrg#include "inpututils.h"
46ed6184dfSmrg#include "dixgrabs.h"
4705b261ecSmrg#define EXTENSION_EVENT_BASE 64
4805b261ecSmrg
496747b715SmrgDevPrivateKeyRec xkbDevicePrivateKeyRec;
506747b715Smrg
5135c4bbdfSmrgstatic void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags, int x,
5235c4bbdfSmrg                                 int y);
5305b261ecSmrg
5405b261ecSmrgvoid
5535c4bbdfSmrgxkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc, void *data)
5605b261ecSmrg{
5705b261ecSmrg    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device);
5805b261ecSmrg    ProcessInputProc backupproc;
5905b261ecSmrg
6035c4bbdfSmrg    if (xkbPrivPtr->unwrapProc)
6135c4bbdfSmrg        xkbPrivPtr->unwrapProc = NULL;
6235c4bbdfSmrg
6335c4bbdfSmrg    UNWRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, backupproc);
6435c4bbdfSmrg    proc(device, data);
6535c4bbdfSmrg    COND_WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, backupproc, xkbUnwrapProc);
6605b261ecSmrg}
6705b261ecSmrg
686747b715SmrgBool
696747b715SmrgXkbInitPrivates(void)
706747b715Smrg{
7135c4bbdfSmrg    return dixRegisterPrivateKey(&xkbDevicePrivateKeyRec, PRIVATE_DEVICE,
7235c4bbdfSmrg                                 sizeof(xkbDeviceInfoRec));
736747b715Smrg}
7405b261ecSmrg
7505b261ecSmrgvoid
7605b261ecSmrgXkbSetExtension(DeviceIntPtr device, ProcessInputProc proc)
7705b261ecSmrg{
789ace9065Smrg    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device);
7935c4bbdfSmrg
8005b261ecSmrg    WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, proc, xkbUnwrapProc);
8105b261ecSmrg}
8205b261ecSmrg
8305b261ecSmrg/***====================================================================***/
8405b261ecSmrg
8505b261ecSmrgstatic XkbAction
8635c4bbdfSmrg_FixUpAction(XkbDescPtr xkb, XkbAction *act)
8705b261ecSmrg{
8835c4bbdfSmrg    static XkbAction fake;
8905b261ecSmrg
9035c4bbdfSmrg    if (XkbIsPtrAction(act) &&
9135c4bbdfSmrg        (!(xkb->ctrls->enabled_ctrls & XkbMouseKeysMask))) {
9235c4bbdfSmrg        fake.type = XkbSA_NoAction;
9335c4bbdfSmrg        return fake;
9405b261ecSmrg    }
9535c4bbdfSmrg    if (xkb->ctrls->enabled_ctrls & XkbStickyKeysMask) {
9635c4bbdfSmrg        if (act->any.type == XkbSA_SetMods) {
9735c4bbdfSmrg            fake.mods.type = XkbSA_LatchMods;
9835c4bbdfSmrg            fake.mods.mask = act->mods.mask;
9935c4bbdfSmrg            if (XkbAX_NeedOption(xkb->ctrls, XkbAX_LatchToLockMask))
10035c4bbdfSmrg                fake.mods.flags = XkbSA_ClearLocks | XkbSA_LatchToLock;
10135c4bbdfSmrg            else
10235c4bbdfSmrg                fake.mods.flags = XkbSA_ClearLocks;
10335c4bbdfSmrg            return fake;
10435c4bbdfSmrg        }
10535c4bbdfSmrg        if (act->any.type == XkbSA_SetGroup) {
10635c4bbdfSmrg            fake.group.type = XkbSA_LatchGroup;
10735c4bbdfSmrg            if (XkbAX_NeedOption(xkb->ctrls, XkbAX_LatchToLockMask))
10835c4bbdfSmrg                fake.group.flags = XkbSA_ClearLocks | XkbSA_LatchToLock;
10935c4bbdfSmrg            else
11035c4bbdfSmrg                fake.group.flags = XkbSA_ClearLocks;
11135c4bbdfSmrg            XkbSASetGroup(&fake.group, XkbSAGroup(&act->group));
11235c4bbdfSmrg            return fake;
11335c4bbdfSmrg        }
11405b261ecSmrg    }
11505b261ecSmrg    return *act;
11605b261ecSmrg}
11705b261ecSmrg
11805b261ecSmrgstatic XkbAction
11935c4bbdfSmrgXkbGetKeyAction(XkbSrvInfoPtr xkbi, XkbStatePtr xkbState, CARD8 key)
12005b261ecSmrg{
12135c4bbdfSmrg    int effectiveGroup;
12235c4bbdfSmrg    int col;
12335c4bbdfSmrg    XkbDescPtr xkb;
12435c4bbdfSmrg    XkbKeyTypePtr type;
12535c4bbdfSmrg    XkbAction *pActs;
12635c4bbdfSmrg    static XkbAction fake;
12735c4bbdfSmrg
12835c4bbdfSmrg    xkb = xkbi->desc;
12935c4bbdfSmrg    if (!XkbKeyHasActions(xkb, key) || !XkbKeycodeInRange(xkb, key)) {
13035c4bbdfSmrg        fake.type = XkbSA_NoAction;
13135c4bbdfSmrg        return fake;
13205b261ecSmrg    }
13335c4bbdfSmrg    pActs = XkbKeyActionsPtr(xkb, key);
13435c4bbdfSmrg    col = 0;
1356747b715Smrg
1366747b715Smrg    effectiveGroup = XkbGetEffectiveGroup(xkbi, xkbState, key);
1376747b715Smrg    if (effectiveGroup != XkbGroup1Index)
1386747b715Smrg        col += (effectiveGroup * XkbKeyGroupsWidth(xkb, key));
1396747b715Smrg
14035c4bbdfSmrg    type = XkbKeyKeyType(xkb, key, effectiveGroup);
14135c4bbdfSmrg    if (type->map != NULL) {
14235c4bbdfSmrg        register unsigned i, mods;
14335c4bbdfSmrg        register XkbKTMapEntryPtr entry;
14435c4bbdfSmrg
14535c4bbdfSmrg        mods = xkbState->mods & type->mods.mask;
14635c4bbdfSmrg        for (entry = type->map, i = 0; i < type->map_count; i++, entry++) {
14735c4bbdfSmrg            if ((entry->active) && (entry->mods.mask == mods)) {
14835c4bbdfSmrg                col += entry->level;
14935c4bbdfSmrg                break;
15035c4bbdfSmrg            }
15135c4bbdfSmrg        }
15205b261ecSmrg    }
15335c4bbdfSmrg    if (pActs[col].any.type == XkbSA_NoAction)
15435c4bbdfSmrg        return pActs[col];
15535c4bbdfSmrg    fake = _FixUpAction(xkb, &pActs[col]);
15605b261ecSmrg    return fake;
15705b261ecSmrg}
15805b261ecSmrg
15905b261ecSmrgstatic XkbAction
16035c4bbdfSmrgXkbGetButtonAction(DeviceIntPtr kbd, DeviceIntPtr dev, int button)
16105b261ecSmrg{
16235c4bbdfSmrg    XkbAction fake;
16335c4bbdfSmrg
16435c4bbdfSmrg    if ((dev->button) && (dev->button->xkb_acts)) {
16535c4bbdfSmrg        if (dev->button->xkb_acts[button - 1].any.type != XkbSA_NoAction) {
16635c4bbdfSmrg            fake = _FixUpAction(kbd->key->xkbInfo->desc,
16735c4bbdfSmrg                                &dev->button->xkb_acts[button - 1]);
16835c4bbdfSmrg            return fake;
16935c4bbdfSmrg        }
17035c4bbdfSmrg    }
17135c4bbdfSmrg    fake.any.type = XkbSA_NoAction;
17235c4bbdfSmrg    return fake;
17305b261ecSmrg}
17405b261ecSmrg
17505b261ecSmrg/***====================================================================***/
17605b261ecSmrg
17705b261ecSmrg#define	SYNTHETIC_KEYCODE	1
17805b261ecSmrg#define	BTN_ACT_FLAG		0x100
17905b261ecSmrg
18005b261ecSmrgstatic int
18135c4bbdfSmrg_XkbFilterSetState(XkbSrvInfoPtr xkbi,
18235c4bbdfSmrg                   XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
18305b261ecSmrg{
18435c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
18535c4bbdfSmrg        AccessXCancelRepeatKey(xkbi, keycode);
18635c4bbdfSmrg        filter->keycode = keycode;
18735c4bbdfSmrg        filter->active = 1;
18835c4bbdfSmrg        filter->filterOthers = ((pAction->mods.mask & XkbSA_ClearLocks) != 0);
18935c4bbdfSmrg        filter->priv = 0;
19035c4bbdfSmrg        filter->filter = _XkbFilterSetState;
19135c4bbdfSmrg        if (pAction->type == XkbSA_SetMods) {
19235c4bbdfSmrg            filter->upAction = *pAction;
19335c4bbdfSmrg            xkbi->setMods = pAction->mods.mask;
19435c4bbdfSmrg        }
19535c4bbdfSmrg        else {
19635c4bbdfSmrg            xkbi->groupChange = XkbSAGroup(&pAction->group);
19735c4bbdfSmrg            if (pAction->group.flags & XkbSA_GroupAbsolute)
19835c4bbdfSmrg                xkbi->groupChange -= xkbi->state.base_group;
19935c4bbdfSmrg            filter->upAction = *pAction;
20035c4bbdfSmrg            XkbSASetGroup(&filter->upAction.group, xkbi->groupChange);
20135c4bbdfSmrg        }
20205b261ecSmrg    }
20335c4bbdfSmrg    else if (filter->keycode == keycode) {
20435c4bbdfSmrg        if (filter->upAction.type == XkbSA_SetMods) {
20535c4bbdfSmrg            xkbi->clearMods = filter->upAction.mods.mask;
20635c4bbdfSmrg            if (filter->upAction.mods.flags & XkbSA_ClearLocks) {
20735c4bbdfSmrg                xkbi->state.locked_mods &= ~filter->upAction.mods.mask;
20835c4bbdfSmrg            }
20935c4bbdfSmrg        }
21035c4bbdfSmrg        else {
21135c4bbdfSmrg            if (filter->upAction.group.flags & XkbSA_ClearLocks) {
21235c4bbdfSmrg                xkbi->state.locked_group = 0;
21335c4bbdfSmrg            }
21435c4bbdfSmrg            xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
21535c4bbdfSmrg        }
21635c4bbdfSmrg        filter->active = 0;
21705b261ecSmrg    }
21805b261ecSmrg    else {
21935c4bbdfSmrg        filter->upAction.mods.flags &= ~XkbSA_ClearLocks;
22035c4bbdfSmrg        filter->filterOthers = 0;
22105b261ecSmrg    }
22205b261ecSmrg    return 1;
22305b261ecSmrg}
22405b261ecSmrg
22505b261ecSmrg#define	LATCH_KEY_DOWN	1
22605b261ecSmrg#define	LATCH_PENDING	2
22705b261ecSmrg
22805b261ecSmrgstatic int
22935c4bbdfSmrg_XkbFilterLatchState(XkbSrvInfoPtr xkbi,
23035c4bbdfSmrg                     XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
23105b261ecSmrg{
23205b261ecSmrg
23335c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
23435c4bbdfSmrg        AccessXCancelRepeatKey(xkbi,keycode);
23535c4bbdfSmrg        filter->keycode = keycode;
23635c4bbdfSmrg        filter->active = 1;
23735c4bbdfSmrg        filter->filterOthers = 1;
23835c4bbdfSmrg        filter->priv = LATCH_KEY_DOWN;
23935c4bbdfSmrg        filter->filter = _XkbFilterLatchState;
24035c4bbdfSmrg        if (pAction->type == XkbSA_LatchMods) {
24135c4bbdfSmrg            filter->upAction = *pAction;
24235c4bbdfSmrg            xkbi->setMods = pAction->mods.mask;
24335c4bbdfSmrg        }
24435c4bbdfSmrg        else {
24535c4bbdfSmrg            xkbi->groupChange = XkbSAGroup(&pAction->group);
24635c4bbdfSmrg            if (pAction->group.flags & XkbSA_GroupAbsolute)
24735c4bbdfSmrg                xkbi->groupChange -= xkbi->state.base_group;
24835c4bbdfSmrg            filter->upAction = *pAction;
24935c4bbdfSmrg            XkbSASetGroup(&filter->upAction.group, xkbi->groupChange);
25035c4bbdfSmrg        }
25105b261ecSmrg    }
25235c4bbdfSmrg    else if (pAction && (filter->priv == LATCH_PENDING)) {
25335c4bbdfSmrg        if (((1 << pAction->type) & XkbSA_BreakLatch) != 0) {
25435c4bbdfSmrg            filter->active = 0;
25535c4bbdfSmrg            /* If one latch is broken, all latches are broken, so it's no use
25635c4bbdfSmrg               to find out which particular latch this filter tracks. */
25735c4bbdfSmrg            xkbi->state.latched_mods = 0;
25835c4bbdfSmrg            xkbi->state.latched_group = 0;
25935c4bbdfSmrg        }
26005b261ecSmrg    }
26135c4bbdfSmrg    else if (filter->keycode == keycode && filter->priv != LATCH_PENDING){
26235c4bbdfSmrg        /* The test above for LATCH_PENDING skips subsequent releases of the
26335c4bbdfSmrg           key after it has been released first time and the latch became
26435c4bbdfSmrg           pending. */
26535c4bbdfSmrg        XkbControlsPtr ctrls = xkbi->desc->ctrls;
26635c4bbdfSmrg        int needBeep = ((ctrls->enabled_ctrls & XkbStickyKeysMask) &&
26735c4bbdfSmrg                        XkbAX_NeedFeedback(ctrls, XkbAX_StickyKeysFBMask));
26835c4bbdfSmrg
26935c4bbdfSmrg        if (filter->upAction.type == XkbSA_LatchMods) {
27035c4bbdfSmrg            unsigned char mask = filter->upAction.mods.mask;
27135c4bbdfSmrg            unsigned char common;
27235c4bbdfSmrg
27335c4bbdfSmrg            xkbi->clearMods = mask;
27435c4bbdfSmrg
27535c4bbdfSmrg            /* ClearLocks */
27635c4bbdfSmrg            common = mask & xkbi->state.locked_mods;
27735c4bbdfSmrg            if ((filter->upAction.mods.flags & XkbSA_ClearLocks) && common) {
27835c4bbdfSmrg                mask &= ~common;
27935c4bbdfSmrg                xkbi->state.locked_mods &= ~common;
28035c4bbdfSmrg                if (needBeep)
28135c4bbdfSmrg                    XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_UNLOCK,
28235c4bbdfSmrg                                      XkbStickyKeysMask);
28335c4bbdfSmrg            }
28435c4bbdfSmrg            /* LatchToLock */
28535c4bbdfSmrg            common = mask & xkbi->state.latched_mods;
28635c4bbdfSmrg            if ((filter->upAction.mods.flags & XkbSA_LatchToLock) && common) {
28735c4bbdfSmrg                unsigned char newlocked;
28835c4bbdfSmrg
28935c4bbdfSmrg                mask &= ~common;
29035c4bbdfSmrg                newlocked = common & ~xkbi->state.locked_mods;
29135c4bbdfSmrg                if(newlocked){
29235c4bbdfSmrg                    xkbi->state.locked_mods |= newlocked;
29335c4bbdfSmrg                    if (needBeep)
29435c4bbdfSmrg                        XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LOCK,
29535c4bbdfSmrg                                          XkbStickyKeysMask);
29635c4bbdfSmrg
29735c4bbdfSmrg                }
29835c4bbdfSmrg                xkbi->state.latched_mods &= ~common;
29935c4bbdfSmrg            }
30035c4bbdfSmrg            /* Latch remaining modifiers, if any. */
30135c4bbdfSmrg            if (mask) {
30235c4bbdfSmrg                xkbi->state.latched_mods |= mask;
30335c4bbdfSmrg                filter->priv = LATCH_PENDING;
30435c4bbdfSmrg                if (needBeep)
30535c4bbdfSmrg                    XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LATCH,
30635c4bbdfSmrg                                      XkbStickyKeysMask);
30735c4bbdfSmrg            }
30835c4bbdfSmrg        }
30935c4bbdfSmrg        else {
31035c4bbdfSmrg            xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
31135c4bbdfSmrg            /* ClearLocks */
31235c4bbdfSmrg            if ((filter->upAction.group.flags & XkbSA_ClearLocks) &&
31335c4bbdfSmrg                (xkbi->state.locked_group)) {
31435c4bbdfSmrg                xkbi->state.locked_group = 0;
31535c4bbdfSmrg                if (needBeep)
31635c4bbdfSmrg                    XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_UNLOCK,
31735c4bbdfSmrg                                      XkbStickyKeysMask);
31835c4bbdfSmrg            }
31935c4bbdfSmrg            /* LatchToLock */
32035c4bbdfSmrg            else if ((filter->upAction.group.flags & XkbSA_LatchToLock)
32135c4bbdfSmrg                     && (xkbi->state.latched_group)) {
32235c4bbdfSmrg                xkbi->state.locked_group  += XkbSAGroup(&filter->upAction.group);
32335c4bbdfSmrg                xkbi->state.latched_group -= XkbSAGroup(&filter->upAction.group);
32435c4bbdfSmrg                if(XkbSAGroup(&filter->upAction.group) && needBeep)
32535c4bbdfSmrg                    XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LOCK,
32635c4bbdfSmrg                                      XkbStickyKeysMask);
32735c4bbdfSmrg            }
32835c4bbdfSmrg            /* Latch group */
32935c4bbdfSmrg            else if(XkbSAGroup(&filter->upAction.group)){
33035c4bbdfSmrg                xkbi->state.latched_group += XkbSAGroup(&filter->upAction.group);
33135c4bbdfSmrg                filter->priv = LATCH_PENDING;
33235c4bbdfSmrg                if (needBeep)
33335c4bbdfSmrg                    XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LATCH,
33435c4bbdfSmrg                                      XkbStickyKeysMask);
33535c4bbdfSmrg            }
33635c4bbdfSmrg        }
33735c4bbdfSmrg
33835c4bbdfSmrg        if (filter->priv != LATCH_PENDING)
33935c4bbdfSmrg            filter->active = 0;
34005b261ecSmrg    }
34135c4bbdfSmrg    else if (pAction && (filter->priv == LATCH_KEY_DOWN)) {
34235c4bbdfSmrg        /* Latch was broken before it became pending: degrade to a
34335c4bbdfSmrg           SetMods/SetGroup. */
34435c4bbdfSmrg        if (filter->upAction.type == XkbSA_LatchMods)
34535c4bbdfSmrg            filter->upAction.type = XkbSA_SetMods;
34635c4bbdfSmrg        else
34735c4bbdfSmrg            filter->upAction.type = XkbSA_SetGroup;
34835c4bbdfSmrg        filter->filter = _XkbFilterSetState;
34935c4bbdfSmrg        filter->priv = 0;
35035c4bbdfSmrg        return filter->filter(xkbi, filter, keycode, pAction);
35105b261ecSmrg    }
35205b261ecSmrg    return 1;
35305b261ecSmrg}
35405b261ecSmrg
35505b261ecSmrgstatic int
35635c4bbdfSmrg_XkbFilterLockState(XkbSrvInfoPtr xkbi,
35735c4bbdfSmrg                    XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
35805b261ecSmrg{
35935c4bbdfSmrg    if (filter->keycode == 0) /* initial press */
36035c4bbdfSmrg        AccessXCancelRepeatKey(xkbi, keycode);
36135c4bbdfSmrg
36235c4bbdfSmrg    if (pAction && (pAction->type == XkbSA_LockGroup)) {
36335c4bbdfSmrg        if (pAction->group.flags & XkbSA_GroupAbsolute)
36435c4bbdfSmrg            xkbi->state.locked_group = XkbSAGroup(&pAction->group);
36535c4bbdfSmrg        else
36635c4bbdfSmrg            xkbi->state.locked_group += XkbSAGroup(&pAction->group);
36735c4bbdfSmrg        return 1;
36805b261ecSmrg    }
36935c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
37035c4bbdfSmrg        filter->keycode = keycode;
37135c4bbdfSmrg        filter->active = 1;
37235c4bbdfSmrg        filter->filterOthers = 0;
37335c4bbdfSmrg        filter->priv = xkbi->state.locked_mods & pAction->mods.mask;
37435c4bbdfSmrg        filter->filter = _XkbFilterLockState;
37535c4bbdfSmrg        filter->upAction = *pAction;
37635c4bbdfSmrg        if (!(filter->upAction.mods.flags & XkbSA_LockNoLock))
37735c4bbdfSmrg            xkbi->state.locked_mods |= pAction->mods.mask;
37835c4bbdfSmrg        xkbi->setMods = pAction->mods.mask;
37905b261ecSmrg    }
38035c4bbdfSmrg    else if (filter->keycode == keycode) {
38135c4bbdfSmrg        filter->active = 0;
38235c4bbdfSmrg        xkbi->clearMods = filter->upAction.mods.mask;
38335c4bbdfSmrg        if (!(filter->upAction.mods.flags & XkbSA_LockNoUnlock))
38435c4bbdfSmrg            xkbi->state.locked_mods &= ~filter->priv;
38505b261ecSmrg    }
38605b261ecSmrg    return 1;
38705b261ecSmrg}
38805b261ecSmrg
38905b261ecSmrg#define	ISO_KEY_DOWN		0
39005b261ecSmrg#define	NO_ISO_LOCK		1
39105b261ecSmrg
39205b261ecSmrgstatic int
39335c4bbdfSmrg_XkbFilterISOLock(XkbSrvInfoPtr xkbi,
39435c4bbdfSmrg                  XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
39505b261ecSmrg{
39605b261ecSmrg
39735c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
39835c4bbdfSmrg        CARD8 flags = pAction->iso.flags;
39935c4bbdfSmrg
40035c4bbdfSmrg        filter->keycode = keycode;
40135c4bbdfSmrg        filter->active = 1;
40235c4bbdfSmrg        filter->filterOthers = 1;
40335c4bbdfSmrg        filter->priv = ISO_KEY_DOWN;
40435c4bbdfSmrg        filter->upAction = *pAction;
40535c4bbdfSmrg        filter->filter = _XkbFilterISOLock;
40635c4bbdfSmrg        if (flags & XkbSA_ISODfltIsGroup) {
40735c4bbdfSmrg            xkbi->groupChange = XkbSAGroup(&pAction->iso);
40835c4bbdfSmrg            xkbi->setMods = 0;
40935c4bbdfSmrg        }
41035c4bbdfSmrg        else {
41135c4bbdfSmrg            xkbi->setMods = pAction->iso.mask;
41235c4bbdfSmrg            xkbi->groupChange = 0;
41335c4bbdfSmrg        }
41435c4bbdfSmrg        if ((!(flags & XkbSA_ISONoAffectMods)) && (xkbi->state.base_mods)) {
41535c4bbdfSmrg            filter->priv = NO_ISO_LOCK;
41635c4bbdfSmrg            xkbi->state.locked_mods ^= xkbi->state.base_mods;
41735c4bbdfSmrg        }
41835c4bbdfSmrg        if ((!(flags & XkbSA_ISONoAffectGroup)) && (xkbi->state.base_group)) {
41905b261ecSmrg/* 6/22/93 (ef) -- lock groups if group key is down first */
42035c4bbdfSmrg        }
42135c4bbdfSmrg        if (!(flags & XkbSA_ISONoAffectPtr)) {
42205b261ecSmrg/* 6/22/93 (ef) -- lock mouse buttons if they're down */
42335c4bbdfSmrg        }
42405b261ecSmrg    }
42535c4bbdfSmrg    else if (filter->keycode == keycode) {
42635c4bbdfSmrg        CARD8 flags = filter->upAction.iso.flags;
42735c4bbdfSmrg
42835c4bbdfSmrg        if (flags & XkbSA_ISODfltIsGroup) {
42935c4bbdfSmrg            xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso);
43035c4bbdfSmrg            xkbi->clearMods = 0;
43135c4bbdfSmrg            if (filter->priv == ISO_KEY_DOWN)
43235c4bbdfSmrg                xkbi->state.locked_group += XkbSAGroup(&filter->upAction.iso);
43335c4bbdfSmrg        }
43435c4bbdfSmrg        else {
43535c4bbdfSmrg            xkbi->clearMods = filter->upAction.iso.mask;
43635c4bbdfSmrg            xkbi->groupChange = 0;
43735c4bbdfSmrg            if (filter->priv == ISO_KEY_DOWN)
43835c4bbdfSmrg                xkbi->state.locked_mods ^= filter->upAction.iso.mask;
43935c4bbdfSmrg        }
44035c4bbdfSmrg        filter->active = 0;
44105b261ecSmrg    }
44205b261ecSmrg    else if (pAction) {
44335c4bbdfSmrg        CARD8 flags = filter->upAction.iso.flags;
44435c4bbdfSmrg
44535c4bbdfSmrg        switch (pAction->type) {
44635c4bbdfSmrg        case XkbSA_SetMods:
44735c4bbdfSmrg        case XkbSA_LatchMods:
44835c4bbdfSmrg            if (!(flags & XkbSA_ISONoAffectMods)) {
44935c4bbdfSmrg                pAction->type = XkbSA_LockMods;
45035c4bbdfSmrg                filter->priv = NO_ISO_LOCK;
45135c4bbdfSmrg            }
45235c4bbdfSmrg            break;
45335c4bbdfSmrg        case XkbSA_SetGroup:
45435c4bbdfSmrg        case XkbSA_LatchGroup:
45535c4bbdfSmrg            if (!(flags & XkbSA_ISONoAffectGroup)) {
45635c4bbdfSmrg                pAction->type = XkbSA_LockGroup;
45735c4bbdfSmrg                filter->priv = NO_ISO_LOCK;
45835c4bbdfSmrg            }
45935c4bbdfSmrg            break;
46035c4bbdfSmrg        case XkbSA_PtrBtn:
46135c4bbdfSmrg            if (!(flags & XkbSA_ISONoAffectPtr)) {
46235c4bbdfSmrg                pAction->type = XkbSA_LockPtrBtn;
46335c4bbdfSmrg                filter->priv = NO_ISO_LOCK;
46435c4bbdfSmrg            }
46535c4bbdfSmrg            break;
46635c4bbdfSmrg        case XkbSA_SetControls:
46735c4bbdfSmrg            if (!(flags & XkbSA_ISONoAffectCtrls)) {
46835c4bbdfSmrg                pAction->type = XkbSA_LockControls;
46935c4bbdfSmrg                filter->priv = NO_ISO_LOCK;
47035c4bbdfSmrg            }
47135c4bbdfSmrg            break;
47235c4bbdfSmrg        }
47305b261ecSmrg    }
47405b261ecSmrg    return 1;
47505b261ecSmrg}
47605b261ecSmrg
47705b261ecSmrgstatic CARD32
47835c4bbdfSmrg_XkbPtrAccelExpire(OsTimerPtr timer, CARD32 now, void *arg)
47905b261ecSmrg{
48035c4bbdfSmrg    XkbSrvInfoPtr xkbi = (XkbSrvInfoPtr) arg;
48135c4bbdfSmrg    XkbControlsPtr ctrls = xkbi->desc->ctrls;
48235c4bbdfSmrg    int dx, dy;
48305b261ecSmrg
48435c4bbdfSmrg    if (xkbi->mouseKey == 0)
48535c4bbdfSmrg        return 0;
48605b261ecSmrg
48705b261ecSmrg    if (xkbi->mouseKeysAccel) {
48835c4bbdfSmrg        if ((xkbi->mouseKeysCounter) < ctrls->mk_time_to_max) {
48935c4bbdfSmrg            double step;
49035c4bbdfSmrg
49135c4bbdfSmrg            xkbi->mouseKeysCounter++;
49235c4bbdfSmrg            step = xkbi->mouseKeysCurveFactor *
49335c4bbdfSmrg                pow((double) xkbi->mouseKeysCounter, xkbi->mouseKeysCurve);
49435c4bbdfSmrg            if (xkbi->mouseKeysDX < 0)
49535c4bbdfSmrg                dx = floor(((double) xkbi->mouseKeysDX) * step);
49635c4bbdfSmrg            else
49735c4bbdfSmrg                dx = ceil(((double) xkbi->mouseKeysDX) * step);
49835c4bbdfSmrg            if (xkbi->mouseKeysDY < 0)
49935c4bbdfSmrg                dy = floor(((double) xkbi->mouseKeysDY) * step);
50035c4bbdfSmrg            else
50135c4bbdfSmrg                dy = ceil(((double) xkbi->mouseKeysDY) * step);
50235c4bbdfSmrg        }
50335c4bbdfSmrg        else {
50435c4bbdfSmrg            dx = xkbi->mouseKeysDX * ctrls->mk_max_speed;
50535c4bbdfSmrg            dy = xkbi->mouseKeysDY * ctrls->mk_max_speed;
50635c4bbdfSmrg        }
50735c4bbdfSmrg        if (xkbi->mouseKeysFlags & XkbSA_MoveAbsoluteX)
50835c4bbdfSmrg            dx = xkbi->mouseKeysDX;
50935c4bbdfSmrg        if (xkbi->mouseKeysFlags & XkbSA_MoveAbsoluteY)
51035c4bbdfSmrg            dy = xkbi->mouseKeysDY;
51105b261ecSmrg    }
51205b261ecSmrg    else {
51335c4bbdfSmrg        dx = xkbi->mouseKeysDX;
51435c4bbdfSmrg        dy = xkbi->mouseKeysDY;
51505b261ecSmrg    }
51635c4bbdfSmrg    XkbFakePointerMotion(xkbi->device, xkbi->mouseKeysFlags, dx, dy);
51705b261ecSmrg    return xkbi->desc->ctrls->mk_interval;
51805b261ecSmrg}
51905b261ecSmrg
52005b261ecSmrgstatic int
52135c4bbdfSmrg_XkbFilterPointerMove(XkbSrvInfoPtr xkbi,
52235c4bbdfSmrg                      XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
52305b261ecSmrg{
52435c4bbdfSmrg    int x, y;
52535c4bbdfSmrg    Bool accel;
52635c4bbdfSmrg
52735c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
52835c4bbdfSmrg        filter->keycode = keycode;
52935c4bbdfSmrg        filter->active = 1;
53035c4bbdfSmrg        filter->filterOthers = 0;
53135c4bbdfSmrg        filter->priv = 0;
53235c4bbdfSmrg        filter->filter = _XkbFilterPointerMove;
53335c4bbdfSmrg        filter->upAction = *pAction;
53435c4bbdfSmrg        xkbi->mouseKeysCounter = 0;
53535c4bbdfSmrg        xkbi->mouseKey = keycode;
53635c4bbdfSmrg        accel = ((pAction->ptr.flags & XkbSA_NoAcceleration) == 0);
53735c4bbdfSmrg        x = XkbPtrActionX(&pAction->ptr);
53835c4bbdfSmrg        y = XkbPtrActionY(&pAction->ptr);
53935c4bbdfSmrg        XkbFakePointerMotion(xkbi->device, pAction->ptr.flags, x, y);
54035c4bbdfSmrg        AccessXCancelRepeatKey(xkbi, keycode);
54135c4bbdfSmrg        xkbi->mouseKeysAccel = accel &&
54235c4bbdfSmrg            (xkbi->desc->ctrls->enabled_ctrls & XkbMouseKeysAccelMask);
54335c4bbdfSmrg        xkbi->mouseKeysFlags = pAction->ptr.flags;
54435c4bbdfSmrg        xkbi->mouseKeysDX = XkbPtrActionX(&pAction->ptr);
54535c4bbdfSmrg        xkbi->mouseKeysDY = XkbPtrActionY(&pAction->ptr);
54635c4bbdfSmrg        xkbi->mouseKeyTimer = TimerSet(xkbi->mouseKeyTimer, 0,
54735c4bbdfSmrg                                       xkbi->desc->ctrls->mk_delay,
54835c4bbdfSmrg                                       _XkbPtrAccelExpire, (void *) xkbi);
54905b261ecSmrg    }
55035c4bbdfSmrg    else if (filter->keycode == keycode) {
55135c4bbdfSmrg        filter->active = 0;
55235c4bbdfSmrg        if (xkbi->mouseKey == keycode) {
55335c4bbdfSmrg            xkbi->mouseKey = 0;
55435c4bbdfSmrg            xkbi->mouseKeyTimer = TimerSet(xkbi->mouseKeyTimer, 0, 0,
55535c4bbdfSmrg                                           NULL, NULL);
55635c4bbdfSmrg        }
55705b261ecSmrg    }
55805b261ecSmrg    return 0;
55905b261ecSmrg}
56005b261ecSmrg
56105b261ecSmrgstatic int
56235c4bbdfSmrg_XkbFilterPointerBtn(XkbSrvInfoPtr xkbi,
56335c4bbdfSmrg                     XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
56405b261ecSmrg{
56535c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
56635c4bbdfSmrg        int button = pAction->btn.button;
56735c4bbdfSmrg
56835c4bbdfSmrg        if (button == XkbSA_UseDfltButton)
56935c4bbdfSmrg            button = xkbi->desc->ctrls->mk_dflt_btn;
57035c4bbdfSmrg
57135c4bbdfSmrg        filter->keycode = keycode;
57235c4bbdfSmrg        filter->active = 1;
57335c4bbdfSmrg        filter->filterOthers = 0;
57435c4bbdfSmrg        filter->priv = 0;
57535c4bbdfSmrg        filter->filter = _XkbFilterPointerBtn;
57635c4bbdfSmrg        filter->upAction = *pAction;
57735c4bbdfSmrg        filter->upAction.btn.button = button;
57835c4bbdfSmrg        switch (pAction->type) {
57935c4bbdfSmrg        case XkbSA_LockPtrBtn:
58035c4bbdfSmrg            if (((xkbi->lockedPtrButtons & (1 << button)) == 0) &&
58135c4bbdfSmrg                ((pAction->btn.flags & XkbSA_LockNoLock) == 0)) {
58235c4bbdfSmrg                xkbi->lockedPtrButtons |= (1 << button);
58335c4bbdfSmrg                AccessXCancelRepeatKey(xkbi, keycode);
58435c4bbdfSmrg                XkbFakeDeviceButton(xkbi->device, 1, button);
58535c4bbdfSmrg                filter->upAction.type = XkbSA_NoAction;
58635c4bbdfSmrg            }
58735c4bbdfSmrg            break;
58835c4bbdfSmrg        case XkbSA_PtrBtn:
58935c4bbdfSmrg        {
59035c4bbdfSmrg            register int i, nClicks;
59135c4bbdfSmrg
59235c4bbdfSmrg            AccessXCancelRepeatKey(xkbi, keycode);
59335c4bbdfSmrg            if (pAction->btn.count > 0) {
59435c4bbdfSmrg                nClicks = pAction->btn.count;
59535c4bbdfSmrg                for (i = 0; i < nClicks; i++) {
59635c4bbdfSmrg                    XkbFakeDeviceButton(xkbi->device, 1, button);
59735c4bbdfSmrg                    XkbFakeDeviceButton(xkbi->device, 0, button);
59835c4bbdfSmrg                }
59935c4bbdfSmrg                filter->upAction.type = XkbSA_NoAction;
60035c4bbdfSmrg            }
60135c4bbdfSmrg            else
60235c4bbdfSmrg                XkbFakeDeviceButton(xkbi->device, 1, button);
60335c4bbdfSmrg        }
60435c4bbdfSmrg            break;
60535c4bbdfSmrg        case XkbSA_SetPtrDflt:
60635c4bbdfSmrg        {
60735c4bbdfSmrg            XkbControlsPtr ctrls = xkbi->desc->ctrls;
60835c4bbdfSmrg            XkbControlsRec old;
60935c4bbdfSmrg            xkbControlsNotify cn;
61035c4bbdfSmrg
61135c4bbdfSmrg            old = *ctrls;
61235c4bbdfSmrg            AccessXCancelRepeatKey(xkbi, keycode);
61335c4bbdfSmrg            switch (pAction->dflt.affect) {
61435c4bbdfSmrg            case XkbSA_AffectDfltBtn:
61535c4bbdfSmrg                if (pAction->dflt.flags & XkbSA_DfltBtnAbsolute)
61635c4bbdfSmrg                    ctrls->mk_dflt_btn = XkbSAPtrDfltValue(&pAction->dflt);
61735c4bbdfSmrg                else {
61835c4bbdfSmrg                    ctrls->mk_dflt_btn += XkbSAPtrDfltValue(&pAction->dflt);
61935c4bbdfSmrg                    if (ctrls->mk_dflt_btn > 5)
62035c4bbdfSmrg                        ctrls->mk_dflt_btn = 5;
62135c4bbdfSmrg                    else if (ctrls->mk_dflt_btn < 1)
62235c4bbdfSmrg                        ctrls->mk_dflt_btn = 1;
62335c4bbdfSmrg                }
62435c4bbdfSmrg                break;
62535c4bbdfSmrg            default:
62635c4bbdfSmrg                ErrorF
62735c4bbdfSmrg                    ("Attempt to change unknown pointer default (%d) ignored\n",
62835c4bbdfSmrg                     pAction->dflt.affect);
62935c4bbdfSmrg                break;
63035c4bbdfSmrg            }
63135c4bbdfSmrg            if (XkbComputeControlsNotify(xkbi->device,
63235c4bbdfSmrg                                         &old, xkbi->desc->ctrls, &cn, FALSE)) {
63335c4bbdfSmrg                cn.keycode = keycode;
63435c4bbdfSmrg                /* XXX: what about DeviceKeyPress? */
63535c4bbdfSmrg                cn.eventType = KeyPress;
63635c4bbdfSmrg                cn.requestMajor = 0;
63735c4bbdfSmrg                cn.requestMinor = 0;
63835c4bbdfSmrg                XkbSendControlsNotify(xkbi->device, &cn);
63935c4bbdfSmrg            }
64035c4bbdfSmrg        }
64135c4bbdfSmrg            break;
64235c4bbdfSmrg        }
64335c4bbdfSmrg        return 0;
64405b261ecSmrg    }
64535c4bbdfSmrg    else if (filter->keycode == keycode) {
64635c4bbdfSmrg        int button = filter->upAction.btn.button;
64735c4bbdfSmrg
64835c4bbdfSmrg        switch (filter->upAction.type) {
64935c4bbdfSmrg        case XkbSA_LockPtrBtn:
65035c4bbdfSmrg            if (((filter->upAction.btn.flags & XkbSA_LockNoUnlock) != 0) ||
65135c4bbdfSmrg                ((xkbi->lockedPtrButtons & (1 << button)) == 0)) {
65235c4bbdfSmrg                break;
65335c4bbdfSmrg            }
65435c4bbdfSmrg            xkbi->lockedPtrButtons &= ~(1 << button);
65535c4bbdfSmrg
65635c4bbdfSmrg            if (IsMaster(xkbi->device)) {
65735c4bbdfSmrg                XkbMergeLockedPtrBtns(xkbi->device);
65835c4bbdfSmrg                /* One SD still has lock set, don't post event */
65935c4bbdfSmrg                if ((xkbi->lockedPtrButtons & (1 << button)) != 0)
66035c4bbdfSmrg                    break;
66135c4bbdfSmrg            }
66235c4bbdfSmrg
66335c4bbdfSmrg            /* fallthrough */
66435c4bbdfSmrg        case XkbSA_PtrBtn:
66535c4bbdfSmrg            XkbFakeDeviceButton(xkbi->device, 0, button);
66635c4bbdfSmrg            break;
66735c4bbdfSmrg        }
66835c4bbdfSmrg        filter->active = 0;
66935c4bbdfSmrg        return 0;
67005b261ecSmrg    }
67135c4bbdfSmrg    return 1;
67205b261ecSmrg}
67305b261ecSmrg
67405b261ecSmrgstatic int
67535c4bbdfSmrg_XkbFilterControls(XkbSrvInfoPtr xkbi,
67635c4bbdfSmrg                   XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
67705b261ecSmrg{
67835c4bbdfSmrg    XkbControlsRec old;
67935c4bbdfSmrg    XkbControlsPtr ctrls;
68035c4bbdfSmrg    DeviceIntPtr kbd;
68135c4bbdfSmrg    unsigned int change;
68235c4bbdfSmrg    XkbEventCauseRec cause;
68335c4bbdfSmrg
68435c4bbdfSmrg    kbd = xkbi->device;
68535c4bbdfSmrg    ctrls = xkbi->desc->ctrls;
68635c4bbdfSmrg    old = *ctrls;
68735c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
68835c4bbdfSmrg        AccessXCancelRepeatKey(xkbi, keycode);
68935c4bbdfSmrg        filter->keycode = keycode;
69035c4bbdfSmrg        filter->active = 1;
69135c4bbdfSmrg        filter->filterOthers = 0;
69235c4bbdfSmrg        change = XkbActionCtrls(&pAction->ctrls);
69335c4bbdfSmrg        filter->priv = change;
69435c4bbdfSmrg        filter->filter = _XkbFilterControls;
69535c4bbdfSmrg        filter->upAction = *pAction;
69635c4bbdfSmrg
69735c4bbdfSmrg        if (pAction->type == XkbSA_LockControls) {
69835c4bbdfSmrg            filter->priv = (ctrls->enabled_ctrls & change);
69935c4bbdfSmrg            change &= ~ctrls->enabled_ctrls;
70035c4bbdfSmrg        }
70135c4bbdfSmrg
70235c4bbdfSmrg        if (change) {
70335c4bbdfSmrg            xkbControlsNotify cn;
70435c4bbdfSmrg            XkbSrvLedInfoPtr sli;
70535c4bbdfSmrg
70635c4bbdfSmrg            ctrls->enabled_ctrls |= change;
70735c4bbdfSmrg            if (XkbComputeControlsNotify(kbd, &old, ctrls, &cn, FALSE)) {
70835c4bbdfSmrg                cn.keycode = keycode;
70905b261ecSmrg                /* XXX: what about DeviceKeyPress? */
71035c4bbdfSmrg                cn.eventType = KeyPress;
71135c4bbdfSmrg                cn.requestMajor = 0;
71235c4bbdfSmrg                cn.requestMinor = 0;
71335c4bbdfSmrg                XkbSendControlsNotify(kbd, &cn);
71435c4bbdfSmrg            }
71535c4bbdfSmrg
71635c4bbdfSmrg            XkbSetCauseKey(&cause, keycode, KeyPress);
71735c4bbdfSmrg
71835c4bbdfSmrg            /* If sticky keys were disabled, clear all locks and latches */
71935c4bbdfSmrg            if ((old.enabled_ctrls & XkbStickyKeysMask) &&
72035c4bbdfSmrg                (!(ctrls->enabled_ctrls & XkbStickyKeysMask))) {
72135c4bbdfSmrg                XkbClearAllLatchesAndLocks(kbd, xkbi, FALSE, &cause);
72235c4bbdfSmrg            }
72335c4bbdfSmrg            sli = XkbFindSrvLedInfo(kbd, XkbDfltXIClass, XkbDfltXIId, 0);
72435c4bbdfSmrg            XkbUpdateIndicators(kbd, sli->usesControls, TRUE, NULL, &cause);
72535c4bbdfSmrg            if (XkbAX_NeedFeedback(ctrls, XkbAX_FeatureFBMask))
72635c4bbdfSmrg                XkbDDXAccessXBeep(kbd, _BEEP_FEATURE_ON, change);
72735c4bbdfSmrg        }
72805b261ecSmrg    }
72935c4bbdfSmrg    else if (filter->keycode == keycode) {
73035c4bbdfSmrg        change = filter->priv;
73135c4bbdfSmrg        if (change) {
73235c4bbdfSmrg            xkbControlsNotify cn;
73335c4bbdfSmrg            XkbSrvLedInfoPtr sli;
73435c4bbdfSmrg
73535c4bbdfSmrg            ctrls->enabled_ctrls &= ~change;
73635c4bbdfSmrg            if (XkbComputeControlsNotify(kbd, &old, ctrls, &cn, FALSE)) {
73735c4bbdfSmrg                cn.keycode = keycode;
73835c4bbdfSmrg                cn.eventType = KeyRelease;
73935c4bbdfSmrg                cn.requestMajor = 0;
74035c4bbdfSmrg                cn.requestMinor = 0;
74135c4bbdfSmrg                XkbSendControlsNotify(kbd, &cn);
74235c4bbdfSmrg            }
74335c4bbdfSmrg
74435c4bbdfSmrg            XkbSetCauseKey(&cause, keycode, KeyRelease);
74535c4bbdfSmrg            /* If sticky keys were disabled, clear all locks and latches */
74635c4bbdfSmrg            if ((old.enabled_ctrls & XkbStickyKeysMask) &&
74735c4bbdfSmrg                (!(ctrls->enabled_ctrls & XkbStickyKeysMask))) {
74835c4bbdfSmrg                XkbClearAllLatchesAndLocks(kbd, xkbi, FALSE, &cause);
74935c4bbdfSmrg            }
75035c4bbdfSmrg            sli = XkbFindSrvLedInfo(kbd, XkbDfltXIClass, XkbDfltXIId, 0);
75135c4bbdfSmrg            XkbUpdateIndicators(kbd, sli->usesControls, TRUE, NULL, &cause);
75235c4bbdfSmrg            if (XkbAX_NeedFeedback(ctrls, XkbAX_FeatureFBMask))
75335c4bbdfSmrg                XkbDDXAccessXBeep(kbd, _BEEP_FEATURE_OFF, change);
75435c4bbdfSmrg        }
75535c4bbdfSmrg        filter->keycode = 0;
75635c4bbdfSmrg        filter->active = 0;
75705b261ecSmrg    }
75805b261ecSmrg    return 1;
75905b261ecSmrg}
76005b261ecSmrg
76105b261ecSmrgstatic int
76235c4bbdfSmrg_XkbFilterActionMessage(XkbSrvInfoPtr xkbi,
76335c4bbdfSmrg                        XkbFilterPtr filter,
76435c4bbdfSmrg                        unsigned keycode, XkbAction *pAction)
76505b261ecSmrg{
76635c4bbdfSmrg    XkbMessageAction *pMsg;
76735c4bbdfSmrg    DeviceIntPtr kbd;
76835c4bbdfSmrg
76935c4bbdfSmrg    if ((filter->keycode != 0) && (filter->keycode != keycode))
77035c4bbdfSmrg	return 1;
77135c4bbdfSmrg
77235c4bbdfSmrg    /* This can happen if the key repeats, and the state (modifiers or group)
77335c4bbdfSmrg       changes meanwhile. */
77435c4bbdfSmrg    if ((filter->keycode == keycode) && pAction &&
77535c4bbdfSmrg	(pAction->type != XkbSA_ActionMessage))
77635c4bbdfSmrg	return 1;
77735c4bbdfSmrg
77835c4bbdfSmrg    kbd = xkbi->device;
77935c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
78035c4bbdfSmrg        pMsg = &pAction->msg;
78135c4bbdfSmrg        if ((pMsg->flags & XkbSA_MessageOnRelease) ||
78235c4bbdfSmrg            ((pMsg->flags & XkbSA_MessageGenKeyEvent) == 0)) {
78335c4bbdfSmrg            filter->keycode = keycode;
78435c4bbdfSmrg            filter->active = 1;
78535c4bbdfSmrg            filter->filterOthers = 0;
78635c4bbdfSmrg            filter->priv = 0;
78735c4bbdfSmrg            filter->filter = _XkbFilterActionMessage;
78835c4bbdfSmrg            filter->upAction = *pAction;
78935c4bbdfSmrg        }
79035c4bbdfSmrg        if (pMsg->flags & XkbSA_MessageOnPress) {
79135c4bbdfSmrg            xkbActionMessage msg;
79235c4bbdfSmrg
79335c4bbdfSmrg            msg.keycode = keycode;
79435c4bbdfSmrg            msg.press = 1;
79535c4bbdfSmrg            msg.keyEventFollows =
79635c4bbdfSmrg                ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
79735c4bbdfSmrg            memcpy((char *) msg.message, (char *) pMsg->message,
79835c4bbdfSmrg                   XkbActionMessageLength);
79935c4bbdfSmrg            XkbSendActionMessage(kbd, &msg);
80035c4bbdfSmrg        }
80135c4bbdfSmrg        return ((pAction->msg.flags & XkbSA_MessageGenKeyEvent) != 0);
80205b261ecSmrg    }
80335c4bbdfSmrg    else if (filter->keycode == keycode) {
80435c4bbdfSmrg        pMsg = &filter->upAction.msg;
80535c4bbdfSmrg	if (pAction == NULL) {
80635c4bbdfSmrg	    if (pMsg->flags & XkbSA_MessageOnRelease) {
80735c4bbdfSmrg		xkbActionMessage msg;
80835c4bbdfSmrg
80935c4bbdfSmrg		msg.keycode = keycode;
81035c4bbdfSmrg		msg.press = 0;
81135c4bbdfSmrg		msg.keyEventFollows =
81235c4bbdfSmrg		    ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
81335c4bbdfSmrg		memcpy((char *) msg.message, (char *) pMsg->message,
81435c4bbdfSmrg		       XkbActionMessageLength);
81535c4bbdfSmrg		XkbSendActionMessage(kbd, &msg);
81635c4bbdfSmrg	    }
81735c4bbdfSmrg	    filter->keycode = 0;
81835c4bbdfSmrg	    filter->active = 0;
81935c4bbdfSmrg	    return ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
82035c4bbdfSmrg	} else if (memcmp(pMsg, pAction, 8) == 0) {
82135c4bbdfSmrg	    /* Repeat: If we send the same message, avoid multiple messages
82235c4bbdfSmrg	       on release from piling up. */
82335c4bbdfSmrg	    filter->keycode = 0;
82435c4bbdfSmrg	    filter->active = 0;
82535c4bbdfSmrg        }
82605b261ecSmrg    }
82735c4bbdfSmrg    return 1;
82805b261ecSmrg}
82905b261ecSmrg
83005b261ecSmrgstatic int
83135c4bbdfSmrg_XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
83235c4bbdfSmrg                      XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
83305b261ecSmrg{
83435c4bbdfSmrg    DeviceEvent ev;
83535c4bbdfSmrg    int x, y;
83635c4bbdfSmrg    XkbStateRec old, old_prev;
83735c4bbdfSmrg    unsigned mods, mask;
83835c4bbdfSmrg    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
83935c4bbdfSmrg    ProcessInputProc backupproc;
84035c4bbdfSmrg
84135c4bbdfSmrg    if ((filter->keycode != 0) && (filter->keycode != keycode))
84235c4bbdfSmrg        return 1;
84335c4bbdfSmrg
84435c4bbdfSmrg    /* This can happen if the key repeats, and the state (modifiers or group)
84535c4bbdfSmrg       changes meanwhile. */
84635c4bbdfSmrg    if ((filter->keycode == keycode) && pAction &&
84735c4bbdfSmrg	(pAction->type != XkbSA_RedirectKey))
84835c4bbdfSmrg	return 1;
84905b261ecSmrg
85005b261ecSmrg    /* never actually used uninitialised, but gcc isn't smart enough
85105b261ecSmrg     * to work that out. */
85205b261ecSmrg    memset(&old, 0, sizeof(old));
85335c4bbdfSmrg    memset(&old_prev, 0, sizeof(old_prev));
8546747b715Smrg    memset(&ev, 0, sizeof(ev));
85505b261ecSmrg
85635c4bbdfSmrg    GetSpritePosition(xkbi->device, &x, &y);
8576747b715Smrg    ev.header = ET_Internal;
8586747b715Smrg    ev.length = sizeof(DeviceEvent);
8596747b715Smrg    ev.time = GetTimeInMillis();
8606747b715Smrg    ev.root_x = x;
8616747b715Smrg    ev.root_y = y;
86235c4bbdfSmrg    /* redirect actions do not work across devices, therefore the following is
86335c4bbdfSmrg     * correct: */
86435c4bbdfSmrg    ev.deviceid = xkbi->device->id;
86535c4bbdfSmrg    /* filter->priv must be set up by the caller for the initial press. */
86635c4bbdfSmrg    ev.sourceid = filter->priv;
86735c4bbdfSmrg
86835c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
86935c4bbdfSmrg        if ((pAction->redirect.new_key < xkbi->desc->min_key_code) ||
87035c4bbdfSmrg            (pAction->redirect.new_key > xkbi->desc->max_key_code)) {
87135c4bbdfSmrg            return 1;
87235c4bbdfSmrg        }
87335c4bbdfSmrg        filter->keycode = keycode;
87435c4bbdfSmrg        filter->active = 1;
87535c4bbdfSmrg        filter->filterOthers = 0;
87635c4bbdfSmrg        filter->filter = _XkbFilterRedirectKey;
87735c4bbdfSmrg        filter->upAction = *pAction;
87805b261ecSmrg
8796747b715Smrg        ev.type = ET_KeyPress;
8806747b715Smrg        ev.detail.key = pAction->redirect.new_key;
88105b261ecSmrg
88235c4bbdfSmrg        mask = XkbSARedirectVModsMask(&pAction->redirect);
88335c4bbdfSmrg        mods = XkbSARedirectVMods(&pAction->redirect);
88435c4bbdfSmrg        if (mask)
88535c4bbdfSmrg            XkbVirtualModsToReal(xkbi->desc, mask, &mask);
88635c4bbdfSmrg        if (mods)
88735c4bbdfSmrg            XkbVirtualModsToReal(xkbi->desc, mods, &mods);
88835c4bbdfSmrg        mask |= pAction->redirect.mods_mask;
88935c4bbdfSmrg        mods |= pAction->redirect.mods;
89035c4bbdfSmrg
89135c4bbdfSmrg        if (mask || mods) {
89235c4bbdfSmrg            old = xkbi->state;
89335c4bbdfSmrg            old_prev = xkbi->prev_state;
89435c4bbdfSmrg            xkbi->state.base_mods &= ~mask;
89535c4bbdfSmrg            xkbi->state.base_mods |= (mods & mask);
89635c4bbdfSmrg            xkbi->state.latched_mods &= ~mask;
89735c4bbdfSmrg            xkbi->state.latched_mods |= (mods & mask);
89835c4bbdfSmrg            xkbi->state.locked_mods &= ~mask;
89935c4bbdfSmrg            xkbi->state.locked_mods |= (mods & mask);
90035c4bbdfSmrg            XkbComputeDerivedState(xkbi);
90135c4bbdfSmrg            xkbi->prev_state = xkbi->state;
90235c4bbdfSmrg        }
90335c4bbdfSmrg
90435c4bbdfSmrg        UNWRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc);
90535c4bbdfSmrg        xkbi->device->public.processInputProc((InternalEvent *) &ev,
90635c4bbdfSmrg                                              xkbi->device);
90735c4bbdfSmrg        COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc,
90835c4bbdfSmrg                                     xkbUnwrapProc);
90935c4bbdfSmrg
91035c4bbdfSmrg        if (mask || mods) {
91135c4bbdfSmrg            xkbi->state = old;
91235c4bbdfSmrg            xkbi->prev_state = old_prev;
91335c4bbdfSmrg        }
91435c4bbdfSmrg	return 0;
91535c4bbdfSmrg    }
91635c4bbdfSmrg    else {
91735c4bbdfSmrg	/* If it is a key release, or we redirect to another key, release the
91835c4bbdfSmrg	   previous new_key.  Otherwise, repeat. */
91935c4bbdfSmrg	ev.detail.key = filter->upAction.redirect.new_key;
92035c4bbdfSmrg	if (pAction == NULL ||  ev.detail.key != pAction->redirect.new_key) {
92135c4bbdfSmrg	    ev.type = ET_KeyRelease;
92235c4bbdfSmrg	    filter->active = 0;
92335c4bbdfSmrg	}
92435c4bbdfSmrg	else {
92535c4bbdfSmrg	    ev.type = ET_KeyPress;
92635c4bbdfSmrg	    ev.key_repeat = TRUE;
92705b261ecSmrg	}
92805b261ecSmrg
92935c4bbdfSmrg	mask = XkbSARedirectVModsMask(&filter->upAction.redirect);
93035c4bbdfSmrg	mods = XkbSARedirectVMods(&filter->upAction.redirect);
93135c4bbdfSmrg	if (mask)
93235c4bbdfSmrg	    XkbVirtualModsToReal(xkbi->desc, mask, &mask);
93335c4bbdfSmrg	if (mods)
93435c4bbdfSmrg	    XkbVirtualModsToReal(xkbi->desc, mods, &mods);
93535c4bbdfSmrg	mask |= filter->upAction.redirect.mods_mask;
93635c4bbdfSmrg	mods |= filter->upAction.redirect.mods;
93735c4bbdfSmrg
93835c4bbdfSmrg	if (mask || mods) {
93935c4bbdfSmrg	    old = xkbi->state;
94035c4bbdfSmrg	    old_prev = xkbi->prev_state;
94135c4bbdfSmrg	    xkbi->state.base_mods &= ~mask;
94235c4bbdfSmrg	    xkbi->state.base_mods |= (mods & mask);
94335c4bbdfSmrg	    xkbi->state.latched_mods &= ~mask;
94435c4bbdfSmrg	    xkbi->state.latched_mods |= (mods & mask);
94535c4bbdfSmrg	    xkbi->state.locked_mods &= ~mask;
94635c4bbdfSmrg	    xkbi->state.locked_mods |= (mods & mask);
94705b261ecSmrg	    XkbComputeDerivedState(xkbi);
94835c4bbdfSmrg	    xkbi->prev_state = xkbi->state;
94905b261ecSmrg	}
95005b261ecSmrg
95135c4bbdfSmrg	UNWRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc);
95235c4bbdfSmrg	xkbi->device->public.processInputProc((InternalEvent *) &ev,
95335c4bbdfSmrg					      xkbi->device);
95435c4bbdfSmrg	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc,
95535c4bbdfSmrg				     xkbUnwrapProc);
95605b261ecSmrg
95735c4bbdfSmrg	if (mask || mods) {
95835c4bbdfSmrg	    xkbi->state = old;
95935c4bbdfSmrg	    xkbi->prev_state = old_prev;
96035c4bbdfSmrg	}
96105b261ecSmrg
96235c4bbdfSmrg	/* We return 1 in case we have sent a release event because the new_key
96335c4bbdfSmrg	   has changed.  Then, subsequently, we will call this function again
96435c4bbdfSmrg	   with the same pAction, which will create the press for the new
96535c4bbdfSmrg	   new_key. */
96635c4bbdfSmrg	return (pAction && ev.detail.key != pAction->redirect.new_key);
96705b261ecSmrg    }
96805b261ecSmrg}
96905b261ecSmrg
97005b261ecSmrgstatic int
97135c4bbdfSmrg_XkbFilterSwitchScreen(XkbSrvInfoPtr xkbi,
97235c4bbdfSmrg                       XkbFilterPtr filter,
97335c4bbdfSmrg                       unsigned keycode, XkbAction *pAction)
97405b261ecSmrg{
97505b261ecSmrg    DeviceIntPtr dev = xkbi->device;
97635c4bbdfSmrg
97705b261ecSmrg    if (dev == inputInfo.keyboard)
97805b261ecSmrg        return 0;
97905b261ecSmrg
98035c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
98135c4bbdfSmrg        filter->keycode = keycode;
98235c4bbdfSmrg        filter->active = 1;
98335c4bbdfSmrg        filter->filterOthers = 0;
98435c4bbdfSmrg        filter->filter = _XkbFilterSwitchScreen;
98535c4bbdfSmrg        AccessXCancelRepeatKey(xkbi, keycode);
98635c4bbdfSmrg        XkbDDXSwitchScreen(dev, keycode, pAction);
98735c4bbdfSmrg        return 0;
98805b261ecSmrg    }
98935c4bbdfSmrg    else if (filter->keycode == keycode) {
99035c4bbdfSmrg        filter->active = 0;
99135c4bbdfSmrg        return 0;
99205b261ecSmrg    }
99305b261ecSmrg    return 1;
99405b261ecSmrg}
99505b261ecSmrg
996ed6184dfSmrgstatic int
997ed6184dfSmrgXkbHandlePrivate(DeviceIntPtr dev, KeyCode keycode, XkbAction *pAction)
998ed6184dfSmrg{
999ed6184dfSmrg    XkbAnyAction *xkb_act = &(pAction->any);
1000ed6184dfSmrg
1001ed6184dfSmrg    if (xkb_act->type == XkbSA_XFree86Private) {
1002ed6184dfSmrg        char msgbuf[XkbAnyActionDataSize + 1];
1003ed6184dfSmrg
1004ed6184dfSmrg        memcpy(msgbuf, xkb_act->data, XkbAnyActionDataSize);
1005ed6184dfSmrg        msgbuf[XkbAnyActionDataSize] = '\0';
1006ed6184dfSmrg
1007ed6184dfSmrg        if (strcasecmp(msgbuf, "prgrbs") == 0) {
1008ed6184dfSmrg            DeviceIntPtr tmp;
1009ed6184dfSmrg
1010ed6184dfSmrg            LogMessage(X_INFO, "Printing all currently active device grabs:\n");
1011ed6184dfSmrg            for (tmp = inputInfo.devices; tmp; tmp = tmp->next)
1012ed6184dfSmrg                if (tmp->deviceGrab.grab)
1013ed6184dfSmrg                    PrintDeviceGrabInfo(tmp);
1014ed6184dfSmrg            LogMessage(X_INFO, "End list of active device grabs\n");
1015ed6184dfSmrg
1016ed6184dfSmrg            PrintPassiveGrabs();
1017ed6184dfSmrg        }
1018ed6184dfSmrg        else if (strcasecmp(msgbuf, "ungrab") == 0) {
1019ed6184dfSmrg            LogMessage(X_INFO, "Ungrabbing devices\n");
1020ed6184dfSmrg            UngrabAllDevices(FALSE);
1021ed6184dfSmrg        }
1022ed6184dfSmrg        else if (strcasecmp(msgbuf, "clsgrb") == 0) {
1023ed6184dfSmrg            LogMessage(X_INFO, "Clear grabs\n");
1024ed6184dfSmrg            UngrabAllDevices(TRUE);
1025ed6184dfSmrg        }
1026ed6184dfSmrg        else if (strcasecmp(msgbuf, "prwins") == 0) {
1027ed6184dfSmrg            LogMessage(X_INFO, "Printing window tree\n");
1028ed6184dfSmrg            PrintWindowTree();
1029ed6184dfSmrg        }
1030ed6184dfSmrg    }
1031ed6184dfSmrg
1032ed6184dfSmrg    return XkbDDXPrivate(dev, keycode, pAction);
1033ed6184dfSmrg}
1034ed6184dfSmrg
103505b261ecSmrgstatic int
103635c4bbdfSmrg_XkbFilterXF86Private(XkbSrvInfoPtr xkbi,
103735c4bbdfSmrg                      XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
103805b261ecSmrg{
103905b261ecSmrg    DeviceIntPtr dev = xkbi->device;
104035c4bbdfSmrg
104105b261ecSmrg    if (dev == inputInfo.keyboard)
104205b261ecSmrg        return 0;
104305b261ecSmrg
104435c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
104535c4bbdfSmrg        filter->keycode = keycode;
104635c4bbdfSmrg        filter->active = 1;
104735c4bbdfSmrg        filter->filterOthers = 0;
104835c4bbdfSmrg        filter->filter = _XkbFilterXF86Private;
1049ed6184dfSmrg        XkbHandlePrivate(dev, keycode, pAction);
105035c4bbdfSmrg        return 0;
105105b261ecSmrg    }
105235c4bbdfSmrg    else if (filter->keycode == keycode) {
105335c4bbdfSmrg        filter->active = 0;
105435c4bbdfSmrg        return 0;
105505b261ecSmrg    }
105605b261ecSmrg    return 1;
105705b261ecSmrg}
105805b261ecSmrg
105905b261ecSmrgstatic int
106035c4bbdfSmrg_XkbFilterDeviceBtn(XkbSrvInfoPtr xkbi,
106135c4bbdfSmrg                    XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
106205b261ecSmrg{
10634642e01fSmrg    if (xkbi->device == inputInfo.keyboard)
106405b261ecSmrg        return 0;
106505b261ecSmrg
106635c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
106735c4bbdfSmrg        DeviceIntPtr dev;
106835c4bbdfSmrg        int button;
106935c4bbdfSmrg
107035c4bbdfSmrg        _XkbLookupButtonDevice(&dev, pAction->devbtn.device, serverClient,
107135c4bbdfSmrg                               DixUnknownAccess, &button);
107235c4bbdfSmrg        if (!dev || !dev->public.on)
107335c4bbdfSmrg            return 1;
107435c4bbdfSmrg
107535c4bbdfSmrg        button = pAction->devbtn.button;
107635c4bbdfSmrg        if ((button < 1) || (button > dev->button->numButtons))
107735c4bbdfSmrg            return 1;
107835c4bbdfSmrg
107935c4bbdfSmrg        filter->keycode = keycode;
108035c4bbdfSmrg        filter->active = 1;
108135c4bbdfSmrg        filter->filterOthers = 0;
108235c4bbdfSmrg        filter->priv = 0;
108335c4bbdfSmrg        filter->filter = _XkbFilterDeviceBtn;
108435c4bbdfSmrg        filter->upAction = *pAction;
108535c4bbdfSmrg        switch (pAction->type) {
108635c4bbdfSmrg        case XkbSA_LockDeviceBtn:
108735c4bbdfSmrg            if ((pAction->devbtn.flags & XkbSA_LockNoLock) ||
108835c4bbdfSmrg                BitIsOn(dev->button->down, button))
108935c4bbdfSmrg                return 0;
109035c4bbdfSmrg            XkbFakeDeviceButton(dev, TRUE, button);
109135c4bbdfSmrg            filter->upAction.type = XkbSA_NoAction;
109235c4bbdfSmrg            break;
109335c4bbdfSmrg        case XkbSA_DeviceBtn:
109435c4bbdfSmrg            if (pAction->devbtn.count > 0) {
109535c4bbdfSmrg                int nClicks, i;
109635c4bbdfSmrg
109735c4bbdfSmrg                nClicks = pAction->btn.count;
109835c4bbdfSmrg                for (i = 0; i < nClicks; i++) {
109935c4bbdfSmrg                    XkbFakeDeviceButton(dev, TRUE, button);
110035c4bbdfSmrg                    XkbFakeDeviceButton(dev, FALSE, button);
110135c4bbdfSmrg                }
110235c4bbdfSmrg                filter->upAction.type = XkbSA_NoAction;
110335c4bbdfSmrg            }
110435c4bbdfSmrg            else
110535c4bbdfSmrg                XkbFakeDeviceButton(dev, TRUE, button);
110635c4bbdfSmrg            break;
110735c4bbdfSmrg        }
110805b261ecSmrg    }
110935c4bbdfSmrg    else if (filter->keycode == keycode) {
111035c4bbdfSmrg        DeviceIntPtr dev;
111135c4bbdfSmrg        int button;
111235c4bbdfSmrg
111335c4bbdfSmrg        filter->active = 0;
111435c4bbdfSmrg        _XkbLookupButtonDevice(&dev, filter->upAction.devbtn.device,
111535c4bbdfSmrg                               serverClient, DixUnknownAccess, &button);
111635c4bbdfSmrg        if (!dev || !dev->public.on)
111735c4bbdfSmrg            return 1;
111835c4bbdfSmrg
111935c4bbdfSmrg        button = filter->upAction.btn.button;
112035c4bbdfSmrg        switch (filter->upAction.type) {
112135c4bbdfSmrg        case XkbSA_LockDeviceBtn:
112235c4bbdfSmrg            if ((filter->upAction.devbtn.flags & XkbSA_LockNoUnlock) ||
112335c4bbdfSmrg                !BitIsOn(dev->button->down, button))
112435c4bbdfSmrg                return 0;
112535c4bbdfSmrg            XkbFakeDeviceButton(dev, FALSE, button);
112635c4bbdfSmrg            break;
112735c4bbdfSmrg        case XkbSA_DeviceBtn:
112835c4bbdfSmrg            XkbFakeDeviceButton(dev, FALSE, button);
112935c4bbdfSmrg            break;
113035c4bbdfSmrg        }
113135c4bbdfSmrg        filter->active = 0;
113205b261ecSmrg    }
113305b261ecSmrg    return 0;
113405b261ecSmrg}
113505b261ecSmrg
113605b261ecSmrgstatic XkbFilterPtr
113735c4bbdfSmrg_XkbNextFreeFilter(XkbSrvInfoPtr xkbi)
113805b261ecSmrg{
113935c4bbdfSmrg    register int i;
114005b261ecSmrg
114135c4bbdfSmrg    if (xkbi->szFilters == 0) {
114235c4bbdfSmrg        xkbi->szFilters = 4;
114335c4bbdfSmrg        xkbi->filters = calloc(xkbi->szFilters, sizeof(XkbFilterRec));
114435c4bbdfSmrg        /* 6/21/93 (ef) -- XXX! deal with allocation failure */
114505b261ecSmrg    }
114635c4bbdfSmrg    for (i = 0; i < xkbi->szFilters; i++) {
114735c4bbdfSmrg        if (!xkbi->filters[i].active) {
114835c4bbdfSmrg            xkbi->filters[i].keycode = 0;
114935c4bbdfSmrg            return &xkbi->filters[i];
115035c4bbdfSmrg        }
115105b261ecSmrg    }
115235c4bbdfSmrg    xkbi->szFilters *= 2;
115335c4bbdfSmrg    xkbi->filters = reallocarray(xkbi->filters,
115435c4bbdfSmrg                                 xkbi->szFilters, sizeof(XkbFilterRec));
115505b261ecSmrg    /* 6/21/93 (ef) -- XXX! deal with allocation failure */
115635c4bbdfSmrg    memset(&xkbi->filters[xkbi->szFilters / 2], 0,
115735c4bbdfSmrg           (xkbi->szFilters / 2) * sizeof(XkbFilterRec));
115835c4bbdfSmrg    return &xkbi->filters[xkbi->szFilters / 2];
115905b261ecSmrg}
116005b261ecSmrg
116105b261ecSmrgstatic int
116235c4bbdfSmrg_XkbApplyFilters(XkbSrvInfoPtr xkbi, unsigned kc, XkbAction *pAction)
116305b261ecSmrg{
116435c4bbdfSmrg    register int i, send;
116535c4bbdfSmrg
116635c4bbdfSmrg    send = 1;
116735c4bbdfSmrg    for (i = 0; i < xkbi->szFilters; i++) {
116835c4bbdfSmrg        if ((xkbi->filters[i].active) && (xkbi->filters[i].filter))
116935c4bbdfSmrg            send =
117035c4bbdfSmrg                ((*xkbi->filters[i].filter) (xkbi, &xkbi->filters[i], kc,
117135c4bbdfSmrg                                             pAction)
117235c4bbdfSmrg                 && send);
117305b261ecSmrg    }
117405b261ecSmrg    return send;
117505b261ecSmrg}
117605b261ecSmrg
117735c4bbdfSmrgstatic int
117835c4bbdfSmrg_XkbEnsureStateChange(XkbSrvInfoPtr xkbi)
117905b261ecSmrg{
118035c4bbdfSmrg    Bool genStateNotify = FALSE;
118135c4bbdfSmrg
118205b261ecSmrg    /* The state may change, so if we're not in the middle of sending a state
118305b261ecSmrg     * notify, prepare for it */
118435c4bbdfSmrg    if ((xkbi->flags & _XkbStateNotifyInProgress) == 0) {
118535c4bbdfSmrg        xkbi->prev_state = xkbi->state;
118635c4bbdfSmrg        xkbi->flags |= _XkbStateNotifyInProgress;
118735c4bbdfSmrg        genStateNotify = TRUE;
118805b261ecSmrg    }
118935c4bbdfSmrg
119035c4bbdfSmrg    return genStateNotify;
119135c4bbdfSmrg}
119235c4bbdfSmrg
119335c4bbdfSmrgstatic void
119435c4bbdfSmrg_XkbApplyState(DeviceIntPtr dev, Bool genStateNotify, int evtype, int key)
119535c4bbdfSmrg{
119635c4bbdfSmrg    XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
119735c4bbdfSmrg    int changed;
119835c4bbdfSmrg
119935c4bbdfSmrg    XkbComputeDerivedState(xkbi);
120035c4bbdfSmrg
120135c4bbdfSmrg    changed = XkbStateChangedFlags(&xkbi->prev_state, &xkbi->state);
120235c4bbdfSmrg    if (genStateNotify) {
120335c4bbdfSmrg        if (changed) {
120435c4bbdfSmrg            xkbStateNotify sn;
120535c4bbdfSmrg
120635c4bbdfSmrg            sn.keycode = key;
120735c4bbdfSmrg            sn.eventType = evtype;
120835c4bbdfSmrg            sn.requestMajor = sn.requestMinor = 0;
120935c4bbdfSmrg            sn.changed = changed;
121035c4bbdfSmrg            XkbSendStateNotify(dev, &sn);
121135c4bbdfSmrg        }
121235c4bbdfSmrg        xkbi->flags &= ~_XkbStateNotifyInProgress;
121335c4bbdfSmrg    }
121435c4bbdfSmrg
121535c4bbdfSmrg    changed = XkbIndicatorsToUpdate(dev, changed, FALSE);
121635c4bbdfSmrg    if (changed) {
121735c4bbdfSmrg        XkbEventCauseRec cause;
121835c4bbdfSmrg        XkbSetCauseKey(&cause, key, evtype);
121935c4bbdfSmrg        XkbUpdateIndicators(dev, changed, FALSE, NULL, &cause);
122035c4bbdfSmrg    }
122135c4bbdfSmrg}
122235c4bbdfSmrg
122335c4bbdfSmrgvoid
122435c4bbdfSmrgXkbPushLockedStateToSlaves(DeviceIntPtr master, int evtype, int key)
122535c4bbdfSmrg{
122635c4bbdfSmrg    DeviceIntPtr dev;
122735c4bbdfSmrg    Bool genStateNotify;
122835c4bbdfSmrg
122935c4bbdfSmrg    nt_list_for_each_entry(dev, inputInfo.devices, next) {
123035c4bbdfSmrg        if (!dev->key || GetMaster(dev, MASTER_KEYBOARD) != master)
123135c4bbdfSmrg            continue;
123235c4bbdfSmrg
123335c4bbdfSmrg        genStateNotify = _XkbEnsureStateChange(dev->key->xkbInfo);
123435c4bbdfSmrg
123535c4bbdfSmrg        dev->key->xkbInfo->state.locked_mods =
123635c4bbdfSmrg            master->key->xkbInfo->state.locked_mods;
123735c4bbdfSmrg
123835c4bbdfSmrg        _XkbApplyState(dev, genStateNotify, evtype, key);
123935c4bbdfSmrg    }
124035c4bbdfSmrg}
124135c4bbdfSmrg
12421b5d61b8Smrgstatic void
12431b5d61b8SmrgXkbActionGetFilter(DeviceIntPtr dev, DeviceEvent *event, KeyCode key,
12441b5d61b8Smrg                   XkbAction *act, int *sendEvent)
12451b5d61b8Smrg{
12461b5d61b8Smrg    XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
12471b5d61b8Smrg    XkbFilterPtr filter;
12481b5d61b8Smrg
12491b5d61b8Smrg    /* For focus events, we only want to run actions which update our state to
12501b5d61b8Smrg     * (hopefully vaguely kinda) match that of the host server, rather than
12511b5d61b8Smrg     * actually execute anything. For example, if we enter our VT with
12521b5d61b8Smrg     * Ctrl+Alt+Backspace held down, we don't want to terminate our server
12531b5d61b8Smrg     * immediately, but we _do_ want Ctrl+Alt to be latched down, so if
12541b5d61b8Smrg     * Backspace is released and then pressed again, the server will terminate.
12551b5d61b8Smrg     *
12561b5d61b8Smrg     * This is pretty flaky, and we should in fact inherit the complete state
12571b5d61b8Smrg     * from the host server. There are some state combinations that we cannot
12581b5d61b8Smrg     * express by running the state machine over every key, e.g. if AltGr+Shift
12591b5d61b8Smrg     * generates a different state to Shift+AltGr. */
12601b5d61b8Smrg    if (event->source_type == EVENT_SOURCE_FOCUS) {
12611b5d61b8Smrg        switch (act->type) {
12621b5d61b8Smrg        case XkbSA_SetMods:
12631b5d61b8Smrg        case XkbSA_SetGroup:
12641b5d61b8Smrg        case XkbSA_LatchMods:
12651b5d61b8Smrg        case XkbSA_LatchGroup:
12661b5d61b8Smrg        case XkbSA_LockMods:
12671b5d61b8Smrg        case XkbSA_LockGroup:
12681b5d61b8Smrg            break;
12691b5d61b8Smrg        default:
12701b5d61b8Smrg            *sendEvent = 1;
12711b5d61b8Smrg            return;
12721b5d61b8Smrg        }
12731b5d61b8Smrg    }
12741b5d61b8Smrg
12751b5d61b8Smrg    switch (act->type) {
12761b5d61b8Smrg    case XkbSA_SetMods:
12771b5d61b8Smrg    case XkbSA_SetGroup:
12781b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12791b5d61b8Smrg        *sendEvent = _XkbFilterSetState(xkbi, filter, key, act);
12801b5d61b8Smrg        break;
12811b5d61b8Smrg    case XkbSA_LatchMods:
12821b5d61b8Smrg    case XkbSA_LatchGroup:
12831b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12841b5d61b8Smrg        *sendEvent = _XkbFilterLatchState(xkbi, filter, key, act);
12851b5d61b8Smrg        break;
12861b5d61b8Smrg    case XkbSA_LockMods:
12871b5d61b8Smrg    case XkbSA_LockGroup:
12881b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12891b5d61b8Smrg        *sendEvent = _XkbFilterLockState(xkbi, filter, key, act);
12901b5d61b8Smrg        break;
12911b5d61b8Smrg    case XkbSA_ISOLock:
12921b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12931b5d61b8Smrg        *sendEvent = _XkbFilterISOLock(xkbi, filter, key, act);
12941b5d61b8Smrg        break;
12951b5d61b8Smrg    case XkbSA_MovePtr:
12961b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12971b5d61b8Smrg        *sendEvent = _XkbFilterPointerMove(xkbi, filter, key, act);
12981b5d61b8Smrg        break;
12991b5d61b8Smrg    case XkbSA_PtrBtn:
13001b5d61b8Smrg    case XkbSA_LockPtrBtn:
13011b5d61b8Smrg    case XkbSA_SetPtrDflt:
13021b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
13031b5d61b8Smrg        *sendEvent = _XkbFilterPointerBtn(xkbi, filter, key, act);
13041b5d61b8Smrg        break;
13051b5d61b8Smrg    case XkbSA_Terminate:
13061b5d61b8Smrg        *sendEvent = XkbDDXTerminateServer(dev, key, act);
13071b5d61b8Smrg        break;
13081b5d61b8Smrg    case XkbSA_SwitchScreen:
13091b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
13101b5d61b8Smrg        *sendEvent = _XkbFilterSwitchScreen(xkbi, filter, key, act);
13111b5d61b8Smrg        break;
13121b5d61b8Smrg    case XkbSA_SetControls:
13131b5d61b8Smrg    case XkbSA_LockControls:
13141b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
13151b5d61b8Smrg        *sendEvent = _XkbFilterControls(xkbi, filter, key, act);
13161b5d61b8Smrg        break;
13171b5d61b8Smrg    case XkbSA_ActionMessage:
13181b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
13191b5d61b8Smrg        *sendEvent = _XkbFilterActionMessage(xkbi, filter, key, act);
13201b5d61b8Smrg        break;
13211b5d61b8Smrg    case XkbSA_RedirectKey:
13221b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
13231b5d61b8Smrg        /* redirect actions must create a new DeviceEvent.  The
13241b5d61b8Smrg         * source device id for this event cannot be obtained from
13251b5d61b8Smrg         * xkbi, so we pass it here explicitly. The field deviceid
13261b5d61b8Smrg         * equals to xkbi->device->id. */
13271b5d61b8Smrg        filter->priv = event->sourceid;
13281b5d61b8Smrg        *sendEvent = _XkbFilterRedirectKey(xkbi, filter, key, act);
13291b5d61b8Smrg        break;
13301b5d61b8Smrg    case XkbSA_DeviceBtn:
13311b5d61b8Smrg    case XkbSA_LockDeviceBtn:
13321b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
13331b5d61b8Smrg        *sendEvent = _XkbFilterDeviceBtn(xkbi, filter, key, act);
13341b5d61b8Smrg        break;
13351b5d61b8Smrg    case XkbSA_XFree86Private:
13361b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
13371b5d61b8Smrg        *sendEvent = _XkbFilterXF86Private(xkbi, filter, key, act);
13381b5d61b8Smrg        break;
13391b5d61b8Smrg    }
13401b5d61b8Smrg}
13411b5d61b8Smrg
134235c4bbdfSmrgvoid
134335c4bbdfSmrgXkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
134435c4bbdfSmrg{
134535c4bbdfSmrg    int key, bit, i;
134635c4bbdfSmrg    XkbSrvInfoPtr xkbi;
134735c4bbdfSmrg    KeyClassPtr keyc;
134835c4bbdfSmrg    int sendEvent;
134935c4bbdfSmrg    Bool genStateNotify;
135035c4bbdfSmrg    XkbAction act;
135135c4bbdfSmrg    Bool keyEvent;
135235c4bbdfSmrg    Bool pressEvent;
135335c4bbdfSmrg    ProcessInputProc backupproc;
135435c4bbdfSmrg
135535c4bbdfSmrg    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
135635c4bbdfSmrg
135735c4bbdfSmrg    keyc = kbd->key;
135835c4bbdfSmrg    xkbi = keyc->xkbInfo;
135935c4bbdfSmrg    key = event->detail.key;
136035c4bbdfSmrg
136135c4bbdfSmrg    genStateNotify = _XkbEnsureStateChange(xkbi);
136205b261ecSmrg
136305b261ecSmrg    xkbi->clearMods = xkbi->setMods = 0;
136405b261ecSmrg    xkbi->groupChange = 0;
136505b261ecSmrg
136605b261ecSmrg    sendEvent = 1;
136735c4bbdfSmrg    keyEvent = ((event->type == ET_KeyPress) || (event->type == ET_KeyRelease));
136835c4bbdfSmrg    pressEvent = ((event->type == ET_KeyPress) ||
136935c4bbdfSmrg                  (event->type == ET_ButtonPress));
137005b261ecSmrg
137105b261ecSmrg    if (pressEvent) {
137235c4bbdfSmrg        if (keyEvent)
137335c4bbdfSmrg            act = XkbGetKeyAction(xkbi, &xkbi->state, key);
137435c4bbdfSmrg        else {
137535c4bbdfSmrg            act = XkbGetButtonAction(kbd, dev, key);
137635c4bbdfSmrg            key |= BTN_ACT_FLAG;
137735c4bbdfSmrg        }
13781b5d61b8Smrg
137935c4bbdfSmrg        sendEvent = _XkbApplyFilters(xkbi, key, &act);
13801b5d61b8Smrg        if (sendEvent)
13811b5d61b8Smrg            XkbActionGetFilter(dev, event, key, &act, &sendEvent);
138205b261ecSmrg    }
138305b261ecSmrg    else {
138435c4bbdfSmrg        if (!keyEvent)
138535c4bbdfSmrg            key |= BTN_ACT_FLAG;
138635c4bbdfSmrg        sendEvent = _XkbApplyFilters(xkbi, key, NULL);
138705b261ecSmrg    }
138805b261ecSmrg
138935c4bbdfSmrg    if (xkbi->groupChange != 0)
139035c4bbdfSmrg        xkbi->state.base_group += xkbi->groupChange;
139105b261ecSmrg    if (xkbi->setMods) {
139235c4bbdfSmrg        for (i = 0, bit = 1; xkbi->setMods; i++, bit <<= 1) {
139335c4bbdfSmrg            if (xkbi->setMods & bit) {
139435c4bbdfSmrg                keyc->modifierKeyCount[i]++;
139535c4bbdfSmrg                xkbi->state.base_mods |= bit;
139635c4bbdfSmrg                xkbi->setMods &= ~bit;
139735c4bbdfSmrg            }
139835c4bbdfSmrg        }
139905b261ecSmrg    }
140005b261ecSmrg    if (xkbi->clearMods) {
140135c4bbdfSmrg        for (i = 0, bit = 1; xkbi->clearMods; i++, bit <<= 1) {
140235c4bbdfSmrg            if (xkbi->clearMods & bit) {
140335c4bbdfSmrg                keyc->modifierKeyCount[i]--;
140435c4bbdfSmrg                if (keyc->modifierKeyCount[i] <= 0) {
140535c4bbdfSmrg                    xkbi->state.base_mods &= ~bit;
140635c4bbdfSmrg                    keyc->modifierKeyCount[i] = 0;
140735c4bbdfSmrg                }
140835c4bbdfSmrg                xkbi->clearMods &= ~bit;
140935c4bbdfSmrg            }
141035c4bbdfSmrg        }
141105b261ecSmrg    }
141205b261ecSmrg
141305b261ecSmrg    if (sendEvent) {
14144642e01fSmrg        DeviceIntPtr tmpdev;
141535c4bbdfSmrg
141635c4bbdfSmrg        if (keyEvent)
14174642e01fSmrg            tmpdev = dev;
14186747b715Smrg        else
141935c4bbdfSmrg            tmpdev = GetMaster(dev, POINTER_OR_FLOAT);
142005b261ecSmrg
142135c4bbdfSmrg        UNWRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr, backupproc);
142235c4bbdfSmrg        dev->public.processInputProc((InternalEvent *) event, tmpdev);
14234642e01fSmrg        COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr,
142435c4bbdfSmrg                                     backupproc, xkbUnwrapProc);
142505b261ecSmrg    }
142605b261ecSmrg    else if (keyEvent) {
142735c4bbdfSmrg        FixKeyState(event, dev);
142805b261ecSmrg    }
142905b261ecSmrg
143035c4bbdfSmrg    _XkbApplyState(dev, genStateNotify, event->type, key);
143135c4bbdfSmrg    XkbPushLockedStateToSlaves(dev, event->type, key);
143205b261ecSmrg}
143305b261ecSmrg
143405b261ecSmrgint
143535c4bbdfSmrgXkbLatchModifiers(DeviceIntPtr pXDev, CARD8 mask, CARD8 latches)
143605b261ecSmrg{
143735c4bbdfSmrg    XkbSrvInfoPtr xkbi;
143835c4bbdfSmrg    XkbFilterPtr filter;
143935c4bbdfSmrg    XkbAction act;
144035c4bbdfSmrg    unsigned clear;
144135c4bbdfSmrg
144235c4bbdfSmrg    if (pXDev && pXDev->key && pXDev->key->xkbInfo) {
144335c4bbdfSmrg        xkbi = pXDev->key->xkbInfo;
144435c4bbdfSmrg        clear = (mask & (~latches));
144535c4bbdfSmrg        xkbi->state.latched_mods &= ~clear;
144635c4bbdfSmrg        /* Clear any pending latch to locks.
144735c4bbdfSmrg         */
144835c4bbdfSmrg        act.type = XkbSA_NoAction;
144935c4bbdfSmrg        _XkbApplyFilters(xkbi, SYNTHETIC_KEYCODE, &act);
145035c4bbdfSmrg        act.type = XkbSA_LatchMods;
145135c4bbdfSmrg        act.mods.flags = 0;
145235c4bbdfSmrg        act.mods.mask = mask & latches;
145335c4bbdfSmrg        filter = _XkbNextFreeFilter(xkbi);
145435c4bbdfSmrg        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE, &act);
145535c4bbdfSmrg        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE,
145635c4bbdfSmrg                             (XkbAction *) NULL);
145735c4bbdfSmrg        return Success;
145805b261ecSmrg    }
145905b261ecSmrg    return BadValue;
146005b261ecSmrg}
146105b261ecSmrg
146205b261ecSmrgint
146335c4bbdfSmrgXkbLatchGroup(DeviceIntPtr pXDev, int group)
146405b261ecSmrg{
146535c4bbdfSmrg    XkbSrvInfoPtr xkbi;
146635c4bbdfSmrg    XkbFilterPtr filter;
146735c4bbdfSmrg    XkbAction act;
146835c4bbdfSmrg
146935c4bbdfSmrg    if (pXDev && pXDev->key && pXDev->key->xkbInfo) {
147035c4bbdfSmrg        xkbi = pXDev->key->xkbInfo;
147135c4bbdfSmrg        act.type = XkbSA_LatchGroup;
147235c4bbdfSmrg        act.group.flags = 0;
147335c4bbdfSmrg        XkbSASetGroup(&act.group, group);
147435c4bbdfSmrg        filter = _XkbNextFreeFilter(xkbi);
147535c4bbdfSmrg        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE, &act);
147635c4bbdfSmrg        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE,
147735c4bbdfSmrg                             (XkbAction *) NULL);
147835c4bbdfSmrg        return Success;
147905b261ecSmrg    }
148005b261ecSmrg    return BadValue;
148105b261ecSmrg}
148205b261ecSmrg
148305b261ecSmrg/***====================================================================***/
148405b261ecSmrg
148505b261ecSmrgvoid
148635c4bbdfSmrgXkbClearAllLatchesAndLocks(DeviceIntPtr dev,
148735c4bbdfSmrg                           XkbSrvInfoPtr xkbi,
148835c4bbdfSmrg                           Bool genEv, XkbEventCausePtr cause)
148905b261ecSmrg{
149035c4bbdfSmrg    XkbStateRec os;
149135c4bbdfSmrg    xkbStateNotify sn;
149235c4bbdfSmrg
149335c4bbdfSmrg    sn.changed = 0;
149435c4bbdfSmrg    os = xkbi->state;
149535c4bbdfSmrg    if (os.latched_mods) {      /* clear all latches */
149635c4bbdfSmrg        XkbLatchModifiers(dev, ~0, 0);
149735c4bbdfSmrg        sn.changed |= XkbModifierLatchMask;
149805b261ecSmrg    }
149905b261ecSmrg    if (os.latched_group) {
150035c4bbdfSmrg        XkbLatchGroup(dev, 0);
150135c4bbdfSmrg        sn.changed |= XkbGroupLatchMask;
150205b261ecSmrg    }
150305b261ecSmrg    if (os.locked_mods) {
150435c4bbdfSmrg        xkbi->state.locked_mods = 0;
150535c4bbdfSmrg        sn.changed |= XkbModifierLockMask;
150605b261ecSmrg    }
150705b261ecSmrg    if (os.locked_group) {
150835c4bbdfSmrg        xkbi->state.locked_group = 0;
150935c4bbdfSmrg        sn.changed |= XkbGroupLockMask;
151005b261ecSmrg    }
151135c4bbdfSmrg    if (genEv && sn.changed) {
151235c4bbdfSmrg        CARD32 changed;
151335c4bbdfSmrg
151435c4bbdfSmrg        XkbComputeDerivedState(xkbi);
151535c4bbdfSmrg        sn.keycode = cause->kc;
151635c4bbdfSmrg        sn.eventType = cause->event;
151735c4bbdfSmrg        sn.requestMajor = cause->mjr;
151835c4bbdfSmrg        sn.requestMinor = cause->mnr;
151935c4bbdfSmrg        sn.changed = XkbStateChangedFlags(&os, &xkbi->state);
152035c4bbdfSmrg        XkbSendStateNotify(dev, &sn);
152135c4bbdfSmrg        changed = XkbIndicatorsToUpdate(dev, sn.changed, FALSE);
152235c4bbdfSmrg        if (changed) {
152335c4bbdfSmrg            XkbUpdateIndicators(dev, changed, TRUE, NULL, cause);
152435c4bbdfSmrg        }
152505b261ecSmrg    }
152605b261ecSmrg    return;
152705b261ecSmrg}
152805b261ecSmrg
15296747b715Smrg/*
15306747b715Smrg * The event is injected into the event processing, not the EQ. Thus,
15316747b715Smrg * ensure that we restore the master after the event sequence to the
15326747b715Smrg * original set of classes. Otherwise, the master remains on the XTEST
15336747b715Smrg * classes and drops events that don't fit into the XTEST layout (e.g.
15346747b715Smrg * events with more than 2 valuators).
15356747b715Smrg *
15366747b715Smrg * FIXME: EQ injection in the processing stage is not designed for, so this
15376747b715Smrg * is a rather awkward hack. The event list returned by GetPointerEvents()
15386747b715Smrg * and friends is always prefixed with a DCE if the last _posted_ device was
15396747b715Smrg * different. For normal events, this sequence then resets the master during
15406747b715Smrg * the processing stage. Since we inject the PointerKey events in the
15416747b715Smrg * processing stage though, we need to manually reset to restore the
15426747b715Smrg * previous order, because the events already in the EQ must be sent for the
15436747b715Smrg * right device.
15446747b715Smrg * So we post-fix the event list we get from GPE with a DCE back to the
15456747b715Smrg * previous slave device.
15466747b715Smrg *
15476747b715Smrg * First one on drinking island wins!
15486747b715Smrg */
15496747b715Smrgstatic void
155035c4bbdfSmrgInjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags,
155135c4bbdfSmrg                       ValuatorMask *mask)
15526747b715Smrg{
155335c4bbdfSmrg    ScreenPtr pScreen;
155435c4bbdfSmrg    InternalEvent *events;
155535c4bbdfSmrg    int nevents, i;
155635c4bbdfSmrg    DeviceIntPtr ptr, mpointer, lastSlave = NULL;
155735c4bbdfSmrg    Bool saveWait;
15586747b715Smrg
15596747b715Smrg    if (IsMaster(dev)) {
15606747b715Smrg        mpointer = GetMaster(dev, MASTER_POINTER);
156135c4bbdfSmrg        lastSlave = mpointer->lastSlave;
15626747b715Smrg        ptr = GetXTestDevice(mpointer);
156335c4bbdfSmrg    }
156435c4bbdfSmrg    else if (IsFloating(dev))
15656747b715Smrg        ptr = dev;
15666747b715Smrg    else
15676747b715Smrg        return;
15686747b715Smrg
15696747b715Smrg    events = InitEventList(GetMaximumEventsNum() + 1);
15701b5d61b8Smrg    input_lock();
15716747b715Smrg    pScreen = miPointerGetScreen(ptr);
15726747b715Smrg    saveWait = miPointerSetWaitForUpdate(pScreen, FALSE);
15739ace9065Smrg    nevents = GetPointerEvents(events, ptr, type, button, flags, mask);
15746747b715Smrg    if (IsMaster(dev) && (lastSlave && lastSlave != ptr))
157535c4bbdfSmrg        UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT,
157635c4bbdfSmrg                         &nevents);
15776747b715Smrg    miPointerSetWaitForUpdate(pScreen, saveWait);
15786747b715Smrg
15796747b715Smrg    for (i = 0; i < nevents; i++)
158035c4bbdfSmrg        mieqProcessDeviceEvent(ptr, &events[i], NULL);
15811b5d61b8Smrg    input_unlock();
15826747b715Smrg
15836747b715Smrg    FreeEventList(events, GetMaximumEventsNum());
15846747b715Smrg}
15856747b715Smrg
15866747b715Smrgstatic void
158735c4bbdfSmrgXkbFakePointerMotion(DeviceIntPtr dev, unsigned flags, int x, int y)
15886747b715Smrg{
158935c4bbdfSmrg    ValuatorMask mask;
159035c4bbdfSmrg    int gpe_flags = 0;
15916747b715Smrg
15926747b715Smrg    /* ignore attached SDs */
159335c4bbdfSmrg    if (!IsMaster(dev) && !IsFloating(dev))
15946747b715Smrg        return;
15956747b715Smrg
15966747b715Smrg    if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
15976747b715Smrg        gpe_flags = POINTER_ABSOLUTE;
15986747b715Smrg    else
15996747b715Smrg        gpe_flags = POINTER_RELATIVE;
16006747b715Smrg
160135c4bbdfSmrg    valuator_mask_set_range(&mask, 0, 2, (int[]) {
160235c4bbdfSmrg                            x, y});
16039ace9065Smrg
16049ace9065Smrg    InjectPointerKeyEvents(dev, MotionNotify, 0, gpe_flags, &mask);
16056747b715Smrg}
16066747b715Smrg
16076747b715Smrgvoid
160835c4bbdfSmrgXkbFakeDeviceButton(DeviceIntPtr dev, Bool press, int button)
16096747b715Smrg{
161035c4bbdfSmrg    DeviceIntPtr ptr;
161135c4bbdfSmrg    int down;
16126747b715Smrg
16136747b715Smrg    /* If dev is a slave device, and the SD is attached, do nothing. If we'd
16146747b715Smrg     * post through the attached master pointer we'd get duplicate events.
16156747b715Smrg     *
16166747b715Smrg     * if dev is a master keyboard, post through the XTEST device
16176747b715Smrg     *
16186747b715Smrg     * if dev is a floating slave, post through the device itself.
16196747b715Smrg     */
16206747b715Smrg
16216747b715Smrg    if (IsMaster(dev)) {
16226747b715Smrg        DeviceIntPtr mpointer = GetMaster(dev, MASTER_POINTER);
162335c4bbdfSmrg
16246747b715Smrg        ptr = GetXTestDevice(mpointer);
162535c4bbdfSmrg    }
162635c4bbdfSmrg    else if (IsFloating(dev))
16276747b715Smrg        ptr = dev;
16286747b715Smrg    else
16296747b715Smrg        return;
16306747b715Smrg
16316747b715Smrg    down = button_is_down(ptr, button, BUTTON_PROCESSED);
16326747b715Smrg    if (press == down)
16336747b715Smrg        return;
16346747b715Smrg
16356747b715Smrg    InjectPointerKeyEvents(dev, press ? ButtonPress : ButtonRelease,
16369ace9065Smrg                           button, 0, NULL);
16376747b715Smrg}
1638