Closed Bug 254966 Opened 20 years ago Closed 20 years ago

overflow:scroll/auto not keyboard accessible/focusable

Categories

(Core :: DOM: UI Events & Focus Handling, defect)

x86
All
defect
Not set
normal

Tracking

()

VERIFIED FIXED

People

(Reporter: aaronlev, Assigned: aaronlev)

Details

(Keywords: access, testcase)

Attachments

(6 files, 2 obsolete files)

In order for position:fixed and overflow:scroll objects to be accessibility and section 508 compliant, they must be in the tab order and be able show focus. This is what IE already does.
Turns out IE has these problems too -- thought I had seen otherwise. We still need to fix this for section 508 compliance.
Summary: position:fixed and overflow:scroll not keyboard accessibile → position:fixed and overflow:scroll not keyboard accessible
duplicate of 140644?
No, that bug is related to caret browsing (moving selection). This one is tabbing (moving focus).
Attached patch Patch, tested-works (obsolete) (deleted) — Splinter Review
1) nsFrame.cpp: Scrollable HTML frames should be focusable+tabbable 2) nsEventStateManager.cpp: Allow multiple focusable elements in the same ancestor chain 3) nsPresShell.cpp: GetNearestScrollingView uses focus not selection 4) SetFocus() asks frame if focusable, which knows more than content does
Comment on attachment 155935 [details] [diff] [review] Patch, tested-works I'll use bryner or roc for sr=
Attachment #155935 - Flags: review?(mats.palmgren)
Attached file Testcase #1 (deleted) —
The patch works fine in most cases (and is close to what I had ;-), but there are a couple of cases where the tabbing isn't doing what I'm expecting. 1. When tabbing forward over the 2nd set of DIVs, the focus moves from the DIV to the 2nd link in that DIV (expecting first link would be focused). 2. When tabbing forward over the last set of DIVs, the first link seems to get focused at first but then focus is moved to the follwing DIV, (expecting the first link would be focused) (maybe this is the same as 1, I can't tell) 3. When tabbing backward in the 2nd and 3rd set of DIVs, focus gets stuck on the DIV (expecting focus to be moved to the last link in the preceeding DIV)
Comment on attachment 155935 [details] [diff] [review] Patch, tested-works >Index: layout/html/base/src/nsFrame.cpp >+#include "nsIScrollableView.h" This isn't needed for the code you added. >Index: layout/html/base/src/nsPresShell.cpp >- esm->GetDocSelectionLocation(getter_AddRefs(selectionContent), This means we can remove it from nsIEventStateManager.h and make it non-virtual in nsEventStateManager.h again, if we want to... (it was added in bug 251986 to get the caret for kbd scrolling.) >Index: content/base/src/nsGenericElement.cpp >+ nsIPresShell *presShell = aPresContext->GetPresShell(); >+ if (presShell) { Do we really need to null-check the result from GetPresShell() ? (GetDocument()/GetViewManager()/StyleSet() in nsPresContext.h doesn't) The rest of the code looks fine and I agree with your listed changes in comment 5, but there seems to be a couple of glitches still with Testcase #1, so I review- this one hoping you will fix those too :-)
Attachment #155935 - Flags: review?(mats.palmgren) → review-
Keywords: testcase
I can't figure out when a frame has scrollbars or not.
Frame dump for the file: Type Manifest File: C:\moz\mozilla\dist\bin\components\xpti.dat ++WEBSHELL == 1 ++DOMWINDOW == 1 Note: verifyreflow is disabled Note: styleverifytree is disabled Note: frameverifytree is disabled webshell=01241CC8 Viewport(-1)@02B1E36C [view=02B13D88] {0,0,9180,4350} [state=00042004] [content=00000000] [sc=02B1E2A8]< HTMLScroll(html)(-1)@02B1E598 {0,0,9180,4350} [state=81c40004] [content=02B17860] [sc=02B1E514]< ScrollPortFrame(html)(-1)@02B1E6D0 [view=02B26298] next=02B1E9B8 {0,0,9180,4350} [state=80c42004] [content=02B17860] [sc=02B62B4C]< Canvas(html)(-1)@02B1E46C [view=02B6E9A0] {0,0,9180,4350} [state=00042004] [content=02B17860] [sc=02B6D8B4]< Area(html)(-1)@02B6DAE0 {0,0,9180,3660} [state=00c40014] sc=02B6D9AC(i=1,b=1)< line 02B6DD3C: count=1 state=inline,clean,prevmarginclean,not impacted,not wrapped,nobr[0x800] {0,0,0,0} < Text(1)@02B6DBDC[0,1,T] next=02B6DCE8 {0,0,0,0} [state=41100024] sc=02B6DA5C< "\n" > > line 02B6DD6C: count=1 state=block,clean,prevmarginclean,not impacted,not wrapped,nobr[0x804] bm=240 {120,120,8940,3300} ca={120,120,8940,3300} < Block(body)(2)@02B6DCE8 {120,120,8940,3300} [state=00040004] sc=02B6DC1C(i=3,b=2)< line 02B8498C: count=1 state=inline,clean,prevmarginclean,not impacted,not wrapped,nobr[0x800] {0,0,0,0} < Text(0)@02B6E084[0,2,T] next=02B6E214 {0,0,0,0} [state=51100024] sc=02B6E058< "\n\n" > > line 02B849BC: count=1 state=block,clean,prevmarginclean,not impacted,not wrapped,nobr[0x804] bm=240 {0,0,8940,1530} ca={0,0,8940,1530} < HTMLScroll(div)(1)@02B6E214 next=02B84498 {0,0,8940,1530} [state=80c40004] [content=02B836D8] [sc=02B6E11C]< ScrollPortFrame(div)(1)@02B6E2D8 [view=02B84208] {15,15,8910,1500} [state=80c42004] [content=02B836D8] [sc=02B6E388]< Area(div)(1)@02B6E1C0 [view=02B843A8] {0,0,8910,1500} [state=00d02004] sc=02B6E438(i=0,b=1)< line 02B84468: count=1 state=block,clean,prevmarginclean,not impacted,not wrapped,nobr[0x804] mew=1200 {0,0,8910,300} < Block(div)(0)@02B6E58C {0,0,8910,300} [state=00000004] sc=02B6E540(i=1,b=0)< line 02B84438: count=2 state=inline,clean,prevmarginclean,not impacted,not wrapped,nobr[0x1000] mew=1200 {0,0,1200,300} < Inline(a)(0)@02B6E6F0 next=02B6E794 {0,7,600,285} [state=00000004] [content=02B83800] [sc=02B6E664]< Text(0)@02B6E754[0,6,T] {0,0,600,285} [state=40200024] sc=02B6E728< "hidden" > > Inline(a)(1)@02B6E794 {600,7,600,285} [state=00000004] [content=02B839B8] [sc=02B6E664]< Text(0)@02B6E7CC[0,6,T] {0,0,600,285} [state=44200024] sc=02B6E728< "hidden" > > > > > > > > > line 02B849EC: count=1 state=inline,clean,prevmarginclean,not impacted,not wrapped,nobr[0x800] {0,1530,0,0} < Text(2)@02B84498[0,1,T] next=02B845A8 {0,1770,0,0} [state=41100024] sc=02B6E058< "\n" > > line 02B84A1C: count=1 state=block,clean,prevmarginclean,not impacted,not wrapped,nobr[0x804] bm=240 {0,1770,8940,1530} ca={0,1770,8940,1530} < Block(div)(3)@02B845A8 [view=02B85468] next=02B8494C {0,1770,8940,1530} [state=00002004] sc=02B84504(i=0,b=1)< line 02B8491C: count=1 state=block,clean,prevmarginclean,not impacted,not wrapped,nobr[0x804] {15,15,8910,300} < Block(div)(0)@02B84730 {15,15,8910,300} [state=00000004] sc=02B846E4(i=1,b=0)< line 02B848EC: count=2 state=inline,clean,prevmarginclean,not impacted,not wrapped,nobr[0x1000] {0,0,4620,300} < Inline(a)(0)@02B847D0 next=02B84874 {0,7,2310,285} [state=00000004] [content=02B83D30] [sc=02B84784]< Text(0)@02B84834[0,24,T] {0,0,2310,285} [state=40200024] sc=02B84808< "-moz-hidden-unscrollable" > > Inline(a)(1)@02B84874 {2310,7,2310,285} [state=00000004] [content=02B83EF8] [sc=02B84784]< Text(0)@02B848AC[0,24,T] {0,0,2310,285} [state=44200024] sc=02B84808< "-moz-hidden-unscrollable" > > > > > > > line 02B84A4C: count=1 state=inline,clean,prevmarginclean,not impacted,not wrapped,nobr[0x800] {0,3300,0,0} < Text(4)@02B8494C[0,2,T] {0,3540,0,0} [state=51100024] sc=02B6E058< "\n\n" > > > > > > > ScrollbarFrame(scrollbar)(-1)@02B1E9B8 [view=02B24050] next=02B621B4 {0,4350,9180,0} [state=80cc2024] [content=02B2D8B8] [sc=02B1E830]< Box(scrollbarbutton)(-1)@02B1EBC8 next=02B1EDE8 {0,15,255,255} [state=80c00024] [content=02B53D90] [sc=02B1E90C]<> SliderFrame(slider)(-1)@02B1EDE8 [view=02B61B08] next=02B6203C {255,15,8670,255} [state=80c02024] [content=02B52940] [sc=02B1ED44]< Box(thumb)(0)@02B61C68 {0,0,8670,255} [state=80400024] [content=02B53990] [sc=02B61BC4]< Box(gripper)(-1)@02B61E34 {4275,67,120,120} [state=80c00024] [content=02B62CF0] [sc=02B61D90]<> > > Box(scrollbarbutton)(-1)@02B6203C {8925,15,255,255} [state=80c00024] [content=02B43D50] [sc=02B61F98]<> > ScrollbarFrame(scrollbar)(-1)@02B621B4 [view=02B66DD0] next=02B62A50 {9180,0,0,4350} [state=808c2024] [content=02B41350] [sc=02B62108]< Box(scrollbarbutton)(-1)@02B62314 next=02B624B0 {15,0,255,255} [state=80c00024] [content=02B661F8] [sc=02B62270]<> SliderFrame(slider)(-1)@02B624B0 [view=02B26CB0] next=02B62938 {15,255,255,3840} [state=80802024] [content=02B66530] [sc=02B62464]< Box(thumb)(0)@02B62604 {0,0,255,3840} [state=80000024] [content=02B66688] [sc=02B62560]< Box(gripper)(-1)@02B62730 {67,1860,120,120} [state=80c00024] [content=02B6A1E8] [sc=02B6268C]<> > > Box(scrollbarbutton)(-1)@02B62938 {15,4095,255,255} [state=80c00024] [content=02B66980] [sc=02B62894]<> > Box(scrollcorner)(-1)@02B62A50 {9180,4350,0,0} [state=80c00024] [content=02B41520] [sc=02B62A04]<> > > nsPluginHostImpl::Observe "xpcom-shutdown" --WEBSHELL == 0 nsPluginHostImpl dtor
GetActualScrollbarSizes has a bug. It's including the borders as part of the scrollbar size. I can fix that. Now that I see what you're trying to do, I don't think you want GetActualScrollbarSizes at all. I don't think tabbability should depend on whether a frame is currently overflowing. I think you want to call nsIScrollableFrame::GetScrollbarStyles() and allow scrolling when the style is AUTO or SCROLL in either direction.
Mat, I fixed the tab order issue by changing nsEventStateManager::GetDocSelectionLocation()
Attachment #155935 - Attachment is obsolete: true
Attachment #156285 - Flags: review?(mats.palmgren)
+ mContent->IsContentOfType(nsIContent::eHTML) && Do you really want to restrict to HTML? I think the generic accessible should be created by a method in nsFrame, either nsFrame::GetAccessible, or if you detect accessibility based on the nsresult code, then put the generic accessible creation in an nsFrame helper function and just call it from nsHTMLScrollFrame/nsXULScrollFrame::GetAccessible.
(In reply to comment #13) > + mContent->IsContentOfType(nsIContent::eHTML) && > > Do you really want to restrict to HTML? For the moment, yes. The reason is that XUL provides much better semantics for what things are in the actual element names + XBL. The underlying tag in HTML is usually generic, such as <div>. We need to mess around in this way for HTML but not XUL. > I think the generic accessible should be created by a method in nsFrame, either > nsFrame::GetAccessible, or if you detect accessibility based on the nsresult > code, then put the generic accessible creation in an nsFrame helper function and > just call it from nsHTMLScrollFrame/nsXULScrollFrame::GetAccessible. I'm not sure understand this part. It seems like putting it in nsHTMLScrollFrame works perfectly. We don't detect whether accessibility is turned on by any nsresult. If we do_GetService for accessibilityservice that initializes the accessibility module. We detect whether accessibility is happening because someone calls nsIFrame::GetAccessible(). I don't think we're going to have generic accessibles for XUL, since we can more or less ensure that the language supports reasonable semantics instead of vanilla <div> tags everywhere.
(In reply to comment #14) > > Do you really want to restrict to HTML? > For the moment, yes. The reason is that XUL provides much better semantics for > what things are in the actual element names + XBL. The underlying tag in HTML > is usually generic, such as <div>. We need to mess around in this way for HTML > but not XUL. There is non-XUL, non-HTML content. But OK. My thought was that if we need to add generic accessible support to other frames than scrollframes, it'll be easier if the generic accessible creation code was factored out somewhere it can be shared. If for some reason you know that's not going to happen, then OK.
I understand. * We're not working to make SVG, MathML or other non-HTML non-XUL content accessible yet. * The other place we need to create generic accessibles is in the mozilla/accessible module itself. However, we're doing that based on tag names and attributes, not layout info.
Attachment #156285 - Flags: superreview?(roc)
We still don't handle tabbing to IFRAME and FRAME: http://bugzilla.mozilla.org/attachment.cgi?id=153477&action=view http://bugzilla.mozilla.org/attachment.cgi?id=153478&action=view I don't know if you want to address that here or not - I'm just noting it so we don't forget it...
Attached file Testcase #3 (deleted) —
I see that overflow:hidden is not focusable as it was in the first patch. Note that it *is* scrollable however (e.g. after focusing a link in it). In a way this makes sense though and I actually prefer this behaviour. Others may have a different opinion so I thought I would point it out.
Comment on attachment 156285 [details] [diff] [review] 1) Fixes issues noted by Mat, 2) Makes sure ScrollFrameIntoView() is called, 3) Put scrollable items in accessibility hierarchy, 4) Fix warning in nsAccessibilityService::CreateHTMLComboboxAccessible >Index: content/base/src/nsGenericElement.cpp >+ presShell->ScrollFrameIntoView(frame, NS_PRESSHELL_SCROLL_ANYWHERE, >+ NS_PRESSHELL_SCROLL_ANYWHERE); The above will cause problems with mouse-selection. Try for example: 1. load http://bugzilla.mozilla.org/attachment.cgi?id=153476&action=view 2. scroll the green box (middle) to the end 3. try to mouse-drag-select some of the "_2_" text in the inner DIV Result: the inner DIV scrolls, interfering badly with my selection. Also, when clicking on the inner DIV scollbar to scroll it, the outer DIV first scrolls it then the inner DIV does the scroll I wanted... One quick solution could be to not scroll at all if any part of the focused frame is visible? (or the event was mouse-triggered?). If you remove the above lines then I'll review+ it. (in case you want to handle the scroll-into-view problem later).
Attachment #156285 - Flags: review?(mats.palmgren) → review-
> Result: the inner DIV scrolls, interfering badly with my selection. What I meant was that the outer DIV scrolls so that the inner DIV moves under the mouse which interfers badly with my ongoing mouse-selection.
Attachment #156285 - Flags: superreview?(roc)
Filed bug 255881 on frame/iframe tabbing regression. That used to work -- nice catch! Also great work on the review in general. Thanks.
Attachment #156285 - Attachment is obsolete: true
Attachment #156348 - Flags: superreview?(roc)
Attachment #156348 - Flags: review?(mats.palmgren)
Comment on attachment 156348 [details] [diff] [review] Fix mouse drag scrolling. Scroll to iframe only if not already partially visible via ScrollFrameIntoView(frame, NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE, ...) r=mats.palmgren@bredband.net but there is one minor edge case still...
Attachment #156348 - Flags: review?(mats.palmgren) → review+
Attached file Testcase #5 (deleted) —
Also try: 3. scroll the SELECT to the end 4. click on the green background -> SELECT scrolls to top.
Blocks: 256276
I don't understand. Mats gave r= even though there's still a bug?
(In reply to comment #25) > I don't understand. Mats gave r= even though there's still a bug? Maybe we should file a separate bug on that part. After a couple hours of debugging I realized that it's caused by the reflow which happens for the outline. I'm not sure how to fix it. Any ideas? I'll post a stack trace for the extra scrolling occuring inside of the <select>
So, the last flaws in testcase #5 are because of nsChangeHint nsStyleOutline::CalcDifference(const nsStyleOutline& aOther) const ... if (outlineWasVisible != outlineIsVisible || mOutlineWidth != aOther.mOutlineWidth) { return NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame); } The reflow is causing the scrolling.
Robert, that sounds like it would be fixed by bug 249102. Is that right?
(In reply to comment #25) > I don't understand. Mats gave r= even though there's still a bug? My reasoning was that the remaining problem would only occur rarely and when it does it's a minor problem. Since the code in the patch is good, I thought I would just clearly point out the problem and leave the decision with you guys.
(In reply to comment #29) > Robert, that sounds like it would be fixed by bug 249102. Is that right? I don't think so.
Comment on attachment 156348 [details] [diff] [review] Fix mouse drag scrolling. Scroll to iframe only if not already partially visible via ScrollFrameIntoView(frame, NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE, ...) content/events/public/nsIEventStateManager.h Change the IID please. accessible/public/nsIAccessibilityService.idl Here too.
Attachment #156348 - Flags: superreview?(roc) → superreview+
Checking in content/base/src/nsGenericElement.cpp; /cvsroot/mozilla/content/base/src/nsGenericElement.cpp,v <-- nsGenericElement.cpp new revision: 3.354; previous revision: 3.353 done Checking in content/events/public/nsIEventStateManager.h; /cvsroot/mozilla/content/events/public/nsIEventStateManager.h,v <-- nsIEventStateManager.h new revision: 1.57; previous revision: 1.56 done Checking in content/events/src/nsEventStateManager.cpp; /cvsroot/mozilla/content/events/src/nsEventStateManager.cpp,v <-- nsEventStateManager.cpp new revision: 1.524; previous revision: 1.523 done Checking in content/events/src/nsEventStateManager.h; /cvsroot/mozilla/content/events/src/nsEventStateManager.h,v <-- nsEventStateManager.h new revision: 1.120; previous revision: 1.119 done Checking in layout/html/base/src/nsFrame.cpp; /cvsroot/mozilla/layout/html/base/src/nsFrame.cpp,v <-- nsFrame.cpp new revision: 3.513; previous revision: 3.512 done Checking in layout/html/base/src/nsGfxScrollFrame.cpp; /cvsroot/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp,v <-- nsGfxScrollFrame.cpp new revision: 3.170; previous revision: 3.169 done Checking in layout/html/base/src/nsGfxScrollFrame.h; /cvsroot/mozilla/layout/html/base/src/nsGfxScrollFrame.h,v <-- nsGfxScrollFrame.h new revision: 3.48; previous revision: 3.47 done Checking in layout/html/base/src/nsPresShell.cpp; /cvsroot/mozilla/layout/html/base/src/nsPresShell.cpp,v <-- nsPresShell.cpp new revision: 3.765; previous revision: 3.764 done Checking in layout/html/forms/src/nsComboboxControlFrame.cpp; /cvsroot/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp,v <-- nsComboboxControlFrame.cpp new revision: 1.292; previous revision: 1.291 done Checking in accessible/public/nsIAccessibilityService.idl; /cvsroot/mozilla/accessible/public/nsIAccessibilityService.idl,v <-- nsIAccessibilityService.idl new revision: 1.44; previous revision: 1.43 done Checking in accessible/src/base/nsAccessibilityService.cpp; /cvsroot/mozilla/accessible/src/base/nsAccessibilityService.cpp,v <-- nsAccessibilityService.cpp new revision: 1.117; previous revision: 1.116 done Checking in accessible/src/base/nsBaseWidgetAccessible.cpp; /cvsroot/mozilla/accessible/src/base/nsBaseWidgetAccessible.cpp,v <-- nsBaseWidgetAccessible.cpp new revision: 1.29; previous revision: 1.28 done
Status: NEW → RESOLVED
Closed: 20 years ago
Resolution: --- → FIXED
No longer blocks: 256276
The scroll problem was spawned off as bug 257672. Verified fixed in 2004-09-02-05 trunk Linux.
Status: RESOLVED → VERIFIED
Summary: position:fixed and overflow:scroll not keyboard accessible → overflow:scroll/auto not keyboard accessible/focusable
Component: Keyboard: Navigation → User events and focus handling
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: