Re: Event handling in clipping conditions

Hi, Thomas-

Thanks again for your input.  Replies inline...

thomas.deweese@kodak.com wrote (on 12/10/08 7:09 AM):
>  
> Doug Schepers <schepers@w3.org> wrote on 12/09/2008 03:49:24 AM:
> 
>> We certainly didn't intend to convey that... can you suggest a better
>> way of wording it?
> 
>    Therefore, an element which has 'pointer-events' property values
> which depend upon the 'visibility' property of the element (i.e.
> 'visiblePainted', 'visibleFill', 'visibleStroke', 'visible') will not
> receive pointer events outside of the clipping region, regardless of
> the setting of the 'visibility' property.  Within the clipping region
> the 'visibility' property acts normally on event sensitivity.

Great, thank you.  We agree that this wording does make it more clear,
and I have replaced the relevant section with this wording.


>    Of course this will need to be rewritten/augmented to clarify
> the relationship between the clip-path element and the event target.

Understood.


>> >> In what way is the behavior not consistent with mask?
> 
>> > from 14.3.1 Introduction:
>> >
>> >      A clipping path can be thought of as a mask wherein those pixels
>> > outside the clipping path are black with an alpha value of zero and
>> > those pixels inside the clipping path are white with an alpha value
>> > of one (with the possible exception of anti-aliasing along the edge
>> > of the silhouette).
>>
>> This strikes me more as an explanatory metaphor, rather than an
>> implementation (or authoring) direction.  The basic concepts are
>> similar, but they diverge from there.
> 
>    Well in Batik we actually do turn clip into a mask when
> shape-rendering="geometricPrecision" on the clipPath element,
> giving fully anti-aliased edges on the clip path[1].  For performance
> we also support the more common 'hard edged' clip as well.

Cameron did not seem to think it would be hard to adapt the Batik code
to match the more detailed description of clipping and pointer-events,
so presumably this is not a blocker?


>> >    The two features are combined in one chapter in the specification.
>> > Really this addition to the standard is the first instance where a
>> > significant _semantic_ difference between the two elements is introduced
>> > (clipping effects events as well as rendering).
>>
>> The visual effect is similar, so it does make some sense to bundle them
>> together.  However,  masks have a closer similarity to filters, in that
>> they are both raster operations, than on the geometric rendering effects
>> of clipping paths.
> 
>    I doubt any SVG engine treats clip as a geometric rendering effect.  
> All engines I am aware of handle clip as a raster operation, typically as
> some sort of runs/boxes of unclipped _pixels_.  This is faster and more
> compact than a full mask but is very different from treating it as a
> geometric effect (which would involve geometric intersection of the
> vector geometry).  Often the rasterization is limited to the bbox of the
> clip path which is vaguely vector oriented but the same optimization
> applies to mask.

Fair enough.  But still, that is an implementation detail that doesn't
necessarily impact the issues at hand, specifically:

* determining the bounding box of clipped elements

* indicating whether and how pointer-events on a clipped element are
affected by clipping

* indicating whether and how pointer-events are affected by masks


>> >    Really the SVG standard should (eventually) have a defined set of
>> > properties that actually act on events that is orthogonal to rendering.
>> > Trying to tie the two together is just too likely to cause unintended
>> > side effects.  A really nice SVG 1.2 solution would be and 'event-clip'
>> > property that can either reference a clipPath element, or have the
>> > value 'clip-path' (which uses what ever clip-path is referencing).
>> >
>> >    My fear is that this quick fix will make that future 'clean'
>> > solution to the problem more complex and likely not backwards
>> > compatible.
>>
>> The SVG WG has talked about more nuanced attributes to modify events
>> based on raster effects such as those with filters, and we may still do
>> this.  The proposed errata wording doesn't seem to close any doors
>> regarding this.
> 
>    This change ties clip path to event propagation directly, perhaps
> worse it ties the visibility values for pointer-events to clipping.  
> I'm not sure how you would fix that later unless you simply broke
> backwards compatibility, or end up with a default special 'backwards
> compatibility' value (as mentioned in my other message).

The SVG WG doesn't see a conflict there.  Indeed, as you suggest, the
initial value for such a property would be the same as the current
behavior.  This is a pragmatic way of adding new properties.

