diff options
-rw-r--r-- | dix/Makefile.am | 2 | ||||
-rw-r--r-- | dix/eventconvert.c | 290 | ||||
-rw-r--r-- | include/Makefile.am | 2 | ||||
-rw-r--r-- | include/eventconvert.h | 34 |
4 files changed, 327 insertions, 1 deletions
diff --git a/dix/Makefile.am b/dix/Makefile.am index 34eeb6ddd..8c5f3c00e 100644 --- a/dix/Makefile.am +++ b/dix/Makefile.am @@ -17,6 +17,8 @@ libdix_la_SOURCES = \ enterleave.c \ enterleave.h \ events.c \ + eventconvert.h \ + eventconvert.c \ extension.c \ ffs.c \ gc.c \ diff --git a/dix/eventconvert.c b/dix/eventconvert.c new file mode 100644 index 000000000..c3658112d --- /dev/null +++ b/dix/eventconvert.c @@ -0,0 +1,290 @@ +/* + * Copyright © 2009 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file This file contains event conversion routines from InternalEvent to + * the matching protocol events. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/extensions/XIproto.h> +#include <X11/extensions/XI.h> + +#include "dix.h" +#include "inputstr.h" +#include "misc.h" +#include "events.h" +#include "exglobals.h" +#include "eventconvert.h" +#include "listdev.h" + +static int countValuators(DeviceEvent *ev, int *first); +static int getValuatorEvents(DeviceEvent *ev, EventListPtr xi); +static int eventToKeyButtonPointer(DeviceEvent *ev, EventListPtr xi, int *count); +static int eventToClassesChanged(DeviceChangedEvent *ev, EventListPtr dcce, + int *count); + +/** + * Convert the given event @ev to the respective core event and store it in + * @core. + * + * Return values: + * Success ... @core contains the matching core event. + * BadValue .. One or more values in the internal event are invalid. + * BadMatch .. The event has no core equivalent. + * + * @return Success or the matching error code. + */ +int +EventToCore(InternalEvent *event, xEvent *core) +{ + switch(event->u.any.type) + { + case ET_Motion: + case ET_ButtonPress: + case ET_ButtonRelease: + case ET_KeyPress: + case ET_KeyRelease: + case ET_ProximityIn: + case ET_ProximityOut: + { + DeviceEvent *e = (DeviceEvent*)event; + + if (e->detail.key > 0xFF) + return BadMatch; + + memset(core, 0, sizeof(xEvent)); + core->u.u.type = e->type - ET_KeyPress + KeyPress; + core->u.u.detail = e->detail.key & 0xFF; + core->u.keyButtonPointer.time = e->time; + core->u.keyButtonPointer.rootX = e->root_x; + core->u.keyButtonPointer.rootY = e->root_y; + core->u.keyButtonPointer.state = e->corestate; + } + break; + default: + /* XXX: */ + ErrorF("[dix] EventToCore: Not implemented yet \n"); + return BadImplementation; + } + return Success; +} + +/** + * Convert the given event @ev to the respective XI 1.x event and store it in + * @xi. @xi must be allocated by the caller, @count specifies the number of + * events in @xi. + * + * + * If less than @count events are needed, @count is set to the events stored + * in @xi and Success is returned. + * + * If more than @count events are needed, @count is set to the number of + * events required, and BadAlloc is returned. @xi is untouched. + * + * If necessary, @xi is realloced using SetMinimumEventSize() to fit the + * largest event being returned. + * + * If the event cannot be converted into an XI event because of protocol + * restrictions, @count is 0 and Success is returned. + */ +int +EventToXI(InternalEvent *ev, EventListPtr xi, int *count) +{ + switch (ev->u.any.type) + { + case ET_Motion: + case ET_ButtonPress: + case ET_ButtonRelease: + case ET_KeyPress: + case ET_KeyRelease: + case ET_ProximityIn: + case ET_ProximityOut: + return eventToKeyButtonPointer((DeviceEvent*)ev, xi, count); + case ET_DeviceChanged: + return eventToClassesChanged((DeviceChangedEvent*)ev, xi, count); + break; + } + + ErrorF("[dix] EventToXI: Not implemented for %d \n", ev->u.any.type); + return BadImplementation; +} + +static int +eventToKeyButtonPointer(DeviceEvent *ev, EventListPtr xi, int *count) +{ + int num_events; + int first; /* dummy */ + deviceKeyButtonPointer *kbp; + + /* Sorry, XI 1.x protocol restrictions. */ + if (ev->detail.button > 0xFF || ev->deviceid >= 0x80) + { + *count = 0; + return Success; + } + + num_events = (countValuators(ev, &first) + 5)/6; /* valuator ev */ + num_events++; /* the actual event event */ + + if (*count < num_events) + { + *count = num_events; + return BadAlloc; + } + + SetMinimumEventSize(xi, *count, 32); + + kbp = (deviceKeyButtonPointer*)xi->event; + kbp->detail = ev->detail.button; + kbp->time = ev->time; + kbp->root = ev->root; + kbp->root_x = ev->root_x; + kbp->root_y = ev->root_y; + kbp->deviceid = ev->deviceid; + kbp->state = ev->corestate; + + if (num_events > 1) + kbp->deviceid |= MORE_EVENTS; + + switch(ev->type) + { + case ET_Motion: kbp->type = DeviceMotionNotify; break; + case ET_ButtonPress: kbp->type = DeviceButtonPress; break; + case ET_ButtonRelease: kbp->type = DeviceButtonRelease; break; + case ET_KeyPress: kbp->type = DeviceKeyPress; break; + case ET_KeyRelease: kbp->type = DeviceKeyRelease; break; + case ET_ProximityIn: kbp->type = ProximityIn; break; + case ET_ProximityOut: kbp->type = ProximityOut; break; + } + + + if (num_events > 1) + { + getValuatorEvents(ev, xi + 1); + } + + *count = num_events; + return Success; +} + + +/** + * Set @first to the first valuator in the event @ev and return the number of + * valuators from @first to the last set valuator. + */ +static int +countValuators(DeviceEvent *ev, int *first) +{ + int first_valuator = -1, last_valuator = -1, num_valuators = 0; + int i; + + for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) + { + if (BitIsOn(ev->valuators.mask, i)) + { + if (first_valuator == -1) + first_valuator = i; + last_valuator = i; + } + } + + if (first_valuator != -1) + { + num_valuators = last_valuator - first_valuator + 1; + *first = first_valuator; + } + + return num_valuators; +} + +static int +getValuatorEvents(DeviceEvent *ev, EventListPtr events) +{ + int i; + deviceValuator *xv; + int first_valuator, num_valuators; + + num_valuators = countValuators(ev, &first_valuator); + + /* FIXME: non-continuous valuator data in internal events*/ + for (i = 0; i < num_valuators; i += 6, events++) { + xv = (deviceValuator*)events->event; + xv->type = DeviceValuator; + xv->first_valuator = first_valuator + i; + xv->num_valuators = ((num_valuators - i) > 6) ? 6 : (num_valuators - i); + xv->deviceid = ev->deviceid; + switch (xv->num_valuators) { + case 6: + xv->valuator5 = ev->valuators.data[i + 5]; + case 5: + xv->valuator4 = ev->valuators.data[i + 4]; + case 4: + xv->valuator3 = ev->valuators.data[i + 3]; + case 3: + xv->valuator2 = ev->valuators.data[i + 2]; + case 2: + xv->valuator1 = ev->valuators.data[i + 1]; + case 1: + xv->valuator0 = ev->valuators.data[i + 0]; + } + + if (i + 6 < num_valuators) + xv->deviceid |= MORE_EVENTS; + } + + return (num_valuators + 5) / 6; +} + +static int +eventToClassesChanged(DeviceChangedEvent *ev, EventListPtr events, int *count) +{ + int len = sizeof(xEvent); + int namelen = 0; /* dummy */ + DeviceIntPtr slave; + int rc; + deviceClassesChangedEvent *dcce = (deviceClassesChangedEvent*)events->event; + + rc = dixLookupDevice(&slave, ev->new_slaveid, + serverClient, DixReadAccess); + + if (rc != Success) + return rc; + + SizeDeviceInfo(slave, &namelen, &len); + + dcce->type = GenericEvent; + dcce->extension = IReqCode; + dcce->evtype = XI_DeviceClassesChangedNotify; + dcce->time = GetTimeInMillis(); + dcce->new_slave = slave->id; + dcce->length = (len - sizeof(xEvent))/4; + + *count = 1; + return Success; +} diff --git a/include/Makefile.am b/include/Makefile.am index 09300fe2d..fda4b70ac 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -57,7 +57,7 @@ sdk_HEADERS = \ xkbrules.h \ xserver-properties.h -nodist_sdk_HEADERS = xorg-server.h events.h +nodist_sdk_HEADERS = xorg-server.h events.h eventconvert.h endif AM_CFLAGS = $(DIX_CFLAGS) diff --git a/include/eventconvert.h b/include/eventconvert.h new file mode 100644 index 000000000..244358261 --- /dev/null +++ b/include/eventconvert.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2009 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _EVENTCONVERT_H_ +#include <X11/X.h> +#include <X11/extensions/XIproto.h> +#include "input.h" +#include "events.h" + +_X_INTERNAL int EventToCore(InternalEvent *event, xEvent *core); +_X_INTERNAL int EventToXI(InternalEvent *ev, EventListPtr xi, int *count); + +#endif /* _EVENTCONVERT_H_ */ |