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