}
}
-void WindowEventDispatcher::DispatchMouseExitAtPoint(const gfx::Point& point) {
+DispatchDetails WindowEventDispatcher::DispatchMouseExitAtPoint(
+ const gfx::Point& point) {
ui::MouseEvent event(ui::ET_MOUSE_EXITED, point, point, ui::EF_NONE,
ui::EF_NONE);
- DispatchDetails details =
- DispatchMouseEnterOrExit(event, ui::ET_MOUSE_EXITED);
- if (details.dispatcher_destroyed)
- return;
+ return DispatchMouseEnterOrExit(event, ui::ET_MOUSE_EXITED);
}
void WindowEventDispatcher::ProcessedTouchEvent(ui::TouchEvent* event,
Window* window,
ui::EventResult result) {
- scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
- gestures.reset(ui::GestureRecognizer::Get()->
- ProcessTouchEventForGesture(*event, result, window));
+ ui::TouchEvent orig_event(*event, window, this->window());
+ // Once we've fully migrated to the eager gesture detector, we won't need to
+ // pass an event here.
+ scoped_ptr<ui::GestureRecognizer::Gestures> gestures(
+ ui::GestureRecognizer::Get()->ProcessTouchEventOnAsyncAck(
+ orig_event, result, window));
DispatchDetails details = ProcessGestures(gestures.get());
if (details.dispatcher_destroyed)
return;
// |window| is the capture window.
gfx::Point last_mouse_location = GetLastMouseLocationInRoot();
if (window->Contains(mouse_moved_handler_) &&
- window->ContainsPointInRoot(last_mouse_location))
- DispatchMouseExitAtPoint(last_mouse_location);
+ window->ContainsPointInRoot(last_mouse_location)) {
+ DispatchDetails details = DispatchMouseExitAtPoint(last_mouse_location);
+ if (details.dispatcher_destroyed)
+ return;
+ }
}
ui::EventDispatchDetails WindowEventDispatcher::DispatchMouseEnterOrExit(
}
void WindowEventDispatcher::OnOtherRootGotCapture() {
+ // Windows provides the TrackMouseEvents API which allows us to rely on the
+ // OS to send us the mouse exit events (WM_MOUSELEAVE). Additionally on
+ // desktop Windows, every top level window could potentially have its own
+ // root window, in which case this function will get called whenever those
+ // windows grab mouse capture. Sending mouse exit messages in these cases
+ // causes subtle bugs like (crbug.com/394672).
+#if !defined(OS_WIN)
+ if (mouse_moved_handler_) {
+ // Dispatch a mouse exit to reset any state associated with hover. This is
+ // important when going from no window having capture to a window having
+ // capture because we do not dispatch ET_MOUSE_CAPTURE_CHANGED in this case.
+ DispatchDetails details = DispatchMouseExitAtPoint(
+ GetLastMouseLocationInRoot());
+ if (details.dispatcher_destroyed)
+ return;
+ }
+#endif
+
mouse_moved_handler_ = NULL;
mouse_pressed_handler_ = NULL;
}
// being dispatched.
if (dispatching_held_event_ || !held_move_event_ ||
!held_move_event_->IsTouchEvent()) {
- ui::TouchEvent orig_event(static_cast<const ui::TouchEvent&>(event),
- static_cast<Window*>(event.target()), window());
- // Get the list of GestureEvents from GestureRecognizer.
+ // If the event is being handled asynchronously, ignore it.
+ if(event.result() & ui::ER_CONSUMED)
+ return details;
scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
- gestures.reset(ui::GestureRecognizer::Get()->
- ProcessTouchEventForGesture(orig_event, event.result(),
- static_cast<Window*>(target)));
+
+ // Once we've fully migrated to the eager gesture detector, we won't
+ // need to pass an event here.
+ ui::TouchEvent orig_event(static_cast<const ui::TouchEvent&>(event),
+ static_cast<Window*>(event.target()),
+ window());
+ gestures.reset(
+ ui::GestureRecognizer::Get()->ProcessTouchEventPostDispatch(
+ orig_event, event.result(), static_cast<Window*>(target)));
+
return ProcessGestures(gestures.get());
}
}
NOTREACHED();
break;
}
+
+ if (dispatching_held_event_ || !held_move_event_ ||
+ !held_move_event_->IsTouchEvent()) {
+ ui::TouchEvent orig_event(*event, target, window());
+
+ // If the touch event is invalid in some way, the gesture recognizer will
+ // reject it. This must call |StopPropagation()|, in order to prevent the
+ // touch from being acked in |PostDispatchEvent|.
+ if (!ui::GestureRecognizer::Get()->ProcessTouchEventPreDispatch(orig_event,
+ target)) {
+ event->StopPropagation();
+ }
+ }
+
PreDispatchLocatedEvent(target, event);
}