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.