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