From c6093430aefa067fc411385027b529d14c87b0ea Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Thu, 20 Jun 2013 23:13:10 +0200 Subject: [PATCH] Canvas: Fix creating/forwarding of mouseenter/mouseleave events. --- simgear/canvas/CanvasEventManager.cxx | 43 +++++++++++++++++++++++-- simgear/canvas/elements/CanvasImage.cxx | 2 +- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/simgear/canvas/CanvasEventManager.cxx b/simgear/canvas/CanvasEventManager.cxx index 7a05a23e..ed4a90c1 100644 --- a/simgear/canvas/CanvasEventManager.cxx +++ b/simgear/canvas/CanvasEventManager.cxx @@ -157,21 +157,55 @@ namespace canvas void EventManager::handleMove( const MouseEventPtr& event, const EventPropagationPath& path ) { - if( _last_mouse_over.path == path ) + EventPropagationPath& last_path = _last_mouse_over.path; + if( last_path == path ) return; - if( !_last_mouse_over.path.empty() ) + // Leave old element + if( !last_path.empty() ) { MouseEventPtr mouseout(new MouseEvent(*event)); mouseout->type = Event::MOUSE_OUT; - propagateEvent(mouseout, _last_mouse_over.path); + propagateEvent(mouseout, last_path); + + // Send a mouseleave event to all ancestors of the currently left element + // which are not ancestor of the new element currently entered + EventPropagationPath path_leave = last_path; + for(size_t i = path_leave.size() - 1; i > 0; --i) + { + if( i < path.size() && path[i] == path_leave[i] ) + break; + + MouseEventPtr mouseleave(new MouseEvent(*event)); + mouseleave->type = Event::MOUSE_LEAVE; + propagateEvent(mouseleave, path_leave); + + path_leave.pop_back(); + } } + // Enter new element if( !path.empty() ) { MouseEventPtr mouseover(new MouseEvent(*event)); mouseover->type = Event::MOUSE_OVER; propagateEvent(mouseover, path); + + // Send a mouseenter event to all ancestors of the currently entered + // element which are not ancestor of the old element currently being + // left + EventPropagationPath path_enter; + for(size_t i = 0; i < path.size(); ++i) + { + path_enter.push_back(path[i]); + + if( i < last_path.size() && path[i] == last_path[i] ) + continue; + + MouseEventPtr mouseenter(new MouseEvent(*event)); + mouseenter->type = Event::MOUSE_ENTER; + propagateEvent(mouseenter, path_enter); + } } _last_mouse_over.path = path; @@ -248,6 +282,9 @@ namespace canvas EventManager::getCommonAncestor( const EventPropagationPath& path1, const EventPropagationPath& path2 ) const { + if( path1.empty() || path2.empty() ) + return EventPropagationPath(); + if( path1.back().element.lock() == path2.back().element.lock() ) return path2; diff --git a/simgear/canvas/elements/CanvasImage.cxx b/simgear/canvas/elements/CanvasImage.cxx index 5500f32d..5b88807b 100644 --- a/simgear/canvas/elements/CanvasImage.cxx +++ b/simgear/canvas/elements/CanvasImage.cxx @@ -470,7 +470,7 @@ namespace canvas mouse_event->local_pos = mouse_event->client_pos; } - return handled || src_canvas->handleMouseEvent(mouse_event); + return handled | src_canvas->handleMouseEvent(mouse_event); } //---------------------------------------------------------------------------- -- 2.39.5