[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.19-706-ge5415e9

cfleizach at apple.com cfleizach at apple.com
Thu Feb 4 21:28:09 UTC 2010


The following commit has been merged in the webkit-1.1 branch:
commit 8d80a8270d4e82386825081adb5536c5a2a91984
Author: cfleizach at apple.com <cfleizach at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Jan 26 18:06:41 2010 +0000

    Add ability for image maps to be focused via tabbing
    https://bugs.webkit.org/show_bug.cgi?id=17513
    
    Reviewed by Darin Adler.
    
    WebCore:
    
    Test: fast/events/tab-imagemap.html
    
    * accessibility/AXObjectCache.cpp:
    (WebCore::AXObjectCache::focusedImageMapUIElement):
    (WebCore::AXObjectCache::focusedUIElementForPage):
    * accessibility/AXObjectCache.h:
    * accessibility/AccessibilityImageMapLink.h:
    (WebCore::AccessibilityImageMapLink::areaElement):
    (WebCore::AccessibilityImageMapLink::mapElement):
    (WebCore::AccessibilityImageMapLink::isImageMapLink):
    * accessibility/AccessibilityObject.h:
    (WebCore::AccessibilityObject::isImageMapLink):
    * accessibility/AccessibilityRenderObject.cpp:
    (WebCore::AccessibilityRenderObject::accessibilityParentForImageMap):
    * html/HTMLAreaElement.cpp:
    (WebCore::HTMLAreaElement::getPath):
    (WebCore::HTMLAreaElement::getRect):
    (WebCore::HTMLAreaElement::imageElement):
    (WebCore::HTMLAreaElement::isKeyboardFocusable):
    (WebCore::HTMLAreaElement::isFocusable):
    (WebCore::HTMLAreaElement::dispatchBlurEvent):
    (WebCore::HTMLAreaElement::updateFocusAppearance):
    (WebCore::HTMLAreaElement::supportsFocus):
    * html/HTMLAreaElement.h:
    * html/HTMLMapElement.cpp:
    (WebCore::HTMLMapElement::imageElement):
    * html/HTMLMapElement.h:
    * platform/graphics/GraphicsContext.h:
    * platform/graphics/cairo/GraphicsContextCairo.cpp:
    (WebCore::GraphicsContext::drawFocusRing):
    * platform/graphics/haiku/GraphicsContextHaiku.cpp:
    (WebCore::GraphicsContext::drawFocusRing):
    * platform/graphics/mac/GraphicsContextMac.mm:
    (WebCore::drawFocusRingToContext):
    (WebCore::GraphicsContext::drawFocusRing):
    * platform/graphics/qt/GraphicsContextQt.cpp:
    (WebCore::GraphicsContext::drawFocusRing):
    * platform/graphics/skia/GraphicsContextSkia.cpp:
    (WebCore::GraphicsContext::drawFocusRing):
    * platform/graphics/win/GraphicsContextCGWin.cpp:
    (WebCore::GraphicsContext::drawFocusRing):
    * platform/graphics/wince/GraphicsContextWince.cpp:
    (WebCore::GraphicsContext::drawFocusRing):
    * platform/graphics/wx/GraphicsContextWx.cpp:
    (WebCore::GraphicsContext::drawFocusRing):
    * rendering/RenderImage.cpp:
    (WebCore::RenderImage::paint):
    (WebCore::RenderImage::paintFocusRings):
    (WebCore::RenderImage::imageMap):
    * rendering/RenderImage.h:
    * rendering/RenderReplaced.h:
    
    LayoutTests:
    
    * fast/events/resources/tabindex-focus-blur-all.js:
    (test):
    (testProgrammaticFocus):
    * fast/events/tab-imagemap-expected.txt: Added.
    * fast/events/tab-imagemap.html: Added.
    * fast/events/tabindex-focus-blur-all-expected.txt:
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@53857 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 443d438..9e10ff7 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,17 @@
+2010-01-26  Chris Fleizach  <cfleizach at apple.com>
+
+        Reviewed by Darin Adler.
+
+        Add ability for image maps to be focused via tabbing
+        https://bugs.webkit.org/show_bug.cgi?id=17513
+
+        * fast/events/resources/tabindex-focus-blur-all.js:
+        (test):
+        (testProgrammaticFocus):
+        * fast/events/tab-imagemap-expected.txt: Added.
+        * fast/events/tab-imagemap.html: Added.
+        * fast/events/tabindex-focus-blur-all-expected.txt:
+
 2010-01-26  Simon Hausmann  <simon.hausmann at nokia.com>
 
         Reviewed by Holger Freyther.
diff --git a/LayoutTests/fast/events/resources/tabindex-focus-blur-all.js b/LayoutTests/fast/events/resources/tabindex-focus-blur-all.js
index 1a6cc81..3355630 100644
--- a/LayoutTests/fast/events/resources/tabindex-focus-blur-all.js
+++ b/LayoutTests/fast/events/resources/tabindex-focus-blur-all.js
@@ -11,6 +11,7 @@ var focusedElem = null;
 var failedTestCount = 0;
 
 var tagNamesAlwaysFocused = ["A",
+                             "AREA",
                              "BUTTON",
                              "IFRAME",
                              "INPUT",
@@ -20,6 +21,8 @@ var tagNamesAlwaysFocused = ["A",
 
 var tagNamesTransferFocused = ["LABEL"]; // labels always transfer focus to the labeled element
 
+var noDisplayTagNamesWithFocus = ["AREA"];  // AREA elements can get focus, but are not displayed.
+
 function printToConsole(str)
 {
     if (!consoleOutput) {
@@ -49,7 +52,7 @@ function test()
     var homeBase = window.frames[1].document.getElementsByClassName('homebase');
     homeBase[0].focus();
 
-    var resultSummary = focusCount+" focus / "+blurCount+" blur events dispatched, and should be 329 / 329 ";
+    var resultSummary = focusCount+" focus / "+blurCount+" blur events dispatched, and should be 337 / 337 ";
     resultSummary += (focusCount==blurCount) ? "<span style='color:green'>PASSED</span><br>" : "<span style='color:red'>FAILED</span><br>";
     resultSummary += "Total of "+failedTestCount+" focus test(s) failed.";
     if (failedTestCount)
@@ -102,9 +105,9 @@ function testProgrammaticFocus(elem)
         elemThatShouldFocus = elem;
     else if (tagNamesAlwaysFocused.find(elem.tagName)) // special case form elements and other controls that are always focusable
         elemThatShouldFocus = elem;
-    
+
     // Hidden elements should not be focusable. https://bugs.webkit.org/show_bug.cgi?id=27099
-    if (document.defaultView.getComputedStyle(elem).display == "none")
+    if (document.defaultView.getComputedStyle(elem).display == "none" && !noDisplayTagNamesWithFocus.find(elem.tagName))
         elemThatShouldFocus = null;
 
     if (tagNamesTransferFocused.find(elem.tagName)) {
diff --git a/LayoutTests/fast/events/tab-imagemap-expected.txt b/LayoutTests/fast/events/tab-imagemap-expected.txt
new file mode 100644
index 0000000..9bcb5bc
--- /dev/null
+++ b/LayoutTests/fast/events/tab-imagemap-expected.txt
@@ -0,0 +1,13 @@
+ 
+This tests that links in a image map are able to be reached through keyboard access and tabbing.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.activeElement.id is 'area1'
+PASS document.activeElement.id is 'area2'
+PASS document.activeElement.id is 'area3'
+PASS document.activeElement.id is 'area5'
+PASS document.activeElement.id is 'area6'
+PASS document.activeElement.id is 'area1'
+
diff --git a/LayoutTests/fast/events/tab-imagemap.html b/LayoutTests/fast/events/tab-imagemap.html
new file mode 100644
index 0000000..a19bbda
--- /dev/null
+++ b/LayoutTests/fast/events/tab-imagemap.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../js/resources/js-test-style.css">
+<script>
+var successfullyParsed = false;
+</script>
+<script src="../js/resources/js-test-pre.js"></script>
+<body id="body">
+
+<map name="mymap">
+<area id="area1" shape="circle" coords="70,84,51" href="1">
+<area id="area2" shape="rect" coords="25,180,125,280" href="2">
+<area id="area3" shape="poly" coords="153,106,186,225,340,193,315,81,304,167" href="3">
+<area id="area4" shape="rect" coords="420,19,478,278" nohref>
+<area id="area5" shape="circle" coords="220,150,100" href="4">
+<area id="area6" shape="default" coords="0,0,500,300" href="5">
+<area id="area7" shape="rect" coords="1, 1, 10, 10" tabindex=-1 href="6">
+</map>
+
+<img src="resources/abe.png" width="500" height="300" alt="Image Map" usemap="#mymap" ismap>
+
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+
+    description("This tests that links in a image map are able to be reached through keyboard access and tabbing.");
+
+    eventSender.keyDown('\t');
+    shouldBe("document.activeElement.id", "'area1'");
+
+    eventSender.keyDown('\t');
+    shouldBe("document.activeElement.id", "'area2'");
+
+    eventSender.keyDown('\t');
+    shouldBe("document.activeElement.id", "'area3'");
+
+    // We'll skip over area4 because its nohref
+    eventSender.keyDown('\t');
+    shouldBe("document.activeElement.id", "'area5'");
+
+    eventSender.keyDown('\t');
+    shouldBe("document.activeElement.id", "'area6'");
+
+    // We'll skip over area7 because its tabindex=-1
+    eventSender.keyDown('\t');
+    shouldBe("document.activeElement.id", "'area1'");
+
+    successfullyParsed = true;
+</script>
+
+<script src="../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/tabindex-focus-blur-all-expected.txt b/LayoutTests/fast/events/tabindex-focus-blur-all-expected.txt
index 2c5bf62..e26093c 100644
--- a/LayoutTests/fast/events/tabindex-focus-blur-all-expected.txt
+++ b/LayoutTests/fast/events/tabindex-focus-blur-all-expected.txt
@@ -1,2 +1,2 @@
-329 focus / 329 blur events dispatched, and should be 329 / 329 PASSED
+337 focus / 337 blur events dispatched, and should be 337 / 337 PASSED
 Total of 0 focus test(s) failed. PASSED
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index f0767ee..ef8dba1 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,62 @@
+2010-01-26  Chris Fleizach  <cfleizach at apple.com>
+
+        Reviewed by Darin Adler.
+
+        Add ability for image maps to be focused via tabbing
+        https://bugs.webkit.org/show_bug.cgi?id=17513
+
+        Test: fast/events/tab-imagemap.html
+
+        * accessibility/AXObjectCache.cpp:
+        (WebCore::AXObjectCache::focusedImageMapUIElement):
+        (WebCore::AXObjectCache::focusedUIElementForPage):
+        * accessibility/AXObjectCache.h:
+        * accessibility/AccessibilityImageMapLink.h:
+        (WebCore::AccessibilityImageMapLink::areaElement):
+        (WebCore::AccessibilityImageMapLink::mapElement):
+        (WebCore::AccessibilityImageMapLink::isImageMapLink):
+        * accessibility/AccessibilityObject.h:
+        (WebCore::AccessibilityObject::isImageMapLink):
+        * accessibility/AccessibilityRenderObject.cpp:
+        (WebCore::AccessibilityRenderObject::accessibilityParentForImageMap):
+        * html/HTMLAreaElement.cpp:
+        (WebCore::HTMLAreaElement::getPath):
+        (WebCore::HTMLAreaElement::getRect):
+        (WebCore::HTMLAreaElement::imageElement):
+        (WebCore::HTMLAreaElement::isKeyboardFocusable):
+        (WebCore::HTMLAreaElement::isFocusable):
+        (WebCore::HTMLAreaElement::dispatchBlurEvent):
+        (WebCore::HTMLAreaElement::updateFocusAppearance):
+        (WebCore::HTMLAreaElement::supportsFocus):
+        * html/HTMLAreaElement.h:
+        * html/HTMLMapElement.cpp:
+        (WebCore::HTMLMapElement::imageElement):
+        * html/HTMLMapElement.h:
+        * platform/graphics/GraphicsContext.h:
+        * platform/graphics/cairo/GraphicsContextCairo.cpp:
+        (WebCore::GraphicsContext::drawFocusRing):
+        * platform/graphics/haiku/GraphicsContextHaiku.cpp:
+        (WebCore::GraphicsContext::drawFocusRing):
+        * platform/graphics/mac/GraphicsContextMac.mm:
+        (WebCore::drawFocusRingToContext):
+        (WebCore::GraphicsContext::drawFocusRing):
+        * platform/graphics/qt/GraphicsContextQt.cpp:
+        (WebCore::GraphicsContext::drawFocusRing):
+        * platform/graphics/skia/GraphicsContextSkia.cpp:
+        (WebCore::GraphicsContext::drawFocusRing):
+        * platform/graphics/win/GraphicsContextCGWin.cpp:
+        (WebCore::GraphicsContext::drawFocusRing):
+        * platform/graphics/wince/GraphicsContextWince.cpp:
+        (WebCore::GraphicsContext::drawFocusRing):
+        * platform/graphics/wx/GraphicsContextWx.cpp:
+        (WebCore::GraphicsContext::drawFocusRing):
+        * rendering/RenderImage.cpp:
+        (WebCore::RenderImage::paint):
+        (WebCore::RenderImage::paintFocusRings):
+        (WebCore::RenderImage::imageMap):
+        * rendering/RenderImage.h:
+        * rendering/RenderReplaced.h:
+
 2010-01-26  Pavel Feldman  <pfeldman at chromium.org>
 
         Reviewed by Timothy Hatcher.
diff --git a/WebCore/accessibility/AXObjectCache.cpp b/WebCore/accessibility/AXObjectCache.cpp
index 1cd917f..60ac97a 100644
--- a/WebCore/accessibility/AXObjectCache.cpp
+++ b/WebCore/accessibility/AXObjectCache.cpp
@@ -50,6 +50,8 @@
 #include "AccessibilityTableRow.h"
 #include "FocusController.h"
 #include "Frame.h"
+#include "HTMLAreaElement.h"
+#include "HTMLImageElement.h"
 #include "HTMLNames.h"
 #if ENABLE(VIDEO)
 #include "MediaControlElements.h"
@@ -84,6 +86,35 @@ AXObjectCache::~AXObjectCache()
     }
 }
 
+AccessibilityObject* AXObjectCache::focusedImageMapUIElement(HTMLAreaElement* areaElement)
+{
+    // Find the corresponding accessibility object for the HTMLAreaElement. This should be
+    // in the list of children for its corresponding image.
+    if (!areaElement)
+        return 0;
+    
+    HTMLImageElement* imageElement = areaElement->imageElement();
+    if (!imageElement)
+        return 0;
+    
+    AccessibilityObject* axRenderImage = areaElement->document()->axObjectCache()->getOrCreate(imageElement->renderer());
+    if (!axRenderImage)
+        return 0;
+    
+    AccessibilityObject::AccessibilityChildrenVector imageChildren = axRenderImage->children();
+    unsigned count = imageChildren.size();
+    for (unsigned k = 0; k < count; ++k) {
+        AccessibilityObject* child = imageChildren[k].get();
+        if (!child->isImageMapLink())
+            continue;
+        
+        if (static_cast<AccessibilityImageMapLink*>(child)->areaElement() == areaElement)
+            return child;
+    }    
+    
+    return 0;
+}
+    
 AccessibilityObject* AXObjectCache::focusedUIElementForPage(const Page* page)
 {
     // get the focused node in the page
@@ -92,6 +123,9 @@ AccessibilityObject* AXObjectCache::focusedUIElementForPage(const Page* page)
     if (!focusedNode)
         focusedNode = focusedDocument;
 
+    if (focusedNode->hasTagName(areaTag))
+        return focusedImageMapUIElement(static_cast<HTMLAreaElement*>(focusedNode));
+    
     RenderObject* focusedNodeRenderer = focusedNode->renderer();
     if (!focusedNodeRenderer)
         return 0;
diff --git a/WebCore/accessibility/AXObjectCache.h b/WebCore/accessibility/AXObjectCache.h
index ee51ff5..450396f 100644
--- a/WebCore/accessibility/AXObjectCache.h
+++ b/WebCore/accessibility/AXObjectCache.h
@@ -42,6 +42,7 @@ class WebCoreTextMarker;
 
 namespace WebCore {
 
+class HTMLAreaElement;
 class Node;
 class Page;
 class RenderObject;
@@ -135,6 +136,8 @@ private:
     Vector<pair<RefPtr<AccessibilityObject>, AXNotification> > m_notificationsToPost;
     void notificationPostTimerFired(Timer<AXObjectCache>*);
     
+    static AccessibilityObject* focusedImageMapUIElement(HTMLAreaElement*);
+    
     AXID getAXID(AccessibilityObject*);
     bool nodeIsAriaType(Node*, String role);
 };
diff --git a/WebCore/accessibility/AccessibilityImageMapLink.h b/WebCore/accessibility/AccessibilityImageMapLink.h
index 3024f37..ca4c62c 100644
--- a/WebCore/accessibility/AccessibilityImageMapLink.h
+++ b/WebCore/accessibility/AccessibilityImageMapLink.h
@@ -44,13 +44,17 @@ public:
     virtual ~AccessibilityImageMapLink();
     
     void setHTMLAreaElement(HTMLAreaElement* element) { m_areaElement = element; }
+    HTMLAreaElement* areaElement() const { return m_areaElement; }
+    
     void setHTMLMapElement(HTMLMapElement* element) { m_mapElement = element; }    
+    HTMLMapElement* mapElement() const { return m_mapElement; }
+    
     void setParent(AccessibilityObject* parent) { m_parent = parent; }
         
     virtual AccessibilityRole roleValue() const;
     virtual bool accessibilityIsIgnored() const { return false; }
     virtual bool isEnabled() const { return true; }
-
+    
     virtual AccessibilityObject* parentObject() const;
     virtual Element* anchorElement() const;
     virtual Element* actionElement() const;
@@ -70,6 +74,8 @@ private:
     HTMLAreaElement* m_areaElement;
     HTMLMapElement* m_mapElement;
     AccessibilityObject* m_parent;
+    
+    virtual bool isImageMapLink() const { return true; }
 };
     
 } // namespace WebCore
diff --git a/WebCore/accessibility/AccessibilityObject.h b/WebCore/accessibility/AccessibilityObject.h
index 363681d..e4b1d99 100644
--- a/WebCore/accessibility/AccessibilityObject.h
+++ b/WebCore/accessibility/AccessibilityObject.h
@@ -285,6 +285,7 @@ public:
     virtual bool isFieldset() const { return false; }
     virtual bool isGroup() const { return false; }
     virtual bool isARIATreeGridRow() const { return false; }
+    virtual bool isImageMapLink() const { return false; }
     virtual bool isMenuList() const { return false; }
     virtual bool isMenuListPopup() const { return false; }
     virtual bool isMenuListOption() const { return false; }
diff --git a/WebCore/accessibility/AccessibilityRenderObject.cpp b/WebCore/accessibility/AccessibilityRenderObject.cpp
index 45228ec..8cd51ae 100644
--- a/WebCore/accessibility/AccessibilityRenderObject.cpp
+++ b/WebCore/accessibility/AccessibilityRenderObject.cpp
@@ -2049,24 +2049,14 @@ AXObjectCache* AccessibilityRenderObject::axObjectCache() const
 AccessibilityObject* AccessibilityRenderObject::accessibilityParentForImageMap(HTMLMapElement* map) const
 {
     // find an image that is using this map
-    if (!m_renderer || !map)
+    if (!map)
         return 0;
 
-    String mapName = map->getName().string().lower();
-    RefPtr<HTMLCollection> coll = m_renderer->document()->images();
-    for (Node* curr = coll->firstItem(); curr; curr = coll->nextItem()) {
-        RenderObject* obj = curr->renderer();
-        if (!obj || !curr->hasTagName(imgTag))
-            continue;
-        
-        // The HTMLImageElement's useMap() value includes the '#' symbol at the beginning,
-        // which has to be stripped off
-        String useMapName = static_cast<HTMLImageElement*>(curr)->getAttribute(usemapAttr).string().substring(1).lower();
-        if (useMapName == mapName)
-            return axObjectCache()->getOrCreate(obj);
-    }
+    HTMLImageElement* imageElement = map->imageElement();
+    if (!imageElement)
+        return 0;
     
-    return 0;
+    return axObjectCache()->getOrCreate(imageElement->renderer());
 }
     
 void AccessibilityRenderObject::getDocumentLinks(AccessibilityChildrenVector& result)
diff --git a/WebCore/html/HTMLAreaElement.cpp b/WebCore/html/HTMLAreaElement.cpp
index b202cae..b862f69 100644
--- a/WebCore/html/HTMLAreaElement.cpp
+++ b/WebCore/html/HTMLAreaElement.cpp
@@ -22,6 +22,8 @@
 #include "config.h"
 #include "HTMLAreaElement.h"
 
+#include "HTMLImageElement.h"
+#include "HTMLMapElement.h"
 #include "HTMLNames.h"
 #include "HitTestResult.h"
 #include "MappedAttribute.h"
@@ -82,13 +84,27 @@ bool HTMLAreaElement::mapMouseEvent(int x, int y, const IntSize& size, HitTestRe
     return true;
 }
 
-IntRect HTMLAreaElement::getRect(RenderObject* obj) const
+Path HTMLAreaElement::getPath(RenderObject* obj) const
 {
+    if (!obj)
+        return Path();
+    
     // FIXME: This doesn't work correctly with transforms.
     FloatPoint absPos = obj->localToAbsolute();
-    Path p = getRegion(m_lastSize);
+
+    // Default should default to the size of the containing object.
+    IntSize size = m_lastSize;
+    if (m_shape == Default)
+        size = obj->absoluteOutlineBounds().size();
+    
+    Path p = getRegion(size);
     p.translate(absPos - FloatPoint());
-    return enclosingIntRect(p.boundingRect());
+    return p;
+}
+    
+IntRect HTMLAreaElement::getRect(RenderObject* obj) const
+{
+    return enclosingIntRect(getPath(obj).boundingRect());
 }
 
 Path HTMLAreaElement::getRegion(const IntSize& size) const
@@ -161,11 +177,58 @@ void HTMLAreaElement::setNoHref(bool noHref)
 {
     setAttribute(nohrefAttr, noHref ? "" : 0);
 }
+    
+HTMLImageElement* HTMLAreaElement::imageElement() const
+{
+    Node* mapElement = parent();
+    if (!mapElement->hasTagName(mapTag))
+        return 0;
+    
+    return static_cast<HTMLMapElement*>(mapElement)->imageElement();
+}
 
+bool HTMLAreaElement::isKeyboardFocusable(KeyboardEvent*) const
+{
+    return supportsFocus();
+}
+
+bool HTMLAreaElement::isFocusable() const
+{
+    return supportsFocus();
+}
+    
+void HTMLAreaElement::dispatchBlurEvent()
+{
+    HTMLAnchorElement::dispatchBlurEvent();
+    
+    // On a blur, we might need to remove our focus rings by repainting.
+    updateFocusAppearance(false);
+}
+    
+void HTMLAreaElement::updateFocusAppearance(bool restorePreviousSelection)
+{
+    Node* parent = parentNode();
+    if (!parent || !parent->hasTagName(mapTag))
+        return;
+    
+    HTMLImageElement* imageElement = static_cast<HTMLMapElement*>(parent)->imageElement();
+    if (!imageElement)
+        return;
+    
+    // This will handle scrolling to the image if necessary.
+    imageElement->updateFocusAppearance(restorePreviousSelection);
+    
+    RenderObject* imageRenderer = imageElement->renderer();
+    if (imageRenderer)
+        imageRenderer->setNeedsLayout(true);
+}
+    
 bool HTMLAreaElement::supportsFocus() const
 {
-    // Skip HTMLAnchorElements isLink() check.
-    return HTMLElement::supportsFocus();
+    // If the AREA element was a link, it should support focus.
+    // The inherited method is not used because it assumes that a render object must exist 
+    // for the element to support focus. AREA elements do not have render objects.
+    return isLink();
 }
 
 String HTMLAreaElement::target() const
diff --git a/WebCore/html/HTMLAreaElement.h b/WebCore/html/HTMLAreaElement.h
index 7b2497c..f8e2564 100644
--- a/WebCore/html/HTMLAreaElement.h
+++ b/WebCore/html/HTMLAreaElement.h
@@ -30,6 +30,7 @@
 namespace WebCore {
 
 class HitTestResult;
+class HTMLImageElement;
 class Path;
 
 class HTMLAreaElement : public HTMLAnchorElement {
@@ -41,7 +42,11 @@ public:
     bool mapMouseEvent(int x, int y, const IntSize&, HitTestResult&);
 
     IntRect getRect(RenderObject*) const;
-
+    Path getPath(RenderObject*) const;
+    
+    // Convenience method to get the parent map's image.
+    HTMLImageElement* imageElement() const;
+    
     KURL href() const;
 
     bool noHref() const;
@@ -55,7 +60,11 @@ private:
     virtual void parseMappedAttribute(MappedAttribute*);
     virtual bool supportsFocus() const;
     virtual String target() const;
-
+    virtual bool isKeyboardFocusable(KeyboardEvent*) const;
+    virtual bool isFocusable() const;
+    virtual void updateFocusAppearance(bool /*restorePreviousSelection*/);
+    virtual void dispatchBlurEvent();
+    
     enum Shape { Default, Poly, Rect, Circle, Unknown };
     Path getRegion(const IntSize&) const;
 
diff --git a/WebCore/html/HTMLMapElement.cpp b/WebCore/html/HTMLMapElement.cpp
index 2d623b2..9617afc 100644
--- a/WebCore/html/HTMLMapElement.cpp
+++ b/WebCore/html/HTMLMapElement.cpp
@@ -25,10 +25,12 @@
 #include "Document.h"
 #include "HTMLAreaElement.h"
 #include "HTMLCollection.h"
+#include "HTMLImageElement.h"
 #include "HTMLNames.h"
 #include "HitTestResult.h"
 #include "IntSize.h"
 #include "MappedAttribute.h"
+#include "RenderObject.h"
 
 using namespace std;
 
@@ -75,6 +77,24 @@ bool HTMLMapElement::mapMouseEvent(int x, int y, const IntSize& size, HitTestRes
     return defaultArea;
 }
 
+HTMLImageElement* HTMLMapElement::imageElement() const
+{
+    RefPtr<HTMLCollection> coll = renderer()->document()->images();
+    for (Node* curr = coll->firstItem(); curr; curr = coll->nextItem()) {
+        if (!curr->hasTagName(imgTag))
+            continue;
+        
+        // The HTMLImageElement's useMap() value includes the '#' symbol at the beginning,
+        // which has to be stripped off.
+        HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(curr);
+        String useMapName = imageElement->getAttribute(usemapAttr).string().substring(1);
+        if (equalIgnoringCase(useMapName, m_name))
+            return imageElement;
+    }
+    
+    return 0;    
+}
+    
 void HTMLMapElement::parseMappedAttribute(MappedAttribute* attr)
 {
     const QualifiedName& attrName = attr->name();
diff --git a/WebCore/html/HTMLMapElement.h b/WebCore/html/HTMLMapElement.h
index 2a6eb8d..f40e78e 100644
--- a/WebCore/html/HTMLMapElement.h
+++ b/WebCore/html/HTMLMapElement.h
@@ -29,7 +29,8 @@ namespace WebCore {
 
 class IntSize;
 class HitTestResult;
-
+class HTMLImageElement;
+    
 class HTMLMapElement : public HTMLElement {
 public:
     HTMLMapElement(const QualifiedName&, Document*);
@@ -44,7 +45,8 @@ public:
     virtual void parseMappedAttribute(MappedAttribute*);
 
     bool mapMouseEvent(int x, int y, const IntSize&, HitTestResult&);
-
+    
+    HTMLImageElement* imageElement() const;
     PassRefPtr<HTMLCollection> areas();
 
     String name() const;
diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h
index 9d7bac3..1946b97 100644
--- a/WebCore/platform/graphics/GraphicsContext.h
+++ b/WebCore/platform/graphics/GraphicsContext.h
@@ -263,6 +263,7 @@ namespace WebCore {
         void clearShadow();
 
         void drawFocusRing(const Vector<IntRect>&, int width, int offset, const Color&);
+        void drawFocusRing(const Vector<Path>&, int width, int offset, const Color&);
 
         void setLineCap(LineCap);
         void setLineDash(const DashArray&, float dashOffset);
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index 9e1cd1e..d866b6c 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -606,6 +606,11 @@ void GraphicsContext::clipPath(WindRule clipRule)
     cairo_clip(cr);
 }
 
+void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color)
+{
+    // FIXME: implement
+}
+
 void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int /* offset */, const Color& color)
 {
     if (paintingDisabled())
diff --git a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
index 64d1179..6038c6a 100644
--- a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
@@ -204,6 +204,11 @@ void GraphicsContext::clip(const FloatRect& rect)
     m_data->m_view->ConstrainClippingRegion(&region);
 }
 
+void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color)
+{
+    // FIXME: implement
+}
+
 void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int /* width */, int /* offset */, const Color& color)
 {
     if (paintingDisabled())
diff --git a/WebCore/platform/graphics/mac/GraphicsContextMac.mm b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
index 5cf127b..5f111f6 100644
--- a/WebCore/platform/graphics/mac/GraphicsContextMac.mm
+++ b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
@@ -43,6 +43,38 @@ namespace WebCore {
 // calls in this file are all exception-safe, so we don't block
 // exceptions for those.
 
+static void drawFocusRingToContext(CGContextRef context, RetainPtr<CGPathRef> focusRingPath, RetainPtr<CGColorRef> colorRef, int radius)
+{
+#ifdef BUILDING_ON_TIGER
+    CGContextBeginTransparencyLayer(context, 0);
+#endif
+    CGContextBeginPath(context);
+    CGContextAddPath(context, focusRingPath.get());
+    wkDrawFocusRing(context, colorRef.get(), radius);
+#ifdef BUILDING_ON_TIGER
+    CGContextEndTransparencyLayer(context);
+#endif
+}
+
+void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color)
+{
+    if (paintingDisabled())
+        return;
+    
+    int radius = (width - 1) / 2;
+    offset += radius;
+    RetainPtr<CGColorRef> colorRef;
+    if (color.isValid())
+        colorRef.adoptCF(createCGColor(color));
+    
+    RetainPtr<CGMutablePathRef> focusRingPath(AdoptCF, CGPathCreateMutable());
+    unsigned pathCount = paths.size();
+    for (unsigned i = 0; i < pathCount; i++)
+        CGPathAddPath(focusRingPath.get(), 0, paths[i].platformPath());
+    
+    drawFocusRingToContext(platformContext(), focusRingPath, colorRef, radius);
+}    
+    
 void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
 {
     if (paintingDisabled())
@@ -59,16 +91,7 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int
     for (unsigned i = 0; i < rectCount; i++)
         CGPathAddRect(focusRingPath.get(), 0, CGRectInset(rects[i], -offset, -offset));
 
-    CGContextRef context = platformContext();
-#ifdef BUILDING_ON_TIGER
-    CGContextBeginTransparencyLayer(context, NULL);
-#endif
-    CGContextBeginPath(context);
-    CGContextAddPath(context, focusRingPath.get());
-    wkDrawFocusRing(context, colorRef.get(), radius);
-#ifdef BUILDING_ON_TIGER
-    CGContextEndTransparencyLayer(context);
-#endif
+    drawFocusRingToContext(platformContext(), focusRingPath, colorRef, radius);
 }
 
 #ifdef BUILDING_ON_TIGER // Post-Tiger's setCompositeOperation() is defined in GraphicsContextCG.cpp.
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index 043ab0b..b78a6e8 100644
--- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -795,6 +795,11 @@ void GraphicsContext::clipPath(WindRule clipRule)
     p->setClipPath(newPath);
 }
 
+void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color)
+{
+    // FIXME: implement
+}
+
 /**
  * Focus ring handling is not handled here. Qt style in 
  * RenderTheme handles drawing focus on widgets which 
diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
index 7d4c01a..985442c 100644
--- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -501,6 +501,11 @@ void GraphicsContext::drawEllipse(const IntRect& elipseRect)
     }
 }
 
+void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color)
+{
+    // FIXME: implement
+}
+
 void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int /* width */, int /* offset */, const Color& color)
 {
     if (paintingDisabled())
diff --git a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
index e5ebaf0..47a51de 100644
--- a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
@@ -124,6 +124,11 @@ void GraphicsContext::drawWindowsBitmap(WindowsBitmap* image, const IntPoint& po
     CGContextDrawImage(m_data->m_cgContext.get(), CGRectMake(point.x(), point.y(), image->size().width(), image->size().height()), cgImage.get());   
 }
 
+void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color)
+{
+    // FIXME: implement
+}
+
 void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
 {
     if (paintingDisabled())
diff --git a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp
index 608cdd1..0e387f5 100644
--- a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp
+++ b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp
@@ -1002,6 +1002,11 @@ void GraphicsContext::clipOut(const IntRect& rect)
     ExcludeClipRect(m_data->m_dc, trRect.x(), trRect.y(), trRect.right(), trRect.bottom());
 }
 
+void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color)
+{
+    // FIXME: implement
+}
+
 void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
 {
     if (!m_data->m_opacity || paintingDisabled())
diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
index f5dfe00..839bc59 100644
--- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
+++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
@@ -270,6 +270,11 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
     notImplemented();
 }
 
+void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color)
+{
+    // FIXME: implement
+}
+
 void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
 {
     if (paintingDisabled())
diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp
index c10ab8e..a14ab27 100644
--- a/WebCore/rendering/RenderImage.cpp
+++ b/WebCore/rendering/RenderImage.cpp
@@ -26,14 +26,19 @@
 #include "config.h"
 #include "RenderImage.h"
 
+#include "Frame.h"
 #include "GraphicsContext.h"
+#include "HTMLAreaElement.h"
+#include "HTMLCollection.h"
 #include "HTMLImageElement.h"
 #include "HTMLInputElement.h"
 #include "HTMLMapElement.h"
 #include "HTMLNames.h"
 #include "HitTestResult.h"
 #include "Page.h"
+#include "RenderTheme.h"
 #include "RenderView.h"
+#include "SelectionController.h"
 #include <wtf/CurrentTime.h>
 #include <wtf/UnusedParam.h>
 
@@ -425,6 +430,51 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty)
     }
 }
 
