Re: Event handling in clipping conditions

Hi, Thomas-

The SVG WG has been talking about this whole issue.  Rather than come
back immediately with a conclusion, we would like to discuss it with you
and others more on-list first.

Replies inline...

thomas.deweese@kodak.com wrote (on 12/5/08 6:38 AM):
> 
> www-svg-request@w3.org wrote on 12/05/2008 04:29:35 AM:
> 
>> On Dec 4, 2008, at 22:52 , Thomas.DeWeese@Kodak.com wrote:
>> > www-svg-request@w3.org wrote on 12/04/2008 10:43:58 AM:
>> > > [[
>> > > 14.3.6 Clipping paths and geometry
>> > > [...]
>> > > Therefore, an element which has 'pointer-events' property
>> > > values which depend  upon the visibility of the element
>> > > (i.e. 'visiblePainted', 'visibleFill', 'visibleStroke',
>> > > 'visible') will not receive pointer events for the
>> > > occluded parts of the element.
>> >
>> >    So does this apply to Mask as well, which has _exactly_ the same
>> > appearance implications in many cases?  If so at what level of
>> > opacity does the Mask stop transmitting events?
>>
>> It's not about the appearance implications, display none, visibility  
>> hidden, and opacity 0 all have the same appearance implications but  
>> different semantics, and behave differently.
> 
>    When I read the quoted part of the errata it seems pretty clear
> that it tying the concept of pointer events that refer to the
> 'visibility' of the element to the actual visibility
> of the element.

Yes, in a sense.  But 'visibility' and 'opacity' are different
properties, with different effects on pointer-events. [1]


>> I'd expect mask to work  like opacity, but that's just my
>> personal opinion.
> 
>    Sure, but I would argue that given the wording in the spec one
> could easily decide that an element with opacity="0" should not
> receive events if it's pointer-events is any of the 'visible*'
> values; "Will not receive pointer events for the occluded parts
> of the element".

We certainly didn't intend to convey that... can you suggest a better
way of wording it?


>> > > We believe that this is the most consistent and predictable  
>> > > behavior, and that it should be relatively simple to implement.
>> >
>> >    It's not very consistent with the mask element.  And implementing
>> > it with mask may not be relatively simple to implement...
>>
>> In what way is the behavior not consistent with mask?
> 
>    <clipPath id="clip1">
>      <rect x="0" y="0" width="640" height="480"/>
>    </clipPath>
>    <g clip-path="url(#clip1)"> <!-- Doesn't recieve events outside rect -->
>         ....
>    </g>
> 
>    <mask id="mask1">
>      <rect x="0" y="0" width="640" height="480"/>
>    </mask>
>    <g mask="url(#mask1)"> <!-- Does recieve events outside rect -->
>         ....
>    </g>
> 
>    These two snippets have effectively identical results on the
> image, the difference being that the mask will likely have anti-aliased
> edges.  

Actually, they have different use cases, and as an author, there have
been times when I wanted to achieve both effects. [2]


> Honestly I think that clipping is simply a lightweight version
> of mask, so I think adding this extra baggage to clip retroactively
> is really not good.  

>From checking various implementations, clipping and masking don't seem
to share the same behaviors, and thus don't seem to be using the same
code.  I wouldn't infer too much from this passage.


> In fact the standard it's self seems to support
> this view (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.


>    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.

Perhaps we should clarify this in SVG 2.0.


>> >    There are of course other cases that have similar issues like
>> > filters where the actual geometry can be offset from the apparent
>> > geometry.
>> >
>> >    My personal opinion is that content authors should handle these  
>> > cases with 'hidden' event targets that gives them much more control
>> > over the behavior they desire.
>>
>> I don't think that's a very nice solution, it forces people to update  
>> things twice whenever they script or animate.
> 
>    Sure, I understand that the specification as written isn't perfect
> but this 'patch' is really a poor hack for the real problem.  I'll
> agree that it captures a good chunk of the common use cases but I
> think it does it in a clumsy way that is likely to cause problems
> in the future.

What problems do you anticipate?  I don't think it's a hack... I think
it's a logical extension of the questions that arise between geometric
effects and pointer-events.


>    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.

In fact, we originally discussed doing the very same thing with clipping
effects.  But I don't personally think that we need to add special
attributes when the desired behavior can be achieved more simply.  As
you mention, the combination of 'pointer-event' values captures most (or
all?) behaviors that users could want from clipping paths regarding
pointer events... If you can think of cases that aren't covered, that
would be helpful in determining if we have made the right decision here.


>> And even if it were a solution, UAs still need to have properly defined
>> interoperable behaviour for hit testing in all cases.
> 
>    I would argue the standard already has an interoperable behaviour.
> The standard makes no reference to clipping with regards to hit testing,
> why someone would decide that they should added such a thing when it is
> totally absent from the standard makes no sense to me.  I understand that
> a number of UA agents decided to do just that but it doesn't make it
> correct.  Going this route wouldn't even require an errata it would
> simply be a clarification.

The fact that we encountered different behavior from WebKit/Safari and
Firefox and Opera regarding how pointer-events are treated, and what the
effect was on the bounding box, shows that we didn't have
interoperability.  When authors are depending on the same behavior for
edge cases like this, it is frustrating to find that one or the other
browser acts differently.


>    Aside from all the above I have an actual question on implementation
> of the proposed errata.  The errata talks a lot like the element with
> the clip-path and the event target must be the same element.  In practice
> the clip is often on a higher level 'g' element.  So the question I
> have is do I take the errata literally and stop event propagation if
> the 'g' element has pointer-events="visible" and the event is outside
> of the clip the event will not propagate to the children of the 'g'
> even though some of the children may have their pointer-events set to
> 'all' (and hence should not be effected by clipping).

That's a good point we should clarify.  Do you have an opinion?
Personally, I say that it should happen at the target-element level,
regardless of the pointer-event value at the referencing element.


>    It's especially unclear because of course a 'g' element is never
> actually the event target (and hence it's pointer-event's property
> is currently never used in SVG).  I actually think it's more useful
> if the pointer-event property of the element with the clip-path
> effects event propagation for that clip as it allows one to
> effectively control if the clip-path also effects events (which I
> think is more useful than overloading the pointer-events property
> on the actual target which would then need to serve two masters).

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.

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.

[1] http://www.svg-whiz.com/svg/HideShow.svg
[2]
http://dev.w3.org/SVG/profiles/1.1F2/errata/errata.xml#capturing-pointer-events-zero-opacity

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

Received on Tuesday, 9 December 2008 08:49:35 UTC