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