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