Replaces sendWheelStripEvents and getWheelButton with several
small functions to reduce unnecessary code duplication.

As a side-effect, it is now possible for the driver to handle
simultaneous scrolls on multiple axes. Previously, getWheelButton
would go through all the axes but was limited to returning a
single button/action.

Signed-off-by: Jason Gerecke <killert...@gmail.com>
---
 src/wcmCommon.c |  206 ++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 121 insertions(+), 85 deletions(-)

diff --git a/src/wcmCommon.c b/src/wcmCommon.c
index 0e719cf..170d1d0 100644
--- a/src/wcmCommon.c
+++ b/src/wcmCommon.c
@@ -317,98 +317,106 @@ static void sendAButton(InputInfoPtr pInfo, int button, 
int mask,
                   first_val, num_val, valuators);
 }
 
-/*****************************************************************************
- * getWheelButton --
- *   Get the wheel button to be sent for the current device state.
- ****************************************************************************/
-
-static int getWheelButton(InputInfoPtr pInfo, const WacomDeviceState* ds,
-                         unsigned int **fakeKey)
+/**
+ * Get the distance an axis was scrolled. This function is aware
+ * of the different ways different scrolling axes work and strives
+ * to produce a common representation of relative change.
+ *
+ * @param current  Current value of the axis
+ * @param old      Previous value of the axis
+ * @param wrap     Value after which wraparound occurs (0 if axis does not 
wrap)
+ * @param invert   Scroll axis is inverted
+ * @param bitwise  Scroll axis values change in a bitwise manner
+ * @return         Relative change in axis value
+ */
+static int getScrollDelta(int current, int old, int wrap, Bool invert, Bool 
bitwise)
 {
-       WacomDevicePtr priv = (WacomDevicePtr) pInfo->private;
-       int fakeButton = 0, value = 0;
+       int delta;
 
-       /* emulate events for relative wheel */
-       if ( ds->relwheel )
+       if (bitwise)
        {
-               value = ds->relwheel;
-               fakeButton = (value > 0) ? priv->relup : priv->reldn;
-               *fakeKey = (value > 0) ? priv->wheel_keys[0+1] : 
priv->wheel_keys[1+1];
+               current = (int)log2(current);
+               old = (int)log2(old);
        }
 
-       /* emulate events for absolute wheel when it is a touch ring (on pad) */
-       if ( (ds->abswheel != priv->oldWheel) && IsPad(priv) &&
-           (priv->oldProximity == ds->proximity))
-       {
-               int wrap_delta;
-               value = priv->oldWheel - ds->abswheel;
-
-               /* Wraparound detection. If the distance oldvalue..value is
-                * larger than the oldvalue..value considering the
-                * wraparound, assume wraparound and readjust */
-               if (value < 0)
-                       wrap_delta = ((MAX_PAD_RING + 1) + priv->oldWheel) - 
ds->abswheel;
-               else
-                       wrap_delta = priv->oldWheel - ((MAX_PAD_RING + 1) + 
ds->abswheel);
+       delta = current - old;
 
-               DBG(12, priv, "wrap detection for %d (old %d): %d (wrap %d)\n",
-                   ds->abswheel, priv->oldWheel, value, wrap_delta);
+       if (invert)
+               delta = -delta;
 
-               if (abs(wrap_delta) < abs(value))
-                       value = wrap_delta;
-
-               fakeButton = (value > 0) ? priv->wheelup : priv->wheeldn;
-               *fakeKey = (value > 0) ? priv->wheel_keys[2+1] : 
priv->wheel_keys[3+1];
-       }
-
-       /* emulate events for 2nd absolute wheel when it is a touch ring (on 
pad) */
-       if ( (ds->abswheel2 != priv->oldWheel2) && IsPad(priv) &&
-           (priv->oldProximity == ds->proximity))
+       if (wrap != 0)
        {
+               /* Wraparound detection. If the distance old..current
+                * is larger than the old..current considering the
+                * wraparound, assume wraparound and readjust */
                int wrap_delta;
-               value = priv->oldWheel2 - ds->abswheel2;
 
-               /* Wraparound detection. If the distance oldvalue..value is
-                * larger than the oldvalue..value considering the
-                * wraparound, assume wraparound and readjust */
-               if (value < 0)
-                       wrap_delta = ((MAX_PAD_RING + 1) + priv->oldWheel2) - 
ds->abswheel2;
+               if (delta < 0)
+                       wrap_delta = (wrap + 1) + delta;
                else
-                       wrap_delta = priv->oldWheel2 - ((MAX_PAD_RING + 1) + 
ds->abswheel2);
+                       wrap_delta = -((wrap + 1) - delta);
 
-               DBG(12, priv, "wrap detection for %d (old %d): %d (wrap %d)\n",
-                   ds->abswheel2, priv->oldWheel2, value, wrap_delta);
+               if (abs(wrap_delta) < abs(delta))
+                       delta = wrap_delta;
+       }
 
-               if (abs(wrap_delta) < abs(value))
-                       value = wrap_delta;
+       return delta;
+}
 
