summaryrefslogtreecommitdiff
path: root/Source/WebCore/svg/SVGAElement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/svg/SVGAElement.cpp')
-rw-r--r--Source/WebCore/svg/SVGAElement.cpp138
1 files changed, 61 insertions, 77 deletions
diff --git a/Source/WebCore/svg/SVGAElement.cpp b/Source/WebCore/svg/SVGAElement.cpp
index f6fbbc669..710dece81 100644
--- a/Source/WebCore/svg/SVGAElement.cpp
+++ b/Source/WebCore/svg/SVGAElement.cpp
@@ -21,15 +21,10 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGAElement.h"
-#include "Attr.h"
-#include "Attribute.h"
#include "Document.h"
#include "EventHandler.h"
-#include "EventNames.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameLoaderTypes.h"
@@ -42,15 +37,12 @@
#include "RenderSVGText.h"
#include "RenderSVGTransformableContainer.h"
#include "ResourceRequest.h"
-#include "SVGElementInstance.h"
#include "SVGNames.h"
#include "SVGSMILElement.h"
#include "XLinkNames.h"
namespace WebCore {
-using namespace HTMLNames;
-
// Animated property definitions
DEFINE_ANIMATED_STRING(SVGAElement, SVGNames::targetAttr, SVGTarget, svgTarget)
DEFINE_ANIMATED_STRING(SVGAElement, XLinkNames::hrefAttr, Href, href)
@@ -70,15 +62,15 @@ inline SVGAElement::SVGAElement(const QualifiedName& tagName, Document& document
registerAnimatedPropertiesForSVGAElement();
}
-PassRefPtr<SVGAElement> SVGAElement::create(const QualifiedName& tagName, Document& document)
+Ref<SVGAElement> SVGAElement::create(const QualifiedName& tagName, Document& document)
{
- return adoptRef(new SVGAElement(tagName, document));
+ return adoptRef(*new SVGAElement(tagName, document));
}
String SVGAElement::title() const
{
// If the xlink:title is set (non-empty string), use it.
- const AtomicString& title = fastGetAttribute(XLinkNames::titleAttr);
+ const AtomicString& title = attributeWithoutSynchronization(XLinkNames::titleAttr);
if (!title.isEmpty())
return title;
@@ -86,84 +78,57 @@ String SVGAElement::title() const
return SVGElement::title();
}
-bool SVGAElement::isSupportedAttribute(const QualifiedName& attrName)
-{
- DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
- if (supportedAttributes.isEmpty()) {
- SVGURIReference::addSupportedAttributes(supportedAttributes);
- SVGLangSpace::addSupportedAttributes(supportedAttributes);
- SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
- supportedAttributes.add(SVGNames::targetAttr);
- }
- return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
-}
-
void SVGAElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
- if (!isSupportedAttribute(name)) {
- SVGGraphicsElement::parseAttribute(name, value);
- return;
- }
-
if (name == SVGNames::targetAttr) {
setSVGTargetBaseValue(value);
return;
}
- if (SVGURIReference::parseAttribute(name, value))
- return;
- if (SVGLangSpace::parseAttribute(name, value))
- return;
- if (SVGExternalResourcesRequired::parseAttribute(name, value))
- return;
-
- ASSERT_NOT_REACHED();
+ SVGGraphicsElement::parseAttribute(name, value);
+ SVGURIReference::parseAttribute(name, value);
+ SVGExternalResourcesRequired::parseAttribute(name, value);
}
void SVGAElement::svgAttributeChanged(const QualifiedName& attrName)
{
- if (!isSupportedAttribute(attrName)) {
- SVGGraphicsElement::svgAttributeChanged(attrName);
- return;
- }
-
- SVGElementInstance::InvalidationGuard invalidationGuard(this);
-
- // Unlike other SVG*Element classes, SVGAElement only listens to SVGURIReference changes
- // as none of the other properties changes the linking behaviour for our <a> element.
if (SVGURIReference::isKnownAttribute(attrName)) {
bool wasLink = isLink();
setIsLink(!href().isNull() && !shouldProhibitLinks(this));
- if (wasLink != isLink())
- setNeedsStyleRecalc();
+ if (wasLink != isLink()) {
+ InstanceInvalidationGuard guard(*this);
+ invalidateStyleForSubtree();
+ }
}
+
+ SVGGraphicsElement::svgAttributeChanged(attrName);
}
-RenderPtr<RenderElement> SVGAElement::createElementRenderer(PassRef<RenderStyle> style)
+RenderPtr<RenderElement> SVGAElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
{
- if (parentNode() && parentNode()->isSVGElement() && toSVGElement(parentNode())->isTextContent())
- return createRenderer<RenderSVGInline>(*this, std::move(style));
+ if (parentNode() && parentNode()->isSVGElement() && downcast<SVGElement>(*parentNode()).isTextContent())
+ return createRenderer<RenderSVGInline>(*this, WTFMove(style));
- return createRenderer<RenderSVGTransformableContainer>(*this, std::move(style));
+ return createRenderer<RenderSVGTransformableContainer>(*this, WTFMove(style));
}
-void SVGAElement::defaultEventHandler(Event* event)
+void SVGAElement::defaultEventHandler(Event& event)
{
if (isLink()) {
if (focused() && isEnterKeyKeydownEvent(event)) {
- event->setDefaultHandled();
- dispatchSimulatedClick(event);
+ event.setDefaultHandled();
+ dispatchSimulatedClick(&event);
return;
}
- if (isLinkClick(event)) {
+ if (MouseEvent::canTriggerActivationBehavior(event)) {
String url = stripLeadingAndTrailingHTMLSpaces(href());
if (url[0] == '#') {
- Element* targetElement = treeScope().getElementById(url.substring(1));
- if (targetElement && isSVGSMILElement(*targetElement)) {
- toSVGSMILElement(*targetElement).beginByLinkActivation();
- event->setDefaultHandled();
+ Element* targetElement = treeScope().getElementById(url.substringSharingImpl(1));
+ if (is<SVGSMILElement>(targetElement)) {
+ downcast<SVGSMILElement>(*targetElement).beginByLinkActivation();
+ event.setDefaultHandled();
return;
}
// Only allow navigation to internal <view> anchors.
@@ -172,14 +137,14 @@ void SVGAElement::defaultEventHandler(Event* event)
}
String target = this->target();
- if (target.isEmpty() && fastGetAttribute(XLinkNames::showAttr) == "new")
+ if (target.isEmpty() && attributeWithoutSynchronization(XLinkNames::showAttr) == "new")
target = "_blank";
- event->setDefaultHandled();
+ event.setDefaultHandled();
Frame* frame = document().frame();
if (!frame)
return;
- frame->loader().urlSelected(document().completeURL(url), target, event, false, false, MaybeSendReferrer);
+ frame->loader().urlSelected(document().completeURL(url), target, &event, LockHistory::No, LockBackForwardList::No, MaybeSendReferrer, document().shouldOpenExternalURLsPolicyToPropagate());
return;
}
}
@@ -187,11 +152,18 @@ void SVGAElement::defaultEventHandler(Event* event)
SVGGraphicsElement::defaultEventHandler(event);
}
+int SVGAElement::tabIndex() const
+{
+ // Skip the supportsFocus check in SVGElement.
+ return Element::tabIndex();
+}
+
bool SVGAElement::supportsFocus() const
{
if (hasEditableStyle())
return SVGGraphicsElement::supportsFocus();
- return true;
+ // If not a link we should still be able to focus the element if it has a tabIndex.
+ return isLink() || Element::supportsFocus();
}
bool SVGAElement::isFocusable() const
@@ -204,23 +176,36 @@ bool SVGAElement::isFocusable() const
bool SVGAElement::isURLAttribute(const Attribute& attribute) const
{
- return attribute.name().localName() == hrefAttr || SVGGraphicsElement::isURLAttribute(attribute);
+ return attribute.name().localName() == XLinkNames::hrefAttr || SVGGraphicsElement::isURLAttribute(attribute);
}
bool SVGAElement::isMouseFocusable() const
{
- return false;
+ // Links are focusable by default, but only allow links with tabindex or contenteditable to be mouse focusable.
+ // https://bugs.webkit.org/show_bug.cgi?id=26856
+ if (isLink())
+ return Element::supportsFocus();
+
+ return SVGElement::isMouseFocusable();
}
-bool SVGAElement::isKeyboardFocusable(KeyboardEvent* event) const
+bool SVGAElement::isKeyboardFocusable(KeyboardEvent& event) const
{
- if (!isFocusable())
- return false;
-
- if (!document().frame())
- return false;
-
- return document().frame()->eventHandler().tabsToLinks(event);
+ if (isFocusable() && Element::supportsFocus())
+ return SVGElement::isKeyboardFocusable(event);
+
+ if (isLink())
+ return document().frame()->eventHandler().tabsToLinks(event);
+
+ return SVGElement::isKeyboardFocusable(event);
+}
+
+bool SVGAElement::canStartSelection() const
+{
+ if (!isLink())
+ return SVGElement::canStartSelection();
+
+ return hasEditableStyle();
}
bool SVGAElement::childShouldCreateRenderer(const Node& child) const
@@ -229,8 +214,9 @@ bool SVGAElement::childShouldCreateRenderer(const Node& child) const
// The 'a' element may contain any element that its parent may contain, except itself.
if (child.hasTagName(SVGNames::aTag))
return false;
- if (parentNode() && parentNode()->isSVGElement())
- return parentNode()->childShouldCreateRenderer(child);
+
+ if (parentElement() && parentElement()->isSVGElement())
+ return parentElement()->childShouldCreateRenderer(child);
return SVGElement::childShouldCreateRenderer(child);
}
@@ -241,5 +227,3 @@ bool SVGAElement::willRespondToMouseClickEvents()
}
} // namespace WebCore
-
-#endif // ENABLE(SVG)