Title: [122550] trunk
Revision
122550
Author
[email protected]
Date
2012-07-13 01:06:58 -0700 (Fri, 13 Jul 2012)

Log Message

Should be possible to focus elements within canvas fallback content
https://bugs.webkit.org/show_bug.cgi?id=87898

Reviewed by Chris Fleizach.

Source/WebCore:

Patches isFocusable in dom/Node.cpp and html/HTMLFormControlElement.cpp
to make elements focusable if they're a descendent of a canvas element
if they would otherwise have been focusable but just didn't have
a renderer. Adds a bit to ElementRareData to efficiently keep track
of elements in a canvas subtree.

Test: fast/canvas/fallback-content.html

* dom/Element.cpp:
(WebCore::Element::attach):
(WebCore::Element::detach):
(WebCore::Element::setIsInCanvasSubtree):
(WebCore):
(WebCore::Element::isInCanvasSubtree):
* dom/Element.h:
(Element):
* dom/ElementRareData.h:
(ElementRareData):
(WebCore::ElementRareData::ElementRareData):
* dom/Node.cpp:
(WebCore::Node::isFocusable):
* html/HTMLCanvasElement.cpp:
(WebCore::HTMLCanvasElement::attach):
(WebCore):
* html/HTMLCanvasElement.h:
(HTMLCanvasElement):
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::isFocusable):

LayoutTests:

* fast/canvas/fallback-content-expected.txt: Added.
* fast/canvas/fallback-content.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (122549 => 122550)


--- trunk/LayoutTests/ChangeLog	2012-07-13 07:45:09 UTC (rev 122549)
+++ trunk/LayoutTests/ChangeLog	2012-07-13 08:06:58 UTC (rev 122550)
@@ -1,3 +1,13 @@
+2012-07-13  Dominic Mazzoni  <[email protected]>
+
+        Should be possible to focus elements within canvas fallback content
+        https://bugs.webkit.org/show_bug.cgi?id=87898
+
+        Reviewed by Chris Fleizach.
+
+        * fast/canvas/fallback-content-expected.txt: Added.
+        * fast/canvas/fallback-content.html: Added.
+
 2012-07-13  Vsevolod Vlasov  <[email protected]>
 
         Unreviewed inspector test fix.

Added: trunk/LayoutTests/fast/canvas/fallback-content-expected.txt (0 => 122550)


--- trunk/LayoutTests/fast/canvas/fallback-content-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/fallback-content-expected.txt	2012-07-13 08:06:58 UTC (rev 122550)
@@ -0,0 +1,80 @@
+Link  Button                
+Focusable
+This test makes sure that focusable elements in canvas fallback content are focusable.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+link1 should be focusable.
+PASS document.activeElement == element is true
+
+button1 should be focusable.
+PASS document.activeElement == element is true
+
+text1 should be focusable.
+PASS document.activeElement == element is true
+
+checkbox1 should be focusable.
+PASS document.activeElement == element is true
+
+radio1 should be focusable.
+PASS document.activeElement == element is true
+
+slider1 should be focusable.
+PASS document.activeElement == element is true
+
+submit1 should be focusable.
+PASS document.activeElement == element is true
+
+combobox1 should be focusable.
+PASS document.activeElement == element is true
+
+listbox1 should be focusable.
+PASS document.activeElement == element is true
+
+textarea1 should be focusable.
+PASS document.activeElement == element is true
+
+focusable1 should be focusable.
+PASS document.activeElement == element is true
+
+link2 should be focusable.
+PASS document.activeElement == element is true
+
+button2 should be focusable.
+PASS document.activeElement == element is true
+
+text2 should be focusable.
+PASS document.activeElement == element is true
+
+checkbox2 should be focusable.
+PASS document.activeElement == element is true
+
+radio2 should be focusable.
+PASS document.activeElement == element is true
+
+slider2 should be focusable.
+PASS document.activeElement == element is true
+
+submit2 should be focusable.
+PASS document.activeElement == element is true
+
+combobox2 should be focusable.
+PASS document.activeElement == element is true
+
+listbox2 should be focusable.
+PASS document.activeElement == element is true
+
+textarea2 should be focusable.
+PASS document.activeElement == element is true
+
+focusable2 should be focusable.
+PASS document.activeElement == element is true
+
+linkInHiddenCanvas should not be focusable.
+PASS document.activeElement == previousFocusedElement is true
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/canvas/fallback-content.html (0 => 122550)


