1 // Copyright (c) 2012 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/views/widget/root_view.h" 6 7 #include <algorithm> 8 9 #include "base/logging.h" 10 #include "base/message_loop/message_loop.h" 11 #include "ui/accessibility/ax_view_state.h" 12 #include "ui/base/cursor/cursor.h" 13 #include "ui/base/dragdrop/drag_drop_types.h" 14 #include "ui/base/ui_base_switches_util.h" 15 #include "ui/compositor/layer.h" 16 #include "ui/events/event.h" 17 #include "ui/events/keycodes/keyboard_codes.h" 18 #include "ui/gfx/canvas.h" 19 #include "ui/views/drag_controller.h" 20 #include "ui/views/focus/view_storage.h" 21 #include "ui/views/layout/fill_layout.h" 22 #include "ui/views/view_targeter.h" 23 #include "ui/views/views_switches.h" 24 #include "ui/views/widget/widget.h" 25 #include "ui/views/widget/widget_delegate.h" 26 27 typedef ui::EventDispatchDetails DispatchDetails; 28 29 namespace views { 30 namespace internal { 31 32 namespace { 33 34 enum EventType { 35 EVENT_ENTER, 36 EVENT_EXIT 37 }; 38 39 class MouseEnterExitEvent : public ui::MouseEvent { 40 public: 41 MouseEnterExitEvent(const ui::MouseEvent& event, ui::EventType type) 42 : ui::MouseEvent(event, 43 static_cast<View*>(NULL), 44 static_cast<View*>(NULL)) { 45 DCHECK(type == ui::ET_MOUSE_ENTERED || 46 type == ui::ET_MOUSE_EXITED); 47 SetType(type); 48 } 49 50 virtual ~MouseEnterExitEvent() {} 51 }; 52 53 } // namespace 54 55 // This event handler receives events in the pre-target phase and takes care of 56 // the following: 57 // - Shows keyboard-triggered context menus. 58 class PreEventDispatchHandler : public ui::EventHandler { 59 public: 60 explicit PreEventDispatchHandler(View* owner) 61 : owner_(owner) { 62 } 63 virtual ~PreEventDispatchHandler() {} 64 65 private: 66 // ui::EventHandler: 67 virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE { 68 CHECK_EQ(ui::EP_PRETARGET, event->phase()); 69 if (event->handled()) 70 return; 71 72 View* v = NULL; 73 if (owner_->GetFocusManager()) // Can be NULL in unittests. 74 v = owner_->GetFocusManager()->GetFocusedView(); 75 76 // Special case to handle keyboard-triggered context menus. 77 if (v && v->enabled() && ((event->key_code() == ui::VKEY_APPS) || 78 (event->key_code() == ui::VKEY_F10 && event->IsShiftDown()))) { 79 // Clamp the menu location within the visible bounds of each ancestor view 80 // to avoid showing the menu over a completely different view or window. 81 gfx::Point location = v->GetKeyboardContextMenuLocation(); 82 for (View* parent = v->parent(); parent; parent = parent->parent()) { 83 const gfx::Rect& parent_bounds = parent->GetBoundsInScreen(); 84 location.SetToMax(parent_bounds.origin()); 85 location.SetToMin(parent_bounds.bottom_right()); 86 } 87 v->ShowContextMenu(location, ui::MENU_SOURCE_KEYBOARD); 88 event->StopPropagation(); 89 } 90 } 91 92 View* owner_; 93 94 DISALLOW_COPY_AND_ASSIGN(PreEventDispatchHandler); 95 }; 96 97 // This event handler receives events in the post-target phase and takes care of 98 // the following: 99 // - Generates context menu, or initiates drag-and-drop, from gesture events. 100 class PostEventDispatchHandler : public ui::EventHandler { 101 public: 102 PostEventDispatchHandler() 103 : touch_dnd_enabled_(::switches::IsTouchDragDropEnabled()) { 104 } 105 virtual ~PostEventDispatchHandler() {} 106 107 private: 108 // Overridden from ui::EventHandler: 109 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { 110 DCHECK_EQ(ui::EP_POSTTARGET, event->phase()); 111 if (event->handled()) 112 return; 113 114 View* target = static_cast<View*>(event->target()); 115 gfx::Point location = event->location(); 116 if (touch_dnd_enabled_ && 117 event->type() == ui::ET_GESTURE_LONG_PRESS && 118 (!target->drag_controller() || 119 target->drag_controller()->CanStartDragForView( 120 target, location, location))) { 121 if (target->DoDrag(*event, location, 122 ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH)) { 123 event->StopPropagation(); 124 return; 125 } 126 } 127 128 if (target->context_menu_controller() && 129 (event->type() == ui::ET_GESTURE_LONG_PRESS || 130 event->type() == ui::ET_GESTURE_LONG_TAP || 131 event->type() == ui::ET_GESTURE_TWO_FINGER_TAP)) { 132 gfx::Point screen_location(location); 133 View::ConvertPointToScreen(target, &screen_location); 134 target->ShowContextMenu(screen_location, ui::MENU_SOURCE_TOUCH); 135 event->StopPropagation(); 136 } 137 } 138 139 bool touch_dnd_enabled_; 140 141 DISALLOW_COPY_AND_ASSIGN(PostEventDispatchHandler); 142 }; 143 144 // static 145 const char RootView::kViewClassName[] = "RootView"; 146 147 //////////////////////////////////////////////////////////////////////////////// 148 // RootView, public: 149 150 // Creation and lifetime ------------------------------------------------------- 151 152 RootView::RootView(Widget* widget) 153 : widget_(widget), 154 mouse_pressed_handler_(NULL), 155 mouse_move_handler_(NULL), 156 last_click_handler_(NULL), 157 explicit_mouse_handler_(false), 158 last_mouse_event_flags_(0), 159 last_mouse_event_x_(-1), 160 last_mouse_event_y_(-1), 161 gesture_handler_(NULL), 162 scroll_gesture_handler_(NULL), 163 pre_dispatch_handler_(new internal::PreEventDispatchHandler(this)), 164 post_dispatch_handler_(new internal::PostEventDispatchHandler), 165 focus_search_(this, false, false), 166 focus_traversable_parent_(NULL), 167 focus_traversable_parent_view_(NULL), 168 event_dispatch_target_(NULL), 169 old_dispatch_target_(NULL) { 170 AddPreTargetHandler(pre_dispatch_handler_.get()); 171 AddPostTargetHandler(post_dispatch_handler_.get()); 172 SetEventTargeter(scoped_ptr<ui::EventTargeter>(new ViewTargeter())); 173 } 174 175 RootView::~RootView() { 176 // If we have children remove them explicitly so to make sure a remove 177 // notification is sent for each one of them. 178 if (has_children()) 179 RemoveAllChildViews(true); 180 } 181 182 // Tree operations ------------------------------------------------------------- 183 184 void RootView::SetContentsView(View* contents_view) { 185 DCHECK(contents_view && GetWidget()->native_widget()) << 186 "Can't be called until after the native widget is created!"; 187 // The ContentsView must be set up _after_ the window is created so that its 188 // Widget pointer is valid. 189 SetLayoutManager(new FillLayout); 190 if (has_children()) 191 RemoveAllChildViews(true); 192 AddChildView(contents_view); 193 194 // Force a layout now, since the attached hierarchy won't be ready for the 195 // containing window's bounds. Note that we call Layout directly rather than 196 // calling the widget's size changed handler, since the RootView's bounds may 197 // not have changed, which will cause the Layout not to be done otherwise. 198 Layout(); 199 } 200 201 View* RootView::GetContentsView() { 202 return child_count() > 0 ? child_at(0) : NULL; 203 } 204 205 void RootView::NotifyNativeViewHierarchyChanged() { 206 PropagateNativeViewHierarchyChanged(); 207 } 208 209 // Focus ----------------------------------------------------------------------- 210 211 void RootView::SetFocusTraversableParent(FocusTraversable* focus_traversable) { 212 DCHECK(focus_traversable != this); 213 focus_traversable_parent_ = focus_traversable; 214 } 215 216 void RootView::SetFocusTraversableParentView(View* view) { 217 focus_traversable_parent_view_ = view; 218 } 219 220 // System events --------------------------------------------------------------- 221 222 void RootView::ThemeChanged() { 223 View::PropagateThemeChanged(); 224 } 225 226 void RootView::LocaleChanged() { 227 View::PropagateLocaleChanged(); 228 } 229 230 //////////////////////////////////////////////////////////////////////////////// 231 // RootView, FocusTraversable implementation: 232 233 FocusSearch* RootView::GetFocusSearch() { 234 return &focus_search_; 235 } 236 237 FocusTraversable* RootView::GetFocusTraversableParent() { 238 return focus_traversable_parent_; 239 } 240 241 View* RootView::GetFocusTraversableParentView() { 242 return focus_traversable_parent_view_; 243 } 244 245 //////////////////////////////////////////////////////////////////////////////// 246 // RootView, ui::EventProcessor overrides: 247 248 ui::EventTarget* RootView::GetRootTarget() { 249 return this; 250 } 251 252 ui::EventDispatchDetails RootView::OnEventFromSource(ui::Event* event) { 253 // TODO(tdanderson): Replace the calls to Dispatch*Event() with calls to 254 // EventProcessor::OnEventFromSource() once the code for 255 // that event type has been refactored, and then 256 // eventually remove this function altogether. See 257 // crbug.com/348083. 258 if (event->IsKeyEvent()) 259 return EventProcessor::OnEventFromSource(event); 260 else if (event->IsScrollEvent()) 261 return EventProcessor::OnEventFromSource(event); 262 else if (event->IsTouchEvent()) 263 NOTREACHED() << "Touch events should not be sent to RootView."; 264 else if (event->IsGestureEvent()) 265 DispatchGestureEvent(static_cast<ui::GestureEvent*>(event)); 266 else if (event->IsMouseEvent()) 267 NOTREACHED() << "Should not be called with a MouseEvent."; 268 else 269 NOTREACHED() << "Invalid event type."; 270 271 return DispatchDetails(); 272 } 273 274 //////////////////////////////////////////////////////////////////////////////// 275 // RootView, View overrides: 276 277 const Widget* RootView::GetWidget() const { 278 return widget_; 279 } 280 281 Widget* RootView::GetWidget() { 282 return const_cast<Widget*>(const_cast<const RootView*>(this)->GetWidget()); 283 } 284 285 bool RootView::IsDrawn() const { 286 return visible(); 287 } 288 289 void RootView::Layout() { 290 View::Layout(); 291 widget_->OnRootViewLayout(); 292 } 293 294 const char* RootView::GetClassName() const { 295 return kViewClassName; 296 } 297 298 void RootView::SchedulePaintInRect(const gfx::Rect& rect) { 299 if (layer()) { 300 layer()->SchedulePaint(rect); 301 } else { 302 gfx::Rect xrect = ConvertRectToParent(rect); 303 gfx::Rect invalid_rect = gfx::IntersectRects(GetLocalBounds(), xrect); 304 if (!invalid_rect.IsEmpty()) 305 widget_->SchedulePaintInRect(invalid_rect); 306 } 307 } 308 309 bool RootView::OnMousePressed(const ui::MouseEvent& event) { 310 UpdateCursor(event); 311 SetMouseLocationAndFlags(event); 312 313 // If mouse_pressed_handler_ is non null, we are currently processing 314 // a pressed -> drag -> released session. In that case we send the 315 // event to mouse_pressed_handler_ 316 if (mouse_pressed_handler_) { 317 ui::MouseEvent mouse_pressed_event(event, static_cast<View*>(this), 318 mouse_pressed_handler_); 319 drag_info_.Reset(); 320 ui::EventDispatchDetails dispatch_details = 321 DispatchEvent(mouse_pressed_handler_, &mouse_pressed_event); 322 if (dispatch_details.dispatcher_destroyed) 323 return true; 324 return true; 325 } 326 DCHECK(!explicit_mouse_handler_); 327 328 bool hit_disabled_view = false; 329 // Walk up the tree until we find a view that wants the mouse event. 330 for (mouse_pressed_handler_ = GetEventHandlerForPoint(event.location()); 331 mouse_pressed_handler_ && (mouse_pressed_handler_ != this); 332 mouse_pressed_handler_ = mouse_pressed_handler_->parent()) { 333 DVLOG(1) << "OnMousePressed testing " 334 << mouse_pressed_handler_->GetClassName(); 335 if (!mouse_pressed_handler_->enabled()) { 336 // Disabled views should eat events instead of propagating them upwards. 337 hit_disabled_view = true; 338 break; 339 } 340 341 // See if this view wants to handle the mouse press. 342 ui::MouseEvent mouse_pressed_event(event, static_cast<View*>(this), 343 mouse_pressed_handler_); 344 345 // Remove the double-click flag if the handler is different than the 346 // one which got the first click part of the double-click. 347 if (mouse_pressed_handler_ != last_click_handler_) 348 mouse_pressed_event.set_flags(event.flags() & ~ui::EF_IS_DOUBLE_CLICK); 349 350 drag_info_.Reset(); 351 ui::EventDispatchDetails dispatch_details = 352 DispatchEvent(mouse_pressed_handler_, &mouse_pressed_event); 353 if (dispatch_details.dispatcher_destroyed) 354 return mouse_pressed_event.handled(); 355 356 // The view could have removed itself from the tree when handling 357 // OnMousePressed(). In this case, the removal notification will have 358 // reset mouse_pressed_handler_ to NULL out from under us. Detect this 359 // case and stop. (See comments in view.h.) 360 // 361 // NOTE: Don't return true here, because we don't want the frame to 362 // forward future events to us when there's no handler. 363 if (!mouse_pressed_handler_) 364 break; 365 366 // If the view handled the event, leave mouse_pressed_handler_ set and 367 // return true, which will cause subsequent drag/release events to get 368 // forwarded to that view. 369 if (mouse_pressed_event.handled()) { 370 last_click_handler_ = mouse_pressed_handler_; 371 DVLOG(1) << "OnMousePressed handled by " 372 << mouse_pressed_handler_->GetClassName(); 373 return true; 374 } 375 } 376 377 // Reset mouse_pressed_handler_ to indicate that no processing is occurring. 378 mouse_pressed_handler_ = NULL; 379 380 // In the event that a double-click is not handled after traversing the 381 // entire hierarchy (even as a single-click when sent to a different view), 382 // it must be marked as handled to avoid anything happening from default 383 // processing if it the first click-part was handled by us. 384 if (last_click_handler_ && (event.flags() & ui::EF_IS_DOUBLE_CLICK)) 385 hit_disabled_view = true; 386 387 last_click_handler_ = NULL; 388 return hit_disabled_view; 389 } 390 391 bool RootView::OnMouseDragged(const ui::MouseEvent& event) { 392 if (mouse_pressed_handler_) { 393 SetMouseLocationAndFlags(event); 394 395 ui::MouseEvent mouse_event(event, static_cast<View*>(this), 396 mouse_pressed_handler_); 397 ui::EventDispatchDetails dispatch_details = 398 DispatchEvent(mouse_pressed_handler_, &mouse_event); 399 if (dispatch_details.dispatcher_destroyed) 400 return false; 401 } 402 return false; 403 } 404 405 void RootView::OnMouseReleased(const ui::MouseEvent& event) { 406 UpdateCursor(event); 407 408 if (mouse_pressed_handler_) { 409 ui::MouseEvent mouse_released(event, static_cast<View*>(this), 410 mouse_pressed_handler_); 411 // We allow the view to delete us from the event dispatch callback. As such, 412 // configure state such that we're done first, then call View. 413 View* mouse_pressed_handler = mouse_pressed_handler_; 414 SetMouseHandler(NULL); 415 ui::EventDispatchDetails dispatch_details = 416 DispatchEvent(mouse_pressed_handler, &mouse_released); 417 if (dispatch_details.dispatcher_destroyed) 418 return; 419 } 420 } 421 422 void RootView::OnMouseCaptureLost() { 423 // TODO: this likely needs to reset touch handler too. 424 425 if (mouse_pressed_handler_ || gesture_handler_) { 426 // Synthesize a release event for UpdateCursor. 427 if (mouse_pressed_handler_) { 428 gfx::Point last_point(last_mouse_event_x_, last_mouse_event_y_); 429 ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, 430 last_point, last_point, 431 last_mouse_event_flags_, 432 0); 433 UpdateCursor(release_event); 434 } 435 // We allow the view to delete us from OnMouseCaptureLost. As such, 436 // configure state such that we're done first, then call View. 437 View* mouse_pressed_handler = mouse_pressed_handler_; 438 View* gesture_handler = gesture_handler_; 439 SetMouseHandler(NULL); 440 if (mouse_pressed_handler) 441 mouse_pressed_handler->OnMouseCaptureLost(); 442 else 443 gesture_handler->OnMouseCaptureLost(); 444 // WARNING: we may have been deleted. 445 } 446 } 447 448 void RootView::OnMouseMoved(const ui::MouseEvent& event) { 449 View* v = GetEventHandlerForPoint(event.location()); 450 // Find the first enabled view, or the existing move handler, whichever comes 451 // first. The check for the existing handler is because if a view becomes 452 // disabled while handling moves, it's wrong to suddenly send ET_MOUSE_EXITED 453 // and ET_MOUSE_ENTERED events, because the mouse hasn't actually exited yet. 454 while (v && !v->enabled() && (v != mouse_move_handler_)) 455 v = v->parent(); 456 if (v && v != this) { 457 if (v != mouse_move_handler_) { 458 if (mouse_move_handler_ != NULL && 459 (!mouse_move_handler_->notify_enter_exit_on_child() || 460 !mouse_move_handler_->Contains(v))) { 461 MouseEnterExitEvent exit(event, ui::ET_MOUSE_EXITED); 462 exit.ConvertLocationToTarget(static_cast<View*>(this), 463 mouse_move_handler_); 464 ui::EventDispatchDetails dispatch_details = 465 DispatchEvent(mouse_move_handler_, &exit); 466 if (dispatch_details.dispatcher_destroyed) 467 return; 468 NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED, 469 mouse_move_handler_, v); 470 } 471 View* old_handler = mouse_move_handler_; 472 mouse_move_handler_ = v; 473 if (!mouse_move_handler_->notify_enter_exit_on_child() || 474 !mouse_move_handler_->Contains(old_handler)) { 475 MouseEnterExitEvent entered(event, ui::ET_MOUSE_ENTERED); 476 entered.ConvertLocationToTarget(static_cast<View*>(this), 477 mouse_move_handler_); 478 ui::EventDispatchDetails dispatch_details = 479 DispatchEvent(mouse_move_handler_, &entered); 480 if (dispatch_details.dispatcher_destroyed) 481 return; 482 NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_ENTERED, 483 mouse_move_handler_, old_handler); 484 } 485 } 486 ui::MouseEvent moved_event(event, static_cast<View*>(this), 487 mouse_move_handler_); 488 mouse_move_handler_->OnMouseMoved(moved_event); 489 // TODO(tdanderson): It may be possible to avoid setting the cursor twice 490 // (once here and once from CompoundEventFilter) on a 491 // mousemove. See crbug.com/351469. 492 if (!(moved_event.flags() & ui::EF_IS_NON_CLIENT)) 493 widget_->SetCursor(mouse_move_handler_->GetCursor(moved_event)); 494 } else if (mouse_move_handler_ != NULL) { 495 MouseEnterExitEvent exited(event, ui::ET_MOUSE_EXITED); 496 ui::EventDispatchDetails dispatch_details = 497 DispatchEvent(mouse_move_handler_, &exited); 498 if (dispatch_details.dispatcher_destroyed) 499 return; 500 NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED, 501 mouse_move_handler_, v); 502 // On Aura the non-client area extends slightly outside the root view for 503 // some windows. Let the non-client cursor handling code set the cursor 504 // as we do above. 505 if (!(event.flags() & ui::EF_IS_NON_CLIENT)) 506 widget_->SetCursor(gfx::kNullCursor); 507 mouse_move_handler_ = NULL; 508 } 509 } 510 511 void RootView::OnMouseExited(const ui::MouseEvent& event) { 512 if (mouse_move_handler_ != NULL) { 513 MouseEnterExitEvent exited(event, ui::ET_MOUSE_EXITED); 514 ui::EventDispatchDetails dispatch_details = 515 DispatchEvent(mouse_move_handler_, &exited); 516 if (dispatch_details.dispatcher_destroyed) 517 return; 518 NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED, 519 mouse_move_handler_, NULL); 520 mouse_move_handler_ = NULL; 521 } 522 } 523 524 bool RootView::OnMouseWheel(const ui::MouseWheelEvent& event) { 525 for (View* v = GetEventHandlerForPoint(event.location()); 526 v && v != this && !event.handled(); v = v->parent()) { 527 ui::EventDispatchDetails dispatch_details = 528 DispatchEvent(v, const_cast<ui::MouseWheelEvent*>(&event)); 529 if (dispatch_details.dispatcher_destroyed || 530 dispatch_details.target_destroyed) { 531 return event.handled(); 532 } 533 } 534 return event.handled(); 535 } 536 537 void RootView::SetMouseHandler(View* new_mh) { 538 // If we're clearing the mouse handler, clear explicit_mouse_handler_ as well. 539 explicit_mouse_handler_ = (new_mh != NULL); 540 mouse_pressed_handler_ = new_mh; 541 gesture_handler_ = new_mh; 542 scroll_gesture_handler_ = new_mh; 543 drag_info_.Reset(); 544 } 545 546 void RootView::GetAccessibleState(ui::AXViewState* state) { 547 state->name = widget_->widget_delegate()->GetAccessibleWindowTitle(); 548 state->role = widget_->widget_delegate()->GetAccessibleWindowRole(); 549 } 550 551 void RootView::UpdateParentLayer() { 552 if (layer()) 553 ReparentLayer(gfx::Vector2d(GetMirroredX(), y()), widget_->GetLayer()); 554 } 555 556 //////////////////////////////////////////////////////////////////////////////// 557 // RootView, protected: 558 559 void RootView::DispatchGestureEvent(ui::GestureEvent* event) { 560 if (gesture_handler_) { 561 // |gesture_handler_| (or |scroll_gesture_handler_|) can be deleted during 562 // processing. 563 View* handler = scroll_gesture_handler_ && 564 (event->IsScrollGestureEvent() || event->IsFlingScrollEvent()) ? 565 scroll_gesture_handler_ : gesture_handler_; 566 ui::GestureEvent handler_event(*event, static_cast<View*>(this), handler); 567 ui::EventDispatchDetails dispatch_details = 568 DispatchEvent(handler, &handler_event); 569 if (dispatch_details.dispatcher_destroyed) 570 return; 571 572 if (event->type() == ui::ET_GESTURE_END && 573 event->details().touch_points() <= 1) { 574 // In case a drag was in progress, reset all the handlers. Otherwise, just 575 // reset the gesture handler. 576 if (gesture_handler_ == mouse_pressed_handler_) 577 SetMouseHandler(NULL); 578 else 579 gesture_handler_ = NULL; 580 } 581 582 if (scroll_gesture_handler_ && 583 (event->type() == ui::ET_GESTURE_SCROLL_END || 584 event->type() == ui::ET_SCROLL_FLING_START)) { 585 scroll_gesture_handler_ = NULL; 586 } 587 588 if (handler_event.stopped_propagation()) { 589 event->StopPropagation(); 590 return; 591 } else if (handler_event.handled()) { 592 event->SetHandled(); 593 return; 594 } 595 596 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN && 597 !scroll_gesture_handler_) { 598 // Some view started processing gesture events, however it does not 599 // process scroll-gesture events. In such case, we allow the event to 600 // bubble up, and install a different scroll-gesture handler different 601 // from the default gesture handler. 602 for (scroll_gesture_handler_ = gesture_handler_->parent(); 603 scroll_gesture_handler_ && scroll_gesture_handler_ != this; 604 scroll_gesture_handler_ = scroll_gesture_handler_->parent()) { 605 ui::GestureEvent gesture_event(*event, static_cast<View*>(this), 606 scroll_gesture_handler_); 607 ui::EventDispatchDetails dispatch_details = 608 DispatchEvent(scroll_gesture_handler_, &gesture_event); 609 if (gesture_event.stopped_propagation()) { 610 event->StopPropagation(); 611 return; 612 } else if (gesture_event.handled()) { 613 event->SetHandled(); 614 return; 615 } else if (dispatch_details.dispatcher_destroyed || 616 dispatch_details.target_destroyed) { 617 return; 618 } 619 } 620 scroll_gesture_handler_ = NULL; 621 } 622 623 return; 624 } 625 626 // If there was no handler for a SCROLL_BEGIN event, then subsequent scroll 627 // events are not dispatched to any views. 628 switch (event->type()) { 629 case ui::ET_GESTURE_SCROLL_UPDATE: 630 case ui::ET_GESTURE_SCROLL_END: 631 case ui::ET_SCROLL_FLING_START: 632 return; 633 default: 634 break; 635 } 636 637 View* gesture_handler = NULL; 638 if (views::switches::IsRectBasedTargetingEnabled() && 639 !event->details().bounding_box().IsEmpty()) { 640 // TODO(tdanderson): Pass in the bounding box to GetEventHandlerForRect() 641 // once crbug.com/313392 is resolved. 642 gfx::Rect touch_rect(event->details().bounding_box()); 643 touch_rect.set_origin(event->location()); 644 touch_rect.Offset(-touch_rect.width() / 2, -touch_rect.height() / 2); 645 gesture_handler = GetEventHandlerForRect(touch_rect); 646 } else { 647 gesture_handler = GetEventHandlerForPoint(event->location()); 648 } 649 650 // Walk up the tree until we find a view that wants the gesture event. 651 for (gesture_handler_ = gesture_handler; 652 gesture_handler_ && (gesture_handler_ != this); 653 gesture_handler_ = gesture_handler_->parent()) { 654 if (!gesture_handler_->enabled()) { 655 // Disabled views eat events but are treated as not handled. 656 return; 657 } 658 659 // See if this view wants to handle the Gesture. 660 ui::GestureEvent gesture_event(*event, static_cast<View*>(this), 661 gesture_handler_); 662 ui::EventDispatchDetails dispatch_details = 663 DispatchEvent(gesture_handler_, &gesture_event); 664 if (dispatch_details.dispatcher_destroyed) 665 return; 666 667 // The view could have removed itself from the tree when handling 668 // OnGestureEvent(). So handle as per OnMousePressed. NB: we 669 // assume that the RootView itself cannot be so removed. 670 if (!gesture_handler_) 671 return; 672 673 if (gesture_event.handled()) { 674 if (gesture_event.type() == ui::ET_GESTURE_SCROLL_BEGIN) 675 scroll_gesture_handler_ = gesture_handler_; 676 if (gesture_event.stopped_propagation()) 677 event->StopPropagation(); 678 else 679 event->SetHandled(); 680 // Last ui::ET_GESTURE_END should not set the gesture_handler_. 681 if (gesture_event.type() == ui::ET_GESTURE_END && 682 event->details().touch_points() <= 1) { 683 gesture_handler_ = NULL; 684 } 685 return; 686 } 687 688 // The gesture event wasn't processed. Go up the view hierarchy and 689 // dispatch the gesture event. 690 } 691 692 gesture_handler_ = NULL; 693 } 694 695 void RootView::ViewHierarchyChanged( 696 const ViewHierarchyChangedDetails& details) { 697 widget_->ViewHierarchyChanged(details); 698 699 if (!details.is_add) { 700 if (!explicit_mouse_handler_ && mouse_pressed_handler_ == details.child) 701 mouse_pressed_handler_ = NULL; 702 if (mouse_move_handler_ == details.child) 703 mouse_move_handler_ = NULL; 704 if (gesture_handler_ == details.child) 705 gesture_handler_ = NULL; 706 if (scroll_gesture_handler_ == details.child) 707 scroll_gesture_handler_ = NULL; 708 if (event_dispatch_target_ == details.child) 709 event_dispatch_target_ = NULL; 710 if (old_dispatch_target_ == details.child) 711 old_dispatch_target_ = NULL; 712 } 713 } 714 715 void RootView::VisibilityChanged(View* /*starting_from*/, bool is_visible) { 716 if (!is_visible) { 717 // When the root view is being hidden (e.g. when widget is minimized) 718 // handlers are reset, so that after it is reshown, events are not captured 719 // by old handlers. 720 explicit_mouse_handler_ = false; 721 mouse_pressed_handler_ = NULL; 722 mouse_move_handler_ = NULL; 723 gesture_handler_ = NULL; 724 scroll_gesture_handler_ = NULL; 725 event_dispatch_target_ = NULL; 726 old_dispatch_target_ = NULL; 727 } 728 } 729 730 void RootView::OnPaint(gfx::Canvas* canvas) { 731 if (!layer() || !layer()->fills_bounds_opaquely()) 732 canvas->DrawColor(SK_ColorBLACK, SkXfermode::kClear_Mode); 733 734 View::OnPaint(canvas); 735 } 736 737 gfx::Vector2d RootView::CalculateOffsetToAncestorWithLayer( 738 ui::Layer** layer_parent) { 739 gfx::Vector2d offset(View::CalculateOffsetToAncestorWithLayer(layer_parent)); 740 if (!layer() && layer_parent) 741 *layer_parent = widget_->GetLayer(); 742 return offset; 743 } 744 745 View::DragInfo* RootView::GetDragInfo() { 746 return &drag_info_; 747 } 748 749 //////////////////////////////////////////////////////////////////////////////// 750 // RootView, private: 751 752 // Input ----------------------------------------------------------------------- 753 754 void RootView::UpdateCursor(const ui::MouseEvent& event) { 755 if (!(event.flags() & ui::EF_IS_NON_CLIENT)) { 756 View* v = GetEventHandlerForPoint(event.location()); 757 ui::MouseEvent me(event, static_cast<View*>(this), v); 758 widget_->SetCursor(v->GetCursor(me)); 759 } 760 } 761 762 void RootView::SetMouseLocationAndFlags(const ui::MouseEvent& event) { 763 last_mouse_event_flags_ = event.flags(); 764 last_mouse_event_x_ = event.x(); 765 last_mouse_event_y_ = event.y(); 766 } 767 768 void RootView::NotifyEnterExitOfDescendant(const ui::MouseEvent& event, 769 ui::EventType type, 770 View* view, 771 View* sibling) { 772 for (View* p = view->parent(); p; p = p->parent()) { 773 if (!p->notify_enter_exit_on_child()) 774 continue; 775 if (sibling && p->Contains(sibling)) 776 break; 777 // It is necessary to recreate the notify-event for each dispatch, since one 778 // of the callbacks can mark the event as handled, and that would cause 779 // incorrect event dispatch. 780 MouseEnterExitEvent notify_event(event, type); 781 ui::EventDispatchDetails dispatch_details = DispatchEvent(p, ¬ify_event); 782 if (dispatch_details.dispatcher_destroyed || 783 dispatch_details.target_destroyed) { 784 return; 785 } 786 } 787 } 788 789 bool RootView::CanDispatchToTarget(ui::EventTarget* target) { 790 return event_dispatch_target_ == target; 791 } 792 793 ui::EventDispatchDetails RootView::PreDispatchEvent(ui::EventTarget* target, 794 ui::Event* event) { 795 old_dispatch_target_ = event_dispatch_target_; 796 event_dispatch_target_ = static_cast<View*>(target); 797 return DispatchDetails(); 798 } 799 800 ui::EventDispatchDetails RootView::PostDispatchEvent(ui::EventTarget* target, 801 const ui::Event& event) { 802 DispatchDetails details; 803 if (target != event_dispatch_target_) 804 details.target_destroyed = true; 805 806 event_dispatch_target_ = old_dispatch_target_; 807 old_dispatch_target_ = NULL; 808 809 #ifndef NDEBUG 810 DCHECK(!event_dispatch_target_ || Contains(event_dispatch_target_)); 811 #endif 812 813 return details; 814 } 815 816 } // namespace internal 817 } // namespace views 818