From olli@lurza.secnetix.de  Sat Jun 16 11:13:13 2007
Return-Path: <olli@lurza.secnetix.de>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id 77BB716A47F
	for <FreeBSD-gnats-submit@freebsd.org>; Sat, 16 Jun 2007 11:13:13 +0000 (UTC)
	(envelope-from olli@lurza.secnetix.de)
Received: from lurza.secnetix.de (lurza.secnetix.de [83.120.8.8])
	by mx1.freebsd.org (Postfix) with ESMTP id E090013C4B9
	for <FreeBSD-gnats-submit@freebsd.org>; Sat, 16 Jun 2007 11:13:12 +0000 (UTC)
	(envelope-from olli@lurza.secnetix.de)
Received: from lurza.secnetix.de (fwnetw@localhost [127.0.0.1])
	by lurza.secnetix.de (8.13.4/8.13.4) with ESMTP id l5GBD5KV050974;
	Sat, 16 Jun 2007 13:13:10 +0200 (CEST)
	(envelope-from oliver.fromme@secnetix.de)
Received: (from olli@localhost)
	by lurza.secnetix.de (8.13.4/8.13.1/Submit) id l5GBD55D050973;
	Sat, 16 Jun 2007 13:13:05 +0200 (CEST)
	(envelope-from olli)
Message-Id: <200706161113.l5GBD55D050973@lurza.secnetix.de>
Date: Sat, 16 Jun 2007 13:13:05 +0200 (CEST)
From: Oliver Fromme <olli@secnetix.de>
Reply-To: Oliver Fromme <olli@secnetix.de>
To: FreeBSD-gnats-submit@freebsd.org
Cc: Oliver Fromme <olli@secnetix.de>
Subject: [PATCH] moused(8) -a drops movements due to rounding errors
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         113749
>Category:       bin
>Synopsis:       [PATCH] moused(8) -a drops movements due to rounding errors
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    philip
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Jun 16 11:20:03 GMT 2007
>Closed-Date:    Wed Jun 20 08:30:40 GMT 2007
>Last-Modified:  Wed Jun 20 08:30:40 GMT 2007
>Originator:     Oliver Fromme
>Release:        RELENG_6 and HEAD
>Organization:
secnetix GmbH & Co. KG
		http://www.secnetix.de/bsd
>Environment:

The problem described here exists for as long as moused(8)
exists.  It existed before the recent addition of the -A
option and is unrelated to it, but the -A option inherited
the problem and is also affected.

The patch presented below applies to HEAD (moused.c 1.78)
and RELENG_6 (moused.c 1.70.2.4).

>Description:

The problem was first reported by Harald Schmalzbauer in
this thread on the -current ML, and I have been able to
reproduce it:

http://lists.freebsd.org/pipermail/freebsd-current/2007-June/073694.html      

When the -a option (linear acceleration) is used with an
acceleration value less than one (i.e. to slow a mouse
down because it has a very high resolution), rounding
errors occur:  Slow movements are not reported at all,
movement information is dropped.  You have to move the
mouse at a certain minimum speed to get any movement of
the pointer on the screen at all.

The culprit is this code in moused.c:

        mouse.u.data.x = action2.dx * rodent.accelx;
        mouse.u.data.y = action2.dy * rodent.accely;

mouse.u.data.* is the movement reported to the application
(e.g. Xorg), action2.d* is the movement reported by the
device, and rodent.accel* is the acceleration factor set
by the -a option (e.g. 0.3 to reduce the speed to 30%).

All those variables are ints, except for the accel* values
which are floats.  So if you move the mouse slowly so the
device reports only 1, 2 or 3 units of movement, they will
all be rounded down to zero:  3 * 0.3 = 0.9 = (int) 0.
Therefore, with an acceleration value of 0.3, you have to
move the mouse fast enough so it constantly reports at
least four units of movement to get any movement of the
pointer at all.

Of course, the solution is to calculate and accumulate the
rounding error and take it into account upon the next
movement.  That's what the following patch does, both for
the -a option (linear acceleration) and for the new -A
option (dynamic acceleration).

>How-To-Repeat:

Run moused(8) with some low -a value (less than 1), e.g. 0.3,
and move the mouse slowly.

>Fix:

As mentioned above, this patch applies to both HEAD
(moused.c 1.78) and RELENG_6 (moused.c 1.70.2.4).
It should be applied in the directory src/usr.sbin/moused.

Harald Schmalzbauer confirmed that this patch fixes the
problem for him.

If the patch got somehow mangled during transmission of
the PR e-mail, it is also available from this URL:

http://www.secnetix.de/~olli/tmp/moused.v2.patch

--- moused.c.orig	Sun Jun  3 15:36:04 2007
+++ moused.c	Sat Jun 16 09:58:10 2007
@@ -400,6 +400,8 @@
     float accely;		/* Acceleration in the Y axis */
     float expoaccel;		/* Exponential acceleration */
     float expoffset;		/* Movement offset for exponential accel. */
