1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
6
7#include "base/debug/trace_event.h"
8#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
9#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
10#include "content/common/input_messages.h"
11#include "content/public/browser/render_widget_host.h"
12
13namespace content {
14
15SyntheticGestureController::SyntheticGestureController(
16    scoped_ptr<SyntheticGestureTarget> gesture_target)
17    : gesture_target_(gesture_target.Pass()) {}
18
19SyntheticGestureController::~SyntheticGestureController() {}
20
21void SyntheticGestureController::QueueSyntheticGesture(
22    scoped_ptr<SyntheticGesture> synthetic_gesture,
23    const OnGestureCompleteCallback& completion_callback) {
24  DCHECK(synthetic_gesture);
25
26  bool was_empty = pending_gesture_queue_.IsEmpty();
27
28  pending_gesture_queue_.Push(synthetic_gesture.Pass(), completion_callback);
29
30  if (was_empty)
31    StartGesture(*pending_gesture_queue_.FrontGesture());
32}
33
34void SyntheticGestureController::Flush(base::TimeTicks timestamp) {
35  TRACE_EVENT0("input", "SyntheticGestureController::Flush");
36  if (pending_gesture_queue_.IsEmpty())
37    return;
38
39  if (pending_gesture_result_)
40    return;
41
42  SyntheticGesture* gesture = pending_gesture_queue_.FrontGesture();
43  SyntheticGesture::Result result =
44      gesture->ForwardInputEvents(timestamp, gesture_target_.get());
45
46  if (result == SyntheticGesture::GESTURE_RUNNING) {
47    gesture_target_->SetNeedsFlush();
48    return;
49  }
50
51  // It's possible that all events generated by the gesture have been fully
52  // dispatched at this point, in which case |OnDidFlushInput()| was called
53  // before |pending_gesture_result_| was initialized. Requesting another flush
54  // will trigger the necessary gesture-ending call to |OnDidFlushInput()|.
55  pending_gesture_result_.reset(new SyntheticGesture::Result(result));
56  gesture_target_->SetNeedsFlush();
57}
58
59void SyntheticGestureController::OnDidFlushInput() {
60  if (!pending_gesture_result_)
61    return;
62
63  DCHECK(!pending_gesture_queue_.IsEmpty());
64  StopGesture(*pending_gesture_queue_.FrontGesture(),
65              pending_gesture_queue_.FrontCallback(),
66              *pending_gesture_result_.Pass());
67  pending_gesture_queue_.Pop();
68
69  if (!pending_gesture_queue_.IsEmpty())
70    StartGesture(*pending_gesture_queue_.FrontGesture());
71}
72
73void SyntheticGestureController::StartGesture(const SyntheticGesture& gesture) {
74  TRACE_EVENT_ASYNC_BEGIN0("input,benchmark",
75                           "SyntheticGestureController::running",
76                           &gesture);
77  gesture_target_->SetNeedsFlush();
78}
79
80void SyntheticGestureController::StopGesture(
81    const SyntheticGesture& gesture,
82    const OnGestureCompleteCallback& completion_callback,
83    SyntheticGesture::Result result) {
84  DCHECK_NE(result, SyntheticGesture::GESTURE_RUNNING);
85  TRACE_EVENT_ASYNC_END0("input,benchmark",
86                         "SyntheticGestureController::running",
87                         &gesture);
88
89  completion_callback.Run(result);
90}
91
92SyntheticGestureController::GestureAndCallbackQueue::GestureAndCallbackQueue() {
93}
94
95SyntheticGestureController::GestureAndCallbackQueue::
96    ~GestureAndCallbackQueue() {
97}
98
99}  // namespace content
100