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

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

Powered by Google App Engine
This is Rietveld 408576698