Bug 120273

Summary: Making a focused element invisible should make it blur
Product: WebKit Reporter: Arunprasad Rajkumar <arurajku>
Component: WebCore Misc.Assignee: Nobody <webkit-unassigned>
Status: RESOLVED DUPLICATE    
Severity: Normal CC: ararunprasad, commit-queue, darin, esprehn+autocc, jose.lejin, kangil.han, rniwa, simon.fraser
Priority: P2 Keywords: BlinkMergeCandidate
Version: 528+ (Nightly build)   
Hardware: All   
OS: All   
Attachments:
Description Flags
Patch
none
Patch
darin: review-
It is not working in Chrome even it has fix
none
test case - chrome also not working for certain cases(like calling display:none from timer) none

Description Arunprasad Rajkumar 2013-08-25 05:54:01 PDT
It is a blink merge https://chromiumcodereview.appspot.com/14248006.

According to the specification, we should remove focus when a focused element
becomes unforcusable, and Internet Explorer follows it.

We check focusable state after layout asynchronously because setFocusedNode(0)
dispatches synchronous events and callers of Document::updateLayout don't expect
DOM state changes. Also, we introduce m_didPostCheckFocusedNodeTask flag to avoid
duplicated tasks in the pending task queue.
Comment 1 Arunprasad Rajkumar 2013-08-25 06:17:58 PDT
Created attachment 209592 [details]
Patch
Comment 2 Sergio Correia (qrwteyrutiyoup) 2013-08-25 07:41:15 PDT
Comment on attachment 209592 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=209592&action=review

> LayoutTests/ChangeLog:8
> +        * fast/dom/HTMLDocument/active-element-gets-unforcusable.html: Added.

