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