Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Intent to ship: Return pixel deltas in wheel event if deltaMode is not checked by authors

224 views
Skip to first unread message

Emilio Cobos Álvarez

unread,
Mar 9, 2021, 10:45:38 AM3/9/21
to Mozilla
Hi,

In bug 1696384, I plan to enable
dom.event.wheel-deltaMode-lines.disabled on all channels.

This is a compat intervention for sites that check
WheelEvent.delta{X,Y,Z} before checking WheelEvent.deltaMode, generally
assuming that the deltas are going to be pixels.

These deltas are environment-specific, generally, and authors are always
expected to check the deltaMode to determine how to scroll, see:

https://w3c.github.io/uievents/#events-wheelevents

But other browsers historically have always returned pixels, and some
websites depend on that behavior. That makes Firefox feel super-slow on
those websites (as the site scrolls by e.g. 3 pixels rather than the
equivalent 3 lines of content). See bug 1392460 and webcompat issues
linked from there.

The behavior is the following, decided per event:

* If deltaMode has been accessed, or the feature is disabled, then
return the original delta mode and deltas (no behavior change from
current release).

* If deltaMode has _not_ been accessed, and it's DOM_DELTA_LINE,
accessing any of the deltas cause the event to always report
DOM_DELTA_PIXELS, and the deltas get appropriately converted to pixels too.

There are three prefs involved in controlling the behavior:

* dom.event.wheel-deltaMode-lines.disabled: This is the global switch
and if false the behavior doesn't change. If true, it implements the
behavior described above.

* dom.event.wheel-deltaMode-lines.always-disabled: This implements the
behavior of converting lines to pixels unconditionally (without
depending on event ordering etc). Mostly intended for debugging.

* dom.event.wheel-deltaMode-lines.always-enabled: This is a domain
list for domains that might need to switch to the previous behavior. I
really think that given how this is implemented it shouldn't cause
trouble for most websites (the pref has been on on nightly for 4 months,
with no serious regressions), so it should hopefully remain empty.

Let me know if you have any concerns with this or what not.

Cheers,

-- Emilio

Anne van Kesteren

unread,
Mar 9, 2021, 11:11:03 AM3/9/21
to Emilio Cobos Alvarez, Mozilla
On Tue, Mar 9, 2021 at 4:45 PM Emilio Cobos Álvarez <emi...@mozilla.com> wrote:
> Let me know if you have any concerns with this or what not.

So if I understand it correctly we'll have a getter with side effects.
Is the expectation that we can eventually remove this? Are other
browsers on board with this model?

Emilio Cobos Álvarez

unread,
Mar 9, 2021, 1:21:35 PM3/9/21
to Anne van Kesteren, Emilio Cobos Alvarez, Mozilla
Well, the side effect is not _quite_ that bad IMO, in the sense that the
page can't really tell whether the event is returning pixels because the
scroll was actually pixel-based (e.g., trackpads do this IIRC) or
because they didn't check deltaMode.

The only alternative to this that I can think of is basically never
return DOM_DELTA_LINE (which is what other browsers do in practice), but
that seemed both more risky for us, and also a potential regression
(knowing lines can be useful).

-- Emilio

James Graham

unread,
Mar 9, 2021, 2:36:15 PM3/9/21
to dev-pl...@lists.mozilla.org
It seems like having all browsers have the same behaviour is going to be
better in the long run than having some weird heuristic in gecko that
acts as a footgun for authors going forward.

Do we have any way to assess the compat impact of switching to match
Blink and WebKit always?

Emilio Cobos Álvarez

unread,
Mar 9, 2021, 5:13:27 PM3/9/21
to James Graham, dev-pl...@lists.mozilla.org


On 3/9/21 20:36, James Graham wrote:
> It seems like having all browsers have the same behaviour is going to be
> better in the long run than having some weird heuristic in gecko that
> acts as a footgun for authors going forward.
>
> Do we have any way to assess the compat impact of switching to match
> Blink and WebKit always?

Not an easy one that I can think at least. We can measure how often
pages access the deltas without the deltaMode or vice versa, but it's
not clear to me how to correlate that to broken or good behavior easily.

