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