exevents.c revision bde01a6b
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));
589d931189fSmrg        } else {
590706f2543Smrg            free(to->button->xkb_acts);
591d931189fSmrg            to->button->xkb_acts = NULL;
592d931189fSmrg	}
593706f2543Smrg
594706f2543Smrg         memcpy(to->button->labels, from->button->labels,
595706f2543Smrg                from->button->numButtons * sizeof(Atom));
596706f2543Smrg        to->button->sourceid = from->id;
597706f2543Smrg    } else if (to->button && !from->button)
598706f2543Smrg    {
599706f2543Smrg        ClassesPtr classes;
600706f2543Smrg        classes = to->unused_classes;
601706f2543Smrg        classes->button = to->button;
602706f2543Smrg        to->button      = NULL;
603706f2543Smrg    }
604706f2543Smrg
605706f2543Smrg    if (from->proximity)
606706f2543Smrg    {
607706f2543Smrg        if (!to->proximity)
608706f2543Smrg        {
609706f2543Smrg            classes = to->unused_classes;
610706f2543Smrg            to->proximity = classes->proximity;
611706f2543Smrg            if (!to->proximity)
612706f2543Smrg            {
613706f2543Smrg                to->proximity = calloc(1, sizeof(ProximityClassRec));
614706f2543Smrg                if (!to->proximity)
615706f2543Smrg                    FatalError("[Xi] no memory for class shift.\n");
616706f2543Smrg            } else
617706f2543Smrg                classes->proximity = NULL;
618706f2543Smrg        }
619706f2543Smrg        memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
620706f2543Smrg        to->proximity->sourceid = from->id;
621706f2543Smrg    } else if (to->proximity)
622706f2543Smrg    {
623706f2543Smrg        ClassesPtr classes;
624706f2543Smrg        classes = to->unused_classes;
625706f2543Smrg        classes->proximity = to->proximity;
626706f2543Smrg        to->proximity      = NULL;
627706f2543Smrg    }
628706f2543Smrg
629706f2543Smrg    if (from->absolute)
630706f2543Smrg    {
631706f2543Smrg        if (!to->absolute)
632706f2543Smrg        {
633706f2543Smrg            classes = to->unused_classes;
634706f2543Smrg            to->absolute = classes->absolute;
635706f2543Smrg            if (!to->absolute)
636706f2543Smrg            {
637706f2543Smrg                to->absolute = calloc(1, sizeof(AbsoluteClassRec));
638706f2543Smrg                if (!to->absolute)
639706f2543Smrg                    FatalError("[Xi] no memory for class shift.\n");
640706f2543Smrg            } else
641706f2543Smrg                classes->absolute = NULL;
642706f2543Smrg        }
643706f2543Smrg        memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
644706f2543Smrg        to->absolute->sourceid = from->id;
645706f2543Smrg    } else if (to->absolute)
646706f2543Smrg    {
647706f2543Smrg        ClassesPtr classes;
648706f2543Smrg        classes = to->unused_classes;
649706f2543Smrg        classes->absolute = to->absolute;
650706f2543Smrg        to->absolute      = NULL;
651706f2543Smrg    }
652706f2543Smrg}
653706f2543Smrg
654706f2543Smrg/**
655706f2543Smrg * Copies the CONTENT of the classes of device from into the classes in device
656706f2543Smrg * to. From and to are identical after finishing.
657706f2543Smrg *
658706f2543Smrg * If to does not have classes from currenly has, the classes are stored in
659706f2543Smrg * to's devPrivates system. Later, we recover it again from there if needed.
660706f2543Smrg * Saves a few memory allocations.
661706f2543Smrg */
662706f2543Smrgvoid
663706f2543SmrgDeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce)
664706f2543Smrg{
665706f2543Smrg    /* generic feedback classes, not tied to pointer and/or keyboard */
666706f2543Smrg    DeepCopyFeedbackClasses(from, to);
667706f2543Smrg
668706f2543Smrg    if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
669706f2543Smrg        DeepCopyKeyboardClasses(from, to);
670706f2543Smrg    if ((dce->flags & DEVCHANGE_POINTER_EVENT))
671706f2543Smrg        DeepCopyPointerClasses(from, to);
672706f2543Smrg}
673706f2543Smrg
674706f2543Smrg
675706f2543Smrg/**
676706f2543Smrg * Send an XI2 DeviceChangedEvent to all interested clients.
677706f2543Smrg */
678706f2543Smrgvoid
679706f2543SmrgXISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChangedEvent *dce)
680706f2543Smrg{
681706f2543Smrg    xXIDeviceChangedEvent *dcce;
682706f2543Smrg    int rc;
683706f2543Smrg
684706f2543Smrg    rc = EventToXI2((InternalEvent*)dce, (xEvent**)&dcce);
685706f2543Smrg    if (rc != Success)
686706f2543Smrg    {
687706f2543Smrg        ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
688706f2543Smrg        return;
689706f2543Smrg    }
690706f2543Smrg
691706f2543Smrg    /* we don't actually swap if there's a NullClient, swapping is done
692706f2543Smrg     * later when event is delivered. */
693706f2543Smrg    SendEventToAllWindows(master, XI_DeviceChangedMask, (xEvent*)dcce, 1);
694706f2543Smrg    free(dcce);
695706f2543Smrg}
696706f2543Smrg
697706f2543Smrgstatic void
698706f2543SmrgChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
699706f2543Smrg{
700706f2543Smrg    DeviceIntPtr slave;
701706f2543Smrg    int rc;
702706f2543Smrg
703706f2543Smrg    /* For now, we don't have devices that change physically. */
704706f2543Smrg    if (!IsMaster(device))
705706f2543Smrg        return;
706706f2543Smrg
707706f2543Smrg    rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
708706f2543Smrg
709706f2543Smrg    if (rc != Success)
710706f2543Smrg        return; /* Device has disappeared */
711706f2543Smrg
712706f2543Smrg    if (!slave->u.master)
713706f2543Smrg        return; /* set floating since the event */
714706f2543Smrg
715706f2543Smrg    if (slave->u.master->id != dce->masterid)
716706f2543Smrg        return; /* not our slave anymore, don't care */
717706f2543Smrg
718706f2543Smrg    /* FIXME: we probably need to send a DCE for the new slave now */
719706f2543Smrg
720706f2543Smrg    device->public.devicePrivate = slave->public.devicePrivate;
721706f2543Smrg
722706f2543Smrg    /* FIXME: the classes may have changed since we generated the event. */
723706f2543Smrg    DeepCopyDeviceClasses(slave, device, dce);
724706f2543Smrg    XISendDeviceChangedEvent(slave, device, dce);
725706f2543Smrg}
726706f2543Smrg
727706f2543Smrg/**
728706f2543Smrg * Update the device state according to the data in the event.
729706f2543Smrg *
730706f2543Smrg * return values are
731706f2543Smrg *   DEFAULT ... process as normal
732706f2543Smrg *   DONT_PROCESS ... return immediately from caller
733706f2543Smrg */
734706f2543Smrg#define DEFAULT 0
735706f2543Smrg#define DONT_PROCESS 1
736706f2543Smrgint
737706f2543SmrgUpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
738706f2543Smrg{
739706f2543Smrg    int i;
740706f2543Smrg    int key = 0,
741706f2543Smrg        bit = 0,
742706f2543Smrg        last_valuator;
743706f2543Smrg
744706f2543Smrg    KeyClassPtr k       = NULL;
745706f2543Smrg    ButtonClassPtr b    = NULL;
746706f2543Smrg    ValuatorClassPtr v  = NULL;
747706f2543Smrg
748706f2543Smrg    /* This event is always the first we get, before the actual events with
749706f2543Smrg     * the data. However, the way how the DDX is set up, "device" will
750706f2543Smrg     * actually be the slave device that caused the event.
751706f2543Smrg     */
752706f2543Smrg    switch(event->type)
753706f2543Smrg    {
754706f2543Smrg        case ET_DeviceChanged:
755706f2543Smrg            ChangeMasterDeviceClasses(device, (DeviceChangedEvent*)event);
756706f2543Smrg            return DONT_PROCESS; /* event has been sent already */
757706f2543Smrg        case ET_Motion:
758706f2543Smrg        case ET_ButtonPress:
759706f2543Smrg        case ET_ButtonRelease:
760706f2543Smrg        case ET_KeyPress:
761706f2543Smrg        case ET_KeyRelease:
762706f2543Smrg        case ET_ProximityIn:
763706f2543Smrg        case ET_ProximityOut:
764706f2543Smrg            break;
765706f2543Smrg        default:
766706f2543Smrg            /* other events don't update the device */
767706f2543Smrg            return DEFAULT;
768706f2543Smrg    }
769706f2543Smrg
770706f2543Smrg    k = device->key;
771706f2543Smrg    v = device->valuator;
772706f2543Smrg    b = device->button;
773706f2543Smrg
774706f2543Smrg    key = event->detail.key;
775706f2543Smrg    bit = 1 << (key & 7);
776706f2543Smrg
777706f2543Smrg    /* Update device axis */
778706f2543Smrg    /* Check valuators first */
779706f2543Smrg    last_valuator = -1;
780706f2543Smrg    for (i = 0; i < MAX_VALUATORS; i++)
781706f2543Smrg    {
782706f2543Smrg        if (BitIsOn(&event->valuators.mask, i))
783706f2543Smrg        {
784706f2543Smrg            if (!v)
785706f2543Smrg            {
786706f2543Smrg                ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
787706f2543Smrg                        "Ignoring event.\n", device->name);
788706f2543Smrg                return DONT_PROCESS;
789706f2543Smrg            } else if (v->numAxes < i)
790706f2543Smrg            {
791706f2543Smrg                ErrorF("[Xi] Too many valuators reported for device '%s'. "
792706f2543Smrg                        "Ignoring event.\n", device->name);
793706f2543Smrg                return DONT_PROCESS;
794706f2543Smrg            }
795706f2543Smrg            last_valuator = i;
796706f2543Smrg        }
797706f2543Smrg    }
798706f2543Smrg
799706f2543Smrg    for (i = 0; i <= last_valuator && i < v->numAxes; i++)
800706f2543Smrg    {
801706f2543Smrg        if (BitIsOn(&event->valuators.mask, i))
802706f2543Smrg        {
803706f2543Smrg            /* XXX: Relative/Absolute mode */
804706f2543Smrg            v->axisVal[i] = event->valuators.data[i];
805706f2543Smrg            v->axisVal[i] += (event->valuators.data_frac[i] * 1.0f / (1 << 16) / (1 << 16));
806706f2543Smrg        }
807706f2543Smrg    }
808706f2543Smrg
809706f2543Smrg    if (event->type == ET_KeyPress) {
810706f2543Smrg        if (!k)
811706f2543Smrg            return DONT_PROCESS;
812706f2543Smrg
813706f2543Smrg	/* don't allow ddx to generate multiple downs, but repeats are okay */
814706f2543Smrg	if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
815706f2543Smrg	    return DONT_PROCESS;
816706f2543Smrg
817706f2543Smrg	if (device->valuator)
818706f2543Smrg	    device->valuator->motionHintWindow = NullWindow;
819706f2543Smrg	set_key_down(device, key, KEY_PROCESSED);
820706f2543Smrg    } else if (event->type == ET_KeyRelease) {
821706f2543Smrg        if (!k)
822706f2543Smrg            return DONT_PROCESS;
823706f2543Smrg
824706f2543Smrg	if (!key_is_down(device, key, KEY_PROCESSED))	/* guard against duplicates */
825706f2543Smrg	    return DONT_PROCESS;
826706f2543Smrg	if (device->valuator)
827706f2543Smrg	    device->valuator->motionHintWindow = NullWindow;
828706f2543Smrg	set_key_up(device, key, KEY_PROCESSED);
829706f2543Smrg    } else if (event->type == ET_ButtonPress) {
830706f2543Smrg        Mask mask;
831706f2543Smrg        if (!b)
832706f2543Smrg            return DONT_PROCESS;
833706f2543Smrg
834706f2543Smrg        if (button_is_down(device, key, BUTTON_PROCESSED))
835706f2543Smrg            return DONT_PROCESS;
836706f2543Smrg
837706f2543Smrg        set_button_down(device, key, BUTTON_PROCESSED);
838706f2543Smrg	if (device->valuator)
839706f2543Smrg	    device->valuator->motionHintWindow = NullWindow;
840706f2543Smrg        if (!b->map[key])
841706f2543Smrg            return DONT_PROCESS;
842706f2543Smrg        b->buttonsDown++;
843706f2543Smrg	b->motionMask = DeviceButtonMotionMask;
844706f2543Smrg        if (b->map[key] <= 5)
845706f2543Smrg	    b->state |= (Button1Mask >> 1) << b->map[key];
846706f2543Smrg
847706f2543Smrg        /* Add state and motionMask to the filter for this event */
848706f2543Smrg        mask = DevicePointerMotionMask | b->state | b->motionMask;
849706f2543Smrg        SetMaskForEvent(device->id, mask, DeviceMotionNotify);
850706f2543Smrg        mask = PointerMotionMask | b->state | b->motionMask;
851706f2543Smrg        SetMaskForEvent(device->id, mask, MotionNotify);
852706f2543Smrg    } else if (event->type == ET_ButtonRelease) {
853706f2543Smrg        Mask mask;
854706f2543Smrg        if (!b)
855706f2543Smrg            return DONT_PROCESS;
856706f2543Smrg
857706f2543Smrg        if (!button_is_down(device, key, BUTTON_PROCESSED))
858706f2543Smrg            return DONT_PROCESS;
859706f2543Smrg        if (IsMaster(device)) {
860706f2543Smrg            DeviceIntPtr sd;
861706f2543Smrg
862706f2543Smrg            /*
863706f2543Smrg             * Leave the button down if any slave has the
864706f2543Smrg             * button still down. Note that this depends on the
865706f2543Smrg             * event being delivered through the slave first
866706f2543Smrg             */
867706f2543Smrg            for (sd = inputInfo.devices; sd; sd = sd->next) {
868706f2543Smrg                if (IsMaster(sd) || sd->u.master != device)
869706f2543Smrg                    continue;
870706f2543Smrg                if (!sd->button)
871706f2543Smrg                    continue;
872706f2543Smrg                for (i = 1; i <= sd->button->numButtons; i++)
873706f2543Smrg                    if (sd->button->map[i] == key &&
874706f2543Smrg                        button_is_down(sd, i, BUTTON_PROCESSED))
875706f2543Smrg                        return DONT_PROCESS;
876706f2543Smrg            }
877706f2543Smrg        }
878706f2543Smrg        set_button_up(device, key, BUTTON_PROCESSED);
879706f2543Smrg	if (device->valuator)
880706f2543Smrg	    device->valuator->motionHintWindow = NullWindow;
881706f2543Smrg        if (!b->map[key])
882706f2543Smrg            return DONT_PROCESS;
883706f2543Smrg        if (b->buttonsDown >= 1 && !--b->buttonsDown)
884706f2543Smrg	    b->motionMask = 0;
885706f2543Smrg	if (b->map[key] <= 5)
886706f2543Smrg	    b->state &= ~((Button1Mask >> 1) << b->map[key]);
887706f2543Smrg
888706f2543Smrg        /* Add state and motionMask to the filter for this event */
889706f2543Smrg        mask = DevicePointerMotionMask | b->state | b->motionMask;
890706f2543Smrg        SetMaskForEvent(device->id, mask, DeviceMotionNotify);
891706f2543Smrg        mask = PointerMotionMask | b->state | b->motionMask;
892706f2543Smrg        SetMaskForEvent(device->id, mask, MotionNotify);
893706f2543Smrg    } else if (event->type == ET_ProximityIn)
894706f2543Smrg	device->proximity->in_proximity = TRUE;
895706f2543Smrg    else if (event->type == ET_ProximityOut)
896706f2543Smrg	device->proximity->in_proximity = FALSE;
897706f2543Smrg
898706f2543Smrg    return DEFAULT;
899706f2543Smrg}
900706f2543Smrg
901706f2543Smrgstatic void
902706f2543SmrgProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
903706f2543Smrg{
904706f2543Smrg    GrabPtr grab = device->deviceGrab.grab;
905706f2543Smrg
906706f2543Smrg    if (grab)
907706f2543Smrg        DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE);
908706f2543Smrg    else { /* deliver to all root windows */
909706f2543Smrg        xEvent *xi;
910706f2543Smrg        int i;
911706f2543Smrg
912706f2543Smrg        i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi);
913706f2543Smrg        if (i != Success)
914706f2543Smrg        {
915706f2543Smrg            ErrorF("[Xi] %s: XI2 conversion failed in ProcessRawEvent (%d)\n",
916706f2543Smrg                    device->name, i);
917706f2543Smrg            return;
918706f2543Smrg        }
919706f2543Smrg
920706f2543Smrg        for (i = 0; i < screenInfo.numScreens; i++)
921706f2543Smrg            DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1,
922706f2543Smrg                                  GetEventFilter(device, xi), NULL);
923706f2543Smrg        free(xi);
924706f2543Smrg    }
925706f2543Smrg}
926706f2543Smrg
927706f2543Smrg/**
928706f2543Smrg * Main device event processing function.
929706f2543Smrg * Called from when processing the events from the event queue.
930706f2543Smrg *
931706f2543Smrg */
932706f2543Smrgvoid
933706f2543SmrgProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
934706f2543Smrg{
935706f2543Smrg    GrabPtr grab;
936706f2543Smrg    Bool deactivateDeviceGrab = FALSE;
937706f2543Smrg    int key = 0, rootX, rootY;
938706f2543Smrg    ButtonClassPtr b;
939706f2543Smrg    KeyClassPtr k;
940706f2543Smrg    ValuatorClassPtr v;
941706f2543Smrg    int ret = 0;
942706f2543Smrg    int state, i;
943706f2543Smrg    DeviceIntPtr mouse = NULL, kbd = NULL;
944706f2543Smrg    DeviceEvent *event = &ev->device_event;
945706f2543Smrg
946706f2543Smrg    CHECKEVENT(ev);
947706f2543Smrg
948706f2543Smrg    if (ev->any.type == ET_RawKeyPress ||
949706f2543Smrg        ev->any.type == ET_RawKeyRelease ||
950706f2543Smrg        ev->any.type == ET_RawButtonPress ||
951706f2543Smrg        ev->any.type == ET_RawButtonRelease ||
952706f2543Smrg        ev->any.type == ET_RawMotion)
953706f2543Smrg    {
954706f2543Smrg        ProcessRawEvent(&ev->raw_event, device);
955706f2543Smrg        return;
956706f2543Smrg    }
957706f2543Smrg
958706f2543Smrg    if (IsPointerDevice(device))
959706f2543Smrg    {
960706f2543Smrg        kbd = GetPairedDevice(device);
961706f2543Smrg        mouse = device;
962706f2543Smrg        if (!kbd->key) /* can happen with floating SDs */
963706f2543Smrg            kbd = NULL;
964706f2543Smrg    } else
965706f2543Smrg    {
966706f2543Smrg        mouse = GetPairedDevice(device);
967706f2543Smrg        kbd = device;
968706f2543Smrg        if (!mouse->valuator || !mouse->button) /* may be float. SDs */
969706f2543Smrg            mouse = NULL;
970706f2543Smrg    }
971706f2543Smrg
972706f2543Smrg    /* State needs to be assembled BEFORE the device is updated. */
973706f2543Smrg    state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0;
974706f2543Smrg    state |= (mouse && mouse->button) ? (mouse->button->state) : 0;
975706f2543Smrg
976706f2543Smrg    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
977706f2543Smrg        if (BitIsOn(mouse->button->down, i))
978706f2543Smrg            SetBit(event->buttons, i);
979706f2543Smrg
980706f2543Smrg    if (kbd && kbd->key)
981706f2543Smrg    {
982706f2543Smrg        XkbStatePtr state;
983706f2543Smrg        /* we need the state before the event happens */
984706f2543Smrg        if (event->type == ET_KeyPress || event->type == ET_KeyRelease)
985706f2543Smrg            state = &kbd->key->xkbInfo->prev_state;
986706f2543Smrg        else
987706f2543Smrg            state = &kbd->key->xkbInfo->state;
988706f2543Smrg
989706f2543Smrg        event->mods.base = state->base_mods;
990706f2543Smrg        event->mods.latched = state->latched_mods;
991706f2543Smrg        event->mods.locked = state->locked_mods;
992706f2543Smrg        event->mods.effective = state->mods;
993706f2543Smrg
994706f2543Smrg        event->group.base = state->base_group;
995706f2543Smrg        event->group.latched = state->latched_group;
996706f2543Smrg        event->group.locked = state->locked_group;
997706f2543Smrg        event->group.effective = state->group;
998706f2543Smrg    }
999706f2543Smrg
1000706f2543Smrg    ret = UpdateDeviceState(device, event);
1001706f2543Smrg    if (ret == DONT_PROCESS)
1002706f2543Smrg        return;
1003706f2543Smrg
1004706f2543Smrg    v = device->valuator;
1005706f2543Smrg    b = device->button;
1006706f2543Smrg    k = device->key;
1007706f2543Smrg
1008706f2543Smrg    if (IsMaster(device) || !device->u.master)
1009706f2543Smrg        CheckMotion(event, device);
1010706f2543Smrg
1011706f2543Smrg    switch (event->type)
1012706f2543Smrg    {
1013706f2543Smrg        case ET_Motion:
1014706f2543Smrg        case ET_ButtonPress:
1015706f2543Smrg        case ET_ButtonRelease:
1016706f2543Smrg        case ET_KeyPress:
1017706f2543Smrg        case ET_KeyRelease:
1018706f2543Smrg        case ET_ProximityIn:
1019706f2543Smrg        case ET_ProximityOut:
1020706f2543Smrg            GetSpritePosition(device, &rootX, &rootY);
1021706f2543Smrg            event->root_x = rootX;
1022706f2543Smrg            event->root_y = rootY;
1023706f2543Smrg            NoticeEventTime((InternalEvent*)event);
1024706f2543Smrg            event->corestate = state;
1025706f2543Smrg            key = event->detail.key;
1026706f2543Smrg            break;
1027706f2543Smrg        default:
1028706f2543Smrg            break;
1029706f2543Smrg    }
1030706f2543Smrg
1031706f2543Smrg    if (DeviceEventCallback && !syncEvents.playingEvents) {
1032706f2543Smrg	DeviceEventInfoRec eventinfo;
1033706f2543Smrg	SpritePtr pSprite = device->spriteInfo->sprite;
1034706f2543Smrg
1035706f2543Smrg	/* see comment in EnqueueEvents regarding the next three lines */
1036706f2543Smrg	if (ev->any.type == ET_Motion)
1037706f2543Smrg	    ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1038706f2543Smrg
1039706f2543Smrg	eventinfo.device = device;
1040706f2543Smrg	eventinfo.event = ev;
1041706f2543Smrg	CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
1042706f2543Smrg    }
1043706f2543Smrg
1044706f2543Smrg    grab = device->deviceGrab.grab;
1045706f2543Smrg
1046706f2543Smrg    switch(event->type)
1047706f2543Smrg    {
1048706f2543Smrg        case ET_KeyPress:
1049706f2543Smrg            if (!grab && CheckDeviceGrabs(device, event, 0)) {
1050706f2543Smrg                device->deviceGrab.activatingKey = key;
1051706f2543Smrg                return;
1052706f2543Smrg            }
1053706f2543Smrg            break;
1054706f2543Smrg        case ET_KeyRelease:
1055706f2543Smrg            if (grab && device->deviceGrab.fromPassiveGrab &&
1056706f2543Smrg                (key == device->deviceGrab.activatingKey) &&
1057706f2543Smrg                (device->deviceGrab.grab->type == KeyPress ||
1058706f2543Smrg                 device->deviceGrab.grab->type == DeviceKeyPress ||
1059706f2543Smrg                 device->deviceGrab.grab->type == XI_KeyPress))
1060706f2543Smrg                deactivateDeviceGrab = TRUE;
1061706f2543Smrg            break;
1062706f2543Smrg        case ET_ButtonPress:
1063706f2543Smrg            event->detail.button = b->map[key];
1064706f2543Smrg            if (!event->detail.button) { /* there's no button 0 */
1065706f2543Smrg                event->detail.button = key;
1066706f2543Smrg                return;
1067706f2543Smrg            }
1068706f2543Smrg            if (!grab && CheckDeviceGrabs(device, event, 0))
1069706f2543Smrg            {
1070706f2543Smrg                /* if a passive grab was activated, the event has been sent
1071706f2543Smrg                 * already */
1072706f2543Smrg                return;
1073706f2543Smrg            }
1074706f2543Smrg            break;
1075706f2543Smrg        case ET_ButtonRelease:
1076706f2543Smrg            event->detail.button = b->map[key];
1077706f2543Smrg            if (!event->detail.button) { /* there's no button 0 */
1078706f2543Smrg                event->detail.button = key;
1079706f2543Smrg                return;
1080706f2543Smrg            }
1081706f2543Smrg            if (grab && !b->buttonsDown &&
1082706f2543Smrg                device->deviceGrab.fromPassiveGrab &&
1083706f2543Smrg                (device->deviceGrab.grab->type == ButtonPress ||
1084706f2543Smrg                 device->deviceGrab.grab->type == DeviceButtonPress ||
1085706f2543Smrg                 device->deviceGrab.grab->type == XI_ButtonPress))
1086706f2543Smrg                deactivateDeviceGrab = TRUE;
1087706f2543Smrg        default:
1088706f2543Smrg            break;
1089706f2543Smrg    }
1090706f2543Smrg
1091706f2543Smrg
1092706f2543Smrg    if (grab)
1093706f2543Smrg        DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
1094706f2543Smrg    else if (device->focus && !IsPointerEvent((InternalEvent*)ev))
1095706f2543Smrg        DeliverFocusedEvent(device, (InternalEvent*)event,
1096706f2543Smrg                            GetSpriteWindow(device));
1097706f2543Smrg    else
1098706f2543Smrg        DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
1099706f2543Smrg                            NullGrab, NullWindow, device);
1100706f2543Smrg
1101706f2543Smrg    if (deactivateDeviceGrab == TRUE)
1102706f2543Smrg	(*device->deviceGrab.DeactivateGrab) (device);
1103706f2543Smrg    event->detail.key = key;
1104706f2543Smrg}
1105706f2543Smrg
1106706f2543Smrgint
1107706f2543SmrgInitProximityClassDeviceStruct(DeviceIntPtr dev)
1108706f2543Smrg{
1109706f2543Smrg    ProximityClassPtr proxc;
1110706f2543Smrg
1111706f2543Smrg    proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
1112706f2543Smrg    if (!proxc)
1113706f2543Smrg	return FALSE;
1114706f2543Smrg    proxc->sourceid = dev->id;
1115706f2543Smrg    proxc->in_proximity = TRUE;
1116706f2543Smrg    dev->proximity = proxc;
1117706f2543Smrg    return TRUE;
1118706f2543Smrg}
1119706f2543Smrg
1120706f2543Smrg/**
1121706f2543Smrg * Initialise the device's valuators. The memory must already be allocated,
1122706f2543Smrg * this function merely inits the matching axis (specified through axnum) to
1123706f2543Smrg * sane values.
1124706f2543Smrg *
1125706f2543Smrg * It is a condition that (minval < maxval).
1126706f2543Smrg *
1127706f2543Smrg * @see InitValuatorClassDeviceStruct
1128706f2543Smrg */
1129706f2543Smrgvoid
1130706f2543SmrgInitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
1131706f2543Smrg		       int resolution, int min_res, int max_res, int mode)
1132706f2543Smrg{
1133706f2543Smrg    AxisInfoPtr ax;
1134706f2543Smrg
1135706f2543Smrg    if (!dev || !dev->valuator || minval > maxval)
1136706f2543Smrg        return;
1137706f2543Smrg    if (axnum >= dev->valuator->numAxes)
1138706f2543Smrg        return;
1139706f2543Smrg
1140706f2543Smrg    ax = dev->valuator->axes + axnum;
1141706f2543Smrg
1142706f2543Smrg    ax->min_value = minval;
1143706f2543Smrg    ax->max_value = maxval;
1144706f2543Smrg    ax->resolution = resolution;
1145706f2543Smrg    ax->min_resolution = min_res;
1146706f2543Smrg    ax->max_resolution = max_res;
1147706f2543Smrg    ax->label = label;
1148706f2543Smrg    ax->mode = mode;
1149706f2543Smrg
1150706f2543Smrg    if (mode & OutOfProximity)
1151706f2543Smrg        dev->proximity->in_proximity = FALSE;
1152706f2543Smrg}
1153706f2543Smrg
1154706f2543Smrgstatic void
1155706f2543SmrgFixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
1156706f2543Smrg		     ButtonClassPtr b, ValuatorClassPtr v, int first)
1157706f2543Smrg{
1158706f2543Smrg    ev->type = DeviceStateNotify;
1159706f2543Smrg    ev->deviceid = dev->id;
1160706f2543Smrg    ev->time = currentTime.milliseconds;
1161706f2543Smrg    ev->classes_reported = 0;
1162706f2543Smrg    ev->num_keys = 0;
1163706f2543Smrg    ev->num_buttons = 0;
1164706f2543Smrg    ev->num_valuators = 0;
1165706f2543Smrg
1166706f2543Smrg    if (b) {
1167706f2543Smrg	ev->classes_reported |= (1 << ButtonClass);
1168706f2543Smrg	ev->num_buttons = b->numButtons;
1169706f2543Smrg	memcpy((char*)ev->buttons, (char*)b->down, 4);
1170706f2543Smrg    } else if (k) {
1171706f2543Smrg	ev->classes_reported |= (1 << KeyClass);
1172706f2543Smrg	ev->num_keys = k->xkbInfo->desc->max_key_code -
1173706f2543Smrg                       k->xkbInfo->desc->min_key_code;
1174706f2543Smrg	memmove((char *)&ev->keys[0], (char *)k->down, 4);
1175706f2543Smrg    }
1176706f2543Smrg    if (v) {
1177706f2543Smrg	int nval = v->numAxes - first;
1178706f2543Smrg
1179706f2543Smrg	ev->classes_reported |= (1 << ValuatorClass);
1180706f2543Smrg	ev->classes_reported |= valuator_get_mode(dev, 0) << ModeBitsShift;
1181706f2543Smrg	ev->num_valuators = nval < 3 ? nval : 3;
1182706f2543Smrg	switch (ev->num_valuators) {
1183706f2543Smrg	case 3:
1184706f2543Smrg	    ev->valuator2 = v->axisVal[first + 2];
1185706f2543Smrg	case 2:
1186706f2543Smrg	    ev->valuator1 = v->axisVal[first + 1];
1187706f2543Smrg	case 1:
1188706f2543Smrg	    ev->valuator0 = v->axisVal[first];
1189706f2543Smrg	    break;
1190706f2543Smrg	}
1191706f2543Smrg    }
1192706f2543Smrg}
1193706f2543Smrg
1194706f2543Smrgstatic void
1195706f2543SmrgFixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
1196706f2543Smrg		  int first)
1197706f2543Smrg{
1198706f2543Smrg    int nval = v->numAxes - first;
1199706f2543Smrg
1200706f2543Smrg    ev->type = DeviceValuator;
1201706f2543Smrg    ev->deviceid = dev->id;
1202706f2543Smrg    ev->num_valuators = nval < 3 ? nval : 3;
1203706f2543Smrg    ev->first_valuator = first;
1204706f2543Smrg    switch (ev->num_valuators) {
1205706f2543Smrg    case 3:
1206706f2543Smrg	ev->valuator2 = v->axisVal[first + 2];
1207706f2543Smrg    case 2:
1208706f2543Smrg	ev->valuator1 = v->axisVal[first + 1];
1209706f2543Smrg    case 1:
1210706f2543Smrg	ev->valuator0 = v->axisVal[first];
1211706f2543Smrg	break;
1212706f2543Smrg    }
1213706f2543Smrg    first += ev->num_valuators;
1214706f2543Smrg}
1215706f2543Smrg
1216706f2543Smrgvoid
1217706f2543SmrgDeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
1218706f2543Smrg		 WindowPtr pWin)
1219706f2543Smrg{
1220706f2543Smrg    deviceFocus event;
1221706f2543Smrg    xXIFocusInEvent *xi2event;
1222706f2543Smrg    DeviceIntPtr mouse;
1223706f2543Smrg    int btlen, len, i;
1224706f2543Smrg
1225706f2543Smrg    mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev;
1226706f2543Smrg
1227bde01a6bSmrg    /* XI 2 event contains the logical button map - maps are CARD8
1228bde01a6bSmrg     * so we need 256 bits for the possibly maximum mapping */
1229bde01a6bSmrg    btlen = (mouse->button) ? bits_to_bytes(256) : 0;
1230706f2543Smrg    btlen = bytes_to_int32(btlen);
1231706f2543Smrg    len = sizeof(xXIFocusInEvent) + btlen * 4;
1232706f2543Smrg
1233706f2543Smrg    xi2event = calloc(1, len);
1234706f2543Smrg    xi2event->type         = GenericEvent;
1235706f2543Smrg    xi2event->extension    = IReqCode;
1236706f2543Smrg    xi2event->evtype       = type;
1237706f2543Smrg    xi2event->length       = bytes_to_int32(len - sizeof(xEvent));
1238706f2543Smrg    xi2event->buttons_len  = btlen;
1239706f2543Smrg    xi2event->detail       = detail;
1240706f2543Smrg    xi2event->time         = currentTime.milliseconds;
1241706f2543Smrg    xi2event->deviceid     = dev->id;
1242706f2543Smrg    xi2event->sourceid     = dev->id; /* a device doesn't change focus by itself */
1243706f2543Smrg    xi2event->mode         = mode;
1244706f2543Smrg    xi2event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
1245706f2543Smrg    xi2event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
1246706f2543Smrg
1247706f2543Smrg    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
1248706f2543Smrg        if (BitIsOn(mouse->button->down, i))
1249706f2543Smrg            SetBit(&xi2event[1], i);
1250706f2543Smrg
1251706f2543Smrg    if (dev->key)
1252706f2543Smrg    {
1253706f2543Smrg        xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
1254706f2543Smrg        xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
1255706f2543Smrg        xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
1256706f2543Smrg        xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
1257706f2543Smrg
1258706f2543Smrg        xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
1259706f2543Smrg        xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
1260706f2543Smrg        xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
1261706f2543Smrg        xi2event->group.effective_group = dev->key->xkbInfo->state.group;
1262706f2543Smrg    }
1263706f2543Smrg
1264706f2543Smrg    FixUpEventFromWindow(dev->spriteInfo->sprite, (xEvent*)xi2event, pWin,
1265706f2543Smrg                         None, FALSE);
1266706f2543Smrg
1267706f2543Smrg    DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
1268706f2543Smrg                          GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
1269706f2543Smrg
1270706f2543Smrg    free(xi2event);
1271706f2543Smrg
1272706f2543Smrg    /* XI 1.x event */
1273706f2543Smrg    event.deviceid = dev->id;
1274706f2543Smrg    event.mode = mode;
1275706f2543Smrg    event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
1276706f2543Smrg    event.detail = detail;
1277706f2543Smrg    event.window = pWin->drawable.id;
1278706f2543Smrg    event.time = currentTime.milliseconds;
1279706f2543Smrg
1280706f2543Smrg    DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
1281706f2543Smrg				DeviceFocusChangeMask, NullGrab);
1282706f2543Smrg
1283706f2543Smrg    if ((event.type == DeviceFocusIn) &&
1284706f2543Smrg	(wOtherInputMasks(pWin)) &&
1285706f2543Smrg	(wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
1286706f2543Smrg    {
1287706f2543Smrg	int evcount = 1;
1288706f2543Smrg	deviceStateNotify *ev, *sev;
1289706f2543Smrg	deviceKeyStateNotify *kev;
1290706f2543Smrg	deviceButtonStateNotify *bev;
1291706f2543Smrg
1292706f2543Smrg	KeyClassPtr k;
1293706f2543Smrg	ButtonClassPtr b;
1294706f2543Smrg	ValuatorClassPtr v;
1295706f2543Smrg	int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
1296706f2543Smrg
1297706f2543Smrg	if ((b = dev->button) != NULL) {
1298706f2543Smrg	    nbuttons = b->numButtons;
1299706f2543Smrg	    if (nbuttons > 32)
1300706f2543Smrg		evcount++;
1301706f2543Smrg	}
1302706f2543Smrg	if ((k = dev->key) != NULL) {
1303706f2543Smrg	    nkeys = k->xkbInfo->desc->max_key_code -
1304706f2543Smrg                    k->xkbInfo->desc->min_key_code;
1305706f2543Smrg	    if (nkeys > 32)
1306706f2543Smrg		evcount++;
1307706f2543Smrg	    if (nbuttons > 0) {
1308706f2543Smrg		evcount++;
1309706f2543Smrg	    }
1310706f2543Smrg	}
1311706f2543Smrg	if ((v = dev->valuator) != NULL) {
1312706f2543Smrg	    nval = v->numAxes;
1313706f2543Smrg
1314706f2543Smrg	    if (nval > 3)
1315706f2543Smrg		evcount++;
1316706f2543Smrg	    if (nval > 6) {
1317706f2543Smrg		if (!(k && b))
1318706f2543Smrg		    evcount++;
1319706f2543Smrg		if (nval > 9)
1320706f2543Smrg		    evcount += ((nval - 7) / 3);
1321706f2543Smrg	    }
1322706f2543Smrg	}
1323706f2543Smrg
1324706f2543Smrg	sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
1325706f2543Smrg	FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
1326706f2543Smrg
1327706f2543Smrg	if (b != NULL) {
1328706f2543Smrg	    FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
1329706f2543Smrg	    first += 3;
1330706f2543Smrg	    nval -= 3;
1331706f2543Smrg	    if (nbuttons > 32) {
1332706f2543Smrg		(ev - 1)->deviceid |= MORE_EVENTS;
1333706f2543Smrg		bev = (deviceButtonStateNotify *) ev++;
1334706f2543Smrg		bev->type = DeviceButtonStateNotify;
1335706f2543Smrg		bev->deviceid = dev->id;
1336706f2543Smrg		memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
1337706f2543Smrg	    }
1338706f2543Smrg	    if (nval > 0) {
1339706f2543Smrg		(ev - 1)->deviceid |= MORE_EVENTS;
1340706f2543Smrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1341706f2543Smrg		first += 3;
1342706f2543Smrg		nval -= 3;
1343706f2543Smrg	    }
1344706f2543Smrg	}
1345706f2543Smrg
1346706f2543Smrg	if (k != NULL) {
1347706f2543Smrg	    FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
1348706f2543Smrg	    first += 3;
1349706f2543Smrg	    nval -= 3;
1350706f2543Smrg	    if (nkeys > 32) {
1351706f2543Smrg		(ev - 1)->deviceid |= MORE_EVENTS;
1352706f2543Smrg		kev = (deviceKeyStateNotify *) ev++;
1353706f2543Smrg		kev->type = DeviceKeyStateNotify;
1354706f2543Smrg		kev->deviceid = dev->id;
1355706f2543Smrg		memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
1356706f2543Smrg	    }
1357706f2543Smrg	    if (nval > 0) {
1358706f2543Smrg		(ev - 1)->deviceid |= MORE_EVENTS;
1359706f2543Smrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1360706f2543Smrg		first += 3;
1361706f2543Smrg		nval -= 3;
1362706f2543Smrg	    }
1363706f2543Smrg	}
1364706f2543Smrg
1365706f2543Smrg	while (nval > 0) {
1366706f2543Smrg	    FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
1367706f2543Smrg	    first += 3;
1368706f2543Smrg	    nval -= 3;
1369706f2543Smrg	    if (nval > 0) {
1370706f2543Smrg		(ev - 1)->deviceid |= MORE_EVENTS;
1371706f2543Smrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1372706f2543Smrg		first += 3;
1373706f2543Smrg		nval -= 3;
1374706f2543Smrg	    }
1375706f2543Smrg	}
1376706f2543Smrg
1377706f2543Smrg	DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
1378706f2543Smrg				    DeviceStateNotifyMask, NullGrab);
1379706f2543Smrg	free(sev);
1380706f2543Smrg    }
1381706f2543Smrg}
1382706f2543Smrg
1383706f2543Smrgint
1384706f2543SmrgCheckGrabValues(ClientPtr client, GrabParameters* param)
1385706f2543Smrg{
1386706f2543Smrg    if (param->grabtype != GRABTYPE_CORE &&
1387706f2543Smrg        param->grabtype != GRABTYPE_XI &&
1388706f2543Smrg        param->grabtype != GRABTYPE_XI2)
1389706f2543Smrg    {
1390706f2543Smrg        ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
1391706f2543Smrg        return BadImplementation;
1392706f2543Smrg    }
1393706f2543Smrg
1394706f2543Smrg    if ((param->this_device_mode != GrabModeSync) &&
1395706f2543Smrg	(param->this_device_mode != GrabModeAsync)) {
1396706f2543Smrg	client->errorValue = param->this_device_mode;
1397706f2543Smrg	return BadValue;
1398706f2543Smrg    }
1399706f2543Smrg    if ((param->other_devices_mode != GrabModeSync) &&
1400706f2543Smrg	(param->other_devices_mode != GrabModeAsync)) {
1401706f2543Smrg	client->errorValue = param->other_devices_mode;
1402706f2543Smrg	return BadValue;
1403706f2543Smrg    }
1404706f2543Smrg
1405706f2543Smrg    if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
1406706f2543Smrg        (param->modifiers & ~AllModifiersMask)) {
1407706f2543Smrg	client->errorValue = param->modifiers;
1408706f2543Smrg	return BadValue;
1409706f2543Smrg    }
1410706f2543Smrg
1411706f2543Smrg    if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
1412706f2543Smrg	client->errorValue = param->ownerEvents;
1413706f2543Smrg	return BadValue;
1414706f2543Smrg    }
1415706f2543Smrg    return Success;
1416706f2543Smrg}
1417706f2543Smrg
1418706f2543Smrgint
1419706f2543SmrgGrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
1420706f2543Smrg           int button, GrabParameters *param, GrabType grabtype,
1421706f2543Smrg	   GrabMask *mask)
1422706f2543Smrg{
1423706f2543Smrg    WindowPtr pWin, confineTo;
1424706f2543Smrg    CursorPtr cursor;
1425706f2543Smrg    GrabPtr grab;
1426706f2543Smrg    int rc, type = -1;
1427706f2543Smrg    Mask access_mode = DixGrabAccess;
1428706f2543Smrg
1429706f2543Smrg    rc = CheckGrabValues(client, param);
1430706f2543Smrg    if (rc != Success)
1431706f2543Smrg	return rc;
1432706f2543Smrg    if (param->confineTo == None)
1433706f2543Smrg	confineTo = NullWindow;
1434706f2543Smrg    else {
1435706f2543Smrg	rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
1436706f2543Smrg	if (rc != Success)
1437706f2543Smrg	    return rc;
1438706f2543Smrg    }
1439706f2543Smrg    if (param->cursor == None)
1440706f2543Smrg	cursor = NullCursor;
1441706f2543Smrg    else {
1442706f2543Smrg	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
1443706f2543Smrg				     RT_CURSOR, client, DixUseAccess);
1444706f2543Smrg	if (rc != Success)
1445706f2543Smrg	{
1446706f2543Smrg	    client->errorValue = param->cursor;
1447706f2543Smrg	    return rc;
1448706f2543Smrg	}
1449706f2543Smrg	access_mode |= DixForceAccess;
1450706f2543Smrg    }
1451706f2543Smrg    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1452706f2543Smrg	access_mode |= DixFreezeAccess;
1453706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1454706f2543Smrg    if (rc != Success)
1455706f2543Smrg	return rc;
1456706f2543Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1457706f2543Smrg    if (rc != Success)
1458706f2543Smrg	return rc;
1459706f2543Smrg
1460706f2543Smrg    if (grabtype == GRABTYPE_XI)
1461706f2543Smrg        type = DeviceButtonPress;
1462706f2543Smrg    else if (grabtype == GRABTYPE_XI2)
1463706f2543Smrg        type = XI_ButtonPress;
1464706f2543Smrg
1465706f2543Smrg    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
1466706f2543Smrg                      mask, param, type, button, confineTo, cursor);
1467706f2543Smrg    if (!grab)
1468706f2543Smrg	return BadAlloc;
1469706f2543Smrg    return AddPassiveGrabToList(client, grab);
1470706f2543Smrg}
1471706f2543Smrg
1472706f2543Smrg/**
1473706f2543Smrg * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If
1474706f2543Smrg * grabtype is GRABTYPE_XI2, the key is a keysym.
1475706f2543Smrg */
1476706f2543Smrgint
1477706f2543SmrgGrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
1478706f2543Smrg        int key, GrabParameters *param, GrabType grabtype, GrabMask *mask)
1479706f2543Smrg{
1480706f2543Smrg    WindowPtr pWin;
1481706f2543Smrg    GrabPtr grab;
1482706f2543Smrg    KeyClassPtr k = dev->key;
1483706f2543Smrg    Mask access_mode = DixGrabAccess;
1484706f2543Smrg    int rc, type = -1;
1485706f2543Smrg
1486706f2543Smrg    rc = CheckGrabValues(client, param);
1487706f2543Smrg    if (rc != Success)
1488706f2543Smrg        return rc;
1489706f2543Smrg    if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL)
1490706f2543Smrg	return BadMatch;
1491706f2543Smrg    if (grabtype == GRABTYPE_XI)
1492706f2543Smrg    {
1493706f2543Smrg        if ((key > k->xkbInfo->desc->max_key_code ||
1494706f2543Smrg                    key < k->xkbInfo->desc->min_key_code)
1495706f2543Smrg                && (key != AnyKey)) {
1496706f2543Smrg            client->errorValue = key;
1497706f2543Smrg            return BadValue;
1498706f2543Smrg        }
1499706f2543Smrg        type = DeviceKeyPress;
1500706f2543Smrg    } else if (grabtype == GRABTYPE_XI2)
1501706f2543Smrg        type = XI_KeyPress;
1502706f2543Smrg
1503706f2543Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1504706f2543Smrg    if (rc != Success)
1505706f2543Smrg	return rc;
1506706f2543Smrg    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1507706f2543Smrg	access_mode |= DixFreezeAccess;
1508706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1509706f2543Smrg    if (rc != Success)
1510706f2543Smrg	return rc;
1511706f2543Smrg
1512706f2543Smrg    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
1513706f2543Smrg                      mask, param, type, key, NULL, NULL);
1514706f2543Smrg    if (!grab)
1515706f2543Smrg	return BadAlloc;
1516706f2543Smrg    return AddPassiveGrabToList(client, grab);
1517706f2543Smrg}
1518706f2543Smrg
1519706f2543Smrg/* Enter/FocusIn grab */
1520706f2543Smrgint
1521706f2543SmrgGrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
1522706f2543Smrg           GrabParameters *param, GrabMask *mask)
1523706f2543Smrg{
1524706f2543Smrg    WindowPtr pWin;
1525706f2543Smrg    CursorPtr cursor;
1526706f2543Smrg    GrabPtr grab;
1527706f2543Smrg    Mask access_mode = DixGrabAccess;
1528706f2543Smrg    int rc;
1529706f2543Smrg
1530706f2543Smrg    rc = CheckGrabValues(client, param);
1531706f2543Smrg    if (rc != Success)
1532706f2543Smrg        return rc;
1533706f2543Smrg
1534706f2543Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1535706f2543Smrg    if (rc != Success)
1536706f2543Smrg	return rc;
1537706f2543Smrg    if (param->cursor == None)
1538706f2543Smrg	cursor = NullCursor;
1539706f2543Smrg    else {
1540706f2543Smrg	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
1541706f2543Smrg				     RT_CURSOR, client, DixUseAccess);
1542706f2543Smrg	if (rc != Success)
1543706f2543Smrg	{
1544706f2543Smrg	    client->errorValue = param->cursor;
1545706f2543Smrg	    return rc;
1546706f2543Smrg	}
1547706f2543Smrg	access_mode |= DixForceAccess;
1548706f2543Smrg    }
1549706f2543Smrg    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1550706f2543Smrg	access_mode |= DixFreezeAccess;
1551706f2543Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1552706f2543Smrg    if (rc != Success)
1553706f2543Smrg	return rc;
1554706f2543Smrg
1555706f2543Smrg    grab = CreateGrab(client->index, dev, dev, pWin, GRABTYPE_XI2,
1556706f2543Smrg                      mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
1557706f2543Smrg                      0, NULL, cursor);
1558706f2543Smrg
1559706f2543Smrg    if (!grab)
1560706f2543Smrg        return BadAlloc;
1561706f2543Smrg
1562706f2543Smrg    return AddPassiveGrabToList(client, grab);
1563706f2543Smrg}
1564706f2543Smrg
1565706f2543Smrgint
1566706f2543SmrgSelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
1567706f2543Smrg		Mask mask, Mask exclusivemasks)
1568706f2543Smrg{
1569706f2543Smrg    int mskidx = dev->id;
1570706f2543Smrg    int i, ret;
1571706f2543Smrg    Mask check;
1572706f2543Smrg    InputClientsPtr others;
1573706f2543Smrg
1574706f2543Smrg    check = (mask & exclusivemasks);
1575706f2543Smrg    if (wOtherInputMasks(pWin)) {
1576706f2543Smrg	if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {	/* It is illegal for two different
1577706f2543Smrg									 * clients to select on any of the
1578706f2543Smrg									 * events for maskcheck. However,
1579706f2543Smrg									 * it is OK, for some client to
1580706f2543Smrg									 * continue selecting on one of those
1581706f2543Smrg									 * events.  */
1582706f2543Smrg	    for (others = wOtherInputMasks(pWin)->inputClients; others;
1583706f2543Smrg		 others = others->next) {
1584706f2543Smrg		if (!SameClient(others, client) && (check &
1585706f2543Smrg						    others->mask[mskidx]))
1586706f2543Smrg		    return BadAccess;
1587706f2543Smrg	    }
1588706f2543Smrg	}
1589706f2543Smrg	for (others = wOtherInputMasks(pWin)->inputClients; others;
1590706f2543Smrg	     others = others->next) {
1591706f2543Smrg	    if (SameClient(others, client)) {
1592706f2543Smrg		check = others->mask[mskidx];
1593706f2543Smrg		others->mask[mskidx] = mask;
1594706f2543Smrg		if (mask == 0) {
1595706f2543Smrg		    for (i = 0; i < EMASKSIZE; i++)
1596706f2543Smrg			if (i != mskidx && others->mask[i] != 0)
1597706f2543Smrg			    break;
1598706f2543Smrg		    if (i == EMASKSIZE) {
1599706f2543Smrg			RecalculateDeviceDeliverableEvents(pWin);
1600706f2543Smrg			if (ShouldFreeInputMasks(pWin, FALSE))
1601706f2543Smrg			    FreeResource(others->resource, RT_NONE);
1602706f2543Smrg			return Success;
1603706f2543Smrg		    }
1604706f2543Smrg		}
1605706f2543Smrg		goto maskSet;
1606706f2543Smrg	    }
1607706f2543Smrg	}
1608706f2543Smrg    }
1609706f2543Smrg    check = 0;
1610706f2543Smrg    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
1611706f2543Smrg	return ret;
1612706f2543Smrg  maskSet:
1613706f2543Smrg    if (dev->valuator)
1614706f2543Smrg	if ((dev->valuator->motionHintWindow == pWin) &&
1615706f2543Smrg	    (mask & DevicePointerMotionHintMask) &&
1616706f2543Smrg	    !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
1617706f2543Smrg	    dev->valuator->motionHintWindow = NullWindow;
1618706f2543Smrg    RecalculateDeviceDeliverableEvents(pWin);
1619706f2543Smrg    return Success;
1620706f2543Smrg}
1621706f2543Smrg
1622706f2543Smrgint
1623706f2543SmrgAddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
1624706f2543Smrg{
1625706f2543Smrg    InputClientsPtr others;
1626706f2543Smrg
1627706f2543Smrg    if (!pWin->optional && !MakeWindowOptional(pWin))
1628706f2543Smrg	return BadAlloc;
1629706f2543Smrg    others = calloc(1, sizeof(InputClients));
1630706f2543Smrg    if (!others)
1631706f2543Smrg	return BadAlloc;
1632706f2543Smrg    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
1633706f2543Smrg	goto bail;
1634706f2543Smrg    others->mask[mskidx] = mask;
1635706f2543Smrg    others->resource = FakeClientID(client->index);
1636706f2543Smrg    others->next = pWin->optional->inputMasks->inputClients;
1637706f2543Smrg    pWin->optional->inputMasks->inputClients = others;
1638706f2543Smrg    if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
1639706f2543Smrg	goto bail;
1640706f2543Smrg    return Success;
1641706f2543Smrg
1642706f2543Smrgbail:
1643706f2543Smrg    free(others);
1644706f2543Smrg    return BadAlloc;
1645706f2543Smrg}
1646706f2543Smrg
1647706f2543Smrgstatic Bool
1648706f2543SmrgMakeInputMasks(WindowPtr pWin)
1649706f2543Smrg{
1650706f2543Smrg    struct _OtherInputMasks *imasks;
1651706f2543Smrg
1652706f2543Smrg    imasks = calloc(1, sizeof(struct _OtherInputMasks));
1653706f2543Smrg    if (!imasks)
1654706f2543Smrg	return FALSE;
1655706f2543Smrg    pWin->optional->inputMasks = imasks;
1656706f2543Smrg    return TRUE;
1657706f2543Smrg}
1658706f2543Smrg
1659706f2543Smrgvoid
1660706f2543SmrgRecalculateDeviceDeliverableEvents(WindowPtr pWin)
1661706f2543Smrg{
1662706f2543Smrg    InputClientsPtr others;
1663706f2543Smrg    struct _OtherInputMasks *inputMasks;	/* default: NULL */
1664706f2543Smrg    WindowPtr pChild, tmp;
1665706f2543Smrg    int i, j;
1666706f2543Smrg
1667706f2543Smrg    pChild = pWin;
1668706f2543Smrg    while (1) {
1669706f2543Smrg	if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
1670706f2543Smrg            for (i = 0; i < EMASKSIZE; i++)
1671706f2543Smrg                memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i]));
1672706f2543Smrg	    for (others = inputMasks->inputClients; others;
1673706f2543Smrg		 others = others->next) {
1674706f2543Smrg		for (i = 0; i < EMASKSIZE; i++)
1675706f2543Smrg		    inputMasks->inputEvents[i] |= others->mask[i];
1676706f2543Smrg                for (i = 0; i < EMASKSIZE; i++)
1677706f2543Smrg                    for (j = 0; j < XI2MASKSIZE; j++)
1678706f2543Smrg                        inputMasks->xi2mask[i][j] |= others->xi2mask[i][j];
1679706f2543Smrg	    }
1680706f2543Smrg	    for (i = 0; i < EMASKSIZE; i++)
1681706f2543Smrg		inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
1682706f2543Smrg	    for (tmp = pChild->parent; tmp; tmp = tmp->parent)
1683706f2543Smrg		if (wOtherInputMasks(tmp))
1684706f2543Smrg		    for (i = 0; i < EMASKSIZE; i++)
1685706f2543Smrg			inputMasks->deliverableEvents[i] |=
1686706f2543Smrg			    (wOtherInputMasks(tmp)->deliverableEvents[i]
1687706f2543Smrg			     & ~inputMasks->
1688706f2543Smrg			     dontPropagateMask[i] & PropagateMask[i]);
1689706f2543Smrg	}
1690706f2543Smrg	if (pChild->firstChild) {
1691706f2543Smrg	    pChild = pChild->firstChild;
1692706f2543Smrg	    continue;
1693706f2543Smrg	}
1694706f2543Smrg	while (!pChild->nextSib && (pChild != pWin))
1695706f2543Smrg	    pChild = pChild->parent;
1696706f2543Smrg	if (pChild == pWin)
1697706f2543Smrg	    break;
1698706f2543Smrg	pChild = pChild->nextSib;
1699706f2543Smrg    }
1700706f2543Smrg}
1701706f2543Smrg
1702706f2543Smrgint
1703706f2543SmrgInputClientGone(WindowPtr pWin, XID id)
1704706f2543Smrg{
1705706f2543Smrg    InputClientsPtr other, prev;
1706706f2543Smrg
1707706f2543Smrg    if (!wOtherInputMasks(pWin))
1708706f2543Smrg	return Success;
1709706f2543Smrg    prev = 0;
1710706f2543Smrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
1711706f2543Smrg	 other = other->next) {
1712706f2543Smrg	if (other->resource == id) {
1713706f2543Smrg	    if (prev) {
1714706f2543Smrg		prev->next = other->next;
1715706f2543Smrg		free(other);
1716706f2543Smrg	    } else if (!(other->next)) {
1717706f2543Smrg		if (ShouldFreeInputMasks(pWin, TRUE)) {
1718706f2543Smrg		    wOtherInputMasks(pWin)->inputClients = other->next;
1719706f2543Smrg		    free(wOtherInputMasks(pWin));
1720706f2543Smrg		    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
1721706f2543Smrg		    CheckWindowOptionalNeed(pWin);
1722706f2543Smrg		    free(other);
1723706f2543Smrg		} else {
1724706f2543Smrg		    other->resource = FakeClientID(0);
1725706f2543Smrg		    if (!AddResource(other->resource, RT_INPUTCLIENT,
1726706f2543Smrg				     (pointer) pWin))
1727706f2543Smrg			return BadAlloc;
1728706f2543Smrg		}
1729706f2543Smrg	    } else {
1730706f2543Smrg		wOtherInputMasks(pWin)->inputClients = other->next;
1731706f2543Smrg		free(other);
1732706f2543Smrg	    }
1733706f2543Smrg	    RecalculateDeviceDeliverableEvents(pWin);
1734706f2543Smrg	    return Success;
1735706f2543Smrg	}
1736706f2543Smrg	prev = other;
1737706f2543Smrg    }
1738706f2543Smrg    FatalError("client not on device event list");
1739706f2543Smrg}
1740706f2543Smrg
1741706f2543Smrgint
1742706f2543SmrgSendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
1743706f2543Smrg	  xEvent * ev, Mask mask, int count)
1744706f2543Smrg{
1745706f2543Smrg    WindowPtr pWin;
1746706f2543Smrg    WindowPtr effectiveFocus = NullWindow;	/* only set if dest==InputFocus */
1747706f2543Smrg    WindowPtr spriteWin = GetSpriteWindow(d);
1748706f2543Smrg
1749706f2543Smrg    if (dest == PointerWindow)
1750706f2543Smrg	pWin = spriteWin;
1751706f2543Smrg    else if (dest == InputFocus) {
1752706f2543Smrg	WindowPtr inputFocus;
1753706f2543Smrg
1754706f2543Smrg	if (!d->focus)
1755706f2543Smrg	    inputFocus = spriteWin;
1756706f2543Smrg	else
1757706f2543Smrg	    inputFocus = d->focus->win;
1758706f2543Smrg
1759706f2543Smrg	if (inputFocus == FollowKeyboardWin)
1760706f2543Smrg	    inputFocus = inputInfo.keyboard->focus->win;
1761706f2543Smrg
1762706f2543Smrg	if (inputFocus == NoneWin)
1763706f2543Smrg	    return Success;
1764706f2543Smrg
1765706f2543Smrg	/* If the input focus is PointerRootWin, send the event to where
1766706f2543Smrg	 * the pointer is if possible, then perhaps propogate up to root. */
1767706f2543Smrg	if (inputFocus == PointerRootWin)
1768706f2543Smrg	    inputFocus = GetCurrentRootWindow(d);
1769706f2543Smrg
1770706f2543Smrg	if (IsParent(inputFocus, spriteWin)) {
1771706f2543Smrg	    effectiveFocus = inputFocus;
1772706f2543Smrg	    pWin = spriteWin;
1773706f2543Smrg	} else
1774706f2543Smrg	    effectiveFocus = pWin = inputFocus;
1775706f2543Smrg    } else
1776706f2543Smrg	dixLookupWindow(&pWin, dest, client, DixSendAccess);
1777706f2543Smrg    if (!pWin)
1778706f2543Smrg	return BadWindow;
1779706f2543Smrg    if ((propagate != xFalse) && (propagate != xTrue)) {
1780706f2543Smrg	client->errorValue = propagate;
1781706f2543Smrg	return BadValue;
1782706f2543Smrg    }
1783706f2543Smrg    ev->u.u.type |= 0x80;
1784706f2543Smrg    if (propagate) {
1785706f2543Smrg	for (; pWin; pWin = pWin->parent) {
1786706f2543Smrg	    if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
1787706f2543Smrg		return Success;
1788706f2543Smrg	    if (pWin == effectiveFocus)
1789706f2543Smrg		return Success;
1790706f2543Smrg	    if (wOtherInputMasks(pWin))
1791706f2543Smrg		mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
1792706f2543Smrg	    if (!mask)
1793706f2543Smrg		break;
1794706f2543Smrg	}
1795706f2543Smrg    } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
1796706f2543Smrg	DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
1797706f2543Smrg    return Success;
1798706f2543Smrg}
1799706f2543Smrg
1800706f2543Smrgint
1801706f2543SmrgSetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
1802706f2543Smrg{
1803706f2543Smrg    int i;
1804706f2543Smrg    ButtonClassPtr b = dev->button;
1805706f2543Smrg
1806706f2543Smrg    if (b == NULL)
1807706f2543Smrg	return BadMatch;
1808706f2543Smrg
1809706f2543Smrg    if (nElts != b->numButtons) {
1810706f2543Smrg	client->errorValue = nElts;
1811706f2543Smrg	return BadValue;
1812706f2543Smrg    }
1813706f2543Smrg    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
1814706f2543Smrg	return BadValue;
1815706f2543Smrg    for (i = 0; i < nElts; i++)
1816706f2543Smrg	if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
1817706f2543Smrg	    return MappingBusy;
1818706f2543Smrg    for (i = 0; i < nElts; i++)
1819706f2543Smrg	b->map[i + 1] = map[i];
1820706f2543Smrg    return Success;
1821706f2543Smrg}
1822706f2543Smrg
1823706f2543Smrgint
1824706f2543SmrgChangeKeyMapping(ClientPtr client,
1825706f2543Smrg		 DeviceIntPtr dev,
1826706f2543Smrg		 unsigned len,
1827706f2543Smrg		 int type,
1828706f2543Smrg		 KeyCode firstKeyCode,
1829706f2543Smrg		 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
1830706f2543Smrg{
1831706f2543Smrg    KeySymsRec keysyms;
1832706f2543Smrg    KeyClassPtr k = dev->key;
1833706f2543Smrg
1834706f2543Smrg    if (k == NULL)
1835706f2543Smrg	return BadMatch;
1836706f2543Smrg
1837706f2543Smrg    if (len != (keyCodes * keySymsPerKeyCode))
1838706f2543Smrg	return BadLength;
1839706f2543Smrg
1840706f2543Smrg    if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
1841706f2543Smrg	(firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
1842706f2543Smrg	client->errorValue = firstKeyCode;
1843706f2543Smrg	return BadValue;
1844706f2543Smrg    }
1845706f2543Smrg    if (keySymsPerKeyCode == 0) {
1846706f2543Smrg	client->errorValue = 0;
1847706f2543Smrg	return BadValue;
1848706f2543Smrg    }
1849706f2543Smrg    keysyms.minKeyCode = firstKeyCode;
1850706f2543Smrg    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
1851706f2543Smrg    keysyms.mapWidth = keySymsPerKeyCode;
1852706f2543Smrg    keysyms.map = map;
1853706f2543Smrg
1854706f2543Smrg    XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
1855706f2543Smrg                          serverClient);
1856706f2543Smrg
1857706f2543Smrg    return Success;
1858706f2543Smrg}
1859706f2543Smrg
1860706f2543Smrgstatic void
1861706f2543SmrgDeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
1862706f2543Smrg{
1863706f2543Smrg    WindowPtr parent;
1864706f2543Smrg
1865706f2543Smrg    /* Deactivate any grabs performed on this window, before making
1866706f2543Smrg     * any input focus changes.
1867706f2543Smrg     * Deactivating a device grab should cause focus events. */
1868706f2543Smrg
1869706f2543Smrg    if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
1870706f2543Smrg	(*dev->deviceGrab.DeactivateGrab) (dev);
1871706f2543Smrg
1872706f2543Smrg    /* If the focus window is a root window (ie. has no parent)
1873706f2543Smrg     * then don't delete the focus from it. */
1874706f2543Smrg
1875706f2543Smrg    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
1876706f2543Smrg	int focusEventMode = NotifyNormal;
1877706f2543Smrg
1878706f2543Smrg	/* If a grab is in progress, then alter the mode of focus events. */
1879706f2543Smrg
1880706f2543Smrg	if (dev->deviceGrab.grab)
1881706f2543Smrg	    focusEventMode = NotifyWhileGrabbed;
1882706f2543Smrg
1883706f2543Smrg	switch (dev->focus->revert) {
1884706f2543Smrg	case RevertToNone:
1885706f2543Smrg	    if (!ActivateFocusInGrab(dev, pWin, NoneWin))
1886706f2543Smrg		DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1887706f2543Smrg	    dev->focus->win = NoneWin;
1888706f2543Smrg	    dev->focus->traceGood = 0;
1889706f2543Smrg	    break;
1890706f2543Smrg	case RevertToParent:
1891706f2543Smrg	    parent = pWin;
1892706f2543Smrg	    do {
1893706f2543Smrg		parent = parent->parent;
1894706f2543Smrg		dev->focus->traceGood--;
1895706f2543Smrg	    }
1896706f2543Smrg	    while (!parent->realized);
1897706f2543Smrg	    if (!ActivateFocusInGrab(dev, pWin, parent))
1898706f2543Smrg		DoFocusEvents(dev, pWin, parent, focusEventMode);
1899706f2543Smrg	    dev->focus->win = parent;
1900706f2543Smrg	    dev->focus->revert = RevertToNone;
1901706f2543Smrg	    break;
1902706f2543Smrg	case RevertToPointerRoot:
1903706f2543Smrg	    if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
1904706f2543Smrg		DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
1905706f2543Smrg	    dev->focus->win = PointerRootWin;
1906706f2543Smrg	    dev->focus->traceGood = 0;
1907706f2543Smrg	    break;
1908706f2543Smrg	case RevertToFollowKeyboard:
1909706f2543Smrg            {
1910706f2543Smrg                DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
1911706f2543Smrg                if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
1912706f2543Smrg                    kbd = inputInfo.keyboard;
1913706f2543Smrg	    if (kbd->focus->win) {
1914706f2543Smrg		if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
1915706f2543Smrg		    DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
1916706f2543Smrg		dev->focus->win = FollowKeyboardWin;
1917706f2543Smrg		dev->focus->traceGood = 0;
1918706f2543Smrg	    } else {
1919706f2543Smrg                if (!ActivateFocusInGrab(dev, pWin, NoneWin))
1920706f2543Smrg                    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1921706f2543Smrg		dev->focus->win = NoneWin;
1922706f2543Smrg		dev->focus->traceGood = 0;
1923706f2543Smrg	    }
1924706f2543Smrg            }
1925706f2543Smrg	    break;
1926706f2543Smrg	}
1927706f2543Smrg    }
1928706f2543Smrg
1929706f2543Smrg    if (dev->valuator)
1930706f2543Smrg	if (dev->valuator->motionHintWindow == pWin)
1931706f2543Smrg	    dev->valuator->motionHintWindow = NullWindow;
1932706f2543Smrg}
1933706f2543Smrg
1934706f2543Smrgvoid
1935706f2543SmrgDeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
1936706f2543Smrg{
1937706f2543Smrg    int i;
1938706f2543Smrg    DeviceIntPtr dev;
1939706f2543Smrg    InputClientsPtr ic;
1940706f2543Smrg    struct _OtherInputMasks *inputMasks;
1941706f2543Smrg
1942706f2543Smrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
1943706f2543Smrg	DeleteDeviceFromAnyExtEvents(pWin, dev);
1944706f2543Smrg    }
1945706f2543Smrg
1946706f2543Smrg    for (dev = inputInfo.off_devices; dev; dev = dev->next)
1947706f2543Smrg	DeleteDeviceFromAnyExtEvents(pWin, dev);
1948706f2543Smrg
1949706f2543Smrg    if (freeResources)
1950706f2543Smrg	while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
1951706f2543Smrg	    ic = inputMasks->inputClients;
1952706f2543Smrg	    for (i = 0; i < EMASKSIZE; i++)
1953706f2543Smrg		inputMasks->dontPropagateMask[i] = 0;
1954706f2543Smrg	    FreeResource(ic->resource, RT_NONE);
1955706f2543Smrg	}
1956706f2543Smrg}
1957706f2543Smrg
1958706f2543Smrgint
1959706f2543SmrgMaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
1960706f2543Smrg{
1961706f2543Smrg    DeviceIntPtr dev;
1962706f2543Smrg
1963706f2543Smrg    dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
1964706f2543Smrg		    DixReadAccess);
1965706f2543Smrg    if (!dev)
1966706f2543Smrg        return 0;
1967706f2543Smrg
1968706f2543Smrg    if (pEvents->type == DeviceMotionNotify) {
1969706f2543Smrg	if (mask & DevicePointerMotionHintMask) {
1970706f2543Smrg	    if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
1971706f2543Smrg		return 1;	/* don't send, but pretend we did */
1972706f2543Smrg	    }
1973706f2543Smrg	    pEvents->detail = NotifyHint;
1974706f2543Smrg	} else {
1975706f2543Smrg	    pEvents->detail = NotifyNormal;
1976706f2543Smrg	}
1977706f2543Smrg    }
1978706f2543Smrg    return 0;
1979706f2543Smrg}
1980706f2543Smrg
1981706f2543Smrgvoid
1982706f2543SmrgCheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
1983706f2543Smrg			     deviceKeyButtonPointer * xE, GrabPtr grab,
1984706f2543Smrg			     ClientPtr client, Mask deliveryMask)
1985706f2543Smrg{
1986706f2543Smrg    DeviceIntPtr dev;
1987706f2543Smrg
1988706f2543Smrg    dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
1989706f2543Smrg		    DixGrabAccess);
1990706f2543Smrg    if (!dev)
1991706f2543Smrg        return;
1992706f2543Smrg
1993706f2543Smrg    if (type == DeviceMotionNotify)
1994706f2543Smrg	dev->valuator->motionHintWindow = pWin;
1995706f2543Smrg    else if ((type == DeviceButtonPress) && (!grab) &&
1996706f2543Smrg	     (deliveryMask & DeviceButtonGrabMask)) {
1997706f2543Smrg	GrabRec tempGrab;
1998706f2543Smrg
1999706f2543Smrg	tempGrab.device = dev;
2000706f2543Smrg	tempGrab.resource = client->clientAsMask;
2001706f2543Smrg	tempGrab.window = pWin;
2002706f2543Smrg	tempGrab.ownerEvents =
2003706f2543Smrg	    (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
2004706f2543Smrg	tempGrab.eventMask = deliveryMask;
2005706f2543Smrg	tempGrab.keyboardMode = GrabModeAsync;
2006706f2543Smrg	tempGrab.pointerMode = GrabModeAsync;
2007706f2543Smrg	tempGrab.confineTo = NullWindow;
2008706f2543Smrg	tempGrab.cursor = NullCursor;
2009706f2543Smrg        tempGrab.next = NULL;
2010706f2543Smrg	(*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
2011706f2543Smrg    }
2012706f2543Smrg}
2013706f2543Smrg
2014706f2543Smrgstatic Mask
2015706f2543SmrgDeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
2016706f2543Smrg{
2017706f2543Smrg    InputClientsPtr other;
2018706f2543Smrg
2019706f2543Smrg    if (!wOtherInputMasks(pWin))
2020706f2543Smrg	return 0;
2021706f2543Smrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
2022706f2543Smrg	 other = other->next) {
2023706f2543Smrg	if (SameClient(other, client))
2024706f2543Smrg	    return other->mask[dev->id];
2025706f2543Smrg    }
2026706f2543Smrg    return 0;
2027706f2543Smrg}
2028706f2543Smrg
2029706f2543Smrgvoid
2030706f2543SmrgMaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
2031706f2543Smrg{
2032706f2543Smrg    WindowPtr pWin;
2033706f2543Smrg    GrabPtr grab = dev->deviceGrab.grab;
2034706f2543Smrg
2035706f2543Smrg    pWin = dev->valuator->motionHintWindow;
2036706f2543Smrg
2037706f2543Smrg    if ((grab && SameClient(grab, client) &&
2038706f2543Smrg	 ((grab->eventMask & DevicePointerMotionHintMask) ||
2039706f2543Smrg	  (grab->ownerEvents &&
2040706f2543Smrg	   (DeviceEventMaskForClient(dev, pWin, client) &
2041706f2543Smrg	    DevicePointerMotionHintMask)))) ||
2042706f2543Smrg	(!grab &&
2043706f2543Smrg	 (DeviceEventMaskForClient(dev, pWin, client) &
2044706f2543Smrg	  DevicePointerMotionHintMask)))
2045706f2543Smrg	dev->valuator->motionHintWindow = NullWindow;
2046706f2543Smrg}
2047706f2543Smrg
2048706f2543Smrgint
2049706f2543SmrgDeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
2050706f2543Smrg			     int maskndx)
2051706f2543Smrg{
2052706f2543Smrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2053706f2543Smrg
2054706f2543Smrg    if (mask & ~PropagateMask[maskndx]) {
2055706f2543Smrg	client->errorValue = mask;
2056706f2543Smrg	return BadValue;
2057706f2543Smrg    }
2058706f2543Smrg
2059706f2543Smrg    if (mask == 0) {
2060706f2543Smrg	if (inputMasks)
2061706f2543Smrg	    inputMasks->dontPropagateMask[maskndx] = mask;
2062706f2543Smrg    } else {
2063706f2543Smrg	if (!inputMasks)
2064706f2543Smrg	    AddExtensionClient(pWin, client, 0, 0);
2065706f2543Smrg	inputMasks = wOtherInputMasks(pWin);
2066706f2543Smrg	inputMasks->dontPropagateMask[maskndx] = mask;
2067706f2543Smrg    }
2068706f2543Smrg    RecalculateDeviceDeliverableEvents(pWin);
2069706f2543Smrg    if (ShouldFreeInputMasks(pWin, FALSE))
2070706f2543Smrg	FreeResource(inputMasks->inputClients->resource, RT_NONE);
2071706f2543Smrg    return Success;
2072706f2543Smrg}
2073706f2543Smrg
2074706f2543SmrgBool
2075706f2543SmrgShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
2076706f2543Smrg{
2077706f2543Smrg    int i;
2078706f2543Smrg    Mask allInputEventMasks = 0;
2079706f2543Smrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2080706f2543Smrg
2081706f2543Smrg    for (i = 0; i < EMASKSIZE; i++)
2082706f2543Smrg	allInputEventMasks |= inputMasks->dontPropagateMask[i];
2083706f2543Smrg    if (!ignoreSelectedEvents)
2084706f2543Smrg	for (i = 0; i < EMASKSIZE; i++)
2085706f2543Smrg	    allInputEventMasks |= inputMasks->inputEvents[i];
2086706f2543Smrg    if (allInputEventMasks == 0)
2087706f2543Smrg	return TRUE;
2088706f2543Smrg    else
2089706f2543Smrg	return FALSE;
2090706f2543Smrg}
2091706f2543Smrg
2092706f2543Smrg/***********************************************************************
2093706f2543Smrg *
2094706f2543Smrg * Walk through the window tree, finding all clients that want to know
2095706f2543Smrg * about the Event.
2096706f2543Smrg *
2097706f2543Smrg */
2098706f2543Smrg
2099706f2543Smrgstatic void
2100706f2543SmrgFindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
2101706f2543Smrg                       xEvent * ev, int count)
2102706f2543Smrg{
2103706f2543Smrg    WindowPtr p2;
2104706f2543Smrg
2105706f2543Smrg    while (p1) {
2106706f2543Smrg        p2 = p1->firstChild;
2107706f2543Smrg        DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
2108706f2543Smrg        FindInterestedChildren(dev, p2, mask, ev, count);
2109706f2543Smrg        p1 = p1->nextSib;
2110706f2543Smrg    }
2111706f2543Smrg}
2112706f2543Smrg
2113706f2543Smrg/***********************************************************************
2114706f2543Smrg *
2115706f2543Smrg * Send an event to interested clients in all windows on all screens.
2116706f2543Smrg *
2117706f2543Smrg */
2118706f2543Smrg
2119706f2543Smrgvoid
2120706f2543SmrgSendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
2121706f2543Smrg{
2122706f2543Smrg    int i;
2123706f2543Smrg    WindowPtr pWin, p1;
2124706f2543Smrg
2125706f2543Smrg    for (i = 0; i < screenInfo.numScreens; i++) {
2126706f2543Smrg        pWin = screenInfo.screens[i]->root;
2127706f2543Smrg        if (!pWin)
2128706f2543Smrg            continue;
2129706f2543Smrg        DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
2130706f2543Smrg        p1 = pWin->firstChild;
2131706f2543Smrg        FindInterestedChildren(dev, p1, mask, ev, count);
2132706f2543Smrg    }
2133706f2543Smrg}
2134706f2543Smrg
2135706f2543Smrg/**
2136706f2543Smrg * Set the XI2 mask for the given client on the given window.
2137706f2543Smrg * @param dev The device to set the mask for.
2138706f2543Smrg * @param win The window to set the mask on.
2139706f2543Smrg * @param client The client setting the mask.
2140706f2543Smrg * @param len Number of bytes in mask.
2141706f2543Smrg * @param mask Event mask in the form of (1 << eventtype)
2142706f2543Smrg */
2143706f2543Smrgint
2144706f2543SmrgXISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
2145706f2543Smrg               unsigned int len, unsigned char* mask)
2146706f2543Smrg{
2147706f2543Smrg    OtherInputMasks *masks;
2148706f2543Smrg    InputClientsPtr others = NULL;
2149706f2543Smrg
2150706f2543Smrg    masks = wOtherInputMasks(win);
2151706f2543Smrg    if (masks)
2152706f2543Smrg    {
2153706f2543Smrg	for (others = wOtherInputMasks(win)->inputClients; others;
2154706f2543Smrg	     others = others->next) {
2155706f2543Smrg	    if (SameClient(others, client)) {
2156706f2543Smrg                memset(others->xi2mask[dev->id], 0,
2157706f2543Smrg                       sizeof(others->xi2mask[dev->id]));
2158706f2543Smrg                break;
2159706f2543Smrg            }
2160706f2543Smrg        }
2161706f2543Smrg    }
2162706f2543Smrg
2163706f2543Smrg    len = min(len, sizeof(others->xi2mask[dev->id]));
2164706f2543Smrg
2165706f2543Smrg    if (len && !others)
2166706f2543Smrg    {
2167706f2543Smrg        if (AddExtensionClient(win, client, 0, 0) != Success)
2168706f2543Smrg            return BadAlloc;
2169706f2543Smrg        others= wOtherInputMasks(win)->inputClients;
2170706f2543Smrg    }
2171706f2543Smrg
2172706f2543Smrg    if (others)
2173706f2543Smrg        memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id]));
2174706f2543Smrg
2175706f2543Smrg    if (len)
2176706f2543Smrg        memcpy(others->xi2mask[dev->id], mask, len);
2177706f2543Smrg
2178706f2543Smrg    RecalculateDeviceDeliverableEvents(win);
2179706f2543Smrg
2180706f2543Smrg    return Success;
2181706f2543Smrg}
2182