| Index: WebCore/html/HTMLAnchorElement.cpp
|
| ===================================================================
|
| --- WebCore/html/HTMLAnchorElement.cpp (revision 67261)
|
| +++ WebCore/html/HTMLAnchorElement.cpp (working copy)
|
| @@ -2,7 +2,7 @@
|
| * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
|
| * (C) 1999 Antti Koivisto (koivisto@kde.org)
|
| * (C) 2000 Simon Hausmann <hausmann@kde.org>
|
| - * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
|
| + * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
|
| * (C) 2006 Graham Dennis (graham.dennis@gmail.com)
|
| *
|
| * This library is free software; you can redistribute it and/or
|
| @@ -105,117 +105,67 @@
|
| return hasNonEmptyBoundingBox();
|
| }
|
|
|
| -void HTMLAnchorElement::defaultEventHandler(Event* evt)
|
| +static void appendServerMapMousePosition(String& url, Event* event)
|
| {
|
| - // React on clicks and on keypresses.
|
| - // Don't make this KEYUP_EVENT again, it makes khtml follow links it shouldn't,
|
| - // when pressing Enter in the combo.
|
| - if (isLink() && (evt->type() == eventNames().clickEvent || (evt->type() == eventNames().keydownEvent && focused()))) {
|
| - MouseEvent* e = 0;
|
| - if (evt->type() == eventNames().clickEvent && evt->isMouseEvent())
|
| - e = static_cast<MouseEvent*>(evt);
|
| + if (!event->isMouseEvent())
|
| + return;
|
|
|
| - KeyboardEvent* k = 0;
|
| - if (evt->type() == eventNames().keydownEvent && evt->isKeyboardEvent())
|
| - k = static_cast<KeyboardEvent*>(evt);
|
| + ASSERT(event->target());
|
| + Node* target = event->target()->toNode();
|
| + ASSERT(target);
|
| + if (!target->hasTagName(imgTag))
|
| + return;
|
|
|
| - if (e && e->button() == RightButton) {
|
| - HTMLElement::defaultEventHandler(evt);
|
| - return;
|
| - }
|
| + HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(event->target()->toNode());
|
| + if (!imageElement || !imageElement->isServerMap())
|
| + return;
|
|
|
| - // If the link is editable, then we need to check the settings to see whether or not to follow the link
|
| - if (isContentEditable()) {
|
| - EditableLinkBehavior editableLinkBehavior = EditableLinkDefaultBehavior;
|
| - if (Settings* settings = document()->settings())
|
| - editableLinkBehavior = settings->editableLinkBehavior();
|
| -
|
| - switch (editableLinkBehavior) {
|
| - // Always follow the link (Safari 2.0 behavior)
|
| - default:
|
| - case EditableLinkDefaultBehavior:
|
| - case EditableLinkAlwaysLive:
|
| - break;
|
| + RenderImage* renderer = toRenderImage(imageElement->renderer());
|
| + if (!renderer)
|
| + return;
|
|
|
| - case EditableLinkNeverLive:
|
| - HTMLElement::defaultEventHandler(evt);
|
| - return;
|
| + // FIXME: This should probably pass true for useTransforms.
|
| + FloatPoint absolutePosition = renderer->absoluteToLocal(FloatPoint(static_cast<MouseEvent*>(event)->pageX(), static_cast<MouseEvent*>(event)->pageY()));
|
| + int x = absolutePosition.x();
|
| + int y = absolutePosition.y();
|
| + url += "?";
|
| + url += String::number(x);
|
| + url += ",";
|
| + url += String::number(y);
|
| +}
|
|
|
| - // If the selection prior to clicking on this link resided in the same editable block as this link,
|
| - // and the shift key isn't pressed, we don't want to follow the link
|
| - case EditableLinkLiveWhenNotFocused:
|
| - if (e && !e->shiftKey() && m_rootEditableElementForSelectionOnMouseDown == rootEditableElement()) {
|
| - HTMLElement::defaultEventHandler(evt);
|
| - return;
|
| - }
|
| - break;
|
| -
|
| - // Only follow the link if the shift key is down (WinIE/Firefox behavior)
|
| - case EditableLinkOnlyLiveWithShiftKey:
|
| - if (e && !e->shiftKey()) {
|
| - HTMLElement::defaultEventHandler(evt);
|
| - return;
|
| - }
|
| - break;
|
| - }
|
| +void HTMLAnchorElement::defaultEventHandler(Event* event)
|
| +{
|
| + if (isLink()) {
|
| + if (focused() && isEnterKeyKeydownEvent(event) && treatLinkAsLiveForEventType(NonMouseEvent)) {
|
| + event->setDefaultHandled();
|
| + dispatchSimulatedClick(event);
|
| + return;
|
| }
|
|
|
| - if (k) {
|
| - if (k->keyIdentifier() != "Enter") {
|
| - HTMLElement::defaultEventHandler(evt);
|
| - return;
|
| - }
|
| - evt->setDefaultHandled();
|
| - dispatchSimulatedClick(evt);
|
| + if (isLinkClick(event) && treatLinkAsLiveForEventType(eventType(event))) {
|
| + String url = deprecatedParseURL(getAttribute(hrefAttr));
|
| + appendServerMapMousePosition(url, event);
|
| + handleLinkClick(event, document(), url, getAttribute(targetAttr), hasRel(RelationNoReferrer));
|
| return;
|
| }
|
|
|
| - String url = deprecatedParseURL(getAttribute(hrefAttr));
|
| -
|
| - ASSERT(evt->target());
|
| - ASSERT(evt->target()->toNode());
|
| - if (evt->target()->toNode()->hasTagName(imgTag)) {
|
| - HTMLImageElement* img = static_cast<HTMLImageElement*>(evt->target()->toNode());
|
| - if (img && img->isServerMap()) {
|
| - RenderImage* r = toRenderImage(img->renderer());
|
| - if (r && e) {
|
| - // FIXME: broken with transforms
|
| - FloatPoint absPos = r->localToAbsolute();
|
| - int x = e->pageX() - absPos.x();
|
| - int y = e->pageY() - absPos.y();
|
| - url += "?";
|
| - url += String::number(x);
|
| - url += ",";
|
| - url += String::number(y);
|
| - } else {
|
| - evt->setDefaultHandled();
|
| - HTMLElement::defaultEventHandler(evt);
|
| - return;
|
| - }
|
| + if (isContentEditable()) {
|
| + // This keeps track of the editable block that the selection was in (if it was in one) just before the link was clicked
|
| + // for the LiveWhenNotFocused editable link behavior
|
| + if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() != RightButton && document()->frame() && document()->frame()->selection()) {
|
| + m_rootEditableElementForSelectionOnMouseDown = document()->frame()->selection()->rootEditableElement();
|
| + m_wasShiftKeyDownOnMouseDown = static_cast<MouseEvent*>(event)->shiftKey();
|
| + } else if (event->type() == eventNames().mouseoverEvent) {
|
| + // These are cleared on mouseover and not mouseout because their values are needed for drag events,
|
| + // but drag events happen after mouse out events.
|
| + m_rootEditableElementForSelectionOnMouseDown = 0;
|
| + m_wasShiftKeyDownOnMouseDown = false;
|
| }
|
| }
|
| -
|
| - if (!evt->defaultPrevented() && document()->frame())
|
| - document()->frame()->loader()->urlSelected(document()->completeURL(url), getAttribute(targetAttr), evt, false, false, true, hasRel(RelationNoReferrer) ? NoReferrer : SendReferrer);
|
| -
|
| - evt->setDefaultHandled();
|
| - } else if (isLink() && isContentEditable()) {
|
| - // This keeps track of the editable block that the selection was in (if it was in one) just before the link was clicked
|
| - // for the LiveWhenNotFocused editable link behavior
|
| - if (evt->type() == eventNames().mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() != RightButton && document()->frame() && document()->frame()->selection()) {
|
| - MouseEvent* e = static_cast<MouseEvent*>(evt);
|
| -
|
| - m_rootEditableElementForSelectionOnMouseDown = document()->frame()->selection()->rootEditableElement();
|
| - m_wasShiftKeyDownOnMouseDown = e && e->shiftKey();
|
| - } else if (evt->type() == eventNames().mouseoverEvent) {
|
| - // These are cleared on mouseover and not mouseout because their values are needed for drag events, but these happen
|
| - // after mouse out events.
|
| - m_rootEditableElementForSelectionOnMouseDown = 0;
|
| - m_wasShiftKeyDownOnMouseDown = false;
|
| - }
|
| }
|
|
|
| - HTMLElement::defaultEventHandler(evt);
|
| + HTMLElement::defaultEventHandler(event);
|
| }
|
|
|
| void HTMLAnchorElement::setActive(bool down, bool pause)
|
| @@ -512,32 +462,69 @@
|
|
|
| bool HTMLAnchorElement::isLiveLink() const
|
| {
|
| - if (!isLink())
|
| - return false;
|
| + return isLink() && treatLinkAsLiveForEventType(m_wasShiftKeyDownOnMouseDown ? MouseEventWithShiftKey : MouseEventWithoutShiftKey);
|
| +}
|
| +
|
| +HTMLAnchorElement::EventType HTMLAnchorElement::eventType(Event* event)
|
| +{
|
| + if (!event->isMouseEvent())
|
| + return NonMouseEvent;
|
| + return static_cast<MouseEvent*>(event)->shiftKey() ? MouseEventWithShiftKey : MouseEventWithoutShiftKey;
|
| +}
|
| +
|
| +bool HTMLAnchorElement::treatLinkAsLiveForEventType(EventType eventType) const
|
| +{
|
| if (!isContentEditable())
|
| return true;
|
| -
|
| - EditableLinkBehavior editableLinkBehavior = EditableLinkDefaultBehavior;
|
| - if (Settings* settings = document()->settings())
|
| - editableLinkBehavior = settings->editableLinkBehavior();
|
| -
|
| - switch (editableLinkBehavior) {
|
| - default:
|
| - case EditableLinkDefaultBehavior:
|
| - case EditableLinkAlwaysLive:
|
| - return true;
|
|
|
| - case EditableLinkNeverLive:
|
| - return false;
|
| + Settings* settings = document()->settings();
|
| + if (!settings)
|
| + return true;
|
|
|
| - // Don't set the link to be live if the current selection is in the same editable block as
|
| - // this link or if the shift key is down
|
| - case EditableLinkLiveWhenNotFocused:
|
| - return m_wasShiftKeyDownOnMouseDown || m_rootEditableElementForSelectionOnMouseDown != rootEditableElement();
|
| -
|
| - case EditableLinkOnlyLiveWithShiftKey:
|
| - return m_wasShiftKeyDownOnMouseDown;
|
| + switch (settings->editableLinkBehavior()) {
|
| + case EditableLinkDefaultBehavior:
|
| + case EditableLinkAlwaysLive:
|
| + return true;
|
| +
|
| + case EditableLinkNeverLive:
|
| + return false;
|
| +
|
| + // If the selection prior to clicking on this link resided in the same editable block as this link,
|
| + // and the shift key isn't pressed, we don't want to follow the link.
|
| + case EditableLinkLiveWhenNotFocused:
|
| + return eventType == MouseEventWithShiftKey || (eventType == MouseEventWithoutShiftKey && m_rootEditableElementForSelectionOnMouseDown != rootEditableElement());
|
| +
|
| + case EditableLinkOnlyLiveWithShiftKey:
|
| + return eventType == MouseEventWithShiftKey;
|
| }
|
| +
|
| + ASSERT_NOT_REACHED();
|
| + return false;
|
| }
|
|
|
| +bool isEnterKeyKeydownEvent(Event* event)
|
| +{
|
| + return event->type() == eventNames().keydownEvent && event->isKeyboardEvent() && static_cast<KeyboardEvent*>(event)->keyIdentifier() == "Enter";
|
| }
|
| +
|
| +bool isMiddleMouseButtonEvent(Event* event)
|
| +{
|
| + return event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == MiddleButton;
|
| +}
|
| +
|
| +bool isLinkClick(Event* event)
|
| +{
|
| + return event->type() == eventNames().clickEvent && (!event->isMouseEvent() || static_cast<MouseEvent*>(event)->button() != RightButton);
|
| +}
|
| +
|
| +void handleLinkClick(Event* event, Document* document, const String& url, const String& target, bool hideReferrer)
|
| +{
|
| + event->setDefaultHandled();
|
| +
|
| + Frame* frame = document->frame();
|
| + if (!frame)
|
| + return;
|
| + frame->loader()->urlSelected(document->completeURL(url), target, event, false, false, true, hideReferrer ? NoReferrer : SendReferrer);
|
| +}
|
| +
|
| +}
|
|
|