[Patch] Improved mouse acceleration
Alex Deucher
alexdeucher at gmail.com
Mon Oct 9 08:44:38 PDT 2006
you might want to post this as a bug on https://bugs.freedesktop.org
so it doesn't get lost and can be properly reviewed.
Alex
On 10/7/06, Simon Thum <simon.thum at mni.fh-giessen.de> wrote:
> Hi list,
>
> I first tried on xorg-mentors, but the effort seems dead. Basically, I
> am seeking comment on this one, and maybe someone would bother to
> 'mentor' me/the patch. Sorry if this list is not the right place.
>
> I have revised the mouse acceleration code since I think there are
> better ways to do it. I fixed a couple of problems and introduced some
> more flexibility. For example it is easy (for a coder) to exchange
> acceleration profiles, which some moves in this direction had tried to
> do. However, I think this doesn't tackle the right spots. But this is
> covered in the attached documentation.
>
> I am right now using it, and I had no stability problems though it is
> quite a lenghty change.
>
> Please let me know what you think about it!
>
> Thanks in advance,
>
> Simon Thum
>
>
>
> X.org mouse acceleration proposal
>
> Author: Simon Thum (simon [dot] thum [at] gmx de)
> Date: 09/2006
>
>
>
> Intent
>
> - provide a better 'feel' for the X pointing device
> - fix current problems, especially with polynomial acceleration
>
>
>
> Postulate
> or
> How to provide a better mouse feeling for the user?
>
> It is presumed that the most critical part is doing a sophisticated guess on
> the velocity of the device in a user's hand, as this is the reference the
> user's brain has to build its own knowledge about the applied translation from
> mouse to screen. Because this is an intuitive process, easing it just 'feels
> better'.
>
> Velocity is a physical quantity usually measured in m/s. This is what is
> accessible to our nerves and brains, delivering the data for intuition.
> Acceleration therefore needs to depend on velocity, which we try to deduct
> from the measurements the device provides us with.
>
> It follows that any introduced lag should be small enough not to be noted, and
> any behind-the-scenes data should not counter intuitive mechanisms.
>
>
>
> Current problems adressed
>
> 1) Current acceleration code devises velocity (and thus acceleration) directly
> from device data at any given instant. This makes it very vunerable to
> precision problems, such as a 'jumpy' mouse.
>
> 2) If a system is under load, a device may accumulate its movement delta over
> some time, causing irrational high cursor movement in case of polynomial
> acceleration (threshold = 0, acc > 1) because velocity is guessed in an
> oversimplified fashion.
>
> 3) Some people have overly responsive devices, creating a need to reduce speed
> on precise tasks or in general. Current implementation will discard precision
> if pushed there (threshold = 1, acc < 1).
>
> These problems result in a reduced ability for our intuition to predict a
> correct hand movement for desired screen movement, causing more correctional
> moves than neccessary. Put simply, the mouse 'feels bad'.
>
>
>
> Method
>
> First, a better guess on velocity is done.
> Given available data, we calc dots per millisecond. This is quite intractable
> in integers, so we multiply by a configurable factor to arrive at values the
> usual X controls, treshold and acceleration, can be applied with some sense.
>
> This velocity is then weighted with an exponentially dropping curve, i.e. the
> longer a movement signal is back in time, the less influence it has on the
> current guess.
>
> Typically during begin and end of a mouse stroke, such weighting is not
> approriate. Therefore, a coupling is employed to use current data if weighted
> data is too far apart.
>
> After some short inactivity time, such background data is reset (called
> non-visible state (reset) in the patch).
>
> Second,the applied acceleration is made steady (over velocity) to enhance
> intuitivity furter.
>
> Third, reported values are slightly flattened (just below mouse precision)
> ONLY if acceleration is actually performed to improve evolving-speed movements
> as painting w/mouse typically requires. This can be independently turned off
> (Softening).
>
> Fourth, for too responsive devices, two methods are available (together if
> desired):
> 1) a constant deceleration can be applied
> 2) acceleration curve can be allowed to decelerate on slow movements
> (adaptive deceleration)
>
>
>
> Benefits
>
> Mostly, the polynomial acceleration becomes more usable. It can be used with
> higher acceleration coefficients (x > 2), still providing enough control. But
> also the classic acceleration should become less jumpy since it now graduates
> (rather) soft towards accelerated motion.
>
> Users with too precise devices can slow them without loosing precision,
> independent of hw driver support. Even more important, polynomial acceleration
> can now decelerate on slow movements, giving (sub)pixel precision without
> sacrificing on pointer speed.
>
> The code is more robust towards different devices: One could imagine a mouse
> reporting very often, but only 1 dot per event. Old code would not accelerate
> such a device at all. While this is a theoretical case, there is robustness
> against jitter in device event frequency, as could be caused by system load.
>
> By introducing a coefficient in xorg.conf you can make two attached devices
> feel similar, as is often the case on laptops. (untested)
>
> Users disliking all this can switch it off, retaining constant deceleration
> if desired.
>
>
>
> Problems / Todo
>
> I am not an experienced X dev, so some points are left.
>
> More complex algorithms have more knobs, and currently they can only be set in
> the server config. If you have suitable values however, change should only be
> needed when the device changes. Better would be access via xset and/or API.
> However, even removing the PerCent in VelocityScalePerCent would be an
> improvement [by reading a float from cfg]. Or simply to make the code cease
> reading those options into keyboards.
>
> If adaptive deceleration is used, the first motion event after some time will
> lead to (probalby) underestimated velocity, making it subject to maximum
> slowdown, so it might appear to be skipped. Hard to note anyway.
>
> Some mice could push the limit and report so often that milliseconds don't
> provide reliable timing; in that case, some precision is lost.
>
> A mouse velocity monitor would be nice-to-have for tweaking. Any tracing in X?
>
> The simple acceleration curve (threshold > 0) is now steady, but a function
> steady also over its derivative(s) would be preferred. Also, it does not
> support adaptive deceleration since it won't go below 1.
>
>
>
> Configuration
>
> The defaults should suffice if you had no big problems before, and feel quite
> similar. Setting treshold to 0 is strongly recommended, to use the more
> intuitive polynomial acceleration. Acceleration should be about 1.5 to 2.5
> then.
>
>
> A few tips
>
> If you have a feeling your mouse moves far too fast, ConstantDeceleration is
> your friend. Set to 2 or higher to divide speed accordingly. This will not
> discard precision (at least only on nv-reset, see Method or below).
>
> If you like the speed but need some more control at pixel-level, you should
> set AdaptiveDeceleration to 2 or more. This allows to decelerate slow
> movements down to the given factor. You might want to keep nv-resets away by
> setting VelocityReset to e.g. 500 ms, and maybe tweak VelocityScalePerCent to
> give good results. [Note this only works with polynomial acceleration]
>
> If you are picky about a smooth kick-in of acceleration, for example to ease
> doing art, I suggest tweaking VelocityScalePerCent so acceleration is done
> before the device starts reporting axis deltas above 1 (which is the point the
> old code starts accelerating). A good value for VelocityScalePerCent should
> IMHO be around 200 to 2000, 1000 being default (x10). Unfortunately, there is
> no live-monitor program for tweaking.
>
>
> Settings
>
> AdaptiveDeceleration [integer]
>
> Allows polynomial acceleration funtion (threshold = 0) to actually decelerate
> the pointer, giving enhanced precision on slow moves. Default is 1, which
> deactivates adaptive deceleration. 2 or higher allows respective deceleration.
>
> Adaptive deceleration should not affect your normal mouse useage; if it does,
> VelocityScalePerCent is probably too low.
>
> ConstantDeceleration [integer]
>
> Constantly decelerates the mouse by given factor. Default is 1 (no
> deceleration).
>
> VelocityScalePerCent [integer]
>
> In short, this controls sensitivity of acceleration.
>
> It is designed to be device-dependent, i.e. you set it once to match your
> device, then modify behaviour using the classical controls.
> This factor is given in Percent, so multiply by 100 first.
>
> Rationale: Device deltas are being divided by delta milliseconds before being
> weighted, so they are about 10 times too small compared to a device reporting
> every 10 ms. Because the reporting rate is usually unknown in advance, this is
> the only way to scale up to 'normal' values.
>
> Default is 1000, or 10x, which is suitable for devices reporting at 100hz
> maximum. If your mouse reports x times per second, set to (100000/x).
>
> WeightingDecay [integer]
>
> Default 15 milliseconds. Tweaks the weighting applied to approximate velocity.
> Higher values exhibit more integrating behaviour, introducing some lag but
> also may feel smoother. Lesser is more responsive, but less smooth. However,
> any lag will only show up if velocity coupling is disabled.
>
> VelocityReset [integer]
>
> Specifies after how many milliseconds of inactivity non-visible state (i.e.
> background info not reflected by pointer position) is discarded. This affects
> two issues:
> 1) Velocity guesing remains correct within this time if the pointer/X is stuck
> for a short moment
> 2) slow movements are guessed correctly if all device movement events are
> inside this time from each other. An increment might be neccessary to
> fully take advantage of adaptive deceleration.
>
> Default 200 ms.
>
> VelocityCouplingPerCent [integer]
>
> Specifies coupling, a feature ensuring responsivity by determining if the
> weighted guess is a valid one. Weighted guess is deemed valid if it differs
> from current either below 1.0 (hardcoded) or below this percentage.
> 0 disables, so only weighted velocity is used. This may exhibit some lag,
> depending on WeightingDecay. Higher setting means it is more likely that
> weighted velocity is taken into account. Default is 25%.
>
> Softening [boolean]
>
> Tweaks motion deltas from device before applying acceleration a bit to
> smooth rather constant moves. Tweaking is always below device precision to
> make sure it doesn't get in the way. Also, when ConstantDeceleration is used,
> Softening is not enabled by default because this already provides some
> subpixel precision.
> However you can set this "off" or "false" if you don't like it.
>
> VelocityGuessing [boolean]
>
> Setting this to "off" retains the simpler, old-fashioned algorithm for
> determining velocity. It doesn't behave exactly like the old algorithm but
> similar enough most people wouldn't note a difference.
>
>
>
> Reference
>
> http://lists.freedesktop.org/archives/xorg/2005-September/010211.html
> https://bugs.freedesktop.org/show_bug.cgi?id=138
> https://bugs.freedesktop.org/show_bug.cgi?id=2927
>
>
> diff -Bbc common_old/xf86Xinput.c common/xf86Xinput.c
> *** common_old/xf86Xinput.c Fri Oct 21 19:06:13 2005
> --- common/xf86Xinput.c Sat Oct 7 16:50:13 2006
> ***************
> *** 119,124 ****
> --- 119,273 ----
> *****************************************************************************/
> #define ENQUEUE(e) xf86eqEnqueue((e))
>
> +
> +
> +
> + /******************************************************************************
> + * Mouse softening fns
> + *
> + * Serves 3 complementary functions:
> + * 1) provide a sophisticated ballistic velocity guess to give better acceleration
> + * 2) slightly soften out mouse data when acceleration is applied
> + * 3) decelerate by two means (constant and adaptive) if enabled
> + *****************************************************************************/
> +
> + static void
> + InitVelocityData(MouseVelocityPtr s, float rdecay)
> + {
> + s->lrm_time = 0;
> + s->velocity = 0;
> + s->lrm_velocity = 0;
> + s->corr_mul = 10.0; //dots per 10 milisecond is a usable form
> + s->const_acceleration = 1.0; //no acceleration/deceleration
> + s->rdecay = rdecay; //TODO: init a lookup for common pow() values here
> + s->reset_time = 0;
> + s->last_dx = 0;
> + s->last_dy = 0;
> + s->use_softening = 1;
> + s->min_acceleration = 1.0;
> + s->use_coupling = 1;
> + s->coupling = 0.3;
> + }
> +
> +
> + // Perform velocity guessing
> + // return true if non-visible state reset is suggested
> + static inline short
> + ProcessVelocityData(MouseVelocityPtr s, int dx, int dy, int time)
> + {
> + int diff = time - s->lrm_time;
> + float cvelocity = (float)sqrt(dx*dx + dy*dy) * s->const_acceleration; //not a real velocity yet, more a motion delta
> + float fade, div;
> + short reset = FALSE;
> +
> + s->lrm_time = time;
> +
> + if (s->reset_time < 0 || diff < 0) { //disabled or timer overrun?
> + s->velocity = cvelocity; //simply set velocity from current movement, no reset.
> + return 0;
> + }
> + if (diff >= s->reset_time) { //no movement for some time, suggest to reset nonvisible state
> + s->velocity = 0;
> + reset = TRUE;
> + }
> +
> + if (diff == 0)
> + diff = 1; //prevent div-by-zero, though it shouldn't happen anyway
> + else if (diff > s->reset_time)
> + diff = s->reset_time;
> + //translate velocity to dots/ms (somewhat untractable in integers, so we multiply by some adjustable factor)
> + cvelocity = cvelocity * s->corr_mul / (float)diff;
> + s->lrm_velocity = cvelocity;
> + fade = pow(0.5, ((float)diff) * s->rdecay); //plot [x=0:10] 0.5**x, (0.5**x)/log(0.5) [its integral] for rationale
> + s->velocity *= fade; //fade out old velocity info
> + s->velocity += cvelocity * (1.0f - fade); //and add up current
> +
> + if(s->use_coupling && !reset && cvelocity != 0 && fabs(s->velocity - cvelocity) > 1.0){
> + div = fabs(1.0f - (s->velocity / cvelocity));
> + if(div > s->coupling){ //if divergence is too high...
> + s->velocity = cvelocity; //set current velocity as weighted to help catch up quickly
> + }
> + }
> + //xf86Msg(X_CONFIG, "ProcessVelocityData acceleration guessing: vel=%.3f diff=%d curw=%.4f, fade=%.4f\n", s->velocity, diff, (1.0- fade), fade);
> + return reset;
> + }
> +
> + //this flattens significant values a little bit for more steady constant-velocity response
> + static inline float
> + ApplySimpleSoftening(int od, int d)
> + {
> + float res = d;
> + if (d <= 1 && d >= -1)
> + return res;
> + if (d > od)
> + res -= 0.5;
> + else if (d < od)
> + res += 0.5;
> + return res;
> + }
> +
> + //the name says it all
> + static inline void
> + ApplySofteningAndDeceleration(MouseVelocityPtr s, int dx, int dy, float* fdx, float* fdy, short do_soften)
> + {
> + if (do_soften && s->use_softening) {
> + *fdx = ApplySimpleSoftening(s->last_dx, dx);
> + *fdy = ApplySimpleSoftening(s->last_dy, dy);
> + }
> + else {
> + *fdx = dx;
> + *fdy = dy;
> + }
> + *fdx *= s->const_acceleration;
> + *fdy *= s->const_acceleration;
> + }
> +
> +
> +
> + //return acceleration for velocity/threshold
> + typedef float (*accelerationFunc)(float velocity, float threshold, float max_acc);
> +
> + //classic X algorithm for threshold > 0, has the disadvantage of discarding all the nice data we have about mouse velocity
> + /*static float
> + ClassicAccelerationFunc(float velocity, float threshold, float acc)
> + {
> + if (velocity <= threshold)
> + return 1;
> + else
> + return acc;
> + }*/
> +
> + //steady function similar to Classic
> + static float
> + SimpleAccelerationFunc(float velocity, float threshold, float acc)
> + {
> + if (velocity <= threshold)
> + return 1;
> + velocity /= threshold;
> + if (velocity >= acc)
> + return acc;
> + else
> + return velocity;
> +
> + }
> +
> +
> + //Classic X Polynomial function for threshold = 0, somewhat quirky due to non-unity respone to velocity = 1 (unsteady acceleration)
> + /*static float
> + ClassicPolynomialAccelerationFunc(float velocity, float ignored, float acc)
> + {
> + return pow(velocity, (acc - 1.0) * 0.5) * 0.5;
> + }*/
> +
> + //Polynomial function similar classic one, but with steady response
> + static float
> + PolynomialAccelerationFunc(float velocity, float ignored, float acc)
> + {
> + return pow(velocity, (acc - 1.0) * 0.5);
> + }
> +
> +
> +
> /***********************************************************************
> *
> * xf86AlwaysCoreControl --
> ***************
> *** 233,238 ****
> --- 382,388 ----
> xf86ProcessCommonOptions(LocalDevicePtr local,
> pointer list)
> {
> + float tempf;
> if (xf86SetBoolOption(list, "AlwaysCore", 0) ||
> xf86SetBoolOption(list, "SendCoreEvents", 0)) {
> local->flags |= XI86_ALWAYS_CORE;
> ***************
> *** 261,266 ****
> --- 410,462 ----
> xf86Msg(X_CONFIG, "%s: has a history of %d motions\n", local->name,
> local->history_size);
> }
> +
> + //FIXME These should be reachable by API/xset and/or be read only for (relative) pointing devices not keyboards
> + tempf = xf86SetIntOption(list, "WeightingDecay", 15);
> + xf86Msg(X_CONFIG, "%s: weighting decay %d ms\n", local->name, (int)tempf);
> + if(tempf > 0)
> + tempf = 1.0 / tempf; //set reciprocal if possible
> + else
> + tempf = 10000; //else set fairly high
> +
> + InitVelocityData(&(local->velocitydata), tempf);
> +
> + tempf = xf86SetIntOption(list, "ConstantDeceleration", 1);
> + if(tempf > 1.0){
> + xf86Msg(X_CONFIG, "%s: constant deceleration by %.1f\n", local->name, tempf);
> + local->velocitydata.const_acceleration = 1.0 / tempf; //set reciprocal deceleration aka acceleration
> + }
> +
> + tempf = xf86SetIntOption(list, "AdaptiveDeceleration", 1);
> + if(tempf > 1.0){
> + xf86Msg(X_CONFIG, "%s: adaptive deceleration by %.1f\n", local->name, tempf);
> + local->velocitydata.min_acceleration = 1.0 / tempf; //set minimum acceleration
> + }
> +
> + tempf = xf86SetIntOption(list, "VelocityCouplingPerCent", 25);
> + if(tempf > 0.0){
> + xf86Msg(X_CONFIG, "%s: velocity coupling is %d%%\n", local->name, (int)tempf);
> + local->velocitydata.use_coupling = 1;
> + local->velocitydata.coupling = tempf / 100.0; //set max divergence
> + }else{
> + local->velocitydata.use_coupling = 0;
> + xf86Msg(X_CONFIG, "%s: disabled velocity coupling\n", local->name);
> + }
> +
> + // Read Softening cfg. if deceleration is used, this is expected to provide enough subpixel information so we enable
> + // Softening by default only if ConstantDeceleration is not used
> + local->velocitydata.use_softening = xf86SetBoolOption(list, "Softening", local->velocitydata.const_acceleration == 1.0);
> +
> + local->velocitydata.reset_time = xf86SetIntOption(list, "VelocityReset", 200);
> +
> + local->velocitydata.corr_mul = xf86SetIntOption(list, "VelocityScalePerCent", 1000); //FIXME reading a float preferred
> + local->velocitydata.corr_mul /= 100.0;
> +
> + if (xf86SetBoolOption(list, "VelocityGuessing", 1) == 0) {
> + local->velocitydata.reset_time = -1; //Disable
> + local->velocitydata.use_softening = 0;
> + xf86Msg(X_CONFIG, "%s: Disabled velocity guessing\n", local->name);
> + }
> }
>
> /***********************************************************************
> ***************
> *** 277,284 ****
> {
> LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate;
>
> ! local->dxremaind = 0.0;
> ! local->dyremaind = 0.0;
>
> if (InitIntegerFeedbackClassDeviceStruct(dev, xf86AlwaysCoreControl) == FALSE) {
> ErrorF("Unable to init integer feedback for always core feature\n");
> --- 473,480 ----
> {
> LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate;
>
> ! local->dxremaind = 0.5f;
> ! local->dyremaind = 0.5f;
>
> if (InitIntegerFeedbackClassDeviceStruct(dev, xf86AlwaysCoreControl) == FALSE) {
> ErrorF("Unable to init integer feedback for always core feature\n");
> ***************
> *** 875,880 ****
> --- 1073,1079 ----
> deviceKeyButtonPointer *xev = (deviceKeyButtonPointer*) xE;
> deviceValuator *xv = (deviceValuator*) xev+1;
> LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate;
> + MouseVelocityPtr velocitydata;
> char *buff = 0;
> Time current;
> Bool is_core = xf86IsCorePointer(device);
> ***************
> *** 885,891 ****
> int oldaxis[6];
> int *axisvals;
> int dx = 0, dy = 0;
> ! float mult;
> int x, y;
> int loop_start;
> int i;
> --- 1084,1090 ----
> int oldaxis[6];
> int *axisvals;
> int dx = 0, dy = 0;
> ! float acc, apxvelocity, fdx, fdy;
> int x, y;
> int loop_start;
> int i;
> ***************
> *** 922,927 ****
> --- 1121,1127 ----
>
> if (loop % 6 == 5 || loop == num_valuators - 1) {
> num = loop % 6 + 1;
> + velocitydata = &local->velocitydata;
> /*
> * Adjust first two relative valuators
> */
> ***************
> *** 930,972 ****
> dx = valuator[0];
> dy = valuator[1];
>
> /*
> * Accelerate
> */
> ! if (device->ptrfeed && device->ptrfeed->ctrl.num) {
> ! /* modeled from xf86Events.c */
> ! if (device->ptrfeed->ctrl.threshold) {
> ! if ((abs(dx) + abs(dy)) >= device->ptrfeed->ctrl.threshold) {
> ! local->dxremaind = ((float)dx * (float)(device->ptrfeed->ctrl.num)) /
> ! (float)(device->ptrfeed->ctrl.den) + local->dxremaind;
> ! valuator[0] = (int)local->dxremaind;
> ! local->dxremaind = local->dxremaind - (float)valuator[0];
>
> ! local->dyremaind = ((float)dy * (float)(device->ptrfeed->ctrl.num)) /
> ! (float)(device->ptrfeed->ctrl.den) + local->dyremaind;
> ! valuator[1] = (int)local->dyremaind;
> ! local->dyremaind = local->dyremaind - (float)valuator[1];
> ! }
> ! }
> ! else if (dx || dy) {
> ! mult = pow((float)(dx*dx+dy*dy),
> ! ((float)(device->ptrfeed->ctrl.num) /
> ! (float)(device->ptrfeed->ctrl.den) - 1.0) /
> ! 2.0) / 2.0;
> if (dx) {
> ! local->dxremaind = mult * (float)dx + local->dxremaind;
> valuator[0] = (int)local->dxremaind;
> local->dxremaind = local->dxremaind - (float)valuator[0];
> }
> if (dy) {
> ! local->dyremaind = mult * (float)dy + local->dyremaind;
> valuator[1] = (int)local->dyremaind;
> local->dyremaind = local->dyremaind - (float)valuator[1];
> }
> }
> - DBG(6, ErrorF("xf86PostMotionEvent acceleration v0=%d v1=%d\n",
> - valuator[0], valuator[1]));
> }
>
> /*
> * Map current position back to device space in case
> --- 1130,1181 ----
> dx = valuator[0];
> dy = valuator[1];
>
> + if (ProcessVelocityData(velocitydata, dx , dy, current)) { //reset nonvisible state?
> + local->dxremaind = local->dyremaind = 0.5f; //do rounding by pre-adding 0.5 once (see below and xf86XinputFinalizeInit)
> + velocitydata->last_dx = dx; //prevent softening (somewhat quirky solution, as it depends on the algorithm)
> + velocitydata->last_dy = dy;
> + }
> +
> /*
> * Accelerate
> */
> ! if ((dx || dy) && device->ptrfeed) {
> ! apxvelocity = velocitydata->velocity;
>
> ! if (device->ptrfeed->ctrl.num) {
> ! // Calc Acceleration for current velocity
> ! if (device->ptrfeed->ctrl.threshold) { //select acceleration style
> ! //use ClassicAccelerationFunc for old-style jumpy behaviour
> ! acc = SimpleAccelerationFunc(apxvelocity, device->ptrfeed->ctrl.threshold, (float)(device->ptrfeed->ctrl.num) /
> ! (float)(device->ptrfeed->ctrl.den));
> ! }else {
> ! acc = PolynomialAccelerationFunc(apxvelocity, 0, (float)(device->ptrfeed->ctrl.num) / (float)(device->ptrfeed->ctrl.den));
> ! }
> !
> ! //do at least this much acceleration (or deceleration)
> ! if (acc < velocitydata->min_acceleration)
> ! acc = velocitydata->min_acceleration;
> !
> !
> ! if(acc != 1.0 || velocitydata->const_acceleration != 1.0) {
> ! ApplySofteningAndDeceleration(velocitydata, dx, dy, &fdx, &fdy, acc > 1.0);
> if (dx) {
> ! local->dxremaind = acc * fdx + local->dxremaind;
> valuator[0] = (int)local->dxremaind;
> local->dxremaind = local->dxremaind - (float)valuator[0];
> }
> if (dy) {
> ! local->dyremaind = acc * fdy + local->dyremaind;
> valuator[1] = (int)local->dyremaind;
> local->dyremaind = local->dyremaind - (float)valuator[1];
> }
> + DBG(6, ErrorF /* or xf86Msg */ ("xf86PostMotionEvent acceleration v=(%d, %d) vel=%.3f acc=%.2f appliedv=(%.1f, %.1f) devicev=(%d, %d)\n", valuator[0], valuator[1], apxvelocity, acc, fdx, fdy, dx, dy));
> + }
> }
> }
> + //remember last motion delta (for softening)
> + velocitydata->last_dx = dx;
> + velocitydata->last_dy = dy;
>
> /*
> * Map current position back to device space in case
> diff -Bbc common_old/xf86Xinput.h common/xf86Xinput.h
> *** common_old/xf86Xinput.h Wed Aug 24 11:18:32 2005
> --- common/xf86Xinput.h Thu Oct 5 14:03:15 2006
> ***************
> *** 113,118 ****
> --- 113,135 ----
> } InputDriverRec, *InputDriverPtr;
> #endif
>
> +
> + //Contains all Data needed to implement the mouse ballistics
> + typedef struct _MouseVelocityData {
> + int lrm_time; //time the last motion event was processed
> + float velocity; //velocity as guessed by algo (weighted)
> + float lrm_velocity; //velocity as by last movement event
> + int last_dx, last_dy; //last motions delta (for cheap softening algo)
> + float corr_mul; //config: multiply this into velocity; can be used to adujust behaviour, about 2 to 25 is sensible
> + float rdecay; //config: reciprocal decay ms are between full and half weight (see AddVelocityData)
> + float const_acceleration; //config: USED FOR CONSTANT DECELERATION ! but stored reciprocal for fmul is usually faster
> + float min_acceleration; //config: minimum acceleration; normally 1, set lower to enable subpixel precision
> + short reset_time; //config: reset non-visible state after this number of miliseconds inactivity, -1 means disable velocity guessing
> + short use_softening; //config: use softening of actual mouse values (if accelerated)
> + short use_coupling; //config: use coupling of weighted and current velocity
> + float coupling; //config: maximum divergence to allow weighted velocity to be preferred
> + } MouseVelocityData, *MouseVelocityPtr;
> +
> /* This is to input devices what the ScrnInfoRec is to screens. */
>
> typedef struct _LocalDeviceRec {
> ***************
> *** 155,160 ****
> --- 172,178 ----
> InputDriverPtr drv;
> pointer module;
> pointer options;
> + MouseVelocityData velocitydata;
> } LocalDeviceRec, *LocalDevicePtr, InputInfoRec, *InputInfoPtr;
>
> typedef struct _DeviceAssocRec
>
>
> _______________________________________________
> xorg mailing list
> xorg at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/xorg
>
>
More information about the xorg
mailing list