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