Index: content/browser/renderer_host/input/gestures/zoom_manager.cc |
diff --git a/content/browser/renderer_host/input/gestures/zoom_manager.cc b/content/browser/renderer_host/input/gestures/zoom_manager.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5bea6963793abfea95f72f182edbfb9e5bb7732d |
--- /dev/null |
+++ b/content/browser/renderer_host/input/gestures/zoom_manager.cc |
@@ -0,0 +1,92 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/browser/renderer_host/input/gestures/zoom_manager.h" |
+ |
+#include "base/auto_reset.h" |
+#include "base/logging.h" |
+#include "content/browser/renderer_host/input/gestures/motion_event.h" |
+ |
+namespace content { |
+ |
+ZoomManager::ZoomManager(ScaleGestureDetector::Config config, |
+ ScaleGestureDetector::OnScaleGestureListener* listener) |
+ : listener_(listener), |
+ permanently_ignore_detector_events_(false), |
+ temporarily_ignore_detector_events_(false), |
+ pinch_event_sent_(false) { |
+ DCHECK(listener_); |
+ multi_touch_detector_.reset(new ScaleGestureDetector(config, this)); |
+} |
+ |
+ZoomManager::~ZoomManager() {} |
+ |
+void ZoomManager::PassTouchEventThrough(const MotionEvent& event) { |
+ base::AutoReset<bool> temporarily_ignore_detector_events( |
+ &temporarily_ignore_detector_events_, true); |
+ multi_touch_detector_->OnTouchEvent(event); |
+} |
+ |
+bool ZoomManager::ProcessTouchEvent(const MotionEvent& event) { |
+ // TODO: Need to deal with multi-touch transition |
+ bool in_gesture = IsScaleGestureDetectionInProgress(); |
+ bool result = multi_touch_detector_->OnTouchEvent(event); |
+ if (!in_gesture && (event.GetActionMasked() == MotionEvent::ACTION_UP || |
+ event.GetActionMasked() == MotionEvent::ACTION_CANCEL)) { |
+ return false; |
+ } |
+ return result; |
+} |
+ |
+void ZoomManager::UpdateMultiTouchSupport(bool supports_multi_touch_zoom) { |
+ // Note that returning false from onScaleBegin / onScale makes the |
+ // gesture detector not to emit further scaling notifications |
+ // related to this gesture. Thus, if detector events are enabled in |
+ // the middle of the gesture, we don't need to do anything. |
+ permanently_ignore_detector_events_ = !supports_multi_touch_zoom; |
+} |
+ |
+bool ZoomManager::IsScaleGestureDetectionInProgress() const { |
+ return !permanently_ignore_detector_events_ && |
+ multi_touch_detector_->IsInProgress(); |
+} |
+ |
+bool ZoomManager::OnScaleBegin(const ScaleGestureDetector& detector) { |
+ if (IgnoreDetectorEvents()) |
+ return false; |
+ pinch_event_sent_ = false; |
+ // TODO(jdduke): Ignore single tap? |
+ return true; |
+} |
+ |
+void ZoomManager::OnScaleEnd(const ScaleGestureDetector& detector) { |
+ if (!pinch_event_sent_) |
+ return; |
+ listener_->OnScaleEnd(detector); |
+ pinch_event_sent_ = false; |
+} |
+ |
+bool ZoomManager::OnScale(const ScaleGestureDetector& detector) { |
+ if (IgnoreDetectorEvents()) |
+ return false; |
+ // It is possible that OnScaleBegin() was never called when we reach here. |
+ // This happens when webkit handles the 2nd touch down event. That causes |
+ // ContentView to ignore the OnScaleBegin() call. And if webkit does not |
+ // handle the touch move events afterwards, we will face a situation |
+ // that OnScale() is called without any OnScaleBegin(). |
+ // To solve this problem, we call OnScaleBegin() here if it is never called. |
+ if (!pinch_event_sent_) { |
+ pinch_event_sent_ = true; |
+ listener_->OnScaleBegin(detector); |
+ } |
+ listener_->OnScale(detector); |
+ return true; |
+} |
+ |
+bool ZoomManager::IgnoreDetectorEvents() const { |
+ return permanently_ignore_detector_events_ || |
+ temporarily_ignore_detector_events_; |
+} |
+ |
+} // namespace content |