typo in the filenames? "unfoRcusable"
Comment 3 Arunprasad Rajkumar 2013-08-25 08:06:40 PDT
Created attachment 209593 [details]
Patch
Comment 4 Arunprasad Rajkumar 2013-08-25 08:07:35 PDT
(In reply to comment #2)
> (From update of attachment 209592 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=209592&action=review
> 
> > LayoutTests/ChangeLog:8
> > +        * fast/dom/HTMLDocument/active-element-gets-unforcusable.html: Added.
> 
> typo in the filenames? "unfoRcusable"

Oops!. Fixed in the new patch :)
Comment 5 Jose Lejin PJ 2013-08-26 06:19:19 PDT
Seems use case in Bug#120283 can be resolved with this.
Comment 6 Darin Adler 2013-08-26 09:57:58 PDT
Comment on attachment 209593 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=209593&action=review

> Source/WebCore/dom/Document.cpp:381
> +// This class should be passed only to Document::postTask.

I don't understand the value of this comment. What other bad thing could someone do with this class. Next time just leave this out. I suspect this entire class will go away, but we if keep it I have a few comments.

> Source/WebCore/dom/Document.cpp:386
> +        return adoptPtr(new CheckFocusedNodeTask());

I suggest omitting the "()" here.

> Source/WebCore/dom/Document.cpp:388
> +    virtual ~CheckFocusedNodeTask() { }

I suggest omitting this entirely. It should be generated.

> Source/WebCore/dom/Document.cpp:391
> +    CheckFocusedNodeTask() { }

Doesn't seem to be valuable to make this private. There would be no harm if someone constructed one of these without using the create function. I suggest just omitting this and letting it be generated.

> Source/WebCore/dom/Document.cpp:395
> +        Document* document = toDocument(context);

I suggest using Document& here instead of Document* since it can’t be null. In newer code in general we are trying to use references for such things.

> Source/WebCore/dom/Document.cpp:401
> +        if (focusedElement->renderer() && focusedElement->renderer()->needsLayout())
> +            return;

This needsLayout check does not make sense. It's not helpful to check if the single renderer has the needs-layout bit set on it. What bug did it fix to check this?

> Source/WebCore/dom/Document.cpp:1885
> +    // FIXME: Using a Task doesn't look a good idea.

Yes, a Task is not a good fix for this. I suggest sharing the updateFocusAppearance timer.

> Source/WebCore/dom/Document.cpp:1889
> +    if (m_focusedElement && !m_didPostCheckFocusedNodeTask) {
> +        postTask(CheckFocusedNodeTask::create());
> +        m_didPostCheckFocusedNodeTask = true;
> +    }

Here’s what I think this code should say:

    if (!m_focusedElement->isFocusable())
        updateFocusAppearanceSoon(false);

Then, inside the updateFocusAppearanceTimerFired function:

        if (element->isFocusable())
            element->updateFocusAppearance(m_updateFocusAppearanceRestoresSelection);
        else
            document->setFocusedElement(0);

Please give that a try and see if there are any problems caused by that approach.
Comment 7 Arunprasad Rajkumar 2013-08-26 10:36:28 PDT
(In reply to comment #6)
> (From update of attachment 209593 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=209593&action=review
> 
> > Source/WebCore/dom/Document.cpp:381
> > +// This class should be passed only to Document::postTask.
> 
> I don't understand the value of this comment. What other bad thing could someone do with this class. Next time just leave this out. I suspect this entire class will go away, but we if keep it I have a few comments.
> 
> > Source/WebCore/dom/Document.cpp:386
> > +        return adoptPtr(new CheckFocusedNodeTask());
> 
> I suggest omitting the "()" here.
> 
> > Source/WebCore/dom/Document.cpp:388
> > +    virtual ~CheckFocusedNodeTask() { }
> 
> I suggest omitting this entirely. It should be generated.
> 
> > Source/WebCore/dom/Document.cpp:391
> > +    CheckFocusedNodeTask() { }
> 
> Doesn't seem to be valuable to make this private. There would be no harm if someone constructed one of these without using the create function. I suggest just omitting this and letting it be generated.
> 
> > Source/WebCore/dom/Document.cpp:395
> > +        Document* document = toDocument(context);
> 
> I suggest using Document& here instead of Document* since it can’t be null. In newer code in general we are trying to use references for such things.
> 
> > Source/WebCore/dom/Document.cpp:401
> > +        if (focusedElement->renderer() && focusedElement->renderer()->needsLayout())
> > +            return;
> 
> This needsLayout check does not make sense. It's not helpful to check if the single renderer has the needs-layout bit set on it. What bug did it fix to check this?
> 
> > Source/WebCore/dom/Document.cpp:1885
> > +    // FIXME: Using a Task doesn't look a good idea.
> 
> Yes, a Task is not a good fix for this. I suggest sharing the updateFocusAppearance timer.
> 
> > Source/WebCore/dom/Document.cpp:1889
> > +    if (m_focusedElement && !m_didPostCheckFocusedNodeTask) {
> > +        postTask(CheckFocusedNodeTask::create());
> > +        m_didPostCheckFocusedNodeTask = true;
> > +    }
> 
> Here’s what I think this code should say:
> 
>     if (!m_focusedElement->isFocusable())
>         updateFocusAppearanceSoon(false);
> 
> Then, inside the updateFocusAppearanceTimerFired function:
> 
>         if (element->isFocusable())
>             element->updateFocusAppearance(m_updateFocusAppearanceRestoresSelection);
>         else
>             document->setFocusedElement(0);
> 
> Please give that a try and see if there are any problems caused by that approach.

Darin, Thanks for your comments :) Sure, I will try with  m_updateFocusAppearanceTimer and let u know the result.
Comment 8 Arunprasad Rajkumar 2013-08-29 08:46:17 PDT
Comment on attachment 209593 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=209593&action=review

>> Source/WebCore/dom/Document.cpp:1885
>> +    // FIXME: Using a Task doesn't look a good idea.
> 
> Yes, a Task is not a good fix for this. I suggest sharing the updateFocusAppearance timer.

I tried using updateFocusAppearance timer, but Document::updateFocusAppearanceTimerFired calls Document::updateLayout, from Document::updateLayout() again we are scheduling a timer. It cases  above 2 functions being called repeatedly.

I'm going to try with a separate timer for this instead of reusing updateFocusAppearance timer. Hope it will be good to do. What do you think?
Comment 9 Arunprasad Rajkumar 2013-08-29 09:03:23 PDT
(In reply to comment #8)
> (From update of attachment 209593 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=209593&action=review
> 
> >> Source/WebCore/dom/Document.cpp:1885
> >> +    // FIXME: Using a Task doesn't look a good idea.
> > 
> > Yes, a Task is not a good fix for this. I suggest sharing the updateFocusAppearance timer.
> 
> I tried using updateFocusAppearance timer, but Document::updateFocusAppearanceTimerFired calls Document::updateLayout, from Document::updateLayout() again we are scheduling a timer. It cases  above 2 functions being called repeatedly.
> 
> I'm going to try with a separate timer for this instead of reusing updateFocusAppearance timer. Hope it will be good to do. What do you think?

May be with little tweaking it is achievable :) Will try with a recursive guard member.
Comment 10 Alexey Proskuryakov 2013-08-29 09:13:34 PDT
This loooks like a duplicate of bug 29241.
Comment 11 Arunprasad Rajkumar 2013-08-29 09:42:03 PDT
(In reply to comment #10)
> This loooks like a duplicate of bug 29241.
Yes, you are right :)
Comment 12 Darin Adler 2013-08-29 10:15:40 PDT
Can we avoid the recursion by ordering the operations appropriately without a recursion guard? Please keep in mind the timer again is *not* recursion. Scheduling timer over and over again infinitely would be a problem, but still, not infinite recursion.
Comment 13 Darin Adler 2013-08-29 10:16:24 PDT
Please keep in mind that scheduling the timer again is *not* recursion (I meant to say).

Also lets mark this a duplicate of the older bug.

*** This bug has been marked as a duplicate of bug 29241 ***
Comment 14 Arunprasad Rajkumar 2013-08-29 12:09:20 PDT
Created attachment 210012 [details]
It is not working in Chrome even it has fix
Comment 15 Arunprasad Rajkumar 2013-08-29 12:11:21 PDT
(In reply to comment #12)
> Can we avoid the recursion by ordering the operations appropriately without a recursion guard? Please keep in mind the timer again is *not* recursion. Scheduling timer over and over again infinitely would be a problem, but still, not infinite recursion.

(In reply to comment #13)
> Please keep in mind that scheduling the timer again is *not* recursion (I meant to say).
> 
Yeah, understood :)

> Also lets mark this a duplicate of the older bug.
Patch should be submitted to #29241 ?
 
> 
> *** This bug has been marked as a duplicate of bug 29241 ***

Refer the attachment, https://bugs.webkit.org/attachment.cgi?id=210012, it is not working in chrome also. I think Chrome haven't implemented properly it seems.
Comment 16 Arunprasad Rajkumar 2013-08-29 12:22:21 PDT
Created attachment 210015 [details]
test case - chrome also not working for certain cases(like calling display:none from timer)
Comment 17 Darin Adler 2013-08-29 13:03:50 PDT
Yes, lets move discussion and further patches to bug 29241.