# # Updated but not checked in: # (will commit) # # modified: dix/Makefile.am # modified: dix/devices.c # modified: dix/getevents.c # new file: dix/ptraccel.c # new file: dix/ptrveloc.c # modified: hw/xfree86/common/xf86Xinput.c # modified: include/inputstr.h # new file: include/ptraccel.h # new file: include/ptrveloc.h # # # Untracked files: # (use "git add" to add to commit) # # dix/devices.c.orig # doc/SecurityPolicy.5x # doc/SecurityPolicy.man # hw/xfree86/common/xf86Xinput.c.orig # hw/xfree86/common/xf86Xinput.c.rej # hw/xfree86/xf1bpp/maskbits.c # hw/xfree86/xf1bpp/mfbbitblt.c # hw/xfree86/xf1bpp/mfbbres.c # hw/xfree86/xf1bpp/mfbbresd.c # hw/xfree86/xf1bpp/mfbbstore.c # hw/xfree86/xf1bpp/mfbclip.c # hw/xfree86/xf1bpp/mfbcmap.c # hw/xfree86/xf1bpp/mfbfillarc.c # hw/xfree86/xf1bpp/mfbfillrct.c # hw/xfree86/xf1bpp/mfbfillsp.c # hw/xfree86/xf1bpp/mfbfont.c # hw/xfree86/xf1bpp/mfbgc.c # hw/xfree86/xf1bpp/mfbgetsp.c # hw/xfree86/xf1bpp/mfbhrzvert.c # hw/xfree86/xf1bpp/mfbimage.c # hw/xfree86/xf1bpp/mfbline.c # hw/xfree86/xf1bpp/mfbmisc.c # hw/xfree86/xf1bpp/mfbpixmap.c # hw/xfree86/xf1bpp/mfbpntwin.c # hw/xfree86/xf1bpp/mfbpolypnt.c # hw/xfree86/xf1bpp/mfbpushpxl.c # hw/xfree86/xf1bpp/mfbscrclse.c # hw/xfree86/xf1bpp/mfbscrinit.c # hw/xfree86/xf1bpp/mfbsetsp.c # hw/xfree86/xf1bpp/mfbwindow.c # hw/xfree86/xf1bpp/mfbzerarc.c # hw/xfree86/xorg.conf.example # hw/xfree86/xorg.conf.example.pre # ylwrap diff --git a/dix/Makefile.am b/dix/Makefile.am index a1f02c1..697c85e 100644 --- a/dix/Makefile.am +++ b/dix/Makefile.am @@ -26,6 +26,8 @@ libdix_la_SOURCES = \ pixmap.c \ privates.c \ property.c \ + ptrveloc.c \ + ptraccel.c \ resource.c \ swaprep.c \ swapreq.c \ diff --git a/dix/devices.c b/dix/devices.c index f622be7..c98c340 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -62,6 +62,7 @@ #include "inputstr.h" #include "scrnintstr.h" #include "cursorstr.h" #include "dixstruct.h" +#include "ptraccel.h" #include "site.h" #ifndef XKB_IN_SERVER #define XKB_IN_SERVER @@ -431,8 +432,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 @@ -819,6 +824,8 @@ InitValuatorClassDeviceStruct(DeviceIntP valc->lasty = 0; valc->dxremaind = 0; valc->dyremaind = 0; + valc->AccelScheme = acceleratePointerPlain; //simpler, needs no config + valc->accelData = NULL; dev->valuator = valc; /* biggest hack ever. */ diff --git a/dix/getevents.c b/dix/getevents.c index 3f636bc..5180b43 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,80 +198,6 @@ #endif } -/* 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 * 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); - } - } - } -} - - /** * Clip an axis to its bounds, which are declared in the call to * InitValuatorAxisClassStruct. @@ -546,9 +473,13 @@ GetPointerEvents(xEvent *events, DeviceI } } 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) { if (first_valuator == 0 && num_valuators >= 1) diff --git a/dix/ptraccel.c b/dix/ptraccel.c new file mode 100644 index 0000000..2035347 --- /dev/null +++ b/dix/ptraccel.c @@ -0,0 +1,156 @@ +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include + +/* + * acceleration schemes + */ + +/* 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); + } + } + } +} + +/** +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; + MouseVelocityPtr velocitydata = (MouseVelocityPtr) 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 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; +} diff --git a/dix/ptrveloc.c b/dix/ptrveloc.c new file mode 100644 index 0000000..5cb1eb3 --- /dev/null +++ b/dix/ptrveloc.c @@ -0,0 +1,243 @@ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "misc.h" +#include +#include + + + +/***************************************************************************** + * 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 (in case of the new scheme) selects the + * * Function, + * which in turn selects an acceleration for any given velocity. + * + * The Profile is a somewhat superfluous intermediary intended to + * cleanly emulate 'oldstyle' function selection (threshold =/!= 0) + ****************************************************************************/ + +/* +Init struct so it should match the average case +*/ +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 should be usable */ + s->const_acceleration = 1.0; /* no acceleration/deceleration */ + s->reset_time = 200; + 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->profile = ClassicProfile; + s->fading_lut_size = 0; + s->fading_lut = NULL; + InitFadingLookup(s, rdecay, 40); +} + +/* +Runtime-adjust weighting decay and lut in sync +*/ +void +InitFadingLookup(MouseVelocityPtr s, float rdecay, int lutsize) +{ + int x; + float *newlut; + float *oldlut; + + s->fading_lut_size = 0; /* prevent use of lut in transition */ + //if thread safety is needed am mem barrier should be here + if(lutsize > 0){ + newlut = xalloc (sizeof(float)* lutsize); + + 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); +} + + + +/* Perform velocity approximation + return true if non-visible state reset is suggested */ +short +ProcessVelocityData(MouseVelocityPtr s, int dx, int dy, int time) +{ + int diff = time - s->lrm_time; + /* cvelocity is not a real velocity yet, more a motion delta. Whether to + mulitply the contant acceleration here is a matter of taste; basically + it is about on-screen-verlocity vs. device velocity */ + float cvelocity = (float)sqrt(dx*dx + dy*dy);/* * s->const_acceleration;*/ + float fade, div; + short reset = FALSE; + + 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 (diff >= s->reset_time) { + /* 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-mouse adjustable factor) */ + cvelocity = cvelocity * s->corr_mul / (float)diff; + s->lrm_velocity = cvelocity; + + /* 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; + } + } + /* 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 ( > 1) 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; +} + + +void +ApplySofteningAndConstantDeceleration( + 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; +} + + + +/* 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. The function is given the whole +MouseVelocityPtr as param to be able to adapt the function so it holds +property (4) as specified in doc (bug#8583) +The code below doesn't and needs only the velocity field. +*/ +float +ClassicProfile( + MouseVelocityPtr pVel, + float threshold, + float acc){ + + if (threshold) { + return SimpleAccelerationFunc (pVel->velocity, + threshold, + acc); + } + else { + return PolynomialAccelerationFunc(pVel->velocity, + 0, + acc); + } +} + + + diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c index 17ffed8..1bba6c7 100644 --- a/hw/xfree86/common/xf86Xinput.c +++ b/hw/xfree86/common/xf86Xinput.c @@ -1,6 +1,6 @@ /* * Copyright 1995-1999 by Frederic Lepied, France. - * + * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that @@ -9,8 +9,8 @@ * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Frederic Lepied makes no * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * + * is provided "as is" without express or implied warranty. + * * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL FREDERIC LEPIED BE LIABLE FOR ANY SPECIAL, INDIRECT OR @@ -90,6 +90,10 @@ #include "xf86_OSproc.h" /* sigio stuff #include "mi.h" +#include /* dix pointer acceleration */ +#include + + #ifdef XFreeXDGA #include "dgaproc.h" #endif @@ -100,7 +104,7 @@ static Bool xf86SendDragEvents(DeviceIntPtr device) { LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate; - + if (device->button->buttonsDown > 0) return (local->flags & XI86_SEND_DRAG_EVENTS); else @@ -110,7 +114,7 @@ xf86SendDragEvents(DeviceIntPtr device) /*********************************************************************** * * xf86ProcessCommonOptions -- - * + * * Process global options. * *********************************************************************** @@ -137,10 +141,115 @@ xf86ProcessCommonOptions(LocalDevicePtr local->history_size = GetMotionHistorySize(); } +/** + * Eval config and init MouseVelocityData accordingly + */ +static MouseVelocityPtr +ProcessVelocityConfiguration(char* devname, pointer list){ + float tempf; + MouseVelocityPtr s = xalloc(sizeof(MouseVelocityData)); + + /* 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); + } + return s; +} + +/* + * evalute local device options and move to dix valuator + * Should be executed during init when valuator exists + */ +static void +ApplyExtendedValuatorSettings(LocalDevicePtr local, char* caller){ + int scheme; + /* Apply improved acceleration; Better be a device-class final init proc + * or whatever... + */ + if(local && local->dev && local->dev->valuator + && (strcmp (local->type_name, XI_MOUSE) == 0)){ + /* Enable improved pointer acceleration by reading its options + which later get applied (when valuator is inited) */ + scheme = xf86SetIntOption(local->options, "AccelerationScheme", 1); + switch(scheme){ + case 0: + local->dev->valuator->AccelScheme = acceleratePointerPlain; + break; + case 1: + local->dev->valuator->accelData = ProcessVelocityConfiguration( + local->name, + local->options); + local->dev->valuator->AccelScheme = acceleratePointer; + break; + } + /*xf86Msg(X_CONFIG, "%s: $%() success type %s from %s\n", local->name, + local->type_name, caller);*/ + } + /*else{ //Debug stuff + int a1 = 0, a2 = 0, a3 = 0; + if(local){ + a1 = 1; + if(local->dev){ + a2 = 1; + if(local->dev->valuator) + a3 = 1; + } + } + xf86Msg(X_CONFIG, "%s: $%() fail type %s from %s (%1i|%1i|%1i)\n", local->name, local->type_name, caller, a1, a2, a3); + }*/ +} + /*********************************************************************** * * xf86ActivateDevice -- - * + * * Initialize an input device. * *********************************************************************** @@ -155,18 +264,18 @@ xf86ActivateDevice(LocalDevicePtr local) if (dev == NULL) FatalError("Too many input devices"); - + local->atom = MakeAtom(local->type_name, strlen(local->type_name), TRUE); AssignTypeAndName(dev, local->atom, local->name); dev->public.devicePrivate = (pointer) local; - local->dev = dev; - + local->dev = dev; + dev->coreEvents = local->flags & XI86_ALWAYS_CORE; RegisterOtherDevice(dev); - if (serverGeneration == 1) + if (serverGeneration == 1) xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n", local->name, local->type_name); } @@ -183,7 +292,7 @@ #ifdef XINPUT * initialized, and never close them. Other implementations open only * the X pointer and keyboard devices during server initialization, * and only open other input devices when some client makes an - * XOpenDevice request. This entry point is for the latter type of + * XOpenDevice request. This entry point is for the latter type of * implementation. * * If the physical device is not already open, do it here. In this case, @@ -389,7 +498,7 @@ NewInputDeviceRequest (InputOption *opti return Success; } -/* +/* * convenient functions to post events */ @@ -413,7 +522,7 @@ xf86PostMotionEvent(DeviceIntPtr device, flags = POINTER_ABSOLUTE; else flags = POINTER_RELATIVE | POINTER_ACCELERATE; - + valuators = xcalloc(sizeof(int), num_valuators); va_start(var, num_valuators); @@ -484,7 +593,7 @@ xf86PostProximityEvent(DeviceIntPtr devi FatalError("Couldn't allocate event store\n"); nevents = GetProximityEvents(xf86Events, device, - is_in ? ProximityIn : ProximityOut, + is_in ? ProximityIn : ProximityOut, first_valuator, num_valuators, valuators); for (i = 0; i < nevents; i++) mieqEnqueue(device, xf86Events + i); @@ -513,7 +622,7 @@ #if XFreeXDGA return; } #endif - + valuators = xcalloc(sizeof(int), num_valuators); va_start(var, num_valuators); @@ -617,7 +726,7 @@ xf86FirstLocalDevice() return xf86InputDevs; } -/* +/* * Cx - raw data from touch screen * Sxhigh - scaled highest dimension * (remember, this is of rows - 1 because of 0 origin) @@ -649,12 +758,12 @@ xf86ScaleAxis(int Cx, X = 0; ErrorF ("Divide by Zero in xf86ScaleAxis"); } - + if (X > Sxlow) X = Sxlow; if (X < Sxhigh) X = Sxhigh; - + return (X); } @@ -679,13 +788,17 @@ xf86XInputSetScreen(LocalDevicePtr local _X_EXPORT void xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval, - int resolution, int min_res, int max_res) + int resolution, int min_res, int max_res) { if (!dev || !dev->valuator) return; InitValuatorAxisStruct(dev, axnum, minval, maxval, resolution, min_res, - max_res); + max_res); + /*could as well be arguments to InitValuatorAxisStruct... + also this fn gets called twice, once for each axis */ + if(axnum == 0) + ApplyExtendedValuatorSettings(dev->public.devicePrivate, "xf86InitValuatorAxisStruct"); } /* diff --git a/include/inputstr.h b/include/inputstr.h index 8f4e9b9..3951dd9 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -52,6 +52,7 @@ #define INPUTSTRUCT_H #include "input.h" #include "window.h" #include "dixstruct.h" +#include "ptraccel.h" #define BitIsOn(ptr, bit) (((BYTE *) (ptr))[(bit)>>3] & (1 << ((bit) & 7))) @@ -158,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 */ + PointerSchemeProc AccelScheme; + void *accelData; /* at disposal of AccelScheme */ CARD8 mode; } ValuatorClassRec, *ValuatorClassPtr; diff --git a/include/ptraccel.h b/include/ptraccel.h new file mode 100644 index 0000000..8a06de6 --- /dev/null +++ b/include/ptraccel.h @@ -0,0 +1,23 @@ + +#ifndef POINTERACCELERATIONSCHEMES_H +#define POINTERACCELERATIONSCHEMES_H + +//an acceleration scheme +typedef void (*PointerSchemeProc)( + DeviceIntPtr pDev, + int first_valuator, + int num_valuators, + int *valuators, + int evtime); + + +void +acceleratePointer(DeviceIntPtr pDev, int first_valuator, int num_valuators, + int *valuators, int evtime); + + +void +acceleratePointerPlain(DeviceIntPtr pDev, int first_valuator, + int num_valuators, int *valuators, int ignore); + +#endif /* POINTERACCELERATIONSCHEMES_H */ diff --git a/include/ptrveloc.h b/include/ptrveloc.h new file mode 100644 index 0000000..381f503 --- /dev/null +++ b/include/ptrveloc.h @@ -0,0 +1,77 @@ +/* +* 2006/2007 by Simon Thum +*/ + +#ifndef POINTERVELOCITY_H +#define POINTERVELOCITY_H + +struct _MouseVelocityData; + +/* return acceleration for velocity/threshold (profile) */ +typedef float (*PointerAccelerationProfileFunc) + (struct _MouseVelocityData* /*pVel*/, + float /*threshold*/, float /*acc*/); + +/* Contains all Data needed to implement mouse ballistics */ + +typedef struct _MouseVelocityData { + /* time the last motion event was processed */ + int lrm_time; + /* velocity as guessed by algo (read: weighted) */ + float velocity; + /* velocity as from last movement event */ + float lrm_velocity; + /* last motions delta (for cheap softening algo) */ + int last_dx, last_dy; + /* 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; + /* selected acceleration profile */ + PointerAccelerationProfileFunc profile; + /* config: maximum divergence to allow weighted velocity to be taken */ + float coupling; +} MouseVelocityData, *MouseVelocityPtr; + + +extern void +InitVelocityData(MouseVelocityPtr s, float rdecay); + +extern void +InitFadingLookup(MouseVelocityPtr s, float rdecay, int lutsize); + +extern short +ProcessVelocityData(MouseVelocityPtr s, int dx, int dy, int time); + +extern void +ApplySofteningAndConstantDeceleration( + MouseVelocityPtr s, + int dx, + int dy, + float* fdx, + float* fdy, + short do_soften); + +extern float ClassicProfile(MouseVelocityPtr /*pVel*/, + float /*threshold*/, float /*max_acc*/); + + +#endif /* POINTERVELOCITY_H */