--- trunk/LayoutTests/fast/canvas/fallback-content.html	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/fallback-content.html	2012-07-13 08:06:58 UTC (rev 122550)
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<script src=""
+
+<div>
+  <a id="link1" href=""
+  <button id="button1">Button</button>
+  <input id="text1" type="text">
+  <input id="checkbox1" type="checkbox">
+  <input id="radio1" type="radio">
+  <input id="slider1" type="range">
+  <input id="submit1" type="submit">
+  <select id="combobox1"><option>1<option>2</select>
+  <select id="listbox1" multiple><option>1<option>2</select>
+  <textarea id="textarea1"></textarea>
+  <div id="focusable1" tabindex="0">Focusable</div>
+</div>
+
+<canvas id="myCanvas" width="300" height="300">
+  <a id="link2" href=""
+  <button id="button2">Button</button>
+  <input id="text2" type="text">
+  <input id="checkbox2" type="checkbox">
+  <input id="radio2" type="radio">
+  <input id="slider2" type="range">
+  <input id="submit2" type="submit">
+  <select id="combobox2"><option>1<option>2</select>
+  <select id="listbox2" multiple><option>1<option>2</select>
+  <textarea id="textarea2"></textarea>
+  <div id="focusable2" tabindex="0">Focusable</div>
+</canvas>
+
+<canvas hidden id="hiddenCanvas" width="300" height="300">
+  <a id="linkInHiddenCanvas" href=""
+</canvas>
+
+<div id="console"></div>
+<script>
+description("This test makes sure that focusable elements in canvas fallback content are focusable.");
+
+if (window.layoutTestController)
+    window.layoutTestController.dumpAsText();
+
+var element;
+function checkFocusable(id) {
+    debug(id + " should be focusable.");
+    element = document.getElementById(id);
+    element.focus();
+    shouldBe("document.activeElement == element", "true");
+    debug("");
+}
+
+checkFocusable("link1");
+checkFocusable("button1");
+checkFocusable("text1");
+checkFocusable("checkbox1");
+checkFocusable("radio1");
+checkFocusable("slider1");
+checkFocusable("submit1");
+checkFocusable("combobox1");
+checkFocusable("listbox1");
+checkFocusable("textarea1");
+checkFocusable("focusable1");
+
+checkFocusable("link2");
+checkFocusable("button2");
+checkFocusable("text2");
+checkFocusable("checkbox2");
+checkFocusable("radio2");
+checkFocusable("slider2");
+checkFocusable("submit2");
+checkFocusable("combobox2");
+checkFocusable("listbox2");
+checkFocusable("textarea2");
+checkFocusable("focusable2");
+
+var previousFocusedElement;
+function checkNotFocusable(id) {
+    debug(id + " should not be focusable.");
+    previousFocusedElement = document.activeElement;
+    element = document.getElementById(id);
+    element.focus();
+    shouldBe("document.activeElement == previousFocusedElement", "true");
+    debug("");
+}
+
+checkNotFocusable("linkInHiddenCanvas");
+
+</script>
+
+<script src=""
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (122549 => 122550)


