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

document.createEvent() should maybe not be conditional upon exposure #952

Open
annevk opened this issue Feb 25, 2021 · 23 comments · May be fixed by #1071
Open

document.createEvent() should maybe not be conditional upon exposure #952

annevk opened this issue Feb 25, 2021 · 23 comments · May be fixed by #1071
Labels
interop Implementations are not interoperable with each other

Comments

@annevk
Copy link
Member

annevk commented Feb 25, 2021

Apparently TouchEvent is always exposed in Chrome, but document.createEvent("touchevent") depends on the "touch events flag" (see w3c/touch-events#64). Having said that, neither Firefox nor Safari expose TouchEvent so maybe Chrome should change?

cc @patrickhlauke @RByers

(Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1693172.)

@annevk annevk added the interop Implementations are not interoperable with each other label Feb 25, 2021
@patrickhlauke
Copy link
Member

I vaguely remember asking before somewhere, but: philosophically, does it not make sense to expose TouchEvent (as an API that the browser understands/supports) regardless of presence of an actual touchscreen? Are there other APIs that are simply not exposed (as if the browser didn't understand them / support them at all) in the absence of certain conditions?

And yes, Chrome's selective support for certain properties/calls based on the actual presence of a touchscreen is a hacky workaround to naive "mobile-only" detection that assumed "if there's a touchscreen, then i can just listen to touch events as it's mobile ... no need to use mouse events or keyboard / can just switch the the 'mobile' version of the site / etc"

@annevk
Copy link
Member Author

annevk commented Mar 2, 2021

It makes sense, but it might well break code that does

if ("TouchEvent" in self) { ... }

and the precedent was set by WebKit as I understand it, so legacy code would assume WebKit's model.

@patrickhlauke
Copy link
Member

patrickhlauke commented Mar 9, 2021

so legacy code would assume WebKit's model.

I seem to remember (but Googlers may have more detail) that the internal touch events flag thing and deciding when to be truthful (yes, of course we know what Touch Events are, even if you don't have an actual touchscreen) and when to lie came mostly from looking at (then already) legacy code to see how sites were doing naive "isMobile?" type sniffing and then essentially only listening for touch events and not mouse/keyboard - breaking sites on touch-enabled laptops/desktops. This may have been based on data analysis of "what's the most prevalent pattern that sites use for this sort of naive detection", but I'm not sure).

If that's now less of a problem (?) then I guess it does make sense to go with the wonky WebKit precedent...

@RByers
Copy link
Contributor

RByers commented Mar 9, 2021

Mobile Safari exposes TouchEvent, right? Desktop Safari doesn't support touch at all, so no surprise not to have it there. Anyway further alignment on any differences between browsers SGTM. Anything in mobile Safari or Firefox for Android is probably sufficiently web compatible for chromium to try.

Over to @flackr who leads input on Chrome these days (I'm not sure who on the team might be working in this area).

@patrickhlauke
Copy link
Member

sorry, I realised just now that I almost repeated everything I said a few days ago already in my second comment. Serves me right to try and "catch up" with threads without seeing what I might have previously said.

In any case, as long as this doesn't end up breaking sites on touch-enabled desktop/laptop (to the point where users are locked out of using mouse/keyboard and forced to use touch) somehow, it probably makes sense to align...

@flackr
Copy link

flackr commented Mar 10, 2021

Mobile Safari does indeed expose TouchEvent. My understanding is that desktop Safari never supports touch (is compiled without support). I created a test page https://output.jsbin.com/pipudek which tests a few means of detecting touch support.

Test Chrome Desktop Firefox Desktop Safari Desktop Chrome Mobile Firefox Mobile Safari Mobile
'TouchEvent' in window true false / true* false true true true
document.createEvent('touchevent') throws throws throws object object object
typeof(TouchEvent) function undefined / function* undefined function function function
'ontouchstart' in window false false false true true true

* Depends if local device supports touch

Is the proposal is to not expose TouchEvent, but still dispatch TouchEvents to touch event handlers? I worry existing sites may be using UA detection to decide whether to include references to TouchEvent, which would then turn into errors if we were to do this.

@annevk
Copy link
Member Author

annevk commented Mar 10, 2021

I don't have a concrete proposal, but it seems Firefox's behavior would allow you to detect touch support across all browsers, whereas what Chrome shipped defeats that? Maybe that's okay though.

I should also note that since I filed OP I learned that a simple flag as suggested in w3c/touch-events#64 might not be enough (as your table also shows), depending on which way we go.

@smaug----
Copy link
Collaborator

smaug---- commented Mar 10, 2021

@RByers Is the anyway in desktop Chrome to detect touch support? Perhaps using navigator.maxTouchPoints ?

@RByers
Copy link
Contributor

RByers commented Mar 10, 2021

Chrome desktop always has "touch support". A user could plug in a touch device at any moment, including devtools emulation etc. More commonly many Windows machines appear to have "touch devices" the user never actually uses or knows about (IIRC Visual Studio installs an emulated touchscreen driver that's indistinguishable to us from a real touch screen, and we had user complaints about using a touch laptop with external screen/keyboard).

I forget all the details (@flackr can reflect current expertise/guidance), but I think the 'pointer' and 'hover' media queries are what we consider the 'right' way to detect whether a user is likely to use touch as their input modality. I.e. asking "does the browser/hardware support touch" is usually the wrong question, instead "should I be optimizing my UI for larger targets" and "should I expect the user has the ability to 'hover' their pointing device'.

https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how/

@patrickhlauke
Copy link
Member

who's that handsome gentleman that wrote that hacks article, i wonder...i'd say it's good to consider this chaser as well though https://css-tricks.com/interaction-media-features-and-their-potential-for-incorrect-assumptions/

@patrickhlauke
Copy link
Member

incidentally, one case i remember where i site made a naive/wrong assumption about touch support - flickr on a Surface. they fixed this after I reported it though. https://www.youtube.com/watch?v=f_2GKsI9TQU

@RByers
Copy link
Contributor

RByers commented Mar 10, 2021

😄 Awesome, hadn't seen that one Patrick.

BTW you can tell it's performance review season at Google when I start engaging with low-latency on GitHub issues (wishing I still got to hack on this stuff with you awesome folks instead of doing management crap) 😉 .

@flackr
Copy link

flackr commented Mar 10, 2021

I don't have a concrete proposal, but it seems Firefox's behavior would allow you to detect touch support across all browsers, whereas what Chrome shipped defeats that? Maybe that's okay though.

I should also note that since I filed OP I learned that a simple flag as suggested in w3c/touch-events#64 might not be enough (as your table also shows), depending on which way we go.

We used to enable / disable touch API's based on the existence of a touchscreen but ran into the issues @RByers mentioned above.

@RByers Is the anyway in desktop Chrome to detech touch support? Perhaps using navigator.maxTouchPoints ?

This does indeed reflect whether Chrome currently believes it has a touchscreen attached however it can change dynamically when you attach a touchscreen or enable touch emulation in dev tools. I've noticed the detection can also can be a little flaky (on my ChromeOS Linux container running desktop Chrome Linux it claims 0 even though it fires touchevents).

As @RByers mentioned we encourage developers to handle both types of events and use media queries to determine whether they should size elements for touch or not. Note that the pointer / hover media queries effectively answer the opposite question, does the user have a mouse capable of hovering, you can use any-pointer / any-hover as @patrickhlauke noted in his article, optionally using window.matchMedia to observe changes to these queries, e.g. https://jsbin.com/daqedes/edit?js,output

P.S. apologies if this no longer adds value, other replies came in while I was still writing this :-)

@annevk annevk linked a pull request May 3, 2022 that will close this issue
3 tasks
@zcorpan
Copy link
Member

zcorpan commented May 3, 2022

Is there a recommendation here? Should we specify what Chromium does? It is evidently web compatible (at least for Chromium-based browsers) to expose window.TouchEvent always. It also seems more flexible since a desktop browser could have touch supported and web devs could still use touch events, only not the event handlers or createEvent.

@zcorpan
Copy link
Member

zcorpan commented May 3, 2022

Gecko seems to have two levels of API exposure:

  • dom_w3c_touch_events_enabled (set to 0 on macOS, 1 on Android and autodetect on some platforms)
  • dom_w3c_touch_events_legacy_apis_enabled (affects createEvent and ontouch* handlers)

References

So I think Gecko matches Chromium when dom_w3c_touch_events_enabled is 1 (or autodetected as enabled).

@annevk
Copy link
Member Author

annevk commented May 4, 2022

@cdumez @smaug---- thoughts? Aligning with Chrome here seems relatively straightforward and it is somewhat nice that at least the event constructors would end up being consistently exposed.

@smaug----
Copy link
Collaborator

smaug---- commented May 6, 2022

Curious to know if that would break sites which don't expect TouchEvent constructor especially with desktop Safari.

Does Chrome expose TouchEvent even on Mac where the interface is never used?

@annevk
Copy link
Member Author

annevk commented May 6, 2022

Yeah it does.

@gsnedders
Copy link
Member

Is there a recommendation here? Should we specify what Chromium does? It is evidently web compatible (at least for Chromium-based browsers) to expose window.TouchEvent always. It also seems more flexible since a desktop browser could have touch supported and web devs could still use touch events, only not the event handlers or createEvent.

It is evidently web compatible at least for Chromium-based browsers, yes. But there's historically been content that has relied on the presence of TouchEvent to distinguish mobile Safari from desktop Safari, so there is still web compat risk for Safari from that. (There's also—inevitably—some risk in shipping more code.)

@zcorpan
Copy link
Member

zcorpan commented Jun 7, 2022

OK.

If WebKit is unable to change this, the spec can document this lack of interop through the navigator compatibility mode.

I ran a query on the 10k sample mobile pages in httparchive for pages containing "window.TouchEvent". There were 163 matches. I haven't looked at them, but you could look for evidence that there are web pages that would break in desktop Safari (or macOS Firefox) before trying to ship the suggested change.

https://docs.google.com/spreadsheets/d/1G3qs7i6V2E5NWVPHZY5E1GAHFYwo1frDxoLhqaYIQrU/edit#gid=752407919

Query
SELECT * FROM (
SELECT
  page,
  url,
  REGEXP_EXTRACT(body, r'(\bwindow\.TouchEvent\b)') AS match
FROM
  `httparchive.sample_data.response_bodies_mobile_10k`
) WHERE match IS NOT NULL

@hsivonen
Copy link
Member

What does Epiphany do?

@howard-e
Copy link

@zcorpan shared:

I ran a query on the 10k sample mobile pages in httparchive for pages containing "window.TouchEvent". There were 163 matches. I haven't looked at them, but you could look for evidence that there are web pages that would break in desktop Safari (or macOS Firefox) before trying to ship the suggested change.
https://docs.google.com/spreadsheets/d/1G3qs7i6V2E5NWVPHZY5E1GAHFYwo1frDxoLhqaYIQrU/edit#gid=752407919

Created a copy of this worksheet to expand on it. Using an extension to modify and intercept calls done to window.TouchEvent, found that at least one of the sites in the list was affected. It displayed a difference in the layout when window.TouchEvent was nullified. This can be viewed at https://docs.google.com/spreadsheets/d/1VQW1ZFP-FEsGoSpEfy6VpThsqKBuksJZ3bnYlDOZXjg/edit?usp=sharing.

Additional notes also detail the supposed use with which checking for window.TouchEvent, may be trying to perform.

The original list hasn’t been exhausted as yet.

@zcorpan
Copy link
Member

zcorpan commented Aug 8, 2022

Thanks @howard-e ! To clarify the methodology, you tested in Desktop Safari with the "Userscripts" extension (or maybe "Tampermonkey"), with a user script something like:

// ==UserScript==
// @name        TouchEvent compat research
// @description Expose window.TouchEvent
// @match       *://*/*
// ==/UserScript==

Object.defineProperty(window, 'TouchEvent', {
  get: () => {
    console.log('TouchEvent getter called');
    debugger;
  }
});

and then load each page and check if the layout is different or if something is clearly broken.

And out of the 45 pages analyzed, 1 page (https://meridian.broker/) had different layout, for the chat bot thing.

I couldn't see any difference, though. Can you post screenshots? Does it only happen at certain viewport widths?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interop Implementations are not interoperable with each other
Development

Successfully merging a pull request may close this issue.

10 participants