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.
5 #include "ui/views/widget/root_view.h"
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"
24 #include "ui/base/cursor/cursor.h"
37 class MouseEnterExitEvent : public ui::MouseEvent {
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);
48 virtual ~MouseEnterExitEvent() {}
54 const char RootView::kViewClassName[] = "RootView";
56 ////////////////////////////////////////////////////////////////////////////////
59 // Creation and lifetime -------------------------------------------------------
61 RootView::RootView(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) {
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.
83 RemoveAllChildViews(true);
86 // Tree operations -------------------------------------------------------------
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);
95 RemoveAllChildViews(true);
96 AddChildView(contents_view);
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.
105 View* RootView::GetContentsView() {
106 return child_count() > 0 ? child_at(0) : NULL;
109 void RootView::NotifyNativeViewHierarchyChanged() {
110 PropagateNativeViewHierarchyChanged();
113 // Input -----------------------------------------------------------------------
115 void RootView::DispatchKeyEvent(ui::KeyEvent* event) {
117 if (GetFocusManager()) // NULL in unittests.
118 v = GetFocusManager()->GetFocusedView();
119 // Special case to handle right-click context menus triggered by the
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(),
131 keyboard_loc.AdjustToFit(visible_bounds);
132 v->ShowContextMenu(keyboard_loc.origin(), ui::MENU_SOURCE_KEYBOARD);
133 event->StopPropagation();
137 DispatchKeyEventStartAt(v, event);
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);
146 if (event->handled() || event->type() != ui::ET_SCROLL)
149 // Convert unprocessed scroll events into mouse-wheel events.
150 ui::MouseWheelEvent wheel(*event);
151 if (OnMouseWheel(wheel))
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).
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_
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())
170 if (touch_event.stopped_propagation())
171 event->StopPropagation();
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.
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())
190 if (touch_event.stopped_propagation())
191 event->StopPropagation();
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_)
199 // The touch event wasn't processed. Go up the view hierarchy and dispatch
201 if (!event->handled())
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;
212 // Reset touch_pressed_handler_ to indicate that no processing is occurring.
213 touch_pressed_handler_ = NULL;
218 void RootView::DispatchGestureEvent(ui::GestureEvent* event) {
219 if (gesture_handler_) {
220 // |gesture_handler_| (or |scroll_gesture_handler_|) can be deleted during
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);
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);
235 gesture_handler_ = NULL;
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;
244 if (handler_event.stopped_propagation()) {
245 event->StopPropagation();
247 } else if (handler_event.handled()) {
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();
267 } else if (gesture_event.handled()) {
272 scroll_gesture_handler_ = NULL;
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:
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.
298 // See if this view wants to handle the Gesture.
299 ui::GestureEvent gesture_event(*event, static_cast<View*>(this),
301 DispatchEventToTarget(gesture_handler_, &gesture_event);
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_)
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();
319 // The gesture event wasn't processed. Go up the view hierarchy and
320 // dispatch the gesture event.
323 gesture_handler_ = NULL;
326 // Focus -----------------------------------------------------------------------
328 void RootView::SetFocusTraversableParent(FocusTraversable* focus_traversable) {
329 DCHECK(focus_traversable != this);
330 focus_traversable_parent_ = focus_traversable;
333 void RootView::SetFocusTraversableParentView(View* view) {
334 focus_traversable_parent_view_ = view;
337 // System events ---------------------------------------------------------------
339 void RootView::ThemeChanged() {
340 View::PropagateThemeChanged();
343 void RootView::LocaleChanged() {
344 View::PropagateLocaleChanged();
347 ////////////////////////////////////////////////////////////////////////////////
348 // RootView, FocusTraversable implementation:
350 FocusSearch* RootView::GetFocusSearch() {
351 return &focus_search_;
354 FocusTraversable* RootView::GetFocusTraversableParent() {
355 return focus_traversable_parent_;
358 View* RootView::GetFocusTraversableParentView() {
359 return focus_traversable_parent_view_;
362 ////////////////////////////////////////////////////////////////////////////////
363 // RootView, View overrides:
365 const Widget* RootView::GetWidget() const {
369 Widget* RootView::GetWidget() {
370 return const_cast<Widget*>(const_cast<const RootView*>(this)->GetWidget());
373 bool RootView::IsDrawn() const {
377 void RootView::Layout() {
379 widget_->OnRootViewLayout();
382 const char* RootView::GetClassName() const {
383 return kViewClassName;
386 void RootView::SchedulePaintInRect(const gfx::Rect& rect) {
388 layer()->SchedulePaint(rect);
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);
397 bool RootView::OnMousePressed(const ui::MouseEvent& event) {
399 SetMouseLocationAndFlags(event);
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_);
408 DispatchEventToTarget(mouse_pressed_handler_, &mouse_pressed_event);
411 DCHECK(!explicit_mouse_handler_);
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;
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_);
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);
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();
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.)
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_)
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();
464 // Reset mouse_pressed_handler_ to indicate that no processing is occurring.
465 mouse_pressed_handler_ = NULL;
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;
474 last_click_handler_ = NULL;
475 return hit_disabled_view;
478 bool RootView::OnMouseDragged(const ui::MouseEvent& event) {
479 if (mouse_pressed_handler_) {
480 SetMouseLocationAndFlags(event);
482 ui::MouseEvent mouse_event(event, static_cast<View*>(this),
483 mouse_pressed_handler_);
484 DispatchEventToTarget(mouse_pressed_handler_, &mouse_event);
489 void RootView::OnMouseReleased(const ui::MouseEvent& event) {
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.
504 void RootView::OnMouseCaptureLost() {
505 // TODO: this likely needs to reset touch handler too.
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);
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();
524 gesture_handler->OnMouseCaptureLost();
525 // WARNING: we may have been deleted.
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_))
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);
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,
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
572 if (!(event.flags() & ui::EF_IS_NON_CLIENT))
573 widget_->SetCursor(gfx::kNullCursor);
574 mouse_move_handler_ = NULL;
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;
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();
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;
604 void RootView::GetAccessibleState(ui::AccessibleViewState* state) {
605 state->name = widget_->widget_delegate()->GetAccessibleWindowTitle();
606 state->role = widget_->widget_delegate()->GetAccessibleWindowRole();
609 void RootView::UpdateParentLayer() {
611 ReparentLayer(gfx::Vector2d(GetMirroredX(), y()), widget_->GetLayer());
614 ////////////////////////////////////////////////////////////////////////////////
615 // RootView, protected:
617 void RootView::ViewHierarchyChanged(
618 const ViewHierarchyChangedDetails& details) {
619 widget_->ViewHierarchyChanged(details);
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;
637 void RootView::VisibilityChanged(View* /*starting_from*/, bool 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
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;
652 void RootView::OnPaint(gfx::Canvas* canvas) {
653 if (!layer() || !layer()->fills_bounds_opaquely())
654 canvas->DrawColor(SK_ColorBLACK, SkXfermode::kClear_Mode);
656 View::OnPaint(canvas);
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();
667 View::DragInfo* RootView::GetDragInfo() {
671 ////////////////////////////////////////////////////////////////////////////////
672 // RootView, private:
674 // Input -----------------------------------------------------------------------
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));
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();
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;
697 void RootView::NotifyEnterExitOfDescendant(const ui::MouseEvent& event,
701 for (View* p = view->parent(); p; p = p->parent()) {
702 if (!p->notify_enter_exit_on_child())
704 if (sibling && p->Contains(sibling))
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, ¬ify_event);
715 void RootView::DispatchKeyEventStartAt(View* view, ui::KeyEvent* event) {
716 if (event->handled() || !view)
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())
727 bool RootView::CanDispatchToTarget(ui::EventTarget* target) {
728 return event_dispatch_target_ == target;
731 } // namespace internal