Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 |
| OLD | NEW |