Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Side by Side Diff: content/browser/renderer_host/input/touch_selection_controller_client_aura.cc

Issue 698253004: Reland: Implement Aura side of unified touch text selection for contents (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased after blink issue fixed: r200194 Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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/touch_selection_controller_client_ aura.h"
6
7 #include "content/browser/renderer_host/render_widget_host_delegate.h"
8 #include "content/browser/renderer_host/render_widget_host_impl.h"
9 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
10 #include "content/common/view_messages.h"
11 #include "content/public/browser/render_view_host.h"
12 #include "ui/aura/client/cursor_client.h"
13 #include "ui/aura/client/screen_position_client.h"
14 #include "ui/aura/env.h"
15 #include "ui/aura/window.h"
16 #include "ui/base/clipboard/clipboard.h"
17 #include "ui/gfx/geometry/point_conversions.h"
18 #include "ui/gfx/geometry/size_conversions.h"
19 #include "ui/strings/grit/ui_strings.h"
20 #include "ui/touch_selection/touch_handle_drawable_aura.h"
21 #include "ui/touch_selection/touch_selection_menu_runner.h"
22
23 namespace content {
24 namespace {
25
26 // Delay before showing the quick menu, in milliseconds.
27 const int kQuickMenuDelayInMs = 100;
28
29 gfx::Rect ConvertRectToScreen(aura::Window* window, const gfx::RectF& rect) {
30 gfx::Point origin = gfx::ToRoundedPoint(rect.origin());
31 gfx::Point bottom_right = gfx::ToRoundedPoint(rect.bottom_right());
32
33 aura::Window* root_window = window->GetRootWindow();
34 if (root_window) {
35 aura::client::ScreenPositionClient* screen_position_client =
36 aura::client::GetScreenPositionClient(root_window);
37 if (screen_position_client) {
38 screen_position_client->ConvertPointToScreen(window, &origin);
39 screen_position_client->ConvertPointToScreen(window, &bottom_right);
40 }
41 }
42 return gfx::Rect(origin.x(), origin.y(), bottom_right.x() - origin.x(),
43 bottom_right.y() - origin.y());
44 }
45
46 } // namespace
47
48 // A pre-target event handler for aura::Env which deactivates touch selection on
49 // mouse and keyboard events.
50 class TouchSelectionControllerClientAura::EnvPreTargetHandler
51 : public ui::EventHandler {
52 public:
53 EnvPreTargetHandler(ui::TouchSelectionController* selection_controller,
54 aura::Window* window);
55 ~EnvPreTargetHandler() override;
56
57 private:
58 // EventHandler:
59 void OnKeyEvent(ui::KeyEvent* event) override;
60 void OnMouseEvent(ui::MouseEvent* event) override;
61 void OnScrollEvent(ui::ScrollEvent* event) override;
62
63 ui::TouchSelectionController* selection_controller_;
64 aura::Window* window_;
65
66 DISALLOW_COPY_AND_ASSIGN(EnvPreTargetHandler);
67 };
68
69 TouchSelectionControllerClientAura::EnvPreTargetHandler::EnvPreTargetHandler(
70 ui::TouchSelectionController* selection_controller,
71 aura::Window* window)
72 : selection_controller_(selection_controller), window_(window) {
73 aura::Env::GetInstance()->AddPreTargetHandler(this);
74 }
75
76 TouchSelectionControllerClientAura::EnvPreTargetHandler::
77 ~EnvPreTargetHandler() {
78 aura::Env::GetInstance()->RemovePreTargetHandler(this);
79 }
80
81 void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnKeyEvent(
82 ui::KeyEvent* event) {
83 DCHECK_NE(ui::TouchSelectionController::INACTIVE,
84 selection_controller_->active_status());
85
86 selection_controller_->HideAndDisallowShowingAutomatically();
87 }
88
89 void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnMouseEvent(
90 ui::MouseEvent* event) {
91 DCHECK_NE(ui::TouchSelectionController::INACTIVE,
92 selection_controller_->active_status());
93
94 // If mouse events are not enabled, this mouse event is synthesized from a
95 // touch event in which case we don't want to deactivate touch selection.
96 aura::client::CursorClient* cursor_client =
97 aura::client::GetCursorClient(window_->GetRootWindow());
98 if (!cursor_client || cursor_client->IsMouseEventsEnabled())
99 selection_controller_->HideAndDisallowShowingAutomatically();
100 }
101
102 void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnScrollEvent(
103 ui::ScrollEvent* event) {
104 DCHECK_NE(ui::TouchSelectionController::INACTIVE,
105 selection_controller_->active_status());
106
107 selection_controller_->HideAndDisallowShowingAutomatically();
108 }
109
110 TouchSelectionControllerClientAura::TouchSelectionControllerClientAura(
111 RenderWidgetHostViewAura* rwhva)
112 : rwhva_(rwhva),
113 quick_menu_timer_(
114 FROM_HERE,
115 base::TimeDelta::FromMilliseconds(kQuickMenuDelayInMs),
116 base::Bind(&TouchSelectionControllerClientAura::ShowQuickMenu,
117 base::Unretained(this)),
118 false),
119 touch_down_(false),
120 scroll_in_progress_(false),
121 handle_drag_in_progress_(false) {
122 DCHECK(rwhva_);
123 }
124
125 TouchSelectionControllerClientAura::~TouchSelectionControllerClientAura() {
126 }
127
128 void TouchSelectionControllerClientAura::OnWindowMoved() {
129 UpdateQuickMenu();
130 }
131
132 void TouchSelectionControllerClientAura::OnTouchDown() {
133 touch_down_ = true;
134 UpdateQuickMenu();
135 }
136
137 void TouchSelectionControllerClientAura::OnTouchUp() {
138 touch_down_ = false;
139 UpdateQuickMenu();
140 }
141
142 void TouchSelectionControllerClientAura::OnScrollStarted() {
143 scroll_in_progress_ = true;
144 rwhva_->selection_controller()->SetTemporarilyHidden(true);
145 UpdateQuickMenu();
146 }
147
148 void TouchSelectionControllerClientAura::OnScrollCompleted() {
149 scroll_in_progress_ = false;
150 rwhva_->selection_controller()->SetTemporarilyHidden(false);
151 UpdateQuickMenu();
152 }
153
154 bool TouchSelectionControllerClientAura::IsQuickMenuAllowed() const {
155 return !touch_down_ && !scroll_in_progress_ && !handle_drag_in_progress_;
156 }
157
158 void TouchSelectionControllerClientAura::ShowQuickMenu() {
159 if (!ui::TouchSelectionMenuRunner::GetInstance())
160 return;
161
162 gfx::RectF rect = rwhva_->selection_controller()->GetRectBetweenBounds();
163
164 // Clip rect, which is in |rwhva_|'s window's coordinate space, to client
165 // bounds.
166 gfx::PointF origin = rect.origin();
167 gfx::PointF bottom_right = rect.bottom_right();
168 gfx::Rect client_bounds = rwhva_->GetNativeView()->bounds();
169 origin.SetToMax(client_bounds.origin());
170 bottom_right.SetToMin(client_bounds.bottom_right());
171 if (origin.x() > bottom_right.x() || origin.y() > bottom_right.y())
172 return;
173
174 gfx::Vector2dF diagonal = bottom_right - origin;
175 gfx::SizeF size(diagonal.x(), diagonal.y());
176 gfx::RectF anchor_rect(origin, size);
177
178 // Calculate maximum handle image size;
179 gfx::SizeF max_handle_size =
180 rwhva_->selection_controller()->GetStartHandleRect().size();
181 max_handle_size.SetToMax(
182 rwhva_->selection_controller()->GetEndHandleRect().size());
183
184 aura::Window* parent = rwhva_->GetNativeView();
185 ui::TouchSelectionMenuRunner::GetInstance()->OpenMenu(
186 this, ConvertRectToScreen(parent, anchor_rect),
187 gfx::ToRoundedSize(max_handle_size), parent->GetToplevelWindow());
188 }
189
190 void TouchSelectionControllerClientAura::UpdateQuickMenu() {
191 bool menu_is_showing =
192 ui::TouchSelectionMenuRunner::GetInstance() &&
193 ui::TouchSelectionMenuRunner::GetInstance()->IsRunning();
194 bool menu_should_show = rwhva_->selection_controller()->active_status() !=
195 ui::TouchSelectionController::INACTIVE &&
196 IsQuickMenuAllowed();
197
198 // Hide the quick menu if there is any. This should happen even if the menu
199 // should be shown again, in order to update its location or content.
200 if (menu_is_showing)
201 ui::TouchSelectionMenuRunner::GetInstance()->CloseMenu();
202 else
203 quick_menu_timer_.Stop();
204
205 // Start timer to show quick menu if necessary.
206 if (menu_should_show) {
207 if (show_quick_menu_immediately_for_test_)
208 ShowQuickMenu();
209 else
210 quick_menu_timer_.Reset();
211 }
212 }
213
214 bool TouchSelectionControllerClientAura::SupportsAnimation() const {
215 return false;
216 }
217
218 void TouchSelectionControllerClientAura::SetNeedsAnimate() {
219 NOTREACHED();
220 }
221
222 void TouchSelectionControllerClientAura::MoveCaret(
223 const gfx::PointF& position) {
224 RenderWidgetHostImpl* host =
225 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost());
226 host->MoveCaret(gfx::ToRoundedPoint(position));
227 }
228
229 void TouchSelectionControllerClientAura::MoveRangeSelectionExtent(
230 const gfx::PointF& extent) {
231 RenderWidgetHostDelegate* host_delegate =
232 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost())->delegate();
233 if (host_delegate)
234 host_delegate->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent));
235 }
236
237 void TouchSelectionControllerClientAura::SelectBetweenCoordinates(
238 const gfx::PointF& base,
239 const gfx::PointF& extent) {
240 RenderWidgetHostDelegate* host_delegate =
241 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost())->delegate();
242 if (host_delegate) {
243 host_delegate->SelectRange(gfx::ToRoundedPoint(base),
244 gfx::ToRoundedPoint(extent));
245 }
246 }
247
248 void TouchSelectionControllerClientAura::OnSelectionEvent(
249 ui::SelectionEventType event) {
250 switch (event) {
251 case ui::SELECTION_HANDLES_SHOWN:
252 case ui::INSERTION_HANDLE_SHOWN:
253 UpdateQuickMenu();
254 env_pre_target_handler_.reset(new EnvPreTargetHandler(
255 rwhva_->selection_controller(), rwhva_->GetNativeView()));
256 break;
257 case ui::SELECTION_HANDLES_CLEARED:
258 case ui::INSERTION_HANDLE_CLEARED:
259 env_pre_target_handler_.reset();
260 UpdateQuickMenu();
261 break;
262 case ui::SELECTION_HANDLE_DRAG_STARTED:
263 case ui::INSERTION_HANDLE_DRAG_STARTED:
264 handle_drag_in_progress_ = true;
265 UpdateQuickMenu();
266 break;
267 case ui::SELECTION_HANDLE_DRAG_STOPPED:
268 case ui::INSERTION_HANDLE_DRAG_STOPPED:
269 handle_drag_in_progress_ = false;
270 UpdateQuickMenu();
271 break;
272 case ui::SELECTION_HANDLES_MOVED:
273 case ui::INSERTION_HANDLE_MOVED:
274 UpdateQuickMenu();
275 break;
276 case ui::INSERTION_HANDLE_TAPPED:
277 case ui::SELECTION_ESTABLISHED:
278 case ui::SELECTION_DISSOLVED:
279 break;
280 };
281 }
282
283 scoped_ptr<ui::TouchHandleDrawable>
284 TouchSelectionControllerClientAura::CreateDrawable() {
285 return scoped_ptr<ui::TouchHandleDrawable>(
286 new ui::TouchHandleDrawableAura(rwhva_->GetNativeView()));
287 }
288
289 bool TouchSelectionControllerClientAura::IsCommandIdEnabled(
290 int command_id) const {
291 bool editable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
292 bool readable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_PASSWORD;
293 gfx::Range selection_range;
294 rwhva_->GetSelectionRange(&selection_range);
295 bool has_selection = !selection_range.is_empty();
296 switch (command_id) {
297 case IDS_APP_CUT:
298 return editable && readable && has_selection;
299 case IDS_APP_COPY:
300 return readable && has_selection;
301 case IDS_APP_PASTE: {
302 base::string16 result;
303 ui::Clipboard::GetForCurrentThread()->ReadText(
304 ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
305 return editable && !result.empty();
306 }
307 default:
308 return false;
309 }
310 }
311
312 void TouchSelectionControllerClientAura::ExecuteCommand(int command_id,
313 int event_flags) {
314 rwhva_->selection_controller()->HideAndDisallowShowingAutomatically();
315 RenderWidgetHostDelegate* host_delegate =
316 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost())->delegate();
317 if (!host_delegate)
318 return;
319
320 switch (command_id) {
321 case IDS_APP_CUT:
322 host_delegate->Cut();
323 break;
324 case IDS_APP_COPY:
325 host_delegate->Copy();
326 break;
327 case IDS_APP_PASTE:
328 host_delegate->Paste();
329 break;
330 default:
331 NOTREACHED();
332 break;
333 }
334 }
335
336 void TouchSelectionControllerClientAura::RunContextMenu() {
337 gfx::RectF anchor_rect =
338 rwhva_->selection_controller()->GetRectBetweenBounds();
339 gfx::PointF anchor_point =
340 gfx::PointF(anchor_rect.CenterPoint().x(), anchor_rect.y());
341 RenderWidgetHostImpl* host =
342 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost());
343 host->Send(new ViewMsg_ShowContextMenu(host->GetRoutingID(),
344 ui::MENU_SOURCE_TOUCH_EDIT_MENU,
345 gfx::ToRoundedPoint(anchor_point)));
346
347 // Hide selection handles after getting rect-between-bounds from touch
348 // selection controller; otherwise, rect would be empty and the above
349 // calculations would be invalid.
350 rwhva_->selection_controller()->HideAndDisallowShowingAutomatically();
351 }
352
353 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698