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

Side by Side Diff: ui/views/touchui/touch_selection_controller_impl.cc

Issue 700563002: Implementing directional text selection handles (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@new_assets_text
Patch Set: Addressing feedback (contd) plus Rebase Created 6 years, 1 month 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
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/touchui/touch_selection_controller_impl.h" 5 #include "ui/views/touchui/touch_selection_controller_impl.h"
6 6
7 #include "base/time/time.h" 7 #include "base/time/time.h"
8 #include "ui/aura/client/cursor_client.h" 8 #include "ui/aura/client/cursor_client.h"
9 #include "ui/aura/env.h" 9 #include "ui/aura/env.h"
10 #include "ui/aura/window.h" 10 #include "ui/aura/window.h"
11 #include "ui/base/resource/resource_bundle.h" 11 #include "ui/base/resource/resource_bundle.h"
12 #include "ui/gfx/canvas.h" 12 #include "ui/gfx/canvas.h"
13 #include "ui/gfx/image/image.h" 13 #include "ui/gfx/image/image.h"
14 #include "ui/gfx/path.h" 14 #include "ui/gfx/path.h"
15 #include "ui/gfx/rect.h" 15 #include "ui/gfx/rect.h"
16 #include "ui/gfx/screen.h" 16 #include "ui/gfx/screen.h"
17 #include "ui/gfx/size.h" 17 #include "ui/gfx/size.h"
18 #include "ui/resources/grit/ui_resources.h" 18 #include "ui/resources/grit/ui_resources.h"
19 #include "ui/strings/grit/ui_strings.h" 19 #include "ui/strings/grit/ui_strings.h"
20 #include "ui/views/widget/widget.h" 20 #include "ui/views/widget/widget.h"
21 #include "ui/wm/core/coordinate_conversion.h"
21 #include "ui/wm/core/masked_window_targeter.h" 22 #include "ui/wm/core/masked_window_targeter.h"
22 23
23 namespace { 24 namespace {
24 25
25 // Constants defining the visual attributes of selection handles 26 // Constants defining the visual attributes of selection handles
26 const int kSelectionHandleLineWidth = 1; 27
28 // Controls the width of the cursor line associated with the selection handle.
29 const int kSelectionHandleLineWidth = 2;
30
27 const SkColor kSelectionHandleLineColor = 31 const SkColor kSelectionHandleLineColor =
28 SkColorSetRGB(0x42, 0x81, 0xf4); 32 SkColorSetRGB(0x42, 0x81, 0xf4);
29 33
30 // When a handle is dragged, the drag position reported to the client view is 34 // When a handle is dragged, the drag position reported to the client view is
31 // offset vertically to represent the cursor position. This constant specifies 35 // offset vertically to represent the cursor position. This constant specifies
32 // the offset in pixels above the "O" (see pic below). This is required because 36 // the offset in pixels above the "O" (see pic below). This is required because
33 // say if this is zero, that means the drag position we report is the point 37 // say if this is zero, that means the drag position we report is the point
34 // right above the "O" or the bottom most point of the cursor "|". In that case, 38 // right above the "O" or the bottom most point of the cursor "|". In that case,
35 // a vertical movement of even one pixel will make the handle jump to the line 39 // a vertical movement of even one pixel will make the handle jump to the line
36 // below it. So when the user just starts dragging, the handle will jump to the 40 // below it. So when the user just starts dragging, the handle will jump to the
37 // next line if the user makes any vertical movement. It is correct but 41 // next line if the user makes any vertical movement. It is correct but
38 // looks/feels weird. So we have this non-zero offset to prevent this jumping. 42 // looks/feels weird. So we have this non-zero offset to prevent this jumping.
39 // 43 //
40 // Editing handle widget showing the difference between the position of the 44 // Editing handle widget showing the padding and difference between the position
41 // ET_GESTURE_SCROLL_UPDATE event and the drag position reported to the client: 45 // of the ET_GESTURE_SCROLL_UPDATE event and the drag position reported to the
46 // client:
42 // _____ 47 // _____
43 // | |<-|---- Drag position reported to client 48 // | |<-|---- Drag position reported to client
44 // _ | O | 49 // _ | O |
45 // Vertical Padding __| | <-|---- ET_GESTURE_SCROLL_UPDATE position 50 // Vertical Padding __| | <-|---- ET_GESTURE_SCROLL_UPDATE position
46 // |_ |_____|<--- Editing handle widget 51 // |_ |_____|<--- Editing handle widget
47 // 52 //
48 // | | 53 // | |
49 // T 54 // T
50 // Horizontal Padding 55 // Horizontal Padding
51 // 56 //
(...skipping 23 matching lines...) Expand all
75 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); 80 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
76 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 81 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
77 params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE; 82 params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE;
78 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 83 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
79 params.parent = context; 84 params.parent = context;
80 params.delegate = widget_delegate; 85 params.delegate = widget_delegate;
81 widget->Init(params); 86 widget->Init(params);
82 return widget; 87 return widget;
83 } 88 }
84 89
85 gfx::Image* GetHandleImage() { 90 gfx::Image* GetCenterHandleImage() {
86 static gfx::Image* handle_image = NULL; 91 static gfx::Image* handle_image = nullptr;
87 if (!handle_image) { 92 if (!handle_image) {
88 handle_image = &ui::ResourceBundle::GetSharedInstance().GetImageNamed( 93 handle_image = &ui::ResourceBundle::GetSharedInstance().GetImageNamed(
89 IDR_TEXT_SELECTION_HANDLE); 94 IDR_TEXT_SELECTION_HANDLE_CENTER);
90 } 95 }
91 return handle_image; 96 return handle_image;
92 } 97 }
93 98
94 gfx::Size GetHandleImageSize() { 99 gfx::Image* GetLeftHandleImage() {
95 return GetHandleImage()->Size(); 100 static gfx::Image* handle_image = nullptr;
101 if (!handle_image) {
102 handle_image = &ui::ResourceBundle::GetSharedInstance().GetImageNamed(
103 IDR_TEXT_SELECTION_HANDLE_LEFT);
104 }
105 return handle_image;
96 } 106 }
97 107
98 // Cannot use gfx::UnionRect since it does not work for empty rects. 108 gfx::Image* GetRightHandleImage() {
99 gfx::Rect Union(const gfx::Rect& r1, const gfx::Rect& r2) { 109 static gfx::Image* handle_image = nullptr;
100 int rx = std::min(r1.x(), r2.x()); 110 if (!handle_image) {
101 int ry = std::min(r1.y(), r2.y()); 111 handle_image = &ui::ResourceBundle::GetSharedInstance().GetImageNamed(
102 int rr = std::max(r1.right(), r2.right()); 112 IDR_TEXT_SELECTION_HANDLE_RIGHT);
103 int rb = std::max(r1.bottom(), r2.bottom()); 113 }
104 114 return handle_image;
105 return gfx::Rect(rx, ry, rr - rx, rb - ry);
106 } 115 }
107 116
108 // Convenience methods to convert a |rect| from screen to the |client|'s 117 // Return the appropriate handle image based on the bound's type
118 gfx::Image* GetHandleImage(ui::SelectionBound::Type bound_type) {
119 switch(bound_type) {
120 case ui::SelectionBound::LEFT:
121 return GetLeftHandleImage();
122 case ui::SelectionBound::CENTER:
123 return GetCenterHandleImage();
124 case ui::SelectionBound::RIGHT:
125 return GetRightHandleImage();
126 default:
127 NOTREACHED() << "Invalid touch handle bound type.";
128 return nullptr;
129 };
130 }
131
132 enum Alignment {ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT};
133
134 // Determine the cursor line alignment to the handle image based on the bound
135 // type. Depends on the visual shapes of the handle image assets.
136 Alignment GetCursorAlignment(ui::SelectionBound::Type bound_type) {
137 switch (bound_type) {
138 case ui::SelectionBound::LEFT:
139 return ALIGN_RIGHT;
140 case ui::SelectionBound::RIGHT:
141 return ALIGN_LEFT;
142 case ui::SelectionBound::CENTER:
143 return ALIGN_CENTER;
144 default:
145 NOTREACHED() << "Undefined bound type for cursor alignment.";
146 return ALIGN_LEFT;
147 };
148 }
149
150 // Calculates the bounds of the widget containing the selection handle based
151 // on the SelectionBound's type and location
152 gfx::Rect GetSelectionWidgetBounds(const ui::SelectionBound& bound) {
153 Alignment cursor_alignment = GetCursorAlignment(bound.type);
154 gfx::Size image_size = GetHandleImage(bound.type)->Size();
155 int widget_width = image_size.width() + 2 * kSelectionHandleHorizPadding;
156 int widget_height = bound.GetHeight() + image_size.height() +
157 kSelectionHandleVertPadding;
158 int widget_left = 0;
159 switch (cursor_alignment) {
160 case ALIGN_LEFT:
161 widget_left = bound.edge_top.x() - kSelectionHandleHorizPadding;
162 break;
163 case ALIGN_RIGHT:
164 widget_left = bound.edge_top.x() - image_size.width() -
165 kSelectionHandleHorizPadding;
166 break;
167 case ALIGN_CENTER:
168 widget_left = bound.edge_top.x() - widget_width / 2;
169 break;
170 };
171 return gfx::Rect(
172 widget_left, bound.edge_top.y(), widget_width, widget_height);
173 }
174
175 gfx::Size GetMaxHandleImageSize() {
176 gfx::Rect center_rect = gfx::Rect(GetCenterHandleImage()->Size());
177 gfx::Rect left_rect = gfx::Rect(GetLeftHandleImage()->Size());
178 gfx::Rect right_rect = gfx::Rect(GetRightHandleImage()->Size());
179 gfx::Rect union_rect = center_rect;
180 union_rect.Union(left_rect);
181 union_rect.Union(right_rect);
182 return union_rect.size();
183 }
184
185 // Convenience methods to convert a |bound| from screen to the |client|'s
109 // coordinate system and vice versa. 186 // coordinate system and vice versa.
110 // Note that this is not quite correct because it does not take into account 187 // Note that this is not quite correct because it does not take into account
111 // transforms such as rotation and scaling. This should be in TouchEditable. 188 // transforms such as rotation and scaling. This should be in TouchEditable.
112 // TODO(varunjain): Fix this. 189 // TODO(varunjain): Fix this.
113 gfx::Rect ConvertFromScreen(ui::TouchEditable* client, const gfx::Rect& rect) { 190 ui::SelectionBound ConvertFromScreen(ui::TouchEditable* client,
114 gfx::Point origin = rect.origin(); 191 const ui::SelectionBound& bound) {
115 client->ConvertPointFromScreen(&origin); 192 ui::SelectionBound result = bound;
116 return gfx::Rect(origin, rect.size()); 193 gfx::Point edge_bottom = bound.edge_bottom;
194 gfx::Point edge_top = bound.edge_top;
195 client->ConvertPointFromScreen(&edge_bottom);
196 client->ConvertPointFromScreen(&edge_top);
197 result.edge_bottom = edge_bottom;
198 result.edge_top = edge_top;
199 return result;
117 } 200 }
118 gfx::Rect ConvertToScreen(ui::TouchEditable* client, const gfx::Rect& rect) { 201
119 gfx::Point origin = rect.origin(); 202 ui::SelectionBound ConvertToScreen(ui::TouchEditable* client,
120 client->ConvertPointToScreen(&origin); 203 const ui::SelectionBound& bound) {
121 return gfx::Rect(origin, rect.size()); 204 ui::SelectionBound result = bound;
205 gfx::Point edge_bottom = bound.edge_bottom;
206 gfx::Point edge_top = bound.edge_top;
207 client->ConvertPointToScreen(&edge_bottom);
208 client->ConvertPointToScreen(&edge_top);
209 result.edge_bottom = edge_bottom;
210 result.edge_top = edge_top;
211 return result;
212 }
213
214 gfx::Rect BoundToRect(const ui::SelectionBound& bound) {
215 return gfx::BoundingRect(bound.edge_top, bound.edge_bottom);
122 } 216 }
123 217
124 } // namespace 218 } // namespace
125 219
126 namespace views { 220 namespace views {
127 221
128 typedef TouchSelectionControllerImpl::EditingHandleView EditingHandleView; 222 typedef TouchSelectionControllerImpl::EditingHandleView EditingHandleView;
129 223
130 class TouchHandleWindowTargeter : public wm::MaskedWindowTargeter { 224 class TouchHandleWindowTargeter : public wm::MaskedWindowTargeter {
131 public: 225 public:
132 TouchHandleWindowTargeter(aura::Window* window, 226 TouchHandleWindowTargeter(aura::Window* window,
133 EditingHandleView* handle_view); 227 EditingHandleView* handle_view);
134 228
135 ~TouchHandleWindowTargeter() override {} 229 ~TouchHandleWindowTargeter() override {}
136 230
137 private: 231 private:
138 // wm::MaskedWindowTargeter: 232 // wm::MaskedWindowTargeter:
139 bool GetHitTestMask(aura::Window* window, gfx::Path* mask) const override; 233 bool GetHitTestMask(aura::Window* window, gfx::Path* mask) const override;
140 234
141 EditingHandleView* handle_view_; 235 EditingHandleView* handle_view_;
142 236
143 DISALLOW_COPY_AND_ASSIGN(TouchHandleWindowTargeter); 237 DISALLOW_COPY_AND_ASSIGN(TouchHandleWindowTargeter);
144 }; 238 };
145 239
146 // A View that displays the text selection handle. 240 // A View that displays the text selection handle.
147 class TouchSelectionControllerImpl::EditingHandleView 241 class TouchSelectionControllerImpl::EditingHandleView
148 : public views::WidgetDelegateView { 242 : public views::WidgetDelegateView {
149 public: 243 public:
150 EditingHandleView(TouchSelectionControllerImpl* controller, 244 EditingHandleView(TouchSelectionControllerImpl* controller,
151 gfx::NativeView context) 245 gfx::NativeView context,
246 bool is_cursor_handle)
152 : controller_(controller), 247 : controller_(controller),
153 drag_offset_(0), 248 image_(GetCenterHandleImage()),
249 is_cursor_handle_(is_cursor_handle),
154 draw_invisible_(false) { 250 draw_invisible_(false) {
155 widget_.reset(CreateTouchSelectionPopupWidget(context, this)); 251 widget_.reset(CreateTouchSelectionPopupWidget(context, this));
156 widget_->SetContentsView(this); 252 widget_->SetContentsView(this);
157 253
158 aura::Window* window = widget_->GetNativeWindow(); 254 aura::Window* window = widget_->GetNativeWindow();
159 window->SetEventTargeter(scoped_ptr<ui::EventTargeter>( 255 window->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
160 new TouchHandleWindowTargeter(window, this))); 256 new TouchHandleWindowTargeter(window, this)));
161 257
162 // We are owned by the TouchSelectionController. 258 // We are owned by the TouchSelectionController.
163 set_owned_by_client(); 259 set_owned_by_client();
164 } 260 }
165 261
166 ~EditingHandleView() override { SetWidgetVisible(false, false); } 262 ~EditingHandleView() override { SetWidgetVisible(false, false); }
167 263
168 // Overridden from views::WidgetDelegateView: 264 // Overridden from views::WidgetDelegateView:
169 bool WidgetHasHitTestMask() const override { return true; } 265 bool WidgetHasHitTestMask() const override { return true; }
170 266
171 void GetWidgetHitTestMask(gfx::Path* mask) const override { 267 void GetWidgetHitTestMask(gfx::Path* mask) const override {
172 gfx::Size image_size = GetHandleImageSize(); 268 gfx::Size image_size = image_->Size();
173 mask->addRect(SkIntToScalar(0), SkIntToScalar(selection_rect_.height()), 269 mask->addRect(
270 SkIntToScalar(0),
271 SkIntToScalar(selection_bound_.GetHeight()),
174 SkIntToScalar(image_size.width()) + 2 * kSelectionHandleHorizPadding, 272 SkIntToScalar(image_size.width()) + 2 * kSelectionHandleHorizPadding,
175 SkIntToScalar(selection_rect_.height() + image_size.height() + 273 SkIntToScalar(selection_bound_.GetHeight() + image_size.height() +
176 kSelectionHandleVertPadding)); 274 kSelectionHandleVertPadding));
177 } 275 }
178 276
179 void DeleteDelegate() override { 277 void DeleteDelegate() override {
180 // We are owned and deleted by TouchSelectionController. 278 // We are owned and deleted by TouchSelectionController.
181 } 279 }
182 280
183 // Overridden from views::View: 281 // Overridden from views::View:
184 void OnPaint(gfx::Canvas* canvas) override { 282 void OnPaint(gfx::Canvas* canvas) override {
185 if (draw_invisible_) 283 if (draw_invisible_)
186 return; 284 return;
187 gfx::Size image_size = GetHandleImageSize();
188 int cursor_pos_x = image_size.width() / 2 - kSelectionHandleLineWidth +
189 kSelectionHandleHorizPadding;
190 285
286 Alignment cursor_alignment = GetCursorAlignment(selection_bound_.type);
287 int cursor_x = 0;
288 switch (cursor_alignment) {
289 case ALIGN_RIGHT:
290 cursor_x =
291 selection_bound_.edge_top.x() - kSelectionHandleLineWidth + 1;
292 break;
293 case ALIGN_LEFT:
294 cursor_x = selection_bound_.edge_top.x() - 1;
295 break;
296 case ALIGN_CENTER:
297 cursor_x =
298 selection_bound_.edge_top.x() - kSelectionHandleLineWidth / 2;
299 break;
300 };
191 // Draw the cursor line. 301 // Draw the cursor line.
192 canvas->FillRect( 302 canvas->FillRect(gfx::Rect(cursor_x,
193 gfx::Rect(cursor_pos_x, 0, 303 0,
194 2 * kSelectionHandleLineWidth + 1, selection_rect_.height()), 304 kSelectionHandleLineWidth,
195 kSelectionHandleLineColor); 305 selection_bound_.GetHeight()),
196 306 kSelectionHandleLineColor);
197 // Draw the handle image. 307 // Draw the handle image.
198 canvas->DrawImageInt(*GetHandleImage()->ToImageSkia(), 308 canvas->DrawImageInt(*image_->ToImageSkia(),
199 kSelectionHandleHorizPadding, selection_rect_.height()); 309 kSelectionHandleHorizPadding, selection_bound_.GetHeight());
200 } 310 }
201 311
202 void OnGestureEvent(ui::GestureEvent* event) override { 312 void OnGestureEvent(ui::GestureEvent* event) override {
203 event->SetHandled(); 313 event->SetHandled();
204 switch (event->type()) { 314 switch (event->type()) {
205 case ui::ET_GESTURE_SCROLL_BEGIN: 315 case ui::ET_GESTURE_SCROLL_BEGIN: {
206 widget_->SetCapture(this); 316 widget_->SetCapture(this);
207 controller_->SetDraggingHandle(this); 317 controller_->SetDraggingHandle(this);
208 drag_offset_ = event->y() - selection_rect_.height() + 318 // Distance from the point which is |kSelectionHandleVerticalDragOffset|
209 kSelectionHandleVerticalDragOffset; 319 // pixels above the bottom of the handle's cursor line to the event
320 // location (aka the touch-drag point).
321 drag_offset_ = selection_bound_.edge_bottom -
322 gfx::Vector2d(0, kSelectionHandleVerticalDragOffset) -
323 event->location();
210 break; 324 break;
325 }
211 case ui::ET_GESTURE_SCROLL_UPDATE: { 326 case ui::ET_GESTURE_SCROLL_UPDATE: {
212 gfx::Point drag_pos(event->location().x(), 327 controller_->SelectionHandleDragged(event->location() + drag_offset_);
213 event->location().y() - drag_offset_);
214 controller_->SelectionHandleDragged(drag_pos);
215 break; 328 break;
216 } 329 }
217 case ui::ET_GESTURE_SCROLL_END: 330 case ui::ET_GESTURE_SCROLL_END:
218 case ui::ET_SCROLL_FLING_START: 331 case ui::ET_SCROLL_FLING_START:
219 widget_->ReleaseCapture(); 332 widget_->ReleaseCapture();
220 controller_->SetDraggingHandle(NULL); 333 controller_->SetDraggingHandle(nullptr);
221 break; 334 break;
222 default: 335 default:
223 break; 336 break;
224 } 337 }
225 } 338 }
226 339
227 gfx::Size GetPreferredSize() const override { 340 gfx::Size GetPreferredSize() const override {
228 gfx::Size image_size = GetHandleImageSize(); 341 gfx::Size image_size = image_->Size();
229 return gfx::Size(image_size.width() + 2 * kSelectionHandleHorizPadding, 342 return gfx::Size(image_size.width() + 2 * kSelectionHandleHorizPadding,
230 image_size.height() + selection_rect_.height() + 343 image_size.height() + selection_bound_.GetHeight() +
231 kSelectionHandleVertPadding); 344 kSelectionHandleVertPadding);
232 } 345 }
233 346
234 bool IsWidgetVisible() const { 347 bool IsWidgetVisible() const {
235 return widget_->IsVisible(); 348 return widget_->IsVisible();
236 } 349 }
237 350
238 void SetWidgetVisible(bool visible, bool quick) { 351 void SetWidgetVisible(bool visible, bool quick) {
239 if (widget_->IsVisible() == visible) 352 if (widget_->IsVisible() == visible)
240 return; 353 return;
241 widget_->SetVisibilityAnimationDuration( 354 widget_->SetVisibilityAnimationDuration(
242 base::TimeDelta::FromMilliseconds( 355 base::TimeDelta::FromMilliseconds(
243 quick ? kSelectionHandleQuickFadeDurationMs : 0)); 356 quick ? kSelectionHandleQuickFadeDurationMs : 0));
244 if (visible) 357 if (visible)
245 widget_->Show(); 358 widget_->Show();
246 else 359 else
247 widget_->Hide(); 360 widget_->Hide();
248 } 361 }
249 362
250 void SetSelectionRectInScreen(const gfx::Rect& rect) { 363 void SetBoundInScreen(const ui::SelectionBound& bound) {
251 gfx::Size image_size = GetHandleImageSize(); 364 bool update_bound_type = false;
252 selection_rect_ = rect; 365 // Cursor handle should always have the bound type CENTER
253 gfx::Rect widget_bounds( 366 DCHECK(!is_cursor_handle_ || bound.type == ui::SelectionBound::CENTER);
254 rect.x() - image_size.width() / 2 - kSelectionHandleHorizPadding,
255 rect.y(),
256 image_size.width() + 2 * kSelectionHandleHorizPadding,
257 rect.height() + image_size.height() + kSelectionHandleVertPadding);
258 widget_->SetBounds(widget_bounds);
259 }
260 367
261 gfx::Point GetScreenPosition() { 368 if (bound.type != selection_bound_.type) {
262 return widget_->GetClientAreaBoundsInScreen().origin(); 369 // Unless this is a cursor handle, do not set the type to CENTER -
370 // selection handles corresponding to a selection should always use left
371 // or right handle image. If selection handles are dragged to be located
372 // at the same spot, the |bound|'s type here will be CENTER for both of
373 // them. In this case do not update the type of the |selection_bound_|.
374 if (bound.type != ui::SelectionBound::CENTER || is_cursor_handle_)
375 update_bound_type = true;
376 }
377 if (update_bound_type) {
378 selection_bound_ = bound;
379 image_ = GetHandleImage(bound.type);
380 SchedulePaint();
381 } else {
382 selection_bound_.edge_top = bound.edge_top;
383 selection_bound_.edge_bottom = bound.edge_bottom;
384 }
385
386 widget_->SetBounds(GetSelectionWidgetBounds(selection_bound_));
387
388 aura::Window* window = widget_->GetNativeView();
389 wm::ConvertPointFromScreen(window, &selection_bound_.edge_top);
390 wm::ConvertPointFromScreen(window, &selection_bound_.edge_bottom);
263 } 391 }
264 392
265 void SetDrawInvisible(bool draw_invisible) { 393 void SetDrawInvisible(bool draw_invisible) {
266 if (draw_invisible_ == draw_invisible) 394 if (draw_invisible_ == draw_invisible)
267 return; 395 return;
268 draw_invisible_ = draw_invisible; 396 draw_invisible_ = draw_invisible;
269 SchedulePaint(); 397 SchedulePaint();
270 } 398 }
271 399
272 const gfx::Rect& selection_rect() const { return selection_rect_; }
273
274 private: 400 private:
275 scoped_ptr<Widget> widget_; 401 scoped_ptr<Widget> widget_;
276 TouchSelectionControllerImpl* controller_; 402 TouchSelectionControllerImpl* controller_;
277 gfx::Rect selection_rect_;
278 403
279 // Vertical offset between the scroll event position and the drag position 404 // In local coordinates
280 // reported to the client view (see the ASCII figure at the top of the file 405 ui::SelectionBound selection_bound_;
281 // and its description for more details). 406 gfx::Image* image_;
282 int drag_offset_; 407
408 // If true, this is a handle corresponding to the single cursor, otherwise it
409 // is a handle corresponding to one of the two selection bounds.
410 bool is_cursor_handle_;
411
412 // Offset applied to the scroll events location when calling
413 // TouchSelectionControllerImpl::SelectionHandleDragged while dragging the
414 // handle.
415 gfx::Vector2d drag_offset_;
283 416
284 // If set to true, the handle will not draw anything, hence providing an empty 417 // If set to true, the handle will not draw anything, hence providing an empty
285 // widget. We need this because we may want to stop showing the handle while 418 // widget. We need this because we may want to stop showing the handle while
286 // it is being dragged. Since it is being dragged, we cannot destroy the 419 // it is being dragged. Since it is being dragged, we cannot destroy the
287 // handle. 420 // handle.
288 bool draw_invisible_; 421 bool draw_invisible_;
289 422
290 DISALLOW_COPY_AND_ASSIGN(EditingHandleView); 423 DISALLOW_COPY_AND_ASSIGN(EditingHandleView);
291 }; 424 };
292 425
293 TouchHandleWindowTargeter::TouchHandleWindowTargeter( 426 TouchHandleWindowTargeter::TouchHandleWindowTargeter(
294 aura::Window* window, 427 aura::Window* window,
295 EditingHandleView* handle_view) 428 EditingHandleView* handle_view)
296 : wm::MaskedWindowTargeter(window), 429 : wm::MaskedWindowTargeter(window),
297 handle_view_(handle_view) { 430 handle_view_(handle_view) {
298 } 431 }
299 432
300 bool TouchHandleWindowTargeter::GetHitTestMask(aura::Window* window, 433 bool TouchHandleWindowTargeter::GetHitTestMask(aura::Window* window,
301 gfx::Path* mask) const { 434 gfx::Path* mask) const {
302 const gfx::Rect& selection_rect = handle_view_->selection_rect(); 435 handle_view_->GetWidgetHitTestMask(mask);
303 gfx::Size image_size = GetHandleImageSize();
304 mask->addRect(SkIntToScalar(0), SkIntToScalar(selection_rect.height()),
305 SkIntToScalar(image_size.width()) + 2 * kSelectionHandleHorizPadding,
306 SkIntToScalar(selection_rect.height() + image_size.height() +
307 kSelectionHandleVertPadding));
308 return true; 436 return true;
309 } 437 }
310 438
311 TouchSelectionControllerImpl::TouchSelectionControllerImpl( 439 TouchSelectionControllerImpl::TouchSelectionControllerImpl(
312 ui::TouchEditable* client_view) 440 ui::TouchEditable* client_view)
313 : client_view_(client_view), 441 : client_view_(client_view),
314 client_widget_(NULL), 442 client_widget_(nullptr),
315 selection_handle_1_(new EditingHandleView(this, 443 selection_handle_1_(new EditingHandleView(this,
316 client_view->GetNativeView())), 444 client_view->GetNativeView(),
445 false)),
317 selection_handle_2_(new EditingHandleView(this, 446 selection_handle_2_(new EditingHandleView(this,
318 client_view->GetNativeView())), 447 client_view->GetNativeView(),
448 false)),
319 cursor_handle_(new EditingHandleView(this, 449 cursor_handle_(new EditingHandleView(this,
320 client_view->GetNativeView())), 450 client_view->GetNativeView(),
321 context_menu_(NULL), 451 true)),
322 dragging_handle_(NULL) { 452 context_menu_(nullptr),
453 dragging_handle_(nullptr) {
323 aura::Window* client_window = client_view_->GetNativeView(); 454 aura::Window* client_window = client_view_->GetNativeView();
324 client_window->AddObserver(this); 455 client_window->AddObserver(this);
325 client_widget_ = Widget::GetTopLevelWidgetForNativeView(client_window); 456 client_widget_ = Widget::GetTopLevelWidgetForNativeView(client_window);
326 if (client_widget_) 457 if (client_widget_)
327 client_widget_->AddObserver(this); 458 client_widget_->AddObserver(this);
328 aura::Env::GetInstance()->AddPreTargetHandler(this); 459 aura::Env::GetInstance()->AddPreTargetHandler(this);
329 } 460 }
330 461
331 TouchSelectionControllerImpl::~TouchSelectionControllerImpl() { 462 TouchSelectionControllerImpl::~TouchSelectionControllerImpl() {
332 HideContextMenu(); 463 HideContextMenu();
333 aura::Env::GetInstance()->RemovePreTargetHandler(this); 464 aura::Env::GetInstance()->RemovePreTargetHandler(this);
334 if (client_widget_) 465 if (client_widget_)
335 client_widget_->RemoveObserver(this); 466 client_widget_->RemoveObserver(this);
336 client_view_->GetNativeView()->RemoveObserver(this); 467 client_view_->GetNativeView()->RemoveObserver(this);
337 } 468 }
338 469
339 void TouchSelectionControllerImpl::SelectionChanged() { 470 void TouchSelectionControllerImpl::SelectionChanged() {
340 gfx::Rect r1, r2; 471 ui::SelectionBound anchor, focus;
341 client_view_->GetSelectionEndPoints(&r1, &r2); 472 client_view_->GetSelectionEndPoints(&anchor, &focus);
342 gfx::Rect screen_rect_1 = ConvertToScreen(client_view_, r1); 473 ui::SelectionBound screen_bound_anchor =
343 gfx::Rect screen_rect_2 = ConvertToScreen(client_view_, r2); 474 ConvertToScreen(client_view_, anchor);
475 ui::SelectionBound screen_bound_focus = ConvertToScreen(client_view_, focus);
344 gfx::Rect client_bounds = client_view_->GetBounds(); 476 gfx::Rect client_bounds = client_view_->GetBounds();
345 if (r1.y() < client_bounds.y()) 477 if (anchor.edge_top.y() < client_bounds.y())
346 r1.Inset(0, client_bounds.y() - r1.y(), 0, 0); 478 anchor.edge_top.set_y(client_bounds.y());
347 if (r2.y() < client_bounds.y()) 479 if (focus.edge_top.y() < client_bounds.y())
348 r2.Inset(0, client_bounds.y() - r2.y(), 0, 0); 480 focus.edge_top.set_y(client_bounds.y());
349 gfx::Rect screen_rect_1_clipped = ConvertToScreen(client_view_, r1); 481 ui::SelectionBound screen_bound_anchor_clipped =
350 gfx::Rect screen_rect_2_clipped = ConvertToScreen(client_view_, r2); 482 ConvertToScreen(client_view_, anchor);
351 if (screen_rect_1_clipped == selection_end_point_1_clipped_ && 483 ui::SelectionBound screen_bound_focus_clipped =
352 screen_rect_2_clipped == selection_end_point_2_clipped_) 484 ConvertToScreen(client_view_, focus);
485 if (screen_bound_anchor_clipped == selection_bound_1_clipped_ &&
486 screen_bound_focus_clipped == selection_bound_2_clipped_)
353 return; 487 return;
354 488
355 selection_end_point_1_ = screen_rect_1; 489 selection_bound_1_ = screen_bound_anchor;
356 selection_end_point_2_ = screen_rect_2; 490 selection_bound_2_ = screen_bound_focus;
357 selection_end_point_1_clipped_ = screen_rect_1_clipped; 491 selection_bound_1_clipped_ = screen_bound_anchor_clipped;
358 selection_end_point_2_clipped_ = screen_rect_2_clipped; 492 selection_bound_2_clipped_ = screen_bound_focus_clipped;
359 493
360 if (client_view_->DrawsHandles()) { 494 if (client_view_->DrawsHandles()) {
361 UpdateContextMenu(); 495 UpdateContextMenu();
362 return; 496 return;
363 } 497 }
498
364 if (dragging_handle_) { 499 if (dragging_handle_) {
365 // We need to reposition only the selection handle that is being dragged. 500 // We need to reposition only the selection handle that is being dragged.
366 // The other handle stays the same. Also, the selection handle being dragged 501 // The other handle stays the same. Also, the selection handle being dragged
367 // will always be at the end of selection, while the other handle will be at 502 // will always be at the end of selection, while the other handle will be at
368 // the start. 503 // the start.
369 // If the new location of this handle is out of client view, its widget 504 // If the new location of this handle is out of client view, its widget
370 // should not get hidden, since it should still receive touch events. 505 // should not get hidden, since it should still receive touch events.
371 // Hence, we are not using |SetHandleSelectionRect()| method here. 506 // Hence, we are not using |SetHandleBound()| method here.
372 dragging_handle_->SetSelectionRectInScreen(screen_rect_2_clipped); 507 dragging_handle_->SetBoundInScreen(screen_bound_focus_clipped);
373 508
374 // Temporary fix for selection handle going outside a window. On a webpage, 509 // Temporary fix for selection handle going outside a window. On a webpage,
375 // the page should scroll if the selection handle is dragged outside the 510 // the page should scroll if the selection handle is dragged outside the
376 // window. That does not happen currently. So we just hide the handle for 511 // window. That does not happen currently. So we just hide the handle for
377 // now. 512 // now.
378 // TODO(varunjain): Fix this: crbug.com/269003 513 // TODO(varunjain): Fix this: crbug.com/269003
379 dragging_handle_->SetDrawInvisible(!ShouldShowHandleFor(r2)); 514 dragging_handle_->SetDrawInvisible(!ShouldShowHandleFor(focus));
380 515
381 if (dragging_handle_ != cursor_handle_.get()) { 516 if (dragging_handle_ != cursor_handle_.get()) {
382 // The non-dragging-handle might have recently become visible. 517 // The non-dragging-handle might have recently become visible.
383 EditingHandleView* non_dragging_handle = selection_handle_1_.get(); 518 EditingHandleView* non_dragging_handle = selection_handle_1_.get();
384 if (dragging_handle_ == selection_handle_1_) { 519 if (dragging_handle_ == selection_handle_1_) {
385 non_dragging_handle = selection_handle_2_.get(); 520 non_dragging_handle = selection_handle_2_.get();
386 // if handle 1 is being dragged, it is corresponding to the end of 521 // if handle 1 is being dragged, it is corresponding to the end of
387 // selection and the other handle to the start of selection. 522 // selection and the other handle to the start of selection.
388 selection_end_point_1_ = screen_rect_2; 523 selection_bound_1_ = screen_bound_focus;
389 selection_end_point_2_ = screen_rect_1; 524 selection_bound_2_ = screen_bound_anchor;
390 selection_end_point_1_clipped_ = screen_rect_2_clipped; 525 selection_bound_1_clipped_ = screen_bound_focus_clipped;
391 selection_end_point_2_clipped_ = screen_rect_1_clipped; 526 selection_bound_2_clipped_ = screen_bound_anchor_clipped;
392 } 527 }
393 SetHandleSelectionRect(non_dragging_handle, r1, screen_rect_1_clipped); 528 SetHandleBound(non_dragging_handle, anchor, screen_bound_anchor_clipped);
394 } 529 }
395 } else { 530 } else {
396 UpdateContextMenu(); 531 UpdateContextMenu();
397 532
398 // Check if there is any selection at all. 533 // Check if there is any selection at all.
399 if (screen_rect_1.origin() == screen_rect_2.origin()) { 534 if (screen_bound_anchor.edge_top == screen_bound_focus.edge_top &&
535 screen_bound_anchor.edge_bottom == screen_bound_focus.edge_bottom) {
400 selection_handle_1_->SetWidgetVisible(false, false); 536 selection_handle_1_->SetWidgetVisible(false, false);
401 selection_handle_2_->SetWidgetVisible(false, false); 537 selection_handle_2_->SetWidgetVisible(false, false);
402 SetHandleSelectionRect(cursor_handle_.get(), r1, screen_rect_1_clipped); 538 SetHandleBound(cursor_handle_.get(), anchor, screen_bound_anchor_clipped);
403 return; 539 return;
404 } 540 }
405 541
406 cursor_handle_->SetWidgetVisible(false, false); 542 cursor_handle_->SetWidgetVisible(false, false);
407 SetHandleSelectionRect(selection_handle_1_.get(), r1, 543 SetHandleBound(
408 screen_rect_1_clipped); 544 selection_handle_1_.get(), anchor, screen_bound_anchor_clipped);
409 SetHandleSelectionRect(selection_handle_2_.get(), r2, 545 SetHandleBound(
410 screen_rect_2_clipped); 546 selection_handle_2_.get(), focus, screen_bound_focus_clipped);
411 } 547 }
412 } 548 }
413 549
414 bool TouchSelectionControllerImpl::IsHandleDragInProgress() { 550 bool TouchSelectionControllerImpl::IsHandleDragInProgress() {
415 return !!dragging_handle_; 551 return !!dragging_handle_;
416 } 552 }
417 553
418 void TouchSelectionControllerImpl::HideHandles(bool quick) { 554 void TouchSelectionControllerImpl::HideHandles(bool quick) {
419 selection_handle_1_->SetWidgetVisible(false, quick); 555 selection_handle_1_->SetWidgetVisible(false, quick);
420 selection_handle_2_->SetWidgetVisible(false, quick); 556 selection_handle_2_->SetWidgetVisible(false, quick);
(...skipping 14 matching lines...) Expand all
435 DCHECK(dragging_handle_); 571 DCHECK(dragging_handle_);
436 gfx::Point drag_pos_in_client = drag_pos; 572 gfx::Point drag_pos_in_client = drag_pos;
437 ConvertPointToClientView(dragging_handle_, &drag_pos_in_client); 573 ConvertPointToClientView(dragging_handle_, &drag_pos_in_client);
438 574
439 if (dragging_handle_ == cursor_handle_.get()) { 575 if (dragging_handle_ == cursor_handle_.get()) {
440 client_view_->MoveCaretTo(drag_pos_in_client); 576 client_view_->MoveCaretTo(drag_pos_in_client);
441 return; 577 return;
442 } 578 }
443 579
444 // Find the stationary selection handle. 580 // Find the stationary selection handle.
445 gfx::Rect fixed_handle_rect = selection_end_point_1_; 581 ui::SelectionBound anchor_bound =
446 if (selection_handle_1_ == dragging_handle_) 582 selection_handle_1_ == dragging_handle_ ? selection_bound_2_
447 fixed_handle_rect = selection_end_point_2_; 583 : selection_bound_1_;
448 584
449 // Find selection end points in client_view's coordinate system. 585 // Find selection end points in client_view's coordinate system.
450 gfx::Point p2 = fixed_handle_rect.origin(); 586 gfx::Point p2 = anchor_bound.edge_top;
451 p2.Offset(0, fixed_handle_rect.height() / 2); 587 p2.Offset(0, anchor_bound.GetHeight() / 2);
452 client_view_->ConvertPointFromScreen(&p2); 588 client_view_->ConvertPointFromScreen(&p2);
453 589
454 // Instruct client_view to select the region between p1 and p2. The position 590 // Instruct client_view to select the region between p1 and p2. The position
455 // of |fixed_handle| is the start and that of |dragging_handle| is the end 591 // of |fixed_handle| is the start and that of |dragging_handle| is the end
456 // of selection. 592 // of selection.
457 client_view_->SelectRect(p2, drag_pos_in_client); 593 client_view_->SelectRect(p2, drag_pos_in_client);
458 } 594 }
459 595
460 void TouchSelectionControllerImpl::ConvertPointToClientView( 596 void TouchSelectionControllerImpl::ConvertPointToClientView(
461 EditingHandleView* source, gfx::Point* point) { 597 EditingHandleView* source, gfx::Point* point) {
462 View::ConvertPointToScreen(source, point); 598 View::ConvertPointToScreen(source, point);
463 client_view_->ConvertPointFromScreen(point); 599 client_view_->ConvertPointFromScreen(point);
464 } 600 }
465 601
466 void TouchSelectionControllerImpl::SetHandleSelectionRect( 602 void TouchSelectionControllerImpl::SetHandleBound(
467 EditingHandleView* handle, 603 EditingHandleView* handle,
468 const gfx::Rect& rect, 604 const ui::SelectionBound& bound,
469 const gfx::Rect& rect_in_screen) { 605 const ui::SelectionBound& bound_in_screen) {
470 handle->SetWidgetVisible(ShouldShowHandleFor(rect), false); 606 handle->SetWidgetVisible(ShouldShowHandleFor(bound), false);
471 if (handle->IsWidgetVisible()) 607 if (handle->IsWidgetVisible())
472 handle->SetSelectionRectInScreen(rect_in_screen); 608 handle->SetBoundInScreen(bound_in_screen);
473 } 609 }
474 610
475 bool TouchSelectionControllerImpl::ShouldShowHandleFor( 611 bool TouchSelectionControllerImpl::ShouldShowHandleFor(
476 const gfx::Rect& rect) const { 612 const ui::SelectionBound& bound) const {
477 if (rect.height() < kSelectionHandleBarMinHeight) 613 if (bound.GetHeight() < kSelectionHandleBarMinHeight)
478 return false; 614 return false;
479 gfx::Rect bounds = client_view_->GetBounds(); 615 gfx::Rect client_bounds = client_view_->GetBounds();
480 bounds.Inset(0, 0, 0, -kSelectionHandleBarBottomAllowance); 616 client_bounds.Inset(0, 0, 0, -kSelectionHandleBarBottomAllowance);
481 return bounds.Contains(rect); 617 return client_bounds.Contains(BoundToRect(bound));
482 } 618 }
483 619
484 bool TouchSelectionControllerImpl::IsCommandIdEnabled(int command_id) const { 620 bool TouchSelectionControllerImpl::IsCommandIdEnabled(int command_id) const {
485 return client_view_->IsCommandIdEnabled(command_id); 621 return client_view_->IsCommandIdEnabled(command_id);
486 } 622 }
487 623
488 void TouchSelectionControllerImpl::ExecuteCommand(int command_id, 624 void TouchSelectionControllerImpl::ExecuteCommand(int command_id,
489 int event_flags) { 625 int event_flags) {
490 HideContextMenu(); 626 HideContextMenu();
491 client_view_->ExecuteCommand(command_id, event_flags); 627 client_view_->ExecuteCommand(command_id, event_flags);
492 } 628 }
493 629
494 void TouchSelectionControllerImpl::OpenContextMenu() { 630 void TouchSelectionControllerImpl::OpenContextMenu() {
495 // Context menu should appear centered on top of the selected region. 631 // Context menu should appear centered on top of the selected region.
496 const gfx::Rect rect = context_menu_->GetAnchorRect(); 632 const gfx::Rect rect = context_menu_->GetAnchorRect();
497 const gfx::Point anchor(rect.CenterPoint().x(), rect.y()); 633 const gfx::Point anchor(rect.CenterPoint().x(), rect.y());
498 HideContextMenu(); 634 HideContextMenu();
499 client_view_->OpenContextMenu(anchor); 635 client_view_->OpenContextMenu(anchor);
500 } 636 }
501 637
502 void TouchSelectionControllerImpl::OnMenuClosed(TouchEditingMenuView* menu) { 638 void TouchSelectionControllerImpl::OnMenuClosed(TouchEditingMenuView* menu) {
503 if (menu == context_menu_) 639 if (menu == context_menu_)
504 context_menu_ = NULL; 640 context_menu_ = nullptr;
505 } 641 }
506 642
507 void TouchSelectionControllerImpl::OnAncestorWindowTransformed( 643 void TouchSelectionControllerImpl::OnAncestorWindowTransformed(
508 aura::Window* window, 644 aura::Window* window,
509 aura::Window* ancestor) { 645 aura::Window* ancestor) {
510 client_view_->DestroyTouchSelection(); 646 client_view_->DestroyTouchSelection();
511 } 647 }
512 648
513 void TouchSelectionControllerImpl::OnWidgetClosing(Widget* widget) { 649 void TouchSelectionControllerImpl::OnWidgetClosing(Widget* widget) {
514 DCHECK_EQ(client_widget_, widget); 650 DCHECK_EQ(client_widget_, widget);
515 client_widget_ = NULL; 651 client_widget_ = nullptr;
516 } 652 }
517 653
518 void TouchSelectionControllerImpl::OnWidgetBoundsChanged( 654 void TouchSelectionControllerImpl::OnWidgetBoundsChanged(
519 Widget* widget, 655 Widget* widget,
520 const gfx::Rect& new_bounds) { 656 const gfx::Rect& new_bounds) {
521 DCHECK_EQ(client_widget_, widget); 657 DCHECK_EQ(client_widget_, widget);
522 SelectionChanged(); 658 SelectionChanged();
523 } 659 }
524 660
525 void TouchSelectionControllerImpl::OnKeyEvent(ui::KeyEvent* event) { 661 void TouchSelectionControllerImpl::OnKeyEvent(ui::KeyEvent* event) {
526 client_view_->DestroyTouchSelection(); 662 client_view_->DestroyTouchSelection();
527 } 663 }
528 664
529 void TouchSelectionControllerImpl::OnMouseEvent(ui::MouseEvent* event) { 665 void TouchSelectionControllerImpl::OnMouseEvent(ui::MouseEvent* event) {
530 aura::client::CursorClient* cursor_client = aura::client::GetCursorClient( 666 aura::client::CursorClient* cursor_client = aura::client::GetCursorClient(
531 client_view_->GetNativeView()->GetRootWindow()); 667 client_view_->GetNativeView()->GetRootWindow());
532 if (!cursor_client || cursor_client->IsMouseEventsEnabled()) 668 if (!cursor_client || cursor_client->IsMouseEventsEnabled())
533 client_view_->DestroyTouchSelection(); 669 client_view_->DestroyTouchSelection();
534 } 670 }
535 671
536 void TouchSelectionControllerImpl::OnScrollEvent(ui::ScrollEvent* event) { 672 void TouchSelectionControllerImpl::OnScrollEvent(ui::ScrollEvent* event) {
537 client_view_->DestroyTouchSelection(); 673 client_view_->DestroyTouchSelection();
538 } 674 }
539 675
540 void TouchSelectionControllerImpl::ContextMenuTimerFired() { 676 void TouchSelectionControllerImpl::ContextMenuTimerFired() {
541 // Get selection end points in client_view's space. 677 // Get selection end points in client_view's space.
542 gfx::Rect end_rect_1_in_screen; 678 ui::SelectionBound b1_in_screen = selection_bound_1_clipped_;
543 gfx::Rect end_rect_2_in_screen; 679 ui::SelectionBound b2_in_screen =
544 if (cursor_handle_->IsWidgetVisible()) { 680 cursor_handle_->IsWidgetVisible() ? b1_in_screen
545 end_rect_1_in_screen = selection_end_point_1_clipped_; 681 : selection_bound_2_clipped_;
546 end_rect_2_in_screen = end_rect_1_in_screen;
547 } else {
548 end_rect_1_in_screen = selection_end_point_1_clipped_;
549 end_rect_2_in_screen = selection_end_point_2_clipped_;
550 }
551
552 // Convert from screen to client. 682 // Convert from screen to client.
553 gfx::Rect end_rect_1(ConvertFromScreen(client_view_, end_rect_1_in_screen)); 683 ui::SelectionBound b1 = ConvertFromScreen(client_view_, b1_in_screen);
554 gfx::Rect end_rect_2(ConvertFromScreen(client_view_, end_rect_2_in_screen)); 684 ui::SelectionBound b2 = ConvertFromScreen(client_view_, b2_in_screen);
555 685
556 // if selection is completely inside the view, we display the context menu 686 // if selection is completely inside the view, we display the context menu
557 // in the middle of the end points on the top. Else, we show it above the 687 // in the middle of the end points on the top. Else, we show it above the
558 // visible handle. If no handle is visible, we do not show the menu. 688 // visible handle. If no handle is visible, we do not show the menu.
559 gfx::Rect menu_anchor; 689 gfx::Rect menu_anchor;
560 if (ShouldShowHandleFor(end_rect_1) && 690 if (ShouldShowHandleFor(b1) && ShouldShowHandleFor(b2))
561 ShouldShowHandleFor(end_rect_2)) 691 menu_anchor = ui::RectBetweenSelectionBounds(b1_in_screen, b2_in_screen);
562 menu_anchor = Union(end_rect_1_in_screen,end_rect_2_in_screen); 692 else if (ShouldShowHandleFor(b1))
563 else if (ShouldShowHandleFor(end_rect_1)) 693 menu_anchor = BoundToRect(b1_in_screen);
564 menu_anchor = end_rect_1_in_screen; 694 else if (ShouldShowHandleFor(b2))
565 else if (ShouldShowHandleFor(end_rect_2)) 695 menu_anchor = BoundToRect(b2_in_screen);
566 menu_anchor = end_rect_2_in_screen;
567 else 696 else
568 return; 697 return;
569 698
570 DCHECK(!context_menu_); 699 DCHECK(!context_menu_);
571 context_menu_ = TouchEditingMenuView::Create(this, menu_anchor, 700 context_menu_ = TouchEditingMenuView::Create(this, menu_anchor,
572 GetHandleImageSize(), 701 GetMaxHandleImageSize(),
573 client_view_->GetNativeView()); 702 client_view_->GetNativeView());
574 } 703 }
575 704
576 void TouchSelectionControllerImpl::StartContextMenuTimer() { 705 void TouchSelectionControllerImpl::StartContextMenuTimer() {
577 if (context_menu_timer_.IsRunning()) 706 if (context_menu_timer_.IsRunning())
578 return; 707 return;
579 context_menu_timer_.Start( 708 context_menu_timer_.Start(
580 FROM_HERE, 709 FROM_HERE,
581 base::TimeDelta::FromMilliseconds(kContextMenuTimoutMs), 710 base::TimeDelta::FromMilliseconds(kContextMenuTimoutMs),
582 this, 711 this,
583 &TouchSelectionControllerImpl::ContextMenuTimerFired); 712 &TouchSelectionControllerImpl::ContextMenuTimerFired);
584 } 713 }
585 714
586 void TouchSelectionControllerImpl::UpdateContextMenu() { 715 void TouchSelectionControllerImpl::UpdateContextMenu() {
587 // Hide context menu to be shown when the timer fires. 716 // Hide context menu to be shown when the timer fires.
588 HideContextMenu(); 717 HideContextMenu();
589 StartContextMenuTimer(); 718 StartContextMenuTimer();
590 } 719 }
591 720
592 void TouchSelectionControllerImpl::HideContextMenu() { 721 void TouchSelectionControllerImpl::HideContextMenu() {
593 if (context_menu_) 722 if (context_menu_)
594 context_menu_->Close(); 723 context_menu_->Close();
595 context_menu_ = NULL; 724 context_menu_ = nullptr;
596 context_menu_timer_.Stop(); 725 context_menu_timer_.Stop();
597 } 726 }
598 727
599 gfx::NativeView TouchSelectionControllerImpl::GetCursorHandleNativeView() { 728 gfx::NativeView TouchSelectionControllerImpl::GetCursorHandleNativeView() {
600 return cursor_handle_->GetWidget()->GetNativeView(); 729 return cursor_handle_->GetWidget()->GetNativeView();
601 } 730 }
602 731
603 gfx::Point TouchSelectionControllerImpl::GetSelectionHandle1Position() { 732 gfx::Rect TouchSelectionControllerImpl::GetSelectionHandle1Bounds() {
604 return selection_handle_1_->GetScreenPosition(); 733 return selection_handle_1_->GetBoundsInScreen();
605 } 734 }
606 735
607 gfx::Point TouchSelectionControllerImpl::GetSelectionHandle2Position() { 736 gfx::Rect TouchSelectionControllerImpl::GetSelectionHandle2Bounds() {
608 return selection_handle_2_->GetScreenPosition(); 737 return selection_handle_2_->GetBoundsInScreen();
609 } 738 }
610 739
611 gfx::Point TouchSelectionControllerImpl::GetCursorHandlePosition() { 740 gfx::Rect TouchSelectionControllerImpl::GetCursorHandleBounds() {
612 return cursor_handle_->GetScreenPosition(); 741 return cursor_handle_->GetBoundsInScreen();
613 } 742 }
614 743
615 bool TouchSelectionControllerImpl::IsSelectionHandle1Visible() { 744 bool TouchSelectionControllerImpl::IsSelectionHandle1Visible() {
616 return selection_handle_1_->IsWidgetVisible(); 745 return selection_handle_1_->IsWidgetVisible();
617 } 746 }
618 747
619 bool TouchSelectionControllerImpl::IsSelectionHandle2Visible() { 748 bool TouchSelectionControllerImpl::IsSelectionHandle2Visible() {
620 return selection_handle_2_->IsWidgetVisible(); 749 return selection_handle_2_->IsWidgetVisible();
621 } 750 }
622 751
623 bool TouchSelectionControllerImpl::IsCursorHandleVisible() { 752 bool TouchSelectionControllerImpl::IsCursorHandleVisible() {
624 return cursor_handle_->IsWidgetVisible(); 753 return cursor_handle_->IsWidgetVisible();
625 } 754 }
626 755
756 gfx::Rect TouchSelectionControllerImpl::GetExpectedHandleBounds(
757 const ui::SelectionBound& bound) {
758 return GetSelectionWidgetBounds(bound);
759 }
760
761 views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle1View() {
762 return selection_handle_1_.get();
763 }
764
765 views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle2View() {
766 return selection_handle_2_.get();
767 }
768
627 } // namespace views 769 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698