Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / content / browser / web_contents / touch_editable_impl_aura.cc
blobb161773aa199280b7e8b41e217e2684f5c52a4e1
1 // Copyright (c) 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.
5 #include "content/browser/web_contents/touch_editable_impl_aura.h"
7 #include "content/browser/renderer_host/render_widget_host_impl.h"
8 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
9 #include "content/browser/web_contents/web_contents_impl.h"
10 #include "content/common/view_messages.h"
11 #include "content/public/browser/render_view_host.h"
12 #include "content/public/browser/render_widget_host.h"
13 #include "grit/ui_strings.h"
14 #include "ui/aura/client/screen_position_client.h"
15 #include "ui/aura/window.h"
16 #include "ui/aura/window_tree_host.h"
17 #include "ui/base/clipboard/clipboard.h"
18 #include "ui/base/ui_base_switches_util.h"
19 #include "ui/gfx/range/range.h"
20 #include "ui/wm/public/activation_client.h"
22 namespace content {
24 ////////////////////////////////////////////////////////////////////////////////
25 // TouchEditableImplAura, public:
27 TouchEditableImplAura::~TouchEditableImplAura() {
28 Cleanup();
31 // static
32 TouchEditableImplAura* TouchEditableImplAura::Create() {
33 if (switches::IsTouchEditingEnabled())
34 return new TouchEditableImplAura();
35 return NULL;
38 void TouchEditableImplAura::AttachToView(RenderWidgetHostViewAura* view) {
39 if (rwhva_ == view)
40 return;
42 Cleanup();
43 if (!view)
44 return;
46 rwhva_ = view;
47 rwhva_->set_touch_editing_client(this);
50 void TouchEditableImplAura::UpdateEditingController() {
51 if (!rwhva_ || !rwhva_->HasFocus())
52 return;
54 if (text_input_type_ != ui::TEXT_INPUT_TYPE_NONE ||
55 selection_anchor_rect_ != selection_focus_rect_) {
56 if (touch_selection_controller_)
57 touch_selection_controller_->SelectionChanged();
58 } else {
59 EndTouchEditing(false);
63 void TouchEditableImplAura::OverscrollStarted() {
64 overscroll_in_progress_ = true;
67 void TouchEditableImplAura::OverscrollCompleted() {
68 // We might receive multiple OverscrollStarted() and OverscrollCompleted()
69 // during the same scroll session (for example, when the scroll direction
70 // changes). We want to show the handles only when:
71 // 1. Overscroll has completed
72 // 2. Scrolling session is over, i.e. we have received ET_GESTURE_SCROLL_END.
73 // 3. If we had hidden the handles when scrolling started
74 // 4. If there is still a need to show handles (there is a non-empty selection
75 // or non-NONE |text_input_type_|)
76 if (overscroll_in_progress_ && !scroll_in_progress_ &&
77 handles_hidden_due_to_scroll_ &&
78 (selection_anchor_rect_ != selection_focus_rect_ ||
79 text_input_type_ != ui::TEXT_INPUT_TYPE_NONE)) {
80 StartTouchEditing();
81 UpdateEditingController();
83 overscroll_in_progress_ = false;
86 ////////////////////////////////////////////////////////////////////////////////
87 // TouchEditableImplAura, RenderWidgetHostViewAura::TouchEditingClient
88 // implementation:
90 void TouchEditableImplAura::StartTouchEditing() {
91 if (!rwhva_ || !rwhva_->HasFocus())
92 return;
94 if (!touch_selection_controller_) {
95 touch_selection_controller_.reset(
96 ui::TouchSelectionController::create(this));
98 if (touch_selection_controller_)
99 touch_selection_controller_->SelectionChanged();
102 void TouchEditableImplAura::EndTouchEditing(bool quick) {
103 if (touch_selection_controller_) {
104 if (touch_selection_controller_->IsHandleDragInProgress()) {
105 touch_selection_controller_->SelectionChanged();
106 } else {
107 touch_selection_controller_->HideHandles(quick);
108 touch_selection_controller_.reset();
113 void TouchEditableImplAura::OnSelectionOrCursorChanged(const gfx::Rect& anchor,
114 const gfx::Rect& focus) {
115 selection_anchor_rect_ = anchor;
116 selection_focus_rect_ = focus;
118 // If touch editing handles were not visible, we bring them up only if
119 // there is non-zero selection on the page. And the current event is a
120 // gesture event (we dont want to show handles if the user is selecting
121 // using mouse or keyboard).
122 if (selection_gesture_in_process_ && !scroll_in_progress_ &&
123 !overscroll_in_progress_ &&
124 selection_anchor_rect_ != selection_focus_rect_) {
125 StartTouchEditing();
126 selection_gesture_in_process_ = false;
129 UpdateEditingController();
132 void TouchEditableImplAura::OnTextInputTypeChanged(ui::TextInputType type) {
133 text_input_type_ = type;
136 bool TouchEditableImplAura::HandleInputEvent(const ui::Event* event) {
137 DCHECK(rwhva_);
138 if (event->IsTouchEvent())
139 return false;
141 if (!event->IsGestureEvent()) {
142 selection_gesture_in_process_ = false;
143 EndTouchEditing(false);
144 return false;
147 const ui::GestureEvent* gesture_event =
148 static_cast<const ui::GestureEvent*>(event);
149 switch (event->type()) {
150 case ui::ET_GESTURE_TAP:
151 if (gesture_event->details().tap_count() > 1)
152 selection_gesture_in_process_ = true;
153 // When the user taps, we want to show touch editing handles if user
154 // tapped on selected text.
155 if (selection_anchor_rect_ != selection_focus_rect_) {
156 // UnionRects only works for rects with non-zero width.
157 gfx::Rect anchor(selection_anchor_rect_.origin(),
158 gfx::Size(1, selection_anchor_rect_.height()));
159 gfx::Rect focus(selection_focus_rect_.origin(),
160 gfx::Size(1, selection_focus_rect_.height()));
161 gfx::Rect selection_rect = gfx::UnionRects(anchor, focus);
162 if (selection_rect.Contains(gesture_event->location())) {
163 StartTouchEditing();
164 return true;
167 // For single taps, not inside selected region, we want to show handles
168 // only when the tap is on an already focused textfield.
169 textfield_was_focused_on_tap_ = false;
170 if (gesture_event->details().tap_count() == 1 &&
171 text_input_type_ != ui::TEXT_INPUT_TYPE_NONE)
172 textfield_was_focused_on_tap_ = true;
173 break;
174 case ui::ET_GESTURE_LONG_PRESS:
175 selection_gesture_in_process_ = true;
176 break;
177 case ui::ET_GESTURE_SCROLL_BEGIN:
178 // If selection handles are currently visible, we want to get them back up
179 // when scrolling ends. So we set |handles_hidden_due_to_scroll_| so that
180 // we can re-start touch editing on scroll end gesture.
181 scroll_in_progress_ = true;
182 handles_hidden_due_to_scroll_ = false;
183 if (touch_selection_controller_)
184 handles_hidden_due_to_scroll_ = true;
185 EndTouchEditing(true);
186 break;
187 case ui::ET_GESTURE_SCROLL_END:
188 // Scroll has ended, but we might still be in overscroll animation.
189 if (handles_hidden_due_to_scroll_ && !overscroll_in_progress_ &&
190 (selection_anchor_rect_ != selection_focus_rect_ ||
191 text_input_type_ != ui::TEXT_INPUT_TYPE_NONE)) {
192 StartTouchEditing();
193 UpdateEditingController();
195 // fall through to reset |scroll_in_progress_|.
196 case ui::ET_SCROLL_FLING_START:
197 selection_gesture_in_process_ = false;
198 scroll_in_progress_ = false;
199 break;
200 default:
201 break;
203 return false;
206 void TouchEditableImplAura::GestureEventAck(int gesture_event_type) {
207 DCHECK(rwhva_);
208 if (gesture_event_type == blink::WebInputEvent::GestureTap &&
209 text_input_type_ != ui::TEXT_INPUT_TYPE_NONE &&
210 textfield_was_focused_on_tap_) {
211 StartTouchEditing();
212 UpdateEditingController();
216 void TouchEditableImplAura::OnViewDestroyed() {
217 Cleanup();
220 ////////////////////////////////////////////////////////////////////////////////
221 // TouchEditableImplAura, ui::TouchEditable implementation:
223 void TouchEditableImplAura::SelectRect(const gfx::Point& start,
224 const gfx::Point& end) {
225 RenderWidgetHost* host = rwhva_->GetRenderWidgetHost();
226 RenderViewHost* rvh = RenderViewHost::From(host);
227 WebContentsImpl* wc =
228 static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvh));
229 wc->SelectRange(start, end);
232 void TouchEditableImplAura::MoveCaretTo(const gfx::Point& point) {
233 if (!rwhva_)
234 return;
236 RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
237 rwhva_->GetRenderWidgetHost());
238 host->MoveCaret(point);
241 void TouchEditableImplAura::GetSelectionEndPoints(gfx::Rect* p1,
242 gfx::Rect* p2) {
243 *p1 = selection_anchor_rect_;
244 *p2 = selection_focus_rect_;
247 gfx::Rect TouchEditableImplAura::GetBounds() {
248 return rwhva_ ? gfx::Rect(rwhva_->GetNativeView()->bounds().size()) :
249 gfx::Rect();
252 gfx::NativeView TouchEditableImplAura::GetNativeView() const {
253 return rwhva_ ? rwhva_->GetNativeView()->GetToplevelWindow() : NULL;
256 void TouchEditableImplAura::ConvertPointToScreen(gfx::Point* point) {
257 if (!rwhva_)
258 return;
259 aura::Window* window = rwhva_->GetNativeView();
260 aura::client::ScreenPositionClient* screen_position_client =
261 aura::client::GetScreenPositionClient(window->GetRootWindow());
262 if (screen_position_client)
263 screen_position_client->ConvertPointToScreen(window, point);
266 void TouchEditableImplAura::ConvertPointFromScreen(gfx::Point* point) {
267 if (!rwhva_)
268 return;
269 aura::Window* window = rwhva_->GetNativeView();
270 aura::client::ScreenPositionClient* screen_position_client =
271 aura::client::GetScreenPositionClient(window->GetRootWindow());
272 if (screen_position_client)
273 screen_position_client->ConvertPointFromScreen(window, point);
276 bool TouchEditableImplAura::DrawsHandles() {
277 return false;
280 void TouchEditableImplAura::OpenContextMenu(const gfx::Point& anchor) {
281 if (!rwhva_)
282 return;
283 gfx::Point point = anchor;
284 ConvertPointFromScreen(&point);
285 RenderWidgetHost* host = rwhva_->GetRenderWidgetHost();
286 host->Send(new ViewMsg_ShowContextMenu(host->GetRoutingID(), point));
287 EndTouchEditing(false);
290 bool TouchEditableImplAura::IsCommandIdChecked(int command_id) const {
291 NOTREACHED();
292 return false;
295 bool TouchEditableImplAura::IsCommandIdEnabled(int command_id) const {
296 if (!rwhva_)
297 return false;
298 bool editable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
299 gfx::Range selection_range;
300 rwhva_->GetSelectionRange(&selection_range);
301 bool has_selection = !selection_range.is_empty();
302 switch (command_id) {
303 case IDS_APP_CUT:
304 return editable && has_selection;
305 case IDS_APP_COPY:
306 return has_selection;
307 case IDS_APP_PASTE: {
308 base::string16 result;
309 ui::Clipboard::GetForCurrentThread()->ReadText(
310 ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
311 return editable && !result.empty();
313 case IDS_APP_DELETE:
314 return editable && has_selection;
315 case IDS_APP_SELECT_ALL:
316 return true;
317 default:
318 return false;
322 bool TouchEditableImplAura::GetAcceleratorForCommandId(
323 int command_id,
324 ui::Accelerator* accelerator) {
325 return false;
328 void TouchEditableImplAura::ExecuteCommand(int command_id, int event_flags) {
329 RenderWidgetHost* host = rwhva_->GetRenderWidgetHost();
330 RenderViewHost* rvh = RenderViewHost::From(host);
331 WebContents* wc = WebContents::FromRenderViewHost(rvh);
333 switch (command_id) {
334 case IDS_APP_CUT:
335 wc->Cut();
336 break;
337 case IDS_APP_COPY:
338 wc->Copy();
339 break;
340 case IDS_APP_PASTE:
341 wc->Paste();
342 break;
343 case IDS_APP_DELETE:
344 wc->Delete();
345 break;
346 case IDS_APP_SELECT_ALL:
347 wc->SelectAll();
348 break;
349 default:
350 NOTREACHED();
351 break;
353 EndTouchEditing(false);
356 void TouchEditableImplAura::DestroyTouchSelection() {
357 EndTouchEditing(false);
360 ////////////////////////////////////////////////////////////////////////////////
361 // TouchEditableImplAura, private:
363 TouchEditableImplAura::TouchEditableImplAura()
364 : text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
365 rwhva_(NULL),
366 selection_gesture_in_process_(false),
367 handles_hidden_due_to_scroll_(false),
368 scroll_in_progress_(false),
369 overscroll_in_progress_(false),
370 textfield_was_focused_on_tap_(false) {
373 void TouchEditableImplAura::Cleanup() {
374 if (rwhva_) {
375 rwhva_->set_touch_editing_client(NULL);
376 rwhva_ = NULL;
378 text_input_type_ = ui::TEXT_INPUT_TYPE_NONE;
379 EndTouchEditing(true);
380 selection_gesture_in_process_ = false;
381 handles_hidden_due_to_scroll_ = false;
382 scroll_in_progress_ = false;
383 overscroll_in_progress_ = false;
386 } // namespace content