Open Bug 434301 Opened 16 years ago Updated 2 years ago

'outline' (focus outline) on inline containing only block causes visual artifact (extra dots) {ib}

Categories

(Core :: Layout: Block and Inline, defect)

defect

Tracking

()

People

(Reporter: deleeuw+bugzilla, Unassigned)

References

(Blocks 1 open bug)

Details

(Keywords: testcase)

Attachments

(8 files, 5 obsolete files)

User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9pre) Gecko/2008051706 Minefield/3.0pre
Build Identifier: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9pre) Gecko/2008051706 Minefield/3.0pre

See attached minimized testcase.

Reproducible: Always

Steps to Reproduce:
1.Load testcase
2.Press tab until link is focused
3.Behold the artifact above the link to the left
Actual Results:  
Artifact visible

Expected Results:  
Artifact not visible
Keywords: testcase
Block-level elements are not allowed inside inline elements.  If you set display:block on the image, then you must do so for the anchor as well.
Whiteboard: [invalid?]
yeah, you are right... I feel ashamed I didn't get this earlier...
Status: UNCONFIRMED → RESOLVED
Closed: 16 years ago
Resolution: --- → INVALID
(In reply to comment #3)
> Block-level elements are not allowed inside inline elements.  If you set
> display:block on the image, then you must do so for the anchor as well.
> 

You're confusing HTML4 %block and %inline with CSS display:block and display:inline.

CSS does not forbid display:block inside display:inline.
So how should it be displayed?

Now it looks like this:

|      <------- this is in some older builds that I checked, like a tail sticking
-------         out from on top of the pic with focus outline, in later builds, 
| pic |         the dot
-------
What CSS says is that inlines that contain blocks get split into a piece before the block and a piece after the block; you're seeing the piece before the block get an outline around it.  That behavior probably isn't ideal...

See also bug 424236, bug 270191.
Status: RESOLVED → UNCONFIRMED
Resolution: INVALID → ---
Attached file Testcase #2
There seems to be some difference between UAs on this testcase.

Safari 3.1 and latest Webkit:
  no outline around empty inlines, except if 'background'
  is set (huh?).  (ie. 3 green,pruple boxes)

Opera 9.50b2 (Linux)
  no outline around empty inlines or blocks
  (and shows an outline around the focused block-in-inline block box)
Opera 9.27 (Linux)
  no outline around empty inlines
  (no outline around the focused block-in-inline block box)

IE8b1 (Windows XPSP3)
  outline around empty inlines and blocks, looks close
  to what we used to implemented before bug 424236.
Attached patch wip1 (obsolete) — Splinter Review
The change in 424236 also targets normal inlines, was that intentional?

Perhaps something like this would be better if we want to target the
block-in-inline problem specifically.
Note that one of the patches in bug 424236 isn't actually landed yet (I've been waiting for mozilla-central to open).

Right now the part of the inline after the block essentially disappears; it would be nice if the part before it did as well.  (Do we even construct frames for the part after when it would be empty?)

