xkbActions.c revision 35c4bbdf
1/************************************************************
2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4Permission to use, copy, modify, and distribute this
5software and its documentation for any purpose and without
6fee is hereby granted, provided that the above copyright
7notice appear in all copies and that both that copyright
8notice and this permission notice appear in supporting
9documentation, and that the name of Silicon Graphics not be
10used in advertising or publicity pertaining to distribution
11of the software without specific prior written permission.
12Silicon Graphics makes no representation about the suitability
13of this software for any purpose. It is provided "as is"
14without any express or implied warranty.
15
16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25********************************************************/
26
27#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#endif
30
31#include <stdio.h>
32#include <math.h>
33#include <X11/X.h>
34#include <X11/Xproto.h>
35#include <X11/keysym.h>
36#include "misc.h"
37#include "inputstr.h"
38#include "exevents.h"
39#include "eventstr.h"
40#include <xkbsrv.h>
41#include "xkb.h"
42#include <ctype.h>
43#include "mi.h"
44#include "mipointer.h"
45#include "inpututils.h"
46#define EXTENSION_EVENT_BASE 64
47
48DevPrivateKeyRec xkbDevicePrivateKeyRec;
49
50static void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags, int x,
51                                 int y);
52
53void
54xkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc, void *data)
55{
56    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device);
57    ProcessInputProc backupproc;
58
59    if (xkbPrivPtr->unwrapProc)
60        xkbPrivPtr->unwrapProc = NULL;
61
62    UNWRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, backupproc);
63    proc(device, data);
64    COND_WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, backupproc, xkbUnwrapProc);
65}
66
67Bool
68XkbInitPrivates(void)
69{
70    return dixRegisterPrivateKey(&xkbDevicePrivateKeyRec, PRIVATE_DEVICE,
71                                 sizeof(xkbDeviceInfoRec));
72}
73
74void
75XkbSetExtension(DeviceIntPtr device, ProcessInputProc proc)
76{
77    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device);
78
79    WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, proc, xkbUnwrapProc);
80}
81
82/***====================================================================***/
83
84static XkbAction
85_FixUpAction(XkbDescPtr xkb, XkbAction *act)
86{
87    static XkbAction fake;
88
89    if (XkbIsPtrAction(act) &&
90        (!(xkb->ctrls->enabled_ctrls & XkbMouseKeysMask))) {
91        fake.type = XkbSA_NoAction;
92        return fake;
93    }
94    if (xkb->ctrls->enabled_ctrls & XkbStickyKeysMask) {
95        if (act->any.type == XkbSA_SetMods) {
96            fake.mods.type = XkbSA_LatchMods;
97            fake.mods.mask = act->mods.mask;
98            if (XkbAX_NeedOption(xkb->ctrls, XkbAX_LatchToLockMask))
99                fake.mods.flags = XkbSA_ClearLocks | XkbSA_LatchToLock;
100            else
101                fake.mods.flags = XkbSA_ClearLocks;
102            return fake;
103        }
104        if (act->any.type == XkbSA_SetGroup) {
105            fake.group.type = XkbSA_LatchGroup;
106            if (XkbAX_NeedOption(xkb->ctrls, XkbAX_LatchToLockMask))
107                fake.group.flags = XkbSA_ClearLocks | XkbSA_LatchToLock;
108            else
109                fake.group.flags = XkbSA_ClearLocks;
110            XkbSASetGroup(&fake.group, XkbSAGroup(&act->group));
111            return fake;
112        }
113    }
114    return *act;
115}
116
117static XkbAction
118XkbGetKeyAction(XkbSrvInfoPtr xkbi, XkbStatePtr xkbState, CARD8 key)
119{
120    int effectiveGroup;
121    int col;
122    XkbDescPtr xkb;
123    XkbKeyTypePtr type;
124    XkbAction *pActs;
125    static XkbAction fake;
126
127    xkb = xkbi->desc;
128    if (!XkbKeyHasActions(xkb, key) || !XkbKeycodeInRange(xkb, key)) {
129        fake.type = XkbSA_NoAction;
130        return fake;
131    }
132    pActs = XkbKeyActionsPtr(xkb, key);
133    col = 0;
134
135    effectiveGroup = XkbGetEffectiveGroup(xkbi, xkbState, key);
136    if (effectiveGroup != XkbGroup1Index)
137        col += (effectiveGroup * XkbKeyGroupsWidth(xkb, key));
138
139    type = XkbKeyKeyType(xkb, key, effectiveGroup);
140    if (type->map != NULL) {
141        register unsigned i, mods;
142        register XkbKTMapEntryPtr entry;
143
144        mods = xkbState->mods & type->mods.mask;
145        for (entry = type->map, i = 0; i < type->map_count; i++, entry++) {
146            if ((entry->active) && (entry->mods.mask == mods)) {
147                col += entry->level;
148                break;
149            }
150        }
151    }
152    if (pActs[col].any.type == XkbSA_NoAction)
153        return pActs[col];
154    fake = _FixUpAction(xkb, &pActs[col]);
155    return fake;
156}
157
158static XkbAction
159XkbGetButtonAction(DeviceIntPtr kbd, DeviceIntPtr dev, int button)
160{
161    XkbAction fake;
162
163    if ((dev->button) && (dev->button->xkb_acts)) {
164        if (dev->button->xkb_acts[button - 1].any.type != XkbSA_NoAction) {
165            fake = _FixUpAction(kbd->key->xkbInfo->desc,
166                                &dev->button->xkb_acts[button - 1]);
167            return fake;
168        }
169    }
170    fake.any.type = XkbSA_NoAction;
171    return fake;
172}
173
174/***====================================================================***/
175
176#define	SYNTHETIC_KEYCODE	1
177#define	BTN_ACT_FLAG		0x100
178
179static int
180_XkbFilterSetState(XkbSrvInfoPtr xkbi,
181                   XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
182{
183    if (filter->keycode == 0) { /* initial press */
184        AccessXCancelRepeatKey(xkbi, keycode);
185        filter->keycode = keycode;
186        filter->active = 1;
187        filter->filterOthers = ((pAction->mods.mask & XkbSA_ClearLocks) != 0);
188        filter->priv = 0;
189        filter->filter = _XkbFilterSetState;
190        if (pAction->type == XkbSA_SetMods) {
191            filter->upAction = *pAction;
192            xkbi->setMods = pAction->mods.mask;
193        }
194        else {
195            xkbi->groupChange = XkbSAGroup(&pAction->group);
196            if (pAction->group.flags & XkbSA_GroupAbsolute)
197                xkbi->groupChange -= xkbi->state.base_group;
198            filter->upAction = *pAction;
199            XkbSASetGroup(&filter->upAction.group, xkbi->groupChange);
200        }
201    }
202    else if (filter->keycode == keycode) {
203        if (filter->upAction.type == XkbSA_SetMods) {
204            xkbi->clearMods = filter->upAction.mods.mask;
205            if (filter->upAction.mods.flags & XkbSA_ClearLocks) {
206                xkbi->state.locked_mods &= ~filter->upAction.mods.mask;
207            }
208        }
209        else {
210            if (filter->upAction.group.flags & XkbSA_ClearLocks) {
211                xkbi->state.locked_group = 0;
212            }
213            xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
214        }
215        filter->active = 0;
216    }
217    else {
218        filter->upAction.mods.flags &= ~XkbSA_ClearLocks;
219        filter->filterOthers = 0;
220    }
221    return 1;
222}
223
224#define	LATCH_KEY_DOWN	1
225#define	LATCH_PENDING	2
226
227static int
228_XkbFilterLatchState(XkbSrvInfoPtr xkbi,
229                     XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
230{
231
232    if (filter->keycode == 0) { /* initial press */
233        AccessXCancelRepeatKey(xkbi,keycode);
234        filter->keycode = keycode;
235        filter->active = 1;
236        filter->filterOthers = 1;
237        filter->priv = LATCH_KEY_DOWN;
238        filter->filter = _XkbFilterLatchState;
239        if (pAction->type == XkbSA_LatchMods) {
240            filter->upAction = *pAction;
241            xkbi->setMods = pAction->mods.mask;
242        }
243        else {
244            xkbi->groupChange = XkbSAGroup(&pAction->group);
245            if (pAction->group.flags & XkbSA_GroupAbsolute)
246                xkbi->groupChange -= xkbi->state.base_group;
247            filter->upAction = *pAction;
248            XkbSASetGroup(&filter->upAction.group, xkbi->groupChange);
249        }
250    }
251    else if (pAction && (filter->priv == LATCH_PENDING)) {
252        if (((1 << pAction->type) & XkbSA_BreakLatch) != 0) {
253            filter->active = 0;
254            /* If one latch is broken, all latches are broken, so it's no use
255               to find out which particular latch this filter tracks. */
256            xkbi->state.latched_mods = 0;
257            xkbi->state.latched_group = 0;
258        }
259    }
260    else if (filter->keycode == keycode && filter->priv != LATCH_PENDING){
261        /* The test above for LATCH_PENDING skips subsequent releases of the
262           key after it has been released first time and the latch became
263           pending. */
264        XkbControlsPtr ctrls = xkbi->desc->ctrls;
265        int needBeep = ((ctrls->enabled_ctrls & XkbStickyKeysMask) &&
266                        XkbAX_NeedFeedback(ctrls, XkbAX_StickyKeysFBMask));
267
268        if (filter->upAction.type == XkbSA_LatchMods) {
269            unsigned char mask = filter->upAction.mods.mask;
270            unsigned char common;
271
272            xkbi->clearMods = mask;
273
274            /* ClearLocks */
275            common = mask & xkbi->state.locked_mods;
276            if ((filter->upAction.mods.flags & XkbSA_ClearLocks) && common) {
277                mask &= ~common;
278                xkbi->state.locked_mods &= ~common;
279                if (needBeep)
280                    XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_UNLOCK,
281                                      XkbStickyKeysMask);
282            }
283            /* LatchToLock */
284            common = mask & xkbi->state.latched_mods;
285            if ((filter->upAction.mods.flags & XkbSA_LatchToLock) && common) {
286                unsigned char newlocked;
287
288                mask &= ~common;
289                newlocked = common & ~xkbi->state.locked_mods;
290                if(newlocked){
291                    xkbi->state.locked_mods |= newlocked;
292                    if (needBeep)
293                        XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LOCK,
294                                          XkbStickyKeysMask);
295
296                }
297                xkbi->state.latched_mods &= ~common;
298            }
299            /* Latch remaining modifiers, if any. */
300            if (mask) {
301                xkbi->state.latched_mods |= mask;
302                filter->priv = LATCH_PENDING;
303                if (needBeep)
304                    XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LATCH,
305                                      XkbStickyKeysMask);
306            }
307        }
308        else {
309            xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
310            /* ClearLocks */
311            if ((filter->upAction.group.flags & XkbSA_ClearLocks) &&
312                (xkbi->state.locked_group)) {
313                xkbi->state.locked_group = 0;
314                if (needBeep)
315                    XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_UNLOCK,
316                                      XkbStickyKeysMask);
317            }
318            /* LatchToLock */
319            else if ((filter->upAction.group.flags & XkbSA_LatchToLock)
320                     && (xkbi->state.latched_group)) {
321                xkbi->state.locked_group  += XkbSAGroup(&filter->upAction.group);
322                xkbi->state.latched_group -= XkbSAGroup(&filter->upAction.group);
323                if(XkbSAGroup(&filter->upAction.group) && needBeep)
324                    XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LOCK,
325                                      XkbStickyKeysMask);
326            }
327            /* Latch group */
328            else if(XkbSAGroup(&filter->upAction.group)){
329                xkbi->state.latched_group += XkbSAGroup(&filter->upAction.group);
330                filter->priv = LATCH_PENDING;
331                if (needBeep)
332                    XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LATCH,
333                                      XkbStickyKeysMask);
334            }
335        }
336
337        if (filter->priv != LATCH_PENDING)
338            filter->active = 0;
339    }
340    else if (pAction && (filter->priv == LATCH_KEY_DOWN)) {
341        /* Latch was broken before it became pending: degrade to a
342           SetMods/SetGroup. */
343        if (filter->upAction.type == XkbSA_LatchMods)
344            filter->upAction.type = XkbSA_SetMods;
345        else
346            filter->upAction.type = XkbSA_SetGroup;
347        filter->filter = _XkbFilterSetState;
348        filter->priv = 0;
349        return filter->filter(xkbi, filter, keycode, pAction);
350    }
351    return 1;
352}
353
354static int
355_XkbFilterLockState(XkbSrvInfoPtr xkbi,
356                    XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
357{
358    if (filter->keycode == 0) /* initial press */
359        AccessXCancelRepeatKey(xkbi, keycode);
360
361    if (pAction && (pAction->type == XkbSA_LockGroup)) {
362        if (pAction->group.flags & XkbSA_GroupAbsolute)
363            xkbi->state.locked_group = XkbSAGroup(&pAction->group);
364        else
365            xkbi->state.locked_group += XkbSAGroup(&pAction->group);
366        return 1;
367    }
368    if (filter->keycode == 0) { /* initial press */
369        filter->keycode = keycode;
370        filter->active = 1;
371        filter->filterOthers = 0;
372        filter->priv = xkbi->state.locked_mods & pAction->mods.mask;
373        filter->filter = _XkbFilterLockState;
374        filter->upAction = *pAction;
375        if (!(filter->upAction.mods.flags & XkbSA_LockNoLock))
376            xkbi->state.locked_mods |= pAction->mods.mask;
377        xkbi->setMods = pAction->mods.mask;
378    }
379    else if (filter->keycode == keycode) {
380        filter->active = 0;
381        xkbi->clearMods = filter->upAction.mods.mask;
382        if (!(filter->upAction.mods.flags & XkbSA_LockNoUnlock))
383            xkbi->state.locked_mods &= ~filter->priv;
384    }
385    return 1;
386}
387
388#define	ISO_KEY_DOWN		0
389#define	NO_ISO_LOCK		1
390
391static int
392_XkbFilterISOLock(XkbSrvInfoPtr xkbi,
393                  XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
394{
395
396    if (filter->keycode == 0) { /* initial press */
397        CARD8 flags = pAction->iso.flags;
398
399        filter->keycode = keycode;
400        filter->active = 1;
401        filter->filterOthers = 1;
402        filter->priv = ISO_KEY_DOWN;
403        filter->upAction = *pAction;
404        filter->filter = _XkbFilterISOLock;
405        if (flags & XkbSA_ISODfltIsGroup) {
406            xkbi->groupChange = XkbSAGroup(&pAction->iso);
407            xkbi->setMods = 0;
408        }
409        else {
410            xkbi->setMods = pAction->iso.mask;
411            xkbi->groupChange = 0;
412        }
413        if ((!(flags & XkbSA_ISONoAffectMods)) && (xkbi->state.base_mods)) {
414            filter->priv = NO_ISO_LOCK;
415            xkbi->state.locked_mods ^= xkbi->state.base_mods;
416        }
417        if ((!(flags & XkbSA_ISONoAffectGroup)) && (xkbi->state.base_group)) {
418/* 6/22/93 (ef) -- lock groups if group key is down first */
419        }
420        if (!(flags & XkbSA_ISONoAffectPtr)) {
421/* 6/22/93 (ef) -- lock mouse buttons if they're down */
422        }
423    }
424    else if (filter->keycode == keycode) {
425        CARD8 flags = filter->upAction.iso.flags;
426
427        if (flags & XkbSA_ISODfltIsGroup) {
428            xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso);
429            xkbi->clearMods = 0;
430            if (filter->priv == ISO_KEY_DOWN)
431                xkbi->state.locked_group += XkbSAGroup(&filter->upAction.iso);
432        }
433        else {
434            xkbi->clearMods = filter->upAction.iso.mask;
435            xkbi->groupChange = 0;
436            if (filter->priv == ISO_KEY_DOWN)
437                xkbi->state.locked_mods ^= filter->upAction.iso.mask;
438        }
439        filter->active = 0;
440    }
441    else if (pAction) {
442        CARD8 flags = filter->upAction.iso.flags;
443
444        switch (pAction->type) {
445        case XkbSA_SetMods:
446        case XkbSA_LatchMods:
447            if (!(flags & XkbSA_ISONoAffectMods)) {
448                pAction->type = XkbSA_LockMods;
449                filter->priv = NO_ISO_LOCK;
450            }
451            break;
452        case XkbSA_SetGroup:
453        case XkbSA_LatchGroup:
454            if (!(flags & XkbSA_ISONoAffectGroup)) {
455                pAction->type = XkbSA_LockGroup;
456                filter->priv = NO_ISO_LOCK;
457            }
458            break;
459        case XkbSA_PtrBtn:
460            if (!(flags & XkbSA_ISONoAffectPtr)) {
461                pAction->type = XkbSA_LockPtrBtn;
462                filter->priv = NO_ISO_LOCK;
463            }
464            break;
465        case XkbSA_SetControls:
466            if (!(flags & XkbSA_ISONoAffectCtrls)) {
467                pAction->type = XkbSA_LockControls;
468                filter->priv = NO_ISO_LOCK;
469            }
470            break;
471        }
472    }
473    return 1;
474}
475
476static CARD32
477_XkbPtrAccelExpire(OsTimerPtr timer, CARD32 now, void *arg)
478{
479    XkbSrvInfoPtr xkbi = (XkbSrvInfoPtr) arg;
480    XkbControlsPtr ctrls = xkbi->desc->ctrls;
481    int dx, dy;
482
483    if (xkbi->mouseKey == 0)
484        return 0;
485
486    if (xkbi->mouseKeysAccel) {
487        if ((xkbi->mouseKeysCounter) < ctrls->mk_time_to_max) {
488            double step;
489
490            xkbi->mouseKeysCounter++;
491            step = xkbi->mouseKeysCurveFactor *
492                pow((double) xkbi->mouseKeysCounter, xkbi->mouseKeysCurve);
493            if (xkbi->mouseKeysDX < 0)
494                dx = floor(((double) xkbi->mouseKeysDX) * step);
495            else
496                dx = ceil(((double) xkbi->mouseKeysDX) * step);
497            if (xkbi->mouseKeysDY < 0)
498                dy = floor(((double) xkbi->mouseKeysDY) * step);
499            else
500                dy = ceil(((double) xkbi->mouseKeysDY) * step);
501        }
502        else {
503            dx = xkbi->mouseKeysDX * ctrls->mk_max_speed;
504            dy = xkbi->mouseKeysDY * ctrls->mk_max_speed;
505        }
506        if (xkbi->mouseKeysFlags & XkbSA_MoveAbsoluteX)
507            dx = xkbi->mouseKeysDX;
508        if (xkbi->mouseKeysFlags & XkbSA_MoveAbsoluteY)
509            dy = xkbi->mouseKeysDY;
510    }
511    else {
512        dx = xkbi->mouseKeysDX;
513        dy = xkbi->mouseKeysDY;
514    }
515    XkbFakePointerMotion(xkbi->device, xkbi->mouseKeysFlags, dx, dy);
516    return xkbi->desc->ctrls->mk_interval;
517}
518
519static int
520_XkbFilterPointerMove(XkbSrvInfoPtr xkbi,
521                      XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
522{
523    int x, y;
524    Bool accel;
525
526    if (filter->keycode == 0) { /* initial press */
527        filter->keycode = keycode;
528        filter->active = 1;
529        filter->filterOthers = 0;
530        filter->priv = 0;
531        filter->filter = _XkbFilterPointerMove;
532        filter->upAction = *pAction;
533        xkbi->mouseKeysCounter = 0;
534        xkbi->mouseKey = keycode;
535        accel = ((pAction->ptr.flags & XkbSA_NoAcceleration) == 0);
536        x = XkbPtrActionX(&pAction->ptr);
537        y = XkbPtrActionY(&pAction->ptr);
538        XkbFakePointerMotion(xkbi->device, pAction->ptr.flags, x, y);
539        AccessXCancelRepeatKey(xkbi, keycode);
540        xkbi->mouseKeysAccel = accel &&
541            (xkbi->desc->ctrls->enabled_ctrls & XkbMouseKeysAccelMask);
542        xkbi->mouseKeysFlags = pAction->ptr.flags;
543        xkbi->mouseKeysDX = XkbPtrActionX(&pAction->ptr);
544        xkbi->mouseKeysDY = XkbPtrActionY(&pAction->ptr);
545        xkbi->mouseKeyTimer = TimerSet(xkbi->mouseKeyTimer, 0,
546                                       xkbi->desc->ctrls->mk_delay,
547                                       _XkbPtrAccelExpire, (void *) xkbi);
548    }
549    else if (filter->keycode == keycode) {
550        filter->active = 0;
551        if (xkbi->mouseKey == keycode) {
552            xkbi->mouseKey = 0;
553            xkbi->mouseKeyTimer = TimerSet(xkbi->mouseKeyTimer, 0, 0,
554                                           NULL, NULL);
555        }
556    }
557    return 0;
558}
559
560static int
561_XkbFilterPointerBtn(XkbSrvInfoPtr xkbi,
562                     XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
563{
564    if (filter->keycode == 0) { /* initial press */
565        int button = pAction->btn.button;
566
567        if (button == XkbSA_UseDfltButton)
568            button = xkbi->desc->ctrls->mk_dflt_btn;
569
570        filter->keycode = keycode;
571        filter->active = 1;
572        filter->filterOthers = 0;
573        filter->priv = 0;
574        filter->filter = _XkbFilterPointerBtn;
575        filter->upAction = *pAction;
576        filter->upAction.btn.button = button;
577        switch (pAction->type) {
578        case XkbSA_LockPtrBtn:
579            if (((xkbi->lockedPtrButtons & (1 << button)) == 0) &&
580                ((pAction->btn.flags & XkbSA_LockNoLock) == 0)) {
581                xkbi->lockedPtrButtons |= (1 << button);
582                AccessXCancelRepeatKey(xkbi, keycode);
583                XkbFakeDeviceButton(xkbi->device, 1, button);
584                filter->upAction.type = XkbSA_NoAction;
585            }
586            break;
587        case XkbSA_PtrBtn:
588        {
589            register int i, nClicks;
590
591            AccessXCancelRepeatKey(xkbi, keycode);
592            if (pAction->btn.count > 0) {
593                nClicks = pAction->btn.count;
594                for (i = 0; i < nClicks; i++) {
595                    XkbFakeDeviceButton(xkbi->device, 1, button);
596                    XkbFakeDeviceButton(xkbi->device, 0, button);
597                }
598                filter->upAction.type = XkbSA_NoAction;
599            }
600            else
601                XkbFakeDeviceButton(xkbi->device, 1, button);
602        }
603            break;
604        case XkbSA_SetPtrDflt:
605        {
606            XkbControlsPtr ctrls = xkbi->desc->ctrls;
607            XkbControlsRec old;
608            xkbControlsNotify cn;
609
610            old = *ctrls;
611            AccessXCancelRepeatKey(xkbi, keycode);
612            switch (pAction->dflt.affect) {
613            case XkbSA_AffectDfltBtn:
614                if (pAction->dflt.flags & XkbSA_DfltBtnAbsolute)
615                    ctrls->mk_dflt_btn = XkbSAPtrDfltValue(&pAction->dflt);
616                else {
617                    ctrls->mk_dflt_btn += XkbSAPtrDfltValue(&pAction->dflt);
618                    if (ctrls->mk_dflt_btn > 5)
619                        ctrls->mk_dflt_btn = 5;
620                    else if (ctrls->mk_dflt_btn < 1)
621                        ctrls->mk_dflt_btn = 1;
622                }
623                break;
624            default:
625                ErrorF
626                    ("Attempt to change unknown pointer default (%d) ignored\n",
627                     pAction->dflt.affect);
628                break;
629            }
630            if (XkbComputeControlsNotify(xkbi->device,
631                                         &old, xkbi->desc->ctrls, &cn, FALSE)) {
632                cn.keycode = keycode;
633                /* XXX: what about DeviceKeyPress? */
634                cn.eventType = KeyPress;
635                cn.requestMajor = 0;
636                cn.requestMinor = 0;
637                XkbSendControlsNotify(xkbi->device, &cn);
638            }
639        }
640            break;
641        }
642        return 0;
643    }
644    else if (filter->keycode == keycode) {
645        int button = filter->upAction.btn.button;
646
647        switch (filter->upAction.type) {
648        case XkbSA_LockPtrBtn:
649            if (((filter->upAction.btn.flags & XkbSA_LockNoUnlock) != 0) ||
650                ((xkbi->lockedPtrButtons & (1 << button)) == 0)) {
651                break;
652            }
653            xkbi->lockedPtrButtons &= ~(1 << button);
654
655            if (IsMaster(xkbi->device)) {
656                XkbMergeLockedPtrBtns(xkbi->device);
657                /* One SD still has lock set, don't post event */
658                if ((xkbi->lockedPtrButtons & (1 << button)) != 0)
659                    break;
660            }
661
662            /* fallthrough */
663        case XkbSA_PtrBtn:
664            XkbFakeDeviceButton(xkbi->device, 0, button);
665            break;
666        }
667        filter->active = 0;
668        return 0;
669    }
670    return 1;
671}
672
673static int
674_XkbFilterControls(XkbSrvInfoPtr xkbi,
675                   XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
676{
677    XkbControlsRec old;
678    XkbControlsPtr ctrls;
679    DeviceIntPtr kbd;
680    unsigned int change;
681    XkbEventCauseRec cause;
682
683    kbd = xkbi->device;
684    ctrls = xkbi->desc->ctrls;
685    old = *ctrls;
686    if (filter->keycode == 0) { /* initial press */
687        AccessXCancelRepeatKey(xkbi, keycode);
688        filter->keycode = keycode;
689        filter->active = 1;
690        filter->filterOthers = 0;
691        change = XkbActionCtrls(&pAction->ctrls);
692        filter->priv = change;
693        filter->filter = _XkbFilterControls;
694        filter->upAction = *pAction;
695
696        if (pAction->type == XkbSA_LockControls) {
697            filter->priv = (ctrls->enabled_ctrls & change);
698            change &= ~ctrls->enabled_ctrls;
699        }
700
701        if (change) {
702            xkbControlsNotify cn;
703            XkbSrvLedInfoPtr sli;
704
705            ctrls->enabled_ctrls |= change;
706            if (XkbComputeControlsNotify(kbd, &old, ctrls, &cn, FALSE)) {
707                cn.keycode = keycode;
708                /* XXX: what about DeviceKeyPress? */
709                cn.eventType = KeyPress;
710                cn.requestMajor = 0;
711                cn.requestMinor = 0;
712                XkbSendControlsNotify(kbd, &cn);
713            }
714
715            XkbSetCauseKey(&cause, keycode, KeyPress);
716
717            /* If sticky keys were disabled, clear all locks and latches */
718            if ((old.enabled_ctrls & XkbStickyKeysMask) &&
719                (!(ctrls->enabled_ctrls & XkbStickyKeysMask))) {
720                XkbClearAllLatchesAndLocks(kbd, xkbi, FALSE, &cause);
721            }
722            sli = XkbFindSrvLedInfo(kbd, XkbDfltXIClass, XkbDfltXIId, 0);
723            XkbUpdateIndicators(kbd, sli->usesControls, TRUE, NULL, &cause);
724            if (XkbAX_NeedFeedback(ctrls, XkbAX_FeatureFBMask))
725                XkbDDXAccessXBeep(kbd, _BEEP_FEATURE_ON, change);
726        }
727    }
728    else if (filter->keycode == keycode) {
729        change = filter->priv;
730        if (change) {
731            xkbControlsNotify cn;
732            XkbSrvLedInfoPtr sli;
733
734            ctrls->enabled_ctrls &= ~change;
735            if (XkbComputeControlsNotify(kbd, &old, ctrls, &cn, FALSE)) {
736                cn.keycode = keycode;
737                cn.eventType = KeyRelease;
738                cn.requestMajor = 0;
739                cn.requestMinor = 0;
740                XkbSendControlsNotify(kbd, &cn);
741            }
742
743            XkbSetCauseKey(&cause, keycode, KeyRelease);
744            /* If sticky keys were disabled, clear all locks and latches */
745            if ((old.enabled_ctrls & XkbStickyKeysMask) &&
746                (!(ctrls->enabled_ctrls & XkbStickyKeysMask))) {
747                XkbClearAllLatchesAndLocks(kbd, xkbi, FALSE, &cause);
748            }
749            sli = XkbFindSrvLedInfo(kbd, XkbDfltXIClass, XkbDfltXIId, 0);
750            XkbUpdateIndicators(kbd, sli->usesControls, TRUE, NULL, &cause);
751            if (XkbAX_NeedFeedback(ctrls, XkbAX_FeatureFBMask))
752                XkbDDXAccessXBeep(kbd, _BEEP_FEATURE_OFF, change);
753        }
754        filter->keycode = 0;
755        filter->active = 0;
756    }
757    return 1;
758}
759
760static int
761_XkbFilterActionMessage(XkbSrvInfoPtr xkbi,
762                        XkbFilterPtr filter,
763                        unsigned keycode, XkbAction *pAction)
764{
765    XkbMessageAction *pMsg;
766    DeviceIntPtr kbd;
767
768    if ((filter->keycode != 0) && (filter->keycode != keycode))
769	return 1;
770
771    /* This can happen if the key repeats, and the state (modifiers or group)
772       changes meanwhile. */
773    if ((filter->keycode == keycode) && pAction &&
774	(pAction->type != XkbSA_ActionMessage))
775	return 1;
776
777    kbd = xkbi->device;
778    if (filter->keycode == 0) { /* initial press */
779        pMsg = &pAction->msg;
780        if ((pMsg->flags & XkbSA_MessageOnRelease) ||
781            ((pMsg->flags & XkbSA_MessageGenKeyEvent) == 0)) {
782            filter->keycode = keycode;
783            filter->active = 1;
784            filter->filterOthers = 0;
785            filter->priv = 0;
786            filter->filter = _XkbFilterActionMessage;
787            filter->upAction = *pAction;
788        }
789        if (pMsg->flags & XkbSA_MessageOnPress) {
790            xkbActionMessage msg;
791
792            msg.keycode = keycode;
793            msg.press = 1;
794            msg.keyEventFollows =
795                ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
796            memcpy((char *) msg.message, (char *) pMsg->message,
797                   XkbActionMessageLength);
798            XkbSendActionMessage(kbd, &msg);
799        }
800        return ((pAction->msg.flags & XkbSA_MessageGenKeyEvent) != 0);
801    }
802    else if (filter->keycode == keycode) {
803        pMsg = &filter->upAction.msg;
804	if (pAction == NULL) {
805	    if (pMsg->flags & XkbSA_MessageOnRelease) {
806		xkbActionMessage msg;
807
808		msg.keycode = keycode;
809		msg.press = 0;
810		msg.keyEventFollows =
811		    ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
812		memcpy((char *) msg.message, (char *) pMsg->message,
813		       XkbActionMessageLength);
814		XkbSendActionMessage(kbd, &msg);
815	    }
816	    filter->keycode = 0;
817	    filter->active = 0;
818	    return ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
819	} else if (memcmp(pMsg, pAction, 8) == 0) {
820	    /* Repeat: If we send the same message, avoid multiple messages
821	       on release from piling up. */
822	    filter->keycode = 0;
823	    filter->active = 0;
824        }
825    }
826    return 1;
827}
828
829static int
830_XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
831                      XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
832{
833    DeviceEvent ev;
834    int x, y;
835    XkbStateRec old, old_prev;
836    unsigned mods, mask;
837    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
838    ProcessInputProc backupproc;
839
840    if ((filter->keycode != 0) && (filter->keycode != keycode))
841        return 1;
842
843    /* This can happen if the key repeats, and the state (modifiers or group)
844       changes meanwhile. */
845    if ((filter->keycode == keycode) && pAction &&
846	(pAction->type != XkbSA_RedirectKey))
847	return 1;
848
849    /* never actually used uninitialised, but gcc isn't smart enough
850     * to work that out. */
851    memset(&old, 0, sizeof(old));
852    memset(&old_prev, 0, sizeof(old_prev));
853    memset(&ev, 0, sizeof(ev));
854
855    GetSpritePosition(xkbi->device, &x, &y);
856    ev.header = ET_Internal;
857    ev.length = sizeof(DeviceEvent);
858    ev.time = GetTimeInMillis();
859    ev.root_x = x;
860    ev.root_y = y;
861    /* redirect actions do not work across devices, therefore the following is
862     * correct: */
863    ev.deviceid = xkbi->device->id;
864    /* filter->priv must be set up by the caller for the initial press. */
865    ev.sourceid = filter->priv;
866
867    if (filter->keycode == 0) { /* initial press */
868        if ((pAction->redirect.new_key < xkbi->desc->min_key_code) ||
869            (pAction->redirect.new_key > xkbi->desc->max_key_code)) {
870            return 1;
871        }
872        filter->keycode = keycode;
873        filter->active = 1;
874        filter->filterOthers = 0;
875        filter->filter = _XkbFilterRedirectKey;
876        filter->upAction = *pAction;
877
878        ev.type = ET_KeyPress;
879        ev.detail.key = pAction->redirect.new_key;
880
881        mask = XkbSARedirectVModsMask(&pAction->redirect);
882        mods = XkbSARedirectVMods(&pAction->redirect);
883        if (mask)
884            XkbVirtualModsToReal(xkbi->desc, mask, &mask);
885        if (mods)
886            XkbVirtualModsToReal(xkbi->desc, mods, &mods);
887        mask |= pAction->redirect.mods_mask;
888        mods |= pAction->redirect.mods;
889
890        if (mask || mods) {
891            old = xkbi->state;
892            old_prev = xkbi->prev_state;
893            xkbi->state.base_mods &= ~mask;
894            xkbi->state.base_mods |= (mods & mask);
895            xkbi->state.latched_mods &= ~mask;
896            xkbi->state.latched_mods |= (mods & mask);
897            xkbi->state.locked_mods &= ~mask;
898            xkbi->state.locked_mods |= (mods & mask);
899            XkbComputeDerivedState(xkbi);
900            xkbi->prev_state = xkbi->state;
901        }
902
903        UNWRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc);
904        xkbi->device->public.processInputProc((InternalEvent *) &ev,
905                                              xkbi->device);
906        COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc,
907                                     xkbUnwrapProc);
908
909        if (mask || mods) {
910            xkbi->state = old;
911            xkbi->prev_state = old_prev;
912        }
913	return 0;
914    }
915    else {
916	/* If it is a key release, or we redirect to another key, release the
917	   previous new_key.  Otherwise, repeat. */
918	ev.detail.key = filter->upAction.redirect.new_key;
919	if (pAction == NULL ||  ev.detail.key != pAction->redirect.new_key) {
920	    ev.type = ET_KeyRelease;
921	    filter->active = 0;
922	}
923	else {
924	    ev.type = ET_KeyPress;
925	    ev.key_repeat = TRUE;
926	}
927
928	mask = XkbSARedirectVModsMask(&filter->upAction.redirect);
929	mods = XkbSARedirectVMods(&filter->upAction.redirect);
930	if (mask)
931	    XkbVirtualModsToReal(xkbi->desc, mask, &mask);
932	if (mods)
933	    XkbVirtualModsToReal(xkbi->desc, mods, &mods);
934	mask |= filter->upAction.redirect.mods_mask;
935	mods |= filter->upAction.redirect.mods;
936
937	if (mask || mods) {
938	    old = xkbi->state;
939	    old_prev = xkbi->prev_state;
940	    xkbi->state.base_mods &= ~mask;
941	    xkbi->state.base_mods |= (mods & mask);
942	    xkbi->state.latched_mods &= ~mask;
943	    xkbi->state.latched_mods |= (mods & mask);
944	    xkbi->state.locked_mods &= ~mask;
945	    xkbi->state.locked_mods |= (mods & mask);
946	    XkbComputeDerivedState(xkbi);
947	    xkbi->prev_state = xkbi->state;
948	}
949
950	UNWRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc);
951	xkbi->device->public.processInputProc((InternalEvent *) &ev,
952					      xkbi->device);
953	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc,
954				     xkbUnwrapProc);
955
956	if (mask || mods) {
957	    xkbi->state = old;
958	    xkbi->prev_state = old_prev;
959	}
960
961	/* We return 1 in case we have sent a release event because the new_key
962	   has changed.  Then, subsequently, we will call this function again
963	   with the same pAction, which will create the press for the new
964	   new_key. */
965	return (pAction && ev.detail.key != pAction->redirect.new_key);
966    }
967}
968
969static int
970_XkbFilterSwitchScreen(XkbSrvInfoPtr xkbi,
971                       XkbFilterPtr filter,
972                       unsigned keycode, XkbAction *pAction)
973{
974    DeviceIntPtr dev = xkbi->device;
975
976    if (dev == inputInfo.keyboard)
977        return 0;
978
979    if (filter->keycode == 0) { /* initial press */
980        filter->keycode = keycode;
981        filter->active = 1;
982        filter->filterOthers = 0;
983        filter->filter = _XkbFilterSwitchScreen;
984        AccessXCancelRepeatKey(xkbi, keycode);
985        XkbDDXSwitchScreen(dev, keycode, pAction);
986        return 0;
987    }
988    else if (filter->keycode == keycode) {
989        filter->active = 0;
990        return 0;
991    }
992    return 1;
993}
994
995static int
996_XkbFilterXF86Private(XkbSrvInfoPtr xkbi,
997                      XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
998{
999    DeviceIntPtr dev = xkbi->device;
1000
1001    if (dev == inputInfo.keyboard)
1002        return 0;
1003
1004    if (filter->keycode == 0) { /* initial press */
1005        filter->keycode = keycode;
1006        filter->active = 1;
1007        filter->filterOthers = 0;
1008        filter->filter = _XkbFilterXF86Private;
1009        XkbDDXPrivate(dev, keycode, pAction);
1010        return 0;
1011    }
1012    else if (filter->keycode == keycode) {
1013        filter->active = 0;
1014        return 0;
1015    }
1016    return 1;
1017}
1018
1019static int
1020_XkbFilterDeviceBtn(XkbSrvInfoPtr xkbi,
1021                    XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
1022{
1023    if (xkbi->device == inputInfo.keyboard)
1024        return 0;
1025
1026    if (filter->keycode == 0) { /* initial press */
1027        DeviceIntPtr dev;
1028        int button;
1029
1030        _XkbLookupButtonDevice(&dev, pAction->devbtn.device, serverClient,
1031                               DixUnknownAccess, &button);
1032        if (!dev || !dev->public.on)
1033            return 1;
1034
1035        button = pAction->devbtn.button;
1036        if ((button < 1) || (button > dev->button->numButtons))
1037            return 1;
1038
1039        filter->keycode = keycode;
1040        filter->active = 1;
1041        filter->filterOthers = 0;
1042        filter->priv = 0;
1043        filter->filter = _XkbFilterDeviceBtn;
1044        filter->upAction = *pAction;
1045        switch (pAction->type) {
1046        case XkbSA_LockDeviceBtn:
1047            if ((pAction->devbtn.flags & XkbSA_LockNoLock) ||
1048                BitIsOn(dev->button->down, button))
1049                return 0;
1050            XkbFakeDeviceButton(dev, TRUE, button);
1051            filter->upAction.type = XkbSA_NoAction;
1052            break;
1053        case XkbSA_DeviceBtn:
1054            if (pAction->devbtn.count > 0) {
1055                int nClicks, i;
1056
1057                nClicks = pAction->btn.count;
1058                for (i = 0; i < nClicks; i++) {
1059                    XkbFakeDeviceButton(dev, TRUE, button);
1060                    XkbFakeDeviceButton(dev, FALSE, button);
1061                }
1062                filter->upAction.type = XkbSA_NoAction;
1063            }
1064            else
1065                XkbFakeDeviceButton(dev, TRUE, button);
1066            break;
1067        }
1068    }
1069    else if (filter->keycode == keycode) {
1070        DeviceIntPtr dev;
1071        int button;
1072
1073        filter->active = 0;
1074        _XkbLookupButtonDevice(&dev, filter->upAction.devbtn.device,
1075                               serverClient, DixUnknownAccess, &button);
1076        if (!dev || !dev->public.on)
1077            return 1;
1078
1079        button = filter->upAction.btn.button;
1080        switch (filter->upAction.type) {
1081        case XkbSA_LockDeviceBtn:
1082            if ((filter->upAction.devbtn.flags & XkbSA_LockNoUnlock) ||
1083                !BitIsOn(dev->button->down, button))
1084                return 0;
1085            XkbFakeDeviceButton(dev, FALSE, button);
1086            break;
1087        case XkbSA_DeviceBtn:
1088            XkbFakeDeviceButton(dev, FALSE, button);
1089            break;
1090        }
1091        filter->active = 0;
1092    }
1093    return 0;
1094}
1095
1096static XkbFilterPtr
1097_XkbNextFreeFilter(XkbSrvInfoPtr xkbi)
1098{
1099    register int i;
1100
1101    if (xkbi->szFilters == 0) {
1102        xkbi->szFilters = 4;
1103        xkbi->filters = calloc(xkbi->szFilters, sizeof(XkbFilterRec));
1104        /* 6/21/93 (ef) -- XXX! deal with allocation failure */
1105    }
1106    for (i = 0; i < xkbi->szFilters; i++) {
1107        if (!xkbi->filters[i].active) {
1108            xkbi->filters[i].keycode = 0;
1109            return &xkbi->filters[i];
1110        }
1111    }
1112    xkbi->szFilters *= 2;
1113    xkbi->filters = reallocarray(xkbi->filters,
1114                                 xkbi->szFilters, sizeof(XkbFilterRec));
1115    /* 6/21/93 (ef) -- XXX! deal with allocation failure */
1116    memset(&xkbi->filters[xkbi->szFilters / 2], 0,
1117           (xkbi->szFilters / 2) * sizeof(XkbFilterRec));
1118    return &xkbi->filters[xkbi->szFilters / 2];
1119}
1120
1121static int
1122_XkbApplyFilters(XkbSrvInfoPtr xkbi, unsigned kc, XkbAction *pAction)
1123{
1124    register int i, send;
1125
1126    send = 1;
1127    for (i = 0; i < xkbi->szFilters; i++) {
1128        if ((xkbi->filters[i].active) && (xkbi->filters[i].filter))
1129            send =
1130                ((*xkbi->filters[i].filter) (xkbi, &xkbi->filters[i], kc,
1131                                             pAction)
1132                 && send);
1133    }
1134    return send;
1135}
1136
1137static int
1138_XkbEnsureStateChange(XkbSrvInfoPtr xkbi)
1139{
1140    Bool genStateNotify = FALSE;
1141
1142    /* The state may change, so if we're not in the middle of sending a state
1143     * notify, prepare for it */
1144    if ((xkbi->flags & _XkbStateNotifyInProgress) == 0) {
1145        xkbi->prev_state = xkbi->state;
1146        xkbi->flags |= _XkbStateNotifyInProgress;
1147        genStateNotify = TRUE;
1148    }
1149
1150    return genStateNotify;
1151}
1152
1153static void
1154_XkbApplyState(DeviceIntPtr dev, Bool genStateNotify, int evtype, int key)
1155{
1156    XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
1157    int changed;
1158
1159    XkbComputeDerivedState(xkbi);
1160
1161    changed = XkbStateChangedFlags(&xkbi->prev_state, &xkbi->state);
1162    if (genStateNotify) {
1163        if (changed) {
1164            xkbStateNotify sn;
1165
1166            sn.keycode = key;
1167            sn.eventType = evtype;
1168            sn.requestMajor = sn.requestMinor = 0;
1169            sn.changed = changed;
1170            XkbSendStateNotify(dev, &sn);
1171        }
1172        xkbi->flags &= ~_XkbStateNotifyInProgress;
1173    }
1174
1175    changed = XkbIndicatorsToUpdate(dev, changed, FALSE);
1176    if (changed) {
1177        XkbEventCauseRec cause;
1178        XkbSetCauseKey(&cause, key, evtype);
1179        XkbUpdateIndicators(dev, changed, FALSE, NULL, &cause);
1180    }
1181}
1182
1183void
1184XkbPushLockedStateToSlaves(DeviceIntPtr master, int evtype, int key)
1185{
1186    DeviceIntPtr dev;
1187    Bool genStateNotify;
1188
1189    nt_list_for_each_entry(dev, inputInfo.devices, next) {
1190        if (!dev->key || GetMaster(dev, MASTER_KEYBOARD) != master)
1191            continue;
1192
1193        genStateNotify = _XkbEnsureStateChange(dev->key->xkbInfo);
1194
1195        dev->key->xkbInfo->state.locked_mods =
1196            master->key->xkbInfo->state.locked_mods;
1197
1198        _XkbApplyState(dev, genStateNotify, evtype, key);
1199    }
1200}
1201
1202void
1203XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
1204{
1205    int key, bit, i;
1206    XkbSrvInfoPtr xkbi;
1207    KeyClassPtr keyc;
1208    int sendEvent;
1209    Bool genStateNotify;
1210    XkbAction act;
1211    XkbFilterPtr filter;
1212    Bool keyEvent;
1213    Bool pressEvent;
1214    ProcessInputProc backupproc;
1215
1216    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
1217
1218    keyc = kbd->key;
1219    xkbi = keyc->xkbInfo;
1220    key = event->detail.key;
1221
1222    genStateNotify = _XkbEnsureStateChange(xkbi);
1223
1224    xkbi->clearMods = xkbi->setMods = 0;
1225    xkbi->groupChange = 0;
1226
1227    sendEvent = 1;
1228    keyEvent = ((event->type == ET_KeyPress) || (event->type == ET_KeyRelease));
1229    pressEvent = ((event->type == ET_KeyPress) ||
1230                  (event->type == ET_ButtonPress));
1231
1232    if (pressEvent) {
1233        if (keyEvent)
1234            act = XkbGetKeyAction(xkbi, &xkbi->state, key);
1235        else {
1236            act = XkbGetButtonAction(kbd, dev, key);
1237            key |= BTN_ACT_FLAG;
1238        }
1239        sendEvent = _XkbApplyFilters(xkbi, key, &act);
1240        if (sendEvent) {
1241            switch (act.type) {
1242            case XkbSA_SetMods:
1243            case XkbSA_SetGroup:
1244                filter = _XkbNextFreeFilter(xkbi);
1245                sendEvent = _XkbFilterSetState(xkbi, filter, key, &act);
1246                break;
1247            case XkbSA_LatchMods:
1248            case XkbSA_LatchGroup:
1249                filter = _XkbNextFreeFilter(xkbi);
1250                sendEvent = _XkbFilterLatchState(xkbi, filter, key, &act);
1251                break;
1252            case XkbSA_LockMods:
1253            case XkbSA_LockGroup:
1254                filter = _XkbNextFreeFilter(xkbi);
1255                sendEvent = _XkbFilterLockState(xkbi, filter, key, &act);
1256                break;
1257            case XkbSA_ISOLock:
1258                filter = _XkbNextFreeFilter(xkbi);
1259                sendEvent = _XkbFilterISOLock(xkbi, filter, key, &act);
1260                break;
1261            case XkbSA_MovePtr:
1262                filter = _XkbNextFreeFilter(xkbi);
1263                sendEvent = _XkbFilterPointerMove(xkbi, filter, key, &act);
1264                break;
1265            case XkbSA_PtrBtn:
1266            case XkbSA_LockPtrBtn:
1267            case XkbSA_SetPtrDflt:
1268                filter = _XkbNextFreeFilter(xkbi);
1269                sendEvent = _XkbFilterPointerBtn(xkbi, filter, key, &act);
1270                break;
1271            case XkbSA_Terminate:
1272                sendEvent = XkbDDXTerminateServer(dev, key, &act);
1273                break;
1274            case XkbSA_SwitchScreen:
1275                filter = _XkbNextFreeFilter(xkbi);
1276                sendEvent = _XkbFilterSwitchScreen(xkbi, filter, key, &act);
1277                break;
1278            case XkbSA_SetControls:
1279            case XkbSA_LockControls:
1280                filter = _XkbNextFreeFilter(xkbi);
1281                sendEvent = _XkbFilterControls(xkbi, filter, key, &act);
1282                break;
1283            case XkbSA_ActionMessage:
1284                filter = _XkbNextFreeFilter(xkbi);
1285                sendEvent = _XkbFilterActionMessage(xkbi, filter, key, &act);
1286                break;
1287            case XkbSA_RedirectKey:
1288                filter = _XkbNextFreeFilter(xkbi);
1289                /* redirect actions must create a new DeviceEvent.  The
1290                 * source device id for this event cannot be obtained from
1291                 * xkbi, so we pass it here explicitly. The field deviceid
1292                 * equals to xkbi->device->id. */
1293                filter->priv = event->sourceid;
1294                sendEvent = _XkbFilterRedirectKey(xkbi, filter, key, &act);
1295                break;
1296            case XkbSA_DeviceBtn:
1297            case XkbSA_LockDeviceBtn:
1298                filter = _XkbNextFreeFilter(xkbi);
1299                sendEvent = _XkbFilterDeviceBtn(xkbi, filter, key, &act);
1300                break;
1301            case XkbSA_XFree86Private:
1302                filter = _XkbNextFreeFilter(xkbi);
1303                sendEvent = _XkbFilterXF86Private(xkbi, filter, key, &act);
1304                break;
1305            }
1306        }
1307    }
1308    else {
1309        if (!keyEvent)
1310            key |= BTN_ACT_FLAG;
1311        sendEvent = _XkbApplyFilters(xkbi, key, NULL);
1312    }
1313
1314    if (xkbi->groupChange != 0)
1315        xkbi->state.base_group += xkbi->groupChange;
1316    if (xkbi->setMods) {
1317        for (i = 0, bit = 1; xkbi->setMods; i++, bit <<= 1) {
1318            if (xkbi->setMods & bit) {
1319                keyc->modifierKeyCount[i]++;
1320                xkbi->state.base_mods |= bit;
1321                xkbi->setMods &= ~bit;
1322            }
1323        }
1324    }
1325    if (xkbi->clearMods) {
1326        for (i = 0, bit = 1; xkbi->clearMods; i++, bit <<= 1) {
1327            if (xkbi->clearMods & bit) {
1328                keyc->modifierKeyCount[i]--;
1329                if (keyc->modifierKeyCount[i] <= 0) {
1330                    xkbi->state.base_mods &= ~bit;
1331                    keyc->modifierKeyCount[i] = 0;
1332                }
1333                xkbi->clearMods &= ~bit;
1334            }
1335        }
1336    }
1337
1338    if (sendEvent) {
1339        DeviceIntPtr tmpdev;
1340
1341        if (keyEvent)
1342            tmpdev = dev;
1343        else
1344            tmpdev = GetMaster(dev, POINTER_OR_FLOAT);
1345
1346        UNWRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr, backupproc);
1347        dev->public.processInputProc((InternalEvent *) event, tmpdev);
1348        COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr,
1349                                     backupproc, xkbUnwrapProc);
1350    }
1351    else if (keyEvent) {
1352        FixKeyState(event, dev);
1353    }
1354
1355    _XkbApplyState(dev, genStateNotify, event->type, key);
1356    XkbPushLockedStateToSlaves(dev, event->type, key);
1357}
1358
1359int
1360XkbLatchModifiers(DeviceIntPtr pXDev, CARD8 mask, CARD8 latches)
1361{
1362    XkbSrvInfoPtr xkbi;
1363    XkbFilterPtr filter;
1364    XkbAction act;
1365    unsigned clear;
1366
1367    if (pXDev && pXDev->key && pXDev->key->xkbInfo) {
1368        xkbi = pXDev->key->xkbInfo;
1369        clear = (mask & (~latches));
1370        xkbi->state.latched_mods &= ~clear;
1371        /* Clear any pending latch to locks.
1372         */
1373        act.type = XkbSA_NoAction;
1374        _XkbApplyFilters(xkbi, SYNTHETIC_KEYCODE, &act);
1375        act.type = XkbSA_LatchMods;
1376        act.mods.flags = 0;
1377        act.mods.mask = mask & latches;
1378        filter = _XkbNextFreeFilter(xkbi);
1379        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE, &act);
1380        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE,
1381                             (XkbAction *) NULL);
1382        return Success;
1383    }
1384    return BadValue;
1385}
1386
1387int
1388XkbLatchGroup(DeviceIntPtr pXDev, int group)
1389{
1390    XkbSrvInfoPtr xkbi;
1391    XkbFilterPtr filter;
1392    XkbAction act;
1393
1394    if (pXDev && pXDev->key && pXDev->key->xkbInfo) {
1395        xkbi = pXDev->key->xkbInfo;
1396        act.type = XkbSA_LatchGroup;
1397        act.group.flags = 0;
1398        XkbSASetGroup(&act.group, group);
1399        filter = _XkbNextFreeFilter(xkbi);
1400        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE, &act);
1401        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE,
1402                             (XkbAction *) NULL);
1403        return Success;
1404    }
1405    return BadValue;
1406}
1407
1408/***====================================================================***/
1409
1410void
1411XkbClearAllLatchesAndLocks(DeviceIntPtr dev,
1412                           XkbSrvInfoPtr xkbi,
1413                           Bool genEv, XkbEventCausePtr cause)
1414{
1415    XkbStateRec os;
1416    xkbStateNotify sn;
1417
1418    sn.changed = 0;
1419    os = xkbi->state;
1420    if (os.latched_mods) {      /* clear all latches */
1421        XkbLatchModifiers(dev, ~0, 0);
1422        sn.changed |= XkbModifierLatchMask;
1423    }
1424    if (os.latched_group) {
1425        XkbLatchGroup(dev, 0);
1426        sn.changed |= XkbGroupLatchMask;
1427    }
1428    if (os.locked_mods) {
1429        xkbi->state.locked_mods = 0;
1430        sn.changed |= XkbModifierLockMask;
1431    }
1432    if (os.locked_group) {
1433        xkbi->state.locked_group = 0;
1434        sn.changed |= XkbGroupLockMask;
1435    }
1436    if (genEv && sn.changed) {
1437        CARD32 changed;
1438
1439        XkbComputeDerivedState(xkbi);
1440        sn.keycode = cause->kc;
1441        sn.eventType = cause->event;
1442        sn.requestMajor = cause->mjr;
1443        sn.requestMinor = cause->mnr;
1444        sn.changed = XkbStateChangedFlags(&os, &xkbi->state);
1445        XkbSendStateNotify(dev, &sn);
1446        changed = XkbIndicatorsToUpdate(dev, sn.changed, FALSE);
1447        if (changed) {
1448            XkbUpdateIndicators(dev, changed, TRUE, NULL, cause);
1449        }
1450    }
1451    return;
1452}
1453
1454/*
1455 * The event is injected into the event processing, not the EQ. Thus,
1456 * ensure that we restore the master after the event sequence to the
1457 * original set of classes. Otherwise, the master remains on the XTEST
1458 * classes and drops events that don't fit into the XTEST layout (e.g.
1459 * events with more than 2 valuators).
1460 *
1461 * FIXME: EQ injection in the processing stage is not designed for, so this
1462 * is a rather awkward hack. The event list returned by GetPointerEvents()
1463 * and friends is always prefixed with a DCE if the last _posted_ device was
1464 * different. For normal events, this sequence then resets the master during
1465 * the processing stage. Since we inject the PointerKey events in the
1466 * processing stage though, we need to manually reset to restore the
1467 * previous order, because the events already in the EQ must be sent for the
1468 * right device.
1469 * So we post-fix the event list we get from GPE with a DCE back to the
1470 * previous slave device.
1471 *
1472 * First one on drinking island wins!
1473 */
1474static void
1475InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags,
1476                       ValuatorMask *mask)
1477{
1478    ScreenPtr pScreen;
1479    InternalEvent *events;
1480    int nevents, i;
1481    DeviceIntPtr ptr, mpointer, lastSlave = NULL;
1482    Bool saveWait;
1483
1484    if (IsMaster(dev)) {
1485        mpointer = GetMaster(dev, MASTER_POINTER);
1486        lastSlave = mpointer->lastSlave;
1487        ptr = GetXTestDevice(mpointer);
1488    }
1489    else if (IsFloating(dev))
1490        ptr = dev;
1491    else
1492        return;
1493
1494    events = InitEventList(GetMaximumEventsNum() + 1);
1495    OsBlockSignals();
1496    pScreen = miPointerGetScreen(ptr);
1497    saveWait = miPointerSetWaitForUpdate(pScreen, FALSE);
1498    nevents = GetPointerEvents(events, ptr, type, button, flags, mask);
1499    if (IsMaster(dev) && (lastSlave && lastSlave != ptr))
1500        UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT,
1501                         &nevents);
1502    miPointerSetWaitForUpdate(pScreen, saveWait);
1503    OsReleaseSignals();
1504
1505    for (i = 0; i < nevents; i++)
1506        mieqProcessDeviceEvent(ptr, &events[i], NULL);
1507
1508    FreeEventList(events, GetMaximumEventsNum());
1509
1510}
1511
1512static void
1513XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags, int x, int y)
1514{
1515    ValuatorMask mask;
1516    int gpe_flags = 0;
1517
1518    /* ignore attached SDs */
1519    if (!IsMaster(dev) && !IsFloating(dev))
1520        return;
1521
1522    if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
1523        gpe_flags = POINTER_ABSOLUTE;
1524    else
1525        gpe_flags = POINTER_RELATIVE;
1526
1527    valuator_mask_set_range(&mask, 0, 2, (int[]) {
1528                            x, y});
1529
1530    InjectPointerKeyEvents(dev, MotionNotify, 0, gpe_flags, &mask);
1531}
1532
1533void
1534XkbFakeDeviceButton(DeviceIntPtr dev, Bool press, int button)
1535{
1536    DeviceIntPtr ptr;
1537    int down;
1538
1539    /* If dev is a slave device, and the SD is attached, do nothing. If we'd
1540     * post through the attached master pointer we'd get duplicate events.
1541     *
1542     * if dev is a master keyboard, post through the XTEST device
1543     *
1544     * if dev is a floating slave, post through the device itself.
1545     */
1546
1547    if (IsMaster(dev)) {
1548        DeviceIntPtr mpointer = GetMaster(dev, MASTER_POINTER);
1549
1550        ptr = GetXTestDevice(mpointer);
1551    }
1552    else if (IsFloating(dev))
1553        ptr = dev;
1554    else
1555        return;
1556
1557    down = button_is_down(ptr, button, BUTTON_PROCESSED);
1558    if (press == down)
1559        return;
1560
1561    InjectPointerKeyEvents(dev, press ? ButtonPress : ButtonRelease,
1562                           button, 0, NULL);
1563}
1564