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