exevents.c revision 706f2543
1706f2543Smrg/************************************************************
2706f2543Smrg
3706f2543SmrgCopyright 1989, 1998  The Open Group
4706f2543Smrg
5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its
6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that
7706f2543Smrgthe above copyright notice appear in all copies and that both that
8706f2543Smrgcopyright notice and this permission notice appear in supporting
9706f2543Smrgdocumentation.
10706f2543Smrg
11706f2543SmrgThe above copyright notice and this permission notice shall be included in
12706f2543Smrgall copies or substantial portions of the Software.
13706f2543Smrg
14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20706f2543Smrg
21706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be
22706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings
23706f2543Smrgin this Software without prior written authorization from The Open Group.
24706f2543Smrg
25706f2543SmrgCopyright 1989 by Hewlett-Packard Company, Palo Alto, California.
26706f2543Smrg
27706f2543Smrg			All Rights Reserved
28706f2543Smrg
29706f2543SmrgPermission to use, copy, modify, and distribute this software and its
30706f2543Smrgdocumentation for any purpose and without fee is hereby granted,
31706f2543Smrgprovided that the above copyright notice appear in all copies and that
32706f2543Smrgboth that copyright notice and this permission notice appear in
33706f2543Smrgsupporting documentation, and that the name of Hewlett-Packard not be
34706f2543Smrgused in advertising or publicity pertaining to distribution of the
35706f2543Smrgsoftware without specific, written prior permission.
36706f2543Smrg
37706f2543SmrgHEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38706f2543SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39706f2543SmrgHEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40706f2543SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42706f2543SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43706f2543SmrgSOFTWARE.
44706f2543Smrg
45706f2543Smrg********************************************************/
46706f2543Smrg
47706f2543Smrg/********************************************************************
48706f2543Smrg *
49706f2543Smrg *  Routines to register and initialize extension input devices.
50706f2543Smrg *  This also contains ProcessOtherEvent, the routine called from DDX
51706f2543Smrg *  to route extension events.
52706f2543Smrg *
53706f2543Smrg */
54706f2543Smrg
55706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
56706f2543Smrg#include <dix-config.h>
57706f2543Smrg#endif
58706f2543Smrg
59706f2543Smrg#include "inputstr.h"
60706f2543Smrg#include <X11/X.h>
61706f2543Smrg#include <X11/Xproto.h>
62706f2543Smrg#include <X11/extensions/XI.h>
63706f2543Smrg#include <X11/extensions/XIproto.h>
64706f2543Smrg#include <X11/extensions/XI2proto.h>
65706f2543Smrg#include <X11/extensions/geproto.h>
66706f2543Smrg#include "windowstr.h"
67706f2543Smrg#include "miscstruct.h"
68706f2543Smrg#include "region.h"
69706f2543Smrg#include "exevents.h"
70706f2543Smrg#include "extnsionst.h"
71706f2543Smrg#include "exglobals.h"
72706f2543Smrg#include "dixevents.h"	/* DeliverFocusedEvent */
73706f2543Smrg#include "dixgrabs.h"	/* CreateGrab() */
74706f2543Smrg#include "scrnintstr.h"
75706f2543Smrg#include "listdev.h" /* for CopySwapXXXClass */
76706f2543Smrg#include "xace.h"
77706f2543Smrg#include "xiquerydevice.h" /* For List*Info */
78706f2543Smrg#include "eventconvert.h"
79706f2543Smrg#include "eventstr.h"
80706f2543Smrg
81706f2543Smrg#include <X11/extensions/XKBproto.h>
82706f2543Smrg#include "xkbsrv.h"
83706f2543Smrg
84706f2543Smrg#define WID(w) ((w) ? ((w)->drawable.id) : 0)
85706f2543Smrg#define AllModifiersMask ( \
86706f2543Smrg	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
87706f2543Smrg	Mod3Mask | Mod4Mask | Mod5Mask )
88706f2543Smrg#define AllButtonsMask ( \
89706f2543Smrg	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
90706f2543Smrg
91706f2543SmrgBool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
92706f2543Smrg				 Bool	/* ignoreSelectedEvents */
93706f2543Smrg    );
94706f2543Smrgstatic Bool MakeInputMasks(WindowPtr	/* pWin */
95706f2543Smrg    );
96706f2543Smrg
97706f2543Smrg/*
98706f2543Smrg * Only let the given client know of core events which will affect its
99706f2543Smrg * interpretation of input events, if the client's ClientPointer (or the
100706f2543Smrg * paired keyboard) is the current device.
101706f2543Smrg */
102706f2543Smrgint
103706f2543SmrgXIShouldNotify(ClientPtr client, DeviceIntPtr dev)
104706f2543Smrg{
105706f2543Smrg    DeviceIntPtr current_ptr = PickPointer(client);
106706f2543Smrg    DeviceIntPtr current_kbd = GetPairedDevice(current_ptr);
107706f2543Smrg
108706f2543Smrg    if (dev == current_kbd || dev == current_ptr)
109706f2543Smrg        return 1;
110706f2543Smrg
111706f2543Smrg    return 0;
112706f2543Smrg}
113706f2543Smrg
114706f2543SmrgBool
115706f2543SmrgIsPointerEvent(InternalEvent* event)
116706f2543Smrg{
117706f2543Smrg    switch(event->any.type)
118706f2543Smrg    {
119706f2543Smrg        case ET_ButtonPress:
120706f2543Smrg        case ET_ButtonRelease:
121706f2543Smrg        case ET_Motion:
122706f2543Smrg            /* XXX: enter/leave ?? */
123706f2543Smrg            return TRUE;
124706f2543Smrg        default:
125706f2543Smrg            break;
126706f2543Smrg    }
127706f2543Smrg    return FALSE;
128706f2543Smrg}
129706f2543Smrg
130706f2543Smrg/**
131706f2543Smrg * @return the device matching the deviceid of the device set in the event, or
132706f2543Smrg * NULL if the event is not an XInput event.
133706f2543Smrg */
134706f2543SmrgDeviceIntPtr
135706f2543SmrgXIGetDevice(xEvent* xE)
136706f2543Smrg{
137706f2543Smrg    DeviceIntPtr pDev = NULL;
138706f2543Smrg
139706f2543Smrg    if (xE->u.u.type == DeviceButtonPress ||
140706f2543Smrg        xE->u.u.type == DeviceButtonRelease ||
141706f2543Smrg        xE->u.u.type == DeviceMotionNotify ||
142706f2543Smrg        xE->u.u.type == ProximityIn ||
143706f2543Smrg        xE->u.u.type == ProximityOut ||
144706f2543Smrg        xE->u.u.type == DevicePropertyNotify)
145706f2543Smrg    {
146706f2543Smrg        int rc;
147706f2543Smrg        int id;
148706f2543Smrg
149706f2543Smrg        id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
150706f2543Smrg
151706f2543Smrg        rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
152706f2543Smrg        if (rc != Success)
153706f2543Smrg            ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
154706f2543Smrg    }
155706f2543Smrg    return pDev;
156706f2543Smrg}
157706f2543Smrg
158706f2543Smrg
159706f2543Smrg/**
160706f2543Smrg * Copy the device->key into master->key and send a mapping notify to the
161706f2543Smrg * clients if appropriate.
162706f2543Smrg * master->key needs to be allocated by the caller.
163706f2543Smrg *
164706f2543Smrg * Device is the slave device. If it is attached to a master device, we may
165706f2543Smrg * need to send a mapping notify to the client because it causes the MD
166706f2543Smrg * to change state.
167706f2543Smrg *
168706f2543Smrg * Mapping notify needs to be sent in the following cases:
169706f2543Smrg *      - different slave device on same master
170706f2543Smrg *      - different master
171706f2543Smrg *
172706f2543Smrg * XXX: They way how the code is we also send a map notify if the slave device
173706f2543Smrg * stays the same, but the master changes. This isn't really necessary though.
174706f2543Smrg *
175706f2543Smrg * XXX: this gives you funny behaviour with the ClientPointer. When a
176706f2543Smrg * MappingNotify is sent to the client, the client usually responds with a
177706f2543Smrg * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
178706f2543Smrg * mapping, regardless of which keyboard sent the last mapping notify request.
179706f2543Smrg * So depending on the CP setting, your keyboard may change layout in each
180706f2543Smrg * app...
181706f2543Smrg *
182706f2543Smrg * This code is basically the old SwitchCoreKeyboard.
183706f2543Smrg */
184706f2543Smrg
185706f2543Smrgvoid
186706f2543SmrgCopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
187706f2543Smrg{
188706f2543Smrg    KeyClassPtr mk = master->key;
189706f2543Smrg
190706f2543Smrg    if (device == master)
191706f2543Smrg        return;
192706f2543Smrg
193706f2543Smrg    mk->sourceid = device->id;
194706f2543Smrg
195706f2543Smrg
196706f2543Smrg    if (!XkbCopyDeviceKeymap(master, device))
197706f2543Smrg        FatalError("Couldn't pivot keymap from device to core!\n");
198706f2543Smrg}
199706f2543Smrg
200706f2543Smrg/**
201706f2543Smrg * Copies the feedback classes from device "from" into device "to". Classes
202706f2543Smrg * are duplicated (not just flipping the pointers). All feedback classes are
203706f2543Smrg * linked lists, the full list is duplicated.
204706f2543Smrg */
205706f2543Smrgstatic void
206706f2543SmrgDeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
207706f2543Smrg{
208706f2543Smrg    ClassesPtr classes;
209706f2543Smrg
210706f2543Smrg
211706f2543Smrg    if (from->intfeed)
212706f2543Smrg    {
213706f2543Smrg        IntegerFeedbackPtr *i, it;
214706f2543Smrg
215706f2543Smrg        if (!to->intfeed)
216706f2543Smrg        {
217706f2543Smrg            classes = to->unused_classes;
218706f2543Smrg            to->intfeed = classes->intfeed;
219706f2543Smrg            classes->intfeed = NULL;
220706f2543Smrg        }
221706f2543Smrg
222706f2543Smrg        i = &to->intfeed;
223706f2543Smrg        for (it = from->intfeed; it; it = it->next)
224706f2543Smrg        {
225706f2543Smrg            if (!(*i))
226706f2543Smrg            {
227706f2543Smrg                *i = calloc(1, sizeof(IntegerFeedbackClassRec));
228706f2543Smrg                if (!(*i))
229706f2543Smrg                {
230706f2543Smrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
231706f2543Smrg                    return;
232706f2543Smrg                }
233706f2543Smrg            }
234706f2543Smrg            (*i)->CtrlProc = it->CtrlProc;
235706f2543Smrg            (*i)->ctrl     = it->ctrl;
236706f2543Smrg
237706f2543Smrg            i = &(*i)->next;
238706f2543Smrg        }
239706f2543Smrg    } else if (to->intfeed && !from->intfeed)
240706f2543Smrg    {
241706f2543Smrg        ClassesPtr classes;
242706f2543Smrg        classes = to->unused_classes;
243706f2543Smrg        classes->intfeed = to->intfeed;
244706f2543Smrg        to->intfeed      = NULL;
245706f2543Smrg    }
246706f2543Smrg
247706f2543Smrg    if (from->stringfeed)
248706f2543Smrg    {
249706f2543Smrg        StringFeedbackPtr *s, it;
250706f2543Smrg
251706f2543Smrg        if (!to->stringfeed)
252706f2543Smrg        {
253706f2543Smrg            classes = to->unused_classes;
254706f2543Smrg            to->stringfeed = classes->stringfeed;
255706f2543Smrg            classes->stringfeed = NULL;
256706f2543Smrg        }
257706f2543Smrg
258706f2543Smrg        s = &to->stringfeed;
259706f2543Smrg        for (it = from->stringfeed; it; it = it->next)
260706f2543Smrg        {
261706f2543Smrg            if (!(*s))
262706f2543Smrg            {
263706f2543Smrg                *s = calloc(1, sizeof(StringFeedbackClassRec));
264706f2543Smrg                if (!(*s))
265706f2543Smrg                {
266706f2543Smrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
267706f2543Smrg                    return;
268706f2543Smrg                }
269706f2543Smrg            }
270706f2543Smrg            (*s)->CtrlProc = it->CtrlProc;
271706f2543Smrg            (*s)->ctrl     = it->ctrl;
272706f2543Smrg
273706f2543Smrg            s = &(*s)->next;
274706f2543Smrg        }
275706f2543Smrg    } else if (to->stringfeed && !from->stringfeed)
276706f2543Smrg    {
277706f2543Smrg        ClassesPtr classes;
278706f2543Smrg        classes = to->unused_classes;
279706f2543Smrg        classes->stringfeed = to->stringfeed;
280706f2543Smrg        to->stringfeed      = NULL;
281706f2543Smrg    }
282706f2543Smrg
283706f2543Smrg    if (from->bell)
284706f2543Smrg    {
285706f2543Smrg        BellFeedbackPtr *b, it;
286706f2543Smrg
287706f2543Smrg        if (!to->bell)
288706f2543Smrg        {
289706f2543Smrg            classes = to->unused_classes;
290706f2543Smrg            to->bell = classes->bell;
291706f2543Smrg            classes->bell = NULL;
292706f2543Smrg        }
293706f2543Smrg
294706f2543Smrg        b = &to->bell;
295706f2543Smrg        for (it = from->bell; it; it = it->next)
296706f2543Smrg        {
297706f2543Smrg            if (!(*b))
298706f2543Smrg            {
299706f2543Smrg                *b = calloc(1, sizeof(BellFeedbackClassRec));
300706f2543Smrg                if (!(*b))
301706f2543Smrg                {
302706f2543Smrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
303706f2543Smrg                    return;
304706f2543Smrg                }
305706f2543Smrg            }
306706f2543Smrg            (*b)->BellProc = it->BellProc;
307706f2543Smrg            (*b)->CtrlProc = it->CtrlProc;
308706f2543Smrg            (*b)->ctrl     = it->ctrl;
309706f2543Smrg
310706f2543Smrg            b = &(*b)->next;
311706f2543Smrg        }
312706f2543Smrg    } else if (to->bell && !from->bell)
313706f2543Smrg    {
314706f2543Smrg        ClassesPtr classes;
315706f2543Smrg        classes = to->unused_classes;
316706f2543Smrg        classes->bell = to->bell;
317706f2543Smrg        to->bell      = NULL;
318706f2543Smrg    }
319706f2543Smrg
320706f2543Smrg    if (from->leds)
321706f2543Smrg    {
322706f2543Smrg        LedFeedbackPtr *l, it;
323706f2543Smrg
324706f2543Smrg        if (!to->leds)
325706f2543Smrg        {
326706f2543Smrg            classes = to->unused_classes;
327706f2543Smrg            to->leds = classes->leds;
328706f2543Smrg            classes->leds = NULL;
329706f2543Smrg        }
330706f2543Smrg
331706f2543Smrg        l = &to->leds;
332706f2543Smrg        for (it = from->leds; it; it = it->next)
333706f2543Smrg        {
334706f2543Smrg            if (!(*l))
335706f2543Smrg            {
336706f2543Smrg                *l = calloc(1, sizeof(LedFeedbackClassRec));
337706f2543Smrg                if (!(*l))
338706f2543Smrg                {
339706f2543Smrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
340706f2543Smrg                    return;
341706f2543Smrg                }
342706f2543Smrg            }
343706f2543Smrg            (*l)->CtrlProc = it->CtrlProc;
344706f2543Smrg            (*l)->ctrl     = it->ctrl;
345706f2543Smrg            if ((*l)->xkb_sli)
346706f2543Smrg                XkbFreeSrvLedInfo((*l)->xkb_sli);
347706f2543Smrg            (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
348706f2543Smrg
349706f2543Smrg            l = &(*l)->next;
350706f2543Smrg        }
351706f2543Smrg    } else if (to->leds && !from->leds)
352706f2543Smrg    {
353706f2543Smrg        ClassesPtr classes;
354706f2543Smrg        classes = to->unused_classes;
355706f2543Smrg        classes->leds = to->leds;
356706f2543Smrg        to->leds      = NULL;
357706f2543Smrg    }
358706f2543Smrg}
359706f2543Smrg
360706f2543Smrgstatic void
361706f2543SmrgDeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
362706f2543Smrg{
363706f2543Smrg    ClassesPtr classes;
364706f2543Smrg
365706f2543Smrg    /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
366706f2543Smrg     * kbdfeed to be set up properly, so let's do the feedback classes first.
367706f2543Smrg     */
368706f2543Smrg    if (from->kbdfeed)
369706f2543Smrg    {
370706f2543Smrg        KbdFeedbackPtr *k, it;
371706f2543Smrg
372706f2543Smrg        if (!to->kbdfeed)
373706f2543Smrg        {
374706f2543Smrg            classes = to->unused_classes;
375706f2543Smrg
376706f2543Smrg            to->kbdfeed = classes->kbdfeed;
377706f2543Smrg            if (!to->kbdfeed)
378706f2543Smrg                InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
379706f2543Smrg            classes->kbdfeed = NULL;
380706f2543Smrg        }
381706f2543Smrg
382706f2543Smrg        k = &to->kbdfeed;
383706f2543Smrg        for(it = from->kbdfeed; it; it = it->next)
384706f2543Smrg        {
385706f2543Smrg            if (!(*k))
386706f2543Smrg            {
387706f2543Smrg                *k = calloc(1, sizeof(KbdFeedbackClassRec));
388706f2543Smrg                if (!*k)
389706f2543Smrg                {
390706f2543Smrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
391706f2543Smrg                    return;
392706f2543Smrg                }
393706f2543Smrg            }
394706f2543Smrg            (*k)->BellProc = it->BellProc;
395706f2543Smrg            (*k)->CtrlProc = it->CtrlProc;
396706f2543Smrg            (*k)->ctrl     = it->ctrl;
397706f2543Smrg            if ((*k)->xkb_sli)
398706f2543Smrg                XkbFreeSrvLedInfo((*k)->xkb_sli);
399706f2543Smrg            (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
400706f2543Smrg
401706f2543Smrg            k = &(*k)->next;
402706f2543Smrg        }
403706f2543Smrg    } else if (to->kbdfeed && !from->kbdfeed)
404706f2543Smrg    {
405706f2543Smrg        ClassesPtr classes;
406706f2543Smrg        classes = to->unused_classes;
407706f2543Smrg        classes->kbdfeed = to->kbdfeed;
408706f2543Smrg        to->kbdfeed      = NULL;
409706f2543Smrg    }
410706f2543Smrg
411706f2543Smrg    if (from->key)
412706f2543Smrg    {
413706f2543Smrg        if (!to->key)
414706f2543Smrg        {
415706f2543Smrg            classes = to->unused_classes;
416706f2543Smrg            to->key = classes->key;
417706f2543Smrg            if (!to->key)
418706f2543Smrg                InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
419706f2543Smrg            else
420706f2543Smrg                classes->key = NULL;
421706f2543Smrg        }
422706f2543Smrg
423706f2543Smrg        CopyKeyClass(from, to);
424706f2543Smrg    } else if (to->key && !from->key)
425706f2543Smrg    {
426706f2543Smrg        ClassesPtr classes;
427706f2543Smrg        classes = to->unused_classes;
428706f2543Smrg        classes->key = to->key;
429706f2543Smrg        to->key      = NULL;
430706f2543Smrg    }
431706f2543Smrg
432706f2543Smrg    /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
433706f2543Smrg     * pointer point into the xkbInfo->desc struct.  XkbCopySrvLedInfo
434706f2543Smrg     * didn't update the pointers so we need to do it manually here.
435706f2543Smrg     */
436706f2543Smrg    if (to->kbdfeed)
437706f2543Smrg    {
438706f2543Smrg        KbdFeedbackPtr k;
439706f2543Smrg
440706f2543Smrg        for (k = to->kbdfeed; k; k = k->next)
441706f2543Smrg        {
442706f2543Smrg            if (!k->xkb_sli)
443706f2543Smrg                continue;
444706f2543Smrg            if (k->xkb_sli->flags & XkbSLI_IsDefault)
445706f2543Smrg            {
446706f2543Smrg                k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
447706f2543Smrg                k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
448706f2543Smrg            }
449706f2543Smrg        }
450706f2543Smrg    }
451706f2543Smrg
452706f2543Smrg    /* We can't just copy over the focus class. When an app sets the focus,
453706f2543Smrg     * it'll do so on the master device. Copying the SDs focus means losing
454706f2543Smrg     * the focus.
455706f2543Smrg     * So we only copy the focus class if the device didn't have one,
456706f2543Smrg     * otherwise we leave it as it is.
457706f2543Smrg     */
458706f2543Smrg    if (from->focus)
459706f2543Smrg    {
460706f2543Smrg        if (!to->focus)
461706f2543Smrg        {
462706f2543Smrg            WindowPtr *oldTrace;
463706f2543Smrg
464706f2543Smrg            classes = to->unused_classes;
465706f2543Smrg            to->focus = classes->focus;
466706f2543Smrg            if (!to->focus)
467706f2543Smrg            {
468706f2543Smrg                to->focus = calloc(1, sizeof(FocusClassRec));
469706f2543Smrg                if (!to->focus)
470706f2543Smrg                    FatalError("[Xi] no memory for class shift.\n");
471706f2543Smrg            } else
472706f2543Smrg                classes->focus = NULL;
473706f2543Smrg
474706f2543Smrg            oldTrace = to->focus->trace;
475706f2543Smrg            memcpy(to->focus, from->focus, sizeof(FocusClassRec));
476706f2543Smrg            to->focus->trace = realloc(oldTrace,
477706f2543Smrg                                  to->focus->traceSize * sizeof(WindowPtr));
478706f2543Smrg            if (!to->focus->trace && to->focus->traceSize)
479706f2543Smrg                FatalError("[Xi] no memory for trace.\n");
480706f2543Smrg            memcpy(to->focus->trace, from->focus->trace,
481706f2543Smrg                    from->focus->traceSize * sizeof(WindowPtr));
482706f2543Smrg            to->focus->sourceid = from->id;
483706f2543Smrg        }
484706f2543Smrg    } else if (to->focus)
485706f2543Smrg    {
486706f2543Smrg        ClassesPtr classes;
487706f2543Smrg        classes = to->unused_classes;
488706f2543Smrg        classes->focus = to->focus;
489706f2543Smrg        to->focus      = NULL;
490706f2543Smrg    }
491706f2543Smrg
492706f2543Smrg}
493706f2543Smrg
494706f2543Smrgstatic void
495706f2543SmrgDeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
496706f2543Smrg{
497706f2543Smrg    ClassesPtr classes;
498706f2543Smrg
499706f2543Smrg    /* Feedback classes must be copied first */
500706f2543Smrg    if (from->ptrfeed)
501706f2543Smrg    {
502706f2543Smrg        PtrFeedbackPtr *p, it;
503706f2543Smrg        if (!to->ptrfeed)
504706f2543Smrg        {
505706f2543Smrg            classes = to->unused_classes;
506706f2543Smrg            to->ptrfeed = classes->ptrfeed;
507706f2543Smrg            classes->ptrfeed = NULL;
508706f2543Smrg        }
509706f2543Smrg
510706f2543Smrg        p = &to->ptrfeed;
511706f2543Smrg        for (it = from->ptrfeed; it; it = it->next)
512706f2543Smrg        {
513706f2543Smrg            if (!(*p))
514706f2543Smrg            {
515706f2543Smrg                *p = calloc(1, sizeof(PtrFeedbackClassRec));
516706f2543Smrg                if (!*p)
517706f2543Smrg                {
518706f2543Smrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
519706f2543Smrg                    return;
520706f2543Smrg                }
521706f2543Smrg            }
522706f2543Smrg            (*p)->CtrlProc = it->CtrlProc;
523706f2543Smrg            (*p)->ctrl     = it->ctrl;
524706f2543Smrg
525706f2543Smrg            p = &(*p)->next;
526706f2543Smrg        }
527706f2543Smrg    } else if (to->ptrfeed && !from->ptrfeed)
528706f2543Smrg    {
529706f2543Smrg        ClassesPtr classes;
530706f2543Smrg        classes = to->unused_classes;
531706f2543Smrg        classes->ptrfeed = to->ptrfeed;
532706f2543Smrg        to->ptrfeed      = NULL;
533706f2543Smrg    }
534706f2543Smrg
535706f2543Smrg    if (from->valuator)
536706f2543Smrg    {
537706f2543Smrg        ValuatorClassPtr v;
538706f2543Smrg
539706f2543Smrg        if (!to->valuator)
540706f2543Smrg        {
541706f2543Smrg            classes = to->unused_classes;
542706f2543Smrg            to->valuator = classes->valuator;
543706f2543Smrg            if (to->valuator)
544706f2543Smrg                classes->valuator = NULL;
545706f2543Smrg        }
546706f2543Smrg
547706f2543Smrg        v = AllocValuatorClass(to->valuator, from->valuator->numAxes);
548706f2543Smrg
549706f2543Smrg        if (!v)
550706f2543Smrg            FatalError("[Xi] no memory for class shift.\n");
551706f2543Smrg
552706f2543Smrg        to->valuator = v;
553706f2543Smrg        memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
554706f2543Smrg
555706f2543Smrg        v->sourceid = from->id;
556706f2543Smrg    } else if (to->valuator && !from->valuator)
557706f2543Smrg    {
558706f2543Smrg        ClassesPtr classes;
559706f2543Smrg        classes = to->unused_classes;
560706f2543Smrg        classes->valuator = to->valuator;
561706f2543Smrg        to->valuator      = NULL;
562706f2543Smrg    }
563706f2543Smrg
564706f2543Smrg    if (from->button)
565706f2543Smrg    {
566706f2543Smrg        if (!to->button)
567706f2543Smrg        {
568706f2543Smrg            classes = to->unused_classes;
569706f2543Smrg            to->button = classes->button;
570706f2543Smrg            if (!to->button)
571706f2543Smrg            {
572706f2543Smrg                to->button = calloc(1, sizeof(ButtonClassRec));
573706f2543Smrg                if (!to->button)
574706f2543Smrg                    FatalError("[Xi] no memory for class shift.\n");
575706f2543Smrg            } else
576706f2543Smrg                classes->button = NULL;
577706f2543Smrg        }
578706f2543Smrg
579706f2543Smrg        if (from->button->xkb_acts)
580706f2543Smrg        {
581706f2543Smrg            if (!to->button->xkb_acts)
582706f2543Smrg            {
583706f2543Smrg                to->button->xkb_acts = calloc(1, sizeof(XkbAction));
584706f2543Smrg                if (!to->button->xkb_acts)
585706f2543Smrg                    FatalError("[Xi] not enough memory for xkb_acts.\n");
586706f2543Smrg            }
587706f2543Smrg            memcpy(to->button->xkb_acts, from->button->xkb_acts,
588706f2543Smrg                    sizeof(XkbAction));
589706f2543Smrg        } else
590706f2543Smrg            free(to->button->xkb_acts);
591706f2543Smrg
592706f2543Smrg         memcpy(to->button->labels, from->button->labels,
593706f2543Smrg                from->button->numButtons * sizeof(Atom));
594706f2543Smrg        to->button->sourceid = from->id;
595706f2543Smrg    } else if (to->button && !from->button)
596706f2543Smrg    {
597706f2543Smrg        ClassesPtr classes;
598706f2543Smrg        classes = to->unused_classes;
599706f2543Smrg        classes->button = to->button;
600706f2543Smrg        to->button      = NULL;
601706f2543Smrg    }
602706f2543Smrg
603706f2543Smrg    if (from->proximity)
604706f2543Smrg    {
605706f2543Smrg        if (!to->proximity)
606706f2543Smrg        {
607706f2543Smrg            classes = to->unused_classes;
608706f2543Smrg            to->proximity = classes->proximity;
609706f2543Smrg            if (!to->proximity)
610706f2543Smrg            {
611706f2543Smrg                to->proximity = calloc(1, sizeof(ProximityClassRec));
612706f2543Smrg                if (!to->proximity)
613706f2543Smrg                    FatalError("[Xi] no memory for class shift.\n");
614706f2543Smrg            } else
615706f2543Smrg                classes->proximity = NULL;
616706f2543Smrg        }
617706f2543Smrg        memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
618706f2543Smrg        to->proximity->sourceid = from->id;
619706f2543Smrg    } else if (to->proximity)
620706f2543Smrg    {
621706f2543Smrg        ClassesPtr classes;
622706f2543Smrg        classes = to->unused_classes;
623706f2543Smrg        classes->proximity = to->proximity;
624706f2543Smrg        to->proximity      = NULL;
625706f2543Smrg    }
626706f2543Smrg
627706f2543Smrg    if (from->absolute)
628706f2543Smrg    {
629706f2543Smrg        if (!to->absolute)
630706f2543Smrg        {
631706f2543Smrg            classes = to->unused_classes;
632706f2543Smrg            to->absolute = classes->absolute;
633706f2543Smrg            if (!to->absolute)
634706f2543Smrg            {
635706f2543Smrg                to->absolute = calloc(1, sizeof(AbsoluteClassRec));
636706f2543Smrg                if (!to->absolute)
637706f2543Smrg                    FatalError("[Xi] no memory for class shift.\n");
638706f2543Smrg            } else
639706f2543Smrg                classes->absolute = NULL;
640706f2543Smrg        }
641706f2543Smrg        memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
642706f2543Smrg        to->absolute->sourceid = from->id;
643706f2543Smrg    } else if (to->absolute)
644706f2543Smrg    {
645706f2543Smrg        ClassesPtr classes;
646706f2543Smrg        classes = to->unused_classes;
647706f2543Smrg        classes->absolute = to->absolute;
648706f2543Smrg        to->absolute      = NULL;
649706f2543Smrg    }
650706f2543Smrg}
651706f2543Smrg
652706f2543Smrg/**
653706f2543Smrg * Copies the CONTENT of the classes of device from into the classes in device
654706f2543Smrg * to. From and to are identical after finishing.
655706f2543Smrg *
656706f2543Smrg * If to does not have classes from currenly has, the classes are stored in
657706f2543Smrg * to's devPrivates system. Later, we recover it again from there if needed.
658706f2543Smrg * Saves a few memory allocations.
659706f2543Smrg */
660706f2543Smrgvoid
661706f2543SmrgDeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce)
662706f2543Smrg{
663706f2543Smrg    /* generic feedback classes, not tied to pointer and/or keyboard */
664706f2543Smrg    DeepCopyFeedbackClasses(from, to);
665706f2543Smrg
666706f2543Smrg    if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
667706f2543Smrg        DeepCopyKeyboardClasses(from, to);
668706f2543Smrg    if ((dce->flags & DEVCHANGE_POINTER_EVENT))
669706f2543Smrg        DeepCopyPointerClasses(from, to);
670706f2543Smrg}
671706f2543Smrg
672706f2543Smrg
673706f2543Smrg/**
674706f2543Smrg * Send an XI2 DeviceChangedEvent to all interested clients.
675706f2543Smrg */
676706f2543Smrgvoid
677706f2543SmrgXISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChangedEvent *dce)
678706f2543Smrg{
679706f2543Smrg    xXIDeviceChangedEvent *dcce;
680706f2543Smrg    int rc;
681706f2543Smrg
682706f2543Smrg    rc = EventToXI2((InternalEvent*)dce, (xEvent**)&dcce);
683706f2543Smrg    if (rc != Success)
684706f2543Smrg    {
685706f2543Smrg        ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
686706f2543Smrg        return;
687706f2543Smrg    }
688706f2543Smrg
689706f2543Smrg    /* we don't actually swap if there's a NullClient, swapping is done
690706f2543Smrg     * later when event is delivered. */
691706f2543Smrg    SendEventToAllWindows(master, XI_DeviceChangedMask, (xEvent*)dcce, 1);
692706f2543Smrg    free(dcce);
693706f2543Smrg}
694706f2543Smrg
695706f2543Smrgstatic void
696706f2543SmrgChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
697706f2543Smrg{
698706f2543Smrg    DeviceIntPtr slave;
699706f2543Smrg    int rc;
700706f2543Smrg
701706f2543Smrg    /* For now, we don't have devices that change physically. */
702706f2543Smrg    if (!IsMaster(device))
703706f2543Smrg        return;
704706f2543Smrg
705706f2543Smrg    rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
706706f2543Smrg
707706f2543Smrg    if (rc != Success)
708706f2543Smrg        return; /* Device has disappeared */
709706f2543Smrg
710706f2543Smrg    if (!slave->u.master)
711706f2543Smrg        return; /* set floating since the event */
712706f2543Smrg
713706f2543Smrg    if (slave->u.master->id != dce->masterid)
714706f2543Smrg        return; /* not our slave anymore, don't care */
715706f2543Smrg
716706f2543Smrg    /* FIXME: we probably need to send a DCE for the new slave now */
717706f2543Smrg
718706f2543Smrg    device->public.devicePrivate = slave->public.devicePrivate;
719706f2543Smrg
720706f2543Smrg    /* FIXME: the classes may have changed since we generated the event. */
721706f2543Smrg    DeepCopyDeviceClasses(slave, device, dce);
722706f2543Smrg    XISendDeviceChangedEvent(slave, device, dce);
723706f2543Smrg}
724706f2543Smrg
725706f2543Smrg/**
726706f2543Smrg * Update the device state according to the data in the event.
727706f2543Smrg *
728706f2543Smrg * return values are
729706f2543Smrg *   DEFAULT ... process as normal
730706f2543Smrg *   DONT_PROCESS ... return immediately from caller
731706f2543Smrg */
732706f2543Smrg#define DEFAULT 0
733706f2543Smrg#define DONT_PROCESS 1
734706f2543Smrgint
735706f2543SmrgUpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
736706f2543Smrg{
737706f2543Smrg    int i;
738706f2543Smrg    int key = 0,
739706f2543Smrg        bit = 0,
740706f2543Smrg        last_valuator;
741706f2543Smrg
742706f2543Smrg    KeyClassPtr k       = NULL;
743706f2543Smrg    ButtonClassPtr b    = NULL;
744706f2543Smrg    ValuatorClassPtr v  = NULL;
745706f2543Smrg
746706f2543Smrg    /* This event is always the first we get, before the actual events with
747706f2543Smrg     * the data. However, the way how the DDX is set up, "device" will
748706f2543Smrg     * actually be the slave device that caused the event.
749706f2543Smrg     */
750706f2543Smrg    switch(event->type)
751706f2543Smrg    {
752706f2543Smrg        case ET_DeviceChanged:
753706f2543Smrg            ChangeMasterDeviceClasses(device, (DeviceChangedEvent*)event);
754706f2543Smrg            return DONT_PROCESS; /* event has been sent already */
755706f2543Smrg        case ET_Motion:
756706f2543Smrg        case ET_ButtonPress:
757706f2543Smrg        case ET_ButtonRelease:
758706f2543Smrg        case ET_KeyPress:
759706f2543Smrg        case ET_KeyRelease:
760706f2543Smrg        case ET_ProximityIn:
761706f2543Smrg        case ET_ProximityOut:
762706f2543Smrg            break;
763706f2543Smrg        default:
764706f2543Smrg            /* other events don't update the device */
765706f2543Smrg            return DEFAULT;
766706f2543Smrg    }
767706f2543Smrg
768706f2543Smrg    k = device->key;
769706f2543Smrg    v = device->valuator;
770706f2543Smrg    b = device->button;
771706f2543Smrg
772706f2543Smrg    key = event->detail.key;
773706f2543Smrg    bit = 1 << (key & 7);
774706f2543Smrg
775706f2543Smrg    /* Update device axis */
776706f2543Smrg    /* Check valuators first */
777706f2543Smrg    last_valuator = -1;
778706f2543Smrg    for (i = 0; i < MAX_VALUATORS; i++)
779706f2543Smrg    {
780706f2543Smrg        if (BitIsOn(&event->valuators.mask, i))
781706f2543Smrg        {
782706f2543Smrg            if (!v)
783706f2543Smrg            {
784706f2543Smrg                ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
785706f2543Smrg                        "Ignoring event.\n", device->name);
786706f2543Smrg                return DONT_PROCESS;
787706f2543Smrg            } else if (v->numAxes < i)
788706f2543Smrg            {
789706f2543Smrg                ErrorF("[Xi] Too many valuators reported for device '%s'. "
790706f2543Smrg                        "Ignoring event.\n", device->name);
791706f2543Smrg                return DONT_PROCESS;
792706f2543Smrg            }
793706f2543Smrg            last_valuator = i;
794706f2543Smrg        }
795706f2543Smrg    }
796706f2543Smrg
797706f2543Smrg    for (i = 0; i <= last_valuator && i < v->numAxes; i++)
798706f2543Smrg    {
799706f2543Smrg        if (BitIsOn(&event->valuators.mask, i))
800706f2543Smrg        {
801706f2543Smrg            /* XXX: Relative/Absolute mode */
802706f2543Smrg            v->axisVal[i] = event->valuators.data[i];
803706f2543Smrg            v->axisVal[i] += (event->valuators.data_frac[i] * 1.0f / (1 << 16) / (1 << 16));
804706f2543Smrg        }
805706f2543Smrg    }
806706f2543Smrg
807706f2543Smrg    if (event->type == ET_KeyPress) {
808706f2543Smrg        if (!k)
809706f2543Smrg            return DONT_PROCESS;
810706f2543Smrg
811706f2543Smrg	/* don't allow ddx to generate multiple downs, but repeats are okay */
812706f2543Smrg	if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
813706f2543Smrg	    return DONT_PROCESS;
814706f2543Smrg
815706f2543Smrg	if (device->valuator)
816706f2543Smrg	    device->valuator->motionHintWindow = NullWindow;
817706f2543Smrg	set_key_down(device, key, KEY_PROCESSED);
818706f2543Smrg    } else if (event->type == ET_KeyRelease) {
819706f2543Smrg        if (!k)
820706f2543Smrg            return DONT_PROCESS;
821706f2543Smrg
822706f2543Smrg	if (!key_is_down(device, key, KEY_PROCESSED))	/* guard against duplicates */
823706f2543Smrg	    return DONT_PROCESS;
824706f2543Smrg	if (device->valuator)
825706f2543Smrg	    device->valuator->motionHintWindow = NullWindow;
826706f2543Smrg	set_key_up(device, key, KEY_PROCESSED);
827706f2543Smrg    } else if (event->type == ET_ButtonPress) {
828706f2543Smrg        Mask mask;
829706f2543Smrg        if (!b)
830706f2543Smrg            return DONT_PROCESS;
831706f2543Smrg
832706f2543Smrg        if (button_is_down(device, key, BUTTON_PROCESSED))
833706f2543Smrg            return DONT_PROCESS;
834706f2543Smrg
835706f2543Smrg        set_button_down(device, key, BUTTON_PROCESSED);
836706f2543Smrg	if (device->valuator)
837706f2543Smrg	    device->valuator->motionHintWindow = NullWindow;
838706f2543Smrg        if (!b->map[key])
839706f2543Smrg            return DONT_PROCESS;
840706f2543Smrg        b->buttonsDown++;
841706f2543Smrg	b->motionMask = DeviceButtonMotionMask;
842706f2543Smrg        if (b->map[key] <= 5)
843706f2543Smrg	    b->state |= (Button1Mask >> 1) << b->map[key];
844706f2543Smrg
845706f2543Smrg        /* Add state and motionMask to the filter for this event */
846706f2543Smrg        mask = DevicePointerMotionMask | b->state | b->motionMask;
847706f2543Smrg        SetMaskForEvent(device->id, mask, DeviceMotionNotify);
848706f2543Smrg        mask = PointerMotionMask | b->state | b->motionMask;
849706f2543Smrg        SetMaskForEvent(device->id, mask, MotionNotify);
850706f2543Smrg    } else if (event->type == ET_ButtonRelease) {
851706f2543Smrg        Mask mask;
852706f2543Smrg        if (!b)
853706f2543Smrg            return DONT_PROCESS;
854706f2543Smrg
855706f2543Smrg        if (!button_is_down(device, key, BUTTON_PROCESSED))
856706f2543Smrg            return DONT_PROCESS;
857706f2543Smrg        if (IsMaster(device)) {
858706f2543Smrg            DeviceIntPtr sd;
859706f2543Smrg
860706f2543Smrg            /*
861706f2543Smrg             * Leave the button down if any slave has the
862706f2543Smrg             * button still down. Note that this depends on the
863706f2543Smrg             * event being delivered through the slave first
864706f2543Smrg             */
865706f2543Smrg            for (sd = inputInfo.devices; sd; sd = sd->next) {
866706f2543Smrg                if (IsMaster(sd) || sd->u.master != device)
867706f2543Smrg                    continue;
868706f2543Smrg                if (!sd->button)
869706f2543Smrg                    continue;
870706f2543Smrg                for (i = 1; i <= sd->button->numButtons; i++)
871706f2543Smrg                    if (sd->button->map[i] == key &&
872706f2543Smrg                        button_is_down(sd, i, BUTTON_PROCESSED))
873706f2543Smrg                        return DONT_PROCESS;
874706f2543Smrg            }
875706f2543Smrg        }
876706f2543Smrg        set_button_up(device, key, BUTTON_PROCESSED);
877706f2543Smrg	if (device->valuator)
878706f2543Smrg	    device->valuator->motionHintWindow = NullWindow;
879706f2543Smrg        if (!b->map[key])
880706f2543Smrg            return DONT_PROCESS;
881706f2543Smrg        if (b->buttonsDown >= 1 && !--b->buttonsDown)
882706f2543Smrg	    b->motionMask = 0;
883706f2543Smrg	if (b->map[key] <= 5)
884706f2543Smrg	    b->state &= ~((Button1Mask >> 1) << b->map[key]);
885706f2543Smrg
886706f2543Smrg        /* Add state and motionMask to the filter for this event */
887706f2543Smrg        mask = DevicePointerMotionMask | b->state | b->motionMask;
888706f2543Smrg        SetMaskForEvent(device->id, mask, DeviceMotionNotify);
889706f2543Smrg        mask = PointerMotionMask | b->state | b->motionMask;
890706f2543Smrg        SetMaskForEvent(device->id, mask, MotionNotify);
891706f2543Smrg    } else if (event->type == ET_ProximityIn)
892706f2543Smrg	device->proximity->in_proximity = TRUE;
893706f2543Smrg    else if (event->type == ET_ProximityOut)
894706f2543Smrg	device->proximity->in_proximity = FALSE;
895706f2543Smrg
896706f2543Smrg    return DEFAULT;
897706f2543Smrg}
898706f2543Smrg
899706f2543Smrgstatic void
900706f2543SmrgProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
901706f2543Smrg{
902706f2543Smrg    GrabPtr grab = device->deviceGrab.grab;
903706f2543Smrg
904706f2543Smrg    if (grab)
905706f2543Smrg        DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE);
906706f2543Smrg    else { /* deliver to all root windows */
907706f2543Smrg        xEvent *xi;
908706f2543Smrg        int i;
909706f2543Smrg
910706f2543Smrg        i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi);
911706f2543Smrg        if (i != Success)
912706f2543Smrg        {
913706f2543Smrg            ErrorF("[Xi] %s: XI2 conversion failed in ProcessRawEvent (%d)\n",
914706f2543Smrg                    device->name, i);
915706f2543Smrg            return;
916706f2543Smrg        }
917706f2543Smrg
918706f2543Smrg        for (i = 0; i < screenInfo.numScreens; i++)
919706f2543Smrg            DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1,
920706f2543Smrg                                  GetEventFilter(device, xi), NULL);
921706f2543Smrg        free(xi);
922706f2543Smrg    }
923706f2543Smrg}
924706f2543Smrg
925706f2543Smrg/**
926706f2543Smrg * Main device event processing function.
927706f2543Smrg * Called from when processing the events from the event queue.
928706f2543Smrg *
929706f2543Smrg */
930706f2543Smrgvoid
931706f2543SmrgProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
932706f2543Smrg{
933706f2543Smrg    GrabPtr grab;
934706f2543Smrg    Bool deactivateDeviceGrab = FALSE;
935706f2543Smrg    int key = 0, rootX, rootY;
936706f2543Smrg    ButtonClassPtr b;
937706f2543Smrg    KeyClassPtr k;
938706f2543Smrg    ValuatorClassPtr v;
939706f2543Smrg    int ret = 0;
940706f2543Smrg    int state, i;
941706f2543Smrg    DeviceIntPtr mouse = NULL, kbd = NULL;
942706f2543Smrg    DeviceEvent *event = &ev->device_event;
943706f2543Smrg
944706f2543Smrg    CHECKEVENT(ev);
945706f2543Smrg
946706f2543Smrg    if (ev->any.type == ET_RawKeyPress ||
947706f2543Smrg        ev->any.type == ET_RawKeyRelease ||
948706f2543Smrg        ev->any.type == ET_RawButtonPress ||
949706f2543Smrg        ev->any.type == ET_RawButtonRelease ||
950706f2543Smrg        ev->any.type == ET_RawMotion)
951706f2543Smrg    {
952706f2543Smrg        ProcessRawEvent(&ev->raw_event, device);
953706f2543Smrg        return;
954706f2543Smrg    }
955706f2543Smrg
956706f2543Smrg    if (IsPointerDevice(device))
957706f2543Smrg    {
958706f2543Smrg        kbd = GetPairedDevice(device);
959706f2543Smrg        mouse = device;
960706f2543Smrg        if (!kbd->key) /* can happen with floating SDs */
961706f2543Smrg            kbd = NULL;
962706f2543Smrg    } else
963706f2543Smrg    {
964706f2543Smrg        mouse = GetPairedDevice(device);
965706f2543Smrg        kbd = device;
966706f2543Smrg        if (!mouse->valuator || !mouse->button) /* may be float. SDs */
967706f2543Smrg            mouse = NULL;
968706f2543Smrg    }
969706f2543Smrg
970706f2543Smrg    /* State needs to be assembled BEFORE the device is updated. */
971706f2543Smrg    state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0;
972706f2543Smrg    state |= (mouse && mouse->button) ? (mouse->button->state) : 0;
973706f2543Smrg
974706f2543Smrg    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
975706f2543Smrg        if (BitIsOn(mouse->button->down, i))
976706f2543Smrg            SetBit(event->buttons, i);
977706f2543Smrg
978706f2543Smrg    if (kbd && kbd->key)
979706f2543Smrg    {
980706f2543Smrg        XkbStatePtr state;
981706f2543Smrg        /* we need the state before the event happens */
982706f2543Smrg        if (event->type == ET_KeyPress || event->type == ET_KeyRelease)
983706f2543Smrg            state = &kbd->key->xkbInfo->prev_state;
984706f2543Smrg        else
985706f2543Smrg            state = &kbd->key->xkbInfo->state;
986706f2543Smrg
987706f2543Smrg        event->mods.base = state->base_mods;
988706f2543Smrg        event->mods.latched = state->latched_mods;
989706f2543Smrg        event->mods.locked = state->locked_mods;
990706f2543Smrg        event->mods.effective = state->mods;
991706f2543Smrg
992706f2543Smrg        event->group.base = state->base_group;
993706f2543Smrg        event->group.latched = state->latched_group;
994706f2543Smrg        event->group.locked = state->locked_group;
995706f2543Smrg        event->group.effective = state->group;
996706f2543Smrg    }
997706f2543Smrg
998706f2543Smrg    ret = UpdateDeviceState(device, event);
999706f2543Smrg    if (ret == DONT_PROCESS)
1000706f2543Smrg        return;
1001706f2543Smrg
1002706f2543Smrg    v = device->valuator;
1003706f2543Smrg    b = device->button;
1004706f2543Smrg    k = device->key;
1005706f2543Smrg
1006706f2543Smrg    if (IsMaster(device) || !device->u.master)
1007706f2543Smrg        CheckMotion(event, device);
1008706f2543Smrg
1009706f2543Smrg    switch (event->type)
1010706f2543Smrg    {
1011706f2543Smrg        case ET_Motion:
1012706f2543Smrg        case ET_ButtonPress:
1013706f2543Smrg        case ET_ButtonRelease:
1014706f2543Smrg        case ET_KeyPress:
1015706f2543Smrg        case ET_KeyRelease:
1016706f2543Smrg        case ET_ProximityIn:
1017706f2543Smrg        case ET_ProximityOut:
1018706f2543Smrg            GetSpritePosition(device, &rootX, &rootY);
1019706f2543Smrg            event->root_x = rootX;
1020706f2543Smrg            event->root_y = rootY;
1021706f2543Smrg            NoticeEventTime((InternalEvent*)event);
1022706f2543Smrg            event->corestate = state;
1023706f2543Smrg            key = event->detail.key;
1024706f2543Smrg            break;
1025706f2543Smrg        default:
1026706f2543Smrg            break;
1027706f2543Smrg    }
1028706f2543Smrg
1029706f2543Smrg    if (DeviceEventCallback && !syncEvents.playingEvents) {
1030706f2543Smrg	DeviceEventInfoRec eventinfo;
1031706f2543Smrg	SpritePtr pSprite = device->spriteInfo->sprite;
1032706f2543Smrg
1033706f2543Smrg	/* see comment in EnqueueEvents regarding the next three lines */
1034706f2543Smrg	if (ev->any.type == ET_Motion)
1035706f2543Smrg	    ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1036706f2543Smrg
1037706f2543Smrg	eventinfo.device = device;
1038706f2543Smrg	eventinfo.event = ev;
1039706f2543Smrg	CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
1040706f2543Smrg    }
1041706f2543Smrg
1042706f2543Smrg    grab = device->deviceGrab.grab;
1043706f2543Smrg
1044706f2543Smrg    switch(event->type)
1045706f2543Smrg    {
1046706f2543Smrg        case ET_KeyPress:
1047706f2543Smrg            if (!grab && CheckDeviceGrabs(device, event, 0)) {
1048706f2543Smrg                device->deviceGrab.activatingKey = key;
1049706f2543Smrg                return;
1050706f2543Smrg            }
1051706f2543Smrg            break;
1052706f2543Smrg        case ET_KeyRelease:
1053706f2543Smrg            if (grab && device->deviceGrab.fromPassiveGrab &&
1054706f2543Smrg                (key == device->deviceGrab.activatingKey) &&
1055706f2543Smrg                (device->deviceGrab.grab->type == KeyPress ||
1056706f2543Smrg                 device->deviceGrab.grab->type == DeviceKeyPress ||
1057706f2543Smrg                 device->deviceGrab.grab->type == XI_KeyPress))
1058706f2543Smrg                deactivateDeviceGrab = TRUE;
1059706f2543Smrg            break;
1060706f2543Smrg        case ET_ButtonPress:
1061706f2543Smrg            event->detail.button = b->map[key];
1062706f2543Smrg            if (!event->detail.button) { /* there's no button 0 */
1063706f2543Smrg                event->detail.button = key;
1064706f2543Smrg                return;
1065706f2543Smrg            }
1066706f2543Smrg            if (!grab && CheckDeviceGrabs(device, event, 0))
1067706f2543Smrg            {
1068706f2543Smrg                /* if a passive grab was activated, the event has been sent
1069706f2543Smrg                 * already */
1070706f2543Smrg                return;
1071706f2543Smrg            }
1072706f2543Smrg            break;
1073706f2543Smrg        case ET_ButtonRelease:
1074706f2543Smrg            event->detail.button = b->map[key];
1075706f2543Smrg            if (!event->detail.button) { /* there's no button 0 */
1076706f2543Smrg                event->detail.button = key;
1077706f2543Smrg                return;
1078706f2543Smrg            }
1079706f2543Smrg            if (grab && !b->buttonsDown &&
1080706f2543Smrg                device->deviceGrab.fromPassiveGrab &&
1081706f2543Smrg                (device->deviceGrab.grab->type == ButtonPress ||
1082706f2543Smrg                 device->deviceGrab.grab->type == DeviceButtonPress ||
1083706f2543Smrg                 device->deviceGrab.grab->type == XI_ButtonPress))
1084706f2543Smrg                deactivateDeviceGrab = TRUE;
1085706f2543Smrg        default:
1086706f2543Smrg            break;
1087706f2543Smrg    }
1088706f2543Smrg
1089706f2543Smrg
1090706f2543Smrg    if (grab)
1091706f2543Smrg        DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
1092706f2543Smrg    else if (device->focus && !IsPointerEvent((InternalEvent*)ev))
1093706f2543Smrg        DeliverFocusedEvent(device, (InternalEvent*)event,
1094706f2543Smrg                            GetSpriteWindow(device));
1095706f2543Smrg    else
1096706f2543Smrg        DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
1097706f2543Smrg                            NullGrab, NullWindow, device);
1098706f2543Smrg
1099706f2543Smrg    if (deactivateDeviceGrab == TRUE)
1100706f2543Smrg	(*device->deviceGrab.DeactivateGrab) (device);
1101706f2543Smrg    event->detail.key = key;
1102706f2543Smrg}
1103706f2543Smrg
1104706f2543Smrgint
1105706f2543SmrgInitProximityClassDeviceStruct(DeviceIntPtr dev)
1106706f2543Smrg{
1107706f2543Smrg    ProximityClassPtr proxc;
1108706f2543Smrg
1109706f2543Smrg    proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
1110706f2543Smrg    if (!proxc)
1111706f2543Smrg	return FALSE;
1112706f2543Smrg    proxc->sourceid = dev->id;
1113706f2543Smrg    proxc->in_proximity = TRUE;
1114706f2543Smrg    dev->proximity = proxc;
1115706f2543Smrg    return TRUE;
1116706f2543Smrg}
1117706f2543Smrg
1118706f2543Smrg/**
1119706f2543Smrg * Initialise the device's valuators. The memory must already be allocated,
1120706f2543Smrg * this function merely inits the matching axis (specified through axnum) to
1121706f2543Smrg * sane values.
1122706f2543Smrg *
1123706f2543Smrg * It is a condition that (minval < maxval).
1124706f2543Smrg *
1125706f2543Smrg * @see InitValuatorClassDeviceStruct
1126706f2543Smrg */
1127706f2543Smrgvoid
1128706f2543SmrgInitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
1129706f2543Smrg		       int resolution, int min_res, int max_res, int mode)
1130706f2543Smrg{
1131706f2543Smrg    AxisInfoPtr ax;
1132706f2543Smrg
1133706f2543Smrg    if (!dev || !dev->valuator || minval > maxval)
1134706f2543Smrg        return;
1135706f2543Smrg    if (axnum >= dev->valuator->numAxes)
1136706f2543Smrg        return;
1137706f2543Smrg
1138706f2543Smrg    ax = dev->valuator->axes + axnum;
1139706f2543Smrg
1140706f2543Smrg    ax->min_value = minval;
1141706f2543Smrg    ax->max_value = maxval;
1142706f2543Smrg    ax->resolution = resolution;
1143706f2543Smrg    ax->min_resolution = min_res;
1144706f2543Smrg    ax->max_resolution = max_res;
1145706f2543Smrg    ax->label = label;
1146706f2543Smrg    ax->mode = mode;
1147706f2543Smrg
1148706f2543Smrg    if (mode & OutOfProximity)
1149706f2543Smrg        dev->proximity->in_proximity = FALSE;
1150706f2543Smrg}
1151706f2543Smrg
1152706f2543Smrgstatic void
1153706f2543SmrgFixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
1154706f2543Smrg		     ButtonClassPtr b, ValuatorClassPtr v, int first)
1155706f2543Smrg{
1156706f2543Smrg    ev->type = DeviceStateNotify;
1157706f2543Smrg    ev->deviceid = dev->id;
1158706f2543Smrg    ev->time = currentTime.milliseconds;
1159706f2543Smrg    ev->classes_reported = 0;
1160706f2543Smrg    ev->num_keys = 0;
1161706f2543Smrg    ev->num_buttons = 0;
1162706f2543Smrg    ev->num_valuators = 0;
1163706f2543Smrg
1164706f2543Smrg    if (b) {
1165706f2543Smrg	ev->classes_reported |= (1 << ButtonClass);
1166706f2543Smrg	ev->num_buttons = b->numButtons;
1167706f2543Smrg	memcpy((char*)ev->buttons, (char*)b->down, 4);
1168706f2543Smrg    } else if (k) {
1169706f2543Smrg	ev->classes_reported |= (1 << KeyClass);
1170706f2543Smrg	ev->num_keys = k->xkbInfo->desc->max_key_code -
1171706f2543Smrg                       k->xkbInfo->desc->min_key_code;
1172706f2543Smrg	memmove((char *)&ev->keys[0], (char *)k->down, 4);
1173706f2543Smrg    }
1174706f2543Smrg    if (v) {
1175706f2543Smrg	int nval = v->numAxes - first;
1176706f2543Smrg
1177706f2543Smrg	ev->classes_reported |= (1 << ValuatorClass);
1178706f2543Smrg	ev->classes_reported |= valuator_get_mode(dev, 0) << ModeBitsShift;
1179706f2543Smrg	ev->num_valuators = nval < 3 ? nval : 3;
1180706f2543Smrg	switch (ev->num_valuators) {
1181706f2543Smrg	case 3:
1182706f2543Smrg	    ev->valuator2 = v->axisVal[first + 2];
1183706f2543Smrg	case 2:
1184706f2543Smrg	    ev->valuator1 = v->axisVal[first + 1];
1185706f2543Smrg	case 1:
1186706f2543Smrg	    ev->valuator0 = v->axisVal[first];
1187706f2543Smrg	    break;
1188706f2543Smrg	}
1189706f2543Smrg    }
1190706f2543Smrg}
1191706f2543Smrg
1192706f2543Smrgstatic void
1193706f2543SmrgFixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
1194706f2543Smrg		  int first)
1195706f2543Smrg{
1196706f2543Smrg    int nval = v->numAxes - first;
1197706f2543Smrg
1198706f2543Smrg    ev->type = DeviceValuator;
1199706f2543Smrg    ev->deviceid = dev->id;
1200706f2543Smrg    ev->num_valuators = nval < 3 ? nval : 3;
1201706f2543Smrg    ev->first_valuator = first;
1202706f2543Smrg    switch (ev->num_valuators) {
1203706f2543Smrg    case 3:
1204706f2543Smrg	ev->valuator2 = v->axisVal[first + 2];
1205706f2543Smrg    case 2:
1206706f2543Smrg	ev->valuator1 = v->axisVal[first + 1];
1207706f2543Smrg    case 1:
1208706f2543Smrg	ev->valuator0 = v->axisVal[first];
1209706f2543Smrg	break;
1210706f2543Smrg    }
1211706f2543Smrg    first += ev->num_valuators;
1212706f2543Smrg}
1213706f2543Smrg
1214706f2543Smrgvoid
1215706f2543SmrgDeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
1216706f2543Smrg		 WindowPtr pWin)
1217706f2543Smrg{
1218706f2543Smrg    deviceFocus event;
1219706f2543Smrg    xXIFocusInEvent *xi2event;
1220706f2543Smrg    DeviceIntPtr mouse;
1221706f2543Smrg    int btlen, len, i;
1222706f2543Smrg
1223706f2543Smrg    mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev;
1224706f2543Smrg
1225706f2543Smrg    /* XI 2 event */
1226706f2543Smrg    btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
1227706f2543Smrg    btlen = bytes_to_int32(btlen);
1228706f2543Smrg    len = sizeof(xXIFocusInEvent) + btlen * 4;
1229706f2543Smrg
1230706f2543Smrg    xi2event = calloc(1, len);
1231706f2543Smrg    xi2event->type         = GenericEvent;
1232706f2543Smrg    xi2event->extension    = IReqCode;
1233706f2543Smrg    xi2event->evtype       = type;
1234706f2543Smrg    xi2event->length       = bytes_to_int32(len - sizeof(xEvent));
1235706f2543Smrg    xi2event->buttons_len  = btlen;
1236706f2543Smrg    xi2event->detail       = detail;
1237706f2543Smrg    xi2event->time         = currentTime.milliseconds;
1238706f2543Smrg    xi2event->deviceid     = dev->id;
1239706f2543Smrg    xi2event->sourceid     = dev->id; /* a device doesn't change focus by itself */
1240706f2543Smrg    xi2event->mode         = mode;
1241706f2543Smrg    xi2event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
1242706f2543Smrg    xi2event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
1243706f2543Smrg
1244706f2543Smrg    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
1245706f2543Smrg        if (BitIsOn(mouse->button->down, i))
1246706f2543Smrg            SetBit(&xi2event[1], i);
1247706f2543Smrg
1248706f2543Smrg    if (dev->key)
1249706f2543Smrg    {
1250706f2543Smrg        xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
1251706f2543Smrg        xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
1252706f2543Smrg        xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
1253706f2543Smrg        xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
1254706f2543Smrg
1255706f2543Smrg        xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
1256706f2543Smrg        xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
1257706f2543Smrg        xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
1258706f2543Smrg        xi2event->group.effective_group = dev->key->xkbInfo->state.group;
1259706f2543Smrg    }
1260706f2543Smrg
1261706f2543Smrg    FixUpEventFromWindow(dev->spriteInfo->sprite, (xEvent*)xi2event, pWin,
1262706f2543Smrg                         None, FALSE);
1263706f2543Smrg
1264706f2543Smrg    DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
1265706f2543Smrg                          GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
1266706f2543Smrg
1267706f2543Smrg    free(xi2event);
1268706f2543Smrg
1269706f2543Smrg    /* XI 1.x event */
1270706f2543Smrg    event.deviceid = dev->id;
1271706f2543Smrg    event.mode = mode;
1272706f2543Smrg    event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
1273706f2543Smrg    event.detail = detail;
1274706f2543Smrg    event.window = pWin->drawable.id;
1275706f2543Smrg    event.time = currentTime.milliseconds;
1276706f2543Smrg
1277706f2543Smrg    DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
1278706f2543Smrg				DeviceFocusChangeMask, NullGrab);
1279706f2543Smrg
1280706f2543Smrg    if ((event.type == DeviceFocusIn) &&
1281706f2543Smrg	(wOtherInputMasks(pWin)) &&
1282706f2543Smrg	(wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
1283706f2543Smrg    {
1284706f2543Smrg	int evcount = 1;
1285706f2543Smrg	deviceStateNotify *ev, *sev;
1286706f2543Smrg	deviceKeyStateNotify *kev;
1287706f2543Smrg	deviceButtonStateNotify *bev;
1288706f2543Smrg
1289706f2543Smrg	KeyClassPtr k;
1290706f2543Smrg	ButtonClassPtr b;
1291706f2543Smrg	ValuatorClassPtr v;
1292706f2543Smrg	int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
1293706f2543Smrg
1294706f2543Smrg	if ((b = dev->button) != NULL) {
1295706f2543Smrg	    nbuttons = b->numButtons;
1296706f2543Smrg	    if (nbuttons > 32)
1297706f2543Smrg		evcount++;
1298706f2543Smrg	}
1299706f2543Smrg	if ((k = dev->key) != NULL) {
1300706f2543Smrg	    nkeys = k->xkbInfo->desc->max_key_code -
1301706f2543Smrg                    k->xkbInfo->desc->min_key_code;
1302706f2543Smrg	    if (nkeys > 32)
1303706f2543Smrg		evcount++;
1304706f2543Smrg	    if (nbuttons > 0) {
1305706f2543Smrg		evcount++;
1306706f2543Smrg	    }
1307706f2543Smrg	}
1308706f2543Smrg	if ((v = dev->valuator) != NULL) {
1309706f2543Smrg	    nval = v->numAxes;
1310706f2543Smrg
1311706f2543Smrg	    if (nval > 3)
1312706f2543Smrg		evcount++;
1313706f2543Smrg	    if (nval > 6) {
1314706f2543Smrg		if (!(k && b))
1315706f2543Smrg		    evcount++;
1316706f2543Smrg		if (nval > 9)
1317706f2543Smrg		    evcount += ((nval - 7) / 3);
1318706f2543Smrg	    }
1319706f2543Smrg	}
1320706f2543Smrg
1321706f2543Smrg	sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
1322706f2543Smrg	FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
1323706f2543Smrg
1324706f2543Smrg	if (b != NULL) {
1325706f2543Smrg	    FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
1326706f2543Smrg	    first += 3;
1327706f2543Smrg	    nval -= 3;
1328706f2543Smrg	    if (nbuttons > 32) {
1329706f2543Smrg		(ev - 1)->deviceid |= MORE_EVENTS;
1330706f2543Smrg		bev = (deviceButtonStateNotify *) ev++;
1331706f2543Smrg		bev->type = DeviceButtonStateNotify;
1332706f2543Smrg		bev->deviceid = dev->id;
1333706f2543Smrg		memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
1334706f2543Smrg	    }
1335706f2543Smrg	    if (nval > 0) {
1336706f2543Smrg		(ev - 1)->deviceid |= MORE_EVENTS;
1337706f2543Smrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1338706f2543Smrg		first += 3;
1339706f2543Smrg		nval -= 3;
1340706f2543Smrg	    }
1341706f2543Smrg	}
1342706f2543Smrg
1343706f2543Smrg	if (k != NULL) {
1344706f2543Smrg	    FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
1345706f2543Smrg	    first += 3;
1346706f2543Smrg	    nval -= 3;
1347706f2543Smrg	    if (nkeys > 32) {
1348706f2543Smrg		(ev - 1)->deviceid |= MORE_EVENTS;
1349706f2543Smrg		kev = (deviceKeyStateNotify *) ev++;
1350706f2543Smrg		kev->type = DeviceKeyStateNotify;
1351706f2543Smrg		kev->deviceid = dev->id;
1352706f2543Smrg		memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
1353706f2543Smrg	    }
1354706f2543Smrg	    if (nval > 0) {
1355706f2543Smrg		(ev - 1)->deviceid |= MORE_EVENTS;
1356706f2543Smrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1357706f2543Smrg		first += 3;
1358706f2543Smrg		nval -= 3;
1359706f2543Smrg	    }
1360706f2543Smrg	}
1361706f2543Smrg
1362706f2543Smrg	while (nval > 0) {
1363706f2543Smrg	    FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
1364706f2543Smrg	    first += 3;
1365706f2543Smrg	    nval -= 3;
1366706f2543Smrg	    if (nval > 0) {
1367706f2543Smrg		(ev - 1)->deviceid |= MORE_EVENTS;
1368706f2543Smrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1369706f2543Smrg		first += 3;
1370706f2543Smrg		nval -= 3;
1371706f2543Smrg	    }
1372706f2543Smrg	}
1373706f2543Smrg
1374706f2543Smrg	DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
1375706f2543Smrg				    DeviceStateNotifyMask, NullGrab);
1376706f2543Smrg	free(sev);
1377706f2543Smrg    }
1378706f2543Smrg}
1379706f2543Smrg
1380706f2543Smrgint
1381706f2543SmrgCheckGrabValues(ClientPtr client, GrabParameters* param)
1382706f2543Smrg{
1383706f2543Smrg    if (param->grabtype != GRABTYPE_CORE &&
1384706f2543Smrg        param->grabtype != GRABTYPE_XI &&
1385706f2543Smrg        param->grabtype != GRABTYPE_XI2)
1386706f2543Smrg    {
1387706f2543Smrg        ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
1388706f2543Smrg        return BadImplementation;
1389706f2543Smrg    }
1390706f2543Smrg
1391706f2543Smrg    if ((param->this_device_mode != GrabModeSync) &&
1392706f2543Smrg	(param->this_device_mode != GrabModeAsync)) {
1393706f2543Smrg	client->errorValue = param->this_device_mode;
1394706f2543Smrg	return BadValue;
1395706f2543Smrg    }
1396706f2543Smrg    if ((param->other_devices_mode != GrabModeSync) &&
1397706f2543Smrg	(param->other_devices_mode != GrabModeAsync)) {
1398706f2543Smrg	client->errorValue = param->other_devices_mode;
1399706f2543Smrg	return BadValue;
1400706f2543Smrg    }
1401706f2543Smrg
1402706f2543Smrg    if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
1403706f2543Smrg        (param->modifiers & ~AllModifiersMask)) {
1404706f2543Smrg	client->errorValue = param->modifiers;
1405706f2543Smrg	return BadValue;
1406706f2543Smrg    }
1407706f2543Smrg
1408706f2543Smrg    if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
1409706f2543Smrg	client->errorValue = param->ownerEvents;
1410706f2543Smrg	return BadValue;
1411706f2543Smrg    }
1412706f2543Smrg    return Success;
1413706f2543Smrg}
1414706f2543Smrg
1415706f2543Smrgint
1416706f2543SmrgGrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
1417706f2543Smrg           int button, GrabParameters *param, GrabType grabtype,
1418706f2543Smrg	   GrabMask *mask)
1419706f2543Smrg{
1420706f2543Smrg    WindowPtr pWin, confineTo;
1421706f2543Smrg    CursorPtr cursor;
1422706f2543Smrg    GrabPtr grab;
1423706f2543Smrg    int rc, type = -1;
1424706f2543Smrg    Mask access_mode = DixGrabAccess;
1425706f2543Smrg
1426706f2543Smrg    rc = CheckGrabValues(client, param);
1427706f2543Smrg    if (rc != Success)
1428706f2543Smrg	return rc;
1429706f2543Smrg    if (param->confineTo == None)
1430706f2543Smrg	confineTo = NullWindow;
1431706f2543Smrg    else {
1432706f2543Smrg	rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
1433706f2543Smrg	if (rc != Success)
1434706f2543Smrg	    return rc;
1435706f2543Smrg    }
1436706f2543Smrg    if (param->cursor == None)
1437706f2543Smrg	cursor = NullCursor;
1438706f2543Smrg    else {
1439706f2543Smrg	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
1440706f2543Smrg				     RT_CURSOR, client, DixUseAccess);
1441706f2543Smrg	if (rc != Success)
1442706f2543Smrg	{
1443706f2543Smrg	    client->errorValue = param->cursor;
1444706f2543Smrg	    return rc;
1445706f2543Smrg	}
1446706f2543Smrg	access_mode |= DixForceAccess;
1447706f2543Smrg    }
1448706f2543Smrg    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1449706f2543Smrg	access_mode |= DixFreezeAccess;
1450706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1451706f2543Smrg    if (rc != Success)
1452706f2543Smrg	return rc;
1453706f2543Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1454706f2543Smrg    if (rc != Success)
1455706f2543Smrg	return rc;
1456706f2543Smrg
1457706f2543Smrg    if (grabtype == GRABTYPE_XI)
1458706f2543Smrg        type = DeviceButtonPress;
1459706f2543Smrg    else if (grabtype == GRABTYPE_XI2)
1460706f2543Smrg        type = XI_ButtonPress;
1461706f2543Smrg
1462706f2543Smrg    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
1463706f2543Smrg                      mask, param, type, button, confineTo, cursor);
1464706f2543Smrg    if (!grab)
1465706f2543Smrg	return BadAlloc;
1466706f2543Smrg    return AddPassiveGrabToList(client, grab);
1467706f2543Smrg}
1468706f2543Smrg
1469706f2543Smrg/**
1470706f2543Smrg * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If
1471706f2543Smrg * grabtype is GRABTYPE_XI2, the key is a keysym.
1472706f2543Smrg */
1473706f2543Smrgint
1474706f2543SmrgGrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
1475706f2543Smrg        int key, GrabParameters *param, GrabType grabtype, GrabMask *mask)
1476706f2543Smrg{
1477706f2543Smrg    WindowPtr pWin;
1478706f2543Smrg    GrabPtr grab;
1479706f2543Smrg    KeyClassPtr k = dev->key;
1480706f2543Smrg    Mask access_mode = DixGrabAccess;
1481706f2543Smrg    int rc, type = -1;
1482706f2543Smrg
1483706f2543Smrg    rc = CheckGrabValues(client, param);
1484706f2543Smrg    if (rc != Success)
1485706f2543Smrg        return rc;
1486706f2543Smrg    if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL)
1487706f2543Smrg	return BadMatch;
1488706f2543Smrg    if (grabtype == GRABTYPE_XI)
1489706f2543Smrg    {
1490706f2543Smrg        if ((key > k->xkbInfo->desc->max_key_code ||
1491706f2543Smrg                    key < k->xkbInfo->desc->min_key_code)
1492706f2543Smrg                && (key != AnyKey)) {
1493706f2543Smrg            client->errorValue = key;
1494706f2543Smrg            return BadValue;
1495706f2543Smrg        }
1496706f2543Smrg        type = DeviceKeyPress;
1497706f2543Smrg    } else if (grabtype == GRABTYPE_XI2)
1498706f2543Smrg        type = XI_KeyPress;
1499706f2543Smrg
1500706f2543Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1501706f2543Smrg    if (rc != Success)
1502706f2543Smrg	return rc;
1503706f2543Smrg    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1504706f2543Smrg	access_mode |= DixFreezeAccess;
1505706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1506706f2543Smrg    if (rc != Success)
1507706f2543Smrg	return rc;
1508706f2543Smrg
1509706f2543Smrg    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
1510706f2543Smrg                      mask, param, type, key, NULL, NULL);
1511706f2543Smrg    if (!grab)
1512706f2543Smrg	return BadAlloc;
1513706f2543Smrg    return AddPassiveGrabToList(client, grab);
1514706f2543Smrg}
1515706f2543Smrg
1516706f2543Smrg/* Enter/FocusIn grab */
1517706f2543Smrgint
1518706f2543SmrgGrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
1519706f2543Smrg           GrabParameters *param, GrabMask *mask)
1520706f2543Smrg{
1521706f2543Smrg    WindowPtr pWin;
1522706f2543Smrg    CursorPtr cursor;
1523706f2543Smrg    GrabPtr grab;
1524706f2543Smrg    Mask access_mode = DixGrabAccess;
1525706f2543Smrg    int rc;
1526706f2543Smrg
1527706f2543Smrg    rc = CheckGrabValues(client, param);
1528706f2543Smrg    if (rc != Success)
1529706f2543Smrg        return rc;
1530706f2543Smrg
1531706f2543Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1532706f2543Smrg    if (rc != Success)
1533706f2543Smrg	return rc;
1534706f2543Smrg    if (param->cursor == None)
1535706f2543Smrg	cursor = NullCursor;
1536706f2543Smrg    else {
1537706f2543Smrg	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
1538706f2543Smrg				     RT_CURSOR, client, DixUseAccess);
1539706f2543Smrg	if (rc != Success)
1540706f2543Smrg	{
1541706f2543Smrg	    client->errorValue = param->cursor;
1542706f2543Smrg	    return rc;
1543706f2543Smrg	}
1544706f2543Smrg	access_mode |= DixForceAccess;
1545706f2543Smrg    }
1546706f2543Smrg    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1547706f2543Smrg	access_mode |= DixFreezeAccess;
1548706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1549706f2543Smrg    if (rc != Success)
1550706f2543Smrg	return rc;
1551706f2543Smrg
1552706f2543Smrg    grab = CreateGrab(client->index, dev, dev, pWin, GRABTYPE_XI2,
1553706f2543Smrg                      mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
1554706f2543Smrg                      0, NULL, cursor);
1555706f2543Smrg
1556706f2543Smrg    if (!grab)
1557706f2543Smrg        return BadAlloc;
1558706f2543Smrg
1559706f2543Smrg    return AddPassiveGrabToList(client, grab);
1560706f2543Smrg}
1561706f2543Smrg
1562706f2543Smrgint
1563706f2543SmrgSelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
1564706f2543Smrg		Mask mask, Mask exclusivemasks)
1565706f2543Smrg{
1566706f2543Smrg    int mskidx = dev->id;
1567706f2543Smrg    int i, ret;
1568706f2543Smrg    Mask check;
1569706f2543Smrg    InputClientsPtr others;
1570706f2543Smrg
1571706f2543Smrg    check = (mask & exclusivemasks);
1572706f2543Smrg    if (wOtherInputMasks(pWin)) {
1573706f2543Smrg	if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {	/* It is illegal for two different
1574706f2543Smrg									 * clients to select on any of the
1575706f2543Smrg									 * events for maskcheck. However,
1576706f2543Smrg									 * it is OK, for some client to
1577706f2543Smrg									 * continue selecting on one of those
1578706f2543Smrg									 * events.  */
1579706f2543Smrg	    for (others = wOtherInputMasks(pWin)->inputClients; others;
1580706f2543Smrg		 others = others->next) {
1581706f2543Smrg		if (!SameClient(others, client) && (check &
1582706f2543Smrg						    others->mask[mskidx]))
1583706f2543Smrg		    return BadAccess;
1584706f2543Smrg	    }
1585706f2543Smrg	}
1586706f2543Smrg	for (others = wOtherInputMasks(pWin)->inputClients; others;
1587706f2543Smrg	     others = others->next) {
1588706f2543Smrg	    if (SameClient(others, client)) {
1589706f2543Smrg		check = others->mask[mskidx];
1590706f2543Smrg		others->mask[mskidx] = mask;
1591706f2543Smrg		if (mask == 0) {
1592706f2543Smrg		    for (i = 0; i < EMASKSIZE; i++)
1593706f2543Smrg			if (i != mskidx && others->mask[i] != 0)
1594706f2543Smrg			    break;
1595706f2543Smrg		    if (i == EMASKSIZE) {
1596706f2543Smrg			RecalculateDeviceDeliverableEvents(pWin);
1597706f2543Smrg			if (ShouldFreeInputMasks(pWin, FALSE))
1598706f2543Smrg			    FreeResource(others->resource, RT_NONE);
1599706f2543Smrg			return Success;
1600706f2543Smrg		    }
1601706f2543Smrg		}
1602706f2543Smrg		goto maskSet;
1603706f2543Smrg	    }
1604706f2543Smrg	}
1605706f2543Smrg    }
1606706f2543Smrg    check = 0;
1607706f2543Smrg    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
1608706f2543Smrg	return ret;
1609706f2543Smrg  maskSet:
1610706f2543Smrg    if (dev->valuator)
1611706f2543Smrg	if ((dev->valuator->motionHintWindow == pWin) &&
1612706f2543Smrg	    (mask & DevicePointerMotionHintMask) &&
1613706f2543Smrg	    !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
1614706f2543Smrg	    dev->valuator->motionHintWindow = NullWindow;
1615706f2543Smrg    RecalculateDeviceDeliverableEvents(pWin);
1616706f2543Smrg    return Success;
1617706f2543Smrg}
1618706f2543Smrg
1619706f2543Smrgint
1620706f2543SmrgAddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
1621706f2543Smrg{
1622706f2543Smrg    InputClientsPtr others;
1623706f2543Smrg
1624706f2543Smrg    if (!pWin->optional && !MakeWindowOptional(pWin))
1625706f2543Smrg	return BadAlloc;
1626706f2543Smrg    others = calloc(1, sizeof(InputClients));
1627706f2543Smrg    if (!others)
1628706f2543Smrg	return BadAlloc;
1629706f2543Smrg    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
1630706f2543Smrg	goto bail;
1631706f2543Smrg    others->mask[mskidx] = mask;
1632706f2543Smrg    others->resource = FakeClientID(client->index);
1633706f2543Smrg    others->next = pWin->optional->inputMasks->inputClients;
1634706f2543Smrg    pWin->optional->inputMasks->inputClients = others;
1635706f2543Smrg    if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
1636706f2543Smrg	goto bail;
1637706f2543Smrg    return Success;
1638706f2543Smrg
1639706f2543Smrgbail:
1640706f2543Smrg    free(others);
1641706f2543Smrg    return BadAlloc;
1642706f2543Smrg}
1643706f2543Smrg
1644706f2543Smrgstatic Bool
1645706f2543SmrgMakeInputMasks(WindowPtr pWin)
1646706f2543Smrg{
1647706f2543Smrg    struct _OtherInputMasks *imasks;
1648706f2543Smrg
1649706f2543Smrg    imasks = calloc(1, sizeof(struct _OtherInputMasks));
1650706f2543Smrg    if (!imasks)
1651706f2543Smrg	return FALSE;
1652706f2543Smrg    pWin->optional->inputMasks = imasks;
1653706f2543Smrg    return TRUE;
1654706f2543Smrg}
1655706f2543Smrg
1656706f2543Smrgvoid
1657706f2543SmrgRecalculateDeviceDeliverableEvents(WindowPtr pWin)
1658706f2543Smrg{
1659706f2543Smrg    InputClientsPtr others;
1660706f2543Smrg    struct _OtherInputMasks *inputMasks;	/* default: NULL */
1661706f2543Smrg    WindowPtr pChild, tmp;
1662706f2543Smrg    int i, j;
1663706f2543Smrg
1664706f2543Smrg    pChild = pWin;
1665706f2543Smrg    while (1) {
1666706f2543Smrg	if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
1667706f2543Smrg            for (i = 0; i < EMASKSIZE; i++)
1668706f2543Smrg                memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i]));
1669706f2543Smrg	    for (others = inputMasks->inputClients; others;
1670706f2543Smrg		 others = others->next) {
1671706f2543Smrg		for (i = 0; i < EMASKSIZE; i++)
1672706f2543Smrg		    inputMasks->inputEvents[i] |= others->mask[i];
1673706f2543Smrg                for (i = 0; i < EMASKSIZE; i++)
1674706f2543Smrg                    for (j = 0; j < XI2MASKSIZE; j++)
1675706f2543Smrg                        inputMasks->xi2mask[i][j] |= others->xi2mask[i][j];
1676706f2543Smrg	    }
1677706f2543Smrg	    for (i = 0; i < EMASKSIZE; i++)
1678706f2543Smrg		inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
1679706f2543Smrg	    for (tmp = pChild->parent; tmp; tmp = tmp->parent)
1680706f2543Smrg		if (wOtherInputMasks(tmp))
1681706f2543Smrg		    for (i = 0; i < EMASKSIZE; i++)
1682706f2543Smrg			inputMasks->deliverableEvents[i] |=
1683706f2543Smrg			    (wOtherInputMasks(tmp)->deliverableEvents[i]
1684706f2543Smrg			     & ~inputMasks->
1685706f2543Smrg			     dontPropagateMask[i] & PropagateMask[i]);
1686706f2543Smrg	}
1687706f2543Smrg	if (pChild->firstChild) {
1688706f2543Smrg	    pChild = pChild->firstChild;
1689706f2543Smrg	    continue;
1690706f2543Smrg	}
1691706f2543Smrg	while (!pChild->nextSib && (pChild != pWin))
1692706f2543Smrg	    pChild = pChild->parent;
1693706f2543Smrg	if (pChild == pWin)
1694706f2543Smrg	    break;
1695706f2543Smrg	pChild = pChild->nextSib;
1696706f2543Smrg    }
1697706f2543Smrg}
1698706f2543Smrg
1699706f2543Smrgint
1700706f2543SmrgInputClientGone(WindowPtr pWin, XID id)
1701706f2543Smrg{
1702706f2543Smrg    InputClientsPtr other, prev;
1703706f2543Smrg
1704706f2543Smrg    if (!wOtherInputMasks(pWin))
1705706f2543Smrg	return Success;
1706706f2543Smrg    prev = 0;
1707706f2543Smrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
1708706f2543Smrg	 other = other->next) {
1709706f2543Smrg	if (other->resource == id) {
1710706f2543Smrg	    if (prev) {
1711706f2543Smrg		prev->next = other->next;
1712706f2543Smrg		free(other);
1713706f2543Smrg	    } else if (!(other->next)) {
1714706f2543Smrg		if (ShouldFreeInputMasks(pWin, TRUE)) {
1715706f2543Smrg		    wOtherInputMasks(pWin)->inputClients = other->next;
1716706f2543Smrg		    free(wOtherInputMasks(pWin));
1717706f2543Smrg		    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
1718706f2543Smrg		    CheckWindowOptionalNeed(pWin);
1719706f2543Smrg		    free(other);
1720706f2543Smrg		} else {
1721706f2543Smrg		    other->resource = FakeClientID(0);
1722706f2543Smrg		    if (!AddResource(other->resource, RT_INPUTCLIENT,
1723706f2543Smrg				     (pointer) pWin))
1724706f2543Smrg			return BadAlloc;
1725706f2543Smrg		}
1726706f2543Smrg	    } else {
1727706f2543Smrg		wOtherInputMasks(pWin)->inputClients = other->next;
1728706f2543Smrg		free(other);
1729706f2543Smrg	    }
1730706f2543Smrg	    RecalculateDeviceDeliverableEvents(pWin);
1731706f2543Smrg	    return Success;
1732706f2543Smrg	}
1733706f2543Smrg	prev = other;
1734706f2543Smrg    }
1735706f2543Smrg    FatalError("client not on device event list");
1736706f2543Smrg}
1737706f2543Smrg
1738706f2543Smrgint
1739706f2543SmrgSendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
1740706f2543Smrg	  xEvent * ev, Mask mask, int count)
1741706f2543Smrg{
1742706f2543Smrg    WindowPtr pWin;
1743706f2543Smrg    WindowPtr effectiveFocus = NullWindow;	/* only set if dest==InputFocus */
1744706f2543Smrg    WindowPtr spriteWin = GetSpriteWindow(d);
1745706f2543Smrg
1746706f2543Smrg    if (dest == PointerWindow)
1747706f2543Smrg	pWin = spriteWin;
1748706f2543Smrg    else if (dest == InputFocus) {
1749706f2543Smrg	WindowPtr inputFocus;
1750706f2543Smrg
1751706f2543Smrg	if (!d->focus)
1752706f2543Smrg	    inputFocus = spriteWin;
1753706f2543Smrg	else
1754706f2543Smrg	    inputFocus = d->focus->win;
1755706f2543Smrg
1756706f2543Smrg	if (inputFocus == FollowKeyboardWin)
1757706f2543Smrg	    inputFocus = inputInfo.keyboard->focus->win;
1758706f2543Smrg
1759706f2543Smrg	if (inputFocus == NoneWin)
1760706f2543Smrg	    return Success;
1761706f2543Smrg
1762706f2543Smrg	/* If the input focus is PointerRootWin, send the event to where
1763706f2543Smrg	 * the pointer is if possible, then perhaps propogate up to root. */
1764706f2543Smrg	if (inputFocus == PointerRootWin)
1765706f2543Smrg	    inputFocus = GetCurrentRootWindow(d);
1766706f2543Smrg
1767706f2543Smrg	if (IsParent(inputFocus, spriteWin)) {
1768706f2543Smrg	    effectiveFocus = inputFocus;
1769706f2543Smrg	    pWin = spriteWin;
1770706f2543Smrg	} else
1771706f2543Smrg	    effectiveFocus = pWin = inputFocus;
1772706f2543Smrg    } else
1773706f2543Smrg	dixLookupWindow(&pWin, dest, client, DixSendAccess);
1774706f2543Smrg    if (!pWin)
1775706f2543Smrg	return BadWindow;
1776706f2543Smrg    if ((propagate != xFalse) && (propagate != xTrue)) {
1777706f2543Smrg	client->errorValue = propagate;
1778706f2543Smrg	return BadValue;
1779706f2543Smrg    }
1780706f2543Smrg    ev->u.u.type |= 0x80;
1781706f2543Smrg    if (propagate) {
1782706f2543Smrg	for (; pWin; pWin = pWin->parent) {
1783706f2543Smrg	    if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
1784706f2543Smrg		return Success;
1785706f2543Smrg	    if (pWin == effectiveFocus)
1786706f2543Smrg		return Success;
1787706f2543Smrg	    if (wOtherInputMasks(pWin))
1788706f2543Smrg		mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
1789706f2543Smrg	    if (!mask)
1790706f2543Smrg		break;
1791706f2543Smrg	}
1792706f2543Smrg    } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
1793706f2543Smrg	DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
1794706f2543Smrg    return Success;
1795706f2543Smrg}
1796706f2543Smrg
1797706f2543Smrgint
1798706f2543SmrgSetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
1799706f2543Smrg{
1800706f2543Smrg    int i;
1801706f2543Smrg    ButtonClassPtr b = dev->button;
1802706f2543Smrg
1803706f2543Smrg    if (b == NULL)
1804706f2543Smrg	return BadMatch;
1805706f2543Smrg
1806706f2543Smrg    if (nElts != b->numButtons) {
1807706f2543Smrg	client->errorValue = nElts;
1808706f2543Smrg	return BadValue;
1809706f2543Smrg    }
1810706f2543Smrg    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
1811706f2543Smrg	return BadValue;
1812706f2543Smrg    for (i = 0; i < nElts; i++)
1813706f2543Smrg	if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
1814706f2543Smrg	    return MappingBusy;
1815706f2543Smrg    for (i = 0; i < nElts; i++)
1816706f2543Smrg	b->map[i + 1] = map[i];
1817706f2543Smrg    return Success;
1818706f2543Smrg}
1819706f2543Smrg
1820706f2543Smrgint
1821706f2543SmrgChangeKeyMapping(ClientPtr client,
1822706f2543Smrg		 DeviceIntPtr dev,
1823706f2543Smrg		 unsigned len,
1824706f2543Smrg		 int type,
1825706f2543Smrg		 KeyCode firstKeyCode,
1826706f2543Smrg		 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
1827706f2543Smrg{
1828706f2543Smrg    KeySymsRec keysyms;
1829706f2543Smrg    KeyClassPtr k = dev->key;
1830706f2543Smrg
1831706f2543Smrg    if (k == NULL)
1832706f2543Smrg	return BadMatch;
1833706f2543Smrg
1834706f2543Smrg    if (len != (keyCodes * keySymsPerKeyCode))
1835706f2543Smrg	return BadLength;
1836706f2543Smrg
1837706f2543Smrg    if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
1838706f2543Smrg	(firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
1839706f2543Smrg	client->errorValue = firstKeyCode;
1840706f2543Smrg	return BadValue;
1841706f2543Smrg    }
1842706f2543Smrg    if (keySymsPerKeyCode == 0) {
1843706f2543Smrg	client->errorValue = 0;
1844706f2543Smrg	return BadValue;
1845706f2543Smrg    }
1846706f2543Smrg    keysyms.minKeyCode = firstKeyCode;
1847706f2543Smrg    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
1848706f2543Smrg    keysyms.mapWidth = keySymsPerKeyCode;
1849706f2543Smrg    keysyms.map = map;
1850706f2543Smrg
1851706f2543Smrg    XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
1852706f2543Smrg                          serverClient);
1853706f2543Smrg
1854706f2543Smrg    return Success;
1855706f2543Smrg}
1856706f2543Smrg
1857706f2543Smrgstatic void
1858706f2543SmrgDeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
1859706f2543Smrg{
1860706f2543Smrg    WindowPtr parent;
1861706f2543Smrg
1862706f2543Smrg    /* Deactivate any grabs performed on this window, before making
1863706f2543Smrg     * any input focus changes.
1864706f2543Smrg     * Deactivating a device grab should cause focus events. */
1865706f2543Smrg
1866706f2543Smrg    if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
1867706f2543Smrg	(*dev->deviceGrab.DeactivateGrab) (dev);
1868706f2543Smrg
1869706f2543Smrg    /* If the focus window is a root window (ie. has no parent)
1870706f2543Smrg     * then don't delete the focus from it. */
1871706f2543Smrg
1872706f2543Smrg    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
1873706f2543Smrg	int focusEventMode = NotifyNormal;
1874706f2543Smrg
1875706f2543Smrg	/* If a grab is in progress, then alter the mode of focus events. */
1876706f2543Smrg
1877706f2543Smrg	if (dev->deviceGrab.grab)
1878706f2543Smrg	    focusEventMode = NotifyWhileGrabbed;
1879706f2543Smrg
1880706f2543Smrg	switch (dev->focus->revert) {
1881706f2543Smrg	case RevertToNone:
1882706f2543Smrg	    if (!ActivateFocusInGrab(dev, pWin, NoneWin))
1883706f2543Smrg		DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1884706f2543Smrg	    dev->focus->win = NoneWin;
1885706f2543Smrg	    dev->focus->traceGood = 0;
1886706f2543Smrg	    break;
1887706f2543Smrg	case RevertToParent:
1888706f2543Smrg	    parent = pWin;
1889706f2543Smrg	    do {
1890706f2543Smrg		parent = parent->parent;
1891706f2543Smrg		dev->focus->traceGood--;
1892706f2543Smrg	    }
1893706f2543Smrg	    while (!parent->realized);
1894706f2543Smrg	    if (!ActivateFocusInGrab(dev, pWin, parent))
1895706f2543Smrg		DoFocusEvents(dev, pWin, parent, focusEventMode);
1896706f2543Smrg	    dev->focus->win = parent;
1897706f2543Smrg	    dev->focus->revert = RevertToNone;
1898706f2543Smrg	    break;
1899706f2543Smrg	case RevertToPointerRoot:
1900706f2543Smrg	    if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
1901706f2543Smrg		DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
1902706f2543Smrg	    dev->focus->win = PointerRootWin;
1903706f2543Smrg	    dev->focus->traceGood = 0;
1904706f2543Smrg	    break;
1905706f2543Smrg	case RevertToFollowKeyboard:
1906706f2543Smrg            {
1907706f2543Smrg                DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
1908706f2543Smrg                if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
1909706f2543Smrg                    kbd = inputInfo.keyboard;
1910706f2543Smrg	    if (kbd->focus->win) {
1911706f2543Smrg		if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
1912706f2543Smrg		    DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
1913706f2543Smrg		dev->focus->win = FollowKeyboardWin;
1914706f2543Smrg		dev->focus->traceGood = 0;
1915706f2543Smrg	    } else {
1916706f2543Smrg                if (!ActivateFocusInGrab(dev, pWin, NoneWin))
1917706f2543Smrg                    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1918706f2543Smrg		dev->focus->win = NoneWin;
1919706f2543Smrg		dev->focus->traceGood = 0;
1920706f2543Smrg	    }
1921706f2543Smrg            }
1922706f2543Smrg	    break;
1923706f2543Smrg	}
1924706f2543Smrg    }
1925706f2543Smrg
1926706f2543Smrg    if (dev->valuator)
1927706f2543Smrg	if (dev->valuator->motionHintWindow == pWin)
1928706f2543Smrg	    dev->valuator->motionHintWindow = NullWindow;
1929706f2543Smrg}
1930706f2543Smrg
1931706f2543Smrgvoid
1932706f2543SmrgDeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
1933706f2543Smrg{
1934706f2543Smrg    int i;
1935706f2543Smrg    DeviceIntPtr dev;
1936706f2543Smrg    InputClientsPtr ic;
1937706f2543Smrg    struct _OtherInputMasks *inputMasks;
1938706f2543Smrg
1939706f2543Smrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
1940706f2543Smrg	DeleteDeviceFromAnyExtEvents(pWin, dev);
1941706f2543Smrg    }
1942706f2543Smrg
1943706f2543Smrg    for (dev = inputInfo.off_devices; dev; dev = dev->next)
1944706f2543Smrg	DeleteDeviceFromAnyExtEvents(pWin, dev);
1945706f2543Smrg
1946706f2543Smrg    if (freeResources)
1947706f2543Smrg	while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
1948706f2543Smrg	    ic = inputMasks->inputClients;
1949706f2543Smrg	    for (i = 0; i < EMASKSIZE; i++)
1950706f2543Smrg		inputMasks->dontPropagateMask[i] = 0;
1951706f2543Smrg	    FreeResource(ic->resource, RT_NONE);
1952706f2543Smrg	}
1953706f2543Smrg}
1954706f2543Smrg
1955706f2543Smrgint
1956706f2543SmrgMaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
1957706f2543Smrg{
1958706f2543Smrg    DeviceIntPtr dev;
1959706f2543Smrg
1960706f2543Smrg    dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
1961706f2543Smrg		    DixReadAccess);
1962706f2543Smrg    if (!dev)
1963706f2543Smrg        return 0;
1964706f2543Smrg
1965706f2543Smrg    if (pEvents->type == DeviceMotionNotify) {
1966706f2543Smrg	if (mask & DevicePointerMotionHintMask) {
1967706f2543Smrg	    if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
1968706f2543Smrg		return 1;	/* don't send, but pretend we did */
1969706f2543Smrg	    }
1970706f2543Smrg	    pEvents->detail = NotifyHint;
1971706f2543Smrg	} else {
1972706f2543Smrg	    pEvents->detail = NotifyNormal;
1973706f2543Smrg	}
1974706f2543Smrg    }
1975706f2543Smrg    return 0;
1976706f2543Smrg}
1977706f2543Smrg
1978706f2543Smrgvoid
1979706f2543SmrgCheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
1980706f2543Smrg			     deviceKeyButtonPointer * xE, GrabPtr grab,
1981706f2543Smrg			     ClientPtr client, Mask deliveryMask)
1982706f2543Smrg{
1983706f2543Smrg    DeviceIntPtr dev;
1984706f2543Smrg
1985706f2543Smrg    dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
1986706f2543Smrg		    DixGrabAccess);
1987706f2543Smrg    if (!dev)
1988706f2543Smrg        return;
1989706f2543Smrg
1990706f2543Smrg    if (type == DeviceMotionNotify)
1991706f2543Smrg	dev->valuator->motionHintWindow = pWin;
1992706f2543Smrg    else if ((type == DeviceButtonPress) && (!grab) &&
1993706f2543Smrg	     (deliveryMask & DeviceButtonGrabMask)) {
1994706f2543Smrg	GrabRec tempGrab;
1995706f2543Smrg
1996706f2543Smrg	tempGrab.device = dev;
1997706f2543Smrg	tempGrab.resource = client->clientAsMask;
1998706f2543Smrg	tempGrab.window = pWin;
1999706f2543Smrg	tempGrab.ownerEvents =
2000706f2543Smrg	    (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
2001706f2543Smrg	tempGrab.eventMask = deliveryMask;
2002706f2543Smrg	tempGrab.keyboardMode = GrabModeAsync;
2003706f2543Smrg	tempGrab.pointerMode = GrabModeAsync;
2004706f2543Smrg	tempGrab.confineTo = NullWindow;
2005706f2543Smrg	tempGrab.cursor = NullCursor;
2006706f2543Smrg        tempGrab.next = NULL;
2007706f2543Smrg	(*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
2008706f2543Smrg    }
2009706f2543Smrg}
2010706f2543Smrg
2011706f2543Smrgstatic Mask
2012706f2543SmrgDeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
2013706f2543Smrg{
2014706f2543Smrg    InputClientsPtr other;
2015706f2543Smrg
2016706f2543Smrg    if (!wOtherInputMasks(pWin))
2017706f2543Smrg	return 0;
2018706f2543Smrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
2019706f2543Smrg	 other = other->next) {
2020706f2543Smrg	if (SameClient(other, client))
2021706f2543Smrg	    return other->mask[dev->id];
2022706f2543Smrg    }
2023706f2543Smrg    return 0;
2024706f2543Smrg}
2025706f2543Smrg
2026706f2543Smrgvoid
2027706f2543SmrgMaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
2028706f2543Smrg{
2029706f2543Smrg    WindowPtr pWin;
2030706f2543Smrg    GrabPtr grab = dev->deviceGrab.grab;
2031706f2543Smrg
2032706f2543Smrg    pWin = dev->valuator->motionHintWindow;
2033706f2543Smrg
2034706f2543Smrg    if ((grab && SameClient(grab, client) &&
2035706f2543Smrg	 ((grab->eventMask & DevicePointerMotionHintMask) ||
2036706f2543Smrg	  (grab->ownerEvents &&
2037706f2543Smrg	   (DeviceEventMaskForClient(dev, pWin, client) &
2038706f2543Smrg	    DevicePointerMotionHintMask)))) ||
2039706f2543Smrg	(!grab &&
2040706f2543Smrg	 (DeviceEventMaskForClient(dev, pWin, client) &
2041706f2543Smrg	  DevicePointerMotionHintMask)))
2042706f2543Smrg	dev->valuator->motionHintWindow = NullWindow;
2043706f2543Smrg}
2044706f2543Smrg
2045706f2543Smrgint
2046706f2543SmrgDeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
2047706f2543Smrg			     int maskndx)
2048706f2543Smrg{
2049706f2543Smrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2050706f2543Smrg
2051706f2543Smrg    if (mask & ~PropagateMask[maskndx]) {
2052706f2543Smrg	client->errorValue = mask;
2053706f2543Smrg	return BadValue;
2054706f2543Smrg    }
2055706f2543Smrg
2056706f2543Smrg    if (mask == 0) {
2057706f2543Smrg	if (inputMasks)
2058706f2543Smrg	    inputMasks->dontPropagateMask[maskndx] = mask;
2059706f2543Smrg    } else {
2060706f2543Smrg	if (!inputMasks)
2061706f2543Smrg	    AddExtensionClient(pWin, client, 0, 0);
2062706f2543Smrg	inputMasks = wOtherInputMasks(pWin);
2063706f2543Smrg	inputMasks->dontPropagateMask[maskndx] = mask;
2064706f2543Smrg    }
2065706f2543Smrg    RecalculateDeviceDeliverableEvents(pWin);
2066706f2543Smrg    if (ShouldFreeInputMasks(pWin, FALSE))
2067706f2543Smrg	FreeResource(inputMasks->inputClients->resource, RT_NONE);
2068706f2543Smrg    return Success;
2069706f2543Smrg}
2070706f2543Smrg
2071706f2543SmrgBool
2072706f2543SmrgShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
2073706f2543Smrg{
2074706f2543Smrg    int i;
2075706f2543Smrg    Mask allInputEventMasks = 0;
2076706f2543Smrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2077706f2543Smrg
2078706f2543Smrg    for (i = 0; i < EMASKSIZE; i++)
2079706f2543Smrg	allInputEventMasks |= inputMasks->dontPropagateMask[i];
2080706f2543Smrg    if (!ignoreSelectedEvents)
2081706f2543Smrg	for (i = 0; i < EMASKSIZE; i++)
2082706f2543Smrg	    allInputEventMasks |= inputMasks->inputEvents[i];
2083706f2543Smrg    if (allInputEventMasks == 0)
2084706f2543Smrg	return TRUE;
2085706f2543Smrg    else
2086706f2543Smrg	return FALSE;
2087706f2543Smrg}
2088706f2543Smrg
2089706f2543Smrg/***********************************************************************
2090706f2543Smrg *
2091706f2543Smrg * Walk through the window tree, finding all clients that want to know
2092706f2543Smrg * about the Event.
2093706f2543Smrg *
2094706f2543Smrg */
2095706f2543Smrg
2096706f2543Smrgstatic void
2097706f2543SmrgFindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
2098706f2543Smrg                       xEvent * ev, int count)
2099706f2543Smrg{
2100706f2543Smrg    WindowPtr p2;
2101706f2543Smrg
2102706f2543Smrg    while (p1) {
2103706f2543Smrg        p2 = p1->firstChild;
2104706f2543Smrg        DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
2105706f2543Smrg        FindInterestedChildren(dev, p2, mask, ev, count);
2106706f2543Smrg        p1 = p1->nextSib;
2107706f2543Smrg    }
2108706f2543Smrg}
2109706f2543Smrg
2110706f2543Smrg/***********************************************************************
2111706f2543Smrg *
2112706f2543Smrg * Send an event to interested clients in all windows on all screens.
2113706f2543Smrg *
2114706f2543Smrg */
2115706f2543Smrg
2116706f2543Smrgvoid
2117706f2543SmrgSendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
2118706f2543Smrg{
2119706f2543Smrg    int i;
2120706f2543Smrg    WindowPtr pWin, p1;
2121706f2543Smrg
2122706f2543Smrg    for (i = 0; i < screenInfo.numScreens; i++) {
2123706f2543Smrg        pWin = screenInfo.screens[i]->root;
2124706f2543Smrg        if (!pWin)
2125706f2543Smrg            continue;
2126706f2543Smrg        DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
2127706f2543Smrg        p1 = pWin->firstChild;
2128706f2543Smrg        FindInterestedChildren(dev, p1, mask, ev, count);
2129706f2543Smrg    }
2130706f2543Smrg}
2131706f2543Smrg
2132706f2543Smrg/**
2133706f2543Smrg * Set the XI2 mask for the given client on the given window.
2134706f2543Smrg * @param dev The device to set the mask for.
2135706f2543Smrg * @param win The window to set the mask on.
2136706f2543Smrg * @param client The client setting the mask.
2137706f2543Smrg * @param len Number of bytes in mask.
2138706f2543Smrg * @param mask Event mask in the form of (1 << eventtype)
2139706f2543Smrg */
2140706f2543Smrgint
2141706f2543SmrgXISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
2142706f2543Smrg               unsigned int len, unsigned char* mask)
2143706f2543Smrg{
2144706f2543Smrg    OtherInputMasks *masks;
2145706f2543Smrg    InputClientsPtr others = NULL;
2146706f2543Smrg
2147706f2543Smrg    masks = wOtherInputMasks(win);
2148706f2543Smrg    if (masks)
2149706f2543Smrg    {
2150706f2543Smrg	for (others = wOtherInputMasks(win)->inputClients; others;
2151706f2543Smrg	     others = others->next) {
2152706f2543Smrg	    if (SameClient(others, client)) {
2153706f2543Smrg                memset(others->xi2mask[dev->id], 0,
2154706f2543Smrg                       sizeof(others->xi2mask[dev->id]));
2155706f2543Smrg                break;
2156706f2543Smrg            }
2157706f2543Smrg        }
2158706f2543Smrg    }
2159706f2543Smrg
2160706f2543Smrg    len = min(len, sizeof(others->xi2mask[dev->id]));
2161706f2543Smrg
2162706f2543Smrg    if (len && !others)
2163706f2543Smrg    {
2164706f2543Smrg        if (AddExtensionClient(win, client, 0, 0) != Success)
2165706f2543Smrg            return BadAlloc;
2166706f2543Smrg        others= wOtherInputMasks(win)->inputClients;
2167706f2543Smrg    }
2168706f2543Smrg
2169706f2543Smrg    if (others)
2170706f2543Smrg        memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id]));
2171706f2543Smrg
2172706f2543Smrg    if (len)
2173706f2543Smrg        memcpy(others->xi2mask[dev->id], mask, len);
2174706f2543Smrg
2175706f2543Smrg    RecalculateDeviceDeliverableEvents(win);
2176706f2543Smrg
2177706f2543Smrg    return Success;
2178706f2543Smrg}
2179