Mouseenter/-leave not triggered when element under cursor is moved/removed

https://bugs.webkit.org/show_bug.cgi?id=120786

Reviewed by Antonio Gomes.

Source/WebCore:

When a hovered element is detached it will now emit a fake mousemove event
similar to what happens when a hovered element has CSS display set to none.

Test: fast/events/mouseenterleave-detached-element.html

* dom/Document.cpp:
(WebCore::Document::hoveredElementDidDetach):
* page/EventHandler.cpp:
(WebCore::EventHandler::EventHandler):
(WebCore::EventHandler::clear):
(WebCore::EventHandler::handleMouseMoveEvent):
* page/EventHandler.h:

LayoutTests:

Test of mouseenter/mouseleave events when a hovered element is removed.

* fast/events/mouseenterleave-detached-element-expected.txt: Added.
* fast/events/mouseenterleave-detached-element.html: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@155519 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 413f75b1
2013-09-11 Allan Sandfeld Jensen <allan.jensen@digia.com>
Mouseenter/-leave not triggered when element under cursor is moved/removed
https://bugs.webkit.org/show_bug.cgi?id=120786
Reviewed by Antonio Gomes.
Test of mouseenter/mouseleave events when a hovered element is removed.
* fast/events/mouseenterleave-detached-element-expected.txt: Added.
* fast/events/mouseenterleave-detached-element.html: Added.
2013-09-11 Krzysztof Czech <k.czech@samsung.com>
[ATK] Adds mapping MenuItemRadioRole to ATK
This is a test that mouseenter/mouseleave events are emitted correctly when a hovered element is removed from the document.
mouseenter on DIV#mydiv1
removing DIV#mydiv1
mouseenter on DIV#mydiv2
PASS
<!DOCTYPE html>
<html>
<head>
<script>
function log(message) {
document.getElementById('console').innerHTML += (message + "\n");
}
function logMouseEvent(ev) {
var target = (ev.target)? ev.target : ev.srcElement;
var targetName = target.nodeName;
if (target.id)
targetName += "#" + target.id;
log(ev.type + " on " + targetName);
}
function logMouseEventAndEnd(ev) {
logMouseEvent(ev);
log('PASS');
if (window.testRunner)
testRunner.notifyDone();
}
function timeoutAndEnd() {
log('FAIL');
if (window.testRunner)
testRunner.notifyDone();
}
function doTest() {
var div1 = document.getElementById('mydiv1');
var div2 = document.getElementById('mydiv2');
div1.addEventListener('mouseenter', logMouseEvent, false);
div1.addEventListener('mouseleave', logMouseEvent, false);
div2.addEventListener('mouseenter', logMouseEventAndEnd, false);
div2.addEventListener('mouseleave', logMouseEvent, false);
if (window.testRunner && window.eventSender) {
eventSender.mouseMoveTo(50, 50);
testRunner.dumpAsText();
// The event is not emitted synchronously so we need to wait until we get it.
testRunner.waitUntilDone();
window.setTimeout(timeoutAndEnd, 300);
}
log('removing DIV#mydiv1');
div1.parentNode.removeChild(div1);
}
</script>
</head>
<body onload="doTest()">
<div id=mydiv1 style="height:100px;"></div>
<div id=mydiv2 style="height:100px;"></div>
<p>This is a test that mouseenter/mouseleave events are emitted correctly when a hovered
element is removed from the document.
<pre id="console"></pre>
</body>
</html>
2013-09-11 Allan Sandfeld Jensen <allan.jensen@digia.com>
Mouseenter/-leave not triggered when element under cursor is moved/removed
https://bugs.webkit.org/show_bug.cgi?id=120786
Reviewed by Antonio Gomes.
When a hovered element is detached it will now emit a fake mousemove event
similar to what happens when a hovered element has CSS display set to none.
Test: fast/events/mouseenterleave-detached-element.html
* dom/Document.cpp:
(WebCore::Document::hoveredElementDidDetach):
* page/EventHandler.cpp:
(WebCore::EventHandler::EventHandler):
(WebCore::EventHandler::clear):
(WebCore::EventHandler::handleMouseMoveEvent):
* page/EventHandler.h:
2013-09-11 Krzysztof Czech <k.czech@samsung.com>
[ATK] Adds mapping MenuItemRadioRole to ATK
......@@ -3269,11 +3269,14 @@ void Document::hoveredElementDidDetach(Element* element)
if (!m_hoveredElement || element != m_hoveredElement)
return;
m_hoveredElement = element->parentElement();
while (m_hoveredElement && !m_hoveredElement->renderer())
m_hoveredElement = m_hoveredElement->parentElement();
RenderObject* hoverAncestor = element->renderer()->hoverAncestor();
if (hoverAncestor && hoverAncestor->node() && hoverAncestor->node()->isElementNode())
m_hoveredElement = toElement(hoverAncestor->node());
else
m_hoveredElement = 0;
if (frame())
frame()->eventHandler().scheduleHoverStateUpdate();
frame()->eventHandler().dispatchFakeMouseMoveEventSoon();
}
void Document::elementInActiveChainDidDetach(Element* element)
......
......@@ -319,7 +319,6 @@ EventHandler::EventHandler(Frame& frame)
#endif
, m_mouseDownWasSingleClickInSelection(false)
, m_selectionInitiationState(HaveNotStartedSelection)
, m_hoverTimer(this, &EventHandler::hoverTimerFired)
, m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired)
, m_autoscrollController(adoptPtr(new AutoscrollController))
, m_mouseDownMayStartAutoscroll(false)
......@@ -377,7 +376,6 @@ DragState& EventHandler::dragState()
void EventHandler::clear()
{
m_hoverTimer.stop();
m_cursorUpdateTimer.stop();
m_fakeMouseMoveEventTimer.stop();
#if ENABLE(CURSOR_VISIBILITY)
......@@ -1732,9 +1730,6 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, Hi
setLastKnownMousePosition(mouseEvent);
if (m_hoverTimer.isActive())
m_hoverTimer.stop();
m_cursorUpdateTimer.stop();
cancelFakeMouseMoveEvent();
......@@ -3101,12 +3096,6 @@ bool EventHandler::sendContextMenuEventForGesture(const PlatformGestureEvent& ev
#endif // ENABLE(GESTURE_EVENTS)
#endif // ENABLE(CONTEXT_MENUS)
void EventHandler::scheduleHoverStateUpdate()
{
if (!m_hoverTimer.isActive())
m_hoverTimer.startOneShot(0);
}
void EventHandler::scheduleCursorUpdate()
{
if (!m_cursorUpdateTimer.isActive())
......@@ -3190,22 +3179,6 @@ void EventHandler::resizeLayerDestroyed()
m_resizeLayer = 0;
}
void EventHandler::hoverTimerFired(Timer<EventHandler>*)
{
m_hoverTimer.stop();
ASSERT(m_frame.document());
if (RenderView* renderer = m_frame.contentRenderer()) {
if (FrameView* view = m_frame.view()) {
HitTestRequest request(HitTestRequest::Move | HitTestRequest::DisallowShadowContent);
HitTestResult result(view->windowToContents(m_lastKnownMousePosition));
renderer->hitTest(request, result);
m_frame.document()->updateHoverActiveState(request, result.innerElement());
}
}
}
bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& evt)
{
// FIXME: Ignoring the state of Shift key is what neither IE nor Firefox do.
......
......@@ -287,7 +287,6 @@ private:
OptionalCursor selectCursor(const HitTestResult&, bool shiftKey);
void hoverTimerFired(Timer<EventHandler>*);
void cursorUpdateTimerFired(Timer<EventHandler>*);
bool logicalScrollOverflow(ScrollLogicalDirection, ScrollGranularity, Node* startingNode = 0);
......@@ -430,7 +429,6 @@ private:
bool m_panScrollButtonPressed;
Timer<EventHandler> m_hoverTimer;
Timer<EventHandler> m_cursorUpdateTimer;
OwnPtr<AutoscrollController> m_autoscrollController;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment