Hey again!

I'm sending hopefully a better version of my wheel emulation patch. I merged 
the configuration properties into two multivalued, as Peter advised. Otherwise 
the functionality remains the same.

If somebody actually tries this, please give me some feedback and ideas for 
improvement ;)

Have a great day!

Lukas

Signed-off-by: Lukas Zilka <[email protected]>
---
 include/wacom-properties.h |    6 ++
 src/wcmCommon.c            |  130 ++++++++++++++++++++++++++++++++++++++------
 src/wcmConfig.c            |    6 ++
 src/wcmXCommand.c          |   31 +++++++++++
 src/xf86WacomDefs.h        |   10 ++++
 5 files changed, 167 insertions(+), 16 deletions(-)

diff --git a/include/wacom-properties.h b/include/wacom-properties.h
index f6633a1..8785e04 100644
--- a/include/wacom-properties.h
+++ b/include/wacom-properties.h
@@ -96,4 +96,10 @@
  */
 #define WACOM_PROP_DEBUGLEVELS "Wacom Debug Levels"
 
+/* 32bit, 32bit - movement tolerance (-> start scrolling after exceeding this 
distance), delay in miliseconds between 2 consecutive scrolls sent */
+#define WACOM_PROP_WHEEL_SCROLL_PARAMETERS "Wacom Wheel Emulation Scroll 
Parameters"
+
+/* bool, 8 bit, bool - on/off, button number, scroll only when floating above 
tablet? */
+#define WACOM_PROP_WHEEL_EMULATION "Wacom Wheel Emulation"
+
 #endif
diff --git a/src/wcmCommon.c b/src/wcmCommon.c
index 7e50878..e77bc8e 100644
--- a/src/wcmCommon.c
+++ b/src/wcmCommon.c
@@ -810,7 +810,7 @@ void wcmSendEvents(InputInfoPtr pInfo, const 
WacomDeviceState* ds)
                         */
                        if (!is_absolute(pInfo))
                                x *= priv->factorY / priv->factorX;
-                       else
+                       else
                        {
                                /* Padding virtual values */
                                wcmVirtualTabletPadding(pInfo);
@@ -822,25 +822,39 @@ void wcmSendEvents(InputInfoPtr pInfo, const 
WacomDeviceState* ds)
                        if ((pInfo->dev->proximity && !priv->oldProximity))
                                xf86PostProximityEvent(pInfo->dev, 1, 0, naxes, 
x, y, z, v3, v4, v5);
 
-                       /* Move the cursor to where it should be before sending 
button events */
-                       if(!(priv->flags & BUTTONS_ONLY_FLAG))
+                       /* do the usual only if we are not scrolling (scrolling 
conditions aren't met) */
+                       if( !wcmWheelEmuScrollButtonPressed( ds, priv ) )
                        {
-                               xf86PostMotionEvent(pInfo->dev, 
is_absolute(pInfo),
-                                       0, naxes, x, y, z, v3, v4, v5);
-                               /* For relative events, reset the axes as
-                                * we've already moved the device by the
-                                * relative amount. Otherwise, a button
-                                * event in sendCommonEvents will move the
-                                * axes again.
-                                */
-                               if (!is_absolute(pInfo))
+                               /* Move the cursor to where it should be before 
sending button events */
+                               if(!(priv->flags & BUTTONS_ONLY_FLAG))
                                {
-                                       x = y = z = 0;
-                                       v3 = v4 = v5 = 0;
+                                       xf86PostMotionEvent(pInfo->dev, 
is_absolute(pInfo),
+                                                       0, naxes, x, y, z, v3, 
v4, v5);
+                                       /* For relative events, reset the axes 
as
+                                        * we've already moved the device by the
+                                        * relative amount. Otherwise, a button
+                                        * event in sendCommonEvents will move 
the
+                                        * axes again.
+                                        */
+                                       if (!is_absolute(pInfo))
+                                       {
+                                               x = y = z = 0;
+                                               v3 = v4 = v5 = 0;
+                                       }
+                               }
+                               sendCommonEvents(pInfo, ds, x, y, z, v3, v4, 
v5);
+                               /* the srolling button is not pressed, so make 
sure that scrolling is stopped */
+                               if( wcmWheelEmuIsScrolling( priv ) ) {
+                                       wcmWheelEmuScrollOff( priv );
+                               }
+                       } else {
+                               /* the scrolling button is pressed, so start 
scrolling if it hasn't already been started */
+                               if( !wcmWheelEmuIsScrolling( priv ) ) {
+                                       wcmWheelEmuScrollOn( priv, x, y );
                                }
                        }
-
-                       sendCommonEvents(pInfo, ds, x, y, z, v3, v4, v5);
+                       /* do the scrolling stuff */
+                       wcmWheelEmuScroll( priv );
                }
                else /* not in proximity */
                {
@@ -1951,4 +1965,88 @@ WacomCommonPtr wcmRefCommon(WacomCommonPtr common)
        return common;
 }
 
