[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-10851-g50815da

yael.aharon at nokia.com yael.aharon at nokia.com
Wed Dec 22 18:07:24 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit f1b5ab4e6d04ed6275551e46b0409f3e703feca7
Author: yael.aharon at nokia.com <yael.aharon at nokia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Dec 7 19:04:10 2010 +0000

    Spatial navigation not Working for Map and Area Tags
    https://bugs.webkit.org/show_bug.cgi?id=47142
    
    Reviewed by Antonio Gomes.
    
    WebCore:
    
    Give area elements special treatment in spatial navigation algorithm by getting the
    rect of the area from the associated image. Since area elements are likely to overlap
    if they are not rects, or if authors are not careful, we flatten the rect of area elements.
    
    Tests: fast/spatial-navigation/snav-imagemap-area-not-focusable.html
           fast/spatial-navigation/snav-imagemap-area-without-image.html
           fast/spatial-navigation/snav-imagemap-overlapped-areas.html
           fast/spatial-navigation/snav-imagemap-simple.html
    
    * page/FocusController.cpp:
    (WebCore::FocusController::findFocusCandidateInContainer):
    (WebCore::FocusController::advanceFocusDirectionallyInContainer):
    (WebCore::FocusController::advanceFocusDirectionally):
    * page/SpatialNavigation.cpp:
    (WebCore::FocusCandidate::FocusCandidate):
    (WebCore::virtualRectForDirection):
    (WebCore::virtualRectForAreaElementAndDirection):
    * page/SpatialNavigation.h:
    (WebCore::FocusCandidate::FocusCandidate):
    
    LayoutTests:
    
    * fast/spatial-navigation/snav-imagemap-area-not-focusable-expected.txt: Added.
    * fast/spatial-navigation/snav-imagemap-area-not-focusable.html: Added.
    * fast/spatial-navigation/snav-imagemap-area-without-image-expected.txt: Added.
    * fast/spatial-navigation/snav-imagemap-area-without-image.html: Added.
    * fast/spatial-navigation/snav-imagemap-overlapped-areas-expected.txt: Added.
    * fast/spatial-navigation/snav-imagemap-overlapped-areas.html: Added.
    * fast/spatial-navigation/snav-imagemap-simple-expected.txt: Added.
    * fast/spatial-navigation/snav-imagemap-simple.html: Added.
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@73452 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index fe65cad..ab20c87 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,19 @@
+2010-12-07  Yael Aharon  <yael.aharon at nokia.com>
+
+        Reviewed by Antonio Gomes.
+
+        Spatial navigation not Working for Map and Area Tags
+        https://bugs.webkit.org/show_bug.cgi?id=47142
+
+        * fast/spatial-navigation/snav-imagemap-area-not-focusable-expected.txt: Added.
+        * fast/spatial-navigation/snav-imagemap-area-not-focusable.html: Added.
+        * fast/spatial-navigation/snav-imagemap-area-without-image-expected.txt: Added.
+        * fast/spatial-navigation/snav-imagemap-area-without-image.html: Added.
+        * fast/spatial-navigation/snav-imagemap-overlapped-areas-expected.txt: Added.
+        * fast/spatial-navigation/snav-imagemap-overlapped-areas.html: Added.
+        * fast/spatial-navigation/snav-imagemap-simple-expected.txt: Added.
+        * fast/spatial-navigation/snav-imagemap-simple.html: Added.
+
 2010-12-07  Yury Semikhatsky  <yurys at chromium.org>
 
         Reviewed by Pavel Feldman.
diff --git a/LayoutTests/fast/spatial-navigation/snav-imagemap-area-not-focusable-expected.txt b/LayoutTests/fast/spatial-navigation/snav-imagemap-area-not-focusable-expected.txt
new file mode 100644
index 0000000..708f3d3
--- /dev/null
+++ b/LayoutTests/fast/spatial-navigation/snav-imagemap-area-not-focusable-expected.txt
@@ -0,0 +1,8 @@
+ 
+
+
+PASS gFocusedDocument.activeElement.getAttribute("id") is "1"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "3"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "1"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+This test tests that areas of an imagemap without an href are not focusable, thus can not be reached with spatial navigation.
diff --git a/LayoutTests/fast/spatial-navigation/snav-imagemap-area-not-focusable.html b/LayoutTests/fast/spatial-navigation/snav-imagemap-area-not-focusable.html
new file mode 100644
index 0000000..846fd89
--- /dev/null
+++ b/LayoutTests/fast/spatial-navigation/snav-imagemap-area-not-focusable.html
@@ -0,0 +1,58 @@
+<html>
+  <head>
+
+    <script src="../js/resources/js-test-pre.js"></script>
+    <script src="resources/spatial-navigation-utils.js"></script>
+    <script type="application/javascript">
+
+    var resultMap = [
+      ["Down", "1"],
+      ["Down", "3"],
+      ["Up", "1"],
+      ["Up", "start"],
+      ["DONE", "DONE"]
+    ];
+
+    if (window.layoutTestController) {
+      layoutTestController.dumpAsText();
+      layoutTestController.setSpatialNavigationEnabled(true);
+      layoutTestController.overridePreference("WebKitTabToLinksPreferenceKey", 1);
+      layoutTestController.waitUntilDone();
+    }
+
+    function runTest()
+    {
+      // starting the test itself: get to a known place.
+      document.getElementById("start").focus();
+
+      initTest(resultMap, testCompleted);
+    }
+
+    function testCompleted()
+    {
+      if (window.layoutTestController)
+        layoutTestController.notifyDone();
+    }
+
+    window.onload = runTest;
+
+    </script>
+    <script src="js/resources/js-test-post.js"></script>
+  </head>
+
+  <body id="some-content" xmlns="http://www.w3.org/1999/xhtml">
+  <map name="map" title="map" id="firstmap">
+    <area shape="rect" coords="20,20,70,70" href="#" id="1">
+    <area shape="rect" coords="20,130,70,180" id="2">
+  </map>
+
+    <a id="start" href="a"><img src="resources/green.png" width=50px height=50px></a>
+    <div>
+      <img src="resources/green.png" width=200px height=200px usemap="#map"><a id="6" href="a"><img src="resources/green.png" width=50px height=50px></a>
+    </div>
+    <a id="3" href="a"><img src="resources/green.png" width=50px height=50px></a>
+    <div id="console"></div>
+    <div>This test tests that areas of an imagemap without an href are not focusable, thus can not be reached with spatial navigation.</div>
+  </body>
+</html>
+
diff --git a/LayoutTests/fast/spatial-navigation/snav-imagemap-area-without-image-expected.txt b/LayoutTests/fast/spatial-navigation/snav-imagemap-area-without-image-expected.txt
new file mode 100644
index 0000000..254a96a
--- /dev/null
+++ b/LayoutTests/fast/spatial-navigation/snav-imagemap-area-without-image-expected.txt
@@ -0,0 +1,6 @@
+ 
+
+
+PASS gFocusedDocument.activeElement.getAttribute("id") is "3"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+This test tests that areas of an imagemap without an image using it, are not focusable, thus can not be reached with spatial navigation.
diff --git a/LayoutTests/fast/spatial-navigation/snav-imagemap-area-without-image.html b/LayoutTests/fast/spatial-navigation/snav-imagemap-area-without-image.html
new file mode 100644
index 0000000..423ef34
--- /dev/null
+++ b/LayoutTests/fast/spatial-navigation/snav-imagemap-area-without-image.html
@@ -0,0 +1,56 @@
+<html>
+  <head>
+
+    <script src="../js/resources/js-test-pre.js"></script>
+    <script src="resources/spatial-navigation-utils.js"></script>
+    <script type="application/javascript">
+
+    var resultMap = [
+      ["Down", "3"],
+      ["Up", "start"],
+      ["DONE", "DONE"]
+    ];
+
+    if (window.layoutTestController) {
+      layoutTestController.dumpAsText();
+      layoutTestController.setSpatialNavigationEnabled(true);
+      layoutTestController.overridePreference("WebKitTabToLinksPreferenceKey", 1);
+      layoutTestController.waitUntilDone();
+    }
+
+    function runTest()
+    {
+      // starting the test itself: get to a known place.
+      document.getElementById("start").focus();
+
+      initTest(resultMap, testCompleted);
+    }
+
+    function testCompleted()
+    {
+      if (window.layoutTestController)
+        layoutTestController.notifyDone();
+    }
+
+    window.onload = runTest;
+
+    </script>
+    <script src="js/resources/js-test-post.js"></script>
+  </head>
+
+  <body id="some-content" xmlns="http://www.w3.org/1999/xhtml">
+  <map name="map" title="map" id="firstmap">
+    <area shape="rect" coords="20,20,70,70" href="#" id="1">
+    <area shape="rect" coords="20,130,70,180" href="#" id="2">
+  </map>
+
+    <a id="start" href="a"><img src="resources/green.png" width=50px height=50px></a>
+    <div>
+      <img src="resources/green.png" width=200px height=200px usemap="#othermap"><a id="6" href="a"><img src="resources/green.png" width=50px height=50px></a>
+    </div>
+    <a id="3" href="a"><img src="resources/green.png" width=50px height=50px></a>
+    <div id="console"></div>
+    <div>This test tests that areas of an imagemap without an image using it, are not focusable, thus can not be reached with spatial navigation.</div>
+  </body>
+</html>
+
diff --git a/LayoutTests/fast/spatial-navigation/snav-imagemap-overlapped-areas-expected.txt b/LayoutTests/fast/spatial-navigation/snav-imagemap-overlapped-areas-expected.txt
new file mode 100644
index 0000000..bb3b35d
--- /dev/null
+++ b/LayoutTests/fast/spatial-navigation/snav-imagemap-overlapped-areas-expected.txt
@@ -0,0 +1,16 @@
+ 
+
+
+PASS gFocusedDocument.activeElement.getAttribute("id") is "4"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "1"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "2"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "5"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "4"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "3"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "2"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "1"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "3"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "2"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "1"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+This test tests that areas of an imagemap can be reached with spatial navigation even if they are overlapped.
diff --git a/LayoutTests/fast/spatial-navigation/snav-imagemap-overlapped-areas.html b/LayoutTests/fast/spatial-navigation/snav-imagemap-overlapped-areas.html
new file mode 100644
index 0000000..5eb2ad4
--- /dev/null
+++ b/LayoutTests/fast/spatial-navigation/snav-imagemap-overlapped-areas.html
@@ -0,0 +1,68 @@
+<html>
+  <head>
+
+    <script src="../js/resources/js-test-pre.js"></script>
+    <script src="resources/spatial-navigation-utils.js"></script>
+    <script type="application/javascript">
+
+    var resultMap = [
+      ["Down", "4"],
+      ["Down", "1"],
+      ["Down", "2"],
+      ["Down", "5"],
+      ["Up", "4"],
+      ["Up", "3"],
+      ["Up", "2"],
+      ["Left", "1"],
+      ["Right", "3"],
+      ["Left", "2"],
+      ["Up", "1"],
+      ["Up", "start"],
+      ["DONE", "DONE"]
+    ];
+
+    if (window.layoutTestController) {
+      layoutTestController.dumpAsText();
+      layoutTestController.setSpatialNavigationEnabled(true);
+      layoutTestController.overridePreference("WebKitTabToLinksPreferenceKey", 1);
+      layoutTestController.waitUntilDone();
+    }
+
+    function runTest()
+    {
+      // starting the test itself: get to a known place.
+      document.getElementById("start").focus();
+
+      initTest(resultMap, testCompleted);
+    }
+
+    function testCompleted()
+    {
+      if (window.layoutTestController)
+        layoutTestController.notifyDone();
+    }
+
+    window.onload = runTest;
+
+    </script>
+    <script src="js/resources/js-test-post.js"></script>
+  </head>
+
+  <body id="some-content" xmlns="http://www.w3.org/1999/xhtml">
+  <map name="map" title="map" id="firstmap">
+    <area shape="circle" coords="45,45,25" href="#" id="1">
+    <area shape="rect" coords="45,60,95,110" href="#" id="2">
+    <area shape="poly" coords="80,20,130,20,130,180,30,180,30,130,80,130" href="#" id="3">
+    <area shape="default" href="#" id="4">
+  </map>
+
+    <a id="start" href="a"><img src="resources/green.png" width=50px height=50px></a>
+    <div>
+      <img src="resources/green.png" width=200px height=200px usemap="#map">
+    </div>
+    <a id="5" href="a"><img src="resources/green.png" width=50px height=50px></a>
+    <div id="console"></div>
+    <div>This test tests that areas of an imagemap can be reached with spatial navigation even if they are overlapped.</div>
+  </body>
+</html>
+
diff --git a/LayoutTests/fast/spatial-navigation/snav-imagemap-simple-expected.txt b/LayoutTests/fast/spatial-navigation/snav-imagemap-simple-expected.txt
new file mode 100644
index 0000000..22aae88
--- /dev/null
+++ b/LayoutTests/fast/spatial-navigation/snav-imagemap-simple-expected.txt
@@ -0,0 +1,14 @@
+ 
+
+
+PASS gFocusedDocument.activeElement.getAttribute("id") is "1"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "3"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "5"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "3"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "4"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "6"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "4"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "2"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "1"
+PASS gFocusedDocument.activeElement.getAttribute("id") is "start"
+This test tests that areas of an imagemap can be reached with spatial navigation.
diff --git a/LayoutTests/fast/spatial-navigation/snav-imagemap-simple.html b/LayoutTests/fast/spatial-navigation/snav-imagemap-simple.html
new file mode 100644
index 0000000..f1d1e8a
--- /dev/null
+++ b/LayoutTests/fast/spatial-navigation/snav-imagemap-simple.html
@@ -0,0 +1,66 @@
+<html>
+  <head>
+
+    <script src="../js/resources/js-test-pre.js"></script>
+    <script src="resources/spatial-navigation-utils.js"></script>
+    <script type="application/javascript">
+
+    var resultMap = [
+      ["Down", "1"],
+      ["Down", "3"],
+      ["Down", "5"],
+      ["Up", "3"],
+      ["Right", "4"],
+      ["Right", "6"],
+      ["Left", "4"],
+      ["Up", "2"],
+      ["Left", "1"],
+      ["Up", "start"],
+      ["DONE", "DONE"]
+    ];
+
+    if (window.layoutTestController) {
+      layoutTestController.dumpAsText();
+      layoutTestController.setSpatialNavigationEnabled(true);
+      layoutTestController.overridePreference("WebKitTabToLinksPreferenceKey", 1);
+      layoutTestController.waitUntilDone();
+    }
+
+    function runTest()
+    {
+      // starting the test itself: get to a known place.
+      document.getElementById("start").focus();
+
+      initTest(resultMap, testCompleted);
+    }
+
+    function testCompleted()
+    {
+      if (window.layoutTestController)
+        layoutTestController.notifyDone();
+    }
+
+    window.onload = runTest;
+
+    </script>
+    <script src="js/resources/js-test-post.js"></script>
+  </head>
+
+  <body id="some-content" xmlns="http://www.w3.org/1999/xhtml">
+  <map name="map" title="map" id="firstmap">
+    <area shape="rect" coords="20,20,70,70" href="#" id="1">
+    <area shape="rect" coords="130,20,180,70" href="#" id="2">
+    <area shape="rect" coords="20,130,70,180" href="#" id="3">
+    <area shape="rect" coords="130,130,180,180" href="#" id="4">
+  </map>
+
+    <a id="start" href="a"><img src="resources/green.png" width=50px height=50px></a>
+    <div>
+      <img src="resources/green.png" width=200px height=200px usemap="#map"><a id="6" href="a"><img src="resources/green.png" width=50px height=50px></a>
+    </div>
+    <a id="5" href="a"><img src="resources/green.png" width=50px height=50px></a>
+    <div id="console"></div>
+    <div>This test tests that areas of an imagemap can be reached with spatial navigation.</div>
+  </body>
+</html>
+
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 3b5ee2c..3a2feb8 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,30 @@
+2010-12-07  Yael Aharon  <yael.aharon at nokia.com>
+
+        Reviewed by Antonio Gomes.
+
+        Spatial navigation not Working for Map and Area Tags
+        https://bugs.webkit.org/show_bug.cgi?id=47142
+
+        Give area elements special treatment in spatial navigation algorithm by getting the
+        rect of the area from the associated image. Since area elements are likely to overlap
+        if they are not rects, or if authors are not careful, we flatten the rect of area elements.
+
+        Tests: fast/spatial-navigation/snav-imagemap-area-not-focusable.html
+               fast/spatial-navigation/snav-imagemap-area-without-image.html
+               fast/spatial-navigation/snav-imagemap-overlapped-areas.html
+               fast/spatial-navigation/snav-imagemap-simple.html
+
+        * page/FocusController.cpp:
+        (WebCore::FocusController::findFocusCandidateInContainer):
+        (WebCore::FocusController::advanceFocusDirectionallyInContainer):
+        (WebCore::FocusController::advanceFocusDirectionally):
+        * page/SpatialNavigation.cpp:
+        (WebCore::FocusCandidate::FocusCandidate):
+        (WebCore::virtualRectForDirection):
+        (WebCore::virtualRectForAreaElementAndDirection):
+        * page/SpatialNavigation.h:
+        (WebCore::FocusCandidate::FocusCandidate):
+
 2010-12-07  Darin Adler  <darin at apple.com>
 
         Try to fix V8 build.
diff --git a/WebCore/page/FocusController.cpp b/WebCore/page/FocusController.cpp
index 5418c89..55009a6 100644
--- a/WebCore/page/FocusController.cpp
+++ b/WebCore/page/FocusController.cpp
@@ -40,9 +40,11 @@
 #include "Frame.h"
 #include "FrameTree.h"
 #include "FrameView.h"
-#include "HitTestResult.h"
+#include "HTMLAreaElement.h"
 #include "HTMLFrameOwnerElement.h"
+#include "HTMLImageElement.h"
 #include "HTMLNames.h"
+#include "HitTestResult.h"
 #include "KeyboardEvent.h"
 #include "Page.h"
 #include "Range.h"
@@ -414,11 +416,11 @@ void FocusController::setActive(bool active)
 
 void updateFocusCandidateIfNeeded(FocusDirection direction, const IntRect& startingRect, FocusCandidate& candidate, FocusCandidate& closest)
 {
-    if (!candidate.node->isElementNode() || !candidate.node->renderer())
+    if (!candidate.visibleNode->isElementNode() || !candidate.visibleNode->renderer())
         return;
 
     // Ignore iframes that don't have a src attribute
-    if (candidate.node->isFrameOwnerElement() && !static_cast<HTMLFrameOwnerElement*>(candidate.node)->contentFrame())
+    if (candidate.visibleNode->isFrameOwnerElement() && !static_cast<HTMLFrameOwnerElement*>(candidate.visibleNode)->contentFrame())
         return;
 
     // Ignore off screen child nodes of containers that do not scroll (overflow:hidden)
@@ -444,12 +446,12 @@ void updateFocusCandidateIfNeeded(FocusDirection direction, const IntRect& start
         // If 2 nodes are intersecting, do hit test to find which node in on top.
         int x = intersectionRect.x() + intersectionRect.width() / 2;
         int y = intersectionRect.y() + intersectionRect.height() / 2;
-        HitTestResult result = candidate.node->document()->page()->mainFrame()->eventHandler()->hitTestResultAtPoint(IntPoint(x, y), false, true);
-        if (candidate.node->contains(result.innerNode())) {
+        HitTestResult result = candidate.visibleNode->document()->page()->mainFrame()->eventHandler()->hitTestResultAtPoint(IntPoint(x, y), false, true);
+        if (candidate.visibleNode->contains(result.innerNode())) {
             closest = candidate;
             return;
         }
-        if (closest.node->contains(result.innerNode()))
+        if (closest.visibleNode->contains(result.innerNode()))
             return;
     }
 
@@ -473,10 +475,21 @@ void FocusController::findFocusCandidateInContainer(Node* container, const IntRe
         if (node == focusedNode)
             continue;
 
-        if (!node->renderer())
+        if (!node->isKeyboardFocusable(event) && !node->isFrameOwnerElement() && !canScrollInDirection(direction, node))
             continue;
 
-        if (!node->isKeyboardFocusable(event) && !node->isFrameOwnerElement() && !canScrollInDirection(direction, node))
+        if (node->hasTagName(areaTag)) {
+            HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node);
+            FocusCandidate candidate(area, direction);
+            if (candidate.isNull())
+                continue;
+
+            candidate.enclosingScrollableBox = container;
+            updateFocusCandidateIfNeeded(direction, startingRect, candidate, closest);
+            continue;
+        }
+
+        if (!node->renderer())
             continue;
 
         FocusCandidate candidate(node, direction);
@@ -508,15 +521,15 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons
         // Return false will cause a re-try, skipping this container.
         return false;
     }
-    if (focusCandidate.node->isFrameOwnerElement()) {
-        HTMLFrameOwnerElement* frameElement = static_cast<HTMLFrameOwnerElement*>(focusCandidate.node);
+    if (focusCandidate.visibleNode->isFrameOwnerElement()) {
+        HTMLFrameOwnerElement* frameElement = static_cast<HTMLFrameOwnerElement*>(focusCandidate.visibleNode);
         // If we have an iframe without the src attribute, it will not have a contentFrame().
         // We ASSERT here to make sure that
         // updateFocusCandidateIfNeeded() will never consider such an iframe as a candidate.
         ASSERT(frameElement->contentFrame());
 
         if (focusCandidate.isOffscreenAfterScrolling) {
-            scrollInDirection(focusCandidate.node->document(), direction);
+            scrollInDirection(focusCandidate.visibleNode->document(), direction);
             return true;
         }
         // Navigate into a new frame.
@@ -527,13 +540,13 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons
         frameElement->contentFrame()->document()->updateLayoutIgnorePendingStylesheets();
         if (!advanceFocusDirectionallyInContainer(frameElement->contentFrame()->document(), rect, direction, event)) {
             // The new frame had nothing interesting, need to find another candidate.
-            return advanceFocusDirectionallyInContainer(container, nodeRectInAbsoluteCoordinates(focusCandidate.node, true), direction, event);
+            return advanceFocusDirectionallyInContainer(container, nodeRectInAbsoluteCoordinates(focusCandidate.visibleNode, true), direction, event);
         }
         return true;
     }
-    if (canScrollInDirection(direction, focusCandidate.node)) {
+    if (canScrollInDirection(direction, focusCandidate.visibleNode)) {
         if (focusCandidate.isOffscreenAfterScrolling) {
-            scrollInDirection(focusCandidate.node, direction);
+            scrollInDirection(focusCandidate.visibleNode, direction);
             return true;
         }
         // Navigate into a new scrollable container.
@@ -541,7 +554,7 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons
         Node* focusedNode = focusedOrMainFrame()->document()->focusedNode();
         if (focusedNode && !hasOffscreenRect(focusedNode))
             startingRect = nodeRectInAbsoluteCoordinates(focusedNode, true);
-        return advanceFocusDirectionallyInContainer(focusCandidate.node, startingRect, direction, event);
+        return advanceFocusDirectionallyInContainer(focusCandidate.visibleNode, startingRect, direction, event);
     }
     if (focusCandidate.isOffscreenAfterScrolling) {
         Node* container = focusCandidate.enclosingScrollableBox;
@@ -550,7 +563,7 @@ bool FocusController::advanceFocusDirectionallyInContainer(Node* container, cons
     }
 
     // We found a new focus node, navigate to it.
-    Element* element = toElement(focusCandidate.node);
+    Element* element = toElement(focusCandidate.focusableNode);
     ASSERT(element);
 
     element->focus(false);
@@ -571,9 +584,15 @@ bool FocusController::advanceFocusDirectionally(FocusDirection direction, Keyboa
 
     // Figure out the starting rect.
     IntRect startingRect;
-    if (focusedNode && !hasOffscreenRect(focusedNode)) {
-        container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, focusedNode);
-        startingRect = nodeRectInAbsoluteCoordinates(focusedNode, true /* ignore border */);
+    if (focusedNode) {
+        if (!hasOffscreenRect(focusedNode)) {
+            container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, focusedNode);
+            startingRect = nodeRectInAbsoluteCoordinates(focusedNode, true /* ignore border */);
+        } else if (focusedNode->hasTagName(areaTag)) {
+            HTMLAreaElement* area = static_cast<HTMLAreaElement*>(focusedNode);
+            container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, area->imageElement());
+            startingRect = virtualRectForAreaElementAndDirection(direction, area);
+        }
     }
 
     bool consumed = false;
diff --git a/WebCore/page/SpatialNavigation.cpp b/WebCore/page/SpatialNavigation.cpp
index ffc65b4..1750500 100644
--- a/WebCore/page/SpatialNavigation.cpp
+++ b/WebCore/page/SpatialNavigation.cpp
@@ -32,7 +32,10 @@
 #include "Frame.h"
 #include "FrameTree.h"
 #include "FrameView.h"
+#include "HTMLAreaElement.h"
 #include "HTMLFrameOwnerElement.h"
+#include "HTMLImageElement.h"
+#include "HTMLMapElement.h"
 #include "IntRect.h"
 #include "Node.h"
 #include "Page.h"
@@ -52,7 +55,8 @@ static void entryAndExitPointsForDirection(FocusDirection direction, const IntRe
 
 
 FocusCandidate::FocusCandidate(Node* n, FocusDirection direction)
-    : node(n)
+    : visibleNode(n)
+    , focusableNode(n)
     , enclosingScrollableBox(0)
     , distance(maxDistance())
     , parentDistance(maxDistance())
@@ -64,6 +68,28 @@ FocusCandidate::FocusCandidate(Node* n, FocusDirection direction)
 {
 }
 
+FocusCandidate::FocusCandidate(HTMLAreaElement* area, FocusDirection direction)
+    : visibleNode(0)
+    , focusableNode(0)
+    , enclosingScrollableBox(0)
+    , distance(maxDistance())
+    , parentDistance(maxDistance())
+    , alignment(None)
+    , parentAlignment(None)
+    , isOffscreen(true)
+    , isOffscreenAfterScrolling(true)
+{
+    HTMLImageElement* image = area->imageElement();
+    if (!image)
+        return;
+
+    focusableNode = area;
+    visibleNode = image;
+    rect = virtualRectForAreaElementAndDirection(direction, area);
+    isOffscreen = hasOffscreenRect(image);
+    isOffscreenAfterScrolling = hasOffscreenRect(image, direction);
+}
+
 bool isSpatialNavigationEnabled(const Frame* frame)
 {
     return (frame && frame->settings() && frame->settings()->isSpatialNavigationEnabled());
@@ -571,7 +597,7 @@ void distanceDataForNode(FocusDirection direction, FocusCandidate& current, Focu
 {
     if (candidate.isNull())
         return;
-    if (!candidate.node->renderer())
+    if (!candidate.visibleNode->renderer())
         return;
     IntRect nodeRect = candidate.rect;
     IntRect currentRect = current.rect;
@@ -618,15 +644,15 @@ void distanceDataForNode(FocusDirection direction, FocusCandidate& current, Focu
 
     float distance = euclidianDistance + sameAxisDistance + 2 * otherAxisDistance;
     candidate.distance = roundf(distance);
-    IntSize viewSize = candidate.node->document()->page()->mainFrame()->view()->visibleContentRect().size();
+    IntSize viewSize = candidate.visibleNode->document()->page()->mainFrame()->view()->visibleContentRect().size();
     candidate.alignment = alignmentForRects(direction, currentRect, nodeRect, viewSize);
 }
 
 bool canBeScrolledIntoView(FocusDirection direction, const FocusCandidate& candidate)
 {
-    ASSERT(candidate.node && candidate.isOffscreen);
+    ASSERT(candidate.visibleNode && candidate.isOffscreen);
     IntRect candidateRect = candidate.rect;
-    for (Node* parentNode = candidate.node->parentNode(); parentNode; parentNode = parentNode->parentNode()) {
+    for (Node* parentNode = candidate.visibleNode->parentNode(); parentNode; parentNode = parentNode->parentNode()) {
         IntRect parentRect = nodeRectInAbsoluteCoordinates(parentNode);
         if (!candidateRect.intersects(parentRect)) {
             if (((direction == FocusDirectionLeft || direction == FocusDirectionRight) && parentNode->renderer()->style()->overflowX() == OHIDDEN)
@@ -643,23 +669,23 @@ bool canBeScrolledIntoView(FocusDirection direction, const FocusCandidate& candi
 // Compose a virtual starting rect if there is no focused node or if it is off screen.
 // The virtual rect is the edge of the container or frame. We select which
 // edge depending on the direction of the navigation.
-IntRect virtualRectForDirection(FocusDirection direction, const IntRect& startingRect)
+IntRect virtualRectForDirection(FocusDirection direction, const IntRect& startingRect, int width)
 {
     IntRect virtualStartingRect = startingRect;
     switch (direction) {
     case FocusDirectionLeft:
-        virtualStartingRect.setX(virtualStartingRect.right());
-        virtualStartingRect.setWidth(0);
+        virtualStartingRect.setX(virtualStartingRect.right() - width);
+        virtualStartingRect.setWidth(width);
         break;
     case FocusDirectionUp:
-        virtualStartingRect.setY(virtualStartingRect.bottom());
-        virtualStartingRect.setHeight(0);
+        virtualStartingRect.setY(virtualStartingRect.bottom() - width);
+        virtualStartingRect.setHeight(width);
         break;
     case FocusDirectionRight:
-        virtualStartingRect.setWidth(0);
+        virtualStartingRect.setWidth(width);
         break;
     case FocusDirectionDown:
-        virtualStartingRect.setHeight(0);
+        virtualStartingRect.setHeight(width);
         break;
     default:
         ASSERT_NOT_REACHED();
@@ -668,5 +694,13 @@ IntRect virtualRectForDirection(FocusDirection direction, const IntRect& startin
     return virtualStartingRect;
 }
 
+IntRect virtualRectForAreaElementAndDirection(FocusDirection direction, HTMLAreaElement* area)
+{
+    // Area elements tend to overlap more than other focusable elements. We flatten the rect of the area elements
+    // to minimize the effect of overlapping areas.
+    IntRect rect = virtualRectForDirection(direction, rectToAbsoluteCoordinates(area->document()->frame(), area->getRect(area->imageElement()->renderer())), 1);
+    return rect;
+}
+
 
 } // namespace WebCore
diff --git a/WebCore/page/SpatialNavigation.h b/WebCore/page/SpatialNavigation.h
index 153d0ac..c911376 100644
--- a/WebCore/page/SpatialNavigation.h
+++ b/WebCore/page/SpatialNavigation.h
@@ -31,6 +31,7 @@ namespace WebCore {
 
 class Element;
 class Frame;
+class HTMLAreaElement;
 class IntRect;
 class RenderObject;
 
@@ -99,7 +100,8 @@ enum RectsAlignment {
 
 struct FocusCandidate {
     FocusCandidate()
-        : node(0)
+        : visibleNode(0)
+        , focusableNode(0)
         , enclosingScrollableBox(0)
         , distance(maxDistance())
         , parentDistance(maxDistance())
@@ -111,11 +113,16 @@ struct FocusCandidate {
     }
 
     FocusCandidate(Node* n, FocusDirection);
-    bool isNull() const { return !node; }
-    bool inScrollableContainer() const { return node && enclosingScrollableBox; }
-    Document* document() const { return node ? node->document() : 0; }
+    explicit FocusCandidate(HTMLAreaElement* area, FocusDirection);
+    bool isNull() const { return !visibleNode; }
+    bool inScrollableContainer() const { return visibleNode && enclosingScrollableBox; }
+    Document* document() const { return visibleNode ? visibleNode->document() : 0; }
 
-    Node* node;
+    // We handle differently visibleNode and FocusableNode to properly handle the areas of imagemaps,
+    // where visibleNode would represent the image element and focusableNode would represent the area element.
+    // In all other cases, visibleNode and focusableNode are one and the same.
+    Node* visibleNode;
+    Node* focusableNode;
     Node* enclosingScrollableBox;
     long long distance;
     long long parentDistance;
@@ -138,7 +145,8 @@ IntRect nodeRectInAbsoluteCoordinates(Node*, bool ignoreBorder = false);
 IntRect frameRectInAbsoluteCoordinates(Frame*);
 void distanceDataForNode(FocusDirection, FocusCandidate& current, FocusCandidate& candidate);
 bool canBeScrolledIntoView(FocusDirection, const FocusCandidate&);
-IntRect virtualRectForDirection(FocusDirection, const IntRect& startingRect);
+IntRect virtualRectForDirection(FocusDirection, const IntRect& startingRect, int width = 0);
+IntRect virtualRectForAreaElementAndDirection(FocusDirection, HTMLAreaElement*);
 } // namspace WebCore
 
 #endif // SpatialNavigation_h

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list