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

Side by Side Diff: content/browser/web_contents/aura/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: Fixed test failures on Mac Created 5 years, 7 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/web_contents/aura/touch_selection_controller_client_au ra.h"
6
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 "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 class TouchSelectionControllerClientAura::EnvPreTargetHandler
49 : public ui::EventHandler {
sadrul 2015/04/29 19:55:03 Consider using a UserActivityObserver instead.
mohsen 2015/04/30 18:29:34 Apparently, UserActivityObserver mechanism is not
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_;
sadrul 2015/04/29 19:55:03 DISALLOW_COPY_AND_ASSIGN
mohsen 2015/04/30 18:29:34 Done.
63 };
64
65 TouchSelectionControllerClientAura::EnvPreTargetHandler::EnvPreTargetHandler(
66 ui::TouchSelectionController* selection_controller,
67 aura::Window* window)
68 : selection_controller_(selection_controller), window_(window) {
69 aura::Env::GetInstance()->AddPreTargetHandler(this);
70 }
71
72 TouchSelectionControllerClientAura::EnvPreTargetHandler::
73 ~EnvPreTargetHandler() {
74 aura::Env::GetInstance()->RemovePreTargetHandler(this);
75 }
76
77 void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnKeyEvent(
78 ui::KeyEvent* event) {
79 DCHECK(selection_controller_->is_insertion_active() ||
80 selection_controller_->is_selection_active());
81
82 selection_controller_->HideAndDisallowShowingAutomatically();
83 }
84
85 void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnMouseEvent(
86 ui::MouseEvent* event) {
87 DCHECK(selection_controller_->is_insertion_active() ||
88 selection_controller_->is_selection_active());
89
90 aura::client::CursorClient* cursor_client =
91 aura::client::GetCursorClient(window_->GetRootWindow());
92 if (!cursor_client || cursor_client->IsMouseEventsEnabled())
93 selection_controller_->HideAndDisallowShowingAutomatically();
94 }
95
96 void TouchSelectionControllerClientAura::EnvPreTargetHandler::OnScrollEvent(
97 ui::ScrollEvent* event) {
98 DCHECK(selection_controller_->is_insertion_active() ||
99 selection_controller_->is_selection_active());
100
101 selection_controller_->HideAndDisallowShowingAutomatically();
102 }
103
104 TouchSelectionControllerClientAura::TouchSelectionControllerClientAura(
105 RenderWidgetHostViewAura* rwhva)
106 : rwhva_(rwhva),
107 quick_menu_timer_(
108 FROM_HERE,
109 base::TimeDelta::FromMilliseconds(kQuickMenuDelayInMs),
110 base::Bind(&TouchSelectionControllerClientAura::ShowQuickMenu,
111 base::Unretained(this)),
112 false),
113 scroll_in_progress_(false),
114 handle_drag_in_progress_(false) {
115 }
116
117 TouchSelectionControllerClientAura::~TouchSelectionControllerClientAura() {
118 }
119
120 bool TouchSelectionControllerClientAura::SupportsAnimation() const {
121 return false;
122 }
123
124 void TouchSelectionControllerClientAura::SetNeedsAnimate() {
125 NOTREACHED();
126 }
127
128 void TouchSelectionControllerClientAura::MoveCaret(
129 const gfx::PointF& position) {
130 RenderWidgetHostImpl* host =
131 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost());
132 host->MoveCaret(gfx::ToRoundedPoint(position));
133 }
134
135 void TouchSelectionControllerClientAura::MoveRangeSelectionExtent(
136 const gfx::PointF& extent) {
137 RenderViewHost* rvh = RenderViewHost::From(rwhva_->GetRenderWidgetHost());
138 WebContentsImpl* wc =
139 static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvh));
140 wc->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent));
141 }
142
143 void TouchSelectionControllerClientAura::SelectBetweenCoordinates(
144 const gfx::PointF& base,
145 const gfx::PointF& extent) {
146 RenderViewHost* rvh = RenderViewHost::From(rwhva_->GetRenderWidgetHost());
147 WebContentsImpl* wc =
148 static_cast<WebContentsImpl*>(WebContents::FromRenderViewHost(rvh));
149 wc->SelectRange(gfx::ToRoundedPoint(base), gfx::ToRoundedPoint(extent));
150 }
151
152 void TouchSelectionControllerClientAura::OnSelectionEvent(
153 ui::SelectionEventType event) {
154 switch (event) {
155 case ui::SELECTION_SHOWN:
156 case ui::INSERTION_SHOWN:
157 UpdateQuickMenu();
158 env_pre_target_handler_.reset(new EnvPreTargetHandler(
159 rwhva_->selection_controller(), rwhva_->GetNativeView()));
160 break;
161 case ui::SELECTION_CLEARED:
162 case ui::INSERTION_CLEARED:
163 env_pre_target_handler_.reset();
164 UpdateQuickMenu();
165 break;
166 case ui::SELECTION_DRAG_STARTED:
167 case ui::INSERTION_DRAG_STARTED:
168 handle_drag_in_progress_ = true;
169 UpdateQuickMenu();
170 break;
171 case ui::SELECTION_DRAG_STOPPED:
172 case ui::INSERTION_DRAG_STOPPED:
173 handle_drag_in_progress_ = false;
174 UpdateQuickMenu();
175 break;
176 case ui::SELECTION_MOVED:
177 case ui::INSERTION_MOVED:
178 UpdateQuickMenu();
179 break;
180 case ui::INSERTION_TAPPED:
181 break;
182 };
183 }
184
185 scoped_ptr<ui::TouchHandleDrawable>
186 TouchSelectionControllerClientAura::CreateDrawable() {
187 return scoped_ptr<ui::TouchHandleDrawable>(
188 new ui::TouchHandleDrawableAura(rwhva_->GetNativeView()));
189 }
190
191 void TouchSelectionControllerClientAura::OnScrollStarted() {
192 rwhva_->selection_controller()->SetTemporarilyHidden(true);
193 scroll_in_progress_ = true;
194 UpdateQuickMenu();
195 }
196
197 void TouchSelectionControllerClientAura::OnScrollCompleted() {
198 rwhva_->selection_controller()->SetTemporarilyHidden(false);
199 scroll_in_progress_ = false;
200 UpdateQuickMenu();
201 }
202
203 bool TouchSelectionControllerClientAura::IsCommandIdEnabled(
204 int command_id) const {
205 bool editable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
206 bool readable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_PASSWORD;
207 gfx::Range selection_range;
208 rwhva_->GetSelectionRange(&selection_range);
209 bool has_selection = !selection_range.is_empty();
210 switch (command_id) {
211 case IDS_APP_CUT:
212 return editable && readable && has_selection;
213 case IDS_APP_COPY:
214 return readable && has_selection;
215 case IDS_APP_PASTE: {
216 base::string16 result;
217 ui::Clipboard::GetForCurrentThread()->ReadText(
218 ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
219 return editable && !result.empty();
220 }
221 case IDS_APP_DELETE:
222 return editable && has_selection;
223 case IDS_APP_SELECT_ALL:
224 return true;
225 default:
226 return false;
227 }
228 }
229
230 void TouchSelectionControllerClientAura::ExecuteCommand(int command_id,
231 int event_flags) {
232 rwhva_->selection_controller()->HideAndDisallowShowingAutomatically();
233 RenderViewHost* rvh = RenderViewHost::From(rwhva_->GetRenderWidgetHost());
234 WebContents* wc = WebContents::FromRenderViewHost(rvh);
235 switch (command_id) {
236 case IDS_APP_CUT:
237 wc->Cut();
238 break;
239 case IDS_APP_COPY:
240 wc->Copy();
241 break;
242 case IDS_APP_PASTE:
243 wc->Paste();
244 break;
245 case IDS_APP_DELETE:
246 wc->Delete();
247 break;
248 case IDS_APP_SELECT_ALL:
249 wc->SelectAll();
250 break;
251 default:
252 NOTREACHED();
253 break;
254 }
255 }
256
257 void TouchSelectionControllerClientAura::OpenContextMenu() {
258 rwhva_->selection_controller()->HideAndDisallowShowingAutomatically();
259 gfx::RectF anchor_rect =
260 rwhva_->selection_controller()->GetRectBetweenBounds();
261 gfx::PointF anchor_point =
262 gfx::PointF(anchor_rect.CenterPoint().x(), anchor_rect.y());
263 RenderWidgetHostImpl* host =
264 RenderWidgetHostImpl::From(rwhva_->GetRenderWidgetHost());
265 host->Send(new ViewMsg_ShowContextMenu(host->GetRoutingID(),
266 ui::MENU_SOURCE_TOUCH_EDIT_MENU,
267 gfx::ToRoundedPoint(anchor_point)));
268 }
269
270 bool TouchSelectionControllerClientAura::IsQuickMenuAllowed() const {
271 return !scroll_in_progress_ && !handle_drag_in_progress_;
272 }
273
274 void TouchSelectionControllerClientAura::ShowQuickMenu() {
275 if (!ui::TouchSelectionMenuRunner::GetInstance())
276 return;
277
278 gfx::RectF rect = rwhva_->selection_controller()->GetRectBetweenBounds();
279
280 // Clip rect to client bounds.
281 gfx::PointF origin = rect.origin();
282 gfx::PointF bottom_right = rect.bottom_right();
283 gfx::Rect client_bounds = rwhva_->GetNativeView()->bounds();
284 origin.SetToMax(client_bounds.origin());
285 bottom_right.SetToMin(client_bounds.bottom_right());
286 if (origin.x() > bottom_right.x() || origin.y() > bottom_right.y())
287 return;
288
289 gfx::Vector2dF diagonal = bottom_right - origin;
290 gfx::SizeF size(diagonal.x(), diagonal.y());
291 gfx::RectF anchor_rect(origin, size);
292
293 // Calculate maximum handle image size;
294 gfx::SizeF max_handle_size =
295 rwhva_->selection_controller()->GetStartHandleRect().size();
296 max_handle_size.SetToMax(
297 rwhva_->selection_controller()->GetEndHandleRect().size());
298
299 aura::Window* parent = rwhva_->GetNativeView();
300 ui::TouchSelectionMenuRunner::GetInstance()->RunMenu(
301 this, ConvertRectToScreen(parent, anchor_rect),
302 gfx::ToRoundedSize(max_handle_size), parent->GetToplevelWindow());
303 }
304
305 void TouchSelectionControllerClientAura::UpdateQuickMenu() {
306 // Hide quick menu if there is any.
307 if (ui::TouchSelectionMenuRunner::GetInstance() &&
308 ui::TouchSelectionMenuRunner::GetInstance()->IsRunning()) {
309 ui::TouchSelectionMenuRunner::GetInstance()->CloseMenu();
310 } else {
311 quick_menu_timer_.Stop();
312 }
313
314 // Start timer to show quick menu if necessary.
315 if (!rwhva_->selection_controller()->is_insertion_active() &&
316 !rwhva_->selection_controller()->is_selection_active())
317 return;
318
319 if (!IsQuickMenuAllowed())
320 return;
321
322 quick_menu_timer_.Reset();
323 }
324
325 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698