xkbActions.c revision 1b5d61b8
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"
4605b261ecSmrg#define EXTENSION_EVENT_BASE 64
4705b261ecSmrg
486747b715SmrgDevPrivateKeyRec xkbDevicePrivateKeyRec;
496747b715Smrg
5035c4bbdfSmrgstatic void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags, int x,
5135c4bbdfSmrg                                 int y);
5205b261ecSmrg
5305b261ecSmrgvoid
5435c4bbdfSmrgxkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc, void *data)
5505b261ecSmrg{
5605b261ecSmrg    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device);
5705b261ecSmrg    ProcessInputProc backupproc;
5805b261ecSmrg
5935c4bbdfSmrg    if (xkbPrivPtr->unwrapProc)
6035c4bbdfSmrg        xkbPrivPtr->unwrapProc = NULL;
6135c4bbdfSmrg
6235c4bbdfSmrg    UNWRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, backupproc);
6335c4bbdfSmrg    proc(device, data);
6435c4bbdfSmrg    COND_WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, backupproc, xkbUnwrapProc);
6505b261ecSmrg}
6605b261ecSmrg
676747b715SmrgBool
686747b715SmrgXkbInitPrivates(void)
696747b715Smrg{
7035c4bbdfSmrg    return dixRegisterPrivateKey(&xkbDevicePrivateKeyRec, PRIVATE_DEVICE,
7135c4bbdfSmrg                                 sizeof(xkbDeviceInfoRec));
726747b715Smrg}
7305b261ecSmrg
7405b261ecSmrgvoid
7505b261ecSmrgXkbSetExtension(DeviceIntPtr device, ProcessInputProc proc)
7605b261ecSmrg{
779ace9065Smrg    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device);
7835c4bbdfSmrg
7905b261ecSmrg    WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, proc, xkbUnwrapProc);
8005b261ecSmrg}
8105b261ecSmrg
8205b261ecSmrg/***====================================================================***/
8305b261ecSmrg
8405b261ecSmrgstatic XkbAction
8535c4bbdfSmrg_FixUpAction(XkbDescPtr xkb, XkbAction *act)
8605b261ecSmrg{
8735c4bbdfSmrg    static XkbAction fake;
8805b261ecSmrg
8935c4bbdfSmrg    if (XkbIsPtrAction(act) &&
9035c4bbdfSmrg        (!(xkb->ctrls->enabled_ctrls & XkbMouseKeysMask))) {
9135c4bbdfSmrg        fake.type = XkbSA_NoAction;
9235c4bbdfSmrg        return fake;
9305b261ecSmrg    }
9435c4bbdfSmrg    if (xkb->ctrls->enabled_ctrls & XkbStickyKeysMask) {
9535c4bbdfSmrg        if (act->any.type == XkbSA_SetMods) {
9635c4bbdfSmrg            fake.mods.type = XkbSA_LatchMods;
9735c4bbdfSmrg            fake.mods.mask = act->mods.mask;
9835c4bbdfSmrg            if (XkbAX_NeedOption(xkb->ctrls, XkbAX_LatchToLockMask))
9935c4bbdfSmrg                fake.mods.flags = XkbSA_ClearLocks | XkbSA_LatchToLock;
10035c4bbdfSmrg            else
10135c4bbdfSmrg                fake.mods.flags = XkbSA_ClearLocks;
10235c4bbdfSmrg            return fake;
10335c4bbdfSmrg        }
10435c4bbdfSmrg        if (act->any.type == XkbSA_SetGroup) {
10535c4bbdfSmrg            fake.group.type = XkbSA_LatchGroup;
10635c4bbdfSmrg            if (XkbAX_NeedOption(xkb->ctrls, XkbAX_LatchToLockMask))
10735c4bbdfSmrg                fake.group.flags = XkbSA_ClearLocks | XkbSA_LatchToLock;
10835c4bbdfSmrg            else
10935c4bbdfSmrg                fake.group.flags = XkbSA_ClearLocks;
11035c4bbdfSmrg            XkbSASetGroup(&fake.group, XkbSAGroup(&act->group));
11135c4bbdfSmrg            return fake;
11235c4bbdfSmrg        }
11305b261ecSmrg    }
11405b261ecSmrg    return *act;
11505b261ecSmrg}
11605b261ecSmrg
11705b261ecSmrgstatic XkbAction
11835c4bbdfSmrgXkbGetKeyAction(XkbSrvInfoPtr xkbi, XkbStatePtr xkbState, CARD8 key)
11905b261ecSmrg{
12035c4bbdfSmrg    int effectiveGroup;
12135c4bbdfSmrg    int col;
12235c4bbdfSmrg    XkbDescPtr xkb;
12335c4bbdfSmrg    XkbKeyTypePtr type;
12435c4bbdfSmrg    XkbAction *pActs;
12535c4bbdfSmrg    static XkbAction fake;
12635c4bbdfSmrg
12735c4bbdfSmrg    xkb = xkbi->desc;
12835c4bbdfSmrg    if (!XkbKeyHasActions(xkb, key) || !XkbKeycodeInRange(xkb, key)) {
12935c4bbdfSmrg        fake.type = XkbSA_NoAction;
13035c4bbdfSmrg        return fake;
13105b261ecSmrg    }
13235c4bbdfSmrg    pActs = XkbKeyActionsPtr(xkb, key);
13335c4bbdfSmrg    col = 0;
1346747b715Smrg
1356747b715Smrg    effectiveGroup = XkbGetEffectiveGroup(xkbi, xkbState, key);
1366747b715Smrg    if (effectiveGroup != XkbGroup1Index)
1376747b715Smrg        col += (effectiveGroup * XkbKeyGroupsWidth(xkb, key));
1386747b715Smrg
13935c4bbdfSmrg    type = XkbKeyKeyType(xkb, key, effectiveGroup);
14035c4bbdfSmrg    if (type->map != NULL) {
14135c4bbdfSmrg        register unsigned i, mods;
14235c4bbdfSmrg        register XkbKTMapEntryPtr entry;
14335c4bbdfSmrg
14435c4bbdfSmrg        mods = xkbState->mods & type->mods.mask;
14535c4bbdfSmrg        for (entry = type->map, i = 0; i < type->map_count; i++, entry++) {
14635c4bbdfSmrg            if ((entry->active) && (entry->mods.mask == mods)) {
14735c4bbdfSmrg                col += entry->level;
14835c4bbdfSmrg                break;
14935c4bbdfSmrg            }
15035c4bbdfSmrg        }
15105b261ecSmrg    }
15235c4bbdfSmrg    if (pActs[col].any.type == XkbSA_NoAction)
15335c4bbdfSmrg        return pActs[col];
15435c4bbdfSmrg    fake = _FixUpAction(xkb, &pActs[col]);
15505b261ecSmrg    return fake;
15605b261ecSmrg}
15705b261ecSmrg
15805b261ecSmrgstatic XkbAction
15935c4bbdfSmrgXkbGetButtonAction(DeviceIntPtr kbd, DeviceIntPtr dev, int button)
16005b261ecSmrg{
16135c4bbdfSmrg    XkbAction fake;
16235c4bbdfSmrg
16335c4bbdfSmrg    if ((dev->button) && (dev->button->xkb_acts)) {
16435c4bbdfSmrg        if (dev->button->xkb_acts[button - 1].any.type != XkbSA_NoAction) {
16535c4bbdfSmrg            fake = _FixUpAction(kbd->key->xkbInfo->desc,
16635c4bbdfSmrg                                &dev->button->xkb_acts[button - 1]);
16735c4bbdfSmrg            return fake;
16835c4bbdfSmrg        }
16935c4bbdfSmrg    }
17035c4bbdfSmrg    fake.any.type = XkbSA_NoAction;
17135c4bbdfSmrg    return fake;
17205b261ecSmrg}
17305b261ecSmrg
17405b261ecSmrg/***====================================================================***/
17505b261ecSmrg
17605b261ecSmrg#define	SYNTHETIC_KEYCODE	1
17705b261ecSmrg#define	BTN_ACT_FLAG		0x100
17805b261ecSmrg
17905b261ecSmrgstatic int
18035c4bbdfSmrg_XkbFilterSetState(XkbSrvInfoPtr xkbi,
18135c4bbdfSmrg                   XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
18205b261ecSmrg{
18335c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
18435c4bbdfSmrg        AccessXCancelRepeatKey(xkbi, keycode);
18535c4bbdfSmrg        filter->keycode = keycode;
18635c4bbdfSmrg        filter->active = 1;
18735c4bbdfSmrg        filter->filterOthers = ((pAction->mods.mask & XkbSA_ClearLocks) != 0);
18835c4bbdfSmrg        filter->priv = 0;
18935c4bbdfSmrg        filter->filter = _XkbFilterSetState;
19035c4bbdfSmrg        if (pAction->type == XkbSA_SetMods) {
19135c4bbdfSmrg            filter->upAction = *pAction;
19235c4bbdfSmrg            xkbi->setMods = pAction->mods.mask;
19335c4bbdfSmrg        }
19435c4bbdfSmrg        else {
19535c4bbdfSmrg            xkbi->groupChange = XkbSAGroup(&pAction->group);
19635c4bbdfSmrg            if (pAction->group.flags & XkbSA_GroupAbsolute)
19735c4bbdfSmrg                xkbi->groupChange -= xkbi->state.base_group;
19835c4bbdfSmrg            filter->upAction = *pAction;
19935c4bbdfSmrg            XkbSASetGroup(&filter->upAction.group, xkbi->groupChange);
20035c4bbdfSmrg        }
20105b261ecSmrg    }
20235c4bbdfSmrg    else if (filter->keycode == keycode) {
20335c4bbdfSmrg        if (filter->upAction.type == XkbSA_SetMods) {
20435c4bbdfSmrg            xkbi->clearMods = filter->upAction.mods.mask;
20535c4bbdfSmrg            if (filter->upAction.mods.flags & XkbSA_ClearLocks) {
20635c4bbdfSmrg                xkbi->state.locked_mods &= ~filter->upAction.mods.mask;
20735c4bbdfSmrg            }
20835c4bbdfSmrg        }
20935c4bbdfSmrg        else {
21035c4bbdfSmrg            if (filter->upAction.group.flags & XkbSA_ClearLocks) {
21135c4bbdfSmrg                xkbi->state.locked_group = 0;
21235c4bbdfSmrg            }
21335c4bbdfSmrg            xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
21435c4bbdfSmrg        }
21535c4bbdfSmrg        filter->active = 0;
21605b261ecSmrg    }
21705b261ecSmrg    else {
21835c4bbdfSmrg        filter->upAction.mods.flags &= ~XkbSA_ClearLocks;
21935c4bbdfSmrg        filter->filterOthers = 0;
22005b261ecSmrg    }
22105b261ecSmrg    return 1;
22205b261ecSmrg}
22305b261ecSmrg
22405b261ecSmrg#define	LATCH_KEY_DOWN	1
22505b261ecSmrg#define	LATCH_PENDING	2
22605b261ecSmrg
22705b261ecSmrgstatic int
22835c4bbdfSmrg_XkbFilterLatchState(XkbSrvInfoPtr xkbi,
22935c4bbdfSmrg                     XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
23005b261ecSmrg{
23105b261ecSmrg
23235c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
23335c4bbdfSmrg        AccessXCancelRepeatKey(xkbi,keycode);
23435c4bbdfSmrg        filter->keycode = keycode;
23535c4bbdfSmrg        filter->active = 1;
23635c4bbdfSmrg        filter->filterOthers = 1;
23735c4bbdfSmrg        filter->priv = LATCH_KEY_DOWN;
23835c4bbdfSmrg        filter->filter = _XkbFilterLatchState;
23935c4bbdfSmrg        if (pAction->type == XkbSA_LatchMods) {
24035c4bbdfSmrg            filter->upAction = *pAction;
24135c4bbdfSmrg            xkbi->setMods = pAction->mods.mask;
24235c4bbdfSmrg        }
24335c4bbdfSmrg        else {
24435c4bbdfSmrg            xkbi->groupChange = XkbSAGroup(&pAction->group);
24535c4bbdfSmrg            if (pAction->group.flags & XkbSA_GroupAbsolute)
24635c4bbdfSmrg                xkbi->groupChange -= xkbi->state.base_group;
24735c4bbdfSmrg            filter->upAction = *pAction;
24835c4bbdfSmrg            XkbSASetGroup(&filter->upAction.group, xkbi->groupChange);
24935c4bbdfSmrg        }
25005b261ecSmrg    }
25135c4bbdfSmrg    else if (pAction && (filter->priv == LATCH_PENDING)) {
25235c4bbdfSmrg        if (((1 << pAction->type) & XkbSA_BreakLatch) != 0) {
25335c4bbdfSmrg            filter->active = 0;
25435c4bbdfSmrg            /* If one latch is broken, all latches are broken, so it's no use
25535c4bbdfSmrg               to find out which particular latch this filter tracks. */
25635c4bbdfSmrg            xkbi->state.latched_mods = 0;
25735c4bbdfSmrg            xkbi->state.latched_group = 0;
25835c4bbdfSmrg        }
25905b261ecSmrg    }
26035c4bbdfSmrg    else if (filter->keycode == keycode && filter->priv != LATCH_PENDING){
26135c4bbdfSmrg        /* The test above for LATCH_PENDING skips subsequent releases of the
26235c4bbdfSmrg           key after it has been released first time and the latch became
26335c4bbdfSmrg           pending. */
26435c4bbdfSmrg        XkbControlsPtr ctrls = xkbi->desc->ctrls;
26535c4bbdfSmrg        int needBeep = ((ctrls->enabled_ctrls & XkbStickyKeysMask) &&
26635c4bbdfSmrg                        XkbAX_NeedFeedback(ctrls, XkbAX_StickyKeysFBMask));
26735c4bbdfSmrg
26835c4bbdfSmrg        if (filter->upAction.type == XkbSA_LatchMods) {
26935c4bbdfSmrg            unsigned char mask = filter->upAction.mods.mask;
27035c4bbdfSmrg            unsigned char common;
27135c4bbdfSmrg
27235c4bbdfSmrg            xkbi->clearMods = mask;
27335c4bbdfSmrg
27435c4bbdfSmrg            /* ClearLocks */
27535c4bbdfSmrg            common = mask & xkbi->state.locked_mods;
27635c4bbdfSmrg            if ((filter->upAction.mods.flags & XkbSA_ClearLocks) && common) {
27735c4bbdfSmrg                mask &= ~common;
27835c4bbdfSmrg                xkbi->state.locked_mods &= ~common;
27935c4bbdfSmrg                if (needBeep)
28035c4bbdfSmrg                    XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_UNLOCK,
28135c4bbdfSmrg                                      XkbStickyKeysMask);
28235c4bbdfSmrg            }
28335c4bbdfSmrg            /* LatchToLock */
28435c4bbdfSmrg            common = mask & xkbi->state.latched_mods;
28535c4bbdfSmrg            if ((filter->upAction.mods.flags & XkbSA_LatchToLock) && common) {
28635c4bbdfSmrg                unsigned char newlocked;
28735c4bbdfSmrg
28835c4bbdfSmrg                mask &= ~common;
28935c4bbdfSmrg                newlocked = common & ~xkbi->state.locked_mods;
29035c4bbdfSmrg                if(newlocked){
29135c4bbdfSmrg                    xkbi->state.locked_mods |= newlocked;
29235c4bbdfSmrg                    if (needBeep)
29335c4bbdfSmrg                        XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LOCK,
29435c4bbdfSmrg                                          XkbStickyKeysMask);
29535c4bbdfSmrg
29635c4bbdfSmrg                }
29735c4bbdfSmrg                xkbi->state.latched_mods &= ~common;
29835c4bbdfSmrg            }
29935c4bbdfSmrg            /* Latch remaining modifiers, if any. */
30035c4bbdfSmrg            if (mask) {
30135c4bbdfSmrg                xkbi->state.latched_mods |= mask;
30235c4bbdfSmrg                filter->priv = LATCH_PENDING;
30335c4bbdfSmrg                if (needBeep)
30435c4bbdfSmrg                    XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LATCH,
30535c4bbdfSmrg                                      XkbStickyKeysMask);
30635c4bbdfSmrg            }
30735c4bbdfSmrg        }
30835c4bbdfSmrg        else {
30935c4bbdfSmrg            xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
31035c4bbdfSmrg            /* ClearLocks */
31135c4bbdfSmrg            if ((filter->upAction.group.flags & XkbSA_ClearLocks) &&
31235c4bbdfSmrg                (xkbi->state.locked_group)) {
31335c4bbdfSmrg                xkbi->state.locked_group = 0;
31435c4bbdfSmrg                if (needBeep)
31535c4bbdfSmrg                    XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_UNLOCK,
31635c4bbdfSmrg                                      XkbStickyKeysMask);
31735c4bbdfSmrg            }
31835c4bbdfSmrg            /* LatchToLock */
31935c4bbdfSmrg            else if ((filter->upAction.group.flags & XkbSA_LatchToLock)
32035c4bbdfSmrg                     && (xkbi->state.latched_group)) {
32135c4bbdfSmrg                xkbi->state.locked_group  += XkbSAGroup(&filter->upAction.group);
32235c4bbdfSmrg                xkbi->state.latched_group -= XkbSAGroup(&filter->upAction.group);
32335c4bbdfSmrg                if(XkbSAGroup(&filter->upAction.group) && needBeep)
32435c4bbdfSmrg                    XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LOCK,
32535c4bbdfSmrg                                      XkbStickyKeysMask);
32635c4bbdfSmrg            }
32735c4bbdfSmrg            /* Latch group */
32835c4bbdfSmrg            else if(XkbSAGroup(&filter->upAction.group)){
32935c4bbdfSmrg                xkbi->state.latched_group += XkbSAGroup(&filter->upAction.group);
33035c4bbdfSmrg                filter->priv = LATCH_PENDING;
33135c4bbdfSmrg                if (needBeep)
33235c4bbdfSmrg                    XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LATCH,
33335c4bbdfSmrg                                      XkbStickyKeysMask);
33435c4bbdfSmrg            }
33535c4bbdfSmrg        }
33635c4bbdfSmrg
33735c4bbdfSmrg        if (filter->priv != LATCH_PENDING)
33835c4bbdfSmrg            filter->active = 0;
33905b261ecSmrg    }
34035c4bbdfSmrg    else if (pAction && (filter->priv == LATCH_KEY_DOWN)) {
34135c4bbdfSmrg        /* Latch was broken before it became pending: degrade to a
34235c4bbdfSmrg           SetMods/SetGroup. */
34335c4bbdfSmrg        if (filter->upAction.type == XkbSA_LatchMods)
34435c4bbdfSmrg            filter->upAction.type = XkbSA_SetMods;
34535c4bbdfSmrg        else
34635c4bbdfSmrg            filter->upAction.type = XkbSA_SetGroup;
34735c4bbdfSmrg        filter->filter = _XkbFilterSetState;
34835c4bbdfSmrg        filter->priv = 0;
34935c4bbdfSmrg        return filter->filter(xkbi, filter, keycode, pAction);
35005b261ecSmrg    }
35105b261ecSmrg    return 1;
35205b261ecSmrg}
35305b261ecSmrg
35405b261ecSmrgstatic int
35535c4bbdfSmrg_XkbFilterLockState(XkbSrvInfoPtr xkbi,
35635c4bbdfSmrg                    XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
35705b261ecSmrg{
35835c4bbdfSmrg    if (filter->keycode == 0) /* initial press */
35935c4bbdfSmrg        AccessXCancelRepeatKey(xkbi, keycode);
36035c4bbdfSmrg
36135c4bbdfSmrg    if (pAction && (pAction->type == XkbSA_LockGroup)) {
36235c4bbdfSmrg        if (pAction->group.flags & XkbSA_GroupAbsolute)
36335c4bbdfSmrg            xkbi->state.locked_group = XkbSAGroup(&pAction->group);
36435c4bbdfSmrg        else
36535c4bbdfSmrg            xkbi->state.locked_group += XkbSAGroup(&pAction->group);
36635c4bbdfSmrg        return 1;
36705b261ecSmrg    }
36835c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
36935c4bbdfSmrg        filter->keycode = keycode;
37035c4bbdfSmrg        filter->active = 1;
37135c4bbdfSmrg        filter->filterOthers = 0;
37235c4bbdfSmrg        filter->priv = xkbi->state.locked_mods & pAction->mods.mask;
37335c4bbdfSmrg        filter->filter = _XkbFilterLockState;
37435c4bbdfSmrg        filter->upAction = *pAction;
37535c4bbdfSmrg        if (!(filter->upAction.mods.flags & XkbSA_LockNoLock))
37635c4bbdfSmrg            xkbi->state.locked_mods |= pAction->mods.mask;
37735c4bbdfSmrg        xkbi->setMods = pAction->mods.mask;
37805b261ecSmrg    }
37935c4bbdfSmrg    else if (filter->keycode == keycode) {
38035c4bbdfSmrg        filter->active = 0;
38135c4bbdfSmrg        xkbi->clearMods = filter->upAction.mods.mask;
38235c4bbdfSmrg        if (!(filter->upAction.mods.flags & XkbSA_LockNoUnlock))
38335c4bbdfSmrg            xkbi->state.locked_mods &= ~filter->priv;
38405b261ecSmrg    }
38505b261ecSmrg    return 1;
38605b261ecSmrg}
38705b261ecSmrg
38805b261ecSmrg#define	ISO_KEY_DOWN		0
38905b261ecSmrg#define	NO_ISO_LOCK		1
39005b261ecSmrg
39105b261ecSmrgstatic int
39235c4bbdfSmrg_XkbFilterISOLock(XkbSrvInfoPtr xkbi,
39335c4bbdfSmrg                  XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
39405b261ecSmrg{
39505b261ecSmrg
39635c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
39735c4bbdfSmrg        CARD8 flags = pAction->iso.flags;
39835c4bbdfSmrg
39935c4bbdfSmrg        filter->keycode = keycode;
40035c4bbdfSmrg        filter->active = 1;
40135c4bbdfSmrg        filter->filterOthers = 1;
40235c4bbdfSmrg        filter->priv = ISO_KEY_DOWN;
40335c4bbdfSmrg        filter->upAction = *pAction;
40435c4bbdfSmrg        filter->filter = _XkbFilterISOLock;
40535c4bbdfSmrg        if (flags & XkbSA_ISODfltIsGroup) {
40635c4bbdfSmrg            xkbi->groupChange = XkbSAGroup(&pAction->iso);
40735c4bbdfSmrg            xkbi->setMods = 0;
40835c4bbdfSmrg        }
40935c4bbdfSmrg        else {
41035c4bbdfSmrg            xkbi->setMods = pAction->iso.mask;
41135c4bbdfSmrg            xkbi->groupChange = 0;
41235c4bbdfSmrg        }
41335c4bbdfSmrg        if ((!(flags & XkbSA_ISONoAffectMods)) && (xkbi->state.base_mods)) {
41435c4bbdfSmrg            filter->priv = NO_ISO_LOCK;
41535c4bbdfSmrg            xkbi->state.locked_mods ^= xkbi->state.base_mods;
41635c4bbdfSmrg        }
41735c4bbdfSmrg        if ((!(flags & XkbSA_ISONoAffectGroup)) && (xkbi->state.base_group)) {
41805b261ecSmrg/* 6/22/93 (ef) -- lock groups if group key is down first */
41935c4bbdfSmrg        }
42035c4bbdfSmrg        if (!(flags & XkbSA_ISONoAffectPtr)) {
42105b261ecSmrg/* 6/22/93 (ef) -- lock mouse buttons if they're down */
42235c4bbdfSmrg        }
42305b261ecSmrg    }
42435c4bbdfSmrg    else if (filter->keycode == keycode) {
42535c4bbdfSmrg        CARD8 flags = filter->upAction.iso.flags;
42635c4bbdfSmrg
42735c4bbdfSmrg        if (flags & XkbSA_ISODfltIsGroup) {
42835c4bbdfSmrg            xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso);
42935c4bbdfSmrg            xkbi->clearMods = 0;
43035c4bbdfSmrg            if (filter->priv == ISO_KEY_DOWN)
43135c4bbdfSmrg                xkbi->state.locked_group += XkbSAGroup(&filter->upAction.iso);
43235c4bbdfSmrg        }
43335c4bbdfSmrg        else {
43435c4bbdfSmrg            xkbi->clearMods = filter->upAction.iso.mask;
43535c4bbdfSmrg            xkbi->groupChange = 0;
43635c4bbdfSmrg            if (filter->priv == ISO_KEY_DOWN)
43735c4bbdfSmrg                xkbi->state.locked_mods ^= filter->upAction.iso.mask;
43835c4bbdfSmrg        }
43935c4bbdfSmrg        filter->active = 0;
44005b261ecSmrg    }
44105b261ecSmrg    else if (pAction) {
44235c4bbdfSmrg        CARD8 flags = filter->upAction.iso.flags;
44335c4bbdfSmrg
44435c4bbdfSmrg        switch (pAction->type) {
44535c4bbdfSmrg        case XkbSA_SetMods:
44635c4bbdfSmrg        case XkbSA_LatchMods:
44735c4bbdfSmrg            if (!(flags & XkbSA_ISONoAffectMods)) {
44835c4bbdfSmrg                pAction->type = XkbSA_LockMods;
44935c4bbdfSmrg                filter->priv = NO_ISO_LOCK;
45035c4bbdfSmrg            }
45135c4bbdfSmrg            break;
45235c4bbdfSmrg        case XkbSA_SetGroup:
45335c4bbdfSmrg        case XkbSA_LatchGroup:
45435c4bbdfSmrg            if (!(flags & XkbSA_ISONoAffectGroup)) {
45535c4bbdfSmrg                pAction->type = XkbSA_LockGroup;
45635c4bbdfSmrg                filter->priv = NO_ISO_LOCK;
45735c4bbdfSmrg            }
45835c4bbdfSmrg            break;
45935c4bbdfSmrg        case XkbSA_PtrBtn:
46035c4bbdfSmrg            if (!(flags & XkbSA_ISONoAffectPtr)) {
46135c4bbdfSmrg                pAction->type = XkbSA_LockPtrBtn;
46235c4bbdfSmrg                filter->priv = NO_ISO_LOCK;
46335c4bbdfSmrg            }
46435c4bbdfSmrg            break;
46535c4bbdfSmrg        case XkbSA_SetControls:
46635c4bbdfSmrg            if (!(flags & XkbSA_ISONoAffectCtrls)) {
46735c4bbdfSmrg                pAction->type = XkbSA_LockControls;
46835c4bbdfSmrg                filter->priv = NO_ISO_LOCK;
46935c4bbdfSmrg            }
47035c4bbdfSmrg            break;
47135c4bbdfSmrg        }
47205b261ecSmrg    }
47305b261ecSmrg    return 1;
47405b261ecSmrg}
47505b261ecSmrg
47605b261ecSmrgstatic CARD32
47735c4bbdfSmrg_XkbPtrAccelExpire(OsTimerPtr timer, CARD32 now, void *arg)
47805b261ecSmrg{
47935c4bbdfSmrg    XkbSrvInfoPtr xkbi = (XkbSrvInfoPtr) arg;
48035c4bbdfSmrg    XkbControlsPtr ctrls = xkbi->desc->ctrls;
48135c4bbdfSmrg    int dx, dy;
48205b261ecSmrg
48335c4bbdfSmrg    if (xkbi->mouseKey == 0)
48435c4bbdfSmrg        return 0;
48505b261ecSmrg
48605b261ecSmrg    if (xkbi->mouseKeysAccel) {
48735c4bbdfSmrg        if ((xkbi->mouseKeysCounter) < ctrls->mk_time_to_max) {
48835c4bbdfSmrg            double step;
48935c4bbdfSmrg
49035c4bbdfSmrg            xkbi->mouseKeysCounter++;
49135c4bbdfSmrg            step = xkbi->mouseKeysCurveFactor *
49235c4bbdfSmrg                pow((double) xkbi->mouseKeysCounter, xkbi->mouseKeysCurve);
49335c4bbdfSmrg            if (xkbi->mouseKeysDX < 0)
49435c4bbdfSmrg                dx = floor(((double) xkbi->mouseKeysDX) * step);
49535c4bbdfSmrg            else
49635c4bbdfSmrg                dx = ceil(((double) xkbi->mouseKeysDX) * step);
49735c4bbdfSmrg            if (xkbi->mouseKeysDY < 0)
49835c4bbdfSmrg                dy = floor(((double) xkbi->mouseKeysDY) * step);
49935c4bbdfSmrg            else
50035c4bbdfSmrg                dy = ceil(((double) xkbi->mouseKeysDY) * step);
50135c4bbdfSmrg        }
50235c4bbdfSmrg        else {
50335c4bbdfSmrg            dx = xkbi->mouseKeysDX * ctrls->mk_max_speed;
50435c4bbdfSmrg            dy = xkbi->mouseKeysDY * ctrls->mk_max_speed;
50535c4bbdfSmrg        }
50635c4bbdfSmrg        if (xkbi->mouseKeysFlags & XkbSA_MoveAbsoluteX)
50735c4bbdfSmrg            dx = xkbi->mouseKeysDX;
50835c4bbdfSmrg        if (xkbi->mouseKeysFlags & XkbSA_MoveAbsoluteY)
50935c4bbdfSmrg            dy = xkbi->mouseKeysDY;
51005b261ecSmrg    }
51105b261ecSmrg    else {
51235c4bbdfSmrg        dx = xkbi->mouseKeysDX;
51335c4bbdfSmrg        dy = xkbi->mouseKeysDY;
51405b261ecSmrg    }
51535c4bbdfSmrg    XkbFakePointerMotion(xkbi->device, xkbi->mouseKeysFlags, dx, dy);
51605b261ecSmrg    return xkbi->desc->ctrls->mk_interval;
51705b261ecSmrg}
51805b261ecSmrg
51905b261ecSmrgstatic int
52035c4bbdfSmrg_XkbFilterPointerMove(XkbSrvInfoPtr xkbi,
52135c4bbdfSmrg                      XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
52205b261ecSmrg{
52335c4bbdfSmrg    int x, y;
52435c4bbdfSmrg    Bool accel;
52535c4bbdfSmrg
52635c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
52735c4bbdfSmrg        filter->keycode = keycode;
52835c4bbdfSmrg        filter->active = 1;
52935c4bbdfSmrg        filter->filterOthers = 0;
53035c4bbdfSmrg        filter->priv = 0;
53135c4bbdfSmrg        filter->filter = _XkbFilterPointerMove;
53235c4bbdfSmrg        filter->upAction = *pAction;
53335c4bbdfSmrg        xkbi->mouseKeysCounter = 0;
53435c4bbdfSmrg        xkbi->mouseKey = keycode;
53535c4bbdfSmrg        accel = ((pAction->ptr.flags & XkbSA_NoAcceleration) == 0);
53635c4bbdfSmrg        x = XkbPtrActionX(&pAction->ptr);
53735c4bbdfSmrg        y = XkbPtrActionY(&pAction->ptr);
53835c4bbdfSmrg        XkbFakePointerMotion(xkbi->device, pAction->ptr.flags, x, y);
53935c4bbdfSmrg        AccessXCancelRepeatKey(xkbi, keycode);
54035c4bbdfSmrg        xkbi->mouseKeysAccel = accel &&
54135c4bbdfSmrg            (xkbi->desc->ctrls->enabled_ctrls & XkbMouseKeysAccelMask);
54235c4bbdfSmrg        xkbi->mouseKeysFlags = pAction->ptr.flags;
54335c4bbdfSmrg        xkbi->mouseKeysDX = XkbPtrActionX(&pAction->ptr);
54435c4bbdfSmrg        xkbi->mouseKeysDY = XkbPtrActionY(&pAction->ptr);
54535c4bbdfSmrg        xkbi->mouseKeyTimer = TimerSet(xkbi->mouseKeyTimer, 0,
54635c4bbdfSmrg                                       xkbi->desc->ctrls->mk_delay,
54735c4bbdfSmrg                                       _XkbPtrAccelExpire, (void *) xkbi);
54805b261ecSmrg    }
54935c4bbdfSmrg    else if (filter->keycode == keycode) {
55035c4bbdfSmrg        filter->active = 0;
55135c4bbdfSmrg        if (xkbi->mouseKey == keycode) {
55235c4bbdfSmrg            xkbi->mouseKey = 0;
55335c4bbdfSmrg            xkbi->mouseKeyTimer = TimerSet(xkbi->mouseKeyTimer, 0, 0,
55435c4bbdfSmrg                                           NULL, NULL);
55535c4bbdfSmrg        }
55605b261ecSmrg    }
55705b261ecSmrg    return 0;
55805b261ecSmrg}
55905b261ecSmrg
56005b261ecSmrgstatic int
56135c4bbdfSmrg_XkbFilterPointerBtn(XkbSrvInfoPtr xkbi,
56235c4bbdfSmrg                     XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
56305b261ecSmrg{
56435c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
56535c4bbdfSmrg        int button = pAction->btn.button;
56635c4bbdfSmrg
56735c4bbdfSmrg        if (button == XkbSA_UseDfltButton)
56835c4bbdfSmrg            button = xkbi->desc->ctrls->mk_dflt_btn;
56935c4bbdfSmrg
57035c4bbdfSmrg        filter->keycode = keycode;
57135c4bbdfSmrg        filter->active = 1;
57235c4bbdfSmrg        filter->filterOthers = 0;
57335c4bbdfSmrg        filter->priv = 0;
57435c4bbdfSmrg        filter->filter = _XkbFilterPointerBtn;
57535c4bbdfSmrg        filter->upAction = *pAction;
57635c4bbdfSmrg        filter->upAction.btn.button = button;
57735c4bbdfSmrg        switch (pAction->type) {
57835c4bbdfSmrg        case XkbSA_LockPtrBtn:
57935c4bbdfSmrg            if (((xkbi->lockedPtrButtons & (1 << button)) == 0) &&
58035c4bbdfSmrg                ((pAction->btn.flags & XkbSA_LockNoLock) == 0)) {
58135c4bbdfSmrg                xkbi->lockedPtrButtons |= (1 << button);
58235c4bbdfSmrg                AccessXCancelRepeatKey(xkbi, keycode);
58335c4bbdfSmrg                XkbFakeDeviceButton(xkbi->device, 1, button);
58435c4bbdfSmrg                filter->upAction.type = XkbSA_NoAction;
58535c4bbdfSmrg            }
58635c4bbdfSmrg            break;
58735c4bbdfSmrg        case XkbSA_PtrBtn:
58835c4bbdfSmrg        {
58935c4bbdfSmrg            register int i, nClicks;
59035c4bbdfSmrg
59135c4bbdfSmrg            AccessXCancelRepeatKey(xkbi, keycode);
59235c4bbdfSmrg            if (pAction->btn.count > 0) {
59335c4bbdfSmrg                nClicks = pAction->btn.count;
59435c4bbdfSmrg                for (i = 0; i < nClicks; i++) {
59535c4bbdfSmrg                    XkbFakeDeviceButton(xkbi->device, 1, button);
59635c4bbdfSmrg                    XkbFakeDeviceButton(xkbi->device, 0, button);
59735c4bbdfSmrg                }
59835c4bbdfSmrg                filter->upAction.type = XkbSA_NoAction;
59935c4bbdfSmrg            }
60035c4bbdfSmrg            else
60135c4bbdfSmrg                XkbFakeDeviceButton(xkbi->device, 1, button);
60235c4bbdfSmrg        }
60335c4bbdfSmrg            break;
60435c4bbdfSmrg        case XkbSA_SetPtrDflt:
60535c4bbdfSmrg        {
60635c4bbdfSmrg            XkbControlsPtr ctrls = xkbi->desc->ctrls;
60735c4bbdfSmrg            XkbControlsRec old;
60835c4bbdfSmrg            xkbControlsNotify cn;
60935c4bbdfSmrg
61035c4bbdfSmrg            old = *ctrls;
61135c4bbdfSmrg            AccessXCancelRepeatKey(xkbi, keycode);
61235c4bbdfSmrg            switch (pAction->dflt.affect) {
61335c4bbdfSmrg            case XkbSA_AffectDfltBtn:
61435c4bbdfSmrg                if (pAction->dflt.flags & XkbSA_DfltBtnAbsolute)
61535c4bbdfSmrg                    ctrls->mk_dflt_btn = XkbSAPtrDfltValue(&pAction->dflt);
61635c4bbdfSmrg                else {
61735c4bbdfSmrg                    ctrls->mk_dflt_btn += XkbSAPtrDfltValue(&pAction->dflt);
61835c4bbdfSmrg                    if (ctrls->mk_dflt_btn > 5)
61935c4bbdfSmrg                        ctrls->mk_dflt_btn = 5;
62035c4bbdfSmrg                    else if (ctrls->mk_dflt_btn < 1)
62135c4bbdfSmrg                        ctrls->mk_dflt_btn = 1;
62235c4bbdfSmrg                }
62335c4bbdfSmrg                break;
62435c4bbdfSmrg            default:
62535c4bbdfSmrg                ErrorF
62635c4bbdfSmrg                    ("Attempt to change unknown pointer default (%d) ignored\n",
62735c4bbdfSmrg                     pAction->dflt.affect);
62835c4bbdfSmrg                break;
62935c4bbdfSmrg            }
63035c4bbdfSmrg            if (XkbComputeControlsNotify(xkbi->device,
63135c4bbdfSmrg                                         &old, xkbi->desc->ctrls, &cn, FALSE)) {
63235c4bbdfSmrg                cn.keycode = keycode;
63335c4bbdfSmrg                /* XXX: what about DeviceKeyPress? */
63435c4bbdfSmrg                cn.eventType = KeyPress;
63535c4bbdfSmrg                cn.requestMajor = 0;
63635c4bbdfSmrg                cn.requestMinor = 0;
63735c4bbdfSmrg                XkbSendControlsNotify(xkbi->device, &cn);
63835c4bbdfSmrg            }
63935c4bbdfSmrg        }
64035c4bbdfSmrg            break;
64135c4bbdfSmrg        }
64235c4bbdfSmrg        return 0;
64305b261ecSmrg    }
64435c4bbdfSmrg    else if (filter->keycode == keycode) {
64535c4bbdfSmrg        int button = filter->upAction.btn.button;
64635c4bbdfSmrg
64735c4bbdfSmrg        switch (filter->upAction.type) {
64835c4bbdfSmrg        case XkbSA_LockPtrBtn:
64935c4bbdfSmrg            if (((filter->upAction.btn.flags & XkbSA_LockNoUnlock) != 0) ||
65035c4bbdfSmrg                ((xkbi->lockedPtrButtons & (1 << button)) == 0)) {
65135c4bbdfSmrg                break;
65235c4bbdfSmrg            }
65335c4bbdfSmrg            xkbi->lockedPtrButtons &= ~(1 << button);
65435c4bbdfSmrg
65535c4bbdfSmrg            if (IsMaster(xkbi->device)) {
65635c4bbdfSmrg                XkbMergeLockedPtrBtns(xkbi->device);
65735c4bbdfSmrg                /* One SD still has lock set, don't post event */
65835c4bbdfSmrg                if ((xkbi->lockedPtrButtons & (1 << button)) != 0)
65935c4bbdfSmrg                    break;
66035c4bbdfSmrg            }
66135c4bbdfSmrg
66235c4bbdfSmrg            /* fallthrough */
66335c4bbdfSmrg        case XkbSA_PtrBtn:
66435c4bbdfSmrg            XkbFakeDeviceButton(xkbi->device, 0, button);
66535c4bbdfSmrg            break;
66635c4bbdfSmrg        }
66735c4bbdfSmrg        filter->active = 0;
66835c4bbdfSmrg        return 0;
66905b261ecSmrg    }
67035c4bbdfSmrg    return 1;
67105b261ecSmrg}
67205b261ecSmrg
67305b261ecSmrgstatic int
67435c4bbdfSmrg_XkbFilterControls(XkbSrvInfoPtr xkbi,
67535c4bbdfSmrg                   XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
67605b261ecSmrg{
67735c4bbdfSmrg    XkbControlsRec old;
67835c4bbdfSmrg    XkbControlsPtr ctrls;
67935c4bbdfSmrg    DeviceIntPtr kbd;
68035c4bbdfSmrg    unsigned int change;
68135c4bbdfSmrg    XkbEventCauseRec cause;
68235c4bbdfSmrg
68335c4bbdfSmrg    kbd = xkbi->device;
68435c4bbdfSmrg    ctrls = xkbi->desc->ctrls;
68535c4bbdfSmrg    old = *ctrls;
68635c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
68735c4bbdfSmrg        AccessXCancelRepeatKey(xkbi, keycode);
68835c4bbdfSmrg        filter->keycode = keycode;
68935c4bbdfSmrg        filter->active = 1;
69035c4bbdfSmrg        filter->filterOthers = 0;
69135c4bbdfSmrg        change = XkbActionCtrls(&pAction->ctrls);
69235c4bbdfSmrg        filter->priv = change;
69335c4bbdfSmrg        filter->filter = _XkbFilterControls;
69435c4bbdfSmrg        filter->upAction = *pAction;
69535c4bbdfSmrg
69635c4bbdfSmrg        if (pAction->type == XkbSA_LockControls) {
69735c4bbdfSmrg            filter->priv = (ctrls->enabled_ctrls & change);
69835c4bbdfSmrg            change &= ~ctrls->enabled_ctrls;
69935c4bbdfSmrg        }
70035c4bbdfSmrg
70135c4bbdfSmrg        if (change) {
70235c4bbdfSmrg            xkbControlsNotify cn;
70335c4bbdfSmrg            XkbSrvLedInfoPtr sli;
70435c4bbdfSmrg
70535c4bbdfSmrg            ctrls->enabled_ctrls |= change;
70635c4bbdfSmrg            if (XkbComputeControlsNotify(kbd, &old, ctrls, &cn, FALSE)) {
70735c4bbdfSmrg                cn.keycode = keycode;
70805b261ecSmrg                /* XXX: what about DeviceKeyPress? */
70935c4bbdfSmrg                cn.eventType = KeyPress;
71035c4bbdfSmrg                cn.requestMajor = 0;
71135c4bbdfSmrg                cn.requestMinor = 0;
71235c4bbdfSmrg                XkbSendControlsNotify(kbd, &cn);
71335c4bbdfSmrg            }
71435c4bbdfSmrg
71535c4bbdfSmrg            XkbSetCauseKey(&cause, keycode, KeyPress);
71635c4bbdfSmrg
71735c4bbdfSmrg            /* If sticky keys were disabled, clear all locks and latches */
71835c4bbdfSmrg            if ((old.enabled_ctrls & XkbStickyKeysMask) &&
71935c4bbdfSmrg                (!(ctrls->enabled_ctrls & XkbStickyKeysMask))) {
72035c4bbdfSmrg                XkbClearAllLatchesAndLocks(kbd, xkbi, FALSE, &cause);
72135c4bbdfSmrg            }
72235c4bbdfSmrg            sli = XkbFindSrvLedInfo(kbd, XkbDfltXIClass, XkbDfltXIId, 0);
72335c4bbdfSmrg            XkbUpdateIndicators(kbd, sli->usesControls, TRUE, NULL, &cause);
72435c4bbdfSmrg            if (XkbAX_NeedFeedback(ctrls, XkbAX_FeatureFBMask))
72535c4bbdfSmrg                XkbDDXAccessXBeep(kbd, _BEEP_FEATURE_ON, change);
72635c4bbdfSmrg        }
72705b261ecSmrg    }
72835c4bbdfSmrg    else if (filter->keycode == keycode) {
72935c4bbdfSmrg        change = filter->priv;
73035c4bbdfSmrg        if (change) {
73135c4bbdfSmrg            xkbControlsNotify cn;
73235c4bbdfSmrg            XkbSrvLedInfoPtr sli;
73335c4bbdfSmrg
73435c4bbdfSmrg            ctrls->enabled_ctrls &= ~change;
73535c4bbdfSmrg            if (XkbComputeControlsNotify(kbd, &old, ctrls, &cn, FALSE)) {
73635c4bbdfSmrg                cn.keycode = keycode;
73735c4bbdfSmrg                cn.eventType = KeyRelease;
73835c4bbdfSmrg                cn.requestMajor = 0;
73935c4bbdfSmrg                cn.requestMinor = 0;
74035c4bbdfSmrg                XkbSendControlsNotify(kbd, &cn);
74135c4bbdfSmrg            }
74235c4bbdfSmrg
74335c4bbdfSmrg            XkbSetCauseKey(&cause, keycode, KeyRelease);
74435c4bbdfSmrg            /* If sticky keys were disabled, clear all locks and latches */
74535c4bbdfSmrg            if ((old.enabled_ctrls & XkbStickyKeysMask) &&
74635c4bbdfSmrg                (!(ctrls->enabled_ctrls & XkbStickyKeysMask))) {
74735c4bbdfSmrg                XkbClearAllLatchesAndLocks(kbd, xkbi, FALSE, &cause);
74835c4bbdfSmrg            }
74935c4bbdfSmrg            sli = XkbFindSrvLedInfo(kbd, XkbDfltXIClass, XkbDfltXIId, 0);
75035c4bbdfSmrg            XkbUpdateIndicators(kbd, sli->usesControls, TRUE, NULL, &cause);
75135c4bbdfSmrg            if (XkbAX_NeedFeedback(ctrls, XkbAX_FeatureFBMask))
75235c4bbdfSmrg                XkbDDXAccessXBeep(kbd, _BEEP_FEATURE_OFF, change);
75335c4bbdfSmrg        }
75435c4bbdfSmrg        filter->keycode = 0;
75535c4bbdfSmrg        filter->active = 0;
75605b261ecSmrg    }
75705b261ecSmrg    return 1;
75805b261ecSmrg}
75905b261ecSmrg
76005b261ecSmrgstatic int
76135c4bbdfSmrg_XkbFilterActionMessage(XkbSrvInfoPtr xkbi,
76235c4bbdfSmrg                        XkbFilterPtr filter,
76335c4bbdfSmrg                        unsigned keycode, XkbAction *pAction)
76405b261ecSmrg{
76535c4bbdfSmrg    XkbMessageAction *pMsg;
76635c4bbdfSmrg    DeviceIntPtr kbd;
76735c4bbdfSmrg
76835c4bbdfSmrg    if ((filter->keycode != 0) && (filter->keycode != keycode))
76935c4bbdfSmrg	return 1;
77035c4bbdfSmrg
77135c4bbdfSmrg    /* This can happen if the key repeats, and the state (modifiers or group)
77235c4bbdfSmrg       changes meanwhile. */
77335c4bbdfSmrg    if ((filter->keycode == keycode) && pAction &&
77435c4bbdfSmrg	(pAction->type != XkbSA_ActionMessage))
77535c4bbdfSmrg	return 1;
77635c4bbdfSmrg
77735c4bbdfSmrg    kbd = xkbi->device;
77835c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
77935c4bbdfSmrg        pMsg = &pAction->msg;
78035c4bbdfSmrg        if ((pMsg->flags & XkbSA_MessageOnRelease) ||
78135c4bbdfSmrg            ((pMsg->flags & XkbSA_MessageGenKeyEvent) == 0)) {
78235c4bbdfSmrg            filter->keycode = keycode;
78335c4bbdfSmrg            filter->active = 1;
78435c4bbdfSmrg            filter->filterOthers = 0;
78535c4bbdfSmrg            filter->priv = 0;
78635c4bbdfSmrg            filter->filter = _XkbFilterActionMessage;
78735c4bbdfSmrg            filter->upAction = *pAction;
78835c4bbdfSmrg        }
78935c4bbdfSmrg        if (pMsg->flags & XkbSA_MessageOnPress) {
79035c4bbdfSmrg            xkbActionMessage msg;
79135c4bbdfSmrg
79235c4bbdfSmrg            msg.keycode = keycode;
79335c4bbdfSmrg            msg.press = 1;
79435c4bbdfSmrg            msg.keyEventFollows =
79535c4bbdfSmrg                ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
79635c4bbdfSmrg            memcpy((char *) msg.message, (char *) pMsg->message,
79735c4bbdfSmrg                   XkbActionMessageLength);
79835c4bbdfSmrg            XkbSendActionMessage(kbd, &msg);
79935c4bbdfSmrg        }
80035c4bbdfSmrg        return ((pAction->msg.flags & XkbSA_MessageGenKeyEvent) != 0);
80105b261ecSmrg    }
80235c4bbdfSmrg    else if (filter->keycode == keycode) {
80335c4bbdfSmrg        pMsg = &filter->upAction.msg;
80435c4bbdfSmrg	if (pAction == NULL) {
80535c4bbdfSmrg	    if (pMsg->flags & XkbSA_MessageOnRelease) {
80635c4bbdfSmrg		xkbActionMessage msg;
80735c4bbdfSmrg
80835c4bbdfSmrg		msg.keycode = keycode;
80935c4bbdfSmrg		msg.press = 0;
81035c4bbdfSmrg		msg.keyEventFollows =
81135c4bbdfSmrg		    ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
81235c4bbdfSmrg		memcpy((char *) msg.message, (char *) pMsg->message,
81335c4bbdfSmrg		       XkbActionMessageLength);
81435c4bbdfSmrg		XkbSendActionMessage(kbd, &msg);
81535c4bbdfSmrg	    }
81635c4bbdfSmrg	    filter->keycode = 0;
81735c4bbdfSmrg	    filter->active = 0;
81835c4bbdfSmrg	    return ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
81935c4bbdfSmrg	} else if (memcmp(pMsg, pAction, 8) == 0) {
82035c4bbdfSmrg	    /* Repeat: If we send the same message, avoid multiple messages
82135c4bbdfSmrg	       on release from piling up. */
82235c4bbdfSmrg	    filter->keycode = 0;
82335c4bbdfSmrg	    filter->active = 0;
82435c4bbdfSmrg        }
82505b261ecSmrg    }
82635c4bbdfSmrg    return 1;
82705b261ecSmrg}
82805b261ecSmrg
82905b261ecSmrgstatic int
83035c4bbdfSmrg_XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
83135c4bbdfSmrg                      XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
83205b261ecSmrg{
83335c4bbdfSmrg    DeviceEvent ev;
83435c4bbdfSmrg    int x, y;
83535c4bbdfSmrg    XkbStateRec old, old_prev;
83635c4bbdfSmrg    unsigned mods, mask;
83735c4bbdfSmrg    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
83835c4bbdfSmrg    ProcessInputProc backupproc;
83935c4bbdfSmrg
84035c4bbdfSmrg    if ((filter->keycode != 0) && (filter->keycode != keycode))
84135c4bbdfSmrg        return 1;
84235c4bbdfSmrg
84335c4bbdfSmrg    /* This can happen if the key repeats, and the state (modifiers or group)
84435c4bbdfSmrg       changes meanwhile. */
84535c4bbdfSmrg    if ((filter->keycode == keycode) && pAction &&
84635c4bbdfSmrg	(pAction->type != XkbSA_RedirectKey))
84735c4bbdfSmrg	return 1;
84805b261ecSmrg
84905b261ecSmrg    /* never actually used uninitialised, but gcc isn't smart enough
85005b261ecSmrg     * to work that out. */
85105b261ecSmrg    memset(&old, 0, sizeof(old));
85235c4bbdfSmrg    memset(&old_prev, 0, sizeof(old_prev));
8536747b715Smrg    memset(&ev, 0, sizeof(ev));
85405b261ecSmrg
85535c4bbdfSmrg    GetSpritePosition(xkbi->device, &x, &y);
8566747b715Smrg    ev.header = ET_Internal;
8576747b715Smrg    ev.length = sizeof(DeviceEvent);
8586747b715Smrg    ev.time = GetTimeInMillis();
8596747b715Smrg    ev.root_x = x;
8606747b715Smrg    ev.root_y = y;
86135c4bbdfSmrg    /* redirect actions do not work across devices, therefore the following is
86235c4bbdfSmrg     * correct: */
86335c4bbdfSmrg    ev.deviceid = xkbi->device->id;
86435c4bbdfSmrg    /* filter->priv must be set up by the caller for the initial press. */
86535c4bbdfSmrg    ev.sourceid = filter->priv;
86635c4bbdfSmrg
86735c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
86835c4bbdfSmrg        if ((pAction->redirect.new_key < xkbi->desc->min_key_code) ||
86935c4bbdfSmrg            (pAction->redirect.new_key > xkbi->desc->max_key_code)) {
87035c4bbdfSmrg            return 1;
87135c4bbdfSmrg        }
87235c4bbdfSmrg        filter->keycode = keycode;
87335c4bbdfSmrg        filter->active = 1;
87435c4bbdfSmrg        filter->filterOthers = 0;
87535c4bbdfSmrg        filter->filter = _XkbFilterRedirectKey;
87635c4bbdfSmrg        filter->upAction = *pAction;
87705b261ecSmrg
8786747b715Smrg        ev.type = ET_KeyPress;
8796747b715Smrg        ev.detail.key = pAction->redirect.new_key;
88005b261ecSmrg
88135c4bbdfSmrg        mask = XkbSARedirectVModsMask(&pAction->redirect);
88235c4bbdfSmrg        mods = XkbSARedirectVMods(&pAction->redirect);
88335c4bbdfSmrg        if (mask)
88435c4bbdfSmrg            XkbVirtualModsToReal(xkbi->desc, mask, &mask);
88535c4bbdfSmrg        if (mods)
88635c4bbdfSmrg            XkbVirtualModsToReal(xkbi->desc, mods, &mods);
88735c4bbdfSmrg        mask |= pAction->redirect.mods_mask;
88835c4bbdfSmrg        mods |= pAction->redirect.mods;
88935c4bbdfSmrg
89035c4bbdfSmrg        if (mask || mods) {
89135c4bbdfSmrg            old = xkbi->state;
89235c4bbdfSmrg            old_prev = xkbi->prev_state;
89335c4bbdfSmrg            xkbi->state.base_mods &= ~mask;
89435c4bbdfSmrg            xkbi->state.base_mods |= (mods & mask);
89535c4bbdfSmrg            xkbi->state.latched_mods &= ~mask;
89635c4bbdfSmrg            xkbi->state.latched_mods |= (mods & mask);
89735c4bbdfSmrg            xkbi->state.locked_mods &= ~mask;
89835c4bbdfSmrg            xkbi->state.locked_mods |= (mods & mask);
89935c4bbdfSmrg            XkbComputeDerivedState(xkbi);
90035c4bbdfSmrg            xkbi->prev_state = xkbi->state;
90135c4bbdfSmrg        }
90235c4bbdfSmrg
90335c4bbdfSmrg        UNWRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc);
90435c4bbdfSmrg        xkbi->device->public.processInputProc((InternalEvent *) &ev,
90535c4bbdfSmrg                                              xkbi->device);
90635c4bbdfSmrg        COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc,
90735c4bbdfSmrg                                     xkbUnwrapProc);
90835c4bbdfSmrg
90935c4bbdfSmrg        if (mask || mods) {
91035c4bbdfSmrg            xkbi->state = old;
91135c4bbdfSmrg            xkbi->prev_state = old_prev;
91235c4bbdfSmrg        }
91335c4bbdfSmrg	return 0;
91435c4bbdfSmrg    }
91535c4bbdfSmrg    else {
91635c4bbdfSmrg	/* If it is a key release, or we redirect to another key, release the
91735c4bbdfSmrg	   previous new_key.  Otherwise, repeat. */
91835c4bbdfSmrg	ev.detail.key = filter->upAction.redirect.new_key;
91935c4bbdfSmrg	if (pAction == NULL ||  ev.detail.key != pAction->redirect.new_key) {
92035c4bbdfSmrg	    ev.type = ET_KeyRelease;
92135c4bbdfSmrg	    filter->active = 0;
92235c4bbdfSmrg	}
92335c4bbdfSmrg	else {
92435c4bbdfSmrg	    ev.type = ET_KeyPress;
92535c4bbdfSmrg	    ev.key_repeat = TRUE;
92605b261ecSmrg	}
92705b261ecSmrg
92835c4bbdfSmrg	mask = XkbSARedirectVModsMask(&filter->upAction.redirect);
92935c4bbdfSmrg	mods = XkbSARedirectVMods(&filter->upAction.redirect);
93035c4bbdfSmrg	if (mask)
93135c4bbdfSmrg	    XkbVirtualModsToReal(xkbi->desc, mask, &mask);
93235c4bbdfSmrg	if (mods)
93335c4bbdfSmrg	    XkbVirtualModsToReal(xkbi->desc, mods, &mods);
93435c4bbdfSmrg	mask |= filter->upAction.redirect.mods_mask;
93535c4bbdfSmrg	mods |= filter->upAction.redirect.mods;
93635c4bbdfSmrg
93735c4bbdfSmrg	if (mask || mods) {
93835c4bbdfSmrg	    old = xkbi->state;
93935c4bbdfSmrg	    old_prev = xkbi->prev_state;
94035c4bbdfSmrg	    xkbi->state.base_mods &= ~mask;
94135c4bbdfSmrg	    xkbi->state.base_mods |= (mods & mask);
94235c4bbdfSmrg	    xkbi->state.latched_mods &= ~mask;
94335c4bbdfSmrg	    xkbi->state.latched_mods |= (mods & mask);
94435c4bbdfSmrg	    xkbi->state.locked_mods &= ~mask;
94535c4bbdfSmrg	    xkbi->state.locked_mods |= (mods & mask);
94605b261ecSmrg	    XkbComputeDerivedState(xkbi);
94735c4bbdfSmrg	    xkbi->prev_state = xkbi->state;
94805b261ecSmrg	}
94905b261ecSmrg
95035c4bbdfSmrg	UNWRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc);
95135c4bbdfSmrg	xkbi->device->public.processInputProc((InternalEvent *) &ev,
95235c4bbdfSmrg					      xkbi->device);
95335c4bbdfSmrg	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc,
95435c4bbdfSmrg				     xkbUnwrapProc);
95505b261ecSmrg
95635c4bbdfSmrg	if (mask || mods) {
95735c4bbdfSmrg	    xkbi->state = old;
95835c4bbdfSmrg	    xkbi->prev_state = old_prev;
95935c4bbdfSmrg	}
96005b261ecSmrg
96135c4bbdfSmrg	/* We return 1 in case we have sent a release event because the new_key
96235c4bbdfSmrg	   has changed.  Then, subsequently, we will call this function again
96335c4bbdfSmrg	   with the same pAction, which will create the press for the new
96435c4bbdfSmrg	   new_key. */
96535c4bbdfSmrg	return (pAction && ev.detail.key != pAction->redirect.new_key);
96605b261ecSmrg    }
96705b261ecSmrg}
96805b261ecSmrg
96905b261ecSmrgstatic int
97035c4bbdfSmrg_XkbFilterSwitchScreen(XkbSrvInfoPtr xkbi,
97135c4bbdfSmrg                       XkbFilterPtr filter,
97235c4bbdfSmrg                       unsigned keycode, XkbAction *pAction)
97305b261ecSmrg{
97405b261ecSmrg    DeviceIntPtr dev = xkbi->device;
97535c4bbdfSmrg
97605b261ecSmrg    if (dev == inputInfo.keyboard)
97705b261ecSmrg        return 0;
97805b261ecSmrg
97935c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
98035c4bbdfSmrg        filter->keycode = keycode;
98135c4bbdfSmrg        filter->active = 1;
98235c4bbdfSmrg        filter->filterOthers = 0;
98335c4bbdfSmrg        filter->filter = _XkbFilterSwitchScreen;
98435c4bbdfSmrg        AccessXCancelRepeatKey(xkbi, keycode);
98535c4bbdfSmrg        XkbDDXSwitchScreen(dev, keycode, pAction);
98635c4bbdfSmrg        return 0;
98705b261ecSmrg    }
98835c4bbdfSmrg    else if (filter->keycode == keycode) {
98935c4bbdfSmrg        filter->active = 0;
99035c4bbdfSmrg        return 0;
99105b261ecSmrg    }
99205b261ecSmrg    return 1;
99305b261ecSmrg}
99405b261ecSmrg
99505b261ecSmrgstatic int
99635c4bbdfSmrg_XkbFilterXF86Private(XkbSrvInfoPtr xkbi,
99735c4bbdfSmrg                      XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
99805b261ecSmrg{
99905b261ecSmrg    DeviceIntPtr dev = xkbi->device;
100035c4bbdfSmrg
100105b261ecSmrg    if (dev == inputInfo.keyboard)
100205b261ecSmrg        return 0;
100305b261ecSmrg
100435c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
100535c4bbdfSmrg        filter->keycode = keycode;
100635c4bbdfSmrg        filter->active = 1;
100735c4bbdfSmrg        filter->filterOthers = 0;
100835c4bbdfSmrg        filter->filter = _XkbFilterXF86Private;
100935c4bbdfSmrg        XkbDDXPrivate(dev, keycode, pAction);
101035c4bbdfSmrg        return 0;
101105b261ecSmrg    }
101235c4bbdfSmrg    else if (filter->keycode == keycode) {
101335c4bbdfSmrg        filter->active = 0;
101435c4bbdfSmrg        return 0;
101505b261ecSmrg    }
101605b261ecSmrg    return 1;
101705b261ecSmrg}
101805b261ecSmrg
101905b261ecSmrgstatic int
102035c4bbdfSmrg_XkbFilterDeviceBtn(XkbSrvInfoPtr xkbi,
102135c4bbdfSmrg                    XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
102205b261ecSmrg{
10234642e01fSmrg    if (xkbi->device == inputInfo.keyboard)
102405b261ecSmrg        return 0;
102505b261ecSmrg
102635c4bbdfSmrg    if (filter->keycode == 0) { /* initial press */
102735c4bbdfSmrg        DeviceIntPtr dev;
102835c4bbdfSmrg        int button;
102935c4bbdfSmrg
103035c4bbdfSmrg        _XkbLookupButtonDevice(&dev, pAction->devbtn.device, serverClient,
103135c4bbdfSmrg                               DixUnknownAccess, &button);
103235c4bbdfSmrg        if (!dev || !dev->public.on)
103335c4bbdfSmrg            return 1;
103435c4bbdfSmrg
103535c4bbdfSmrg        button = pAction->devbtn.button;
103635c4bbdfSmrg        if ((button < 1) || (button > dev->button->numButtons))
103735c4bbdfSmrg            return 1;
103835c4bbdfSmrg
103935c4bbdfSmrg        filter->keycode = keycode;
104035c4bbdfSmrg        filter->active = 1;
104135c4bbdfSmrg        filter->filterOthers = 0;
104235c4bbdfSmrg        filter->priv = 0;
104335c4bbdfSmrg        filter->filter = _XkbFilterDeviceBtn;
104435c4bbdfSmrg        filter->upAction = *pAction;
104535c4bbdfSmrg        switch (pAction->type) {
104635c4bbdfSmrg        case XkbSA_LockDeviceBtn:
104735c4bbdfSmrg            if ((pAction->devbtn.flags & XkbSA_LockNoLock) ||
104835c4bbdfSmrg                BitIsOn(dev->button->down, button))
104935c4bbdfSmrg                return 0;
105035c4bbdfSmrg            XkbFakeDeviceButton(dev, TRUE, button);
105135c4bbdfSmrg            filter->upAction.type = XkbSA_NoAction;
105235c4bbdfSmrg            break;
105335c4bbdfSmrg        case XkbSA_DeviceBtn:
105435c4bbdfSmrg            if (pAction->devbtn.count > 0) {
105535c4bbdfSmrg                int nClicks, i;
105635c4bbdfSmrg
105735c4bbdfSmrg                nClicks = pAction->btn.count;
105835c4bbdfSmrg                for (i = 0; i < nClicks; i++) {
105935c4bbdfSmrg                    XkbFakeDeviceButton(dev, TRUE, button);
106035c4bbdfSmrg                    XkbFakeDeviceButton(dev, FALSE, button);
106135c4bbdfSmrg                }
106235c4bbdfSmrg                filter->upAction.type = XkbSA_NoAction;
106335c4bbdfSmrg            }
106435c4bbdfSmrg            else
106535c4bbdfSmrg                XkbFakeDeviceButton(dev, TRUE, button);
106635c4bbdfSmrg            break;
106735c4bbdfSmrg        }
106805b261ecSmrg    }
106935c4bbdfSmrg    else if (filter->keycode == keycode) {
107035c4bbdfSmrg        DeviceIntPtr dev;
107135c4bbdfSmrg        int button;
107235c4bbdfSmrg
107335c4bbdfSmrg        filter->active = 0;
107435c4bbdfSmrg        _XkbLookupButtonDevice(&dev, filter->upAction.devbtn.device,
107535c4bbdfSmrg                               serverClient, DixUnknownAccess, &button);
107635c4bbdfSmrg        if (!dev || !dev->public.on)
107735c4bbdfSmrg            return 1;
107835c4bbdfSmrg
107935c4bbdfSmrg        button = filter->upAction.btn.button;
108035c4bbdfSmrg        switch (filter->upAction.type) {
108135c4bbdfSmrg        case XkbSA_LockDeviceBtn:
108235c4bbdfSmrg            if ((filter->upAction.devbtn.flags & XkbSA_LockNoUnlock) ||
108335c4bbdfSmrg                !BitIsOn(dev->button->down, button))
108435c4bbdfSmrg                return 0;
108535c4bbdfSmrg            XkbFakeDeviceButton(dev, FALSE, button);
108635c4bbdfSmrg            break;
108735c4bbdfSmrg        case XkbSA_DeviceBtn:
108835c4bbdfSmrg            XkbFakeDeviceButton(dev, FALSE, button);
108935c4bbdfSmrg            break;
109035c4bbdfSmrg        }
109135c4bbdfSmrg        filter->active = 0;
109205b261ecSmrg    }
109305b261ecSmrg    return 0;
109405b261ecSmrg}
109505b261ecSmrg
109605b261ecSmrgstatic XkbFilterPtr
109735c4bbdfSmrg_XkbNextFreeFilter(XkbSrvInfoPtr xkbi)
109805b261ecSmrg{
109935c4bbdfSmrg    register int i;
110005b261ecSmrg
110135c4bbdfSmrg    if (xkbi->szFilters == 0) {
110235c4bbdfSmrg        xkbi->szFilters = 4;
110335c4bbdfSmrg        xkbi->filters = calloc(xkbi->szFilters, sizeof(XkbFilterRec));
110435c4bbdfSmrg        /* 6/21/93 (ef) -- XXX! deal with allocation failure */
110505b261ecSmrg    }
110635c4bbdfSmrg    for (i = 0; i < xkbi->szFilters; i++) {
110735c4bbdfSmrg        if (!xkbi->filters[i].active) {
110835c4bbdfSmrg            xkbi->filters[i].keycode = 0;
110935c4bbdfSmrg            return &xkbi->filters[i];
111035c4bbdfSmrg        }
111105b261ecSmrg    }
111235c4bbdfSmrg    xkbi->szFilters *= 2;
111335c4bbdfSmrg    xkbi->filters = reallocarray(xkbi->filters,
111435c4bbdfSmrg                                 xkbi->szFilters, sizeof(XkbFilterRec));
111505b261ecSmrg    /* 6/21/93 (ef) -- XXX! deal with allocation failure */
111635c4bbdfSmrg    memset(&xkbi->filters[xkbi->szFilters / 2], 0,
111735c4bbdfSmrg           (xkbi->szFilters / 2) * sizeof(XkbFilterRec));
111835c4bbdfSmrg    return &xkbi->filters[xkbi->szFilters / 2];
111905b261ecSmrg}
112005b261ecSmrg
112105b261ecSmrgstatic int
112235c4bbdfSmrg_XkbApplyFilters(XkbSrvInfoPtr xkbi, unsigned kc, XkbAction *pAction)
112305b261ecSmrg{
112435c4bbdfSmrg    register int i, send;
112535c4bbdfSmrg
112635c4bbdfSmrg    send = 1;
112735c4bbdfSmrg    for (i = 0; i < xkbi->szFilters; i++) {
112835c4bbdfSmrg        if ((xkbi->filters[i].active) && (xkbi->filters[i].filter))
112935c4bbdfSmrg            send =
113035c4bbdfSmrg                ((*xkbi->filters[i].filter) (xkbi, &xkbi->filters[i], kc,
113135c4bbdfSmrg                                             pAction)
113235c4bbdfSmrg                 && send);
113305b261ecSmrg    }
113405b261ecSmrg    return send;
113505b261ecSmrg}
113605b261ecSmrg
113735c4bbdfSmrgstatic int
113835c4bbdfSmrg_XkbEnsureStateChange(XkbSrvInfoPtr xkbi)
113905b261ecSmrg{
114035c4bbdfSmrg    Bool genStateNotify = FALSE;
114135c4bbdfSmrg
114205b261ecSmrg    /* The state may change, so if we're not in the middle of sending a state
114305b261ecSmrg     * notify, prepare for it */
114435c4bbdfSmrg    if ((xkbi->flags & _XkbStateNotifyInProgress) == 0) {
114535c4bbdfSmrg        xkbi->prev_state = xkbi->state;
114635c4bbdfSmrg        xkbi->flags |= _XkbStateNotifyInProgress;
114735c4bbdfSmrg        genStateNotify = TRUE;
114805b261ecSmrg    }
114935c4bbdfSmrg
115035c4bbdfSmrg    return genStateNotify;
115135c4bbdfSmrg}
115235c4bbdfSmrg
115335c4bbdfSmrgstatic void
115435c4bbdfSmrg_XkbApplyState(DeviceIntPtr dev, Bool genStateNotify, int evtype, int key)
115535c4bbdfSmrg{
115635c4bbdfSmrg    XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
115735c4bbdfSmrg    int changed;
115835c4bbdfSmrg
115935c4bbdfSmrg    XkbComputeDerivedState(xkbi);
116035c4bbdfSmrg
116135c4bbdfSmrg    changed = XkbStateChangedFlags(&xkbi->prev_state, &xkbi->state);
116235c4bbdfSmrg    if (genStateNotify) {
116335c4bbdfSmrg        if (changed) {
116435c4bbdfSmrg            xkbStateNotify sn;
116535c4bbdfSmrg
116635c4bbdfSmrg            sn.keycode = key;
116735c4bbdfSmrg            sn.eventType = evtype;
116835c4bbdfSmrg            sn.requestMajor = sn.requestMinor = 0;
116935c4bbdfSmrg            sn.changed = changed;
117035c4bbdfSmrg            XkbSendStateNotify(dev, &sn);
117135c4bbdfSmrg        }
117235c4bbdfSmrg        xkbi->flags &= ~_XkbStateNotifyInProgress;
117335c4bbdfSmrg    }
117435c4bbdfSmrg
117535c4bbdfSmrg    changed = XkbIndicatorsToUpdate(dev, changed, FALSE);
117635c4bbdfSmrg    if (changed) {
117735c4bbdfSmrg        XkbEventCauseRec cause;
117835c4bbdfSmrg        XkbSetCauseKey(&cause, key, evtype);
117935c4bbdfSmrg        XkbUpdateIndicators(dev, changed, FALSE, NULL, &cause);
118035c4bbdfSmrg    }
118135c4bbdfSmrg}
118235c4bbdfSmrg
118335c4bbdfSmrgvoid
118435c4bbdfSmrgXkbPushLockedStateToSlaves(DeviceIntPtr master, int evtype, int key)
118535c4bbdfSmrg{
118635c4bbdfSmrg    DeviceIntPtr dev;
118735c4bbdfSmrg    Bool genStateNotify;
118835c4bbdfSmrg
118935c4bbdfSmrg    nt_list_for_each_entry(dev, inputInfo.devices, next) {
119035c4bbdfSmrg        if (!dev->key || GetMaster(dev, MASTER_KEYBOARD) != master)
119135c4bbdfSmrg            continue;
119235c4bbdfSmrg
119335c4bbdfSmrg        genStateNotify = _XkbEnsureStateChange(dev->key->xkbInfo);
119435c4bbdfSmrg
119535c4bbdfSmrg        dev->key->xkbInfo->state.locked_mods =
119635c4bbdfSmrg            master->key->xkbInfo->state.locked_mods;
119735c4bbdfSmrg
119835c4bbdfSmrg        _XkbApplyState(dev, genStateNotify, evtype, key);
119935c4bbdfSmrg    }
120035c4bbdfSmrg}
120135c4bbdfSmrg
12021b5d61b8Smrgstatic void
12031b5d61b8SmrgXkbActionGetFilter(DeviceIntPtr dev, DeviceEvent *event, KeyCode key,
12041b5d61b8Smrg                   XkbAction *act, int *sendEvent)
12051b5d61b8Smrg{
12061b5d61b8Smrg    XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
12071b5d61b8Smrg    XkbFilterPtr filter;
12081b5d61b8Smrg
12091b5d61b8Smrg    /* For focus events, we only want to run actions which update our state to
12101b5d61b8Smrg     * (hopefully vaguely kinda) match that of the host server, rather than
12111b5d61b8Smrg     * actually execute anything. For example, if we enter our VT with
12121b5d61b8Smrg     * Ctrl+Alt+Backspace held down, we don't want to terminate our server
12131b5d61b8Smrg     * immediately, but we _do_ want Ctrl+Alt to be latched down, so if
12141b5d61b8Smrg     * Backspace is released and then pressed again, the server will terminate.
12151b5d61b8Smrg     *
12161b5d61b8Smrg     * This is pretty flaky, and we should in fact inherit the complete state
12171b5d61b8Smrg     * from the host server. There are some state combinations that we cannot
12181b5d61b8Smrg     * express by running the state machine over every key, e.g. if AltGr+Shift
12191b5d61b8Smrg     * generates a different state to Shift+AltGr. */
12201b5d61b8Smrg    if (event->source_type == EVENT_SOURCE_FOCUS) {
12211b5d61b8Smrg        switch (act->type) {
12221b5d61b8Smrg        case XkbSA_SetMods:
12231b5d61b8Smrg        case XkbSA_SetGroup:
12241b5d61b8Smrg        case XkbSA_LatchMods:
12251b5d61b8Smrg        case XkbSA_LatchGroup:
12261b5d61b8Smrg        case XkbSA_LockMods:
12271b5d61b8Smrg        case XkbSA_LockGroup:
12281b5d61b8Smrg            break;
12291b5d61b8Smrg        default:
12301b5d61b8Smrg            *sendEvent = 1;
12311b5d61b8Smrg            return;
12321b5d61b8Smrg        }
12331b5d61b8Smrg    }
12341b5d61b8Smrg
12351b5d61b8Smrg    switch (act->type) {
12361b5d61b8Smrg    case XkbSA_SetMods:
12371b5d61b8Smrg    case XkbSA_SetGroup:
12381b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12391b5d61b8Smrg        *sendEvent = _XkbFilterSetState(xkbi, filter, key, act);
12401b5d61b8Smrg        break;
12411b5d61b8Smrg    case XkbSA_LatchMods:
12421b5d61b8Smrg    case XkbSA_LatchGroup:
12431b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12441b5d61b8Smrg        *sendEvent = _XkbFilterLatchState(xkbi, filter, key, act);
12451b5d61b8Smrg        break;
12461b5d61b8Smrg    case XkbSA_LockMods:
12471b5d61b8Smrg    case XkbSA_LockGroup:
12481b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12491b5d61b8Smrg        *sendEvent = _XkbFilterLockState(xkbi, filter, key, act);
12501b5d61b8Smrg        break;
12511b5d61b8Smrg    case XkbSA_ISOLock:
12521b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12531b5d61b8Smrg        *sendEvent = _XkbFilterISOLock(xkbi, filter, key, act);
12541b5d61b8Smrg        break;
12551b5d61b8Smrg    case XkbSA_MovePtr:
12561b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12571b5d61b8Smrg        *sendEvent = _XkbFilterPointerMove(xkbi, filter, key, act);
12581b5d61b8Smrg        break;
12591b5d61b8Smrg    case XkbSA_PtrBtn:
12601b5d61b8Smrg    case XkbSA_LockPtrBtn:
12611b5d61b8Smrg    case XkbSA_SetPtrDflt:
12621b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12631b5d61b8Smrg        *sendEvent = _XkbFilterPointerBtn(xkbi, filter, key, act);
12641b5d61b8Smrg        break;
12651b5d61b8Smrg    case XkbSA_Terminate:
12661b5d61b8Smrg        *sendEvent = XkbDDXTerminateServer(dev, key, act);
12671b5d61b8Smrg        break;
12681b5d61b8Smrg    case XkbSA_SwitchScreen:
12691b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12701b5d61b8Smrg        *sendEvent = _XkbFilterSwitchScreen(xkbi, filter, key, act);
12711b5d61b8Smrg        break;
12721b5d61b8Smrg    case XkbSA_SetControls:
12731b5d61b8Smrg    case XkbSA_LockControls:
12741b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12751b5d61b8Smrg        *sendEvent = _XkbFilterControls(xkbi, filter, key, act);
12761b5d61b8Smrg        break;
12771b5d61b8Smrg    case XkbSA_ActionMessage:
12781b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12791b5d61b8Smrg        *sendEvent = _XkbFilterActionMessage(xkbi, filter, key, act);
12801b5d61b8Smrg        break;
12811b5d61b8Smrg    case XkbSA_RedirectKey:
12821b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12831b5d61b8Smrg        /* redirect actions must create a new DeviceEvent.  The
12841b5d61b8Smrg         * source device id for this event cannot be obtained from
12851b5d61b8Smrg         * xkbi, so we pass it here explicitly. The field deviceid
12861b5d61b8Smrg         * equals to xkbi->device->id. */
12871b5d61b8Smrg        filter->priv = event->sourceid;
12881b5d61b8Smrg        *sendEvent = _XkbFilterRedirectKey(xkbi, filter, key, act);
12891b5d61b8Smrg        break;
12901b5d61b8Smrg    case XkbSA_DeviceBtn:
12911b5d61b8Smrg    case XkbSA_LockDeviceBtn:
12921b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12931b5d61b8Smrg        *sendEvent = _XkbFilterDeviceBtn(xkbi, filter, key, act);
12941b5d61b8Smrg        break;
12951b5d61b8Smrg    case XkbSA_XFree86Private:
12961b5d61b8Smrg        filter = _XkbNextFreeFilter(xkbi);
12971b5d61b8Smrg        *sendEvent = _XkbFilterXF86Private(xkbi, filter, key, act);
12981b5d61b8Smrg        break;
12991b5d61b8Smrg    }
13001b5d61b8Smrg}
13011b5d61b8Smrg
130235c4bbdfSmrgvoid
130335c4bbdfSmrgXkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
130435c4bbdfSmrg{
130535c4bbdfSmrg    int key, bit, i;
130635c4bbdfSmrg    XkbSrvInfoPtr xkbi;
130735c4bbdfSmrg    KeyClassPtr keyc;
130835c4bbdfSmrg    int sendEvent;
130935c4bbdfSmrg    Bool genStateNotify;
131035c4bbdfSmrg    XkbAction act;
131135c4bbdfSmrg    Bool keyEvent;
131235c4bbdfSmrg    Bool pressEvent;
131335c4bbdfSmrg    ProcessInputProc backupproc;
131435c4bbdfSmrg
131535c4bbdfSmrg    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
131635c4bbdfSmrg
131735c4bbdfSmrg    keyc = kbd->key;
131835c4bbdfSmrg    xkbi = keyc->xkbInfo;
131935c4bbdfSmrg    key = event->detail.key;
132035c4bbdfSmrg
132135c4bbdfSmrg    genStateNotify = _XkbEnsureStateChange(xkbi);
132205b261ecSmrg
132305b261ecSmrg    xkbi->clearMods = xkbi->setMods = 0;
132405b261ecSmrg    xkbi->groupChange = 0;
132505b261ecSmrg
132605b261ecSmrg    sendEvent = 1;
132735c4bbdfSmrg    keyEvent = ((event->type == ET_KeyPress) || (event->type == ET_KeyRelease));
132835c4bbdfSmrg    pressEvent = ((event->type == ET_KeyPress) ||
132935c4bbdfSmrg                  (event->type == ET_ButtonPress));
133005b261ecSmrg
133105b261ecSmrg    if (pressEvent) {
133235c4bbdfSmrg        if (keyEvent)
133335c4bbdfSmrg            act = XkbGetKeyAction(xkbi, &xkbi->state, key);
133435c4bbdfSmrg        else {
133535c4bbdfSmrg            act = XkbGetButtonAction(kbd, dev, key);
133635c4bbdfSmrg            key |= BTN_ACT_FLAG;
133735c4bbdfSmrg        }
13381b5d61b8Smrg
133935c4bbdfSmrg        sendEvent = _XkbApplyFilters(xkbi, key, &act);
13401b5d61b8Smrg        if (sendEvent)
13411b5d61b8Smrg            XkbActionGetFilter(dev, event, key, &act, &sendEvent);
134205b261ecSmrg    }
134305b261ecSmrg    else {
134435c4bbdfSmrg        if (!keyEvent)
134535c4bbdfSmrg            key |= BTN_ACT_FLAG;
134635c4bbdfSmrg        sendEvent = _XkbApplyFilters(xkbi, key, NULL);
134705b261ecSmrg    }
134805b261ecSmrg
134935c4bbdfSmrg    if (xkbi->groupChange != 0)
135035c4bbdfSmrg        xkbi->state.base_group += xkbi->groupChange;
135105b261ecSmrg    if (xkbi->setMods) {
135235c4bbdfSmrg        for (i = 0, bit = 1; xkbi->setMods; i++, bit <<= 1) {
135335c4bbdfSmrg            if (xkbi->setMods & bit) {
135435c4bbdfSmrg                keyc->modifierKeyCount[i]++;
135535c4bbdfSmrg                xkbi->state.base_mods |= bit;
135635c4bbdfSmrg                xkbi->setMods &= ~bit;
135735c4bbdfSmrg            }
135835c4bbdfSmrg        }
135905b261ecSmrg    }
136005b261ecSmrg    if (xkbi->clearMods) {
136135c4bbdfSmrg        for (i = 0, bit = 1; xkbi->clearMods; i++, bit <<= 1) {
136235c4bbdfSmrg            if (xkbi->clearMods & bit) {
136335c4bbdfSmrg                keyc->modifierKeyCount[i]--;
136435c4bbdfSmrg                if (keyc->modifierKeyCount[i] <= 0) {
136535c4bbdfSmrg                    xkbi->state.base_mods &= ~bit;
136635c4bbdfSmrg                    keyc->modifierKeyCount[i] = 0;
136735c4bbdfSmrg                }
136835c4bbdfSmrg                xkbi->clearMods &= ~bit;
136935c4bbdfSmrg            }
137035c4bbdfSmrg        }
137105b261ecSmrg    }
137205b261ecSmrg
137305b261ecSmrg    if (sendEvent) {
13744642e01fSmrg        DeviceIntPtr tmpdev;
137535c4bbdfSmrg
137635c4bbdfSmrg        if (keyEvent)
13774642e01fSmrg            tmpdev = dev;
13786747b715Smrg        else
137935c4bbdfSmrg            tmpdev = GetMaster(dev, POINTER_OR_FLOAT);
138005b261ecSmrg
138135c4bbdfSmrg        UNWRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr, backupproc);
138235c4bbdfSmrg        dev->public.processInputProc((InternalEvent *) event, tmpdev);
13834642e01fSmrg        COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr,
138435c4bbdfSmrg                                     backupproc, xkbUnwrapProc);
138505b261ecSmrg    }
138605b261ecSmrg    else if (keyEvent) {
138735c4bbdfSmrg        FixKeyState(event, dev);
138805b261ecSmrg    }
138905b261ecSmrg
139035c4bbdfSmrg    _XkbApplyState(dev, genStateNotify, event->type, key);
139135c4bbdfSmrg    XkbPushLockedStateToSlaves(dev, event->type, key);
139205b261ecSmrg}
139305b261ecSmrg
139405b261ecSmrgint
139535c4bbdfSmrgXkbLatchModifiers(DeviceIntPtr pXDev, CARD8 mask, CARD8 latches)
139605b261ecSmrg{
139735c4bbdfSmrg    XkbSrvInfoPtr xkbi;
139835c4bbdfSmrg    XkbFilterPtr filter;
139935c4bbdfSmrg    XkbAction act;
140035c4bbdfSmrg    unsigned clear;
140135c4bbdfSmrg
140235c4bbdfSmrg    if (pXDev && pXDev->key && pXDev->key->xkbInfo) {
140335c4bbdfSmrg        xkbi = pXDev->key->xkbInfo;
140435c4bbdfSmrg        clear = (mask & (~latches));
140535c4bbdfSmrg        xkbi->state.latched_mods &= ~clear;
140635c4bbdfSmrg        /* Clear any pending latch to locks.
140735c4bbdfSmrg         */
140835c4bbdfSmrg        act.type = XkbSA_NoAction;
140935c4bbdfSmrg        _XkbApplyFilters(xkbi, SYNTHETIC_KEYCODE, &act);
141035c4bbdfSmrg        act.type = XkbSA_LatchMods;
141135c4bbdfSmrg        act.mods.flags = 0;
141235c4bbdfSmrg        act.mods.mask = mask & latches;
141335c4bbdfSmrg        filter = _XkbNextFreeFilter(xkbi);
141435c4bbdfSmrg        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE, &act);
141535c4bbdfSmrg        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE,
141635c4bbdfSmrg                             (XkbAction *) NULL);
141735c4bbdfSmrg        return Success;
141805b261ecSmrg    }
141905b261ecSmrg    return BadValue;
142005b261ecSmrg}
142105b261ecSmrg
142205b261ecSmrgint
142335c4bbdfSmrgXkbLatchGroup(DeviceIntPtr pXDev, int group)
142405b261ecSmrg{
142535c4bbdfSmrg    XkbSrvInfoPtr xkbi;
142635c4bbdfSmrg    XkbFilterPtr filter;
142735c4bbdfSmrg    XkbAction act;
142835c4bbdfSmrg
142935c4bbdfSmrg    if (pXDev && pXDev->key && pXDev->key->xkbInfo) {
143035c4bbdfSmrg        xkbi = pXDev->key->xkbInfo;
143135c4bbdfSmrg        act.type = XkbSA_LatchGroup;
143235c4bbdfSmrg        act.group.flags = 0;
143335c4bbdfSmrg        XkbSASetGroup(&act.group, group);
143435c4bbdfSmrg        filter = _XkbNextFreeFilter(xkbi);
143535c4bbdfSmrg        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE, &act);
143635c4bbdfSmrg        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE,
143735c4bbdfSmrg                             (XkbAction *) NULL);
143835c4bbdfSmrg        return Success;
143905b261ecSmrg    }
144005b261ecSmrg    return BadValue;
144105b261ecSmrg}
144205b261ecSmrg
144305b261ecSmrg/***====================================================================***/
144405b261ecSmrg
144505b261ecSmrgvoid
144635c4bbdfSmrgXkbClearAllLatchesAndLocks(DeviceIntPtr dev,
144735c4bbdfSmrg                           XkbSrvInfoPtr xkbi,
144835c4bbdfSmrg                           Bool genEv, XkbEventCausePtr cause)
144905b261ecSmrg{
145035c4bbdfSmrg    XkbStateRec os;
145135c4bbdfSmrg    xkbStateNotify sn;
145235c4bbdfSmrg
145335c4bbdfSmrg    sn.changed = 0;
145435c4bbdfSmrg    os = xkbi->state;
145535c4bbdfSmrg    if (os.latched_mods) {      /* clear all latches */
145635c4bbdfSmrg        XkbLatchModifiers(dev, ~0, 0);
145735c4bbdfSmrg        sn.changed |= XkbModifierLatchMask;
145805b261ecSmrg    }
145905b261ecSmrg    if (os.latched_group) {
146035c4bbdfSmrg        XkbLatchGroup(dev, 0);
146135c4bbdfSmrg        sn.changed |= XkbGroupLatchMask;
146205b261ecSmrg    }
146305b261ecSmrg    if (os.locked_mods) {
146435c4bbdfSmrg        xkbi->state.locked_mods = 0;
146535c4bbdfSmrg        sn.changed |= XkbModifierLockMask;
146605b261ecSmrg    }
146705b261ecSmrg    if (os.locked_group) {
146835c4bbdfSmrg        xkbi->state.locked_group = 0;
146935c4bbdfSmrg        sn.changed |= XkbGroupLockMask;
147005b261ecSmrg    }
147135c4bbdfSmrg    if (genEv && sn.changed) {
147235c4bbdfSmrg        CARD32 changed;
147335c4bbdfSmrg
147435c4bbdfSmrg        XkbComputeDerivedState(xkbi);
147535c4bbdfSmrg        sn.keycode = cause->kc;
147635c4bbdfSmrg        sn.eventType = cause->event;
147735c4bbdfSmrg        sn.requestMajor = cause->mjr;
147835c4bbdfSmrg        sn.requestMinor = cause->mnr;
147935c4bbdfSmrg        sn.changed = XkbStateChangedFlags(&os, &xkbi->state);
148035c4bbdfSmrg        XkbSendStateNotify(dev, &sn);
148135c4bbdfSmrg        changed = XkbIndicatorsToUpdate(dev, sn.changed, FALSE);
148235c4bbdfSmrg        if (changed) {
148335c4bbdfSmrg            XkbUpdateIndicators(dev, changed, TRUE, NULL, cause);
148435c4bbdfSmrg        }
148505b261ecSmrg    }
148605b261ecSmrg    return;
148705b261ecSmrg}
148805b261ecSmrg
14896747b715Smrg/*
14906747b715Smrg * The event is injected into the event processing, not the EQ. Thus,
14916747b715Smrg * ensure that we restore the master after the event sequence to the
14926747b715Smrg * original set of classes. Otherwise, the master remains on the XTEST
14936747b715Smrg * classes and drops events that don't fit into the XTEST layout (e.g.
14946747b715Smrg * events with more than 2 valuators).
14956747b715Smrg *
14966747b715Smrg * FIXME: EQ injection in the processing stage is not designed for, so this
14976747b715Smrg * is a rather awkward hack. The event list returned by GetPointerEvents()
14986747b715Smrg * and friends is always prefixed with a DCE if the last _posted_ device was
14996747b715Smrg * different. For normal events, this sequence then resets the master during
15006747b715Smrg * the processing stage. Since we inject the PointerKey events in the
15016747b715Smrg * processing stage though, we need to manually reset to restore the
15026747b715Smrg * previous order, because the events already in the EQ must be sent for the
15036747b715Smrg * right device.
15046747b715Smrg * So we post-fix the event list we get from GPE with a DCE back to the
15056747b715Smrg * previous slave device.
15066747b715Smrg *
15076747b715Smrg * First one on drinking island wins!
15086747b715Smrg */
15096747b715Smrgstatic void
151035c4bbdfSmrgInjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags,
151135c4bbdfSmrg                       ValuatorMask *mask)
15126747b715Smrg{
151335c4bbdfSmrg    ScreenPtr pScreen;
151435c4bbdfSmrg    InternalEvent *events;
151535c4bbdfSmrg    int nevents, i;
151635c4bbdfSmrg    DeviceIntPtr ptr, mpointer, lastSlave = NULL;
151735c4bbdfSmrg    Bool saveWait;
15186747b715Smrg
15196747b715Smrg    if (IsMaster(dev)) {
15206747b715Smrg        mpointer = GetMaster(dev, MASTER_POINTER);
152135c4bbdfSmrg        lastSlave = mpointer->lastSlave;
15226747b715Smrg        ptr = GetXTestDevice(mpointer);
152335c4bbdfSmrg    }
152435c4bbdfSmrg    else if (IsFloating(dev))
15256747b715Smrg        ptr = dev;
15266747b715Smrg    else
15276747b715Smrg        return;
15286747b715Smrg
15296747b715Smrg    events = InitEventList(GetMaximumEventsNum() + 1);
15301b5d61b8Smrg    input_lock();
15316747b715Smrg    pScreen = miPointerGetScreen(ptr);
15326747b715Smrg    saveWait = miPointerSetWaitForUpdate(pScreen, FALSE);
15339ace9065Smrg    nevents = GetPointerEvents(events, ptr, type, button, flags, mask);
15346747b715Smrg    if (IsMaster(dev) && (lastSlave && lastSlave != ptr))
153535c4bbdfSmrg        UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT,
153635c4bbdfSmrg                         &nevents);
15376747b715Smrg    miPointerSetWaitForUpdate(pScreen, saveWait);
15386747b715Smrg
15396747b715Smrg    for (i = 0; i < nevents; i++)
154035c4bbdfSmrg        mieqProcessDeviceEvent(ptr, &events[i], NULL);
15411b5d61b8Smrg    input_unlock();
15426747b715Smrg
15436747b715Smrg    FreeEventList(events, GetMaximumEventsNum());
15446747b715Smrg}
15456747b715Smrg
15466747b715Smrgstatic void
154735c4bbdfSmrgXkbFakePointerMotion(DeviceIntPtr dev, unsigned flags, int x, int y)
15486747b715Smrg{
154935c4bbdfSmrg    ValuatorMask mask;
155035c4bbdfSmrg    int gpe_flags = 0;
15516747b715Smrg
15526747b715Smrg    /* ignore attached SDs */
155335c4bbdfSmrg    if (!IsMaster(dev) && !IsFloating(dev))
15546747b715Smrg        return;
15556747b715Smrg
15566747b715Smrg    if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
15576747b715Smrg        gpe_flags = POINTER_ABSOLUTE;
15586747b715Smrg    else
15596747b715Smrg        gpe_flags = POINTER_RELATIVE;
15606747b715Smrg
156135c4bbdfSmrg    valuator_mask_set_range(&mask, 0, 2, (int[]) {
156235c4bbdfSmrg                            x, y});
15639ace9065Smrg
15649ace9065Smrg    InjectPointerKeyEvents(dev, MotionNotify, 0, gpe_flags, &mask);
15656747b715Smrg}
15666747b715Smrg
15676747b715Smrgvoid
156835c4bbdfSmrgXkbFakeDeviceButton(DeviceIntPtr dev, Bool press, int button)
15696747b715Smrg{
157035c4bbdfSmrg    DeviceIntPtr ptr;
157135c4bbdfSmrg    int down;
15726747b715Smrg
15736747b715Smrg    /* If dev is a slave device, and the SD is attached, do nothing. If we'd
15746747b715Smrg     * post through the attached master pointer we'd get duplicate events.
15756747b715Smrg     *
15766747b715Smrg     * if dev is a master keyboard, post through the XTEST device
15776747b715Smrg     *
15786747b715Smrg     * if dev is a floating slave, post through the device itself.
15796747b715Smrg     */
15806747b715Smrg
15816747b715Smrg    if (IsMaster(dev)) {
15826747b715Smrg        DeviceIntPtr mpointer = GetMaster(dev, MASTER_POINTER);
158335c4bbdfSmrg
15846747b715Smrg        ptr = GetXTestDevice(mpointer);
158535c4bbdfSmrg    }
158635c4bbdfSmrg    else if (IsFloating(dev))
15876747b715Smrg        ptr = dev;
15886747b715Smrg    else
15896747b715Smrg        return;
15906747b715Smrg
15916747b715Smrg    down = button_is_down(ptr, button, BUTTON_PROCESSED);
15926747b715Smrg    if (press == down)
15936747b715Smrg        return;
15946747b715Smrg
15956747b715Smrg    InjectPointerKeyEvents(dev, press ? ButtonPress : ButtonRelease,
15969ace9065Smrg                           button, 0, NULL);
15976747b715Smrg}
1598