So, this new potential value would be applicable to the <clipPath>
element (as opposed to the current behavior, which is tied to the values
on the "target" of the clip).  The initial value of the 'event-clip'
property would be 'default' (or something), which would simply cede
control of pointer-event behavior to the clipped elements.  There would
be 3 additional values (please ignore the names for now), 'clip-area'
(pointer events only on the areas not clipped), 'all' (pointer events on
the clipped and non-clipped area), and 'none' (no pointer events).
These values would probably override any "local" values, though I can
also see a case for them being supplementary... that is, given the
following:

  <clipPath id="rectClip1" event-clip="clip-area">
    <rect x="30" y="0" width="40" height="300" />
  </clipPath>

  <circle cx="50" cy="50" r="30" fill="blue"
    clip-path="url(#rectClip1)" pointer-events="visiblePainted"/>

  <circle cx="50" cy="150" r="30" fill="yellow"
    clip-path="url(#rectClip1)" pointer-events="all"/>

  <circle cx="50" cy="250" r="30" fill="red"
    clip-path="url(#rectClip1)" pointer-events="none"/>

The clipPath would allow pointer events within the non-clipped parts
only... so, the blue circle would act normally (that is, the non-clipped
part would be sensitive to pointer events, as expected from its value);
the yellow circle would behave just the same as the blue one, despite it
explicitly allowing pointer-events on the clipped parts (this behavior
would be overriden by the 'event-clip' value of the <clipPath>);
finally, the red circle would not be sensitive to any pointer events at
all (despite it being allowed by the 'event-clip' value, this element
explicitly "declines the offer" to receive pointer events).  If the
'event-clip' value were 'all', then the behavior of the blue and the red
circle would remain the same, but the yellow circle would be sensitive
to pointer events in or out of the clipped area.  If the 'event-clip'
value were 'none', then none of the circles would be sensitive to
pointer events at all.

That would seem most intuitive to me, and not too burdensome to
implement, and would be compatible with existing behavior.  That said,
were we to add this, we'd have to discuss it at that time.  If you are
interested in seeing this, I'd be happy to raise an issue on SVG 2.0, to
make sure we cover the case, and we would be grateful if you were to
help us define it.


>     So let me put it this way.  What was the justification for these
> implementations clipping events?  What part of the SVG 1.1 specification
> lead them to believe this was the correct implementation?

Because the spec didn't specify behavior one way or another, the
implementers had to make a judgment call.  You made the decision that
events weren't clipped, probably based on the way it fell out of your
architectural model, and I'd guess that others did the opposite but for
the same reasons.  Possibly they looked at the way viewport-establishing
elements clipped events and mimicked that, or possibly they simply
thought this was the most useful or intuitive way to do it for content
authors and users.  Presumably some copied the behavior of other UAs; I
know that some issues, some people have simply followed Batik's behavior
where the spec wasn't clear (and that is generally good for
interoperability), so it may be that that's why WebKit does it the way
it does.

Personally, I would expect events to be clipped by default.  Maybe my
mental model of pointer-events ties them to the element being visible.
If other authors have a different opinion, I invite them to chime in here.


>    There is no way to keep an implementer from doing anything they want.
> Is it really incumbent on the specification to say 'clipping does not
> effect events'?  If so then it must list every other feature of SVG
> that doesn't effect events, of course standards aren't written that way.

Well, the more precise the specification, the easier it is for authors
to make content that works interoperably, and the easier it is to
implement (usually)... implementers and authors know exactly what
behavior to expect.  Sure, implementers could do whatever they want, but
I know that Opera and Firefox have gone to great pains to get more
errata issued, to clarify issues, and they follow the specification
where it is clear.  So, I argue that implementers generally act in good
faith.


>    Anyway this is a moot point as the WG has clearly decided to make
> the standard conformant with implementations.

