Merge remote branch 'jeremyhu/master'
[gstreamer-omap:xserver.git] / Xi / exevents.c
1 /************************************************************
2
3 Copyright 1989, 1998  The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24
25 Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
26
27                         All Rights Reserved
28
29 Permission to use, copy, modify, and distribute this software and its
30 documentation for any purpose and without fee is hereby granted,
31 provided that the above copyright notice appear in all copies and that
32 both that copyright notice and this permission notice appear in
33 supporting documentation, and that the name of Hewlett-Packard not be
34 used in advertising or publicity pertaining to distribution of the
35 software without specific, written prior permission.
36
37 HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39 HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43 SOFTWARE.
44
45 ********************************************************/
46
47 /********************************************************************
48  *
49  *  Routines to register and initialize extension input devices.
50  *  This also contains ProcessOtherEvent, the routine called from DDX
51  *  to route extension events.
52  *
53  */
54
55 #ifdef HAVE_DIX_CONFIG_H
56 #include <dix-config.h>
57 #endif
58
59 #include "inputstr.h"
60 #include <X11/X.h>
61 #include <X11/Xproto.h>
62 #include <X11/extensions/XI.h>
63 #include <X11/extensions/XIproto.h>
64 #include <X11/extensions/XI2proto.h>
65 #include <X11/extensions/geproto.h>
66 #include "windowstr.h"
67 #include "miscstruct.h"
68 #include "region.h"
69 #include "exevents.h"
70 #include "extnsionst.h"
71 #include "exglobals.h"
72 #include "dixevents.h"  /* DeliverFocusedEvent */
73 #include "dixgrabs.h"   /* CreateGrab() */
74 #include "scrnintstr.h"
75 #include "listdev.h" /* for CopySwapXXXClass */
76 #include "xace.h"
77 #include "xiquerydevice.h" /* For List*Info */
78 #include "eventconvert.h"
79 #include "eventstr.h"
80
81 #include <X11/extensions/XKBproto.h>
82 #include "xkbsrv.h"
83
84 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
85 #define AllModifiersMask ( \
86         ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
87         Mod3Mask | Mod4Mask | Mod5Mask )
88 #define AllButtonsMask ( \
89         Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
90
91 Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
92                                  Bool   /* ignoreSelectedEvents */
93     );
94 static Bool MakeInputMasks(WindowPtr    /* pWin */
95     );
96
97 /*
98  * Only let the given client know of core events which will affect its
99  * interpretation of input events, if the client's ClientPointer (or the
100  * paired keyboard) is the current device.
101  */
102 int
103 XIShouldNotify(ClientPtr client, DeviceIntPtr dev)
104 {
105     DeviceIntPtr current_ptr = PickPointer(client);
106     DeviceIntPtr current_kbd = GetPairedDevice(current_ptr);
107
108     if (dev == current_kbd || dev == current_ptr)
109         return 1;
110
111     return 0;
112 }
113
114 void
115 RegisterOtherDevice(DeviceIntPtr device)
116 {
117     device->public.processInputProc = ProcessOtherEvent;
118     device->public.realInputProc = ProcessOtherEvent;
119 }
120
121 Bool
122 IsPointerEvent(InternalEvent* event)
123 {
124     switch(event->any.type)
125     {
126         case ET_ButtonPress:
127         case ET_ButtonRelease:
128         case ET_Motion:
129             /* XXX: enter/leave ?? */
130             return TRUE;
131         default:
132             break;
133     }
134     return FALSE;
135 }
136
137 /**
138  * @return the device matching the deviceid of the device set in the event, or
139  * NULL if the event is not an XInput event.
140  */
141 DeviceIntPtr
142 XIGetDevice(xEvent* xE)
143 {
144     DeviceIntPtr pDev = NULL;
145
146     if (xE->u.u.type == DeviceButtonPress ||
147         xE->u.u.type == DeviceButtonRelease ||
148         xE->u.u.type == DeviceMotionNotify ||
149         xE->u.u.type == ProximityIn ||
150         xE->u.u.type == ProximityOut ||
151         xE->u.u.type == DevicePropertyNotify)
152     {
153         int rc;
154         int id;
155
156         id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
157
158         rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
159         if (rc != Success)
160             ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
161     }
162     return pDev;
163 }
164
165
166 /**
167  * Copy the device->key into master->key and send a mapping notify to the
168  * clients if appropriate.
169  * master->key needs to be allocated by the caller.
170  *
171  * Device is the slave device. If it is attached to a master device, we may
172  * need to send a mapping notify to the client because it causes the MD
173  * to change state.
174  *
175  * Mapping notify needs to be sent in the following cases:
176  *      - different slave device on same master
177  *      - different master
178  *
179  * XXX: They way how the code is we also send a map notify if the slave device
180  * stays the same, but the master changes. This isn't really necessary though.
181  *
182  * XXX: this gives you funny behaviour with the ClientPointer. When a
183  * MappingNotify is sent to the client, the client usually responds with a
184  * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
185  * mapping, regardless of which keyboard sent the last mapping notify request.
186  * So depending on the CP setting, your keyboard may change layout in each
187  * app...
188  *
189  * This code is basically the old SwitchCoreKeyboard.
190  */
191
192 void
193 CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
194 {
195     KeyClassPtr mk = master->key;
196     KeyClassPtr dk = device->key;
197     int i;
198
199     if (device == master)
200         return;
201
202     mk->sourceid = device->id;
203
204     for (i = 0; i < 8; i++)
205         mk->modifierKeyCount[i] = dk->modifierKeyCount[i];
206
207     if (!XkbCopyDeviceKeymap(master, device))
208         FatalError("Couldn't pivot keymap from device to core!\n");
209 }
210
211 /**
212  * Copies the feedback classes from device "from" into device "to". Classes
213  * are duplicated (not just flipping the pointers). All feedback classes are
214  * linked lists, the full list is duplicated.
215  */
216 static void
217 DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
218 {
219     ClassesPtr classes;
220
221
222     if (from->intfeed)
223     {
224         IntegerFeedbackPtr *i, it;
225
226         if (!to->intfeed)
227         {
228             classes = to->unused_classes;
229             to->intfeed = classes->intfeed;
230         }
231
232         i = &to->intfeed;
233         for (it = from->intfeed; it; it = it->next)
234         {
235             if (!(*i))
236             {
237                 *i = calloc(1, sizeof(IntegerFeedbackClassRec));
238                 if (!(*i))
239                 {
240                     ErrorF("[Xi] Cannot alloc memory for class copy.");
241                     return;
242                 }
243             }
244             (*i)->CtrlProc = it->CtrlProc;
245             (*i)->ctrl     = it->ctrl;
246
247             i = &(*i)->next;
248         }
249     } else if (to->intfeed && !from->intfeed)
250     {
251         ClassesPtr classes;
252         classes = to->unused_classes;
253         classes->intfeed = to->intfeed;
254         to->intfeed      = NULL;
255     }
256
257     if (from->stringfeed)
258     {
259         StringFeedbackPtr *s, it;
260
261         if (!to->stringfeed)
262         {
263             classes = to->unused_classes;
264             to->stringfeed = classes->stringfeed;
265         }
266
267         s = &to->stringfeed;
268         for (it = from->stringfeed; it; it = it->next)
269         {
270             if (!(*s))
271             {
272                 *s = calloc(1, sizeof(StringFeedbackClassRec));
273                 if (!(*s))
274                 {
275                     ErrorF("[Xi] Cannot alloc memory for class copy.");
276                     return;
277                 }
278             }
279             (*s)->CtrlProc = it->CtrlProc;
280             (*s)->ctrl     = it->ctrl;
281
282             s = &(*s)->next;
283         }
284     } else if (to->stringfeed && !from->stringfeed)
285     {
286         ClassesPtr classes;
287         classes = to->unused_classes;
288         classes->stringfeed = to->stringfeed;
289         to->stringfeed      = NULL;
290     }
291
292     if (from->bell)
293     {
294         BellFeedbackPtr *b, it;
295
296         if (!to->bell)
297         {
298             classes = to->unused_classes;
299             to->bell = classes->bell;
300         }
301
302         b = &to->bell;
303         for (it = from->bell; it; it = it->next)
304         {
305             if (!(*b))
306             {
307                 *b = calloc(1, sizeof(BellFeedbackClassRec));
308                 if (!(*b))
309                 {
310                     ErrorF("[Xi] Cannot alloc memory for class copy.");
311                     return;
312                 }
313             }
314             (*b)->BellProc = it->BellProc;
315             (*b)->CtrlProc = it->CtrlProc;
316             (*b)->ctrl     = it->ctrl;
317
318             b = &(*b)->next;
319         }
320     } else if (to->bell && !from->bell)
321     {
322         ClassesPtr classes;
323         classes = to->unused_classes;
324         classes->bell = to->bell;
325         to->bell      = NULL;
326     }
327
328     if (from->leds)
329     {
330         LedFeedbackPtr *l, it;
331
332         if (!to->leds)
333         {
334             classes = to->unused_classes;
335             to->leds = classes->leds;
336         }
337
338         l = &to->leds;
339         for (it = from->leds; it; it = it->next)
340         {
341             if (!(*l))
342             {
343                 *l = calloc(1, sizeof(LedFeedbackClassRec));
344                 if (!(*l))
345                 {
346                     ErrorF("[Xi] Cannot alloc memory for class copy.");
347                     return;
348                 }
349             }
350             (*l)->CtrlProc = it->CtrlProc;
351             (*l)->ctrl     = it->ctrl;
352             if ((*l)->xkb_sli)
353                 XkbFreeSrvLedInfo((*l)->xkb_sli);
354             (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
355
356             l = &(*l)->next;
357         }
358     } else if (to->leds && !from->leds)
359     {
360         ClassesPtr classes;
361         classes = to->unused_classes;
362         classes->leds = to->leds;
363         to->leds      = NULL;
364     }
365 }
366
367 static void
368 DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
369 {
370     ClassesPtr classes;
371
372     /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
373      * kbdfeed to be set up properly, so let's do the feedback classes first.
374      */
375     if (from->kbdfeed)
376     {
377         KbdFeedbackPtr *k, it;
378
379         if (!to->kbdfeed)
380         {
381             classes = to->unused_classes;
382
383             to->kbdfeed = classes->kbdfeed;
384             if (!to->kbdfeed)
385                 InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
386         }
387
388         k = &to->kbdfeed;
389         for(it = from->kbdfeed; it; it = it->next)
390         {
391             if (!(*k))
392             {
393                 *k = calloc(1, sizeof(KbdFeedbackClassRec));
394                 if (!*k)
395                 {
396                     ErrorF("[Xi] Cannot alloc memory for class copy.");
397                     return;
398                 }
399             }
400             (*k)->BellProc = it->BellProc;
401             (*k)->CtrlProc = it->CtrlProc;
402             (*k)->ctrl     = it->ctrl;
403             if ((*k)->xkb_sli)
404                 XkbFreeSrvLedInfo((*k)->xkb_sli);
405             (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
406
407             k = &(*k)->next;
408         }
409     } else if (to->kbdfeed && !from->kbdfeed)
410     {
411         ClassesPtr classes;
412         classes = to->unused_classes;
413         classes->kbdfeed = to->kbdfeed;
414         to->kbdfeed      = NULL;
415     }
416
417     if (from->key)
418     {
419         if (!to->key)
420         {
421             classes = to->unused_classes;
422             to->key = classes->key;
423             if (!to->key)
424                 InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
425             else
426                 classes->key = NULL;
427         }
428
429         CopyKeyClass(from, to);
430     } else if (to->key && !from->key)
431     {
432         ClassesPtr classes;
433         classes = to->unused_classes;
434         classes->key = to->key;
435         to->key      = NULL;
436     }
437
438     /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
439      * pointer point into the xkbInfo->desc struct.  XkbCopySrvLedInfo
440      * didn't update the pointers so we need to do it manually here.
441      */
442     if (to->kbdfeed)
443     {
444         KbdFeedbackPtr k;
445
446         for (k = to->kbdfeed; k; k = k->next)
447         {
448             if (!k->xkb_sli)
449                 continue;
450             if (k->xkb_sli->flags & XkbSLI_IsDefault)
451             {
452                 k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
453                 k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
454             }
455         }
456     }
457
458     /* We can't just copy over the focus class. When an app sets the focus,
459      * it'll do so on the master device. Copying the SDs focus means losing
460      * the focus.
461      * So we only copy the focus class if the device didn't have one,
462      * otherwise we leave it as it is.
463      */
464     if (from->focus)
465     {
466         if (!to->focus)
467         {
468             WindowPtr *oldTrace;
469
470             classes = to->unused_classes;
471             to->focus = classes->focus;
472             if (!to->focus)
473             {
474                 to->focus = calloc(1, sizeof(FocusClassRec));
475                 if (!to->focus)
476                     FatalError("[Xi] no memory for class shift.\n");
477             } else
478                 classes->focus = NULL;
479
480             oldTrace = to->focus->trace;
481             memcpy(to->focus, from->focus, sizeof(FocusClassRec));
482             to->focus->trace = realloc(oldTrace,
483                                   to->focus->traceSize * sizeof(WindowPtr));
484             if (!to->focus->trace && to->focus->traceSize)
485                 FatalError("[Xi] no memory for trace.\n");
486             memcpy(to->focus->trace, from->focus->trace,
487                     from->focus->traceSize * sizeof(WindowPtr));
488             to->focus->sourceid = from->id;
489         }
490     } else if (to->focus)
491     {
492         ClassesPtr classes;
493         classes = to->unused_classes;
494         classes->focus = to->focus;
495         to->focus      = NULL;
496     }
497
498 }
499
500 static void
501 DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
502 {
503     ClassesPtr classes;
504
505     /* Feedback classes must be copied first */
506     if (from->ptrfeed)
507     {
508         PtrFeedbackPtr *p, it;
509         if (!to->ptrfeed)
510         {
511             classes = to->unused_classes;
512             to->ptrfeed = classes->ptrfeed;
513         }
514
515         p = &to->ptrfeed;
516         for (it = from->ptrfeed; it; it = it->next)
517         {
518             if (!(*p))
519             {
520                 *p = calloc(1, sizeof(PtrFeedbackClassRec));
521                 if (!*p)
522                 {
523                     ErrorF("[Xi] Cannot alloc memory for class copy.");
524                     return;
525                 }
526             }
527             (*p)->CtrlProc = it->CtrlProc;
528             (*p)->ctrl     = it->ctrl;
529
530             p = &(*p)->next;
531         }
532     } else if (to->ptrfeed && !from->ptrfeed)
533     {
534         ClassesPtr classes;
535         classes = to->unused_classes;
536         classes->ptrfeed = to->ptrfeed;
537         to->ptrfeed      = NULL;
538     }
539
540     if (from->valuator)
541     {
542         ValuatorClassPtr v;
543         if (!to->valuator)
544         {
545             classes = to->unused_classes;
546             to->valuator = classes->valuator;
547             if (to->valuator)
548                 classes->valuator = NULL;
549         }
550
551         to->valuator = realloc(to->valuator, sizeof(ValuatorClassRec) +
552                 from->valuator->numAxes * sizeof(AxisInfo) +
553                 from->valuator->numAxes * sizeof(double));
554         v = to->valuator;
555         if (!v)
556             FatalError("[Xi] no memory for class shift.\n");
557
558         v->numAxes = from->valuator->numAxes;
559         v->axes = (AxisInfoPtr)&v[1];
560         memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
561
562         v->axisVal = (double*)(v->axes + from->valuator->numAxes);
563         v->sourceid = from->id;
564         v->mode = from->valuator->mode;
565     } else if (to->valuator && !from->valuator)
566     {
567         ClassesPtr classes;
568         classes = to->unused_classes;
569         classes->valuator = to->valuator;
570         to->valuator      = NULL;
571     }
572
573     if (from->button)
574     {
575         if (!to->button)
576         {
577             classes = to->unused_classes;
578             to->button = classes->button;
579             if (!to->button)
580             {
581                 to->button = calloc(1, sizeof(ButtonClassRec));
582                 if (!to->button)
583                     FatalError("[Xi] no memory for class shift.\n");
584             } else
585                 classes->button = NULL;
586         }
587
588         if (from->button->xkb_acts)
589         {
590             if (!to->button->xkb_acts)
591             {
592                 to->button->xkb_acts = calloc(1, sizeof(XkbAction));
593                 if (!to->button->xkb_acts)
594                     FatalError("[Xi] not enough memory for xkb_acts.\n");
595             }
596             memcpy(to->button->xkb_acts, from->button->xkb_acts,
597                     sizeof(XkbAction));
598         } else
599             free(to->button->xkb_acts);
600
601          memcpy(to->button->labels, from->button->labels,
602                 from->button->numButtons * sizeof(Atom));
603         to->button->sourceid = from->id;
604     } else if (to->button && !from->button)
605     {
606         ClassesPtr classes;
607         classes = to->unused_classes;
608         classes->button = to->button;
609         to->button      = NULL;
610     }
611
612     if (from->proximity)
613     {
614         if (!to->proximity)
615         {
616             classes = to->unused_classes;
617             to->proximity = classes->proximity;
618             if (!to->proximity)
619             {
620                 to->proximity = calloc(1, sizeof(ProximityClassRec));
621                 if (!to->proximity)
622                     FatalError("[Xi] no memory for class shift.\n");
623             } else
624                 classes->proximity = NULL;
625         }
626         memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
627         to->proximity->sourceid = from->id;
628     } else if (to->proximity)
629     {
630         ClassesPtr classes;
631         classes = to->unused_classes;
632         classes->proximity = to->proximity;
633         to->proximity      = NULL;
634     }
635
636     if (from->absolute)
637     {
638         if (!to->absolute)
639         {
640             classes = to->unused_classes;
641             to->absolute = classes->absolute;
642             if (!to->absolute)
643             {
644                 to->absolute = calloc(1, sizeof(AbsoluteClassRec));
645                 if (!to->absolute)
646                     FatalError("[Xi] no memory for class shift.\n");
647             } else
648                 classes->absolute = NULL;
649         }
650         memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
651         to->absolute->sourceid = from->id;
652     } else if (to->absolute)
653     {
654         ClassesPtr classes;
655         classes = to->unused_classes;
656         classes->absolute = to->absolute;
657         to->absolute      = NULL;
658     }
659 }
660
661 /**
662  * Copies the CONTENT of the classes of device from into the classes in device
663  * to. From and to are identical after finishing.
664  *
665  * If to does not have classes from currenly has, the classes are stored in
666  * to's devPrivates system. Later, we recover it again from there if needed.
667  * Saves a few memory allocations.
668  */
669 void
670 DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce)
671 {
672     /* generic feedback classes, not tied to pointer and/or keyboard */
673     DeepCopyFeedbackClasses(from, to);
674
675     if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
676         DeepCopyKeyboardClasses(from, to);
677     if ((dce->flags & DEVCHANGE_POINTER_EVENT))
678         DeepCopyPointerClasses(from, to);
679 }
680
681
682 /**
683  * Send an XI2 DeviceChangedEvent to all interested clients.
684  */
685 void
686 XISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChangedEvent *dce)
687 {
688     xXIDeviceChangedEvent *dcce;
689     int rc;
690
691     rc = EventToXI2((InternalEvent*)dce, (xEvent**)&dcce);
692     if (rc != Success)
693     {
694         ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
695         return;
696     }
697
698     /* we don't actually swap if there's a NullClient, swapping is done
699      * later when event is delivered. */
700     SendEventToAllWindows(master, XI_DeviceChangedMask, (xEvent*)dcce, 1);
701     free(dcce);
702 }
703
704 static void
705 ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
706 {
707     DeviceIntPtr slave;
708     int rc;
709
710     /* For now, we don't have devices that change physically. */
711     if (!IsMaster(device))
712         return;
713
714     rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
715
716     if (rc != Success)
717         return; /* Device has disappeared */
718
719     if (!slave->u.master)
720         return; /* set floating since the event */
721
722     if (slave->u.master->id != dce->masterid)
723         return; /* not our slave anymore, don't care */
724
725     /* FIXME: we probably need to send a DCE for the new slave now */
726
727     device->public.devicePrivate = slave->public.devicePrivate;
728
729     /* FIXME: the classes may have changed since we generated the event. */
730     DeepCopyDeviceClasses(slave, device, dce);
731     XISendDeviceChangedEvent(slave, device, dce);
732 }
733
734 /**
735  * Update the device state according to the data in the event.
736  *
737  * return values are
738  *   DEFAULT ... process as normal
739  *   DONT_PROCESS ... return immediately from caller
740  */
741 #define DEFAULT 0
742 #define DONT_PROCESS 1
743 int
744 UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
745 {
746     int i;
747     int key = 0,
748         bit = 0,
749         last_valuator;
750
751     KeyClassPtr k       = NULL;
752     ButtonClassPtr b    = NULL;
753     ValuatorClassPtr v  = NULL;
754     BYTE *kptr          = NULL;
755
756     /* This event is always the first we get, before the actual events with
757      * the data. However, the way how the DDX is set up, "device" will
758      * actually be the slave device that caused the event.
759      */
760     switch(event->type)
761     {
762         case ET_DeviceChanged:
763             ChangeMasterDeviceClasses(device, (DeviceChangedEvent*)event);
764             return DONT_PROCESS; /* event has been sent already */
765         case ET_Motion:
766         case ET_ButtonPress:
767         case ET_ButtonRelease:
768         case ET_KeyPress:
769         case ET_KeyRelease:
770         case ET_ProximityIn:
771         case ET_ProximityOut:
772             break;
773         default:
774             /* other events don't update the device */
775             return DEFAULT;
776     }
777
778     k = device->key;
779     v = device->valuator;
780     b = device->button;
781
782     key = event->detail.key;
783     bit = 1 << (key & 7);
784
785     /* Update device axis */
786     /* Check valuators first */
787     last_valuator = -1;
788     for (i = 0; i < MAX_VALUATORS; i++)
789     {
790         if (BitIsOn(&event->valuators.mask, i))
791         {
792             if (!v)
793             {
794                 ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
795                         "Ignoring event.\n", device->name);
796                 return DONT_PROCESS;
797             } else if (v->numAxes < i)
798             {
799                 ErrorF("[Xi] Too many valuators reported for device '%s'. "
800                         "Ignoring event.\n", device->name);
801                 return DONT_PROCESS;
802             }
803             last_valuator = i;
804         }
805     }
806
807     for (i = 0; i <= last_valuator && i < v->numAxes; i++)
808     {
809         if (BitIsOn(&event->valuators.mask, i))
810         {
811             /* XXX: Relative/Absolute mode */
812             v->axisVal[i] = event->valuators.data[i];
813             v->axisVal[i] += (event->valuators.data_frac[i] * 1.0f / (1 << 16) / (1 << 16));
814         }
815     }
816
817     if (event->type == ET_KeyPress) {
818         if (!k)
819             return DONT_PROCESS;
820
821         kptr = &k->down[key >> 3];
822         /* don't allow ddx to generate multiple downs, but repeats are okay */
823         if ((*kptr & bit) && !event->key_repeat)
824             return DONT_PROCESS;
825         if (device->valuator)
826             device->valuator->motionHintWindow = NullWindow;
827         *kptr |= bit;
828     } else if (event->type == ET_KeyRelease) {
829         if (!k)
830             return DONT_PROCESS;
831
832         kptr = &k->down[key >> 3];
833         if (!(*kptr & bit))     /* guard against duplicates */
834             return DONT_PROCESS;
835         if (device->valuator)
836             device->valuator->motionHintWindow = NullWindow;
837         *kptr &= ~bit;
838     } else if (event->type == ET_ButtonPress) {
839         Mask mask;
840         if (!b)
841             return DONT_PROCESS;
842
843         kptr = &b->down[key >> 3];
844         if ((*kptr & bit) != 0)
845             return DONT_PROCESS;
846         *kptr |= bit;
847         if (device->valuator)
848             device->valuator->motionHintWindow = NullWindow;
849         if (!b->map[key])
850             return DONT_PROCESS;
851         b->buttonsDown++;
852         b->motionMask = DeviceButtonMotionMask;
853         if (b->map[key] <= 5)
854             b->state |= (Button1Mask >> 1) << b->map[key];
855
856         /* Add state and motionMask to the filter for this event */
857         mask = DevicePointerMotionMask | b->state | b->motionMask;
858         SetMaskForEvent(device->id, mask, DeviceMotionNotify);
859         mask = PointerMotionMask | b->state | b->motionMask;
860         SetMaskForEvent(device->id, mask, MotionNotify);
861     } else if (event->type == ET_ButtonRelease) {
862         Mask mask;
863         if (!b)
864             return DONT_PROCESS;
865
866         kptr = &b->down[key>>3];
867         if (!(*kptr & bit))
868             return DONT_PROCESS;
869         if (IsMaster(device)) {
870             DeviceIntPtr sd;
871
872             /*
873              * Leave the button down if any slave has the
874              * button still down. Note that this depends on the
875              * event being delivered through the slave first
876              */
877             for (sd = inputInfo.devices; sd; sd = sd->next) {
878                 if (IsMaster(sd) || sd->u.master != device)
879                     continue;
880                 if (!sd->button)
881                     continue;
882                 if ((sd->button->down[key>>3] & bit) != 0)
883                     return DONT_PROCESS;
884             }
885         }
886         *kptr &= ~bit;
887         if (device->valuator)
888             device->valuator->motionHintWindow = NullWindow;
889         if (!b->map[key])
890             return DONT_PROCESS;
891         if (b->buttonsDown >= 1 && !--b->buttonsDown)
892             b->motionMask = 0;
893         if (b->map[key] <= 5)
894             b->state &= ~((Button1Mask >> 1) << b->map[key]);
895
896         /* Add state and motionMask to the filter for this event */
897         mask = DevicePointerMotionMask | b->state | b->motionMask;
898         SetMaskForEvent(device->id, mask, DeviceMotionNotify);
899         mask = PointerMotionMask | b->state | b->motionMask;
900         SetMaskForEvent(device->id, mask, MotionNotify);
901     } else if (event->type == ET_ProximityIn)
902         device->valuator->mode &= ~OutOfProximity;
903     else if (event->type == ET_ProximityOut)
904         device->valuator->mode |= OutOfProximity;
905
906     return DEFAULT;
907 }
908
909 static void
910 ProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
911 {
912     GrabPtr grab = device->deviceGrab.grab;
913
914     if (grab)
915         DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE);
916     else { /* deliver to all root windows */
917         xEvent *xi;
918         int i;
919
920         i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi);
921         if (i != Success)
922         {
923             ErrorF("[Xi] %s: XI2 conversion failed in ProcessRawEvent (%d)\n",
924                     device->name, i);
925             return;
926         }
927
928         for (i = 0; i < screenInfo.numScreens; i++)
929             DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1,
930                                   GetEventFilter(device, xi), NULL);
931         free(xi);
932     }
933 }
934
935 /**
936  * Main device event processing function.
937  * Called from when processing the events from the event queue.
938  *
939  */
940 void
941 ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
942 {
943     GrabPtr grab;
944     Bool deactivateDeviceGrab = FALSE;
945     int key = 0, rootX, rootY;
946     ButtonClassPtr b;
947     KeyClassPtr k;
948     ValuatorClassPtr v;
949     int ret = 0;
950     int state, i;
951     DeviceIntPtr mouse = NULL, kbd = NULL;
952     DeviceEvent *event = &ev->device_event;
953
954     CHECKEVENT(ev);
955
956     if (ev->any.type == ET_RawKeyPress ||
957         ev->any.type == ET_RawKeyRelease ||
958         ev->any.type == ET_RawButtonPress ||
959         ev->any.type == ET_RawButtonRelease ||
960         ev->any.type == ET_RawMotion)
961     {
962         ProcessRawEvent(&ev->raw_event, device);
963         return;
964     }
965
966     if (IsPointerDevice(device))
967     {
968         kbd = GetPairedDevice(device);
969         mouse = device;
970         if (!kbd->key) /* can happen with floating SDs */
971             kbd = NULL;
972     } else
973     {
974         mouse = GetPairedDevice(device);
975         kbd = device;
976         if (!mouse->valuator || !mouse->button) /* may be float. SDs */
977             mouse = NULL;
978     }
979
980     /* State needs to be assembled BEFORE the device is updated. */
981     state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0;
982     state |= (mouse && mouse->button) ? (mouse->button->state) : 0;
983
984     for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
985         if (BitIsOn(mouse->button->down, i))
986             SetBit(event->buttons, i);
987
988     if (kbd && kbd->key)
989     {
990         XkbStatePtr state;
991         /* we need the state before the event happens */
992         if (event->type == ET_KeyPress || event->type == ET_KeyRelease)
993             state = &kbd->key->xkbInfo->prev_state;
994         else
995             state = &kbd->key->xkbInfo->state;
996
997         event->mods.base = state->base_mods;
998         event->mods.latched = state->latched_mods;
999         event->mods.locked = state->locked_mods;
1000         event->mods.effective = state->mods;
1001
1002         event->group.base = state->base_group;
1003         event->group.latched = state->latched_group;
1004         event->group.locked = state->locked_group;
1005         event->group.effective = state->group;
1006     }
1007
1008     ret = UpdateDeviceState(device, event);
1009     if (ret == DONT_PROCESS)
1010         return;
1011
1012     v = device->valuator;
1013     b = device->button;
1014     k = device->key;
1015
1016     if (IsMaster(device) || !device->u.master)
1017         CheckMotion(event, device);
1018
1019     switch (event->type)
1020     {
1021         case ET_Motion:
1022         case ET_ButtonPress:
1023         case ET_ButtonRelease:
1024         case ET_KeyPress:
1025         case ET_KeyRelease:
1026         case ET_ProximityIn:
1027         case ET_ProximityOut:
1028             GetSpritePosition(device, &rootX, &rootY);
1029             event->root_x = rootX;
1030             event->root_y = rootY;
1031             NoticeEventTime((InternalEvent*)event);
1032             event->corestate = state;
1033             key = event->detail.key;
1034             break;
1035         default:
1036             break;
1037     }
1038
1039     if (DeviceEventCallback && !syncEvents.playingEvents) {
1040         DeviceEventInfoRec eventinfo;
1041         SpritePtr pSprite = device->spriteInfo->sprite;
1042
1043         /* see comment in EnqueueEvents regarding the next three lines */
1044         if (ev->any.type == ET_Motion)
1045             ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1046
1047         eventinfo.device = device;
1048         eventinfo.event = ev;
1049         CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
1050     }
1051
1052     grab = device->deviceGrab.grab;
1053
1054     switch(event->type)
1055     {
1056         case ET_KeyPress:
1057             if (!grab && CheckDeviceGrabs(device, event, 0)) {
1058                 device->deviceGrab.activatingKey = key;
1059                 return;
1060             }
1061             break;
1062         case ET_KeyRelease:
1063             if (grab && device->deviceGrab.fromPassiveGrab &&
1064                 (key == device->deviceGrab.activatingKey) &&
1065                 (device->deviceGrab.grab->type == KeyPress ||
1066                  device->deviceGrab.grab->type == DeviceKeyPress ||
1067                  device->deviceGrab.grab->type == XI_KeyPress))
1068                 deactivateDeviceGrab = TRUE;
1069             break;
1070         case ET_ButtonPress:
1071             event->detail.button = b->map[key];
1072             if (!event->detail.button) { /* there's no button 0 */
1073                 event->detail.button = key;
1074                 return;
1075             }
1076             if (!grab && CheckDeviceGrabs(device, event, 0))
1077             {
1078                 /* if a passive grab was activated, the event has been sent
1079                  * already */
1080                 return;
1081             }
1082             break;
1083         case ET_ButtonRelease:
1084             event->detail.button = b->map[key];
1085             if (!event->detail.button) { /* there's no button 0 */
1086                 event->detail.button = key;
1087                 return;
1088             }
1089             if (grab && !b->buttonsDown &&
1090                 device->deviceGrab.fromPassiveGrab &&
1091                 (device->deviceGrab.grab->type == ButtonPress ||
1092                  device->deviceGrab.grab->type == DeviceButtonPress ||
1093                  device->deviceGrab.grab->type == XI_ButtonPress))
1094                 deactivateDeviceGrab = TRUE;
1095         default:
1096             break;
1097     }
1098
1099
1100     if (grab)
1101         DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
1102     else if (device->focus && !IsPointerEvent((InternalEvent*)ev))
1103         DeliverFocusedEvent(device, (InternalEvent*)event,
1104                             GetSpriteWindow(device));
1105     else
1106         DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
1107                             NullGrab, NullWindow, device);
1108
1109     if (deactivateDeviceGrab == TRUE)
1110         (*device->deviceGrab.DeactivateGrab) (device);
1111     event->detail.key = key;
1112 }
1113
1114 int
1115 InitProximityClassDeviceStruct(DeviceIntPtr dev)
1116 {
1117     ProximityClassPtr proxc;
1118
1119     proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
1120     if (!proxc)
1121         return FALSE;
1122     proxc->sourceid = dev->id;
1123     dev->proximity = proxc;
1124     return TRUE;
1125 }
1126
1127 /**
1128  * Initialise the device's valuators. The memory must already be allocated,
1129  * this function merely inits the matching axis (specified through axnum) to
1130  * sane values.
1131  *
1132  * It is a condition that (minval < maxval).
1133  *
1134  * @see InitValuatorClassDeviceStruct
1135  */
1136 void
1137 InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
1138                        int resolution, int min_res, int max_res)
1139 {
1140     AxisInfoPtr ax;
1141
1142     if (!dev || !dev->valuator || minval > maxval)
1143         return;
1144     if (axnum >= dev->valuator->numAxes)
1145         return;
1146
1147     ax = dev->valuator->axes + axnum;
1148
1149     ax->min_value = minval;
1150     ax->max_value = maxval;
1151     ax->resolution = resolution;
1152     ax->min_resolution = min_res;
1153     ax->max_resolution = max_res;
1154     ax->label = label;
1155 }
1156
1157 static void
1158 FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
1159                      ButtonClassPtr b, ValuatorClassPtr v, int first)
1160 {
1161     ev->type = DeviceStateNotify;
1162     ev->deviceid = dev->id;
1163     ev->time = currentTime.milliseconds;
1164     ev->classes_reported = 0;
1165     ev->num_keys = 0;
1166     ev->num_buttons = 0;
1167     ev->num_valuators = 0;
1168
1169     if (b) {
1170         ev->classes_reported |= (1 << ButtonClass);
1171         ev->num_buttons = b->numButtons;
1172         memcpy((char*)ev->buttons, (char*)b->down, 4);
1173     } else if (k) {
1174         ev->classes_reported |= (1 << KeyClass);
1175         ev->num_keys = k->xkbInfo->desc->max_key_code -
1176                        k->xkbInfo->desc->min_key_code;
1177         memmove((char *)&ev->keys[0], (char *)k->down, 4);
1178     }
1179     if (v) {
1180         int nval = v->numAxes - first;
1181
1182         ev->classes_reported |= (1 << ValuatorClass);
1183         ev->classes_reported |= (dev->valuator->mode << ModeBitsShift);
1184         ev->num_valuators = nval < 3 ? nval : 3;
1185         switch (ev->num_valuators) {
1186         case 3:
1187             ev->valuator2 = v->axisVal[first + 2];
1188         case 2:
1189             ev->valuator1 = v->axisVal[first + 1];
1190         case 1:
1191             ev->valuator0 = v->axisVal[first];
1192             break;
1193         }
1194     }
1195 }
1196
1197 static void
1198 FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
1199                   int first)
1200 {
1201     int nval = v->numAxes - first;
1202
1203     ev->type = DeviceValuator;
1204     ev->deviceid = dev->id;
1205     ev->num_valuators = nval < 3 ? nval : 3;
1206     ev->first_valuator = first;
1207     switch (ev->num_valuators) {
1208     case 3:
1209         ev->valuator2 = v->axisVal[first + 2];
1210     case 2:
1211         ev->valuator1 = v->axisVal[first + 1];
1212     case 1:
1213         ev->valuator0 = v->axisVal[first];
1214         break;
1215     }
1216     first += ev->num_valuators;
1217 }
1218
1219 void
1220 DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
1221                  WindowPtr pWin)
1222 {
1223     deviceFocus event;
1224     xXIFocusInEvent *xi2event;
1225     DeviceIntPtr mouse;
1226     int btlen, len, i;
1227
1228     mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev;
1229
1230     /* XI 2 event */
1231     btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
1232     btlen = bytes_to_int32(btlen);
1233     len = sizeof(xXIFocusInEvent) + btlen * 4;
1234
1235     xi2event = calloc(1, len);
1236     xi2event->type         = GenericEvent;
1237     xi2event->extension    = IReqCode;
1238     xi2event->evtype       = type;
1239     xi2event->length       = bytes_to_int32(len - sizeof(xEvent));
1240     xi2event->buttons_len  = btlen;
1241     xi2event->detail       = detail;
1242     xi2event->time         = currentTime.milliseconds;
1243     xi2event->deviceid     = dev->id;
1244     xi2event->sourceid     = dev->id; /* a device doesn't change focus by itself */
1245     xi2event->mode         = mode;
1246     xi2event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
1247     xi2event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
1248
1249     for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
1250         if (BitIsOn(mouse->button->down, i))
1251             SetBit(&xi2event[1], i);
1252
1253     if (dev->key)
1254     {
1255         xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
1256         xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
1257         xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
1258         xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
1259
1260         xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
1261         xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
1262         xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
1263         xi2event->group.effective_group = dev->key->xkbInfo->state.group;
1264     }
1265
1266     FixUpEventFromWindow(dev, (xEvent*)xi2event, pWin, None, FALSE);
1267
1268     DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
1269                           GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
1270
1271     free(xi2event);
1272
1273     /* XI 1.x event */
1274     event.deviceid = dev->id;
1275     event.mode = mode;
1276     event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
1277     event.detail = detail;
1278     event.window = pWin->drawable.id;
1279     event.time = currentTime.milliseconds;
1280
1281     DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
1282                                 DeviceFocusChangeMask, NullGrab);
1283
1284     if ((type == DeviceFocusIn) &&
1285         (wOtherInputMasks(pWin)) &&
1286         (wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
1287     {
1288         int evcount = 1;
1289         deviceStateNotify *ev, *sev;
1290         deviceKeyStateNotify *kev;
1291         deviceButtonStateNotify *bev;
1292
1293         KeyClassPtr k;
1294         ButtonClassPtr b;
1295         ValuatorClassPtr v;
1296         int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
1297
1298         if ((b = dev->button) != NULL) {
1299             nbuttons = b->numButtons;
1300             if (nbuttons > 32)
1301                 evcount++;
1302         }
1303         if ((k = dev->key) != NULL) {
1304             nkeys = k->xkbInfo->desc->max_key_code -
1305                     k->xkbInfo->desc->min_key_code;
1306             if (nkeys > 32)
1307                 evcount++;
1308             if (nbuttons > 0) {
1309                 evcount++;
1310             }
1311         }
1312         if ((v = dev->valuator) != NULL) {
1313             nval = v->numAxes;
1314
1315             if (nval > 3)
1316                 evcount++;
1317             if (nval > 6) {
1318                 if (!(k && b))
1319                     evcount++;
1320                 if (nval > 9)
1321                     evcount += ((nval - 7) / 3);
1322             }
1323         }
1324
1325         sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
1326         FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
1327
1328         if (b != NULL) {
1329             FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
1330             first += 3;
1331             nval -= 3;
1332             if (nbuttons > 32) {
1333                 (ev - 1)->deviceid |= MORE_EVENTS;
1334                 bev = (deviceButtonStateNotify *) ev++;
1335                 bev->type = DeviceButtonStateNotify;
1336                 bev->deviceid = dev->id;
1337                 memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
1338             }
1339             if (nval > 0) {
1340                 (ev - 1)->deviceid |= MORE_EVENTS;
1341                 FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1342                 first += 3;
1343                 nval -= 3;
1344             }
1345         }
1346
1347         if (k != NULL) {
1348             FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
1349             first += 3;
1350             nval -= 3;
1351             if (nkeys > 32) {
1352                 (ev - 1)->deviceid |= MORE_EVENTS;
1353                 kev = (deviceKeyStateNotify *) ev++;
1354                 kev->type = DeviceKeyStateNotify;
1355                 kev->deviceid = dev->id;
1356                 memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
1357             }
1358             if (nval > 0) {
1359                 (ev - 1)->deviceid |= MORE_EVENTS;
1360                 FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1361                 first += 3;
1362                 nval -= 3;
1363             }
1364         }
1365
1366         while (nval > 0) {
1367             FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
1368             first += 3;
1369             nval -= 3;
1370             if (nval > 0) {
1371                 (ev - 1)->deviceid |= MORE_EVENTS;
1372                 FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1373                 first += 3;
1374                 nval -= 3;
1375             }
1376         }
1377
1378         DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
1379                                     DeviceStateNotifyMask, NullGrab);
1380         free(sev);
1381     }
1382 }
1383
1384 int
1385 CheckGrabValues(ClientPtr client, GrabParameters* param)
1386 {
1387     if (param->grabtype != GRABTYPE_CORE &&
1388         param->grabtype != GRABTYPE_XI &&
1389         param->grabtype != GRABTYPE_XI2)
1390     {
1391         ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
1392         return BadImplementation;
1393     }
1394
1395     if ((param->this_device_mode != GrabModeSync) &&
1396         (param->this_device_mode != GrabModeAsync)) {
1397         client->errorValue = param->this_device_mode;
1398         return BadValue;
1399     }
1400     if ((param->other_devices_mode != GrabModeSync) &&
1401         (param->other_devices_mode != GrabModeAsync)) {
1402         client->errorValue = param->other_devices_mode;
1403         return BadValue;
1404     }
1405
1406     if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
1407         (param->modifiers & ~AllModifiersMask)) {
1408         client->errorValue = param->modifiers;
1409         return BadValue;
1410     }
1411
1412     if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
1413         client->errorValue = param->ownerEvents;
1414         return BadValue;
1415     }
1416     return Success;
1417 }
1418
1419 int
1420 GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
1421            int button, GrabParameters *param, GrabType grabtype,
1422            GrabMask *mask)
1423 {
1424     WindowPtr pWin, confineTo;
1425     CursorPtr cursor;
1426     GrabPtr grab;
1427     int rc, type = -1;
1428     Mask access_mode = DixGrabAccess;
1429
1430     rc = CheckGrabValues(client, param);
1431     if (rc != Success)
1432         return rc;
1433     if (param->confineTo == None)
1434         confineTo = NullWindow;
1435     else {
1436         rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
1437         if (rc != Success)
1438             return rc;
1439     }
1440     if (param->cursor == None)
1441         cursor = NullCursor;
1442     else {
1443         rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
1444                                      RT_CURSOR, client, DixUseAccess);
1445         if (rc != Success)
1446         {
1447             client->errorValue = param->cursor;
1448             return rc;
1449         }
1450         access_mode |= DixForceAccess;
1451     }
1452     if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1453         access_mode |= DixFreezeAccess;
1454     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1455     if (rc != Success)
1456         return rc;
1457     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1458     if (rc != Success)
1459         return rc;
1460
1461     if (grabtype == GRABTYPE_XI)
1462         type = DeviceButtonPress;
1463     else if (grabtype == GRABTYPE_XI2)
1464         type = XI_ButtonPress;
1465
1466     grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
1467                       mask, param, type, button, confineTo, cursor);
1468     if (!grab)
1469         return BadAlloc;
1470     return AddPassiveGrabToList(client, grab);
1471 }
1472
1473 /**
1474  * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If
1475  * grabtype is GRABTYPE_XI2, the key is a keysym.
1476  */
1477 int
1478 GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
1479         int key, GrabParameters *param, GrabType grabtype, GrabMask *mask)
1480 {
1481     WindowPtr pWin;
1482     GrabPtr grab;
1483     KeyClassPtr k = dev->key;
1484     Mask access_mode = DixGrabAccess;
1485     int rc, type = -1;
1486
1487     rc = CheckGrabValues(client, param);
1488     if (rc != Success)
1489         return rc;
1490     if (k == NULL)
1491         return BadMatch;
1492     if (grabtype == GRABTYPE_XI)
1493     {
1494         if ((key > k->xkbInfo->desc->max_key_code ||
1495                     key < k->xkbInfo->desc->min_key_code)
1496                 && (key != AnyKey)) {
1497             client->errorValue = key;
1498             return BadValue;
1499         }
1500         type = DeviceKeyPress;
1501     } else if (grabtype == GRABTYPE_XI2)
1502         type = XI_KeyPress;
1503
1504     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1505     if (rc != Success)
1506         return rc;
1507     if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1508         access_mode |= DixFreezeAccess;
1509     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1510     if (rc != Success)
1511         return rc;
1512
1513     grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
1514                       mask, param, type, key, NULL, NULL);
1515     if (!grab)
1516         return BadAlloc;
1517     return AddPassiveGrabToList(client, grab);
1518 }
1519
1520 /* Enter/FocusIn grab */
1521 int
1522 GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
1523            GrabParameters *param, GrabMask *mask)
1524 {
1525     WindowPtr pWin;
1526     CursorPtr cursor;
1527     GrabPtr grab;
1528     Mask access_mode = DixGrabAccess;
1529     int rc;
1530
1531     rc = CheckGrabValues(client, param);
1532     if (rc != Success)
1533         return rc;
1534
1535     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1536     if (rc != Success)
1537         return rc;
1538     if (param->cursor == None)
1539         cursor = NullCursor;
1540     else {
1541         rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
1542                                      RT_CURSOR, client, DixUseAccess);
1543         if (rc != Success)
1544         {
1545             client->errorValue = param->cursor;
1546             return rc;
1547         }
1548         access_mode |= DixForceAccess;
1549     }
1550     if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1551         access_mode |= DixFreezeAccess;
1552     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1553     if (rc != Success)
1554         return rc;
1555
1556     grab = CreateGrab(client->index, dev, dev, pWin, GRABTYPE_XI2,
1557                       mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
1558                       0, NULL, cursor);
1559
1560     if (!grab)
1561         return BadAlloc;
1562
1563     return AddPassiveGrabToList(client, grab);
1564 }
1565
1566 int
1567 SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
1568                 Mask mask, Mask exclusivemasks)
1569 {
1570     int mskidx = dev->id;
1571     int i, ret;
1572     Mask check;
1573     InputClientsPtr others;
1574
1575     check = (mask & exclusivemasks);
1576     if (wOtherInputMasks(pWin)) {
1577         if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {      /* It is illegal for two different
1578                                                                          * clients to select on any of the
1579                                                                          * events for maskcheck. However,
1580                                                                          * it is OK, for some client to
1581                                                                          * continue selecting on one of those
1582                                                                          * events.  */
1583             for (others = wOtherInputMasks(pWin)->inputClients; others;
1584                  others = others->next) {
1585                 if (!SameClient(others, client) && (check &
1586                                                     others->mask[mskidx]))
1587                     return BadAccess;
1588             }
1589         }
1590         for (others = wOtherInputMasks(pWin)->inputClients; others;
1591              others = others->next) {
1592             if (SameClient(others, client)) {
1593                 check = others->mask[mskidx];
1594                 others->mask[mskidx] = mask;
1595                 if (mask == 0) {
1596                     for (i = 0; i < EMASKSIZE; i++)
1597                         if (i != mskidx && others->mask[i] != 0)
1598                             break;
1599                     if (i == EMASKSIZE) {
1600                         RecalculateDeviceDeliverableEvents(pWin);
1601                         if (ShouldFreeInputMasks(pWin, FALSE))
1602                             FreeResource(others->resource, RT_NONE);
1603                         return Success;
1604                     }
1605                 }
1606                 goto maskSet;
1607             }
1608         }
1609     }
1610     check = 0;
1611     if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
1612         return ret;
1613   maskSet:
1614     if (dev->valuator)
1615         if ((dev->valuator->motionHintWindow == pWin) &&
1616             (mask & DevicePointerMotionHintMask) &&
1617             !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
1618             dev->valuator->motionHintWindow = NullWindow;
1619     RecalculateDeviceDeliverableEvents(pWin);
1620     return Success;
1621 }
1622
1623 int
1624 AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
1625 {
1626     InputClientsPtr others;
1627
1628     if (!pWin->optional && !MakeWindowOptional(pWin))
1629         return BadAlloc;
1630     others = calloc(1, sizeof(InputClients));
1631     if (!others)
1632         return BadAlloc;
1633     if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
1634         return BadAlloc;
1635     others->mask[mskidx] = mask;
1636     others->resource = FakeClientID(client->index);
1637     others->next = pWin->optional->inputMasks->inputClients;
1638     pWin->optional->inputMasks->inputClients = others;
1639     if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
1640         return BadAlloc;
1641     return Success;
1642 }
1643
1644 static Bool
1645 MakeInputMasks(WindowPtr pWin)
1646 {
1647     struct _OtherInputMasks *imasks;
1648
1649     imasks = calloc(1, sizeof(struct _OtherInputMasks));
1650     if (!imasks)
1651         return FALSE;
1652     pWin->optional->inputMasks = imasks;
1653     return TRUE;
1654 }
1655
1656 void
1657 RecalculateDeviceDeliverableEvents(WindowPtr pWin)
1658 {
1659     InputClientsPtr others;
1660     struct _OtherInputMasks *inputMasks;        /* default: NULL */
1661     WindowPtr pChild, tmp;
1662     int i, j;
1663
1664     pChild = pWin;
1665     while (1) {
1666         if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
1667             for (i = 0; i < EMASKSIZE; i++)
1668                 memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i]));
1669             for (others = inputMasks->inputClients; others;
1670                  others = others->next) {
1671                 for (i = 0; i < EMASKSIZE; i++)
1672                     inputMasks->inputEvents[i] |= others->mask[i];
1673                 for (i = 0; i < EMASKSIZE; i++)
1674                     for (j = 0; j < XI2MASKSIZE; j++)
1675                         inputMasks->xi2mask[i][j] |= others->xi2mask[i][j];
1676             }
1677             for (i = 0; i < EMASKSIZE; i++)
1678                 inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
1679             for (tmp = pChild->parent; tmp; tmp = tmp->parent)
1680                 if (wOtherInputMasks(tmp))
1681                     for (i = 0; i < EMASKSIZE; i++)
1682                         inputMasks->deliverableEvents[i] |=
1683                             (wOtherInputMasks(tmp)->deliverableEvents[i]
1684                              & ~inputMasks->
1685                              dontPropagateMask[i] & PropagateMask[i]);
1686         }
1687         if (pChild->firstChild) {
1688             pChild = pChild->firstChild;
1689             continue;
1690         }
1691         while (!pChild->nextSib && (pChild != pWin))
1692             pChild = pChild->parent;
1693         if (pChild == pWin)
1694             break;
1695         pChild = pChild->nextSib;
1696     }
1697 }
1698
1699 int
1700 InputClientGone(WindowPtr pWin, XID id)
1701 {
1702     InputClientsPtr other, prev;
1703
1704     if (!wOtherInputMasks(pWin))
1705         return Success;
1706     prev = 0;
1707     for (other = wOtherInputMasks(pWin)->inputClients; other;
1708          other = other->next) {
1709         if (other->resource == id) {
1710             if (prev) {
1711                 prev->next = other->next;
1712                 free(other);
1713             } else if (!(other->next)) {
1714                 if (ShouldFreeInputMasks(pWin, TRUE)) {
1715                     wOtherInputMasks(pWin)->inputClients = other->next;
1716                     free(wOtherInputMasks(pWin));
1717                     pWin->optional->inputMasks = (OtherInputMasks *) NULL;
1718                     CheckWindowOptionalNeed(pWin);
1719                     free(other);
1720                 } else {
1721                     other->resource = FakeClientID(0);
1722                     if (!AddResource(other->resource, RT_INPUTCLIENT,
1723                                      (pointer) pWin))
1724                         return BadAlloc;
1725                 }
1726             } else {
1727                 wOtherInputMasks(pWin)->inputClients = other->next;
1728                 free(other);
1729             }
1730             RecalculateDeviceDeliverableEvents(pWin);
1731             return Success;
1732         }
1733         prev = other;
1734     }
1735     FatalError("client not on device event list");
1736 }
1737
1738 int
1739 SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
1740           xEvent * ev, Mask mask, int count)
1741 {
1742     WindowPtr pWin;
1743     WindowPtr effectiveFocus = NullWindow;      /* only set if dest==InputFocus */
1744     WindowPtr spriteWin = GetSpriteWindow(d);
1745
1746     if (dest == PointerWindow)
1747         pWin = spriteWin;
1748     else if (dest == InputFocus) {
1749         WindowPtr inputFocus;
1750
1751         if (!d->focus)
1752             inputFocus = spriteWin;
1753         else
1754             inputFocus = d->focus->win;
1755
1756         if (inputFocus == FollowKeyboardWin)
1757             inputFocus = inputInfo.keyboard->focus->win;
1758
1759         if (inputFocus == NoneWin)
1760             return Success;
1761
1762         /* If the input focus is PointerRootWin, send the event to where
1763          * the pointer is if possible, then perhaps propogate up to root. */
1764         if (inputFocus == PointerRootWin)
1765             inputFocus = GetCurrentRootWindow(d);
1766
1767         if (IsParent(inputFocus, spriteWin)) {
1768             effectiveFocus = inputFocus;
1769             pWin = spriteWin;
1770         } else
1771             effectiveFocus = pWin = inputFocus;
1772     } else
1773         dixLookupWindow(&pWin, dest, client, DixSendAccess);
1774     if (!pWin)
1775         return BadWindow;
1776     if ((propagate != xFalse) && (propagate != xTrue)) {
1777         client->errorValue = propagate;
1778         return BadValue;
1779     }
1780     ev->u.u.type |= 0x80;
1781     if (propagate) {
1782         for (; pWin; pWin = pWin->parent) {
1783             if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
1784                 return Success;
1785             if (pWin == effectiveFocus)
1786                 return Success;
1787             if (wOtherInputMasks(pWin))
1788                 mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
1789             if (!mask)
1790                 break;
1791         }
1792     } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
1793         DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
1794     return Success;
1795 }
1796
1797 int
1798 SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
1799 {
1800     int i;
1801     ButtonClassPtr b = dev->button;
1802
1803     if (b == NULL)
1804         return BadMatch;
1805
1806     if (nElts != b->numButtons) {
1807         client->errorValue = nElts;
1808         return BadValue;
1809     }
1810     if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
1811         return BadValue;
1812     for (i = 0; i < nElts; i++)
1813         if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
1814             return MappingBusy;
1815     for (i = 0; i < nElts; i++)
1816         b->map[i + 1] = map[i];
1817     return Success;
1818 }
1819
1820 int
1821 ChangeKeyMapping(ClientPtr client,
1822                  DeviceIntPtr dev,
1823                  unsigned len,
1824                  int type,
1825                  KeyCode firstKeyCode,
1826                  CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
1827 {
1828     KeySymsRec keysyms;
1829     KeyClassPtr k = dev->key;
1830
1831     if (k == NULL)
1832         return BadMatch;
1833
1834     if (len != (keyCodes * keySymsPerKeyCode))
1835         return BadLength;
1836
1837     if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
1838         (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
1839         client->errorValue = firstKeyCode;
1840         return BadValue;
1841     }
1842     if (keySymsPerKeyCode == 0) {
1843         client->errorValue = 0;
1844         return BadValue;
1845     }
1846     keysyms.minKeyCode = firstKeyCode;
1847     keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
1848     keysyms.mapWidth = keySymsPerKeyCode;
1849     keysyms.map = map;
1850
1851     XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
1852                           serverClient);
1853
1854     return Success;
1855 }
1856
1857 static void
1858 DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
1859 {
1860     WindowPtr parent;
1861
1862     /* Deactivate any grabs performed on this window, before making
1863      * any input focus changes.
1864      * Deactivating a device grab should cause focus events. */
1865
1866     if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
1867         (*dev->deviceGrab.DeactivateGrab) (dev);
1868
1869     /* If the focus window is a root window (ie. has no parent)
1870      * then don't delete the focus from it. */
1871
1872     if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
1873         int focusEventMode = NotifyNormal;
1874
1875         /* If a grab is in progress, then alter the mode of focus events. */
1876
1877         if (dev->deviceGrab.grab)
1878             focusEventMode = NotifyWhileGrabbed;
1879
1880         switch (dev->focus->revert) {
1881         case RevertToNone:
1882             if (!ActivateFocusInGrab(dev, pWin, NoneWin))
1883                 DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1884             dev->focus->win = NoneWin;
1885             dev->focus->traceGood = 0;
1886             break;
1887         case RevertToParent:
1888             parent = pWin;
1889             do {
1890                 parent = parent->parent;
1891                 dev->focus->traceGood--;
1892             }
1893             while (!parent->realized);
1894             if (!ActivateFocusInGrab(dev, pWin, parent))
1895                 DoFocusEvents(dev, pWin, parent, focusEventMode);
1896             dev->focus->win = parent;
1897             dev->focus->revert = RevertToNone;
1898             break;
1899         case RevertToPointerRoot:
1900             if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
1901                 DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
1902             dev->focus->win = PointerRootWin;
1903             dev->focus->traceGood = 0;
1904             break;
1905         case RevertToFollowKeyboard:
1906             {
1907                 DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
1908                 if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
1909                     kbd = inputInfo.keyboard;
1910             if (kbd->focus->win) {
1911                 if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
1912                     DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
1913                 dev->focus->win = FollowKeyboardWin;
1914                 dev->focus->traceGood = 0;
1915             } else {
1916                 if (!ActivateFocusInGrab(dev, pWin, NoneWin))
1917                     DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1918                 dev->focus->win = NoneWin;
1919                 dev->focus->traceGood = 0;
1920             }
1921             }
1922             break;
1923         }
1924     }
1925
1926     if (dev->valuator)
1927         if (dev->valuator->motionHintWindow == pWin)
1928             dev->valuator->motionHintWindow = NullWindow;
1929 }
1930
1931 void
1932 DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
1933 {
1934     int i;
1935     DeviceIntPtr dev;
1936     InputClientsPtr ic;
1937     struct _OtherInputMasks *inputMasks;
1938
1939     for (dev = inputInfo.devices; dev; dev = dev->next) {
1940         DeleteDeviceFromAnyExtEvents(pWin, dev);
1941     }
1942
1943     for (dev = inputInfo.off_devices; dev; dev = dev->next)
1944         DeleteDeviceFromAnyExtEvents(pWin, dev);
1945
1946     if (freeResources)
1947         while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
1948             ic = inputMasks->inputClients;
1949             for (i = 0; i < EMASKSIZE; i++)
1950                 inputMasks->dontPropagateMask[i] = 0;
1951             FreeResource(ic->resource, RT_NONE);
1952         }
1953 }
1954
1955 int
1956 MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
1957 {
1958     DeviceIntPtr dev;
1959
1960     dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
1961                     DixReadAccess);
1962     if (!dev)
1963         return 0;
1964
1965     if (pEvents->type == DeviceMotionNotify) {
1966         if (mask & DevicePointerMotionHintMask) {
1967             if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
1968                 return 1;       /* don't send, but pretend we did */
1969             }
1970             pEvents->detail = NotifyHint;
1971         } else {
1972             pEvents->detail = NotifyNormal;
1973         }
1974     }
1975     return 0;
1976 }
1977
1978 void
1979 CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
1980                              deviceKeyButtonPointer * xE, GrabPtr grab,
1981                              ClientPtr client, Mask deliveryMask)
1982 {
1983     DeviceIntPtr dev;
1984
1985     dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
1986                     DixGrabAccess);
1987     if (!dev)
1988         return;
1989
1990     if (type == DeviceMotionNotify)
1991         dev->valuator->motionHintWindow = pWin;
1992     else if ((type == DeviceButtonPress) && (!grab) &&
1993              (deliveryMask & DeviceButtonGrabMask)) {
1994         GrabRec tempGrab;
1995
1996         tempGrab.device = dev;
1997         tempGrab.resource = client->clientAsMask;
1998         tempGrab.window = pWin;
1999         tempGrab.ownerEvents =
2000             (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
2001         tempGrab.eventMask = deliveryMask;
2002         tempGrab.keyboardMode = GrabModeAsync;
2003         tempGrab.pointerMode = GrabModeAsync;
2004         tempGrab.confineTo = NullWindow;
2005         tempGrab.cursor = NullCursor;
2006         tempGrab.next = NULL;
2007         (*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
2008     }
2009 }
2010
2011 static Mask
2012 DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
2013 {
2014     InputClientsPtr other;
2015
2016     if (!wOtherInputMasks(pWin))
2017         return 0;
2018     for (other = wOtherInputMasks(pWin)->inputClients; other;
2019          other = other->next) {
2020         if (SameClient(other, client))
2021             return other->mask[dev->id];
2022     }
2023     return 0;
2024 }
2025
2026 void
2027 MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
2028 {
2029     WindowPtr pWin;
2030     GrabPtr grab = dev->deviceGrab.grab;
2031
2032     pWin = dev->valuator->motionHintWindow;
2033
2034     if ((grab && SameClient(grab, client) &&
2035          ((grab->eventMask & DevicePointerMotionHintMask) ||
2036           (grab->ownerEvents &&
2037            (DeviceEventMaskForClient(dev, pWin, client) &
2038             DevicePointerMotionHintMask)))) ||
2039         (!grab &&
2040          (DeviceEventMaskForClient(dev, pWin, client) &
2041           DevicePointerMotionHintMask)))
2042         dev->valuator->motionHintWindow = NullWindow;
2043 }
2044
2045 int
2046 DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
2047                              int maskndx)
2048 {
2049     struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2050
2051     if (mask & ~PropagateMask[maskndx]) {
2052         client->errorValue = mask;
2053         return BadValue;
2054     }
2055
2056     if (mask == 0) {
2057         if (inputMasks)
2058             inputMasks->dontPropagateMask[maskndx] = mask;
2059     } else {
2060         if (!inputMasks)
2061             AddExtensionClient(pWin, client, 0, 0);
2062         inputMasks = wOtherInputMasks(pWin);
2063         inputMasks->dontPropagateMask[maskndx] = mask;
2064     }
2065     RecalculateDeviceDeliverableEvents(pWin);
2066     if (ShouldFreeInputMasks(pWin, FALSE))
2067         FreeResource(inputMasks->inputClients->resource, RT_NONE);
2068     return Success;
2069 }
2070
2071 Bool
2072 ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
2073 {
2074     int i;
2075     Mask allInputEventMasks = 0;
2076     struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2077
2078     for (i = 0; i < EMASKSIZE; i++)
2079         allInputEventMasks |= inputMasks->dontPropagateMask[i];
2080     if (!ignoreSelectedEvents)
2081         for (i = 0; i < EMASKSIZE; i++)
2082             allInputEventMasks |= inputMasks->inputEvents[i];
2083     if (allInputEventMasks == 0)
2084         return TRUE;
2085     else
2086         return FALSE;
2087 }
2088
2089 /***********************************************************************
2090  *
2091  * Walk through the window tree, finding all clients that want to know
2092  * about the Event.
2093  *
2094  */
2095
2096 static void
2097 FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
2098                        xEvent * ev, int count)
2099 {
2100     WindowPtr p2;
2101
2102     while (p1) {
2103         p2 = p1->firstChild;
2104         DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
2105         FindInterestedChildren(dev, p2, mask, ev, count);
2106         p1 = p1->nextSib;
2107     }
2108 }
2109
2110 /***********************************************************************
2111  *
2112  * Send an event to interested clients in all windows on all screens.
2113  *
2114  */
2115
2116 void
2117 SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
2118 {
2119     int i;
2120     WindowPtr pWin, p1;
2121
2122     for (i = 0; i < screenInfo.numScreens; i++) {
2123         pWin = screenInfo.screens[i]->root;
2124         if (!pWin)
2125             continue;
2126         DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
2127         p1 = pWin->firstChild;
2128         FindInterestedChildren(dev, p1, mask, ev, count);
2129     }
2130 }
2131
2132 /**
2133  * Set the XI2 mask for the given client on the given window.
2134  * @param dev The device to set the mask for.
2135  * @param win The window to set the mask on.
2136  * @param client The client setting the mask.
2137  * @param len Number of bytes in mask.
2138  * @param mask Event mask in the form of (1 << eventtype)
2139  */
2140 int
2141 XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
2142                unsigned int len, unsigned char* mask)
2143 {
2144     OtherInputMasks *masks;
2145     InputClientsPtr others = NULL;
2146
2147     masks = wOtherInputMasks(win);
2148     if (masks)
2149     {
2150         for (others = wOtherInputMasks(win)->inputClients; others;
2151              others = others->next) {
2152             if (SameClient(others, client)) {
2153                 memset(others->xi2mask[dev->id], 0,
2154                        sizeof(others->xi2mask[dev->id]));
2155                 break;
2156             }
2157         }
2158     }
2159
2160     len = min(len, sizeof(others->xi2mask[dev->id]));
2161
2162     if (len && !others)
2163     {
2164         if (AddExtensionClient(win, client, 0, 0) != Success)
2165             return BadAlloc;
2166         others= wOtherInputMasks(win)->inputClients;
2167     }
2168
2169     if (others)
2170         memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id]));
2171
2172     if (len)
2173         memcpy(others->xi2mask[dev->id], mask, len);
2174
2175     RecalculateDeviceDeliverableEvents(win);
2176
2177     return Success;
2178 }