Chromium Code Reviews| Index: ui/views/widget/root_view.cc |
| diff --git a/ui/views/widget/root_view.cc b/ui/views/widget/root_view.cc |
| index f3ad2a08d6849b779e7bf5634218b57b6144176f..35e85a37a00f975c5cc780bf40ed941a84c365ef 100644 |
| --- a/ui/views/widget/root_view.cc |
| +++ b/ui/views/widget/root_view.cc |
| @@ -19,7 +19,6 @@ |
| #include "ui/views/views_switches.h" |
| #include "ui/views/widget/widget.h" |
| #include "ui/views/widget/widget_delegate.h" |
| -#include "ui/views/widget/widget_deletion_observer.h" |
| #if defined(USE_AURA) |
| #include "ui/base/cursor/cursor.h" |
| @@ -141,7 +140,11 @@ void RootView::DispatchKeyEvent(ui::KeyEvent* event) { |
| void RootView::DispatchScrollEvent(ui::ScrollEvent* event) { |
| for (View* v = GetEventHandlerForPoint(event->location()); |
| v && v != this && !event->stopped_propagation(); v = v->parent()) { |
| - DispatchEventToTarget(v, event); |
| + ui::EventDispatchDetails dispatch_details = DispatchEventToTarget(v, event); |
| + if (dispatch_details.dispatcher_destroyed || |
| + dispatch_details.target_destroyed) { |
| + return; |
| + } |
| } |
| if (event->handled() || event->type() != ui::ET_SCROLL) |
| @@ -165,11 +168,14 @@ void RootView::DispatchTouchEvent(ui::TouchEvent* event) { |
| if (touch_pressed_handler_) { |
| ui::TouchEvent touch_event(*event, static_cast<View*>(this), |
| touch_pressed_handler_); |
| - DispatchEventToTarget(touch_pressed_handler_, &touch_event); |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(touch_pressed_handler_, &touch_event); |
| if (touch_event.handled()) |
| event->SetHandled(); |
| if (touch_event.stopped_propagation()) |
| event->StopPropagation(); |
| + if (dispatch_details.dispatcher_destroyed) |
| + return; |
| return; |
| } |
| @@ -185,11 +191,14 @@ void RootView::DispatchTouchEvent(ui::TouchEvent* event) { |
| // See if this view wants to handle the touch |
| ui::TouchEvent touch_event(*event, static_cast<View*>(this), |
| touch_pressed_handler_); |
| - DispatchEventToTarget(touch_pressed_handler_, &touch_event); |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(touch_pressed_handler_, &touch_event); |
| if (touch_event.handled()) |
| event->SetHandled(); |
| if (touch_event.stopped_propagation()) |
| event->StopPropagation(); |
| + if (dispatch_details.dispatcher_destroyed) |
| + return; |
| // The view could have removed itself from the tree when handling |
| // OnTouchEvent(). So handle as per OnMousePressed. NB: we |
| @@ -224,7 +233,10 @@ void RootView::DispatchGestureEvent(ui::GestureEvent* event) { |
| (event->IsScrollGestureEvent() || event->IsFlingScrollEvent()) ? |
| scroll_gesture_handler_ : gesture_handler_; |
| ui::GestureEvent handler_event(*event, static_cast<View*>(this), handler); |
| - DispatchEventToTarget(handler, &handler_event); |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(handler, &handler_event); |
| + if (dispatch_details.dispatcher_destroyed) |
| + return; |
| if (event->type() == ui::ET_GESTURE_END && |
| event->details().touch_points() <= 1) { |
| @@ -261,13 +273,16 @@ void RootView::DispatchGestureEvent(ui::GestureEvent* event) { |
| scroll_gesture_handler_ = scroll_gesture_handler_->parent()) { |
| ui::GestureEvent gesture_event(*event, static_cast<View*>(this), |
| scroll_gesture_handler_); |
| - DispatchEventToTarget(scroll_gesture_handler_, &gesture_event); |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(scroll_gesture_handler_, &gesture_event); |
| if (gesture_event.stopped_propagation()) { |
| event->StopPropagation(); |
| return; |
| } else if (gesture_event.handled()) { |
| event->SetHandled(); |
| return; |
| + } else if (dispatch_details.dispatcher_destroyed) { |
| + return; |
| } |
| } |
| scroll_gesture_handler_ = NULL; |
| @@ -312,7 +327,10 @@ void RootView::DispatchGestureEvent(ui::GestureEvent* event) { |
| // See if this view wants to handle the Gesture. |
| ui::GestureEvent gesture_event(*event, static_cast<View*>(this), |
| gesture_handler_); |
| - DispatchEventToTarget(gesture_handler_, &gesture_event); |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(gesture_handler_, &gesture_event); |
| + if (dispatch_details.dispatcher_destroyed) |
| + return; |
| // The view could have removed itself from the tree when handling |
| // OnGestureEvent(). So handle as per OnMousePressed. NB: we |
| @@ -419,7 +437,10 @@ bool RootView::OnMousePressed(const ui::MouseEvent& event) { |
| ui::MouseEvent mouse_pressed_event(event, static_cast<View*>(this), |
| mouse_pressed_handler_); |
| drag_info_.Reset(); |
| - DispatchEventToTarget(mouse_pressed_handler_, &mouse_pressed_event); |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(mouse_pressed_handler_, &mouse_pressed_event); |
| + if (dispatch_details.dispatcher_destroyed) |
| + return true; |
| return true; |
| } |
| DCHECK(!explicit_mouse_handler_); |
| @@ -447,12 +468,10 @@ bool RootView::OnMousePressed(const ui::MouseEvent& event) { |
| mouse_pressed_event.set_flags(event.flags() & ~ui::EF_IS_DOUBLE_CLICK); |
| drag_info_.Reset(); |
| - { |
| - WidgetDeletionObserver widget_deletion_observer(widget_); |
| - DispatchEventToTarget(mouse_pressed_handler_, &mouse_pressed_event); |
| - if (!widget_deletion_observer.IsWidgetAlive()) |
| - return mouse_pressed_event.handled(); |
| - } |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(mouse_pressed_handler_, &mouse_pressed_event); |
| + if (dispatch_details.dispatcher_destroyed) |
| + return mouse_pressed_event.handled(); |
| // The view could have removed itself from the tree when handling |
| // OnMousePressed(). In this case, the removal notification will have |
| @@ -495,7 +514,10 @@ bool RootView::OnMouseDragged(const ui::MouseEvent& event) { |
| ui::MouseEvent mouse_event(event, static_cast<View*>(this), |
| mouse_pressed_handler_); |
| - DispatchEventToTarget(mouse_pressed_handler_, &mouse_event); |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(mouse_pressed_handler_, &mouse_event); |
| + if (dispatch_details.dispatcher_destroyed) |
| + return false; |
| } |
| return false; |
| } |
| @@ -510,8 +532,10 @@ void RootView::OnMouseReleased(const ui::MouseEvent& event) { |
| // configure state such that we're done first, then call View. |
| View* mouse_pressed_handler = mouse_pressed_handler_; |
| SetMouseHandler(NULL); |
| - DispatchEventToTarget(mouse_pressed_handler, &mouse_released); |
| - // WARNING: we may have been deleted. |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(mouse_pressed_handler, &mouse_released); |
| + if (dispatch_details.dispatcher_destroyed) |
| + return; |
| } |
| } |
| @@ -555,7 +579,10 @@ void RootView::OnMouseMoved(const ui::MouseEvent& event) { |
| (!mouse_move_handler_->notify_enter_exit_on_child() || |
| !mouse_move_handler_->Contains(v))) { |
| MouseEnterExitEvent exit(event, ui::ET_MOUSE_EXITED); |
| - DispatchEventToTarget(mouse_move_handler_, &exit); |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(mouse_move_handler_, &exit); |
| + if (dispatch_details.dispatcher_destroyed) |
| + return; |
| NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED, |
| mouse_move_handler_, v); |
| } |
| @@ -566,7 +593,10 @@ void RootView::OnMouseMoved(const ui::MouseEvent& event) { |
| MouseEnterExitEvent entered(event, ui::ET_MOUSE_ENTERED); |
| entered.ConvertLocationToTarget(static_cast<View*>(this), |
| mouse_move_handler_); |
| - DispatchEventToTarget(mouse_move_handler_, &entered); |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(mouse_move_handler_, &entered); |
| + if (dispatch_details.dispatcher_destroyed) |
| + return; |
| NotifyEnterExitOfDescendant(entered, ui::ET_MOUSE_ENTERED, v, |
| old_handler); |
| } |
| @@ -578,7 +608,10 @@ void RootView::OnMouseMoved(const ui::MouseEvent& event) { |
| widget_->SetCursor(mouse_move_handler_->GetCursor(moved_event)); |
| } else if (mouse_move_handler_ != NULL) { |
| MouseEnterExitEvent exited(event, ui::ET_MOUSE_EXITED); |
| - DispatchEventToTarget(mouse_move_handler_, &exited); |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(mouse_move_handler_, &exited); |
| + if (dispatch_details.dispatcher_destroyed) |
| + return; |
| NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED, |
| mouse_move_handler_, v); |
| // On Aura the non-client area extends slightly outside the root view for |
| @@ -593,7 +626,10 @@ void RootView::OnMouseMoved(const ui::MouseEvent& event) { |
| void RootView::OnMouseExited(const ui::MouseEvent& event) { |
| if (mouse_move_handler_ != NULL) { |
| MouseEnterExitEvent exited(event, ui::ET_MOUSE_EXITED); |
| - DispatchEventToTarget(mouse_move_handler_, &exited); |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(mouse_move_handler_, &exited); |
| + if (dispatch_details.dispatcher_destroyed) |
| + return; |
| NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED, |
| mouse_move_handler_, NULL); |
| mouse_move_handler_ = NULL; |
| @@ -602,8 +638,14 @@ void RootView::OnMouseExited(const ui::MouseEvent& event) { |
| bool RootView::OnMouseWheel(const ui::MouseWheelEvent& event) { |
| for (View* v = GetEventHandlerForPoint(event.location()); |
| - v && v != this && !event.handled(); v = v->parent()) |
| - DispatchEventToTarget(v, const_cast<ui::MouseWheelEvent*>(&event)); |
| + v && v != this && !event.handled(); v = v->parent()) { |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(v, const_cast<ui::MouseWheelEvent*>(&event)); |
| + if (dispatch_details.dispatcher_destroyed || |
| + dispatch_details.target_destroyed) { |
| + return event.handled(); |
| + } |
| + } |
| return event.handled(); |
| } |
| @@ -702,12 +744,14 @@ void RootView::SetMouseLocationAndFlags(const ui::MouseEvent& event) { |
| last_mouse_event_y_ = event.y(); |
| } |
| -void RootView::DispatchEventToTarget(View* target, ui::Event* event) { |
| +ui::EventDispatchDetails RootView::DispatchEventToTarget(View* target, |
| + ui::Event* event) { |
| View* old_target = event_dispatch_target_; |
| event_dispatch_target_ = target; |
| ui::EventDispatchDetails details = DispatchEvent(target, event); |
| if (!details.dispatcher_destroyed) |
| event_dispatch_target_ = old_target; |
| + return details; |
| } |
| void RootView::NotifyEnterExitOfDescendant(const ui::MouseEvent& event, |
| @@ -723,20 +767,24 @@ void RootView::NotifyEnterExitOfDescendant(const ui::MouseEvent& event, |
| // of the callbacks can mark the event as handled, and that would cause |
| // incorrect event dispatch. |
| MouseEnterExitEvent notify_event(event, type); |
| - DispatchEventToTarget(p, ¬ify_event); |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(p, ¬ify_event); |
| + if (dispatch_details.dispatcher_destroyed || |
| + dispatch_details.target_destroyed) { |
| + return; |
| + } |
| } |
| } |
| void RootView::DispatchKeyEventStartAt(View* view, ui::KeyEvent* event) { |
| - if (event->handled() || !view) |
| - return; |
| - |
| - for (; view && view != this; view = view->parent()) { |
| - DispatchEventToTarget(view, event); |
| - // Do this check here rather than in the if as |view| may have been deleted. |
| - if (event->handled()) |
| + for (; view && view != this && !event->handled(); view = view->parent()) { |
| + ui::EventDispatchDetails dispatch_details = |
| + DispatchEventToTarget(view, event); |
| + if (dispatch_details.dispatcher_destroyed || |
|
sadrul
2014/02/20 15:45:49
Perhaps we are not setting |target_destroyed| corr
|
| + dispatch_details.target_destroyed) { |
| return; |
| + } |
| } |
| } |