On Wed, Dec 21, 2011 at 03:28:54PM -0800, Jason Gerecke wrote:
> 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>

Reviewed-by: Peter Hutterer <peter.hutte...@who-t.net>

thank you!

Cheers,
  Peter

> ---
> Changes from v3:
>  * Move to head of patchset
>  * Add tests for getScrollDelta and getWheelButton
>  * Fix bugs in getScrollDelta doc (wrap is max, not max+1)
>  * Fix bugs in getScrollDelta implementation
>     * log2(0) is undef; caused problems with current or old == 0
>     * wrap now properly handled with AXIS_BITWISE
> 
>  src/wcmCommon.c     |  177 
> +++++++++++++++++++++++++++++++++------------------
>  src/xf86WacomDefs.h |    2 +
>  test/wacom-tests.c  |   84 ++++++++++++++++++++++++
>  3 files changed, 200 insertions(+), 63 deletions(-)
> 
> diff --git a/src/wcmCommon.c b/src/wcmCommon.c
> index e85c6d8..e6eb958 100644
> --- a/src/wcmCommon.c
> +++ b/src/wcmCommon.c
> @@ -317,73 +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     Maximum value before wraparound occurs (0 if axis does 
> not wrap)
> + * @param flags    Flags defining axis attributes: AXIS_INVERT and 
> AXIS_BITWISE
> + * @return         Relative change in axis value
> + */
> +static int getScrollDelta(int current, int old, int wrap, int flags)
>  {
> -     WacomDevicePtr priv = (WacomDevicePtr) pInfo->private;
> -     int fakeButton = 0, value = 0;
> +     int delta;
>  
> -     /* emulate events for relative wheel */
> -     if ( ds->relwheel )
> +     if (flags & AXIS_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 << 1) | 0x01);
> +             old = (int)log2((old << 1) | 0x01);
> +             wrap = (int)log2((wrap << 1) | 0x01);
>       }
>  
> -     /* emulate events for absolute wheel when it is a touch ring (on pad) */
> -     if ( (ds->abswheel != priv->oldWheel) && IsPad(priv) &&
> -         (priv->oldProximity == ds->proximity))
> +     delta = current - old;
> +
> +     if (flags & AXIS_INVERT)
> +             delta = -delta;
> +
> +     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->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;
> +             if (delta < 0)
> +                     wrap_delta =  (wrap + 1) + delta;
>               else
> -                     wrap_delta = priv->oldWheel - ((MAX_PAD_RING + 1) + 
> ds->abswheel);
> +                     wrap_delta = -((wrap + 1) - delta);
>  
> -             DBG(12, priv, "wrap detection for %d (old %d): %d (wrap %d)\n",
> -                 ds->abswheel, priv->oldWheel, 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->wheelup : priv->wheeldn;
> -             *fakeKey = (value > 0) ? priv->wheel_keys[2+1] : 
> priv->wheel_keys[3+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
> @@ -393,31 +426,49 @@ 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);
> -
> -     if (!fakeButton && (!fakeKey || !(*fakeKey)))
> -             return;
> +     /* emulate events for left strip */
> +     delta = getScrollDelta(ds->stripx, priv->oldStripX, 0, AXIS_INVERT | 
> AXIS_BITWISE);
> +     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 (!fakeKey || !(*fakeKey))
> +     /* emulate events for right strip */
> +     delta = getScrollDelta(ds->stripy, priv->oldStripY, 0, AXIS_INVERT | 
> AXIS_BITWISE);
> +     if (delta && IsPad(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, "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);
> +     }
>  
> -             xf86PostButtonEventP(pInfo->dev, is_absolute(pInfo), fakeButton 
> & AC_CODE,
> -                                  0, first_val, num_vals, VCOPY(valuators, 
> num_vals));
> +     /* emulate events for relative wheel */
> +     delta = getScrollDelta(ds->relwheel, 0, 0, 0);
> +     if (delta && IsCursor(priv) && priv->oldProximity == ds->proximity)
> +     {
> +             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);
>       }
> -     else
> +
> +     /* emulate events for left touch ring */
> +     delta = getScrollDelta(ds->abswheel, priv->oldWheel, MAX_PAD_RING, 
> AXIS_INVERT);
> +     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, "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);
>       }
>  }
>  
> diff --git a/src/xf86WacomDefs.h b/src/xf86WacomDefs.h
> index 1cdfa1a..32b18ee 100644
> --- a/src/xf86WacomDefs.h
> +++ b/src/xf86WacomDefs.h
> @@ -189,6 +189,8 @@ struct _WacomModel
>                                        * For backward compability support,
>                                        * tablet buttons besides the strips are
>                                        * treated as buttons */
> +#define AXIS_INVERT  0x01               /* Flag describing an axis which 
> increases "downward" */
> +#define AXIS_BITWISE 0x02               /* Flag describing an axis which 
> changes bitwise */
>  
>  /* get/set/property */
>  typedef struct _PROPINFO PROPINFO;
> diff --git a/test/wacom-tests.c b/test/wacom-tests.c
> index d91d9c3..a22c970 100644
> --- a/test/wacom-tests.c
> +++ b/test/wacom-tests.c
> @@ -29,6 +29,88 @@
>   * change the behaviour.
>   */
>  
> +static void
> +test_get_scroll_delta(void)
> +{
> +     int test_table[][5] = {
> +             { 100,  25, 0, 0,  75}, { 25,  100, 0, 0, -75},
> +             {-100, -25, 0, 0, -75}, {-25, -100, 0, 0,  75},
> +             { 100, -25, 0, 0, 125}, {-25,  100, 0, 0,-125},
> +             { 100, 100, 0, 0,   0}, {-25,  -25, 0, 0,   0},
> +
> +             {23, 0, 50, 0,  23}, {0, 23, 50, 0, -23},
> +             {24, 0, 50, 0,  24}, {0, 24, 50, 0, -24},
> +             {25, 0, 50, 0,  25}, {0, 25, 50, 0, -25},
> +             {26, 0, 50, 0, -25}, {0, 26, 50, 0,  25},
> +             {27, 0, 50, 0, -24}, {0, 27, 50, 0,  24},
> +             {28, 0, 50, 0, -23}, {0, 28, 50, 0,  23},
> +
> +             {1024, 0, 0, AXIS_BITWISE, 11}, {0, 1024, 0, AXIS_BITWISE, -11},
> +
> +             {  0, 4, 256, AXIS_BITWISE, -3}, {4,   0, 256, AXIS_BITWISE,  
> 3},
> +             {  1, 4, 256, AXIS_BITWISE, -2}, {4,   1, 256, AXIS_BITWISE,  
> 2},
> +             {  2, 4, 256, AXIS_BITWISE, -1}, {4,   2, 256, AXIS_BITWISE,  
> 1},
> +             {  4, 4, 256, AXIS_BITWISE,  0}, {4,   4, 256, AXIS_BITWISE,  
> 0},
> +             {  8, 4, 256, AXIS_BITWISE,  1}, {4,   8, 256, AXIS_BITWISE, 
> -1},
> +             { 16, 4, 256, AXIS_BITWISE,  2}, {4,  16, 256, AXIS_BITWISE, 
> -2},
> +             { 32, 4, 256, AXIS_BITWISE,  3}, {4,  32, 256, AXIS_BITWISE, 
> -3},
> +             { 64, 4, 256, AXIS_BITWISE,  4}, {4,  64, 256, AXIS_BITWISE, 
> -4},
> +             {128, 4, 256, AXIS_BITWISE,  5}, {4, 128, 256, AXIS_BITWISE, 
> -5},
> +             {256, 4, 256, AXIS_BITWISE, -4}, {4, 256, 256, AXIS_BITWISE,  4}
> +     };
> +     int i;
> +
> +     for (i = 0; i < ARRAY_SIZE(test_table); i++)
> +     {
> +             int delta;
> +             int current, old, wrap, flags;
> +             current = test_table[i][0];
> +             old     = test_table[i][1];
> +             wrap    = test_table[i][2];
> +             flags   = test_table[i][3];
> +
> +             delta = getScrollDelta(current, old, wrap, flags);
> +             assert(delta == test_table[i][4]);
> +
> +             flags |= AXIS_INVERT;
> +             delta = getScrollDelta(current, old, wrap, flags);
> +             assert(delta == -1 * test_table[i][4]);
> +     }
> +}
> +
> +static void
> +test_get_wheel_button(void)
> +{
> +     int delta;
> +     int button_up, button_dn, action_up, action_dn;
> +
> +     button_up = 100;
> +     button_dn = 200;
> +     action_up = 300;
> +     action_dn = 400;
> +
> +     for (delta = -32; delta <= 32; delta++)
> +     {
> +             int *action;
> +             int result = getWheelButton(delta, button_up, button_dn, 
> &action_up, &action_dn, &action);
> +             if (delta < 0)
> +             {
> +                     assert(result == button_dn);
> +                     assert(action == &action_dn);
> +             }
> +             else if (delta == 0)
> +             {
> +                     assert(result == 0);
> +                     assert(action == NULL);
> +             }
> +             else
> +             {
> +                     assert(result == button_up);
> +                     assert(action == &action_up);
> +             }
> +     }
> +}
> +
>  /**
>   * Test refcounting of the common struct.
>   */
> @@ -552,6 +634,8 @@ int main(int argc, char** argv)
>       test_mod_buttons();
>       test_set_type();
>       test_flag_set();
> +     test_get_scroll_delta();
> +     test_get_wheel_button();
>       return 0;
>  }
>  
> -- 
> 1.7.7.3
> 
> 
> ------------------------------------------------------------------------------
> Write once. Port to many.
> Get the SDK and tools to simplify cross-platform app development. Create 
> new or port existing apps to sell to consumers worldwide. Explore the 
> Intel AppUpSM program developer opportunity. appdeveloper.intel.com/join
> http://p.sf.net/sfu/intel-appdev
> _______________________________________________
> Linuxwacom-devel mailing list
> Linuxwacom-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel
> 

------------------------------------------------------------------------------
Write once. Port to many.
Get the SDK and tools to simplify cross-platform app development. Create 
new or port existing apps to sell to consumers worldwide. Explore the 
Intel AppUpSM program developer opportunity. appdeveloper.intel.com/join
http://p.sf.net/sfu/intel-appdev
_______________________________________________
Linuxwacom-devel mailing list
Linuxwacom-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel

Reply via email to