16747b715Smrg/*
26747b715Smrg * Copyright © 2009 Red Hat, Inc.
36747b715Smrg *
46747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a
56747b715Smrg * copy of this software and associated documentation files (the "Software"),
66747b715Smrg * to deal in the Software without restriction, including without limitation
76747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
86747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the
96747b715Smrg * Software is furnished to do so, subject to the following conditions:
106747b715Smrg *
116747b715Smrg * The above copyright notice and this permission notice (including the next
126747b715Smrg * paragraph) shall be included in all copies or substantial portions of the
136747b715Smrg * Software.
146747b715Smrg *
156747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
166747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
176747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
186747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
196747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
206747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
216747b715Smrg * DEALINGS IN THE SOFTWARE.
226747b715Smrg *
236747b715Smrg */
246747b715Smrg
256747b715Smrg/**
266747b715Smrg * @file eventconvert.c
276747b715Smrg * This file contains event conversion routines from InternalEvent to the
286747b715Smrg * matching protocol events.
296747b715Smrg */
306747b715Smrg
316747b715Smrg#ifdef HAVE_DIX_CONFIG_H
326747b715Smrg#include <dix-config.h>
336747b715Smrg#endif
346747b715Smrg
356747b715Smrg#include <stdint.h>
366747b715Smrg#include <X11/X.h>
376747b715Smrg#include <X11/extensions/XIproto.h>
386747b715Smrg#include <X11/extensions/XI2proto.h>
396747b715Smrg#include <X11/extensions/XI.h>
406747b715Smrg#include <X11/extensions/XI2.h>
416747b715Smrg
426747b715Smrg#include "dix.h"
436747b715Smrg#include "inputstr.h"
446747b715Smrg#include "misc.h"
456747b715Smrg#include "eventstr.h"
4635c4bbdfSmrg#include "exevents.h"
476747b715Smrg#include "exglobals.h"
486747b715Smrg#include "eventconvert.h"
4935c4bbdfSmrg#include "inpututils.h"
506747b715Smrg#include "xiquerydevice.h"
516747b715Smrg#include "xkbsrv.h"
5235c4bbdfSmrg#include "inpututils.h"
536747b715Smrg
546747b715Smrgstatic int countValuators(DeviceEvent *ev, int *first);
5535c4bbdfSmrgstatic int getValuatorEvents(DeviceEvent *ev, deviceValuator * xv);
566747b715Smrgstatic int eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count);
576747b715Smrgstatic int eventToDeviceChanged(DeviceChangedEvent *ev, xEvent **dcce);
586747b715Smrgstatic int eventToDeviceEvent(DeviceEvent *ev, xEvent **xi);
596747b715Smrgstatic int eventToRawEvent(RawDeviceEvent *ev, xEvent **xi);
6035c4bbdfSmrgstatic int eventToBarrierEvent(BarrierEvent *ev, xEvent **xi);
6135c4bbdfSmrgstatic int eventToTouchOwnershipEvent(TouchOwnershipEvent *ev, xEvent **xi);
62ed6184dfSmrgstatic int eventToGestureSwipeEvent(GestureEvent *ev, xEvent **xi);
63ed6184dfSmrgstatic int eventToGesturePinchEvent(GestureEvent *ev, xEvent **xi);
646747b715Smrg
656747b715Smrg/* Do not use, read comments below */
666747b715SmrgBOOL EventIsKeyRepeat(xEvent *event);
676747b715Smrg
686747b715Smrg/**
696747b715Smrg * Hack to allow detectable autorepeat for core and XI1 events.
706747b715Smrg * The sequence number is unused until we send to the client and can be
716747b715Smrg * misused to store data. More or less, anyway.
726747b715Smrg *
736747b715Smrg * Do not use this. It may change any time without warning, eat your babies
746747b715Smrg * and piss on your cat.
756747b715Smrg */
766747b715Smrgstatic void
776747b715SmrgEventSetKeyRepeatFlag(xEvent *event, BOOL on)
786747b715Smrg{
796747b715Smrg    event->u.u.sequenceNumber = on;
806747b715Smrg}
816747b715Smrg
826747b715Smrg/**
836747b715Smrg * Check if the event was marked as a repeat event before.
846747b715Smrg * NOTE: This is a nasty hack and should NOT be used by anyone else but
856747b715Smrg * TryClientEvents.
866747b715Smrg */
876747b715SmrgBOOL
886747b715SmrgEventIsKeyRepeat(xEvent *event)
896747b715Smrg{
9035c4bbdfSmrg    return ! !event->u.u.sequenceNumber;
916747b715Smrg}
926747b715Smrg
936747b715Smrg/**
946747b715Smrg * Convert the given event to the respective core event.
956747b715Smrg *
966747b715Smrg * Return values:
976747b715Smrg * Success ... core contains the matching core event.
986747b715Smrg * BadValue .. One or more values in the internal event are invalid.
996747b715Smrg * BadMatch .. The event has no core equivalent.
1006747b715Smrg *
1016747b715Smrg * @param[in] event The event to convert into a core event.
1026747b715Smrg * @param[in] core The memory location to store the core event at.
1036747b715Smrg * @return Success or the matching error code.
1046747b715Smrg */
1056747b715Smrgint
10635c4bbdfSmrgEventToCore(InternalEvent *event, xEvent **core_out, int *count_out)
1076747b715Smrg{
10835c4bbdfSmrg    xEvent *core = NULL;
10935c4bbdfSmrg    int count = 0;
11035c4bbdfSmrg    int ret = BadImplementation;
11135c4bbdfSmrg
11235c4bbdfSmrg    switch (event->any.type) {
11335c4bbdfSmrg    case ET_Motion:
1146747b715Smrg    {
11535c4bbdfSmrg        DeviceEvent *e = &event->device_event;
11635c4bbdfSmrg
11735c4bbdfSmrg        /* Don't create core motion event if neither x nor y are
11835c4bbdfSmrg         * present */
11935c4bbdfSmrg        if (!BitIsOn(e->valuators.mask, 0) && !BitIsOn(e->valuators.mask, 1)) {
12035c4bbdfSmrg            ret = BadMatch;
12135c4bbdfSmrg            goto out;
12235c4bbdfSmrg        }
1236747b715Smrg    }
12435c4bbdfSmrg        /* fallthrough */
12535c4bbdfSmrg    case ET_ButtonPress:
12635c4bbdfSmrg    case ET_ButtonRelease:
12735c4bbdfSmrg    case ET_KeyPress:
12835c4bbdfSmrg    case ET_KeyRelease:
12935c4bbdfSmrg    {
13035c4bbdfSmrg        DeviceEvent *e = &event->device_event;
13135c4bbdfSmrg
13235c4bbdfSmrg        if (e->detail.key > 0xFF) {
13335c4bbdfSmrg            ret = BadMatch;
13435c4bbdfSmrg            goto out;
13535c4bbdfSmrg        }
13635c4bbdfSmrg
13735c4bbdfSmrg        core = calloc(1, sizeof(*core));
13835c4bbdfSmrg        if (!core)
13935c4bbdfSmrg            return BadAlloc;
14035c4bbdfSmrg        count = 1;
14135c4bbdfSmrg        core->u.u.type = e->type - ET_KeyPress + KeyPress;
14235c4bbdfSmrg        core->u.u.detail = e->detail.key & 0xFF;
14335c4bbdfSmrg        core->u.keyButtonPointer.time = e->time;
14435c4bbdfSmrg        core->u.keyButtonPointer.rootX = e->root_x;
14535c4bbdfSmrg        core->u.keyButtonPointer.rootY = e->root_y;
14635c4bbdfSmrg        core->u.keyButtonPointer.state = e->corestate;
14735c4bbdfSmrg        core->u.keyButtonPointer.root = e->root;
14835c4bbdfSmrg        EventSetKeyRepeatFlag(core, (e->type == ET_KeyPress && e->key_repeat));
14935c4bbdfSmrg        ret = Success;
15035c4bbdfSmrg    }
15135c4bbdfSmrg        break;
15235c4bbdfSmrg    case ET_ProximityIn:
15335c4bbdfSmrg    case ET_ProximityOut:
15435c4bbdfSmrg    case ET_RawKeyPress:
15535c4bbdfSmrg    case ET_RawKeyRelease:
15635c4bbdfSmrg    case ET_RawButtonPress:
15735c4bbdfSmrg    case ET_RawButtonRelease:
15835c4bbdfSmrg    case ET_RawMotion:
15935c4bbdfSmrg    case ET_RawTouchBegin:
16035c4bbdfSmrg    case ET_RawTouchUpdate:
16135c4bbdfSmrg    case ET_RawTouchEnd:
16235c4bbdfSmrg    case ET_TouchBegin:
16335c4bbdfSmrg    case ET_TouchUpdate:
16435c4bbdfSmrg    case ET_TouchEnd:
16535c4bbdfSmrg    case ET_TouchOwnership:
16635c4bbdfSmrg    case ET_BarrierHit:
16735c4bbdfSmrg    case ET_BarrierLeave:
168ed6184dfSmrg    case ET_GesturePinchBegin:
169ed6184dfSmrg    case ET_GesturePinchUpdate:
170ed6184dfSmrg    case ET_GesturePinchEnd:
171ed6184dfSmrg    case ET_GestureSwipeBegin:
172ed6184dfSmrg    case ET_GestureSwipeUpdate:
173ed6184dfSmrg    case ET_GestureSwipeEnd:
17435c4bbdfSmrg        ret = BadMatch;
17535c4bbdfSmrg        break;
17635c4bbdfSmrg    default:
17735c4bbdfSmrg        /* XXX: */
17835c4bbdfSmrg        ErrorF("[dix] EventToCore: Not implemented yet \n");
17935c4bbdfSmrg        ret = BadImplementation;
18035c4bbdfSmrg    }
18135c4bbdfSmrg
18235c4bbdfSmrg out:
18335c4bbdfSmrg    *core_out = core;
18435c4bbdfSmrg    *count_out = count;
18535c4bbdfSmrg    return ret;
1866747b715Smrg}
1876747b715Smrg
1886747b715Smrg/**
1896747b715Smrg * Convert the given event to the respective XI 1.x event and store it in
1906747b715Smrg * xi. xi is allocated on demand and must be freed by the caller.
1916747b715Smrg * count returns the number of events in xi. If count is 1, and the type of
1926747b715Smrg * xi is GenericEvent, then xi may be larger than 32 bytes.
1936747b715Smrg *
1946747b715Smrg * Return values:
1956747b715Smrg * Success ... core contains the matching core event.
1966747b715Smrg * BadValue .. One or more values in the internal event are invalid.
1976747b715Smrg * BadMatch .. The event has no XI equivalent.
1986747b715Smrg *
1996747b715Smrg * @param[in] ev The event to convert into an XI 1 event.
2006747b715Smrg * @param[out] xi Future memory location for the XI event.
2016747b715Smrg * @param[out] count Number of elements in xi.
2026747b715Smrg *
2036747b715Smrg * @return Success or the error code.
2046747b715Smrg */
2056747b715Smrgint
2066747b715SmrgEventToXI(InternalEvent *ev, xEvent **xi, int *count)
2076747b715Smrg{
20835c4bbdfSmrg    switch (ev->any.type) {
20935c4bbdfSmrg    case ET_Motion:
21035c4bbdfSmrg    case ET_ButtonPress:
21135c4bbdfSmrg    case ET_ButtonRelease:
21235c4bbdfSmrg    case ET_KeyPress:
21335c4bbdfSmrg    case ET_KeyRelease:
21435c4bbdfSmrg    case ET_ProximityIn:
21535c4bbdfSmrg    case ET_ProximityOut:
21635c4bbdfSmrg        return eventToKeyButtonPointer(&ev->device_event, xi, count);
21735c4bbdfSmrg    case ET_DeviceChanged:
21835c4bbdfSmrg    case ET_RawKeyPress:
21935c4bbdfSmrg    case ET_RawKeyRelease:
22035c4bbdfSmrg    case ET_RawButtonPress:
22135c4bbdfSmrg    case ET_RawButtonRelease:
22235c4bbdfSmrg    case ET_RawMotion:
22335c4bbdfSmrg    case ET_RawTouchBegin:
22435c4bbdfSmrg    case ET_RawTouchUpdate:
22535c4bbdfSmrg    case ET_RawTouchEnd:
22635c4bbdfSmrg    case ET_TouchBegin:
22735c4bbdfSmrg    case ET_TouchUpdate:
22835c4bbdfSmrg    case ET_TouchEnd:
22935c4bbdfSmrg    case ET_TouchOwnership:
23035c4bbdfSmrg    case ET_BarrierHit:
23135c4bbdfSmrg    case ET_BarrierLeave:
232ed6184dfSmrg    case ET_GesturePinchBegin:
233ed6184dfSmrg    case ET_GesturePinchUpdate:
234ed6184dfSmrg    case ET_GesturePinchEnd:
235ed6184dfSmrg    case ET_GestureSwipeBegin:
236ed6184dfSmrg    case ET_GestureSwipeUpdate:
237ed6184dfSmrg    case ET_GestureSwipeEnd:
23835c4bbdfSmrg        *count = 0;
23935c4bbdfSmrg        *xi = NULL;
24035c4bbdfSmrg        return BadMatch;
24135c4bbdfSmrg    default:
24235c4bbdfSmrg        break;
2436747b715Smrg    }
2446747b715Smrg
2456747b715Smrg    ErrorF("[dix] EventToXI: Not implemented for %d \n", ev->any.type);
2466747b715Smrg    return BadImplementation;
2476747b715Smrg}
2486747b715Smrg
2496747b715Smrg/**
2506747b715Smrg * Convert the given event to the respective XI 2.x event and store it in xi.
2516747b715Smrg * xi is allocated on demand and must be freed by the caller.
2526747b715Smrg *
2536747b715Smrg * Return values:
2546747b715Smrg * Success ... core contains the matching core event.
2556747b715Smrg * BadValue .. One or more values in the internal event are invalid.
2566747b715Smrg * BadMatch .. The event has no XI2 equivalent.
2576747b715Smrg *
2586747b715Smrg * @param[in] ev The event to convert into an XI2 event
2596747b715Smrg * @param[out] xi Future memory location for the XI2 event.
2606747b715Smrg *
2616747b715Smrg * @return Success or the error code.
2626747b715Smrg */
2636747b715Smrgint
2646747b715SmrgEventToXI2(InternalEvent *ev, xEvent **xi)
2656747b715Smrg{
26635c4bbdfSmrg    switch (ev->any.type) {
2676747b715Smrg        /* Enter/FocusIn are for grabs. We don't need an actual event, since
2686747b715Smrg         * the real events delivered are triggered elsewhere */
26935c4bbdfSmrg    case ET_Enter:
27035c4bbdfSmrg    case ET_FocusIn:
27135c4bbdfSmrg        *xi = NULL;
27235c4bbdfSmrg        return Success;
27335c4bbdfSmrg    case ET_Motion:
27435c4bbdfSmrg    case ET_ButtonPress:
27535c4bbdfSmrg    case ET_ButtonRelease:
27635c4bbdfSmrg    case ET_KeyPress:
27735c4bbdfSmrg    case ET_KeyRelease:
27835c4bbdfSmrg    case ET_TouchBegin:
27935c4bbdfSmrg    case ET_TouchUpdate:
28035c4bbdfSmrg    case ET_TouchEnd:
28135c4bbdfSmrg        return eventToDeviceEvent(&ev->device_event, xi);
28235c4bbdfSmrg    case ET_TouchOwnership:
28335c4bbdfSmrg        return eventToTouchOwnershipEvent(&ev->touch_ownership_event, xi);
28435c4bbdfSmrg    case ET_ProximityIn:
28535c4bbdfSmrg    case ET_ProximityOut:
28635c4bbdfSmrg        *xi = NULL;
28735c4bbdfSmrg        return BadMatch;
28835c4bbdfSmrg    case ET_DeviceChanged:
28935c4bbdfSmrg        return eventToDeviceChanged(&ev->changed_event, xi);
29035c4bbdfSmrg    case ET_RawKeyPress:
29135c4bbdfSmrg    case ET_RawKeyRelease:
29235c4bbdfSmrg    case ET_RawButtonPress:
29335c4bbdfSmrg    case ET_RawButtonRelease:
29435c4bbdfSmrg    case ET_RawMotion:
29535c4bbdfSmrg    case ET_RawTouchBegin:
29635c4bbdfSmrg    case ET_RawTouchUpdate:
29735c4bbdfSmrg    case ET_RawTouchEnd:
29835c4bbdfSmrg        return eventToRawEvent(&ev->raw_event, xi);
29935c4bbdfSmrg    case ET_BarrierHit:
30035c4bbdfSmrg    case ET_BarrierLeave:
30135c4bbdfSmrg        return eventToBarrierEvent(&ev->barrier_event, xi);
302ed6184dfSmrg    case ET_GesturePinchBegin:
303ed6184dfSmrg    case ET_GesturePinchUpdate:
304ed6184dfSmrg    case ET_GesturePinchEnd:
305ed6184dfSmrg        return eventToGesturePinchEvent(&ev->gesture_event, xi);
306ed6184dfSmrg    case ET_GestureSwipeBegin:
307ed6184dfSmrg    case ET_GestureSwipeUpdate:
308ed6184dfSmrg    case ET_GestureSwipeEnd:
309ed6184dfSmrg        return eventToGestureSwipeEvent(&ev->gesture_event, xi);
31035c4bbdfSmrg    default:
31135c4bbdfSmrg        break;
3126747b715Smrg    }
3136747b715Smrg
3146747b715Smrg    ErrorF("[dix] EventToXI2: Not implemented for %d \n", ev->any.type);
3156747b715Smrg    return BadImplementation;
3166747b715Smrg}
3176747b715Smrg
3186747b715Smrgstatic int
3196747b715SmrgeventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count)
3206747b715Smrg{
3216747b715Smrg    int num_events;
32235c4bbdfSmrg    int first;                  /* dummy */
3236747b715Smrg    deviceKeyButtonPointer *kbp;
3246747b715Smrg
3256747b715Smrg    /* Sorry, XI 1.x protocol restrictions. */
32635c4bbdfSmrg    if (ev->detail.button > 0xFF || ev->deviceid >= 0x80) {
3276747b715Smrg        *count = 0;
3286747b715Smrg        return Success;
3296747b715Smrg    }
3306747b715Smrg
33135c4bbdfSmrg    num_events = (countValuators(ev, &first) + 5) / 6;  /* valuator ev */
33235c4bbdfSmrg    if (num_events <= 0) {
33335c4bbdfSmrg        switch (ev->type) {
33435c4bbdfSmrg        case ET_KeyPress:
33535c4bbdfSmrg        case ET_KeyRelease:
33635c4bbdfSmrg        case ET_ButtonPress:
33735c4bbdfSmrg        case ET_ButtonRelease:
33835c4bbdfSmrg            /* no axes is ok */
33935c4bbdfSmrg            break;
34035c4bbdfSmrg        case ET_Motion:
34135c4bbdfSmrg        case ET_ProximityIn:
34235c4bbdfSmrg        case ET_ProximityOut:
34335c4bbdfSmrg            *count = 0;
34435c4bbdfSmrg            return BadMatch;
34535c4bbdfSmrg        default:
34635c4bbdfSmrg            *count = 0;
34735c4bbdfSmrg            return BadImplementation;
3489ace9065Smrg        }
3499ace9065Smrg    }
3509ace9065Smrg
35135c4bbdfSmrg    num_events++;               /* the actual event event */
3526747b715Smrg
3536747b715Smrg    *xi = calloc(num_events, sizeof(xEvent));
35435c4bbdfSmrg    if (!(*xi)) {
3556747b715Smrg        return BadAlloc;
3566747b715Smrg    }
3576747b715Smrg
35835c4bbdfSmrg    kbp = (deviceKeyButtonPointer *) (*xi);
35935c4bbdfSmrg    kbp->detail = ev->detail.button;
36035c4bbdfSmrg    kbp->time = ev->time;
36135c4bbdfSmrg    kbp->root = ev->root;
36235c4bbdfSmrg    kbp->root_x = ev->root_x;
36335c4bbdfSmrg    kbp->root_y = ev->root_y;
3646747b715Smrg    kbp->deviceid = ev->deviceid;
36535c4bbdfSmrg    kbp->state = ev->corestate;
36635c4bbdfSmrg    EventSetKeyRepeatFlag((xEvent *) kbp,
3676747b715Smrg                          (ev->type == ET_KeyPress && ev->key_repeat));
3686747b715Smrg
3696747b715Smrg    if (num_events > 1)
3706747b715Smrg        kbp->deviceid |= MORE_EVENTS;
3716747b715Smrg
37235c4bbdfSmrg    switch (ev->type) {
37335c4bbdfSmrg    case ET_Motion:
37435c4bbdfSmrg        kbp->type = DeviceMotionNotify;
37535c4bbdfSmrg        break;
37635c4bbdfSmrg    case ET_ButtonPress:
37735c4bbdfSmrg        kbp->type = DeviceButtonPress;
37835c4bbdfSmrg        break;
37935c4bbdfSmrg    case ET_ButtonRelease:
38035c4bbdfSmrg        kbp->type = DeviceButtonRelease;
38135c4bbdfSmrg        break;
38235c4bbdfSmrg    case ET_KeyPress:
38335c4bbdfSmrg        kbp->type = DeviceKeyPress;
38435c4bbdfSmrg        break;
38535c4bbdfSmrg    case ET_KeyRelease:
38635c4bbdfSmrg        kbp->type = DeviceKeyRelease;
38735c4bbdfSmrg        break;
38835c4bbdfSmrg    case ET_ProximityIn:
38935c4bbdfSmrg        kbp->type = ProximityIn;
39035c4bbdfSmrg        break;
39135c4bbdfSmrg    case ET_ProximityOut:
39235c4bbdfSmrg        kbp->type = ProximityOut;
39335c4bbdfSmrg        break;
39435c4bbdfSmrg    default:
39535c4bbdfSmrg        break;
3966747b715Smrg    }
3976747b715Smrg
39835c4bbdfSmrg    if (num_events > 1) {
39935c4bbdfSmrg        getValuatorEvents(ev, (deviceValuator *) (kbp + 1));
4006747b715Smrg    }
4016747b715Smrg
4026747b715Smrg    *count = num_events;
4036747b715Smrg    return Success;
4046747b715Smrg}
4056747b715Smrg
4066747b715Smrg/**
4076747b715Smrg * Set first to the first valuator in the event ev and return the number of
4086747b715Smrg * valuators from first to the last set valuator.
4096747b715Smrg */
4106747b715Smrgstatic int
4116747b715SmrgcountValuators(DeviceEvent *ev, int *first)
4126747b715Smrg{
4136747b715Smrg    int first_valuator = -1, last_valuator = -1, num_valuators = 0;
4146747b715Smrg    int i;
4156747b715Smrg
41635c4bbdfSmrg    for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) {
41735c4bbdfSmrg        if (BitIsOn(ev->valuators.mask, i)) {
4186747b715Smrg            if (first_valuator == -1)
4196747b715Smrg                first_valuator = i;
4206747b715Smrg            last_valuator = i;
4216747b715Smrg        }
4226747b715Smrg    }
4236747b715Smrg
42435c4bbdfSmrg    if (first_valuator != -1) {
4256747b715Smrg        num_valuators = last_valuator - first_valuator + 1;
4266747b715Smrg        *first = first_valuator;
4276747b715Smrg    }
4286747b715Smrg
4296747b715Smrg    return num_valuators;
4306747b715Smrg}
4316747b715Smrg
4326747b715Smrgstatic int
43335c4bbdfSmrggetValuatorEvents(DeviceEvent *ev, deviceValuator * xv)
4346747b715Smrg{
4356747b715Smrg    int i;
4366747b715Smrg    int state = 0;
4376747b715Smrg    int first_valuator, num_valuators;
4386747b715Smrg
4396747b715Smrg    num_valuators = countValuators(ev, &first_valuator);
44035c4bbdfSmrg    if (num_valuators > 0) {
4416747b715Smrg        DeviceIntPtr dev = NULL;
44235c4bbdfSmrg
4436747b715Smrg        dixLookupDevice(&dev, ev->deviceid, serverClient, DixUseAccess);
4446747b715Smrg        /* State needs to be assembled BEFORE the device is updated. */
44535c4bbdfSmrg        state = (dev &&
44635c4bbdfSmrg                 dev->key) ? XkbStateFieldFromRec(&dev->key->xkbInfo->
44735c4bbdfSmrg                                                  state) : 0;
4486747b715Smrg        state |= (dev && dev->button) ? (dev->button->state) : 0;
4496747b715Smrg    }
4506747b715Smrg
4516747b715Smrg    for (i = 0; i < num_valuators; i += 6, xv++) {
45235c4bbdfSmrg        INT32 *valuators = &xv->valuator0;      // Treat all 6 vals as an array
4539ace9065Smrg        int j;
4549ace9065Smrg
4556747b715Smrg        xv->type = DeviceValuator;
4566747b715Smrg        xv->first_valuator = first_valuator + i;
4576747b715Smrg        xv->num_valuators = ((num_valuators - i) > 6) ? 6 : (num_valuators - i);
4586747b715Smrg        xv->deviceid = ev->deviceid;
4596747b715Smrg        xv->device_state = state;
4609ace9065Smrg
4619ace9065Smrg        /* Unset valuators in masked valuator events have the proper data values
4629ace9065Smrg         * in the case of an absolute axis in between two set valuators. */
4639ace9065Smrg        for (j = 0; j < xv->num_valuators; j++)
4649ace9065Smrg            valuators[j] = ev->valuators.data[xv->first_valuator + j];
4656747b715Smrg
4666747b715Smrg        if (i + 6 < num_valuators)
4676747b715Smrg            xv->deviceid |= MORE_EVENTS;
4686747b715Smrg    }
4696747b715Smrg
4706747b715Smrg    return (num_valuators + 5) / 6;
4716747b715Smrg}
4726747b715Smrg
4736747b715Smrgstatic int
47435c4bbdfSmrgappendKeyInfo(DeviceChangedEvent *dce, xXIKeyInfo * info)
4756747b715Smrg{
4766747b715Smrg    uint32_t *kc;
4776747b715Smrg    int i;
4786747b715Smrg
4796747b715Smrg    info->type = XIKeyClass;
4806747b715Smrg    info->num_keycodes = dce->keys.max_keycode - dce->keys.min_keycode + 1;
48135c4bbdfSmrg    info->length = sizeof(xXIKeyInfo) / 4 + info->num_keycodes;
4826747b715Smrg    info->sourceid = dce->sourceid;
4836747b715Smrg
48435c4bbdfSmrg    kc = (uint32_t *) &info[1];
4856747b715Smrg    for (i = 0; i < info->num_keycodes; i++)
4866747b715Smrg        *kc++ = i + dce->keys.min_keycode;
4876747b715Smrg
4886747b715Smrg    return info->length * 4;
4896747b715Smrg}
4906747b715Smrg
4916747b715Smrgstatic int
49235c4bbdfSmrgappendButtonInfo(DeviceChangedEvent *dce, xXIButtonInfo * info)
4936747b715Smrg{
4946747b715Smrg    unsigned char *bits;
4956747b715Smrg    int mask_len;
4966747b715Smrg
4976747b715Smrg    mask_len = bytes_to_int32(bits_to_bytes(dce->buttons.num_buttons));
4986747b715Smrg
4996747b715Smrg    info->type = XIButtonClass;
5006747b715Smrg    info->num_buttons = dce->buttons.num_buttons;
5016747b715Smrg    info->length = bytes_to_int32(sizeof(xXIButtonInfo)) +
50235c4bbdfSmrg        info->num_buttons + mask_len;
5036747b715Smrg    info->sourceid = dce->sourceid;
5046747b715Smrg
50535c4bbdfSmrg    bits = (unsigned char *) &info[1];
5066747b715Smrg    memset(bits, 0, mask_len * 4);
5076747b715Smrg    /* FIXME: is_down? */
5086747b715Smrg
5096747b715Smrg    bits += mask_len * 4;
5106747b715Smrg    memcpy(bits, dce->buttons.names, dce->buttons.num_buttons * sizeof(Atom));
5116747b715Smrg
5126747b715Smrg    return info->length * 4;
5136747b715Smrg}
5146747b715Smrg
5156747b715Smrgstatic int
51635c4bbdfSmrgappendValuatorInfo(DeviceChangedEvent *dce, xXIValuatorInfo * info,
51735c4bbdfSmrg                   int axisnumber)
5186747b715Smrg{
5196747b715Smrg    info->type = XIValuatorClass;
52035c4bbdfSmrg    info->length = sizeof(xXIValuatorInfo) / 4;
5216747b715Smrg    info->label = dce->valuators[axisnumber].name;
5226747b715Smrg    info->min.integral = dce->valuators[axisnumber].min;
5236747b715Smrg    info->min.frac = 0;
5246747b715Smrg    info->max.integral = dce->valuators[axisnumber].max;
5256747b715Smrg    info->max.frac = 0;
52635c4bbdfSmrg    info->value = double_to_fp3232(dce->valuators[axisnumber].value);
5276747b715Smrg    info->resolution = dce->valuators[axisnumber].resolution;
5286747b715Smrg    info->number = axisnumber;
5299ace9065Smrg    info->mode = dce->valuators[axisnumber].mode;
5306747b715Smrg    info->sourceid = dce->sourceid;
5316747b715Smrg
5326747b715Smrg    return info->length * 4;
5336747b715Smrg}
5346747b715Smrg
53535c4bbdfSmrgstatic int
53635c4bbdfSmrgappendScrollInfo(DeviceChangedEvent *dce, xXIScrollInfo * info, int axisnumber)
53735c4bbdfSmrg{
53835c4bbdfSmrg    if (dce->valuators[axisnumber].scroll.type == SCROLL_TYPE_NONE)
53935c4bbdfSmrg        return 0;
54035c4bbdfSmrg
54135c4bbdfSmrg    info->type = XIScrollClass;
54235c4bbdfSmrg    info->length = sizeof(xXIScrollInfo) / 4;
54335c4bbdfSmrg    info->number = axisnumber;
54435c4bbdfSmrg    switch (dce->valuators[axisnumber].scroll.type) {
54535c4bbdfSmrg    case SCROLL_TYPE_VERTICAL:
54635c4bbdfSmrg        info->scroll_type = XIScrollTypeVertical;
54735c4bbdfSmrg        break;
54835c4bbdfSmrg    case SCROLL_TYPE_HORIZONTAL:
54935c4bbdfSmrg        info->scroll_type = XIScrollTypeHorizontal;
55035c4bbdfSmrg        break;
55135c4bbdfSmrg    default:
55235c4bbdfSmrg        ErrorF("[Xi] Unknown scroll type %d. This is a bug.\n",
55335c4bbdfSmrg               dce->valuators[axisnumber].scroll.type);
55435c4bbdfSmrg        break;
55535c4bbdfSmrg    }
55635c4bbdfSmrg    info->increment =
55735c4bbdfSmrg        double_to_fp3232(dce->valuators[axisnumber].scroll.increment);
55835c4bbdfSmrg    info->sourceid = dce->sourceid;
55935c4bbdfSmrg
56035c4bbdfSmrg    info->flags = 0;
56135c4bbdfSmrg
56235c4bbdfSmrg    if (dce->valuators[axisnumber].scroll.flags & SCROLL_FLAG_DONT_EMULATE)
56335c4bbdfSmrg        info->flags |= XIScrollFlagNoEmulation;
56435c4bbdfSmrg    if (dce->valuators[axisnumber].scroll.flags & SCROLL_FLAG_PREFERRED)
56535c4bbdfSmrg        info->flags |= XIScrollFlagPreferred;
56635c4bbdfSmrg
56735c4bbdfSmrg    return info->length * 4;
56835c4bbdfSmrg}
56935c4bbdfSmrg
5706747b715Smrgstatic int
5716747b715SmrgeventToDeviceChanged(DeviceChangedEvent *dce, xEvent **xi)
5726747b715Smrg{
5736747b715Smrg    xXIDeviceChangedEvent *dcce;
5746747b715Smrg    int len = sizeof(xXIDeviceChangedEvent);
5756747b715Smrg    int nkeys;
5766747b715Smrg    char *ptr;
5776747b715Smrg
57835c4bbdfSmrg    if (dce->buttons.num_buttons) {
5796747b715Smrg        len += sizeof(xXIButtonInfo);
5806747b715Smrg        len += dce->buttons.num_buttons * sizeof(Atom); /* button names */
5816747b715Smrg        len += pad_to_int32(bits_to_bytes(dce->buttons.num_buttons));
5826747b715Smrg    }
58335c4bbdfSmrg    if (dce->num_valuators) {
58435c4bbdfSmrg        int i;
58535c4bbdfSmrg
5866747b715Smrg        len += sizeof(xXIValuatorInfo) * dce->num_valuators;
5876747b715Smrg
58835c4bbdfSmrg        for (i = 0; i < dce->num_valuators; i++)
58935c4bbdfSmrg            if (dce->valuators[i].scroll.type != SCROLL_TYPE_NONE)
59035c4bbdfSmrg                len += sizeof(xXIScrollInfo);
59135c4bbdfSmrg    }
59235c4bbdfSmrg
5936747b715Smrg    nkeys = (dce->keys.max_keycode > 0) ?
59435c4bbdfSmrg        dce->keys.max_keycode - dce->keys.min_keycode + 1 : 0;
59535c4bbdfSmrg    if (nkeys > 0) {
5966747b715Smrg        len += sizeof(xXIKeyInfo);
59735c4bbdfSmrg        len += sizeof(CARD32) * nkeys;  /* keycodes */
5986747b715Smrg    }
5996747b715Smrg
6006747b715Smrg    dcce = calloc(1, len);
60135c4bbdfSmrg    if (!dcce) {
6026747b715Smrg        ErrorF("[Xi] BadAlloc in SendDeviceChangedEvent.\n");
6036747b715Smrg        return BadAlloc;
6046747b715Smrg    }
6056747b715Smrg
60635c4bbdfSmrg    dcce->type = GenericEvent;
60735c4bbdfSmrg    dcce->extension = IReqCode;
60835c4bbdfSmrg    dcce->evtype = XI_DeviceChanged;
60935c4bbdfSmrg    dcce->time = dce->time;
61035c4bbdfSmrg    dcce->deviceid = dce->deviceid;
61135c4bbdfSmrg    dcce->sourceid = dce->sourceid;
61235c4bbdfSmrg    dcce->reason =
61335c4bbdfSmrg        (dce->flags & DEVCHANGE_DEVICE_CHANGE) ? XIDeviceChange : XISlaveSwitch;
61435c4bbdfSmrg    dcce->num_classes = 0;
6156747b715Smrg    dcce->length = bytes_to_int32(len - sizeof(xEvent));
6166747b715Smrg
61735c4bbdfSmrg    ptr = (char *) &dcce[1];
61835c4bbdfSmrg    if (dce->buttons.num_buttons) {
6196747b715Smrg        dcce->num_classes++;
62035c4bbdfSmrg        ptr += appendButtonInfo(dce, (xXIButtonInfo *) ptr);
6216747b715Smrg    }
6226747b715Smrg
62335c4bbdfSmrg    if (nkeys) {
6246747b715Smrg        dcce->num_classes++;
62535c4bbdfSmrg        ptr += appendKeyInfo(dce, (xXIKeyInfo *) ptr);
6266747b715Smrg    }
6276747b715Smrg
62835c4bbdfSmrg    if (dce->num_valuators) {
6296747b715Smrg        int i;
6306747b715Smrg
6316747b715Smrg        dcce->num_classes += dce->num_valuators;
6326747b715Smrg        for (i = 0; i < dce->num_valuators; i++)
63335c4bbdfSmrg            ptr += appendValuatorInfo(dce, (xXIValuatorInfo *) ptr, i);
63435c4bbdfSmrg
63535c4bbdfSmrg        for (i = 0; i < dce->num_valuators; i++) {
63635c4bbdfSmrg            if (dce->valuators[i].scroll.type != SCROLL_TYPE_NONE) {
63735c4bbdfSmrg                dcce->num_classes++;
63835c4bbdfSmrg                ptr += appendScrollInfo(dce, (xXIScrollInfo *) ptr, i);
63935c4bbdfSmrg            }
64035c4bbdfSmrg        }
6416747b715Smrg    }
6426747b715Smrg
64335c4bbdfSmrg    *xi = (xEvent *) dcce;
6446747b715Smrg
6456747b715Smrg    return Success;
6466747b715Smrg}
6476747b715Smrg
64835c4bbdfSmrgstatic int
64935c4bbdfSmrgcount_bits(unsigned char *ptr, int len)
6506747b715Smrg{
6516747b715Smrg    int bits = 0;
6526747b715Smrg    unsigned int i;
6536747b715Smrg    unsigned char x;
6546747b715Smrg
65535c4bbdfSmrg    for (i = 0; i < len; i++) {
6566747b715Smrg        x = ptr[i];
65735c4bbdfSmrg        while (x > 0) {
6586747b715Smrg            bits += (x & 0x1);
6596747b715Smrg            x >>= 1;
6606747b715Smrg        }
6616747b715Smrg    }
6626747b715Smrg    return bits;
6636747b715Smrg}
6646747b715Smrg
6656747b715Smrgstatic int
6666747b715SmrgeventToDeviceEvent(DeviceEvent *ev, xEvent **xi)
6676747b715Smrg{
6686747b715Smrg    int len = sizeof(xXIDeviceEvent);
6696747b715Smrg    xXIDeviceEvent *xde;
6706747b715Smrg    int i, btlen, vallen;
6716747b715Smrg    char *ptr;
6726747b715Smrg    FP3232 *axisval;
6736747b715Smrg
6746747b715Smrg    /* FIXME: this should just send the buttons we have, not MAX_BUTTONs. Same
6756747b715Smrg     * with MAX_VALUATORS below */
6766747b715Smrg    /* btlen is in 4 byte units */
6776747b715Smrg    btlen = bytes_to_int32(bits_to_bytes(MAX_BUTTONS));
67835c4bbdfSmrg    len += btlen * 4;           /* buttonmask len */
6796747b715Smrg
6801b5d61b8Smrg    vallen = count_bits(ev->valuators.mask, ARRAY_SIZE(ev->valuators.mask));
68135c4bbdfSmrg    len += vallen * 2 * sizeof(uint32_t);       /* axisvalues */
6826747b715Smrg    vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS));
68335c4bbdfSmrg    len += vallen * 4;          /* valuators mask */
6846747b715Smrg
6856747b715Smrg    *xi = calloc(1, len);
68658cf2af7Smrg    if (*xi == NULL)
68758cf2af7Smrg        return BadAlloc;
68835c4bbdfSmrg    xde = (xXIDeviceEvent *) * xi;
68935c4bbdfSmrg    xde->type = GenericEvent;
69035c4bbdfSmrg    xde->extension = IReqCode;
69135c4bbdfSmrg    xde->evtype = GetXI2Type(ev->type);
69235c4bbdfSmrg    xde->time = ev->time;
69335c4bbdfSmrg    xde->length = bytes_to_int32(len - sizeof(xEvent));
69435c4bbdfSmrg    if (IsTouchEvent((InternalEvent *) ev))
69535c4bbdfSmrg        xde->detail = ev->touchid;
69635c4bbdfSmrg    else
69735c4bbdfSmrg        xde->detail = ev->detail.button;
69835c4bbdfSmrg
69935c4bbdfSmrg    xde->root = ev->root;
70035c4bbdfSmrg    xde->buttons_len = btlen;
70135c4bbdfSmrg    xde->valuators_len = vallen;
70235c4bbdfSmrg    xde->deviceid = ev->deviceid;
70335c4bbdfSmrg    xde->sourceid = ev->sourceid;
70435c4bbdfSmrg    xde->root_x = double_to_fp1616(ev->root_x + ev->root_x_frac);
70535c4bbdfSmrg    xde->root_y = double_to_fp1616(ev->root_y + ev->root_y_frac);
70635c4bbdfSmrg
70735c4bbdfSmrg    if (IsTouchEvent((InternalEvent *)ev)) {
70835c4bbdfSmrg        if (ev->type == ET_TouchUpdate)
70935c4bbdfSmrg            xde->flags |= (ev->flags & TOUCH_PENDING_END) ? XITouchPendingEnd : 0;
71035c4bbdfSmrg
71135c4bbdfSmrg        if (ev->flags & TOUCH_POINTER_EMULATED)
71235c4bbdfSmrg            xde->flags |= XITouchEmulatingPointer;
71335c4bbdfSmrg    } else {
71435c4bbdfSmrg        xde->flags = ev->flags;
71535c4bbdfSmrg
71635c4bbdfSmrg        if (ev->key_repeat)
71735c4bbdfSmrg            xde->flags |= XIKeyRepeat;
71835c4bbdfSmrg    }
71935c4bbdfSmrg
72035c4bbdfSmrg    xde->mods.base_mods = ev->mods.base;
72135c4bbdfSmrg    xde->mods.latched_mods = ev->mods.latched;
72235c4bbdfSmrg    xde->mods.locked_mods = ev->mods.locked;
72335c4bbdfSmrg    xde->mods.effective_mods = ev->mods.effective;
72435c4bbdfSmrg
72535c4bbdfSmrg    xde->group.base_group = ev->group.base;
72635c4bbdfSmrg    xde->group.latched_group = ev->group.latched;
72735c4bbdfSmrg    xde->group.locked_group = ev->group.locked;
72835c4bbdfSmrg    xde->group.effective_group = ev->group.effective;
72935c4bbdfSmrg
73035c4bbdfSmrg    ptr = (char *) &xde[1];
73135c4bbdfSmrg    for (i = 0; i < sizeof(ev->buttons) * 8; i++) {
7326747b715Smrg        if (BitIsOn(ev->buttons, i))
7336747b715Smrg            SetBit(ptr, i);
7346747b715Smrg    }
7356747b715Smrg
7366747b715Smrg    ptr += xde->buttons_len * 4;
73735c4bbdfSmrg    axisval = (FP3232 *) (ptr + xde->valuators_len * 4);
738f2346221Smrg    for (i = 0; i < MAX_VALUATORS; i++) {
73935c4bbdfSmrg        if (BitIsOn(ev->valuators.mask, i)) {
7406747b715Smrg            SetBit(ptr, i);
74135c4bbdfSmrg            *axisval = double_to_fp3232(ev->valuators.data[i]);
7426747b715Smrg            axisval++;
7436747b715Smrg        }
7446747b715Smrg    }
7456747b715Smrg
7466747b715Smrg    return Success;
7476747b715Smrg}
7486747b715Smrg
74935c4bbdfSmrgstatic int
75035c4bbdfSmrgeventToTouchOwnershipEvent(TouchOwnershipEvent *ev, xEvent **xi)
75135c4bbdfSmrg{
75235c4bbdfSmrg    int len = sizeof(xXITouchOwnershipEvent);
75335c4bbdfSmrg    xXITouchOwnershipEvent *xtoe;
75435c4bbdfSmrg
75535c4bbdfSmrg    *xi = calloc(1, len);
75658cf2af7Smrg    if (*xi == NULL)
75758cf2af7Smrg        return BadAlloc;
75835c4bbdfSmrg    xtoe = (xXITouchOwnershipEvent *) * xi;
75935c4bbdfSmrg    xtoe->type = GenericEvent;
76035c4bbdfSmrg    xtoe->extension = IReqCode;
76135c4bbdfSmrg    xtoe->length = bytes_to_int32(len - sizeof(xEvent));
76235c4bbdfSmrg    xtoe->evtype = GetXI2Type(ev->type);
76335c4bbdfSmrg    xtoe->deviceid = ev->deviceid;
76435c4bbdfSmrg    xtoe->time = ev->time;
76535c4bbdfSmrg    xtoe->sourceid = ev->sourceid;
76635c4bbdfSmrg    xtoe->touchid = ev->touchid;
76735c4bbdfSmrg    xtoe->flags = 0;            /* we don't have wire flags for ownership yet */
76835c4bbdfSmrg
76935c4bbdfSmrg    return Success;
77035c4bbdfSmrg}
77135c4bbdfSmrg
7726747b715Smrgstatic int
7736747b715SmrgeventToRawEvent(RawDeviceEvent *ev, xEvent **xi)
7746747b715Smrg{
77535c4bbdfSmrg    xXIRawEvent *raw;
7766747b715Smrg    int vallen, nvals;
7776747b715Smrg    int i, len = sizeof(xXIRawEvent);
7786747b715Smrg    char *ptr;
77935c4bbdfSmrg    FP3232 *axisval, *axisval_raw;
7806747b715Smrg
7816747b715Smrg    nvals = count_bits(ev->valuators.mask, sizeof(ev->valuators.mask));
78235c4bbdfSmrg    len += nvals * sizeof(FP3232) * 2;  /* 8 byte per valuator, once
78335c4bbdfSmrg                                           raw, once processed */
7846747b715Smrg    vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS));
78535c4bbdfSmrg    len += vallen * 4;          /* valuators mask */
7866747b715Smrg
7876747b715Smrg    *xi = calloc(1, len);
78858cf2af7Smrg    if (*xi == NULL)
78958cf2af7Smrg        return BadAlloc;
79035c4bbdfSmrg    raw = (xXIRawEvent *) * xi;
79135c4bbdfSmrg    raw->type = GenericEvent;
79235c4bbdfSmrg    raw->extension = IReqCode;
79335c4bbdfSmrg    raw->evtype = GetXI2Type(ev->type);
79435c4bbdfSmrg    raw->time = ev->time;
79535c4bbdfSmrg    raw->length = bytes_to_int32(len - sizeof(xEvent));
79635c4bbdfSmrg    raw->detail = ev->detail.button;
79735c4bbdfSmrg    raw->deviceid = ev->deviceid;
79835c4bbdfSmrg    raw->sourceid = ev->sourceid;
79935c4bbdfSmrg    raw->valuators_len = vallen;
80035c4bbdfSmrg    raw->flags = ev->flags;
80135c4bbdfSmrg
80235c4bbdfSmrg    ptr = (char *) &raw[1];
80335c4bbdfSmrg    axisval = (FP3232 *) (ptr + raw->valuators_len * 4);
80435c4bbdfSmrg    axisval_raw = axisval + nvals;
805f2346221Smrg    for (i = 0; i < MAX_VALUATORS; i++) {
80635c4bbdfSmrg        if (BitIsOn(ev->valuators.mask, i)) {
8076747b715Smrg            SetBit(ptr, i);
80835c4bbdfSmrg            *axisval = double_to_fp3232(ev->valuators.data[i]);
80935c4bbdfSmrg            *axisval_raw = double_to_fp3232(ev->valuators.data_raw[i]);
8106747b715Smrg            axisval++;
81135c4bbdfSmrg            axisval_raw++;
8126747b715Smrg        }
8136747b715Smrg    }
8146747b715Smrg
8156747b715Smrg    return Success;
8166747b715Smrg}
8176747b715Smrg
81835c4bbdfSmrgstatic int
81935c4bbdfSmrgeventToBarrierEvent(BarrierEvent *ev, xEvent **xi)
82035c4bbdfSmrg{
82135c4bbdfSmrg    xXIBarrierEvent *barrier;
82235c4bbdfSmrg    int len = sizeof(xXIBarrierEvent);
82335c4bbdfSmrg
82435c4bbdfSmrg    *xi = calloc(1, len);
82558cf2af7Smrg    if (*xi == NULL)
82658cf2af7Smrg        return BadAlloc;
82735c4bbdfSmrg    barrier = (xXIBarrierEvent*) *xi;
82835c4bbdfSmrg    barrier->type = GenericEvent;
82935c4bbdfSmrg    barrier->extension = IReqCode;
83035c4bbdfSmrg    barrier->evtype = GetXI2Type(ev->type);
83135c4bbdfSmrg    barrier->length = bytes_to_int32(len - sizeof(xEvent));
83235c4bbdfSmrg    barrier->deviceid = ev->deviceid;
83335c4bbdfSmrg    barrier->sourceid = ev->sourceid;
83435c4bbdfSmrg    barrier->time = ev->time;
83535c4bbdfSmrg    barrier->event = ev->window;
83635c4bbdfSmrg    barrier->root = ev->root;
83735c4bbdfSmrg    barrier->dx = double_to_fp3232(ev->dx);
83835c4bbdfSmrg    barrier->dy = double_to_fp3232(ev->dy);
83935c4bbdfSmrg    barrier->dtime = ev->dt;
84035c4bbdfSmrg    barrier->flags = ev->flags;
84135c4bbdfSmrg    barrier->eventid = ev->event_id;
84235c4bbdfSmrg    barrier->barrier = ev->barrierid;
84335c4bbdfSmrg    barrier->root_x = double_to_fp1616(ev->root_x);
84435c4bbdfSmrg    barrier->root_y = double_to_fp1616(ev->root_y);
84535c4bbdfSmrg
84635c4bbdfSmrg    return Success;
84735c4bbdfSmrg}
84835c4bbdfSmrg
849ed6184dfSmrgint
850ed6184dfSmrgeventToGesturePinchEvent(GestureEvent *ev, xEvent **xi)
851ed6184dfSmrg{
852ed6184dfSmrg    int len = sizeof(xXIGesturePinchEvent);
853ed6184dfSmrg    xXIGesturePinchEvent *xpe;
854ed6184dfSmrg
855ed6184dfSmrg    *xi = calloc(1, len);
85658cf2af7Smrg    if (*xi == NULL)
85758cf2af7Smrg        return BadAlloc;
858ed6184dfSmrg    xpe = (xXIGesturePinchEvent *) * xi;
859ed6184dfSmrg    xpe->type = GenericEvent;
860ed6184dfSmrg    xpe->extension = IReqCode;
861ed6184dfSmrg    xpe->evtype = GetXI2Type(ev->type);
862ed6184dfSmrg    xpe->time = ev->time;
863ed6184dfSmrg    xpe->length = bytes_to_int32(len - sizeof(xEvent));
864ed6184dfSmrg    xpe->detail = ev->num_touches;
865ed6184dfSmrg
866ed6184dfSmrg    xpe->root = ev->root;
867ed6184dfSmrg    xpe->deviceid = ev->deviceid;
868ed6184dfSmrg    xpe->sourceid = ev->sourceid;
869ed6184dfSmrg    xpe->root_x = double_to_fp1616(ev->root_x);
870ed6184dfSmrg    xpe->root_y = double_to_fp1616(ev->root_y);
871ed6184dfSmrg    xpe->flags |= (ev->flags & GESTURE_CANCELLED) ? XIGesturePinchEventCancelled : 0;
872ed6184dfSmrg
873ed6184dfSmrg    xpe->delta_x = double_to_fp1616(ev->delta_x);
874ed6184dfSmrg    xpe->delta_y = double_to_fp1616(ev->delta_y);
875ed6184dfSmrg    xpe->delta_unaccel_x = double_to_fp1616(ev->delta_unaccel_x);
876ed6184dfSmrg    xpe->delta_unaccel_y = double_to_fp1616(ev->delta_unaccel_y);
877ed6184dfSmrg    xpe->scale = double_to_fp1616(ev->scale);
878ed6184dfSmrg    xpe->delta_angle = double_to_fp1616(ev->delta_angle);
879ed6184dfSmrg
880ed6184dfSmrg    xpe->mods.base_mods = ev->mods.base;
881ed6184dfSmrg    xpe->mods.latched_mods = ev->mods.latched;
882ed6184dfSmrg    xpe->mods.locked_mods = ev->mods.locked;
883ed6184dfSmrg    xpe->mods.effective_mods = ev->mods.effective;
884ed6184dfSmrg
885ed6184dfSmrg    xpe->group.base_group = ev->group.base;
886ed6184dfSmrg    xpe->group.latched_group = ev->group.latched;
887ed6184dfSmrg    xpe->group.locked_group = ev->group.locked;
888ed6184dfSmrg    xpe->group.effective_group = ev->group.effective;
889ed6184dfSmrg
890ed6184dfSmrg    return Success;
891ed6184dfSmrg}
892ed6184dfSmrg
893ed6184dfSmrgint
894ed6184dfSmrgeventToGestureSwipeEvent(GestureEvent *ev, xEvent **xi)
895ed6184dfSmrg{
896ed6184dfSmrg    int len = sizeof(xXIGestureSwipeEvent);
897ed6184dfSmrg    xXIGestureSwipeEvent *xde;
898ed6184dfSmrg
899ed6184dfSmrg    *xi = calloc(1, len);
90058cf2af7Smrg    if (*xi == NULL)
90158cf2af7Smrg        return BadAlloc;
902ed6184dfSmrg    xde = (xXIGestureSwipeEvent *) * xi;
903ed6184dfSmrg    xde->type = GenericEvent;
904ed6184dfSmrg    xde->extension = IReqCode;
905ed6184dfSmrg    xde->evtype = GetXI2Type(ev->type);
906ed6184dfSmrg    xde->time = ev->time;
907ed6184dfSmrg    xde->length = bytes_to_int32(len - sizeof(xEvent));
908ed6184dfSmrg    xde->detail = ev->num_touches;
909ed6184dfSmrg
910ed6184dfSmrg    xde->root = ev->root;
911ed6184dfSmrg    xde->deviceid = ev->deviceid;
912ed6184dfSmrg    xde->sourceid = ev->sourceid;
913ed6184dfSmrg    xde->root_x = double_to_fp1616(ev->root_x);
914ed6184dfSmrg    xde->root_y = double_to_fp1616(ev->root_y);
915ed6184dfSmrg    xde->flags |= (ev->flags & GESTURE_CANCELLED) ? XIGestureSwipeEventCancelled : 0;
916ed6184dfSmrg
917ed6184dfSmrg    xde->delta_x = double_to_fp1616(ev->delta_x);
918ed6184dfSmrg    xde->delta_y = double_to_fp1616(ev->delta_y);
919ed6184dfSmrg    xde->delta_unaccel_x = double_to_fp1616(ev->delta_unaccel_x);
920ed6184dfSmrg    xde->delta_unaccel_y = double_to_fp1616(ev->delta_unaccel_y);
921ed6184dfSmrg
922ed6184dfSmrg    xde->mods.base_mods = ev->mods.base;
923ed6184dfSmrg    xde->mods.latched_mods = ev->mods.latched;
924ed6184dfSmrg    xde->mods.locked_mods = ev->mods.locked;
925ed6184dfSmrg    xde->mods.effective_mods = ev->mods.effective;
926ed6184dfSmrg
927ed6184dfSmrg    xde->group.base_group = ev->group.base;
928ed6184dfSmrg    xde->group.latched_group = ev->group.latched;
929ed6184dfSmrg    xde->group.locked_group = ev->group.locked;
930ed6184dfSmrg    xde->group.effective_group = ev->group.effective;
931ed6184dfSmrg
932ed6184dfSmrg    return Success;
933ed6184dfSmrg}
934ed6184dfSmrg
9356747b715Smrg/**
9366747b715Smrg * Return the corresponding core type for the given event or 0 if no core
9376747b715Smrg * equivalent exists.
9386747b715Smrg */
9396747b715Smrgint
94035c4bbdfSmrgGetCoreType(enum EventType type)
9416747b715Smrg{
9426747b715Smrg    int coretype = 0;
94335c4bbdfSmrg
94435c4bbdfSmrg    switch (type) {
94535c4bbdfSmrg    case ET_Motion:
94635c4bbdfSmrg        coretype = MotionNotify;
94735c4bbdfSmrg        break;
94835c4bbdfSmrg    case ET_ButtonPress:
94935c4bbdfSmrg        coretype = ButtonPress;
95035c4bbdfSmrg        break;
95135c4bbdfSmrg    case ET_ButtonRelease:
95235c4bbdfSmrg        coretype = ButtonRelease;
95335c4bbdfSmrg        break;
95435c4bbdfSmrg    case ET_KeyPress:
95535c4bbdfSmrg        coretype = KeyPress;
95635c4bbdfSmrg        break;
95735c4bbdfSmrg    case ET_KeyRelease:
95835c4bbdfSmrg        coretype = KeyRelease;
95935c4bbdfSmrg        break;
96035c4bbdfSmrg    default:
96135c4bbdfSmrg        break;
9626747b715Smrg    }
9636747b715Smrg    return coretype;
9646747b715Smrg}
9656747b715Smrg
9666747b715Smrg/**
9676747b715Smrg * Return the corresponding XI 1.x type for the given event or 0 if no
9686747b715Smrg * equivalent exists.
9696747b715Smrg */
9706747b715Smrgint
97135c4bbdfSmrgGetXIType(enum EventType type)
9726747b715Smrg{
9736747b715Smrg    int xitype = 0;
97435c4bbdfSmrg
97535c4bbdfSmrg    switch (type) {
97635c4bbdfSmrg    case ET_Motion:
97735c4bbdfSmrg        xitype = DeviceMotionNotify;
97835c4bbdfSmrg        break;
97935c4bbdfSmrg    case ET_ButtonPress:
98035c4bbdfSmrg        xitype = DeviceButtonPress;
98135c4bbdfSmrg        break;
98235c4bbdfSmrg    case ET_ButtonRelease:
98335c4bbdfSmrg        xitype = DeviceButtonRelease;
98435c4bbdfSmrg        break;
98535c4bbdfSmrg    case ET_KeyPress:
98635c4bbdfSmrg        xitype = DeviceKeyPress;
98735c4bbdfSmrg        break;
98835c4bbdfSmrg    case ET_KeyRelease:
98935c4bbdfSmrg        xitype = DeviceKeyRelease;
99035c4bbdfSmrg        break;
99135c4bbdfSmrg    case ET_ProximityIn:
99235c4bbdfSmrg        xitype = ProximityIn;
99335c4bbdfSmrg        break;
99435c4bbdfSmrg    case ET_ProximityOut:
99535c4bbdfSmrg        xitype = ProximityOut;
99635c4bbdfSmrg        break;
99735c4bbdfSmrg    default:
99835c4bbdfSmrg        break;
9996747b715Smrg    }
10006747b715Smrg    return xitype;
10016747b715Smrg}
10026747b715Smrg
10036747b715Smrg/**
10046747b715Smrg * Return the corresponding XI 2.x type for the given event or 0 if no
10056747b715Smrg * equivalent exists.
10066747b715Smrg */
10076747b715Smrgint
100835c4bbdfSmrgGetXI2Type(enum EventType type)
10096747b715Smrg{
10106747b715Smrg    int xi2type = 0;
10116747b715Smrg
101235c4bbdfSmrg    switch (type) {
101335c4bbdfSmrg    case ET_Motion:
101435c4bbdfSmrg        xi2type = XI_Motion;
101535c4bbdfSmrg        break;
101635c4bbdfSmrg    case ET_ButtonPress:
101735c4bbdfSmrg        xi2type = XI_ButtonPress;
101835c4bbdfSmrg        break;
101935c4bbdfSmrg    case ET_ButtonRelease:
102035c4bbdfSmrg        xi2type = XI_ButtonRelease;
102135c4bbdfSmrg        break;
102235c4bbdfSmrg    case ET_KeyPress:
102335c4bbdfSmrg        xi2type = XI_KeyPress;
102435c4bbdfSmrg        break;
102535c4bbdfSmrg    case ET_KeyRelease:
102635c4bbdfSmrg        xi2type = XI_KeyRelease;
102735c4bbdfSmrg        break;
102835c4bbdfSmrg    case ET_Enter:
102935c4bbdfSmrg        xi2type = XI_Enter;
103035c4bbdfSmrg        break;
103135c4bbdfSmrg    case ET_Leave:
103235c4bbdfSmrg        xi2type = XI_Leave;
103335c4bbdfSmrg        break;
103435c4bbdfSmrg    case ET_Hierarchy:
103535c4bbdfSmrg        xi2type = XI_HierarchyChanged;
103635c4bbdfSmrg        break;
103735c4bbdfSmrg    case ET_DeviceChanged:
103835c4bbdfSmrg        xi2type = XI_DeviceChanged;
103935c4bbdfSmrg        break;
104035c4bbdfSmrg    case ET_RawKeyPress:
104135c4bbdfSmrg        xi2type = XI_RawKeyPress;
104235c4bbdfSmrg        break;
104335c4bbdfSmrg    case ET_RawKeyRelease:
104435c4bbdfSmrg        xi2type = XI_RawKeyRelease;
104535c4bbdfSmrg        break;
104635c4bbdfSmrg    case ET_RawButtonPress:
104735c4bbdfSmrg        xi2type = XI_RawButtonPress;
104835c4bbdfSmrg        break;
104935c4bbdfSmrg    case ET_RawButtonRelease:
105035c4bbdfSmrg        xi2type = XI_RawButtonRelease;
105135c4bbdfSmrg        break;
105235c4bbdfSmrg    case ET_RawMotion:
105335c4bbdfSmrg        xi2type = XI_RawMotion;
105435c4bbdfSmrg        break;
105535c4bbdfSmrg    case ET_RawTouchBegin:
105635c4bbdfSmrg        xi2type = XI_RawTouchBegin;
105735c4bbdfSmrg        break;
105835c4bbdfSmrg    case ET_RawTouchUpdate:
105935c4bbdfSmrg        xi2type = XI_RawTouchUpdate;
106035c4bbdfSmrg        break;
106135c4bbdfSmrg    case ET_RawTouchEnd:
106235c4bbdfSmrg        xi2type = XI_RawTouchEnd;
106335c4bbdfSmrg        break;
106435c4bbdfSmrg    case ET_FocusIn:
106535c4bbdfSmrg        xi2type = XI_FocusIn;
106635c4bbdfSmrg        break;
106735c4bbdfSmrg    case ET_FocusOut:
106835c4bbdfSmrg        xi2type = XI_FocusOut;
106935c4bbdfSmrg        break;
107035c4bbdfSmrg    case ET_TouchBegin:
107135c4bbdfSmrg        xi2type = XI_TouchBegin;
107235c4bbdfSmrg        break;
107335c4bbdfSmrg    case ET_TouchEnd:
107435c4bbdfSmrg        xi2type = XI_TouchEnd;
107535c4bbdfSmrg        break;
107635c4bbdfSmrg    case ET_TouchUpdate:
107735c4bbdfSmrg        xi2type = XI_TouchUpdate;
107835c4bbdfSmrg        break;
107935c4bbdfSmrg    case ET_TouchOwnership:
108035c4bbdfSmrg        xi2type = XI_TouchOwnership;
108135c4bbdfSmrg        break;
108235c4bbdfSmrg    case ET_BarrierHit:
108335c4bbdfSmrg        xi2type = XI_BarrierHit;
108435c4bbdfSmrg        break;
108535c4bbdfSmrg    case ET_BarrierLeave:
108635c4bbdfSmrg        xi2type = XI_BarrierLeave;
108735c4bbdfSmrg        break;
1088ed6184dfSmrg    case ET_GesturePinchBegin:
1089ed6184dfSmrg        xi2type = XI_GesturePinchBegin;
1090ed6184dfSmrg        break;
1091ed6184dfSmrg    case ET_GesturePinchUpdate:
1092ed6184dfSmrg        xi2type = XI_GesturePinchUpdate;
1093ed6184dfSmrg        break;
1094ed6184dfSmrg    case ET_GesturePinchEnd:
1095ed6184dfSmrg        xi2type = XI_GesturePinchEnd;
1096ed6184dfSmrg        break;
1097ed6184dfSmrg    case ET_GestureSwipeBegin:
1098ed6184dfSmrg        xi2type = XI_GestureSwipeBegin;
1099ed6184dfSmrg        break;
1100ed6184dfSmrg    case ET_GestureSwipeUpdate:
1101ed6184dfSmrg        xi2type = XI_GestureSwipeUpdate;
1102ed6184dfSmrg        break;
1103ed6184dfSmrg    case ET_GestureSwipeEnd:
1104ed6184dfSmrg        xi2type = XI_GestureSwipeEnd;
1105ed6184dfSmrg        break;
110635c4bbdfSmrg    default:
110735c4bbdfSmrg        break;
11086747b715Smrg    }
11096747b715Smrg    return xi2type;
11106747b715Smrg}
1111ed6184dfSmrg
1112ed6184dfSmrg/**
1113ed6184dfSmrg * Converts a gesture type to corresponding Gesture{Pinch,Swipe}Begin.
1114ed6184dfSmrg * Returns 0 if the input type is not a gesture.
1115ed6184dfSmrg */
1116ed6184dfSmrgenum EventType
1117ed6184dfSmrgGestureTypeToBegin(enum EventType type)
1118ed6184dfSmrg{
1119ed6184dfSmrg    switch (type) {
1120ed6184dfSmrg    case ET_GesturePinchBegin:
1121ed6184dfSmrg    case ET_GesturePinchUpdate:
1122ed6184dfSmrg    case ET_GesturePinchEnd:
1123ed6184dfSmrg        return ET_GesturePinchBegin;
1124ed6184dfSmrg    case ET_GestureSwipeBegin:
1125ed6184dfSmrg    case ET_GestureSwipeUpdate:
1126ed6184dfSmrg    case ET_GestureSwipeEnd:
1127ed6184dfSmrg        return ET_GestureSwipeBegin;
1128ed6184dfSmrg    default:
1129ed6184dfSmrg        return 0;
1130ed6184dfSmrg    }
1131ed6184dfSmrg}
1132ed6184dfSmrg
1133ed6184dfSmrg/**
1134ed6184dfSmrg * Converts a gesture type to corresponding Gesture{Pinch,Swipe}End.
1135ed6184dfSmrg * Returns 0 if the input type is not a gesture.
1136ed6184dfSmrg */
1137ed6184dfSmrgenum EventType
1138ed6184dfSmrgGestureTypeToEnd(enum EventType type)
1139ed6184dfSmrg{
1140ed6184dfSmrg    switch (type) {
1141ed6184dfSmrg    case ET_GesturePinchBegin:
1142ed6184dfSmrg    case ET_GesturePinchUpdate:
1143ed6184dfSmrg    case ET_GesturePinchEnd:
1144ed6184dfSmrg        return ET_GesturePinchEnd;
1145ed6184dfSmrg    case ET_GestureSwipeBegin:
1146ed6184dfSmrg    case ET_GestureSwipeUpdate:
1147ed6184dfSmrg    case ET_GestureSwipeEnd:
1148ed6184dfSmrg        return ET_GestureSwipeEnd;
1149ed6184dfSmrg    default:
1150ed6184dfSmrg        return 0;
1151ed6184dfSmrg    }
1152ed6184dfSmrg}
1153