Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / ui / aura / window_event_dispatcher.cc
index 5cf693d..7b40c71 100644 (file)
@@ -150,21 +150,22 @@ void WindowEventDispatcher::DispatchGestureEvent(ui::GestureEvent* event) {
   }
 }
 
-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;
@@ -242,8 +243,11 @@ void WindowEventDispatcher::DispatchMouseExitToHidingWindow(Window* window) {
   // |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(
@@ -390,6 +394,24 @@ void WindowEventDispatcher::UpdateCapture(Window* old_capture,
 }
 
 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;
 }
@@ -477,13 +499,20 @@ ui::EventDispatchDetails WindowEventDispatcher::PostDispatchEvent(
     // 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());
     }
   }
@@ -858,6 +887,20 @@ void WindowEventDispatcher::PreDispatchTouchEvent(Window* target,
       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);
 }