Index: ApplePS2SynapticsTouchPad.cpp =================================================================== --- ApplePS2SynapticsTouchPad.cpp (revision 135) +++ ApplePS2SynapticsTouchPad.cpp (working copy) @@ -495,7 +495,18 @@ UInt8 prevEvent = _event; UInt8 numFingers; uint32_t currentTime, second; + + // the values we need to properly calculate averages - required for jump prevention. + SInt32 xavg, yavg, xsensitivity, ysensitivity, sensitivity = 0; + // these are related to low-speed jitter on the trackpad. They could be + // tunable, but these are pretty solid defaults and they cancel out + // the jitters. + UInt32 low_speed_threshold = 20; + UInt8 squelch_level = 3; + UInt8 min_movement = 2; + + clock_get_system_microtime(&second, ¤tTime); @@ -518,22 +529,133 @@ SInt32 dx = absX - _prevX; SInt32 dy = absY - _prevY; // Y is negative for ps2 (according to synaptics) - dy /= _scaleFactor; + + // Begin JayK modifications - // Scale dx and dy bassed on the type of movement. This does not need to happen after event calculation because IF the event changes, dx and dy are reset to 0 - if((_event & (SCROLLING | VERTICAL_SCROLLING | HORIZONTAL_SCROLLING)) == 0) { - dx *= _prefTrackSpeed; - dy *= _prefTrackSpeed; - } else { - dx = (dx << 1) * _prefScrollSpeed; - dy *= _prefScrollSpeed; + /* + IOLog("abs: %d,%d,\tdiff: %d,%d, avg: %d,%d\n", absX, absY, dx, dy, _xaverage,_yaverage); + if (ABS(dx) > 550 || ABS(dy) > 550) { + IOLog("Over Max Jump Threshold\n"); + }*/ + + // Jump prevention code - by Jay Kuri (jayk@cpan.org) + // + // If distance spikes, the trackpad thinks we are zooming across the pad. + // This is probably NOT what we want. So if we get a change in any direction + // higher than 550 and it is significantly faster acceleration than our + // previous average, we kill the position and pretend like we've been + // here all along. This smooths out our crazy pointer jumps. + + if ((ABS(dx) > 550 || ABS(dy) > 550) && + ((ABS(dx - _xaverage) > 250) || + (ABS(dy - _yaverage) > 250))) { + + //IOLog("ApplePS2Trackpad: Jump detected, squashing. old: %d,%d \tnew: %d,%d\n",_prevX,_prevY, absX,absY); + + _prevX = absX; + _prevY = absY; + _xaverage = dx; + _yaverage = dy; + dx = 0; + dy = 0; } + // Compute averages of x and y movement. This helps us figure out + // if we just accelerated off the chart which is how we detect the trackpad jump + if (_xaverage == 0) { + _xaverage = dx; + } + if (_yaverage == 0) { + _yaverage = dy; + } + + xavg = _xaverage; + yavg = _yaverage; + + _xaverage = (xavg + dx) /2; + _yaverage = (yavg + dy) /2; + + xsensitivity = ABS(_xaverage - xavg); - // Handel Acceleration - if(ABS(dx) < ACCELERATION_TABLE_SIZE) ABS(dx) == dx ? dx = accelerationTable[ABS(dx)] : dx = -1 * accelerationTable[ABS(dx)]; - if(ABS(dy) < ACCELERATION_TABLE_SIZE) ABS(dy) == dy ? dy = accelerationTable[ABS(dy)] : dy = -1 * accelerationTable[ABS(dy)]; + ysensitivity = ABS(_yaverage - yavg); + + /* + * The sensitivity level is higher the faster the finger + * is moving. It also tends to be higher in the middle + * of a touchpad motion than on either end + * + * Note - sensitivity gets to 0 when moving slowly - so + * we add 1 to it to give it a meaningful value in that case. + */ + sensitivity = (xsensitivity & ysensitivity)+1; + + /* + * If either our x or y change is greater than our + * hi/low speed threshold - we do the high-speed + * absolute to relative calculation otherwise we + * do the low-speed calculation. + */ + if (ABS(dx) > ABS(low_speed_threshold) || + ABS(dy) > ABS(low_speed_threshold)) { + + dy /= _scaleFactor; + + // Scale dx and dy bassed on the type of movement. This does not need to happen after event calculation because IF the event changes, dx and dy are reset to 0 + if((_event & (SCROLLING | VERTICAL_SCROLLING | HORIZONTAL_SCROLLING)) == 0) { + dx *= _prefTrackSpeed; + dy *= _prefTrackSpeed; + } else { + dx = 2 * dx * _prefScrollSpeed; + dy = 2 * dy * _prefScrollSpeed; + } + if(ABS(dx) < ACCELERATION_TABLE_SIZE) ABS(dx) == dx ? dx = accelerationTable[ABS(dx)] : dx = -1 * accelerationTable[ABS(dx)]; + if(ABS(dy) < ACCELERATION_TABLE_SIZE) ABS(dy) == dy ? dy = accelerationTable[ABS(dy)] : dy = -1 * accelerationTable[ABS(dy)]; + + } else { + /* + * This is the low speed calculation. + * We simply check to see if our movement + * is more than our minimum movement threshold + * and if it is - set the movement to 1 in the + * correct direction. + * NOTE - Normally this would result in pointer + * movement that was WAY too fast. This works + * due to the movement squelch we do later. + */ + if (dx < -min_movement) + dx = -1; + else if (dx > min_movement) + dx = 1; + else + dx = 0; + if (dy < -min_movement) + dy = -1; + else if (dy > min_movement) + dy = 1; + else + dy = 0; + } + /* + * ok - the squelch process. Take our sensitivity value + * and add it to the current squelch value - if squelch + * is less than our squelch threshold we kill the movement, + * otherwise we reset squelch and pass the movement through. + * Since squelch is cumulative - when mouse movement is slow + * (around sensitivity 1) the net result is that only + * 1 out of every squelch_level packets is + * delivered, effectively slowing down the movement. + */ + _squelch += sensitivity; + if (_squelch < squelch_level) { + dx = 0; + dy = 0; + } else { + _squelch = 0; + } + + // End jayk jump modifications + _streamdx += dx; _streamdy += dy; Index: ApplePS2SynapticsTouchPad.h =================================================================== --- ApplePS2SynapticsTouchPad.h (revision 135) +++ ApplePS2SynapticsTouchPad.h (working copy) @@ -425,6 +425,9 @@ UInt32 _prevY; UInt8 _prevButtons; UInt8 _prevNumFingers; + SInt32 _xaverage; + SInt32 _yaverage; + UInt32 _squelch; uint32_t _prevPacketTime; uint32_t _prevPacketSecond;