+void RenderImage::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+    RenderReplaced::paint(paintInfo, tx, ty);
+    
+    if (paintInfo.phase == PaintPhaseOutline)
+        paintFocusRings(paintInfo, style());
+}
+    
+void RenderImage::paintFocusRings(PaintInfo& paintInfo, const RenderStyle* style)
+{
+    // Don't draw focus rings if printing.
+    if (document()->printing() || !document()->frame()->selection()->isFocusedAndActive())
+        return;
+    
+    if (paintInfo.context->paintingDisabled() && !paintInfo.context->updatingControlTints())
+        return;
+
+    HTMLMapElement* mapElement = imageMap();
+    if (!mapElement)
+        return;
+    
+    Document* document = mapElement->document();
+    if (!document)
+        return;
+    
+    Node* focusedNode = document->focusedNode();
+    if (!focusedNode)
+        return;
+    
+    RefPtr<HTMLCollection> areas = mapElement->areas();
+    unsigned numAreas = areas->length();
+    
+    // FIXME: Clip the paths to the image bounding box.
+    for (unsigned k = 0; k < numAreas; ++k) {
+        HTMLAreaElement* areaElement = static_cast<HTMLAreaElement*>(areas->item(k));
+        if (focusedNode != areaElement)
+            continue;
+        
+        Vector<Path> focusRingPaths;
+        focusRingPaths.append(areaElement->getPath(this));
+        paintInfo.context->drawFocusRing(focusRingPaths, style->outlineWidth(), style->outlineOffset(), style->outlineColor());
+        break;
+    }
+}
+    
 void RenderImage::paintIntoRect(GraphicsContext* context, const IntRect& rect)
 {
     if (!hasImage() || errorOccurred() || rect.width() <= 0 || rect.height() <= 0)
@@ -445,7 +495,7 @@ int RenderImage::minimumReplacedHeight() const
     return errorOccurred() ? intrinsicSize().height() : 0;
 }
 