While I think that is often justifiable, in order to make sure everyone
is on the same page, that's not how we made this decision.  There is no
interoperability:  Firefox and Opera (and IIRC, ASV) do one thing (the
clip events), and Batik and WebKit do another (they don't clip events).
 We looked at what authors might want to do, and realized that both
cases are useful for different situations.  So, we opted against the
behavior of any one implementation, and specified the behavior we
thought would give the author the most flexibility.



>> >    Aside from all the above I have an actual question on implementation
>> > of the proposed errata.
> 
>> That's a good point we should clarify.  Do you have an opinion?
> 
>    See my other note.

I've clarified this point in the errata, stating that it is the
event-target's 'pointer-events' property that matters, not that of the
parent.


>> I can definitely see where you are coming from here, wanting more
>> general control over how pointer-events are treated within a given
>> clip... but I can also see wanting finer control at the target-element
>> level.  There are use cases for both.
> 
>    I don't really see a use case where some of the children of an
> element should have event's clipped and others shouldn't.

How about a map where you can grab and drag clipped parts of the map
into or out of the clip viewport, but location icons only pop up
infobubbles when they are visible (inside the unclipped area)?

But the more important part of this is not that different child elements
could have different values... it's that authors have control over what
the behavior is at all.


>> If we do add a way to control pointer events at the level of the
>> clipPath itself, we can provide values that override the behavior at the
>> clipped-element level.  This would provide for more author options.
> 
>    Sounds complex to me (in some cases we stop all event propagation
> in some cases we have to mark the event as clipped but continue to
> propagate, getting the processing order right seems complex).  It also
> wouldn't address the fact that the proposed errata mixes
> visibility='hidden' and clipping which I think are distinct cases.

The members of the SVG WG thinks that though they are indeed orthogonal,
yoking them in this way gives an intuitive and simple way to author
content that behaves in a consistent way (an elegant hack).  The fact
that the specification already yokes pointer-events with visibility
makes this a natural extension.


thomas.deweese@kodak.com wrote (on 12/10/08 6:21 AM):
> 
...
> 
>      The current primary WG proposal is that pointer-events on the
> target element can control event clipping for that element.  So if
> pointer-events has any of the 'visible' values then it will not receive
> events that fall outside of any parent's (or selves) clip region.
> 
>       The problem is that this reuse of existing pointer-events values
> means that a document that used 'visibility="hidden"' in conjunction
> with 'pointer-events="fill"' to place event targets would suddenly have
> those event targets have their events be unclipped.  Since I believe the
> above set of properties is the 'best practice' for event targets I think
> this
> is problematic as it would make such a document unable to be enclosed
> in say a scroll-window (the case that triggered this whole issue).

I suspect that the use of that particular combination of elements and
property values is not a common use case (though I'm happy to look at
evidence to the contrary).  A more common and better practice would be
to establish a viewport via a nested SVG element, which is not affected
by these clarifications (a point I have clarified in the errata).  Also,
instead of using 'visibility', the author could use 'opacity' to create
hidden event hotspots.  So, for the great majority of those cases, there
is an easy workaround.


>        Based on that I would like to make a potentially simpler counter
> proposal  that also covers the major use cases but will likely need to be
> extended in future versions of the SVG standard.  Only have the clip of
> elements that create a view-port clip events.  If overflow="visible"
> then they
> wouldn't clip events (in cases where you wanted graphical clipping but not
> event clipping you could add a 'g' with a clip that matches the viewBox of
> the view port creating element as the first child.  This doesn't support
> clipping
> events but not clipping content (but I think that is an unusual use case).
> 
>       Obviously this isn't as flexible as allowing arbitrary clip paths
> for events but
> I think it handles the major case for event clipping which is view-porting.

This proposal is reasonable, but it doesn't cover the case of
non-rectilinear clipping paths.  That is a fairly large set of potential
use cases.  I suppose we could introduce a viewport-establishing element
with an arbitrary shape, but then that would confusingly duplicate
<clipPath>, so it's simpler all around to merely specify the desired
behavior for <clipPath>.


Ultimately, we simply have to make a choice about the behavior in order
to get interoperability, and we are choosing what we think best serves
the needs of the authors.  However, we value your viewpoint, and will be
following up with other implementers to make sure that what we are
proposing is suitable for them, as well.  If it turns out that they too
disagree with our judgment here, then we will revisit this at that point.

Regards-
-Doug Schepers
W3C Team Contact, SVG and WebApps WGs

Received on Wednesday, 17 December 2008 18:25:29 UTC