+int wcmWheelEmuIsScrolling( WacomDevicePtr priv ) {
+    return priv->scrolling;
+}
+
+void wcmWheelEmuScrollOff( WacomDevicePtr priv ) {
+       priv->scrolling = 0;
+}
+
+void wcmWheelEmuScrollOn( WacomDevicePtr priv, int x, int y ) {
+               priv->scrollX = x;
+               priv->scrollY = y;
+               priv->scrolling = 1;
+}
+
+int wcmWheelEmuScrollButtonPressed( const WacomDeviceState* ds, WacomDevicePtr 
priv ) {
+       /* if the scroll-only-when-floating-above-the-tablet option has been 
set in parameters,
+        * we want to scroll only when the button that is activated when the 
stylus touches the 
+        * tablet is not activated. in the other case 
(scroll-only-when-floating-above-the-tablet
+        * is not set), we don't care about this button, and all we care about 
is the scroll button. */
+
+       /* if the wheel emulation is disabled, return false */
+       if( ! priv->common->wcmWheelEmuEnabled ) {
+           return 0;
+       }
+
+       /* check if the scroll button is pressed */
+       if( ( ds-> buttons & priv->common->wcmScrollButton ) == 
priv->common->wcmScrollButton ) {
+               /* if it is pressed, and the scroll-only-when-floating property 
is not set, return true */
+               if( !priv->common->wcmScrollOnlyFloating ) {
+                   return 1;
+               } else {
+                   /* else, check if the stylus doesn't touch the tablet by 
examining the pressed buttons
+                    * for the Button1 one. it can't be on. */
+                   if( ( ds-> buttons & 1 ) == 0 ) {
+                           return 1;
+                   } else {
+                       return 0;
+                   }
+               }
+
+
+       } else {
+               /* if not, return false */
+               return 0;
+       }
+
+}
+
+void wcmWheelEmuScroll( WacomDevicePtr priv, x, y, z, v3, v4, v5 ) {
+       /* start the scrolling procedure only if we are supposed to scroll */
+       if( priv->common->wcmWheelEmuEnabled && wcmWheelEmuIsScrolling( priv ) 
) {
+               /* for scrolling direction */
+               int scroll_where;
+               /* some movement tolerance so as not to yet scroll if we 
haven't moved enough */
+               int scroll_thresh = priv->common->wcmScrollThresh; 
+               /* set scrolling speed in steps of threshold */
+               int scroll_speed = abs(y - priv->scrollY)/scroll_thresh;
+               /* timeout = delay between 2 consecutive scrolls that are 
sent.. so that we don't scroll too fast */
+               int scroll_timeout = 
(1.0*priv->common->wcmScrollTimeout)/scroll_speed;
+
+               /* determine the scrolling direction (mousebutton 4 scroll up, 
5 scroll down, 0 don't scroll as the mouse
+               * hasn't exceeded the threshold value) */
+               if( y < priv->scrollY && abs(y - priv->scrollY) > scroll_thresh 
) 
+                       scroll_where = 4;
+               else {
+                       if( y > priv->scrollY && abs(y - priv->scrollY) > 
scroll_thresh ) 
+                               scroll_where = 5;
+                       else
+                               scroll_where = 0;
+               }
+
+               /* if there is somewhere to scroll, and if the timeout from the 
last executed scroll has passed,
+                * scroll - send the X events */
+               if( scroll_where != 0 && priv->lastScrolled + scroll_timeout < 
GetTimeInMillis() ) {
+                       xf86PostButtonEvent(pInfo->dev, is_absolute(pInfo),
+                                       scroll_where,1,0,priv->naxes, 
priv->scrollX,priv->scrollY,z,v3,v4,v5);
+                       xf86PostButtonEvent(pInfo->dev, is_absolute(pInfo),
+                                       scroll_where,0,0,priv->naxes, 
priv->scrollX,priv->scrollY,z,v3,v4,v5);
+
+                       priv->lastScrolled = GetTimeInMillis();
+               }
+       }
+}
+
 /* vim: set noexpandtab shiftwidth=8: */
diff --git a/src/wcmConfig.c b/src/wcmConfig.c
index 2fdacfa..208101a 100644
--- a/src/wcmConfig.c
+++ b/src/wcmConfig.c
@@ -135,6 +135,12 @@ static int wcmAllocate(InputInfoPtr pInfo)
                        /* transmit position if increment is superior */
        common->wcmRawSample = DEFAULT_SAMPLES;    
                        /* number of raw data to be used to for filtering */
+       
+       common->wcmWheelEmuEnabled = 1;
+       common->wcmScrollThresh = 100;
+       common->wcmScrollTimeout = 100;
+       common->wcmScrollButton = 2;
+       common->wcmScrollOnlyFloating = 1;
 
        /* tool */
        priv->tool = tool;
