# # Updated but not checked in: # (will commit) # # modified: dix/Makefile.am # modified: dix/devices.c # modified: dix/getevents.c # modified: hw/xfree86/common/xf86Xinput.c # modified: hw/xfree86/common/xf86Xinput.h # modified: include/inputstr.h # # # Untracked files: # (use "git add" to add to commit) # # dix/devices.c.orig # dix/getevents.c.orig # dix/ptrveloc.c # hw/xfree86/xorg.conf.example # hw/xfree86/xorg.conf.example.pre # include/ptrveloc.h diff --git a/dix/Makefile.am b/dix/Makefile.am index a1f02c1..c9e56d4 100644 --- a/dix/Makefile.am +++ b/dix/Makefile.am @@ -26,6 +26,7 @@ libdix_la_SOURCES = \ pixmap.c \ privates.c \ property.c \ + ptrveloc.c \ resource.c \ swaprep.c \ swapreq.c \ diff --git a/dix/devices.c b/dix/devices.c index e6a5049..c724869 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -430,8 +430,12 @@ #endif xfree(dev->key); } - if (dev->valuator) + if (dev->valuator){ + if(dev->valuator->accelData) + xfree(dev->valuator->accelData); + /* Todo:Free using InitFadingLookup if approriate */ xfree(dev->valuator); + } if (dev->button) { #ifdef XKB @@ -815,6 +819,8 @@ InitValuatorClassDeviceStruct(DeviceIntP valc->lasty = 0; valc->dxremaind = 0; valc->dyremaind = 0; + valc->accelScheme = 0; + valc->accelData = NULL; dev->valuator = valc; /* biggest hack ever. */ diff --git a/dix/getevents.c b/dix/getevents.c index 4154262..5aeda47 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -60,6 +60,7 @@ #include "exevents.h" #include "exglobals.h" #include "extnsionst.h" +#include /* Maximum number of valuators, divided by six, rounded up, to get number * of events. */ @@ -197,17 +198,96 @@ #endif } + /* Originally a part of xf86PostMotionEvent; modifies valuators * in-place. */ static void -acceleratePointer(DeviceIntPtr pDev, int first_valuator, int num_valuators, - int *valuators) +acceleratePointerOriginal(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 * 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); + } + } + } +} + +/** +Modifies valuators in-place. +This version employs a velocity guessing algorithm, +enabling fine-grained acceleration profiles. +*/ +static 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; + MouseVelocityPtr velocitydata = (MouseVelocityPtr) pDev->valuator->accelData; + float fdx, fdy; /* no need to init */ + + if (!num_valuators || !valuators || !velocitydata) return; if (first_valuator == 0) { @@ -221,53 +301,48 @@ acceleratePointer(DeviceIntPtr pDev, int if (!dx && !dy) return; + + /* reset nonvisible state? */ + if (ProcessVelocityData(velocitydata, dx , dy, evtime)) { + /* round by pre-adding 0.5 once */ + 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) { - /* 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); - } - } + /* invoke acceleration profile and 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) */ + velocitydata->last_dx = dx; + velocitydata->last_dy = dy; } @@ -546,9 +621,20 @@ GetPointerEvents(xEvent *events, DeviceI } } else { - if (flags & POINTER_ACCELERATE) - acceleratePointer(pDev, first_valuator, num_valuators, - valuators); + if (flags & POINTER_ACCELERATE){ + switch(pDev->valuator->accelScheme){ /* select algorithm */ + case 0: + acceleratePointerOriginal(pDev, first_valuator, + num_valuators, valuators); + break; + case 1: + acceleratePointer(pDev, first_valuator, + num_valuators, valuators, ms); + break; + default: + break; /* unknown scheme? do nothing is ok */ + } + } if (pDev->coreEvents) { if (first_valuator == 0 && num_valuators >= 1) diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c index be3368d..6c1d650 100644 --- a/hw/xfree86/common/xf86Xinput.c +++ b/hw/xfree86/common/xf86Xinput.c @@ -90,6 +90,8 @@ #include "xf86_OSproc.h" /* sigio stuff #include "mi.h" +#include /* DIX acceleration code */ + /****************************************************************************** * debugging macro *****************************************************************************/ @@ -113,6 +115,82 @@ xf86SendDragEvents(DeviceIntPtr device) return (TRUE); } +/** + Eval config and init MouseVelocityData accordingly +*/ +static void +ProcessVelocityConfiguration(MouseVelocityPtr s, char* devname, pointer list){ + float tempf; + + /* FIXME These 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->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", 200); + + 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); + } +} + + +/* what a hack... + * Copy from local device to dix/input valuator + * Should be executed during init when valuator exists + */ +void ApplyExtendedValuatorSettings(LocalDevicePtr local){ + /* Apply improved acceleration; Better be a device-class final init proc + * or whatever... + */ + if(local->dev->valuator){ + local->dev->valuator->accelData = local->carryover_accelData; + local->dev->valuator->accelScheme = local->carryover_accelScheme; + } +} + + /*********************************************************************** * * xf86ProcessCommonOptions -- @@ -138,6 +216,17 @@ xf86ProcessCommonOptions(LocalDevicePtr } else { xf86Msg(X_CONFIG, "%s: doesn't report drag events\n", local->name); } + + /* Enable improved pointer acceleration by reading its options + which later get applied (when valuator is inited) */ + local->carryover_accelData = xalloc(sizeof(MouseVelocityData)); + ProcessVelocityConfiguration( + (MouseVelocityPtr)local->carryover_accelData, + local->name, + list); + /* option to retain old scheme */ + local->carryover_accelScheme = xf86SetIntOption(list, + "AccelerationScheme", 1); } void @@ -435,7 +524,6 @@ xf86PostMotionEvent(DeviceIntPtr device, va_list var; int i = 0, nevents = 0; Bool drag = xf86SendDragEvents(device); - LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate; int *valuators = NULL; int flags = 0; @@ -673,6 +761,9 @@ xf86InitValuatorAxisStruct(DeviceIntPtr InitValuatorAxisStruct(dev, axnum, minval, maxval, resolution, min_res, max_res); + /*could as well be arguments to InitValuatorAxisStruct... + also this fn gets called twice, once for each axis */ + ApplyExtendedValuatorSettings(dev->public.devicePrivate); } /* diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h index fe65643..9794683 100644 --- a/hw/xfree86/common/xf86Xinput.h +++ b/hw/xfree86/common/xf86Xinput.h @@ -144,6 +144,8 @@ typedef struct _LocalDeviceRec { InputDriverPtr drv; pointer module; pointer options; + int carryover_accelScheme; /*ugly hack*/ + void* *carryover_accelData; } LocalDeviceRec, *LocalDevicePtr, InputInfoRec, *InputInfoPtr; typedef struct _DeviceAssocRec diff --git a/include/inputstr.h b/include/inputstr.h index ada94e6..32d9bf1 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -158,7 +158,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 */ + int accelScheme; /*0 = old (up to 7.2), 1 = shiny new */ + void *accelData; /* at disposal of accelScheme */ CARD8 mode; } ValuatorClassRec, *ValuatorClassPtr;