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