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