Add support for per-axis valuator modes (Relative/Absolute)
[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, int mode)
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     ax->mode = mode;
1148 }
1149
1150 static void
1151 FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
1152                      ButtonClassPtr b, ValuatorClassPtr v, int first)
1153 {
1154     ev->type = DeviceStateNotify;
1155     ev->deviceid = dev->id;
1156     ev->time = currentTime.milliseconds;
1157     ev->classes_reported = 0;
1158     ev->num_keys = 0;
1159     ev->num_buttons = 0;
1160     ev->num_valuators = 0;
1161
1162     if (b) {
1163         ev->classes_reported |= (1 << ButtonClass);
1164         ev->num_buttons = b->numButtons;
1165         memcpy((char*)ev->buttons, (char*)b->down, 4);
1166     } else if (k) {
1167         ev->classes_reported |= (1 << KeyClass);
1168         ev->num_keys = k->xkbInfo->desc->max_key_code -
1169                        k->xkbInfo->desc->min_key_code;
1170         memmove((char *)&ev->keys[0], (char *)k->down, 4);
1171     }
1172     if (v) {
1173         int nval = v->numAxes - first;
1174
1175         ev->classes_reported |= (1 << ValuatorClass);
1176         ev->classes_reported |= (dev->valuator->mode << ModeBitsShift);
1177         ev->num_valuators = nval < 3 ? nval : 3;
1178         switch (ev->num_valuators) {
1179         case 3:
1180             ev->valuator2 = v->axisVal[first + 2];
1181         case 2:
1182             ev->valuator1 = v->axisVal[first + 1];
1183         case 1:
1184             ev->valuator0 = v->axisVal[first];
1185             break;
1186         }
1187     }
1188 }
1189
1190 static void
1191 FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
1192                   int first)
1193 {
1194     int nval = v->numAxes - first;
1195
1196     ev->type = DeviceValuator;
1197     ev->deviceid = dev->id;
1198     ev->num_valuators = nval < 3 ? nval : 3;
1199     ev->first_valuator = first;
1200     switch (ev->num_valuators) {
1201     case 3:
1202         ev->valuator2 = v->axisVal[first + 2];
1203     case 2:
1204         ev->valuator1 = v->axisVal[first + 1];
1205     case 1:
1206         ev->valuator0 = v->axisVal[first];
1207         break;
1208     }
1209     first += ev->num_valuators;
1210 }
1211
1212 void
1213 DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
1214                  WindowPtr pWin)
1215 {
1216     deviceFocus event;
1217     xXIFocusInEvent *xi2event;
1218     DeviceIntPtr mouse;
1219     int btlen, len, i;
1220
1221     mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev;
1222
1223     /* XI 2 event */
1224     btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
1225     btlen = bytes_to_int32(btlen);
1226     len = sizeof(xXIFocusInEvent) + btlen * 4;
1227
1228     xi2event = calloc(1, len);
1229     xi2event->type         = GenericEvent;
1230     xi2event->extension    = IReqCode;
1231     xi2event->evtype       = type;
1232     xi2event->length       = bytes_to_int32(len - sizeof(xEvent));
1233     xi2event->buttons_len  = btlen;
1234     xi2event->detail       = detail;
1235     xi2event->time         = currentTime.milliseconds;
1236     xi2event->deviceid     = dev->id;
1237     xi2event->sourceid     = dev->id; /* a device doesn't change focus by itself */
1238     xi2event->mode         = mode;
1239     xi2event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
1240     xi2event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
1241
1242     for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
1243         if (BitIsOn(mouse->button->down, i))
1244             SetBit(&xi2event[1], i);
1245
1246     if (dev->key)
1247     {
1248         xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
1249         xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
1250         xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
1251         xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
1252
1253         xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
1254         xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
1255         xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
1256         xi2event->group.effective_group = dev->key->xkbInfo->state.group;
1257     }
1258
1259     FixUpEventFromWindow(dev, (xEvent*)xi2event, pWin, None, FALSE);
1260
1261     DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
1262                           GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
1263
1264     free(xi2event);
1265
1266     /* XI 1.x event */
1267     event.deviceid = dev->id;
1268     event.mode = mode;
1269     event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
1270     event.detail = detail;
1271     event.window = pWin->drawable.id;
1272     event.time = currentTime.milliseconds;
1273
1274     DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
1275                                 DeviceFocusChangeMask, NullGrab);
1276
1277     if ((type == DeviceFocusIn) &&
1278         (wOtherInputMasks(pWin)) &&
1279         (wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
1280     {
1281         int evcount = 1;
1282         deviceStateNotify *ev, *sev;
1283         deviceKeyStateNotify *kev;
1284         deviceButtonStateNotify *bev;
1285
1286         KeyClassPtr k;
1287         ButtonClassPtr b;
1288         ValuatorClassPtr v;
1289         int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
1290
1291         if ((b = dev->button) != NULL) {
1292             nbuttons = b->numButtons;
1293             if (nbuttons > 32)
1294                 evcount++;
1295         }
1296         if ((k = dev->key) != NULL) {
1297             nkeys = k->xkbInfo->desc->max_key_code -
1298                     k->xkbInfo->desc->min_key_code;
1299             if (nkeys > 32)
1300                 evcount++;
1301             if (nbuttons > 0) {
1302                 evcount++;
1303             }
1304         }
1305         if ((v = dev->valuator) != NULL) {
1306             nval = v->numAxes;
1307
1308             if (nval > 3)
1309                 evcount++;
1310             if (nval > 6) {
1311                 if (!(k && b))
1312                     evcount++;
1313                 if (nval > 9)
1314                     evcount += ((nval - 7) / 3);
1315             }
1316         }
1317
1318         sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
1319         FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
1320
1321         if (b != NULL) {
1322             FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
1323             first += 3;
1324             nval -= 3;
1325             if (nbuttons > 32) {
1326                 (ev - 1)->deviceid |= MORE_EVENTS;
1327                 bev = (deviceButtonStateNotify *) ev++;
1328                 bev->type = DeviceButtonStateNotify;
1329                 bev->deviceid = dev->id;
1330                 memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
1331             }
1332             if (nval > 0) {
1333                 (ev - 1)->deviceid |= MORE_EVENTS;
1334                 FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1335                 first += 3;
1336                 nval -= 3;
1337             }
1338         }
1339
1340         if (k != NULL) {
1341             FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
1342             first += 3;
1343             nval -= 3;
1344             if (nkeys > 32) {
1345                 (ev - 1)->deviceid |= MORE_EVENTS;
1346                 kev = (deviceKeyStateNotify *) ev++;
1347                 kev->type = DeviceKeyStateNotify;
1348                 kev->deviceid = dev->id;
1349                 memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
1350             }
1351             if (nval > 0) {
1352                 (ev - 1)->deviceid |= MORE_EVENTS;
1353                 FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1354                 first += 3;
1355                 nval -= 3;
1356             }
1357         }
1358
1359         while (nval > 0) {
1360             FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
1361             first += 3;
1362             nval -= 3;
1363             if (nval > 0) {
1364                 (ev - 1)->deviceid |= MORE_EVENTS;
1365                 FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1366                 first += 3;
1367                 nval -= 3;
1368             }
1369         }
1370
1371         DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
1372                                     DeviceStateNotifyMask, NullGrab);
1373         free(sev);
1374     }
1375 }
1376
1377 int
1378 CheckGrabValues(ClientPtr client, GrabParameters* param)
1379 {
1380     if (param->grabtype != GRABTYPE_CORE &&
1381         param->grabtype != GRABTYPE_XI &&
1382         param->grabtype != GRABTYPE_XI2)
1383     {
1384         ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
1385         return BadImplementation;
1386     }
1387
1388     if ((param->this_device_mode != GrabModeSync) &&
1389         (param->this_device_mode != GrabModeAsync)) {
1390         client->errorValue = param->this_device_mode;
1391         return BadValue;
1392     }
1393     if ((param->other_devices_mode != GrabModeSync) &&
1394         (param->other_devices_mode != GrabModeAsync)) {
1395         client->errorValue = param->other_devices_mode;
1396         return BadValue;
1397     }
1398
1399     if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
1400         (param->modifiers & ~AllModifiersMask)) {
1401         client->errorValue = param->modifiers;
1402         return BadValue;
1403     }
1404
1405     if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
1406         client->errorValue = param->ownerEvents;
1407         return BadValue;
1408     }
1409     return Success;
1410 }
1411
1412 int
1413 GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
1414            int button, GrabParameters *param, GrabType grabtype,
1415            GrabMask *mask)
1416 {
1417     WindowPtr pWin, confineTo;
1418     CursorPtr cursor;
1419     GrabPtr grab;
1420     int rc, type = -1;
1421     Mask access_mode = DixGrabAccess;
1422
1423     rc = CheckGrabValues(client, param);
1424     if (rc != Success)
1425         return rc;
1426     if (param->confineTo == None)
1427         confineTo = NullWindow;
1428     else {
1429         rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
1430         if (rc != Success)
1431             return rc;
1432     }
1433     if (param->cursor == None)
1434         cursor = NullCursor;
1435     else {
1436         rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
1437                                      RT_CURSOR, client, DixUseAccess);
1438         if (rc != Success)
1439         {
1440             client->errorValue = param->cursor;
1441             return rc;
1442         }
1443         access_mode |= DixForceAccess;
1444     }
1445     if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1446         access_mode |= DixFreezeAccess;
1447     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1448     if (rc != Success)
1449         return rc;
1450     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1451     if (rc != Success)
1452         return rc;
1453
1454     if (grabtype == GRABTYPE_XI)
1455         type = DeviceButtonPress;
1456     else if (grabtype == GRABTYPE_XI2)
1457         type = XI_ButtonPress;
1458
1459     grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
1460                       mask, param, type, button, confineTo, cursor);
1461     if (!grab)
1462         return BadAlloc;
1463     return AddPassiveGrabToList(client, grab);
1464 }
1465
1466 /**
1467  * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If
1468  * grabtype is GRABTYPE_XI2, the key is a keysym.
1469  */
1470 int
1471 GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
1472         int key, GrabParameters *param, GrabType grabtype, GrabMask *mask)
1473 {
1474     WindowPtr pWin;
1475     GrabPtr grab;
1476     KeyClassPtr k = dev->key;
1477     Mask access_mode = DixGrabAccess;
1478     int rc, type = -1;
1479
1480     rc = CheckGrabValues(client, param);
1481     if (rc != Success)
1482         return rc;
1483     if (k == NULL)
1484         return BadMatch;
1485     if (grabtype == GRABTYPE_XI)
1486     {
1487         if ((key > k->xkbInfo->desc->max_key_code ||
1488                     key < k->xkbInfo->desc->min_key_code)
1489                 && (key != AnyKey)) {
1490             client->errorValue = key;
1491             return BadValue;
1492         }
1493         type = DeviceKeyPress;
1494     } else if (grabtype == GRABTYPE_XI2)
1495         type = XI_KeyPress;
1496
1497     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1498     if (rc != Success)
1499         return rc;
1500     if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1501         access_mode |= DixFreezeAccess;
1502     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1503     if (rc != Success)
1504         return rc;
1505
1506     grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
1507                       mask, param, type, key, NULL, NULL);
1508     if (!grab)
1509         return BadAlloc;
1510     return AddPassiveGrabToList(client, grab);
1511 }
1512
1513 /* Enter/FocusIn grab */
1514 int
1515 GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
1516            GrabParameters *param, GrabMask *mask)
1517 {
1518     WindowPtr pWin;
1519     CursorPtr cursor;
1520     GrabPtr grab;
1521     Mask access_mode = DixGrabAccess;
1522     int rc;
1523
1524     rc = CheckGrabValues(client, param);
1525     if (rc != Success)
1526         return rc;
1527
1528     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1529     if (rc != Success)
1530         return rc;
1531     if (param->cursor == None)
1532         cursor = NullCursor;
1533     else {
1534         rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
1535                                      RT_CURSOR, client, DixUseAccess);
1536         if (rc != Success)
1537         {
1538             client->errorValue = param->cursor;
1539             return rc;
1540         }
1541         access_mode |= DixForceAccess;
1542     }
1543     if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1544         access_mode |= DixFreezeAccess;
1545     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1546     if (rc != Success)
1547         return rc;
1548
1549     grab = CreateGrab(client->index, dev, dev, pWin, GRABTYPE_XI2,
1550                       mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
1551                       0, NULL, cursor);
1552
1553     if (!grab)
1554         return BadAlloc;
1555
1556     return AddPassiveGrabToList(client, grab);
1557 }
1558
1559 int
1560 SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
1561                 Mask mask, Mask exclusivemasks)
1562 {
1563     int mskidx = dev->id;
1564     int i, ret;
1565     Mask check;
1566     InputClientsPtr others;
1567
1568     check = (mask & exclusivemasks);
1569     if (wOtherInputMasks(pWin)) {
1570         if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {      /* It is illegal for two different
1571                                                                          * clients to select on any of the
1572                                                                          * events for maskcheck. However,
1573                                                                          * it is OK, for some client to
1574                                                                          * continue selecting on one of those
1575                                                                          * events.  */
1576             for (others = wOtherInputMasks(pWin)->inputClients; others;
1577                  others = others->next) {
1578                 if (!SameClient(others, client) && (check &
1579                                                     others->mask[mskidx]))
1580                     return BadAccess;
1581             }
1582         }
1583         for (others = wOtherInputMasks(pWin)->inputClients; others;
1584              others = others->next) {
1585             if (SameClient(others, client)) {
1586                 check = others->mask[mskidx];
1587                 others->mask[mskidx] = mask;
1588                 if (mask == 0) {
1589                     for (i = 0; i < EMASKSIZE; i++)
1590                         if (i != mskidx && others->mask[i] != 0)
1591                             break;
1592                     if (i == EMASKSIZE) {
1593                         RecalculateDeviceDeliverableEvents(pWin);
1594                         if (ShouldFreeInputMasks(pWin, FALSE))
1595                             FreeResource(others->resource, RT_NONE);
1596                         return Success;
1597                     }
1598                 }
1599                 goto maskSet;
1600             }
1601         }
1602     }
1603     check = 0;
1604     if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
1605         return ret;
1606   maskSet:
1607     if (dev->valuator)
1608         if ((dev->valuator->motionHintWindow == pWin) &&
1609             (mask & DevicePointerMotionHintMask) &&
1610             !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
1611             dev->valuator->motionHintWindow = NullWindow;
1612     RecalculateDeviceDeliverableEvents(pWin);
1613     return Success;
1614 }
1615
1616 int
1617 AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
1618 {
1619     InputClientsPtr others;
1620
1621     if (!pWin->optional && !MakeWindowOptional(pWin))
1622         return BadAlloc;
1623     others = calloc(1, sizeof(InputClients));
1624     if (!others)
1625         return BadAlloc;
1626     if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
1627         return BadAlloc;
1628     others->mask[mskidx] = mask;
1629     others->resource = FakeClientID(client->index);
1630     others->next = pWin->optional->inputMasks->inputClients;
1631     pWin->optional->inputMasks->inputClients = others;
1632     if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
1633         return BadAlloc;
1634     return Success;
1635 }
1636
1637 static Bool
1638 MakeInputMasks(WindowPtr pWin)
1639 {
1640     struct _OtherInputMasks *imasks;
1641
1642     imasks = calloc(1, sizeof(struct _OtherInputMasks));
1643     if (!imasks)
1644         return FALSE;
1645     pWin->optional->inputMasks = imasks;
1646     return TRUE;
1647 }
1648
1649 void
1650 RecalculateDeviceDeliverableEvents(WindowPtr pWin)
1651 {
1652     InputClientsPtr others;
1653     struct _OtherInputMasks *inputMasks;        /* default: NULL */
1654     WindowPtr pChild, tmp;
1655     int i, j;
1656
1657     pChild = pWin;
1658     while (1) {
1659         if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
1660             for (i = 0; i < EMASKSIZE; i++)
1661                 memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i]));
1662             for (others = inputMasks->inputClients; others;
1663                  others = others->next) {
1664                 for (i = 0; i < EMASKSIZE; i++)
1665                     inputMasks->inputEvents[i] |= others->mask[i];
1666                 for (i = 0; i < EMASKSIZE; i++)
1667                     for (j = 0; j < XI2MASKSIZE; j++)
1668                         inputMasks->xi2mask[i][j] |= others->xi2mask[i][j];
1669             }
1670             for (i = 0; i < EMASKSIZE; i++)
1671                 inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
1672             for (tmp = pChild->parent; tmp; tmp = tmp->parent)
1673                 if (wOtherInputMasks(tmp))
1674                     for (i = 0; i < EMASKSIZE; i++)
1675                         inputMasks->deliverableEvents[i] |=
1676                             (wOtherInputMasks(tmp)->deliverableEvents[i]
1677                              & ~inputMasks->
1678                              dontPropagateMask[i] & PropagateMask[i]);
1679         }
1680         if (pChild->firstChild) {
1681             pChild = pChild->firstChild;
1682             continue;
1683         }
1684         while (!pChild->nextSib && (pChild != pWin))
1685             pChild = pChild->parent;
1686         if (pChild == pWin)
1687             break;
1688         pChild = pChild->nextSib;
1689     }
1690 }
1691
1692 int
1693 InputClientGone(WindowPtr pWin, XID id)
1694 {
1695     InputClientsPtr other, prev;
1696
1697     if (!wOtherInputMasks(pWin))
1698         return Success;
1699     prev = 0;
1700     for (other = wOtherInputMasks(pWin)->inputClients; other;
1701          other = other->next) {
1702         if (other->resource == id) {
1703             if (prev) {
1704                 prev->next = other->next;
1705                 free(other);
1706             } else if (!(other->next)) {
1707                 if (ShouldFreeInputMasks(pWin, TRUE)) {
1708                     wOtherInputMasks(pWin)->inputClients = other->next;
1709                     free(wOtherInputMasks(pWin));
1710                     pWin->optional->inputMasks = (OtherInputMasks *) NULL;
1711                     CheckWindowOptionalNeed(pWin);
1712                     free(other);
1713                 } else {
1714                     other->resource = FakeClientID(0);
1715                     if (!AddResource(other->resource, RT_INPUTCLIENT,
1716                                      (pointer) pWin))
1717                         return BadAlloc;
1718                 }
1719             } else {
1720                 wOtherInputMasks(pWin)->inputClients = other->next;
1721                 free(other);
1722             }
1723             RecalculateDeviceDeliverableEvents(pWin);
1724             return Success;
1725         }
1726         prev = other;
1727     }
1728     FatalError("client not on device event list");
1729 }
1730
1731 int
1732 SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
1733           xEvent * ev, Mask mask, int count)
1734 {
1735     WindowPtr pWin;
1736     WindowPtr effectiveFocus = NullWindow;      /* only set if dest==InputFocus */
1737     WindowPtr spriteWin = GetSpriteWindow(d);
1738
1739     if (dest == PointerWindow)
1740         pWin = spriteWin;
1741     else if (dest == InputFocus) {
1742         WindowPtr inputFocus;
1743
1744         if (!d->focus)
1745             inputFocus = spriteWin;
1746         else
1747             inputFocus = d->focus->win;
1748
1749         if (inputFocus == FollowKeyboardWin)
1750             inputFocus = inputInfo.keyboard->focus->win;
1751
1752         if (inputFocus == NoneWin)
1753             return Success;
1754
1755         /* If the input focus is PointerRootWin, send the event to where
1756          * the pointer is if possible, then perhaps propogate up to root. */
1757         if (inputFocus == PointerRootWin)
1758             inputFocus = GetCurrentRootWindow(d);
1759
1760         if (IsParent(inputFocus, spriteWin)) {
1761             effectiveFocus = inputFocus;
1762             pWin = spriteWin;
1763         } else
1764             effectiveFocus = pWin = inputFocus;
1765     } else
1766         dixLookupWindow(&pWin, dest, client, DixSendAccess);
1767     if (!pWin)
1768         return BadWindow;
1769     if ((propagate != xFalse) && (propagate != xTrue)) {
1770         client->errorValue = propagate;
1771         return BadValue;
1772     }
1773     ev->u.u.type |= 0x80;
1774     if (propagate) {
1775         for (; pWin; pWin = pWin->parent) {
1776             if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
1777                 return Success;
1778             if (pWin == effectiveFocus)
1779                 return Success;
1780             if (wOtherInputMasks(pWin))
1781                 mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
1782             if (!mask)
1783                 break;
1784         }
1785     } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
1786         DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
1787     return Success;
1788 }
1789
1790 int
1791 SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
1792 {
1793     int i;
1794     ButtonClassPtr b = dev->button;
1795
1796     if (b == NULL)
1797         return BadMatch;
1798
1799     if (nElts != b->numButtons) {
1800         client->errorValue = nElts;
1801         return BadValue;
1802     }
1803     if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
1804         return BadValue;
1805     for (i = 0; i < nElts; i++)
1806         if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
1807             return MappingBusy;
1808     for (i = 0; i < nElts; i++)
1809         b->map[i + 1] = map[i];
1810     return Success;
1811 }
1812
1813 int
1814 ChangeKeyMapping(ClientPtr client,
1815                  DeviceIntPtr dev,
1816                  unsigned len,
1817                  int type,
1818                  KeyCode firstKeyCode,
1819                  CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
1820 {
1821     KeySymsRec keysyms;
1822     KeyClassPtr k = dev->key;
1823
1824     if (k == NULL)
1825         return BadMatch;
1826
1827     if (len != (keyCodes * keySymsPerKeyCode))
1828         return BadLength;
1829
1830     if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
1831         (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
1832         client->errorValue = firstKeyCode;
1833         return BadValue;
1834     }
1835     if (keySymsPerKeyCode == 0) {
1836         client->errorValue = 0;
1837         return BadValue;
1838     }
1839     keysyms.minKeyCode = firstKeyCode;
1840     keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
1841     keysyms.mapWidth = keySymsPerKeyCode;
1842     keysyms.map = map;
1843
1844     XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
1845                           serverClient);
1846
1847     return Success;
1848 }
1849
1850 static void
1851 DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
1852 {
1853     WindowPtr parent;
1854
1855     /* Deactivate any grabs performed on this window, before making
1856      * any input focus changes.
1857      * Deactivating a device grab should cause focus events. */
1858
1859     if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
1860         (*dev->deviceGrab.DeactivateGrab) (dev);
1861
1862     /* If the focus window is a root window (ie. has no parent)
1863      * then don't delete the focus from it. */
1864
1865     if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
1866         int focusEventMode = NotifyNormal;
1867
1868         /* If a grab is in progress, then alter the mode of focus events. */
1869
1870         if (dev->deviceGrab.grab)
1871             focusEventMode = NotifyWhileGrabbed;
1872
1873         switch (dev->focus->revert) {
1874         case RevertToNone:
1875             if (!ActivateFocusInGrab(dev, pWin, NoneWin))
1876                 DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1877             dev->focus->win = NoneWin;
1878             dev->focus->traceGood = 0;
1879             break;
1880         case RevertToParent:
1881             parent = pWin;
1882             do {
1883                 parent = parent->parent;
1884                 dev->focus->traceGood--;
1885             }
1886             while (!parent->realized);
1887             if (!ActivateFocusInGrab(dev, pWin, parent))
1888                 DoFocusEvents(dev, pWin, parent, focusEventMode);
1889             dev->focus->win = parent;
1890             dev->focus->revert = RevertToNone;
1891             break;
1892         case RevertToPointerRoot:
1893             if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
1894                 DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
1895             dev->focus->win = PointerRootWin;
1896             dev->focus->traceGood = 0;
1897             break;
1898         case RevertToFollowKeyboard:
1899             {
1900                 DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
1901                 if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
1902                     kbd = inputInfo.keyboard;
1903             if (kbd->focus->win) {
1904                 if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
1905                     DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
1906                 dev->focus->win = FollowKeyboardWin;
1907                 dev->focus->traceGood = 0;
1908             } else {
1909                 if (!ActivateFocusInGrab(dev, pWin, NoneWin))
1910                     DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1911                 dev->focus->win = NoneWin;
1912                 dev->focus->traceGood = 0;
1913             }
1914             }
1915             break;
1916         }
1917     }
1918
1919     if (dev->valuator)
1920         if (dev->valuator->motionHintWindow == pWin)
1921             dev->valuator->motionHintWindow = NullWindow;
1922 }
1923
1924 void
1925 DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
1926 {
1927     int i;
1928     DeviceIntPtr dev;
1929     InputClientsPtr ic;
1930     struct _OtherInputMasks *inputMasks;
1931
1932     for (dev = inputInfo.devices; dev; dev = dev->next) {
1933         DeleteDeviceFromAnyExtEvents(pWin, dev);
1934     }
1935
1936     for (dev = inputInfo.off_devices; dev; dev = dev->next)
1937         DeleteDeviceFromAnyExtEvents(pWin, dev);
1938
1939     if (freeResources)
1940         while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
1941             ic = inputMasks->inputClients;
1942             for (i = 0; i < EMASKSIZE; i++)
1943                 inputMasks->dontPropagateMask[i] = 0;
1944             FreeResource(ic->resource, RT_NONE);
1945         }
1946 }
1947
1948 int
1949 MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
1950 {
1951     DeviceIntPtr dev;
1952
1953     dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
1954                     DixReadAccess);
1955     if (!dev)
1956         return 0;
1957
1958     if (pEvents->type == DeviceMotionNotify) {
1959         if (mask & DevicePointerMotionHintMask) {
1960             if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
1961                 return 1;       /* don't send, but pretend we did */
1962             }
1963             pEvents->detail = NotifyHint;
1964         } else {
1965             pEvents->detail = NotifyNormal;
1966         }
1967     }
1968     return 0;
1969 }
1970
1971 void
1972 CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
1973                              deviceKeyButtonPointer * xE, GrabPtr grab,
1974                              ClientPtr client, Mask deliveryMask)
1975 {
1976     DeviceIntPtr dev;
1977
1978     dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
1979                     DixGrabAccess);
1980     if (!dev)
1981         return;
1982
1983     if (type == DeviceMotionNotify)
1984         dev->valuator->motionHintWindow = pWin;
1985     else if ((type == DeviceButtonPress) && (!grab) &&
1986              (deliveryMask & DeviceButtonGrabMask)) {
1987         GrabRec tempGrab;
1988
1989         tempGrab.device = dev;
1990         tempGrab.resource = client->clientAsMask;
1991         tempGrab.window = pWin;
1992         tempGrab.ownerEvents =
1993             (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
1994         tempGrab.eventMask = deliveryMask;
1995         tempGrab.keyboardMode = GrabModeAsync;
1996         tempGrab.pointerMode = GrabModeAsync;
1997         tempGrab.confineTo = NullWindow;
1998         tempGrab.cursor = NullCursor;
1999         tempGrab.next = NULL;
2000         (*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
2001     }
2002 }
2003
2004 static Mask
2005 DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
2006 {
2007     InputClientsPtr other;
2008
2009     if (!wOtherInputMasks(pWin))
2010         return 0;
2011     for (other = wOtherInputMasks(pWin)->inputClients; other;
2012          other = other->next) {
2013         if (SameClient(other, client))
2014             return other->mask[dev->id];
2015     }
2016     return 0;
2017 }
2018
2019 void
2020 MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
2021 {
2022     WindowPtr pWin;
2023     GrabPtr grab = dev->deviceGrab.grab;
2024
2025     pWin = dev->valuator->motionHintWindow;
2026
2027     if ((grab && SameClient(grab, client) &&
2028          ((grab->eventMask & DevicePointerMotionHintMask) ||
2029           (grab->ownerEvents &&
2030            (DeviceEventMaskForClient(dev, pWin, client) &
2031             DevicePointerMotionHintMask)))) ||
2032         (!grab &&
2033          (DeviceEventMaskForClient(dev, pWin, client) &
2034           DevicePointerMotionHintMask)))
2035         dev->valuator->motionHintWindow = NullWindow;
2036 }
2037
2038 int
2039 DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
2040                              int maskndx)
2041 {
2042     struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2043
2044     if (mask & ~PropagateMask[maskndx]) {
2045         client->errorValue = mask;
2046         return BadValue;
2047     }
2048
2049     if (mask == 0) {
2050         if (inputMasks)
2051             inputMasks->dontPropagateMask[maskndx] = mask;
2052     } else {
2053         if (!inputMasks)
2054             AddExtensionClient(pWin, client, 0, 0);
2055         inputMasks = wOtherInputMasks(pWin);
2056         inputMasks->dontPropagateMask[maskndx] = mask;
2057     }
2058     RecalculateDeviceDeliverableEvents(pWin);
2059     if (ShouldFreeInputMasks(pWin, FALSE))
2060         FreeResource(inputMasks->inputClients->resource, RT_NONE);
2061     return Success;
2062 }
2063
2064 Bool
2065 ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
2066 {
2067     int i;
2068     Mask allInputEventMasks = 0;
2069     struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2070
2071     for (i = 0; i < EMASKSIZE; i++)
2072         allInputEventMasks |= inputMasks->dontPropagateMask[i];
2073     if (!ignoreSelectedEvents)
2074         for (i = 0; i < EMASKSIZE; i++)
2075             allInputEventMasks |= inputMasks->inputEvents[i];
2076     if (allInputEventMasks == 0)
2077         return TRUE;
2078     else
2079         return FALSE;
2080 }
2081
2082 /***********************************************************************
2083  *
2084  * Walk through the window tree, finding all clients that want to know
2085  * about the Event.
2086  *
2087  */
2088
2089 static void
2090 FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
2091                        xEvent * ev, int count)
2092 {
2093     WindowPtr p2;
2094
2095     while (p1) {
2096         p2 = p1->firstChild;
2097         DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
2098         FindInterestedChildren(dev, p2, mask, ev, count);
2099         p1 = p1->nextSib;
2100     }
2101 }
2102
2103 /***********************************************************************
2104  *
2105  * Send an event to interested clients in all windows on all screens.
2106  *
2107  */
2108
2109 void
2110 SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
2111 {
2112     int i;
2113     WindowPtr pWin, p1;
2114
2115     for (i = 0; i < screenInfo.numScreens; i++) {
2116         pWin = screenInfo.screens[i]->root;
2117         if (!pWin)
2118             continue;
2119         DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
2120         p1 = pWin->firstChild;
2121         FindInterestedChildren(dev, p1, mask, ev, count);
2122     }
2123 }
2124
2125 /**
2126  * Set the XI2 mask for the given client on the given window.
2127  * @param dev The device to set the mask for.
2128  * @param win The window to set the mask on.
2129  * @param client The client setting the mask.
2130  * @param len Number of bytes in mask.
2131  * @param mask Event mask in the form of (1 << eventtype)
2132  */
2133 int
2134 XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
2135                unsigned int len, unsigned char* mask)
2136 {
2137     OtherInputMasks *masks;
2138     InputClientsPtr others = NULL;
2139
2140     masks = wOtherInputMasks(win);
2141     if (masks)
2142     {
2143         for (others = wOtherInputMasks(win)->inputClients; others;
2144              others = others->next) {
2145             if (SameClient(others, client)) {
2146                 memset(others->xi2mask[dev->id], 0,
2147                        sizeof(others->xi2mask[dev->id]));
2148                 break;
2149             }
2150         }
2151     }
2152
2153     len = min(len, sizeof(others->xi2mask[dev->id]));
2154
2155     if (len && !others)
2156     {
2157         if (AddExtensionClient(win, client, 0, 0) != Success)
2158             return BadAlloc;
2159         others= wOtherInputMasks(win)->inputClients;
2160     }
2161
2162     if (others)
2163         memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id]));
2164
2165     if (len)
2166         memcpy(others->xi2mask[dev->id], mask, len);
2167
2168     RecalculateDeviceDeliverableEvents(win);
2169
2170     return Success;
2171 }