[whatwg] Outline style to use for drawSystemFocusRing

Ian Hickson ian at hixie.ch
Fri Jan 24 16:32:45 PST 2014


On Tue, 7 Jan 2014, Dominic Mazzoni wrote:
> On Tue, Jan 7, 2014 at 1:10 PM, Ian Hickson <ian at hixie.ch> wrote:
> >
> > If the user needs a big ring, it seems bad for us not to render one. 
> > Especially since we can know this.
> 
> Yes, there are users who need extra high-contrast focus rings. But no, 
> they don't get that from an operating system setting that the app 
> queries, I think that's the source of the confusion.
> 
> Try checking the "Make the focus rectangle thicker" checkbox in Windows. 
> Any time where a single-pixel dotted outline was shown before, you'll 
> now see a 2-pixel dotted outline. However, in every application I tried, 
> when previously you saw a custom focus highlight (which is the majority 
> of the time - the dotted outline looks very dated), there's no change - 
> including in Windows explorer, Office, IE, Firefox, etc. - I just don't 
> see any precedent for applications that already provide custom focus 
> highlighting to do something different when the "Make the focus 
> rectangle thicker" option is checked.

Why isn't this just a widespread accessibility bug?


> > If you want to give the AT position information when there's no 
> > visible focus ring, that's what addHitRegion() is for.
> 
> For the record, I like addHitRegion and I'd like to go forward with 
> implementing it too. Do you consider it ready for implementation?

Yeah, I'm not aware of any outstanding work for it right now.


> Have any other browsers expressed interest?

I do not recall specific comments from browser vendors one way or the 
other.


> The impression I got a while back was that there were still concerns 
> from some people.

I'm not aware of any outstanding concerns.


> We should probably start a new thread on addHitRegion if there's 
> anything to discuss, and keep this one focused on drawSystemFocusRing, 
> since that's the one that it appears three browsers have implemented 
> now. (I'm assuming IE is implementing it, given that Microsoft has 
> publicly commented on the spec.)

The reason I think it's relevant is that if what people want 
drawSystemFocusRing() to do is in fact what addHitRegion() does, then we 
should not do both.


> It wasn't my intent to implement something different than the spec. The 
> spec only talks about the accessibility part of the implementation in a 
> Note explaining the meaning of "Inform the user", which I didn't think 
> was normative. I took the language in that note as a guide but 
> ultimately tried to implement something that actually works. I made a 
> simple demo app to demonstrate the use of this API, and tested it with 
> three screen magnifiers while developing it.

I apologise that the spec was misleading in its note.

I've tried to update the spec to remove this confusion (and made the new 
paragraph normative.)

I think in practice it may be that for accessibility the right thing is 
for authors to use addHitRegion(), and the focus ring drawing APIs should 
only draw the focus ring and do nothing else.


On Tue, 7 Jan 2014, Rik Cabanier wrote:
> On Tue, Jan 7, 2014 at 9:45 PM, Ian Hickson <ian at hixie.ch> wrote:
> > On Tue, 7 Jan 2014, Rik Cabanier wrote:
> > >
> > > I believe this is where part of our confusion/disagreements come 
> > > from. The draw*FocusRing methods are NOT direct-mode APIs for 
> > > *a11y*.
> >
> > Right. They're not really APIs for accessibility at all. They're about 
> > drawing focus rings.
> 
> No. The only reason for this API is accessibility.

That was not the primary intent of the APIs. (Accessibility, like 
security, performance, or internationalisation, is almost never the 
primary intent of a well-designed API, since accessibility, like security, 
performance, and internationalisation, are concerns that permeate _every_ 
API and well-designed APIs make them non-issues.)


> An author could just check the focused state and draw the ring himself; 
> there's no need for an API to do this.

There's no way to draw a focus ring that has the appearance of the 
platform's focus rings without an API for it.


> > > By calling draw*FocusRing on a fallback element, the a11y software 
> > > will now associate that element (and its aria rules) with the path 
> > > that was in the canvas' state.
> >
> > This is non-conforming behaviour that is incompatible with the API 
> > design. Doing this will cause harm, because the API is incapable, as 
> > designed, of being used in this manner correctly without causing bugs. 
> > For example, if, when an element is not focused, it's split into four 
> > parts, there's no way to draw a single focus ring around it. Thus the 
> > data about that control's position _will be incorrect_ if the UA 
> > relies on this method for this data.
> 
> I don't understand. The path for the focus ring can be anything, 
> including multiple closed paths. The data for the a11y software won't be 
> wrong, it will be the boundingbox of those paths.

