Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not use a timer for an explicit timeout of 0 #1146

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

cduivis
Copy link

@cduivis cduivis commented Oct 13, 2017

The Press gesture recognizer in HammerJS has problems consistently firing a pressup event following a press event in the context of small time values. This is well-known. See e.g. #1011, #836, #751.

We've found that given a pair of Press and Pan gestures configured as below, the pressup event will fairly consistently break ( especially when using touch input ).
This particular scenario is used for detecting a Press for instant setting of a position and Pan gradually controlling a set position ( we specifically use this for creating a "dual-ended between" variant of the input type="range" ):

{
  recognizers : [
    [ Hammer.Pan, {
      direction : Hammer.DIRECTION_HORIZONTAL,
      threshold : 0
    }],
    [ Hammer.Press, {
      threshold : 1,
      time      : 0
    }]
   ]
}

The root cause is with a granularity problem with browser timeouts as used in the setTimeoutContext, which causes part of the gesture logic to fire too late (or not at all). This issue and probably others like it, such as #1011, #836 or #751 can be fixed by not using a timeout at all if the gesture's time property is 0.

The `Press` gesture recognizer in HammerJS has problems consistently firing a `pressup` event following a `press` event in the context of small `time` values. This is well-known. See e.g. hammerjs#1011, hammerjs#836, hammerjs#751.

We've found that given a pair of `Press` and `Pan` gestures configured as below, the `pressup` event will fairly consistently break ( especially when using touch input ).
This particular scenario is used for detecting a `Press` for instant setting of a position and `Pan` gradually controlling a set position ( we specifically use this for creating a "dual-ended between" variant of the `input type="range"` ):

```js
{
  recognizers : [
    [ Hammer.Pan, {
      direction : Hammer.DIRECTION_HORIZONTAL,
      threshold : 0
    }],
    [ Hammer.Press, {
      threshold : 1,
      time      : 0
    }]
   ]
}```

The root cause is with a granularity problem with browser timeouts as used in the `setTimeoutContext`, which causes part of the gesture logic to fire too late (or not at all). This issue and probably others like it, such as hammerjs#1011, hammerjs#836 or hammerjs#751 can be fixed by not using a timeout at all if the gesture's `time` property is 0.
Copy link
Contributor

@runspired runspired left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall 👍

@@ -9,5 +9,10 @@ import bindFn from './bind-fn';
* @returns {number}
*/
export default function setTimeoutContext(fn, timeout, context) {
return setTimeout(bindFn(fn, context), timeout);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to use resolve().then to schedule a microtask (high priority with immediate flush) to ensure we preserve async semantics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants