9d43564f86609ac875a2f176949bb5ccfe9fa67d
[glsdk/xserver.git] / Xi / exevents.c
1 /************************************************************
3 Copyright 1989, 1998  The Open Group
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.
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
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.
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.
25 Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
27                         All Rights Reserved
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.
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.
45 ********************************************************/
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  */
55 #ifdef HAVE_DIX_CONFIG_H
56 #include <dix-config.h>
57 #endif
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"
82 #include <X11/extensions/XKBproto.h>
83 #include "xkbsrv.h"
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 )
92 Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
93                                  Bool   /* ignoreSelectedEvents */
94     );
95 static Bool MakeInputMasks(WindowPtr    /* pWin */
96     );
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)
106     DeviceIntPtr current_ptr = PickPointer(client);
107     DeviceIntPtr current_kbd = GetPairedDevice(current_ptr);
109     if (dev == current_kbd || dev == current_ptr)
110         return 1;
112     return 0;
115 Bool
116 IsPointerEvent(InternalEvent* event)
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;
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)
138     DeviceIntPtr pDev = NULL;
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;
150         id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
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;
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  */
186 void
187 CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
189     KeyClassPtr mk = master->key;
191     if (device == master)
192         return;
194     mk->sourceid = device->id;
197     if (!XkbCopyDeviceKeymap(master, device))
198         FatalError("Couldn't pivot keymap from device to core!\n");
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)
209     ClassesPtr classes;
212     if (from->intfeed)
213     {
214         IntegerFeedbackPtr *i, it;
216         if (!to->intfeed)
217         {
218             classes = to->unused_classes;
219             to->intfeed = classes->intfeed;
220             classes->intfeed = NULL;
221         }
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;
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     }
248     if (from->stringfeed)
249     {
250         StringFeedbackPtr *s, it;
252         if (!to->stringfeed)
253         {
254             classes = to->unused_classes;
255             to->stringfeed = classes->stringfeed;
256             classes->stringfeed = NULL;
257         }
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;
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     }
284     if (from->bell)
285     {
286         BellFeedbackPtr *b, it;
288         if (!to->bell)
289         {
290             classes = to->unused_classes;
291             to->bell = classes->bell;
292             classes->bell = NULL;
293         }
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;
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     }
321     if (from->leds)
322     {
323         LedFeedbackPtr *l, it;
325         if (!to->leds)
326         {
327             classes = to->unused_classes;
328             to->leds = classes->leds;
329             classes->leds = NULL;
330         }
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);
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     }
361 static void
362 DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
364     ClassesPtr classes;
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;
373         if (!to->kbdfeed)
374         {
375             classes = to->unused_classes;
377             to->kbdfeed = classes->kbdfeed;
378             if (!to->kbdfeed)
379                 InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
380             classes->kbdfeed = NULL;
381         }
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);
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     }
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         }
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     }
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;
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     }
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;
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;
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     }
495 static void
496 DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
498     ClassesPtr classes;
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         }
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;
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     }
536     if (from->valuator)
537     {
538         ValuatorClassPtr v;
540         if (!to->valuator)
541         {
542             classes = to->unused_classes;
543             to->valuator = classes->valuator;
544             if (to->valuator)
545                 classes->valuator = NULL;
546         }
548         v = AllocValuatorClass(to->valuator, from->valuator->numAxes);
550         if (!v)
551             FatalError("[Xi] no memory for class shift.\n");
553         to->valuator = v;
554         memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
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     }
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         }
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);
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     }
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     }
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)
640     /* generic feedback classes, not tied to pointer and/or keyboard */
641     DeepCopyFeedbackClasses(from, to);
643     if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
644         DeepCopyKeyboardClasses(from, to);
645     if ((dce->flags & DEVCHANGE_POINTER_EVENT))
646         DeepCopyPointerClasses(from, to);
650 /**
651  * Send an XI2 DeviceChangedEvent to all interested clients.
652  */
653 void
654 XISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChangedEvent *dce)
656     xXIDeviceChangedEvent *dcce;
657     int rc;
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     }
666     /* we don't actually swap if there's a NullClient, swapping is done
667      * later when event is delivered. */
668     SendEventToAllWindows(master, XI_DeviceChangedMask, (xEvent*)dcce, 1);
669     free(dcce);
672 static void
673 ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
675     DeviceIntPtr slave;
676     int rc;
678     /* For now, we don't have devices that change physically. */
679     if (!IsMaster(device))
680         return;
682     rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
684     if (rc != Success)
685         return; /* Device has disappeared */
687     if (IsMaster(slave))
688         return;
690     if (IsFloating(slave))
691         return; /* set floating since the event */
693     if (GetMaster(slave, MASTER_ATTACHED)->id != dce->masterid)
694         return; /* not our slave anymore, don't care */
696     /* FIXME: we probably need to send a DCE for the new slave now */
698     device->public.devicePrivate = slave->public.devicePrivate;
700     /* FIXME: the classes may have changed since we generated the event. */
701     DeepCopyDeviceClasses(slave, device, dce);
702     XISendDeviceChangedEvent(slave, device, dce);
705 /**
706  * Update the device state according to the data in the event.
707  *
708  * return values are
709  *   DEFAULT ... process as normal
710  *   DONT_PROCESS ... return immediately from caller
711  */
712 #define DEFAULT 0
713 #define DONT_PROCESS 1
714 int
715 UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
717     int i;
718     int key = 0,
719         bit = 0,
720         last_valuator;
722     KeyClassPtr k       = NULL;
723     ButtonClassPtr b    = NULL;
724     ValuatorClassPtr v  = NULL;
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     }
748     k = device->key;
749     v = device->valuator;
750     b = device->button;
752     key = event->detail.key;
753     bit = 1 << (key & 7);
755     /* Update device axis */
756     /* Check valuators first */
757     last_valuator = -1;
758     for (i = 0; i < MAX_VALUATORS; i++)
759     {
760         if (BitIsOn(&event->valuators.mask, i))
761         {
762             if (!v)
763             {
764                 ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
765                         "Ignoring event.\n", device->name);
766                 return DONT_PROCESS;
767             } else if (v->numAxes < i)
768             {
769                 ErrorF("[Xi] Too many valuators reported for device '%s'. "
770                         "Ignoring event.\n", device->name);
771                 return DONT_PROCESS;
772             }
773             last_valuator = i;
774         }
775     }
777     for (i = 0; i <= last_valuator && i < v->numAxes; i++)
778     {
779         if (BitIsOn(&event->valuators.mask, i))
780         {
781             /* XXX: Relative/Absolute mode */
782             v->axisVal[i] = event->valuators.data[i];
783             v->axisVal[i] += (event->valuators.data_frac[i] * 1.0f / (1 << 16) / (1 << 16));
784         }
785     }
787     if (event->type == ET_KeyPress) {
788         if (!k)
789             return DONT_PROCESS;
791         /* don't allow ddx to generate multiple downs, but repeats are okay */
792         if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
793             return DONT_PROCESS;
795         if (device->valuator)
796             device->valuator->motionHintWindow = NullWindow;
797         set_key_down(device, key, KEY_PROCESSED);
798     } else if (event->type == ET_KeyRelease) {
799         if (!k)
800             return DONT_PROCESS;
802         if (!key_is_down(device, key, KEY_PROCESSED))   /* guard against duplicates */
803             return DONT_PROCESS;
804         if (device->valuator)
805             device->valuator->motionHintWindow = NullWindow;
806         set_key_up(device, key, KEY_PROCESSED);
807     } else if (event->type == ET_ButtonPress) {
808         Mask mask;
809         if (!b)
810             return DONT_PROCESS;
812         if (button_is_down(device, key, BUTTON_PROCESSED))
813             return DONT_PROCESS;
815         set_button_down(device, key, BUTTON_PROCESSED);
816         if (device->valuator)
817             device->valuator->motionHintWindow = NullWindow;
818         if (!b->map[key])
819             return DONT_PROCESS;
820         b->buttonsDown++;
821         b->motionMask = DeviceButtonMotionMask;
822         if (b->map[key] <= 5)
823             b->state |= (Button1Mask >> 1) << b->map[key];
825         /* Add state and motionMask to the filter for this event */
826         mask = DevicePointerMotionMask | b->state | b->motionMask;
827         SetMaskForEvent(device->id, mask, DeviceMotionNotify);
828         mask = PointerMotionMask | b->state | b->motionMask;
829         SetMaskForEvent(device->id, mask, MotionNotify);
830     } else if (event->type == ET_ButtonRelease) {
831         Mask mask;
832         if (!b)
833             return DONT_PROCESS;
835         if (!button_is_down(device, key, BUTTON_PROCESSED))
836             return DONT_PROCESS;
837         if (IsMaster(device)) {
838             DeviceIntPtr sd;
840             /*
841              * Leave the button down if any slave has the
842              * button still down. Note that this depends on the
843              * event being delivered through the slave first
844              */
845             for (sd = inputInfo.devices; sd; sd = sd->next) {
846                 if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER) != device)
847                     continue;
848                 if (!sd->button)
849                     continue;
850                 for (i = 1; i <= sd->button->numButtons; i++)
851                     if (sd->button->map[i] == key &&
852                         button_is_down(sd, i, BUTTON_PROCESSED))
853                         return DONT_PROCESS;
854             }
855         }
856         set_button_up(device, key, BUTTON_PROCESSED);
857         if (device->valuator)
858             device->valuator->motionHintWindow = NullWindow;
859         if (!b->map[key])
860             return DONT_PROCESS;
861         if (b->buttonsDown >= 1 && !--b->buttonsDown)
862             b->motionMask = 0;
863         if (b->map[key] <= 5)
864             b->state &= ~((Button1Mask >> 1) << b->map[key]);
866         /* Add state and motionMask to the filter for this event */
867         mask = DevicePointerMotionMask | b->state | b->motionMask;
868         SetMaskForEvent(device->id, mask, DeviceMotionNotify);
869         mask = PointerMotionMask | b->state | b->motionMask;
870         SetMaskForEvent(device->id, mask, MotionNotify);
871     } else if (event->type == ET_ProximityIn)
872         device->proximity->in_proximity = TRUE;
873     else if (event->type == ET_ProximityOut)
874         device->proximity->in_proximity = FALSE;
876     return DEFAULT;
879 /**
880  * Main device event processing function.
881  * Called from when processing the events from the event queue.
882  *
883  */
884 void
885 ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
887     GrabPtr grab;
888     Bool deactivateDeviceGrab = FALSE;
889     int key = 0, rootX, rootY;
890     ButtonClassPtr b;
891     KeyClassPtr k;
892     ValuatorClassPtr v;
893     int ret = 0;
894     int state, i;
895     DeviceIntPtr mouse = NULL, kbd = NULL;
896     DeviceEvent *event = &ev->device_event;
898     verify_internal_event(ev);
900     if (ev->any.type == ET_RawKeyPress ||
901         ev->any.type == ET_RawKeyRelease ||
902         ev->any.type == ET_RawButtonPress ||
903         ev->any.type == ET_RawButtonRelease ||
904         ev->any.type == ET_RawMotion)
905     {
906         DeliverRawEvent(&ev->raw_event, device);
907         return;
908     }
910     if (IsPointerDevice(device))
911     {
912         kbd = GetPairedDevice(device);
913         mouse = device;
914         if (!kbd->key) /* can happen with floating SDs */
915             kbd = NULL;
916     } else
917     {
918         mouse = GetPairedDevice(device);
919         kbd = device;
920         if (!mouse->valuator || !mouse->button) /* may be float. SDs */
921             mouse = NULL;
922     }
924     /* State needs to be assembled BEFORE the device is updated. */
925     state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0;
926     state |= (mouse && mouse->button) ? (mouse->button->state) : 0;
928     for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
929         if (BitIsOn(mouse->button->down, i))
930             SetBit(event->buttons, mouse->button->map[i]);
932     if (kbd && kbd->key)
933     {
934         XkbStatePtr state;
935         /* we need the state before the event happens */
936         if (event->type == ET_KeyPress || event->type == ET_KeyRelease)
937             state = &kbd->key->xkbInfo->prev_state;
938         else
939             state = &kbd->key->xkbInfo->state;
941         event->mods.base = state->base_mods;
942         event->mods.latched = state->latched_mods;
943         event->mods.locked = state->locked_mods;
944         event->mods.effective = state->mods;
946         event->group.base = state->base_group;
947         event->group.latched = state->latched_group;
948         event->group.locked = state->locked_group;
949         event->group.effective = state->group;
950     }
952     ret = UpdateDeviceState(device, event);
953     if (ret == DONT_PROCESS)
954         return;
956     v = device->valuator;
957     b = device->button;
958     k = device->key;
960     if (IsMaster(device) || IsFloating(device))
961         CheckMotion(event, device);
963     switch (event->type)
964     {
965         case ET_Motion:
966         case ET_ButtonPress:
967         case ET_ButtonRelease:
968         case ET_KeyPress:
969         case ET_KeyRelease:
970         case ET_ProximityIn:
971         case ET_ProximityOut:
972             GetSpritePosition(device, &rootX, &rootY);
973             event->root_x = rootX;
974             event->root_y = rootY;
975             NoticeEventTime((InternalEvent*)event);
976             event->corestate = state;
977             key = event->detail.key;
978             break;
979         default:
980             break;
981     }
983     if (DeviceEventCallback && !syncEvents.playingEvents) {
984         DeviceEventInfoRec eventinfo;
985         SpritePtr pSprite = device->spriteInfo->sprite;
987         /* see comment in EnqueueEvents regarding the next three lines */
988         if (ev->any.type == ET_Motion)
989             ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
991         eventinfo.device = device;
992         eventinfo.event = ev;
993         CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
994     }
996     grab = device->deviceGrab.grab;
998     switch(event->type)
999     {
1000         case ET_KeyPress:
1001             if (!grab && CheckDeviceGrabs(device, event, 0))
1002                 return;
1003             break;
1004         case ET_KeyRelease:
1005             if (grab && device->deviceGrab.fromPassiveGrab &&
1006                 (key == device->deviceGrab.activatingKey) &&
1007                 (device->deviceGrab.grab->type == KeyPress ||
1008                  device->deviceGrab.grab->type == DeviceKeyPress ||
1009                  device->deviceGrab.grab->type == XI_KeyPress))
1010                 deactivateDeviceGrab = TRUE;
1011             break;
1012         case ET_ButtonPress:
1013             event->detail.button = b->map[key];
1014             if (!event->detail.button) { /* there's no button 0 */
1015                 event->detail.button = key;
1016                 return;
1017             }
1018             if (!grab && CheckDeviceGrabs(device, event, 0))
1019             {
1020                 /* if a passive grab was activated, the event has been sent
1021                  * already */
1022                 return;
1023             }
1024             break;
1025         case ET_ButtonRelease:
1026             event->detail.button = b->map[key];
1027             if (!event->detail.button) { /* there's no button 0 */
1028                 event->detail.button = key;
1029                 return;
1030             }
1031             if (grab && !b->buttonsDown &&
1032                 device->deviceGrab.fromPassiveGrab &&
1033                 (device->deviceGrab.grab->type == ButtonPress ||
1034                  device->deviceGrab.grab->type == DeviceButtonPress ||
1035                  device->deviceGrab.grab->type == XI_ButtonPress))
1036                 deactivateDeviceGrab = TRUE;
1037         default:
1038             break;
1039     }
1042     if (grab)
1043         DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
1044     else if (device->focus && !IsPointerEvent((InternalEvent*)ev))
1045         DeliverFocusedEvent(device, (InternalEvent*)event,
1046                             GetSpriteWindow(device));
1047     else
1048         DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
1049                             NullGrab, NullWindow, device);
1051     if (deactivateDeviceGrab == TRUE)
1052         (*device->deviceGrab.DeactivateGrab) (device);
1053     event->detail.key = key;
1056 int
1057 InitProximityClassDeviceStruct(DeviceIntPtr dev)
1059     ProximityClassPtr proxc;
1061     proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
1062     if (!proxc)
1063         return FALSE;
1064     proxc->sourceid = dev->id;
1065     proxc->in_proximity = TRUE;
1066     dev->proximity = proxc;
1067     return TRUE;
1070 /**
1071  * Initialise the device's valuators. The memory must already be allocated,
1072  * this function merely inits the matching axis (specified through axnum) to
1073  * sane values.
1074  *
1075  * It is a condition that (minval < maxval).
1076  *
1077  * @see InitValuatorClassDeviceStruct
1078  */
1079 void
1080 InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
1081                        int resolution, int min_res, int max_res, int mode)
1083     AxisInfoPtr ax;
1085     if (!dev || !dev->valuator || minval > maxval)
1086         return;
1087     if (axnum >= dev->valuator->numAxes)
1088         return;
1090     ax = dev->valuator->axes + axnum;
1092     ax->min_value = minval;
1093     ax->max_value = maxval;
1094     ax->resolution = resolution;
1095     ax->min_resolution = min_res;
1096     ax->max_resolution = max_res;
1097     ax->label = label;
1098     ax->mode = mode;
1100     if (mode & OutOfProximity)
1101         dev->proximity->in_proximity = FALSE;
1104 static void
1105 FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
1106                      ButtonClassPtr b, ValuatorClassPtr v, int first)
1108     ev->type = DeviceStateNotify;
1109     ev->deviceid = dev->id;
1110     ev->time = currentTime.milliseconds;
1111     ev->classes_reported = 0;
1112     ev->num_keys = 0;
1113     ev->num_buttons = 0;
1114     ev->num_valuators = 0;
1116     if (b) {
1117         ev->classes_reported |= (1 << ButtonClass);
1118         ev->num_buttons = b->numButtons;
1119         memcpy((char*)ev->buttons, (char*)b->down, 4);
1120     } else if (k) {
1121         ev->classes_reported |= (1 << KeyClass);
1122         ev->num_keys = k->xkbInfo->desc->max_key_code -
1123                        k->xkbInfo->desc->min_key_code;
1124         memmove((char *)&ev->keys[0], (char *)k->down, 4);
1125     }
1126     if (v) {
1127         int nval = v->numAxes - first;
1129         ev->classes_reported |= (1 << ValuatorClass);
1130         ev->classes_reported |= valuator_get_mode(dev, 0) << ModeBitsShift;
1131         ev->num_valuators = nval < 3 ? nval : 3;
1132         switch (ev->num_valuators) {
1133         case 3:
1134             ev->valuator2 = v->axisVal[first + 2];
1135         case 2:
1136             ev->valuator1 = v->axisVal[first + 1];
1137         case 1:
1138             ev->valuator0 = v->axisVal[first];
1139             break;
1140         }
1141     }
1144 static void
1145 FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
1146                   int first)
1148     int nval = v->numAxes - first;
1150     ev->type = DeviceValuator;
1151     ev->deviceid = dev->id;
1152     ev->num_valuators = nval < 3 ? nval : 3;
1153     ev->first_valuator = first;
1154     switch (ev->num_valuators) {
1155     case 3:
1156         ev->valuator2 = v->axisVal[first + 2];
1157     case 2:
1158         ev->valuator1 = v->axisVal[first + 1];
1159     case 1:
1160         ev->valuator0 = v->axisVal[first];
1161         break;
1162     }
1163     first += ev->num_valuators;
1166 static void
1167 DeliverStateNotifyEvent(DeviceIntPtr dev, WindowPtr win)
1169     int evcount = 1;
1170     deviceStateNotify *ev, *sev;
1171     deviceKeyStateNotify *kev;
1172     deviceButtonStateNotify *bev;
1174     KeyClassPtr k;
1175     ButtonClassPtr b;
1176     ValuatorClassPtr v;
1177     int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
1179     if (!(wOtherInputMasks(win)) ||
1180         !(wOtherInputMasks(win)->inputEvents[dev->id] & DeviceStateNotifyMask))
1181         return;
1183     if ((b = dev->button) != NULL) {
1184         nbuttons = b->numButtons;
1185         if (nbuttons > 32)
1186             evcount++;
1187     }
1188     if ((k = dev->key) != NULL) {
1189         nkeys = k->xkbInfo->desc->max_key_code -
1190             k->xkbInfo->desc->min_key_code;
1191         if (nkeys > 32)
1192             evcount++;
1193         if (nbuttons > 0) {
1194             evcount++;
1195         }
1196     }
1197     if ((v = dev->valuator) != NULL) {
1198         nval = v->numAxes;
1200         if (nval > 3)
1201             evcount++;
1202         if (nval > 6) {
1203             if (!(k && b))
1204                 evcount++;
1205             if (nval > 9)
1206                 evcount += ((nval - 7) / 3);
1207         }
1208     }
1210     sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
1211     FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
1213     if (b != NULL) {
1214         FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
1215         first += 3;
1216         nval -= 3;
1217         if (nbuttons > 32) {
1218             (ev - 1)->deviceid |= MORE_EVENTS;
1219             bev = (deviceButtonStateNotify *) ev++;
1220             bev->type = DeviceButtonStateNotify;
1221             bev->deviceid = dev->id;
1222             memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
1223         }
1224         if (nval > 0) {
1225             (ev - 1)->deviceid |= MORE_EVENTS;
1226             FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1227             first += 3;
1228             nval -= 3;
1229         }
1230     }
1232     if (k != NULL) {
1233         FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
1234         first += 3;
1235         nval -= 3;
1236         if (nkeys > 32) {
1237             (ev - 1)->deviceid |= MORE_EVENTS;
1238             kev = (deviceKeyStateNotify *) ev++;
1239             kev->type = DeviceKeyStateNotify;
1240             kev->deviceid = dev->id;
1241             memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
1242         }
1243         if (nval > 0) {
1244             (ev - 1)->deviceid |= MORE_EVENTS;
1245             FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1246             first += 3;
1247             nval -= 3;
1248         }
1249     }
1251     while (nval > 0) {
1252         FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
1253         first += 3;
1254         nval -= 3;
1255         if (nval > 0) {
1256             (ev - 1)->deviceid |= MORE_EVENTS;
1257             FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1258             first += 3;
1259             nval -= 3;
1260         }
1261     }
1263     DeliverEventsToWindow(dev, win, (xEvent *) sev, evcount,
1264                           DeviceStateNotifyMask, NullGrab);
1265     free(sev);
1268 void
1269 DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
1270                  WindowPtr pWin)
1272     deviceFocus event;
1273     xXIFocusInEvent *xi2event;
1274     DeviceIntPtr mouse;
1275     int btlen, len, i;
1277     mouse = IsFloating(dev) ? dev : GetMaster(dev, MASTER_POINTER);
1279     /* XI 2 event */
1280     btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
1281     btlen = bytes_to_int32(btlen);
1282     len = sizeof(xXIFocusInEvent) + btlen * 4;
1284     xi2event = calloc(1, len);
1285     xi2event->type         = GenericEvent;
1286     xi2event->extension    = IReqCode;
1287     xi2event->evtype       = type;
1288     xi2event->length       = bytes_to_int32(len - sizeof(xEvent));
1289     xi2event->buttons_len  = btlen;
1290     xi2event->detail       = detail;
1291     xi2event->time         = currentTime.milliseconds;
1292     xi2event->deviceid     = dev->id;
1293     xi2event->sourceid     = dev->id; /* a device doesn't change focus by itself */
1294     xi2event->mode         = mode;
1295     xi2event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
1296     xi2event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
1298     for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
1299         if (BitIsOn(mouse->button->down, i))
1300             SetBit(&xi2event[1], i);
1302     if (dev->key)
1303     {
1304         xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
1305         xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
1306         xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
1307         xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
1309         xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
1310         xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
1311         xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
1312         xi2event->group.effective_group = dev->key->xkbInfo->state.group;
1313     }
1315     FixUpEventFromWindow(dev->spriteInfo->sprite, (xEvent*)xi2event, pWin,
1316                          None, FALSE);
1318     DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
1319                           GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
1321     free(xi2event);
1323     /* XI 1.x event */
1324     event.deviceid = dev->id;
1325     event.mode = mode;
1326     event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
1327     event.detail = detail;
1328     event.window = pWin->drawable.id;
1329     event.time = currentTime.milliseconds;
1331     DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
1332                                 DeviceFocusChangeMask, NullGrab);
1334     if (event.type == DeviceFocusIn)
1335         DeliverStateNotifyEvent(dev, pWin);
1338 int
1339 CheckGrabValues(ClientPtr client, GrabParameters* param)
1341     if (param->grabtype != GRABTYPE_CORE &&
1342         param->grabtype != GRABTYPE_XI &&
1343         param->grabtype != GRABTYPE_XI2)
1344     {
1345         ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
1346         return BadImplementation;
1347     }
1349     if ((param->this_device_mode != GrabModeSync) &&
1350         (param->this_device_mode != GrabModeAsync)) {
1351         client->errorValue = param->this_device_mode;
1352         return BadValue;
1353     }
1354     if ((param->other_devices_mode != GrabModeSync) &&
1355         (param->other_devices_mode != GrabModeAsync)) {
1356         client->errorValue = param->other_devices_mode;
1357         return BadValue;
1358     }
1360     if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
1361         (param->modifiers & ~AllModifiersMask)) {
1362         client->errorValue = param->modifiers;
1363         return BadValue;
1364     }
1366     if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
1367         client->errorValue = param->ownerEvents;
1368         return BadValue;
1369     }
1370     return Success;
1373 int
1374 GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
1375            int button, GrabParameters *param, GrabType grabtype,
1376            GrabMask *mask)
1378     WindowPtr pWin, confineTo;
1379     CursorPtr cursor;
1380     GrabPtr grab;
1381     int rc, type = -1;
1382     Mask access_mode = DixGrabAccess;
1384     rc = CheckGrabValues(client, param);
1385     if (rc != Success)
1386         return rc;
1387     if (param->confineTo == None)
1388         confineTo = NullWindow;
1389     else {
1390         rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
1391         if (rc != Success)
1392             return rc;
1393     }
1394     if (param->cursor == None)
1395         cursor = NullCursor;
1396     else {
1397         rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
1398                                      RT_CURSOR, client, DixUseAccess);
1399         if (rc != Success)
1400         {
1401             client->errorValue = param->cursor;
1402             return rc;
1403         }
1404         access_mode |= DixForceAccess;
1405     }
1406     if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1407         access_mode |= DixFreezeAccess;
1408     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1409     if (rc != Success)
1410         return rc;
1411     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1412     if (rc != Success)
1413         return rc;
1415     if (grabtype == GRABTYPE_XI)
1416         type = DeviceButtonPress;
1417     else if (grabtype == GRABTYPE_XI2)
1418         type = XI_ButtonPress;
1420     grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
1421                       mask, param, type, button, confineTo, cursor);
1422     if (!grab)
1423         return BadAlloc;
1424     return AddPassiveGrabToList(client, grab);
1427 /**
1428  * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If
1429  * grabtype is GRABTYPE_XI2, the key is a keysym.
1430  */
1431 int
1432 GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
1433         int key, GrabParameters *param, GrabType grabtype, GrabMask *mask)
1435     WindowPtr pWin;
1436     GrabPtr grab;
1437     KeyClassPtr k = dev->key;
1438     Mask access_mode = DixGrabAccess;
1439     int rc, type = -1;
1441     rc = CheckGrabValues(client, param);
1442     if (rc != Success)
1443         return rc;
1444     if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL)
1445         return BadMatch;
1446     if (grabtype == GRABTYPE_XI)
1447     {
1448         if ((key > k->xkbInfo->desc->max_key_code ||
1449                     key < k->xkbInfo->desc->min_key_code)
1450                 && (key != AnyKey)) {
1451             client->errorValue = key;
1452             return BadValue;
1453         }
1454         type = DeviceKeyPress;
1455     } else if (grabtype == GRABTYPE_XI2)
1456         type = XI_KeyPress;
1458     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1459     if (rc != Success)
1460         return rc;
1461     if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1462         access_mode |= DixFreezeAccess;
1463     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1464     if (rc != Success)
1465         return rc;
1467     grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
1468                       mask, param, type, key, NULL, NULL);
1469     if (!grab)
1470         return BadAlloc;
1471     return AddPassiveGrabToList(client, grab);
1474 /* Enter/FocusIn grab */
1475 int
1476 GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
1477            GrabParameters *param, GrabMask *mask)
1479     WindowPtr pWin;
1480     CursorPtr cursor;
1481     GrabPtr grab;
1482     Mask access_mode = DixGrabAccess;
1483     int rc;
1485     rc = CheckGrabValues(client, param);
1486     if (rc != Success)
1487         return rc;
1489     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1490     if (rc != Success)
1491         return rc;
1492     if (param->cursor == None)
1493         cursor = NullCursor;
1494     else {
1495         rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
1496                                      RT_CURSOR, client, DixUseAccess);
1497         if (rc != Success)
1498         {
1499             client->errorValue = param->cursor;
1500             return rc;
1501         }
1502         access_mode |= DixForceAccess;
1503     }
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;
1510     grab = CreateGrab(client->index, dev, dev, pWin, GRABTYPE_XI2,
1511                       mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
1512                       0, NULL, cursor);
1514     if (!grab)
1515         return BadAlloc;
1517     return AddPassiveGrabToList(client, grab);
1520 int
1521 SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
1522                 Mask mask, Mask exclusivemasks)
1524     int mskidx = dev->id;
1525     int i, ret;
1526     Mask check;
1527     InputClientsPtr others;
1529     check = (mask & exclusivemasks);
1530     if (wOtherInputMasks(pWin)) {
1531         if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {      /* It is illegal for two different
1532                                                                          * clients to select on any of the
1533                                                                          * events for maskcheck. However,
1534                                                                          * it is OK, for some client to
1535                                                                          * continue selecting on one of those
1536                                                                          * events.  */
1537             for (others = wOtherInputMasks(pWin)->inputClients; others;
1538                  others = others->next) {
1539                 if (!SameClient(others, client) && (check &
1540                                                     others->mask[mskidx]))
1541                     return BadAccess;
1542             }
1543         }
1544         for (others = wOtherInputMasks(pWin)->inputClients; others;
1545              others = others->next) {
1546             if (SameClient(others, client)) {
1547                 check = others->mask[mskidx];
1548                 others->mask[mskidx] = mask;
1549                 if (mask == 0) {
1550                     for (i = 0; i < EMASKSIZE; i++)
1551                         if (i != mskidx && others->mask[i] != 0)
1552                             break;
1553                     if (i == EMASKSIZE) {
1554                         RecalculateDeviceDeliverableEvents(pWin);
1555                         if (ShouldFreeInputMasks(pWin, FALSE))
1556                             FreeResource(others->resource, RT_NONE);
1557                         return Success;
1558                     }
1559                 }
1560                 goto maskSet;
1561             }
1562         }
1563     }
1564     check = 0;
1565     if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
1566         return ret;
1567   maskSet:
1568     if (dev->valuator)
1569         if ((dev->valuator->motionHintWindow == pWin) &&
1570             (mask & DevicePointerMotionHintMask) &&
1571             !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
1572             dev->valuator->motionHintWindow = NullWindow;
1573     RecalculateDeviceDeliverableEvents(pWin);
1574     return Success;
1577 int
1578 AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
1580     InputClientsPtr others;
1582     if (!pWin->optional && !MakeWindowOptional(pWin))
1583         return BadAlloc;
1584     others = calloc(1, sizeof(InputClients));
1585     if (!others)
1586         return BadAlloc;
1587     if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
1588         goto bail;
1589     others->mask[mskidx] = mask;
1590     others->resource = FakeClientID(client->index);
1591     others->next = pWin->optional->inputMasks->inputClients;
1592     pWin->optional->inputMasks->inputClients = others;
1593     if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
1594         goto bail;
1595     return Success;
1597 bail:
1598     free(others);
1599     return BadAlloc;
1602 static Bool
1603 MakeInputMasks(WindowPtr pWin)
1605     struct _OtherInputMasks *imasks;
1607     imasks = calloc(1, sizeof(struct _OtherInputMasks));
1608     if (!imasks)
1609         return FALSE;
1610     pWin->optional->inputMasks = imasks;
1611     return TRUE;
1614 void
1615 RecalculateDeviceDeliverableEvents(WindowPtr pWin)
1617     InputClientsPtr others;
1618     struct _OtherInputMasks *inputMasks;        /* default: NULL */
1619     WindowPtr pChild, tmp;
1620     int i, j;
1622     pChild = pWin;
1623     while (1) {
1624         if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
1625             for (i = 0; i < EMASKSIZE; i++)
1626                 memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i]));
1627             for (others = inputMasks->inputClients; others;
1628                  others = others->next) {
1629                 for (i = 0; i < EMASKSIZE; i++)
1630                     inputMasks->inputEvents[i] |= others->mask[i];
1631                 for (i = 0; i < EMASKSIZE; i++)
1632                     for (j = 0; j < XI2MASKSIZE; j++)
1633                         inputMasks->xi2mask[i][j] |= others->xi2mask[i][j];
1634             }
1635             for (i = 0; i < EMASKSIZE; i++)
1636                 inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
1637             for (tmp = pChild->parent; tmp; tmp = tmp->parent)
1638                 if (wOtherInputMasks(tmp))
1639                     for (i = 0; i < EMASKSIZE; i++)
1640                         inputMasks->deliverableEvents[i] |=
1641                             (wOtherInputMasks(tmp)->deliverableEvents[i]
1642                              & ~inputMasks->
1643                              dontPropagateMask[i] & PropagateMask[i]);
1644         }
1645         if (pChild->firstChild) {
1646             pChild = pChild->firstChild;
1647             continue;
1648         }
1649         while (!pChild->nextSib && (pChild != pWin))
1650             pChild = pChild->parent;
1651         if (pChild == pWin)
1652             break;
1653         pChild = pChild->nextSib;
1654     }
1657 int
1658 InputClientGone(WindowPtr pWin, XID id)
1660     InputClientsPtr other, prev;
1662     if (!wOtherInputMasks(pWin))
1663         return Success;
1664     prev = 0;
1665     for (other = wOtherInputMasks(pWin)->inputClients; other;
1666          other = other->next) {
1667         if (other->resource == id) {
1668             if (prev) {
1669                 prev->next = other->next;
1670                 free(other);
1671             } else if (!(other->next)) {
1672                 if (ShouldFreeInputMasks(pWin, TRUE)) {
1673                     wOtherInputMasks(pWin)->inputClients = other->next;
1674                     free(wOtherInputMasks(pWin));
1675                     pWin->optional->inputMasks = (OtherInputMasks *) NULL;
1676                     CheckWindowOptionalNeed(pWin);
1677                     free(other);
1678                 } else {
1679                     other->resource = FakeClientID(0);
1680                     if (!AddResource(other->resource, RT_INPUTCLIENT,
1681                                      (pointer) pWin))
1682                         return BadAlloc;
1683                 }
1684             } else {
1685                 wOtherInputMasks(pWin)->inputClients = other->next;
1686                 free(other);
1687             }
1688             RecalculateDeviceDeliverableEvents(pWin);
1689             return Success;
1690         }
1691         prev = other;
1692     }
1693     FatalError("client not on device event list");
1696 int
1697 SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
1698           xEvent * ev, Mask mask, int count)
1700     WindowPtr pWin;
1701     WindowPtr effectiveFocus = NullWindow;      /* only set if dest==InputFocus */
1702     WindowPtr spriteWin = GetSpriteWindow(d);
1704     if (dest == PointerWindow)
1705         pWin = spriteWin;
1706     else if (dest == InputFocus) {
1707         WindowPtr inputFocus;
1709         if (!d->focus)
1710             inputFocus = spriteWin;
1711         else
1712             inputFocus = d->focus->win;
1714         if (inputFocus == FollowKeyboardWin)
1715             inputFocus = inputInfo.keyboard->focus->win;
1717         if (inputFocus == NoneWin)
1718             return Success;
1720         /* If the input focus is PointerRootWin, send the event to where
1721          * the pointer is if possible, then perhaps propogate up to root. */
1722         if (inputFocus == PointerRootWin)
1723             inputFocus = GetCurrentRootWindow(d);
1725         if (IsParent(inputFocus, spriteWin)) {
1726             effectiveFocus = inputFocus;
1727             pWin = spriteWin;
1728         } else
1729             effectiveFocus = pWin = inputFocus;
1730     } else
1731         dixLookupWindow(&pWin, dest, client, DixSendAccess);
1732     if (!pWin)
1733         return BadWindow;
1734     if ((propagate != xFalse) && (propagate != xTrue)) {
1735         client->errorValue = propagate;
1736         return BadValue;
1737     }
1738     ev->u.u.type |= 0x80;
1739     if (propagate) {
1740         for (; pWin; pWin = pWin->parent) {
1741             if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
1742                 return Success;
1743             if (pWin == effectiveFocus)
1744                 return Success;
1745             if (wOtherInputMasks(pWin))
1746                 mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
1747             if (!mask)
1748                 break;
1749         }
1750     } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
1751         DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
1752     return Success;
1755 int
1756 SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
1758     int i;
1759     ButtonClassPtr b = dev->button;
1761     if (b == NULL)
1762         return BadMatch;
1764     if (nElts != b->numButtons) {
1765         client->errorValue = nElts;
1766         return BadValue;
1767     }
1768     if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
1769         return BadValue;
1770     for (i = 0; i < nElts; i++)
1771         if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
1772             return MappingBusy;
1773     for (i = 0; i < nElts; i++)
1774         b->map[i + 1] = map[i];
1775     return Success;
1778 int
1779 ChangeKeyMapping(ClientPtr client,
1780                  DeviceIntPtr dev,
1781                  unsigned len,
1782                  int type,
1783                  KeyCode firstKeyCode,
1784                  CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
1786     KeySymsRec keysyms;
1787     KeyClassPtr k = dev->key;
1789     if (k == NULL)
1790         return BadMatch;
1792     if (len != (keyCodes * keySymsPerKeyCode))
1793         return BadLength;
1795     if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
1796         (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
1797         client->errorValue = firstKeyCode;
1798         return BadValue;
1799     }
1800     if (keySymsPerKeyCode == 0) {
1801         client->errorValue = 0;
1802         return BadValue;
1803     }
1804     keysyms.minKeyCode = firstKeyCode;
1805     keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
1806     keysyms.mapWidth = keySymsPerKeyCode;
1807     keysyms.map = map;
1809     XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
1810                           serverClient);
1812     return Success;
1815 static void
1816 DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
1818     WindowPtr parent;
1820     /* Deactivate any grabs performed on this window, before making
1821      * any input focus changes.
1822      * Deactivating a device grab should cause focus events. */
1824     if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
1825         (*dev->deviceGrab.DeactivateGrab) (dev);
1827     /* If the focus window is a root window (ie. has no parent)
1828      * then don't delete the focus from it. */
1830     if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
1831         int focusEventMode = NotifyNormal;
1833         /* If a grab is in progress, then alter the mode of focus events. */
1835         if (dev->deviceGrab.grab)
1836             focusEventMode = NotifyWhileGrabbed;
1838         switch (dev->focus->revert) {
1839         case RevertToNone:
1840             if (!ActivateFocusInGrab(dev, pWin, NoneWin))
1841                 DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1842             dev->focus->win = NoneWin;
1843             dev->focus->traceGood = 0;
1844             break;
1845         case RevertToParent:
1846             parent = pWin;
1847             do {
1848                 parent = parent->parent;
1849                 dev->focus->traceGood--;
1850             }
1851             while (!parent->realized);
1852             if (!ActivateFocusInGrab(dev, pWin, parent))
1853                 DoFocusEvents(dev, pWin, parent, focusEventMode);
1854             dev->focus->win = parent;
1855             dev->focus->revert = RevertToNone;
1856             break;
1857         case RevertToPointerRoot:
1858             if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
1859                 DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
1860             dev->focus->win = PointerRootWin;
1861             dev->focus->traceGood = 0;
1862             break;
1863         case RevertToFollowKeyboard:
1864             {
1865                 DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
1866                 if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
1867                     kbd = inputInfo.keyboard;
1868             if (kbd->focus->win) {
1869                 if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
1870                     DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
1871                 dev->focus->win = FollowKeyboardWin;
1872                 dev->focus->traceGood = 0;
1873             } else {
1874                 if (!ActivateFocusInGrab(dev, pWin, NoneWin))
1875                     DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1876                 dev->focus->win = NoneWin;
1877                 dev->focus->traceGood = 0;
1878             }
1879             }
1880             break;
1881         }
1882     }
1884     if (dev->valuator)
1885         if (dev->valuator->motionHintWindow == pWin)
1886             dev->valuator->motionHintWindow = NullWindow;
1889 void
1890 DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
1892     int i;
1893     DeviceIntPtr dev;
1894     InputClientsPtr ic;
1895     struct _OtherInputMasks *inputMasks;
1897     for (dev = inputInfo.devices; dev; dev = dev->next) {
1898         DeleteDeviceFromAnyExtEvents(pWin, dev);
1899     }
1901     for (dev = inputInfo.off_devices; dev; dev = dev->next)
1902         DeleteDeviceFromAnyExtEvents(pWin, dev);
1904     if (freeResources)
1905         while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
1906             ic = inputMasks->inputClients;
1907             for (i = 0; i < EMASKSIZE; i++)
1908                 inputMasks->dontPropagateMask[i] = 0;
1909             FreeResource(ic->resource, RT_NONE);
1910         }
1913 int
1914 MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
1916     DeviceIntPtr dev;
1918     dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
1919                     DixReadAccess);
1920     if (!dev)
1921         return 0;
1923     if (pEvents->type == DeviceMotionNotify) {
1924         if (mask & DevicePointerMotionHintMask) {
1925             if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
1926                 return 1;       /* don't send, but pretend we did */
1927             }
1928             pEvents->detail = NotifyHint;
1929         } else {
1930             pEvents->detail = NotifyNormal;
1931         }
1932     }
1933     return 0;
1936 void
1937 CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
1938                              deviceKeyButtonPointer * xE, GrabPtr grab,
1939                              ClientPtr client, Mask deliveryMask)
1941     DeviceIntPtr dev;
1943     dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
1944                     DixGrabAccess);
1945     if (!dev)
1946         return;
1948     if (type == DeviceMotionNotify)
1949         dev->valuator->motionHintWindow = pWin;
1950     else if ((type == DeviceButtonPress) && (!grab) &&
1951              (deliveryMask & DeviceButtonGrabMask)) {
1952         GrabRec tempGrab;
1954         tempGrab.device = dev;
1955         tempGrab.resource = client->clientAsMask;
1956         tempGrab.window = pWin;
1957         tempGrab.ownerEvents =
1958             (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
1959         tempGrab.eventMask = deliveryMask;
1960         tempGrab.keyboardMode = GrabModeAsync;
1961         tempGrab.pointerMode = GrabModeAsync;
1962         tempGrab.confineTo = NullWindow;
1963         tempGrab.cursor = NullCursor;
1964         tempGrab.next = NULL;
1965         (*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
1966     }
1969 static Mask
1970 DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
1972     InputClientsPtr other;
1974     if (!wOtherInputMasks(pWin))
1975         return 0;
1976     for (other = wOtherInputMasks(pWin)->inputClients; other;
1977          other = other->next) {
1978         if (SameClient(other, client))
1979             return other->mask[dev->id];
1980     }
1981     return 0;
1984 void
1985 MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
1987     WindowPtr pWin;
1988     GrabPtr grab = dev->deviceGrab.grab;
1990     pWin = dev->valuator->motionHintWindow;
1992     if ((grab && SameClient(grab, client) &&
1993          ((grab->eventMask & DevicePointerMotionHintMask) ||
1994           (grab->ownerEvents &&
1995            (DeviceEventMaskForClient(dev, pWin, client) &
1996             DevicePointerMotionHintMask)))) ||
1997         (!grab &&
1998          (DeviceEventMaskForClient(dev, pWin, client) &
1999           DevicePointerMotionHintMask)))
2000         dev->valuator->motionHintWindow = NullWindow;
2003 int
2004 DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
2005                              int maskndx)
2007     struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2009     if (mask & ~PropagateMask[maskndx]) {
2010         client->errorValue = mask;
2011         return BadValue;
2012     }
2014     if (mask == 0) {
2015         if (inputMasks)
2016             inputMasks->dontPropagateMask[maskndx] = mask;
2017     } else {
2018         if (!inputMasks)
2019             AddExtensionClient(pWin, client, 0, 0);
2020         inputMasks = wOtherInputMasks(pWin);
2021         inputMasks->dontPropagateMask[maskndx] = mask;
2022     }
2023     RecalculateDeviceDeliverableEvents(pWin);
2024     if (ShouldFreeInputMasks(pWin, FALSE))
2025         FreeResource(inputMasks->inputClients->resource, RT_NONE);
2026     return Success;
2029 Bool
2030 ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
2032     int i;
2033     Mask allInputEventMasks = 0;
2034     struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2036     for (i = 0; i < EMASKSIZE; i++)
2037         allInputEventMasks |= inputMasks->dontPropagateMask[i];
2038     if (!ignoreSelectedEvents)
2039         for (i = 0; i < EMASKSIZE; i++)
2040             allInputEventMasks |= inputMasks->inputEvents[i];
2041     if (allInputEventMasks == 0)
2042         return TRUE;
2043     else
2044         return FALSE;
2047 /***********************************************************************
2048  *
2049  * Walk through the window tree, finding all clients that want to know
2050  * about the Event.
2051  *
2052  */
2054 static void
2055 FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
2056                        xEvent * ev, int count)
2058     WindowPtr p2;
2060     while (p1) {
2061         p2 = p1->firstChild;
2062         DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
2063         FindInterestedChildren(dev, p2, mask, ev, count);
2064         p1 = p1->nextSib;
2065     }
2068 /***********************************************************************
2069  *
2070  * Send an event to interested clients in all windows on all screens.
2071  *
2072  */
2074 void
2075 SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
2077     int i;
2078     WindowPtr pWin, p1;
2080     for (i = 0; i < screenInfo.numScreens; i++) {
2081         pWin = screenInfo.screens[i]->root;
2082         if (!pWin)
2083             continue;
2084         DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
2085         p1 = pWin->firstChild;
2086         FindInterestedChildren(dev, p1, mask, ev, count);
2087     }
2090 /**
2091  * Set the XI2 mask for the given client on the given window.
2092  * @param dev The device to set the mask for.
2093  * @param win The window to set the mask on.
2094  * @param client The client setting the mask.
2095  * @param len Number of bytes in mask.
2096  * @param mask Event mask in the form of (1 << eventtype)
2097  */
2098 int
2099 XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
2100                unsigned int len, unsigned char* mask)
2102     OtherInputMasks *masks;
2103     InputClientsPtr others = NULL;
2105     masks = wOtherInputMasks(win);
2106     if (masks)
2107     {
2108         for (others = wOtherInputMasks(win)->inputClients; others;
2109              others = others->next) {
2110             if (SameClient(others, client)) {
2111                 memset(others->xi2mask[dev->id], 0,
2112                        sizeof(others->xi2mask[dev->id]));
2113                 break;
2114             }
2115         }
2116     }
2118     len = min(len, sizeof(others->xi2mask[dev->id]));
2120     if (len && !others)
2121     {
2122         if (AddExtensionClient(win, client, 0, 0) != Success)
2123             return BadAlloc;
2124         others= wOtherInputMasks(win)->inputClients;
2125     }
2127     if (others)
2128         memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id]));
2130     if (len)
2131         memcpy(others->xi2mask[dev->id], mask, len);
2133     RecalculateDeviceDeliverableEvents(win);
2135     return Success;