I think your approach is reasonable, though.
Status: UNCONFIRMED → NEW
Ever confirmed: true
Blocks: 426879
OS: Windows XP → All
Hardware: PC → All
Whiteboard: [invalid?]
Version: unspecified → Trunk
Attached file Testcase #2e
Attached file Testcase #2f
Attached file Testcase #2g
(In reply to comment #10)
> Note that one of the patches in bug 424236 isn't actually landed yet

Yes -- it looks like it fixes the painting of the outline(s) for the
block-in-inline block part.  I was mostly concerned with the rendering of
normal empty inlines here, which I now see really is bug 426879.

> Do we even construct frames for the part after when it would be empty?

If there are no child frames for it, we don't.
But we do create it if there is a zero-width child frame.
Attached patch wip3 (obsolete) — Splinter Review
There are several issues:
1. we should not paint outline for "empty" special frames
2. the outlines we skip should not contribute to the overflow rect
3. we should include outlines we do paint in the proper overflow rect,
   i.e. the painting we intend to do in bug 424236 should contribute
   to each of those child frame's overflow rect -- not the anon block
   overflow rect. Otherwise the surrounding overflow will not be
   correct and damage rect calculations will also be incorrect.

and "empty" in 1. means the overflow rect without outline added
has zero width or height. (the difference can be seen in test #2g
where "after" should have an outline, even though GetRect() is zero)

You can see the problem with 3. in test #2f, using the pending patch
in bug 424236, the right part of the outline inside the last two
blocks are not refreshed properly (try scrolling/covering the window).
And the horizontal scrollbars should not be here (problem 2).

This patch fixes 1 and 2 (although a bit hacky since
IsEmptySpecialFrame() means two different things depending on when
the call is done)
Attachment #321691 - Attachment is obsolete: true
Assignee: nobody → mats.palmgren
Attached patch Patch rev. 5 (obsolete) — Splinter Review
I found the problems with the patch in bug 424236: the paint problem
is caused by an optimisation in nsDisplayOutline::OptimizeVisibility()
http://bonsai.mozilla.org/cvsblame.cgi?file=/mozilla/layout/base/nsDisplayList.cpp&rev=3.44&root=/cvsroot&mark=586-587#573
and the scrollbar is caused by the overflow rect for the anon block
always includes the outline - we should only include it where the
outline around a child will overflow its frame rect.

AFAICT, this patch fixes this bug, bug 426879 and the remaining part
for bug 424236.  Sorry for bundling them together but I found that
some of the code could be shared.
Attachment #321880 - Attachment is obsolete: true
Attachment #322411 - Flags: superreview?(dbaron)
Attachment #322411 - Flags: review?(dbaron)
Attached patch reftest2.diff (obsolete) — Splinter Review
Reftests based on the attached testcases in this bug.
It looks like this patch incorporates the unlanded patch on bug 424236 (but not its tests).  So what I really need to review is the interdiff between the two.

(For what it's worth, I find it easier to review smaller patches, and I don't think it's a problem if one patch requires that another be applied first.  It's been pretty easy for me to do this since I've been using http://www.selenic.com/mercurial/wiki/index.cgi , although mq has its quirks and it's possible to mess things up pretty badly (including potentially losing work) until you get the hang of it.  If you try it remember to (1) use a versioned patch repository (hg init -c, and then hg qcommit frequently) and (2) set the default diff format to git diffs in ~/.hgrc by adding git = 1 in a [diff] section.)

Anyway, have to run now, so can't actually do the review now...
Attached patch reftest3.diff (obsolete) — Splinter Review
Added the pending reftests from bug 424236, with some adjustments
to account for the fix in this bug.
Attachment #322412 - Attachment is obsolete: true
Attached patch Patch rev. 6Splinter Review
Attachment #322411 - Attachment is obsolete: true
Attachment #324130 - Flags: superreview?(dbaron)
Attachment #324130 - Flags: review?(dbaron)
Attachment #322411 - Flags: superreview?(dbaron)
Attachment #322411 - Flags: review?(dbaron)
Attached patch reftest4.diffSplinter Review
Reftests pass locally on Windows/Linux/OSX.
Attachment #322434 - Attachment is obsolete: true
Comment on attachment 324130 [details] [diff] [review]
Patch rev. 6

>-  nsIFrame *frameForArea = aForFrame;
>-  do {
>-    nsIAtom *pseudoType = frameForArea->GetStyleContext()->GetPseudoType();
>-    if (pseudoType != nsCSSAnonBoxes::mozAnonymousBlock &&
>-        pseudoType != nsCSSAnonBoxes::mozAnonymousPositionedBlock)
>-      break;
>-    // If we're done, we really want it and all its later siblings.
>-    frameForArea = frameForArea->GetFirstChild(nsnull);
>-    NS_ASSERTION(frameForArea, "anonymous block with no children?");
>-  } while (frameForArea);

As far as I can tell, you don't have any code that replaces this loop.  I just added a reftest for this as 424236-11.html; presumably this patch breaks that test.
Comment on attachment 324130 [details] [diff] [review]
Patch rev. 6

review- primarily because of the previous comment.  However, I'd add:

>+nsLayoutUtils::ComputeChildOverflowAreaUnion(const nsIFrame* aFrame)
>+{
>+  nsRect overflowArea = nsRect(0, 0, 0, 0);

I'd prefer default initialization, since the concept we want here is "no rectangle" rather than the particular one you give; they just happen to be represented the same way right now.

(in class nsLayoutUtils)
>+  static PRBool IsSpecialAnonymousBlockFrame(const nsIFrame* aFrame)

I don't see any reason for this to be inline.

>diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp
>+  // Skip special frames with an empty overflow rect (bug 434301).
>+  // See also ::ComputeOutlineRect().
>+  if ((GetStateBits() & NS_FRAME_IS_SPECIAL) && GetOverflowRect().IsEmpty())
>+    return NS_OK;

Shouldn't we do this only for the inlines?  I tend to think we actually don't want to skip the blocks.

>+static nsRect
>+ComputeOutlineRect(const nsIFrame* aFrame, PRBool* aAnyOutline,
>+                   const nsRect& aOverflowRect)

>+  if (nsLayoutUtils::IsSpecialAnonymousBlockFrame(aFrame)) {
>+    NS_ASSERTION(aFrame->GetFirstChild(nsnull), "anonymous block must have children");
>+    nsRect r = nsLayoutUtils::ComputeChildOverflowAreaUnion(aFrame);
>+    r.Inflate(inflateBy, inflateBy);
>+    r.UnionRect(aOverflowRect, r);
>+    return r;
>+  }

This UnionRect means we're actually returning something bigger than the outline rect.  It seems like ComputeOutlineRect should be renamed to something that describes what it really does.


Other than those issues (previous comment and this one), this looks good.
Attachment #324130 - Flags: superreview?(dbaron)
Attachment #324130 - Flags: superreview-
Attachment #324130 - Flags: review?(dbaron)
Attachment #324130 - Flags: review-
(In reply to comment #26)
> (From update of attachment 324130 [details] [diff] [review])
> review- primarily because of the previous comment.  However, I'd add:
> 
> >+nsLayoutUtils::ComputeChildOverflowAreaUnion(const nsIFrame* aFrame)
> >+{
> >+  nsRect overflowArea = nsRect(0, 0, 0, 0);
> 
> I'd prefer default initialization, since the concept we want here is "no
> rectangle" rather than the particular one you give; they just happen to be
> represented the same way right now.

Given the changes in bug 439567, feel free to ignore this comment if you want.

However, you probably want to update your unioning to IncludeEmpty, as there.

Any chance of a new patch here?
Summary: IMG with display:block, wrapped in an anchor and a paragraph causes artifact to be visible when the anchor is focused → 'outline' (focus outline) on inline containing only block causes visual artifact (extra dots)
Note that fixing bug 470118 would likely also fix this if we fixed the asymmetry by creating the inline on neither side.
Depends on: 470118
(In reply to comment #31)
> Note that fixing bug 470118 would likely also fix this if we fixed the
> asymmetry by creating the inline on neither side.

The original testcase in bug 477370 had extra whitespace inside the inline but not inside the block.
Summary: 'outline' (focus outline) on inline containing only block causes visual artifact (extra dots) → 'outline' (focus outline) on inline containing only block causes visual artifact (extra dots) {ib}
Why do we need the empty inline boxes on either side of the block box?  Wouldn't it be simpler and more efficient to avoid creating those in the first place, rather than having to recognize and ignore them all over layout?
Blocks: 680807
Flags: needinfo?(emilio)

Why do we need the empty inline boxes on either side of the block box? Wouldn't it be simpler and more efficient to avoid creating those in the first place, rather than having to recognize and ignore them all over layout?

Just to answer this question, there are things (like borders and padding) that can make them nonempty. We generally don't want to reframe for border/padding changes.

Mats, do you recall enough context this bug to know why we can't just do something like this? (Ignore the comment which is wrong):

https://hg.mozilla.org/try/rev/12d7bec9f51467ed2f87bd3d090e2554b6532132

It of course fails the reftests from bug 424236:

https://treeherder.mozilla.org/#/jobs?repo=try&revision=a6f9c51eff04ed349452aa577ce2d11418284566&selectedJob=239725909

But looking at the analyzer we could probably just tweak the expectation.

Flags: needinfo?(emilio) → needinfo?(mats)

I seem to recall that I fixed the calculation of the actual overflow rects
rather than just suppressing painting the outlines in some cases.
But yeah, we could take your patch as a wallpaper since I think it
probably covers the common cases. You should change GetRect() to
GetScrollableOverflowRect() though, and do the same for
mozBlockInsideInlineWrapper (see below). (Probably better to file
a separate bug for that improvement since I think we still might
want to fix some of the overflow calculations here.)

(In reply to David Baron :dbaron: 🏴󠁵󠁳󠁣󠁡󠁿 ⌚UTC-7 from comment #26)

Shouldn't we do this only for the inlines? I tend to think we actually
don't want to skip the blocks.

I'm pretty sure I also skipped empty blocks intentionally.
I can't think of a good reason to include them.
Compare this in Chrome:

<span style="outline: 5px solid red">
  A
  <div style="height:0"></div>
  B
</span>
Flags: needinfo?(mats)
See Also: → 1548809

The bug assignee is inactive on Bugzilla, so the assignee is being reset.

Assignee: MatsPalmgren_bugz → nobody
Severity: normal → S3

The severity field for this bug is relatively low, S3. However, the bug has 10 duplicates.
:jfkthame, could you consider increasing the bug severity?

For more information, please visit auto_nag documentation.

Flags: needinfo?(jfkthame)

The last needinfo from me was triggered in error by recent activity on the bug. I'm clearing the needinfo since this is a very old bug and I don't know if it's still relevant.

Flags: needinfo?(jfkthame)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: