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