I guess we could enable the always-disabled pref on Nighly and watch for
a few releases to see if there's reports of broken sites. Would that
seem reasonable to you?

-- Emilio

Karl Dubost

unread,
Mar 9, 2021, 5:28:34 PM3/9/21
to Emilio Cobos Álvarez, James Graham, moz-dev-platform
Hello,

So about experimenting with wheelEvent…
Cool to see the work of Emilio in that space.

Le 2021/03/10 à 07:13, Emilio Cobos Álvarez <emi...@mozilla.com> a écrit :
> I guess we could enable the always-disabled pref on Nighly and watch for a few releases to see if there's reports of broken sites. Would that seem reasonable to you?

Yes we could do that. Webcompat will probably surface weird cases.

There is a lot of user agent sniffing and weird heuristics going on on Websites to fix this kind of scrolling issues.

Either people are afraid to switch to wheel, because they support mousewheel/DOMMouseScroll (ex: CodeMirror) or they try to fix the scrolling ( ex: svg.panzoom for a recent case)

Everything which goes into direction of simplifying the space will be great and webcompat will likely catch the outcome if it really breaks big sites or some libraries.



https://github.com/svgdotjs/svg.panzoom.js/issues/67
https://github.com/svgdotjs/svg.panzoom.js/pull/68
https://github.com/svgdotjs/svg.panzoom.js/pull/68/files


--
Karl Dubost, mozilla 💡 Webcompat
http://www.la-grange.net/karl/moz





Masayuki Nakano

unread,
Mar 10, 2021, 3:11:29 AM3/10/21
to Emilio Cobos Álvarez, Mozilla
Hi,

Thank you Emilio for your great work!

I'd like to explain the background. First, `WheelEvent` was designed
for making it possible web browsers to expose raw wheel event
information with 3 kinds of delta value modes which listeners can
distinguish with `WheelEvent#deltaMode`. And then, I implemented it
as-is before Chrome/Safari. So, the spec (and I) assumed that the
"wheel" event listeners should be like this:

```
addEventListener("wheel", event => {
let amount = 0;
switch (event.deltaMode) {
case event.DOM_DELTA_PIXEL:
default:
amount = event.deltaY;
break;
case event.DOM_DELTA_LINE:
amount = event.deltaY * computeLineHeight(even.target);
break;
case event.DOM_DELTE_PAGE:
amount = event.deltaY * computePageHeight(event.target);
break;
}
scroll(amount);
event.preventDefault();
});
```

But finally, Chrome implemented "wheel" event only with
`DOM_DELTA_PIXEL` and `DOM_DELTA_PAGE`.

Unfortunately, some web app developers didn't realize that there is
`WheelEvent#deltaMode`. Then, they implemented their own listeners like
these:

Example 1:
```
addEventListener("wheel", event => {
let amount = event.deltaY;
if (isFirefox) {
amount *= 16;
}
scroll(amount);
event.preventDefault();
});
```

Example 2:
```
addEventListener("wheel", event => {
let amount = event.deltaY;
if (isFirefox && navigator.platform.includes("Mac")) {
amount *= 16;
}
scroll(amount);
event.preventDefault();
});
```

Example 3:
```
addEventListener("wheel", event => {
const amount =
event.deltaY > 0
? Math.min(event.deltaY, 16)
: Math.max(event.deltaY, -16);
scroll(amount);
event.preventDefault();
});
```

So, in most broken web apps, current hack must work as expected because
`deltaMode` is not referred.

If `deltaMode` is checked but after referring `deltaY`, the web apps
will lost raw value, but must work mostly as expected since they must
treat the delta value as `DOM_DELTA_LINE`.

Indeed, in long term goal must be that we'd dispatch exactly same wheel
events as Chrome/Chromium. However, without implementing alternative new
API, web apps will not be able to handle raw value for better UX.
Therefore, I filed a spec issue, but it's not been fixed yet.
https://github.com/w3c/uievents/issues/181

(FYI: On Windows, mouse diver/utility can consider wheel delta amount
with native window's class name or process name. E.g., whether the app
support or does not support high resolution wheel events. Therefore,
this fact would cause that it's impossible to dispatch **exactly** same
wheel events as Chrome/Chromium.)

