]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/xserver.git/blob - Xi/exevents.c
6b2db4b5988060da60ffb61706edabe3576732db
[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         TouchPointInfoPtr tmp;
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         }
695         tmp = to->touch->touches;
696         memcpy(to->touch, from->touch, sizeof(TouchClassRec));
697         to->touch->touches = tmp;
698         to->touch->sourceid = from->id;
699     } else if (to->touch)
700     {
701         ClassesPtr classes;
702         classes = to->unused_classes;
703         classes->touch = to->touch;
704         to->touch      = NULL;
705     }
708 /**
709  * Copies the CONTENT of the classes of device from into the classes in device
710  * to. From and to are identical after finishing.
711  *
712  * If to does not have classes from currenly has, the classes are stored in
713  * to's devPrivates system. Later, we recover it again from there if needed.
714  * Saves a few memory allocations.
715  */
716 void
717 DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce)
719     /* generic feedback classes, not tied to pointer and/or keyboard */
720     DeepCopyFeedbackClasses(from, to);
722     if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
723         DeepCopyKeyboardClasses(from, to);
724     if ((dce->flags & DEVCHANGE_POINTER_EVENT))
725         DeepCopyPointerClasses(from, to);
729 /**
730  * Send an XI2 DeviceChangedEvent to all interested clients.
731  */
732 void
733 XISendDeviceChangedEvent(DeviceIntPtr device, DeviceChangedEvent *dce)
735     xXIDeviceChangedEvent *dcce;
736     int rc;
738     rc = EventToXI2((InternalEvent*)dce, (xEvent**)&dcce);
739     if (rc != Success)
740     {
741         ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
742         return;
743     }
745     /* we don't actually swap if there's a NullClient, swapping is done
746      * later when event is delivered. */
747     SendEventToAllWindows(device, XI_DeviceChangedMask, (xEvent*)dcce, 1);
748     free(dcce);
751 static void
752 ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
754     DeviceIntPtr slave;
755     int rc;
757     /* For now, we don't have devices that change physically. */
758     if (!IsMaster(device))
759         return;
761     rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
763     if (rc != Success)
764         return; /* Device has disappeared */
766     if (IsMaster(slave))
767         return;
769     if (IsFloating(slave))
770         return; /* set floating since the event */
772     if (GetMaster(slave, MASTER_ATTACHED)->id != dce->masterid)
773         return; /* not our slave anymore, don't care */
775     /* FIXME: we probably need to send a DCE for the new slave now */
777     device->public.devicePrivate = slave->public.devicePrivate;
779     /* FIXME: the classes may have changed since we generated the event. */
780     DeepCopyDeviceClasses(slave, device, dce);
781     dce->deviceid = device->id;
782     XISendDeviceChangedEvent(device, dce);
785 /**
786  * Add state and motionMask to the filter for this event. The protocol
787  * supports some extra masks for motion when a button is down:
788  * ButtonXMotionMask and the DeviceButtonMotionMask to trigger only when at
789  * least one button (or that specific button is down). These masks need to
790  * be added to the filters for core/XI motion events.
791  *
792  * @param device The device to update the mask for
793  * @param state The current button state mask
794  * @param motion_mask The motion mask (DeviceButtonMotionMask or 0)
795  */
796 static void
797 UpdateDeviceMotionMask(DeviceIntPtr device, unsigned short state,
798                        Mask motion_mask)
800     Mask mask;
802     mask = DevicePointerMotionMask | state | motion_mask;
803     SetMaskForEvent(device->id, mask, DeviceMotionNotify);
804     mask = PointerMotionMask | state | motion_mask;
805     SetMaskForEvent(device->id, mask, MotionNotify);
808 static void
809 IncreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
810                     Mask *motion_mask, unsigned short *state)
812     if (dev->valuator)
813         dev->valuator->motionHintWindow = NullWindow;
815     (*buttons_down)++;
816     *motion_mask = DeviceButtonMotionMask;
817     if (dev->button->map[key] <= 5)
818         *state |= (Button1Mask >> 1) << dev->button->map[key];
821 static void
822 DecreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
823                     Mask *motion_mask, unsigned short *state)
825     if (dev->valuator)
826         dev->valuator->motionHintWindow = NullWindow;
828     if (*buttons_down >= 1 && !--(*buttons_down))
829         *motion_mask = 0;
830     if (dev->button->map[key] <= 5)
831         *state &= ~((Button1Mask >> 1) << dev->button->map[key]);
834 /**
835  * Update the device state according to the data in the event.
836  *
837  * return values are
838  *   DEFAULT ... process as normal
839  *   DONT_PROCESS ... return immediately from caller
840  */
841 #define DEFAULT 0
842 #define DONT_PROCESS 1
843 int
844 UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
846     int i;
847     int key = 0,
848         last_valuator;
850     KeyClassPtr k       = NULL;
851     ButtonClassPtr b    = NULL;
852     ValuatorClassPtr v  = NULL;
853     TouchClassPtr t     = NULL;
855     /* This event is always the first we get, before the actual events with
856      * the data. However, the way how the DDX is set up, "device" will
857      * actually be the slave device that caused the event.
858      */
859     switch(event->type)
860     {
861         case ET_DeviceChanged:
862             ChangeMasterDeviceClasses(device, (DeviceChangedEvent*)event);
863             return DONT_PROCESS; /* event has been sent already */
864         case ET_Motion:
865         case ET_ButtonPress:
866         case ET_ButtonRelease:
867         case ET_KeyPress:
868         case ET_KeyRelease:
869         case ET_ProximityIn:
870         case ET_ProximityOut:
871         case ET_TouchBegin:
872         case ET_TouchUpdate:
873         case ET_TouchEnd:
874             break;
875         default:
876             /* other events don't update the device */
877             return DEFAULT;
878     }
880     k = device->key;
881     v = device->valuator;
882     b = device->button;
883     t = device->touch;
885     key = event->detail.key;
887     /* Update device axis */
888     /* Check valuators first */
889     last_valuator = -1;
890     for (i = 0; i < MAX_VALUATORS; i++)
891     {
892         if (BitIsOn(&event->valuators.mask, i))
893         {
894             if (!v)
895             {
896                 ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
897                         "Ignoring event.\n", device->name);
898                 return DONT_PROCESS;
899             } else if (v->numAxes < i)
900             {
901                 ErrorF("[Xi] Too many valuators reported for device '%s'. "
902                         "Ignoring event.\n", device->name);
903                 return DONT_PROCESS;
904             }
905             last_valuator = i;
906         }
907     }
909     for (i = 0; i <= last_valuator && i < v->numAxes; i++)
910     {
911         /* XXX: Relative/Absolute mode */
912         if (BitIsOn(&event->valuators.mask, i))
913             v->axisVal[i] = event->valuators.data[i];
914     }
916     if (event->type == ET_KeyPress) {
917         if (!k)
918             return DONT_PROCESS;
920         /* don't allow ddx to generate multiple downs, but repeats are okay */
921         if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
922             return DONT_PROCESS;
924         if (device->valuator)
925             device->valuator->motionHintWindow = NullWindow;
926         set_key_down(device, key, KEY_PROCESSED);
927     } else if (event->type == ET_KeyRelease) {
928         if (!k)
929             return DONT_PROCESS;
931         if (!key_is_down(device, key, KEY_PROCESSED))   /* guard against duplicates */
932             return DONT_PROCESS;
933         if (device->valuator)
934             device->valuator->motionHintWindow = NullWindow;
935         set_key_up(device, key, KEY_PROCESSED);
936     } else if (event->type == ET_ButtonPress) {
937         if (!b)
938             return DONT_PROCESS;
940         if (button_is_down(device, key, BUTTON_PROCESSED))
941             return DONT_PROCESS;
943         set_button_down(device, key, BUTTON_PROCESSED);
945         if (!b->map[key])
946             return DONT_PROCESS;
948         IncreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask, &b->state);
949         UpdateDeviceMotionMask(device, b->state, b->motionMask);
950     } else if (event->type == ET_ButtonRelease) {
951         if (!b)
952             return DONT_PROCESS;
954         if (!button_is_down(device, key, BUTTON_PROCESSED))
955             return DONT_PROCESS;
956         if (IsMaster(device)) {
957             DeviceIntPtr sd;
959             /*
960              * Leave the button down if any slave has the
961              * button still down. Note that this depends on the
962              * event being delivered through the slave first
963              */
964             for (sd = inputInfo.devices; sd; sd = sd->next) {
965                 if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER) != device)
966                     continue;
967                 if (!sd->button)
968                     continue;
969                 for (i = 1; i <= sd->button->numButtons; i++)
970                     if (sd->button->map[i] == key &&
971                         button_is_down(sd, i, BUTTON_PROCESSED))
972                         return DONT_PROCESS;
973             }
974         }
975         set_button_up(device, key, BUTTON_PROCESSED);
976         if (!b->map[key])
977             return DONT_PROCESS;
979         DecreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask, &b->state);
980         UpdateDeviceMotionMask(device,  b->state, b->motionMask);
981     } else if (event->type == ET_ProximityIn)
982         device->proximity->in_proximity = TRUE;
983     else if (event->type == ET_ProximityOut)
984         device->proximity->in_proximity = FALSE;
985     else if (event->type == ET_TouchBegin) {
986         BUG_WARN(!b || !v);
987         BUG_WARN(!t);
989         if (!b || !t || !b->map[key])
990             return DONT_PROCESS;
992         if (!(event->flags & TOUCH_POINTER_EMULATED) ||
993             (event->flags & TOUCH_REPLAYING))
994             return DONT_PROCESS;
996         IncreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask, &t->state);
997         UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
998     } else if (event->type == ET_TouchEnd) {
999         BUG_WARN(!b || !v);
1000         BUG_WARN(!t);
1002         if (!b || !t || t->buttonsDown <= 0 || !b->map[key])
1003             return DONT_PROCESS;
1005         if (!(event->flags & TOUCH_POINTER_EMULATED))
1006             return DONT_PROCESS;
1007         if (!(event->flags & TOUCH_END))
1008             return DONT_PROCESS;
1010         DecreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask, &t->state);
1011         UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
1012     }
1014     return DEFAULT;
1017 /**
1018  * A client that does not have the TouchOwnership mask set may not receive a
1019  * TouchBegin event if there is at least one grab active.
1020  *
1021  * @return TRUE if the client selected for ownership events on the given
1022  * window for this device, FALSE otherwise
1023  */
1024 static inline Bool
1025 TouchClientWantsOwnershipEvents(ClientPtr client, DeviceIntPtr dev, WindowPtr win)
1027     InputClients *iclient;
1029     nt_list_for_each_entry(iclient, wOtherInputMasks(win)->inputClients, next)
1030     {
1031         if (rClient(iclient) != client)
1032             continue;
1034         return xi2mask_isset(iclient->xi2mask, dev, XI_TouchOwnership);
1035     }
1037     return FALSE;
1040 static void
1041 TouchSendOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, int reason, XID resource)
1043     int nev, i;
1044     InternalEvent *tel = InitEventList(GetMaximumEventsNum());
1046     nev = GetTouchOwnershipEvents(tel, dev, ti, reason, resource, 0);
1047     for (i = 0; i < nev; i++)
1048         mieqProcessDeviceEvent(dev, tel + i, NULL);
1050     FreeEventList(tel, GetMaximumEventsNum());
1053 /**
1054  * Attempts to deliver a touch event to the given client.
1055  */
1056 static Bool
1057 DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
1058                      GrabPtr grab, WindowPtr win, InternalEvent *ev)
1060     int err;
1061     xEvent *xi2;
1062     Mask filter;
1063     Window child = DeepestSpriteWin(&ti->sprite)->drawable.id;
1065     /* FIXME: owner event handling */
1067     /* If the client does not have the ownership mask set and is not
1068      * the current owner of the touch, only pretend we delivered */
1069     if (!grab && ti->num_grabs != 0 &&
1070            !TouchClientWantsOwnershipEvents(client, dev,win))
1071            return TRUE;
1073     /* If we fail here, we're going to leave a client hanging. */
1074     err = EventToXI2(ev, &xi2);
1075     if (err != Success)
1076         FatalError("[Xi] %s: XI2 conversion failed in %s"
1077                    " (%d)\n", dev->name, __func__, err);
1079     FixUpEventFromWindow(&ti->sprite, xi2, win, child, FALSE);
1080     filter = GetEventFilter(dev, xi2);
1081     if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success)
1082         return FALSE;
1083     err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab);
1084     free(xi2);
1086     /* Returning the value from TryClientEvents isn't useful, since all our
1087      * resource-gone cleanups will update the delivery list anyway. */
1088     return TRUE;
1091 /**
1092  * If the current owner has rejected the event, deliver the
1093  * TouchOwnership/TouchBegin to the next item in the sprite stack.
1094  */
1095 static void
1096 TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
1097                      TouchOwnershipEvent *ev)
1099     InternalEvent *tel = InitEventList(GetMaximumEventsNum());
1100     ValuatorMask *mask = valuator_mask_new(2);
1101     int i, nev;
1103     /* Deliver the ownership */
1104     if (ti->listeners[0].state == LISTENER_AWAITING_OWNER)
1105         DeliverTouchEvents(dev, ti, (InternalEvent*)ev, ti->listeners[0].listener);
1106     else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN)
1107         TouchEventHistoryReplay(ti, dev, ti->listeners[0].listener);
1109     /* If we've just removed the last grab and the touch has physically
1110      * ended, send a TouchEnd event too and finalise the touch. */
1111     if (ti->num_listeners == 1 && ti->num_grabs == 0 &&
1112             ti->pending_finish)
1113     {
1114         int flags;
1115         valuator_mask_set_double(mask, 0,
1116                                  valuator_mask_get_double(ti->valuators, 0));
1117         valuator_mask_set_double(mask, 1,
1118                                  valuator_mask_get_double(ti->valuators, 1));
1120         flags = TOUCH_CLIENT_ID;
1121         if (ti->emulate_pointer)
1122             flags |= TOUCH_POINTER_EMULATED;
1123         nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd, flags, mask);
1124         for (i = 0; i < nev; i++)
1125             DeliverTouchEvents(dev, ti, tel + i, 0);
1126         TouchEndTouch(dev, ti);
1127     }
1129     valuator_mask_free(&mask);
1130     FreeEventList(tel, GetMaximumEventsNum());
1133 static void
1134 TouchEventRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
1135                    TouchOwnershipEvent *ev)
1137     InternalEvent *tel = InitEventList(GetMaximumEventsNum());
1138     ValuatorMask *mask = valuator_mask_new(2);
1139     Bool was_owner = (ev->resource == ti->listeners[0].listener);
1140     void *grab;
1141     int nev, i;
1144     /* Send a TouchEnd event to the resource being removed, but only if they
1145      * haven't received one yet already */
1146     if (ti->listeners[0].state != LISTENER_HAS_END)
1147     {
1148         int flags;
1149         valuator_mask_set_double(mask, 0,
1150                                  valuator_mask_get_double(ti->valuators, 0));
1151         valuator_mask_set_double(mask, 1,
1152                                  valuator_mask_get_double(ti->valuators, 1));
1154         flags = TOUCH_CLIENT_ID|TOUCH_REJECT;
1155         if (ti->emulate_pointer)
1156             flags |= TOUCH_POINTER_EMULATED;
1157         nev = GetTouchEvents(tel, sourcedev, ti->client_id, XI_TouchEnd, flags, mask);
1158         for (i = 0; i < nev; i++)
1159             DeliverTouchEvents(sourcedev, ti, tel + i, ev->resource);
1160     }
1162     /* If there are no other listeners left, and the touchpoint is pending
1163      * finish, then we can just kill it now. */
1164     if (ti->num_listeners == 1 && ti->pending_finish)
1165     {
1166         TouchEndTouch(sourcedev, ti);
1167         goto out;
1168     }
1170     /* Remove the resource from the listener list, updating
1171      * ti->num_listeners, as well as ti->num_grabs if it was a grab. */
1172     if (TouchRemoveListener(ti, ev->resource))
1173     {
1174         if (dixLookupResourceByType(&grab, ev->resource, RT_PASSIVEGRAB,
1175                                     serverClient, DixGetAttrAccess) == Success)
1176             ti->num_grabs--;
1177     }
1179     /* If the current owner was removed and there are further listeners, deliver
1180      * the TouchOwnership or TouchBegin event to the new owner. */
1181     if (ti->num_listeners > 0 && was_owner)
1182         TouchPuntToNextOwner(sourcedev, ti, ev);
1184 out:
1185     FreeEventList(tel, GetMaximumEventsNum());
1186     valuator_mask_free(&mask);
1189 /**
1190  * Processes a TouchOwnership event, indicating a grab has accepted the touch
1191  * it currently owns, or a grab or selection has been removed.  Will generate
1192  * and send TouchEnd events to all clients removed from the delivery list, as
1193  * well as possibly sending the new TouchOwnership event.  May end the
1194  * touchpoint if it is pending finish.
1195  */
1196 static void
1197 ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1198                            TouchOwnershipEvent *ev)
1201     if (ev->reason == XIRejectTouch)
1202         TouchEventRejected(dev, ti, ev);
1203     else if (ev->reason == XIAcceptTouch) {
1204         int flags;
1205         int nev, i;
1206         ValuatorMask *mask;
1208         InternalEvent *tel = InitEventList(GetMaximumEventsNum());
1210         mask = valuator_mask_new(dev->valuator->numAxes);
1211         valuator_mask_set_double(mask, 0,
1212                                  valuator_mask_get_double(ti->valuators, 0));
1213         valuator_mask_set_double(mask, 1,
1214                                  valuator_mask_get_double(ti->valuators, 1));
1216         /* FIXME: what about early acceptance? a client may accept before it
1217          * owns the touch. */
1219         /* The touch owner has accepted the touch.  Send TouchEnd events to
1220          * everyone else, and truncate the list of listeners. */
1221         flags = TOUCH_ACCEPT|TOUCH_CLIENT_ID;
1222         if (ti->emulate_pointer)
1223             flags |= TOUCH_POINTER_EMULATED;
1224         nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd,
1225                              flags, mask);
1226         for (i = 0; i < nev; i++)
1227             DeliverTouchEvents(dev, ti, tel + i, 0);
1229         FreeEventList(tel, GetMaximumEventsNum());
1230         valuator_mask_free(&mask);
1232         while (ti->num_listeners > 1)
1233             TouchRemoveListener(ti, ti->listeners[1].listener);
1234         /* Owner accepted after receiving end */
1235         if (ti->listeners[0].state == LISTENER_HAS_END)
1236             TouchEndTouch(dev, ti);
1237     } else { /* this is the very first ownership event for a grab */
1238         DeliverTouchEvents(dev, ti, (InternalEvent*)ev, ev->resource);
1239     }
1242 /**
1243  * Copy the event's valuator information into the touchpoint, we may need
1244  * this for emulated TouchEnd events.
1245  */
1246 static void
1247 TouchCopyValuatorData(DeviceEvent *ev, TouchPointInfoPtr ti)
1249     int i;
1250     for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++)
1251         if (BitIsOn(ev->valuators.mask, i))
1252             valuator_mask_set_double(ti->valuators, i, ev->valuators.data[i]);
1255 /**
1256  * Given a touch event and a potential listener, retrieve info needed for
1257  * processing the event.
1258  *
1259  * @param dev The device generating the touch event.
1260  * @param ti The touch point info record for the touch event.
1261  * @param ev The touch event to process.
1262  * @param listener The touch event listener that may receive the touch event.
1263  * @param[out] client The client that should receive the touch event.
1264  * @param[out] win The window to deliver the event on.
1265  * @param[out] grab The grab to deliver the event through, if any.
1266  * @param[out] mask The XI 2.x event mask of the grab or selection, if any.
1267  * @return TRUE if an event should be delivered to the listener, FALSE
1268  *         otherwise.
1269  */
1270 static Bool
1271 RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
1272                           InternalEvent *ev, TouchListener *listener,
1273                           ClientPtr *client, WindowPtr *win, GrabPtr *grab,
1274                           XI2Mask **mask)
1276      int rc;
1277      InputClients *iclients = NULL;
1279     if (listener->type == LISTENER_GRAB ||
1280         listener->type == LISTENER_POINTER_GRAB)
1281     {
1282         rc = dixLookupResourceByType((pointer*)grab, listener->listener,
1283                 RT_PASSIVEGRAB,
1284                 serverClient, DixSendAccess);
1285         if (rc != Success)
1286         {
1287             /* the grab doesn't exist but we have a grabbing listener - this
1288              * is an implicit/active grab */
1289             rc = dixLookupClient(client, listener->listener, serverClient, DixSendAccess);
1290             if (rc != Success)
1291                 return FALSE;
1293             *grab = dev->deviceGrab.grab;
1294             if (!*grab)
1295                 return FALSE;
1296         }
1298         *client = rClient(*grab);
1299         *win = (*grab)->window;
1300         *mask = (*grab)->xi2mask;
1301     } else {
1302         if (listener->level == CORE)
1303             rc = dixLookupWindow(win, listener->listener,
1304                                  serverClient, DixSendAccess);
1305         else
1306             rc = dixLookupResourceByType((pointer*)win, listener->listener,
1307                                          RT_INPUTCLIENT,
1308                                          serverClient, DixSendAccess);
1309         if (rc != Success)
1310             return FALSE;
1313         if (listener->level == XI2)
1314         {
1315             int evtype;
1316             if (ti->emulate_pointer && listener->type == LISTENER_POINTER_REGULAR)
1317                 evtype = GetXI2Type(TouchGetPointerEventType(ev));
1318             else
1319                 evtype = GetXI2Type(ev->any.type);
1321             nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next)
1322                 if (xi2mask_isset(iclients->xi2mask, dev, evtype))
1323                     break;
1324             BUG_WARN(!iclients);
1325             if (!iclients)
1326                 return FALSE;
1327         } else if (listener->level == XI)
1328         {
1329             int xi_type = GetXIType(TouchGetPointerEventType(ev));
1330             Mask xi_filter = event_get_filter_from_type(dev, xi_type);
1331             nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next)
1332                 if (iclients->mask[dev->id] & xi_filter)
1333                     break;
1334             BUG_WARN(!iclients);
1335             if (!iclients)
1336                 return FALSE;
1337         } else
1338         {
1339             int coretype = GetCoreType(TouchGetPointerEventType(ev));
1340             Mask core_filter = event_get_filter_from_type(dev, coretype);
1342             /* all others */
1343             nt_list_for_each_entry(iclients, (InputClients*)wOtherClients(*win), next)
1344                 if (iclients->mask[XIAllDevices] & core_filter)
1345                     break;
1346             /* if owner selected, iclients is NULL */
1347         }
1349         *client = iclients ? rClient(iclients) : wClient(*win);
1350         *mask = iclients ? iclients->xi2mask : NULL;
1351         *grab = NULL;
1352     }
1354     return TRUE;
1357 static int
1358 DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1359                           TouchListener *listener, ClientPtr client,
1360                           WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1362     InternalEvent motion, button;
1363     InternalEvent *ptrev = &motion;
1364     int nevents;
1365     DeviceIntPtr kbd;
1367     /* We don't deliver pointer events to non-owners */
1368     if (!TouchResourceIsOwner(ti, listener->listener))
1369         return Success;
1371     nevents = TouchConvertToPointerEvent(ev, &motion, &button);
1372     BUG_WARN(nevents == 0);
1373     if (nevents == 0)
1374         return BadValue;
1376     if (nevents > 1)
1377         ptrev = &button;
1379     kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
1380     event_set_state(dev, kbd, &ptrev->device_event);
1381     ptrev->device_event.corestate = event_get_corestate(dev, kbd);
1383     if (grab)
1384     {
1385         /* this side-steps the usual activation mechansims, but... */
1386         if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab)
1387                 ActivatePassiveGrab(dev, grab, ptrev, ev); /* also delivers the event */
1388         else {
1389             int deliveries = 0;
1390             /* 'grab' is the passive grab, but if the grab isn't active,
1391              * don't deliver */
1392             if (!dev->deviceGrab.grab)
1393                 return Success;
1395             if (grab->ownerEvents)
1396             {
1397                 WindowPtr focus = NullWindow;
1398                 WindowPtr win = dev->spriteInfo->sprite->win;
1399                 deliveries = DeliverDeviceEvents(win, ptrev, grab, focus, dev);
1400             }
1402             if (!deliveries)
1403                 DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
1405             if (ev->any.type == ET_TouchEnd &&
1406                 !dev->button->buttonsDown &&
1407                 dev->deviceGrab.fromPassiveGrab &&
1408                 GrabIsPointerGrab(grab))
1409                 (*dev->deviceGrab.DeactivateGrab)(dev);
1410         }
1411     } else
1412     {
1413         GrabPtr devgrab = dev->deviceGrab.grab;
1415         DeliverDeviceEvents(win, ptrev, grab, win, dev);
1416         /* FIXME: bad hack
1417          * Implicit passive grab activated in response to this event. Store
1418          * the event.
1419          */
1420         if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab)
1421         {
1422             TouchListener *listener;
1424             devgrab = dev->deviceGrab.grab;
1426             *dev->deviceGrab.sync.event = ev->device_event;
1428             /* The listener array has a sequence of grabs and then one event
1429              * selection. Implicit grab activation occurs through delivering an
1430              * event selection. Thus, we update the last listener in the array.
1431              */
1432             listener = &ti->listeners[ti->num_listeners - 1];
1433             listener->listener = devgrab->resource;
1435             if (devgrab->grabtype != XI2 ||
1436                 devgrab->type != XI_TouchBegin)
1437                 listener->type = LISTENER_POINTER_GRAB;
1438             else
1439                 listener->type = LISTENER_GRAB;
1440         }
1442     }
1443     if (ev->any.type == ET_TouchBegin)
1444         listener->state = LISTENER_IS_OWNER;
1445     else if (ev->any.type == ET_TouchEnd)
1446         listener->state = LISTENER_HAS_END;
1448     return Success;
1454 static void
1455 DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1456                            InternalEvent *ev)
1458     InternalEvent motion;
1460     if (ti->num_listeners)
1461     {
1462         ClientPtr client;
1463         WindowPtr win;
1464         GrabPtr grab;
1465         XI2Mask *mask;
1467         if (ti->listeners[0].type != LISTENER_POINTER_REGULAR ||
1468             ti->listeners[0].type != LISTENER_POINTER_GRAB)
1469             return;
1471         motion = *ev;
1472         motion.any.type = ET_TouchUpdate;
1473         motion.device_event.detail.button = 0;
1475         if (!RetrieveTouchDeliveryData(dev, ti, &motion,
1476                                        &ti->listeners[0], &client, &win, &grab,
1477                                        &mask))
1478             return;
1480         /* There may be a pointer grab on the device */
1481         if (!grab)
1482         {
1483             grab = dev->deviceGrab.grab;
1484             if (grab)
1485             {
1486                 win = grab->window;
1487                 mask = grab->xi2mask;
1488                 client = rClient(grab);
1489             }
1490         }
1492         DeliverTouchEmulatedEvent(dev, ti, &motion, &ti->listeners[0], client, win, grab, mask);
1493     } else {
1494         InternalEvent button;
1495         int converted;
1496         converted = TouchConvertToPointerEvent(ev, &motion, &button);
1498         BUG_WARN(converted == 0);
1499         if (converted)
1500             ProcessOtherEvent(&motion, dev);
1501     }
1504 /**
1505  * Processes and delivers a TouchBegin, TouchUpdate, or a
1506  * TouchEnd event.
1507  *
1508  * Due to having rather different delivery semantics (see the Xi 2.2 protocol
1509  * spec for more information), this implements its own grab and event-selection
1510  * delivery logic.
1511  */
1512 static void
1513 ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
1515     TouchClassPtr t = dev->touch;
1516     TouchPointInfoPtr ti;
1517     uint32_t touchid;
1518     int type = ev->any.type;
1519     int emulate_pointer = !!(ev->device_event.flags & TOUCH_POINTER_EMULATED);
1521     if (!t)
1522         return;
1524     if (ev->any.type == ET_TouchOwnership)
1525         touchid = ev->touch_ownership_event.touchid;
1526     else
1527         touchid = ev->device_event.touchid;
1529     if (type == ET_TouchBegin) {
1530         ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
1531                              emulate_pointer);
1532     } else
1533         ti = TouchFindByClientID(dev, touchid);
1535     if (!ti)
1536     {
1537         DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
1538                dev->name, type, touchid);
1539         return;
1540     }
1543     /* if emulate_pointer is set, emulate the motion event right
1544      * here, so we can ignore it for button event emulation. TouchUpdate
1545      * events which _only_ emulate motion just work normally */
1546     if (emulate_pointer && ev->any.type != ET_TouchUpdate)
1547         DeliverEmulatedMotionEvent(dev, ti, ev);
1548     if (emulate_pointer && IsMaster(dev))
1549         CheckMotion(&ev->device_event, dev);
1551     /* Make sure we have a valid window trace for event delivery; must be
1552      * called after event type mutation. */
1553     /* FIXME: check this */
1554     if (!TouchEnsureSprite(dev, ti, ev))
1555         return;
1557     /* TouchOwnership events are handled separately from the rest, as they
1558      * have more complex semantics. */
1559     if (ev->any.type == ET_TouchOwnership)
1560         ProcessTouchOwnershipEvent(dev, ti, &ev->touch_ownership_event);
1561     else
1562     {
1563         TouchCopyValuatorData(&ev->device_event, ti);
1564         /* WARNING: the event type may change to TouchUpdate in
1565          * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
1566          * owner */
1567         DeliverTouchEvents(dev, ti, (InternalEvent *) ev, 0);
1568         if (ev->any.type == ET_TouchEnd)
1569             TouchEndTouch(dev, ti);
1570     }
1574 /**
1575  * Process DeviceEvents and DeviceChangedEvents.
1576  */
1577 static void
1578 ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
1580     GrabPtr grab;
1581     Bool deactivateDeviceGrab = FALSE;
1582     int key = 0, rootX, rootY;
1583     ButtonClassPtr b;
1584     int ret = 0;
1585     int corestate;
1586     DeviceIntPtr mouse = NULL, kbd = NULL;
1587     DeviceEvent *event = &ev->device_event;
1589     if (IsPointerDevice(device))
1590     {
1591         kbd = GetMaster(device, KEYBOARD_OR_FLOAT);
1592         mouse = device;
1593         if (!kbd->key) /* can happen with floating SDs */
1594             kbd = NULL;
1595     } else
1596     {
1597         mouse = GetMaster(device, POINTER_OR_FLOAT);
1598         kbd = device;
1599         if (!mouse->valuator || !mouse->button) /* may be float. SDs */
1600             mouse = NULL;
1601     }
1603     corestate = event_get_corestate(mouse, kbd);
1604     event_set_state(mouse, kbd, event);
1606     ret = UpdateDeviceState(device, event);
1607     if (ret == DONT_PROCESS)
1608         return;
1610     b = device->button;
1612     if (IsMaster(device) || IsFloating(device))
1613         CheckMotion(event, device);
1615     switch (event->type)
1616     {
1617         case ET_Motion:
1618         case ET_ButtonPress:
1619         case ET_ButtonRelease:
1620         case ET_KeyPress:
1621         case ET_KeyRelease:
1622         case ET_ProximityIn:
1623         case ET_ProximityOut:
1624             GetSpritePosition(device, &rootX, &rootY);
1625             event->root_x = rootX;
1626             event->root_y = rootY;
1627             NoticeEventTime((InternalEvent*)event);
1628             event->corestate = corestate;
1629             key = event->detail.key;
1630             break;
1631         default:
1632             break;
1633     }
1635     if (DeviceEventCallback && !syncEvents.playingEvents) {
1636         DeviceEventInfoRec eventinfo;
1637         SpritePtr pSprite = device->spriteInfo->sprite;
1639         /* see comment in EnqueueEvents regarding the next three lines */
1640         if (ev->any.type == ET_Motion)
1641             ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1643         eventinfo.device = device;
1644         eventinfo.event = ev;
1645         CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
1646     }
1648     grab = device->deviceGrab.grab;
1650     switch(event->type)
1651     {
1652         case ET_KeyPress:
1653             if (!grab && CheckDeviceGrabs(device, event, 0))
1654                 return;
1655             break;
1656         case ET_KeyRelease:
1657             if (grab && device->deviceGrab.fromPassiveGrab &&
1658                 (key == device->deviceGrab.activatingKey) &&
1659                 GrabIsKeyboardGrab(device->deviceGrab.grab))
1660                 deactivateDeviceGrab = TRUE;
1661             break;
1662         case ET_ButtonPress:
1663             if (b->map[key] == 0) /* there's no button 0 */
1664                 return;
1665             event->detail.button = b->map[key];
1666             if (!grab && CheckDeviceGrabs(device, event, 0))
1667             {
1668                 /* if a passive grab was activated, the event has been sent
1669                  * already */
1670                 return;
1671             }
1672             break;
1673         case ET_ButtonRelease:
1674             if (b->map[key] == 0) /* there's no button 0 */
1675                 return;
1676             event->detail.button = b->map[key];
1677             if (grab && !b->buttonsDown &&
1678                 device->deviceGrab.fromPassiveGrab &&
1679                 GrabIsPointerGrab(device->deviceGrab.grab))
1680                 deactivateDeviceGrab = TRUE;
1681         default:
1682             break;
1683     }
1686     if (grab)
1687         DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
1688     else if (device->focus && !IsPointerEvent(ev))
1689         DeliverFocusedEvent(device, (InternalEvent*)event,
1690                             GetSpriteWindow(device));
1691     else
1692         DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
1693                             NullGrab, NullWindow, device);
1695     if (deactivateDeviceGrab == TRUE)
1696         (*device->deviceGrab.DeactivateGrab) (device);
1697     event->detail.key = key;
1700 /**
1701  * Main device event processing function.
1702  * Called from when processing the events from the event queue.
1703  *
1704  */
1705 void
1706 ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
1708     verify_internal_event(ev);
1710     switch(ev->any.type)
1711     {
1712         case  ET_RawKeyPress:
1713         case  ET_RawKeyRelease:
1714         case  ET_RawButtonPress:
1715         case  ET_RawButtonRelease:
1716         case  ET_RawMotion:
1717         case  ET_RawTouchBegin:
1718         case  ET_RawTouchUpdate:
1719         case  ET_RawTouchEnd:
1720             DeliverRawEvent(&ev->raw_event, device);
1721             break;
1722         case  ET_TouchBegin:
1723         case  ET_TouchUpdate:
1724         case  ET_TouchOwnership:
1725         case  ET_TouchEnd:
1726             ProcessTouchEvent(ev, device);
1727             break;
1728         default:
1729             ProcessDeviceEvent(ev, device);
1730             break;
1731     }
1734 static int
1735 DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1736                        TouchListener *listener, ClientPtr client,
1737                        WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1739     enum TouchListenerState state;
1740     int rc = Success;
1741     Bool has_ownershipmask;
1743     if (listener->type == LISTENER_POINTER_REGULAR ||
1744         listener->type == LISTENER_POINTER_GRAB)
1745     {
1746         rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1747                                        grab, xi2mask);
1748         goto out;
1749     }
1752     has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
1754     if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
1755         rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1756     if (!TouchResourceIsOwner(ti, listener->listener))
1757     {
1758         if (has_ownershipmask)
1759             state = LISTENER_AWAITING_OWNER;
1760         else
1761             state = LISTENER_AWAITING_BEGIN;
1762     } else
1763     {
1764         if (has_ownershipmask)
1765             TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
1766         state = LISTENER_IS_OWNER;
1767     }
1768     listener->state = state;
1770 out:
1771     return rc;
1774 static int
1775 DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1776                      TouchListener *listener, ClientPtr client,
1777                      WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1779     int rc = Success;
1781     if (listener->type == LISTENER_POINTER_REGULAR ||
1782         listener->type == LISTENER_POINTER_GRAB)
1783     {
1784         rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1785                                        grab, xi2mask);
1786         goto out;
1787     }
1789     /* Event in response to reject */
1790     if (ev->device_event.flags & TOUCH_REJECT)
1791     {
1792         if (listener->state != LISTENER_HAS_END)
1793             rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1794         listener->state = LISTENER_HAS_END;
1795     } else if (TouchResourceIsOwner(ti, listener->listener))
1796     {
1797         /* FIXME: what about early acceptance */
1798         if (!(ev->device_event.flags & TOUCH_ACCEPT))
1799         {
1800             if (listener->state != LISTENER_HAS_END)
1801                 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1802             listener->state = LISTENER_HAS_END;
1803         }
1804         if ((ti->num_listeners > 1 ||
1805              (listener->type == LISTENER_GRAB &&
1806               xi2mask_isset(xi2mask, dev, XI_TouchOwnership))) &&
1807             (ev->device_event.flags & (TOUCH_ACCEPT|TOUCH_REJECT)) == 0)
1808         {
1809             ev->any.type = ET_TouchUpdate;
1810             ev->device_event.flags |= TOUCH_PENDING_END;
1811             ti->pending_finish = TRUE;
1812         }
1813     }
1815 out:
1816     return rc;
1819 static int
1820 DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1821                   TouchListener *listener, ClientPtr client,
1822                   WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1824     Bool has_ownershipmask = FALSE;
1825     int rc = Success;
1827     if (xi2mask)
1828         has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
1830     if (ev->any.type == ET_TouchOwnership)
1831     {
1832         ev->touch_ownership_event.deviceid = dev->id;
1833         if (!TouchResourceIsOwner(ti, listener->listener))
1834             goto out;
1835         rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1836         listener->state = LISTENER_IS_OWNER;
1837     } else
1838         ev->device_event.deviceid = dev->id;
1840     if (ev->any.type == ET_TouchBegin)
1841     {
1842         rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
1843     } else if (ev->any.type == ET_TouchUpdate)
1844     {
1845         if (listener->type == LISTENER_POINTER_REGULAR ||
1846             listener->type == LISTENER_POINTER_GRAB)
1847             DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
1848         else if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
1849             rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1850     } else if (ev->any.type == ET_TouchEnd)
1851         rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
1853 out:
1854     return rc;
1857 /**
1858  * Delivers a touch events to all interested clients.  For TouchBegin events,
1859  * will update ti->listeners, ti->num_listeners, and ti->num_grabs.
1860  * May also mutate ev (type and flags) upon successful delivery.  If
1861  * @resource is non-zero, will only attempt delivery to the owner of that
1862  * resource.
1863  *
1864  * @return TRUE if the event was delivered at least once, FALSE otherwise
1865  */
1866 void
1867 DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
1868                    InternalEvent *ev, XID resource)
1870     int i;
1872     if (ev->any.type == ET_TouchBegin &&
1873         !(ev->device_event.flags & (TOUCH_CLIENT_ID|TOUCH_REPLAYING)))
1874         TouchSetupListeners(dev, ti, ev);
1876     TouchEventHistoryPush(ti, &ev->device_event);
1878     for (i = 0; i < ti->num_listeners; i++)
1879     {
1880         GrabPtr grab = NULL;
1881         ClientPtr client;
1882         WindowPtr win;
1883         XI2Mask *mask;
1884         TouchListener *listener = &ti->listeners[i];
1886         if (resource && listener->listener != resource)
1887             continue;
1889         if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win,
1890                                        &grab, &mask))
1891             continue;
1893         DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
1894     }
1896     if (ti->emulate_pointer)
1897         UpdateDeviceState(dev, &ev->device_event);
1900 int
1901 InitProximityClassDeviceStruct(DeviceIntPtr dev)
1903     ProximityClassPtr proxc;
1905     proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
1906     if (!proxc)
1907         return FALSE;
1908     proxc->sourceid = dev->id;
1909     proxc->in_proximity = TRUE;
1910     dev->proximity = proxc;
1911     return TRUE;
1914 /**
1915  * Initialise the device's valuators. The memory must already be allocated,
1916  * this function merely inits the matching axis (specified through axnum) to
1917  * sane values.
1918  *
1919  * It is a condition that (minval < maxval).
1920  *
1921  * @see InitValuatorClassDeviceStruct
1922  */
1923 Bool
1924 InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
1925                        int resolution, int min_res, int max_res, int mode)
1927     AxisInfoPtr ax;
1929     if (!dev || !dev->valuator || (minval > maxval && mode == Absolute))
1930         return FALSE;
1931     if (axnum >= dev->valuator->numAxes)
1932         return FALSE;
1934     ax = dev->valuator->axes + axnum;
1936     ax->min_value = minval;
1937     ax->max_value = maxval;
1938     ax->resolution = resolution;
1939     ax->min_resolution = min_res;
1940     ax->max_resolution = max_res;
1941     ax->label = label;
1942     ax->mode = mode;
1944     if (mode & OutOfProximity)
1945         dev->proximity->in_proximity = FALSE;
1947     return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE);
1950 /**
1951  * Set the given axis number as a scrolling valuator.
1952  */
1953 Bool
1954 SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type, double increment, int flags)
1956     AxisInfoPtr ax;
1957     int *current_ax;
1958     InternalEvent dce;
1959     DeviceIntPtr master;
1961     if (!dev || !dev->valuator || axnum >= dev->valuator->numAxes)
1962         return FALSE;
1964     switch (type)
1965     {
1966         case SCROLL_TYPE_VERTICAL:
1967             current_ax = &dev->valuator->v_scroll_axis;
1968             break;
1969         case SCROLL_TYPE_HORIZONTAL:
1970             current_ax = &dev->valuator->h_scroll_axis;
1971             break;
1972         case SCROLL_TYPE_NONE:
1973             ax = &dev->valuator->axes[axnum];
1974             ax->scroll.type = type;
1975             return TRUE;
1976         default:
1977             return FALSE;
1978     }
1980     if (increment == 0.0)
1981         return FALSE;
1983     if (*current_ax != -1 && axnum != *current_ax)
1984     {
1985         ax = &dev->valuator->axes[*current_ax];
1986         if (ax->scroll.type == type &&
1987             (flags & SCROLL_FLAG_PREFERRED) && (ax->scroll.flags & SCROLL_FLAG_PREFERRED))
1988             return FALSE;
1989     }
1990     *current_ax = axnum;
1992     ax = &dev->valuator->axes[axnum];
1993     ax->scroll.type = type;
1994     ax->scroll.increment = increment;
1995     ax->scroll.flags = flags;
1997     master = GetMaster(dev, MASTER_ATTACHED);
1998     CreateClassesChangedEvent(&dce, master, dev, DEVCHANGE_POINTER_EVENT | DEVCHANGE_DEVICE_CHANGE);
1999     XISendDeviceChangedEvent(dev, &dce.changed_event);
2001     /* if the current slave is us, update the master. If not, we'll update
2002      * whenever the next slave switch happens anyway. CMDC sends the event
2003      * for us */
2004     if (master && master->lastSlave == dev)
2005         ChangeMasterDeviceClasses(master, &dce.changed_event);
2007     return TRUE;
2010 static void
2011 FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
2012                      ButtonClassPtr b, ValuatorClassPtr v, int first)
2014     ev->type = DeviceStateNotify;
2015     ev->deviceid = dev->id;
2016     ev->time = currentTime.milliseconds;
2017     ev->classes_reported = 0;
2018     ev->num_keys = 0;
2019     ev->num_buttons = 0;
2020     ev->num_valuators = 0;
2022     if (b) {
2023         ev->classes_reported |= (1 << ButtonClass);
2024         ev->num_buttons = b->numButtons;
2025         memcpy((char*)ev->buttons, (char*)b->down, 4);
2026     } else if (k) {
2027         ev->classes_reported |= (1 << KeyClass);
2028         ev->num_keys = k->xkbInfo->desc->max_key_code -
2029                        k->xkbInfo->desc->min_key_code;
2030         memmove((char *)&ev->keys[0], (char *)k->down, 4);
2031     }
2032     if (v) {
2033         int nval = v->numAxes - first;
2035         ev->classes_reported |= (1 << ValuatorClass);
2036         ev->classes_reported |= valuator_get_mode(dev, 0) << ModeBitsShift;
2037         ev->num_valuators = nval < 3 ? nval : 3;
2038         switch (ev->num_valuators) {
2039         case 3:
2040             ev->valuator2 = v->axisVal[first + 2];
2041         case 2:
2042             ev->valuator1 = v->axisVal[first + 1];
2043         case 1:
2044             ev->valuator0 = v->axisVal[first];
2045             break;
2046         }
2047     }
2050 static void
2051 FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
2052                   int first)
2054     int nval = v->numAxes - first;
2056     ev->type = DeviceValuator;
2057     ev->deviceid = dev->id;
2058     ev->num_valuators = nval < 3 ? nval : 3;
2059     ev->first_valuator = first;
2060     switch (ev->num_valuators) {
2061     case 3:
2062         ev->valuator2 = v->axisVal[first + 2];
2063     case 2:
2064         ev->valuator1 = v->axisVal[first + 1];
2065     case 1:
2066         ev->valuator0 = v->axisVal[first];
2067         break;
2068     }
2069     first += ev->num_valuators;
2072 static void
2073 DeliverStateNotifyEvent(DeviceIntPtr dev, WindowPtr win)
2075     int evcount = 1;
2076     deviceStateNotify *ev, *sev;
2077     deviceKeyStateNotify *kev;
2078     deviceButtonStateNotify *bev;
2080     KeyClassPtr k;
2081     ButtonClassPtr b;
2082     ValuatorClassPtr v;
2083     int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
2085     if (!(wOtherInputMasks(win)) ||
2086         !(wOtherInputMasks(win)->inputEvents[dev->id] & DeviceStateNotifyMask))
2087         return;
2089     if ((b = dev->button) != NULL) {
2090         nbuttons = b->numButtons;
2091         if (nbuttons > 32)
2092             evcount++;
2093     }
2094     if ((k = dev->key) != NULL) {
2095         nkeys = k->xkbInfo->desc->max_key_code -
2096             k->xkbInfo->desc->min_key_code;
2097         if (nkeys > 32)
2098             evcount++;
2099         if (nbuttons > 0) {
2100             evcount++;
2101         }
2102     }
2103     if ((v = dev->valuator) != NULL) {
2104         nval = v->numAxes;
2106         if (nval > 3)
2107             evcount++;
2108         if (nval > 6) {
2109             if (!(k && b))
2110                 evcount++;
2111             if (nval > 9)
2112                 evcount += ((nval - 7) / 3);
2113         }
2114     }
2116     sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
2117     FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
2119     if (b != NULL) {
2120         FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
2121         first += 3;
2122         nval -= 3;
2123         if (nbuttons > 32) {
2124             (ev - 1)->deviceid |= MORE_EVENTS;
2125             bev = (deviceButtonStateNotify *) ev++;
2126             bev->type = DeviceButtonStateNotify;
2127             bev->deviceid = dev->id;
2128             memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
2129         }
2130         if (nval > 0) {
2131             (ev - 1)->deviceid |= MORE_EVENTS;
2132             FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
2133             first += 3;
2134             nval -= 3;
2135         }
2136     }
2138     if (k != NULL) {
2139         FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
2140         first += 3;
2141         nval -= 3;
2142         if (nkeys > 32) {
2143             (ev - 1)->deviceid |= MORE_EVENTS;
2144             kev = (deviceKeyStateNotify *) ev++;
2145             kev->type = DeviceKeyStateNotify;
2146             kev->deviceid = dev->id;
2147             memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
2148         }
2149         if (nval > 0) {
2150             (ev - 1)->deviceid |= MORE_EVENTS;
2151             FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
2152             first += 3;
2153             nval -= 3;
2154         }
2155     }
2157     while (nval > 0) {
2158         FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
2159         first += 3;
2160         nval -= 3;
2161         if (nval > 0) {
2162             (ev - 1)->deviceid |= MORE_EVENTS;
2163             FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
2164             first += 3;
2165             nval -= 3;
2166         }
2167     }
2169     DeliverEventsToWindow(dev, win, (xEvent *) sev, evcount,
2170                           DeviceStateNotifyMask, NullGrab);
2171     free(sev);
2174 void
2175 DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
2176                  WindowPtr pWin)
2178     deviceFocus event;
2179     xXIFocusInEvent *xi2event;
2180     DeviceIntPtr mouse;
2181     int btlen, len, i;
2183     mouse = IsFloating(dev) ? dev : GetMaster(dev, MASTER_POINTER);
2185     /* XI 2 event */
2186     btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
2187     btlen = bytes_to_int32(btlen);
2188     len = sizeof(xXIFocusInEvent) + btlen * 4;
2190     xi2event = calloc(1, len);
2191     xi2event->type         = GenericEvent;
2192     xi2event->extension    = IReqCode;
2193     xi2event->evtype       = type;
2194     xi2event->length       = bytes_to_int32(len - sizeof(xEvent));
2195     xi2event->buttons_len  = btlen;
2196     xi2event->detail       = detail;
2197     xi2event->time         = currentTime.milliseconds;
2198     xi2event->deviceid     = dev->id;
2199     xi2event->sourceid     = dev->id; /* a device doesn't change focus by itself */
2200     xi2event->mode         = mode;
2201     xi2event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
2202     xi2event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
2204     for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
2205         if (BitIsOn(mouse->button->down, i))
2206             SetBit(&xi2event[1], i);
2208     if (dev->key)
2209     {
2210         xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
2211         xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
2212         xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
2213         xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
2215         xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
2216         xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
2217         xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
2218         xi2event->group.effective_group = dev->key->xkbInfo->state.group;
2219     }
2221     FixUpEventFromWindow(dev->spriteInfo->sprite, (xEvent*)xi2event, pWin,
2222                          None, FALSE);
2224     DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
2225                           GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
2227     free(xi2event);
2229     /* XI 1.x event */
2230     event.deviceid = dev->id;
2231     event.mode = mode;
2232     event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
2233     event.detail = detail;
2234     event.window = pWin->drawable.id;
2235     event.time = currentTime.milliseconds;
2237     DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
2238                                 DeviceFocusChangeMask, NullGrab);
2240     if (event.type == DeviceFocusIn)
2241         DeliverStateNotifyEvent(dev, pWin);
2244 int
2245 CheckGrabValues(ClientPtr client, GrabParameters* param)
2247     if (param->grabtype != CORE &&
2248         param->grabtype != XI &&
2249         param->grabtype != XI2)
2250     {
2251         ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
2252         return BadImplementation;
2253     }
2255     if ((param->this_device_mode != GrabModeSync) &&
2256         (param->this_device_mode != GrabModeAsync) &&
2257         (param->this_device_mode != XIGrabModeTouch)) {
2258         client->errorValue = param->this_device_mode;
2259         return BadValue;
2260     }
2261     if ((param->other_devices_mode != GrabModeSync) &&
2262         (param->other_devices_mode != GrabModeAsync) &&
2263         (param->other_devices_mode != XIGrabModeTouch)) {
2264         client->errorValue = param->other_devices_mode;
2265         return BadValue;
2266     }
2268     if (param->grabtype != XI2 && (param->modifiers != AnyModifier) &&
2269         (param->modifiers & ~AllModifiersMask)) {
2270         client->errorValue = param->modifiers;
2271         return BadValue;
2272     }
2274     if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
2275         client->errorValue = param->ownerEvents;
2276         return BadValue;
2277     }
2278     return Success;
2281 int
2282 GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2283            int button, GrabParameters *param, enum InputLevel grabtype,
2284            GrabMask *mask)
2286     WindowPtr pWin, confineTo;
2287     CursorPtr cursor;
2288     GrabPtr grab;
2289     int rc, type = -1;
2290     Mask access_mode = DixGrabAccess;
2292     rc = CheckGrabValues(client, param);
2293     if (rc != Success)
2294         return rc;
2295     if (param->confineTo == None)
2296         confineTo = NullWindow;
2297     else {
2298         rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
2299         if (rc != Success)
2300             return rc;
2301     }
2302     if (param->cursor == None)
2303         cursor = NullCursor;
2304     else {
2305         rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
2306                                      RT_CURSOR, client, DixUseAccess);
2307         if (rc != Success)
2308         {
2309             client->errorValue = param->cursor;
2310             return rc;
2311         }
2312         access_mode |= DixForceAccess;
2313     }
2314     if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
2315         access_mode |= DixFreezeAccess;
2316     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2317     if (rc != Success)
2318         return rc;
2319     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2320     if (rc != Success)
2321         return rc;
2323     if (grabtype == XI)
2324         type = DeviceButtonPress;
2325     else if (grabtype == XI2)
2326         type = XI_ButtonPress;
2328     grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2329                       mask, param, type, button, confineTo, cursor);
2330     if (!grab)
2331         return BadAlloc;
2332     return AddPassiveGrabToList(client, grab);
2335 /**
2336  * Grab the given key. If grabtype is XI, the key is a keycode. If
2337  * grabtype is XI2, the key is a keysym.
2338  */
2339 int
2340 GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2341         int key, GrabParameters *param, enum InputLevel grabtype, GrabMask *mask)
2343     WindowPtr pWin;
2344     GrabPtr grab;
2345     KeyClassPtr k = dev->key;
2346     Mask access_mode = DixGrabAccess;
2347     int rc, type = -1;
2349     rc = CheckGrabValues(client, param);
2350     if (rc != Success)
2351         return rc;
2352     if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL)
2353         return BadMatch;
2354     if (grabtype == XI)
2355     {
2356         if ((key > k->xkbInfo->desc->max_key_code ||
2357                     key < k->xkbInfo->desc->min_key_code)
2358                 && (key != AnyKey)) {
2359             client->errorValue = key;
2360             return BadValue;
2361         }
2362         type = DeviceKeyPress;
2363     } else if (grabtype == XI2)
2364         type = XI_KeyPress;
2366     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2367     if (rc != Success)
2368         return rc;
2369     if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
2370         access_mode |= DixFreezeAccess;
2371     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2372     if (rc != Success)
2373         return rc;
2375     grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2376                       mask, param, type, key, NULL, NULL);
2377     if (!grab)
2378         return BadAlloc;
2379     return AddPassiveGrabToList(client, grab);
2382 /* Enter/FocusIn grab */
2383 int
2384 GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
2385            GrabParameters *param, GrabMask *mask)
2387     WindowPtr pWin;
2388     CursorPtr cursor;
2389     GrabPtr grab;
2390     Mask access_mode = DixGrabAccess;
2391     int rc;
2393     rc = CheckGrabValues(client, param);
2394     if (rc != Success)
2395         return rc;
2397     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2398     if (rc != Success)
2399         return rc;
2400     if (param->cursor == None)
2401         cursor = NullCursor;
2402     else {
2403         rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
2404                                      RT_CURSOR, client, DixUseAccess);
2405         if (rc != Success)
2406         {
2407             client->errorValue = param->cursor;
2408             return rc;
2409         }
2410         access_mode |= DixForceAccess;
2411     }
2412     if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
2413         access_mode |= DixFreezeAccess;
2414     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2415     if (rc != Success)
2416         return rc;
2418     grab = CreateGrab(client->index, dev, dev, pWin, XI2,
2419                       mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
2420                       0, NULL, cursor);
2422     if (!grab)
2423         return BadAlloc;
2425     return AddPassiveGrabToList(client, grab);
2428 /* Touch grab */
2429 int
2430 GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
2431           GrabParameters *param, GrabMask *mask)
2433     WindowPtr pWin;
2434     GrabPtr grab;
2435     int rc;
2437     rc = CheckGrabValues(client, param);
2438     if (rc != Success)
2439         return rc;
2441     rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2442     if (rc != Success)
2443        return rc;
2444     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGrabAccess);
2445     if (rc != Success)
2446        return rc;
2448     grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2,
2449                       mask, param, XI_TouchBegin, 0, NullWindow, NullCursor);
2450     if (!grab)
2451         return BadAlloc;
2453     return AddPassiveGrabToList(client, grab);
2456 int
2457 SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
2458                 Mask mask, Mask exclusivemasks)
2460     int mskidx = dev->id;
2461     int i, ret;
2462     Mask check;
2463     InputClientsPtr others;
2465     check = (mask & exclusivemasks);
2466     if (wOtherInputMasks(pWin)) {
2467         if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {      /* It is illegal for two different
2468                                                                          * clients to select on any of the
2469                                                                          * events for maskcheck. However,
2470                                                                          * it is OK, for some client to
2471                                                                          * continue selecting on one of those
2472                                                                          * events.  */
2473             for (others = wOtherInputMasks(pWin)->inputClients; others;
2474                  others = others->next) {
2475                 if (!SameClient(others, client) && (check &
2476                                                     others->mask[mskidx]))
2477                     return BadAccess;
2478             }
2479         }
2480         for (others = wOtherInputMasks(pWin)->inputClients; others;
2481              others = others->next) {
2482             if (SameClient(others, client)) {
2483                 check = others->mask[mskidx];
2484                 others->mask[mskidx] = mask;
2485                 if (mask == 0) {
2486                     for (i = 0; i < EMASKSIZE; i++)
2487                         if (i != mskidx && others->mask[i] != 0)
2488                             break;
2489                     if (i == EMASKSIZE) {
2490                         RecalculateDeviceDeliverableEvents(pWin);
2491                         if (ShouldFreeInputMasks(pWin, FALSE))
2492                             FreeResource(others->resource, RT_NONE);
2493                         return Success;
2494                     }
2495                 }
2496                 goto maskSet;
2497             }
2498         }
2499     }
2500     check = 0;
2501     if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
2502         return ret;
2503   maskSet:
2504     if (dev->valuator)
2505         if ((dev->valuator->motionHintWindow == pWin) &&
2506             (mask & DevicePointerMotionHintMask) &&
2507             !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
2508             dev->valuator->motionHintWindow = NullWindow;
2509     RecalculateDeviceDeliverableEvents(pWin);
2510     return Success;
2513 static void
2514 FreeInputClient(InputClientsPtr *other)
2516     xi2mask_free(&(*other)->xi2mask);
2517     free(*other);
2518     *other = NULL;
2521 static InputClientsPtr
2522 AllocInputClient(void)
2524     return calloc(1, sizeof(InputClients));
2527 int
2528 AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
2530     InputClientsPtr others;
2532     if (!pWin->optional && !MakeWindowOptional(pWin))
2533         return BadAlloc;
2534     others = AllocInputClient();
2535     if (!others)
2536         return BadAlloc;
2537     if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
2538         goto bail;
2539     others->xi2mask = xi2mask_new();
2540     if (!others->xi2mask)
2541         goto bail;
2542     others->mask[mskidx] = mask;
2543     others->resource = FakeClientID(client->index);
2544     others->next = pWin->optional->inputMasks->inputClients;
2545     pWin->optional->inputMasks->inputClients = others;
2546     if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
2547         goto bail;
2548     return Success;
2550 bail:
2551     FreeInputClient(&others);
2552     return BadAlloc;
2555 static Bool
2556 MakeInputMasks(WindowPtr pWin)
2558     struct _OtherInputMasks *imasks;
2560     imasks = calloc(1, sizeof(struct _OtherInputMasks));
2561     if (!imasks)
2562         return FALSE;
2563     imasks->xi2mask = xi2mask_new();
2564     if (!imasks->xi2mask)
2565     {
2566         free(imasks);
2567         return FALSE;
2568     }
2569     pWin->optional->inputMasks = imasks;
2570     return TRUE;
2573 static void
2574 FreeInputMask(OtherInputMasks **imask)
2576     xi2mask_free(&(*imask)->xi2mask);
2577     free(*imask);
2578     *imask = NULL;
2581 void
2582 RecalculateDeviceDeliverableEvents(WindowPtr pWin)
2584     InputClientsPtr others;
2585     struct _OtherInputMasks *inputMasks;        /* default: NULL */
2586     WindowPtr pChild, tmp;
2587     int i;
2589     pChild = pWin;
2590     while (1) {
2591         if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
2592             xi2mask_zero(inputMasks->xi2mask, -1);
2593             for (others = inputMasks->inputClients; others;
2594                  others = others->next) {
2595                 for (i = 0; i < EMASKSIZE; i++)
2596                     inputMasks->inputEvents[i] |= others->mask[i];
2597                 xi2mask_merge(inputMasks->xi2mask, others->xi2mask);
2598             }
2599             for (i = 0; i < EMASKSIZE; i++)
2600                 inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
2601             for (tmp = pChild->parent; tmp; tmp = tmp->parent)
2602                 if (wOtherInputMasks(tmp))
2603                     for (i = 0; i < EMASKSIZE; i++)
2604                         inputMasks->deliverableEvents[i] |=
2605                             (wOtherInputMasks(tmp)->deliverableEvents[i]
2606                              & ~inputMasks->
2607                              dontPropagateMask[i] & PropagateMask[i]);
2608         }
2609         if (pChild->firstChild) {
2610             pChild = pChild->firstChild;
2611             continue;
2612         }
2613         while (!pChild->nextSib && (pChild != pWin))
2614             pChild = pChild->parent;
2615         if (pChild == pWin)
2616             break;
2617         pChild = pChild->nextSib;
2618     }
2621 int
2622 InputClientGone(WindowPtr pWin, XID id)
2624     InputClientsPtr other, prev;
2626     if (!wOtherInputMasks(pWin))
2627         return Success;
2628     prev = 0;
2629     for (other = wOtherInputMasks(pWin)->inputClients; other;
2630          other = other->next) {
2631         if (other->resource == id) {
2632             if (prev) {
2633                 prev->next = other->next;
2634                 FreeInputClient(&other);
2635             } else if (!(other->next)) {
2636                 if (ShouldFreeInputMasks(pWin, TRUE)) {
2637                     OtherInputMasks *mask = wOtherInputMasks(pWin);
2638                     mask->inputClients = other->next;
2639                     FreeInputMask(&mask);
2640                     pWin->optional->inputMasks = (OtherInputMasks *) NULL;
2641                     CheckWindowOptionalNeed(pWin);
2642                     FreeInputClient(&other);
2643                 } else {
2644                     other->resource = FakeClientID(0);
2645                     if (!AddResource(other->resource, RT_INPUTCLIENT,
2646                                      (pointer) pWin))
2647                         return BadAlloc;
2648                 }
2649             } else {
2650                 wOtherInputMasks(pWin)->inputClients = other->next;
2651                 FreeInputClient(&other);
2652             }
2653             RecalculateDeviceDeliverableEvents(pWin);
2654             return Success;
2655         }
2656         prev = other;
2657     }
2658     FatalError("client not on device event list");
2661 /**
2662  * Search for window in each touch trace for each device. Remove the window
2663  * and all its subwindows from the trace when found. The initial window
2664  * order is preserved.
2665  */
2666 void WindowGone(WindowPtr win)
2668     DeviceIntPtr dev;
2670     for (dev = inputInfo.devices; dev; dev = dev->next) {
2671         TouchClassPtr t = dev->touch;
2672         int i;
2674         if (!t)
2675             continue;
2677         for (i = 0; i < t->num_touches; i++) {
2678             SpritePtr sprite = &t->touches[i].sprite;
2679             int j;
2681             for (j = 0; j < sprite->spriteTraceGood; j++) {
2682                 if (sprite->spriteTrace[j] == win) {
2683                     sprite->spriteTraceGood = j;
2684                     break;
2685                 }
2686             }
2687         }
2688     }
2691 int
2692 SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
2693           xEvent * ev, Mask mask, int count)
2695     WindowPtr pWin;
2696     WindowPtr effectiveFocus = NullWindow;      /* only set if dest==InputFocus */
2697     WindowPtr spriteWin = GetSpriteWindow(d);
2699     if (dest == PointerWindow)
2700         pWin = spriteWin;
2701     else if (dest == InputFocus) {
2702         WindowPtr inputFocus;
2704         if (!d->focus)
2705             inputFocus = spriteWin;
2706         else
2707             inputFocus = d->focus->win;
2709         if (inputFocus == FollowKeyboardWin)
2710             inputFocus = inputInfo.keyboard->focus->win;
2712         if (inputFocus == NoneWin)
2713             return Success;
2715         /* If the input focus is PointerRootWin, send the event to where
2716          * the pointer is if possible, then perhaps propogate up to root. */
2717         if (inputFocus == PointerRootWin)
2718             inputFocus = GetCurrentRootWindow(d);
2720         if (IsParent(inputFocus, spriteWin)) {
2721             effectiveFocus = inputFocus;
2722             pWin = spriteWin;
2723         } else
2724             effectiveFocus = pWin = inputFocus;
2725     } else
2726         dixLookupWindow(&pWin, dest, client, DixSendAccess);
2727     if (!pWin)
2728         return BadWindow;
2729     if ((propagate != xFalse) && (propagate != xTrue)) {
2730         client->errorValue = propagate;
2731         return BadValue;
2732     }
2733     ev->u.u.type |= 0x80;
2734     if (propagate) {
2735         for (; pWin; pWin = pWin->parent) {
2736             if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
2737                 return Success;
2738             if (pWin == effectiveFocus)
2739                 return Success;
2740             if (wOtherInputMasks(pWin))
2741                 mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
2742             if (!mask)
2743                 break;
2744         }
2745     } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
2746         DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
2747     return Success;
2750 int
2751 SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
2753     int i;
2754     ButtonClassPtr b = dev->button;
2756     if (b == NULL)
2757         return BadMatch;
2759     if (nElts != b->numButtons) {
2760         client->errorValue = nElts;
2761         return BadValue;
2762     }
2763     if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
2764         return BadValue;
2765     for (i = 0; i < nElts; i++)
2766         if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
2767             return MappingBusy;
2768     for (i = 0; i < nElts; i++)
2769         b->map[i + 1] = map[i];
2770     return Success;
2773 int
2774 ChangeKeyMapping(ClientPtr client,
2775                  DeviceIntPtr dev,
2776                  unsigned len,
2777                  int type,
2778                  KeyCode firstKeyCode,
2779                  CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
2781     KeySymsRec keysyms;
2782     KeyClassPtr k = dev->key;
2784     if (k == NULL)
2785         return BadMatch;
2787     if (len != (keyCodes * keySymsPerKeyCode))
2788         return BadLength;
2790     if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
2791         (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
2792         client->errorValue = firstKeyCode;
2793         return BadValue;
2794     }
2795     if (keySymsPerKeyCode == 0) {
2796         client->errorValue = 0;
2797         return BadValue;
2798     }
2799     keysyms.minKeyCode = firstKeyCode;
2800     keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
2801     keysyms.mapWidth = keySymsPerKeyCode;
2802     keysyms.map = map;
2804     XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
2805                           serverClient);
2807     return Success;
2810 static void
2811 DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
2813     WindowPtr parent;
2815     /* Deactivate any grabs performed on this window, before making
2816      * any input focus changes.
2817      * Deactivating a device grab should cause focus events. */
2819     if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
2820         (*dev->deviceGrab.DeactivateGrab) (dev);
2822     /* If the focus window is a root window (ie. has no parent)
2823      * then don't delete the focus from it. */
2825     if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
2826         int focusEventMode = NotifyNormal;
2828         /* If a grab is in progress, then alter the mode of focus events. */
2830         if (dev->deviceGrab.grab)
2831             focusEventMode = NotifyWhileGrabbed;
2833         switch (dev->focus->revert) {
2834         case RevertToNone:
2835             if (!ActivateFocusInGrab(dev, pWin, NoneWin))
2836                 DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
2837             dev->focus->win = NoneWin;
2838             dev->focus->traceGood = 0;
2839             break;
2840         case RevertToParent:
2841             parent = pWin;
2842             do {
2843                 parent = parent->parent;
2844                 dev->focus->traceGood--;
2845             }
2846             while (!parent->realized);
2847             if (!ActivateFocusInGrab(dev, pWin, parent))
2848                 DoFocusEvents(dev, pWin, parent, focusEventMode);
2849             dev->focus->win = parent;
2850             dev->focus->revert = RevertToNone;
2851             break;
2852         case RevertToPointerRoot:
2853             if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
2854                 DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
2855             dev->focus->win = PointerRootWin;
2856             dev->focus->traceGood = 0;
2857             break;
2858         case RevertToFollowKeyboard:
2859             {
2860                 DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
2861                 if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
2862                     kbd = inputInfo.keyboard;
2863             if (kbd->focus->win) {
2864                 if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
2865                     DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
2866                 dev->focus->win = FollowKeyboardWin;
2867                 dev->focus->traceGood = 0;
2868             } else {
2869                 if (!ActivateFocusInGrab(dev, pWin, NoneWin))
2870                     DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
2871                 dev->focus->win = NoneWin;
2872                 dev->focus->traceGood = 0;
2873             }
2874             }
2875             break;
2876         }
2877     }
2879     if (dev->valuator)
2880         if (dev->valuator->motionHintWindow == pWin)
2881             dev->valuator->motionHintWindow = NullWindow;
2884 void
2885 DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
2887     int i;
2888     DeviceIntPtr dev;
2889     InputClientsPtr ic;
2890     struct _OtherInputMasks *inputMasks;
2892     for (dev = inputInfo.devices; dev; dev = dev->next) {
2893         DeleteDeviceFromAnyExtEvents(pWin, dev);
2894     }
2896     for (dev = inputInfo.off_devices; dev; dev = dev->next)
2897         DeleteDeviceFromAnyExtEvents(pWin, dev);
2899     if (freeResources)
2900         while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
2901             ic = inputMasks->inputClients;
2902             for (i = 0; i < EMASKSIZE; i++)
2903                 inputMasks->dontPropagateMask[i] = 0;
2904             FreeResource(ic->resource, RT_NONE);
2905         }
2908 int
2909 MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
2911     DeviceIntPtr dev;
2913     dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
2914                     DixReadAccess);
2915     if (!dev)
2916         return 0;
2918     if (pEvents->type == DeviceMotionNotify) {
2919         if (mask & DevicePointerMotionHintMask) {
2920             if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
2921                 return 1;       /* don't send, but pretend we did */
2922             }
2923             pEvents->detail = NotifyHint;
2924         } else {
2925             pEvents->detail = NotifyNormal;
2926         }
2927     }
2928     return 0;
2931 void
2932 CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
2933                              deviceKeyButtonPointer * xE, GrabPtr grab,
2934                              ClientPtr client, Mask deliveryMask)
2936     DeviceIntPtr dev;
2938     dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
2939                     DixGrabAccess);
2940     if (!dev)
2941         return;
2943     if (type == DeviceMotionNotify)
2944         dev->valuator->motionHintWindow = pWin;
2945     else if ((type == DeviceButtonPress) && (!grab) &&
2946              (deliveryMask & DeviceButtonGrabMask)) {
2947         GrabPtr tempGrab;
2949         tempGrab = AllocGrab();
2950         if (!tempGrab)
2951             return;
2953         tempGrab->device = dev;
2954         tempGrab->resource = client->clientAsMask;
2955         tempGrab->window = pWin;
2956         tempGrab->ownerEvents =
2957             (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
2958         tempGrab->eventMask = deliveryMask;
2959         tempGrab->keyboardMode = GrabModeAsync;
2960         tempGrab->pointerMode = GrabModeAsync;
2961         tempGrab->confineTo = NullWindow;
2962         tempGrab->cursor = NullCursor;
2963         tempGrab->next = NULL;
2964         (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE);
2965         FreeGrab(tempGrab);
2966     }
2969 static Mask
2970 DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
2972     InputClientsPtr other;
2974     if (!wOtherInputMasks(pWin))
2975         return 0;
2976     for (other = wOtherInputMasks(pWin)->inputClients; other;
2977          other = other->next) {
2978         if (SameClient(other, client))
2979             return other->mask[dev->id];
2980     }
2981     return 0;
2984 void
2985 MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
2987     WindowPtr pWin;
2988     GrabPtr grab = dev->deviceGrab.grab;
2990     pWin = dev->valuator->motionHintWindow;
2992     if ((grab && SameClient(grab, client) &&
2993          ((grab->eventMask & DevicePointerMotionHintMask) ||
2994           (grab->ownerEvents &&
2995            (DeviceEventMaskForClient(dev, pWin, client) &
2996             DevicePointerMotionHintMask)))) ||
2997         (!grab &&
2998          (DeviceEventMaskForClient(dev, pWin, client) &
2999           DevicePointerMotionHintMask)))
3000         dev->valuator->motionHintWindow = NullWindow;
3003 int
3004 DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
3005                              int maskndx)
3007     struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
3009     if (mask & ~PropagateMask[maskndx]) {
3010         client->errorValue = mask;
3011         return BadValue;
3012     }
3014     if (mask == 0) {
3015         if (inputMasks)
3016             inputMasks->dontPropagateMask[maskndx] = mask;
3017     } else {
3018         if (!inputMasks)
3019             AddExtensionClient(pWin, client, 0, 0);
3020         inputMasks = wOtherInputMasks(pWin);
3021         inputMasks->dontPropagateMask[maskndx] = mask;
3022     }
3023     RecalculateDeviceDeliverableEvents(pWin);
3024     if (ShouldFreeInputMasks(pWin, FALSE))
3025         FreeResource(inputMasks->inputClients->resource, RT_NONE);
3026     return Success;
3029 Bool
3030 ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
3032     int i;
3033     Mask allInputEventMasks = 0;
3034     struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
3036     for (i = 0; i < EMASKSIZE; i++)
3037         allInputEventMasks |= inputMasks->dontPropagateMask[i];
3038     if (!ignoreSelectedEvents)
3039         for (i = 0; i < EMASKSIZE; i++)
3040             allInputEventMasks |= inputMasks->inputEvents[i];
3041     if (allInputEventMasks == 0)
3042         return TRUE;
3043     else
3044         return FALSE;
3047 /***********************************************************************
3048  *
3049  * Walk through the window tree, finding all clients that want to know
3050  * about the Event.
3051  *
3052  */
3054 static void
3055 FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
3056                        xEvent * ev, int count)
3058     WindowPtr p2;
3060     while (p1) {
3061         p2 = p1->firstChild;
3062         DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
3063         FindInterestedChildren(dev, p2, mask, ev, count);
3064         p1 = p1->nextSib;
3065     }
3068 /***********************************************************************
3069  *
3070  * Send an event to interested clients in all windows on all screens.
3071  *
3072  */
3074 void
3075 SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
3077     int i;
3078     WindowPtr pWin, p1;
3080     for (i = 0; i < screenInfo.numScreens; i++) {
3081         pWin = screenInfo.screens[i]->root;
3082         if (!pWin)
3083             continue;
3084         DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
3085         p1 = pWin->firstChild;
3086         FindInterestedChildren(dev, p1, mask, ev, count);
3087     }
3090 /**
3091  * Set the XI2 mask for the given client on the given window.
3092  * @param dev The device to set the mask for.
3093  * @param win The window to set the mask on.
3094  * @param client The client setting the mask.
3095  * @param len Number of bytes in mask.
3096  * @param mask Event mask in the form of (1 << eventtype)
3097  */
3098 int
3099 XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
3100                unsigned int len, unsigned char* mask)
3102     OtherInputMasks *masks;
3103     InputClientsPtr others = NULL;
3105     masks = wOtherInputMasks(win);
3106     if (masks)
3107     {
3108         for (others = wOtherInputMasks(win)->inputClients; others;
3109              others = others->next) {
3110             if (SameClient(others, client)) {
3111                 xi2mask_zero(others->xi2mask, dev->id);
3112                 break;
3113             }
3114         }
3115     }
3118     if (len && !others)
3119     {
3120         if (AddExtensionClient(win, client, 0, 0) != Success)
3121             return BadAlloc;
3122         others= wOtherInputMasks(win)->inputClients;
3123     }
3125     if (others) {
3126         xi2mask_zero(others->xi2mask, dev->id);
3127         len = min(len, xi2mask_mask_size(others->xi2mask));
3128     }
3130     if (len) {
3131         xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len);
3132     }
3134     RecalculateDeviceDeliverableEvents(win);
3136     return Success;