diff -Ndupr xorg-server-1.4.2-orig/dix/devices.c xorg-server-1.4.2/dix/devices.c
--- xorg-server-1.4.2-orig/dix/devices.c	2009-03-26 08:38:39.000000000 +0100
+++ xorg-server-1.4.2/dix/devices.c	2009-03-26 23:59:15.000000000 +0100
@@ -62,6 +62,7 @@ SOFTWARE.
 #include "scrnintstr.h"
 #include "cursorstr.h"
 #include "dixstruct.h"
+#include "ptrveloc.h"
 #include "site.h"
 #ifndef XKB_IN_SERVER
 #define	XKB_IN_SERVER
@@ -536,6 +537,12 @@ CloseDevice(DeviceIntPtr dev)
     }
 
     if (dev->valuator) {
+        if(dev->valuator->accelData && 
+           dev->valuator->AccelScheme == acceleratePointer){
+            /* if more schemes are added this would need to be factored out */
+            FreeVelocityData(dev->valuator->accelData);
+            xfree(dev->valuator->accelData);
+        }
         /* Counterpart to 'biggest hack ever' in init. */
         if (dev->valuator->motion &&
             dev->valuator->GetMotionProc == GetMotionHistory)
@@ -944,6 +951,8 @@ InitValuatorClassDeviceStruct(DeviceIntP
     valc->lasty = 0;
     valc->dxremaind = 0;
     valc->dyremaind = 0;
+    valc->AccelScheme = acceleratePointerPlain;
+    valc->accelData = NULL;
     dev->valuator = valc;
 
     /* biggest hack ever. */
diff -Ndupr xorg-server-1.4.2-orig/dix/getevents.c xorg-server-1.4.2/dix/getevents.c
--- xorg-server-1.4.2-orig/dix/getevents.c	2009-03-26 08:38:39.000000000 +0100
+++ xorg-server-1.4.2/dix/getevents.c	2009-03-26 23:59:15.000000000 +0100
@@ -62,6 +62,7 @@ extern Bool XkbCopyKeymap(XkbDescPtr src
 #include "exglobals.h"
 #include "extnsionst.h"
 
+#include <ptrveloc.h>
 
 /* Maximum number of valuators, divided by six, rounded up, to get number
  * of events. */
@@ -223,80 +224,6 @@ GetMaximumEventsNum(void) {
 }
 
 
-/* Originally a part of xf86PostMotionEvent; modifies valuators
- * in-place. */
-static void
-acceleratePointer(DeviceIntPtr pDev, int first_valuator, int num_valuators,
-                  int *valuators)
-{
-    float mult = 0.0;
-    int dx = 0, dy = 0;
-    int *px = NULL, *py = NULL;
-
-    if (!num_valuators || !valuators)
-        return;
-
-    if (first_valuator == 0) {
-        dx = valuators[0];
-        px = &valuators[0];
-    }
-    if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
-        dy = valuators[1 - first_valuator];
-        py = &valuators[1 - first_valuator];
-    }
-
-    if (!dx && !dy)
-        return;
-
-    if (pDev->ptrfeed && pDev->ptrfeed->ctrl.num) {
-        /* modeled from xf86Events.c */
-        if (pDev->ptrfeed->ctrl.threshold) {
-            if ((abs(dx) + abs(dy)) >= pDev->ptrfeed->ctrl.threshold) {
-                pDev->valuator->dxremaind = ((float)dx *
-                                             (float)(pDev->ptrfeed->ctrl.num)) /
-                                             (float)(pDev->ptrfeed->ctrl.den) +
-                                            pDev->valuator->dxremaind;
-                if (px) {
-                    *px = (int)pDev->valuator->dxremaind;
-                    pDev->valuator->dxremaind = pDev->valuator->dxremaind -
-                                                (float)(*px);
-                }
-
-                pDev->valuator->dyremaind = ((float)dy *
-                                             (float)(pDev->ptrfeed->ctrl.num)) /
-                                             (float)(pDev->ptrfeed->ctrl.den) +
-                                            pDev->valuator->dyremaind;
-                if (py) {
-                    *py = (int)pDev->valuator->dyremaind;
-                    pDev->valuator->dyremaind = pDev->valuator->dyremaind -
-                                                (float)(*py);
-                }
-            }
-        }
-        else {
-		mult = pow((float)dx * (float)dx + (float)dy * (float)dy,
-                       ((float)(pDev->ptrfeed->ctrl.num) /
-                        (float)(pDev->ptrfeed->ctrl.den) - 1.0) /
-                       2.0) / 2.0;
-            if (dx) {
-                pDev->valuator->dxremaind = mult * (float)dx +
-                                            pDev->valuator->dxremaind;
-                *px = (int)pDev->valuator->dxremaind;
-                pDev->valuator->dxremaind = pDev->valuator->dxremaind -
-                                            (float)(*px);
-            }
-            if (dy) {
-                pDev->valuator->dyremaind = mult * (float)dy +
-                                            pDev->valuator->dyremaind;
-                *py = (int)pDev->valuator->dyremaind;
-                pDev->valuator->dyremaind = pDev->valuator->dyremaind -
-                                            (float)(*py);
-            }
-        }
-    }
-}
-
-
 /**
  * Clip an axis to its bounds, which are declared in the call to
  * InitValuatorAxisClassStruct.
@@ -616,9 +543,13 @@ GetPointerEvents(xEvent *events, DeviceI
         clipAxis(pDev, 1, &y);
     }
     else {
-        if (flags & POINTER_ACCELERATE)
-            acceleratePointer(pDev, first_valuator, num_valuators,
-                              valuators);
+	if ((flags & POINTER_ACCELERATE) && pDev->valuator->AccelScheme){
+            pDev->valuator->AccelScheme(pDev,
+                                        first_valuator,
+                                        num_valuators,
+                                        valuators,
+                                        ms);
+	}
 
         if (pDev->coreEvents) {
             /* Get and convert the core pointer coordinate space into
diff -Ndupr xorg-server-1.4.2-orig/dix/Makefile.am xorg-server-1.4.2/dix/Makefile.am
--- xorg-server-1.4.2-orig/dix/Makefile.am	2009-03-26 08:38:39.000000000 +0100
+++ xorg-server-1.4.2/dix/Makefile.am	2009-03-26 23:59:15.000000000 +0100
@@ -26,6 +26,7 @@ libdix_la_SOURCES = 	\
 	pixmap.c	\
 	privates.c	\
 	property.c	\
+	ptrveloc.c	\
 	resource.c	\
 	swaprep.c	\
 	swapreq.c	\
diff -Ndupr xorg-server-1.4.2-orig/dix/Makefile.in xorg-server-1.4.2/dix/Makefile.in
--- xorg-server-1.4.2-orig/dix/Makefile.in	2009-03-26 08:38:39.000000000 +0100
+++ xorg-server-1.4.2/dix/Makefile.in	2009-03-26 23:59:36.000000000 +0100
@@ -56,7 +56,7 @@ libdix_la_LIBADD =
 am_libdix_la_OBJECTS = atom.lo colormap.lo cursor.lo devices.lo \
 	dispatch.lo dixfonts.lo dixutils.lo events.lo extension.lo \
 	ffs.lo gc.lo getevents.lo globals.lo glyphcurs.lo grabs.lo \
-	initatoms.lo main.lo pixmap.lo privates.lo property.lo \
+	initatoms.lo main.lo pixmap.lo privates.lo property.lo ptrveloc.lo \
 	resource.lo swaprep.lo swapreq.lo tables.lo window.lo \
 	strcasecmp.lo
 libdix_la_OBJECTS = $(am_libdix_la_OBJECTS)
@@ -402,6 +402,7 @@ libdix_la_SOURCES = \
 	pixmap.c	\
 	privates.c	\
 	property.c	\
+	ptrveloc.c	\
 	resource.c	\
 	swaprep.c	\
 	swapreq.c	\
@@ -503,6 +504,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pixmap.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/privates.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/property.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ptrveloc.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resource.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strcasecmp.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swaprep.Plo@am__quote@
diff -Ndupr xorg-server-1.4.2-orig/dix/ptrveloc.c xorg-server-1.4.2/dix/ptrveloc.c
--- xorg-server-1.4.2-orig/dix/ptrveloc.c	1970-01-01 01:00:00.000000000 +0100
+++ xorg-server-1.4.2/dix/ptrveloc.c	2009-03-26 23:59:15.000000000 +0100
@@ -0,0 +1,587 @@
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <math.h>
+#include <ptrveloc.h>
+#include <inputstr.h>
+#include <assert.h>
+
+
+/*****************************************************************************
+ * Pointer ballistics 2006/2007 by Simon Thum (simon [dot] thum [at] gmx de)
+ *
+ * Serves 3 complementary functions:
+ * 1) provide a sophisticated ballistic velocity estimate to improve
+ *    the relation between velocity (of the device) and acceleration
+ * 2) slightly soften mouse data when acceleration is applied
+ * 3) decelerate by two means (constant and adaptive) if enabled
+ *
+ * Important concepts are the
+ *
+ * - Scheme
+ *      which selects the basic algorithm (old/new (new is the stuff herein))
+ * - Profile
+ *      which selects or excutes the
+ * - Function,
+ *      which returns an acceleration for any given velocity.
+ *
+ *  The Profile is an intermediary intended to cleanly perform old-style
+ *  function selection (threshold =/!= 0)
+ *  However, custom functions should be implemented as a profile.
+ *  A function as such can be identical with a profile, see below.
+ ****************************************************************************/
+
+
+
+
+/********************************
+ *  Init/Uninit etc
+ *******************************/
+
+/*
+Init struct so it should match the average case
+*/
+void
+InitVelocityData(DeviceVelocityPtr s, float rdecay)
+{
+    s->lrm_time = 0;
+    s->velocity  = 0;
+    s->corr_mul = 10.0;      /* dots per 10 milisecond should be usable */
+    s->const_acceleration = 1.0;   /* no acceleration/deceleration  */
+    s->reset_time = 300;
+    s->last_dx = 0;
+    s->last_dy = 0;
+    s->use_softening = 1;
+    s->min_acceleration = 1.0; /* don't decelerate */
+    s->use_coupling = 1;
+    s->coupling = 0.2;
+    s->fading_lut_size = 0;
+    s->fading_lut = NULL;
+    s->profile_private = NULL;
+    SetAccelerationProfile(s, 0);
+    InitFadingLookup(s, rdecay, 40);
+}
+
+/*
+Clean up
+param is a void* since the ptr in ValuatorClassRec is not typed either
+*/
+void
+FreeVelocityData(void* p){
+    DeviceVelocityPtr s = (DeviceVelocityPtr)p;
+    s->fading_lut_size = 0;
+    xfree(s->fading_lut);
+    s->fading_lut = NULL;
+    xfree(s->profile_private);
+    s->profile_private = NULL;
+}
+
+/*
+Adjust weighting decay and lut in sync
+*/
+void
+InitFadingLookup(DeviceVelocityPtr s, float rdecay, int lutsize)
+{
+    int x;
+    float *newlut;
+    float *oldlut;
+
+    if(lutsize > 0){
+        newlut = xalloc (sizeof(float)* lutsize);
+        if(!newlut)
+            return;
+        for(x = 0; x < lutsize; x++)
+            newlut[x] = pow(0.5, ((float)x) * rdecay);
+    }else{
+        newlut = NULL;
+    }
+    oldlut = s->fading_lut;
+    s->fading_lut = newlut;
+    s->rdecay = rdecay;
+    s->fading_lut_size = lutsize;
+    if(oldlut != NULL)
+        xfree(oldlut);
+}
+
+
+
+/********************************
+ *  general Velocity and
+ *  acceleration computation
+ *******************************/
+
+/**
+return the axis if mickey is insignificant and axis-aligned
+or -1 otherwise
+1 for hz
+2 for vt
+*/
+static inline short
+GetAxis(int dx, int dy){
+    if(dx == 0 || dy == 0){
+        if(dx == 1 || dx == -1)
+            return 1;
+        if(dy == 1 || dy == -1)
+            return 2;
+        return -1;
+    }else{
+        return -1;
+    }
+}
+
+/*  Perform velocity approximation
+    return true if non-visible state reset is suggested  */
+short
+ProcessVelocityData(DeviceVelocityPtr s, int dx, int dy, int time)
+{
+    int diff = time - s->lrm_time;
+    int cur_ax = GetAxis(dx, dy);
+    int last_ax = GetAxis(s->last_dx, s->last_dy);
+    float cvelocity, fade, div;
+    short reset = (diff >= s->reset_time);
+    if(cur_ax != last_ax && cur_ax != -1 && last_ax != -1 && !reset){
+        /*DebugF("(dix) ProcessVelocityData diagonal correction %i %i",
+                  cur_ax, last_ax);*/
+        /* correct for the error induced when diagonal movements are
+           reported as alternating axis mickeys */
+        dx += s->last_dx;
+        dy += s->last_dy;
+        diff += s->last_diff;
+        s->last_diff = time - s->lrm_time; /* prevent continuous add-up */
+    }else{
+        s->last_diff = diff;
+    }
+
+    /* cvelocity is not a real velocity yet, more a motion delta. contant
+    acceleration is multiplied here to make the velocity an on-screen velocity
+    (px/t as opposed to some device velocity). This is intended to make
+    multiple devices with widely varying ConstantDecelerations
+    behave more similar */
+    cvelocity = (float)sqrt(dx*dx + dy*dy) * s->const_acceleration;
+
+    s->lrm_time = time;
+
+    if (s->reset_time < 0 || diff < 0) {     /* disabled or timer overrun? */
+        /* simply set velocity from current movement, no reset. */
+        s->velocity = cvelocity;
+        return 0;
+    }
+
+    if (reset) {
+        /* no movement for some time, suggest to reset nonvisible state */
+        diff = s->reset_time;
+        reset = TRUE;
+    }
+
+    if (diff == 0)
+        diff = 1; /* prevent div-by-zero, though it shouldn't happen anyway*/
+
+    /* translate velocity to dots/ms (somewhat untractable in integers,
+       so we multiply by some per-device adjustable factor) */
+    cvelocity = cvelocity * s->corr_mul / (float)diff;
+
+    /* short-circuit: when nv-reset the rest can be skipped */
+    if(reset == TRUE){
+        s->velocity = cvelocity;
+        return TRUE;
+    }
+
+    /* fading factor; crucial it matches definition in InitFadingLookup */
+    if(diff < s->fading_lut_size)
+        fade = s->fading_lut[diff];
+    else
+        fade = pow(0.5, ((float)diff) * s->rdecay);
+
+    s->velocity *= fade;    /* fade out old velocity info */
+    s->velocity += cvelocity * (1.0f - fade);    /* and add up current */
+
+    /* perform coupling */
+    if(s->use_coupling && cvelocity > 0 && fabs(s->velocity-cvelocity) > 1.0){
+        div = fabs(cvelocity - s->velocity) / (s->velocity + cvelocity);
+        if(div > s->coupling){    /* if divergence is too high...  */
+            /* set current velocity as weighted to catch up quickly */
+            s->velocity = cvelocity;
+        }
+    }
+    /*DebugF("ProcessVelocityData acceleration guessing: vel=%.3f
+    diff=%d curw=%.4f, fade=%.4f\n", s->velocity, diff, (1.0- fade), fade);*/
+    return reset;
+}
+
+
+/* this flattens significant ( > 1) mickeys 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;
+}
+
+
+static void
+ApplySofteningAndConstantDeceleration(
+    DeviceVelocityPtr 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;
+}
+
+
+
+
+/*****************************************
+ *  Acceleration functions and profiles
+ ****************************************/
+
+/* acceleration function similar to classic accelerated/unaccelerated,
+   introducing some transition range
+*/
+static float
+SimpleAccelerationFunc(float velocity, float threshold, float acc)
+{
+    if(velocity < 1.0)
+        return velocity;
+    if (velocity <= threshold)
+        return 1;
+    velocity /= threshold;
+    if (velocity >= acc)
+        return acc;
+    else
+        return velocity;
+
+}
+
+/* Polynomial function similar previous one, but with f(1) = 1 */
+static float
+PolynomialAccelerationFunc(float velocity, float ignored, float acc)
+{
+   return pow(velocity, (acc - 1.0) * 0.5);
+}
+
+/**
+returns acceleration for velocity.
+This profile selects the two functions like the old scheme did
+*/
+static float
+ClassicProfile(
+    DeviceVelocityPtr pVel,
+    float threshold,
+    float acc)
+{
+
+    if (threshold) {
+	return SimpleAccelerationFunc  (pVel->velocity,
+				        threshold,
+					acc);
+    }
+    else {
+	return PolynomialAccelerationFunc(pVel->velocity,
+	                                  0,
+	                                  acc);
+    }
+}
+
+/**
+Power profile
+This has a completely smooth transition curve, i.e. no jumps in the
+derivatives. 
+
+This comes at the expense of overall response dependency on min-acceleration.
+In effect, min_acceleration mimics const_acceleration in this profile.
+*/
+static float
+PowerProfile(
+    DeviceVelocityPtr pVel,
+    float threshold,
+    float acc)
+{
+    float vel_dist;
+    
+    acc /= 10.f; //without this, acc of 2 is unuseable
+
+    if (pVel->velocity <= threshold)
+        return pVel->min_acceleration;
+    vel_dist = pVel->velocity - threshold;
+    return (pow(acc, vel_dist)) * pVel->min_acceleration;
+}
+
+
+//just a smooth function in [0..1] -> [0..1]
+//has to be point-symmetric at 0.5
+static float
+CalcNaturalGradient(float x){
+    x *= 2.0f;
+    x -= 1.0f;
+    return 0.5f + (x * sqrt(1.0f - x*x) + asin(x))/M_PI;
+}
+
+/**
+  acceleration function similar to classic accelerated/unaccelerated,
+  but with smooth transition in between (and towards zero for adaptive dec.).
+*/
+static float
+SimpleSmoothProfile(
+    DeviceVelocityPtr pVel,
+    float threshold,
+    float acc)
+{
+    float velocity = pVel->velocity;
+    if(velocity < 1.0f)
+        return CalcNaturalGradient(0.5 + velocity*0.5) * 2.0f - 1.0f;
+    if(threshold < 1.0f)
+        threshold = 1.0f;
+    if (velocity <= threshold)
+        return 1;
+    velocity /= threshold;
+    if (velocity >= acc)
+        return acc;
+    else
+        return 1.0f + (CalcNaturalGradient(velocity/acc) * (acc - 1.0f));
+}
+
+/**
+  This profile uses the first half of the narural gradient as a start
+  and then scales linearly. might not bear f(1) = 1
+*/
+static float
+SmoothLinearProfile(
+    DeviceVelocityPtr pVel,
+    float threshold,
+    float acc)
+{
+    if(acc > 1.0f)
+        acc -= 1.0f; /*this is so acc = 1 is no acceleration */
+    else
+        return 1.0f; /* originally X just went stupid, here we disable */
+
+    float nv = (pVel->velocity - threshold) * acc * 0.5f;
+    float res;
+    if(nv < 0){
+        res = 0;
+    }else if(nv < 2){
+        res = CalcNaturalGradient(nv*0.25f)*2.0f;
+    }else{
+        nv -= 2.0f;
+        res = nv * 2.0f / M_PI  /* steepness of gradient at 0.5 */
+              + 1.0f; /* gradient leaves at 2|1 */
+    }
+    res += pVel->min_acceleration;
+    return res;
+}
+
+/**
+ Set the profile by number.
+ Intended to make profiles exchangeable at runtime.
+ If you created a profile, give it a number here to make it selectable.
+ In case some profile-specific init is needed, here would be a good place.
+ returns FALSE (0) if profile number is unknown (nondestructive, of course).
+*/
+int
+SetAccelerationProfile(
+    DeviceVelocityPtr s,
+    int profile_num)
+{
+    PointerAccelerationProfileFunc profile;
+    switch(profile_num){
+        default:
+            return FALSE;
+        case 0:
+            profile = ClassicProfile;
+            break;
+        case 1:
+            profile = SmoothLinearProfile;
+            break;
+        case 2:
+            profile = SimpleSmoothProfile;
+            break;
+        case 3:
+            profile = PowerProfile;
+            break;
+    }
+    if(s->profile_private != NULL){
+        /*Here one could clean old profile data*/
+        xfree(s->profile_private);
+        s->profile_private = NULL;
+    }
+    /*Here one could init profile-private data*/
+    s->Profile = profile;
+    return TRUE;
+}
+
+
+
+
+/********************************
+ *  acceleration schemes
+ *******************************/
+
+/*
+Modifies valuators in-place.
+This version employs a velocity approximation algorithm to
+enable fine-grained acceleration profiles.
+*/
+void
+acceleratePointer(DeviceIntPtr pDev, int first_valuator, int num_valuators,
+                  int *valuators, int evtime)
+{
+    float mult = 0.0;
+    int dx = 0, dy = 0;
+    int *px = NULL, *py = NULL;
+    DeviceVelocityPtr velocitydata = (DeviceVelocityPtr) pDev->valuator->accelData;
+    float fdx, fdy; /* no need to init */
+
+    if (!num_valuators || !valuators || !velocitydata)
+        return;
+
+    if (first_valuator == 0) {
+        dx = valuators[0];
+        px = &valuators[0];
+    }
+    if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
+        dy = valuators[1 - first_valuator];
+        py = &valuators[1 - first_valuator];
+    }
+
+    if (dx || dy){
+        /* reset nonvisible state? */
+        if (ProcessVelocityData(velocitydata, dx , dy, evtime)) {
+            /* set to center of pixel */
+            pDev->valuator->dxremaind = pDev->valuator->dyremaind = 0.5f;
+            /* prevent softening (somewhat quirky solution,
+            as it depends on the algorithm) */
+            velocitydata->last_dx = dx;
+            velocitydata->last_dy = dy;
+        }
+
+        if (pDev->ptrfeed && pDev->ptrfeed->ctrl.num) {
+            /* invoke acceleration profile to determine acceleration */
+            mult = velocitydata->Profile(velocitydata,
+                                pDev->ptrfeed->ctrl.threshold,
+                                (float)(pDev->ptrfeed->ctrl.num) /
+                                (float)(pDev->ptrfeed->ctrl.den));
+
+            /* enforce min_acceleration */
+            if (mult < velocitydata->min_acceleration)
+                mult = velocitydata->min_acceleration;
+
+            if(mult != 1.0 || velocitydata->const_acceleration != 1.0) {
+                ApplySofteningAndConstantDeceleration(  velocitydata,
+                                                        dx, dy,
+                                                        &fdx, &fdy,
+                                                        mult > 1.0);
+                if (dx) {
+                    pDev->valuator->dxremaind = mult * fdx + pDev->valuator->dxremaind;
+                    *px = (int)pDev->valuator->dxremaind;
+                    pDev->valuator->dxremaind = pDev->valuator->dxremaind - (float)*px;
+                }
+                if (dy) {
+                    pDev->valuator->dyremaind = mult * fdy + pDev->valuator->dyremaind;
+                    *py = (int)pDev->valuator->dyremaind;
+                    pDev->valuator->dyremaind = pDev->valuator->dyremaind - (float)*py;
+                }
+            }
+        }
+    }
+    /* remember last motion delta (for softening/slow movement treatment) */
+    velocitydata->last_dx = dx;
+    velocitydata->last_dy = dy;
+}
+
+
+
+/* Originally a part of xf86PostMotionEvent; modifies valuators
+ * in-place. */
+void
+acceleratePointerPlain(DeviceIntPtr pDev, int first_valuator, int num_valuators,
+                        int *valuators, int ignore)
+{
+    float mult = 0.0;
+    int dx = 0, dy = 0;
+    int *px = NULL, *py = NULL;
+
+    if (!num_valuators || !valuators)
+        return;
+
+    if (first_valuator == 0) {
+        dx = valuators[0];
+        px = &valuators[0];
+    }
+    if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
+        dy = valuators[1 - first_valuator];
+        py = &valuators[1 - first_valuator];
+    }
+
+    if (!dx && !dy)
+        return;
+
+    if (pDev->ptrfeed && pDev->ptrfeed->ctrl.num) {
+        /* modeled from xf86Events.c */
+        if (pDev->ptrfeed->ctrl.threshold) {
+            if ((abs(dx) + abs(dy)) >= pDev->ptrfeed->ctrl.threshold) {
+                pDev->valuator->dxremaind = ((float)dx *
+                        (float)(pDev->ptrfeed->ctrl.num)) /
+                        (float)(pDev->ptrfeed->ctrl.den) +
+                        pDev->valuator->dxremaind;
+                if (px) {
+                    *px = (int)pDev->valuator->dxremaind;
+                    pDev->valuator->dxremaind = pDev->valuator->dxremaind -
+                            (float)(*px);
+                }
+
+                pDev->valuator->dyremaind = ((float)dy *
+                        (float)(pDev->ptrfeed->ctrl.num)) /
+                        (float)(pDev->ptrfeed->ctrl.den) +
+                        pDev->valuator->dyremaind;
+                if (py) {
+                    *py = (int)pDev->valuator->dyremaind;
+                    pDev->valuator->dyremaind = pDev->valuator->dyremaind -
+                            (float)(*py);
+                }
+            }
+        }
+        else {
+            mult = pow((float)(dx * dx + dy * dy),
+                        ((float)(pDev->ptrfeed->ctrl.num) /
+                                (float)(pDev->ptrfeed->ctrl.den) - 1.0) /
+                                2.0) / 2.0;
+            if (dx) {
+                pDev->valuator->dxremaind = mult * (float)dx +
+                        pDev->valuator->dxremaind;
+                *px = (int)pDev->valuator->dxremaind;
+                pDev->valuator->dxremaind = pDev->valuator->dxremaind -
+                        (float)(*px);
+            }
+            if (dy) {
+                pDev->valuator->dyremaind = mult * (float)dy +
+                        pDev->valuator->dyremaind;
+                *py = (int)pDev->valuator->dyremaind;
+                pDev->valuator->dyremaind = pDev->valuator->dyremaind -
+                        (float)(*py);
+            }
+        }
+    }
+}
diff -Ndupr xorg-server-1.4.2-orig/hw/xfree86/common/xf86Xinput.c xorg-server-1.4.2/hw/xfree86/common/xf86Xinput.c
--- xorg-server-1.4.2-orig/hw/xfree86/common/xf86Xinput.c	2009-03-26 08:38:39.000000000 +0100
+++ xorg-server-1.4.2/hw/xfree86/common/xf86Xinput.c	2009-03-26 23:59:15.000000000 +0100
@@ -87,12 +87,126 @@
 
 #include "mi.h"
 