-HTMLMapElement* RenderImage::imageMap()
+HTMLMapElement* RenderImage::imageMap() const
 {
     HTMLImageElement* i = node() && node()->hasTagName(imgTag) ? static_cast<HTMLImageElement*>(node()) : 0;
     return i ? i->document()->getImageMap(i->getAttribute(usemapAttr)) : 0;
diff --git a/WebCore/rendering/RenderImage.h b/WebCore/rendering/RenderImage.h
index ab94667..bc5e2d8 100644
--- a/WebCore/rendering/RenderImage.h
+++ b/WebCore/rendering/RenderImage.h
@@ -43,7 +43,7 @@ public:
     void setCachedImage(CachedImage*);
     CachedImage* cachedImage() const { return m_cachedImage.get(); }
 
-    HTMLMapElement* imageMap();
+    HTMLMapElement* imageMap() const;
 
     void resetAnimation();
 
@@ -58,6 +58,8 @@ protected:
     virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
 
     virtual void paintIntoRect(GraphicsContext*, const IntRect&);
+    void paintFocusRings(PaintInfo&, const RenderStyle*);
+    virtual void paint(PaintInfo&, int tx, int ty);
 
     bool isWidthSpecified() const;
     bool isHeightSpecified() const;
diff --git a/WebCore/rendering/RenderReplaced.h b/WebCore/rendering/RenderReplaced.h
index 0ba6b8a..bcf565d 100644
--- a/WebCore/rendering/RenderReplaced.h
+++ b/WebCore/rendering/RenderReplaced.h
@@ -46,6 +46,7 @@ protected:
     void setIntrinsicSize(const IntSize&);
     virtual void intrinsicSizeChanged();
 
+    virtual void paint(PaintInfo&, int tx, int ty);
     bool shouldPaint(PaintInfo&, int& tx, int& ty);
     void adjustOverflowForBoxShadowAndReflect();
     IntRect localSelectionRect(bool checkWhetherSelected = true) const;
@@ -62,7 +63,6 @@ private:
 
     virtual int minimumReplacedHeight() const { return 0; }
 
-    virtual void paint(PaintInfo&, int tx, int ty);
     virtual void paintReplaced(PaintInfo&, int /*tx*/, int /*ty*/) { }
 
     virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list