1/* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20#ifndef EventRetargeter_h 21#define EventRetargeter_h 22 23#include "ContainerNode.h" 24#include "EventContext.h" 25#include "ShadowRoot.h" 26#include <wtf/HashMap.h> 27#include <wtf/PassRefPtr.h> 28#include <wtf/RefPtr.h> 29 30#if ENABLE(SVG) 31#include "SVGElementInstance.h" 32#include "SVGNames.h" 33#include "SVGUseElement.h" 34#endif 35 36namespace WebCore { 37 38class EventTarget; 39class FocusEvent; 40class MouseEvent; 41class Node; 42#if ENABLE(TOUCH_EVENTS) 43class TouchEvent; 44#endif 45class TreeScope; 46 47enum EventDispatchBehavior { 48 RetargetEvent, 49 StayInsideShadowDOM 50}; 51 52class EventRetargeter { 53public: 54 static void calculateEventPath(Node*, Event*, EventPath&); 55 static void adjustForMouseEvent(Node*, const MouseEvent&, EventPath&); 56 static void adjustForFocusEvent(Node*, const FocusEvent&, EventPath&); 57#if ENABLE(TOUCH_EVENTS) 58 typedef Vector<RefPtr<TouchList> > EventPathTouchLists; 59 static void adjustForTouchEvent(Node*, const TouchEvent&, EventPath&); 60#endif 61 static EventTarget* eventTargetRespectingTargetRules(Node* referenceNode); 62 63private: 64 typedef Vector<RefPtr<Node> > AdjustedNodes; 65 typedef HashMap<TreeScope*, Node*> RelatedNodeMap; 66 enum EventWithRelatedTargetDispatchBehavior { 67 StopAtBoundaryIfNeeded, 68 DoesNotStopAtBoundary 69 }; 70 static void adjustForRelatedTarget(const Node*, EventTarget* relatedTarget, EventPath&); 71 static void calculateAdjustedNodes(const Node*, const Node* relatedNode, EventWithRelatedTargetDispatchBehavior, EventPath&, AdjustedNodes&); 72 static void buildRelatedNodeMap(const Node*, RelatedNodeMap&); 73 static Node* findRelatedNode(TreeScope*, RelatedNodeMap&); 74#if ENABLE(TOUCH_EVENTS) 75 static void adjustTouchList(const Node*, const TouchList*, const EventPath&, EventPathTouchLists&); 76#endif 77}; 78 79inline EventTarget* EventRetargeter::eventTargetRespectingTargetRules(Node* referenceNode) 80{ 81 ASSERT(referenceNode); 82 83 if (referenceNode->isPseudoElement()) 84 return referenceNode->parentNode(); 85 86#if ENABLE(SVG) 87 if (!referenceNode->isSVGElement() || !referenceNode->isInShadowTree()) 88 return referenceNode; 89 90 // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included 91 // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects 92 Node* rootNode = referenceNode->treeScope()->rootNode(); 93 Element* shadowHostElement = rootNode->isShadowRoot() ? toShadowRoot(rootNode)->host() : 0; 94 // At this time, SVG nodes are not supported in non-<use> shadow trees. 95 if (!shadowHostElement || !shadowHostElement->hasTagName(SVGNames::useTag)) 96 return referenceNode; 97 SVGUseElement* useElement = static_cast<SVGUseElement*>(shadowHostElement); 98 if (SVGElementInstance* instance = useElement->instanceForShadowTreeElement(referenceNode)) 99 return instance; 100#endif 101 102 return referenceNode; 103} 104 105} 106 107#endif // EventRetargeter_h 108