Right. If the intent, however, is for one part of the element to be 
magnified, and the other parts to just be decorative, then this would 
result in the wrong bounding box for the AT.

   
> > > This HAS to be stateful because the a11y software queries the 
> > > browser for the bounds of the fallback element to draw its own focus 
> > > rectangle.
> >
> > The paths provided by the draw*FocusRing() methods aren't useful for 
> > this purpose. Using them for this purpose is bogus. The paths provided 
> > to those methods are only useful for direct-mode painting and 
> > direct-mode notification to an AT API if such an API accepts 
> > direct-mode notifications. If it doesn't, then the addHitRegion() API 
> > is what should be used to send the notifications.
> 
> No, the AT API is not direct mode.

For accessibility APIs that do not accept direct-mode notifications, the 
draw*FocusRing() methods aren't useful, and the addHitRegion() API is what 
should be used to send the notifications.


> > > For the blink and firefox implementations (and the webkit patch) 
> > > "informing the user" [1] means telling the DOM about the region of 
> > > the fallback element so the a11y software can query it later.
> >
> > That's not conformant, and will lead to accessibility problems.
> >
> > Informing the user is an imperative action, not an indirect action 
> > involving caching state over multiple frames.
> 
> If that is the case, we should drop focus ring support. There's no point 
> to just draw rings.

I am in agreement that implementations should not attempt to use the 
draw*FocusRing() methods to set state in accessibility APIs.

This is separate from whether we need an API to draw a focus ring that 
obeys platform conventions, which is useful irrespective of accessibility 
API concerns.


> > > Because of this, there also needs to be a way to disassociate the 
> > > region from the fallback element (ie by having no current path when 
> > > you call draw*FocusRing)
> >
> > Yes, if draw*FocusRing() were the API you describe, we would need such 
> > a thing. The API you describe, however, is not draw*FocusRing(), it's 
> > addHitRegion(), and it already has such a thing.
> 
> addHitRegion is a much bigger implementation burden for authors and 
> browser vendors. My fear is that given their complexity, authors will 
> not provide a11y support.

It's actually simpler for authors to use addHitRegion() to set the region 
of a control than it is for them to use the focus rings APIs, as 
demonstrated by the examples in the spec, e.g.:

 function drawCheckbox(context, element, x, y, paint) {
   context.save();
   context.font = '10px sans-serif';
   context.textAlign = 'left';
   context.textBaseline = 'middle';
   var metrics = context.measureText(element.labels[0].textContent);
   if (paint) {
     context.beginPath();
     context.strokeStyle = 'black';
     context.rect(x-5, y-5, 10, 10);
     context.stroke();
     context.addHitRegion({ control: element });
     if (element.checked) {
       context.fillStyle = 'black';
       context.fill();
     }
     context.fillText(element.labels[0].textContent, x+5, y);
   }
   context.beginPath();
   context.rect(x-7, y-7, 12 + metrics.width+2, 14);
   if (paint && context.drawCustomFocusRing(element)) {
     context.strokeStyle = 'silver';
     context.stroke();
   }
   context.restore();
 }

The addHitRegion() call can just be added wherever you have a convenient 
path. The drawCustomFocusRing() call is in an if-statement. I'd say 
they're at least as simple as each other, but actually I think 
addHitRegion() ends up being simpler.

It also does other things, things which authors will want, like getting 
the cursor to change in real time as the user hovers the canvas, without 
having to do any additional hit testing.


On Tue, 7 Jan 2014, Dominic Mazzoni wrote:
> 
> A11y APIs on every platform I'm familiar with (Windows, Mac, Linux/ATK, 
> Android, iOS) are essentially retained-mode. When focus changes, the 
> application notifies the system and gives it an ID or reference that 
> identifies the focused object. Assistive technology may query the bounds 
> of this object immediately, or at any time in the future. If you restart 
> or load a magnifier while the browser is already running, it will 
> explore the tree, discover the object that has focus, and zoom the 
> screen and/or draw its own ring around it at that time.

This makes sense, yes. This is the kind of API for which addHitRegion() is 
well-suited.


On Wed, 8 Jan 2014, Rik Cabanier wrote:
> 
> Note that the draw*FocusRing functions don't update the a11y of the 
> canvas. Instead, they update the fallback element's region. This element 
> is part of the HTML DOM and as such, is retained.

They don't update anything. All they do is paint to the canvas, and, 
optionally, send a direct-mode notification if the OS supports it.


In any case. If there's no implementation interest in supporting 
the "draw high-contrast focus rings if necessary otherwise do nothing" 
API, we can certainly drop drawCustomFocusRing(). I think that would be a 
shame, but it's not a huge loss.

If implementors feel that it'd be better to not support direct-mode 
accessibility APIs at all, we can also drop the mention of "inform the 
user" in the drawSystemFocusRing() API. We can always update the spec 
again should a platform come around with such an API.

-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'



More information about the whatwg mailing list