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