[CSS Regions] Add new regionOversetChange event
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Jun 2013 16:13:11 +0000 (16:13 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Jun 2013 16:13:11 +0000 (16:13 +0000)
https://bugs.webkit.org/show_bug.cgi?id=117508

Source/WebCore:

Added regionOversetChange event and tests for it. The overset value of the region has been moved to the ElementRareData
object instead of the RenderRegion object. This was needed for the case when a reattach is performed (for instance by changing
the display type of the region's containing block) and the RenderRegion object is destroyed. When computing the overset again,
there would be no "previous" value to compare it to and decide whether the regionOversetChange event must be dispatched.

Patch by Radu Stavila <stavila@adobe.com> on 2013-06-20
Reviewed by Antti Koivisto.

Tests:  fast/regions/webkit-named-flow-event-add-to-flow.html:
        fast/regions/webkit-named-flow-event-auto-height.html:
        fast/regions/webkit-named-flow-event-crash.html:
        fast/regions/webkit-named-flow-event-no-regions.html:
        fast/regions/webkit-named-flow-event-region-in-flexbox-no-overset-change.html: Added.
        fast/regions/webkit-named-flow-event-region-in-flexbox-overset-change.html: Added.
        fast/regions/webkit-named-flow-event-remove-from-dom.html:
        fast/regions/webkit-named-flow-event-remove-from-flow.html:
        fast/regions/webkit-named-flow-event-target.html:
        fast/regions/webkit-named-flow-event-to-null.html:
        fast/regions/webkit-named-flow-event.html:

* GNUmakefile.list.am:
* Target.pri:
* WebCore.xcodeproj/project.pbxproj:
* dom/Element.cpp:
(WebCore::Element::setRegionOversetState):
(WebCore::Element::regionOversetState):
(WebCore::Element::webkitRegionOverset):
* dom/Element.h:
* dom/ElementRareData.cpp:
* dom/ElementRareData.h:
(WebCore::ElementRareData::regionOversetState):
(WebCore::ElementRareData::setRegionOversetState):
(WebCore::ElementRareData::ElementRareData):
* dom/EventNames.h:
* dom/WebKitNamedFlow.cpp:
(WebCore::WebKitNamedFlow::firstEmptyRegionIndex):
(WebCore::WebKitNamedFlow::dispatchRegionOversetChangeEvent):
* dom/WebKitNamedFlow.h:
(WebCore::ChangeRegionOversetTask::ChangeRegionOversetTask):
(WebCore::ChangeRegionOversetTask::scheduleFor):
(WebCore::ChangeRegionOversetTask::unschedule):
(WebCore::ChangeRegionOversetTask::reset):
(WebCore::ChangeRegionOversetTask::onTimer):
* rendering/RegionOversetState.h: Added.
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::computeOverflow):
* rendering/RenderFlowThread.cpp:
(WebCore::RenderFlowThread::RenderFlowThread):
(WebCore::RenderFlowThread::layout):
(WebCore::RenderFlowThread::computeOversetStateForRegions):
* rendering/RenderFlowThread.h:
* rendering/RenderNamedFlowThread.cpp:
(WebCore::RenderNamedFlowThread::RenderNamedFlowThread):
(WebCore::RenderNamedFlowThread::dispatchRegionOversetChangeEvent):
(WebCore::RenderNamedFlowThread::regionOversetChangeEventTimerFired):
* rendering/RenderNamedFlowThread.h:
* rendering/RenderRegion.cpp:
(WebCore::RenderRegion::RenderRegion):
(WebCore::RenderRegion::regionOversetState):
(WebCore::RenderRegion::setRegionOversetState):
* rendering/RenderRegion.h:

LayoutTests:

Changed regionLayoutUpdate tests to regionOversetChange and added new tests for regionOversetChange.

Patch by Radu Stavila <stavila@adobe.com> on 2013-06-20
Reviewed by Antti Koivisto.

* fast/regions/webkit-named-flow-event-add-to-flow-expected.txt:
* fast/regions/webkit-named-flow-event-add-to-flow.html:
* fast/regions/webkit-named-flow-event-auto-height-expected.txt:
* fast/regions/webkit-named-flow-event-auto-height.html: Added.
* fast/regions/webkit-named-flow-event-crash-expected.txt:
* fast/regions/webkit-named-flow-event-crash.html:
* fast/regions/webkit-named-flow-event-expected.txt:
* fast/regions/webkit-named-flow-event-no-regions-expected.txt:
* fast/regions/webkit-named-flow-event-no-regions.html:
* fast/regions/webkit-named-flow-event-region-in-flexbox-no-overset-change-expected.txt:
* fast/regions/webkit-named-flow-event-region-in-flexbox-no-overset-change.html: Added.
* fast/regions/webkit-named-flow-event-region-in-flexbox-overset-change-expected.txt:
* fast/regions/webkit-named-flow-event-region-in-flexbox-overset-change.html: Added.
* fast/regions/webkit-named-flow-event-remove-from-dom-expected.txt:
* fast/regions/webkit-named-flow-event-remove-from-dom.html:
* fast/regions/webkit-named-flow-event-remove-from-flow-expected.txt:
* fast/regions/webkit-named-flow-event-remove-from-flow.html:
* fast/regions/webkit-named-flow-event-target-expected.txt:
* fast/regions/webkit-named-flow-event-target.html:
* fast/regions/webkit-named-flow-event-to-null-expected.txt:
* fast/regions/webkit-named-flow-event-to-null.html:
* fast/regions/webkit-named-flow-event.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@151777 268f45cc-cd09-0410-ab3c-d52691b4dbfc

43 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/regions/webkit-named-flow-event-add-to-flow-expected.txt
LayoutTests/fast/regions/webkit-named-flow-event-add-to-flow.html
LayoutTests/fast/regions/webkit-named-flow-event-auto-height-expected.txt [new file with mode: 0644]
LayoutTests/fast/regions/webkit-named-flow-event-auto-height.html [new file with mode: 0644]
LayoutTests/fast/regions/webkit-named-flow-event-crash-expected.txt
LayoutTests/fast/regions/webkit-named-flow-event-crash.html
LayoutTests/fast/regions/webkit-named-flow-event-expected.txt
LayoutTests/fast/regions/webkit-named-flow-event-no-regions-expected.txt
LayoutTests/fast/regions/webkit-named-flow-event-no-regions.html
LayoutTests/fast/regions/webkit-named-flow-event-region-in-flexbox-no-overset-change-expected.txt [new file with mode: 0644]
LayoutTests/fast/regions/webkit-named-flow-event-region-in-flexbox-no-overset-change.html [new file with mode: 0644]
LayoutTests/fast/regions/webkit-named-flow-event-region-in-flexbox-overset-change-expected.txt [new file with mode: 0644]
LayoutTests/fast/regions/webkit-named-flow-event-region-in-flexbox-overset-change.html [new file with mode: 0644]
LayoutTests/fast/regions/webkit-named-flow-event-remove-from-dom-expected.txt
LayoutTests/fast/regions/webkit-named-flow-event-remove-from-dom.html
LayoutTests/fast/regions/webkit-named-flow-event-remove-from-flow-expected.txt
LayoutTests/fast/regions/webkit-named-flow-event-remove-from-flow.html
LayoutTests/fast/regions/webkit-named-flow-event-target-expected.txt
LayoutTests/fast/regions/webkit-named-flow-event-target.html
LayoutTests/fast/regions/webkit-named-flow-event-to-null-expected.txt
LayoutTests/fast/regions/webkit-named-flow-event-to-null.html
LayoutTests/fast/regions/webkit-named-flow-event.html
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/Element.h
Source/WebCore/dom/ElementRareData.cpp
Source/WebCore/dom/ElementRareData.h
Source/WebCore/dom/EventNames.h
Source/WebCore/dom/WebKitNamedFlow.cpp
Source/WebCore/dom/WebKitNamedFlow.h
Source/WebCore/inspector/InspectorCSSAgent.cpp
Source/WebCore/rendering/RegionOversetState.h [new file with mode: 0644]
Source/WebCore/rendering/RenderBlock.cpp
Source/WebCore/rendering/RenderFlowThread.cpp
Source/WebCore/rendering/RenderFlowThread.h
Source/WebCore/rendering/RenderNamedFlowThread.cpp
Source/WebCore/rendering/RenderNamedFlowThread.h
Source/WebCore/rendering/RenderRegion.cpp
Source/WebCore/rendering/RenderRegion.h

index 7c91b67..40825b5 100644 (file)
@@ -1,3 +1,35 @@
+2013-06-20  Radu Stavila  <stavila@adobe.com>
+
+        [CSS Regions] Add new regionOversetChange event
+        https://bugs.webkit.org/show_bug.cgi?id=117508
+
+        Changed regionLayoutUpdate tests to regionOversetChange and added new tests for regionOversetChange.
+
+        Reviewed by Antti Koivisto.
+
+        * fast/regions/webkit-named-flow-event-add-to-flow-expected.txt:
+        * fast/regions/webkit-named-flow-event-add-to-flow.html:
+        * fast/regions/webkit-named-flow-event-auto-height-expected.txt:
+        * fast/regions/webkit-named-flow-event-auto-height.html: Added.
+        * fast/regions/webkit-named-flow-event-crash-expected.txt:
+        * fast/regions/webkit-named-flow-event-crash.html:
+        * fast/regions/webkit-named-flow-event-expected.txt:
+        * fast/regions/webkit-named-flow-event-no-regions-expected.txt:
+        * fast/regions/webkit-named-flow-event-no-regions.html:
+        * fast/regions/webkit-named-flow-event-region-in-flexbox-no-overset-change-expected.txt:
+        * fast/regions/webkit-named-flow-event-region-in-flexbox-no-overset-change.html: Added.
+        * fast/regions/webkit-named-flow-event-region-in-flexbox-overset-change-expected.txt:
+        * fast/regions/webkit-named-flow-event-region-in-flexbox-overset-change.html: Added.
+        * fast/regions/webkit-named-flow-event-remove-from-dom-expected.txt:
+        * fast/regions/webkit-named-flow-event-remove-from-dom.html:
+        * fast/regions/webkit-named-flow-event-remove-from-flow-expected.txt:
+        * fast/regions/webkit-named-flow-event-remove-from-flow.html:
+        * fast/regions/webkit-named-flow-event-target-expected.txt:
+        * fast/regions/webkit-named-flow-event-target.html:
+        * fast/regions/webkit-named-flow-event-to-null-expected.txt:
+        * fast/regions/webkit-named-flow-event-to-null.html:
+        * fast/regions/webkit-named-flow-event.html:
+
 2013-06-20  James Craig  <james@cookiecrook.com>
 
         AX: aria-required is not exposed on all expected roles
index c81a05e..db01d3f 100644 (file)
@@ -1,10 +1,11 @@
-Tests regionLayoutEvent
+Tests regionOversetChange event
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
  Flow content
 PASS event.target.name is "article"
 PASS event.target.name is "article"
+PASS eventCount is 2
 PASS successfullyParsed is true
 
 TEST COMPLETE
index facdc27..c6b2d25 100644 (file)
@@ -17,7 +17,7 @@
 .block {
    display:block;
 }
-#region_1, #region_2 { height:110px; width:200px; margin: 5px;}
+#region_1, #region_2 { height:110px; width:200px; margin: 5px; border: 1px solid red;}
 </style>
 </head>
 <body>
@@ -34,7 +34,7 @@
 <div id="console" class="block"></div>
 
 <script>
-    description("Tests regionLayoutEvent")
+    description("Tests regionOversetChange event")
     if (window.testRunner) {
         testRunner.dumpAsText();
         testRunner.waitUntilDone();
         var r = document.getElementById(region);
         r.style.webkitFlowFrom = flowName;
     }
-    
-    var count = 0;
-    function regionLayoutUpdated(event) {
+
+    var eventCount = 0;
+    function finishTest() {
+        shouldBe("eventCount", "2");
+        finishJSTest();
+    }
+
+    function regionOversetChanged(event) {
         shouldBeEqualToString("event.target.name", "article");
         
-        if (++count > 1) {
-            event.target.removeEventListener("webkitregionlayoutupdate", regionLayoutUpdated);
-            
+        if (++eventCount > 1) {
             // this should be reached after region_2 is added to flow
-            finishJSTest();
+            finishTest();
             return;
         }
         
@@ -62,7 +65,7 @@
 
     function startTest() {
         var flow = getFlowByName("article");
-        flow.addEventListener("webkitregionlayoutupdate", regionLayoutUpdated);
+        flow.addEventListener("webkitregionoversetchange", regionOversetChanged);
         
         debug("Flow content");
         flowContent("region_1", "article");
diff --git a/LayoutTests/fast/regions/webkit-named-flow-event-auto-height-expected.txt b/LayoutTests/fast/regions/webkit-named-flow-event-auto-height-expected.txt
new file mode 100644 (file)
index 0000000..55f7593
--- /dev/null
@@ -0,0 +1,12 @@
+Tests the regionOversetChange event for regions with height:auto
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Flowing content into regions...
+PASS event.target.name is "article"
+PASS eventFiredCount is 1
+PASS successfullyParsed is true
+
+TEST COMPLETE
diff --git a/LayoutTests/fast/regions/webkit-named-flow-event-auto-height.html b/LayoutTests/fast/regions/webkit-named-flow-event-auto-height.html
new file mode 100644 (file)
index 0000000..e075a2a
--- /dev/null
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="../js/resources/js-test-pre.js"></script>
+<script src="resources/helper.js"></script>
+<style>
+    #article {
+        -webkit-flow-into: article;
+        border: 10px solid black;
+    }
+    #region_1, #region_2 {
+        -webkit-flow-from: no_article;
+        overflow:hidden;
+        display:inline-block;
+        vertical-align:top;
+        margin:10px;
+        height:auto;
+        width:200px;
+        border: 1px solid red;
+        padding: 5px;
+    }
+    .content {
+        background-color: green;
+        border: 3px dashed blue;
+    }
+    #part1 {
+        height: 180px;
+    }
+    #part2 {
+        -webkit-region-break-before: always;
+        height: 160px;
+    }
+</style>
+</head>
+<body>
+    <div id="article">
+        <div>
+            <div id="part1" class="content"></div>
+            <div id="part2" class="content"></div>
+        </div>
+    </div>
+
+    <div id="region_1"></div>
+    <div id="region_2"></div>
+
+    <script>
+
+        description("Tests the regionOversetChange event for regions with height:auto");
+
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+        window.jsTestIsAsync = true;
+        function flowContent(flowName) {
+            var region = document.getElementById("region_1");
+            region.style.webkitFlowFrom = flowName;
+            region = document.getElementById("region_2");
+            region.style.webkitFlowFrom = flowName;
+        }
+
+        var eventFiredCount = 0;
+        function finishTest() {
+            shouldBe("eventFiredCount", "1");
+            finishJSTest();
+        }
+
+        function regionOversetChanged(event) {
+               ++eventFiredCount;
+            shouldBeEqualToString("event.target.name", "article");
+            
+            // wait and make sure no other events arrive
+            setTimeout("finishTest()", 200);
+        }
+
+        function startTest() {    
+            var flowThread = getFlowByName("article");
+            flowThread.addEventListener("webkitregionoversetchange", regionOversetChanged);
+            
+            debug("Flowing content into regions...");
+            flowContent("article");
+        }
+
+        window.addEventListener("load", startTest);
+    </script>
+    <script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
index c5b1b4c..64d949a 100644 (file)
@@ -1,4 +1,4 @@
-Test for https://bugs.webkit.org/show_bug.cgi?id=102944 [CSS Regions] Crash when dispatching regionlayoutupdate. The test passes if there is no crash or assert.
+The test passes if there is no crash or assert.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
index fe63c3b..81ff3c0 100644 (file)
         <div id="region">
         </div>
         <script>
-        description("Test for https://bugs.webkit.org/show_bug.cgi?id=102944 [CSS Regions] Crash when dispatching regionlayoutupdate. The test passes if there is no crash or assert.");
+        description("The test passes if there is no crash or assert.");
         if (window.testRunner) {
             testRunner.dumpAsText();
             testRunner.waitUntilDone();
         }
 
         function dummyHandler (evt) {
-            evt.target.removeEventListener("webkitregionlayoutupdate", dummyHandler);
+            evt.target.removeEventListener("webkitregionoversetchange", dummyHandler);
+            debug("This line should not appear!");
         }
 
         setTimeout(function() {
             var namedFlows = document.webkitGetNamedFlows();
-            namedFlows["flow"].addEventListener("webkitregionlayoutupdate", dummyHandler);
+            namedFlows["flow"].addEventListener("webkitregionoversetchange", dummyHandler);
             var content = document.getElementById("content");
             var region = document.getElementById("region");
             content.style.height = "600px";
 
-            // Schedule a regionlayoutupdate event.
+            // Schedule a regionoversetchange event.
             document.body.offsetTop;
 
             // Transition the flow to the "NULL" state.
index f93e9c7..7c79339 100644 (file)
@@ -1,4 +1,4 @@
-Tests regionLayoutEvent
+Tests regionOversetChange event
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
index ea2b219..820bd95 100644 (file)
@@ -1,4 +1,4 @@
-Tests regionLayoutEvent being dispatched when the region chain is removed
+Tests regionOversetChange being dispatched when the region chain is removed
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
@@ -8,6 +8,7 @@ PASS event.target.name is "article"
 Removing region 1
 Removing region 2
 PASS event.target.name is "article"
+PASS eventCount is 2
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 27fe632..bb46fa3 100644 (file)
@@ -35,7 +35,7 @@
 </div>
 
 <script>
-    description("Tests regionLayoutEvent being dispatched when the region chain is removed");
+    description("Tests regionOversetChange being dispatched when the region chain is removed");
     if (window.testRunner) {
         testRunner.dumpAsText();
         testRunner.waitUntilDone();
         r.style.webkitFlowFrom = flowName;
     }
 
-    var count = 0;
-    function regionLayoutUpdated(event) {
+    function finishTest() {
+        shouldBe("eventCount", "2");
+        finishJSTest();
+    }
+
+    var eventCount = 0;
+    function regionOversetChanged(event) {
         shouldBeEqualToString("event.target.name", "article");
-        if (++count > 1) {
-           event.target.removeEventListener("webkitregionlayoutupdate", regionLayoutUpdated);
-           finishJSTest();
+        if (++eventCount > 1) {
+           event.target.removeEventListener("webkitregionoversetchange", regionOversetChanged);
+           finishTest();
            return;
         }
 
@@ -68,7 +73,7 @@
 
     function startTest() {
         var flow = getFlowByName("article");
-        flow.addEventListener("webkitregionlayoutupdate", regionLayoutUpdated);
+        flow.addEventListener("webkitregionoversetchange", regionOversetChanged);
 
         debug("Flow content");
         flowContent("article");
diff --git a/LayoutTests/fast/regions/webkit-named-flow-event-region-in-flexbox-no-overset-change-expected.txt b/LayoutTests/fast/regions/webkit-named-flow-event-region-in-flexbox-no-overset-change-expected.txt
new file mode 100644 (file)
index 0000000..8b29468
--- /dev/null
@@ -0,0 +1,13 @@
+Tests the regionOversetChange event for regions inside flexboxes
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Flowing content into regions...
+PASS event.target.name is "article"
+Engaging flexbox...
+PASS eventFiredCount is 1
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/regions/webkit-named-flow-event-region-in-flexbox-no-overset-change.html b/LayoutTests/fast/regions/webkit-named-flow-event-region-in-flexbox-no-overset-change.html
new file mode 100644 (file)
index 0000000..430a314
--- /dev/null
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="../js/resources/js-test-pre.js"></script>
+<script src="resources/helper.js"></script>
+<style>
+    #article {
+        -webkit-flow-into: article;
+        border: 10px solid black;
+    }
+    #region_1, #region_2 {
+        -webkit-flow-from: no_article;
+        overflow:hidden;
+        display:inline-block;
+        vertical-align:top;
+        margin:10px;
+        height:190px;
+        width:200px;
+        border: 1px solid red;
+        padding: 5px;
+        -webkit-flex-grow: 1;
+        -webkit-flex-basis: 100%;
+    }
+    #region_2 {
+        -webkit-flex-basis: 30%;
+    }
+    .content {
+        background-color: green;
+        border: 3px dashed blue;
+        margin: 5px;
+    }
+    #part1 {
+        height: 140px;
+    }
+    #part2 {
+        height: 160px;
+    }
+    #flexbox {
+        border: 2px solid green;
+        margin: 5px;
+    }
+</style>
+</head>
+<body>
+    <div id="article">
+        <div>
+            <div id="part1" class="content"></div>
+            <div id="part2" class="content"></div>
+        </div>
+    </div>
+
+    <div id="flexbox">
+        <div id="region_1"></div>
+        <div id="region_2"></div>
+    </div>
+
+    <script>
+
+        description("Tests the regionOversetChange event for regions inside flexboxes");
+
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+        window.jsTestIsAsync = true;
+        function flowContent(flowName) {
+            var region = document.getElementById("region_1");
+            region.style.webkitFlowFrom = flowName;
+            region = document.getElementById("region_2");
+            region.style.webkitFlowFrom = flowName;
+        }
+
+        var eventFiredCount = 0;
+        function finishTest() {
+            shouldBe("eventFiredCount", "1");
+            finishJSTest();
+        }
+
+        function EnableFlexbox() {
+            debug("Engaging flexbox...")
+            document.getElementById("flexbox").style.display = "-webkit-flex";
+
+            // wait and make sure no other events arrive
+            setTimeout("finishTest()", 200);
+        }
+
+        function regionOversetChanged(event) {
+               ++eventFiredCount;
+            shouldBeEqualToString("event.target.name", "article");
+
+            // activate the flexbox
+            if (eventFiredCount == 1) {
+                if (window.testRunner)
+                    EnableFlexbox();
+                else
+                    setTimeout("EnableFlexbox()", 1000);
+
+                return;
+            }
+        }
+
+        function startTest() {    
+            var flowThread = getFlowByName("article");
+            flowThread.addEventListener("webkitregionoversetchange", regionOversetChanged);
+            
+            debug("Flowing content into regions...");
+            flowContent("article");
+        }
+
+        window.addEventListener("load", startTest);
+    </script>
+    <script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/regions/webkit-named-flow-event-region-in-flexbox-overset-change-expected.txt b/LayoutTests/fast/regions/webkit-named-flow-event-region-in-flexbox-overset-change-expected.txt
new file mode 100644 (file)
index 0000000..8818de9
--- /dev/null
@@ -0,0 +1,14 @@
+Tests the regionOversetChange event for regions inside flexboxes
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Flowing content into regions...
+PASS event.target.name is "article"
+Engaging flexbox...
+PASS event.target.name is "article"
+PASS eventFiredCount is 2
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/regions/webkit-named-flow-event-region-in-flexbox-overset-change.html b/LayoutTests/fast/regions/webkit-named-flow-event-region-in-flexbox-overset-change.html
new file mode 100644 (file)
index 0000000..1190920
--- /dev/null
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="../js/resources/js-test-pre.js"></script>
+<script src="resources/helper.js"></script>
+<style>
+    #article {
+        -webkit-flow-into: article;
+        border: 10px solid black;
+    }
+    #region_1, #region_2 {
+        -webkit-flow-from: no_article;
+        overflow:hidden;
+        display:inline-block;
+        vertical-align:top;
+        margin:10px;
+        height:auto;
+        width:200px;
+        border: 1px solid red;
+        padding: 5px;
+        -webkit-flex-grow: 1;
+        -webkit-flex-basis: 100%;
+    }
+    #region_2 {
+        -webkit-flex-basis: 70%;
+    }
+    .content {
+        background-color: green;
+        border: 3px dashed blue;
+        margin: 5px;
+    }
+    #part1 {
+        height: 70px;
+    }
+    #part2 {
+        height: 80px;
+    }
+    #flexbox {
+        border: 2px solid green;
+        margin: 5px;
+        width: 240px;
+        height: 300px;
+        -webkit-flex-direction: column;
+    }
+</style>
+</head>
+<body>
+    <div id="article">
+        <div>
+            <div id="part1" class="content"></div>
+            <div id="part2" class="content"></div>
+        </div>
+    </div>
+
+    <div id="flexbox">
+        <div id="region_1"></div>
+        <div id="region_2"></div>
+    </div>
+
+    <script>
+
+        description("Tests the regionOversetChange event for regions inside flexboxes");
+
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+        window.jsTestIsAsync = true;
+        function flowContent(flowName) {
+            var region = document.getElementById("region_1");
+            region.style.webkitFlowFrom = flowName;
+            region = document.getElementById("region_2");
+            region.style.webkitFlowFrom = flowName;
+        }
+
+        var eventFiredCount = 0;
+        function finishTest() {
+            shouldBe("eventFiredCount", "2");
+            finishJSTest();
+        }
+
+        function EnableFlexbox() {
+            debug("Engaging flexbox...")
+            document.getElementById("flexbox").style.display = "-webkit-flex";
+        }
+
+        function regionOversetChanged(event) {
+               ++eventFiredCount;
+            shouldBeEqualToString("event.target.name", "article");
+
+            // activate the flexbox
+            if (eventFiredCount == 1) {
+                if (window.testRunner)
+                    EnableFlexbox();
+                else
+                    setTimeout("EnableFlexbox()", 1000);
+
+                return;
+            }
+
+            else 
+                setTimeout("finishTest()", 200);
+        }
+
+        function startTest() {    
+            var flowThread = getFlowByName("article");
+            flowThread.addEventListener("webkitregionoversetchange", regionOversetChanged);
+            
+            debug("Flowing content into regions...");
+            flowContent("article");
+        }
+
+        window.addEventListener("load", startTest);
+    </script>
+    <script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
index cb4ae01..27594f9 100644 (file)
@@ -1,4 +1,4 @@
-Tests regionLayoutEvent
+Tests regionOversetChange event
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
@@ -6,6 +6,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 PASS event.target.name is "article"
 Removing region_2 from DOM
 PASS event.target.name is "article"
