summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dix/Makefile.am2
-rw-r--r--dix/eventconvert.c290
-rw-r--r--include/Makefile.am2
-rw-r--r--include/eventconvert.h34
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_ */