- From: Rick Byers <rbyers@google.com>
- Date: Fri, 6 Mar 2015 12:20:10 -0500
- To: Jacob Rossi <Jacob.Rossi@microsoft.com>
- Cc: "public-touchevents@w3.org" <public-touchevents@w3.org>, Mustaq Ahmed <mustaq@chromium.org>
- Message-ID: <CAFUtAY-Sbcp=X_jmuUdy80_tigVuBMy6p_ujzAx0HS80M66F9g@mail.gmail.com>
Jacob, I realized it's not completely obvious what semantics we want here. mouseenter/mouseleave are normally tied to matching :hover state exactly. In chromium we set :hover shortly after touchstart, and clear it on (or shortly after) touchend, which is very different from the WebKit-style synthetic mouse event behavior. So in this scenario, we have to choose one of the following: 1) Break the connection between :hover and mouseenter/mouseleave for tap gestures. Fire the mouseenter/mouseleave events consistent with the existing mouse event sequence, i.e.: touchstart, touchend, mouseenter, mouseover, mousemove, mousedown, mouseup, click This is probably the most compatible thing, so probably what we want. But it turns out it may be some non-trivial implementation work for us (since today our mouseenter/mouseleave logic is tied to setting/clearing of :hover). 2) Change our :hover behavior. I know this is an area you and I have discussed as needing interoperability improvement. Is now the time to talk about this in detail perhaps? 3) Break the mouse event sequence (but keep the mouseenter/leave :hover connection), so it might sometimes look something like this on dwell-then-drag gesture that normally doesn't fire any mouse events: touchstart, mouseenter, touchmove, mouseleave, touchend or like one of these (depending on timing) on a tap: touchstart, mouseenter, touchend, mouseover, mousemove, mousedown, mouseup, click, mouseleave touchstart, touchend, mouseenter, mouseover, mousemove, mousedown, mouseup, click, mouseleave I'd love to hear more about what exactly IE does when using WebKit-style mouse event behavior. This seems even more complicated when you take pointer events in the mix (presumably the pointer->mouse event mapping gets disconnected). Thanks, RIck On Tue, Feb 17, 2015 at 5:34 PM, Rick Byers <rbyers@google.com> wrote: > For the record, we agreed > <http://www.w3.org/2015/02/17-touchevents-minutes.html> that we should > try to fix the bug > <https://code.google.com/p/chromium/issues/detail?id=457497> with > mouseenter/mouseleave not being fired in Chrome (Jacob says it looks like > it shouldn't be that risky). Mustaq is aiming to land a fix in Chrome 43 > and will follow up here once it's available in Canary for website compat > testing. > > Rick > > On Tue, Feb 10, 2015 at 8:05 PM, Rick Byers <rbyers@google.com> wrote: > >> On Thu, Feb 5, 2015 at 10:36 AM, Jacob Rossi <Jacob.Rossi@microsoft.com> >> wrote: >> >>> I’ve mentioned before that we’re exploring firing the Touch Event >>> spec’s model for compatibility mouse events so we’re more interoperable. >>> In doing so, we uncovered a nasty interoperability issue that’s quite >>> frustrating. This one takes a minute to explain, so grab a cup of coffee >>> and bear with me. :-) >>> >>> >>> >>> Safari implements a proprietary heuristic for detecting hover menus. >>> It works something like this on a simple tap: >>> >>> >>> >>> 1. Fire touch events >>> >>> 2. Fire mouse events for hover (e.g. mouseover/enter) , down, up >>> >>> 3. If “page content changes” (insert undocumented proprietary >>> heuristic), then persist the hover on the node & suppress firing the click >>> event [1] >>> >>> 4. If not, then fire events to remove hover and fire click >>> >>> >>> >>> The heuristic is attempting to detect a hover menu intended for mouse, >>> which enables a “tap to hover menu, tap again to click” type of experience >>> when it works. However, sometimes the heuristic has a false positive >>> causing non-hover-menus to require multiple taps to get a click event on >>> something. This leads web developers to try to work around the heuristic. >>> >>> >>> >>> Here’s a common pattern we’ve found on popular sites like Netflix: >>> >>> >>> http://stackoverflow.com/questions/3038898/ipad-iphone-hover-problem-causes-the-user-to-double-click-a-link/22444819#22444819 >>> >>> >>> >>> In summary, it looks like: >>> mouseenter – open hover menu >>> mouseleave – close hover menu >>> >>> click – toggle hover menu >>> >>> >>> >>> For a mouse in Safari, the menu opens when you mouse over and closes >>> when you click something or move your mouse out. Cool. >>> >>> For touch, the menu opens after you tap. The mouseenter causes “page >>> content changes” in step #2 above. Thus mouseleave and click do not fire. >>> Therefore the menu stays open. You can tap again to click an item in the >>> menu. Cool. >>> >>> >>> >>> Now, consider a browser that does not implement Safari’s non-standard >>> heuristic. In this case, Blink/Gecko follow the Touch Events spec [2] >>> essentially and do this: >>> >>> 1. Fire touch events >>> >>> 2. Fire mousemove >>> >>> a. (While not explicitly mentioned in the spec, this causes a >>> mouseover to fire) >>> >>> 3. Fire mouse down, up >>> >>> 4. Fire click >>> >>> >>> >>> Note, like Safari, this means hover state essentially persists on the >>> node until you tap another node (which fires a new mousemove, which removes >>> hover from the old node and applies it to the new). The Touch Events spec >>> does not, however, explicitly state when hover related events, like >>> over/out/enter/leave occur. It’s just assumed the mousemove causes it >>> (grrr…the spec should say this!). >>> >> >> Agreed, please submit a PR for this. I've always taken it for granted >> that over/out/enter/leave events should ALWAYS be consistent with mousemove >> (any time you get a move with a new target, they're fired appropriate), but >> stating that explicitly doesn't hurt. >> >> Still with me? :-) Here’s the rub: Blink doesn’t fire >>> mouseenter/mouseleave for touch, only mouseover/mouseout (I didn’t have a >>> Firefox mobile device handy to test, but I assume it’s similar). This is >>> despite the fact that Blink does support mouseenter/mouseleave for mouse >>> input. [3] >>> >> >> This is simply a bug from when mouseenter/mouseleave events were first >> implemented. I only noticed this recently from code inspection (I added a FIXME >> in the code >> <https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/core/page/EventHandler.cpp&q=EventHandler.cpp%20mouseenter&sq=package:chromium&type=cs&l=2659> >> but failed to file a bug - just filed one now <http://crbug.com/457497>). >> >> >>> It turns out this is a critical detail missing from the spec. Because >>> if you make the mistake we did, which was to fire mouseenter/mouseleave >>> when processing the mousemove for touch, then the above code I described >>> breaks as you get: >>> >>> >>> >>> 1. Fire touch events >>> >>> 2. Fire mousemove >>> >>> a. Fire mouseover >>> >>> b. Fire mouseenter – open hover menu >>> >>> 3. Fire mouse down, up >>> >>> 4. Fire click – hover menu toggles >>> >>> >>> >>> So the hover menu opens and then immediately closes. Not cool. >>> >>> >>> >>> tl;dr – for best compatibility, browsers need to choose either: >>> (a) try to reverse engineer Safari’s heuristic (not >>> likely to be very interoperable) >>> >>> (b) do not implement mouseenter/mouseleave for touch >>> >> >> Crap crap crap crap. >> >> How prevalent is this pattern? I.e. how much pain would we cause by >> fixing our bug in blink? >> >> The only pragmatic solution I can see (should we end up shipping the >>> Touch Event model for mouse events in IE) is B. It should be noted that >>> I’ve tried to get the Safari engineers to share details about the >>> heuristic, but they have declined. >>> >>> >>> >>> I think this critical detail (not firing mouseenter/mouseleave for >>> touch) should probably be added as errata to the current spec. WDYT? >>> >> >> If we think this is what's best for the web (i.e. enough people have >> already taken a dependency on our bug), then that's OK with me (although as >> Patrick says - perhaps that's part of TEv2, not TEv1 errata). It's not >> very rational though. Is there a better pattern we could advocate for? >> What about combining this with some sort of more explicit signal of >> developer intent (like your aria-hasrole=popup)? Ideally we'd have a path >> where browser's default behavior can be one (confusing) way for compat, but >> we have clear explicit APIs that could be implemented by all browsers to >> get developers out of this mess. >> >> -Jacob >>> >>> >>> >>> [1] >>> https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html >>> >>> [2] http://www.w3.org/TR/touch-events/#mouse-events >>> >>> [3] https://status.modern.ie/dom3mouseentermouseleaveevents >>> >>> >>> >>> >>> >>> >>> >> >> >
Received on Friday, 6 March 2015 17:21:12 UTC