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