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

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: Improved a comment Created 5 years, 5 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.
sadrul 2015/07/15 17:00:15 'mouse event is synthesized from a touch event' ..
mohsen 2015/07/16 22:06:19 Yeah, that's mostly happening on Windows and the E
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();
sadrul 2015/07/15 17:00:15 Document that rect is in rwhva_'s window's coord-s
mohsen 2015/07/16 22:06:19 Done.
163
164 // Clip rect to client bounds.
165 gfx::PointF origin = rect.origin();
166 gfx::PointF bottom_right = rect.bottom_right();
167 gfx::Rect client_bounds = rwhva_->GetNativeView()->bounds();
168 origin.SetToMax(client_bounds.origin());
169 bottom_right.SetToMin(client_bounds.bottom_right());
170 if (origin.x() > bottom_right.x() || origin.y() > bottom_right.y())
171 return;
172
173 gfx::Vector2dF diagonal = bottom_right - origin;
174 gfx::SizeF size(diagonal.x(), diagonal.y());
175 gfx::RectF anchor_rect(origin, size);
176
177 // Calculate maximum handle image size;
178 gfx::SizeF max_handle_size =
179 rwhva_->selection_controller()->GetStartHandleRect().size();
180 max_handle_size.SetToMax(
181 rwhva_->selection_controller()->GetEndHandleRect().size());
182
183 aura::Window* parent = rwhva_->GetNativeView();
184 ui::TouchSelectionMenuRunner::GetInstance()->OpenMenu(
185 this, ConvertRectToScreen(parent, anchor_rect),
186 gfx::ToRoundedSize(max_handle_size), parent->GetToplevelWindow());
187 }
188
189 void TouchSelectionControllerClientAura::UpdateQuickMenu() {
190 bool menu_is_showing =
191 ui::TouchSelectionMenuRunner::GetInstance() &&
192 ui::TouchSelectionMenuRunner::GetInstance()->IsRunning();
193 bool menu_should_show = rwhva_->selection_controller()->active_status() !=
194 ui::TouchSelectionController::INACTIVE &&
195 IsQuickMenuAllowed();
196
197 // Hide the quick menu if there is any. This should happen even if the menu
198 // should be shown again, in order to update its location or content.
199 if (menu_is_showing)
200 ui::TouchSelectionMenuRunner::GetInstance()->CloseMenu();
201 else
202 quick_menu_timer_.Stop();
203
204 // Start timer to show quick menu if necessary.
205 if (menu_should_show)
206 quick_menu_timer_.Reset();
207 }
208
209 bool TouchSelectionControllerClientAura::SupportsAnimation() const {
210 return false;
211 }
212
213 void TouchSelectionControllerClientAura::SetNeedsAnimate() {
214 NOTREACHED();
215 }
216
217 void TouchSelectionControllerClientAura::MoveCaret(
218 const gfx::PointF& position) {
219 RenderWidgetHostImpl* host =
220 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost());
221 host->MoveCaret(gfx::ToRoundedPoint(position));
222 }
223
224 void TouchSelectionControllerClientAura::MoveRangeSelectionExtent(
225 const gfx::PointF& extent) {
226 RenderWidgetHostDelegate* host_delegate =
227 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost())->delegate();
228 if (host_delegate)
229 host_delegate->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent));
230 }
231
232 void TouchSelectionControllerClientAura::SelectBetweenCoordinates(
233 const gfx::PointF& base,
234 const gfx::PointF& extent) {
235 RenderWidgetHostDelegate* host_delegate =
236 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost())->delegate();
237 if (host_delegate) {
238 host_delegate->SelectRange(gfx::ToRoundedPoint(base),
239 gfx::ToRoundedPoint(extent));
240 }
241 }
242
243 void TouchSelectionControllerClientAura::OnSelectionEvent(
244 ui::SelectionEventType event) {
245 switch (event) {
246 case ui::SELECTION_SHOWN:
247 case ui::INSERTION_SHOWN:
248 UpdateQuickMenu();
249 env_pre_target_handler_.reset(new EnvPreTargetHandler(
250 rwhva_->selection_controller(), rwhva_->GetNativeView()));
251 break;
252 case ui::SELECTION_CLEARED:
253 case ui::INSERTION_CLEARED:
254 env_pre_target_handler_.reset();
255 UpdateQuickMenu();
256 break;
257 case ui::SELECTION_DRAG_STARTED:
258 case ui::INSERTION_DRAG_STARTED:
259 handle_drag_in_progress_ = true;
260 UpdateQuickMenu();
261 break;
262 case ui::SELECTION_DRAG_STOPPED:
263 case ui::INSERTION_DRAG_STOPPED:
264 handle_drag_in_progress_ = false;
265 UpdateQuickMenu();
266 break;
267 case ui::SELECTION_MOVED:
268 case ui::INSERTION_MOVED:
269 UpdateQuickMenu();
270 break;
271 case ui::INSERTION_TAPPED:
272 break;
273 };
274 }
275
276 scoped_ptr<ui::TouchHandleDrawable>
277 TouchSelectionControllerClientAura::CreateDrawable() {
278 return scoped_ptr<ui::TouchHandleDrawable>(
279 new ui::TouchHandleDrawableAura(rwhva_->GetNativeView()));
280 }
281
282 bool TouchSelectionControllerClientAura::IsCommandIdEnabled(
283 int command_id) const {
284 bool editable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
285 bool readable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_PASSWORD;
286 gfx::Range selection_range;
287 rwhva_->GetSelectionRange(&selection_range);
288 bool has_selection = !selection_range.is_empty();
289 switch (command_id) {
290 case IDS_APP_CUT:
291 return editable && readable && has_selection;
292 case IDS_APP_COPY:
293 return readable && has_selection;
294 case IDS_APP_PASTE: {
295 base::string16 result;
296 ui::Clipboard::GetForCurrentThread()->ReadText(
297 ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
298 return editable && !result.empty();
299 }
300 default:
301 return false;
302 }
303 }
304
305 void TouchSelectionControllerClientAura::ExecuteCommand(int command_id,
306 int event_flags) {
307 rwhva_->selection_controller()->HideAndDisallowShowingAutomatically();
308 RenderWidgetHostDelegate* host_delegate =
309 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost())->delegate();
310 if (!host_delegate)
311 return;
312
313 switch (command_id) {
314 case IDS_APP_CUT:
315 host_delegate->Cut();
316 break;
317 case IDS_APP_COPY:
318 host_delegate->Copy();
319 break;
320 case IDS_APP_PASTE:
321 host_delegate->Paste();
322 break;
323 default:
324 NOTREACHED();
325 break;
326 }
327 }
328
329 void TouchSelectionControllerClientAura::RunContextMenu() {
330 gfx::RectF anchor_rect =
331 rwhva_->selection_controller()->GetRectBetweenBounds();
332 gfx::PointF anchor_point =
333 gfx::PointF(anchor_rect.CenterPoint().x(), anchor_rect.y());
334 RenderWidgetHostImpl* host =
335 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost());
336 host->Send(new ViewMsg_ShowContextMenu(host->GetRoutingID(),
337 ui::MENU_SOURCE_TOUCH_EDIT_MENU,
338 gfx::ToRoundedPoint(anchor_point)));
339
340 // Hide selection handles after getting rect-between-bounds from touch
341 // selection controller; otherwise, rect would be empty and the above
342 // calculations would be invalid.
343 rwhva_->selection_controller()->HideAndDisallowShowingAutomatically();
344 }
345
346 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698