OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 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 "content/browser/renderer_host/touch_selection_controller_aura.h" |
| 6 |
| 7 #include "base/debug/stack_trace.h" |
| 8 #include "content/browser/renderer_host/touch_handle_drawable_aura.h" |
| 9 #include "ui/aura/client/cursor_client.h" |
| 10 #include "ui/aura/env.h" |
| 11 #include "ui/aura/window.h" |
| 12 #include "ui/events/event.h" |
| 13 #include "ui/events/gesture_detection/gesture_configuration.h" |
| 14 #include "ui/events/gestures/motion_event_aura.h" |
| 15 |
| 16 |
| 17 namespace content { |
| 18 |
| 19 namespace { |
| 20 |
| 21 gfx::RectF Union(const gfx::RectF& r1, const gfx::RectF& r2) { |
| 22 float x = std::min(r1.x(), r2.x()); |
| 23 float y = std::min(r1.y(), r2.y()); |
| 24 float right = std::max(r1.right(), r2.right()); |
| 25 float bottom = std::max(r1.bottom(), r2.bottom()); |
| 26 return gfx::RectF(x, y, right - x, bottom - y); |
| 27 } |
| 28 |
| 29 } |
| 30 |
| 31 TouchSelectionControllerAura::TouchSelectionControllerAura( |
| 32 TouchSelectionControllerAuraClient* client) |
| 33 : client_(client), |
| 34 motion_event_(new ui::MotionEventAura), |
| 35 quick_menu_(NULL), |
| 36 scroll_in_progress_(false), |
| 37 overscroll_in_progress_(false), |
| 38 handle_drag_in_progress_(false) { |
| 39 int tap_timeout_ms = |
| 40 ui::GestureConfiguration::GetInstance()->show_press_delay_in_ms(); |
| 41 int touch_slop_pixels = |
| 42 ui::GestureConfiguration::GetInstance() |
| 43 ->max_touch_move_in_pixels_for_click(); |
| 44 controller_.reset(new TouchSelectionController( |
| 45 this, |
| 46 base::TimeDelta::FromMilliseconds(tap_timeout_ms), |
| 47 touch_slop_pixels / client_->GetDeviceScaleFactor())); |
| 48 } |
| 49 |
| 50 TouchSelectionControllerAura::~TouchSelectionControllerAura() { |
| 51 } |
| 52 |
| 53 //void TouchSelectionControllerAura::SetTemporarilyHidden(bool hidden) { |
| 54 // controller_->SetTemporarilyHidden(hidden); |
| 55 // // hide menu |
| 56 //} |
| 57 |
| 58 void TouchSelectionControllerAura::OnSelectionEditable(bool editable) { |
| 59 controller_->OnSelectionEditable(editable); |
| 60 UpdateQuickMenu(); |
| 61 } |
| 62 |
| 63 void TouchSelectionControllerAura::OnSelectionEmpty(bool empty) { |
| 64 controller_->OnSelectionEmpty(empty); |
| 65 UpdateQuickMenu(); |
| 66 } |
| 67 |
| 68 |
| 69 void TouchSelectionControllerAura::OnSelectionBoundsChanged( |
| 70 const cc::ViewportSelectionBound& start, |
| 71 const cc::ViewportSelectionBound& end) { |
| 72 if (start_ == start && end_ == end) |
| 73 return; |
| 74 |
| 75 start_ = start; |
| 76 end_ = end; |
| 77 |
| 78 controller_->OnSelectionBoundsChanged(start, end); |
| 79 UpdateQuickMenu(); |
| 80 } |
| 81 |
| 82 void TouchSelectionControllerAura::HandleGestureEvent( |
| 83 ui::GestureEvent* event) { |
| 84 switch (event->type()) { |
| 85 case ui::ET_GESTURE_LONG_PRESS: |
| 86 controller_->OnLongPressEvent(); |
| 87 break; |
| 88 case ui::ET_GESTURE_TAP: |
| 89 if (!controller_->is_selection_active() && |
| 90 !controller_->is_selection_active() && |
| 91 GetBoundingRect().Contains(event->x(), event->y())) { |
| 92 controller_->ActivateSelection(start_, end_); |
| 93 event->SetHandled(); |
| 94 } else { |
| 95 controller_->OnTapEvent(); |
| 96 } |
| 97 break; |
| 98 case ui::ET_GESTURE_SCROLL_BEGIN: |
| 99 scroll_in_progress_ = true; |
| 100 UpdateQuickMenu(); |
| 101 break; |
| 102 case ui::ET_GESTURE_SCROLL_END: |
| 103 scroll_in_progress_ = false; |
| 104 UpdateQuickMenu(); |
| 105 break; |
| 106 default: |
| 107 break; |
| 108 } |
| 109 } |
| 110 |
| 111 void TouchSelectionControllerAura::HideAndDisallowShowingAutomatically() { |
| 112 controller_->HideAndDisallowShowingAutomatically(); |
| 113 UpdateQuickMenu(); |
| 114 } |
| 115 |
| 116 void TouchSelectionControllerAura::HandleTouchEvent(ui::TouchEvent* event) { |
| 117 const int index = motion_event_->FindPointerIndexOfId(event->touch_id()); |
| 118 const bool pointer_id_is_active = index != -1; |
| 119 |
| 120 if (event->type() != ui::ET_TOUCH_PRESSED && !pointer_id_is_active) |
| 121 return; |
| 122 |
| 123 if (event->type() == ui::ET_TOUCH_PRESSED && pointer_id_is_active) |
| 124 motion_event_.reset(new ui::MotionEventAura); |
| 125 |
| 126 motion_event_->OnTouch(*event); |
| 127 if (controller_->WillHandleTouchEvent(*motion_event_)) |
| 128 event->SetHandled(); |
| 129 motion_event_->CleanupRemovedTouchPoints(*event); |
| 130 } |
| 131 |
| 132 void TouchSelectionControllerAura::OnWindowMoved() { |
| 133 UpdateQuickMenu(); |
| 134 } |
| 135 |
| 136 void TouchSelectionControllerAura::OnOverscrollStarted() { |
| 137 overscroll_in_progress_ = true; |
| 138 UpdateQuickMenu(); |
| 139 } |
| 140 |
| 141 void TouchSelectionControllerAura::OnOverscrollCompleted() { |
| 142 overscroll_in_progress_ = false; |
| 143 UpdateQuickMenu(); |
| 144 } |
| 145 |
| 146 void TouchSelectionControllerAura::OnFlingCompleted() { |
| 147 scroll_in_progress_ = false; |
| 148 UpdateQuickMenu(); |
| 149 } |
| 150 |
| 151 gfx::RectF TouchSelectionControllerAura::GetCaretBounds() const { |
| 152 return GetBoundingRect(); |
| 153 } |
| 154 |
| 155 gfx::RectF TouchSelectionControllerAura::GetStartRect() const { |
| 156 return gfx::BoundingRect(start_.edge_top, start_.edge_bottom); |
| 157 } |
| 158 |
| 159 gfx::RectF TouchSelectionControllerAura::GetEndRect() const { |
| 160 return gfx::BoundingRect(end_.edge_top, end_.edge_bottom); |
| 161 } |
| 162 |
| 163 gfx::RectF TouchSelectionControllerAura::GetBoundingRect() const { |
| 164 return Union(GetStartRect(), GetEndRect()); |
| 165 } |
| 166 |
| 167 gfx::RectF TouchSelectionControllerAura::GetAnchorRect() const { |
| 168 // TODO: Crop to view bounds |
| 169 if (start_.visible && end_.visible) |
| 170 return GetBoundingRect(); |
| 171 if (start_.visible) |
| 172 return GetStartRect(); |
| 173 return GetEndRect(); |
| 174 } |
| 175 |
| 176 void TouchSelectionControllerAura::QuickMenuTimerFired() { |
| 177 DCHECK(controller_->is_insertion_active() || |
| 178 controller_->is_selection_active()); |
| 179 |
| 180 if (!start_.visible && !end_.visible) |
| 181 return; |
| 182 |
| 183 quick_menu_ = views::TouchEditingMenuView::Create( |
| 184 this, |
| 185 client_->ConvertRectToScreen(GetAnchorRect()), |
| 186 gfx::Size(20, 50), |
| 187 client_->GetParentWindow()->GetToplevelWindow()); |
| 188 } |
| 189 |
| 190 void TouchSelectionControllerAura::UpdateQuickMenu() { |
| 191 // Hide quick menu if there is any. |
| 192 if (quick_menu_) { |
| 193 quick_menu_->Close(); |
| 194 quick_menu_ = NULL; |
| 195 } else { |
| 196 quick_menu_timer_.Stop(); |
| 197 } |
| 198 |
| 199 // Start timer to show quick menu if necessary. |
| 200 if (!controller_->is_insertion_active() && |
| 201 !controller_->is_selection_active()) |
| 202 return; |
| 203 |
| 204 if (!IsQuickMenuAllowed()) |
| 205 return; |
| 206 |
| 207 quick_menu_timer_.Start( |
| 208 FROM_HERE, |
| 209 base::TimeDelta::FromMilliseconds(100), |
| 210 this, |
| 211 &TouchSelectionControllerAura::QuickMenuTimerFired); |
| 212 } |
| 213 |
| 214 bool TouchSelectionControllerAura::IsQuickMenuAllowed() const { |
| 215 return !scroll_in_progress_ && !overscroll_in_progress_ && |
| 216 !handle_drag_in_progress_; |
| 217 } |
| 218 |
| 219 bool TouchSelectionControllerAura::SupportsAnimation() const { |
| 220 return false; |
| 221 } |
| 222 |
| 223 void TouchSelectionControllerAura::SetNeedsAnimate() { |
| 224 NOTREACHED(); |
| 225 } |
| 226 |
| 227 void TouchSelectionControllerAura::MoveCaret(const gfx::PointF& position) { |
| 228 client_->MoveCaret(position); |
| 229 } |
| 230 |
| 231 void TouchSelectionControllerAura::SelectBetweenCoordinates( |
| 232 const gfx::PointF& start, |
| 233 const gfx::PointF& end) { |
| 234 client_->SelectBetweenCoordinates(start, end); |
| 235 } |
| 236 |
| 237 void TouchSelectionControllerAura::OnSelectionEvent( |
| 238 SelectionEventType event, |
| 239 const gfx::PointF& position) { |
| 240 //if (event != INSERTION_MOVED) |
| 241 // handle_drag_in_progress_ = false; |
| 242 switch (event) { |
| 243 case SELECTION_SHOWN: |
| 244 UpdateQuickMenu(); |
| 245 aura::Env::GetInstance()->AddPreTargetHandler(this); |
| 246 break; |
| 247 case SELECTION_CLEARED: |
| 248 aura::Env::GetInstance()->RemovePreTargetHandler(this); |
| 249 UpdateQuickMenu(); |
| 250 break; |
| 251 case SELECTION_DRAG_STARTED: |
| 252 handle_drag_in_progress_ = true; |
| 253 UpdateQuickMenu(); |
| 254 break; |
| 255 case SELECTION_DRAG_STOPPED: |
| 256 handle_drag_in_progress_ = false; |
| 257 UpdateQuickMenu(); |
| 258 break; |
| 259 case INSERTION_SHOWN: |
| 260 UpdateQuickMenu(); |
| 261 aura::Env::GetInstance()->AddPreTargetHandler(this); |
| 262 break; |
| 263 case INSERTION_MOVED: |
| 264 break; |
| 265 case INSERTION_TAPPED: |
| 266 //UpdateQuickMenu(); |
| 267 break; |
| 268 case INSERTION_CLEARED: |
| 269 aura::Env::GetInstance()->RemovePreTargetHandler(this); |
| 270 UpdateQuickMenu(); |
| 271 break; |
| 272 case INSERTION_DRAG_STARTED: |
| 273 //handle_drag_in_progress_ = true; |
| 274 //UpdateQuickMenu(); |
| 275 break; |
| 276 }; |
| 277 } |
| 278 |
| 279 scoped_ptr<TouchHandleDrawable> TouchSelectionControllerAura::CreateDrawable() { |
| 280 return scoped_ptr<TouchHandleDrawable>( |
| 281 new TouchHandleDrawableAura(client_->GetParentWindow())); |
| 282 } |
| 283 |
| 284 bool TouchSelectionControllerAura::IsCommandIdEnabled(int command_id) const { |
| 285 return client_->IsCommandIdEnabled(command_id); |
| 286 } |
| 287 |
| 288 void TouchSelectionControllerAura::ExecuteCommand(int command_id, |
| 289 int event_flags) { |
| 290 HideAndDisallowShowingAutomatically(); |
| 291 client_->ExecuteCommand(command_id, event_flags); |
| 292 } |
| 293 |
| 294 void TouchSelectionControllerAura::OpenContextMenu() { |
| 295 HideAndDisallowShowingAutomatically(); |
| 296 gfx::RectF anchor_rect = GetAnchorRect(); |
| 297 client_->OpenContextMenu( |
| 298 gfx::PointF(anchor_rect.CenterPoint().x(), anchor_rect.y())); |
| 299 } |
| 300 |
| 301 void TouchSelectionControllerAura::OnMenuClosed( |
| 302 views::TouchEditingMenuView* menu) { |
| 303 if (menu == quick_menu_) |
| 304 quick_menu_ = NULL; |
| 305 } |
| 306 |
| 307 void TouchSelectionControllerAura::OnKeyEvent(ui::KeyEvent* event) { |
| 308 LOG(ERROR) << "KeyEvent: " << event->name(); |
| 309 |
| 310 DCHECK(controller_->is_insertion_active() || |
| 311 controller_->is_selection_active()); |
| 312 |
| 313 HideAndDisallowShowingAutomatically(); |
| 314 } |
| 315 |
| 316 void TouchSelectionControllerAura::OnMouseEvent(ui::MouseEvent* event) { |
| 317 LOG(ERROR) << "MouseEvent: " << event->name(); |
| 318 |
| 319 DCHECK(controller_->is_insertion_active() || |
| 320 controller_->is_selection_active()); |
| 321 |
| 322 aura::client::CursorClient* cursor_client = aura::client::GetCursorClient( |
| 323 client_->GetParentWindow()->GetRootWindow()); |
| 324 if (!cursor_client || cursor_client->IsMouseEventsEnabled()) |
| 325 HideAndDisallowShowingAutomatically(); |
| 326 } |
| 327 |
| 328 void TouchSelectionControllerAura::OnScrollEvent(ui::ScrollEvent* event) { |
| 329 LOG(ERROR) << "ScrollEvent: " << event->name(); |
| 330 |
| 331 DCHECK(controller_->is_insertion_active() || |
| 332 controller_->is_selection_active()); |
| 333 |
| 334 HideAndDisallowShowingAutomatically(); |
| 335 } |
| 336 |
| 337 } |
OLD | NEW |