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

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: Without RenderWidgetHostDelegate part (on top of crrev.com/1162373002) Created 5 years, 6 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());
sadrul 2015/06/30 18:33:12 Sadness ... this is still pretty wrong.
mohsen 2015/07/03 18:07:23 Why?
sadrul 2015/07/15 17:00:14 Consider rotated windows. I think this is the app
44 }
45
46 } // namespace
47
48 class TouchSelectionControllerClientAura::EnvPreTargetHandler
49 : public ui::EventHandler {
sadrul 2015/06/30 18:33:12 Document.
mohsen 2015/07/03 18:07:23 Done.
50 public:
51 EnvPreTargetHandler(ui::TouchSelectionController* selection_controller,
52 aura::Window* window);
53 ~EnvPreTargetHandler() override;
54
55 private:
56 // EventHandler:
57 void OnKeyEvent(ui::KeyEvent* event) override;
58 void OnMouseEvent(ui::MouseEvent* event) override;
59 void OnScrollEvent(ui::ScrollEvent* event) override;
60
61 ui::TouchSelectionController* selection_controller_;
62 aura::Window* window_;
63
64 DISALLOW_COPY_AND_ASSIGN(EnvPreTargetHandler);
65 };
66
67 TouchSelectionControllerClientAura::EnvPreTargetHandler::EnvPreTargetHandler(
68 ui::TouchSelectionController* selection_controller,
69 aura::Window* window)
70 : selection_controller_(selection_controller), window_(window) {
71 aura::Env::GetInstance()->AddPreTargetHandler(this);
72 }
73
74 TouchSelectionControllerClientAura::EnvPreTargetHandler::
75 ~EnvPreTargetHandler() {
76 aura::Env::GetInstance()->RemovePreTargetHandler(this);
77 }
78
79 void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnKeyEvent(
80 ui::KeyEvent* event) {
81 DCHECK_NE(ui::TouchSelectionController::INACTIVE,
82 selection_controller_->active_status());
83
84 selection_controller_->HideAndDisallowShowingAutomatically();
85 }
86
87 void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnMouseEvent(
88 ui::MouseEvent* event) {
89 DCHECK_NE(ui::TouchSelectionController::INACTIVE,
90 selection_controller_->active_status());
91
92 aura::client::CursorClient* cursor_client =
93 aura::client::GetCursorClient(window_->GetRootWindow());
94 if (!cursor_client || cursor_client->IsMouseEventsEnabled())
sadrul 2015/06/30 18:33:12 Can you document why this check with cursor-client
mohsen 2015/07/03 18:07:23 Done.
95 selection_controller_->HideAndDisallowShowingAutomatically();
96 }
97
98 void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnScrollEvent(
99 ui::ScrollEvent* event) {
100 DCHECK_NE(ui::TouchSelectionController::INACTIVE,
101 selection_controller_->active_status());
102
103 selection_controller_->HideAndDisallowShowingAutomatically();
104 }
105
106 TouchSelectionControllerClientAura::TouchSelectionControllerClientAura(
107 RenderWidgetHostViewAura* rwhva)
108 : rwhva_(rwhva),
109 quick_menu_timer_(
110 FROM_HERE,
111 base::TimeDelta::FromMilliseconds(kQuickMenuDelayInMs),
112 base::Bind(&TouchSelectionControllerClientAura::ShowQuickMenu,
113 base::Unretained(this)),
114 false),
115 touch_down_(false),
116 scroll_in_progress_(false),
117 handle_drag_in_progress_(false) {
118 DCHECK(rwhva_);
119 }
120
121 TouchSelectionControllerClientAura::~TouchSelectionControllerClientAura() {
122 }
123
124 void TouchSelectionControllerClientAura::OnWindowMoved() {
125 UpdateQuickMenu();
126 }
127
128 void TouchSelectionControllerClientAura::OnTouchDown() {
129 touch_down_ = true;
130 UpdateQuickMenu();
131 }
132
133 void TouchSelectionControllerClientAura::OnTouchUp() {
134 touch_down_ = false;
135 UpdateQuickMenu();
136 }
137
138 void TouchSelectionControllerClientAura::OnSelectionScrollStarted() {
139 scroll_in_progress_ = true;
140 rwhva_->selection_controller()->SetTemporarilyHidden(true);
141 UpdateQuickMenu();
142 }
143
144 void TouchSelectionControllerClientAura::OnSelectionScrollCompleted() {
145 scroll_in_progress_ = false;
146 rwhva_->selection_controller()->SetTemporarilyHidden(false);
147 UpdateQuickMenu();
148 }
149
150 bool TouchSelectionControllerClientAura::IsQuickMenuAllowed() const {
151 return !touch_down_ && !scroll_in_progress_ && !handle_drag_in_progress_;
152 }
153
154 void TouchSelectionControllerClientAura::ShowQuickMenu() {
155 if (!ui::TouchSelectionMenuRunner::GetInstance())
156 return;
157
158 gfx::RectF rect = rwhva_->selection_controller()->GetRectBetweenBounds();
sadrul 2015/06/30 18:33:12 Can you remind me what coord-space this rect is in
mohsen 2015/07/03 18:07:23 This function will return bounding box of selectio
159
160 // Clip rect to client bounds.
161 gfx::PointF origin = rect.origin();
162 gfx::PointF bottom_right = rect.bottom_right();
163 gfx::Rect client_bounds = rwhva_->GetNativeView()->bounds();
164 origin.SetToMax(client_bounds.origin());
165 bottom_right.SetToMin(client_bounds.bottom_right());
166 if (origin.x() > bottom_right.x() || origin.y() > bottom_right.y())
167 return;
168
169 gfx::Vector2dF diagonal = bottom_right - origin;
sadrul 2015/06/30 18:33:12 Do these do the right thing for RTL?
mohsen 2015/07/03 18:07:23 Yeah, 'right' is always greater than or equal to '
170 gfx::SizeF size(diagonal.x(), diagonal.y());
171 gfx::RectF anchor_rect(origin, size);
172
173 // Calculate maximum handle image size;
174 gfx::SizeF max_handle_size =
175 rwhva_->selection_controller()->GetStartHandleRect().size();
176 max_handle_size.SetToMax(
177 rwhva_->selection_controller()->GetEndHandleRect().size());
178
179 aura::Window* parent = rwhva_->GetNativeView();
180 ui::TouchSelectionMenuRunner::GetInstance()->OpenMenu(
181 this, ConvertRectToScreen(parent, anchor_rect),
182 gfx::ToRoundedSize(max_handle_size), parent->GetToplevelWindow());
183 }
184
185 void TouchSelectionControllerClientAura::UpdateQuickMenu() {
186 // Hide quick menu if there is any.
187 if (ui::TouchSelectionMenuRunner::GetInstance() &&
188 ui::TouchSelectionMenuRunner::GetInstance()->IsRunning()) {
189 ui::TouchSelectionMenuRunner::GetInstance()->CloseMenu();
190 } else {
191 quick_menu_timer_.Stop();
192 }
193
194 // Start timer to show quick menu if necessary.
195 if (rwhva_->selection_controller()->active_status() ==
196 ui::TouchSelectionController::INACTIVE) {
197 return;
198 }
199
200 if (!IsQuickMenuAllowed())
201 return;
202
203 quick_menu_timer_.Reset();
204 }
sadrul 2015/06/30 18:33:12 Can this be more like: bool menu_should_show = a
mohsen 2015/07/03 18:07:23 We'd want to hide the menu even if menu_should_sho
205
206 bool TouchSelectionControllerClientAura::SupportsAnimation() const {
207 return false;
208 }
209
210 void TouchSelectionControllerClientAura::SetNeedsAnimate() {
211 NOTREACHED();
212 }
213
214 void TouchSelectionControllerClientAura::MoveCaret(
215 const gfx::PointF& position) {
216 RenderWidgetHostImpl* host =
217 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost());
218 host->MoveCaret(gfx::ToRoundedPoint(position));
219 }
220
221 void TouchSelectionControllerClientAura::MoveRangeSelectionExtent(
222 const gfx::PointF& extent) {
223 RenderWidgetHostDelegate* host_delegate =
224 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost())->delegate();
225 if (host_delegate)
226 host_delegate->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent));
227 }
228
229 void TouchSelectionControllerClientAura::SelectBetweenCoordinates(
230 const gfx::PointF& base,
231 const gfx::PointF& extent) {
232 RenderWidgetHostDelegate* host_delegate =
233 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost())->delegate();
234 if (host_delegate)
235 host_delegate->SelectRange(gfx::ToRoundedPoint(base),
236 gfx::ToRoundedPoint(extent));
sadrul 2015/06/30 18:33:12 {}
mohsen 2015/07/03 18:07:23 Done.
237 }
238
239 void TouchSelectionControllerClientAura::OnSelectionEvent(
240 ui::SelectionEventType event) {
241 switch (event) {
242 case ui::SELECTION_SHOWN:
243 case ui::INSERTION_SHOWN:
244 UpdateQuickMenu();
245 env_pre_target_handler_.reset(new EnvPreTargetHandler(
246 rwhva_->selection_controller(), rwhva_->GetNativeView()));
247 break;
248 case ui::SELECTION_CLEARED:
249 case ui::INSERTION_CLEARED:
250 env_pre_target_handler_.reset();
251 UpdateQuickMenu();
252 break;
253 case ui::SELECTION_DRAG_STARTED:
254 case ui::INSERTION_DRAG_STARTED:
255 handle_drag_in_progress_ = true;
256 UpdateQuickMenu();
257 break;
258 case ui::SELECTION_DRAG_STOPPED:
259 case ui::INSERTION_DRAG_STOPPED:
260 handle_drag_in_progress_ = false;
261 UpdateQuickMenu();
262 break;
263 case ui::SELECTION_MOVED:
264 case ui::INSERTION_MOVED:
265 UpdateQuickMenu();
266 break;
267 case ui::INSERTION_TAPPED:
268 break;
269 };
270 }
271
272 scoped_ptr<ui::TouchHandleDrawable>
273 TouchSelectionControllerClientAura::CreateDrawable() {
274 return scoped_ptr<ui::TouchHandleDrawable>(
275 new ui::TouchHandleDrawableAura(rwhva_->GetNativeView()));
276 }
277
278 bool TouchSelectionControllerClientAura::IsCommandIdEnabled(
279 int command_id) const {
280 bool editable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
281 bool readable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_PASSWORD;
282 gfx::Range selection_range;
283 rwhva_->GetSelectionRange(&selection_range);
284 bool has_selection = !selection_range.is_empty();
285 switch (command_id) {
286 case IDS_APP_CUT:
287 return editable && readable && has_selection;
288 case IDS_APP_COPY:
289 return readable && has_selection;
290 case IDS_APP_PASTE: {
291 base::string16 result;
292 ui::Clipboard::GetForCurrentThread()->ReadText(
293 ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
294 return editable && !result.empty();
295 }
296 case IDS_APP_DELETE:
297 return editable && has_selection;
298 case IDS_APP_SELECT_ALL:
299 return true;
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:
sadrul 2015/06/30 18:33:12 Shouldn't you also handle DELETE and SELECT_ALL? I
mohsen 2015/07/03 18:07:23 The quick menu as implemented for Views only can h
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 // Hide selection handles after getting rect-between-bounds from touch
340 // selection controller; otherwise, rect would be empty.
341 rwhva_->selection_controller()->HideAndDisallowShowingAutomatically();
342 }
343
344 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698