diff --git a/dix/getevents.c b/dix/getevents.c index 02f5366aa..7cc8d8cb5 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]; @@ -1386,7 +1408,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 */ diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c index c7994b03d..d6fef9cf3 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("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: %i dy: %i dir:%i diff: %i]\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,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("query: tracker too old (reset after %d, age is %d)\n", + vel->reset_time, age_ms); break; } @@ -626,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; @@ -647,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; @@ -660,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: %i dy: %i 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 @@ -693,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; } @@ -768,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. */ @@ -792,14 +795,14 @@ 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", - vel->velocity, res); + DebugAccelF("profile sample [%.2f] is %.3f\n", + vel->velocity, result); } return result; @@ -1050,11 +1053,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 && @@ -1113,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); @@ -1122,8 +1123,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); } } } 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 4820e9a77..7b5c9ee1c 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); @@ -345,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 810bd20ed..1ef17af2c 100644 --- a/test/signal-logging.c +++ b/test/signal-logging.c @@ -41,15 +41,22 @@ 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(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,125 +64,90 @@ 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_float_format_test(double number) { char string[21]; + char expected[21]; - FormatUInt64(test->number, string); - if(strncmp(string, test->string, 21) != 0) { + /* 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) +{ + char string[21]; + char expected[21]; + + 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; } 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) { 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])); + + 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" @@ -292,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);