Changeset 149173 in webkit
- Timestamp:
- Apr 26, 2013 2:42:11 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r149171 r149173 1 2013-04-26 Allan Sandfeld Jensen <allan.jensen@digia.com> 2 3 Mouseenter and mouseleave events not supported 4 https://bugs.webkit.org/show_bug.cgi?id=18930 5 6 Reviewed by David Hyatt. 7 8 To new tests that mouseenter and mouseleave works in both bubbling and capture phase. 9 10 * fast/events/mouseenter-mouseleave-capture-expected.txt: Added. 11 * fast/events/mouseenter-mouseleave-capture.html: Added. 12 * fast/events/mouseenter-mouseleave-expected.txt: Added. 13 * fast/events/mouseenter-mouseleave.html: Added. 14 1 15 2013-04-26 Christophe Dumez <ch.dumez@sisa.samsung.com> 2 16 -
trunk/Source/WebCore/ChangeLog
r149170 r149173 1 2013-04-26 Allan Sandfeld Jensen <allan.jensen@digia.com> 2 3 Mouseenter and mouseleave events not supported 4 https://bugs.webkit.org/show_bug.cgi?id=18930 5 6 Reviewed by David Hyatt. 7 8 Implements mouseenter and mouseleave events from W3C DOM Level 3 Events. 9 These event are already supported by all other major browsers. 10 11 To avoid performance regressions the new events are only dispatched when 12 there are event listeners for them. 13 14 Tests: fast/events/mouseenter-mouseleave-capture.html 15 fast/events/mouseenter-mouseleave.html 16 17 * bindings/scripts/CodeGenerator.pm: 18 * dom/Document.cpp: 19 (WebCore::Document::prepareMouseEvent): 20 (WebCore::Document::updateHoverActiveState): 21 * dom/Document.h: 22 (Document): 23 * dom/Document.idl: 24 * dom/Element.h: 25 (Element): 26 * dom/Element.idl: 27 * dom/EventListenerMap.cpp: 28 (WebCore::EventListenerMap::containsCapturing): 29 * dom/EventListenerMap.h: 30 (EventListenerMap): 31 * dom/EventNames.h: 32 * dom/EventTarget.h: 33 (EventTarget): 34 (WebCore::EventTarget::hasCapturingEventListeners): 35 * dom/MouseEvent.cpp: 36 (WebCore::MouseEvent::create): 37 (WebCore::MouseEvent::toElement): 38 (WebCore::MouseEvent::fromElement): 39 * html/HTMLAttributeNames.in: 40 * html/HTMLElement.cpp: 41 (WebCore::HTMLElement::eventNameForAttributeName): 42 * page/DOMWindow.h: 43 (DOMWindow): 44 * page/DOMWindow.idl: 45 * svg/SVGElement.cpp: 46 (WebCore::SVGElement::parseAttribute): 47 * svg/SVGElementInstance.h: 48 (SVGElementInstance): 49 * svg/SVGElementInstance.idl: 50 1 51 2013-04-26 Christophe Dumez <ch.dumez@sisa.samsung.com> 2 52 -
trunk/Source/WebCore/bindings/scripts/CodeGenerator.pm
r147167 r149173 68 68 my %svgAttributesInHTMLHash = ("class" => 1, "id" => 1, "onabort" => 1, "onclick" => 1, 69 69 "onerror" => 1, "onload" => 1, "onmousedown" => 1, 70 "onmouseenter" => 1, "onmouseleave" => 1, 70 71 "onmousemove" => 1, "onmouseout" => 1, "onmouseover" => 1, 71 72 "onmouseup" => 1, "onresize" => 1, "onscroll" => 1, -
trunk/Source/WebCore/dom/Document.cpp
r149131 r149173 3052 3052 3053 3053 if (!request.readOnly()) 3054 updateHoverActiveState(request, result.innerElement() );3054 updateHoverActiveState(request, result.innerElement(), &event); 3055 3055 3056 3056 return MouseEventWithHitTestResults(event, result); … … 5902 5902 } 5903 5903 5904 void Document::updateHoverActiveState(const HitTestRequest& request, Element* innerElement )5904 void Document::updateHoverActiveState(const HitTestRequest& request, Element* innerElement, const PlatformMouseEvent* event) 5905 5905 { 5906 5906 ASSERT(!request.readOnly()); … … 5971 5971 Vector<RefPtr<Node>, 32> nodesToAddToChain; 5972 5972 5973 // mouseenter and mouseleave events are only dispatched if there is a capturing eventhandler on an ancestor 5974 // or a normal eventhandler on the element itself (they don't bubble). 5975 // This optimization is necessary since these events can cause O(n²) capturing event-handler checks. 5976 bool hasCapturingMouseEnterListener = false; 5977 bool hasCapturingMouseLeaveListener = false; 5978 if (event && newHoverNode != oldHoverNode.get()) { 5979 for (Node* curr = newHoverNode; curr; curr = curr->parentOrShadowHostNode()) { 5980 if (curr->hasCapturingEventListeners(eventNames().mouseenterEvent)) { 5981 hasCapturingMouseEnterListener = true; 5982 break; 5983 } 5984 } 5985 for (Node* curr = oldHoverNode.get(); curr; curr = curr->parentOrShadowHostNode()) { 5986 if (curr->hasCapturingEventListeners(eventNames().mouseleaveEvent)) { 5987 hasCapturingMouseLeaveListener = true; 5988 break; 5989 } 5990 } 5991 } 5992 5973 5993 if (oldHoverObj != newHoverObj) { 5974 5994 // The old hover path only needs to be cleared up to (and not including) the common ancestor; … … 5991 6011 5992 6012 size_t removeCount = nodesToRemoveFromChain.size(); 5993 for (size_t i = 0; i < removeCount; ++i) 6013 for (size_t i = 0; i < removeCount; ++i) { 5994 6014 nodesToRemoveFromChain[i]->setHovered(false); 5995 6015 if (event && (hasCapturingMouseLeaveListener || nodesToRemoveFromChain[i]->hasEventListeners(eventNames().mouseleaveEvent))) 6016 nodesToRemoveFromChain[i]->dispatchMouseEvent(*event, eventNames().mouseleaveEvent, 0, newHoverNode); 6017 } 6018 6019 bool sawCommonAncestor = false; 5996 6020 size_t addCount = nodesToAddToChain.size(); 5997 6021 for (size_t i = 0; i < addCount; ++i) { 5998 6022 if (allowActiveChanges) 5999 6023 nodesToAddToChain[i]->setActive(true); 6000 nodesToAddToChain[i]->setHovered(true); 6024 if (ancestor && nodesToAddToChain[i] == ancestor->node()) 6025 sawCommonAncestor = true; 6026 if (!sawCommonAncestor) { 6027 // Elements after the common hover ancestor does not change hover state, but are iterated over because they may change active state. 6028 nodesToAddToChain[i]->setHovered(true); 6029 if (event && (hasCapturingMouseEnterListener || nodesToAddToChain[i]->hasEventListeners(eventNames().mouseenterEvent))) 6030 nodesToAddToChain[i]->dispatchMouseEvent(*event, eventNames().mouseenterEvent, 0, oldHoverNode.get()); 6031 } 6001 6032 } 6002 6033 -
trunk/Source/WebCore/dom/Document.h
r149131 r149173 266 266 DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup); 267 267 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown); 268 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseenter); 269 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseleave); 268 270 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove); 269 271 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout); … … 699 701 void activeChainNodeDetached(Node*); 700 702 701 void updateHoverActiveState(const HitTestRequest&, Element* );703 void updateHoverActiveState(const HitTestRequest&, Element*, const PlatformMouseEvent* = 0); 702 704 703 705 // Updates for :target (CSS3 selector). -
trunk/Source/WebCore/dom/Document.idl
r148098 r149173 291 291 [NotEnumerable] attribute EventListener onload; 292 292 [NotEnumerable] attribute EventListener onmousedown; 293 [NotEnumerable] attribute EventListener onmouseenter; 294 [NotEnumerable] attribute EventListener onmouseleave; 293 295 [NotEnumerable] attribute EventListener onmousemove; 294 296 [NotEnumerable] attribute EventListener onmouseout; -
trunk/Source/WebCore/dom/Element.h
r149061 r149173 200 200 DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup); 201 201 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown); 202 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseenter); 203 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseleave); 202 204 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove); 203 205 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout); -
trunk/Source/WebCore/dom/Element.idl
r147857 r149173 183 183 [NotEnumerable] attribute EventListener onload; 184 184 [NotEnumerable] attribute EventListener onmousedown; 185 [NotEnumerable] attribute EventListener onmouseenter; 186 [NotEnumerable] attribute EventListener onmouseleave; 185 187 [NotEnumerable] attribute EventListener onmousemove; 186 188 [NotEnumerable] attribute EventListener onmouseout; -
trunk/Source/WebCore/dom/EventListenerMap.cpp
r128002 r149173 79 79 } 80 80 81 bool EventListenerMap::containsCapturing(const AtomicString& eventType) const 82 { 83 for (unsigned i = 0; i < m_entries.size(); ++i) { 84 if (m_entries[i].first == eventType) { 85 const EventListenerVector* vector = m_entries[i].second.get(); 86 for (unsigned j = 0; j < vector->size(); ++j) { 87 if (vector->at(j).useCapture) 88 return true; 89 } 90 } 91 } 92 return false; 93 } 94 81 95 void EventListenerMap::clear() 82 96 { -
trunk/Source/WebCore/dom/EventListenerMap.h
r128002 r149173 51 51 bool isEmpty() const { return m_entries.isEmpty(); } 52 52 bool contains(const AtomicString& eventType) const; 53 bool containsCapturing(const AtomicString& eventType) const; 53 54 54 55 void clear(); -
trunk/Source/WebCore/dom/EventNames.h
r148731 r149173 90 90 macro(message) \ 91 91 macro(mousedown) \ 92 macro(mouseenter) \ 93 macro(mouseleave) \ 92 94 macro(mousemove) \ 93 95 macro(mouseout) \ -
trunk/Source/WebCore/dom/EventTarget.h
r148785 r149173 127 127 bool hasEventListeners(); 128 128 bool hasEventListeners(const AtomicString& eventType); 129 bool hasCapturingEventListeners(const AtomicString& eventType); 129 130 const EventListenerVector& getEventListeners(const AtomicString& eventType); 130 131 … … 207 208 } 208 209 210 inline bool EventTarget::hasCapturingEventListeners(const AtomicString& eventType) 211 { 212 EventTargetData* d = eventTargetData(); 213 if (!d) 214 return false; 215 return d->eventListenerMap.containsCapturing(eventType); 216 } 217 209 218 } // namespace WebCore 210 219 -
trunk/Source/WebCore/dom/MouseEvent.cpp
r147135 r149173 58 58 ASSERT(event.type() == PlatformEvent::MouseMoved || event.button() != NoButton); 59 59 60 bool isCancelable = eventType != eventNames().mousemoveEvent; 61 62 return MouseEvent::create(eventType, true, isCancelable, view, 60 bool isMouseEnterOrLeave = eventType == eventNames().mouseenterEvent || eventType == eventNames().mouseleaveEvent; 61 bool isCancelable = eventType != eventNames().mousemoveEvent && !isMouseEnterOrLeave; 62 bool canBubble = !isMouseEnterOrLeave; 63 64 return MouseEvent::create(eventType, canBubble, isCancelable, view, 63 65 detail, event.globalPosition().x(), event.globalPosition().y(), event.position().x(), event.position().y(), 64 66 #if ENABLE(POINTER_LOCK) … … 203 205 { 204 206 // MSIE extension - "the object toward which the user is moving the mouse pointer" 205 if (type() == eventNames().mouseoutEvent )207 if (type() == eventNames().mouseoutEvent || type() == eventNames().mouseleaveEvent) 206 208 return relatedTarget() ? relatedTarget()->toNode() : 0; 207 209 … … 212 214 { 213 215 // MSIE extension - "object from which activation or the mouse pointer is exiting during the event" (huh?) 214 if (type() != eventNames().mouseoutEvent )216 if (type() != eventNames().mouseoutEvent && type() != eventNames().mouseleaveEvent) 215 217 return relatedTarget() ? relatedTarget()->toNode() : 0; 216 218 -
trunk/Source/WebCore/html/HTMLAttributeNames.in
r148731 r149173 209 209 onloadstart 210 210 onmousedown 211 onmouseenter 212 onmouseleave 211 213 onmousemove 212 214 onmouseout -
trunk/Source/WebCore/html/HTMLElement.cpp
r148373 r149173 227 227 attributeNameToEventNameMap.set(ondblclickAttr.localName(), eventNames().dblclickEvent); 228 228 attributeNameToEventNameMap.set(onmousedownAttr.localName(), eventNames().mousedownEvent); 229 attributeNameToEventNameMap.set(onmouseenterAttr.localName(), eventNames().mouseenterEvent); 230 attributeNameToEventNameMap.set(onmouseleaveAttr.localName(), eventNames().mouseleaveEvent); 229 231 attributeNameToEventNameMap.set(onmousemoveAttr.localName(), eventNames().mousemoveEvent); 230 232 attributeNameToEventNameMap.set(onmouseoutAttr.localName(), eventNames().mouseoutEvent); -
trunk/Source/WebCore/page/DOMWindow.h
r148508 r149173 317 317 DEFINE_ATTRIBUTE_EVENT_LISTENER(message); 318 318 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown); 319 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseenter); 320 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseleave); 319 321 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove); 320 322 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout); -
trunk/Source/WebCore/page/DOMWindow.idl
r148731 r149173 247 247 attribute EventListener onmessage; 248 248 attribute EventListener onmousedown; 249 attribute EventListener onmouseenter; 250 attribute EventListener onmouseleave; 249 251 attribute EventListener onmousemove; 250 252 attribute EventListener onmouseout; -
trunk/Source/WebCore/svg/SVGElement.cpp
r148865 r149173 318 318 else if (name == onmousedownAttr) 319 319 setAttributeEventListener(eventNames().mousedownEvent, createAttributeEventListener(this, name, value)); 320 else if (name == onmouseenterAttr) 321 setAttributeEventListener(eventNames().mouseenterEvent, createAttributeEventListener(this, name, value)); 322 else if (name == onmouseleaveAttr) 323 setAttributeEventListener(eventNames().mouseleaveEvent, createAttributeEventListener(this, name, value)); 320 324 else if (name == onmousemoveAttr) 321 325 setAttributeEventListener(eventNames().mousemoveEvent, createAttributeEventListener(this, name, value)); -
trunk/Source/WebCore/svg/SVGElementInstance.h
r141524 r149173 117 117 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(correspondingElement(), load); 118 118 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(correspondingElement(), mousedown); 119 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(correspondingElement(), mouseenter); 120 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(correspondingElement(), mouseleave); 119 121 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(correspondingElement(), mousemove); 120 122 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(correspondingElement(), mouseout); -
trunk/Source/WebCore/svg/SVGElementInstance.idl
r141730 r149173 63 63 attribute [NotEnumerable] EventListener onload; 64 64 attribute [NotEnumerable] EventListener onmousedown; 65 attribute [NotEnumerable] EventListener onmouseenter; 66 attribute [NotEnumerable] EventListener onmouseleave; 65 67 attribute [NotEnumerable] EventListener onmousemove; 66 68 attribute [NotEnumerable] EventListener onmouseout;
Note: See TracChangeset
for help on using the changeset viewer.