-               fakeButton = (value > 0) ? priv->wheel2up : priv->wheel2dn;
-               *fakeKey = (value > 0) ? priv->wheel_keys[4+1] : 
priv->wheel_keys[5+1];
-       }
+/**
+ * Get the scroll button/action to send given the delta of
+ * the scrolling axis and the possible events that can be
+ * sent.
+ * 
+ * @param delta        Amount of change in the scrolling axis
+ * @param button_up    Button event to send on scroll up
+ * @param button_dn    Button event to send on scroll down
+ * @param action_up    Action to send on scroll up
+ * @param action_dn    Action to send on scroll down
+ * @param[out] action  Action that should be performed
+ * @return             Button that should be pressed
+ */
+static int getWheelButton(int delta, int button_up, int button_dn,
+                          unsigned int *action_up, unsigned int *action_dn,
+                          unsigned int **action)
+{
+       int button = 0;
+       *action = NULL;
 
-       /* emulate events for left strip */
-       if ( ds->stripx != priv->oldStripX )
+       if (delta)
        {
-               value = ds->stripx - priv->oldStripX;
-
-               fakeButton = (value < 0) ? priv->striplup : priv->stripldn;
-               *fakeKey = (value < 0) ? priv->strip_keys[0+1] : 
priv->strip_keys[1+1];
+               button  = delta > 0 ? button_up : button_dn;
+               *action = delta > 0 ? action_up : action_dn;
        }
 
-       /* emulate events for right strip */
-       if ( ds->stripy != priv->oldStripY )
-       {
-               value = ds->stripy - priv->oldStripY;
+       return button;
+}
 
-               fakeButton = (value < 0) ? priv->striprup : priv->striprdn;
-               *fakeKey = (value < 0) ? priv->strip_keys[2+1] : 
priv->strip_keys[3+1];
-       }
+/**
+ * Send button or actions for a scrolling axis.
+ *
+ * @param button     X button number to send if no action is defined
+ * @param action     Action to send
+ * @param pInfo
+ * @param first_val  
+ * @param num_vals
+ * @param valuators
+ */
+static void sendWheelStripEvent(int button, unsigned int *action, InputInfoPtr 
pInfo,
+                                 int first_val, int num_vals, int *valuators)
+{
+       WacomDevicePtr priv = (WacomDevicePtr) pInfo->private;
 
-       DBG(10, priv, "send fakeButton %x with value = %d \n",
-               fakeButton, value);
+       unsigned int button_action[1] = {button | AC_BUTTON | AC_KEYBTNPRESS};
+       if (!action || !(*action)) {
+               DBG(10, priv, "No wheel/strip action set; sending button %d 
(action %d).\n", button, button_action[0]);
+               action = &button_action[0];
+       }
 
-       return fakeButton;
+       sendAction(pInfo, 1, action, ARRAY_SIZE(action), first_val, num_vals, 
valuators);
+       sendAction(pInfo, 0, action, ARRAY_SIZE(action), first_val, num_vals, 
valuators);
 }
+
 /*****************************************************************************
  * sendWheelStripEvents --
  *   Send events defined for relative/absolute wheels or strips
@@ -418,31 +426,59 @@ static void sendWheelStripEvents(InputInfoPtr pInfo, 
const WacomDeviceState* ds,
                                 int first_val, int num_vals, int *valuators)
 {
        WacomDevicePtr priv = (WacomDevicePtr) pInfo->private;
-       int fakeButton = 0;
+       int fakeButton = 0, delta = 0;
        unsigned int *fakeKey = NULL;
 
        DBG(10, priv, "\n");
 
-       fakeButton = getWheelButton(pInfo, ds, &fakeKey);
+       /* emulate events for left strip */
+       delta = getScrollDelta(ds->stripx, priv->oldStripX, 0, TRUE, TRUE);
+       if (delta && IsPad(priv) && priv->oldProximity == ds->proximity)
+       {
+               DBG(10, priv, "Left touch strip scroll delta = %d\n", delta);
+               fakeButton = getWheelButton(delta, priv->striplup, 
priv->stripldn,
+                                           priv->strip_keys[0+1], 
priv->strip_keys[1+1], &fakeKey);
+               sendWheelStripEvent(fakeButton, fakeKey, pInfo, first_val, 
num_vals, valuators);
+       }
 
-       if (!fakeButton && (!fakeKey || !(*fakeKey)))
-               return;
+       /* emulate events for right strip */
+       delta = getScrollDelta(ds->stripy, priv->oldStripY, 0, TRUE, TRUE);
+       if (delta && IsPad(priv) && priv->oldProximity == ds->proximity)
+       {
+               DBG(10, priv, "Right touch strip scroll delta = %d\n", delta);
+               fakeButton = getWheelButton(delta, priv->striprup, 
priv->striprdn,
+                                           priv->strip_keys[2+1], 
priv->strip_keys[3+1], &fakeKey);
+               sendWheelStripEvent(fakeButton, fakeKey, pInfo, first_val, 
num_vals, valuators);
+       }
 
-       if (!fakeKey || !(*fakeKey))
+       /* emulate events for relative wheel */
+       delta = getScrollDelta(ds->relwheel, 0, 0, FALSE, FALSE);
+       if (delta && IsCursor(priv) && priv->oldProximity == ds->proximity)
        {
-               /* send both button on/off in the same event for pad */
-               xf86PostButtonEventP(pInfo->dev, is_absolute(pInfo), fakeButton 
& AC_CODE,
-                                    1, first_val, num_vals, VCOPY(valuators, 
num_vals));
+               DBG(10, priv, "Relative wheel scroll delta = %d\n", delta);
+               fakeButton = getWheelButton(delta, priv->relup, priv->reldn,
+                                           priv->wheel_keys[0+1], 
priv->wheel_keys[1+1], &fakeKey);
+               sendWheelStripEvent(fakeButton, fakeKey, pInfo, first_val, 
num_vals, valuators);
+       }
 
-               xf86PostButtonEventP(pInfo->dev, is_absolute(pInfo), fakeButton 
& AC_CODE,
-                                    0, first_val, num_vals, VCOPY(valuators, 
num_vals));
+       /* emulate events for left touch ring */
+       delta = getScrollDelta(ds->abswheel, priv->oldWheel, MAX_PAD_RING, 
TRUE, FALSE);
+       if (delta && IsPad(priv) && priv->oldProximity == ds->proximity)
+       {
+               DBG(10, priv, "Left touch wheel scroll delta = %d\n", delta);
+               fakeButton = getWheelButton(delta, priv->wheelup, priv->wheeldn,
+                                           priv->wheel_keys[2+1], 
priv->wheel_keys[3+1], &fakeKey);
+               sendWheelStripEvent(fakeButton, fakeKey, pInfo, first_val, 
num_vals, valuators);
        }
-       else
+
+       /* emulate events for right touch ring */
+       delta = getScrollDelta(ds->abswheel2, priv->oldWheel2, MAX_PAD_RING, 
TRUE, FALSE);
+       if (delta && IsPad(priv) && priv->oldProximity == ds->proximity)
        {
-               sendAction(pInfo, 1, fakeKey, ARRAY_SIZE(priv->wheel_keys[0]),
-                          first_val, num_vals, valuators);
-               sendAction(pInfo, 0, fakeKey, ARRAY_SIZE(priv->wheel_keys[0]),
-                          first_val, num_vals, valuators);
+               DBG(10, priv, "Right touch wheel scroll delta = %d\n", delta);
+               fakeButton = getWheelButton(delta, priv->wheel2up, 
priv->wheel2dn,
+                                           priv->wheel_keys[4+1], 
priv->wheel_keys[5+1], &fakeKey);
+               sendWheelStripEvent(fakeButton, fakeKey, pInfo, first_val, 
num_vals, valuators);
        }
 }
 
-- 
1.7.7.3


------------------------------------------------------------------------------
Systems Optimization Self Assessment
Improve efficiency and utilization of IT resources. Drive out cost and 
improve service delivery. Take 5 minutes to use this Systems Optimization 
Self Assessment. http://www.accelacomm.com/jaw/sdnl/114/51450054/
_______________________________________________
Linuxwacom-devel mailing list
Linuxwacom-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel

Reply via email to