- From: Mustaq Ahmed <mustaq@chromium.org>
- Date: Mon, 13 Apr 2015 10:40:21 -0400
- To: Jacob Rossi <Jacob.Rossi@microsoft.com>, Patrick Lauke <redux@splintered.co.uk>
- Cc: "public-touchevents@w3.org" <public-touchevents@w3.org>, Rick Byers <rbyers@google.com>
- Message-ID: <CAB0cuO7kmW3W8Gw8dGiBZiP2ETz6QRNoajjdF-JcBwHRat3R8A@mail.gmail.com>
A quick update: the tap event issue (missing mouseenter/mouseleave) has been fixed, available in Chrome 43 (currently in dev channel). See crbug.com/457497 for details. Note that my patch (crrev.com/1047733002) also fixed two other bugs (crbug.com/470258, crbug.com/470947) with the ordering of "pure" mouse-events. Mustaq On Fri, Mar 6, 2015 at 12:20 PM, Rick Byers <rbyers@google.com> wrote: > 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 Monday, 13 April 2015 14:40:59 UTC