--
Masayuki Nakano <masa...@d-toybox.com>
Working on DOM, Events, editor and IME handling for Gecko

Masayuki Nakano

unread,
Mar 10, 2021, 3:20:51 AM3/10/21
to Emilio Cobos Álvarez, Mozilla
Oops,

On 2021/03/10 17:11, Masayuki Nakano wrote:
> Example 1:
> ```
> addEventListener("wheel", event => {
>  let amount = event.deltaY;
>  if (isFirefox) {
>    amount *= 16;
>  }
>  scroll(amount);
>  event.preventDefault();
> });
> ```
>
> Example 2:
> ```
> addEventListener("wheel", event => {
>  let amount = event.deltaY;
>  if (isFirefox && navigator.platform.includes("Mac")) {
>    amount *= 16;
>  }
>  scroll(amount);
>  event.preventDefault();
> });
> ```

These cases are what they will be broken with current hack.

> Example 3:
> ```
> addEventListener("wheel", event => {
>  const amount =
>    event.deltaY > 0
>      ? Math.min(event.deltaY, 16)
>      : Math.max(event.deltaY, -16);
>  scroll(amount);
>  event.preventDefault();
> });
> ```

And this must be better, but may keep broken if user users
high-resolution wheel on Windows (and maybe on Linux?).

> So, in most broken web apps, current hack must work as expected because
> `deltaMode` is not referred.

So, the case which will be fixed by the hack is:

```
addEventListener("wheel", event => {
scroll(event.deltaY);
event.preventDefault();
});
```

Anne van Kesteren

unread,
Mar 10, 2021, 4:01:40 AM3/10/21
to Masayuki Nakano, Emilio Cobos Álvarez, Mozilla
On Wed, Mar 10, 2021 at 9:11 AM Masayuki Nakano <masa...@d-toybox.com> wrote:
> Indeed, in long term goal must be that we'd dispatch exactly same wheel
> events as Chrome/Chromium. However, without implementing alternative new
> API, web apps will not be able to handle raw value for better UX.
> Therefore, I filed a spec issue, but it's not been fixed yet.
> https://github.com/w3c/uievents/issues/181

That does seem unfortunate, but unless other browsers are interested
in picking this up, I think it will hurt us more to be different than
that it helps. I don't think we should make aligning with Chrome and
Safari conditional upon some new API.

Xidorn Quan

unread,
Mar 10, 2021, 7:23:45 AM3/10/21
to dev-pl...@lists.mozilla.org
On Wed, Mar 10, 2021, at 8:01 PM, Anne van Kesteren wrote:
> That does seem unfortunate, but unless other browsers are interested
> in picking this up, I think it will hurt us more to be different than
> that it helps. I don't think we should make aligning with Chrome and
> Safari conditional upon some new API.

I agree with this.

My main concern is that an event may be checked in multiple places, e.g. some in web framework like React, some in the site itself, or maybe just inside code owned by different teams. It would be pretty surprising if some of them checks the `deltaMode` and then the behavior suddenly changes for other places trying to read the value.

I would suggest that we bring this back to W3C to discuss with other vendors regarding the current situation. If the web has been relying on delta being always pixel, maybe we should make `deltaMode` always return `DOM_DELTA_PIXEL`, and deltas always return pixel value.

If the raw value is still useful to authors, one possible solution is that we expose a new `rawDeltaMode` and probably a new `getDeltaValue` method or so which requires a delta mode to be provided, and in the case such mode matches the raw delta mode, the raw value is returned without conversion. This way it could be less likely to be misused.

WDYT?

- XIdorn

Masayuki Nakano

unread,
Mar 10, 2021, 5:21:36 PM3/10/21
to Xidorn Quan, dev-pl...@lists.mozilla.org
Yes, I also think that the current behavior has the risk on web apps
which have multiple `wheel` event listeners. On the other hand, mainly
from my experience at aligning `keypress` event to Chrome, existing
behavior change is also really risky because a lot of web apps may check
UA name and OS instead of checking behavior. The hacky way guarantees
that the behavior does NOT change on web apps which handle `wheel` event
correctly.
0 new messages