summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2011-04-12 10:17:07 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2011-05-04 09:32:36 +1000
commitd6328c6bfe49958f68abbb6ddbc1f1514de6831f (patch)
tree6c11838e80b45e1515c30a2a136127b9a3b58f23
parentb4455b119cb55cc5f61add0c25863afe8cb06484 (diff)
Xi: fix valuator alignment in DeepCopyDeviceClasses (#36119)
commit 678f5396c91b3d0c7572ed579b0a4fb62b2b4655 only fixed the initialization, not the copy. After a slave device change, the valuator were out of alignment again. X.Org Bug 36119 <http://bugs.freedesktop.org/show_bug.cgi?id=36119> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com> (cherry picked from commit 419a27b5219a739f2fbd50cc96a1b54c469e4a88)
-rw-r--r--Xi/exevents.c11
-rw-r--r--dix/devices.c47
-rw-r--r--include/input.h5
-rw-r--r--include/inputstr.h2
-rw-r--r--test/input.c24
5 files changed, 70 insertions, 19 deletions
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 35f96e6cd..9bd9d6078 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -535,6 +535,7 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
if (from->valuator)
{
ValuatorClassPtr v;
+
if (!to->valuator)
{
classes = to->unused_classes;
@@ -543,18 +544,14 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
classes->valuator = NULL;
}
- to->valuator = realloc(to->valuator, sizeof(ValuatorClassRec) +
- from->valuator->numAxes * sizeof(AxisInfo) +
- from->valuator->numAxes * sizeof(double));
- v = to->valuator;
+ v = AllocValuatorClass(to->valuator, from->valuator->numAxes);
+
if (!v)
FatalError("[Xi] no memory for class shift.\n");
- v->numAxes = from->valuator->numAxes;
- v->axes = (AxisInfoPtr)&v[1];
+ to->valuator = v;
memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
- v->axisVal = (double*)(v->axes + from->valuator->numAxes);
v->sourceid = from->id;
} else if (to->valuator && !from->valuator)
{
diff --git a/dix/devices.c b/dix/devices.c
index 55f22cbaf..fed05f5e2 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1221,13 +1221,46 @@ InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, Atom* labels,
return TRUE;
}
+/**
+ * Allocate a valuator class and set up the pointers for the axis values
+ * appropriately.
+ *
+ * @param src If non-NULL, the memory is reallocated from src. If NULL, the
+ * memory is calloc'd.
+ * @parma numAxes Number of axes to allocate.
+ * @return The allocated valuator struct.
+ */
+ValuatorClassPtr
+AllocValuatorClass(ValuatorClassPtr src, int numAxes)
+{
+ ValuatorClassPtr v;
+ /* force alignment with double */
+ union align_u { ValuatorClassRec valc; double d; } *align;
+ int size;
+
+ size = sizeof(union align_u) + numAxes * (sizeof(double) + sizeof(AxisInfo));
+ align = (union align_u *) realloc(src, size);
+
+ if (!align)
+ return NULL;
+
+ if (!src)
+ memset(align, 0, size);
+
+ v = &align->valc;
+ v->numAxes = numAxes;
+ v->axisVal = (double*)(align + 1);
+ v->axes = (AxisInfoPtr)(v->axisVal + numAxes);
+
+ return v;
+}
+
Bool
InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
int numMotionEvents, int mode)
{
int i;
ValuatorClassPtr valc;
- union align_u { ValuatorClassRec valc; double d; } *align;
if (!dev)
return FALSE;
@@ -1240,13 +1273,10 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
numAxes = MAX_VALUATORS;
}
- align = (union align_u *) calloc(1, sizeof(union align_u) +
- numAxes * sizeof(double) +
- numAxes * sizeof(AxisInfo));
- if (!align)
- return FALSE;
+ valc = AllocValuatorClass(NULL, numAxes);
+ if (!valc)
+ return FALSE;
- valc = &align->valc;
valc->sourceid = dev->id;
valc->motion = NULL;
valc->first_motion = 0;
@@ -1254,9 +1284,6 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
valc->numMotionEvents = numMotionEvents;
valc->motionHintWindow = NullWindow;
- valc->numAxes = numAxes;
- valc->axisVal = (double *)(align + 1);
- valc->axes = (AxisInfoPtr)(valc->axisVal + numAxes);
if (mode & OutOfProximity)
InitProximityClassDeviceStruct(dev);
diff --git a/include/input.h b/include/input.h
index f96a0a988..908e595e5 100644
--- a/include/input.h
+++ b/include/input.h
@@ -102,6 +102,7 @@ typedef unsigned long Leds;
typedef struct _OtherClients *OtherClientsPtr;
typedef struct _InputClients *InputClientsPtr;
typedef struct _DeviceIntRec *DeviceIntPtr;
+typedef struct _ValuatorClassRec *ValuatorClassPtr;
typedef struct _ClassesRec *ClassesPtr;
typedef struct _SpriteRec *SpritePtr;
typedef union _GrabMask GrabMask;
@@ -297,6 +298,10 @@ extern _X_EXPORT Bool InitButtonClassDeviceStruct(
Atom* /* labels */,
CARD8* /*map*/);
+extern _X_INTERNAL ValuatorClassPtr AllocValuatorClass(
+ ValuatorClassPtr src,
+ int numAxes);
+
extern _X_EXPORT Bool InitValuatorClassDeviceStruct(
DeviceIntPtr /*device*/,
int /*numAxes*/,
diff --git a/include/inputstr.h b/include/inputstr.h
index b74ee0454..2ee2fd835 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -282,7 +282,7 @@ typedef struct _ValuatorClassRec {
unsigned short numAxes;
double *axisVal; /* always absolute, but device-coord system */
ValuatorAccelerationRec accelScheme;
-} ValuatorClassRec, *ValuatorClassPtr;
+} ValuatorClassRec;
typedef struct _ButtonClassRec {
int sourceid;
diff --git a/test/input.c b/test/input.c
index e0e9e6af7..4d840b9b4 100644
--- a/test/input.c
+++ b/test/input.c
@@ -1199,6 +1199,28 @@ static void include_bit_test_macros(void)
}
}
+/**
+ * Ensure that val->axisVal and val->axes are aligned on doubles.
+ */
+static void dix_valuator_alloc(void)
+{
+ ValuatorClassPtr v = NULL;
+ int num_axes = 0;
+
+ while (num_axes < 5)
+ {
+ v = AllocValuatorClass(v, num_axes);
+
+ g_assert(v);
+ g_assert(v->numAxes == num_axes);
+ g_assert(((void*)v->axisVal - (void*)v) % sizeof(double) == 0);
+ g_assert(((void*)v->axes - (void*)v) % sizeof(double) == 0);
+ num_axes ++;
+ }
+
+ free(v);
+}
+
int main(int argc, char** argv)
{
g_test_init(&argc, &argv,NULL);
@@ -1216,7 +1238,7 @@ int main(int argc, char** argv)
g_test_add_func("/include/byte_padding_macros", include_byte_padding_macros);
g_test_add_func("/include/bit_test_macros", include_bit_test_macros);
g_test_add_func("/Xi/xiproperty/register-unregister", xi_unregister_handlers);
-
+ g_test_add_func("/dix/input/valuator-alloc", dix_valuator_alloc);
return g_test_run();
}