+#include <ptrveloc.h>          /* dix pointer acceleration */
+
+
 #ifdef XFreeXDGA
 #include "dgaproc.h"
 #endif
 
 xEvent *xf86Events = NULL;
 
+
+/*
+ * Eval config and init MouseVelocityData accordingly
+ */
+static DeviceVelocityPtr
+ProcessVelocityConfiguration(char* devname, pointer list){
+    int tempi;
+    float tempf;
+    DeviceVelocityPtr s = xalloc(sizeof(DeviceVelocityData));
+    
+    if(!s)
+        return NULL;
+
+    /* TODO These settings should be reachable by API/xset  */
+    tempf = xf86SetRealOption(list, "WeightingDecay", 15);
+    xf86Msg(X_CONFIG, "%s: weighting decay %.1f ms\n", devname, tempf);
+    if(tempf > 0)
+        tempf = 1.0 / tempf;   /* set reciprocal if possible */
+    else
+        tempf = 10000;   /* else set fairly high */
+
+    InitVelocityData(s, tempf);
+
+    tempf = xf86SetIntOption(list, "ConstantDeceleration", 1);
+    if(tempf > 1.0){
+        xf86Msg(X_CONFIG, "%s: constant deceleration by %.1f\n", devname,
+                tempf);
+        s->const_acceleration = 1.0 / tempf;   /* set reciprocal deceleration
+                                                  alias acceleration */
+    }
+
+    tempf = xf86SetIntOption(list, "AdaptiveDeceleration", 1);
+    if(tempf > 1.0){
+        xf86Msg(X_CONFIG, "%s: adaptive deceleration by %.1f\n", devname,
+                tempf);
+        s->min_acceleration = 1.0 / tempf;   /* set minimum acceleration */
+    }
+
+    tempf = xf86SetRealOption(list, "VelocityCoupling", 0.2);
+    if(tempf > 0.0){
+        xf86Msg(X_CONFIG, "%s: velocity coupling is %.1f%%\n", devname,
+                tempf*100.0);
+        s->coupling = tempf;
+        s->use_coupling = 1;
+    }else{
+        s->use_coupling = 0;
+        xf86Msg(X_CONFIG, "%s: disabled velocity coupling\n", devname);
+    }
+
+    /*  Configure softening. If const deceleration is used, this is expected
+     *  to provide better subpixel information so we enable
+     *  softening by default only if ConstantDeceleration is not used
+     */
+    s->use_softening = xf86SetBoolOption(list, "Softening",
+                                         s->const_acceleration == 1.0);
+
+    s->reset_time = xf86SetIntOption(list, "VelocityReset", 300);
+    
+    tempf = xf86SetRealOption(list, "ExpectedRate", 0);
+    if(tempf > 0){
+        s->corr_mul = 1000.0 / tempf;
+    }else{
+        s->corr_mul = xf86SetRealOption(list, "VelocityScale", 10);
+    }
+
+    if (xf86SetBoolOption(list, "EstimateVelocity", 1) == 0) {
+        s->reset_time = -1;    /* Disable */
+        s->use_softening = 0;
+        xf86Msg(X_CONFIG, "%s: Disabled velocity estimation\n", devname);
+    }
+    
+    //select profile by number; hope there won't be too many
+    tempi= xf86SetIntOption(list, "AccelerationProfile", 0);
+    SetAccelerationProfile(s, tempi);
+    xf86Msg(X_CONFIG, "%s: Set acceleration profile %i\n", devname, tempi);
+
+    return s;
+}
+
+/*
+ * evalute local device options and move to dix valuator
+ * Should be executed during init when valuator exists
+ */
+static void
+ApplyExtendedValuatorSettings(LocalDevicePtr local){
+    int scheme;
+    void* schemedata;
+    /* Apply improved acceleration; Better be a device-class final init proc
+     * or whatever...
+     */
+    if(local && local->dev && local->dev->valuator){
+        scheme = xf86SetIntOption(local->options, "AccelerationScheme", 1);
+        switch(scheme){
+            case 0:
+                local->dev->valuator->AccelScheme = NULL;
+                break;
+            case 1:
+                schemedata = ProcessVelocityConfiguration(local->name,
+                                                          local->options);
+                if(schemedata){
+                    local->dev->valuator->accelData = schemedata;
+                    local->dev->valuator->AccelScheme = acceleratePointer;
+                }
+                break;
+            case 2:
+                local->dev->valuator->AccelScheme = acceleratePointerPlain;
+                break;        
+        }
+    }
+}
+
 static Bool
 xf86SendDragEvents(DeviceIntPtr	device)
 {
@@ -773,6 +887,10 @@ xf86InitValuatorAxisStruct(DeviceIntPtr 
 
     InitValuatorAxisStruct(dev, axnum, minval, maxval, resolution, min_res,
 			   max_res);
+    /* could as well be arguments to InitValuatorAxisStruct */
+    if(axnum == 0)
+        ApplyExtendedValuatorSettings(dev->public.devicePrivate);
+
 }
 
 /*
diff -Ndupr xorg-server-1.4.2-orig/include/input.h xorg-server-1.4.2/include/input.h
--- xorg-server-1.4.2-orig/include/input.h	2009-03-26 08:38:39.000000000 +0100
+++ xorg-server-1.4.2/include/input.h	2009-03-26 23:59:15.000000000 +0100
@@ -455,4 +455,12 @@ extern void DDXRingBell(
     int pitch,
     int duration);
 
+/* pointer acceleration handling */
+typedef void (*PtrAccelSchemeProcPtr)(
+    DeviceIntPtr /*pDev*/,
+    int /*first_valuator*/,
+    int /*num_valuators*/,
+    int* /*valuators*/,
+    int /*evtime*/);
+
 #endif /* INPUT_H */
diff -Ndupr xorg-server-1.4.2-orig/include/inputstr.h xorg-server-1.4.2/include/inputstr.h
--- xorg-server-1.4.2-orig/include/inputstr.h	2009-03-26 08:38:39.000000000 +0100
+++ xorg-server-1.4.2/include/inputstr.h	2009-03-26 23:59:15.000000000 +0100
@@ -159,7 +159,9 @@ typedef struct _ValuatorClassRec {
     int			  *axisVal;
     int                   lastx, lasty; /* last event recorded, not posted to
                                          * client; see dix/devices.c */
-    int                   dxremaind, dyremaind; /* for acceleration */
+    float                 dxremaind, dyremaind; /* for acceleration */
+    PtrAccelSchemeProcPtr AccelScheme;
+    void                  *accelData; /* at disposal of AccelScheme */
     CARD8	 	  mode;
 } ValuatorClassRec, *ValuatorClassPtr;
 
diff -Ndupr xorg-server-1.4.2-orig/include/ptrveloc.h xorg-server-1.4.2/include/ptrveloc.h
--- xorg-server-1.4.2-orig/include/ptrveloc.h	1970-01-01 01:00:00.000000000 +0100
+++ xorg-server-1.4.2/include/ptrveloc.h	2009-03-26 23:59:15.000000000 +0100
@@ -0,0 +1,92 @@
+/*
+*  2006/2007 by Simon Thum
+*/
+
+#ifndef POINTERVELOCITY_H
+#define POINTERVELOCITY_H
+
+#include <input.h> /*only needed for scheme decls */
+
+struct _DeviceVelocityData;
+
+/* return acceleration for velocity/threshold (profile) */
+typedef float (*PointerAccelerationProfileFunc)
+              (struct _DeviceVelocityData* /*pVel*/,
+               float /*threshold*/, float /*acc*/);
+
+/*  Contains all Data needed to implement mouse ballistics  */
+
+typedef struct _DeviceVelocityData {
+    /* time the last motion event was processed  */
+    int     lrm_time;
+    /* velocity as guessed by algo (read: weighted) */
+    float   velocity;
+    /* last motion delta and time-diff  */
+    int     last_dx, last_dy, last_diff;
+    /* lookup for fadeout values; 40 saves 99% of cases, bigger won't help
+     * much, maximum sane size is reset_time+1, yielding 100% hit rate */
+    float*   fading_lut;
+    int fading_lut_size;
+    /* config: multiply this into velocity; can be used to adujust behaviour,
+     * about 2 to 25 is sensible */
+    float   corr_mul;
+    /* config: reciprocal decay ms are between full and half weight */
+    float   rdecay;
+    /* config: USED FOR CONSTANT DECELERATION ! but stored reciprocal
+       for fmul is usually faster */
+    float   const_acceleration;
+    /* config: minimum acceleration; normally 1, set lower to enable subpixel
+       precision */
+    float   min_acceleration;
+    /* config: reset non-visible state after this number of miliseconds
+     * inactivity, -1 means disable velocity guessing */
+    short   reset_time;
+    /* config: use softening of mouse values */
+    short   use_softening;
+    /* config: use coupling of weighted and current velocity */
+    short   use_coupling;
+    /* config: maximum divergence to allow weighted velocity to be taken */
+    float   coupling;
+    /* selected acceleration profile */
+    PointerAccelerationProfileFunc Profile;
+    /* extended data for profile impl, currently unused
+       has to be allocated w/xalloc for correct cleanup */
+    void*   profile_private;
+} DeviceVelocityData, *DeviceVelocityPtr;
+
+
+extern void
+InitVelocityData(DeviceVelocityPtr s, float rdecay);
+
+extern void
+FreeVelocityData(void* s);
+
+extern void
+InitFadingLookup(DeviceVelocityPtr s, float rdecay, int lutsize);
+
+extern  short
+ProcessVelocityData(DeviceVelocityPtr s, int dx, int dy, int time);
+
+extern int 
+SetAccelerationProfile(DeviceVelocityPtr s, int profile_num);
+
+
+/* we don't strictly need to export those two, but otherwise
+there would need to be some framework for init/uninit of schemes. Overkill.
+*/
+extern void acceleratePointer(
+    DeviceIntPtr pDev,
+    int first_valuator,
+    int num_valuators,
+    int *valuators,
+    int evtime);
+
+extern void acceleratePointerPlain(
+    DeviceIntPtr pDev,
+    int first_valuator,
+    int num_valuators,
+    int *valuators,
+    int ignore);
+
+
+#endif  /* POINTERVELOCITY_H */
