Re: [csswg-drafts] Impact of `inert` on hit-testing needs to be specified (#6685)

The CSS Working Group just discussed `effect of inert on hit testing`, and agreed to the following:

* `RESOLVED: Resolve on WK behavior. Use pointer-events:none, but don't reflect into computed style (use "behaves as" wording); same with user-select and related focus behavior`
* `RESOLVED: Add definition of p-e:none, at least, to UI 4`
* `RESOLVED: Steal the top-layer spec from Fullscreen, put it into Position 3.`

<details><summary>The full IRC log of that discussion</summary>
&lt;TabAtkins> Topic: effect of inert on hit testing<br>
&lt;TabAtkins> github: https://github.com/w3c/csswg-drafts/issues/6685<br>
&lt;TabAtkins> smfr: There has been a history of impls of `inert` that haven't matched<br>
&lt;TabAtkins> smfr: Chrome and Gecko already mismatch, now WebKit is implementing and want a spec that is clear<br>
&lt;TabAtkins> smfr: Historically, Chrome's was mor ein terms of DOM propagation<br>
&lt;TabAtkins> smfr: If an event hit an inert node it woudl skip up to an ancestor<br>
&lt;TabAtkins> smfr: Gecko was in terms of pointer-events; it woudl ignore the inert element so clicks could go to underneath it<br>
&lt;TabAtkins> smfr: On a call a few weeks ago chrishtr said he'd talk to Google folks and see if they're okay with doing Gecko's behavior<br>
&lt;TabAtkins> smfr: Also questions about whether inert effects APIs like elementFromPoint()<br>
&lt;TabAtkins> smfr: And some keyboard interactions<br>
&lt;TabAtkins> chrishtr: I did not unfortunatley get to talk to a11y team in Chrome, but I did review the discussions again.<br>
&lt;TabAtkins> chrishtr: I think there are pros and cons to both; I think we could just discuss Tim's proposal point-by-point and see if it's okay to everyone<br>
&lt;TabAtkins> chrishtr: Also no browsers publicly ship the attribute yet, so all browsers are still changeable right now<br>
&lt;bkardell_> q+<br>
&lt;TabAtkins> smfr: Dialog and Fullscreen specs refer to inert and say it should be applied to the document, with the dialog/fullscreen excepted from the effect<br>
&lt;TabAtkins> smfr: So even if the attribute ahsn't shipped, there are implications on those features<br>
&lt;TabAtkins> chrishtr: I didn't look at the code for dialog/fullscreen, did anyone else<br>
&lt;TabAtkins> chrishtr: I assume it ignores hit-test events in the dialog<br>
&lt;TabAtkins> chrishtr: So I think we can discuss this holistically and probably dialog impl coudl be changed in Chromium, unless someone knows about compat problems<br>
&lt;TabAtkins> emilio: I doubt the set order issue is going to be a problem for fullscreen/dialog, because they're on the top layer and thus always on top of everything else<br>
&lt;TabAtkins> emilio: In terms of impl, Gecko's has an internal CSS property called 'inert', and we apply it to everything and reset it on the dialog, that has effects on pointer-events and such<br>
&lt;astearns> ack bkardell_<br>
&lt;TabAtkins> bkardell_: Interesting bc dialog was defined with the terms of top-layer and inertness, but didn't expose them or refer to them elsewhere. They're two separate but related problems, and depending on what you do with the top layer it helps answer the other questions<br>
&lt;TabAtkins> bkardell_: The way libraries today make dialogs is to create a pseudo-top-layer that's a top-level child of body, so they can make everything else inert<br>
&lt;TabAtkins> bkardell_: When we define that, and Alice did the initial impl and we did the polyfill, some of the things around top layer are a little wonky maybe<br>
&lt;TabAtkins> bkardell_: There ahs been an incredible amount of discussion on this topic. Before Alice left on sabbatical, she agreed there were things in Chrome to work on.<br>
&lt;TabAtkins> bkardell_: So I think it's worth talking about top-layer first to set up the questions about inert, imo<br>
&lt;smfr> q+<br>
&lt;TabAtkins> chrishtr: I see now that Tim did put some comments on Chrome's behavior and quirks<br>
&lt;astearns> ack smfr<br>
&lt;TabAtkins> smfr: One fo the fundamental difficulties is the inert spec says you can't make a descendant of an inert node non-inert, and yet the dialog spec says the document is inert and then the dialog (a child of the document) is non-inert...<br>
&lt;TabAtkins> smfr: And if the impl is pointer-events based, youa re allowed to make a descendant of a pointer-events:none node pointer-events:normal<br>
&lt;TabAtkins> ntim: WebKit recently implemented a pointer-events-based approach, similar to Firefox<br>
&lt;TabAtkins> astearns: So bkardell_ suggested starting with top layer<br>
&lt;TabAtkins> bkardell_: So let's discuss how it's defined and how it works<br>
&lt;TabAtkins> bkardell_: If it works something like existing impls in libraries, so it's effectively projected to a sibling of the document, we can think about it one way<br>
&lt;smfr> q+<br>
&lt;TabAtkins> bkardell_: If talking about the tree itself and where it lives normally in the tree, things get a lot more complicated<br>
&lt;TabAtkins> q+<br>
&lt;astearns> ack smfr<br>
&lt;TabAtkins> smfr: I think we're happy with the way top-layer is specified; it renders z-ordered above the rest of the doc<br>
&lt;chrishtr> q+<br>
&lt;TabAtkins> smfr: I think Chrome/WEbKit do that now<br>
&lt;TabAtkins> smfr: If there are implications for event propagation, maybe they're not clear enough<br>
&lt;fantasai> scribe+<br>
&lt;astearns> ack TabAtkins<br>
&lt;fantasai> TabAtkins: IIRC, the way we've described top layer is that it get reparented in the layer tree sense<br>
&lt;fantasai> TabAtkins: being a direct child of the top-level document/canvas/thing<br>
&lt;fantasai> TabAtkins: That way nothing can interfere with its positioning<br>
&lt;fantasai> TabAtkins: That's how we specced it, are we doing something different now?<br>
&lt;fantasai> chrishtr: No, that's what spc and impl do<br>
&lt;fantasai> chrishtr: reparent into new stacking context that is z-indexed above everything else<br>
&lt;fantasai> chrishtr: It's well-specified, afaict<br>
&lt;fantasai> TabAtkins: Shouldn't have any effect on events, that works normally<br>
&lt;ntim> smfr: https://fullscreen.spec.whatwg.org/#rendering<br>
&lt;fantasai> chrishtr: My guess is chromium, hit testing happens on the layout box tree<br>
&lt;fantasai> chrishtr: so the impl probably sees the dialog element and then fails to look up the tree to see the inert attribute above it<br>
&lt;fantasai> chrishtr: If you see an inert node, stop at that node, but don't check ancestors<br>
&lt;fantasai> chrishtr: I think that's how impl, and not consistent with spec<br>
&lt;fantasai> chrishtr: Maybe we should discuss directly, should the impl just be exactly what Firefox and WebKit have already implemented?<br>
&lt;fantasai> chrishtr: Seems the difference is "?? cannot be iner, except when ... dialog"<br>
&lt;fantasai> emilio: That's a Gecko bug<br>
&lt;fantasai> emilio: Dialog is inert, we use the same mechanism<br>
&lt;fantasai> emilio: should be fixable<br>
&lt;fantasai> emilio: Rest of document is inert so can't do anything<br>
&lt;fantasai> emilio: but that seems like Gecko bug<br>
&lt;fantasai> emilio: other is, does this affect computed value of pointer-events?<br>
&lt;fantasai> emilio: In Gecko it does<br>
&lt;fantasai> emilio: The alternative was to have an internal property and check that everywhere you check pointer-events: none<br>
&lt;fantasai> emilio: This way clearer for implementers and authors<br>
&lt;fantasai> emilio: And less likely to accidentally cause divergence in the future<br>
&lt;fantasai> s/authors/more useful to authors/<br>
&lt;fantasai> chrishtr: UA style sheet?<br>
&lt;fantasai> emilio: A bit more magic than that<br>
&lt;fantasai> emilio: It's like an inherited property, which causes a bunch of other properties to compute differently<br>
&lt;fantasai> emilio: It's conceptually same as UA rule<br>
&lt;fantasai> emilio: In practice, we made an internal property to handle the inheritance.<br>
&lt;fantasai> emilio: Anything in subtree will have pointer-events: none forever, unless inert value is changed on descendant<br>
&lt;fantasai> [discussion of the implementation detail and how it's not visible to authors]<br>
&lt;fantasai> bkardell_: ???<br>
&lt;fantasai> emilio: ????<br>
&lt;fantasai> chrishtr: What about dialog?<br>
&lt;ntim> https://searchfox.org/mozilla-central/source/layout/style/res/ua.css#171<br>
&lt;ntim> https://searchfox.org/mozilla-central/source/layout/style/res/html.css#836<br>
&lt;fantasai> emilio: Sets the internal bit on the document element<br>
&lt;fantasai> emilio: and then dialog has a UA rule that applies this inert property to the default when modal<br>
&lt;smfr> s/???/does that also affect the accessibility bits?// ans: yes<br>
&lt;fantasai> chrishtr: So special exception not accessible to developers<br>
&lt;fantasai> emilio: right<br>
&lt;fantasai> emilio: There's no way, spec-wise, for devs to override that<br>
&lt;fantasai> emilio: we could add that capability, unsure how it would look<br>
&lt;fantasai> emilio: Spec says anything under inert subtree is inert, and no way to un-inert a node<br>
&lt;fantasai> flackr: I think it'd get complicated for anything other than top-layer to override<br>
&lt;fantasai> bkardell_: That's why top layer is important here<br>
&lt;fantasai> bkardell_: if you are in top layer, can reason about things<br>
&lt;fantasai> bkardell_: some details that are observable that we need to agree on and document<br>
&lt;fantasai> bkardell_: I believe that back in April, Alice suggested that she might want to take a look at revamping some of Chrome's internals to use a pointer-events-like behavior<br>
&lt;fantasai> bkardell_: There was some hesitance to say the magic *was* pointer-events<br>
&lt;fantasai> bkardell_: because seemed architecturally unfortunate<br>
&lt;fantasai> emilio: why?<br>
&lt;fantasai> emilio: pointer-events shouldn't really be a CSS property, but we're way past that point now<br>
&lt;fantasai> emilio: So given that, I'm happy to say that inert is managed via pointer-events<br>
&lt;fantasai> chrishtr: In the Intent to Ship that didn't complete for this feature<br>
&lt;fantasai> chrishtr: Alice tried it and didn't like it<br>
&lt;fantasai> chrishtr: Didn't like that not targettable from getElementsFromPoint<br>
&lt;fantasai> bkardell_: makes inspector break<br>
&lt;fantasai> emilio: yeah, but that's an issue with inspector<br>
&lt;smfr> q+<br>
&lt;fantasai> chrishtr: It doesn't make sense to have pointer-events: none; and then ...<br>
&lt;fantasai> chrishtr: UA can special-case inspector<br>
&lt;fantasai> bkardell_: we have problem with top layer already, can't inspect stuff underneath<br>
&lt;astearns> ack chrishtr<br>
&lt;astearns> ack smfr<br>
&lt;fantasai> smfr: We could always add an options dictionary to getElementsFromPoint<br>
&lt;TabAtkins> smfr: To let it include pointer-events:none or inert if we wanted to<br>
&lt;TabAtkins> bkardell_: And then devtools would use that by defualt<br>
&lt;TabAtkins> chrishtr: and we could do that as a feature enhancement and devtools can just use magic<br>
&lt;TabAtkins> chrishtr: asking tim/simon, is what Emilio said consistent with what WebKit does?<br>
&lt;TabAtkins> chrishtr: You do some magic thing that makes descendants of inert p-e:none and the dialog is exempted?<br>
&lt;TabAtkins> ntim: It's mostly the same yeah, we just don't hcange the computed styles for pointer-events<br>
&lt;TabAtkins> emilio: I slightly prefer actually changing the computed style, for the reasons i described before, but don't feel super strongly.<br>
&lt;TabAtkins> emilio: Would just be a little unfortunate and easy to make mistakes in the future for authors<br>
&lt;TabAtkins> ntim: Not changing computed styles gives us flexibility to change inert in the future or not be fully consistent with the p-e:none value, but don't feel strongly either<br>
&lt;TabAtkins> bkardell_: I have a slight pref for Apple's because it makes the impl detail visible<br>
&lt;TabAtkins> emilio: We do specify some things in terms of UA style, and other things in terms of "behaves as", so I don't have a strong opinion, it's just a slight pref toward reflecting it in the computed style<br>
&lt;bkardell_> s/makes the impl detail visible/ff's makes the implementation details observable<br>
&lt;TabAtkins> chrishtr: So it sounds like what's already in WK/Gecko is fine, and Chrome can change and the WG can agree on that in spec<br>
&lt;TabAtkins> chrishtr: So next is whether pointer-events:none is okay<br>
&lt;TabAtkins> astearns: Do we want to resolve on that first?<br>
&lt;TabAtkins> chrishtr: Talk about the next first<br>
&lt;TabAtkins> chrishtr: So Chrome originates the event up the tree to the first non-inert ancestor, Gecko just hit-tests down to the next non-inert in the stacking layer<br>
&lt;TabAtkins> chrishtr: I see why Gecko does this - it's easy to reuse behavior - but do we think it's the right semantic choice?<br>
&lt;TabAtkins> emilio: No strong opinion, but if there is a better choice it shoudl be a pointer-events value<br>
&lt;TabAtkins> ntim: Makes sense to me because you can have non-inerts inside of inert trees<br>
&lt;TabAtkins> chrishtr: But that's non web-exposed as a feature, just for this thing<br>
&lt;TabAtkins> TabAtkins: But it's a reasonable use-case that authors would want to do similar things with; why would we treat it as a special case they can't use?<br>
&lt;TabAtkins> chrishtr: Right. I think the question of mixed inertness is separate from whether you hit-test below it.<br>
&lt;TabAtkins> emilio: Yes, orthogonal<br>
&lt;smfr> q+<br>
&lt;TabAtkins> chrishtr: So argument ot make is that p-e:none is already there and sky isn't falling, so maybe it's fine<br>
&lt;TabAtkins> emilio: Yeah, and if we did it another way anyway, we should just add a new p-e value to it<br>
&lt;TabAtkins> flackr: I think hit-testing behidn the thing works well for a lot of use-cases where you have an event handler on an ancestor<br>
&lt;TabAtkins> TabAtkins: That works either way tho - Chrome's behavior will walk the<br>
&lt;TabAtkins> smfr: But that could mean an element gets the event even if you're lcicking elsewhere, if the clicked child is positioned outside<br>
&lt;TabAtkins> TabAtkins: Yeah, but it would have gotten the element if the child weren't inert<br>
&lt;TabAtkins> smfr: [missed about backdrop]<br>
&lt;TabAtkins> ntim: You can display:none the ::backdrop<br>
&lt;TabAtkins> ntim: Question was if we can pierce the top-layer, yes we can<br>
&lt;TabAtkins> chrishtr: Visually yes, but not hit-testing<br>
&lt;TabAtkins> ntim: Because everything else is inert, yes<br>
&lt;emilio> q+<br>
&lt;astearns> ack smfr<br>
&lt;chrishtr> q+<br>
&lt;TabAtkins> emilio: Lacking a strong use-case to pursue a new p-e value, I suggest we just stick with none, and maybe change in the future if we feel it's needed<br>
&lt;TabAtkins> emilio: I'm okay on blocking on the new value if people think it's useful, but unless there's a strong reason to do it...<br>
&lt;TabAtkins> flackr: And there are a lot of use-case for *not* hitting an ancestor, which is p-e:none today, so we should stick with that by default<br>
&lt;astearns> ack chrishtr<br>
&lt;emilio> ack emilio<br>
&lt;TabAtkins> chrishtr: Agree with emilio and rob that we don't have a strong reasons to *not* use p-e:none, so we should just use that<br>
&lt;TabAtkins> chrishtr: So that allows us to resolve<br>
&lt;TabAtkins> chrishtr: I propose we resolve on the webkit behavior - don't expose the computed style (for the reason brian mentioned) and use p-e:none behavior<br>
&lt;TabAtkins> chrishtr: And when inert is set, force p-e, focus, etc in a user-agent way that's not exposed to devs<br>
&lt;TabAtkins> chrishtr: And elementFromPoint() skips the inert elements<br>
&lt;TabAtkins> astearns: I'm a little concerned about having this magic UA behavior...<br>
&lt;TabAtkins> astearns: If it's not *expressible* by authors; I want to make sure that what the UA does is something all the engines can implement in an interoperable way<br>
&lt;TabAtkins> astearns: Usually that means we have a property with the behavior<br>
&lt;TabAtkins> astearns: I'm concerned that magic means we might not get the details right<br>
&lt;TabAtkins> chrishtr: emilio, am I right that the Gecko impl just sets a UA-internal prop?<br>
&lt;TabAtkins> emilio: Yeah<br>
&lt;TabAtkins> flackr: And I think it's equivalent to a descendant selector with p-e:none in the UA, and equivalent rule for modals, etc<br>
&lt;TabAtkins> emilio: Not quite there becuase of shadow dom, it's actually inherited, but close enough<br>
&lt;TabAtkins> astearns: I don't think we've done a feature as a magic property<br>
&lt;TabAtkins> TabAtkins: We've never *specified* one as such, but several features are implemented as such<br>
&lt;fantasai> +1 I'm not concerned about speccing this<br>
&lt;emilio> +1<br>
&lt;TabAtkins> bkardell_: I kinda agree with everyone else; if we can come up with a demonstrable reason to expose this, that should be a separate discussion<br>
&lt;astearns> ack fantasai<br>
&lt;TabAtkins> Proposed resolution: Resolve on WK behavior. Use pointer-events:none, but don't reflect into computed style (use "behaves as" wording); same with user-select and related focus behavior<br>
&lt;TabAtkins> ntim: question about interaction of inert and modals, what if you have an inert node as ancestor of modal?<br>
&lt;TabAtkins> emilio: depends on details of how we spec, maybe modal dialogs are just always non-inert<br>
&lt;TabAtkins> bkardell_: The direct descendant of a top-layer should never be inert, right?<br>
&lt;TabAtkins> ntim: We could let people explicitly opt out of inert<br>
&lt;TabAtkins> emilio: I agree this is a different issue<br>
&lt;TabAtkins> emilio: If we decide that inert works this way, they can still spec it how they want<br>
&lt;TabAtkins> emilio: I do think that a modal dialog should never be inert unless exlicitly given inert<br>
&lt;TabAtkins> bkardell_: Do we need to talk about isInert()?<br>
&lt;TabAtkins> ntim: That's internal<br>
&lt;TabAtkins> ntim: What about &lt;dialog modal inert>?<br>
&lt;TabAtkins> emilio: We should let HTML decide on that<br>
&lt;TabAtkins> emilio: I think it's edge-casey and we should just deal with the general problems here<br>
&lt;TabAtkins> astearns: So punt on explicitly-inert dialog question for now.<br>
&lt;TabAtkins> astearns: Any other discussion?<br>
&lt;TabAtkins> smfr: Where are we writing this? No spec for hit-testing yet<br>
&lt;TabAtkins> chrishtr: Should it live in HTML?<br>
&lt;TabAtkins> TabAtkins: We've got other hit-testing things that we need to define in CSS<br>
&lt;TabAtkins> chrishtr: But for this it just needs to define that something "behaves as..."<br>
&lt;TabAtkins> ntim: And there's already an HTML heading for it<br>
&lt;TabAtkins> florian: Do we need a spec for this with a "Hit Testing: TBD" section?<br>
&lt;TabAtkins> chrishtr: Yes, I took an action item to find someone for that two weeks ago.<br>
&lt;TabAtkins> chrishtr: Would be useful to make an empty spec with a TODO<br>
&lt;TabAtkins> fantasai: Maybe useful for a subsection in UI-4?<br>
&lt;florian> s/with a "Hit Testing: TBD" section?/with a "Hit Testing: TBD" section, and the rest of the spec being a copy of the relevant part of CSS2?/<br>
&lt;TabAtkins> florian: pointer-events:none is not really specified<br>
&lt;ntim> https://html.spec.whatwg.org/multipage/interaction.html#inert-subtrees<br>
&lt;TabAtkins> chrishtr: Oh yeah jeez, we should add a paragraph saying p-e:none means you're not hit-tested<br>
&lt;ntim> top layer is very intuitively in fullscreen<br>
&lt;TabAtkins> RESOLVED: Resolve on WK behavior. Use pointer-events:none, but don't reflect into computed style (use "behaves as" wording); same with user-select and related focus behavior<br>
&lt;TabAtkins> RESOLVED: Add definition of p-e:none, at least, to UI 4<br>
&lt;chrishtr> @smfr what was the top layer stuff that needed specifying that tab just mentioned?<br>
&lt;smfr> chrishtr: see https://fullscreen.spec.whatwg.org/#rendering<br>
&lt;TabAtkins> Yeah they want us to steal that section<br>
&lt;TabAtkins> So we should<br>
&lt;fantasai> [disussing who should draft spec text]<br>
&lt;fantasai> TabAtkins: Also, should we steal the rendering section of fullscreen and import into csswg?<br>
&lt;TabAtkins> smfr: We might already ahve a resolution for specifying top-level<br>
&lt;TabAtkins> astearns: so proposed resolution is to put top layer into Positioning if we don't already have a resolution for it<br>
&lt;TabAtkins> bkardell_: There were some PRs about top layer in HTML itself.<br>
&lt;TabAtkins> astearns: I imagine we can steal the current spec text as-is and the inherit any issues from Fullscreen and HTML<br>
&lt;TabAtkins> astearns: objections?<br>
&lt;TabAtkins> RESOLVED: Steal the top-layer spec from Fullscreen, put it into Position 3.<br>
&lt;emilio> \o/ for making progress on `inert`<br>
</details>


-- 
GitHub Notification of comment by css-meeting-bot
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/6685#issuecomment-930305697 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Wednesday, 29 September 2021 15:51:24 UTC