From 5d62c32981dbe9630bed32567b55008b536c81c5 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Mon, 27 Dec 2010 13:24:35 +0000 Subject: [PATCH 01/41] Input: Add flags to DeviceEvent Add a flags member which will be copied wholesale into the resultant xXIDeviceEvent. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer Reviewed-by: Chase Douglas Reviewed-by: Peter Hutterer --- dix/eventconvert.c | 1 + include/eventstr.h | 1 + 2 files changed, 2 insertions(+) diff --git a/dix/eventconvert.c b/dix/eventconvert.c index 024f2e833..6ddcf9e8b 100644 --- a/dix/eventconvert.c +++ b/dix/eventconvert.c @@ -605,6 +605,7 @@ eventToDeviceEvent(DeviceEvent *ev, xEvent **xi) xde->root_x = FP1616(ev->root_x, ev->root_x_frac); xde->root_y = FP1616(ev->root_y, ev->root_y_frac); + xde->flags = ev->flags; if (ev->key_repeat) xde->flags |= XIKeyRepeat; diff --git a/include/eventstr.h b/include/eventstr.h index 049688ca0..0885883a5 100644 --- a/include/eventstr.h +++ b/include/eventstr.h @@ -113,6 +113,7 @@ struct _DeviceEvent Window root; /**< Root window of the event */ int corestate; /**< Core key/button state BEFORE the event */ int key_repeat; /**< Internally-generated key repeat event */ + uint32_t flags; /**< Flags to be copied into the generated event */ }; From 60a766a96f9ec97adf6d0273f70ec23f313a11c6 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Thu, 9 Jun 2011 16:02:47 +0100 Subject: [PATCH 02/41] Input: Add flags to RawDeviceEvent Add a flags member which will be copied wholesale into the resultant xXIRawEvent. Signed-off-by: Daniel Stone --- dix/eventconvert.c | 1 + include/eventstr.h | 1 + test/xi2/protocol-eventconvert.c | 1 + 3 files changed, 3 insertions(+) diff --git a/dix/eventconvert.c b/dix/eventconvert.c index 6ddcf9e8b..fa8ba9ec0 100644 --- a/dix/eventconvert.c +++ b/dix/eventconvert.c @@ -667,6 +667,7 @@ eventToRawEvent(RawDeviceEvent *ev, xEvent **xi) raw->detail = ev->detail.button; raw->deviceid = ev->deviceid; raw->valuators_len = vallen; + raw->flags = ev->flags; ptr = (char*)&raw[1]; axisval = (FP3232*)(ptr + raw->valuators_len * 4); diff --git a/include/eventstr.h b/include/eventstr.h index 0885883a5..ecaeddcb6 100644 --- a/include/eventstr.h +++ b/include/eventstr.h @@ -204,6 +204,7 @@ struct _RawDeviceEvent int32_t data_raw[MAX_VALUATORS]; /**< Valuator data as posted */ int32_t data_raw_frac[MAX_VALUATORS];/**< Fractional part for data_raw */ } valuators; + uint32_t flags; /**< Flags to be copied into the generated event */ }; #ifdef XQUARTZ diff --git a/test/xi2/protocol-eventconvert.c b/test/xi2/protocol-eventconvert.c index 6ec94be6c..80c47b06f 100644 --- a/test/xi2/protocol-eventconvert.c +++ b/test/xi2/protocol-eventconvert.c @@ -51,6 +51,7 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out, swapl(&out->time); swapl(&out->detail); swaps(&out->valuators_len); + swapl(&out->flags); } From 79d4deb76d5612b75ef26b4549b7ade3a656687d Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 23 Feb 2011 14:31:01 +0000 Subject: [PATCH 03/41] Input: Convert ValuatorMask to double-precision internally Switch the ValuatorMask struct to using doubles instead of ints for the actual values. Preserve the old int API, and (attempt to) round towards zero for values we return. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/inpututils.c | 4 ++-- include/inpututils.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dix/inpututils.c b/dix/inpututils.c index 7aeb1e516..1c4af8e5e 100644 --- a/dix/inpututils.c +++ b/dix/inpututils.c @@ -514,7 +514,7 @@ valuator_mask_set(ValuatorMask *mask, int valuator, int data) int valuator_mask_get(const ValuatorMask *mask, int valuator) { - return mask->valuators[valuator]; + return trunc(mask->valuators[valuator]); } /** @@ -527,7 +527,7 @@ valuator_mask_unset(ValuatorMask *mask, int valuator) int i, lastbit = -1; ClearBit(mask->mask, valuator); - mask->valuators[valuator] = 0; + mask->valuators[valuator] = 0.0; for (i = 0; i <= mask->last_bit; i++) if (valuator_mask_isset(mask, i)) diff --git a/include/inpututils.h b/include/inpututils.h index 63e1a263a..47e242d87 100644 --- a/include/inpututils.h +++ b/include/inpututils.h @@ -34,7 +34,7 @@ struct _ValuatorMask { int8_t last_bit; /* highest bit set in mask */ uint8_t mask[(MAX_VALUATORS + 7)/8]; - int valuators[MAX_VALUATORS]; /* valuator data */ + double valuators[MAX_VALUATORS]; /* valuator data */ }; extern void verify_internal_event(const InternalEvent *ev); From 7e919ef5bfa94d51a06eefb150ab947bdbfb6885 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 23 Feb 2011 17:28:18 +0000 Subject: [PATCH 04/41] Input: Add double-precision valuator_mask API Add API for valuator_mask that accepts and returns doubles, rather than ints. No double API is provided for set_range at the moment. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/inpututils.c | 30 +++++++++++++++++++++++++----- include/input.h | 5 +++++ test/input.c | 21 +++++++++++++++------ 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/dix/inpututils.c b/dix/inpututils.c index 1c4af8e5e..0a3d3d8b4 100644 --- a/dix/inpututils.c +++ b/dix/inpututils.c @@ -497,10 +497,10 @@ valuator_mask_isset(const ValuatorMask *mask, int valuator) } /** - * Set the valuator to the given data. + * Set the valuator to the given floating-point data. */ void -valuator_mask_set(ValuatorMask *mask, int valuator, int data) +valuator_mask_set_double(ValuatorMask *mask, int valuator, double data) { mask->last_bit = max(valuator, mask->last_bit); SetBit(mask->mask, valuator); @@ -508,13 +508,33 @@ valuator_mask_set(ValuatorMask *mask, int valuator, int data) } /** - * Return the requested valuator value. If the mask bit is not set for the - * given valuator, the returned value is undefined. + * Set the valuator to the given integer data. + */ +void +valuator_mask_set(ValuatorMask *mask, int valuator, int data) +{ + valuator_mask_set_double(mask, valuator, data); +} + +/** + * Return the requested valuator value as a double. If the mask bit is not + * set for the given valuator, the returned value is undefined. + */ +double +valuator_mask_get_double(const ValuatorMask *mask, int valuator) +{ + return mask->valuators[valuator]; +} + +/** + * Return the requested valuator value as an integer, rounding towards zero. + * If the mask bit is not set for the given valuator, the returned value is + * undefined. */ int valuator_mask_get(const ValuatorMask *mask, int valuator) { - return trunc(mask->valuators[valuator]); + return trunc(valuator_mask_get_double(mask, valuator)); } /** diff --git a/include/input.h b/include/input.h index 0258f4f18..577f5d992 100644 --- a/include/input.h +++ b/include/input.h @@ -583,6 +583,9 @@ extern _X_EXPORT void valuator_mask_set_range(ValuatorMask *mask, extern _X_EXPORT void valuator_mask_set(ValuatorMask *mask, int valuator, int data); +extern _X_EXPORT void valuator_mask_set_double(ValuatorMask *mask, + int valuator, + double data); extern _X_EXPORT void valuator_mask_zero(ValuatorMask *mask); extern _X_EXPORT int valuator_mask_size(const ValuatorMask *mask); extern _X_EXPORT int valuator_mask_isset(const ValuatorMask *mask, int bit); @@ -591,6 +594,8 @@ extern _X_EXPORT int valuator_mask_num_valuators(const ValuatorMask *mask); extern _X_EXPORT void valuator_mask_copy(ValuatorMask *dest, const ValuatorMask *src); extern _X_EXPORT int valuator_mask_get(const ValuatorMask *mask, int valnum); +extern _X_EXPORT double valuator_mask_get_double(const ValuatorMask *mask, + int valnum); /* InputOption handling interface */ extern _X_EXPORT InputOption* input_option_new(InputOption *list, const char *key, const char *value); diff --git a/test/input.c b/test/input.c index b8dad1c60..2501d59b7 100644 --- a/test/input.c +++ b/test/input.c @@ -1089,12 +1089,16 @@ static void dix_input_valuator_masks(void) { ValuatorMask *mask = NULL, *copy; int nvaluators = MAX_VALUATORS; - int valuators[nvaluators]; + double valuators[nvaluators]; + int val_ranged[nvaluators]; int i; int first_val, num_vals; for (i = 0; i < nvaluators; i++) - valuators[i] = i; + { + valuators[i] = i + 0.5; + val_ranged[i] = i; + } mask = valuator_mask_new(nvaluators); assert(mask != NULL); @@ -1104,9 +1108,10 @@ static void dix_input_valuator_masks(void) for (i = 0; i < nvaluators; i++) { assert(!valuator_mask_isset(mask, i)); - valuator_mask_set(mask, i, valuators[i]); + valuator_mask_set_double(mask, i, valuators[i]); assert(valuator_mask_isset(mask, i)); - assert(valuator_mask_get(mask, i) == valuators[i]); + assert(valuator_mask_get(mask, i) == trunc(valuators[i])); + assert(valuator_mask_get_double(mask, i) == valuators[i]); assert(valuator_mask_size(mask) == i + 1); assert(valuator_mask_num_valuators(mask) == i + 1); } @@ -1132,7 +1137,7 @@ static void dix_input_valuator_masks(void) first_val = 5; num_vals = 6; - valuator_mask_set_range(mask, first_val, num_vals, valuators); + valuator_mask_set_range(mask, first_val, num_vals, val_ranged); assert(valuator_mask_size(mask) == first_val + num_vals); assert(valuator_mask_num_valuators(mask) == num_vals); for (i = 0; i < nvaluators; i++) @@ -1142,7 +1147,9 @@ static void dix_input_valuator_masks(void) else { assert(valuator_mask_isset(mask, i)); - assert(valuator_mask_get(mask, i) == valuators[i - first_val]); + assert(valuator_mask_get(mask, i) == val_ranged[i - first_val]); + assert(valuator_mask_get_double(mask, i) == + val_ranged[i - first_val]); } } @@ -1156,6 +1163,8 @@ static void dix_input_valuator_masks(void) { assert(valuator_mask_isset(mask, i) == valuator_mask_isset(copy, i)); assert(valuator_mask_get(mask, i) == valuator_mask_get(copy, i)); + assert(valuator_mask_get_double(mask, i) == + valuator_mask_get_double(copy, i)); } valuator_mask_free(&mask); From 6a6b4eb05c7822860e2362fa9b8441fc67055e27 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 2 Mar 2011 17:22:59 +0000 Subject: [PATCH 05/41] Input: Store clipped absolute axes in the mask Change moveAbsolute to be more symmetric with moveRelative by storing a clipped axis value back in the mask, rather than just in dev->last.valuators. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/getevents.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dix/getevents.c b/dix/getevents.c index be2840c47..d9c5c0df5 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -721,6 +721,7 @@ moveAbsolute(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask) { dev->last.valuators[i] = valuator_mask_get(mask, i); clipAxis(dev, i, &dev->last.valuators[i]); + valuator_mask_set(mask, i, dev->last.valuators[i]); } } } From 80fdf9ca33a8f50f98a4b1a3279e66b040353b80 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 2 Mar 2011 13:19:00 +0000 Subject: [PATCH 06/41] Input: Prepare moveAbsolute for conversion to double Shuffle some code around to make moving to double easier later. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/getevents.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index d9c5c0df5..bcac6aa9f 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -690,40 +690,30 @@ UpdateFromMaster(InternalEvent* events, DeviceIntPtr dev, int type, int *num_eve /** * Move the device's pointer to the position given in the valuators. * - * @param dev The device which's pointer is to be moved. + * @param dev The device whose pointer is to be moved. * @param x Returns the x position of the pointer after the move. * @param y Returns the y position of the pointer after the move. - * @param mask Bit mask of valid valuators. - * @param valuators Valuator data for each axis between @first and - * @first+@num. + * @param mask Valuator data for this event. */ static void -moveAbsolute(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask) +moveAbsolute(DeviceIntPtr dev, int *x_out, int *y_out, ValuatorMask *mask) { int i; + int x, y; - if (valuator_mask_isset(mask, 0)) - *x = valuator_mask_get(mask, 0); - else - *x = dev->last.valuators[0]; - - if (valuator_mask_isset(mask, 1)) - *y = valuator_mask_get(mask, 1); - else - *y = dev->last.valuators[1]; - - clipAxis(dev, 0, x); - clipAxis(dev, 1, y); - - for (i = 2; i < valuator_mask_size(mask); i++) + for (i = 0; i < valuator_mask_size(mask); i++) { if (valuator_mask_isset(mask, i)) { - dev->last.valuators[i] = valuator_mask_get(mask, i); - clipAxis(dev, i, &dev->last.valuators[i]); - valuator_mask_set(mask, i, dev->last.valuators[i]); + int val = valuator_mask_get(mask, i); + clipAxis(dev, i, &val); + dev->last.valuators[i] = val; + valuator_mask_set(mask, i, val); } } + + *x_out = dev->last.valuators[0]; + *y_out = dev->last.valuators[1]; } /** From 4e52cc0ef48145134cd58d357fb7289e6f8bb709 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 2 Mar 2011 13:20:37 +0000 Subject: [PATCH 07/41] Input: Prepare moveRelative for conversion to double Shuffle some code around in moveRelative to make the conversion to double easier later. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/getevents.c | 46 +++++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index bcac6aa9f..fd8b0988a 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -719,48 +719,36 @@ moveAbsolute(DeviceIntPtr dev, int *x_out, int *y_out, ValuatorMask *mask) /** * Move the device's pointer by the values given in @valuators. * - * @param dev The device which's pointer is to be moved. + * @param dev The device whose pointer is to be moved. * @param x Returns the x position of the pointer after the move. * @param y Returns the y position of the pointer after the move. - * @param mask Bit mask of valid valuators. - * @param valuators Valuator data for each axis between @first and - * @first+@num. + * @param mask Valuator data for this event. */ static void -moveRelative(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask) +moveRelative(DeviceIntPtr dev, int *x_out, int *y_out, ValuatorMask *mask) { int i; - - *x = dev->last.valuators[0]; - *y = dev->last.valuators[1]; - - if (valuator_mask_isset(mask, 0)) - *x += valuator_mask_get(mask, 0); - - if (valuator_mask_isset(mask, 1)) - *y += valuator_mask_get(mask, 1); - - /* if attached, clip both x and y to the defined limits (usually - * co-ord space limit). If it is attached, we need x/y to go over the - * limits to be able to change screens. */ - if (dev->valuator && (IsMaster(dev) || !IsFloating(dev))) { - if (valuator_get_mode(dev, 0) == Absolute) - clipAxis(dev, 0, x); - if (valuator_get_mode(dev, 1) == Absolute) - clipAxis(dev, 1, y); - } + Bool clip_xy = IsMaster(dev) || !IsFloating(dev); /* calc other axes, clip, drop back into valuators */ - for (i = 2; i < valuator_mask_size(mask); i++) + for (i = 0; i < valuator_mask_size(mask); i++) { if (valuator_mask_isset(mask, i)) { - dev->last.valuators[i] += valuator_mask_get(mask, i); - if (valuator_get_mode(dev, i) == Absolute) - clipAxis(dev, i, &dev->last.valuators[i]); - valuator_mask_set(mask, i, dev->last.valuators[i]); + int val = dev->last.valuators[i]; + val += valuator_mask_get(mask, i); + /* x & y need to go over the limits to cross screens if the SD + * isn't currently attached; otherwise, clip to screen bounds. */ + if (valuator_get_mode(dev, i) == Absolute && + ((i != 0 && i != 1) || clip_xy)) + clipAxis(dev, i, &val); + dev->last.valuators[i] = val; + valuator_mask_set(mask, i, val); } } + + *x_out = dev->last.valuators[0]; + *y_out = dev->last.valuators[1]; } /** From 3463078f9697fad0ee11837d80e88889fc6a28a4 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 2 Mar 2011 13:29:24 +0000 Subject: [PATCH 08/41] Input: Convert clipAxis, moveAbsolute and moveRelative to double Change all these three to use doubles internally, though the outputs of moveAbsolute and moveRelative are still truncated to int. Signed-off-by: Daniel Stone --- dix/getevents.c | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index fd8b0988a..30044bae8 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -617,7 +617,7 @@ GetMaximumEventsNum(void) { * InitValuatorAxisClassStruct. */ static void -clipAxis(DeviceIntPtr pDev, int axisNum, int *val) +clipAxis(DeviceIntPtr pDev, int axisNum, double *val) { AxisInfoPtr axis; @@ -647,9 +647,9 @@ clipValuators(DeviceIntPtr pDev, ValuatorMask *mask) for (i = 0; i < valuator_mask_size(mask); i++) if (valuator_mask_isset(mask, i)) { - int val = valuator_mask_get(mask, i); + double val = valuator_mask_get_double(mask, i); clipAxis(pDev, i, &val); - valuator_mask_set(mask, i, val); + valuator_mask_set_double(mask, i, val); } } @@ -699,17 +699,18 @@ static void moveAbsolute(DeviceIntPtr dev, int *x_out, int *y_out, ValuatorMask *mask) { int i; - int x, y; for (i = 0; i < valuator_mask_size(mask); i++) { - if (valuator_mask_isset(mask, i)) - { - int val = valuator_mask_get(mask, i); - clipAxis(dev, i, &val); - dev->last.valuators[i] = val; - valuator_mask_set(mask, i, val); - } + double val; + + if (!valuator_mask_isset(mask, i)) + continue; + val = valuator_mask_get_double(mask, i); + clipAxis(dev, i, &val); + dev->last.valuators[i] = trunc(val); + dev->last.remainder[i] = val - trunc(val); + valuator_mask_set_double(mask, i, val); } *x_out = dev->last.valuators[0]; @@ -733,18 +734,19 @@ moveRelative(DeviceIntPtr dev, int *x_out, int *y_out, ValuatorMask *mask) /* calc other axes, clip, drop back into valuators */ for (i = 0; i < valuator_mask_size(mask); i++) { - if (valuator_mask_isset(mask, i)) - { - int val = dev->last.valuators[i]; - val += valuator_mask_get(mask, i); - /* x & y need to go over the limits to cross screens if the SD - * isn't currently attached; otherwise, clip to screen bounds. */ - if (valuator_get_mode(dev, i) == Absolute && - ((i != 0 && i != 1) || clip_xy)) - clipAxis(dev, i, &val); - dev->last.valuators[i] = val; - valuator_mask_set(mask, i, val); - } + double val = dev->last.valuators[i] + dev->last.remainder[i]; + + if (!valuator_mask_isset(mask, i)) + continue; + val += valuator_mask_get_double(mask, i); + /* x & y need to go over the limits to cross screens if the SD + * isn't currently attached; otherwise, clip to screen bounds. */ + if (valuator_get_mode(dev, i) == Absolute && + ((i != 0 && i != 1) || clip_xy)) + clipAxis(dev, i, &val); + dev->last.valuators[i] = trunc(val); + dev->last.remainder[i] = val - trunc(val); + valuator_mask_set_double(mask, i, val); } *x_out = dev->last.valuators[0]; From cdf202250ef616f3b261db70da30e421ea59a630 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 2 Mar 2011 14:50:29 +0000 Subject: [PATCH 09/41] Input: Convert transformAbsolute to work on doubles Change transformAbsolute to use doubles internally. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/getevents.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index 30044bae8..76e8a32ed 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -1026,32 +1026,37 @@ FreeEventList(InternalEvent *list, int num_events) * back into x/y. */ static void -transform(struct pixman_f_transform *m, int *x, int *y) +transform(struct pixman_f_transform *m, double *x, double *y) { struct pixman_f_vector p = {.v = {*x, *y, 1}}; pixman_f_transform_point(m, &p); - *x = lround(p.v[0]); - *y = lround(p.v[1]); + *x = p.v[0]; + *y = p.v[1]; } static void transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask) { - int x, y, ox, oy; + double x, y, ox, oy; - ox = x = valuator_mask_isset(mask, 0) ? valuator_mask_get(mask, 0) : - dev->last.valuators[0]; - oy = y = valuator_mask_isset(mask, 1) ? valuator_mask_get(mask, 1) : - dev->last.valuators[1]; + if (valuator_mask_isset(mask, 0)) + ox = x = valuator_mask_get_double(mask, 0); + else + ox = x = dev->last.valuators[0] + dev->last.remainder[0]; + + if (valuator_mask_isset(mask, 1)) + oy = y = valuator_mask_get_double(mask, 1); + else + oy = y = dev->last.valuators[1] + dev->last.remainder[1]; transform(&dev->transform, &x, &y); if (valuator_mask_isset(mask, 0) || ox != x) - valuator_mask_set(mask, 0, x); + valuator_mask_set_double(mask, 0, x); if (valuator_mask_isset(mask, 1) || oy != y) - valuator_mask_set(mask, 1, y); + valuator_mask_set_double(mask, 1, y); } /** From e1df51421bc392d57f88c831fe0661871a8aa769 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 2 Mar 2011 13:34:32 +0000 Subject: [PATCH 10/41] Input: Set fractional member in set_raw_valuators RawDeviceEvents have space for fractional valuator members, so might as well start using them. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/getevents.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index 76e8a32ed..b8f4a8cf4 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -167,16 +167,20 @@ init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail) } static void -set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, int32_t* data) +set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, int32_t* data, + int32_t* data_frac) { int i; + double val; for (i = 0; i < valuator_mask_size(mask); i++) { if (valuator_mask_isset(mask, i)) { SetBit(event->valuators.mask, i); - data[i] = valuator_mask_get(mask, i); + val = valuator_mask_get_double(mask, i); + data[i] = trunc(val); + data_frac[i] = (val - data[i]) * (1UL << 32); } } } @@ -969,11 +973,13 @@ GetKeyboardEvents(InternalEvent *events, DeviceIntPtr pDev, int type, valuator_mask_copy(&mask, mask_in); init_raw(pDev, raw, ms, type, key_code); - set_raw_valuators(raw, &mask, raw->valuators.data_raw); + set_raw_valuators(raw, &mask, raw->valuators.data_raw, + raw->valuators.data_raw_frac); clipValuators(pDev, &mask); - set_raw_valuators(raw, &mask, raw->valuators.data); + set_raw_valuators(raw, &mask, raw->valuators.data, + raw->valuators.data_frac); event = &events->device_event; init_device_event(event, pDev, ms); @@ -1147,7 +1153,8 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons num_events++; init_raw(pDev, raw, ms, type, buttons); - set_raw_valuators(raw, &mask, raw->valuators.data_raw); + set_raw_valuators(raw, &mask, raw->valuators.data_raw, + raw->valuators.data_raw_frac); } if (flags & POINTER_ABSOLUTE) @@ -1188,7 +1195,8 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons } if ((flags & POINTER_NORAW) == 0) - set_raw_valuators(raw, &mask, raw->valuators.data); + set_raw_valuators(raw, &mask, raw->valuators.data, + raw->valuators.data_frac); positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac); From 8a4a4e1b8a33899653d68a21bb7ff0557a576338 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Thu, 9 Jun 2011 15:26:55 +0100 Subject: [PATCH 11/41] Input: Use trunc instead of lrintf in acceleration code For compatibility with all the rest of the input code. Signed-off-by: Daniel Stone Reviewed-by: Simon Thum --- dix/ptrveloc.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c index dfccf1581..c50679134 100644 --- a/dix/ptrveloc.c +++ b/dix/ptrveloc.c @@ -1167,19 +1167,14 @@ acceleratePointerPredictable( if (dx) { float tmp; tmp = mult * fdx + dev->last.remainder[0]; - /* Since it may not be apparent: lrintf() does not offer - * strong statements about rounding; however because we - * process each axis conditionally, there's no danger - * of a toggling remainder. Its lack of guarantees likely - * makes it faster on the average target. */ - tmpi = lrintf(tmp); + tmpi = trunc(tmp); valuator_mask_set(val, 0, tmpi); dev->last.remainder[0] = tmp - (float)tmpi; } if (dy) { float tmp; tmp = mult * fdy + dev->last.remainder[1]; - tmpi = lrintf(tmp); + tmpi = trunc(tmp); valuator_mask_set(val, 1, tmpi); dev->last.remainder[1] = tmp - (float)tmpi; } From 2b8f1d07bd42c9d3db3dbacfe6a1335e47236a6c Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 2 Mar 2011 15:37:53 +0000 Subject: [PATCH 12/41] Input: Widen pointer acceleration types to double This widens almost all of the float-using code in ptrveloc.[ch] to doubles, other than values coming from properties which are specified to be floats by the property API. Bumps input API to v14 as this changes the AccelScheme signature, as used by xf86-input-synaptics. Signed-off-by: Daniel Stone --- dix/ptrveloc.c | 230 ++++++++++++++++----------------- hw/xfree86/common/xf86Module.h | 2 +- include/ptrveloc.h | 32 ++--- 3 files changed, 129 insertions(+), 135 deletions(-) diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c index c50679134..6271a6d34 100644 --- a/dix/ptrveloc.c +++ b/dix/ptrveloc.c @@ -63,9 +63,9 @@ /* fwds */ int SetAccelerationProfile(DeviceVelocityPtr vel, int profile_num); -static float -SimpleSmoothProfile(DeviceIntPtr dev, DeviceVelocityPtr vel, float velocity, - float threshold, float acc); +static double +SimpleSmoothProfile(DeviceIntPtr dev, DeviceVelocityPtr vel, double velocity, + double threshold, double acc); static PointerAccelerationProfileFunc GetAccelerationProfile(DeviceVelocityPtr vel, int profile_num); static BOOL @@ -478,14 +478,10 @@ DoGetDirection(int dx, int dy){ else dir = UNDEFINED; /* shouldn't happen */ } else { /* compute angle and set appropriate flags */ - float r; + double r; int i1, i2; -#ifdef _ISOC99_SOURCE - r = atan2f(dy, dx); -#else r = atan2(dy, dx); -#endif /* find direction. * * Add 360° to avoid r become negative since C has no well-defined @@ -524,8 +520,7 @@ static int GetDirection(int dx, int dy){ static int cache[DIRECTION_CACHE_SIZE][DIRECTION_CACHE_SIZE]; int dir; - if (abs(dx) <= DIRECTION_CACHE_RANGE && - abs(dy) <= DIRECTION_CACHE_RANGE) { + if (abs(dx) <= DIRECTION_CACHE_RANGE && abs(dy) <= DIRECTION_CACHE_RANGE) { /* cacheable */ dir = cache[DIRECTION_CACHE_RANGE+dx][DIRECTION_CACHE_RANGE+dy]; if(dir == 0) { @@ -553,7 +548,7 @@ GetDirection(int dx, int dy){ * 0/0 and set it as the current one. */ static inline void -FeedTrackers(DeviceVelocityPtr vel, int dx, int dy, int cur_t) +FeedTrackers(DeviceVelocityPtr vel, double dx, double dy, int cur_t) { int n; for(n = 0; n < vel->num_tracker; n++){ @@ -561,8 +556,8 @@ FeedTrackers(DeviceVelocityPtr vel, int dx, int dy, int cur_t) vel->tracker[n].dy += dy; } n = (vel->cur_tracker + 1) % vel->num_tracker; - vel->tracker[n].dx = 0; - vel->tracker[n].dy = 0; + vel->tracker[n].dx = 0.0; + vel->tracker[n].dy = 0.0; vel->tracker[n].time = cur_t; vel->tracker[n].dir = GetDirection(dx, dy); DebugAccelF("(dix prtacc) motion [dx: %i dy: %i dir:%i diff: %i]\n", @@ -576,9 +571,9 @@ FeedTrackers(DeviceVelocityPtr vel, int dx, int dy, int cur_t) * velocity scaling. * This assumes linear motion. */ -static float +static double CalcTracker(const MotionTracker *tracker, int cur_t){ - float dist = sqrt(tracker->dx * tracker->dx + tracker->dy * tracker->dy); + double dist = sqrt(tracker->dx * tracker->dx + tracker->dy * tracker->dy); int dtime = cur_t - tracker->time; if(dtime > 0) return dist / dtime; @@ -593,16 +588,16 @@ CalcTracker(const MotionTracker *tracker, int cur_t){ * * @return The tracker's velocity or 0 if the above conditions are unmet */ -static float +static double QueryTrackers(DeviceVelocityPtr vel, int cur_t){ int offset, dir = UNDEFINED, used_offset = -1, age_ms; /* initial velocity: a low-offset, valid velocity */ - float initial_velocity = 0, result = 0, velocity_diff; - float velocity_factor = vel->corr_mul * vel->const_acceleration; /* premultiply */ + double initial_velocity = 0, result = 0, velocity_diff; + double velocity_factor = vel->corr_mul * vel->const_acceleration; /* premultiply */ /* loop from current to older data */ for(offset = 1; offset < vel->num_tracker; offset++){ MotionTracker *tracker = TRACKER(vel, offset); - float tracker_velocity; + double tracker_velocity; age_ms = cur_t - tracker->time; @@ -674,11 +669,11 @@ QueryTrackers(DeviceVelocityPtr vel, int cur_t){ BOOL ProcessVelocityData2D( DeviceVelocityPtr vel, - int dx, - int dy, + double dx, + double dy, int time) { - float velocity; + double velocity; vel->last_velocity = vel->velocity; @@ -694,12 +689,12 @@ ProcessVelocityData2D( * this flattens significant ( > 1) mickeys a little bit for more steady * constant-velocity response */ -static inline float -ApplySimpleSoftening(int prev_delta, int delta) +static inline double +ApplySimpleSoftening(double prev_delta, double delta) { - float result = delta; + double result = delta; - if (delta < -1 || delta > 1) { + if (delta < -1.0 || delta > 1.0) { if (delta > prev_delta) result -= 0.5; else if (delta < prev_delta) @@ -718,8 +713,8 @@ ApplySimpleSoftening(int prev_delta, int delta) static void ApplySoftening( DeviceVelocityPtr vel, - float* fdx, - float* fdy) + double* fdx, + double* fdy) { if (vel->use_softening) { *fdx = ApplySimpleSoftening(vel->last_dx, *fdx); @@ -728,7 +723,7 @@ ApplySoftening( } static void -ApplyConstantDeceleration(DeviceVelocityPtr vel, float *fdx, float *fdy) +ApplyConstantDeceleration(DeviceVelocityPtr vel, double *fdx, double *fdy) { *fdx *= vel->const_acceleration; *fdy *= vel->const_acceleration; @@ -737,15 +732,15 @@ ApplyConstantDeceleration(DeviceVelocityPtr vel, float *fdx, float *fdy) /* * compute the acceleration for given velocity and enforce min_acceleartion */ -float +double BasicComputeAcceleration( DeviceIntPtr dev, DeviceVelocityPtr vel, - float velocity, - float threshold, - float acc){ + double velocity, + double threshold, + double acc){ - float result; + double result; result = vel->Profile(dev, vel, velocity, threshold, acc); /* enforce min_acceleration */ @@ -759,13 +754,13 @@ BasicComputeAcceleration( * If the velocity has changed, an average is taken of 6 velocity factors: * current velocity, last velocity and 4 times the average between the two. */ -static float +static double ComputeAcceleration( DeviceIntPtr dev, DeviceVelocityPtr vel, - float threshold, - float acc){ - float result; + double threshold, + double acc){ + double result; if(vel->velocity <= 0){ DebugAccelF("(dix ptracc) profile skipped\n"); @@ -808,13 +803,13 @@ ComputeAcceleration( /** * Polynomial function similar previous one, but with f(1) = 1 */ -static float +static double PolynomialAccelerationProfile( DeviceIntPtr dev, DeviceVelocityPtr vel, - float velocity, - float ignored, - float acc) + double velocity, + double ignored, + double acc) { return pow(velocity, (acc - 1.0) * 0.5); } @@ -824,13 +819,13 @@ PolynomialAccelerationProfile( * returns acceleration for velocity. * This profile selects the two functions like the old scheme did */ -static float +static double ClassicProfile( DeviceIntPtr dev, DeviceVelocityPtr vel, - float velocity, - float threshold, - float acc) + double velocity, + double threshold, + double acc) { if (threshold > 0) { return SimpleSmoothProfile (dev, @@ -856,15 +851,15 @@ ClassicProfile( * This has the expense of overall response dependency on min-acceleration. * In effect, min_acceleration mimics const_acceleration in this profile. */ -static float +static double PowerProfile( DeviceIntPtr dev, DeviceVelocityPtr vel, - float velocity, - float threshold, - float acc) + double velocity, + double threshold, + double acc) { - float vel_dist; + double vel_dist; acc = (acc-1.0) * 0.1f + 1.0; /* without this, acc of 2 is unuseable */ @@ -882,11 +877,11 @@ PowerProfile( * - starts faster than a sinoid * - smoothness C1 (Cinf if you dare to ignore endpoints) */ -static inline float -CalcPenumbralGradient(float x){ +static inline double +CalcPenumbralGradient(double x){ x *= 2.0f; x -= 1.0f; - return 0.5f + (x * sqrt(1.0f - x*x) + asin(x))/M_PI; + return 0.5f + (x * sqrt(1.0 - x*x) + asin(x))/M_PI; } @@ -894,13 +889,13 @@ CalcPenumbralGradient(float x){ * acceleration function similar to classic accelerated/unaccelerated, * but with smooth transition in between (and towards zero for adaptive dec.). */ -static float +static double SimpleSmoothProfile( DeviceIntPtr dev, DeviceVelocityPtr vel, - float velocity, - float threshold, - float acc) + double velocity, + double threshold, + double acc) { if(velocity < 1.0f) return CalcPenumbralGradient(0.5 + velocity*0.5) * 2.0f - 1.0f; @@ -920,15 +915,15 @@ SimpleSmoothProfile( * This profile uses the first half of the penumbral gradient as a start * and then scales linearly. */ -static float +static double SmoothLinearProfile( DeviceIntPtr dev, DeviceVelocityPtr vel, - float velocity, - float threshold, - float acc) + double velocity, + double threshold, + double acc) { - float res, nv; + double res, nv; if(acc > 1.0f) acc -= 1.0f; /*this is so acc = 1 is no acceleration */ @@ -955,15 +950,15 @@ SmoothLinearProfile( * From 0 to threshold, the response graduates smoothly from min_accel to * acceleration. Beyond threshold it is exactly the specified acceleration. */ -static float +static double SmoothLimitedProfile( DeviceIntPtr dev, DeviceVelocityPtr vel, - float velocity, - float threshold, - float acc) + double velocity, + double threshold, + double acc) { - float res; + double res; if(velocity >= threshold || threshold == 0.0f) return acc; @@ -976,24 +971,24 @@ SmoothLimitedProfile( } -static float +static double LinearProfile( DeviceIntPtr dev, DeviceVelocityPtr vel, - float velocity, - float threshold, - float acc) + double velocity, + double threshold, + double acc) { return acc * velocity; } -static float +static double NoProfile( DeviceIntPtr dev, DeviceVelocityPtr vel, - float velocity, - float threshold, - float acc) + double velocity, + double threshold, + double acc) { return 1.0f; } @@ -1119,7 +1114,8 @@ acceleratePointerPredictable( ValuatorMask* val, CARD32 evtime) { - int dx = 0, dy = 0, tmpi; + double dx = 0, dy = 0; + int tmpi; DeviceVelocityPtr velocitydata = GetDevicePredictableAccelData(dev); Bool soften = TRUE; @@ -1139,47 +1135,44 @@ acceleratePointerPredictable( dy = valuator_mask_get(val, 1); } - if (dx || dy){ + if (dx != 0.0 || dy != 0.0) { /* reset non-visible state? */ if (ProcessVelocityData2D(velocitydata, dx , dy, evtime)) { soften = FALSE; } if (dev->ptrfeed && dev->ptrfeed->ctrl.num) { - float mult; + double mult; /* invoke acceleration profile to determine acceleration */ mult = ComputeAcceleration (dev, velocitydata, - dev->ptrfeed->ctrl.threshold, - (float)dev->ptrfeed->ctrl.num / - (float)dev->ptrfeed->ctrl.den); + dev->ptrfeed->ctrl.threshold, + (double)dev->ptrfeed->ctrl.num / + (double)dev->ptrfeed->ctrl.den); if(mult != 1.0f || velocitydata->const_acceleration != 1.0f) { - float fdx = dx, - fdy = dy; - if (mult > 1.0f && soften) - ApplySoftening(velocitydata, &fdx, &fdy); - ApplyConstantDeceleration(velocitydata, &fdx, &fdy); + ApplySoftening(velocitydata, &dx, &dy); + ApplyConstantDeceleration(velocitydata, &dx, &dy); /* Calculate the new delta (with accel) and drop it back * into the valuator masks */ - if (dx) { - float tmp; - tmp = mult * fdx + dev->last.remainder[0]; + if (dx != 0.0) { + double tmp; + tmp = mult * dx + dev->last.remainder[0]; tmpi = trunc(tmp); valuator_mask_set(val, 0, tmpi); - dev->last.remainder[0] = tmp - (float)tmpi; + dev->last.remainder[0] = tmp - (double)tmpi; } - if (dy) { - float tmp; - tmp = mult * fdy + dev->last.remainder[1]; + if (dy != 0.0) { + double tmp; + tmp = mult * dy + dev->last.remainder[1]; tmpi = trunc(tmp); valuator_mask_set(val, 1, tmpi); - dev->last.remainder[1] = tmp - (float)tmpi; + dev->last.remainder[1] = tmp - (double)tmpi; } DebugAccelF("pos (%i | %i) remainders x: %.3f y: %.3f delta x:%.3f y:%.3f\n", - *px, *py, dev->last.remainder[0], dev->last.remainder[1], fdx, fdy); + *px, *py, dev->last.remainder[0], dev->last.remainder[1], dx, dy); } } } @@ -1200,8 +1193,9 @@ acceleratePointerLightweight( ValuatorMask* val, CARD32 ignored) { - float mult = 0.0, tmpf; - int dx = 0, dy = 0, tmpi; + double mult = 0.0, tmpf; + double dx = 0.0, dy = 0.0; + int tmpi; if (valuator_mask_isset(val, 0)) { dx = valuator_mask_get(val, 0); @@ -1211,52 +1205,52 @@ acceleratePointerLightweight( dy = valuator_mask_get(val, 1); } - if (!dx && !dy) + if (dx == 0.0 && dy == 0.0) return; if (dev->ptrfeed && dev->ptrfeed->ctrl.num) { /* modeled from xf86Events.c */ if (dev->ptrfeed->ctrl.threshold) { if ((abs(dx) + abs(dy)) >= dev->ptrfeed->ctrl.threshold) { - tmpf = ((float)dx * - (float)(dev->ptrfeed->ctrl.num)) / - (float)(dev->ptrfeed->ctrl.den) + + tmpf = ((double)dx * + (double)(dev->ptrfeed->ctrl.num)) / + (double)(dev->ptrfeed->ctrl.den) + dev->last.remainder[0]; - if (dx) { + if (dx != 0.0) { tmpi = (int) tmpf; valuator_mask_set(val, 0, tmpi); - dev->last.remainder[0] = tmpf - (float)tmpi; + dev->last.remainder[0] = tmpf - (double)tmpi; } - tmpf = ((float)dy * - (float)(dev->ptrfeed->ctrl.num)) / - (float)(dev->ptrfeed->ctrl.den) + + tmpf = ((double)dy * + (double)(dev->ptrfeed->ctrl.num)) / + (double)(dev->ptrfeed->ctrl.den) + dev->last.remainder[1]; - if (dy) { + if (dy != 0.0) { tmpi = (int) tmpf; valuator_mask_set(val, 1, tmpi); - dev->last.remainder[1] = tmpf - (float)tmpi; + dev->last.remainder[1] = tmpf - (double)tmpi; } } } else { - mult = pow((float)dx * (float)dx + (float)dy * (float)dy, - ((float)(dev->ptrfeed->ctrl.num) / - (float)(dev->ptrfeed->ctrl.den) - 1.0) / + mult = pow((double)dx * (double)dx + (double)dy * (double)dy, + ((double)(dev->ptrfeed->ctrl.num) / + (double)(dev->ptrfeed->ctrl.den) - 1.0) / 2.0) / 2.0; - if (dx) { - tmpf = mult * (float)dx + + if (dx != 0.0) { + tmpf = mult * (double)dx + dev->last.remainder[0]; tmpi = (int) tmpf; valuator_mask_set(val, 0, tmpi); - dev->last.remainder[0] = tmpf - (float)tmpi; + dev->last.remainder[0] = tmpf - (double)tmpi; } - if (dy) { - tmpf = mult * (float)dy + + if (dy != 0.0) { + tmpf = mult * (double)dy + dev->last.remainder[1]; tmpi = (int)tmpf; valuator_mask_set(val, 1, tmpi); - dev->last.remainder[1] = tmpf - (float)tmpi; + dev->last.remainder[1] = tmpf - (double)tmpi; } } } diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h index 3038c0404..330d87ae8 100644 --- a/hw/xfree86/common/xf86Module.h +++ b/hw/xfree86/common/xf86Module.h @@ -83,7 +83,7 @@ typedef enum { */ #define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4) #define ABI_VIDEODRV_VERSION SET_ABI_VERSION(11, 0) -#define ABI_XINPUT_VERSION SET_ABI_VERSION(13, 0) +#define ABI_XINPUT_VERSION SET_ABI_VERSION(14, 0) #define ABI_EXTENSION_VERSION SET_ABI_VERSION(6, 0) #define ABI_FONT_VERSION SET_ABI_VERSION(0, 6) diff --git a/include/ptrveloc.h b/include/ptrveloc.h index 6ca309c8c..4f76b0094 100644 --- a/include/ptrveloc.h +++ b/include/ptrveloc.h @@ -47,9 +47,9 @@ struct _DeviceVelocityRec; * profile * returns actual acceleration depending on velocity, acceleration control,... */ -typedef float (*PointerAccelerationProfileFunc) +typedef double (*PointerAccelerationProfileFunc) (DeviceIntPtr dev, struct _DeviceVelocityRec* vel, - float velocity, float threshold, float accelCoeff); + double velocity, double threshold, double accelCoeff); /** * a motion history, with just enough information to @@ -57,8 +57,8 @@ typedef float (*PointerAccelerationProfileFunc) * a more or less straight line */ typedef struct _MotionTracker { - int dx, dy; /* accumulated delta for each axis */ - int time; /* time of creation */ + double dx, dy; /* accumulated delta for each axis */ + int time; /* time of creation */ int dir; /* initial direction bitfield */ } MotionTracker, *MotionTrackerPtr; @@ -69,17 +69,17 @@ typedef struct _DeviceVelocityRec { MotionTrackerPtr tracker; int num_tracker; int cur_tracker; /* current index */ - float velocity; /* velocity as guessed by algorithm */ - float last_velocity; /* previous velocity estimate */ - int last_dx; /* last time-difference */ - int last_dy ; /* phase of last/current estimate */ - float corr_mul; /* config: multiply this into velocity */ - float const_acceleration; /* config: (recipr.) const deceleration */ - float min_acceleration; /* config: minimum acceleration */ + double velocity; /* velocity as guessed by algorithm */ + double last_velocity; /* previous velocity estimate */ + double last_dx; /* last time-difference */ + double last_dy; /* phase of last/current estimate */ + double corr_mul; /* config: multiply this into velocity */ + double const_acceleration; /* config: (recipr.) const deceleration */ + double min_acceleration; /* config: minimum acceleration */ short reset_time; /* config: reset non-visible state after # ms */ short use_softening; /* config: use softening of mouse values */ - float max_rel_diff; /* config: max. relative difference */ - float max_diff; /* config: max. difference */ + double max_rel_diff; /* config: max. relative difference */ + double max_diff; /* config: max. difference */ int initial_range; /* config: max. offset used as initial velocity */ Bool average_accel; /* config: average acceleration over velocity */ PointerAccelerationProfileFunc Profile; @@ -107,11 +107,11 @@ extern _X_EXPORT void InitTrackers(DeviceVelocityPtr vel, int ntracker); extern _X_EXPORT BOOL -ProcessVelocityData2D(DeviceVelocityPtr vel, int dx, int dy, int time); +ProcessVelocityData2D(DeviceVelocityPtr vel, double dx, double dy, int time); -extern _X_EXPORT float +extern _X_EXPORT double BasicComputeAcceleration(DeviceIntPtr dev, DeviceVelocityPtr vel, - float velocity, float threshold, float acc); + double velocity, double threshold, double acc); extern _X_EXPORT void FreeVelocityData(DeviceVelocityPtr vel); From 0882b788da97c75e464eb352dac1d83c938a148e Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 2 Mar 2011 16:27:31 +0000 Subject: [PATCH 13/41] Input: Convert acceleration code to using ValuatorMask Instead of passing a set of int* to the acceleration code, pass it a mask instead, which avoids an unfortunate loss of precision. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer Reviewed-by: Simon Thum --- dix/getevents.c | 18 ++++++++---- dix/ptrveloc.c | 76 ++++++++++++++----------------------------------- 2 files changed, 34 insertions(+), 60 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index b8f4a8cf4..483d65f0e 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -1184,13 +1184,8 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons transformAbsolute(pDev, &mask); moveAbsolute(pDev, &x, &y, &mask); } else { - if (flags & POINTER_ACCELERATE) { + if (flags & POINTER_ACCELERATE) accelPointer(pDev, &mask, ms); - /* The pointer acceleration code modifies the fractional part - * in-place, so we need to extract this information first */ - x_frac = pDev->last.remainder[0]; - y_frac = pDev->last.remainder[1]; - } moveRelative(pDev, &x, &y, &mask); } @@ -1198,6 +1193,17 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons set_raw_valuators(raw, &mask, raw->valuators.data, raw->valuators.data_frac); + if (valuator_mask_isset(&mask, 0)) + { + x_frac = valuator_mask_get_double(&mask, 0); + x_frac -= trunc(x_frac); + } + if (valuator_mask_isset(&mask, 1)) + { + y_frac = valuator_mask_get_double(&mask, 1); + y_frac -= trunc(y_frac); + } + positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac); updateHistory(pDev, &mask, ms); diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c index 6271a6d34..53a0d0397 100644 --- a/dix/ptrveloc.c +++ b/dix/ptrveloc.c @@ -1115,11 +1115,10 @@ acceleratePointerPredictable( CARD32 evtime) { double dx = 0, dy = 0; - int tmpi; DeviceVelocityPtr velocitydata = GetDevicePredictableAccelData(dev); Bool soften = TRUE; - if (!velocitydata) + if (valuator_mask_num_valuators(val) == 0 || !velocitydata) return; if (velocitydata->statistics.profile_number == AccelProfileNone && @@ -1128,11 +1127,11 @@ acceleratePointerPredictable( } if (valuator_mask_isset(val, 0)) { - dx = valuator_mask_get(val, 0); + dx = valuator_mask_get_double(val, 0); } if (valuator_mask_isset(val, 1)) { - dy = valuator_mask_get(val, 1); + dy = valuator_mask_get_double(val, 1); } if (dx != 0.0 || dy != 0.0) { @@ -1155,24 +1154,12 @@ acceleratePointerPredictable( ApplySoftening(velocitydata, &dx, &dy); ApplyConstantDeceleration(velocitydata, &dx, &dy); - /* Calculate the new delta (with accel) and drop it back - * into the valuator masks */ - if (dx != 0.0) { - double tmp; - tmp = mult * dx + dev->last.remainder[0]; - tmpi = trunc(tmp); - valuator_mask_set(val, 0, tmpi); - dev->last.remainder[0] = tmp - (double)tmpi; - } - if (dy != 0.0) { - double tmp; - tmp = mult * dy + dev->last.remainder[1]; - tmpi = trunc(tmp); - valuator_mask_set(val, 1, tmpi); - dev->last.remainder[1] = tmp - (double)tmpi; - } - DebugAccelF("pos (%i | %i) remainders x: %.3f y: %.3f delta x:%.3f y:%.3f\n", - *px, *py, dev->last.remainder[0], dev->last.remainder[1], dx, dy); + if (dx != 0.0) + valuator_mask_set_double(val, 0, mult * dx); + if (dy != 0.0) + valuator_mask_set_double(val, 1, mult * dy); + DebugAccelF("pos (%i | %i) delta x:%.3f y:%.3f\n", mult * dx, + mult * dy); } } } @@ -1195,7 +1182,6 @@ acceleratePointerLightweight( { double mult = 0.0, tmpf; double dx = 0.0, dy = 0.0; - int tmpi; if (valuator_mask_isset(val, 0)) { dx = valuator_mask_get(val, 0); @@ -1205,53 +1191,35 @@ acceleratePointerLightweight( dy = valuator_mask_get(val, 1); } - if (dx == 0.0 && dy == 0.0) + if (valuator_mask_num_valuators(val) == 0) return; if (dev->ptrfeed && dev->ptrfeed->ctrl.num) { /* modeled from xf86Events.c */ if (dev->ptrfeed->ctrl.threshold) { - if ((abs(dx) + abs(dy)) >= dev->ptrfeed->ctrl.threshold) { - tmpf = ((double)dx * - (double)(dev->ptrfeed->ctrl.num)) / - (double)(dev->ptrfeed->ctrl.den) + - dev->last.remainder[0]; + if ((fabs(dx) + fabs(dy)) >= dev->ptrfeed->ctrl.threshold) { if (dx != 0.0) { - tmpi = (int) tmpf; - valuator_mask_set(val, 0, tmpi); - dev->last.remainder[0] = tmpf - (double)tmpi; + tmpf = (dx * (double)(dev->ptrfeed->ctrl.num)) / + (double)(dev->ptrfeed->ctrl.den); + valuator_mask_set_double(val, 0, tmpf); } - tmpf = ((double)dy * - (double)(dev->ptrfeed->ctrl.num)) / - (double)(dev->ptrfeed->ctrl.den) + - dev->last.remainder[1]; if (dy != 0.0) { - tmpi = (int) tmpf; - valuator_mask_set(val, 1, tmpi); - dev->last.remainder[1] = tmpf - (double)tmpi; + tmpf = (dy * (double)(dev->ptrfeed->ctrl.num)) / + (double)(dev->ptrfeed->ctrl.den); + valuator_mask_set_double(val, 1, tmpf); } } } else { - mult = pow((double)dx * (double)dx + (double)dy * (double)dy, + mult = pow(dx * dx + dy * dy, ((double)(dev->ptrfeed->ctrl.num) / (double)(dev->ptrfeed->ctrl.den) - 1.0) / 2.0) / 2.0; - if (dx != 0.0) { - tmpf = mult * (double)dx + - dev->last.remainder[0]; - tmpi = (int) tmpf; - valuator_mask_set(val, 0, tmpi); - dev->last.remainder[0] = tmpf - (double)tmpi; - } - if (dy != 0.0) { - tmpf = mult * (double)dy + - dev->last.remainder[1]; - tmpi = (int)tmpf; - valuator_mask_set(val, 1, tmpi); - dev->last.remainder[1] = tmpf - (double)tmpi; - } + if (dx != 0.0) + valuator_mask_set_double(val, 0, mult * dx); + if (dy != 0.0) + valuator_mask_set_double(val, 1, mult * dy); } } } From 5680fa41ea3373651f7017898a307e97cf29b0d3 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 2 Mar 2011 16:30:30 +0000 Subject: [PATCH 14/41] Input: Remove x and y from moveAbsolute/moveRelative Both these functions modify the mask and pDev->last.{valuators,remainder} in-place now, so there's no need to pass in pointers to local x and y values. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/getevents.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index 483d65f0e..dcd82639a 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -695,12 +695,10 @@ UpdateFromMaster(InternalEvent* events, DeviceIntPtr dev, int type, int *num_eve * Move the device's pointer to the position given in the valuators. * * @param dev The device whose pointer is to be moved. - * @param x Returns the x position of the pointer after the move. - * @param y Returns the y position of the pointer after the move. * @param mask Valuator data for this event. */ static void -moveAbsolute(DeviceIntPtr dev, int *x_out, int *y_out, ValuatorMask *mask) +moveAbsolute(DeviceIntPtr dev, ValuatorMask *mask) { int i; @@ -716,21 +714,16 @@ moveAbsolute(DeviceIntPtr dev, int *x_out, int *y_out, ValuatorMask *mask) dev->last.remainder[i] = val - trunc(val); valuator_mask_set_double(mask, i, val); } - - *x_out = dev->last.valuators[0]; - *y_out = dev->last.valuators[1]; } /** * Move the device's pointer by the values given in @valuators. * * @param dev The device whose pointer is to be moved. - * @param x Returns the x position of the pointer after the move. - * @param y Returns the y position of the pointer after the move. * @param mask Valuator data for this event. */ static void -moveRelative(DeviceIntPtr dev, int *x_out, int *y_out, ValuatorMask *mask) +moveRelative(DeviceIntPtr dev, ValuatorMask *mask) { int i; Bool clip_xy = IsMaster(dev) || !IsFloating(dev); @@ -752,9 +745,6 @@ moveRelative(DeviceIntPtr dev, int *x_out, int *y_out, ValuatorMask *mask) dev->last.remainder[i] = val - trunc(val); valuator_mask_set_double(mask, i, val); } - - *x_out = dev->last.valuators[0]; - *y_out = dev->last.valuators[1]; } /** @@ -1182,26 +1172,34 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons } transformAbsolute(pDev, &mask); - moveAbsolute(pDev, &x, &y, &mask); + moveAbsolute(pDev, &mask); } else { if (flags & POINTER_ACCELERATE) accelPointer(pDev, &mask, ms); - moveRelative(pDev, &x, &y, &mask); + moveRelative(pDev, &mask); } if ((flags & POINTER_NORAW) == 0) set_raw_valuators(raw, &mask, raw->valuators.data, raw->valuators.data_frac); - if (valuator_mask_isset(&mask, 0)) - { - x_frac = valuator_mask_get_double(&mask, 0); - x_frac -= trunc(x_frac); + if (valuator_mask_isset(&mask, 0)) { + double tmp = valuator_mask_get_double(&mask, 0); + x = trunc(tmp); + x_frac = tmp - x; } - if (valuator_mask_isset(&mask, 1)) - { - y_frac = valuator_mask_get_double(&mask, 1); - y_frac -= trunc(y_frac); + else { + x = pDev->last.valuators[0]; + x_frac = pDev->last.remainder[0]; + } + if (valuator_mask_isset(&mask, 1)) { + double tmp = valuator_mask_get_double(&mask, 1); + y = trunc(tmp); + y_frac = tmp - y; + } + else { + y = pDev->last.valuators[1]; + y_frac = pDev->last.remainder[1]; } positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative, From 4c364a312daf2b743a0a60b9907f671804a1b1b6 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 2 Mar 2011 16:49:53 +0000 Subject: [PATCH 15/41] Input: Convert rescaleValuatorAxis to double Instead of passing fractional pointers around everywhere, just pass doubles instead. Much easier. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/getevents.c | 111 ++++++++++++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 50 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index dcd82639a..2c5138809 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -259,39 +259,29 @@ CreateClassesChangedEvent(InternalEvent* event, /** * Rescale the coord between the two axis ranges. */ -static int -rescaleValuatorAxis(int coord, float remainder, float *remainder_return, AxisInfoPtr from, AxisInfoPtr to, - int defmax) +static double +rescaleValuatorAxis(double coord, AxisInfoPtr from, AxisInfoPtr to, + double defmax) { - int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax, coord_return; - float value; + double fmin = 0.0, fmax = defmax; + double tmin = 0.0, tmax = defmax; - if(from && from->min_value < from->max_value) { + if (from && from->min_value < from->max_value) { fmin = from->min_value; fmax = from->max_value; } - if(to && to->min_value < to->max_value) { + if (to && to->min_value < to->max_value) { tmin = to->min_value; tmax = to->max_value; } - if(fmin == tmin && fmax == tmax) { - if (remainder_return) - *remainder_return = remainder; + if (fmin == tmin && fmax == tmax) return coord; - } - if(fmax == fmin) { /* avoid division by 0 */ - if (remainder_return) - *remainder_return = 0.0; - return 0; - } + if (fmax == fmin) /* avoid division by 0 */ + return 0.0; - value = (coord + remainder - fmin) * (tmax - tmin) / (fmax - fmin) + tmin; - coord_return = lroundf(value); - if (remainder_return) - *remainder_return = value - coord_return; - return coord_return; + return (coord - fmin) * (tmax - tmin) / (fmax - fmin) + tmin; } /** @@ -307,6 +297,7 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev) { ScreenPtr scr = miPointerGetScreen(pDev); int i; + double val, ret; DeviceIntPtr lastSlave; /* master->last.valuators[0]/[1] is in screen coords and the actual @@ -321,11 +312,21 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev) /* scale back to device coordinates */ if(pDev->valuator->numAxes > 0) - pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], pDev->last.remainder[0], - &pDev->last.remainder[0], NULL, pDev->valuator->axes + 0, scr->width); + { + val = pDev->last.valuators[0] + pDev->last.remainder[0]; + ret = rescaleValuatorAxis(val, NULL, pDev->valuator->axes + 0, + scr->width); + pDev->last.valuators[0] = trunc(ret); + pDev->last.remainder[0] = ret - trunc(ret); + } if(pDev->valuator->numAxes > 1) - pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], pDev->last.remainder[1], - &pDev->last.remainder[1], NULL, pDev->valuator->axes + 1, scr->height); + { + val = pDev->last.valuators[1] + pDev->last.remainder[1]; + ret = rescaleValuatorAxis(val, NULL, pDev->valuator->axes + 1, + scr->height); + pDev->last.valuators[1] = trunc(ret); + pDev->last.remainder[1] = ret - trunc(ret); + } /* calculate the other axis as well based on info from the old * slave-device. If the old slave had less axes than this one, @@ -340,12 +341,11 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev) } else { - pDev->last.valuators[i] = - rescaleValuatorAxis(pDev->last.valuators[i], - pDev->last.remainder[i], - &pDev->last.remainder[i], - lastSlave->valuator->axes + i, - pDev->valuator->axes + i, 0); + val = pDev->last.valuators[i] + pDev->last.remainder[i]; + ret = rescaleValuatorAxis(val, lastSlave->valuator->axes + i, + pDev->valuator->axes + i, 0); + pDev->last.valuators[i] = trunc(ret); + pDev->last.remainder[i] = ret - trunc(ret); } } } @@ -456,7 +456,7 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start, /* scale to screen coords */ to = &core_axis; to->max_value = pScreen->width; - coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->width); + coord = rescaleValuatorAxis(coord, &from, to, pScreen->width); memcpy(corebuf, &coord, sizeof(INT16)); corebuf++; @@ -467,7 +467,7 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start, memcpy(&coord, icbuf++, sizeof(INT32)); to->max_value = pScreen->height; - coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->height); + coord = rescaleValuatorAxis(coord, &from, to, pScreen->height); memcpy(corebuf, &coord, sizeof(INT16)); } else if (IsMaster(pDev)) @@ -495,7 +495,7 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start, from.max_value = pScreen->height; /* scale from stored range into current range */ - coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0); + coord = rescaleValuatorAxis(coord, &from, to, 0); memcpy(ocbuf, &coord, sizeof(INT32)); ocbuf++; } @@ -790,19 +790,26 @@ positionSprite(DeviceIntPtr dev, int mode, ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac) { int old_screenx, old_screeny; + double val, ret; /* scale x&y to screen */ if (dev->valuator && dev->valuator->numAxes > 0) { - *screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac, - dev->valuator->axes + 0, NULL, scr->width); + val = *x + x_frac; + ret = rescaleValuatorAxis(val, dev->valuator->axes + 0, NULL, + scr->width); + *screenx = trunc(ret); + *screenx_frac = ret - trunc(ret); } else { *screenx = dev->last.valuators[0]; *screenx_frac = dev->last.remainder[0]; } if (dev->valuator && dev->valuator->numAxes > 1) { - *screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac, - dev->valuator->axes + 1, NULL, scr->height); + val = *y + y_frac; + ret = rescaleValuatorAxis(val, dev->valuator->axes + 1, NULL, + scr->height); + *screeny = trunc(ret); + *screeny_frac = ret - trunc(ret); } else { *screeny = dev->last.valuators[1]; *screeny_frac = dev->last.remainder[1]; @@ -841,14 +848,20 @@ positionSprite(DeviceIntPtr dev, int mode, if(*screenx != old_screenx) { scr = miPointerGetScreen(dev); - *x = rescaleValuatorAxis(*screenx, *screenx_frac, &x_frac, NULL, - dev->valuator->axes + 0, scr->width); + val = *screenx + *screenx_frac; + ret = rescaleValuatorAxis(val, NULL, dev->valuator->axes + 0, + scr->width); + *x = trunc(ret); + x_frac = ret - trunc(ret); } if(*screeny != old_screeny) { scr = miPointerGetScreen(dev); - *y = rescaleValuatorAxis(*screeny, *screeny_frac, &y_frac, NULL, - dev->valuator->axes + 1, scr->height); + val = *screeny + *screeny_frac; + ret = rescaleValuatorAxis(val, NULL, dev->valuator->axes + 1, + scr->height); + *y = trunc(ret); + y_frac = ret - trunc(ret); } } @@ -1155,19 +1168,17 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons if (valuator_mask_isset(&mask, 0)) { - scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 0), - 0.0, &x_frac, NULL, - pDev->valuator->axes + 0, + scaled = rescaleValuatorAxis(valuator_mask_get_double(&mask, 0), + NULL, pDev->valuator->axes + 0, scr->width); - valuator_mask_set(&mask, 0, scaled); + valuator_mask_set_double(&mask, 0, scaled); } if (valuator_mask_isset(&mask, 1)) { - scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 1), - 0.0, &y_frac, NULL, - pDev->valuator->axes + 1, + scaled = rescaleValuatorAxis(valuator_mask_get_double(&mask, 1), + NULL, pDev->valuator->axes + 1, scr->height); - valuator_mask_set(&mask, 1, scaled); + valuator_mask_set_double(&mask, 1, scaled); } } From 51437995a5041a8c53c33b508b1607c78a5fa463 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 2 Mar 2011 16:50:55 +0000 Subject: [PATCH 16/41] Input: Don't call positionSprite for non-pointer devices If the device doesn't have any valuators, or if it has less than two of them, don't bother calling positionSprite. Users with one-dimensional pointing devices may be upset. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/getevents.c | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index 2c5138809..94da143e3 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -792,28 +792,19 @@ positionSprite(DeviceIntPtr dev, int mode, int old_screenx, old_screeny; double val, ret; - /* scale x&y to screen */ - if (dev->valuator && dev->valuator->numAxes > 0) { - val = *x + x_frac; - ret = rescaleValuatorAxis(val, dev->valuator->axes + 0, NULL, - scr->width); - *screenx = trunc(ret); - *screenx_frac = ret - trunc(ret); - } else { - *screenx = dev->last.valuators[0]; - *screenx_frac = dev->last.remainder[0]; - } + if (!dev->valuator || dev->valuator->numAxes < 2) + return; - if (dev->valuator && dev->valuator->numAxes > 1) { - val = *y + y_frac; - ret = rescaleValuatorAxis(val, dev->valuator->axes + 1, NULL, - scr->height); - *screeny = trunc(ret); - *screeny_frac = ret - trunc(ret); - } else { - *screeny = dev->last.valuators[1]; - *screeny_frac = dev->last.remainder[1]; - } + /* scale x&y to screen */ + val = *x + x_frac; + ret = rescaleValuatorAxis(val, dev->valuator->axes + 0, NULL, scr->width); + *screenx = trunc(ret); + *screenx_frac = ret - trunc(ret); + + val = *y + y_frac; + ret = rescaleValuatorAxis(val, dev->valuator->axes + 1, NULL, scr->height); + *screeny = trunc(ret); + *screeny_frac = ret - trunc(ret); /* Hit the left screen edge? */ if (*screenx <= 0 && *screenx_frac < 0.0f) From 629a575261c08ca67324fea4c975636a1a95dc75 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 2 Mar 2011 17:04:57 +0000 Subject: [PATCH 17/41] Input: Convert positionSprite and GetPointerEvents to double Use doubles internally in both of these functions, eliminating most of the remaining int co-ordinate usage. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/getevents.c | 144 ++++++++++++++++++------------------------------ 1 file changed, 54 insertions(+), 90 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index 94da143e3..a9409b4cc 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -776,91 +776,61 @@ accelPointer(DeviceIntPtr dev, ValuatorMask* valuators, CARD32 ms) * @param mode Movement mode (Absolute or Relative) * @param x Pointer to current x-axis value, may be modified. * @param y Pointer to current y-axis value, may be modified. - * @param x_frac Fractional part of current x-axis value, may be modified. - * @param y_frac Fractional part of current y-axis value, may be modified. * @param scr Screen the device's sprite is currently on. * @param screenx Screen x coordinate the sprite is on after the update. * @param screeny Screen y coordinate the sprite is on after the update. - * @param screenx_frac Fractional part of screen x coordinate, as above. - * @param screeny_frac Fractional part of screen y coordinate, as above. */ static void -positionSprite(DeviceIntPtr dev, int mode, - int *x, int *y, float x_frac, float y_frac, - ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac) +positionSprite(DeviceIntPtr dev, int mode, double *x, double *y, ScreenPtr scr, + double *screenx, double *screeny) { - int old_screenx, old_screeny; - double val, ret; + int isx, isy; /* screen {x, y}, in int */ if (!dev->valuator || dev->valuator->numAxes < 2) return; /* scale x&y to screen */ - val = *x + x_frac; - ret = rescaleValuatorAxis(val, dev->valuator->axes + 0, NULL, scr->width); - *screenx = trunc(ret); - *screenx_frac = ret - trunc(ret); + *screenx = rescaleValuatorAxis(*x, dev->valuator->axes + 0, NULL, + scr->width); - val = *y + y_frac; - ret = rescaleValuatorAxis(val, dev->valuator->axes + 1, NULL, scr->height); - *screeny = trunc(ret); - *screeny_frac = ret - trunc(ret); + *screeny = rescaleValuatorAxis(*y, dev->valuator->axes + 1, NULL, + scr->height); - /* Hit the left screen edge? */ - if (*screenx <= 0 && *screenx_frac < 0.0f) + /* miPointerSetPosition takes care of crossing screens for us, as well as + * clipping to the current screen. In the event we actually change screen, + * we just drop the float component on the floor, then convert from + * screenx back into device co-ordinates. */ + isx = trunc(*screenx); + isy = trunc(*screeny); + miPointerSetPosition(dev, mode, &isx, &isy); + scr = miPointerGetScreen(dev); + if (isx != trunc(*screenx)) { - *screenx_frac = 0.0f; - x_frac = 0.0f; + *screenx -= trunc(*screenx) - isx; + *x = rescaleValuatorAxis(*screenx, NULL, dev->valuator->axes + 0, + scr->width); } - if (*screeny <= 0 && *screeny_frac < 0.0f) + if (isy != trunc(*screeny)) { - *screeny_frac = 0.0f; - y_frac = 0.0f; + *screeny -= trunc(*screeny) - isy; + *y = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1, + scr->height); } - - old_screenx = *screenx; - old_screeny = *screeny; - /* This takes care of crossing screens for us, as well as clipping - * to the current screen. */ - miPointerSetPosition(dev, mode, screenx, screeny); - - if(!IsMaster(dev) && !IsFloating(dev)) { + /* Update the MD's co-ordinates, which are always in screen space. */ + if (!IsMaster(dev) || !IsFloating(dev)) { DeviceIntPtr master = GetMaster(dev, MASTER_POINTER); - master->last.valuators[0] = *screenx; - master->last.valuators[1] = *screeny; - master->last.remainder[0] = *screenx_frac; - master->last.remainder[1] = *screeny_frac; - } - - if (dev->valuator) - { - /* Crossed screen? Scale back to device coordiantes */ - if(*screenx != old_screenx) - { - scr = miPointerGetScreen(dev); - val = *screenx + *screenx_frac; - ret = rescaleValuatorAxis(val, NULL, dev->valuator->axes + 0, - scr->width); - *x = trunc(ret); - x_frac = ret - trunc(ret); - } - if(*screeny != old_screeny) - { - scr = miPointerGetScreen(dev); - val = *screeny + *screeny_frac; - ret = rescaleValuatorAxis(val, NULL, dev->valuator->axes + 1, - scr->height); - *y = trunc(ret); - y_frac = ret - trunc(ret); - } + master->last.valuators[0] = trunc(*screenx); + master->last.remainder[0] = *screenx - trunc(*screenx); + master->last.valuators[1] = trunc(*screeny); + master->last.remainder[1] = *screeny - trunc(*screeny); } /* dropy x/y (device coordinates) back into valuators for next event */ - dev->last.valuators[0] = *x; - dev->last.valuators[1] = *y; - dev->last.remainder[0] = x_frac; - dev->last.remainder[1] = y_frac; + dev->last.valuators[0] = trunc(*x); + dev->last.valuators[1] = trunc(*y); + dev->last.remainder[0] = *x - trunc(*x); + dev->last.remainder[1] = *y - trunc(*y); } /** @@ -1106,9 +1076,8 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons CARD32 ms; DeviceEvent *event; RawDeviceEvent *raw; - int x = 0, y = 0, /* device coords */ - cx, cy; /* only screen coordinates */ - float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac; + double x = 0.0, y = 0.0; /* device coords */ + double screenx = 0.0, screeny = 0.0; /* screen coords */ ScreenPtr scr = miPointerGetScreen(pDev); ValuatorMask mask; @@ -1155,7 +1124,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons { if (flags & POINTER_SCREEN) /* valuators are in screen coords */ { - int scaled; + double scaled; if (valuator_mask_isset(&mask, 0)) { @@ -1185,27 +1154,21 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons set_raw_valuators(raw, &mask, raw->valuators.data, raw->valuators.data_frac); - if (valuator_mask_isset(&mask, 0)) { - double tmp = valuator_mask_get_double(&mask, 0); - x = trunc(tmp); - x_frac = tmp - x; - } - else { - x = pDev->last.valuators[0]; - x_frac = pDev->last.remainder[0]; - } - if (valuator_mask_isset(&mask, 1)) { - double tmp = valuator_mask_get_double(&mask, 1); - y = trunc(tmp); - y_frac = tmp - y; - } - else { - y = pDev->last.valuators[1]; - y_frac = pDev->last.remainder[1]; - } + if (valuator_mask_isset(&mask, 0)) + x = valuator_mask_get_double(&mask, 0); + else + x = pDev->last.valuators[0] + pDev->last.remainder[0]; + if (valuator_mask_isset(&mask, 1)) + y = valuator_mask_get_double(&mask, 1); + else + y = pDev->last.valuators[1] + pDev->last.remainder[1]; positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative, - &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac); + &x, &y, scr, &screenx, &screeny); + if (valuator_mask_isset(&mask, 0)) + valuator_mask_set_double(&mask, 0, x); + if (valuator_mask_isset(&mask, 1)) + valuator_mask_set_double(&mask, 1, y); updateHistory(pDev, &mask, ms); /* Update the valuators with the true value sent to the client*/ @@ -1235,10 +1198,11 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons event->detail.button = buttons; } - event->root_x = cx; /* root_x/y always in screen coords */ - event->root_y = cy; - event->root_x_frac = cx_frac; - event->root_y_frac = cy_frac; + /* root_x and root_y must be in screen co-ordinates */ + event->root_x = trunc(screenx); + event->root_y = trunc(screeny); + event->root_x_frac = screenx - trunc(screenx); + event->root_y_frac = screeny - trunc(screeny); set_valuators(pDev, event, &mask); From 3b7fb0f68dc0d40c968c2cfc9bb74b1d0fb48bc8 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 2 Mar 2011 17:18:48 +0000 Subject: [PATCH 18/41] Input: Modify mask in-place in positionSprite Instead of taking pointers to x and y values to modify in positionSprite, just modify the mask (as well as dev->last) in place. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/getevents.c | 69 ++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 38 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index a9409b4cc..ec79fcffe 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -774,26 +774,34 @@ accelPointer(DeviceIntPtr dev, ValuatorMask* valuators, CARD32 ms) * * @param dev The device to be moved. * @param mode Movement mode (Absolute or Relative) - * @param x Pointer to current x-axis value, may be modified. - * @param y Pointer to current y-axis value, may be modified. * @param scr Screen the device's sprite is currently on. + * @param mask Mask of axis values for this event * @param screenx Screen x coordinate the sprite is on after the update. * @param screeny Screen y coordinate the sprite is on after the update. */ static void -positionSprite(DeviceIntPtr dev, int mode, double *x, double *y, ScreenPtr scr, +positionSprite(DeviceIntPtr dev, int mode, ScreenPtr scr, ValuatorMask *mask, double *screenx, double *screeny) { int isx, isy; /* screen {x, y}, in int */ + double x, y; if (!dev->valuator || dev->valuator->numAxes < 2) return; - /* scale x&y to screen */ - *screenx = rescaleValuatorAxis(*x, dev->valuator->axes + 0, NULL, - scr->width); + if (valuator_mask_isset(mask, 0)) + x = valuator_mask_get_double(mask, 0); + else + x = dev->last.valuators[0] + dev->last.remainder[0]; + if (valuator_mask_isset(mask, 1)) + y = valuator_mask_get_double(mask, 1); + else + y = dev->last.valuators[1] + dev->last.remainder[1]; - *screeny = rescaleValuatorAxis(*y, dev->valuator->axes + 1, NULL, + /* scale x&y to screen */ + *screenx = rescaleValuatorAxis(x, dev->valuator->axes + 0, NULL, + scr->width); + *screeny = rescaleValuatorAxis(y, dev->valuator->axes + 1, NULL, scr->height); /* miPointerSetPosition takes care of crossing screens for us, as well as @@ -807,14 +815,14 @@ positionSprite(DeviceIntPtr dev, int mode, double *x, double *y, ScreenPtr scr, if (isx != trunc(*screenx)) { *screenx -= trunc(*screenx) - isx; - *x = rescaleValuatorAxis(*screenx, NULL, dev->valuator->axes + 0, - scr->width); + x = rescaleValuatorAxis(*screenx, NULL, dev->valuator->axes + 0, + scr->width); } if (isy != trunc(*screeny)) { *screeny -= trunc(*screeny) - isy; - *y = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1, - scr->height); + y = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1, + scr->height); } /* Update the MD's co-ordinates, which are always in screen space. */ @@ -827,10 +835,15 @@ positionSprite(DeviceIntPtr dev, int mode, double *x, double *y, ScreenPtr scr, } /* dropy x/y (device coordinates) back into valuators for next event */ - dev->last.valuators[0] = trunc(*x); - dev->last.valuators[1] = trunc(*y); - dev->last.remainder[0] = *x - trunc(*x); - dev->last.remainder[1] = *y - trunc(*y); + dev->last.valuators[0] = trunc(x); + dev->last.valuators[1] = trunc(y); + dev->last.remainder[0] = x - trunc(x); + dev->last.remainder[1] = y - trunc(y); + + if (valuator_mask_isset(mask, 0)) + valuator_mask_set_double(mask, 0, x); + if (valuator_mask_isset(mask, 1)) + valuator_mask_set_double(mask, 1, y); } /** @@ -1076,8 +1089,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons CARD32 ms; DeviceEvent *event; RawDeviceEvent *raw; - double x = 0.0, y = 0.0; /* device coords */ - double screenx = 0.0, screeny = 0.0; /* screen coords */ + double screenx = 0.0, screeny = 0.0; ScreenPtr scr = miPointerGetScreen(pDev); ValuatorMask mask; @@ -1154,29 +1166,10 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons set_raw_valuators(raw, &mask, raw->valuators.data, raw->valuators.data_frac); - if (valuator_mask_isset(&mask, 0)) - x = valuator_mask_get_double(&mask, 0); - else - x = pDev->last.valuators[0] + pDev->last.remainder[0]; - if (valuator_mask_isset(&mask, 1)) - y = valuator_mask_get_double(&mask, 1); - else - y = pDev->last.valuators[1] + pDev->last.remainder[1]; - - positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative, - &x, &y, scr, &screenx, &screeny); - if (valuator_mask_isset(&mask, 0)) - valuator_mask_set_double(&mask, 0, x); - if (valuator_mask_isset(&mask, 1)) - valuator_mask_set_double(&mask, 1, y); + positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative, scr, + &mask, &screenx, &screeny); updateHistory(pDev, &mask, ms); - /* Update the valuators with the true value sent to the client*/ - if (valuator_mask_isset(&mask, 0)) - valuator_mask_set(&mask, 0, x); - if (valuator_mask_isset(&mask, 1)) - valuator_mask_set(&mask, 1, y); - clipValuators(pDev, &mask); event = &events->device_event; From 626f487b97c99b48bf1d8c8ef4367a686639c3e6 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Thu, 3 Mar 2011 15:06:45 +0000 Subject: [PATCH 19/41] Input: Make RawDeviceEvent use doubles internally Change RawDeviceEvent to use doubles for valuators internally, rather than data(_raw) and data(_raw)_frac. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/eventconvert.c | 13 ++++++++----- dix/getevents.c | 20 ++++++-------------- include/eventstr.h | 6 ++---- test/xi2/protocol-eventconvert.c | 14 ++++++-------- 4 files changed, 22 insertions(+), 31 deletions(-) diff --git a/dix/eventconvert.c b/dix/eventconvert.c index fa8ba9ec0..54e902081 100644 --- a/dix/eventconvert.c +++ b/dix/eventconvert.c @@ -649,7 +649,7 @@ eventToRawEvent(RawDeviceEvent *ev, xEvent **xi) int vallen, nvals; int i, len = sizeof(xXIRawEvent); char *ptr; - FP3232 *axisval; + FP3232 *axisval, *axisval_raw; nvals = count_bits(ev->valuators.mask, sizeof(ev->valuators.mask)); len += nvals * sizeof(FP3232) * 2; /* 8 byte per valuator, once @@ -671,16 +671,19 @@ eventToRawEvent(RawDeviceEvent *ev, xEvent **xi) ptr = (char*)&raw[1]; axisval = (FP3232*)(ptr + raw->valuators_len * 4); + axisval_raw = axisval + nvals; for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) { if (BitIsOn(ev->valuators.mask, i)) { SetBit(ptr, i); - axisval->integral = ev->valuators.data[i]; - axisval->frac = ev->valuators.data_frac[i]; - (axisval + nvals)->integral = ev->valuators.data_raw[i]; - (axisval + nvals)->frac = ev->valuators.data_raw_frac[i]; + axisval->integral = trunc(ev->valuators.data[i]); + axisval->frac = ev->valuators.data[i] - axisval->integral; + axisval_raw->integral = trunc(ev->valuators.data_raw[i]); + axisval_raw->frac = ev->valuators.data_raw[i] - + axisval_raw->integral; axisval++; + axisval_raw++; } } diff --git a/dix/getevents.c b/dix/getevents.c index ec79fcffe..d04f4125e 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -167,20 +167,16 @@ init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail) } static void -set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, int32_t* data, - int32_t* data_frac) +set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, double* data) { int i; - double val; for (i = 0; i < valuator_mask_size(mask); i++) { if (valuator_mask_isset(mask, i)) { SetBit(event->valuators.mask, i); - val = valuator_mask_get_double(mask, i); - data[i] = trunc(val); - data_frac[i] = (val - data[i]) * (1UL << 32); + data[i] = valuator_mask_get_double(mask, i); } } } @@ -950,13 +946,11 @@ GetKeyboardEvents(InternalEvent *events, DeviceIntPtr pDev, int type, valuator_mask_copy(&mask, mask_in); init_raw(pDev, raw, ms, type, key_code); - set_raw_valuators(raw, &mask, raw->valuators.data_raw, - raw->valuators.data_raw_frac); + set_raw_valuators(raw, &mask, raw->valuators.data_raw); clipValuators(pDev, &mask); - set_raw_valuators(raw, &mask, raw->valuators.data, - raw->valuators.data_frac); + set_raw_valuators(raw, &mask, raw->valuators.data); event = &events->device_event; init_device_event(event, pDev, ms); @@ -1128,8 +1122,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons num_events++; init_raw(pDev, raw, ms, type, buttons); - set_raw_valuators(raw, &mask, raw->valuators.data_raw, - raw->valuators.data_raw_frac); + set_raw_valuators(raw, &mask, raw->valuators.data_raw); } if (flags & POINTER_ABSOLUTE) @@ -1163,8 +1156,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons } if ((flags & POINTER_NORAW) == 0) - set_raw_valuators(raw, &mask, raw->valuators.data, - raw->valuators.data_frac); + set_raw_valuators(raw, &mask, raw->valuators.data); positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative, scr, &mask, &screenx, &screeny); diff --git a/include/eventstr.h b/include/eventstr.h index ecaeddcb6..0645585a3 100644 --- a/include/eventstr.h +++ b/include/eventstr.h @@ -199,10 +199,8 @@ struct _RawDeviceEvent } detail; struct { 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 */ - int32_t data_raw[MAX_VALUATORS]; /**< Valuator data as posted */ - int32_t data_raw_frac[MAX_VALUATORS];/**< Fractional part for data_raw */ + double data[MAX_VALUATORS]; /**< Valuator data */ + double data_raw[MAX_VALUATORS]; /**< Valuator data as posted */ } valuators; uint32_t flags; /**< Flags to be copied into the generated event */ }; diff --git a/test/xi2/protocol-eventconvert.c b/test/xi2/protocol-eventconvert.c index 80c47b06f..6df9af0fe 100644 --- a/test/xi2/protocol-eventconvert.c +++ b/test/xi2/protocol-eventconvert.c @@ -93,8 +93,8 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out, value = (FP3232*)(((unsigned char*)&out[1]) + out->valuators_len * 4); value += nvals; - vi.integral = in->valuators.data[i]; - vi.frac = in->valuators.data_frac[i]; + vi.integral = trunc(in->valuators.data[i]); + vi.frac = in->valuators.data[i] - vi.integral; vo.integral = value->integral; vo.frac = value->frac; @@ -109,8 +109,8 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out, raw_value = value + bits_set; - vi.integral = in->valuators.data_raw[i]; - vi.frac = in->valuators.data_raw_frac[i]; + vi.integral = trunc(in->valuators.data_raw[i]); + vi.frac = in->valuators.data_raw[i] - vi.integral; vo.integral = raw_value->integral; vo.frac = raw_value->frac; @@ -248,10 +248,8 @@ static void test_convert_XIRawEvent(void) { XISetMask(in.valuators.mask, i); - in.valuators.data[i] = i; - in.valuators.data_raw[i] = i + 10; - in.valuators.data_frac[i] = i + 20; - in.valuators.data_raw_frac[i] = i + 30; + in.valuators.data[i] = i + (i * 0.0010); + in.valuators.data_raw[i] = (i + 10) + (i * 0.0030); test_XIRawEvent(&in); XIClearMask(in.valuators.mask, i); } From 2d9beeb2174661d0a0732403ad4e49e9ff56718d Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Thu, 3 Mar 2011 15:36:55 +0000 Subject: [PATCH 20/41] Input: Make DeviceEvent use doubles internally Change the DeviceEvent InternalEvent to use doubles for its valuators, instead of data and data_frac. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- Xi/exevents.c | 5 +---- dix/eventconvert.c | 5 +++-- dix/getevents.c | 4 +--- include/eventstr.h | 3 +-- test/xi2/protocol-eventconvert.c | 7 +++---- 5 files changed, 9 insertions(+), 15 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 38089a27c..4dd9b85d5 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -774,12 +774,9 @@ UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event) for (i = 0; i <= last_valuator && i < v->numAxes; i++) { + /* XXX: Relative/Absolute mode */ if (BitIsOn(&event->valuators.mask, i)) - { - /* XXX: Relative/Absolute mode */ v->axisVal[i] = event->valuators.data[i]; - v->axisVal[i] += (event->valuators.data_frac[i] * 1.0f / (1 << 16) / (1 << 16)); - } } if (event->type == ET_KeyPress) { diff --git a/dix/eventconvert.c b/dix/eventconvert.c index 54e902081..9cc177efc 100644 --- a/dix/eventconvert.c +++ b/dix/eventconvert.c @@ -633,8 +633,9 @@ eventToDeviceEvent(DeviceEvent *ev, xEvent **xi) if (BitIsOn(ev->valuators.mask, i)) { SetBit(ptr, i); - axisval->integral = ev->valuators.data[i]; - axisval->frac = ev->valuators.data_frac[i]; + axisval->integral = trunc(ev->valuators.data[i]); + axisval->frac = (ev->valuators.data[i] - axisval->integral) * + (1UL << 32); axisval++; } } diff --git a/dix/getevents.c b/dix/getevents.c index d04f4125e..fac845ea0 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -196,9 +196,7 @@ set_valuators(DeviceIntPtr dev, DeviceEvent* event, ValuatorMask *mask) SetBit(event->valuators.mask, i); if (valuator_get_mode(dev, i) == Absolute) SetBit(event->valuators.mode, i); - event->valuators.data[i] = valuator_mask_get(mask, i); - event->valuators.data_frac[i] = - dev->last.remainder[i] * (1 << 16) * (1 << 16); + event->valuators.data[i] = valuator_mask_get_double(mask, i); } else if (valuator_get_mode(dev, i) == Absolute) event->valuators.data[i] = dev->valuator->axisVal[i]; diff --git a/include/eventstr.h b/include/eventstr.h index 0645585a3..2de077fd2 100644 --- a/include/eventstr.h +++ b/include/eventstr.h @@ -95,8 +95,7 @@ struct _DeviceEvent struct { 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 */ - int32_t data_frac[MAX_VALUATORS]; /**< Fractional part for data */ + double data[MAX_VALUATORS]; /**< Valuator data */ } valuators; struct { uint32_t base; /**< XKB base modifiers */ diff --git a/test/xi2/protocol-eventconvert.c b/test/xi2/protocol-eventconvert.c index 6df9af0fe..d7a9ee420 100644 --- a/test/xi2/protocol-eventconvert.c +++ b/test/xi2/protocol-eventconvert.c @@ -374,8 +374,8 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out, { FP3232 vi, vo; - vi.integral = in->valuators.data[i]; - vi.frac = in->valuators.data_frac[i]; + vi.integral = trunc(in->valuators.data[i]); + vi.frac = (in->valuators.data[i] - vi.integral) * (1UL << 32); vo = *values; @@ -617,8 +617,7 @@ static void test_convert_XIDeviceEvent(void) { XISetMask(in.valuators.mask, i); - in.valuators.data[i] = i; - in.valuators.data_frac[i] = i + 20; + in.valuators.data[i] = i + (i * 0.0020); test_XIDeviceEvent(&in); XIClearMask(in.valuators.mask, i); } From 94c19a0a72403fc522e3d05eeb57f35e111a2562 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Thu, 3 Mar 2011 15:46:45 +0000 Subject: [PATCH 21/41] Input: Convert DeviceIntRec::last to use doubles Change the last real user of a split integer/fractional co-ordinate system, DeviceIntRec's last->{valuators,remainder} to just have one set of doubles. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- Xi/xiwarppointer.c | 2 -- dix/getevents.c | 67 ++++++++++++++++++++-------------------------- include/inputstr.h | 3 +-- 3 files changed, 30 insertions(+), 42 deletions(-) diff --git a/Xi/xiwarppointer.c b/Xi/xiwarppointer.c index 8fcb4d16b..11ab241b5 100644 --- a/Xi/xiwarppointer.c +++ b/Xi/xiwarppointer.c @@ -190,8 +190,6 @@ ProcXIWarpPointer(ClientPtr client) /* if we don't update the device, we get a jump next time it moves */ pDev->last.valuators[0] = x; pDev->last.valuators[1] = y; - pDev->last.remainder[0] = 0; - pDev->last.remainder[1] = 0; miPointerUpdateSprite(pDev); /* FIXME: XWarpPointer is supposed to generate an event. It doesn't do it diff --git a/dix/getevents.c b/dix/getevents.c index fac845ea0..db4731569 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -291,15 +291,12 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev) { ScreenPtr scr = miPointerGetScreen(pDev); int i; - double val, ret; DeviceIntPtr lastSlave; /* master->last.valuators[0]/[1] is in screen coords and the actual * position of the pointer */ pDev->last.valuators[0] = master->last.valuators[0]; pDev->last.valuators[1] = master->last.valuators[1]; - pDev->last.remainder[0] = master->last.remainder[0]; - pDev->last.remainder[1] = master->last.remainder[1]; if (!pDev->valuator) return; @@ -307,19 +304,17 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev) /* scale back to device coordinates */ if(pDev->valuator->numAxes > 0) { - val = pDev->last.valuators[0] + pDev->last.remainder[0]; - ret = rescaleValuatorAxis(val, NULL, pDev->valuator->axes + 0, - scr->width); - pDev->last.valuators[0] = trunc(ret); - pDev->last.remainder[0] = ret - trunc(ret); + pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], + NULL, + pDev->valuator->axes + 0, + scr->width); } if(pDev->valuator->numAxes > 1) { - val = pDev->last.valuators[1] + pDev->last.remainder[1]; - ret = rescaleValuatorAxis(val, NULL, pDev->valuator->axes + 1, - scr->height); - pDev->last.valuators[1] = trunc(ret); - pDev->last.remainder[1] = ret - trunc(ret); + pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], + NULL, + pDev->valuator->axes + 1, + scr->height); } /* calculate the other axis as well based on info from the old @@ -331,15 +326,13 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev) if (i >= lastSlave->valuator->numAxes) { pDev->last.valuators[i] = 0; - pDev->last.remainder[i] = 0; } else { - val = pDev->last.valuators[i] + pDev->last.remainder[i]; - ret = rescaleValuatorAxis(val, lastSlave->valuator->axes + i, + double val = pDev->last.valuators[i]; + val = rescaleValuatorAxis(val, lastSlave->valuator->axes + i, pDev->valuator->axes + i, 0); - pDev->last.valuators[i] = trunc(ret); - pDev->last.remainder[i] = ret - trunc(ret); + pDev->last.valuators[i] = val; } } } @@ -523,7 +516,7 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start, */ static void updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask, - int *valuators) + double *valuators) { char *buff = (char *) pDev->valuator->motion; ValuatorClassPtr v; @@ -545,6 +538,7 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask, for (i = 0; i < v->numAxes; i++) { + int val; /* XI1 doesn't support mixed mode devices */ if (valuator_get_mode(pDev, i) != valuator_get_mode(pDev, 0)) break; @@ -557,7 +551,8 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask, buff += sizeof(INT32); memcpy(buff, &v->axes[i].max_value, sizeof(INT32)); buff += sizeof(INT32); - memcpy(buff, &valuators[i], sizeof(INT32)); + val = valuators[i]; + memcpy(buff, &val, sizeof(INT32)); buff += sizeof(INT32); } } else @@ -573,12 +568,14 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask, for (i = 0; i < MAX_VALUATORS; i++) { + int val; if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) { buff += sizeof(INT32); continue; } - memcpy(buff, &valuators[i], sizeof(INT32)); + val = valuators[i]; + memcpy(buff, &val, sizeof(INT32)); buff += sizeof(INT32); } } @@ -704,8 +701,7 @@ moveAbsolute(DeviceIntPtr dev, ValuatorMask *mask) continue; val = valuator_mask_get_double(mask, i); clipAxis(dev, i, &val); - dev->last.valuators[i] = trunc(val); - dev->last.remainder[i] = val - trunc(val); + dev->last.valuators[i] = val; valuator_mask_set_double(mask, i, val); } } @@ -725,7 +721,7 @@ moveRelative(DeviceIntPtr dev, ValuatorMask *mask) /* calc other axes, clip, drop back into valuators */ for (i = 0; i < valuator_mask_size(mask); i++) { - double val = dev->last.valuators[i] + dev->last.remainder[i]; + double val = dev->last.valuators[i]; if (!valuator_mask_isset(mask, i)) continue; @@ -735,8 +731,7 @@ moveRelative(DeviceIntPtr dev, ValuatorMask *mask) if (valuator_get_mode(dev, i) == Absolute && ((i != 0 && i != 1) || clip_xy)) clipAxis(dev, i, &val); - dev->last.valuators[i] = trunc(val); - dev->last.remainder[i] = val - trunc(val); + dev->last.valuators[i] = val; valuator_mask_set_double(mask, i, val); } } @@ -786,11 +781,11 @@ positionSprite(DeviceIntPtr dev, int mode, ScreenPtr scr, ValuatorMask *mask, if (valuator_mask_isset(mask, 0)) x = valuator_mask_get_double(mask, 0); else - x = dev->last.valuators[0] + dev->last.remainder[0]; + x = dev->last.valuators[0]; if (valuator_mask_isset(mask, 1)) y = valuator_mask_get_double(mask, 1); else - y = dev->last.valuators[1] + dev->last.remainder[1]; + y = dev->last.valuators[1]; /* scale x&y to screen */ *screenx = rescaleValuatorAxis(x, dev->valuator->axes + 0, NULL, @@ -822,17 +817,13 @@ positionSprite(DeviceIntPtr dev, int mode, ScreenPtr scr, ValuatorMask *mask, /* Update the MD's co-ordinates, which are always in screen space. */ if (!IsMaster(dev) || !IsFloating(dev)) { DeviceIntPtr master = GetMaster(dev, MASTER_POINTER); - master->last.valuators[0] = trunc(*screenx); - master->last.remainder[0] = *screenx - trunc(*screenx); - master->last.valuators[1] = trunc(*screeny); - master->last.remainder[1] = *screeny - trunc(*screeny); + master->last.valuators[0] = *screenx; + master->last.valuators[1] = *screeny; } /* dropy x/y (device coordinates) back into valuators for next event */ - dev->last.valuators[0] = trunc(x); - dev->last.valuators[1] = trunc(y); - dev->last.remainder[0] = x - trunc(x); - dev->last.remainder[1] = y - trunc(y); + dev->last.valuators[0] = x; + dev->last.valuators[1] = y; if (valuator_mask_isset(mask, 0)) valuator_mask_set_double(mask, 0, x); @@ -1018,12 +1009,12 @@ transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask) if (valuator_mask_isset(mask, 0)) ox = x = valuator_mask_get_double(mask, 0); else - ox = x = dev->last.valuators[0] + dev->last.remainder[0]; + ox = x = dev->last.valuators[0]; if (valuator_mask_isset(mask, 1)) oy = y = valuator_mask_get_double(mask, 1); else - oy = y = dev->last.valuators[1] + dev->last.remainder[1]; + oy = y = dev->last.valuators[1]; transform(&dev->transform, &x, &y); diff --git a/include/inputstr.h b/include/inputstr.h index 480e95671..c25f5c670 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -521,8 +521,7 @@ typedef struct _DeviceIntRec { * remainder supports acceleration */ struct { - int valuators[MAX_VALUATORS]; - float remainder[MAX_VALUATORS]; + double valuators[MAX_VALUATORS]; int numValuators; DeviceIntPtr slave; } last; From bc8aad2376207b5ca9c74effae67fb8183222d2e Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Thu, 3 Mar 2011 19:48:15 +0000 Subject: [PATCH 22/41] Input: Set last valuators in GetPointerEvents only Previously, various pieces of code, including acceleration, used to drop the values into DeviceIntRec::last.valuators. Remove all this and only do it in GetPointerEvents after all transformation, acceleration and clipping, so we're guaranteed to always have the correct values. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/getevents.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index db4731569..7cb2968c4 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -701,7 +701,6 @@ moveAbsolute(DeviceIntPtr dev, ValuatorMask *mask) continue; val = valuator_mask_get_double(mask, i); clipAxis(dev, i, &val); - dev->last.valuators[i] = val; valuator_mask_set_double(mask, i, val); } } @@ -731,7 +730,6 @@ moveRelative(DeviceIntPtr dev, ValuatorMask *mask) if (valuator_get_mode(dev, i) == Absolute && ((i != 0 && i != 1) || clip_xy)) clipAxis(dev, i, &val); - dev->last.valuators[i] = val; valuator_mask_set_double(mask, i, val); } } @@ -821,10 +819,6 @@ positionSprite(DeviceIntPtr dev, int mode, ScreenPtr scr, ValuatorMask *mask, master->last.valuators[1] = *screeny; } - /* dropy x/y (device coordinates) back into valuators for next event */ - dev->last.valuators[0] = x; - dev->last.valuators[1] = y; - if (valuator_mask_isset(mask, 0)) valuator_mask_set_double(mask, 0, x); if (valuator_mask_isset(mask, 1)) @@ -1068,7 +1062,7 @@ QueuePointerEvents(DeviceIntPtr device, int type, int GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons, int flags, const ValuatorMask *mask_in) { - int num_events = 1; + int num_events = 1, i; CARD32 ms; DeviceEvent *event; RawDeviceEvent *raw; @@ -1153,6 +1147,12 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons clipValuators(pDev, &mask); + for (i = 0; i < valuator_mask_size(&mask); i++) + { + if (valuator_mask_isset(&mask, i)) + pDev->last.valuators[i] = valuator_mask_get_double(&mask, i); + } + event = &events->device_event; init_device_event(event, pDev, ms); From d8e42decbad4abe13265f4c546a0c561905d018f Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Tue, 15 Feb 2011 18:54:14 +0000 Subject: [PATCH 23/41] Input: Split GetPointerEvents body into a helper function For smooth-scrolling support, we want GetPointerEvents to generate multiple events, so split the body of the function out into a helper function in order to call it multiple times. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/getevents.c | 76 +++++++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 28 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index 7cb2968c4..4eb1b3afe 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -1043,40 +1043,25 @@ QueuePointerEvents(DeviceIntPtr device, int type, } /** - * Generate a series of InternalEvents representing pointer motion, or - * button presses. + * Helper function for GetPointerEvents, which only generates motion and + * raw motion events for the slave device: does not update the master device. * - * The DDX is responsible for allocating the events in the first - * place via InitEventList() and GetMaximumEventsNum(), and for freeing it. - * - * In the generated events rootX/Y will be in absolute screen coords and - * the valuator information in the absolute or relative device coords. - * - * last.valuators[x] of the device is always in absolute device coords. - * last.valuators[x] of the master device is in absolute screen coords. - * - * master->last.valuators[x] for x > 2 is undefined. + * Should not be called by anyone other than GetPointerEvents. * * @return the number of events written into events. */ -int -GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons, - int flags, const ValuatorMask *mask_in) { +static int +fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type, + int buttons, CARD32 ms, int flags, + const ValuatorMask *mask_in) +{ int num_events = 1, i; - CARD32 ms; DeviceEvent *event; - RawDeviceEvent *raw; + RawDeviceEvent *raw; double screenx = 0.0, screeny = 0.0; ScreenPtr scr = miPointerGetScreen(pDev); ValuatorMask mask; - /* refuse events from disabled devices */ - if (!pDev->enabled) - return 0; - - if (!scr) - return 0; - switch (type) { case MotionNotify: @@ -1092,10 +1077,6 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons return 0; } - ms = GetTimeInMillis(); /* before pointer update to help precision */ - - events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); - valuator_mask_copy(&mask, mask_in); if ((flags & POINTER_NORAW) == 0) @@ -1183,6 +1164,45 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons return num_events; } +/** + * Generate a complete series of InternalEvents (filled into the EventList) + * representing pointer motion, or button presses. If the device is a slave + * device, also potentially generate a DeviceClassesChangedEvent to update + * the master device. + * + * events is not NULL-terminated; the return value is the number of events. + * The DDX is responsible for allocating the event structure in the first + * place via InitEventList() and GetMaximumEventsNum(), and for freeing it. + * + * In the generated events rootX/Y will be in absolute screen coords and + * the valuator information in the absolute or relative device coords. + * + * last.valuators[x] of the device is always in absolute device coords. + * last.valuators[x] of the master device is in absolute screen coords. + * + * master->last.valuators[x] for x > 2 is undefined. + */ +int +GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, + int buttons, int flags, const ValuatorMask *mask_in) +{ + CARD32 ms = GetTimeInMillis(); + int num_events = 0; + + /* refuse events from disabled devices */ + if (!pDev->enabled) + return 0; + + if (!miPointerGetScreen(pDev)) + return 0; + + events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, + &num_events); + num_events += fill_pointer_events(events, pDev, type, buttons, ms, flags, + mask_in); + return num_events; +} + /** * Generate internal events representing this proximity event and enqueue * them on the event queue. From 78d8d6dd7f31cb903d5c8baf64181795736f33ed Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Tue, 15 Feb 2011 14:23:25 +0000 Subject: [PATCH 24/41] Input: Add vertical and horizontal scroll axes To be used for smooth scrolling with future driver APIs, replacing Rel Vert Wheel and Rel Horiz Wheel axes, which have not been used in any open driver to date. Combined with double-granularity ValuatorMasks, these axes allow for fine-grained scroll data to be sent to clients. Future commits allow drivers to post these scroll axes to QueuePointerEvents/GetPointerEvents, which take care of emulating legacy scroll button events. Signed-off-by: Daniel Stone --- Xi/xiproperty.c | 5 +++++ include/xserver-properties.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c index fa0d81188..14f1491b6 100644 --- a/Xi/xiproperty.c +++ b/Xi/xiproperty.c @@ -52,11 +52,14 @@ static struct dev_properties } dev_properties[] = { {0, XI_PROP_ENABLED}, {0, XI_PROP_XTEST_DEVICE}, + {0, XATOM_FLOAT}, + {0, ACCEL_PROP_PROFILE_NUMBER}, {0, ACCEL_PROP_CONSTANT_DECELERATION}, {0, ACCEL_PROP_ADAPTIVE_DECELERATION}, {0, ACCEL_PROP_VELOCITY_SCALING}, + {0, AXIS_LABEL_PROP}, {0, AXIS_LABEL_PROP_REL_X}, {0, AXIS_LABEL_PROP_REL_Y}, @@ -68,6 +71,8 @@ static struct dev_properties {0, AXIS_LABEL_PROP_REL_DIAL}, {0, AXIS_LABEL_PROP_REL_WHEEL}, {0, AXIS_LABEL_PROP_REL_MISC}, + {0, AXIS_LABEL_PROP_REL_VSCROLL}, + {0, AXIS_LABEL_PROP_REL_HSCROLL}, {0, AXIS_LABEL_PROP_ABS_X}, {0, AXIS_LABEL_PROP_ABS_Y}, {0, AXIS_LABEL_PROP_ABS_Z}, diff --git a/include/xserver-properties.h b/include/xserver-properties.h index bf50042d0..18b54ba32 100644 --- a/include/xserver-properties.h +++ b/include/xserver-properties.h @@ -77,6 +77,8 @@ #define AXIS_LABEL_PROP_REL_DIAL "Rel Dial" #define AXIS_LABEL_PROP_REL_WHEEL "Rel Vert Wheel" #define AXIS_LABEL_PROP_REL_MISC "Rel Misc" +#define AXIS_LABEL_PROP_REL_VSCROLL "Rel Vert Scroll" +#define AXIS_LABEL_PROP_REL_HSCROLL "Rel Horiz Scroll" /* * Absolute axes From 5ac1f885f5c106b970835de36e13a9a7ea413df4 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Tue, 15 Feb 2011 19:44:53 +0000 Subject: [PATCH 25/41] Input: Add POINTER_EMULATED flag to GetPointerEvents POINTER_EMULATED merely sets XIPointerEmulated in the generated DeviceEvent. Signed-off-by: Daniel Stone Reviewed-by: Peter Hutterer --- dix/getevents.c | 6 ++++++ include/input.h | 1 + test/xi2/protocol-eventconvert.c | 18 +++++++++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/dix/getevents.c b/dix/getevents.c index 4eb1b3afe..45243df5c 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -58,6 +58,7 @@ #endif #include +#include #include #include #include "exglobals.h" @@ -1159,6 +1160,11 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type, event->root_x_frac = screenx - trunc(screenx); event->root_y_frac = screeny - trunc(screeny); + if (flags & POINTER_EMULATED) { + raw->flags = XIPointerEmulated; + event->flags = XIPointerEmulated; + } + set_valuators(pDev, event, &mask); return num_events; diff --git a/include/input.h b/include/input.h index 577f5d992..6ba1ab200 100644 --- a/include/input.h +++ b/include/input.h @@ -68,6 +68,7 @@ SOFTWARE. #define POINTER_ACCELERATE (1 << 3) #define POINTER_SCREEN (1 << 4) /* Data in screen coordinates */ #define POINTER_NORAW (1 << 5) /* Don't generate RawEvents */ +#define POINTER_EMULATED (1 << 6) /* Event was emulated from another event */ /*int constants for pointer acceleration schemes*/ #define PtrAccelNoOp 0 diff --git a/test/xi2/protocol-eventconvert.c b/test/xi2/protocol-eventconvert.c index d7a9ee420..bfa23b51f 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; + uint32_t flagmask = 0; if (swap) { @@ -62,7 +63,17 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out, 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)))); - assert(out->flags == 0); /* FIXME: we don't set the flags yet */ + + switch (in->type) { + case ET_RawMotion: + case ET_RawButtonPress: + case ET_RawButtonRelease: + flagmask = XIPointerEmulated; + break; + default: + flagmask = 0; + } + assert((out->flags & ~flagmask) == 0); ptr = (unsigned char*)&out[1]; bits_set = 0; @@ -304,6 +315,11 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out, assert(out->sourceid == in->sourceid); switch (in->type) { + case ET_ButtonPress: + case ET_Motion: + case ET_ButtonRelease: + flagmask = XIPointerEmulated; + break; case ET_KeyPress: flagmask = XIKeyRepeat; break; From 8d1a414cca51e7f8a93470c5aa2e998f5ca1bc9a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 23 Sep 2011 12:03:48 +1000 Subject: [PATCH 26/41] input: switch InitValuatorAxisStruct to return Bool Return errors instead of silently ignoring them. Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone --- Xi/exevents.c | 8 +++++--- hw/xfree86/common/xf86Xinput.c | 8 ++++---- hw/xfree86/common/xf86Xinput.h | 2 +- include/exevents.h | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 4dd9b85d5..8a3c25680 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1067,16 +1067,16 @@ InitProximityClassDeviceStruct(DeviceIntPtr dev) * * @see InitValuatorClassDeviceStruct */ -void +Bool InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, int resolution, int min_res, int max_res, int mode) { AxisInfoPtr ax; if (!dev || !dev->valuator || minval > maxval) - return; + return FALSE; if (axnum >= dev->valuator->numAxes) - return; + return FALSE; ax = dev->valuator->axes + axnum; @@ -1090,6 +1090,8 @@ InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int if (mode & OutOfProximity) dev->proximity->in_proximity = FALSE; + + return TRUE; } static void diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c index 9fbcba9d5..49b2fb2e8 100644 --- a/hw/xfree86/common/xf86Xinput.c +++ b/hw/xfree86/common/xf86Xinput.c @@ -1363,15 +1363,15 @@ xf86XInputSetScreen(InputInfoPtr pInfo, } -void +Bool xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, int resolution, int min_res, int max_res, int mode) { if (!dev || !dev->valuator) - return; + return FALSE; - InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res, - max_res, mode); + return InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res, + max_res, mode); } /* diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h index a4d9e58a5..189f7abaf 100644 --- a/hw/xfree86/common/xf86Xinput.h +++ b/hw/xfree86/common/xf86Xinput.h @@ -145,7 +145,7 @@ extern _X_EXPORT InputInfoPtr xf86FirstLocalDevice(void); extern _X_EXPORT int xf86ScaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min); extern _X_EXPORT void xf86XInputSetScreen(InputInfoPtr pInfo, int screen_number, int x, int y); extern _X_EXPORT void xf86ProcessCommonOptions(InputInfoPtr pInfo, XF86OptionPtr options); -extern _X_EXPORT void xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, +extern _X_EXPORT Bool xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, int resolution, int min_res, int max_res, int mode); extern _X_EXPORT void xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum); diff --git a/include/exevents.h b/include/exevents.h index 2b226986b..731f31eac 100644 --- a/include/exevents.h +++ b/include/exevents.h @@ -40,7 +40,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. extern _X_EXPORT int InitProximityClassDeviceStruct( DeviceIntPtr /* dev */); -extern _X_EXPORT void InitValuatorAxisStruct( +extern _X_EXPORT Bool InitValuatorAxisStruct( DeviceIntPtr /* dev */, int /* axnum */, Atom /* label */, From 635a1f50bc65512ec491fe71b9dfa8cf9118e2c2 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 23 Sep 2011 12:04:39 +1000 Subject: [PATCH 27/41] input: allow for max < min for relative axes on InitValuatorAxisStruct Relative axes are initialized with 0, -1 but so far this never had any effect as all users of this function (for relative axes) just set it to the defaults anyway. Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone --- Xi/exevents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 8a3c25680..a6455e6ac 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1073,7 +1073,7 @@ InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int { AxisInfoPtr ax; - if (!dev || !dev->valuator || minval > maxval) + if (!dev || !dev->valuator || (minval > maxval && mode == Absolute)) return FALSE; if (axnum >= dev->valuator->numAxes) return FALSE; From 512a9750c197437889ff7f26a8d2bd242e030745 Mon Sep 17 00:00:00 2001 From: Cyril Brulebois Date: Sun, 5 Jun 2011 03:03:47 +0200 Subject: [PATCH 28/41] xkb: Fix case checks for Latin 1. That one was missing _XkbKSLower: XK_ssharp: U+00DF LATIN SMALL LETTER SHARP S That one was getting _XkbKSLower for no reasons: XK_division: U+00F7 DIVISION SIGN For reference, XK_multiply was already excluded from the _XkbKSUpper check, it's no big surprise XK_division has to be excluded from the _XkbKSLower check. Reviewed-by: Daniel Stone Signed-off-by: Cyril Brulebois --- xkb/xkbfmisc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xkb/xkbfmisc.c b/xkb/xkbfmisc.c index 1ac9d8262..c36cc7bec 100644 --- a/xkb/xkbfmisc.c +++ b/xkb/xkbfmisc.c @@ -62,7 +62,7 @@ unsigned set,rtrn; rtrn|= _XkbKSUpper; } if (((ks>=XK_a)&&(ks<=XK_z))|| - ((ks>=XK_agrave)&&(ks<=XK_ydiaeresis))) { + ((ks>=XK_ssharp)&&(ks<=XK_ydiaeresis)&&(ks!=XK_division))) { rtrn|= _XkbKSLower; } break; From 0b56a7f0ad01d3a86cdd7a14d5e567a00a3553f6 Mon Sep 17 00:00:00 2001 From: Cyril Brulebois Date: Sun, 5 Jun 2011 03:12:44 +0200 Subject: [PATCH 29/41] xkb: Fix case checks for Latin 2. Those ones were getting _XkbKSLower for no reasons: XK_ogonek: U+02DB OGONEK XK_doubleacute: U+02DD DOUBLE ACUTE ACCENT Reviewed-by: Daniel Stone Signed-off-by: Cyril Brulebois --- xkb/xkbfmisc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xkb/xkbfmisc.c b/xkb/xkbfmisc.c index c36cc7bec..e0426718f 100644 --- a/xkb/xkbfmisc.c +++ b/xkb/xkbfmisc.c @@ -71,7 +71,7 @@ unsigned set,rtrn; ((ks>=XK_Racute)&&(ks<=XK_Tcedilla))) { rtrn|= _XkbKSUpper; } - if (((ks>=XK_aogonek)&&(ks<=XK_zabovedot)&&(ks!=XK_caron))|| + if (((ks>=XK_aogonek)&&(ks<=XK_zabovedot)&&(ks!=XK_ogonek)&&(ks!=XK_caron)&&(ks!=XK_doubleacute))|| ((ks>=XK_racute)&&(ks<=XK_tcedilla))) { rtrn|= _XkbKSLower; } From 537c5f631d1f8d526e63355b7d88cb1fb2793492 Mon Sep 17 00:00:00 2001 From: Cyril Brulebois Date: Sun, 5 Jun 2011 03:21:18 +0200 Subject: [PATCH 30/41] xkb: Fix case checks for Latin 4. That one was missing _XkbKSLower: XK_kra: U+0138 LATIN SMALL LETTER KRA Reviewed-by: Daniel Stone Signed-off-by: Cyril Brulebois --- xkb/xkbfmisc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xkb/xkbfmisc.c b/xkb/xkbfmisc.c index e0426718f..d8202b496 100644 --- a/xkb/xkbfmisc.c +++ b/xkb/xkbfmisc.c @@ -92,7 +92,8 @@ unsigned set,rtrn; ((ks>=XK_Amacron)&&(ks<=XK_Umacron))) { rtrn|= _XkbKSUpper; } - if (((ks>=XK_rcedilla)&&(ks<=XK_tslash))|| + if ((ks==XK_kra)|| + ((ks>=XK_rcedilla)&&(ks<=XK_tslash))|| (ks==XK_eng)|| ((ks>=XK_amacron)&&(ks<=XK_umacron))) { rtrn|= _XkbKSLower; From 016413dae947fe4e8e918f728c87354fa4928275 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 27 May 2011 11:40:56 +1000 Subject: [PATCH 31/41] dix: split client list retrieval out of DeliverEventToClients No functional change, but "other" was renamed to "clients". Signed-off-by: Peter Hutterer Reviewed-by: Jeremy Huddleston Reviewed-by: Daniel Stone --- dix/events.c | 58 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/dix/events.c b/dix/events.c index 3c7bd50cd..20754f0c5 100644 --- a/dix/events.c +++ b/dix/events.c @@ -2037,6 +2037,44 @@ DeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win, return EVENT_NOT_DELIVERED; } + +/** + * Get the list of clients that should be tried for event delivery on the + * given window. + * + * @return 1 if the client list should be traversed, zero if the event + * should be skipped. + */ +static Bool +GetClientsForDelivery(DeviceIntPtr dev, WindowPtr win, + xEvent *events, Mask filter, InputClients **clients) +{ + int rc = 0; + + if (core_get_type(events) != 0) + *clients = (InputClients *)wOtherClients(win); + else if (xi2_get_type(events) != 0) + { + OtherInputMasks *inputMasks = wOtherInputMasks(win); + /* Has any client selected for the event? */ + if (!GetWindowXI2Mask(dev, win, events)) + goto out; + *clients = inputMasks->inputClients; + } else { + OtherInputMasks *inputMasks = wOtherInputMasks(win); + /* Has any client selected for the event? */ + if (!inputMasks || + !(inputMasks->inputEvents[dev->id] & filter)) + goto out; + + *clients = inputMasks->inputClients; + } + + rc = 1; +out: + return rc; +} + /** * Deliver events to clients registered on the window. * @@ -2053,24 +2091,8 @@ DeliverEventToClients(DeviceIntPtr dev, WindowPtr win, xEvent *events, enum EventDeliveryState rc = EVENT_SKIP; InputClients *other; - if (core_get_type(events) != 0) - other = (InputClients *)wOtherClients(win); - else if (xi2_get_type(events) != 0) - { - OtherInputMasks *inputMasks = wOtherInputMasks(win); - /* Has any client selected for the event? */ - if (!GetWindowXI2Mask(dev, win, events)) - goto out; - other = inputMasks->inputClients; - } else { - OtherInputMasks *inputMasks = wOtherInputMasks(win); - /* Has any client selected for the event? */ - if (!inputMasks || - !(inputMasks->inputEvents[dev->id] & filter)) - goto out; - - other = inputMasks->inputClients; - } + if (!GetClientsForDelivery(dev, win, events, filter, &other)) + goto out; rc = EVENT_NOT_DELIVERED; From 5ea2fb389fce235366e9fce83d20abdc8874f4e2 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 27 May 2011 11:43:50 +1000 Subject: [PATCH 32/41] dix: rename DeliverEventsToClients to DeliverEventsToWindowMask To avoid confusion with a future patch and it better describes what this does anyway - delivering events to all clients that have the event mask on the window. Signed-off-by: Peter Hutterer Reviewed-by: Jeremy Huddleston Reviewed-by: Daniel Stone --- dix/events.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dix/events.c b/dix/events.c index 20754f0c5..66fbe9a47 100644 --- a/dix/events.c +++ b/dix/events.c @@ -2083,9 +2083,9 @@ out: * mask for this event. */ static enum EventDeliveryState -DeliverEventToClients(DeviceIntPtr dev, WindowPtr win, xEvent *events, - int count, Mask filter, GrabPtr grab, - ClientPtr *client_return, Mask *mask_return) +DeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events, + int count, Mask filter, GrabPtr grab, + ClientPtr *client_return, Mask *mask_return) { int attempt; enum EventDeliveryState rc = EVENT_SKIP; @@ -2192,8 +2192,8 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent { enum EventDeliveryState rc; - rc = DeliverEventToClients(pDev, pWin, pEvents, count, filter, grab, - &client, &deliveryMask); + rc = DeliverEventToWindowMask(pDev, pWin, pEvents, count, filter, + grab, &client, &deliveryMask); switch(rc) { From ac0850e86f22191091a1eb07237cae9de49ee00d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 27 May 2011 12:14:32 +1000 Subject: [PATCH 33/41] dix: split DeliverEventToWindowMask up a bit more. Move out the actual event delivery, it needs to be used from elsewhere. Signed-off-by: Peter Hutterer Reviewed-by: Jeremy Huddleston Reviewed-by: Daniel Stone --- dix/events.c | 52 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/dix/events.c b/dix/events.c index 66fbe9a47..9063c28f5 100644 --- a/dix/events.c +++ b/dix/events.c @@ -2076,35 +2076,27 @@ out: } /** - * Deliver events to clients registered on the window. - * - * @param client_return On successful delivery, set to the recipient. - * @param mask_return On successful delivery, set to the recipient's event - * mask for this event. + * Try delivery on each client in inputclients, provided the event mask + * accepts it and there is no interfering core grab.. */ static enum EventDeliveryState -DeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events, - int count, Mask filter, GrabPtr grab, - ClientPtr *client_return, Mask *mask_return) +DeliverEventToInputClients(DeviceIntPtr dev, InputClients *inputclients, + WindowPtr win, xEvent *events, + int count, Mask filter, GrabPtr grab, + ClientPtr *client_return, Mask *mask_return) { int attempt; - enum EventDeliveryState rc = EVENT_SKIP; - InputClients *other; + enum EventDeliveryState rc = EVENT_NOT_DELIVERED; - if (!GetClientsForDelivery(dev, win, events, filter, &other)) - goto out; - - rc = EVENT_NOT_DELIVERED; - - for (; other; other = other->next) + for (; inputclients; inputclients = inputclients->next) { Mask mask; - ClientPtr client = rClient(other); + ClientPtr client = rClient(inputclients); if (IsInterferingGrab(client, dev, events)) continue; - mask = GetEventMask(dev, events, other); + mask = GetEventMask(dev, events, inputclients); if (XaceHook(XACE_RECEIVE_ACCESS, client, win, events, count)) @@ -2125,11 +2117,33 @@ DeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events, } } -out: return rc; } +/** + * Deliver events to clients registered on the window. + * + * @param client_return On successful delivery, set to the recipient. + * @param mask_return On successful delivery, set to the recipient's event + * mask for this event. + */ +static enum EventDeliveryState +DeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events, + int count, Mask filter, GrabPtr grab, + ClientPtr *client_return, Mask *mask_return) +{ + InputClients *clients; + + if (!GetClientsForDelivery(dev, win, events, filter, &clients)) + return EVENT_SKIP; + + return DeliverEventToInputClients(dev, clients, win, events, count, filter, + grab, client_return, mask_return); + +} + + /** * Deliver events to a window. At this point, we do not yet know if the event * actually needs to be delivered. May activate a grab if the event is a From c48133f133c64d356a1208f185619bfdf7e9a5f2 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 27 May 2011 14:19:45 +1000 Subject: [PATCH 34/41] Xi: use temporary variable for filter. Signed-off-by: Peter Hutterer Reviewed-by: Jeremy Huddleston Reviewed-by: Daniel Stone --- Xi/exevents.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 3b0411d61..042ea69bb 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -886,6 +886,7 @@ ProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) else { /* deliver to all root windows */ xEvent *xi; int i; + int filter; i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi); if (i != Success) @@ -895,9 +896,11 @@ ProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) return; } + filter = GetEventFilter(device, xi); + for (i = 0; i < screenInfo.numScreens; i++) DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1, - GetEventFilter(device, xi), NULL); + filter, NullGrab); free(xi); } } From 54e05d80a122bac57920fce1704c0f57492b849c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 27 May 2011 14:21:39 +1000 Subject: [PATCH 35/41] dix: rename ProcessRawEvents to dix/events.c:DeliverRawEvent No functional changes, prep work for future changes. Signed-off-by: Peter Hutterer Reviewed-by: Cyril Brulebois Reviewed-by: Jeremy Huddleston Reviewed-by: Daniel Stone --- Xi/exevents.c | 31 +------------------------------ dix/events.c | 29 +++++++++++++++++++++++++++++ include/dix.h | 5 +++++ 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 042ea69bb..3e3c67b63 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -876,35 +876,6 @@ UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event) return DEFAULT; } -static void -ProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) -{ - GrabPtr grab = device->deviceGrab.grab; - - if (grab) - DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE); - else { /* deliver to all root windows */ - xEvent *xi; - int i; - int filter; - - i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi); - if (i != Success) - { - ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n", - __func__, device->name, i); - return; - } - - filter = GetEventFilter(device, xi); - - for (i = 0; i < screenInfo.numScreens; i++) - DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1, - filter, NullGrab); - free(xi); - } -} - /** * Main device event processing function. * Called from when processing the events from the event queue. @@ -932,7 +903,7 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) ev->any.type == ET_RawButtonRelease || ev->any.type == ET_RawMotion) { - ProcessRawEvent(&ev->raw_event, device); + DeliverRawEvent(&ev->raw_event, device); return; } diff --git a/dix/events.c b/dix/events.c index 9063c28f5..8a4c6b9ac 100644 --- a/dix/events.c +++ b/dix/events.c @@ -2243,6 +2243,35 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent return nondeliveries; } +void +DeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) +{ + GrabPtr grab = device->deviceGrab.grab; + + if (grab) + DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE); + else { /* deliver to all root windows */ + xEvent *xi; + int i; + int filter; + + i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi); + if (i != Success) + { + ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n", + __func__, device->name, i); + return; + } + + filter = GetEventFilter(device, xi); + + for (i = 0; i < screenInfo.numScreens; i++) + DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1, + filter, NullGrab); + free(xi); + } +} + /* If the event goes to dontClient, don't send it and return 0. if send works, return 1 or if send didn't work, return 2. Only works for core events. diff --git a/include/dix.h b/include/dix.h index 9a111e8a7..b1bf9ed82 100644 --- a/include/dix.h +++ b/include/dix.h @@ -387,6 +387,11 @@ extern _X_EXPORT int DeliverEventsToWindow( Mask /* filter */, GrabPtr /* grab */); +extern _X_EXPORT void DeliverRawEvent( + RawDeviceEvent* /* ev */, + DeviceIntPtr /* dev */ +); + extern int DeliverDeviceEvents( WindowPtr /* pWin */, InternalEvent* /* event */, From 16244fba001826190445302f56784f5de9c59c01 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 2 Jun 2011 13:50:13 +1000 Subject: [PATCH 36/41] Support (and require) XI 2.1 Signed-off-by: Peter Hutterer Reviewed-by: Jeremy Huddleston Reviewed-by: Daniel Stone --- configure.ac | 2 +- include/protocol-versions.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 22566c9ef..da33c1626 100644 --- a/configure.ac +++ b/configure.ac @@ -785,7 +785,7 @@ WINDOWSWMPROTO="windowswmproto" APPLEWMPROTO="applewmproto >= 1.4" dnl Core modules for most extensions, et al. -SDK_REQUIRED_MODULES="[xproto >= 7.0.17] [randrproto >= 1.2.99.3] [renderproto >= 0.11] [xextproto >= 7.1.99] [inputproto >= 1.9.99.902] [kbproto >= 1.0.3] fontsproto" +SDK_REQUIRED_MODULES="[xproto >= 7.0.17] [randrproto >= 1.2.99.3] [renderproto >= 0.11] [xextproto >= 7.1.99] [inputproto >= 2.0.99.1] [kbproto >= 1.0.3] fontsproto" # Make SDK_REQUIRED_MODULES available for inclusion in xorg-server.pc AC_SUBST(SDK_REQUIRED_MODULES) diff --git a/include/protocol-versions.h b/include/protocol-versions.h index 7b7a9f53c..832bcf756 100644 --- a/include/protocol-versions.h +++ b/include/protocol-versions.h @@ -127,7 +127,7 @@ /* X Input */ #define SERVER_XI_MAJOR_VERSION 2 -#define SERVER_XI_MINOR_VERSION 0 +#define SERVER_XI_MINOR_VERSION 1 /* XKB */ #define SERVER_XKB_MAJOR_VERSION 1 From b6b1f1b514bf14ddf6b265b8d4551f892ded0dd2 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 11 May 2011 13:56:08 +1000 Subject: [PATCH 37/41] input: deliver raw events unconditionally for XI 2.1 clients. Deliver raw events regardless whether there is a grab on or not for clients supporting 2.1 or later. Signed-off-by: Peter Hutterer Reviewed-by: Jeremy Huddleston Reviewed-by: Daniel Stone --- dix/events.c | 93 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 16 deletions(-) diff --git a/dix/events.c b/dix/events.c index 8a4c6b9ac..2112a47db 100644 --- a/dix/events.c +++ b/dix/events.c @@ -2243,35 +2243,96 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent return nondeliveries; } +/** + * Filter out raw events for XI 2.0 and XI 2.1 clients. + * + * If there is a grab on the device, 2.0 clients only get raw events if they + * have the grab. 2.1+ clients get raw events in all cases. + * + * @return TRUE if the event should be discarded, FALSE otherwise. + */ +static BOOL +FilterRawEvents(const ClientPtr client, const GrabPtr grab) +{ + XIClientPtr client_xi_version; + int cmp; + + /* device not grabbed -> don't filter */ + if (!grab) + return FALSE; + + client_xi_version = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey); + + cmp = version_compare(client_xi_version->major_version, + client_xi_version->minor_version, 2, 0); + /* XI 2.0: if device is grabbed, skip + XI 2.1: if device is grabbed by us, skip, we've already delivered */ + return (cmp == 0) ? TRUE : SameClient(grab, client); +} + +/** + * Deliver a raw event to the grab owner (if any) and to all root windows. + * + * Raw event delivery differs between XI 2.0 and XI 2.1. + * XI 2.0: events delivered to the grabbing client (if any) OR to all root + * windows + * XI 2.1: events delivered to all root windows, regardless of grabbing + * state. + */ void DeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) { GrabPtr grab = device->deviceGrab.grab; + xEvent *xi; + int i; + int filter; + + i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi); + if (i != Success) + { + ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n", + __func__, device->name, i); + return; + } if (grab) DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE); - else { /* deliver to all root windows */ - xEvent *xi; - int i; - int filter; - i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi); - if (i != Success) + filter = GetEventFilter(device, xi); + + for (i = 0; i < screenInfo.numScreens; i++) + { + WindowPtr root; + InputClients *inputclients; + + root = screenInfo.screens[i]->root; + if (!GetClientsForDelivery(device, root, xi, filter, &inputclients)) + continue; + + for (; inputclients; inputclients = inputclients->next) { - ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n", - __func__, device->name, i); - return; + ClientPtr c; /* unused */ + Mask m; /* unused */ + InputClients ic = *inputclients; + + /* Because we run through the list manually, copy the actual + * list, shorten the copy to only have one client and then pass + * that down to DeliverEventToInputClients. This way we avoid + * double events on XI 2.1 clients that have a grab on the + * device. + */ + ic.next = NULL; + + if (!FilterRawEvents(rClient(&ic), grab)) + DeliverEventToInputClients(device, &ic, root, xi, 1, + filter, NULL, &c, &m); } - - filter = GetEventFilter(device, xi); - - for (i = 0; i < screenInfo.numScreens; i++) - DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1, - filter, NullGrab); - free(xi); } + + free(xi); } + /* If the event goes to dontClient, don't send it and return 0. if send works, return 1 or if send didn't work, return 2. Only works for core events. From 52c9b59a9fed6abfeca775a7a04133cee18eac0b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 30 May 2011 09:47:06 +1000 Subject: [PATCH 38/41] dix: use 'rc' for return code in DeliverRawEvent Reported-by: Walter Harms Signed-off-by: Peter Hutterer Reviewed-by: Cyril Brulebois Reviewed-by: Jeremy Huddleston Reviewed-by: Daniel Stone --- dix/events.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dix/events.c b/dix/events.c index 2112a47db..6b74b1aa9 100644 --- a/dix/events.c +++ b/dix/events.c @@ -2284,14 +2284,14 @@ DeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) { GrabPtr grab = device->deviceGrab.grab; xEvent *xi; - int i; + int i, rc; int filter; - i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi); - if (i != Success) + rc = EventToXI2((InternalEvent*)ev, (xEvent**)&xi); + if (rc != Success) { ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n", - __func__, device->name, i); + __func__, device->name, rc); return; } From 3304bbff9b4ed63f1a47410a5320a136420ba2c6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 15 Feb 2011 18:49:58 +0000 Subject: [PATCH 39/41] Input: Add smooth-scrolling support to GetPointerEvents For scroll wheel support, we used to send buttons 4/5 and 6/7 for horizontal/vertical positive/negative scroll events. For touchpads, we really want more fine-grained scroll values. GetPointerEvents now accepts both old-school scroll button presses, and new-style scroll axis events, while emitting both types of events to support both old and new clients. This works with the new XIScrollClass to mark axes as scrolling axes. Drivers mark any valuators that send scroll events with SetScrollValuator. (Currently missing: the XIDeviceChangeEvent being sent when a driver changes a scroll axis at run-time. This can be added later.) Note: the SCROLL_TYPE enums are intentionally different values to the XI2 proto values to avoid copy/overlapping range bugs. Co-authored-by: Daniel Stone Signed-off-by: Peter Hutterer Reviewed-by: Peter Hutterer Reviewed-by: Daniel Stone --- Xi/exevents.c | 49 +++++++++ Xi/xiquerydevice.c | 73 ++++++++++++- Xi/xiquerydevice.h | 1 + dix/devices.c | 12 +++ dix/getevents.c | 170 +++++++++++++++++++++++++++++- include/exevents.h | 23 ++++ include/inputstr.h | 20 ++++ test/input.c | 57 ++++++++++ test/xi2/protocol-common.c | 63 ++++++++++- test/xi2/protocol-xiquerydevice.c | 49 ++++++++- 10 files changed, 506 insertions(+), 11 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index a6455e6ac..74a78ecf2 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1091,6 +1091,55 @@ InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int if (mode & OutOfProximity) dev->proximity->in_proximity = FALSE; + return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE); +} + +/** + * Set the given axis number as a scrolling valuator. + */ +Bool +SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type, double increment, int flags) +{ + AxisInfoPtr ax; + int *current_ax; + + if (!dev || !dev->valuator || axnum >= dev->valuator->numAxes) + return FALSE; + + switch (type) + { + case SCROLL_TYPE_VERTICAL: + current_ax = &dev->valuator->v_scroll_axis; + break; + case SCROLL_TYPE_HORIZONTAL: + current_ax = &dev->valuator->h_scroll_axis; + break; + case SCROLL_TYPE_NONE: + ax = &dev->valuator->axes[axnum]; + ax->scroll.type = type; + return TRUE; + default: + return FALSE; + } + + if (increment == 0.0) + return FALSE; + + if (*current_ax != -1 && axnum != *current_ax) + { + ax = &dev->valuator->axes[*current_ax]; + if (ax->scroll.type == type && + (flags & SCROLL_FLAG_PREFERRED) && (ax->scroll.flags & SCROLL_FLAG_PREFERRED)) + return FALSE; + } + *current_ax = axnum; + + ax = &dev->valuator->axes[axnum]; + ax->scroll.type = type; + ax->scroll.increment = increment; + ax->scroll.flags = flags; + /* FIXME: generate DeviceChanged Events */ + return TRUE; } diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c index 902eb918c..9961d1b6f 100644 --- a/Xi/xiquerydevice.c +++ b/Xi/xiquerydevice.c @@ -229,7 +229,16 @@ SizeDeviceClasses(DeviceIntPtr dev) } if (dev->valuator) - len += sizeof(xXIValuatorInfo) * dev->valuator->numAxes; + { + int i; + len += (sizeof(xXIValuatorInfo)) * dev->valuator->numAxes; + + for (i = 0; i < dev->valuator->numAxes; i++) { + if (dev->valuator->axes[i].scroll.type != SCROLL_TYPE_NONE) + len += sizeof(xXIScrollInfo); + } + } + return len; } @@ -369,6 +378,56 @@ SwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info) swaps(&info->sourceid); } +int +ListScrollInfo(DeviceIntPtr dev, xXIScrollInfo *info, int axisnumber) +{ + ValuatorClassPtr v = dev->valuator; + AxisInfoPtr axis = &v->axes[axisnumber]; + + if (axis->scroll.type == SCROLL_TYPE_NONE) + return 0; + + info->type = XIScrollClass; + info->length = sizeof(xXIScrollInfo)/4; + info->number = axisnumber; + switch(axis->scroll.type) + { + case SCROLL_TYPE_VERTICAL: + info->scroll_type = XIScrollTypeVertical; + break; + case SCROLL_TYPE_HORIZONTAL: + info->scroll_type = XIScrollTypeHorizontal; + break; + default: + ErrorF("[Xi] Unknown scroll type %d. This is a bug.\n", axis->scroll.type); + break; + } + info->increment.integral = (int)axis->scroll.increment; + info->increment.frac = (unsigned int)(axis->scroll.increment * (1UL << 16) * (1UL << 16)); + info->sourceid = v->sourceid; + + info->flags = 0; + + if (axis->scroll.flags & SCROLL_FLAG_DONT_EMULATE) + info->flags |= XIScrollFlagNoEmulation; + if (axis->scroll.flags & SCROLL_FLAG_PREFERRED) + info->flags |= XIScrollFlagPreferred; + + return info->length * 4; +} + +static void +SwapScrollInfo(DeviceIntPtr dev, xXIScrollInfo* info) +{ + swaps(&info->type); + swaps(&info->length); + swaps(&info->number); + swaps(&info->sourceid); + swaps(&info->scroll_type); + swapl(&info->increment.integral); + swapl(&info->increment.frac); +} + int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment) { DeviceIntPtr master = GetMaster(dev, MASTER_ATTACHED); @@ -458,6 +517,15 @@ ListDeviceClasses(ClientPtr client, DeviceIntPtr dev, total_len += len; } + for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++) + { + len = ListScrollInfo(dev, (xXIScrollInfo*)any, i); + if (len) + (*nclasses)++; + any += len; + total_len += len; + } + return total_len; } @@ -484,6 +552,9 @@ SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info) case XIValuatorClass: SwapValuatorInfo(dev, (xXIValuatorInfo*)any); break; + case XIScrollClass: + SwapScrollInfo(dev, (xXIScrollInfo*)any); + break; } any += len * 4; diff --git a/Xi/xiquerydevice.h b/Xi/xiquerydevice.h index 02f06591e..9db6aa293 100644 --- a/Xi/xiquerydevice.h +++ b/Xi/xiquerydevice.h @@ -44,4 +44,5 @@ int ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info, Bool reportState); int ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info); int ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info, int axisnumber, Bool reportState); +int ListScrollInfo(DeviceIntPtr dev, xXIScrollInfo* info, int axisnumber); #endif /* QUERYDEV_H */ diff --git a/dix/devices.c b/dix/devices.c index ab8a648a9..64557aaf1 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -260,6 +260,8 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) offsetof(DeviceIntRec, devPrivates), PRIVATE_DEVICE); if (!dev) return (DeviceIntPtr)NULL; + + dev->last.scroll = NULL; dev->id = devid; dev->public.processInputProc = ProcessOtherEvent; dev->public.realInputProc = ProcessOtherEvent; @@ -939,6 +941,7 @@ CloseDevice(DeviceIntPtr dev) free(dev->deviceGrab.sync.event); free(dev->config_info); /* Allocated in xf86ActivateDevice. */ + free(dev->last.scroll); dev->config_info = NULL; dixFreeObjectWithPrivates(dev, PRIVATE_DEVICE); } @@ -1277,10 +1280,19 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels, if (!valc) return FALSE; + dev->last.scroll = valuator_mask_new(numAxes); + if (!dev->last.scroll) + { + free(valc); + return FALSE; + } + valc->sourceid = dev->id; valc->motion = NULL; valc->first_motion = 0; valc->last_motion = 0; + valc->h_scroll_axis = -1; + valc->v_scroll_axis = -1; valc->numMotionEvents = numMotionEvents; valc->motionHintWindow = NullWindow; diff --git a/dix/getevents.c b/dix/getevents.c index 45243df5c..c42971592 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -2,6 +2,7 @@ * Copyright © 2006 Nokia Corporation * Copyright © 2006-2007 Daniel Stone * Copyright © 2008 Red Hat, Inc. + * Copyright © 2011 The Chromium Authors * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -603,8 +604,10 @@ GetMaximumEventsNum(void) { /* One raw event * One device event * One possible device changed event + * Lots of possible separate button scroll events (horiz + vert) + * Lots of possible separate raw button scroll events (horiz + vert) */ - return 3; + return 100; } @@ -1170,6 +1173,95 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type, return num_events; } +/** + * Generate events for each scroll axis that changed between before/after + * for the device. + * + * @param events The pointer to the event list to fill the events + * @param dev The device to generate the events for + * @param axis The axis number to generate events for + * @param mask State before this event in absolute coords + * @param[in,out] last Last scroll state posted in absolute coords (modified + * in-place) + * @param ms Current time in ms + * @param max_events Max number of events to be generated + * @return The number of events generated + */ +static int +emulate_scroll_button_events(InternalEvent *events, + DeviceIntPtr dev, + int axis, + const ValuatorMask *mask, + ValuatorMask *last, + CARD32 ms, + int max_events) +{ + AxisInfoPtr ax; + double delta; + double incr; + int num_events = 0; + double total; + int b; + + if (dev->valuator->axes[axis].scroll.type == SCROLL_TYPE_NONE) + return 0; + + if (!valuator_mask_isset(mask, axis)) + return 0; + + ax = &dev->valuator->axes[axis]; + incr = ax->scroll.increment; + + if (!valuator_mask_isset(last, axis)) + valuator_mask_set_double(last, axis, 0); + + delta = valuator_mask_get_double(mask, axis) - valuator_mask_get_double(last, axis); + total = delta; + b = (ax->scroll.type == SCROLL_TYPE_VERTICAL) ? 5 : 7; + + if ((incr > 0 && delta < 0) || + (incr < 0 && delta > 0)) + b--; /* we're scrolling up or left → button 4 or 6 */ + + while (fabs(delta) >= fabs(incr)) + { + int nev_tmp; + + if (delta > 0) + delta -= fabs(incr); + else if (delta < 0) + delta += fabs(incr); + + /* fill_pointer_events() generates four events: one normal and one raw + * event for button press and button release. + * We may get a bigger scroll delta than we can generate events + * for. In that case, we keep decreasing delta, but skip events. + */ + if (num_events + 4 < max_events) + { + nev_tmp = fill_pointer_events(events, dev, ButtonPress, b, ms, + POINTER_EMULATED, NULL); + events += nev_tmp; + num_events += nev_tmp; + nev_tmp = fill_pointer_events(events, dev, ButtonRelease, b, ms, + POINTER_EMULATED, NULL); + events += nev_tmp; + num_events += nev_tmp; + } + } + + /* We emulated, update last.scroll */ + if (total != delta) + { + total -= delta; + valuator_mask_set_double(last, axis, + valuator_mask_get_double(last, axis) + total); + } + + return num_events; +} + + /** * Generate a complete series of InternalEvents (filled into the EventList) * representing pointer motion, or button presses. If the device is a slave @@ -1193,7 +1285,12 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons, int flags, const ValuatorMask *mask_in) { CARD32 ms = GetTimeInMillis(); - int num_events = 0; + int num_events = 0, nev_tmp; + int h_scroll_axis = pDev->valuator->h_scroll_axis; + int v_scroll_axis = pDev->valuator->v_scroll_axis; + ValuatorMask mask; + ValuatorMask scroll; + int i; /* refuse events from disabled devices */ if (!pDev->enabled) @@ -1204,8 +1301,73 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); - num_events += fill_pointer_events(events, pDev, type, buttons, ms, flags, - mask_in); + + valuator_mask_copy(&mask, mask_in); + + /* Turn a scroll button press into a smooth-scrolling event if + * necessary. This only needs to cater for the XIScrollFlagPreferred + * axis (if more than one scrolling axis is present) */ + if (type == ButtonPress) + { + double val, adj; + int axis; + + switch (buttons) { + case 4: + adj = 1.0; + axis = v_scroll_axis; + break; + case 5: + adj = -1.0; + axis = v_scroll_axis; + break; + case 6: + adj = 1.0; + axis = h_scroll_axis; + break; + case 7: + adj = -1.0; + axis = h_scroll_axis; + break; + default: + adj = 0.0; + axis = -1; + break; + } + + if (adj != 0.0 && axis != -1) + { + adj *= pDev->valuator->axes[axis].scroll.increment; + val = valuator_mask_get_double(&mask, axis) + adj; + valuator_mask_set_double(&mask, axis, val); + type = MotionNotify; + buttons = 0; + } + } + + /* First fill out the original event set, with smooth-scrolling axes. */ + nev_tmp = fill_pointer_events(events, pDev, type, buttons, ms, flags, + &mask); + events += nev_tmp; + num_events += nev_tmp; + + valuator_mask_zero(&scroll); + + /* Now turn the smooth-scrolling axes back into emulated button presses + * for legacy clients, based on the integer delta between before and now */ + for (i = 0; i < valuator_mask_size(&mask); i++) { + if (!valuator_mask_isset(&mask, i)) + continue; + + valuator_mask_set_double(&scroll, i, pDev->last.valuators[i]); + + nev_tmp = emulate_scroll_button_events(events, pDev, i, &scroll, + pDev->last.scroll, ms, + GetMaximumEventsNum() - num_events); + events += nev_tmp; + num_events += nev_tmp; + } + return num_events; } diff --git a/include/exevents.h b/include/exevents.h index 731f31eac..4fe6c61a9 100644 --- a/include/exevents.h +++ b/include/exevents.h @@ -37,6 +37,22 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * Interface available to drivers * ***************************************************************/ +/** + * Scroll flags for ::SetScrollValuator. + */ +enum ScrollFlags { + SCROLL_FLAG_NONE = 0, + /** + * Do not emulate legacy button events for valuator events on this axis. + */ + SCROLL_FLAG_DONT_EMULATE = (1 << 1), + /** + * This axis is the preferred axis for valuator emulation for this axis' + * scroll type. + */ + SCROLL_FLAG_PREFERRED = (1 << 2) +}; + extern _X_EXPORT int InitProximityClassDeviceStruct( DeviceIntPtr /* dev */); @@ -51,6 +67,13 @@ extern _X_EXPORT Bool InitValuatorAxisStruct( int /* max_res */, int /* mode */); +extern _X_EXPORT Bool SetScrollValuator( + DeviceIntPtr /* dev */, + int /* axnum */, + enum ScrollType /* type */, + double /* increment */, + int /* flags */); + /* Input device properties */ extern _X_EXPORT void XIDeleteAllDeviceProperties( DeviceIntPtr /* device */ diff --git a/include/inputstr.h b/include/inputstr.h index c25f5c670..9d4108ef5 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -74,6 +74,16 @@ extern _X_EXPORT int CountBits(const uint8_t *mask, int len); #define XI2LASTEVENT 17 /* XI_RawMotion */ #define XI2MASKSIZE ((XI2LASTEVENT + 7)/8) /* no of bits for masks */ +/** + * Scroll types for ::SetScrollValuator and the scroll type in the + * ::ScrollInfoPtr. + */ +enum ScrollType { + SCROLL_TYPE_NONE = 0, /**< Not a scrolling valuator */ + SCROLL_TYPE_VERTICAL = 8, + SCROLL_TYPE_HORIZONTAL = 9, +}; + /** * This struct stores the core event mask for each client except the client * that created the window. @@ -252,6 +262,12 @@ typedef struct _KeyClassRec { struct _XkbSrvInfo *xkbInfo; } KeyClassRec, *KeyClassPtr; +typedef struct _ScrollInfo { + enum ScrollType type; + double increment; + int flags; +} ScrollInfo, *ScrollInfoPtr; + typedef struct _AxisInfo { int resolution; int min_resolution; @@ -260,6 +276,7 @@ typedef struct _AxisInfo { int max_value; Atom label; CARD8 mode; + ScrollInfo scroll; } AxisInfo, *AxisInfoPtr; typedef struct _ValuatorAccelerationRec { @@ -283,6 +300,8 @@ typedef struct _ValuatorClassRec { unsigned short numAxes; double *axisVal; /* always absolute, but device-coord system */ ValuatorAccelerationRec accelScheme; + int h_scroll_axis; /* horiz smooth-scrolling axis */ + int v_scroll_axis; /* vert smooth-scrolling axis */ } ValuatorClassRec; typedef struct _ButtonClassRec { @@ -524,6 +543,7 @@ typedef struct _DeviceIntRec { double valuators[MAX_VALUATORS]; int numValuators; DeviceIntPtr slave; + ValuatorMask *scroll; } last; /* Input device property handling. */ diff --git a/test/input.c b/test/input.c index 2501d59b7..afc4d4d99 100644 --- a/test/input.c +++ b/test/input.c @@ -52,6 +52,7 @@ static void dix_init_valuators(void) { DeviceIntRec dev; ValuatorClassPtr val; + AxisInfoPtr axis; const int num_axes = 2; int i; Atom atoms[MAX_VALUATORS] = { 0 }; @@ -78,6 +79,62 @@ static void dix_init_valuators(void) } assert(dev.last.numValuators == num_axes); + + /* invalid increment */ + assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_VERTICAL, 0.0, SCROLL_FLAG_NONE) == FALSE); + /* invalid type */ + assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_VERTICAL - 1, 1.0, SCROLL_FLAG_NONE) == FALSE); + assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_HORIZONTAL + 1, 1.0, SCROLL_FLAG_NONE) == FALSE); + /* invalid axisnum */ + assert(SetScrollValuator(&dev, 2, SCROLL_TYPE_HORIZONTAL, 1.0, SCROLL_FLAG_NONE) == FALSE); + + /* valid */ + assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_VERTICAL, 3.0, SCROLL_FLAG_NONE) == TRUE); + axis = &dev.valuator->axes[0]; + assert(axis->scroll.increment == 3.0); + assert(axis->scroll.type == SCROLL_TYPE_VERTICAL); + assert(axis->scroll.flags == 0); + + /* valid */ + assert(SetScrollValuator(&dev, 1, SCROLL_TYPE_HORIZONTAL, 2.0, SCROLL_FLAG_NONE) == TRUE); + axis = &dev.valuator->axes[1]; + assert(axis->scroll.increment == 2.0); + assert(axis->scroll.type == SCROLL_TYPE_HORIZONTAL); + assert(axis->scroll.flags == 0); + + /* can add another non-preffered axis */ + assert(SetScrollValuator(&dev, 1, SCROLL_TYPE_VERTICAL, 5.0, SCROLL_FLAG_NONE) == TRUE); + assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_HORIZONTAL, 5.0, SCROLL_FLAG_NONE) == TRUE); + + /* can overwrite with Preferred */ + assert(SetScrollValuator(&dev, 1, SCROLL_TYPE_VERTICAL, 5.5, SCROLL_FLAG_PREFERRED) == TRUE); + axis = &dev.valuator->axes[1]; + assert(axis->scroll.increment == 5.5); + assert(axis->scroll.type == SCROLL_TYPE_VERTICAL); + assert(axis->scroll.flags == SCROLL_FLAG_PREFERRED); + + assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_HORIZONTAL, 8.8, SCROLL_FLAG_PREFERRED) == TRUE); + axis = &dev.valuator->axes[0]; + assert(axis->scroll.increment == 8.8); + assert(axis->scroll.type == SCROLL_TYPE_HORIZONTAL); + assert(axis->scroll.flags == SCROLL_FLAG_PREFERRED); + + /* can overwrite as none */ + assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_NONE, 5.0, + SCROLL_FLAG_NONE) == TRUE); + axis = &dev.valuator->axes[0]; + assert(axis->scroll.type == SCROLL_TYPE_NONE); + + /* can overwrite axis with new settings */ + assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_VERTICAL, 5.0, SCROLL_FLAG_NONE) == TRUE); + axis = &dev.valuator->axes[0]; + assert(axis->scroll.type == SCROLL_TYPE_VERTICAL); + assert(axis->scroll.increment == 5.0); + assert(axis->scroll.flags == SCROLL_FLAG_NONE); + assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_VERTICAL, 3.0, SCROLL_FLAG_NONE) == TRUE); + assert(axis->scroll.type == SCROLL_TYPE_VERTICAL); + assert(axis->scroll.increment == 3.0); + assert(axis->scroll.flags == SCROLL_FLAG_NONE); } /* just check the known success cases, and that error cases set the client's diff --git a/test/xi2/protocol-common.c b/test/xi2/protocol-common.c index 423453358..56d6bd268 100644 --- a/test/xi2/protocol-common.c +++ b/test/xi2/protocol-common.c @@ -29,6 +29,8 @@ #include "extinit.h" /* for XInputExtensionInit */ #include "exglobals.h" #include "xkbsrv.h" /* for XkbInitPrivates */ +#include "xserver-properties.h" +#include #include "protocol-common.h" @@ -63,6 +65,65 @@ static void fake_init_sprite(DeviceIntPtr dev) sprite->physLimits.y2 = screen.height; } +/* This is essentially CorePointerProc with ScrollAxes added */ +static int +TestPointerProc(DeviceIntPtr pDev, int what) +{ +#define NBUTTONS 10 +#define NAXES 4 + BYTE map[NBUTTONS + 1]; + int i = 0; + Atom btn_labels[NBUTTONS] = {0}; + Atom axes_labels[NAXES] = {0}; + + switch (what) { + case DEVICE_INIT: + for (i = 1; i <= NBUTTONS; i++) + map[i] = i; + + btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); + btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); + btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); + btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); + btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); + btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); + btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); + /* don't know about the rest */ + + axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); + axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); + axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL); + axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL); + + if (!InitPointerDeviceStruct((DevicePtr)pDev, map, NBUTTONS, btn_labels, + (PtrCtrlProcPtr)NoopDDA, + GetMotionHistorySize(), NAXES, axes_labels)) + { + ErrorF("Could not initialize device '%s'. Out of memory.\n", + pDev->name); + return BadAlloc; + } + pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; + pDev->last.valuators[0] = pDev->valuator->axisVal[0]; + pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; + pDev->last.valuators[1] = pDev->valuator->axisVal[1]; + + SetScrollValuator(pDev, 2, SCROLL_TYPE_VERTICAL, 2.4, SCROLL_FLAG_NONE); + SetScrollValuator(pDev, 3, SCROLL_TYPE_HORIZONTAL, 3.5, SCROLL_FLAG_PREFERRED); + break; + + case DEVICE_CLOSE: + break; + + default: + break; + } + + return Success; + +#undef NBUTTONS +#undef NAXES +} /** * Create and init 2 master devices (VCP + VCK) and two slave devices, one * default mouse, one default keyboard. @@ -84,7 +145,7 @@ struct devices init_devices(void) EnableDevice(devices.vck, FALSE); AllocDevicePair(&client, "", &devices.mouse, &devices.kbd, - CorePointerProc, CoreKeyboardProc, FALSE); + TestPointerProc, CoreKeyboardProc, FALSE); ActivateDevice(devices.mouse, FALSE); ActivateDevice(devices.kbd, FALSE); EnableDevice(devices.mouse, FALSE); diff --git a/test/xi2/protocol-xiquerydevice.c b/test/xi2/protocol-xiquerydevice.c index 47eb5b14c..63d725f28 100644 --- a/test/xi2/protocol-xiquerydevice.c +++ b/test/xi2/protocol-xiquerydevice.c @@ -127,7 +127,7 @@ static void reply_XIQueryDevice_data(ClientPtr client, int len, char *data, void dev = devices.mouse; assert(info->use == XISlavePointer); assert(info->attachment == devices.vcp->id); - assert(info->num_classes == 3); /* 2 axes + button */ + assert(info->num_classes == 7); /* 4 axes + button + 2 scroll*/ break; case 5: /* keyboard */ dev = devices.kbd; @@ -183,11 +183,48 @@ static void reply_XIQueryDevice_data(ClientPtr client, int len, char *data, void } break; } - case 2: /* VCP and mouse have the same properties */ case 4: { assert(any->type == XIButtonClass || - any->type == XIValuatorClass); + any->type == XIValuatorClass || + any->type == XIScrollClass); + + if (any->type == XIScrollClass) + { + xXIScrollInfo *si = (xXIScrollInfo*)any; + + if (client->swapped) + { + swaps(&si->number); + swaps(&si->scroll_type); + swapl(&si->increment.integral); + swapl(&si->increment.frac); + } + assert(si->length == 6); + assert(si->number == 2 || si->number == 3); + if (si->number == 2) { + assert(si->scroll_type == XIScrollTypeVertical); + assert(!si->flags); + } + if (si->number == 3) { + assert(si->scroll_type == XIScrollTypeHorizontal); + assert(si->flags & XIScrollFlagPreferred); + assert(!(si->flags & ~XIScrollFlagPreferred)); + } + + assert(si->increment.integral == si->number); + /* FIXME: frac testing with float/FP issues? */ + assert(si->increment.frac > 0.3 * (1UL << 32)); + assert(si->increment.frac < 0.6 * (1UL << 32)); + } + + } + /* fall through */ + case 2: /* VCP and mouse have the same properties except for scroll */ + { + if (info->deviceid == 2 ) /* VCP */ + assert(any->type == XIButtonClass || + any->type == XIValuatorClass); if (any->type == XIButtonClass) { @@ -217,8 +254,10 @@ static void reply_XIQueryDevice_data(ClientPtr client, int len, char *data, void } assert(vi->length == 11); - assert(vi->number == 0 || - vi->number == 1); + assert(vi->number >= 0 && vi->number < 4); + if (info->deviceid == 2) /* VCP */ + assert(vi->number < 2); + assert(vi->mode == XIModeRelative); /* device was set up as relative, so standard * values here. */ From f32c827d513c44f07e1d0fbcc0c96cef18c9a4d9 Mon Sep 17 00:00:00 2001 From: Max Schwarz Date: Sun, 25 Sep 2011 20:44:26 +0200 Subject: [PATCH 40/41] Input: Fix frac calculation on [Raw]DeviceEvent conversion (1UL << 32) evaluates to 0 (at least here), so do the fraction calculation in two steps as in libXi. Fractions on xXIRawEvent were not multiplied at all, which also gave 0 as result. Signed-off-by: Max Schwarz Signed-off-by: Peter Hutterer --- dix/eventconvert.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dix/eventconvert.c b/dix/eventconvert.c index 9cc177efc..f9aafa5d1 100644 --- a/dix/eventconvert.c +++ b/dix/eventconvert.c @@ -635,7 +635,7 @@ eventToDeviceEvent(DeviceEvent *ev, xEvent **xi) SetBit(ptr, i); axisval->integral = trunc(ev->valuators.data[i]); axisval->frac = (ev->valuators.data[i] - axisval->integral) * - (1UL << 32); + (1 << 16) * (1 << 16); axisval++; } } @@ -679,10 +679,12 @@ eventToRawEvent(RawDeviceEvent *ev, xEvent **xi) { SetBit(ptr, i); axisval->integral = trunc(ev->valuators.data[i]); - axisval->frac = ev->valuators.data[i] - axisval->integral; + axisval->frac = (ev->valuators.data[i] - axisval->integral) * + (1 << 16) * (1 << 16); axisval_raw->integral = trunc(ev->valuators.data_raw[i]); - axisval_raw->frac = ev->valuators.data_raw[i] - - axisval_raw->integral; + axisval_raw->frac = + (ev->valuators.data_raw[i] - axisval_raw->integral) * + (1 << 16) * (1 << 16); axisval++; axisval_raw++; } From 524e5445c0b6df5247d4aac5368470bb89ef4080 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sat, 1 Oct 2011 08:43:52 -0700 Subject: [PATCH 41/41] Add #include "inpututils.h" to xkbAccessX.c for init_device_event Fixes Sun compiler warning: "xkbAccessX.c", line 128: warning: implicit function declaration: init_device_event Signed-off-by: Alan Coopersmith Reviewed-by: Jamey Sharp Signed-off-by: Peter Hutterer --- xkb/xkbAccessX.c | 1 + 1 file changed, 1 insertion(+) diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c index 4115ff27d..d246827ea 100644 --- a/xkb/xkbAccessX.c +++ b/xkb/xkbAccessX.c @@ -37,6 +37,7 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include "inputstr.h" #include "eventstr.h" +#include "inpututils.h" #include #if !defined(WIN32) #include