| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "ui/touch_selection/touch_selection_controller_aura.h" |
| 6 |
| 7 #include "ui/aura/client/cursor_client.h" |
| 8 #include "ui/aura/client/screen_position_client.h" |
| 9 #include "ui/aura/env.h" |
| 10 #include "ui/aura/window.h" |
| 11 #include "ui/events/event.h" |
| 12 #include "ui/events/gesture_detection/gesture_configuration.h" |
| 13 #include "ui/events/gestures/motion_event_aura.h" |
| 14 #include "ui/touch_selection/touch_handle_drawable_aura.h" |
| 15 |
| 16 namespace ui { |
| 17 namespace { |
| 18 |
| 19 gfx::Rect ConvertRectToScreen(aura::Window* window, const gfx::Rect& rect) { |
| 20 gfx::Point origin = rect.origin(); |
| 21 gfx::Point end = gfx::Point(rect.right(), rect.bottom()); |
| 22 |
| 23 aura::Window* root_window = window->GetRootWindow(); |
| 24 if (!root_window) |
| 25 return rect; |
| 26 aura::client::ScreenPositionClient* screen_position_client = |
| 27 aura::client::GetScreenPositionClient(root_window); |
| 28 if (!screen_position_client) |
| 29 return rect; |
| 30 screen_position_client->ConvertPointToScreen(window, &origin); |
| 31 screen_position_client->ConvertPointToScreen(window, &end); |
| 32 return gfx::Rect(origin.x(), origin.y(), end.x() - origin.x(), |
| 33 end.y() - origin.y()); |
| 34 } |
| 35 |
| 36 void ClipPoint(gfx::PointF* point, const gfx::Rect& clip_rect) { |
| 37 point->SetToMax(clip_rect.origin()); |
| 38 point->SetToMin(clip_rect.bottom_right()); |
| 39 } |
| 40 |
| 41 void ClipSelectionBound(SelectionBound* bound, const gfx::Rect& clip_rect) { |
| 42 gfx::PointF edge_top = bound->edge_top(); |
| 43 gfx::PointF edge_bottom = bound->edge_bottom(); |
| 44 ClipPoint(&edge_top, clip_rect); |
| 45 ClipPoint(&edge_bottom, clip_rect); |
| 46 bound->SetEdge(edge_top, edge_bottom); |
| 47 } |
| 48 |
| 49 } // namespace |
| 50 |
| 51 TouchSelectionControllerAura::TouchSelectionControllerAura( |
| 52 TouchSelectionControllerAuraClient* client) |
| 53 : client_(client), |
| 54 motion_event_(new MotionEventAura), |
| 55 scroll_in_progress_(false), |
| 56 overscroll_in_progress_(false), |
| 57 handle_drag_in_progress_(false), |
| 58 selection_editable_(false) { |
| 59 int tap_timeout_ms = |
| 60 GestureConfiguration::GetInstance()->show_press_delay_in_ms(); |
| 61 int touch_slop = |
| 62 GestureConfiguration::GetInstance()->max_touch_move_in_pixels_for_click(); |
| 63 bool show_on_tap_for_empty_editable = true; |
| 64 controller_.reset(new TouchSelectionController( |
| 65 this, |
| 66 base::TimeDelta::FromMilliseconds(tap_timeout_ms), |
| 67 touch_slop, |
| 68 show_on_tap_for_empty_editable)); |
| 69 } |
| 70 |
| 71 TouchSelectionControllerAura::~TouchSelectionControllerAura() { |
| 72 } |
| 73 |
| 74 void TouchSelectionControllerAura::OnSelectionEditable(bool editable) { |
| 75 selection_editable_ = editable; |
| 76 controller_->OnSelectionEditable(editable); |
| 77 UpdateQuickMenu(); |
| 78 } |
| 79 |
| 80 void TouchSelectionControllerAura::OnSelectionEmpty(bool empty) { |
| 81 controller_->OnSelectionEmpty(empty); |
| 82 UpdateQuickMenu(); |
| 83 } |
| 84 |
| 85 |
| 86 void TouchSelectionControllerAura::OnSelectionBoundsUpdated( |
| 87 const SelectionBound& start, |
| 88 const SelectionBound& end) { |
| 89 if (controller_->OnSelectionBoundsUpdated(start, end)) |
| 90 UpdateQuickMenu(); |
| 91 } |
| 92 |
| 93 void TouchSelectionControllerAura::HandleGestureEvent(GestureEvent* event) { |
| 94 switch (event->type()) { |
| 95 case ET_GESTURE_LONG_PRESS: |
| 96 controller_->OnLongPressEvent(); |
| 97 break; |
| 98 case ET_GESTURE_TAP: |
| 99 if (RectBetweenSelectionBounds( |
| 100 controller_->start(), |
| 101 controller_->end()).Contains(event->x(), event->y())) { |
| 102 if (!controller_->is_insertion_active() && |
| 103 !controller_->is_selection_active()) { |
| 104 controller_->AllowShowingFromCurrentSelection(); |
| 105 event->SetHandled(); |
| 106 } else if (!selection_editable_) { |
| 107 event->SetHandled(); |
| 108 } |
| 109 } |
| 110 if (!event->handled()) |
| 111 controller_->OnTapEvent(); |
| 112 break; |
| 113 case ET_GESTURE_SCROLL_BEGIN: |
| 114 scroll_in_progress_ = true; |
| 115 UpdateQuickMenu(); |
| 116 break; |
| 117 case ET_GESTURE_SCROLL_END: |
| 118 scroll_in_progress_ = false; |
| 119 UpdateQuickMenu(); |
| 120 break; |
| 121 default: |
| 122 break; |
| 123 } |
| 124 } |
| 125 |
| 126 void TouchSelectionControllerAura::HandleTouchEvent(TouchEvent* event) { |
| 127 const int index = motion_event_->FindPointerIndexOfId(event->touch_id()); |
| 128 const bool pointer_id_is_active = index != -1; |
| 129 |
| 130 if (event->type() != ET_TOUCH_PRESSED && !pointer_id_is_active) |
| 131 return; |
| 132 |
| 133 if (event->type() == ET_TOUCH_PRESSED && pointer_id_is_active) |
| 134 motion_event_.reset(new MotionEventAura); |
| 135 |
| 136 motion_event_->OnTouch(*event); |
| 137 if (controller_->WillHandleTouchEvent(*motion_event_)) |
| 138 event->SetHandled(); |
| 139 motion_event_->CleanupRemovedTouchPoints(*event); |
| 140 } |
| 141 |
| 142 void TouchSelectionControllerAura::HideAndDisallowShowingAutomatically() { |
| 143 controller_->HideAndDisallowShowingAutomatically(); |
| 144 UpdateQuickMenu(); |
| 145 } |
| 146 |
| 147 void TouchSelectionControllerAura::OnWindowMoved() { |
| 148 UpdateQuickMenu(); |
| 149 } |
| 150 |
| 151 void TouchSelectionControllerAura::OnOverscrollStarted() { |
| 152 overscroll_in_progress_ = true; |
| 153 UpdateQuickMenu(); |
| 154 } |
| 155 |
| 156 void TouchSelectionControllerAura::OnOverscrollCompleted() { |
| 157 overscroll_in_progress_ = false; |
| 158 UpdateQuickMenu(); |
| 159 } |
| 160 |
| 161 void TouchSelectionControllerAura::OnFlingCompleted() { |
| 162 scroll_in_progress_ = false; |
| 163 UpdateQuickMenu(); |
| 164 } |
| 165 |
| 166 bool TouchSelectionControllerAura::SupportsAnimation() const { |
| 167 return false; |
| 168 } |
| 169 |
| 170 void TouchSelectionControllerAura::SetNeedsAnimate() { |
| 171 NOTREACHED(); |
| 172 } |
| 173 |
| 174 void TouchSelectionControllerAura::MoveCaret(const gfx::PointF& position) { |
| 175 client_->MoveCaret(position); |
| 176 } |
| 177 |
| 178 void TouchSelectionControllerAura::MoveRangeSelectionExtent( |
| 179 const gfx::PointF& extent) { |
| 180 client_->MoveRangeSelectionExtent(extent); |
| 181 } |
| 182 |
| 183 void TouchSelectionControllerAura::SelectBetweenCoordinates( |
| 184 const gfx::PointF& base, |
| 185 const gfx::PointF& extent) { |
| 186 client_->SelectBetweenCoordinates(base, extent); |
| 187 } |
| 188 |
| 189 void TouchSelectionControllerAura::OnSelectionEvent( |
| 190 SelectionEventType event, |
| 191 const gfx::PointF& position) { |
| 192 switch (event) { |
| 193 case SELECTION_SHOWN: |
| 194 UpdateQuickMenu(); |
| 195 aura::Env::GetInstance()->RemovePreTargetHandler(this); |
| 196 aura::Env::GetInstance()->AddPreTargetHandler(this); |
| 197 break; |
| 198 case SELECTION_CLEARED: |
| 199 aura::Env::GetInstance()->RemovePreTargetHandler(this); |
| 200 UpdateQuickMenu(); |
| 201 break; |
| 202 case SELECTION_DRAG_STARTED: |
| 203 handle_drag_in_progress_ = true; |
| 204 UpdateQuickMenu(); |
| 205 break; |
| 206 case SELECTION_DRAG_STOPPED: |
| 207 handle_drag_in_progress_ = false; |
| 208 UpdateQuickMenu(); |
| 209 break; |
| 210 case INSERTION_SHOWN: |
| 211 UpdateQuickMenu(); |
| 212 aura::Env::GetInstance()->RemovePreTargetHandler(this); |
| 213 aura::Env::GetInstance()->AddPreTargetHandler(this); |
| 214 break; |
| 215 case INSERTION_MOVED: |
| 216 break; |
| 217 case INSERTION_TAPPED: |
| 218 //UpdateQuickMenu(); |
| 219 break; |
| 220 case INSERTION_CLEARED: |
| 221 aura::Env::GetInstance()->RemovePreTargetHandler(this); |
| 222 UpdateQuickMenu(); |
| 223 break; |
| 224 case INSERTION_DRAG_STARTED: |
| 225 handle_drag_in_progress_ = true; |
| 226 UpdateQuickMenu(); |
| 227 break; |
| 228 case INSERTION_DRAG_STOPPED: |
| 229 handle_drag_in_progress_ = false; |
| 230 UpdateQuickMenu(); |
| 231 break; |
| 232 }; |
| 233 } |
| 234 |
| 235 scoped_ptr<TouchHandleDrawable> TouchSelectionControllerAura::CreateDrawable() { |
| 236 return scoped_ptr<TouchHandleDrawable>( |
| 237 new TouchHandleDrawableAura(client_->GetParentWindow())); |
| 238 } |
| 239 |
| 240 gfx::Rect TouchSelectionControllerAura::GetMenuAnchorRect() const { |
| 241 SelectionBound start = controller_->start(); |
| 242 SelectionBound end = controller_->end(); |
| 243 const gfx::Rect& client_bounds = client_->GetClientBounds(); |
| 244 if (start.visible()) |
| 245 ClipSelectionBound(&start, client_bounds); |
| 246 if (end.visible()) |
| 247 ClipSelectionBound(&end, client_bounds); |
| 248 |
| 249 if (start.visible() && end.visible()) |
| 250 return RectBetweenSelectionBounds(start, end); |
| 251 if (end.visible()) |
| 252 return gfx::BoundingRect(end.edge_top_rounded(), end.edge_bottom_rounded()); |
| 253 return gfx::BoundingRect(start.edge_top_rounded(), |
| 254 start.edge_bottom_rounded()); |
| 255 } |
| 256 |
| 257 void TouchSelectionControllerAura::ShowQuickMenu() { |
| 258 DCHECK(controller_->is_insertion_active() || |
| 259 controller_->is_selection_active()); |
| 260 |
| 261 if (!controller_->start().visible() && !controller_->end().visible()) |
| 262 return; |
| 263 |
| 264 if (TouchSelectionMenuRunner::GetInstance()) { |
| 265 aura::Window* parent = client_->GetParentWindow(); |
| 266 TouchSelectionMenuRunner::GetInstance()->RunMenu( |
| 267 this, |
| 268 ConvertRectToScreen(parent, GetMenuAnchorRect()), |
| 269 TouchHandleDrawableAura::GetMaxHandleImageSize(), |
| 270 parent->GetToplevelWindow()); |
| 271 } |
| 272 } |
| 273 |
| 274 void TouchSelectionControllerAura::UpdateQuickMenu() { |
| 275 // Hide quick menu if there is any. |
| 276 if (TouchSelectionMenuRunner::GetInstance() && |
| 277 TouchSelectionMenuRunner::GetInstance()->IsRunning()) { |
| 278 TouchSelectionMenuRunner::GetInstance()->CloseMenu(); |
| 279 } else { |
| 280 quick_menu_timer_.Stop(); |
| 281 } |
| 282 |
| 283 // Start timer to show quick menu if necessary. |
| 284 if (!controller_->is_insertion_active() && |
| 285 !controller_->is_selection_active()) |
| 286 return; |
| 287 |
| 288 if (!IsQuickMenuAllowed()) |
| 289 return; |
| 290 |
| 291 if (immediate_quick_menu_for_testing_) { |
| 292 ShowQuickMenu(); |
| 293 } else { |
| 294 quick_menu_timer_.Start( |
| 295 FROM_HERE, |
| 296 base::TimeDelta::FromMilliseconds(100), |
| 297 this, |
| 298 &TouchSelectionControllerAura::ShowQuickMenu); |
| 299 } |
| 300 } |
| 301 |
| 302 bool TouchSelectionControllerAura::IsQuickMenuAllowed() const { |
| 303 return !scroll_in_progress_ && !overscroll_in_progress_ && |
| 304 !handle_drag_in_progress_; |
| 305 } |
| 306 |
| 307 bool TouchSelectionControllerAura::IsCommandIdEnabled(int command_id) const { |
| 308 return client_->IsCommandIdEnabled(command_id); |
| 309 } |
| 310 |
| 311 void TouchSelectionControllerAura::ExecuteCommand(int command_id, |
| 312 int event_flags) { |
| 313 HideAndDisallowShowingAutomatically(); |
| 314 client_->ExecuteCommand(command_id, event_flags); |
| 315 } |
| 316 |
| 317 void TouchSelectionControllerAura::OpenContextMenu() { |
| 318 HideAndDisallowShowingAutomatically(); |
| 319 gfx::Rect anchor_rect = GetMenuAnchorRect(); |
| 320 client_->OpenContextMenu(gfx::Point(anchor_rect.CenterPoint().x(), |
| 321 anchor_rect.y())); |
| 322 } |
| 323 |
| 324 void TouchSelectionControllerAura::OnKeyEvent(KeyEvent* event) { |
| 325 DCHECK(controller_->is_insertion_active() || |
| 326 controller_->is_selection_active()); |
| 327 |
| 328 HideAndDisallowShowingAutomatically(); |
| 329 } |
| 330 |
| 331 void TouchSelectionControllerAura::OnMouseEvent(MouseEvent* event) { |
| 332 DCHECK(controller_->is_insertion_active() || |
| 333 controller_->is_selection_active()); |
| 334 |
| 335 aura::client::CursorClient* cursor_client = aura::client::GetCursorClient( |
| 336 client_->GetParentWindow()->GetRootWindow()); |
| 337 if (!cursor_client || cursor_client->IsMouseEventsEnabled()) |
| 338 HideAndDisallowShowingAutomatically(); |
| 339 } |
| 340 |
| 341 void TouchSelectionControllerAura::OnScrollEvent(ScrollEvent* event) { |
| 342 DCHECK(controller_->is_insertion_active() || |
| 343 controller_->is_selection_active()); |
| 344 |
| 345 HideAndDisallowShowingAutomatically(); |
| 346 } |
| 347 |
| 348 } // namespace ui |
| OLD | NEW |