+PASS eventCount is 2
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 02589e6..3b4638d 100644 (file)
@@ -17,7 +17,7 @@
 .block {
    display:block;
 }
-#region_1, #region_2 { height:110px; width:200px; margin: 5px;}
+#region_1, #region_2 { height:110px; width:200px; margin: 5px; border: 1px solid red;}
 </style>
 </head>
 <body>
@@ -36,7 +36,7 @@
 <div id="console" class="block"></div>
 
 <script>
-    description("Tests regionLayoutEvent")
+    description("Tests regionOversetChange event")
     if (window.testRunner) {
         testRunner.dumpAsText();
         testRunner.waitUntilDone();
         r = document.getElementById("region_2");
         r.style.webkitFlowFrom = flowName;
     }
-    
-    var count = 0;
-    function regionLayoutUpdated(event) {
+
+    var eventCount = 0;
+    function finishTest() {
+        shouldBe("eventCount", "2");
+        finishJSTest();
+    }
+
+    function regionOversetChanged(event) {
         shouldBeEqualToString("event.target.name", "article");
-        if (++count > 1) {
-           event.target.removeEventListener("webkitregionlayoutupdate", regionLayoutUpdated);
+        if (++eventCount > 1) {
+           event.target.removeEventListener("webkitregionoversetchange", regionOversetChanged);
            // this should be reached after region_2 is removed from DOM
-           finishJSTest();
+           finishTest();
            return;
         }
         
@@ -67,7 +72,7 @@
     
     function startTest() {
         var flow = getFlowByName("article");
-        flow.addEventListener("webkitregionlayoutupdate", regionLayoutUpdated);
+        flow.addEventListener("webkitregionoversetchange", regionOversetChanged);
         
         debug("Flow content");
         flowContent("article");
index 234e462..9e6e4c8 100644 (file)
@@ -1,4 +1,4 @@
-Tests regionLayoutEvent
+Tests regionOversetChange event
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
@@ -7,6 +7,7 @@ Flow content
 PASS event.target.name is "article"
 Removing region_2 from flow
 PASS event.target.name is "article"
+PASS eventCount is 2
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 028d448..6450d1e 100644 (file)
@@ -17,7 +17,7 @@
 .block {
    display:block;
 }
-#region_1, #region_2 { height:110px; width:200px; margin: 5px;}
+#region_1, #region_2 { height:110px; width:200px; margin: 5px; border: 1px solid red;}
 </style>
 </head>
 <body>
@@ -34,7 +34,7 @@
 <div id="console" class="block"></div>
 
 <script>
-    description("Tests regionLayoutEvent")
+    description("Tests regionOversetChange event")
     if (window.testRunner) {
         testRunner.dumpAsText();
         testRunner.waitUntilDone();
         r = document.getElementById("region_2");
         r.style.webkitFlowFrom = flowName;
     }
-    
-    var count = 0;
-    function regionLayoutUpdated(event) {
+
+    var eventCount = 0;
+    function finishTest() {
+        shouldBe("eventCount", "2");
+        finishJSTest();
+    }
+
+    function regionOversetChanged(event) {
         shouldBeEqualToString("event.target.name", "article");
-        if (++count > 1) {
-           event.target.removeEventListener("webkitregionlayoutupdate", regionLayoutUpdated);
-           // this should be reached after region_2 is removed from DOM
-           finishJSTest();
+        if (++eventCount > 1) {
+            // this should be reached after region_2 is removed from DOM
+           setTimeout("finishTest()", 200);
            return;
         }
         
@@ -65,7 +69,7 @@
     
     function startTest() {
         var flow = getFlowByName("article");
-        flow.addEventListener("webkitregionlayoutupdate", regionLayoutUpdated);
+        flow.addEventListener("webkitregionoversetchange", regionOversetChanged);
         
         debug("Flow content");
         flowContent("article");
index da8e54d..cd16484 100644 (file)
@@ -5,14 +5,13 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 Flow content
 PASS event.target.name is "article"
-PASS 2 is >= updatedCount
 PASS getFlowByName("article") is non-null.
 PASS recreated is false
 PASS getFlowByName("article") is null
 PASS event.target.name is "article"
-PASS 2 is >= updatedCount
 PASS recreated is true
 PASS getFlowByName("article") is non-null.
+PASS updatedCount is 2
 PASS successfullyParsed is true
 
 TEST COMPLETE
index ef6bb14..0695eb0 100644 (file)
@@ -19,7 +19,7 @@
 .block {
    display:block;
 }
-#region_1, #region_2 { height:110px; width:200px}
+#region_1, #region_2 { height:110px; width:200px; border: 1px solid red;}
 </style>
 </head>
 <body>
@@ -75,17 +75,20 @@ function makeFlowCreated() {
 }
 
 var updatedCount = 0;
+function finishTest() {
+    shouldBe("updatedCount", "2");
+    finishJSTest();
+}
+
 function flowThreadUpdated(event) {
        ++updatedCount;
     shouldBeEqualToString("event.target.name", "article");
 
-    shouldBeGreaterThanOrEqual("2", "updatedCount");
-
     if (updatedCount == 2) {
        shouldBeTrue("recreated");
-       event.target.removeEventListener("webkitregionlayoutupdate", flowThreadUpdated);
+       event.target.removeEventListener("webkitregionoversetchange", flowThreadUpdated);
        makeFlowNull();
-       finishJSTest();
+       setTimeout("finishTest()", 200);
        return;
     }
 
@@ -98,7 +101,7 @@ function flowThreadUpdated(event) {
 
 function startTest() {    
     var flowThread = getFlowByName("article");
-    flowThread.addEventListener("webkitregionlayoutupdate", flowThreadUpdated);
+    flowThread.addEventListener("webkitregionoversetchange", flowThreadUpdated);
     
     debug("Flow content");
     flowContent("article");
index eb2ccb9..6940c36 100644 (file)
@@ -1,4 +1,4 @@
-Tests regionLayoutEvent being dispatched when the content is removed
+Tests regionOversetChange event being dispatched when the content is removed
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
@@ -8,7 +8,7 @@ PASS event.target.name is "article"
 Removing region_2 from flow
 Removing region_1 from flow
 Removing article from flow
-PASS layoutUpdateDispatchedForNullFlow is false
+PASS regionOversetDispatchedForNullFlow is false
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 53f5dec..64fd8ad 100644 (file)
@@ -36,7 +36,7 @@
 
 <script>
 
-description("Tests regionLayoutEvent being dispatched when the content is removed");
+description("Tests regionOversetChange event being dispatched when the content is removed");
 
 if (window.testRunner) {
         testRunner.dumpAsText();
@@ -52,12 +52,12 @@ if (window.testRunner) {
     }
     
     var count = 0;
-    var layoutUpdateDispatchedForNullFlow = false;
-    function regionLayoutUpdated(event) {
+    var regionOversetDispatchedForNullFlow = false;
+    function regionOversetChanged(event) {
         shouldBeEqualToString("event.target.name", "article");
         if (++count > 1) {
-           event.target.removeEventListener("webkitregionlayoutupdate", regionLayoutUpdated);
-           layoutUpdateDispatchedForNullFlow = true;
+           event.target.removeEventListener("webkitregionoversetchange", regionOversetChanged);
+           regionOversetDispatchedForNullFlow = true;
            return;
         }
         
@@ -71,17 +71,17 @@ if (window.testRunner) {
         debug("Removing article from flow");
         el.style.webkitFlowInto = "none";
 
-        setTimeout(checkIfEventDispatched, 500);
+        setTimeout(checkIfEventDispatched, 200);
     }
 
     function checkIfEventDispatched() {
-        shouldBeFalse("layoutUpdateDispatchedForNullFlow");
+        shouldBeFalse("regionOversetDispatchedForNullFlow");
         finishJSTest();
     }
     
     function startTest() {
         var flow = getFlowByName("article");
-        flow.addEventListener("webkitregionlayoutupdate", regionLayoutUpdated);
+        flow.addEventListener("webkitregionoversetchange", regionOversetChanged);
         
         debug("Flow content");
         flowContent("article");
index 766e209..ae084e0 100644 (file)
@@ -34,7 +34,7 @@
 <div id="console" class="block"></div>
 
 <script>
-    description("Tests regionLayoutEvent")
+    description("Tests regionOversetChange event")
     if (window.testRunner) {
         testRunner.dumpAsText();
         testRunner.waitUntilDone();
     
     function flowThreadUpdated(event) {
         shouldBeEqualToString("event.target.name", "article");
-        event.target.removeEventListener("webkitregionlayoutupdate", flowThreadUpdated);
+        event.target.removeEventListener("webkitregionoversetchange", flowThreadUpdated);
         
         finishJSTest();
     }
     
     function startTest() {    
         var flowThread = getFlowByName("article");
-        flowThread.addEventListener("webkitregionlayoutupdate", flowThreadUpdated);
+        flowThread.addEventListener("webkitregionoversetchange", flowThreadUpdated);
         
         debug("Flow content");
         flowContent("article");
     }
-    //startTest();
     window.addEventListener("load", startTest);
 </script>
 <script src="../../fast/js/resources/js-test-post.js"></script>
index e0bc620..b3d7537 100644 (file)
@@ -1,3 +1,70 @@
+2013-06-20  Radu Stavila  <stavila@adobe.com>
+
+        [CSS Regions] Add new regionOversetChange event
+        https://bugs.webkit.org/show_bug.cgi?id=117508
+
+        Added regionOversetChange event and tests for it. The overset value of the region has been moved to the ElementRareData
+        object instead of the RenderRegion object. This was needed for the case when a reattach is performed (for instance by changing
+        the display type of the region's containing block) and the RenderRegion object is destroyed. When computing the overset again,
+        there would be no "previous" value to compare it to and decide whether the regionOversetChange event must be dispatched.
+
+        Reviewed by Antti Koivisto.
+
+        Tests:  fast/regions/webkit-named-flow-event-add-to-flow.html:
+                fast/regions/webkit-named-flow-event-auto-height.html:
+                fast/regions/webkit-named-flow-event-crash.html:
+                fast/regions/webkit-named-flow-event-no-regions.html:
+                fast/regions/webkit-named-flow-event-region-in-flexbox-no-overset-change.html: Added.
+                fast/regions/webkit-named-flow-event-region-in-flexbox-overset-change.html: Added.
+                fast/regions/webkit-named-flow-event-remove-from-dom.html:
+                fast/regions/webkit-named-flow-event-remove-from-flow.html:
+                fast/regions/webkit-named-flow-event-target.html:
+                fast/regions/webkit-named-flow-event-to-null.html:
+                fast/regions/webkit-named-flow-event.html:
+
+
+        * GNUmakefile.list.am:
+        * Target.pri:
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/Element.cpp:
+        (WebCore::Element::setRegionOversetState):
+        (WebCore::Element::regionOversetState):
+        (WebCore::Element::webkitRegionOverset):
+        * dom/Element.h:
+        * dom/ElementRareData.cpp:
+        * dom/ElementRareData.h:
+        (WebCore::ElementRareData::regionOversetState):
+        (WebCore::ElementRareData::setRegionOversetState):
+        (WebCore::ElementRareData::ElementRareData):
+        * dom/EventNames.h:
+        * dom/WebKitNamedFlow.cpp:
+        (WebCore::WebKitNamedFlow::firstEmptyRegionIndex):
+        (WebCore::WebKitNamedFlow::dispatchRegionOversetChangeEvent):
+        * dom/WebKitNamedFlow.h:
+        (WebCore::ChangeRegionOversetTask::ChangeRegionOversetTask):
+        (WebCore::ChangeRegionOversetTask::scheduleFor):
+        (WebCore::ChangeRegionOversetTask::unschedule):
+        (WebCore::ChangeRegionOversetTask::reset):
+        (WebCore::ChangeRegionOversetTask::onTimer):
+        * rendering/RegionOversetState.h: Added.
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::computeOverflow):
+        * rendering/RenderFlowThread.cpp:
+        (WebCore::RenderFlowThread::RenderFlowThread):
+        (WebCore::RenderFlowThread::layout):
+        (WebCore::RenderFlowThread::computeOversetStateForRegions):
+        * rendering/RenderFlowThread.h:
+        * rendering/RenderNamedFlowThread.cpp:
+        (WebCore::RenderNamedFlowThread::RenderNamedFlowThread):
+        (WebCore::RenderNamedFlowThread::dispatchRegionOversetChangeEvent):
+        (WebCore::RenderNamedFlowThread::regionOversetChangeEventTimerFired):
+        * rendering/RenderNamedFlowThread.h:
+        * rendering/RenderRegion.cpp:
+        (WebCore::RenderRegion::RenderRegion):
+        (WebCore::RenderRegion::regionOversetState):
+        (WebCore::RenderRegion::setRegionOversetState):
+        * rendering/RenderRegion.h:
+
 2013-06-20  James Craig  <james@cookiecrook.com>
 
         AX: aria-required is not exposed on all expected roles
index becc4d3..08e3283 100644 (file)
@@ -4400,6 +4400,7 @@ webcore_sources += \
        Source/WebCore/rendering/PaintPhase.h \
        Source/WebCore/rendering/PointerEventsHitRules.cpp \
        Source/WebCore/rendering/PointerEventsHitRules.h \
+       Source/WebCore/rendering/RegionOversetState.h \
        Source/WebCore/rendering/RenderApplet.cpp \
        Source/WebCore/rendering/RenderApplet.h \
        Source/WebCore/rendering/RenderArena.cpp \
index b35fb68..cba426c 100644 (file)
@@ -2421,6 +2421,7 @@ HEADERS += \
     rendering/PaintInfo.h \
     rendering/PaintPhase.h \
     rendering/PointerEventsHitRules.h \
+    rendering/RegionOversetState.h \
     rendering/RenderApplet.h \
     rendering/RenderArena.h \
     rendering/RenderBlock.h \
index f7d9347..b81a8c8 100644 (file)
                6B3480940EEF50D400AC1B41 /* NativeImagePtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 6B3480920EEF50D400AC1B41 /* NativeImagePtr.h */; settings = {ATTRIBUTES = (Private, ); }; };
                6C638895A96CCEE50C8C946C /* CachedResourceRequestInitiators.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C638893A96CCEE50C8C946C /* CachedResourceRequestInitiators.h */; settings = {ATTRIBUTES = (Private, ); }; };
                6C638896A96CCEE50C8C946C /* CachedResourceRequestInitiators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6C638894A96CCEE50C8C946C /* CachedResourceRequestInitiators.cpp */; };
+               6CDDE8D01770BB220016E072 /* RegionOversetState.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C70A81417707C49009A446E /* RegionOversetState.h */; settings = {ATTRIBUTES = (Private, ); }; };
                6E21C6C01126338500A7BE02 /* GraphicsContext3D.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6E21C6BF1126338500A7BE02 /* GraphicsContext3D.cpp */; };
                6E21C6C21126339900A7BE02 /* GraphicsContext3DCG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6E21C6C11126339900A7BE02 /* GraphicsContext3DCG.cpp */; };
                6E3FAD3814733F4000E42306 /* JSWebGLCompressedTextureS3TC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6E3FAD3614733F4000E42306 /* JSWebGLCompressedTextureS3TC.cpp */; };
                6B3480920EEF50D400AC1B41 /* NativeImagePtr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NativeImagePtr.h; sourceTree = "<group>"; };
                6C638893A96CCEE50C8C946C /* CachedResourceRequestInitiators.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CachedResourceRequestInitiators.h; sourceTree = "<group>"; };
                6C638894A96CCEE50C8C946C /* CachedResourceRequestInitiators.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CachedResourceRequestInitiators.cpp; sourceTree = "<group>"; };
+               6C70A81417707C49009A446E /* RegionOversetState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegionOversetState.h; sourceTree = "<group>"; };
                6E21C6BF1126338500A7BE02 /* GraphicsContext3D.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GraphicsContext3D.cpp; sourceTree = "<group>"; };
                6E21C6C11126339900A7BE02 /* GraphicsContext3DCG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GraphicsContext3DCG.cpp; sourceTree = "<group>"; };
                6E3FAD3614733F4000E42306 /* JSWebGLCompressedTextureS3TC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGLCompressedTextureS3TC.cpp; sourceTree = "<group>"; };
                                0885067E11DA045B00182B98 /* PaintPhase.h */,
                                B2B1F7140D00CAA8004AEA64 /* PointerEventsHitRules.cpp */,
                                B2B1F7150D00CAA8004AEA64 /* PointerEventsHitRules.h */,
+                               6C70A81417707C49009A446E /* RegionOversetState.h */,
                                BCEA481C097D93020094C9E4 /* RenderApplet.cpp */,
                                BCEA481D097D93020094C9E4 /* RenderApplet.h */,
                                BCEA481E097D93020094C9E4 /* RenderArena.cpp */,
                                BE8EF04B171C9014009B48C3 /* JSVideoTrack.h in Headers */,
                                BE8EF04D171C9014009B48C3 /* JSVideoTrackList.h in Headers */,
                                FB719C3F17238CA80022DE34 /* WebKitCSSMatFunctionValue.h in Headers */,
+                               6CDDE8D01770BB220016E072 /* RegionOversetState.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 835f8b3..772b449 100644 (file)
@@ -2420,6 +2420,16 @@ bool Element::isInCanvasSubtree() const
     return hasRareData() && elementRareData()->isInCanvasSubtree();
 }
 
+void Element::setRegionOversetState(RegionOversetState state)
+{
+    ensureElementRareData()->setRegionOversetState(state);
+}
+
+RegionOversetState Element::regionOversetState() const
+{
+    return hasRareData() ? elementRareData()->regionOversetState() : RegionUndefined;
+}
+
 AtomicString Element::computeInheritedLanguage() const
 {
     const Node* n = this;
@@ -2790,20 +2800,20 @@ const AtomicString& Element::webkitRegionOverset() const
     if (!document()->cssRegionsEnabled() || !renderRegion())
         return undefinedState;
 
-    switch (renderRegion()->regionState()) {
-    case RenderRegion::RegionFit: {
+    switch (renderRegion()->regionOversetState()) {
+    case RegionFit: {
         DEFINE_STATIC_LOCAL(AtomicString, fitState, ("fit", AtomicString::ConstructFromLiteral));
         return fitState;
     }
-    case RenderRegion::RegionEmpty: {
+    case RegionEmpty: {
         DEFINE_STATIC_LOCAL(AtomicString, emptyState, ("empty", AtomicString::ConstructFromLiteral));
         return emptyState;
     }
-    case RenderRegion::RegionOverset: {
+    case RegionOverset: {
         DEFINE_STATIC_LOCAL(AtomicString, overflowState, ("overset", AtomicString::ConstructFromLiteral));
         return overflowState;
     }
-    case RenderRegion::RegionUndefined:
+    case RegionUndefined:
         return undefinedState;
     }
 
index 93b9677..da76f18 100644 (file)
@@ -29,6 +29,7 @@
 #include "CollectionType.h"
 #include "Document.h"
 #include "HTMLNames.h"
+#include "RegionOversetState.h"
 #include "ScrollTypes.h"
 #include "SpaceSplitString.h"
 
@@ -478,6 +479,9 @@ public:
     void setIsInCanvasSubtree(bool);
     bool isInCanvasSubtree() const;
 
+    void setRegionOversetState(RegionOversetState);
+    RegionOversetState regionOversetState() const;
+
     AtomicString computeInheritedLanguage() const;
     Locale& locale() const;
 
index bc82478..c49874b 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "config.h"
 #include "ElementRareData.h"
-
+#include "RegionOversetState.h"
 #include "RenderStyle.h"
 
 namespace WebCore {
@@ -38,6 +38,7 @@ namespace WebCore {
 struct SameSizeAsElementRareData : NodeRareData {
     short indices[2];
     unsigned bitfields;
+    RegionOversetState regionOversetState;
     LayoutSize sizeForResizing;
     IntSize scrollOffset;
     void* pointers[7];
index c80279e..9c58a2d 100644 (file)
@@ -60,6 +60,9 @@ public:
     bool isInCanvasSubtree() const { return m_isInCanvasSubtree; }
     void setIsInCanvasSubtree(bool value) { m_isInCanvasSubtree = value; }
 
+    RegionOversetState regionOversetState() const { return m_regionOversetState; }
+    void setRegionOversetState(RegionOversetState state) { m_regionOversetState = state; }
+
 #if ENABLE(FULLSCREEN_API)
     bool containsFullScreenElement() { return m_containsFullScreenElement; }
     void setContainsFullScreenElement(bool value) { m_containsFullScreenElement = value; }
@@ -156,6 +159,8 @@ private:
     unsigned m_childrenAffectedByForwardPositionalRules : 1;
     unsigned m_childrenAffectedByBackwardPositionalRules : 1;
 
+    RegionOversetState m_regionOversetState;
+
     LayoutSize m_minimumSizeForResizing;
     IntSize m_savedLayerScrollOffset;
     RefPtr<RenderStyle> m_computedStyle;
@@ -202,6 +207,7 @@ inline ElementRareData::ElementRareData(RenderObject* renderer)
     , m_childrenAffectedByDirectAdjacentRules(false)
     , m_childrenAffectedByForwardPositionalRules(false)
     , m_childrenAffectedByBackwardPositionalRules(false)
+    , m_regionOversetState(RegionUndefined)
     , m_minimumSizeForResizing(defaultMinimumSizeForResizing())
 {
 }
index 8064df2..c1d65ca 100644 (file)
@@ -246,6 +246,8 @@ namespace WebCore {
     \
     macro(webkitregionlayoutupdate) \
     \
+    macro(webkitregionoversetchange) \
+    \
     macro(webkitnetworkinfochange) \
     \
     macro(webkitresourcetimingbufferfull) \
index 59f0999..2709af7 100644 (file)
@@ -101,7 +101,7 @@ int WebKitNamedFlow::firstEmptyRegionIndex() const
     RenderRegionList::const_iterator iter = regionList.begin();
     for (int index = 0; iter != regionList.end(); ++index, ++iter) {
         const RenderRegion* renderRegion = *iter;
-        if (renderRegion->regionState() == RenderRegion::RegionEmpty)
+        if (renderRegion->regionOversetState() == RegionEmpty)
             return index;
     }
     return -1;
@@ -214,6 +214,19 @@ void WebKitNamedFlow::dispatchRegionLayoutUpdateEvent()
 
     dispatchEvent(event);
 }
+    
+void WebKitNamedFlow::dispatchRegionOversetChangeEvent()
+{
+    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
+    
+    // If the flow is in the "NULL" state the event should not be dispatched any more.
+    if (flowState() == FlowStateNull)
+        return;
+    
+    RefPtr<Event> event = UIEvent::create(eventNames().webkitregionoversetchangeEvent, false, false, m_flowManager->document()->defaultView(), 0);
+    
+    dispatchEvent(event);
+}
 
 const AtomicString& WebKitNamedFlow::interfaceName() const
 {
index c544a89..fff362a 100644 (file)
@@ -79,6 +79,7 @@ public:
     FlowState flowState() const { return m_parentFlowThread ? FlowStateCreated : FlowStateNull; }
 
     void dispatchRegionLayoutUpdateEvent();
+    void dispatchRegionOversetChangeEvent();
 
 private:
     WebKitNamedFlow(PassRefPtr<NamedFlowCollection>, const AtomicString&);
index 76b9027..4b77471 100644 (file)
@@ -1285,17 +1285,17 @@ PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::Region> > InspectorCSSAgent::bui
     for (unsigned i = 0; i < regionList->length(); ++i) {
         TypeBuilder::CSS::Region::RegionOverset::Enum regionOverset;
 
-        switch (toElement(regionList->item(i))->renderRegion()->regionState()) {
-        case RenderRegion::RegionFit:
+        switch (toElement(regionList->item(i))->renderRegion()->regionOversetState()) {
+        case RegionFit:
             regionOverset = TypeBuilder::CSS::Region::RegionOverset::Fit;
             break;
-        case RenderRegion::RegionEmpty:
+        case RegionEmpty:
             regionOverset = TypeBuilder::CSS::Region::RegionOverset::Empty;
             break;
-        case RenderRegion::RegionOverset:
+        case RegionOverset:
             regionOverset = TypeBuilder::CSS::Region::RegionOverset::Overset;
             break;
-        case RenderRegion::RegionUndefined:
+        case RegionUndefined:
             continue;
         default:
             ASSERT_NOT_REACHED();
diff --git a/Source/WebCore/rendering/RegionOversetState.h b/Source/WebCore/rendering/RegionOversetState.h
new file mode 100644 (file)
index 0000000..e29e370
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RegionOversetState_h
+#define RegionOversetState_h
+
+namespace WebCore {
+
+enum RegionOversetState {
+    RegionUndefined,
+    RegionEmpty,
+    RegionFit,
+    RegionOverset
+};
+
+} // namespace WebCore
+
+#endif // RegionOversetState_h
index 9d6a0d9..6e01401 100644 (file)
@@ -1816,7 +1816,7 @@ void RenderBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeF
     addVisualOverflowFromTheme();
 
     if (isRenderFlowThread())
-        toRenderFlowThread(this)->computeOverflowStateForRegions(oldClientAfterEdge);
+        toRenderFlowThread(this)->computeOversetStateForRegions(oldClientAfterEdge);
 }
 
 void RenderBlock::clearLayoutOverflow()
index 70208f6..8d34e5b 100644 (file)
@@ -50,6 +50,7 @@ namespace WebCore {
 
 RenderFlowThread::RenderFlowThread()
     : RenderBlock(0)
+    , m_previousRegionCount(0)
     , m_autoLogicalHeightRegionsCount(0)
     , m_regionsInvalidated(false)
     , m_regionsHaveUniformLogicalWidth(true)
@@ -57,6 +58,7 @@ RenderFlowThread::RenderFlowThread()
     , m_overset(true)
     , m_hasRegionsWithStyling(false)
     , m_dispatchRegionLayoutUpdateEvent(false)
+    , m_dispatchRegionOversetChangeEvent(false)
     , m_pageLogicalSizeChanged(false)
     , m_inConstrainedLayoutPhase(false)
     , m_needsTwoPhasesLayout(false)
@@ -219,6 +221,9 @@ void RenderFlowThread::layout()
 
     if (shouldDispatchRegionLayoutUpdateEvent())
         dispatchRegionLayoutUpdateEvent();
+    
+    if (shouldDispatchRegionOversetChangeEvent())
+        dispatchRegionOversetChangeEvent();
 }
 
 void RenderFlowThread::updateLogicalWidth()
@@ -735,7 +740,7 @@ void RenderFlowThread::applyBreakAfterContent(LayoutUnit clientHeight)
     addForcedRegionBreak(clientHeight, this, false);
 }
 
-void RenderFlowThread::computeOverflowStateForRegions(LayoutUnit oldClientAfterEdge)
+void RenderFlowThread::computeOversetStateForRegions(LayoutUnit oldClientAfterEdge)
 {
     LayoutUnit height = oldClientAfterEdge;
 
@@ -753,25 +758,34 @@ void RenderFlowThread::computeOverflowStateForRegions(LayoutUnit oldClientAfterE
         RenderRegion* region = *iter;
         LayoutUnit flowMin = height - (isHorizontalWritingMode() ? region->flowThreadPortionRect().y() : region->flowThreadPortionRect().x());
         LayoutUnit flowMax = height - (isHorizontalWritingMode() ? region->flowThreadPortionRect().maxY() : region->flowThreadPortionRect().maxX());
-        RenderRegion::RegionState previousState = region->regionState();
-        RenderRegion::RegionState state = RenderRegion::RegionFit;
+        RegionOversetState previousState = region->regionOversetState();
+        RegionOversetState state = RegionFit;
         if (flowMin <= 0)
-            state = RenderRegion::RegionEmpty;
+            state = RegionEmpty;
         if (flowMax > 0 && region == lastReg)
-            state = RenderRegion::RegionOverset;
-        region->setRegionState(state);
+            state = RegionOverset;
+        region->setRegionOversetState(state);
         // determine whether the NamedFlow object should dispatch a regionLayoutUpdate event
         // FIXME: currently it cannot determine whether a region whose regionOverset state remained either "fit" or "overset" has actually
         // changed, so it just assumes that the NamedFlow should dispatch the event
         if (previousState != state
-            || state == RenderRegion::RegionFit
-            || state == RenderRegion::RegionOverset)
+            || state == RegionFit
+            || state == RegionOverset)
             setDispatchRegionLayoutUpdateEvent(true);
+        
+        if (previousState != state)
+            setDispatchRegionOversetChangeEvent(true);
+    }
+    
+    // If the number of regions has changed since we last computed the overset property, schedule the regionOversetChange event.
+    if (previousRegionCountChanged()) {
+        setDispatchRegionOversetChangeEvent(true);
+        updatePreviousRegionCount();
     }
 
     // With the regions overflow state computed we can also set the overset flag for the named flow.
     // If there are no valid regions in the chain, overset is true.
-    m_overset = lastReg ? lastReg->regionState() == RenderRegion::RegionOverset : true;
+    m_overset = lastReg ? lastReg->regionOversetState() == RegionOverset : true;
 }
 
 bool RenderFlowThread::regionInRange(const RenderRegion* targetRegion, const RenderRegion* startRegion, const RenderRegion* endRegion) const
index 13bd726..f91764d 100644 (file)
@@ -127,6 +127,9 @@ public:
     RenderRegion* firstRegion() const;
     RenderRegion* lastRegion() const;
 
+    bool previousRegionCountChanged() const { return m_previousRegionCount != m_regionList.size(); };
+    void updatePreviousRegionCount() { m_previousRegionCount = m_regionList.size(); };
+
     void setRegionRangeForBox(const RenderBox*, LayoutUnit offsetFromLogicalTopOfFirstPage);
     void getRegionRangeForBox(const RenderBox*, RenderRegion*& startRegion, RenderRegion*& endRegion) const;
 
@@ -134,7 +137,7 @@ public:
         const RenderRegion* oldStartRegion = 0, const RenderRegion* oldEndRegion = 0,
         const RenderRegion* newStartRegion = 0, const RenderRegion* newEndRegion = 0);
     
-    void computeOverflowStateForRegions(LayoutUnit oldClientAfterEdge);
+    void computeOversetStateForRegions(LayoutUnit oldClientAfterEdge);
 
     bool overset() const { return m_overset; }
 
@@ -187,8 +190,12 @@ protected:
     void setDispatchRegionLayoutUpdateEvent(bool value) { m_dispatchRegionLayoutUpdateEvent = value; }
     bool shouldDispatchRegionLayoutUpdateEvent() { return m_dispatchRegionLayoutUpdateEvent; }
     
+    void setDispatchRegionOversetChangeEvent(bool value) { m_dispatchRegionOversetChangeEvent = value; }
+    bool shouldDispatchRegionOversetChangeEvent() const { return m_dispatchRegionOversetChangeEvent; }
+    
     // Override if the flow thread implementation supports dispatching events when the flow layout is updated (e.g. for named flows)
     virtual void dispatchRegionLayoutUpdateEvent() { m_dispatchRegionLayoutUpdateEvent = false; }
+    virtual void dispatchRegionOversetChangeEvent() { m_dispatchRegionOversetChangeEvent = false; }
 
     void initializeRegionsOverrideLogicalContentHeight(RenderRegion* = 0);
 
@@ -202,6 +209,7 @@ protected:
     inline const RenderBox* currentActiveRenderBox() const;
 
     RenderRegionList m_regionList;
+    unsigned short m_previousRegionCount;
 
     class RenderRegionRange {
     public:
@@ -274,6 +282,7 @@ protected:
     bool m_overset : 1;
     bool m_hasRegionsWithStyling : 1;
     bool m_dispatchRegionLayoutUpdateEvent : 1;
+    bool m_dispatchRegionOversetChangeEvent : 1;
     bool m_pageLogicalSizeChanged : 1;
     bool m_inConstrainedLayoutPhase : 1;
     bool m_needsTwoPhasesLayout : 1;
index 152cdf8..1fcd3b8 100644 (file)
@@ -54,6 +54,7 @@ RenderNamedFlowThread* RenderNamedFlowThread::createAnonymous(Document* document
 RenderNamedFlowThread::RenderNamedFlowThread(PassRefPtr<WebKitNamedFlow> namedFlow)
     : m_namedFlow(namedFlow)
     , m_regionLayoutUpdateEventTimer(this, &RenderNamedFlowThread::regionLayoutUpdateEventTimerFired)
+    , m_regionOversetChangeEventTimer(this, &RenderNamedFlowThread::regionOversetChangeEventTimerFired)
 {
 }
 
@@ -427,6 +428,14 @@ void RenderNamedFlowThread::dispatchRegionLayoutUpdateEvent()
         m_regionLayoutUpdateEventTimer.startOneShot(0);
 }
 
+void RenderNamedFlowThread::dispatchRegionOversetChangeEvent()
+{
+    RenderFlowThread::dispatchRegionOversetChangeEvent();
+    
+    if (!m_regionOversetChangeEventTimer.isActive() && m_namedFlow->hasEventListeners())
+        m_regionOversetChangeEventTimer.startOneShot(0);
+}
+
 void RenderNamedFlowThread::regionLayoutUpdateEventTimerFired(Timer<RenderNamedFlowThread>*)
 {
     ASSERT(m_namedFlow);
@@ -434,6 +443,13 @@ void RenderNamedFlowThread::regionLayoutUpdateEventTimerFired(Timer<RenderNamedF
     m_namedFlow->dispatchRegionLayoutUpdateEvent();
 }
 
+void RenderNamedFlowThread::regionOversetChangeEventTimerFired(Timer<RenderNamedFlowThread>*)
+{
+    ASSERT(m_namedFlow);
+    
+    m_namedFlow->dispatchRegionOversetChangeEvent();
+}
+
 void RenderNamedFlowThread::setMarkForDestruction()
 {
     if (m_namedFlow->flowState() == WebKitNamedFlow::FlowStateNull)
index 3d3a766..1502bd6 100644 (file)
@@ -87,6 +87,7 @@ private:
     virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
 
     virtual void dispatchRegionLayoutUpdateEvent() OVERRIDE;
+    virtual void dispatchRegionOversetChangeEvent() OVERRIDE;
 
     bool dependsOn(RenderNamedFlowThread* otherRenderFlowThread) const;
     void addDependencyOnFlowThread(RenderNamedFlowThread*);
@@ -98,6 +99,7 @@ private:
 
     bool canBeDestroyed() const { return m_invalidRegionList.isEmpty() && m_regionList.isEmpty() && m_contentNodes.isEmpty(); }
     void regionLayoutUpdateEventTimerFired(Timer<RenderNamedFlowThread>*);
+    void regionOversetChangeEventTimerFired(Timer<RenderNamedFlowThread>*);
     void clearContentNodes();
 
 private:
@@ -123,6 +125,7 @@ private:
     RefPtr<WebKitNamedFlow> m_namedFlow;
 
     Timer<RenderNamedFlowThread> m_regionLayoutUpdateEventTimer;
+    Timer<RenderNamedFlowThread> m_regionOversetChangeEventTimer;
 };
 
 inline RenderNamedFlowThread* toRenderNamedFlowThread(RenderObject* object)
index 8e93945..40d269e 100644 (file)
@@ -54,7 +54,6 @@ RenderRegion::RenderRegion(Element* element, RenderFlowThread* flowThread)
     , m_isValid(false)
     , m_hasCustomRegionStyle(false)
     , m_hasAutoLogicalHeight(false)
-    , m_regionState(RegionUndefined)
 {
 }
 
@@ -132,6 +131,20 @@ LayoutRect RenderRegion::overflowRectForFlowThreadPortion(const LayoutRect& flow
     return clipRect;
 }
 
+RegionOversetState RenderRegion::regionOversetState() const
+{
+    if (isValid() && node() && node()->isElementNode())
+        return toElement(node())->regionOversetState();
+    
+    return RegionUndefined;
+}
+
+void RenderRegion::setRegionOversetState(RegionOversetState state)
+{
+    if (node() && node()->isElementNode())
+        toElement(node())->setRegionOversetState(state);
+}
+
 LayoutUnit RenderRegion::pageLogicalTopForOffset(LayoutUnit /* offset */) const
 {
     return flowThread()->isHorizontalWritingMode() ? flowThreadPortionRect().y() : flowThreadPortionRect().x();
index 44f8018..f8cb8a3 100644 (file)
@@ -82,15 +82,8 @@ public:
 
     void clearObjectStyleInRegion(const RenderObject*);
 
-    enum RegionState {
-        RegionUndefined,
-        RegionEmpty,
-        RegionFit,
-        RegionOverset
-    };
-
-    RegionState regionState() const { return isValid() ? m_regionState : RegionUndefined; }
-    void setRegionState(RegionState regionState) { m_regionState = regionState; }
+    RegionOversetState regionOversetState() const;
+    void setRegionOversetState(RegionOversetState);
     
     // These methods represent the width and height of a "page" and for a RenderRegion they are just the
     // content width and content height of a region. For RenderRegionSets, however, they will be the width and
@@ -200,7 +193,6 @@ private:
     bool m_isValid : 1;
     bool m_hasCustomRegionStyle : 1;
     bool m_hasAutoLogicalHeight : 1;
-    RegionState m_regionState;
 };
 
 inline RenderRegion* toRenderRegion(RenderObject* object)