RESOLVED FIXED Bug 37079
Links around blocks (e.g. divs) results in too many VoiceOver call outs
https://bugs.webkit.org/show_bug.cgi?id=37079
Summary Links around blocks (e.g. divs) results in too many VoiceOver call outs
Maciej Stachowiak
Reported 2010-04-05 02:40:26 PDT
Links around blocks (e.g. divs) results in too many VoiceOver call outs
Attachments
Patch (18.13 KB, patch)
2010-04-05 02:52 PDT, Maciej Stachowiak
no flags
Patch (23.62 KB, patch)
2010-04-22 03:22 PDT, Maciej Stachowiak
mitz: review+
Maciej Stachowiak
Comment 1 2010-04-05 02:52:56 PDT
Maciej Stachowiak
Comment 2 2010-04-05 02:53:43 PDT
mitz
Comment 3 2010-04-05 15:36:27 PDT
Comment on attachment 52520 [details] Patch Beth and I looked at the patch, and we suspect the logic for Case 3 below may be wrong: > @@ -158,8 +272,31 @@ AccessibilityObject* AccessibilityRender > { > if (!m_renderer) > return 0; > + > + RenderObject* nextSibling = 0; > + > + // Case 1: node is a block and has an inline continuation. Next sibling is the inline continuation's > + // first child. > + RenderInline* inlineContinuation; > + if (m_renderer->isRenderBlock() && (inlineContinuation = toRenderBlock(m_renderer)->inlineContinuation())) > + nextSibling = firstChildConsideringContinuation(inlineContinuation); > + > + // Case 2: node has an actual next sibling > + else if (RenderObject* ns = m_renderer->nextSibling()) > + nextSibling = ns; > + > + // Case 3: node has no next sibling, and its parent is an inline with a continuation. > + else if (isInlineWithContinuation(m_renderer->parent())) { > + RenderObject* continuation = toRenderInline(m_renderer->parent())->continuation(); > + > + // Case 3a: continuation is a block - in this case the block itself is the next sibling. > + if (continuation->isRenderBlock()) > + nextSibling = continuation; > + // Case 3b: continuation is an inline - in this case the inline's first child is the next sibling > + else > + nextSibling = firstChildConsideringContinuation(continuation); > + } Considering a case like <span id="span1">a<div>b</div></span>c<span id="span2">d</span>, if asked for the next sibling of the first RenderInline for span1, the above code will hit case 3 (because that inline doesn’t have a next sibling in its parent anonymous block), but then it will fail the condition for that case, because its parent is not an inline. Instead, shouldn’t we return the RenderInline for span2? Perhaps the way to do this is to follow the inlineContinuation chain and return the next sibling of the last renderer on the chain?
Maciej Stachowiak
Comment 4 2010-04-05 22:22:10 PDT
Comment on attachment 52520 [details] Patch Marking this r- because upon discussion, Mitz and I concluded that there was indeed a bug.
Maciej Stachowiak
Comment 5 2010-04-22 03:22:12 PDT
Maciej Stachowiak
Comment 6 2010-04-22 03:23:25 PDT
(In reply to comment #5) > Created an attachment (id=54047) [details] > Patch I believe the new patch addresses Mitz's comments above.
mitz
Comment 7 2010-04-22 11:28:52 PDT
Comment on attachment 54047 [details] Patch > +static inline RenderObject* lastChildConsideringContinuation(RenderObject* renderer) > +{ > + RenderObject* lastChild = renderer->lastChild(); > + RenderObject* prev = renderer; prev is unused (you just assign to it). > + RenderObject* cur = renderer; > + > + while (cur) { > + prev = cur; > + > + if (RenderObject* lc = cur->lastChild()) > + lastChild = lc; > + > + if (cur->isRenderInline()) { > + cur = toRenderInline(cur)->continuation(); > + if (cur && cur->isRenderBlock()) > + cur = toRenderBlock(cur)->inlineContinuation(); > + } else > + cur = toRenderBlock(cur)->inlineContinuation(); I can’t think of a case where you couldn’t just do cur = cur->inlineContinuation() (assuming cur is a block or an inline). In other words, the first branch seems needlessly complicated. What am I missing? > AccessibilityObject* AccessibilityRenderObject::firstChild() const > { > if (!m_renderer) > return 0; > > RenderObject* firstChild = m_renderer->firstChild(); > + > + if (!firstChild && isInlineWithContinuation(m_renderer)) > + firstChild = firstChildConsideringContinuation(m_renderer); You can just use firstChildConsideringContinuation(), because it includes the above (getting firstChild() and checking if it’s 0 etc.). > +static inline RenderObject* endOfContinuations(RenderObject* renderer) > +{ > + RenderObject* prev = renderer; > + RenderObject* cur = renderer; > + > + while (cur) { > + prev = cur; > + if (cur->isRenderInline()) { > + cur = toRenderInline(cur)->continuation(); > + if (cur && cur->isRenderBlock()) > + cur = toRenderBlock(cur)->inlineContinuation(); > + } else > + cur = toRenderBlock(cur)->inlineContinuation(); Like in lastChildConsideringContinuations, I don’t understand why the inline case can’t just use inlineContinuation(). r=beth and me
Maciej Stachowiak
Comment 8 2010-04-22 22:47:29 PDT
Note You need to log in before you can comment on or make changes to this bug.