From 5f10cd1f39127bafbd2fa69dd497949487a6e1ae Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 1 Aug 2011 10:51:53 +1000 Subject: [PATCH] input: store the highest valuator in DeviceEvents and RawEvents Don't walk the full length of the valuator mask whenever an event is handled. Instead, save which one is the highest valuator and stop there. Side-effect: we would previously always send a valuator mask down the wire, even if no valuators were sent. Now the valuator mask is not sent when empty. Preparation work for the fix to Bug 38313. Signed-off-by: Peter Hutterer --- Xi/exevents.c | 27 ++++++++++++--------------- dix/eventconvert.c | 36 ++++++++++++++++++++---------------- dix/getevents.c | 8 ++++++++ include/eventstr.h | 2 ++ test/xi2/protocol-eventconvert.c | 23 +++++++++++++++++++++-- 5 files changed, 63 insertions(+), 33 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 3e3c67b..4900193 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -754,23 +754,20 @@ UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event) /* Update device axis */ /* Check valuators first */ - last_valuator = -1; - for (i = 0; i < MAX_VALUATORS; i++) + last_valuator = event->valuators.highest_valuator; + + if (last_valuator >= 0) { - if (BitIsOn(&event->valuators.mask, i)) + if (!v) { - if (!v) - { - ErrorF("[Xi] Valuators reported for non-valuator device '%s'. " - "Ignoring event.\n", device->name); - return DONT_PROCESS; - } else if (v->numAxes < i) - { - ErrorF("[Xi] Too many valuators reported for device '%s'. " - "Ignoring event.\n", device->name); - return DONT_PROCESS; - } - last_valuator = i; + ErrorF("[Xi] Valuators reported for non-valuator device '%s'. " + "Ignoring event.\n", device->name); + return DONT_PROCESS; + } else if (v->numAxes < last_valuator) + { + ErrorF("[Xi] Too many valuators reported for device '%s'. " + "Ignoring event.\n", device->name); + return DONT_PROCESS; } } diff --git a/dix/eventconvert.c b/dix/eventconvert.c index e47348c..624e95b 100644 --- a/dix/eventconvert.c +++ b/dix/eventconvert.c @@ -358,13 +358,13 @@ 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++) + last_valuator = ev->valuators.highest_valuator; + for (i = 0; i <= ev->valuators.highest_valuator; i++) { if (BitIsOn(ev->valuators.mask, i)) { if (first_valuator == -1) first_valuator = i; - last_valuator = i; } } @@ -573,7 +573,7 @@ eventToDeviceEvent(DeviceEvent *ev, xEvent **xi) { int len = sizeof(xXIDeviceEvent); xXIDeviceEvent *xde; - int i, btlen, vallen; + int i, btlen, vallen = 0; char *ptr; FP3232 *axisval; @@ -583,11 +583,13 @@ eventToDeviceEvent(DeviceEvent *ev, xEvent **xi) btlen = bytes_to_int32(bits_to_bytes(MAX_BUTTONS)); len += btlen * 4; /* buttonmask len */ - - vallen = count_bits(ev->valuators.mask, sizeof(ev->valuators.mask)/sizeof(ev->valuators.mask[0])); - len += vallen * 2 * sizeof(uint32_t); /* axisvalues */ - vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS)); - len += vallen * 4; /* valuators mask */ + if (ev->valuators.highest_valuator > -1) + { + vallen = count_bits(ev->valuators.mask, bits_to_bytes(ev->valuators.highest_valuator + 1)); + len += vallen * 2 * sizeof(uint32_t); /* axisvalues */ + vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS)); + len += vallen * 4; /* valuators mask */ + } *xi = calloc(1, len); xde = (xXIDeviceEvent*)*xi; @@ -627,7 +629,7 @@ eventToDeviceEvent(DeviceEvent *ev, xEvent **xi) ptr += xde->buttons_len * 4; axisval = (FP3232*)(ptr + xde->valuators_len * 4); - for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) + for (i = 0; i <= ev->valuators.highest_valuator; i++) { if (BitIsOn(ev->valuators.mask, i)) { @@ -645,16 +647,18 @@ static int eventToRawEvent(RawDeviceEvent *ev, xEvent **xi) { xXIRawEvent* raw; - int vallen, nvals; + int vallen = 0, nvals = 0; int i, len = sizeof(xXIRawEvent); char *ptr; FP3232 *axisval; - nvals = count_bits(ev->valuators.mask, sizeof(ev->valuators.mask)); - len += nvals * sizeof(FP3232) * 2; /* 8 byte per valuator, once - raw, once processed */ - vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS)); - len += vallen * 4; /* valuators mask */ + if (ev->valuators.highest_valuator > -1) { + nvals = count_bits(ev->valuators.mask, bits_to_bytes(ev->valuators.highest_valuator + 1)); + len += nvals * sizeof(FP3232) * 2; /* 8 byte per valuator, once + raw, once processed */ + vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS)); + len += vallen * 4; /* valuators mask */ + } *xi = calloc(1, len); raw = (xXIRawEvent*)*xi; @@ -670,7 +674,7 @@ eventToRawEvent(RawDeviceEvent *ev, xEvent **xi) ptr = (char*)&raw[1]; axisval = (FP3232*)(ptr + raw->valuators_len * 4); - for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) + for (i = 0; i <= ev->valuators.highest_valuator; i++) { if (BitIsOn(ev->valuators.mask, i)) { diff --git a/dix/getevents.c b/dix/getevents.c index a12462a..3e97b01 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -162,6 +162,7 @@ init_event(DeviceIntPtr dev, DeviceEvent* event, Time ms) event->time = ms; event->deviceid = dev->id; event->sourceid = dev->id; + event->valuators.highest_valuator = -1; } static void @@ -182,10 +183,13 @@ set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, int32_t* data) { int i; + event->valuators.highest_valuator = -1; + for (i = 0; i < valuator_mask_size(mask); i++) { if (valuator_mask_isset(mask, i)) { + event->valuators.highest_valuator = i; SetBit(event->valuators.mask, i); data[i] = valuator_mask_get(mask, i); } @@ -198,12 +202,16 @@ set_valuators(DeviceIntPtr dev, DeviceEvent* event, ValuatorMask *mask) { int i; + event->valuators.highest_valuator = -1; + /* Set the data to the previous value for unset absolute axes. The values * may be used when sent as part of an XI 1.x valuator event. */ for (i = 0; i < valuator_mask_size(mask); i++) { if (valuator_mask_isset(mask, i)) { + event->valuators.highest_valuator = i; + SetBit(event->valuators.mask, i); if (valuator_get_mode(dev, i) == Absolute) SetBit(event->valuators.mode, i); diff --git a/include/eventstr.h b/include/eventstr.h index 049688c..fa4ed81 100644 --- a/include/eventstr.h +++ b/include/eventstr.h @@ -93,6 +93,7 @@ struct _DeviceEvent float root_y_frac; /**< Pos relative to root window in frac part */ uint8_t buttons[(MAX_BUTTONS + 7)/8]; /**< Button mask */ struct { + short highest_valuator; /**< highest bit set in mask, -1 if none */ uint8_t mask[(MAX_VALUATORS + 7)/8]; /**< Valuator mask */ uint8_t mode[(MAX_VALUATORS + 7)/8]; /**< Valuator mode (Abs or Rel)*/ int32_t data[MAX_VALUATORS]; /**< Valuator data */ @@ -197,6 +198,7 @@ struct _RawDeviceEvent uint32_t key; /**< Key code */ } detail; struct { + short highest_valuator; /**< highest bit set in mask, -1 if none */ uint8_t mask[(MAX_VALUATORS + 7)/8]; /**< Valuator mask */ int32_t data[MAX_VALUATORS]; /**< Valuator data */ int32_t data_frac[MAX_VALUATORS]; /**< Fractional part for data */ diff --git a/test/xi2/protocol-eventconvert.c b/test/xi2/protocol-eventconvert.c index 6e61d74..bf2cc8b 100644 --- a/test/xi2/protocol-eventconvert.c +++ b/test/xi2/protocol-eventconvert.c @@ -41,6 +41,7 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out, int nvals = 0; int bits_set; int len; + int expected_valuators_len = 0; if (swap) { @@ -62,7 +63,10 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out, assert(out->time == in->time); assert(out->detail == in->detail.button); assert(out->deviceid == in->deviceid); - assert(out->valuators_len >= bytes_to_int32(bits_to_bytes(sizeof(in->valuators.mask)))); + if (in->valuators.highest_valuator > -1) { + expected_valuators_len = bytes_to_int32(bits_to_bytes(sizeof(in->valuators.highest_valuator + 1))); + } + assert(out->valuators_len >= expected_valuators_len); assert(out->flags == 0); /* FIXME: we don't set the flags yet */ ptr = (unsigned char*)&out[1]; @@ -185,6 +189,7 @@ static void test_convert_XIRawEvent(void) int i; memset(&in, 0, sizeof(in)); + in.valuators.highest_valuator = -1; printf("Testing all event types\n"); in.header = ET_Internal; @@ -243,13 +248,16 @@ static void test_convert_XIRawEvent(void) for (i = 0; i < MAX_VALUATORS; i++) { XISetMask(in.valuators.mask, i); + in.valuators.highest_valuator = i; test_XIRawEvent(&in); XIClearMask(in.valuators.mask, i); + in.valuators.highest_valuator = 0; } for (i = 0; i < MAX_VALUATORS; i++) { XISetMask(in.valuators.mask, i); + in.valuators.highest_valuator = i; in.valuators.data[i] = i; in.valuators.data_raw[i] = i + 10; @@ -257,11 +265,13 @@ static void test_convert_XIRawEvent(void) in.valuators.data_raw_frac[i] = i + 30; test_XIRawEvent(&in); XIClearMask(in.valuators.mask, i); + in.valuators.highest_valuator = 0; } for (i = 0; i < MAX_VALUATORS; i++) { XISetMask(in.valuators.mask, i); + in.valuators.highest_valuator = i; test_XIRawEvent(&in); } } @@ -274,6 +284,7 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out, unsigned char *ptr; uint32_t flagmask = 0; FP3232 *values; + int expected_valuators_len = 0; if (swap) { char n; @@ -360,7 +371,10 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out, if (XIMaskIsSet(in->valuators.mask, i)) valuators++; - assert(out->valuators_len >= bytes_to_int32(bits_to_bytes(valuators))); + if (valuators) + expected_valuators_len = bytes_to_int32(bits_to_bytes(valuators)); + + assert(out->valuators_len >= expected_valuators_len); ptr += out->buttons_len * 4; values = (FP3232*)(ptr + out->valuators_len * 4); @@ -617,23 +631,28 @@ static void test_convert_XIDeviceEvent(void) for (i = 0; i < MAX_VALUATORS; i++) { XISetMask(in.valuators.mask, i); + in.valuators.highest_valuator = i; test_XIDeviceEvent(&in); XIClearMask(in.valuators.mask, i); + in.valuators.highest_valuator = -1; } for (i = 0; i < MAX_VALUATORS; i++) { XISetMask(in.valuators.mask, i); + in.valuators.highest_valuator = i; in.valuators.data[i] = i; in.valuators.data_frac[i] = i + 20; test_XIDeviceEvent(&in); XIClearMask(in.valuators.mask, i); + in.valuators.highest_valuator = -1; } for (i = 0; i < MAX_VALUATORS; i++) { XISetMask(in.valuators.mask, i); + in.valuators.highest_valuator = i; test_XIDeviceEvent(&in); } } -- 1.7.6