From 6392ae8ed047dc549e1a513fbe141dde66a57cc3 Mon Sep 17 00:00:00 2001 From: David Bolter Date: Fri, 17 Feb 2012 23:26:37 -0500 Subject: [PATCH] Bug 495912 - Expose content in HTML canvas elements. r=bz,roc r=surkov(tests) layout-mentor: bz (mucho thanks!) We make html canvas frame a container and render frames for its content which makes a lot of what we need for accessibility "just work". --- accessible/tests/mochitest/events/Makefile.in | 1 + .../mochitest/events/test_focus_canvas.html | 59 ++++++++++++ .../tests/mochitest/tree/test_canvas.html | 18 ++-- .../tests/mochitest/treeupdate/Makefile.in | 1 + .../mochitest/treeupdate/test_canvas.html | 92 +++++++++++++++++++ layout/base/nsCSSFrameConstructor.cpp | 3 +- layout/generic/nsHTMLCanvasFrame.cpp | 14 +++ layout/generic/nsHTMLCanvasFrame.h | 11 ++- layout/style/html.css | 6 ++ layout/style/nsCSSAnonBoxList.h | 1 + 10 files changed, 192 insertions(+), 14 deletions(-) create mode 100644 accessible/tests/mochitest/events/test_focus_canvas.html create mode 100644 accessible/tests/mochitest/treeupdate/test_canvas.html diff --git a/accessible/tests/mochitest/events/Makefile.in b/accessible/tests/mochitest/events/Makefile.in index e1bc28398540..f9f1adb32b00 100644 --- a/accessible/tests/mochitest/events/Makefile.in +++ b/accessible/tests/mochitest/events/Makefile.in @@ -65,6 +65,7 @@ _TEST_FILES =\ test_focus_aria_activedescendant.html \ test_focus_autocomplete.xul \ test_focus_browserui.xul \ + test_focus_canvas.html \ test_focus_contextmenu.xul \ test_focus_controls.html \ test_focus_dialog.html \ diff --git a/accessible/tests/mochitest/events/test_focus_canvas.html b/accessible/tests/mochitest/events/test_focus_canvas.html new file mode 100644 index 000000000000..8c72637a6d72 --- /dev/null +++ b/accessible/tests/mochitest/events/test_focus_canvas.html @@ -0,0 +1,59 @@ + + + + Accessible focus testing in canvas subdom + + + + + + + + + + + + + + + + Mozilla Bug 495912 + + +

+ +
+  
+ + + + + + +
+ + diff --git a/accessible/tests/mochitest/tree/test_canvas.html b/accessible/tests/mochitest/tree/test_canvas.html index 59e3de0a9182..e80226a2d869 100644 --- a/accessible/tests/mochitest/tree/test_canvas.html +++ b/accessible/tests/mochitest/tree/test_canvas.html @@ -17,14 +17,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=495912 + + + + + + + + + + + Mozilla Bug 495912 + + +

+ +
+  
+ + + + + +
+ + diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index a6f16adda268..d7c4646989cd 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -3540,7 +3540,8 @@ nsCSSFrameConstructor::FindCanvasData(Element* aElement, } static const FrameConstructionData sCanvasData = - SIMPLE_FCDATA(NS_NewHTMLCanvasFrame); + FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewHTMLCanvasFrame, + nsCSSAnonBoxes::htmlCanvasContent); return &sCanvasData; } diff --git a/layout/generic/nsHTMLCanvasFrame.cpp b/layout/generic/nsHTMLCanvasFrame.cpp index 10b3484728e1..45074f7127d9 100644 --- a/layout/generic/nsHTMLCanvasFrame.cpp +++ b/layout/generic/nsHTMLCanvasFrame.cpp @@ -249,10 +249,24 @@ nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext, Invalidate(nsRect(0, 0, mRect.width, mRect.height)); } + // Reflow the single anon block child. + nsReflowStatus childStatus; + nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE); + nsIFrame* childFrame = mFrames.FirstChild(); + NS_ASSERTION(!childFrame->GetNextSibling(), "HTML canvas should have 1 kid"); + nsHTMLReflowMetrics childDesiredSize(aMetrics.mFlags); + nsHTMLReflowState childReflowState(aPresContext, aReflowState, childFrame, + availSize); + ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowState, + 0, 0, 0, childStatus, nsnull); + FinishReflowChild(childFrame, aPresContext, &childReflowState, + childDesiredSize, 0, 0, 0); + NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("exit nsHTMLCanvasFrame::Reflow: size=%d,%d", aMetrics.width, aMetrics.height)); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics); + return NS_OK; } diff --git a/layout/generic/nsHTMLCanvasFrame.h b/layout/generic/nsHTMLCanvasFrame.h index 707d8db926de..26b1e0388708 100644 --- a/layout/generic/nsHTMLCanvasFrame.h +++ b/layout/generic/nsHTMLCanvasFrame.h @@ -40,7 +40,7 @@ #ifndef nsHTMLCanvasFrame_h___ #define nsHTMLCanvasFrame_h___ -#include "nsSplittableFrame.h" +#include "nsContainerFrame.h" #include "nsString.h" #include "nsAString.h" #include "nsIIOService.h" @@ -52,7 +52,7 @@ class nsDisplayItem; nsIFrame* NS_NewHTMLCanvasFrame (nsIPresShell* aPresShell, nsStyleContext* aContext); -class nsHTMLCanvasFrame : public nsSplittableFrame +class nsHTMLCanvasFrame : public nsContainerFrame { public: typedef mozilla::layers::Layer Layer; @@ -60,7 +60,7 @@ public: NS_DECL_FRAMEARENA_HELPERS - nsHTMLCanvasFrame(nsStyleContext* aContext) : nsSplittableFrame(aContext) {} + nsHTMLCanvasFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {} NS_IMETHOD Init(nsIContent* aContent, nsIFrame* aParent, @@ -108,6 +108,11 @@ public: NS_IMETHOD GetFrameName(nsAString& aResult) const; #endif + // Inserted child content gets its frames parented by our child block + virtual nsIFrame* GetContentInsertionFrame() { + return GetFirstPrincipalChild()->GetContentInsertionFrame(); + } + protected: virtual ~nsHTMLCanvasFrame(); diff --git a/layout/style/html.css b/layout/style/html.css index bdc99eb2314f..7061fd733f9b 100644 --- a/layout/style/html.css +++ b/layout/style/html.css @@ -750,6 +750,12 @@ audio:not([controls]) { display: none; } +*|*::-moz-html-canvas-content { + display: block !important; + /* we want to be an absolute and fixed container */ + -moz-transform: translate(0) !important; +} + /* emulation of non-standard HTML tag */ marquee { width: -moz-available; diff --git a/layout/style/nsCSSAnonBoxList.h b/layout/style/nsCSSAnonBoxList.h index 25d40f78b678..aa9ff65d42b6 100644 --- a/layout/style/nsCSSAnonBoxList.h +++ b/layout/style/nsCSSAnonBoxList.h @@ -72,6 +72,7 @@ CSS_ANON_BOX(dropDownList, ":-moz-dropdown-list") CSS_ANON_BOX(fieldsetContent, ":-moz-fieldset-content") CSS_ANON_BOX(framesetBlank, ":-moz-frameset-blank") CSS_ANON_BOX(mozDisplayComboboxControlFrame, ":-moz-display-comboboxcontrol-frame") +CSS_ANON_BOX(htmlCanvasContent, ":-moz-html-canvas-content") CSS_ANON_BOX(inlineTable, ":-moz-inline-table") CSS_ANON_BOX(table, ":-moz-table")