--- trunk/Source/WebCore/ChangeLog	2012-07-13 07:45:09 UTC (rev 122549)
+++ trunk/Source/WebCore/ChangeLog	2012-07-13 08:06:58 UTC (rev 122550)
@@ -1,3 +1,39 @@
+2012-07-13  Dominic Mazzoni  <[email protected]>
+
+        Should be possible to focus elements within canvas fallback content
+        https://bugs.webkit.org/show_bug.cgi?id=87898
+
+        Reviewed by Chris Fleizach.
+
+        Patches isFocusable in dom/Node.cpp and html/HTMLFormControlElement.cpp
+        to make elements focusable if they're a descendent of a canvas element
+        if they would otherwise have been focusable but just didn't have
+        a renderer. Adds a bit to ElementRareData to efficiently keep track
+        of elements in a canvas subtree.
+
+        Test: fast/canvas/fallback-content.html
+
+        * dom/Element.cpp:
+        (WebCore::Element::attach):
+        (WebCore::Element::detach):
+        (WebCore::Element::setIsInCanvasSubtree):
+        (WebCore):
+        (WebCore::Element::isInCanvasSubtree):
+        * dom/Element.h:
+        (Element):
+        * dom/ElementRareData.h:
+        (ElementRareData):
+        (WebCore::ElementRareData::ElementRareData):
+        * dom/Node.cpp:
+        (WebCore::Node::isFocusable):
+        * html/HTMLCanvasElement.cpp:
+        (WebCore::HTMLCanvasElement::attach):
+        (WebCore):
+        * html/HTMLCanvasElement.h:
+        (HTMLCanvasElement):
+        * html/HTMLFormControlElement.cpp:
+        (WebCore::HTMLFormControlElement::isFocusable):
+
 2012-07-12  Carlos Garcia Campos  <[email protected]>
 
         [GTK] Add API to get HTTPS status to WebKit2 GTK+

Modified: trunk/Source/WebCore/dom/Element.cpp (122549 => 122550)


--- trunk/Source/WebCore/dom/Element.cpp	2012-07-13 07:45:09 UTC (rev 122549)
+++ trunk/Source/WebCore/dom/Element.cpp	2012-07-13 08:06:58 UTC (rev 122550)
@@ -938,6 +938,9 @@
     createRendererIfNeeded();
     StyleResolverParentPusher parentPusher(this);
 
