xkbActions.c revision 1b5d61b8
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
1202static void
1203XkbActionGetFilter(DeviceIntPtr dev, DeviceEvent *event, KeyCode key,
1204                   XkbAction *act, int *sendEvent)
1205{
1206    XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
1207    XkbFilterPtr filter;
1208
1209    /* For focus events, we only want to run actions which update our state to
1210     * (hopefully vaguely kinda) match that of the host server, rather than
1211     * actually execute anything. For example, if we enter our VT with
1212     * Ctrl+Alt+Backspace held down, we don't want to terminate our server
1213     * immediately, but we _do_ want Ctrl+Alt to be latched down, so if
1214     * Backspace is released and then pressed again, the server will terminate.
1215     *
1216     * This is pretty flaky, and we should in fact inherit the complete state
1217     * from the host server. There are some state combinations that we cannot
1218     * express by running the state machine over every key, e.g. if AltGr+Shift
1219     * generates a different state to Shift+AltGr. */
1220    if (event->source_type == EVENT_SOURCE_FOCUS) {
1221        switch (act->type) {
1222        case XkbSA_SetMods:
1223        case XkbSA_SetGroup:
1224        case XkbSA_LatchMods:
1225        case XkbSA_LatchGroup:
1226        case XkbSA_LockMods:
1227        case XkbSA_LockGroup:
1228            break;
1229        default:
1230            *sendEvent = 1;
1231            return;
1232        }
1233    }
1234
1235    switch (act->type) {
1236    case XkbSA_SetMods:
1237    case XkbSA_SetGroup:
1238        filter = _XkbNextFreeFilter(xkbi);
1239        *sendEvent = _XkbFilterSetState(xkbi, filter, key, act);
1240        break;
1241    case XkbSA_LatchMods:
1242    case XkbSA_LatchGroup:
1243        filter = _XkbNextFreeFilter(xkbi);
1244        *sendEvent = _XkbFilterLatchState(xkbi, filter, key, act);
1245        break;
1246    case XkbSA_LockMods:
1247    case XkbSA_LockGroup:
1248        filter = _XkbNextFreeFilter(xkbi);
1249        *sendEvent = _XkbFilterLockState(xkbi, filter, key, act);
1250        break;
1251    case XkbSA_ISOLock:
1252        filter = _XkbNextFreeFilter(xkbi);
1253        *sendEvent = _XkbFilterISOLock(xkbi, filter, key, act);
1254        break;
1255    case XkbSA_MovePtr:
1256        filter = _XkbNextFreeFilter(xkbi);
1257        *sendEvent = _XkbFilterPointerMove(xkbi, filter, key, act);
1258        break;
1259    case XkbSA_PtrBtn:
1260    case XkbSA_LockPtrBtn:
1261    case XkbSA_SetPtrDflt:
1262        filter = _XkbNextFreeFilter(xkbi);
1263        *sendEvent = _XkbFilterPointerBtn(xkbi, filter, key, act);
1264        break;
1265    case XkbSA_Terminate:
1266        *sendEvent = XkbDDXTerminateServer(dev, key, act);
1267        break;
1268    case XkbSA_SwitchScreen:
1269        filter = _XkbNextFreeFilter(xkbi);
1270        *sendEvent = _XkbFilterSwitchScreen(xkbi, filter, key, act);
1271        break;
1272    case XkbSA_SetControls:
1273    case XkbSA_LockControls:
1274        filter = _XkbNextFreeFilter(xkbi);
1275        *sendEvent = _XkbFilterControls(xkbi, filter, key, act);
1276        break;
1277    case XkbSA_ActionMessage:
1278        filter = _XkbNextFreeFilter(xkbi);
1279        *sendEvent = _XkbFilterActionMessage(xkbi, filter, key, act);
1280        break;
1281    case XkbSA_RedirectKey:
1282        filter = _XkbNextFreeFilter(xkbi);
1283        /* redirect actions must create a new DeviceEvent.  The
1284         * source device id for this event cannot be obtained from
1285         * xkbi, so we pass it here explicitly. The field deviceid
1286         * equals to xkbi->device->id. */
1287        filter->priv = event->sourceid;
1288        *sendEvent = _XkbFilterRedirectKey(xkbi, filter, key, act);
1289        break;
1290    case XkbSA_DeviceBtn:
1291    case XkbSA_LockDeviceBtn:
1292        filter = _XkbNextFreeFilter(xkbi);
1293        *sendEvent = _XkbFilterDeviceBtn(xkbi, filter, key, act);
1294        break;
1295    case XkbSA_XFree86Private:
1296        filter = _XkbNextFreeFilter(xkbi);
1297        *sendEvent = _XkbFilterXF86Private(xkbi, filter, key, act);
1298        break;
1299    }
1300}
1301
1302void
1303XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
1304{
1305    int key, bit, i;
1306    XkbSrvInfoPtr xkbi;
1307    KeyClassPtr keyc;
1308    int sendEvent;
1309    Bool genStateNotify;
1310    XkbAction act;
1311    Bool keyEvent;
1312    Bool pressEvent;
1313    ProcessInputProc backupproc;
1314
1315    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
1316
1317    keyc = kbd->key;
1318    xkbi = keyc->xkbInfo;
1319    key = event->detail.key;
1320
1321    genStateNotify = _XkbEnsureStateChange(xkbi);
1322
1323    xkbi->clearMods = xkbi->setMods = 0;
1324    xkbi->groupChange = 0;
1325
1326    sendEvent = 1;
1327    keyEvent = ((event->type == ET_KeyPress) || (event->type == ET_KeyRelease));
1328    pressEvent = ((event->type == ET_KeyPress) ||
1329                  (event->type == ET_ButtonPress));
1330
1331    if (pressEvent) {
1332        if (keyEvent)
1333            act = XkbGetKeyAction(xkbi, &xkbi->state, key);
1334        else {
1335            act = XkbGetButtonAction(kbd, dev, key);
1336            key |= BTN_ACT_FLAG;
1337        }
1338
1339        sendEvent = _XkbApplyFilters(xkbi, key, &act);
1340        if (sendEvent)
1341            XkbActionGetFilter(dev, event, key, &act, &sendEvent);
1342    }
1343    else {
1344        if (!keyEvent)
1345            key |= BTN_ACT_FLAG;
1346        sendEvent = _XkbApplyFilters(xkbi, key, NULL);
1347    }
1348
1349    if (xkbi->groupChange != 0)
1350        xkbi->state.base_group += xkbi->groupChange;
1351    if (xkbi->setMods) {
1352        for (i = 0, bit = 1; xkbi->setMods; i++, bit <<= 1) {
1353            if (xkbi->setMods & bit) {
1354                keyc->modifierKeyCount[i]++;
1355                xkbi->state.base_mods |= bit;
1356                xkbi->setMods &= ~bit;
1357            }
1358        }
1359    }
1360    if (xkbi->clearMods) {
1361        for (i = 0, bit = 1; xkbi->clearMods; i++, bit <<= 1) {
1362            if (xkbi->clearMods & bit) {
1363                keyc->modifierKeyCount[i]--;
1364                if (keyc->modifierKeyCount[i] <= 0) {
1365                    xkbi->state.base_mods &= ~bit;
1366                    keyc->modifierKeyCount[i] = 0;
1367                }
1368                xkbi->clearMods &= ~bit;
1369            }
1370        }
1371    }
1372
1373    if (sendEvent) {
1374        DeviceIntPtr tmpdev;
1375
1376        if (keyEvent)
1377            tmpdev = dev;
1378        else
1379            tmpdev = GetMaster(dev, POINTER_OR_FLOAT);
1380
1381        UNWRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr, backupproc);
1382        dev->public.processInputProc((InternalEvent *) event, tmpdev);
1383        COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr,
1384                                     backupproc, xkbUnwrapProc);
1385    }
1386    else if (keyEvent) {
1387        FixKeyState(event, dev);
1388    }
1389
1390    _XkbApplyState(dev, genStateNotify, event->type, key);
1391    XkbPushLockedStateToSlaves(dev, event->type, key);
1392}
1393
1394int
1395XkbLatchModifiers(DeviceIntPtr pXDev, CARD8 mask, CARD8 latches)
1396{
1397    XkbSrvInfoPtr xkbi;
1398    XkbFilterPtr filter;
1399    XkbAction act;
1400    unsigned clear;
1401
1402    if (pXDev && pXDev->key && pXDev->key->xkbInfo) {
1403        xkbi = pXDev->key->xkbInfo;
1404        clear = (mask & (~latches));
1405        xkbi->state.latched_mods &= ~clear;
1406        /* Clear any pending latch to locks.
1407         */
1408        act.type = XkbSA_NoAction;
1409        _XkbApplyFilters(xkbi, SYNTHETIC_KEYCODE, &act);
1410        act.type = XkbSA_LatchMods;
1411        act.mods.flags = 0;
1412        act.mods.mask = mask & latches;
1413        filter = _XkbNextFreeFilter(xkbi);
1414        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE, &act);
1415        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE,
1416                             (XkbAction *) NULL);
1417        return Success;
1418    }
1419    return BadValue;
1420}
1421
1422int
1423XkbLatchGroup(DeviceIntPtr pXDev, int group)
1424{
1425    XkbSrvInfoPtr xkbi;
1426    XkbFilterPtr filter;
1427    XkbAction act;
1428
1429    if (pXDev && pXDev->key && pXDev->key->xkbInfo) {
1430        xkbi = pXDev->key->xkbInfo;
1431        act.type = XkbSA_LatchGroup;
1432        act.group.flags = 0;
1433        XkbSASetGroup(&act.group, group);
1434        filter = _XkbNextFreeFilter(xkbi);
1435        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE, &act);
1436        _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE,
1437                             (XkbAction *) NULL);
1438        return Success;
1439    }
1440    return BadValue;
1441}
1442
1443/***====================================================================***/
1444
1445void
1446XkbClearAllLatchesAndLocks(DeviceIntPtr dev,
1447                           XkbSrvInfoPtr xkbi,
1448                           Bool genEv, XkbEventCausePtr cause)
1449{
1450    XkbStateRec os;
1451    xkbStateNotify sn;
1452
1453    sn.changed = 0;
1454    os = xkbi->state;
1455    if (os.latched_mods) {      /* clear all latches */
1456        XkbLatchModifiers(dev, ~0, 0);
1457        sn.changed |= XkbModifierLatchMask;
1458    }
1459    if (os.latched_group) {
1460        XkbLatchGroup(dev, 0);
1461        sn.changed |= XkbGroupLatchMask;
1462    }
1463    if (os.locked_mods) {
1464        xkbi->state.locked_mods = 0;
1465        sn.changed |= XkbModifierLockMask;
1466    }
1467    if (os.locked_group) {
1468        xkbi->state.locked_group = 0;
1469        sn.changed |= XkbGroupLockMask;
1470    }
1471    if (genEv && sn.changed) {
1472        CARD32 changed;
1473
1474        XkbComputeDerivedState(xkbi);
1475        sn.keycode = cause->kc;
1476        sn.eventType = cause->event;
1477        sn.requestMajor = cause->mjr;
1478        sn.requestMinor = cause->mnr;
1479        sn.changed = XkbStateChangedFlags(&os, &xkbi->state);
1480        XkbSendStateNotify(dev, &sn);
1481        changed = XkbIndicatorsToUpdate(dev, sn.changed, FALSE);
1482        if (changed) {
1483            XkbUpdateIndicators(dev, changed, TRUE, NULL, cause);
1484        }
1485    }
1486    return;
1487}
1488
1489/*
1490 * The event is injected into the event processing, not the EQ. Thus,
1491 * ensure that we restore the master after the event sequence to the
1492 * original set of classes. Otherwise, the master remains on the XTEST
1493 * classes and drops events that don't fit into the XTEST layout (e.g.
1494 * events with more than 2 valuators).
1495 *
1496 * FIXME: EQ injection in the processing stage is not designed for, so this
1497 * is a rather awkward hack. The event list returned by GetPointerEvents()
1498 * and friends is always prefixed with a DCE if the last _posted_ device was
1499 * different. For normal events, this sequence then resets the master during
1500 * the processing stage. Since we inject the PointerKey events in the
1501 * processing stage though, we need to manually reset to restore the
1502 * previous order, because the events already in the EQ must be sent for the
1503 * right device.
1504 * So we post-fix the event list we get from GPE with a DCE back to the
1505 * previous slave device.
1506 *
1507 * First one on drinking island wins!
1508 */
1509static void
1510InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags,
1511                       ValuatorMask *mask)
1512{
1513    ScreenPtr pScreen;
1514    InternalEvent *events;
1515    int nevents, i;
1516    DeviceIntPtr ptr, mpointer, lastSlave = NULL;
1517    Bool saveWait;
1518
1519    if (IsMaster(dev)) {
1520        mpointer = GetMaster(dev, MASTER_POINTER);
1521        lastSlave = mpointer->lastSlave;
1522        ptr = GetXTestDevice(mpointer);
1523    }
1524    else if (IsFloating(dev))
1525        ptr = dev;
1526    else
1527        return;
1528
1529    events = InitEventList(GetMaximumEventsNum() + 1);
1530    input_lock();
1531    pScreen = miPointerGetScreen(ptr);
1532    saveWait = miPointerSetWaitForUpdate(pScreen, FALSE);
1533    nevents = GetPointerEvents(events, ptr, type, button, flags, mask);
1534    if (IsMaster(dev) && (lastSlave && lastSlave != ptr))
1535        UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT,
1536                         &nevents);
1537    miPointerSetWaitForUpdate(pScreen, saveWait);
1538
1539    for (i = 0; i < nevents; i++)
1540        mieqProcessDeviceEvent(ptr, &events[i], NULL);
1541    input_unlock();
1542
1543    FreeEventList(events, GetMaximumEventsNum());
1544}
1545
1546static void
1547XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags, int x, int y)
1548{
1549    ValuatorMask mask;
1550    int gpe_flags = 0;
1551
1552    /* ignore attached SDs */
1553    if (!IsMaster(dev) && !IsFloating(dev))
1554        return;
1555
1556    if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
1557        gpe_flags = POINTER_ABSOLUTE;
1558    else
1559        gpe_flags = POINTER_RELATIVE;
1560
1561    valuator_mask_set_range(&mask, 0, 2, (int[]) {
1562                            x, y});
1563
1564    InjectPointerKeyEvents(dev, MotionNotify, 0, gpe_flags, &mask);
1565}
1566
1567void
1568XkbFakeDeviceButton(DeviceIntPtr dev, Bool press, int button)
1569{
1570    DeviceIntPtr ptr;
1571    int down;
1572
1573    /* If dev is a slave device, and the SD is attached, do nothing. If we'd
1574     * post through the attached master pointer we'd get duplicate events.
1575     *
1576     * if dev is a master keyboard, post through the XTEST device
1577     *
1578     * if dev is a floating slave, post through the device itself.
1579     */
1580
1581    if (IsMaster(dev)) {
1582        DeviceIntPtr mpointer = GetMaster(dev, MASTER_POINTER);
1583
1584        ptr = GetXTestDevice(mpointer);
1585    }
1586    else if (IsFloating(dev))
1587        ptr = dev;
1588    else
1589        return;
1590
1591    down = button_is_down(ptr, button, BUTTON_PROCESSED);
1592    if (press == down)
1593        return;
1594
1595    InjectPointerKeyEvents(dev, press ? ButtonPress : ButtonRelease,
1596                           button, 0, NULL);
1597}
1598