diff --git a/src/wcmXCommand.c b/src/wcmXCommand.c
index ed14de5..dd45746 100644
--- a/src/wcmXCommand.c
+++ b/src/wcmXCommand.c
@@ -110,6 +110,8 @@ Atom prop_btnactions;
 #ifdef DEBUG
 Atom prop_debuglevels;
 #endif
+Atom prop_wheel_emu;
+Atom prop_wheel_emu_scroll_params;
 
 /* Special case: format -32 means type is XA_ATOM */
 static Atom InitWcmAtom(DeviceIntPtr dev, char *name, int format, int nvalues, 
int *values)
@@ -255,6 +257,16 @@ void InitWcmDeviceProperties(InputInfoPtr pInfo)
        values[1] = common->debugLevel;
        prop_debuglevels = InitWcmAtom(pInfo->dev, WACOM_PROP_DEBUGLEVELS, 8, 
2, values);
 #endif
+       /* wheel emulation settings - on/off, button, scroll-only-when-floating 
*/
+       values[0] = common->wcmWheelEmuEnabled;
+       values[1] = common->wcmScrollButton;
+       values[2] = common->wcmScrollOnlyFloating;
+       prop_wheel_emu = InitWcmAtom(pInfo->dev, WACOM_PROP_WHEEL_EMULATION, 8, 
3, values);
+       
+       /* scrolling parameters - movement tolerance, delay between 2 scrolls */
+       values[0] = common->wcmScrollThresh;
+       values[1] = common->wcmScrollTimeout;
+       prop_scroll_params = InitWcmAtom(pInfo->dev, 
WACOM_PROP_SCROLL_PARAMETERS, 32, 1, values);
 }
 
 /* Returns the offset of the property in the list given. If the property is
@@ -881,6 +893,25 @@ int wcmSetProperty(DeviceIntPtr dev, Atom property, 
XIPropertyValuePtr prop,
                if (prop->size != WCM_MAX_MOUSE_BUTTONS)
                        return BadMatch;
                wcmSetPropertyButtonActions(dev, property, prop, checkonly);
+       } else if (property == prop_wheel_emu)
+       {
+               CARD8 *values = (CARD8*)prop->data;
+
+               if (prop->size != 3 || prop->format != 8)
+                       return BadValue;
+
+               common->wcmWheelEmuEnabled = values[0];
+               common->wcmScrollButton = values[1];
+               common->wcmScrollOnlyFloating = values[2];
+       } else if (property == prop_scroll_params)
+       {
+               CARD32 *values = (CARD32*)prop->data;
+
+               if (prop->size != 2 || prop->format != 32)
+                       return BadValue;
+               
+               common->wcmScrollThreshold = values[0];
+               common->wcmScrollTimeout = values[1];
        } else
                wcmSetActionProperties(dev, property, prop, checkonly);
 
diff --git a/src/xf86WacomDefs.h b/src/xf86WacomDefs.h
index dcd21fc..45b1766 100644
--- a/src/xf86WacomDefs.h
+++ b/src/xf86WacomDefs.h
@@ -225,6 +225,10 @@ struct _WacomDeviceRec
        int oldX;               /* previous X position */
        int oldY;               /* previous Y position */
        int oldZ;               /* previous pressure */
+       int scrolling;          /* are we scrolling now? */
+       int scrollX;            /* the mouseX position when the scroll button 
was pressed */
+       int scrollY;            /* the mouseY position when the scroll button 
was pressed */
+       int lastScrolled;       /* the time in milliseconds, when the last 
scroll event has been sent */
        int oldCapacity;        /* previous capacity */
        int oldTiltX;           /* previous tilt in x direction */
        int oldTiltY;           /* previous tilt in y direction */    
@@ -445,6 +449,12 @@ struct _WacomCommonRec
        void *private;               /* backend-specific information */
 
        WacomToolPtr wcmTool; /* List of unique tools */
+       
+       int wcmWheelEmuEnabled; /* enable/disable the wheel emulation */
+       int wcmScrollThresh;    /* the distance that the mouse must surpass in 
order for us to start scrolling */
+       int wcmScrollTimeout;   /* the delay between sending another scroll 
event */
+       int wcmScrollButton;    /* the button that activates scrolling */
+       int wcmScrollOnlyFloating; /* the 
scroll-only-if-the-stylus-is-floating-above-the-tablet option */
 
        /* DO NOT TOUCH THIS. use wcmRefCommon() instead */
        int refcnt;                     /* number of devices sharing this 
struct */
-- 
1.7.0.4


------------------------------------------------------------------------------
This SF.net email is sponsored by 

Make an app they can't live without
Enter the BlackBerry Developer Challenge
http://p.sf.net/sfu/RIM-dev2dev 
_______________________________________________
Linuxwacom-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel

Reply via email to