From f53b2012f39085d866f267dda1442a48ace3c5a5 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 17 Jan 2013 16:19:51 +1000 Subject: [PATCH 1/8] test/signal-logging: simplify tests using sprintf Ever looked at your own code and thought 'WTF was I thinking?'. yeah, that. Instead of passing in the expected string just use sprintf to print the number for us and compare. In the end we're just trying to emulate printf behaviour anyway. Signed-off-by: Peter Hutterer Reviewed-by: Keith Packard --- test/signal-logging.c | 144 ++++++++++++------------------------------ 1 file changed, 42 insertions(+), 102 deletions(-) diff --git a/test/signal-logging.c b/test/signal-logging.c index 810bd20ed..127a28f26 100644 --- a/test/signal-logging.c +++ b/test/signal-logging.c @@ -42,14 +42,16 @@ struct signed_number_format_test { }; static Bool -check_signed_number_format_test(const struct signed_number_format_test *test) +check_signed_number_format_test(long int number) { char string[21]; + char expected[21]; - FormatInt64(test->number, string); - if(strncmp(string, test->string, 21) != 0) { - fprintf(stderr, "Failed to convert %jd to decimal string (%s vs %s)\n", - test->number, test->string, string); + sprintf(expected, "%ld", number); + FormatInt64(number, string); + if(strncmp(string, expected, 21) != 0) { + fprintf(stderr, "Failed to convert %jd to decimal string (expected %s but got %s)\n", + number, expected, string); return FALSE; } @@ -57,21 +59,25 @@ check_signed_number_format_test(const struct signed_number_format_test *test) } static Bool -check_number_format_test(const struct number_format_test *test) +check_number_format_test(long unsigned int number) { char string[21]; + char expected[21]; - FormatUInt64(test->number, string); - if(strncmp(string, test->string, 21) != 0) { + sprintf(expected, "%lu", number); + + FormatUInt64(number, string); + if(strncmp(string, expected, 21) != 0) { fprintf(stderr, "Failed to convert %ju to decimal string (%s vs %s)\n", - test->number, test->string, string); + number, expected, string); return FALSE; } - FormatUInt64Hex(test->number, string); - if(strncmp(string, test->hex_string, 17) != 0) { - fprintf(stderr, - "Failed to convert %ju to hexadecimal string (%s vs %s)\n", - test->number, test->hex_string, string); + + sprintf(expected, "%lx", number); + FormatUInt64Hex(number, string); + if(strncmp(string, expected, 17) != 0) { + fprintf(stderr, "Failed to convert %ju to hexadecimal string (%s vs %s)\n", + number, expected, string); return FALSE; } @@ -82,100 +88,34 @@ static void number_formatting(void) { int i; - struct number_format_test unsigned_tests[] = { - { /* Zero */ - 0, - "0", - "0", - }, - { /* Single digit number */ - 5, - "5", - "5", - }, - { /* Two digit decimal number */ - 12, - "12", - "c", - }, - { /* Two digit hex number */ - 37, - "37", - "25", - }, - { /* Large < 32 bit number */ - 0xC90B2, - "823474", - "c90b2", - }, - { /* Large > 32 bit number */ - 0x15D027BF211B37A, - "98237498237498234", - "15d027bf211b37a", - }, - { /* Maximum 64-bit number */ - 0xFFFFFFFFFFFFFFFF, - "18446744073709551615", - "ffffffffffffffff", - }, + long unsigned int unsigned_tests[] = { 0,/* Zero */ + 5, /* Single digit number */ + 12, /* Two digit decimal number */ + 37, /* Two digit hex number */ + 0xC90B2, /* Large < 32 bit number */ + 0x15D027BF211B37A, /* Large > 32 bit number */ + 0xFFFFFFFFFFFFFFFF, /* Maximum 64-bit number */ }; - struct signed_number_format_test signed_tests[] = { - { /* Zero */ - 0, - "0", - }, - { /* Single digit number */ - 5, - "5", - }, - { /* Two digit decimal number */ - 12, - "12", - }, - { /* Two digit hex number */ - 37, - "37", - }, - { /* Large < 32 bit number */ - 0xC90B2, - "823474", - }, - { /* Large > 32 bit number */ - 0x15D027BF211B37A, - "98237498237498234", - }, - { /* Maximum 64-bit signed number */ - 0x7FFFFFFFFFFFFFFF, - "9223372036854775807", - }, - { /* Single digit number */ - -1, - "-1", - }, - { /* Two digit decimal number */ - -12, - "-12", - }, - { /* Large < 32 bit number */ - -0xC90B2, - "-823474", - }, - { /* Large > 32 bit number */ - -0x15D027BF211B37A, - "-98237498237498234", - }, - { /* Maximum 64-bit number */ - -0x7FFFFFFFFFFFFFFF, - "-9223372036854775807", - }, - }; + long int signed_tests[] = { 0,/* Zero */ + 5, /* Single digit number */ + 12, /* Two digit decimal number */ + 37, /* Two digit hex number */ + 0xC90B2, /* Large < 32 bit number */ + 0x15D027BF211B37A, /* Large > 32 bit number */ + 0x7FFFFFFFFFFFFFFF, /* Maximum 64-bit signed number */ + -1, /* Single digit number */ + -12, /* Two digit decimal number */ + -0xC90B2, /* Large < 32 bit number */ + -0x15D027BF211B37A, /* Large > 32 bit number */ + -0x7FFFFFFFFFFFFFFF, /* Maximum 64-bit signed number */ + } ; for (i = 0; i < sizeof(unsigned_tests) / sizeof(unsigned_tests[0]); i++) - assert(check_number_format_test(unsigned_tests + i)); + assert(check_number_format_test(unsigned_tests[i])); for (i = 0; i < sizeof(unsigned_tests) / sizeof(signed_tests[0]); i++) - assert(check_signed_number_format_test(signed_tests + i)); + assert(check_signed_number_format_test(signed_tests[i])); } #pragma GCC diagnostic ignored "-Wformat-security" From 20def57632583aef095ca18792c7fce16d2d9004 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 10 Jan 2013 13:24:05 +1000 Subject: [PATCH 2/8] os: silently ignore length modifiers in pnprintf Until we have support for them, ignore any length modifiers so we don't need to update all callers. Signed-off-by: Peter Hutterer Reviewed-by: Keith Packard --- os/log.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/os/log.c b/os/log.c index 4820e9a77..213906420 100644 --- a/os/log.c +++ b/os/log.c @@ -298,7 +298,13 @@ pnprintf(char *string, size_t size, const char *f, va_list args) continue; } - switch (f[++f_idx]) { + f_idx++; + + /* silently swallow length modifiers */ + while (f_idx < f_len && ((f[f_idx] >= '0' && f[f_idx] <= '9') || f[f_idx] == '.')) + f_idx++; + + switch (f[f_idx]) { case 's': string_arg = va_arg(args, char*); p_len = strlen_sigsafe(string_arg); From cde7cbe9674e8a771f9a4e646c1772a46a8230fb Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 10 Jan 2013 13:20:12 +1000 Subject: [PATCH 3/8] os: add support for %f to pnprintf This is the lazy man's %f support. Print the decimal part of the number, then append a decimal point, then print the first two digits of the fractional part. So %f in sigsafe printing is really %.2f. No boundary checks in place here. Signed-off-by: Peter Hutterer Reviewed-by: Keith Packard --- include/misc.h | 1 + os/log.c | 9 +++++++ os/utils.c | 32 +++++++++++++++++++++++++ test/signal-logging.c | 56 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+) diff --git a/include/misc.h b/include/misc.h index 348717676..0c67f11fe 100644 --- a/include/misc.h +++ b/include/misc.h @@ -250,6 +250,7 @@ extern char **xstrtokenize(const char *str, const char *separators); extern void FormatInt64(int64_t num, char *string); extern void FormatUInt64(uint64_t num, char *string); extern void FormatUInt64Hex(uint64_t num, char *string); +extern void FormatDouble(double dbl, char *string); /** * Compare the two version numbers comprising of major.minor. diff --git a/os/log.c b/os/log.c index 213906420..7b5c9ee1c 100644 --- a/os/log.c +++ b/os/log.c @@ -351,7 +351,16 @@ pnprintf(char *string, size_t size, const char *f, va_list args) for (i = 0; i < p_len && s_idx < size - 1; i++) string[s_idx++] = number[i]; break; + case 'f': + { + double d = va_arg(args, double); + FormatDouble(d, number); + p_len = strlen_sigsafe(number); + for (i = 0; i < p_len && s_idx < size - 1; i++) + string[s_idx++] = number[i]; + } + break; default: va_arg(args, char*); string[s_idx++] = '%'; diff --git a/os/utils.c b/os/utils.c index e396ba4b5..3ba6499c4 100644 --- a/os/utils.c +++ b/os/utils.c @@ -1990,6 +1990,38 @@ FormatUInt64(uint64_t num, char *string) string[len] = '\0'; } +/** + * Format a double number as %.2f. + */ +void +FormatDouble(double dbl, char *string) +{ + int slen = 0; + uint64_t frac; + + frac = (dbl > 0 ? dbl : -dbl) * 100.0; + frac %= 100; + + /* write decimal part to string */ + if (dbl < 0 && dbl > -1) + string[slen++] = '-'; + FormatInt64((int64_t)dbl, &string[slen]); + + while(string[slen] != '\0') + slen++; + + /* append fractional part, but only if we have enough characters. We + * expect string to be 21 chars (incl trailing \0) */ + if (slen <= 17) { + string[slen++] = '.'; + if (frac < 10) + string[slen++] = '0'; + + FormatUInt64(frac, &string[slen]); + } +} + + /* Format a number into a hexadecimal string in a signal safe manner. The string * should be at least 17 characters in order to handle all uint64_t values. */ void diff --git a/test/signal-logging.c b/test/signal-logging.c index 127a28f26..1ef17af2c 100644 --- a/test/signal-logging.c +++ b/test/signal-logging.c @@ -41,6 +41,11 @@ struct signed_number_format_test { char string[21]; }; +struct float_number_format_test { + double number; + char string[21]; +}; + static Bool check_signed_number_format_test(long int number) { @@ -58,6 +63,25 @@ check_signed_number_format_test(long int number) return TRUE; } +static Bool +check_float_format_test(double number) +{ + char string[21]; + char expected[21]; + + /* we currently always print float as .2f */ + sprintf(expected, "%.2f", number); + + FormatDouble(number, string); + if(strncmp(string, expected, 21) != 0) { + fprintf(stderr, "Failed to convert %f to string (%s vs %s)\n", + number, expected, string); + return FALSE; + } + + return TRUE; +} + static Bool check_number_format_test(long unsigned int number) { @@ -84,6 +108,11 @@ check_number_format_test(long unsigned int number) return TRUE; } +/* FIXME: max range stuff */ +double float_tests[] = { 0, 5, 0.1, 0.01, 5.2342, 10.2301, + -1, -2.00, -0.6023, -1203.30 + }; + static void number_formatting(void) { @@ -116,6 +145,9 @@ number_formatting(void) for (i = 0; i < sizeof(unsigned_tests) / sizeof(signed_tests[0]); i++) assert(check_signed_number_format_test(signed_tests[i])); + + for (i = 0; i < sizeof(float_tests) / sizeof(float_tests[0]); i++) + assert(check_float_format_test(float_tests[i])); } #pragma GCC diagnostic ignored "-Wformat-security" @@ -232,6 +264,30 @@ static void logging_format(void) ptr <<= 1; } while(ptr); + + for (i = 0; i < sizeof(float_tests)/sizeof(float_tests[0]); i++) { + double d = float_tests[i]; + char expected[30]; + sprintf(expected, "(EE) %.2f\n", d); + LogMessageVerbSigSafe(X_ERROR, -1, "%f\n", d); + read_log_msg(logmsg); + assert(strcmp(logmsg, expected) == 0); + + /* test for length modifiers, we just ignore them atm */ + LogMessageVerbSigSafe(X_ERROR, -1, "%.3f\n", d); + read_log_msg(logmsg); + assert(strcmp(logmsg, expected) == 0); + + LogMessageVerbSigSafe(X_ERROR, -1, "%3f\n", d); + read_log_msg(logmsg); + assert(strcmp(logmsg, expected) == 0); + + LogMessageVerbSigSafe(X_ERROR, -1, "%.0f\n", d); + read_log_msg(logmsg); + assert(strcmp(logmsg, expected) == 0); + } + + LogClose(EXIT_NO_ERROR); unlink(log_file_path); From 95125a7c0cbbbae40216a0497acdd863ddc645ed Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 10 Jan 2013 13:19:27 +1000 Subject: [PATCH 4/8] dix: fix ptraccel debugging printfs This is mostly sigsafe code, so use sigsave printf. And update some fields to double that used to be int. Signed-off-by: Peter Hutterer Reviewed-by: Keith Packard --- dix/ptrveloc.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c index c7994b03d..b95f194cb 100644 --- a/dix/ptrveloc.c +++ b/dix/ptrveloc.c @@ -77,7 +77,7 @@ DeletePredictableAccelerationProperties(DeviceIntPtr, /*#define PTRACCEL_DEBUGGING*/ #ifdef PTRACCEL_DEBUGGING -#define DebugAccelF ErrorF +#define DebugAccelF ErrorFSigSafe #else #define DebugAccelF(...) /* */ #endif @@ -566,7 +566,7 @@ FeedTrackers(DeviceVelocityPtr vel, double dx, double dy, int cur_t) 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", + DebugAccelF("(dix prtacc) motion [dx: %f dy: %f dir:%d diff: %d]\n", dx, dy, vel->tracker[n].dir, cur_t - vel->tracker[vel->cur_tracker].time); vel->cur_tracker = n; @@ -667,7 +667,7 @@ QueryTrackers(DeviceVelocityPtr vel, int cur_t) #ifdef PTRACCEL_DEBUGGING MotionTracker *tracker = TRACKER(vel, used_offset); - DebugAccelF("(dix prtacc) result: offset %i [dx: %i dy: %i diff: %i]\n", + DebugAccelF("(dix prtacc) result: offset %i [dx: %f dy: %f diff: %i]\n", used_offset, tracker->dx, tracker->dy, cur_t - tracker->time); #endif @@ -799,7 +799,7 @@ ComputeAcceleration(DeviceIntPtr dev, result = BasicComputeAcceleration(dev, vel, vel->velocity, threshold, acc); DebugAccelF("(dix ptracc) profile sample [%.2f] is %.3f\n", - vel->velocity, res); + vel->velocity, result); } return result; @@ -1122,8 +1122,7 @@ acceleratePointerPredictable(DeviceIntPtr dev, ValuatorMask *val, CARD32 evtime) 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); + DebugAccelF("delta x:%.3f y:%.3f\n", mult * dx, mult * dy); } } } From a0c38ea6cbad61edcfefff0e5dd6330edb706f13 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 11 Jan 2013 08:49:15 +1000 Subject: [PATCH 5/8] dix: add some more info to a ptraccel debug msg Signed-off-by: Peter Hutterer Reviewed-by: Keith Packard --- dix/ptrveloc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c index b95f194cb..6994bd524 100644 --- a/dix/ptrveloc.c +++ b/dix/ptrveloc.c @@ -614,7 +614,8 @@ QueryTrackers(DeviceVelocityPtr vel, int cur_t) /* bail out if data is too old and protect from overrun */ if (age_ms >= vel->reset_time || age_ms < 0) { - DebugAccelF("(dix prtacc) query: tracker too old\n"); + DebugAccelF("(dix prtacc) query: tracker too old (reset after %d, age is %d)\n", + vel->reset_time, age_ms); break; } From 0d7d79406011169ad95e23c6e937f6d15a5ec3cc Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 11 Jan 2013 08:52:08 +1000 Subject: [PATCH 6/8] dix: use BUG_RETURN_VAL for an error message Signed-off-by: Peter Hutterer Reviewed-by: Keith Packard --- dix/ptrveloc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c index 6994bd524..b6d2daefe 100644 --- a/dix/ptrveloc.c +++ b/dix/ptrveloc.c @@ -1051,11 +1051,8 @@ SetDeviceSpecificAccelerationProfile(DeviceVelocityPtr vel, DeviceVelocityPtr GetDevicePredictableAccelData(DeviceIntPtr dev) { - /*sanity check */ - if (!dev) { - ErrorF("[dix] accel: DeviceIntPtr was NULL"); - return NULL; - } + BUG_RETURN_VAL(!dev, NULL); + if (dev->valuator && dev->valuator->accelScheme.AccelSchemeProc == acceleratePointerPredictable && From a6ba2b79ae8ad0fdee3f208d5e030b012df48785 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 11 Jan 2013 08:53:24 +1000 Subject: [PATCH 7/8] dix: unify prefix for ptraccel debugging in DebugAccelF macro If we're already using our own custom macro, might as well use it properly. Signed-off-by: Peter Hutterer Reviewed-by: Keith Packard --- dix/ptrveloc.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c index b6d2daefe..d6fef9cf3 100644 --- a/dix/ptrveloc.c +++ b/dix/ptrveloc.c @@ -77,7 +77,7 @@ DeletePredictableAccelerationProperties(DeviceIntPtr, /*#define PTRACCEL_DEBUGGING*/ #ifdef PTRACCEL_DEBUGGING -#define DebugAccelF ErrorFSigSafe +#define DebugAccelF(...) ErrorFSigSafe("dix/ptraccel: " __VA_ARGS__) #else #define DebugAccelF(...) /* */ #endif @@ -421,7 +421,7 @@ void InitTrackers(DeviceVelocityPtr vel, int ntracker) { if (ntracker < 1) { - ErrorF("(dix ptracc) invalid number of trackers\n"); + ErrorF("invalid number of trackers\n"); return; } free(vel->tracker); @@ -566,7 +566,7 @@ FeedTrackers(DeviceVelocityPtr vel, double dx, double dy, int cur_t) vel->tracker[n].dy = 0.0; vel->tracker[n].time = cur_t; vel->tracker[n].dir = GetDirection(dx, dy); - DebugAccelF("(dix prtacc) motion [dx: %f dy: %f dir:%d diff: %d]\n", + DebugAccelF("motion [dx: %f dy: %f dir:%d diff: %d]\n", dx, dy, vel->tracker[n].dir, cur_t - vel->tracker[vel->cur_tracker].time); vel->cur_tracker = n; @@ -614,7 +614,7 @@ QueryTrackers(DeviceVelocityPtr vel, int cur_t) /* bail out if data is too old and protect from overrun */ if (age_ms >= vel->reset_time || age_ms < 0) { - DebugAccelF("(dix prtacc) query: tracker too old (reset after %d, age is %d)\n", + DebugAccelF("query: tracker too old (reset after %d, age is %d)\n", vel->reset_time, age_ms); break; } @@ -627,7 +627,7 @@ QueryTrackers(DeviceVelocityPtr vel, int cur_t) */ dir &= tracker->dir; if (dir == 0) { /* we've changed octant of movement (e.g. NE → NW) */ - DebugAccelF("(dix prtacc) query: no longer linear\n"); + DebugAccelF("query: no longer linear\n"); /* instead of breaking it we might also inspect the partition after, * but actual improvement with this is probably rare. */ break; @@ -648,7 +648,7 @@ QueryTrackers(DeviceVelocityPtr vel, int cur_t) velocity_diff / (initial_velocity + tracker_velocity) >= vel->max_rel_diff) { /* we're not in range, quit - it won't get better. */ - DebugAccelF("(dix prtacc) query: tracker too different:" + DebugAccelF("query: tracker too different:" " old %2.2f initial %2.2f diff: %2.2f\n", tracker_velocity, initial_velocity, velocity_diff); break; @@ -661,14 +661,14 @@ QueryTrackers(DeviceVelocityPtr vel, int cur_t) } } if (offset == vel->num_tracker) { - DebugAccelF("(dix prtacc) query: last tracker in effect\n"); + DebugAccelF("query: last tracker in effect\n"); used_offset = vel->num_tracker - 1; } if (used_offset >= 0) { #ifdef PTRACCEL_DEBUGGING MotionTracker *tracker = TRACKER(vel, used_offset); - DebugAccelF("(dix prtacc) result: offset %i [dx: %f dy: %f diff: %i]\n", + DebugAccelF("result: offset %i [dx: %f dy: %f diff: %i]\n", used_offset, tracker->dx, tracker->dy, cur_t - tracker->time); #endif @@ -694,6 +694,8 @@ ProcessVelocityData2D(DeviceVelocityPtr vel, double dx, double dy, int time) velocity = QueryTrackers(vel, time); + DebugAccelF("velocity is %f\n", velocity); + vel->velocity = velocity; return velocity == 0; } @@ -769,7 +771,7 @@ ComputeAcceleration(DeviceIntPtr dev, double result; if (vel->velocity <= 0) { - DebugAccelF("(dix ptracc) profile skipped\n"); + DebugAccelF("profile skipped\n"); /* * If we have no idea about device velocity, don't pretend it. */ @@ -793,13 +795,13 @@ ComputeAcceleration(DeviceIntPtr dev, threshold, acc); result /= 6.0f; - DebugAccelF("(dix ptracc) profile average [%.2f ... %.2f] is %.3f\n", + DebugAccelF("profile average [%.2f ... %.2f] is %.3f\n", vel->velocity, vel->last_velocity, result); } else { result = BasicComputeAcceleration(dev, vel, vel->velocity, threshold, acc); - DebugAccelF("(dix ptracc) profile sample [%.2f] is %.3f\n", + DebugAccelF("profile sample [%.2f] is %.3f\n", vel->velocity, result); } @@ -1111,6 +1113,7 @@ acceleratePointerPredictable(DeviceIntPtr dev, ValuatorMask *val, CARD32 evtime) (double) dev->ptrfeed->ctrl.num / (double) dev->ptrfeed->ctrl.den); + DebugAccelF("mult is %f\n", mult); if (mult != 1.0f || velocitydata->const_acceleration != 1.0f) { if (mult > 1.0f && soften) ApplySoftening(velocitydata, &dx, &dy); From 61a99aff9d33728a0b67920254d2d4d79f80cf39 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 11 Jan 2013 14:22:07 +1000 Subject: [PATCH 8/8] dix: pre-scale relative events from abs devices to desktop ratio (#31636) Absolute devices may send relative events depending on the mode (synaptics by default, wacom per option). The relative events are added to the previous position, converted into device coordinates and then scaled into desktop coordinates for pointer movement. Because the device range must be mapped into the desktop coordinate range, this results in uneven scaling depending dimensions, e.g. on a setup with width == 2 * height, a relative movement of 10/10 in device coordinates results in a cursor movement of 20/10 (+ acceleration) Other commonly user-visible results: * the touchpad changing acceleration once an external monitor as added. * drawing a circle on a wacom tablet in relative mode gives an ellipsis in the same ratio as the desktop dimensions. Solution: pre-scale the incoming relative x/y coordinates by width/height ratio of the total desktop size. Then add them to the previous coordinates and scale back with the previous mapping, which will undo the pre-scaling and give us the right movement. X.Org Bug 31636 Signed-off-by: Peter Hutterer Reviewed-by: Keith Packard --- dix/getevents.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index a1e193815..510060732 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -776,11 +776,33 @@ add_to_scroll_valuator(DeviceIntPtr dev, ValuatorMask *mask, int valuator, doubl * @param[in,out] mask Valuator data for this event, modified in-place. */ static void -moveRelative(DeviceIntPtr dev, ValuatorMask *mask) +moveRelative(DeviceIntPtr dev, int flags, ValuatorMask *mask) { int i; Bool clip_xy = IsMaster(dev) || !IsFloating(dev); + /* for abs devices in relative mode, we've just scaled wrong, since we + mapped the device's shape into the screen shape. Undo this. */ + if ((flags & POINTER_ABSOLUTE) == 0 && dev->valuator && + dev->valuator->axes[0].min_value < dev->valuator->axes[0].max_value) { + + double ratio = 1.0 * screenInfo.width/screenInfo.height; + + if (ratio > 1.0) { + double y; + if (valuator_mask_fetch_double(mask, 1, &y)) { + y *= ratio; + valuator_mask_set_double(mask, 1, y); + } + } else { + double x; + if (valuator_mask_fetch_double(mask, 0, &x)) { + x *= ratio; + valuator_mask_set_double(mask, 0, x); + } + } + } + /* calc other axes, clip, drop back into valuators */ for (i = 0; i < valuator_mask_size(mask); i++) { double val = dev->last.valuators[i]; @@ -1380,7 +1402,7 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type, if ((flags & POINTER_NORAW) == 0) set_raw_valuators(raw, &mask, raw->valuators.data); - moveRelative(pDev, &mask); + moveRelative(pDev, flags, &mask); } /* valuators are in device coordinate system in absolute coordinates */