| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/input/input_event_filter.h" | 5 #include "content/renderer/input/input_event_filter.h" |
| 6 | 6 |
| 7 #include "base/auto_reset.h" |
| 7 #include "base/bind.h" | 8 #include "base/bind.h" |
| 8 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 9 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| 10 #include "base/location.h" | 11 #include "base/location.h" |
| 11 #include "base/message_loop/message_loop_proxy.h" | 12 #include "base/message_loop/message_loop_proxy.h" |
| 12 #include "cc/input/input_handler.h" | 13 #include "cc/input/input_handler.h" |
| 13 #include "content/common/input/did_overscroll_params.h" | 14 #include "content/common/input/did_overscroll_params.h" |
| 14 #include "content/common/input/web_input_event_traits.h" | 15 #include "content/common/input/web_input_event_traits.h" |
| 15 #include "content/common/input_messages.h" | 16 #include "content/common/input_messages.h" |
| 16 #include "content/common/view_messages.h" | 17 #include "content/common/view_messages.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 38 | 39 |
| 39 namespace content { | 40 namespace content { |
| 40 | 41 |
| 41 InputEventFilter::InputEventFilter( | 42 InputEventFilter::InputEventFilter( |
| 42 IPC::Listener* main_listener, | 43 IPC::Listener* main_listener, |
| 43 const scoped_refptr<base::MessageLoopProxy>& target_loop) | 44 const scoped_refptr<base::MessageLoopProxy>& target_loop) |
| 44 : main_loop_(base::MessageLoopProxy::current()), | 45 : main_loop_(base::MessageLoopProxy::current()), |
| 45 main_listener_(main_listener), | 46 main_listener_(main_listener), |
| 46 sender_(NULL), | 47 sender_(NULL), |
| 47 target_loop_(target_loop), | 48 target_loop_(target_loop), |
| 48 overscroll_notifications_enabled_(false) { | 49 overscroll_notifications_enabled_(false), |
| 50 current_overscroll_params_(NULL) { |
| 49 DCHECK(target_loop_.get()); | 51 DCHECK(target_loop_.get()); |
| 50 overscroll_notifications_enabled_ = | 52 overscroll_notifications_enabled_ = |
| 51 CommandLine::ForCurrentProcess()->HasSwitch( | 53 CommandLine::ForCurrentProcess()->HasSwitch( |
| 52 switches::kEnableOverscrollNotifications); | 54 switches::kEnableOverscrollNotifications); |
| 53 } | 55 } |
| 54 | 56 |
| 55 void InputEventFilter::SetBoundHandler(const Handler& handler) { | 57 void InputEventFilter::SetBoundHandler(const Handler& handler) { |
| 56 DCHECK(main_loop_->BelongsToCurrentThread()); | 58 DCHECK(main_loop_->BelongsToCurrentThread()); |
| 57 handler_ = handler; | 59 handler_ = handler; |
| 58 } | 60 } |
| 59 | 61 |
| 60 void InputEventFilter::DidAddInputHandler(int routing_id, | 62 void InputEventFilter::DidAddInputHandler(int routing_id, |
| 61 cc::InputHandler* input_handler) { | 63 cc::InputHandler* input_handler) { |
| 62 base::AutoLock locked(routes_lock_); | 64 base::AutoLock locked(routes_lock_); |
| 63 routes_.insert(routing_id); | 65 routes_.insert(routing_id); |
| 64 } | 66 } |
| 65 | 67 |
| 66 void InputEventFilter::DidRemoveInputHandler(int routing_id) { | 68 void InputEventFilter::DidRemoveInputHandler(int routing_id) { |
| 67 base::AutoLock locked(routes_lock_); | 69 base::AutoLock locked(routes_lock_); |
| 68 routes_.erase(routing_id); | 70 routes_.erase(routing_id); |
| 69 } | 71 } |
| 70 | 72 |
| 71 void InputEventFilter::DidOverscroll(int routing_id, | 73 void InputEventFilter::DidOverscroll(int routing_id, |
| 72 const DidOverscrollParams& params) { | 74 const DidOverscrollParams& params) { |
| 73 if (!overscroll_notifications_enabled_) | 75 if (!overscroll_notifications_enabled_) |
| 74 return; | 76 return; |
| 75 | 77 |
| 76 SendMessage(ViewHostMsg_DidOverscroll(routing_id, params)); | 78 if (current_overscroll_params_) { |
| 79 current_overscroll_params_->reset(new DidOverscrollParams(params)); |
| 80 return; |
| 81 } |
| 82 |
| 83 SendMessage(scoped_ptr<IPC::Message>( |
| 84 new InputHostMsg_DidOverscroll(routing_id, params))); |
| 77 } | 85 } |
| 78 | 86 |
| 79 void InputEventFilter::DidStopFlinging(int routing_id) { | 87 void InputEventFilter::DidStopFlinging(int routing_id) { |
| 80 SendMessage(ViewHostMsg_DidStopFlinging(routing_id)); | 88 SendMessage( |
| 89 scoped_ptr<IPC::Message>(new ViewHostMsg_DidStopFlinging(routing_id))); |
| 81 } | 90 } |
| 82 | 91 |
| 83 void InputEventFilter::OnFilterAdded(IPC::Channel* channel) { | 92 void InputEventFilter::OnFilterAdded(IPC::Channel* channel) { |
| 84 io_loop_ = base::MessageLoopProxy::current(); | 93 io_loop_ = base::MessageLoopProxy::current(); |
| 85 sender_ = channel; | 94 sender_ = channel; |
| 86 } | 95 } |
| 87 | 96 |
| 88 void InputEventFilter::OnFilterRemoved() { | 97 void InputEventFilter::OnFilterRemoved() { |
| 89 sender_ = NULL; | 98 sender_ = NULL; |
| 90 } | 99 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 114 return false; | 123 return false; |
| 115 } | 124 } |
| 116 | 125 |
| 117 target_loop_->PostTask( | 126 target_loop_->PostTask( |
| 118 FROM_HERE, | 127 FROM_HERE, |
| 119 base::Bind(&InputEventFilter::ForwardToHandler, this, message)); | 128 base::Bind(&InputEventFilter::ForwardToHandler, this, message)); |
| 120 return true; | 129 return true; |
| 121 } | 130 } |
| 122 | 131 |
| 123 InputEventFilter::~InputEventFilter() { | 132 InputEventFilter::~InputEventFilter() { |
| 133 DCHECK(!current_overscroll_params_); |
| 124 } | 134 } |
| 125 | 135 |
| 126 void InputEventFilter::ForwardToMainListener(const IPC::Message& message) { | 136 void InputEventFilter::ForwardToMainListener(const IPC::Message& message) { |
| 127 main_listener_->OnMessageReceived(message); | 137 main_listener_->OnMessageReceived(message); |
| 128 } | 138 } |
| 129 | 139 |
| 130 void InputEventFilter::ForwardToHandler(const IPC::Message& message) { | 140 void InputEventFilter::ForwardToHandler(const IPC::Message& message) { |
| 131 DCHECK(!handler_.is_null()); | 141 DCHECK(!handler_.is_null()); |
| 132 DCHECK(target_loop_->BelongsToCurrentThread()); | 142 DCHECK(target_loop_->BelongsToCurrentThread()); |
| 133 TRACE_EVENT1("input", "InputEventFilter::ForwardToHandler", | 143 TRACE_EVENT1("input", "InputEventFilter::ForwardToHandler", |
| (...skipping 13 matching lines...) Expand all Loading... |
| 147 | 157 |
| 148 int routing_id = message.routing_id(); | 158 int routing_id = message.routing_id(); |
| 149 InputMsg_HandleInputEvent::Param params; | 159 InputMsg_HandleInputEvent::Param params; |
| 150 if (!InputMsg_HandleInputEvent::Read(&message, ¶ms)) | 160 if (!InputMsg_HandleInputEvent::Read(&message, ¶ms)) |
| 151 return; | 161 return; |
| 152 const WebInputEvent* event = params.a; | 162 const WebInputEvent* event = params.a; |
| 153 ui::LatencyInfo latency_info = params.b; | 163 ui::LatencyInfo latency_info = params.b; |
| 154 bool is_keyboard_shortcut = params.c; | 164 bool is_keyboard_shortcut = params.c; |
| 155 DCHECK(event); | 165 DCHECK(event); |
| 156 | 166 |
| 157 InputEventAckState ack = handler_.Run(routing_id, event, &latency_info); | 167 // Intercept |DidOverscroll| notifications, bundling any triggered overscroll |
| 168 // response with the input event ack. |
| 169 scoped_ptr<DidOverscrollParams> overscroll_params; |
| 170 base::AutoReset<scoped_ptr<DidOverscrollParams>*> |
| 171 auto_reset_current_overscroll_params(¤t_overscroll_params_, |
| 172 &overscroll_params); |
| 158 | 173 |
| 159 if (ack == INPUT_EVENT_ACK_STATE_NOT_CONSUMED) { | 174 InputEventAckState ack_state = handler_.Run(routing_id, event, &latency_info); |
| 175 |
| 176 if (ack_state == INPUT_EVENT_ACK_STATE_NOT_CONSUMED) { |
| 177 DCHECK(!overscroll_params); |
| 160 TRACE_EVENT_INSTANT0( | 178 TRACE_EVENT_INSTANT0( |
| 161 "input", | 179 "input", |
| 162 "InputEventFilter::ForwardToHandler::ForwardToMainListener", | 180 "InputEventFilter::ForwardToHandler::ForwardToMainListener", |
| 163 TRACE_EVENT_SCOPE_THREAD); | 181 TRACE_EVENT_SCOPE_THREAD); |
| 164 IPC::Message new_msg = InputMsg_HandleInputEvent( | 182 IPC::Message new_msg = InputMsg_HandleInputEvent( |
| 165 routing_id, event, latency_info, is_keyboard_shortcut); | 183 routing_id, event, latency_info, is_keyboard_shortcut); |
| 166 main_loop_->PostTask( | 184 main_loop_->PostTask( |
| 167 FROM_HERE, | 185 FROM_HERE, |
| 168 base::Bind(&InputEventFilter::ForwardToMainListener, | 186 base::Bind(&InputEventFilter::ForwardToMainListener, |
| 169 this, new_msg)); | 187 this, new_msg)); |
| 170 return; | 188 return; |
| 171 } | 189 } |
| 172 | 190 |
| 173 if (!WebInputEventTraits::IgnoresAckDisposition(*event)) | 191 if (WebInputEventTraits::IgnoresAckDisposition(*event)) |
| 174 SendACK(event->type, ack, latency_info, routing_id); | 192 return; |
| 193 |
| 194 InputHostMsg_HandleInputEvent_ACK_Params ack; |
| 195 ack.type = event->type; |
| 196 ack.state = ack_state; |
| 197 ack.latency = latency_info; |
| 198 ack.overscroll = overscroll_params.Pass(); |
| 199 SendMessage(scoped_ptr<IPC::Message>( |
| 200 new InputHostMsg_HandleInputEvent_ACK(routing_id, ack))); |
| 175 } | 201 } |
| 176 | 202 |
| 177 void InputEventFilter::SendACK(blink::WebInputEvent::Type type, | 203 void InputEventFilter::SendMessage(scoped_ptr<IPC::Message> message) { |
| 178 InputEventAckState ack_result, | 204 DCHECK(target_loop_->BelongsToCurrentThread()); |
| 179 const ui::LatencyInfo& latency_info, | 205 |
| 180 int routing_id) { | 206 io_loop_->PostTask(FROM_HERE, |
| 181 SendMessage(InputHostMsg_HandleInputEvent_ACK( | 207 base::Bind(&InputEventFilter::SendMessageOnIOThread, |
| 182 routing_id, type, ack_result, latency_info)); | 208 this, |
| 209 base::Passed(&message))); |
| 183 } | 210 } |
| 184 | 211 |
| 185 void InputEventFilter::SendMessage(const IPC::Message& message) { | 212 void InputEventFilter::SendMessageOnIOThread(scoped_ptr<IPC::Message> message) { |
| 186 DCHECK(target_loop_->BelongsToCurrentThread()); | |
| 187 | |
| 188 io_loop_->PostTask( | |
| 189 FROM_HERE, | |
| 190 base::Bind(&InputEventFilter::SendMessageOnIOThread, this, message)); | |
| 191 } | |
| 192 | |
| 193 void InputEventFilter::SendMessageOnIOThread(const IPC::Message& message) { | |
| 194 DCHECK(io_loop_->BelongsToCurrentThread()); | 213 DCHECK(io_loop_->BelongsToCurrentThread()); |
| 195 | 214 |
| 196 if (!sender_) | 215 if (!sender_) |
| 197 return; // Filter was removed. | 216 return; // Filter was removed. |
| 198 | 217 |
| 199 sender_->Send(new IPC::Message(message)); | 218 sender_->Send(message.release()); |
| 200 } | 219 } |
| 201 | 220 |
| 202 } // namespace content | 221 } // namespace content |
| OLD | NEW |