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