Imported Debian patch 2:1.11.4-0ubuntu10.1
[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  * Copyright © 2010 Collabora Ltd.
49  * Copyright © 2011 Red Hat, Inc.
50  *
51  * Permission is hereby granted, free of charge, to any person obtaining a
52  * copy of this software and associated documentation files (the "Software"),
53  * to deal in the Software without restriction, including without limitation
54  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
55  * and/or sell copies of the Software, and to permit persons to whom the
56  * Software is furnished to do so, subject to the following conditions:
57  *
58  * The above copyright notice and this permission notice (including the next
59  * paragraph) shall be included in all copies or substantial portions of the
60  * Software.
61  *
62  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
65  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
67  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
68  * DEALINGS IN THE SOFTWARE.
69  *
70  * Author: Daniel Stone <daniel@fooishbar.org>
71  */
73 /********************************************************************
74  *
75  *  Routines to register and initialize extension input devices.
76  *  This also contains ProcessOtherEvent, the routine called from DDX
77  *  to route extension events.
78  *
79  */
81 #ifdef HAVE_DIX_CONFIG_H
82 #include <dix-config.h>
83 #endif
85 #include "inputstr.h"
86 #include <X11/X.h>
87 #include <X11/Xproto.h>
88 #include <X11/extensions/XI.h>
89 #include <X11/extensions/XIproto.h>
90 #include <X11/extensions/XI2proto.h>
91 #include <X11/extensions/geproto.h>
92 #include "windowstr.h"
93 #include "miscstruct.h"
94 #include "region.h"
95 #include "exevents.h"
96 #include "extnsionst.h"
97 #include "exglobals.h"
98 #include "dixevents.h"  /* DeliverFocusedEvent */
99 #include "dixgrabs.h"   /* CreateGrab() */
100 #include "scrnintstr.h"
101 #include "listdev.h" /* for CopySwapXXXClass */
102 #include "xace.h"
103 #include "xiquerydevice.h" /* For List*Info */
104 #include "eventconvert.h"
105 #include "eventstr.h"
106 #include "inpututils.h"
107 #include "mi.h"
109 #include <X11/extensions/XKBproto.h>
110 #include "xkbsrv.h"
112 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
113 #define AllModifiersMask ( \
114         ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
115         Mod3Mask | Mod4Mask | Mod5Mask )
116 #define AllButtonsMask ( \
117         Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
119 Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
120                                  Bool   /* ignoreSelectedEvents */
121     );
122 static Bool MakeInputMasks(WindowPtr    /* pWin */
123     );
125 /*
126  * Only let the given client know of core events which will affect its
127  * interpretation of input events, if the client's ClientPointer (or the
128  * paired keyboard) is the current device.
129  */
130 int
131 XIShouldNotify(ClientPtr client, DeviceIntPtr dev)
133     DeviceIntPtr current_ptr = PickPointer(client);
134     DeviceIntPtr current_kbd = GetMaster(current_ptr, KEYBOARD_OR_FLOAT);
136     if (dev == current_kbd || dev == current_ptr)
137         return 1;
139     return 0;
142 Bool
143 IsPointerEvent(InternalEvent* event)
145     switch(event->any.type)
146     {
147         case ET_ButtonPress:
148         case ET_ButtonRelease:
149         case ET_Motion:
150             /* XXX: enter/leave ?? */
151             return TRUE;
152         default:
153             break;
154     }
155     return FALSE;
158 Bool
159 IsTouchEvent(InternalEvent* event)
161     switch(event->any.type)
162     {
163         case ET_TouchBegin:
164         case ET_TouchUpdate:
165         case ET_TouchEnd:
166             return TRUE;
167         default:
168             break;
169     }
170     return FALSE;
173 /**
174  * @return the device matching the deviceid of the device set in the event, or
175  * NULL if the event is not an XInput event.
176  */
177 DeviceIntPtr
178 XIGetDevice(xEvent* xE)
180     DeviceIntPtr pDev = NULL;
182     if (xE->u.u.type == DeviceButtonPress ||
183         xE->u.u.type == DeviceButtonRelease ||
184         xE->u.u.type == DeviceMotionNotify ||
185         xE->u.u.type == ProximityIn ||
186         xE->u.u.type == ProximityOut ||
187         xE->u.u.type == DevicePropertyNotify)
188     {
189         int rc;
190         int id;
192         id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
194         rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
195         if (rc != Success)
196             ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
197     }
198     return pDev;
202 /**
203  * Copy the device->key into master->key and send a mapping notify to the
204  * clients if appropriate.
205  * master->key needs to be allocated by the caller.
206  *
207  * Device is the slave device. If it is attached to a master device, we may
208  * need to send a mapping notify to the client because it causes the MD
209  * to change state.
210  *
211  * Mapping notify needs to be sent in the following cases:
212  *      - different slave device on same master
213  *      - different master
214  *
215  * XXX: They way how the code is we also send a map notify if the slave device
216  * stays the same, but the master changes. This isn't really necessary though.
217  *
218  * XXX: this gives you funny behaviour with the ClientPointer. When a
219  * MappingNotify is sent to the client, the client usually responds with a
220  * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
221  * mapping, regardless of which keyboard sent the last mapping notify request.
222  * So depending on the CP setting, your keyboard may change layout in each
223  * app...
224  *
225  * This code is basically the old SwitchCoreKeyboard.
226  */
228 void
229 CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
231     KeyClassPtr mk = master->key;
233     if (device == master)
234         return;
236     mk->sourceid = device->id;
239     if (!XkbCopyDeviceKeymap(master, device))
240         FatalError("Couldn't pivot keymap from device to core!\n");
243 /**
244  * Copies the feedback classes from device "from" into device "to". Classes
245  * are duplicated (not just flipping the pointers). All feedback classes are
246  * linked lists, the full list is duplicated.
247  */
248 static void
249 DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
251     ClassesPtr classes;
254     if (from->intfeed)
255     {
256         IntegerFeedbackPtr *i, it;
258         if (!to->intfeed)
259         {
260             classes = to->unused_classes;
261             to->intfeed = classes->intfeed;
262             classes->intfeed = NULL;
263         }
265         i = &to->intfeed;
266         for (it = from->intfeed; it; it = it->next)
267         {
268             if (!(*i))
269             {
270                 *i = calloc(1, sizeof(IntegerFeedbackClassRec));
271                 if (!(*i))
272                 {
273                     ErrorF("[Xi] Cannot alloc memory for class copy.");
274                     return;
275                 }
276             }
277             (*i)->CtrlProc = it->CtrlProc;
278             (*i)->ctrl     = it->ctrl;
280             i = &(*i)->next;
281         }
282     } else if (to->intfeed && !from->intfeed)
283     {
284         ClassesPtr classes;
285         classes = to->unused_classes;
286         classes->intfeed = to->intfeed;
287         to->intfeed      = NULL;
288     }
290     if (from->stringfeed)
291     {
292         StringFeedbackPtr *s, it;
294         if (!to->stringfeed)
295         {
296             classes = to->unused_classes;
297             to->stringfeed = classes->stringfeed;
298             classes->stringfeed = NULL;
299         }
301         s = &to->stringfeed;
302         for (it = from->stringfeed; it; it = it->next)
303         {
304             if (!(*s))
305             {
306                 *s = calloc(1, sizeof(StringFeedbackClassRec));
307                 if (!(*s))
308                 {
309                     ErrorF("[Xi] Cannot alloc memory for class copy.");
310                     return;
311                 }
312             }
313             (*s)->CtrlProc = it->CtrlProc;
314             (*s)->ctrl     = it->ctrl;
316             s = &(*s)->next;
317         }
318     } else if (to->stringfeed && !from->stringfeed)
319     {
320         ClassesPtr classes;
321         classes = to->unused_classes;
322         classes->stringfeed = to->stringfeed;
323         to->stringfeed      = NULL;
324     }
326     if (from->bell)
327     {
328         BellFeedbackPtr *b, it;
330         if (!to->bell)
331         {
332             classes = to->unused_classes;
333             to->bell = classes->bell;
334             classes->bell = NULL;
335         }
337         b = &to->bell;
338         for (it = from->bell; it; it = it->next)
339         {
340             if (!(*b))
341             {
342                 *b = calloc(1, sizeof(BellFeedbackClassRec));
343                 if (!(*b))
344                 {
345                     ErrorF("[Xi] Cannot alloc memory for class copy.");
346                     return;
347                 }
348             }
349             (*b)->BellProc = it->BellProc;
350             (*b)->CtrlProc = it->CtrlProc;
351             (*b)->ctrl     = it->ctrl;
353             b = &(*b)->next;
354         }
355     } else if (to->bell && !from->bell)
356     {
357         ClassesPtr classes;
358         classes = to->unused_classes;
359         classes->bell = to->bell;
360         to->bell      = NULL;
361     }
363     if (from->leds)
364     {
365         LedFeedbackPtr *l, it;
367         if (!to->leds)
368         {
369             classes = to->unused_classes;
370             to->leds = classes->leds;
371             classes->leds = NULL;
372         }
374         l = &to->leds;
375         for (it = from->leds; it; it = it->next)
376         {
377             if (!(*l))
378             {
379                 *l = calloc(1, sizeof(LedFeedbackClassRec));
380                 if (!(*l))
381                 {
382                     ErrorF("[Xi] Cannot alloc memory for class copy.");
383                     return;
384                 }
385             }
386             (*l)->CtrlProc = it->CtrlProc;
387             (*l)->ctrl     = it->ctrl;
388             if ((*l)->xkb_sli)
389                 XkbFreeSrvLedInfo((*l)->xkb_sli);
390             (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
392             l = &(*l)->next;
393         }
394     } else if (to->leds && !from->leds)
395     {
396         ClassesPtr classes;
397         classes = to->unused_classes;
398         classes->leds = to->leds;
399         to->leds      = NULL;
400     }
403 static void
404 DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
406     ClassesPtr classes;
408     /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
409      * kbdfeed to be set up properly, so let's do the feedback classes first.
410      */
411     if (from->kbdfeed)
412     {
413         KbdFeedbackPtr *k, it;
415         if (!to->kbdfeed)
416         {
417             classes = to->unused_classes;
419             to->kbdfeed = classes->kbdfeed;
420             if (!to->kbdfeed)
421                 InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
422             classes->kbdfeed = NULL;
423         }
425         k = &to->kbdfeed;
426         for(it = from->kbdfeed; it; it = it->next)
427         {
428             if (!(*k))
429             {
430                 *k = calloc(1, sizeof(KbdFeedbackClassRec));
431                 if (!*k)
432                 {
433                     ErrorF("[Xi] Cannot alloc memory for class copy.");
434                     return;
435                 }
436             }
437             (*k)->BellProc = it->BellProc;
438             (*k)->CtrlProc = it->CtrlProc;
439             (*k)->ctrl     = it->ctrl;
440             if ((*k)->xkb_sli)
441                 XkbFreeSrvLedInfo((*k)->xkb_sli);
442             (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
444             k = &(*k)->next;
445         }
446     } else if (to->kbdfeed && !from->kbdfeed)
447     {
448         ClassesPtr classes;
449         classes = to->unused_classes;
450         classes->kbdfeed = to->kbdfeed;
451         to->kbdfeed      = NULL;
452     }
454     if (from->key)
455     {
456         if (!to->key)
457         {
458             classes = to->unused_classes;
459             to->key = classes->key;
460             if (!to->key)
461                 InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
462             else
463                 classes->key = NULL;
464         }
466         CopyKeyClass(from, to);
467     } else if (to->key && !from->key)
468     {
469         ClassesPtr classes;
470         classes = to->unused_classes;
471         classes->key = to->key;
472         to->key      = NULL;
473     }
475     /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
476      * pointer point into the xkbInfo->desc struct.  XkbCopySrvLedInfo
477      * didn't update the pointers so we need to do it manually here.
478      */
479     if (to->kbdfeed)
480     {
481         KbdFeedbackPtr k;
483         for (k = to->kbdfeed; k; k = k->next)
484         {
485             if (!k->xkb_sli)
486                 continue;
487             if (k->xkb_sli->flags & XkbSLI_IsDefault)
488             {
489                 k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
490                 k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
491             }
492         }
493     }
495     /* We can't just copy over the focus class. When an app sets the focus,
496      * it'll do so on the master device. Copying the SDs focus means losing
497      * the focus.
498      * So we only copy the focus class if the device didn't have one,
499      * otherwise we leave it as it is.
500      */
501     if (from->focus)
502     {
503         if (!to->focus)
504         {
505             WindowPtr *oldTrace;
507             classes = to->unused_classes;
508             to->focus = classes->focus;
509             if (!to->focus)
510             {
511                 to->focus = calloc(1, sizeof(FocusClassRec));
512                 if (!to->focus)
513                     FatalError("[Xi] no memory for class shift.\n");
514             } else
515                 classes->focus = NULL;
517             oldTrace = to->focus->trace;
518             memcpy(to->focus, from->focus, sizeof(FocusClassRec));
519             to->focus->trace = realloc(oldTrace,
520                                   to->focus->traceSize * sizeof(WindowPtr));
521             if (!to->focus->trace && to->focus->traceSize)
522                 FatalError("[Xi] no memory for trace.\n");
523             memcpy(to->focus->trace, from->focus->trace,
524                     from->focus->traceSize * sizeof(WindowPtr));
525             to->focus->sourceid = from->id;
526         }
527     } else if (to->focus)
528     {
529         ClassesPtr classes;
530         classes = to->unused_classes;
531         classes->focus = to->focus;
532         to->focus      = NULL;
533     }
537 /* FIXME: this should really be shared with the InitValuatorAxisClassRec and
538  * similar */
539 static void
540 DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
542     ClassesPtr classes;
544     /* Feedback classes must be copied first */
545     if (from->ptrfeed)
546     {
547         PtrFeedbackPtr *p, it;
548         if (!to->ptrfeed)
549         {
550             classes = to->unused_classes;
551             to->ptrfeed = classes->ptrfeed;
552             classes->ptrfeed = NULL;
553         }
555         p = &to->ptrfeed;
556         for (it = from->ptrfeed; it; it = it->next)
557         {
558             if (!(*p))
559             {
560                 *p = calloc(1, sizeof(PtrFeedbackClassRec));
561                 if (!*p)
562                 {
563                     ErrorF("[Xi] Cannot alloc memory for class copy.");
564                     return;
565                 }
566             }
567             (*p)->CtrlProc = it->CtrlProc;
568             (*p)->ctrl     = it->ctrl;
570             p = &(*p)->next;
571         }
572     } else if (to->ptrfeed && !from->ptrfeed)
573     {
574         ClassesPtr classes;
575         classes = to->unused_classes;
576         classes->ptrfeed = to->ptrfeed;
577         to->ptrfeed      = NULL;
578     }
580     if (from->valuator)
581     {
582         ValuatorClassPtr v;
584         if (!to->valuator)
585         {
586             classes = to->unused_classes;
587             to->valuator = classes->valuator;
588             if (to->valuator)
589                 classes->valuator = NULL;
590         }
592         v = AllocValuatorClass(to->valuator, from->valuator->numAxes);
594         if (!v)
595             FatalError("[Xi] no memory for class shift.\n");
597         to->valuator = v;
598         memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
600         v->sourceid = from->id;
601     } else if (to->valuator && !from->valuator)
602     {
603         ClassesPtr classes;
604         classes = to->unused_classes;
605         classes->valuator = to->valuator;
606         to->valuator      = NULL;
607     }
609     if (from->button)
610     {
611         if (!to->button)
612         {
613             classes = to->unused_classes;
614             to->button = classes->button;
615             if (!to->button)
616             {
617                 to->button = calloc(1, sizeof(ButtonClassRec));
618                 if (!to->button)
619                     FatalError("[Xi] no memory for class shift.\n");
620             } else
621                 classes->button = NULL;
622         }
624         if (from->button->xkb_acts)
625         {
626             if (!to->button->xkb_acts)
627             {
628                 to->button->xkb_acts = calloc(1, sizeof(XkbAction));
629                 if (!to->button->xkb_acts)
630                     FatalError("[Xi] not enough memory for xkb_acts.\n");
631             }
632             memcpy(to->button->xkb_acts, from->button->xkb_acts,
633                     sizeof(XkbAction));
634         } else
635             free(to->button->xkb_acts);
637          memcpy(to->button->labels, from->button->labels,
638                 from->button->numButtons * sizeof(Atom));
639         to->button->sourceid = from->id;
640     } else if (to->button && !from->button)
641     {
642         ClassesPtr classes;
643         classes = to->unused_classes;
644         classes->button = to->button;
645         to->button      = NULL;
646     }
648     if (from->proximity)
649     {
650         if (!to->proximity)
651         {
652             classes = to->unused_classes;
653             to->proximity = classes->proximity;
654             if (!to->proximity)
655             {
656                 to->proximity = calloc(1, sizeof(ProximityClassRec));
657                 if (!to->proximity)
658                     FatalError("[Xi] no memory for class shift.\n");
659             } else
660                 classes->proximity = NULL;
661         }
662         memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
663         to->proximity->sourceid = from->id;
664     } else if (to->proximity)
665     {
666         ClassesPtr classes;
667         classes = to->unused_classes;
668         classes->proximity = to->proximity;
669         to->proximity      = NULL;
670     }
672     if (from->touch)
673     {
674         TouchClassPtr t, f;
675         if (!to->touch)
676         {
677             classes = to->unused_classes;
678             to->touch = classes->touch;
679             if (!to->touch)
680             {
681                 int i;
682                 to->touch = calloc(1, sizeof(TouchClassRec));
683                 if (!to->touch)
684                     FatalError("[Xi] no memory for class shift.\n");
685                 to->touch->num_touches = from->touch->num_touches;
686                 to->touch->touches = calloc(to->touch->num_touches,
687                                             sizeof(TouchPointInfoRec));
688                 for (i = 0; i < to->touch->num_touches; i++)
689                     TouchInitTouchPoint(to->touch, to->valuator, i);
690                 if (!to->touch)
691                     FatalError("[Xi] no memory for class shift.\n");
692             } else
693                 classes->touch = NULL;
694         }
697         t = to->touch;
698         f = from->touch;
699         t->sourceid = f->sourceid;
700         t->max_touches = f->max_touches;
701         t->mode = f->mode;
702         t->buttonsDown = f->buttonsDown;
703         t->state = f->state;
704         t->motionMask = f->motionMask;
705         /* to->touches and to->num_touches are separate on the master,
706          * don't copy */
707     }
708     /* Don't remove touch class if from->touch is non-existent. The to device
709      * may have an active touch grab, so we need to keep the touch class record
710      * around. */
713 /**
714  * Copies the CONTENT of the classes of device from into the classes in device
715  * to. From and to are identical after finishing.
716  *
717  * If to does not have classes from currenly has, the classes are stored in
718  * to's devPrivates system. Later, we recover it again from there if needed.
719  * Saves a few memory allocations.
720  */
721 void
722 DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce)
724     /* generic feedback classes, not tied to pointer and/or keyboard */
725     DeepCopyFeedbackClasses(from, to);
727     if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
728         DeepCopyKeyboardClasses(from, to);
729     if ((dce->flags & DEVCHANGE_POINTER_EVENT))
730         DeepCopyPointerClasses(from, to);
734 /**
735  * Send an XI2 DeviceChangedEvent to all interested clients.
736  */
737 void
738 XISendDeviceChangedEvent(DeviceIntPtr device, DeviceChangedEvent *dce)
740     xXIDeviceChangedEvent *dcce;
741     int rc;
743     rc = EventToXI2((InternalEvent*)dce, (xEvent**)&dcce);
744     if (rc != Success)
745     {
746         ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
747         return;
748     }
750     /* we don't actually swap if there's a NullClient, swapping is done
751      * later when event is delivered. */
752     SendEventToAllWindows(device, XI_DeviceChangedMask, (xEvent*)dcce, 1);
753     free(dcce);
756 static void
757 ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
759     DeviceIntPtr slave;
760     int rc;
762     /* For now, we don't have devices that change physically. */
763     if (!IsMaster(device))
764         return;
766     rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
768     if (rc != Success)
769         return; /* Device has disappeared */
771     if (IsMaster(slave))
772         return;
774     if (IsFloating(slave))
775         return; /* set floating since the event */
777     if (GetMaster(slave, MASTER_ATTACHED)->id != dce->masterid)
778         return; /* not our slave anymore, don't care */
780     /* FIXME: we probably need to send a DCE for the new slave now */
782     device->public.devicePrivate = slave->public.devicePrivate;
784     /* FIXME: the classes may have changed since we generated the event. */
785     DeepCopyDeviceClasses(slave, device, dce);
786     dce->deviceid = device->id;
787     XISendDeviceChangedEvent(device, dce);
790 /**
791  * Add state and motionMask to the filter for this event. The protocol
792  * supports some extra masks for motion when a button is down:
793  * ButtonXMotionMask and the DeviceButtonMotionMask to trigger only when at
794  * least one button (or that specific button is down). These masks need to
795  * be added to the filters for core/XI motion events.
796  *
797  * @param device The device to update the mask for
798  * @param state The current button state mask
799  * @param motion_mask The motion mask (DeviceButtonMotionMask or 0)
800  */
801 static void
802 UpdateDeviceMotionMask(DeviceIntPtr device, unsigned short state,
803                        Mask motion_mask)
805     Mask mask;
807     mask = DevicePointerMotionMask | state | motion_mask;
808     SetMaskForEvent(device->id, mask, DeviceMotionNotify);
809     mask = PointerMotionMask | state | motion_mask;
810     SetMaskForEvent(device->id, mask, MotionNotify);
813 static void
814 IncreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
815                     Mask *motion_mask, unsigned short *state)
817     if (dev->valuator)
818         dev->valuator->motionHintWindow = NullWindow;
820     (*buttons_down)++;
821     *motion_mask = DeviceButtonMotionMask;
822     if (dev->button->map[key] <= 5)
823         *state |= (Button1Mask >> 1) << dev->button->map[key];
826 static void
827 DecreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
828                     Mask *motion_mask, unsigned short *state)
830     if (dev->valuator)
831         dev->valuator->motionHintWindow = NullWindow;
833     if (*buttons_down >= 1 && !--(*buttons_down))
834         *motion_mask = 0;
835     if (dev->button->map[key] <= 5)
836         *state &= ~((Button1Mask >> 1) << dev->button->map[key]);
839 /**
840  * Update the device state according to the data in the event.
841  *
842  * return values are
843  *   DEFAULT ... process as normal
844  *   DONT_PROCESS ... return immediately from caller
845  */
846 #define DEFAULT 0
847 #define DONT_PROCESS 1
848 int
849 UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
851     int i;
852     int key = 0,
853         last_valuator;
855     KeyClassPtr k       = NULL;
856     ButtonClassPtr b    = NULL;
857     ValuatorClassPtr v  = NULL;
858     TouchClassPtr t     = NULL;
860     /* This event is always the first we get, before the actual events with
861      * the data. However, the way how the DDX is set up, "device" will
862      * actually be the slave device that caused the event.
863      */
864     switch(event->type)
865     {
866         case ET_DeviceChanged:
867             ChangeMasterDeviceClasses(device, (DeviceChangedEvent*)event);
868             return DONT_PROCESS; /* event has been sent already */
869         case ET_Motion:
870         case ET_ButtonPress:
871         case ET_ButtonRelease:
872         case ET_KeyPress:
873         case ET_KeyRelease:
874         case ET_ProximityIn:
875         case ET_ProximityOut:
876         case ET_TouchBegin:
877         case ET_TouchUpdate:
878         case ET_TouchEnd:
879             break;
880         default:
881             /* other events don't update the device */
882             return DEFAULT;
883     }
885     k = device->key;
886     v = device->valuator;
887     b = device->button;
888     t = device->touch;
890     key = event->detail.key;
892     /* Update device axis */
893     /* Check valuators first */
894     last_valuator = -1;
895     for (i = 0; i < MAX_VALUATORS; i++)
896     {
897         if (BitIsOn(&event->valuators.mask, i))
898         {
899             if (!v)
900             {
901                 ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
902                         "Ignoring event.\n", device->name);
903                 return DONT_PROCESS;
904             } else if (v->numAxes < i)
905             {
906                 ErrorF("[Xi] Too many valuators reported for device '%s'. "
907                         "Ignoring event.\n", device->name);
908                 return DONT_PROCESS;
909             }
910             last_valuator = i;
911         }
912     }
914     for (i = 0; i <= last_valuator && i < v->numAxes; i++)
915     {
916         /* XXX: Relative/Absolute mode */
917         if (BitIsOn(&event->valuators.mask, i))
918             v->axisVal[i] = event->valuators.data[i];
919     }
921     if (event->type == ET_KeyPress) {
922         if (!k)
923             return DONT_PROCESS;
925         /* don't allow ddx to generate multiple downs, but repeats are okay */
926         if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
927             return DONT_PROCESS;
929         if (device->valuator)
930             device->valuator->motionHintWindow = NullWindow;
931         set_key_down(device, key, KEY_PROCESSED);
932     } else if (event->type == ET_KeyRelease) {
933         if (!k)
934             return DONT_PROCESS;
936         if (!key_is_down(device, key, KEY_PROCESSED))   /* guard against duplicates */
937             return DONT_PROCESS;
938         if (device->valuator)
939             device->valuator->motionHintWindow = NullWindow;
940         set_key_up(device, key, KEY_PROCESSED);
941     } else if (event->type == ET_ButtonPress) {
942         if (!b)
943             return DONT_PROCESS;
945         if (button_is_down(device, key, BUTTON_PROCESSED))
946             return DONT_PROCESS;
948         set_button_down(device, key, BUTTON_PROCESSED);
950         if (!b->map[key])
951             return DONT_PROCESS;
953         IncreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask, &b->state);
954         UpdateDeviceMotionMask(device, b->state, b->motionMask);
955     } else if (event->type == ET_ButtonRelease) {
956         if (!b)
957             return DONT_PROCESS;
959         if (!button_is_down(device, key, BUTTON_PROCESSED))
960             return DONT_PROCESS;
961         if (IsMaster(device)) {
962             DeviceIntPtr sd;
964             /*
965              * Leave the button down if any slave has the
966              * button still down. Note that this depends on the
967              * event being delivered through the slave first
968              */
969             for (sd = inputInfo.devices; sd; sd = sd->next) {
970                 if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER) != device)
971                     continue;
972                 if (!sd->button)
973                     continue;
974                 for (i = 1; i <= sd->button->numButtons; i++)
975                     if (sd->button->map[i] == key &&
976                         button_is_down(sd, i, BUTTON_PROCESSED))
977                         return DONT_PROCESS;
978             }
979         }
980         set_button_up(device, key, BUTTON_PROCESSED);
981         if (!b->map[key])
982             return DONT_PROCESS;
984         DecreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask, &b->state);
985         UpdateDeviceMotionMask(device,  b->state, b->motionMask);
986     } else if (event->type == ET_ProximityIn)
987         device->proximity->in_proximity = TRUE;
988     else if (event->type == ET_ProximityOut)
989         device->proximity->in_proximity = FALSE;
990     else if (event->type == ET_TouchBegin) {
991         BUG_WARN(!b || !v);
992         BUG_WARN(!t);
994         if (!b || !t || !b->map[key])
995             return DONT_PROCESS;
997         if (!(event->flags & TOUCH_POINTER_EMULATED) ||
998             (event->flags & TOUCH_REPLAYING))
999             return DONT_PROCESS;
1001         IncreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask, &t->state);
1002         UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
1003     } else if (event->type == ET_TouchEnd) {
1004         BUG_WARN(!b || !v);
1005         BUG_WARN(!t);
1007         if (!b || !t || t->buttonsDown <= 0 || !b->map[key])
1008             return DONT_PROCESS;
1010         if (!(event->flags & TOUCH_POINTER_EMULATED))
1011             return DONT_PROCESS;
1012         if (!(event->flags & TOUCH_END))
1013             return DONT_PROCESS;
1015         DecreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask, &t->state);
1016         UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
1017     }
1019     return DEFAULT;
1022 /**
1023  * A client that does not have the TouchOwnership mask set may not receive a
1024  * TouchBegin event if there is at least one grab active.
1025  *
1026  * @return TRUE if the client selected for ownership events on the given
1027  * window for this device, FALSE otherwise
1028  */
1029 static inline Bool
1030 TouchClientWantsOwnershipEvents(ClientPtr client, DeviceIntPtr dev, WindowPtr win)
1032     InputClients *iclient;
1034     nt_list_for_each_entry(iclient, wOtherInputMasks(win)->inputClients, next)
1035     {
1036         if (rClient(iclient) != client)
1037             continue;
1039         return xi2mask_isset(iclient->xi2mask, dev, XI_TouchOwnership);
1040     }
1042     return FALSE;
1045 static void
1046 TouchSendOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, int reason, XID resource)
1048     int nev, i;
1049     InternalEvent *tel = InitEventList(GetMaximumEventsNum());
1051     nev = GetTouchOwnershipEvents(tel, dev, ti, reason, resource, 0);
1052     for (i = 0; i < nev; i++)
1053         mieqProcessDeviceEvent(dev, tel + i, NULL);
1055     FreeEventList(tel, GetMaximumEventsNum());
1058 /**
1059  * Attempts to deliver a touch event to the given client.
1060  */
1061 static Bool
1062 DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
1063                      GrabPtr grab, WindowPtr win, InternalEvent *ev)
1065     int err;
1066     xEvent *xi2;
1067     Mask filter;
1068     Window child = DeepestSpriteWin(&ti->sprite)->drawable.id;
1070     /* FIXME: owner event handling */
1072     /* If the client does not have the ownership mask set and is not
1073      * the current owner of the touch, only pretend we delivered */
1074     if (!grab && ti->num_grabs != 0 &&
1075            !TouchClientWantsOwnershipEvents(client, dev,win))
1076            return TRUE;
1078     /* If we fail here, we're going to leave a client hanging. */
1079     err = EventToXI2(ev, &xi2);
1080     if (err != Success)
1081         FatalError("[Xi] %s: XI2 conversion failed in %s"
1082                    " (%d)\n", dev->name, __func__, err);
1084     FixUpEventFromWindow(&ti->sprite, xi2, win, child, FALSE);
1085     filter = GetEventFilter(dev, xi2);
1086     if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success)
1087         return FALSE;
1088     err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab);
1089     free(xi2);
1091     /* Returning the value from TryClientEvents isn't useful, since all our
1092      * resource-gone cleanups will update the delivery list anyway. */
1093     return TRUE;
1096 static void
1097 ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
1099     int rc;
1100     ClientPtr client;
1101     XID error;
1103     rc = dixLookupClient(&client, ti->listeners[0].listener, serverClient,
1104                          DixSendAccess);
1105     if (rc != Success)
1106     {
1107         ErrorF("[Xi] Failed to lookup early accepting client.\n");
1108         return;
1109     }
1111     if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id,
1112                           ti->listeners[0].window->drawable.id, &error) !=
1113         Success)
1114         ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
1117 /**
1118  * Generate and deliver a TouchEnd event.
1119  *
1120  * @param dev The device to deliver the event for.
1121  * @param ti The touch point record to deliver the event for.
1122  * @param flags Internal event flags. The called does not need to provide
1123  *        TOUCH_CLIENT_ID and TOUCH_POINTER_EMULATED, this function will ensure
1124  *        they are set appropriately.
1125  * @param resource The client resource to deliver to, or 0 for all clients.
1126  */
1127 static void
1128 EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
1130     InternalEvent *tel = InitEventList(GetMaximumEventsNum());
1131     ValuatorMask *mask = valuator_mask_new(2);
1132     int i, nev;
1134     valuator_mask_set_double(mask, 0,
1135                              valuator_mask_get_double(ti->valuators, 0));
1136     valuator_mask_set_double(mask, 1,
1137                              valuator_mask_get_double(ti->valuators, 1));
1139     flags |= TOUCH_CLIENT_ID;
1140     if (ti->emulate_pointer)
1141         flags |= TOUCH_POINTER_EMULATED;
1142     nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd, flags, mask);
1143     for (i = 0; i < nev; i++)
1144         DeliverTouchEvents(dev, ti, tel + i, resource);
1146     valuator_mask_free(&mask);
1147     FreeEventList(tel, GetMaximumEventsNum());
1150 /**
1151  * If the current owner has rejected the event, deliver the
1152  * TouchOwnership/TouchBegin to the next item in the sprite stack.
1153  */
1154 static void
1155 TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
1156                      TouchOwnershipEvent *ev)
1158     /* Deliver the ownership */
1159     if (ti->listeners[0].state == LISTENER_AWAITING_OWNER ||
1160         ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
1161         DeliverTouchEvents(dev, ti, (InternalEvent*)ev, ti->listeners[0].listener);
1162     else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN)
1163         TouchEventHistoryReplay(ti, dev, ti->listeners[0].listener);
1165     /* If we've just removed the last grab and the touch has physically
1166      * ended, send a TouchEnd event too and finalise the touch. */
1167     if (ti->num_listeners == 1 && ti->num_grabs == 0 &&
1168             ti->pending_finish)
1169     {
1170         EmitTouchEnd(dev, ti, 0, 0);
1171         TouchEndTouch(dev, ti);
1172         return;
1173     }
1175     if (ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
1176         ActivateEarlyAccept(dev, ti);
1179 /**
1180  * Process a touch rejection.
1181  *
1182  * @param sourcedev The source device of the touch sequence.
1183  * @param ti The touchpoint info record.
1184  * @param resource The resource of the client rejecting the touch.
1185  * @param ev TouchOwnership event to send. Set to NULL if no event should be
1186  *        sent.
1187  */
1188 void
1189 TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
1190               TouchOwnershipEvent *ev)
1192     Bool was_owner = (resource == ti->listeners[0].listener);
1193     void *grab;
1194     int i;
1196     /* Send a TouchEnd event to the resource being removed, but only if they
1197      * haven't received one yet already */
1198     for (i = 0; i < ti->num_listeners; i++)
1199     {
1200         if (ti->listeners[i].listener == resource)
1201         {
1202             if (ti->listeners[i].state != LISTENER_HAS_END)
1203                 EmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource);
1204             break;
1205         }
1206     }
1208     /* If there are no other listeners left, and the touchpoint is pending
1209      * finish, then we can just kill it now. */
1210     if (ti->num_listeners == 1 && ti->pending_finish)
1211     {
1212         TouchEndTouch(sourcedev, ti);
1213         return;
1214     }
1216     /* Remove the resource from the listener list, updating
1217      * ti->num_listeners, as well as ti->num_grabs if it was a grab. */
1218     if (TouchRemoveListener(ti, resource))
1219     {
1220         if (dixLookupResourceByType(&grab, resource, RT_PASSIVEGRAB,
1221                                     serverClient, DixGetAttrAccess) == Success)
1222             ti->num_grabs--;
1223     }
1225     /* If the current owner was removed and there are further listeners, deliver
1226      * the TouchOwnership or TouchBegin event to the new owner. */
1227     if (ev && ti->num_listeners > 0 && was_owner)
1228         TouchPuntToNextOwner(sourcedev, ti, ev);
1231 /**
1232  * Processes a TouchOwnership event, indicating a grab has accepted the touch
1233  * it currently owns, or a grab or selection has been removed.  Will generate
1234  * and send TouchEnd events to all clients removed from the delivery list, as
1235  * well as possibly sending the new TouchOwnership event.  May end the
1236  * touchpoint if it is pending finish.
1237  */
1238 static void
1239 ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1240                            TouchOwnershipEvent *ev)
1243     if (ev->reason == XIRejectTouch)
1244         TouchRejected(dev, ti, ev->resource, ev);
1245     else if (ev->reason == XIAcceptTouch) {
1246         /* The touch owner has accepted the touch.  Send TouchEnd events to
1247          * everyone else, and truncate the list of listeners. */
1248         EmitTouchEnd(dev, ti, TOUCH_ACCEPT, 0);
1250         while (ti->num_listeners > 1)
1251             TouchRemoveListener(ti, ti->listeners[1].listener);
1252         /* Owner accepted after receiving end */
1253         if (ti->listeners[0].state == LISTENER_HAS_END)
1254             TouchEndTouch(dev, ti);
1255         else
1256             ti->listeners[0].state = LISTENER_HAS_ACCEPTED;
1257     } else { /* this is the very first ownership event for a grab */
1258         DeliverTouchEvents(dev, ti, (InternalEvent*)ev, ev->resource);
1259     }
1262 /**
1263  * Copy the event's valuator information into the touchpoint, we may need
1264  * this for emulated TouchEnd events.
1265  */
1266 static void
1267 TouchCopyValuatorData(DeviceEvent *ev, TouchPointInfoPtr ti)
1269     int i;
1270     for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++)
1271         if (BitIsOn(ev->valuators.mask, i))
1272             valuator_mask_set_double(ti->valuators, i, ev->valuators.data[i]);
1275 /**
1276  * Given a touch event and a potential listener, retrieve info needed for
1277  * processing the event.
1278  *
1279  * @param dev The device generating the touch event.
1280  * @param ti The touch point info record for the touch event.
1281  * @param ev The touch event to process.
1282  * @param listener The touch event listener that may receive the touch event.
1283  * @param[out] client The client that should receive the touch event.
1284  * @param[out] win The window to deliver the event on.
1285  * @param[out] grab The grab to deliver the event through, if any.
1286  * @param[out] mask The XI 2.x event mask of the grab or selection, if any.
1287  * @return TRUE if an event should be delivered to the listener, FALSE
1288  *         otherwise.
1289  */
1290 static Bool
1291 RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
1292                           InternalEvent *ev, TouchListener *listener,
1293                           ClientPtr *client, WindowPtr *win, GrabPtr *grab,
1294                           XI2Mask **mask)
1296      int rc;
1297      InputClients *iclients = NULL;
1299     if (listener->type == LISTENER_GRAB ||
1300         listener->type == LISTENER_POINTER_GRAB)
1301     {
1302         rc = dixLookupResourceByType((pointer*)grab, listener->listener,
1303                 RT_PASSIVEGRAB,
1304                 serverClient, DixSendAccess);
1305         if (rc != Success)
1306         {
1307             /* the grab doesn't exist but we have a grabbing listener - this
1308              * is an implicit/active grab */
1309             rc = dixLookupClient(client, listener->listener, serverClient, DixSendAccess);
1310             if (rc != Success)
1311                 return FALSE;
1313             *grab = dev->deviceGrab.grab;
1314             if (!*grab)
1315                 return FALSE;
1316         }
1318         *client = rClient(*grab);
1319         *win = (*grab)->window;
1320         *mask = (*grab)->xi2mask;
1321     } else {
1322         if (listener->level == CORE)
1323             rc = dixLookupWindow(win, listener->listener,
1324                                  serverClient, DixSendAccess);
1325         else
1326             rc = dixLookupResourceByType((pointer*)win, listener->listener,
1327                                          RT_INPUTCLIENT,
1328                                          serverClient, DixSendAccess);
1329         if (rc != Success)
1330             return FALSE;
1333         if (listener->level == XI2)
1334         {
1335             int evtype;
1336             if (ti->emulate_pointer && listener->type == LISTENER_POINTER_REGULAR)
1337                 evtype = GetXI2Type(TouchGetPointerEventType(ev));
1338             else
1339                 evtype = GetXI2Type(ev->any.type);
1341             nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next)
1342                 if (xi2mask_isset(iclients->xi2mask, dev, evtype))
1343                     break;
1344             BUG_WARN(!iclients);
1345             if (!iclients)
1346                 return FALSE;
1347         } else if (listener->level == XI)
1348         {
1349             int xi_type = GetXIType(TouchGetPointerEventType(ev));
1350             Mask xi_filter = event_get_filter_from_type(dev, xi_type);
1351             nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next)
1352                 if (iclients->mask[dev->id] & xi_filter)
1353                     break;
1354             BUG_WARN(!iclients);
1355             if (!iclients)
1356                 return FALSE;
1357         } else
1358         {
1359             int coretype = GetCoreType(TouchGetPointerEventType(ev));
1360             Mask core_filter = event_get_filter_from_type(dev, coretype);
1362             /* all others */
1363             nt_list_for_each_entry(iclients, (InputClients*)wOtherClients(*win), next)
1364                 if (iclients->mask[XIAllDevices] & core_filter)
1365                     break;
1366             /* if owner selected, iclients is NULL */
1367         }
1369         *client = iclients ? rClient(iclients) : wClient(*win);
1370         *mask = iclients ? iclients->xi2mask : NULL;
1371         *grab = NULL;
1372     }
1374     return TRUE;
1377 static int
1378 DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1379                           TouchListener *listener, ClientPtr client,
1380                           WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1382     InternalEvent motion, button;
1383     InternalEvent *ptrev = &motion;
1384     int nevents;
1385     DeviceIntPtr kbd;
1387     /* We don't deliver pointer events to non-owners */
1388     if (!TouchResourceIsOwner(ti, listener->listener))
1389         return Success;
1391     nevents = TouchConvertToPointerEvent(ev, &motion, &button);
1392     BUG_WARN(nevents == 0);
1393     if (nevents == 0)
1394         return BadValue;
1396     if (nevents > 1)
1397         ptrev = &button;
1399     kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
1400     event_set_state(dev, kbd, &ptrev->device_event);
1401     ptrev->device_event.corestate = event_get_corestate(dev, kbd);
1403     if (grab)
1404     {
1405         /* this side-steps the usual activation mechansims, but... */
1406         if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab)
1407                 ActivatePassiveGrab(dev, grab, ptrev, ev); /* also delivers the event */
1408         else {
1409             int deliveries = 0;
1410             /* 'grab' is the passive grab, but if the grab isn't active,
1411              * don't deliver */
1412             if (!dev->deviceGrab.grab)
1413                 return Success;
1415             if (grab->ownerEvents)
1416             {
1417                 WindowPtr focus = NullWindow;
1418                 WindowPtr win = dev->spriteInfo->sprite->win;
1419                 deliveries = DeliverDeviceEvents(win, ptrev, grab, focus, dev);
1420             }
1422             if (!deliveries)
1423                 DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
1425             if (ev->any.type == ET_TouchEnd &&
1426                 !dev->button->buttonsDown &&
1427                 dev->deviceGrab.fromPassiveGrab &&
1428                 GrabIsPointerGrab(grab))
1429                 (*dev->deviceGrab.DeactivateGrab)(dev);
1430         }
1431     } else
1432     {
1433         GrabPtr devgrab = dev->deviceGrab.grab;
1435         DeliverDeviceEvents(win, ptrev, grab, win, dev);
1436         /* FIXME: bad hack
1437          * Implicit passive grab activated in response to this event. Store
1438          * the event.
1439          */
1440         if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab)
1441         {
1442             TouchListener *listener;
1444             devgrab = dev->deviceGrab.grab;
1446             *dev->deviceGrab.sync.event = ev->device_event;
1448             /* The listener array has a sequence of grabs and then one event
1449              * selection. Implicit grab activation occurs through delivering an
1450              * event selection. Thus, we update the last listener in the array.
1451              */
1452             listener = &ti->listeners[ti->num_listeners - 1];
1453             listener->listener = devgrab->resource;
1455             if (devgrab->grabtype != XI2 ||
1456                 devgrab->type != XI_TouchBegin)
1457                 listener->type = LISTENER_POINTER_GRAB;
1458             else
1459                 listener->type = LISTENER_GRAB;
1460         }
1462     }
1463     if (ev->any.type == ET_TouchBegin)
1464         listener->state = LISTENER_IS_OWNER;
1465     else if (ev->any.type == ET_TouchEnd)
1466         listener->state = LISTENER_HAS_END;
1468     return Success;
1474 static void
1475 DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1476                            InternalEvent *ev)
1478     InternalEvent motion;
1480     if (ti->num_listeners)
1481     {
1482         ClientPtr client;
1483         WindowPtr win;
1484         GrabPtr grab;
1485         XI2Mask *mask;
1487         if (ti->listeners[0].type != LISTENER_POINTER_REGULAR ||
1488             ti->listeners[0].type != LISTENER_POINTER_GRAB)
1489             return;
1491         motion = *ev;
1492         motion.any.type = ET_TouchUpdate;
1493         motion.device_event.detail.button = 0;
1495         if (!RetrieveTouchDeliveryData(dev, ti, &motion,
1496                                        &ti->listeners[0], &client, &win, &grab,
1497                                        &mask))
1498             return;
1500         /* There may be a pointer grab on the device */
1501         if (!grab)
1502         {
1503             grab = dev->deviceGrab.grab;
1504             if (grab)
1505             {
1506                 win = grab->window;
1507                 mask = grab->xi2mask;
1508                 client = rClient(grab);
1509             }
1510         }
1512         DeliverTouchEmulatedEvent(dev, ti, &motion, &ti->listeners[0], client, win, grab, mask);
1513     } else {
1514         InternalEvent button;
1515         int converted;
1516         converted = TouchConvertToPointerEvent(ev, &motion, &button);
1518         BUG_WARN(converted == 0);
1519         if (converted)
1520             ProcessOtherEvent(&motion, dev);
1521     }
1524 /**
1525  * Processes and delivers a TouchBegin, TouchUpdate, or a
1526  * TouchEnd event.
1527  *
1528  * Due to having rather different delivery semantics (see the Xi 2.2 protocol
1529  * spec for more information), this implements its own grab and event-selection
1530  * delivery logic.
1531  */
1532 static void
1533 ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
1535     TouchClassPtr t = dev->touch;
1536     TouchPointInfoPtr ti;
1537     uint32_t touchid;
1538     int type = ev->any.type;
1539     int emulate_pointer = !!(ev->device_event.flags & TOUCH_POINTER_EMULATED);
1541     if (!t)
1542         return;
1544     if (ev->any.type == ET_TouchOwnership)
1545         touchid = ev->touch_ownership_event.touchid;
1546     else
1547         touchid = ev->device_event.touchid;
1549     if (type == ET_TouchBegin) {
1550         ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
1551                              emulate_pointer);
1552     } else
1553         ti = TouchFindByClientID(dev, touchid);
1555     if (!ti)
1556     {
1557         DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
1558                dev->name, type, touchid);
1559         return;
1560     }
1563     /* if emulate_pointer is set, emulate the motion event right
1564      * here, so we can ignore it for button event emulation. TouchUpdate
1565      * events which _only_ emulate motion just work normally */
1566     if (emulate_pointer && ev->any.type != ET_TouchUpdate)
1567         DeliverEmulatedMotionEvent(dev, ti, ev);
1568     if (emulate_pointer && IsMaster(dev))
1569         CheckMotion(&ev->device_event, dev);
1571     /* Make sure we have a valid window trace for event delivery; must be
1572      * called after event type mutation. */
1573     /* FIXME: check this */
1574     if (!TouchEnsureSprite(dev, ti, ev))
1575         return;
1577     /* TouchOwnership events are handled separately from the rest, as they
1578      * have more complex semantics. */
1579     if (ev->any.type == ET_TouchOwnership)
1580         ProcessTouchOwnershipEvent(dev, ti, &ev->touch_ownership_event);
1581     else
1582     {
1583         TouchCopyValuatorData(&ev->device_event, ti);
1584         /* WARNING: the event type may change to TouchUpdate in
1585          * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
1586          * owner */
1587         DeliverTouchEvents(dev, ti, (InternalEvent *) ev, 0);
1588         if (ev->any.type == ET_TouchEnd)
1589             TouchEndTouch(dev, ti);
1590     }
1594 /**
1595  * Process DeviceEvents and DeviceChangedEvents.
1596  */
1597 static void
1598 ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
1600     GrabPtr grab;
1601     Bool deactivateDeviceGrab = FALSE;
1602     int key = 0, rootX, rootY;
1603     ButtonClassPtr b;
1604     int ret = 0;
1605     int corestate;
1606     DeviceIntPtr mouse = NULL, kbd = NULL;
1607     DeviceEvent *event = &ev->device_event;
1609     if (IsPointerDevice(device))
1610     {
1611         kbd = GetMaster(device, KEYBOARD_OR_FLOAT);
1612         mouse = device;
1613         if (!kbd->key) /* can happen with floating SDs */
1614             kbd = NULL;
1615     } else
1616     {
1617         mouse = GetMaster(device, POINTER_OR_FLOAT);
1618         kbd = device;
1619         if (!mouse->valuator || !mouse->button) /* may be float. SDs */
1620             mouse = NULL;
1621     }
1623     corestate = event_get_corestate(mouse, kbd);
1624     event_set_state(mouse, kbd, event);
1626     ret = UpdateDeviceState(device, event);
1627     if (ret == DONT_PROCESS)
1628         return;
1630     b = device->button;
1632     if (IsMaster(device) || IsFloating(device))
1633         CheckMotion(event, device);
1635     switch (event->type)
1636     {
1637         case ET_Motion:
1638         case ET_ButtonPress:
1639         case ET_ButtonRelease:
1640         case ET_KeyPress:
1641         case ET_KeyRelease:
1642         case ET_ProximityIn:
1643         case ET_ProximityOut:
1644             GetSpritePosition(device, &rootX, &rootY);
1645             event->root_x = rootX;
1646             event->root_y = rootY;
1647             NoticeEventTime((InternalEvent*)event);
1648             event->corestate = corestate;
1649             key = event->detail.key;
1650             break;
1651         default:
1652             break;
1653     }
1655     if (DeviceEventCallback && !syncEvents.playingEvents) {
1656         DeviceEventInfoRec eventinfo;
1657         SpritePtr pSprite = device->spriteInfo->sprite;
1659         /* see comment in EnqueueEvents regarding the next three lines */
1660         if (ev->any.type == ET_Motion)
1661             ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1663         eventinfo.device = device;
1664         eventinfo.event = ev;
1665         CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
1666     }
1668     grab = device->deviceGrab.grab;
1670     switch(event->type)
1671     {
1672         case ET_KeyPress:
1673             if (!grab && CheckDeviceGrabs(device, event, 0))
1674                 return;
1675             break;
1676         case ET_KeyRelease:
1677             if (grab && device->deviceGrab.fromPassiveGrab &&
1678                 (key == device->deviceGrab.activatingKey) &&
1679                 GrabIsKeyboardGrab(device->deviceGrab.grab))
1680                 deactivateDeviceGrab = TRUE;
1681             break;
1682         case ET_ButtonPress:
1683             if (b->map[key] == 0) /* there's no button 0 */
1684                 return;
1685             event->detail.button = b->map[key];
1686             if (!grab && CheckDeviceGrabs(device, event, 0))
1687             {
1688                 /* if a passive grab was activated, the event has been sent
1689                  * already */
1690                 return;
1691             }
1692             break;
1693         case ET_ButtonRelease:
1694             if (b->map[key] == 0) /* there's no button 0 */
1695                 return;
1696             event->detail.button = b->map[key];
1697             if (grab && !b->buttonsDown &&
1698                 device->deviceGrab.fromPassiveGrab &&
1699                 GrabIsPointerGrab(device->deviceGrab.grab))
1700                 deactivateDeviceGrab = TRUE;
1701         default:
1702             break;
1703     }
1706     if (grab)
1707         DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
1708     else if (device->focus && !IsPointerEvent(ev))
1709         DeliverFocusedEvent(device, (InternalEvent*)event,
1710                             GetSpriteWindow(device));
1711     else
1712         DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
1713                             NullGrab, NullWindow, device);
1715     if (deactivateDeviceGrab == TRUE)
1716         (*device->deviceGrab.DeactivateGrab) (device);
1717     event->detail.key = key;
1720 /**
1721  * Main device event processing function.
1722  * Called from when processing the events from the event queue.
1723  *
1724  */
1725 void
1726 ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
1728     verify_internal_event(ev);
1730     switch(ev->any.type)
1731     {
1732         case  ET_RawKeyPress:
1733         case  ET_RawKeyRelease:
1734         case  ET_RawButtonPress:
1735         case  ET_RawButtonRelease:
1736         case  ET_RawMotion:
1737         case  ET_RawTouchBegin:
1738         case  ET_RawTouchUpdate:
1739         case  ET_RawTouchEnd:
1740             DeliverRawEvent(&ev->raw_event, device);
1741             break;
1742         case  ET_TouchBegin:
1743         case  ET_TouchUpdate:
1744         case  ET_TouchOwnership:
1745         case  ET_TouchEnd:
1746             ProcessTouchEvent(ev, device);
1747             break;
1748         default:
1749             ProcessDeviceEvent(ev, device);
1750             break;
1751     }
1754 static int
1755 DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1756                        TouchListener *listener, ClientPtr client,
1757                        WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1759     enum TouchListenerState state;
1760     int rc = Success;
1761     Bool has_ownershipmask;
1763     if (listener->type == LISTENER_POINTER_REGULAR ||
1764         listener->type == LISTENER_POINTER_GRAB)
1765     {
1766         rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1767                                        grab, xi2mask);
1768         goto out;
1769     }
1772     has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
1774     if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
1775         rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1776     if (!TouchResourceIsOwner(ti, listener->listener))
1777     {
1778         if (has_ownershipmask)
1779             state = LISTENER_AWAITING_OWNER;
1780         else
1781             state = LISTENER_AWAITING_BEGIN;
1782     } else
1783     {
1784         if (has_ownershipmask)
1785             TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
1787         if (!has_ownershipmask || listener->type == LISTENER_REGULAR)
1788             state = LISTENER_HAS_ACCEPTED;
1789         else
1790             state = LISTENER_IS_OWNER;
1791     }
1792     listener->state = state;
1794 out:
1795     return rc;
1798 static int
1799 DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1800                      TouchListener *listener, ClientPtr client,
1801                      WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1803     int rc = Success;
1805     if (listener->type == LISTENER_POINTER_REGULAR ||
1806         listener->type == LISTENER_POINTER_GRAB)
1807     {
1808         rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1809                                        grab, xi2mask);
1810         goto out;
1811     }
1813     /* Event in response to reject */
1814     if (ev->device_event.flags & TOUCH_REJECT)
1815     {
1816         if (listener->state != LISTENER_HAS_END)
1817             rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1818         listener->state = LISTENER_HAS_END;
1819     } else if (TouchResourceIsOwner(ti, listener->listener))
1820     {
1821         Bool normal_end = !(ev->device_event.flags & TOUCH_ACCEPT);
1823         /* FIXME: what about early acceptance */
1824         if (normal_end && listener->state != LISTENER_HAS_END)
1825             rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1827         if ((ti->num_listeners > 1 ||
1828              listener->state != LISTENER_HAS_ACCEPTED) &&
1829             (ev->device_event.flags & (TOUCH_ACCEPT|TOUCH_REJECT)) == 0)
1830         {
1831             ev->any.type = ET_TouchUpdate;
1832             ev->device_event.flags |= TOUCH_PENDING_END;
1833             ti->pending_finish = TRUE;
1834         }
1836         if (normal_end)
1837             listener->state = LISTENER_HAS_END;
1838     }
1840 out:
1841     return rc;
1844 static int
1845 DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1846                   TouchListener *listener, ClientPtr client,
1847                   WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1849     Bool has_ownershipmask = FALSE;
1850     int rc = Success;
1852     if (xi2mask)
1853         has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
1855     if (ev->any.type == ET_TouchOwnership)
1856     {
1857         ev->touch_ownership_event.deviceid = dev->id;
1858         if (!TouchResourceIsOwner(ti, listener->listener))
1859             goto out;
1860         rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1861         listener->state = LISTENER_IS_OWNER;
1862     } else
1863         ev->device_event.deviceid = dev->id;
1865     if (ev->any.type == ET_TouchBegin)
1866     {
1867         rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
1868     } else if (ev->any.type == ET_TouchUpdate)
1869     {
1870         if (listener->type == LISTENER_POINTER_REGULAR ||
1871             listener->type == LISTENER_POINTER_GRAB)
1872             DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
1873         else if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
1874             rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1875     } else if (ev->any.type == ET_TouchEnd)
1876         rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
1878 out:
1879     return rc;
1882 /**
1883  * Delivers a touch events to all interested clients.  For TouchBegin events,
1884  * will update ti->listeners, ti->num_listeners, and ti->num_grabs.
1885  * May also mutate ev (type and flags) upon successful delivery.  If
1886  * @resource is non-zero, will only attempt delivery to the owner of that
1887  * resource.
1888  *
1889  * @return TRUE if the event was delivered at least once, FALSE otherwise
1890  */
1891 void
1892 DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
1893                    InternalEvent *ev, XID resource)
1895     int i;
1897     if (ev->any.type == ET_TouchBegin &&
1898         !(ev->device_event.flags & (TOUCH_CLIENT_ID|TOUCH_REPLAYING)))
1899         TouchSetupListeners(dev, ti, ev);
1901     TouchEventHistoryPush(ti, &ev->device_event);
1903     for (i = 0; i < ti->num_listeners; i++)
1904     {
1905         GrabPtr grab = NULL;
1906         ClientPtr client;
1907         WindowPtr win;
1908         XI2Mask *mask;
1909         TouchListener *listener = &ti->listeners[i];
1911         if (resource && listener->listener != resource)
1912             continue;
1914         if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win,
1915                                        &grab, &mask))
1916             continue;
1918         DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
1919     }
1921     if (ti->emulate_pointer)
1922         UpdateDeviceState(dev, &ev->device_event);
1925 int
1926 InitProximityClassDeviceStruct(DeviceIntPtr dev)
1928     ProximityClassPtr proxc;
1930     proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
1931     if (!proxc)
1932         return FALSE;
1933     proxc->sourceid = dev->id;
1934     proxc->in_proximity = TRUE;
1935     dev->proximity = proxc;
1936     return TRUE;
1939 /**
1940  * Initialise the device's valuators. The memory must already be allocated,
1941  * this function merely inits the matching axis (specified through axnum) to
1942  * sane values.
1943  *
1944  * It is a condition that (minval < maxval).
1945  *
1946  * @see InitValuatorClassDeviceStruct
1947  */
1948 Bool
1949 InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
1950                        int resolution, int min_res, int max_res, int mode)
1952     AxisInfoPtr ax;
1954     if (!dev || !dev->valuator || (minval > maxval && mode == Absolute))
1955         return FALSE;
1956     if (axnum >= dev->valuator->numAxes)
1957         return FALSE;
1959     ax = dev->valuator->axes + axnum;
1961     ax->min_value = minval;
1962     ax->max_value = maxval;
1963     ax->resolution = resolution;
1964     ax->min_resolution = min_res;
1965     ax->max_resolution = max_res;
1966     ax->label = label;
1967     ax->mode = mode;
1969     if (mode & OutOfProximity)
1970         dev->proximity->in_proximity = FALSE;
1972     return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE);
1975 /**
1976  * Set the given axis number as a scrolling valuator.
1977  */
1978 Bool
1979 SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type, double increment, int flags)
1981     AxisInfoPtr ax;
1982     int *current_ax;
1983     InternalEvent dce;
1984     DeviceIntPtr master;
1986     if (!dev || !dev->valuator || axnum >= dev->valuator->numAxes)
1987         return FALSE;
1989     switch (type)
1990     {
1991         case SCROLL_TYPE_VERTICAL:
1992             current_ax = &dev->valuator->v_scroll_axis;
1993             break;
1994         case SCROLL_TYPE_HORIZONTAL:
1995             current_ax = &dev->valuator->h_scroll_axis;
1996             break;
1997         case SCROLL_TYPE_NONE:
1998             ax = &dev->valuator->axes[axnum];
1999             ax->scroll.type = type;
2000             return TRUE;
2001         default:
2002             return FALSE;
2003     }
2005     if (increment == 0.0)
2006         return FALSE;
2008     if (*current_ax != -1 && axnum != *current_ax)
2009     {
2010         ax = &dev->valuator->axes[*current_ax];
2011         if (ax->scroll.type == type &&
2012             (flags & SCROLL_FLAG_PREFERRED) && (ax->scroll.flags & SCROLL_FLAG_PREFERRED))
2013             return FALSE;
2014     }
2015     *current_ax = axnum;
2017     ax = &dev->valuator->axes[axnum];
2018     ax->scroll.type = type;
2019     ax->scroll.increment = increment;
2020     ax->scroll.flags = flags;
2022     master = GetMaster(dev, MASTER_ATTACHED);
2023     CreateClassesChangedEvent(&dce, master, dev, DEVCHANGE_POINTER_EVENT | DEVCHANGE_DEVICE_CHANGE);
2024     XISendDeviceChangedEvent(dev, &dce.changed_event);
2026     /* if the current slave is us, update the master. If not, we'll update
2027      * whenever the next slave switch happens anyway. CMDC sends the event
2028      * for us */
2029     if (master && master->lastSlave == dev)
2030         ChangeMasterDeviceClasses(master, &dce.changed_event);
2032     return TRUE;
2035 static void
2036 FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
2037                      ButtonClassPtr b, ValuatorClassPtr v, int first)
2039     ev->type = DeviceStateNotify;
2040     ev->deviceid = dev->id;
2041     ev->time = currentTime.milliseconds;
2042     ev->classes_reported = 0;
2043     ev->num_keys = 0;
2044     ev->num_buttons = 0;
2045     ev->num_valuators = 0;
2047     if (b) {
2048         ev->classes_reported |= (1 << ButtonClass);
2049         ev->num_buttons = b->numButtons;
2050         memcpy((char*)ev->buttons, (char*)b->down, 4);
2051     } else if (k) {
2052         ev->classes_reported |= (1 << KeyClass);
2053         ev->num_keys = k->xkbInfo->desc->max_key_code -
2054                        k->xkbInfo->desc->min_key_code;
2055         memmove((char *)&ev->keys[0], (char *)k->down, 4);
2056     }
2057     if (v) {
2058         int nval = v->numAxes - first;
2060         ev->classes_reported |= (1 << ValuatorClass);
2061         ev->classes_reported |= valuator_get_mode(dev, 0) << ModeBitsShift;
2062         ev->num_valuators = nval < 3 ? nval : 3;
2063         switch (ev->num_valuators) {
2064         case 3:
2065             ev->valuator2 = v->axisVal[first + 2];
2066         case 2:
2067             ev->valuator1 = v->axisVal[first + 1];
2068         case 1:
2069             ev->valuator0 = v->axisVal[first];
2070             break;
2071         }
2072     }
2075 static void
2076 FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
2077                   int first)
2079     int nval = v->numAxes - first;
2081     ev->type = DeviceValuator;
2082     ev->deviceid = dev->id;
2083     ev->num_valuators = nval < 3 ? nval : 3;
2084     ev->first_valuator = first;
2085     switch (ev->num_valuators) {
2086     case 3:
2087         ev->valuator2 = v->axisVal[first + 2];
2088     case 2:
2089         ev->valuator1 = v->axisVal[first + 1];
2090     case 1:
2091         ev->valuator0 = v->axisVal[first];
2092         break;
2093     }
2094     first += ev->num_valuators;
2097 static void
2098 DeliverStateNotifyEvent(DeviceIntPtr dev, WindowPtr win)
2100     int evcount = 1;
2101     deviceStateNotify *ev, *sev;
2102     deviceKeyStateNotify *kev;
2103     deviceButtonStateNotify *bev;
2105     KeyClassPtr k;
2106     ButtonClassPtr b;
2107     ValuatorClassPtr v;
2108     int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
2110     if (!(wOtherInputMasks(win)) ||
2111         !(wOtherInputMasks(win)->inputEvents[dev->id] & DeviceStateNotifyMask))
2112         return;
2114     if ((b = dev->button) != NULL) {
2115         nbuttons = b->numButtons;
2116         if (nbuttons > 32)
2117             evcount++;
2118     }
2119     if ((k = dev->key) != NULL) {
2120         nkeys = k->xkbInfo->desc->max_key_code -
2121             k->xkbInfo->desc->min_key_code;
2122         if (nkeys > 32)
2123             evcount++;
2124         if (nbuttons > 0) {
2125             evcount++;
2126         }
2127     }
2128     if ((v = dev->valuator) != NULL) {
2129         nval = v->numAxes;
2131         if (nval > 3)
2132             evcount++;
2133         if (nval > 6) {
2134             if (!(k && b))
2135                 evcount++;
2136             if (nval > 9)
2137                 evcount += ((nval - 7) / 3);
2138         }
2139     }
2141     sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
2142     FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
2144     if (b != NULL) {
2145         FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
2146         first += 3;
2147         nval -= 3;
2148         if (nbuttons > 32) {
2149             (ev - 1)->deviceid |= MORE_EVENTS;
2150             bev = (deviceButtonStateNotify *) ev++;
2151             bev->type = DeviceButtonStateNotify;
2152             bev->deviceid = dev->id;
2153             memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
2154         }
2155         if (nval > 0) {
2156             (ev - 1)->deviceid |= MORE_EVENTS;
2157             FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
2158             first += 3;
2159             nval -= 3;
2160         }
2161     }
2163     if (k != NULL) {
2164         FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
2165         first += 3;
2166         nval -= 3;
2167         if (nkeys > 32) {
2168             (ev - 1)->deviceid |= MORE_EVENTS;
2169             kev = (deviceKeyStateNotify *) ev++;
2170             kev->type = DeviceKeyStateNotify;
2171             kev->deviceid = dev->id;
2172             memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
2173         }
2174         if (nval > 0) {
2175             (ev - 1)->deviceid |= MORE_EVENTS;
2176             FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
2177             first += 3;
2178             nval -= 3;
2179         }
2180     }
2182     while (nval > 0) {
2183         FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
2184         first += 3;
2185         nval -= 3;
2186         if (nval > 0) {
2187             (ev - 1)->deviceid |= MORE_EVENTS;
2188             FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
2189             first += 3;
2190             nval -= 3;
2191         }
2192     }
2194     DeliverEventsToWindow(dev, win, (xEvent *) sev, evcount,
2195                           DeviceStateNotifyMask, NullGrab);
2196     free(sev);
2199 void
2200 DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
2201                  WindowPtr pWin)
2203     deviceFocus event;
2204     xXIFocusInEvent *xi2event;
2205     DeviceIntPtr mouse;
2206     int btlen, len, i;
2208     mouse = IsFloating(dev) ? dev : GetMaster(dev, MASTER_POINTER);
2210     /* XI 2 event */
2211     btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
2212     btlen = bytes_to_int32(btlen);
2213     len = sizeof(xXIFocusInEvent) + btlen * 4;
2215     xi2event = calloc(1, len);
2216     xi2event->type         = GenericEvent;
2217     xi2event->extension    = IReqCode;
2218     xi2event->evtype       = type;
2219     xi2event->length       = bytes_to_int32(len - sizeof(xEvent));
2220     xi2event->buttons_len  = btlen;
2221     xi2event->detail       = detail;
2222     xi2event->time         = currentTime.milliseconds;
2223     xi2event->deviceid     = dev->id;
2224     xi2event->sourceid     = dev->id; /* a device doesn't change focus by itself */
2225     xi2event->mode         = mode;
2226     xi2event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
2227     xi2event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
2229     for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
2230         if (BitIsOn(mouse->button->down, i))
2231             SetBit(&xi2event[1], mouse->button->map[i]);
2233     if (dev->key)
2234     {
2235         xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
2236         xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
2237         xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
2238         xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
2240         xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
2241         xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
2242         xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
2243         xi2event->group.effective_group = dev->key->xkbInfo->state.group;
2244     }
2246     FixUpEventFromWindow(dev->spriteInfo->sprite, (xEvent*)xi2event, pWin,
2247                          None, FALSE);
2249     DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
2250                           GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
2252     free(xi2event);
2254     /* XI 1.x event */
2255     event.deviceid = dev->id;
2256     event.mode = mode;
2257     event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
2258     event.detail = detail;
2259     event.window = pWin->drawable.id;
2260     event.time = currentTime.milliseconds;
2262     DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
2263                                 DeviceFocusChangeMask, NullGrab);
2265     if (event.type == DeviceFocusIn)
2266         DeliverStateNotifyEvent(dev, pWin);
2269 int
2270 CheckGrabValues(ClientPtr client, GrabParameters* param)
2272     if (param->grabtype != CORE &&
2273         param->grabtype != XI &&
2274         param->grabtype != XI2)
2275     {
2276         ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
2277         return BadImplementation;
2278     }
2280     if ((param->this_device_mode != GrabModeSync) &&
2281         (param->this_device_mode != GrabModeAsync) &&
2282         (param->this_device_mode != XIGrabModeTouch)) {
2283         client->errorValue = param->this_device_mode;
2284         return BadValue;
2285     }
2286     if ((param->other_devices_mode != GrabModeSync) &&
2287         (param->other_devices_mode != GrabModeAsync) &&
2288         (param->other_devices_mode != XIGrabModeTouch)) {
2289         client->errorValue = param->other_devices_mode;
2290         return BadValue;
2291     }
2293     if (param->grabtype != XI2 && (param->modifiers != AnyModifier) &&
2294         (param->modifiers & ~AllModifiersMask)) {
2295         client->errorValue = param->modifiers;
2296         return BadValue;
2297     }
2299     if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
2300         client->errorValue = param->ownerEvents;
2301         return BadValue;
2302     }
2303     return Success;
2306 int
2307 GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2308            int button, GrabParameters *param, enum InputLevel grabtype,
2309            GrabMask *mask)
2311     WindowPtr pWin, confineTo;
2312     CursorPtr cursor;
2313     GrabPtr grab;
2314     int rc, type = -1;
2315     Mask access_mode = DixGrabAccess;
2317     rc = CheckGrabValues(client, param);
2318     if (rc != Success)
2319         return rc;
2320     if (param->confineTo == None)
2321         confineTo = NullWindow;
2322     else {
2323         rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
2324         if (rc != Success)
2325             return rc;
2326     }
2327     if (param->cursor == None)
2328         cursor = NullCursor;
2329     else {
2330         rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
2331                                      RT_CURSOR, client, DixUseAccess);
2332         if (rc != Success)
2333         {
2334             client->errorValue = param->cursor;
2335             return rc;
2336         }
2337         access_mode |= DixForceAccess;
2338     }
2339     if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
2340         access_mode |= DixFreezeAccess;
2341     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2342     if (rc != Success)
2343         return rc;
2344     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2345     if (rc != Success)
2346         return rc;
2348     if (grabtype == XI)
2349         type = DeviceButtonPress;
2350     else if (grabtype == XI2)
2351         type = XI_ButtonPress;
2353     grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2354                       mask, param, type, button, confineTo, cursor);
2355     if (!grab)
2356         return BadAlloc;
2357     return AddPassiveGrabToList(client, grab);
2360 /**
2361  * Grab the given key. If grabtype is XI, the key is a keycode. If
2362  * grabtype is XI2, the key is a keysym.
2363  */
2364 int
2365 GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2366         int key, GrabParameters *param, enum InputLevel grabtype, GrabMask *mask)
2368     WindowPtr pWin;
2369     GrabPtr grab;
2370     KeyClassPtr k = dev->key;
2371     Mask access_mode = DixGrabAccess;
2372     int rc, type = -1;
2374     rc = CheckGrabValues(client, param);
2375     if (rc != Success)
2376         return rc;
2377     if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL)
2378         return BadMatch;
2379     if (grabtype == XI)
2380     {
2381         if ((key > k->xkbInfo->desc->max_key_code ||
2382                     key < k->xkbInfo->desc->min_key_code)
2383                 && (key != AnyKey)) {
2384             client->errorValue = key;
2385             return BadValue;
2386         }
2387         type = DeviceKeyPress;
2388     } else if (grabtype == XI2)
2389         type = XI_KeyPress;
2391     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2392     if (rc != Success)
2393         return rc;
2394     if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
2395         access_mode |= DixFreezeAccess;
2396     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2397     if (rc != Success)
2398         return rc;
2400     grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2401                       mask, param, type, key, NULL, NULL);
2402     if (!grab)
2403         return BadAlloc;
2404     return AddPassiveGrabToList(client, grab);
2407 /* Enter/FocusIn grab */
2408 int
2409 GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
2410            GrabParameters *param, GrabMask *mask)
2412     WindowPtr pWin;
2413     CursorPtr cursor;
2414     GrabPtr grab;
2415     Mask access_mode = DixGrabAccess;
2416     int rc;
2418     rc = CheckGrabValues(client, param);
2419     if (rc != Success)
2420         return rc;
2422     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2423     if (rc != Success)
2424         return rc;
2425     if (param->cursor == None)
2426         cursor = NullCursor;
2427     else {
2428         rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
2429                                      RT_CURSOR, client, DixUseAccess);
2430         if (rc != Success)
2431         {
2432             client->errorValue = param->cursor;
2433             return rc;
2434         }
2435         access_mode |= DixForceAccess;
2436     }
2437     if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
2438         access_mode |= DixFreezeAccess;
2439     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2440     if (rc != Success)
2441         return rc;
2443     grab = CreateGrab(client->index, dev, dev, pWin, XI2,
2444                       mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
2445                       0, NULL, cursor);
2447     if (!grab)
2448         return BadAlloc;
2450     return AddPassiveGrabToList(client, grab);
2453 /* Touch grab */
2454 int
2455 GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
2456           GrabParameters *param, GrabMask *mask)
2458     WindowPtr pWin;
2459     GrabPtr grab;
2460     int rc;
2462     rc = CheckGrabValues(client, param);
2463     if (rc != Success)
2464         return rc;
2466     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2467     if (rc != Success)
2468        return rc;
2469     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGrabAccess);
2470     if (rc != Success)
2471        return rc;
2473     grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2,
2474                       mask, param, XI_TouchBegin, 0, NullWindow, NullCursor);
2475     if (!grab)
2476         return BadAlloc;
2478     return AddPassiveGrabToList(client, grab);
2481 int
2482 SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
2483                 Mask mask, Mask exclusivemasks)
2485     int mskidx = dev->id;
2486     int i, ret;
2487     Mask check;
2488     InputClientsPtr others;
2490     check = (mask & exclusivemasks);
2491     if (wOtherInputMasks(pWin)) {
2492         if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {      /* It is illegal for two different
2493                                                                          * clients to select on any of the
2494                                                                          * events for maskcheck. However,
2495                                                                          * it is OK, for some client to
2496                                                                          * continue selecting on one of those
2497                                                                          * events.  */
2498             for (others = wOtherInputMasks(pWin)->inputClients; others;
2499                  others = others->next) {
2500                 if (!SameClient(others, client) && (check &
2501                                                     others->mask[mskidx]))
2502                     return BadAccess;
2503             }
2504         }
2505         for (others = wOtherInputMasks(pWin)->inputClients; others;
2506              others = others->next) {
2507             if (SameClient(others, client)) {
2508                 check = others->mask[mskidx];
2509                 others->mask[mskidx] = mask;
2510                 if (mask == 0) {
2511                     for (i = 0; i < EMASKSIZE; i++)
2512                         if (i != mskidx && others->mask[i] != 0)
2513                             break;
2514                     if (i == EMASKSIZE) {
2515                         RecalculateDeviceDeliverableEvents(pWin);
2516                         if (ShouldFreeInputMasks(pWin, FALSE))
2517                             FreeResource(others->resource, RT_NONE);
2518                         return Success;
2519                     }
2520                 }
2521                 goto maskSet;
2522             }
2523         }
2524     }
2525     check = 0;
2526     if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
2527         return ret;
2528   maskSet:
2529     if (dev->valuator)
2530         if ((dev->valuator->motionHintWindow == pWin) &&
2531             (mask & DevicePointerMotionHintMask) &&
2532             !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
2533             dev->valuator->motionHintWindow = NullWindow;
2534     RecalculateDeviceDeliverableEvents(pWin);
2535     return Success;
2538 static void
2539 FreeInputClient(InputClientsPtr *other)
2541     xi2mask_free(&(*other)->xi2mask);
2542     free(*other);
2543     *other = NULL;
2546 static InputClientsPtr
2547 AllocInputClient(void)
2549     return calloc(1, sizeof(InputClients));
2552 int
2553 AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
2555     InputClientsPtr others;
2557     if (!pWin->optional && !MakeWindowOptional(pWin))
2558         return BadAlloc;
2559     others = AllocInputClient();
2560     if (!others)
2561         return BadAlloc;
2562     if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
2563         goto bail;
2564     others->xi2mask = xi2mask_new();
2565     if (!others->xi2mask)
2566         goto bail;
2567     others->mask[mskidx] = mask;
2568     others->resource = FakeClientID(client->index);
2569     others->next = pWin->optional->inputMasks->inputClients;
2570     pWin->optional->inputMasks->inputClients = others;
2571     if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
2572         goto bail;
2573     return Success;
2575 bail:
2576     FreeInputClient(&others);
2577     return BadAlloc;
2580 static Bool
2581 MakeInputMasks(WindowPtr pWin)
2583     struct _OtherInputMasks *imasks;
2585     imasks = calloc(1, sizeof(struct _OtherInputMasks));
2586     if (!imasks)
2587         return FALSE;
2588     imasks->xi2mask = xi2mask_new();
2589     if (!imasks->xi2mask)
2590     {
2591         free(imasks);
2592         return FALSE;
2593     }
2594     pWin->optional->inputMasks = imasks;
2595     return TRUE;
2598 static void
2599 FreeInputMask(OtherInputMasks **imask)
2601     xi2mask_free(&(*imask)->xi2mask);
2602     free(*imask);
2603     *imask = NULL;
2606 void
2607 RecalculateDeviceDeliverableEvents(WindowPtr pWin)
2609     InputClientsPtr others;
2610     struct _OtherInputMasks *inputMasks;        /* default: NULL */
2611     WindowPtr pChild, tmp;
2612     int i;
2614     pChild = pWin;
2615     while (1) {
2616         if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
2617             xi2mask_zero(inputMasks->xi2mask, -1);
2618             for (others = inputMasks->inputClients; others;
2619                  others = others->next) {
2620                 for (i = 0; i < EMASKSIZE; i++)
2621                     inputMasks->inputEvents[i] |= others->mask[i];
2622                 xi2mask_merge(inputMasks->xi2mask, others->xi2mask);
2623             }
2624             for (i = 0; i < EMASKSIZE; i++)
2625                 inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
2626             for (tmp = pChild->parent; tmp; tmp = tmp->parent)
2627                 if (wOtherInputMasks(tmp))
2628                     for (i = 0; i < EMASKSIZE; i++)
2629                         inputMasks->deliverableEvents[i] |=
2630                             (wOtherInputMasks(tmp)->deliverableEvents[i]
2631                              & ~inputMasks->
2632                              dontPropagateMask[i] & PropagateMask[i]);
2633         }
2634         if (pChild->firstChild) {
2635             pChild = pChild->firstChild;
2636             continue;
2637         }
2638         while (!pChild->nextSib && (pChild != pWin))
2639             pChild = pChild->parent;
2640         if (pChild == pWin)
2641             break;
2642         pChild = pChild->nextSib;
2643     }
2646 int
2647 InputClientGone(WindowPtr pWin, XID id)
2649     InputClientsPtr other, prev;
2651     if (!wOtherInputMasks(pWin))
2652         return Success;
2653     prev = 0;
2654     for (other = wOtherInputMasks(pWin)->inputClients; other;
2655          other = other->next) {
2656         if (other->resource == id) {
2657             if (prev) {
2658                 prev->next = other->next;
2659                 FreeInputClient(&other);
2660             } else if (!(other->next)) {
2661                 if (ShouldFreeInputMasks(pWin, TRUE)) {
2662                     OtherInputMasks *mask = wOtherInputMasks(pWin);
2663                     mask->inputClients = other->next;
2664                     FreeInputMask(&mask);
2665                     pWin->optional->inputMasks = (OtherInputMasks *) NULL;
2666                     CheckWindowOptionalNeed(pWin);
2667                     FreeInputClient(&other);
2668                 } else {
2669                     other->resource = FakeClientID(0);
2670                     if (!AddResource(other->resource, RT_INPUTCLIENT,
2671                                      (pointer) pWin))
2672                         return BadAlloc;
2673                 }
2674             } else {
2675                 wOtherInputMasks(pWin)->inputClients = other->next;
2676                 FreeInputClient(&other);
2677             }
2678             RecalculateDeviceDeliverableEvents(pWin);
2679             return Success;
2680         }
2681         prev = other;
2682     }
2683     FatalError("client not on device event list");
2686 /**
2687  * Search for window in each touch trace for each device. Remove the window
2688  * and all its subwindows from the trace when found. The initial window
2689  * order is preserved.
2690  */
2691 void WindowGone(WindowPtr win)
2693     DeviceIntPtr dev;
2695     for (dev = inputInfo.devices; dev; dev = dev->next) {
2696         TouchClassPtr t = dev->touch;
2697         int i;
2699         if (!t)
2700             continue;
2702         for (i = 0; i < t->num_touches; i++) {
2703             SpritePtr sprite = &t->touches[i].sprite;
2704             int j;
2706             for (j = 0; j < sprite->spriteTraceGood; j++) {
2707                 if (sprite->spriteTrace[j] == win) {
2708                     sprite->spriteTraceGood = j;
2709                     break;
2710                 }
2711             }
2712         }
2713     }
2716 int
2717 SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
2718           xEvent * ev, Mask mask, int count)
2720     WindowPtr pWin;
2721     WindowPtr effectiveFocus = NullWindow;      /* only set if dest==InputFocus */
2722     WindowPtr spriteWin = GetSpriteWindow(d);
2724     if (dest == PointerWindow)
2725         pWin = spriteWin;
2726     else if (dest == InputFocus) {
2727         WindowPtr inputFocus;
2729         if (!d->focus)
2730             inputFocus = spriteWin;
2731         else
2732             inputFocus = d->focus->win;
2734         if (inputFocus == FollowKeyboardWin)
2735             inputFocus = inputInfo.keyboard->focus->win;
2737         if (inputFocus == NoneWin)
2738             return Success;
2740         /* If the input focus is PointerRootWin, send the event to where
2741          * the pointer is if possible, then perhaps propogate up to root. */
2742         if (inputFocus == PointerRootWin)
2743             inputFocus = GetCurrentRootWindow(d);
2745         if (IsParent(inputFocus, spriteWin)) {
2746             effectiveFocus = inputFocus;
2747             pWin = spriteWin;
2748         } else
2749             effectiveFocus = pWin = inputFocus;
2750     } else
2751         dixLookupWindow(&pWin, dest, client, DixSendAccess);
2752     if (!pWin)
2753         return BadWindow;
2754     if ((propagate != xFalse) && (propagate != xTrue)) {
2755         client->errorValue = propagate;
2756         return BadValue;
2757     }
2758     ev->u.u.type |= 0x80;
2759     if (propagate) {
2760         for (; pWin; pWin = pWin->parent) {
2761             if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
2762                 return Success;
2763             if (pWin == effectiveFocus)
2764                 return Success;
2765             if (wOtherInputMasks(pWin))
2766                 mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
2767             if (!mask)
2768                 break;
2769         }
2770     } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
2771         DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
2772     return Success;
2775 int
2776 SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
2778     int i;
2779     ButtonClassPtr b = dev->button;
2781     if (b == NULL)
2782         return BadMatch;
2784     if (nElts != b->numButtons) {
2785         client->errorValue = nElts;
2786         return BadValue;
2787     }
2788     if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
2789         return BadValue;
2790     for (i = 0; i < nElts; i++)
2791         if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
2792             return MappingBusy;
2793     for (i = 0; i < nElts; i++)
2794         b->map[i + 1] = map[i];
2795     return Success;
2798 int
2799 ChangeKeyMapping(ClientPtr client,
2800                  DeviceIntPtr dev,
2801                  unsigned len,
2802                  int type,
2803                  KeyCode firstKeyCode,
2804                  CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
2806     KeySymsRec keysyms;
2807     KeyClassPtr k = dev->key;
2809     if (k == NULL)
2810         return BadMatch;
2812     if (len != (keyCodes * keySymsPerKeyCode))
2813         return BadLength;
2815     if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
2816         (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
2817         client->errorValue = firstKeyCode;
2818         return BadValue;
2819     }
2820     if (keySymsPerKeyCode == 0) {
2821         client->errorValue = 0;
2822         return BadValue;
2823     }
2824     keysyms.minKeyCode = firstKeyCode;
2825     keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
2826     keysyms.mapWidth = keySymsPerKeyCode;
2827     keysyms.map = map;
2829     XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
2830                           serverClient);
2832     return Success;
2835 static void
2836 DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
2838     WindowPtr parent;
2840     /* Deactivate any grabs performed on this window, before making
2841      * any input focus changes.
2842      * Deactivating a device grab should cause focus events. */
2844     if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
2845         (*dev->deviceGrab.DeactivateGrab) (dev);
2847     /* If the focus window is a root window (ie. has no parent)
2848      * then don't delete the focus from it. */
2850     if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
2851         int focusEventMode = NotifyNormal;
2853         /* If a grab is in progress, then alter the mode of focus events. */
2855         if (dev->deviceGrab.grab)
2856             focusEventMode = NotifyWhileGrabbed;
2858         switch (dev->focus->revert) {
2859         case RevertToNone:
2860             if (!ActivateFocusInGrab(dev, pWin, NoneWin))
2861                 DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
2862             dev->focus->win = NoneWin;
2863             dev->focus->traceGood = 0;
2864             break;
2865         case RevertToParent:
2866             parent = pWin;
2867             do {
2868                 parent = parent->parent;
2869                 dev->focus->traceGood--;
2870             }
2871             while (!parent->realized);
2872             if (!ActivateFocusInGrab(dev, pWin, parent))
2873                 DoFocusEvents(dev, pWin, parent, focusEventMode);
2874             dev->focus->win = parent;
2875             dev->focus->revert = RevertToNone;
2876             break;
2877         case RevertToPointerRoot:
2878             if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
2879                 DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
2880             dev->focus->win = PointerRootWin;
2881             dev->focus->traceGood = 0;
2882             break;
2883         case RevertToFollowKeyboard:
2884             {
2885                 DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
2886                 if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
2887                     kbd = inputInfo.keyboard;
2888             if (kbd->focus->win) {
2889                 if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
2890                     DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
2891                 dev->focus->win = FollowKeyboardWin;
2892                 dev->focus->traceGood = 0;
2893             } else {
2894                 if (!ActivateFocusInGrab(dev, pWin, NoneWin))
2895                     DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
2896                 dev->focus->win = NoneWin;
2897                 dev->focus->traceGood = 0;
2898             }
2899             }
2900             break;
2901         }
2902     }
2904     if (dev->valuator)
2905         if (dev->valuator->motionHintWindow == pWin)
2906             dev->valuator->motionHintWindow = NullWindow;
2909 void
2910 DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
2912     int i;
2913     DeviceIntPtr dev;
2914     InputClientsPtr ic;
2915     struct _OtherInputMasks *inputMasks;
2917     for (dev = inputInfo.devices; dev; dev = dev->next) {
2918         DeleteDeviceFromAnyExtEvents(pWin, dev);
2919     }
2921     for (dev = inputInfo.off_devices; dev; dev = dev->next)
2922         DeleteDeviceFromAnyExtEvents(pWin, dev);
2924     if (freeResources)
2925         while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
2926             ic = inputMasks->inputClients;
2927             for (i = 0; i < EMASKSIZE; i++)
2928                 inputMasks->dontPropagateMask[i] = 0;
2929             FreeResource(ic->resource, RT_NONE);
2930         }
2933 int
2934 MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
2936     DeviceIntPtr dev;
2938     dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
2939                     DixReadAccess);
2940     if (!dev)
2941         return 0;
2943     if (pEvents->type == DeviceMotionNotify) {
2944         if (mask & DevicePointerMotionHintMask) {
2945             if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
2946                 return 1;       /* don't send, but pretend we did */
2947             }
2948             pEvents->detail = NotifyHint;
2949         } else {
2950             pEvents->detail = NotifyNormal;
2951         }
2952     }
2953     return 0;
2956 void
2957 CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
2958                              deviceKeyButtonPointer * xE, GrabPtr grab,
2959                              ClientPtr client, Mask deliveryMask)
2961     DeviceIntPtr dev;
2963     dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
2964                     DixGrabAccess);
2965     if (!dev)
2966         return;
2968     if (type == DeviceMotionNotify)
2969         dev->valuator->motionHintWindow = pWin;
2970     else if ((type == DeviceButtonPress) && (!grab) &&
2971              (deliveryMask & DeviceButtonGrabMask)) {
2972         GrabPtr tempGrab;
2974         tempGrab = AllocGrab();
2975         if (!tempGrab)
2976             return;
2978         tempGrab->device = dev;
2979         tempGrab->resource = client->clientAsMask;
2980         tempGrab->window = pWin;
2981         tempGrab->ownerEvents =
2982             (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
2983         tempGrab->eventMask = deliveryMask;
2984         tempGrab->keyboardMode = GrabModeAsync;
2985         tempGrab->pointerMode = GrabModeAsync;
2986         tempGrab->confineTo = NullWindow;
2987         tempGrab->cursor = NullCursor;
2988         tempGrab->next = NULL;
2989         (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE);
2990         FreeGrab(tempGrab);
2991     }
2994 static Mask
2995 DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
2997     InputClientsPtr other;
2999     if (!wOtherInputMasks(pWin))
3000         return 0;
3001     for (other = wOtherInputMasks(pWin)->inputClients; other;
3002          other = other->next) {
3003         if (SameClient(other, client))
3004             return other->mask[dev->id];
3005     }
3006     return 0;
3009 void
3010 MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
3012     WindowPtr pWin;
3013     GrabPtr grab = dev->deviceGrab.grab;
3015     pWin = dev->valuator->motionHintWindow;
3017     if ((grab && SameClient(grab, client) &&
3018          ((grab->eventMask & DevicePointerMotionHintMask) ||
3019           (grab->ownerEvents &&
3020            (DeviceEventMaskForClient(dev, pWin, client) &
3021             DevicePointerMotionHintMask)))) ||
3022         (!grab &&
3023          (DeviceEventMaskForClient(dev, pWin, client) &
3024           DevicePointerMotionHintMask)))
3025         dev->valuator->motionHintWindow = NullWindow;
3028 int
3029 DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
3030                              int maskndx)
3032     struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
3034     if (mask & ~PropagateMask[maskndx]) {
3035         client->errorValue = mask;
3036         return BadValue;
3037     }
3039     if (mask == 0) {
3040         if (inputMasks)
3041             inputMasks->dontPropagateMask[maskndx] = mask;
3042     } else {
3043         if (!inputMasks)
3044             AddExtensionClient(pWin, client, 0, 0);
3045         inputMasks = wOtherInputMasks(pWin);
3046         inputMasks->dontPropagateMask[maskndx] = mask;
3047     }
3048     RecalculateDeviceDeliverableEvents(pWin);
3049     if (ShouldFreeInputMasks(pWin, FALSE))
3050         FreeResource(inputMasks->inputClients->resource, RT_NONE);
3051     return Success;
3054 Bool
3055 ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
3057     int i;
3058     Mask allInputEventMasks = 0;
3059     struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
3061     for (i = 0; i < EMASKSIZE; i++)
3062         allInputEventMasks |= inputMasks->dontPropagateMask[i];
3063     if (!ignoreSelectedEvents)
3064         for (i = 0; i < EMASKSIZE; i++)
3065             allInputEventMasks |= inputMasks->inputEvents[i];
3066     if (allInputEventMasks == 0)
3067         return TRUE;
3068     else
3069         return FALSE;
3072 /***********************************************************************
3073  *
3074  * Walk through the window tree, finding all clients that want to know
3075  * about the Event.
3076  *
3077  */
3079 static void
3080 FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
3081                        xEvent * ev, int count)
3083     WindowPtr p2;
3085     while (p1) {
3086         p2 = p1->firstChild;
3087         DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
3088         FindInterestedChildren(dev, p2, mask, ev, count);
3089         p1 = p1->nextSib;
3090     }
3093 /***********************************************************************
3094  *
3095  * Send an event to interested clients in all windows on all screens.
3096  *
3097  */
3099 void
3100 SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
3102     int i;
3103     WindowPtr pWin, p1;
3105     for (i = 0; i < screenInfo.numScreens; i++) {
3106         pWin = screenInfo.screens[i]->root;
3107         if (!pWin)
3108             continue;
3109         DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
3110         p1 = pWin->firstChild;
3111         FindInterestedChildren(dev, p1, mask, ev, count);
3112     }
3115 /**
3116  * Set the XI2 mask for the given client on the given window.
3117  * @param dev The device to set the mask for.
3118  * @param win The window to set the mask on.
3119  * @param client The client setting the mask.
3120  * @param len Number of bytes in mask.
3121  * @param mask Event mask in the form of (1 << eventtype)
3122  */
3123 int
3124 XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
3125                unsigned int len, unsigned char* mask)
3127     OtherInputMasks *masks;
3128     InputClientsPtr others = NULL;
3130     masks = wOtherInputMasks(win);
3131     if (masks)
3132     {
3133         for (others = wOtherInputMasks(win)->inputClients; others;
3134              others = others->next) {
3135             if (SameClient(others, client)) {
3136                 xi2mask_zero(others->xi2mask, dev->id);
3137                 break;
3138             }
3139         }
3140     }
3143     if (len && !others)
3144     {
3145         if (AddExtensionClient(win, client, 0, 0) != Success)
3146             return BadAlloc;
3147         others= wOtherInputMasks(win)->inputClients;
3148     }
3150     if (others) {
3151         xi2mask_zero(others->xi2mask, dev->id);
3152         len = min(len, xi2mask_mask_size(others->xi2mask));
3153     }
3155     if (len) {
3156         xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len);
3157     }
3159     RecalculateDeviceDeliverableEvents(win);
3161     return Success;