+    if (parentElement() && parentElement()->isInCanvasSubtree())
+        setIsInCanvasSubtree(true);
+
     // When a shadow root exists, it does the work of attaching the children.
     if (ElementShadow* shadow = this->shadow()) {
         parentPusher.push();
@@ -976,8 +979,10 @@
     RenderWidget::suspendWidgetHierarchyUpdates();
     unregisterNamedFlowContentNode();
     cancelFocusAppearanceUpdate();
-    if (hasRareData())
+    if (hasRareData()) {
+        setIsInCanvasSubtree(false);
         elementRareData()->resetComputedStyle();
+    }
 
     if (ElementShadow* shadow = this->shadow()) {
         detachChildrenIfNeeded();
@@ -1670,6 +1675,17 @@
     return hasRareData() && elementRareData()->m_styleAffectedByEmpty;
 }
 
+void Element::setIsInCanvasSubtree(bool isInCanvasSubtree)
+{
+    ElementRareData* data = ""
+    data->m_isInCanvasSubtree = isInCanvasSubtree;
+}
+
+bool Element::isInCanvasSubtree() const
+{
+    return hasRareData() && elementRareData()->m_isInCanvasSubtree;
+}
+
 AtomicString Element::computeInheritedLanguage() const
 {
     const Node* n = this;

Modified: trunk/Source/WebCore/dom/Element.h (122549 => 122550)


--- trunk/Source/WebCore/dom/Element.h	2012-07-13 07:45:09 UTC (rev 122549)
+++ trunk/Source/WebCore/dom/Element.h	2012-07-13 08:06:58 UTC (rev 122550)
@@ -283,6 +283,9 @@
     void setStyleAffectedByEmpty();
     bool styleAffectedByEmpty() const;
 
+    void setIsInCanvasSubtree(bool);
+    bool isInCanvasSubtree() const;
+
     AtomicString computeInheritedLanguage() const;
 
     virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }

Modified: trunk/Source/WebCore/dom/ElementRareData.h (122549 => 122550)


--- trunk/Source/WebCore/dom/ElementRareData.h	2012-07-13 07:45:09 UTC (rev 122549)
+++ trunk/Source/WebCore/dom/ElementRareData.h	2012-07-13 08:06:58 UTC (rev 122550)
@@ -76,7 +76,8 @@
     OwnPtr<ElementShadow> m_shadow;
     OwnPtr<NamedNodeMap> m_attributeMap;
 
-    bool m_styleAffectedByEmpty;
+    bool m_styleAffectedByEmpty : 1;
+    bool m_isInCanvasSubtree : 1;
 
     IntSize m_savedLayerScrollOffset;
 
@@ -94,6 +95,7 @@
     : NodeRareData()
     , m_minimumSizeForResizing(defaultMinimumSizeForResizing())
     , m_styleAffectedByEmpty(false)
+    , m_isInCanvasSubtree(false)
 #if ENABLE(FULLSCREEN_API)
     , m_containsFullScreenElement(false)
 #endif

Modified: trunk/Source/WebCore/dom/Node.cpp (122549 => 122550)


--- trunk/Source/WebCore/dom/Node.cpp	2012-07-13 07:45:09 UTC (rev 122549)
+++ trunk/Source/WebCore/dom/Node.cpp	2012-07-13 08:06:58 UTC (rev 122550)
@@ -918,7 +918,17 @@
         // If the node is in a display:none tree it might say it needs style recalc but
         // the whole document is actually up to date.
         ASSERT(!document()->childNeedsStyleRecalc());
-    
+
+    // Elements in canvas fallback content are not rendered, but they are allowed to be
+    // focusable as long as their canvas is displayed and visible.
+    if (isElementNode() && toElement(this)->isInCanvasSubtree()) {
+        const Element* e = toElement(this);
+        while (e && !e->hasLocalName(canvasTag))
+            e = e->parentElement();
+        ASSERT(e);
+        return e->renderer() && e->renderer()->style()->visibility() == VISIBLE;
+    }
+
     // FIXME: Even if we are not visible, we might have a child that is visible.
     // Hyatt wants to fix that some day with a "has visible content" flag or the like.
     if (!renderer() || renderer()->style()->visibility() != VISIBLE)

Modified: trunk/Source/WebCore/html/HTMLCanvasElement.cpp (122549 => 122550)


--- trunk/Source/WebCore/html/HTMLCanvasElement.cpp	2012-07-13 07:45:09 UTC (rev 122549)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.cpp	2012-07-13 08:06:58 UTC (rev 122550)
@@ -135,6 +135,12 @@
     return HTMLElement::createRenderer(arena, style);
 }
 
+void HTMLCanvasElement::attach()
+{
+    setIsInCanvasSubtree(true);
+    HTMLElement::attach();
+}
+
 void HTMLCanvasElement::addObserver(CanvasObserver* observer)
 {
     m_observers.add(observer);

Modified: trunk/Source/WebCore/html/HTMLCanvasElement.h (122549 => 122550)


--- trunk/Source/WebCore/html/HTMLCanvasElement.h	2012-07-13 07:45:09 UTC (rev 122549)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.h	2012-07-13 08:06:58 UTC (rev 122550)
@@ -142,6 +142,7 @@
 
     virtual void parseAttribute(const Attribute&) OVERRIDE;
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
+    virtual void attach();
 
     void reset();
 

Modified: trunk/Source/WebCore/html/HTMLFormControlElement.cpp (122549 => 122550)


--- trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2012-07-13 07:45:09 UTC (rev 122549)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2012-07-13 08:06:58 UTC (rev 122550)
@@ -312,7 +312,9 @@
 
 bool HTMLFormControlElement::isFocusable() const
 {
-    if (!renderer() || !renderer()->isBox() || toRenderBox(renderer())->size().isEmpty())
+    // If there's a renderer, make sure the size isn't empty, but if there's no renderer,
+    // it might still be focusable if it's in a canvas subtree (handled in Node::isFocusable).
+    if (renderer() && (!renderer()->isBox() || toRenderBox(renderer())->size().isEmpty()))
         return false;
     // HTMLElement::isFocusable handles visibility and calls suportsFocus which
     // will cover the disabled case.
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to