On Wed, Dec 21, 2011 at 9:27 PM, Peter Hutterer <peter.hutte...@who-t.net> wrote: > 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 >> >>
Patchset has been merged. Jason --- Day xee-nee-svsh duu-'ushtlh-ts'it; nuu-wee-ya' duu-xan' 'vm-nvshtlh-ts'it. Huu-chan xuu naa~-gha. ------------------------------------------------------------------------------ Ridiculously easy VDI. With Citrix VDI-in-a-Box, you don't need a complex infrastructure or vast IT resources to deliver seamless, secure access to virtual desktops. With this all-in-one solution, easily deploy virtual desktops for less than the cost of PCs and save 60% on VDI infrastructure costs. Try it free! http://p.sf.net/sfu/Citrix-VDIinabox _______________________________________________ Linuxwacom-devel mailing list Linuxwacom-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel