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