eventconvert.c revision 8223e2f2
1/*
2 * Copyright © 2009 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 */
24
25/**
26 * @file eventconvert.c
27 * This file contains event conversion routines from InternalEvent to the
28 * matching protocol events.
29 */
30
31#ifdef HAVE_DIX_CONFIG_H
32#include <dix-config.h>
33#endif
34
35#include <stdint.h>
36#include <X11/X.h>
37#include <X11/extensions/XIproto.h>
38#include <X11/extensions/XI2proto.h>
39#include <X11/extensions/XI.h>
40#include <X11/extensions/XI2.h>
41
42#include "dix.h"
43#include "inputstr.h"
44#include "misc.h"
45#include "eventstr.h"
46#include "exglobals.h"
47#include "eventconvert.h"
48#include "xiquerydevice.h"
49#include "xkbsrv.h"
50
51
52static int countValuators(DeviceEvent *ev, int *first);
53static int getValuatorEvents(DeviceEvent *ev, deviceValuator *xv);
54static int eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count);
55static int eventToDeviceChanged(DeviceChangedEvent *ev, xEvent **dcce);
56static int eventToDeviceEvent(DeviceEvent *ev, xEvent **xi);
57static int eventToRawEvent(RawDeviceEvent *ev, xEvent **xi);
58
59/* Do not use, read comments below */
60BOOL EventIsKeyRepeat(xEvent *event);
61
62/**
63 * Hack to allow detectable autorepeat for core and XI1 events.
64 * The sequence number is unused until we send to the client and can be
65 * misused to store data. More or less, anyway.
66 *
67 * Do not use this. It may change any time without warning, eat your babies
68 * and piss on your cat.
69 */
70static void
71EventSetKeyRepeatFlag(xEvent *event, BOOL on)
72{
73    event->u.u.sequenceNumber = on;
74}
75
76/**
77 * Check if the event was marked as a repeat event before.
78 * NOTE: This is a nasty hack and should NOT be used by anyone else but
79 * TryClientEvents.
80 */
81BOOL
82EventIsKeyRepeat(xEvent *event)
83{
84    return !!event->u.u.sequenceNumber;
85}
86
87/**
88 * Convert the given event to the respective core event.
89 *
90 * Return values:
91 * Success ... core contains the matching core event.
92 * BadValue .. One or more values in the internal event are invalid.
93 * BadMatch .. The event has no core equivalent.
94 *
95 * @param[in] event The event to convert into a core event.
96 * @param[in] core The memory location to store the core event at.
97 * @return Success or the matching error code.
98 */
99int
100EventToCore(InternalEvent *event, xEvent *core)
101{
102    switch(event->any.type)
103    {
104        case ET_Motion:
105            {
106                DeviceEvent *e = &event->device_event;
107                /* Don't create core motion event if neither x nor y are
108                 * present */
109                if (!BitIsOn(e->valuators.mask, 0) &&
110                    !BitIsOn(e->valuators.mask, 1))
111                    return BadMatch;
112            }
113            /* fallthrough */
114        case ET_ButtonPress:
115        case ET_ButtonRelease:
116        case ET_KeyPress:
117        case ET_KeyRelease:
118            {
119                DeviceEvent *e = &event->device_event;
120
121                if (e->detail.key > 0xFF)
122                    return BadMatch;
123
124                memset(core, 0, sizeof(xEvent));
125                core->u.u.type = e->type - ET_KeyPress + KeyPress;
126                core->u.u.detail = e->detail.key & 0xFF;
127                core->u.keyButtonPointer.time = e->time;
128                core->u.keyButtonPointer.rootX = e->root_x;
129                core->u.keyButtonPointer.rootY = e->root_y;
130                core->u.keyButtonPointer.state = e->corestate;
131                core->u.keyButtonPointer.root = e->root;
132                EventSetKeyRepeatFlag(core, (e->type == ET_KeyPress && e->key_repeat));
133            }
134            break;
135        case ET_ProximityIn:
136        case ET_ProximityOut:
137        case ET_RawKeyPress:
138        case ET_RawKeyRelease:
139        case ET_RawButtonPress:
140        case ET_RawButtonRelease:
141        case ET_RawMotion:
142            return BadMatch;
143        default:
144            /* XXX: */
145            ErrorF("[dix] EventToCore: Not implemented yet \n");
146            return BadImplementation;
147    }
148    return Success;
149}
150
151/**
152 * Convert the given event to the respective XI 1.x event and store it in
153 * xi. xi is allocated on demand and must be freed by the caller.
154 * count returns the number of events in xi. If count is 1, and the type of
155 * xi is GenericEvent, then xi may be larger than 32 bytes.
156 *
157 * Return values:
158 * Success ... core contains the matching core event.
159 * BadValue .. One or more values in the internal event are invalid.
160 * BadMatch .. The event has no XI equivalent.
161 *
162 * @param[in] ev The event to convert into an XI 1 event.
163 * @param[out] xi Future memory location for the XI event.
164 * @param[out] count Number of elements in xi.
165 *
166 * @return Success or the error code.
167 */
168int
169EventToXI(InternalEvent *ev, xEvent **xi, int *count)
170{
171    switch (ev->any.type)
172    {
173        case ET_Motion:
174        case ET_ButtonPress:
175        case ET_ButtonRelease:
176        case ET_KeyPress:
177        case ET_KeyRelease:
178        case ET_ProximityIn:
179        case ET_ProximityOut:
180            return eventToKeyButtonPointer(&ev->device_event, xi, count);
181        case ET_DeviceChanged:
182        case ET_RawKeyPress:
183        case ET_RawKeyRelease:
184        case ET_RawButtonPress:
185        case ET_RawButtonRelease:
186        case ET_RawMotion:
187            *count = 0;
188            *xi = NULL;
189            return BadMatch;
190        default:
191            break;
192    }
193
194    ErrorF("[dix] EventToXI: Not implemented for %d \n", ev->any.type);
195    return BadImplementation;
196}
197
198/**
199 * Convert the given event to the respective XI 2.x event and store it in xi.
200 * xi is allocated on demand and must be freed by the caller.
201 *
202 * Return values:
203 * Success ... core contains the matching core event.
204 * BadValue .. One or more values in the internal event are invalid.
205 * BadMatch .. The event has no XI2 equivalent.
206 *
207 * @param[in] ev The event to convert into an XI2 event
208 * @param[out] xi Future memory location for the XI2 event.
209 *
210 * @return Success or the error code.
211 */
212int
213EventToXI2(InternalEvent *ev, xEvent **xi)
214{
215    switch (ev->any.type)
216    {
217        /* Enter/FocusIn are for grabs. We don't need an actual event, since
218         * the real events delivered are triggered elsewhere */
219        case ET_Enter:
220        case ET_FocusIn:
221            *xi = NULL;
222            return Success;
223        case ET_Motion:
224        case ET_ButtonPress:
225        case ET_ButtonRelease:
226        case ET_KeyPress:
227        case ET_KeyRelease:
228            return eventToDeviceEvent(&ev->device_event, xi);
229        case ET_ProximityIn:
230        case ET_ProximityOut:
231            *xi = NULL;
232            return BadMatch;
233        case ET_DeviceChanged:
234            return eventToDeviceChanged(&ev->changed_event, xi);
235        case ET_RawKeyPress:
236        case ET_RawKeyRelease:
237        case ET_RawButtonPress:
238        case ET_RawButtonRelease:
239        case ET_RawMotion:
240            return eventToRawEvent(&ev->raw_event, xi);
241        default:
242            break;
243    }
244
245    ErrorF("[dix] EventToXI2: Not implemented for %d \n", ev->any.type);
246    return BadImplementation;
247}
248
249static int
250eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count)
251{
252    int num_events;
253    int first; /* dummy */
254    deviceKeyButtonPointer *kbp;
255
256    /* Sorry, XI 1.x protocol restrictions. */
257    if (ev->detail.button > 0xFF || ev->deviceid >= 0x80)
258    {
259        *count = 0;
260        return Success;
261    }
262
263    num_events = (countValuators(ev, &first) + 5)/6; /* valuator ev */
264    num_events++; /* the actual event event */
265
266    *xi = calloc(num_events, sizeof(xEvent));
267    if (!(*xi))
268    {
269        return BadAlloc;
270    }
271
272    kbp           = (deviceKeyButtonPointer*)(*xi);
273    kbp->detail   = ev->detail.button;
274    kbp->time     = ev->time;
275    kbp->root     = ev->root;
276    kbp->root_x   = ev->root_x;
277    kbp->root_y   = ev->root_y;
278    kbp->deviceid = ev->deviceid;
279    kbp->state    = ev->corestate;
280    EventSetKeyRepeatFlag((xEvent*)kbp,
281                          (ev->type == ET_KeyPress && ev->key_repeat));
282
283    if (num_events > 1)
284        kbp->deviceid |= MORE_EVENTS;
285
286    switch(ev->type)
287    {
288        case ET_Motion:        kbp->type = DeviceMotionNotify;  break;
289        case ET_ButtonPress:   kbp->type = DeviceButtonPress;   break;
290        case ET_ButtonRelease: kbp->type = DeviceButtonRelease; break;
291        case ET_KeyPress:      kbp->type = DeviceKeyPress;      break;
292        case ET_KeyRelease:    kbp->type = DeviceKeyRelease;    break;
293        case ET_ProximityIn:   kbp->type = ProximityIn;         break;
294        case ET_ProximityOut:  kbp->type = ProximityOut;        break;
295        default:
296            break;
297    }
298
299    if (num_events > 1)
300    {
301        getValuatorEvents(ev, (deviceValuator*)(kbp + 1));
302    }
303
304    *count = num_events;
305    return Success;
306}
307
308
309/**
310 * Set first to the first valuator in the event ev and return the number of
311 * valuators from first to the last set valuator.
312 */
313static int
314countValuators(DeviceEvent *ev, int *first)
315{
316    int first_valuator = -1, last_valuator = -1, num_valuators = 0;
317    int i;
318
319    for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++)
320    {
321        if (BitIsOn(ev->valuators.mask, i))
322        {
323            if (first_valuator == -1)
324                first_valuator = i;
325            last_valuator = i;
326        }
327    }
328
329    if (first_valuator != -1)
330    {
331        num_valuators = last_valuator - first_valuator + 1;
332        *first = first_valuator;
333    }
334
335    return num_valuators;
336}
337
338static int
339getValuatorEvents(DeviceEvent *ev, deviceValuator *xv)
340{
341    int i;
342    int state = 0;
343    int first_valuator, num_valuators;
344
345
346    num_valuators = countValuators(ev, &first_valuator);
347    if (num_valuators > 0)
348    {
349        DeviceIntPtr dev = NULL;
350        dixLookupDevice(&dev, ev->deviceid, serverClient, DixUseAccess);
351        /* State needs to be assembled BEFORE the device is updated. */
352        state = (dev && dev->key) ? XkbStateFieldFromRec(&dev->key->xkbInfo->state) : 0;
353        state |= (dev && dev->button) ? (dev->button->state) : 0;
354    }
355
356    /* FIXME: non-continuous valuator data in internal events*/
357    for (i = 0; i < num_valuators; i += 6, xv++) {
358        xv->type = DeviceValuator;
359        xv->first_valuator = first_valuator + i;
360        xv->num_valuators = ((num_valuators - i) > 6) ? 6 : (num_valuators - i);
361        xv->deviceid = ev->deviceid;
362        xv->device_state = state;
363        switch (xv->num_valuators) {
364        case 6:
365            xv->valuator5 = ev->valuators.data[xv->first_valuator + 5];
366        case 5:
367            xv->valuator4 = ev->valuators.data[xv->first_valuator + 4];
368        case 4:
369            xv->valuator3 = ev->valuators.data[xv->first_valuator + 3];
370        case 3:
371            xv->valuator2 = ev->valuators.data[xv->first_valuator + 2];
372        case 2:
373            xv->valuator1 = ev->valuators.data[xv->first_valuator + 1];
374        case 1:
375            xv->valuator0 = ev->valuators.data[xv->first_valuator + 0];
376        }
377
378        if (i + 6 < num_valuators)
379            xv->deviceid |= MORE_EVENTS;
380    }
381
382    return (num_valuators + 5) / 6;
383}
384
385
386static int
387appendKeyInfo(DeviceChangedEvent *dce, xXIKeyInfo* info)
388{
389    uint32_t *kc;
390    int i;
391
392    info->type = XIKeyClass;
393    info->num_keycodes = dce->keys.max_keycode - dce->keys.min_keycode + 1;
394    info->length = sizeof(xXIKeyInfo)/4 + info->num_keycodes;
395    info->sourceid = dce->sourceid;
396
397    kc = (uint32_t*)&info[1];
398    for (i = 0; i < info->num_keycodes; i++)
399        *kc++ = i + dce->keys.min_keycode;
400
401    return info->length * 4;
402}
403
404static int
405appendButtonInfo(DeviceChangedEvent *dce, xXIButtonInfo *info)
406{
407    unsigned char *bits;
408    int mask_len;
409
410    mask_len = bytes_to_int32(bits_to_bytes(dce->buttons.num_buttons));
411
412    info->type = XIButtonClass;
413    info->num_buttons = dce->buttons.num_buttons;
414    info->length = bytes_to_int32(sizeof(xXIButtonInfo)) +
415                   info->num_buttons + mask_len;
416    info->sourceid = dce->sourceid;
417
418    bits = (unsigned char*)&info[1];
419    memset(bits, 0, mask_len * 4);
420    /* FIXME: is_down? */
421
422    bits += mask_len * 4;
423    memcpy(bits, dce->buttons.names, dce->buttons.num_buttons * sizeof(Atom));
424
425    return info->length * 4;
426}
427
428static int
429appendValuatorInfo(DeviceChangedEvent *dce, xXIValuatorInfo *info, int axisnumber)
430{
431    info->type = XIValuatorClass;
432    info->length = sizeof(xXIValuatorInfo)/4;
433    info->label = dce->valuators[axisnumber].name;
434    info->min.integral = dce->valuators[axisnumber].min;
435    info->min.frac = 0;
436    info->max.integral = dce->valuators[axisnumber].max;
437    info->max.frac = 0;
438    /* FIXME: value */
439    info->value.integral = 0;
440    info->value.frac = 0;
441    info->resolution = dce->valuators[axisnumber].resolution;
442    info->number = axisnumber;
443    info->mode = dce->valuators[axisnumber].mode; /* Server doesn't have per-axis mode yet */
444    info->sourceid = dce->sourceid;
445
446    return info->length * 4;
447}
448
449static int
450eventToDeviceChanged(DeviceChangedEvent *dce, xEvent **xi)
451{
452    xXIDeviceChangedEvent *dcce;
453    int len = sizeof(xXIDeviceChangedEvent);
454    int nkeys;
455    char *ptr;
456
457    if (dce->buttons.num_buttons)
458    {
459        len += sizeof(xXIButtonInfo);
460        len += dce->buttons.num_buttons * sizeof(Atom); /* button names */
461        len += pad_to_int32(bits_to_bytes(dce->buttons.num_buttons));
462    }
463    if (dce->num_valuators)
464        len += sizeof(xXIValuatorInfo) * dce->num_valuators;
465
466    nkeys = (dce->keys.max_keycode > 0) ?
467                dce->keys.max_keycode - dce->keys.min_keycode + 1 : 0;
468    if (nkeys > 0)
469    {
470        len += sizeof(xXIKeyInfo);
471        len += sizeof(CARD32) * nkeys; /* keycodes */
472    }
473
474    dcce = calloc(1, len);
475    if (!dcce)
476    {
477        ErrorF("[Xi] BadAlloc in SendDeviceChangedEvent.\n");
478        return BadAlloc;
479    }
480
481    dcce->type         = GenericEvent;
482    dcce->extension    = IReqCode;
483    dcce->evtype       = XI_DeviceChanged;
484    dcce->time         = dce->time;
485    dcce->deviceid     = dce->deviceid;
486    dcce->sourceid     = dce->sourceid;
487    dcce->reason       = (dce->flags & DEVCHANGE_DEVICE_CHANGE) ? XIDeviceChange : XISlaveSwitch;
488    dcce->num_classes  = 0;
489    dcce->length = bytes_to_int32(len - sizeof(xEvent));
490
491    ptr = (char*)&dcce[1];
492    if (dce->buttons.num_buttons)
493    {
494        dcce->num_classes++;
495        ptr += appendButtonInfo(dce, (xXIButtonInfo*)ptr);
496    }
497
498    if (nkeys)
499    {
500        dcce->num_classes++;
501        ptr += appendKeyInfo(dce, (xXIKeyInfo*)ptr);
502    }
503
504    if (dce->num_valuators)
505    {
506        int i;
507
508        dcce->num_classes += dce->num_valuators;
509        for (i = 0; i < dce->num_valuators; i++)
510            ptr += appendValuatorInfo(dce, (xXIValuatorInfo*)ptr, i);
511    }
512
513    *xi = (xEvent*)dcce;
514
515    return Success;
516}
517
518static int count_bits(unsigned char* ptr, int len)
519{
520    int bits = 0;
521    unsigned int i;
522    unsigned char x;
523
524    for (i = 0; i < len; i++)
525    {
526        x = ptr[i];
527        while(x > 0)
528        {
529            bits += (x & 0x1);
530            x >>= 1;
531        }
532    }
533    return bits;
534}
535
536static int
537eventToDeviceEvent(DeviceEvent *ev, xEvent **xi)
538{
539    int len = sizeof(xXIDeviceEvent);
540    xXIDeviceEvent *xde;
541    int i, btlen, vallen;
542    char *ptr;
543    FP3232 *axisval;
544
545    /* FIXME: this should just send the buttons we have, not MAX_BUTTONs. Same
546     * with MAX_VALUATORS below */
547    /* btlen is in 4 byte units */
548    btlen = bytes_to_int32(bits_to_bytes(MAX_BUTTONS));
549    len += btlen * 4; /* buttonmask len */
550
551
552    vallen = count_bits(ev->valuators.mask, sizeof(ev->valuators.mask)/sizeof(ev->valuators.mask[0]));
553    len += vallen * 2 * sizeof(uint32_t); /* axisvalues */
554    vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS));
555    len += vallen * 4; /* valuators mask */
556
557    *xi = calloc(1, len);
558    xde = (xXIDeviceEvent*)*xi;
559    xde->type           = GenericEvent;
560    xde->extension      = IReqCode;
561    xde->evtype         = GetXI2Type((InternalEvent*)ev);
562    xde->time           = ev->time;
563    xde->length         = bytes_to_int32(len - sizeof(xEvent));
564    xde->detail         = ev->detail.button;
565    xde->root           = ev->root;
566    xde->buttons_len    = btlen;
567    xde->valuators_len  = vallen;
568    xde->deviceid       = ev->deviceid;
569    xde->sourceid       = ev->sourceid;
570    xde->root_x         = FP1616(ev->root_x, ev->root_x_frac);
571    xde->root_y         = FP1616(ev->root_y, ev->root_y_frac);
572
573    if (ev->key_repeat)
574        xde->flags      |= XIKeyRepeat;
575
576    xde->mods.base_mods         = ev->mods.base;
577    xde->mods.latched_mods      = ev->mods.latched;
578    xde->mods.locked_mods       = ev->mods.locked;
579    xde->mods.effective_mods    = ev->mods.effective;
580
581    xde->group.base_group       = ev->group.base;
582    xde->group.latched_group    = ev->group.latched;
583    xde->group.locked_group     = ev->group.locked;
584    xde->group.effective_group  = ev->group.effective;
585
586    ptr = (char*)&xde[1];
587    for (i = 0; i < sizeof(ev->buttons) * 8; i++)
588    {
589        if (BitIsOn(ev->buttons, i))
590            SetBit(ptr, i);
591    }
592
593    ptr += xde->buttons_len * 4;
594    axisval = (FP3232*)(ptr + xde->valuators_len * 4);
595    for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++)
596    {
597        if (BitIsOn(ev->valuators.mask, i))
598        {
599            SetBit(ptr, i);
600            axisval->integral = ev->valuators.data[i];
601            axisval->frac = ev->valuators.data_frac[i];
602            axisval++;
603        }
604    }
605
606    return Success;
607}
608
609static int
610eventToRawEvent(RawDeviceEvent *ev, xEvent **xi)
611{
612    xXIRawEvent* raw;
613    int vallen, nvals;
614    int i, len = sizeof(xXIRawEvent);
615    char *ptr;
616    FP3232 *axisval;
617
618    nvals = count_bits(ev->valuators.mask, sizeof(ev->valuators.mask));
619    len += nvals * sizeof(FP3232) * 2; /* 8 byte per valuator, once
620                                    raw, once processed */
621    vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS));
622    len += vallen * 4; /* valuators mask */
623
624    *xi = calloc(1, len);
625    raw = (xXIRawEvent*)*xi;
626    raw->type           = GenericEvent;
627    raw->extension      = IReqCode;
628    raw->evtype         = GetXI2Type((InternalEvent*)ev);
629    raw->time           = ev->time;
630    raw->length         = bytes_to_int32(len - sizeof(xEvent));
631    raw->detail         = ev->detail.button;
632    raw->deviceid       = ev->deviceid;
633    raw->valuators_len  = vallen;
634
635    ptr = (char*)&raw[1];
636    axisval = (FP3232*)(ptr + raw->valuators_len * 4);
637    for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++)
638    {
639        if (BitIsOn(ev->valuators.mask, i))
640        {
641            SetBit(ptr, i);
642            axisval->integral = ev->valuators.data[i];
643            axisval->frac = ev->valuators.data_frac[i];
644            (axisval + nvals)->integral = ev->valuators.data_raw[i];
645            (axisval + nvals)->frac = ev->valuators.data_raw_frac[i];
646            axisval++;
647        }
648    }
649
650    return Success;
651}
652
653/**
654 * Return the corresponding core type for the given event or 0 if no core
655 * equivalent exists.
656 */
657int
658GetCoreType(InternalEvent *event)
659{
660    int coretype = 0;
661    switch(event->any.type)
662    {
663        case ET_Motion:         coretype = MotionNotify;  break;
664        case ET_ButtonPress:    coretype = ButtonPress;   break;
665        case ET_ButtonRelease:  coretype = ButtonRelease; break;
666        case ET_KeyPress:       coretype = KeyPress;      break;
667        case ET_KeyRelease:     coretype = KeyRelease;    break;
668        default:
669            break;
670    }
671    return coretype;
672}
673
674/**
675 * Return the corresponding XI 1.x type for the given event or 0 if no
676 * equivalent exists.
677 */
678int
679GetXIType(InternalEvent *event)
680{
681    int xitype = 0;
682    switch(event->any.type)
683    {
684        case ET_Motion:         xitype = DeviceMotionNotify;  break;
685        case ET_ButtonPress:    xitype = DeviceButtonPress;   break;
686        case ET_ButtonRelease:  xitype = DeviceButtonRelease; break;
687        case ET_KeyPress:       xitype = DeviceKeyPress;      break;
688        case ET_KeyRelease:     xitype = DeviceKeyRelease;    break;
689        case ET_ProximityIn:    xitype = ProximityIn;         break;
690        case ET_ProximityOut:   xitype = ProximityOut;        break;
691        default:
692            break;
693    }
694    return xitype;
695}
696
697/**
698 * Return the corresponding XI 2.x type for the given event or 0 if no
699 * equivalent exists.
700 */
701int
702GetXI2Type(InternalEvent *event)
703{
704    int xi2type = 0;
705
706    switch(event->any.type)
707    {
708        case ET_Motion:         xi2type = XI_Motion;           break;
709        case ET_ButtonPress:    xi2type = XI_ButtonPress;      break;
710        case ET_ButtonRelease:  xi2type = XI_ButtonRelease;    break;
711        case ET_KeyPress:       xi2type = XI_KeyPress;         break;
712        case ET_KeyRelease:     xi2type = XI_KeyRelease;       break;
713        case ET_Enter:          xi2type = XI_Enter;            break;
714        case ET_Leave:          xi2type = XI_Leave;            break;
715        case ET_Hierarchy:      xi2type = XI_HierarchyChanged; break;
716        case ET_DeviceChanged:  xi2type = XI_DeviceChanged;    break;
717        case ET_RawKeyPress:    xi2type = XI_RawKeyPress;      break;
718        case ET_RawKeyRelease:  xi2type = XI_RawKeyRelease;    break;
719        case ET_RawButtonPress: xi2type = XI_RawButtonPress;   break;
720        case ET_RawButtonRelease: xi2type = XI_RawButtonRelease; break;
721        case ET_RawMotion:      xi2type = XI_RawMotion;        break;
722        case ET_FocusIn:        xi2type = XI_FocusIn;          break;
723        case ET_FocusOut:       xi2type = XI_FocusOut;         break;
724        default:
725            break;
726    }
727    return xi2type;
728}
729