+    float remainx;		/* Remainder on X and Y axis, respectively... */
+    float remainy;		/*    ... to compensate for rounding errors. */
     int scrollthreshold;	/* Movement distance before virtual scrolling */
 } rodent = {
     .flags = 0,
@@ -421,6 +423,8 @@
     .accely = 1.0,
     .expoaccel = 1.0,
     .expoffset = 1.0,
+    .remainx = 0.0,
+    .remainy = 0.0,
     .scrollthreshold = DFLT_SCROLLTHRESHOLD,
 };
 
@@ -500,6 +504,7 @@
 
 /* function prototypes */
 
+static void	linacc(int, int, int*, int*);
 static void	expoacc(int, int, int*, int*);
 static void	moused(void);
 static void	hup(int sig);
@@ -956,7 +961,33 @@
 }
 
 /*
+ * Function to calculate linear acceleration.
+ *
+ * If there are any rounding errors, the remainder
+ * is stored in the remainx and remainy variables
+ * and taken into account upon the next movement.
+ */
+
+static void
+linacc(int dx, int dy, int *movex, int *movey)
+{
+    float fdx, fdy;
+
+    if (dx == 0 && dy == 0) {
+	*movex = *movey = 0;
+	return;
+    }
+    fdx = dx * rodent.accelx + rodent.remainx;
+    fdy = dy * rodent.accely + rodent.remainy;
+    *movex = lround(fdx);
+    *movey = lround(fdy);
+    rodent.remainx = fdx - *movex;
+    rodent.remainy = fdy - *movey;
+}
+
+/*
  * Function to calculate exponential acceleration.
+ * (Also includes linear acceleration if enabled.)
  *
  * In order to give a smoother behaviour, we record the four
  * most recent non-zero movements and use their average value
@@ -979,8 +1010,12 @@
     length = (length + lastlength[0] + lastlength[1] + lastlength[2]) / 4;
     lbase = length / rodent.expoffset;
     accel = powf(lbase, rodent.expoaccel) / lbase;
-    *movex = lroundf(fdx * accel);
-    *movey = lroundf(fdy * accel);
+    fdx = fdx * accel + rodent.remainx;
+    fdy = fdy * accel + rodent.remainy;
+    *movex = lroundf(fdx);
+    *movey = lroundf(fdy);
+    rodent.remainx = fdx - *movex;
+    rodent.remainy = fdy - *movey;
     lastlength[2] = lastlength[1];
     lastlength[1] = lastlength[0];
     lastlength[0] = length;	/* Insert new average, not original length! */
@@ -1250,8 +1285,8 @@
 			    &mouse.u.data.x, &mouse.u.data.y);
 		    }
 		    else {
-			mouse.u.data.x = action2.dx * rodent.accelx;
-			mouse.u.data.y = action2.dy * rodent.accely;
+			linacc(action2.dx, action2.dy,
+			    &mouse.u.data.x, &mouse.u.data.y);
 		    }
 		    mouse.u.data.z = action2.dz;
 		    if (debug < 2)
@@ -1266,8 +1301,8 @@
 			&mouse.u.data.x, &mouse.u.data.y);
 		}
 		else {
-		    mouse.u.data.x = action2.dx * rodent.accelx;
-		    mouse.u.data.y = action2.dy * rodent.accely;
+		    linacc(action2.dx, action2.dy,
+			&mouse.u.data.x, &mouse.u.data.y);
 		}
 		mouse.u.data.z = action2.dz;
 		if (debug < 2)
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->philip 
Responsible-Changed-By: philip 
Responsible-Changed-When: Sun Jun 17 19:32:57 UTC 2007 
Responsible-Changed-Why:  
I'll take it. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=113749 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/113749: commit references a PR
Date: Sun, 17 Jun 2007 20:28:00 +0000 (UTC)

 philip      2007-06-17 20:27:54 UTC
 
   FreeBSD src repository
 
   Modified files:
     usr.sbin/moused      moused.c 
   Log:
   Fix a (very) longstanding bug in moused(8) affecting high-resolution rodents
   when linear acceleration (-a) was enabled with a <1 value to slow them down.
   
   Previously, rounding errors would eat small movements so the mouse had to be
   moved a certain distance to get any movement at all.  We now calculate the
   rounding errors and take them into account when reporting movement.
   
   PR:             bin/113749
   Submitted by:   Oliver Fromme <olli -at- secnetix.de>
   MFC after:      3 days
   
   Revision  Changes    Path
   1.79      +41 -6     src/usr.sbin/moused/moused.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->closed 
State-Changed-By: philip 
State-Changed-When: Wed Jun 20 08:30:30 UTC 2007 
State-Changed-Why:  
Committed. Thanks! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=113749 
>Unformatted:
