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/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/event_utils.h"
18 #include "ui/events/keycodes/keyboard_codes.h"
19 #include "ui/gfx/canvas.h"
20 #include "ui/views/drag_controller.h"
21 #include "ui/views/focus/view_storage.h"
22 #include "ui/views/layout/fill_layout.h"
23 #include "ui/views/view_targeter.h"
24 #include "ui/views/widget/root_view_targeter.h"
25 #include "ui/views/widget/widget.h"
26 #include "ui/views/widget/widget_delegate.h"
28 typedef ui::EventDispatchDetails DispatchDetails
;
40 class MouseEnterExitEvent
: public ui::MouseEvent
{
42 MouseEnterExitEvent(const ui::MouseEvent
& event
, ui::EventType type
)
43 : ui::MouseEvent(event
,
44 static_cast<View
*>(NULL
),
45 static_cast<View
*>(NULL
)) {
46 DCHECK(type
== ui::ET_MOUSE_ENTERED
||
47 type
== ui::ET_MOUSE_EXITED
);
51 ~MouseEnterExitEvent() override
{}
56 // This event handler receives events in the pre-target phase and takes care of
58 // - Shows keyboard-triggered context menus.
59 class PreEventDispatchHandler
: public ui::EventHandler
{
61 explicit PreEventDispatchHandler(View
* owner
)
64 ~PreEventDispatchHandler() override
{}
68 void OnKeyEvent(ui::KeyEvent
* event
) override
{
69 CHECK_EQ(ui::EP_PRETARGET
, event
->phase());
74 if (owner_
->GetFocusManager()) // Can be NULL in unittests.
75 v
= owner_
->GetFocusManager()->GetFocusedView();
77 // Special case to handle keyboard-triggered context menus.
78 if (v
&& v
->enabled() && ((event
->key_code() == ui::VKEY_APPS
) ||
79 (event
->key_code() == ui::VKEY_F10
&& event
->IsShiftDown()))) {
80 // Clamp the menu location within the visible bounds of each ancestor view
81 // to avoid showing the menu over a completely different view or window.
82 gfx::Point location
= v
->GetKeyboardContextMenuLocation();
83 for (View
* parent
= v
->parent(); parent
; parent
= parent
->parent()) {
84 const gfx::Rect
& parent_bounds
= parent
->GetBoundsInScreen();
85 location
.SetToMax(parent_bounds
.origin());
86 location
.SetToMin(parent_bounds
.bottom_right());
88 v
->ShowContextMenu(location
, ui::MENU_SOURCE_KEYBOARD
);
89 event
->StopPropagation();
95 DISALLOW_COPY_AND_ASSIGN(PreEventDispatchHandler
);
98 // This event handler receives events in the post-target phase and takes care of
100 // - Generates context menu, or initiates drag-and-drop, from gesture events.
101 class PostEventDispatchHandler
: public ui::EventHandler
{
103 PostEventDispatchHandler()
104 : touch_dnd_enabled_(::switches::IsTouchDragDropEnabled()) {
106 ~PostEventDispatchHandler() override
{}
109 // Overridden from ui::EventHandler:
110 void OnGestureEvent(ui::GestureEvent
* event
) override
{
111 DCHECK_EQ(ui::EP_POSTTARGET
, event
->phase());
112 if (event
->handled())
115 View
* target
= static_cast<View
*>(event
->target());
116 gfx::Point location
= event
->location();
117 if (touch_dnd_enabled_
&&
118 event
->type() == ui::ET_GESTURE_LONG_PRESS
&&
119 (!target
->drag_controller() ||
120 target
->drag_controller()->CanStartDragForView(
121 target
, location
, location
))) {
122 if (target
->DoDrag(*event
, location
,
123 ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH
)) {
124 event
->StopPropagation();
129 if (target
->context_menu_controller() &&
130 (event
->type() == ui::ET_GESTURE_LONG_PRESS
||
131 event
->type() == ui::ET_GESTURE_LONG_TAP
||
132 event
->type() == ui::ET_GESTURE_TWO_FINGER_TAP
)) {
133 gfx::Point
screen_location(location
);
134 View::ConvertPointToScreen(target
, &screen_location
);
135 target
->ShowContextMenu(screen_location
, ui::MENU_SOURCE_TOUCH
);
136 event
->StopPropagation();
140 bool touch_dnd_enabled_
;
142 DISALLOW_COPY_AND_ASSIGN(PostEventDispatchHandler
);
146 const char RootView::kViewClassName
[] = "RootView";
148 ////////////////////////////////////////////////////////////////////////////////
151 // Creation and lifetime -------------------------------------------------------
153 RootView::RootView(Widget
* widget
)
155 mouse_pressed_handler_(NULL
),
156 mouse_move_handler_(NULL
),
157 last_click_handler_(NULL
),
158 explicit_mouse_handler_(false),
159 last_mouse_event_flags_(0),
160 last_mouse_event_x_(-1),
161 last_mouse_event_y_(-1),
162 gesture_handler_(NULL
),
163 gesture_handler_set_before_processing_(false),
164 pre_dispatch_handler_(new internal::PreEventDispatchHandler(this)),
165 post_dispatch_handler_(new internal::PostEventDispatchHandler
),
166 focus_search_(this, false, false),
167 focus_traversable_parent_(NULL
),
168 focus_traversable_parent_view_(NULL
),
169 event_dispatch_target_(NULL
),
170 old_dispatch_target_(NULL
) {
171 AddPreTargetHandler(pre_dispatch_handler_
.get());
172 AddPostTargetHandler(post_dispatch_handler_
.get());
173 SetEventTargeter(scoped_ptr
<ViewTargeter
>(new RootViewTargeter(this, this)));
176 RootView::~RootView() {
177 // If we have children remove them explicitly so to make sure a remove
178 // notification is sent for each one of them.
180 RemoveAllChildViews(true);
183 // Tree operations -------------------------------------------------------------
185 void RootView::SetContentsView(View
* contents_view
) {
186 DCHECK(contents_view
&& GetWidget()->native_widget()) <<
187 "Can't be called until after the native widget is created!";
188 // The ContentsView must be set up _after_ the window is created so that its
189 // Widget pointer is valid.
190 SetLayoutManager(new FillLayout
);
192 RemoveAllChildViews(true);
193 AddChildView(contents_view
);
195 // Force a layout now, since the attached hierarchy won't be ready for the
196 // containing window's bounds. Note that we call Layout directly rather than
197 // calling the widget's size changed handler, since the RootView's bounds may
198 // not have changed, which will cause the Layout not to be done otherwise.
202 View
* RootView::GetContentsView() {
203 return child_count() > 0 ? child_at(0) : NULL
;
206 void RootView::NotifyNativeViewHierarchyChanged() {
207 PropagateNativeViewHierarchyChanged();
210 // Focus -----------------------------------------------------------------------
212 void RootView::SetFocusTraversableParent(FocusTraversable
* focus_traversable
) {
213 DCHECK(focus_traversable
!= this);
214 focus_traversable_parent_
= focus_traversable
;
217 void RootView::SetFocusTraversableParentView(View
* view
) {
218 focus_traversable_parent_view_
= view
;
221 // System events ---------------------------------------------------------------
223 void RootView::ThemeChanged() {
224 View::PropagateThemeChanged();
227 void RootView::LocaleChanged() {
228 View::PropagateLocaleChanged();
231 void RootView::DeviceScaleFactorChanged(float device_scale_factor
) {
232 View::PropagateDeviceScaleFactorChanged(device_scale_factor
);
235 ////////////////////////////////////////////////////////////////////////////////
236 // RootView, FocusTraversable implementation:
238 FocusSearch
* RootView::GetFocusSearch() {
239 return &focus_search_
;
242 FocusTraversable
* RootView::GetFocusTraversableParent() {
243 return focus_traversable_parent_
;
246 View
* RootView::GetFocusTraversableParentView() {
247 return focus_traversable_parent_view_
;
250 ////////////////////////////////////////////////////////////////////////////////
251 // RootView, ui::EventProcessor overrides:
253 ui::EventTarget
* RootView::GetRootTarget() {
257 void RootView::OnEventProcessingStarted(ui::Event
* event
) {
258 if (!event
->IsGestureEvent())
261 ui::GestureEvent
* gesture_event
= event
->AsGestureEvent();
263 // Do not process ui::ET_GESTURE_BEGIN events.
264 if (gesture_event
->type() == ui::ET_GESTURE_BEGIN
) {
269 // Do not process ui::ET_GESTURE_END events if they do not correspond to the
270 // removal of the final touch point or if no gesture handler has already
272 if (gesture_event
->type() == ui::ET_GESTURE_END
&&
273 (gesture_event
->details().touch_points() > 1 ||
274 !gesture_handler_
)) {
279 // Do not process subsequent gesture scroll events if no handler was set for
280 // a ui::ET_GESTURE_SCROLL_BEGIN event.
281 if (!gesture_handler_
&&
282 (gesture_event
->type() == ui::ET_GESTURE_SCROLL_UPDATE
||
283 gesture_event
->type() == ui::ET_GESTURE_SCROLL_END
||
284 gesture_event
->type() == ui::ET_SCROLL_FLING_START
)) {
289 gesture_handler_set_before_processing_
= !!gesture_handler_
;
292 void RootView::OnEventProcessingFinished(ui::Event
* event
) {
293 // If |event| was not handled and |gesture_handler_| was not set by the
294 // dispatch of a previous gesture event, then no default gesture handler
295 // should be set prior to the next gesture event being received.
296 if (event
->IsGestureEvent() &&
298 !gesture_handler_set_before_processing_
) {
299 gesture_handler_
= NULL
;
303 ////////////////////////////////////////////////////////////////////////////////
304 // RootView, View overrides:
306 const Widget
* RootView::GetWidget() const {
310 Widget
* RootView::GetWidget() {
311 return const_cast<Widget
*>(const_cast<const RootView
*>(this)->GetWidget());
314 bool RootView::IsDrawn() const {
318 void RootView::Layout() {
320 widget_
->OnRootViewLayout();
323 const char* RootView::GetClassName() const {
324 return kViewClassName
;
327 void RootView::SchedulePaintInRect(const gfx::Rect
& rect
) {
329 layer()->SchedulePaint(rect
);
331 gfx::Rect xrect
= ConvertRectToParent(rect
);
332 gfx::Rect invalid_rect
= gfx::IntersectRects(GetLocalBounds(), xrect
);
333 if (!invalid_rect
.IsEmpty())
334 widget_
->SchedulePaintInRect(invalid_rect
);
338 bool RootView::OnMousePressed(const ui::MouseEvent
& event
) {
340 SetMouseLocationAndFlags(event
);
342 // If mouse_pressed_handler_ is non null, we are currently processing
343 // a pressed -> drag -> released session. In that case we send the
344 // event to mouse_pressed_handler_
345 if (mouse_pressed_handler_
) {
346 ui::MouseEvent
mouse_pressed_event(event
, static_cast<View
*>(this),
347 mouse_pressed_handler_
);
349 ui::EventDispatchDetails dispatch_details
=
350 DispatchEvent(mouse_pressed_handler_
, &mouse_pressed_event
);
351 if (dispatch_details
.dispatcher_destroyed
)
355 DCHECK(!explicit_mouse_handler_
);
357 bool hit_disabled_view
= false;
358 // Walk up the tree until we find a view that wants the mouse event.
359 for (mouse_pressed_handler_
= GetEventHandlerForPoint(event
.location());
360 mouse_pressed_handler_
&& (mouse_pressed_handler_
!= this);
361 mouse_pressed_handler_
= mouse_pressed_handler_
->parent()) {
362 DVLOG(1) << "OnMousePressed testing "
363 << mouse_pressed_handler_
->GetClassName();
364 if (!mouse_pressed_handler_
->enabled()) {
365 // Disabled views should eat events instead of propagating them upwards.
366 hit_disabled_view
= true;
370 // See if this view wants to handle the mouse press.
371 ui::MouseEvent
mouse_pressed_event(event
, static_cast<View
*>(this),
372 mouse_pressed_handler_
);
374 // Remove the double-click flag if the handler is different than the
375 // one which got the first click part of the double-click.
376 if (mouse_pressed_handler_
!= last_click_handler_
)
377 mouse_pressed_event
.set_flags(event
.flags() & ~ui::EF_IS_DOUBLE_CLICK
);
380 ui::EventDispatchDetails dispatch_details
=
381 DispatchEvent(mouse_pressed_handler_
, &mouse_pressed_event
);
382 if (dispatch_details
.dispatcher_destroyed
)
383 return mouse_pressed_event
.handled();
385 // The view could have removed itself from the tree when handling
386 // OnMousePressed(). In this case, the removal notification will have
387 // reset mouse_pressed_handler_ to NULL out from under us. Detect this
388 // case and stop. (See comments in view.h.)
390 // NOTE: Don't return true here, because we don't want the frame to
391 // forward future events to us when there's no handler.
392 if (!mouse_pressed_handler_
)
395 // If the view handled the event, leave mouse_pressed_handler_ set and
396 // return true, which will cause subsequent drag/release events to get
397 // forwarded to that view.
398 if (mouse_pressed_event
.handled()) {
399 last_click_handler_
= mouse_pressed_handler_
;
400 DVLOG(1) << "OnMousePressed handled by "
401 << mouse_pressed_handler_
->GetClassName();
406 // Reset mouse_pressed_handler_ to indicate that no processing is occurring.
407 mouse_pressed_handler_
= NULL
;
409 // In the event that a double-click is not handled after traversing the
410 // entire hierarchy (even as a single-click when sent to a different view),
411 // it must be marked as handled to avoid anything happening from default
412 // processing if it the first click-part was handled by us.
413 if (last_click_handler_
&& (event
.flags() & ui::EF_IS_DOUBLE_CLICK
))
414 hit_disabled_view
= true;
416 last_click_handler_
= NULL
;
417 return hit_disabled_view
;
420 bool RootView::OnMouseDragged(const ui::MouseEvent
& event
) {
421 if (mouse_pressed_handler_
) {
422 SetMouseLocationAndFlags(event
);
424 ui::MouseEvent
mouse_event(event
, static_cast<View
*>(this),
425 mouse_pressed_handler_
);
426 ui::EventDispatchDetails dispatch_details
=
427 DispatchEvent(mouse_pressed_handler_
, &mouse_event
);
428 if (dispatch_details
.dispatcher_destroyed
)
434 void RootView::OnMouseReleased(const ui::MouseEvent
& event
) {
437 if (mouse_pressed_handler_
) {
438 ui::MouseEvent
mouse_released(event
, static_cast<View
*>(this),
439 mouse_pressed_handler_
);
440 // We allow the view to delete us from the event dispatch callback. As such,
441 // configure state such that we're done first, then call View.
442 View
* mouse_pressed_handler
= mouse_pressed_handler_
;
443 SetMouseHandler(NULL
);
444 ui::EventDispatchDetails dispatch_details
=
445 DispatchEvent(mouse_pressed_handler
, &mouse_released
);
446 if (dispatch_details
.dispatcher_destroyed
)
451 void RootView::OnMouseCaptureLost() {
452 // TODO: this likely needs to reset touch handler too.
454 if (mouse_pressed_handler_
|| gesture_handler_
) {
455 // Synthesize a release event for UpdateCursor.
456 if (mouse_pressed_handler_
) {
457 gfx::Point
last_point(last_mouse_event_x_
, last_mouse_event_y_
);
458 ui::MouseEvent
release_event(ui::ET_MOUSE_RELEASED
, last_point
,
459 last_point
, ui::EventTimeForNow(),
460 last_mouse_event_flags_
, 0);
461 UpdateCursor(release_event
);
463 // We allow the view to delete us from OnMouseCaptureLost. As such,
464 // configure state such that we're done first, then call View.
465 View
* mouse_pressed_handler
= mouse_pressed_handler_
;
466 View
* gesture_handler
= gesture_handler_
;
467 SetMouseHandler(NULL
);
468 if (mouse_pressed_handler
)
469 mouse_pressed_handler
->OnMouseCaptureLost();
471 gesture_handler
->OnMouseCaptureLost();
472 // WARNING: we may have been deleted.
476 void RootView::OnMouseMoved(const ui::MouseEvent
& event
) {
477 View
* v
= GetEventHandlerForPoint(event
.location());
478 // Find the first enabled view, or the existing move handler, whichever comes
479 // first. The check for the existing handler is because if a view becomes
480 // disabled while handling moves, it's wrong to suddenly send ET_MOUSE_EXITED
481 // and ET_MOUSE_ENTERED events, because the mouse hasn't actually exited yet.
482 while (v
&& !v
->enabled() && (v
!= mouse_move_handler_
))
484 if (v
&& v
!= this) {
485 if (v
!= mouse_move_handler_
) {
486 if (mouse_move_handler_
!= NULL
&&
487 (!mouse_move_handler_
->notify_enter_exit_on_child() ||
488 !mouse_move_handler_
->Contains(v
))) {
489 MouseEnterExitEvent
exit(event
, ui::ET_MOUSE_EXITED
);
490 exit
.ConvertLocationToTarget(static_cast<View
*>(this),
491 mouse_move_handler_
);
492 ui::EventDispatchDetails dispatch_details
=
493 DispatchEvent(mouse_move_handler_
, &exit
);
494 if (dispatch_details
.dispatcher_destroyed
)
496 NotifyEnterExitOfDescendant(event
, ui::ET_MOUSE_EXITED
,
497 mouse_move_handler_
, v
);
499 View
* old_handler
= mouse_move_handler_
;
500 mouse_move_handler_
= v
;
501 if (!mouse_move_handler_
->notify_enter_exit_on_child() ||
502 !mouse_move_handler_
->Contains(old_handler
)) {
503 MouseEnterExitEvent
entered(event
, ui::ET_MOUSE_ENTERED
);
504 entered
.ConvertLocationToTarget(static_cast<View
*>(this),
505 mouse_move_handler_
);
506 ui::EventDispatchDetails dispatch_details
=
507 DispatchEvent(mouse_move_handler_
, &entered
);
508 if (dispatch_details
.dispatcher_destroyed
)
510 NotifyEnterExitOfDescendant(event
, ui::ET_MOUSE_ENTERED
,
511 mouse_move_handler_
, old_handler
);
514 ui::MouseEvent
moved_event(event
, static_cast<View
*>(this),
515 mouse_move_handler_
);
516 mouse_move_handler_
->OnMouseMoved(moved_event
);
517 // TODO(tdanderson): It may be possible to avoid setting the cursor twice
518 // (once here and once from CompoundEventFilter) on a
519 // mousemove. See crbug.com/351469.
520 if (!(moved_event
.flags() & ui::EF_IS_NON_CLIENT
))
521 widget_
->SetCursor(mouse_move_handler_
->GetCursor(moved_event
));
522 } else if (mouse_move_handler_
!= NULL
) {
523 MouseEnterExitEvent
exited(event
, ui::ET_MOUSE_EXITED
);
524 ui::EventDispatchDetails dispatch_details
=
525 DispatchEvent(mouse_move_handler_
, &exited
);
526 if (dispatch_details
.dispatcher_destroyed
)
528 NotifyEnterExitOfDescendant(event
, ui::ET_MOUSE_EXITED
,
529 mouse_move_handler_
, v
);
530 // On Aura the non-client area extends slightly outside the root view for
531 // some windows. Let the non-client cursor handling code set the cursor
533 if (!(event
.flags() & ui::EF_IS_NON_CLIENT
))
534 widget_
->SetCursor(gfx::kNullCursor
);
535 mouse_move_handler_
= NULL
;
539 void RootView::OnMouseExited(const ui::MouseEvent
& event
) {
540 if (mouse_move_handler_
!= NULL
) {
541 MouseEnterExitEvent
exited(event
, ui::ET_MOUSE_EXITED
);
542 ui::EventDispatchDetails dispatch_details
=
543 DispatchEvent(mouse_move_handler_
, &exited
);
544 if (dispatch_details
.dispatcher_destroyed
)
546 NotifyEnterExitOfDescendant(event
, ui::ET_MOUSE_EXITED
,
547 mouse_move_handler_
, NULL
);
548 mouse_move_handler_
= NULL
;
552 bool RootView::OnMouseWheel(const ui::MouseWheelEvent
& event
) {
553 for (View
* v
= GetEventHandlerForPoint(event
.location());
554 v
&& v
!= this && !event
.handled(); v
= v
->parent()) {
555 ui::EventDispatchDetails dispatch_details
=
556 DispatchEvent(v
, const_cast<ui::MouseWheelEvent
*>(&event
));
557 if (dispatch_details
.dispatcher_destroyed
||
558 dispatch_details
.target_destroyed
) {
559 return event
.handled();
562 return event
.handled();
565 void RootView::SetMouseHandler(View
* new_mh
) {
566 // If we're clearing the mouse handler, clear explicit_mouse_handler_ as well.
567 explicit_mouse_handler_
= (new_mh
!= NULL
);
568 mouse_pressed_handler_
= new_mh
;
569 gesture_handler_
= new_mh
;
573 void RootView::GetAccessibleState(ui::AXViewState
* state
) {
574 state
->name
= widget_
->widget_delegate()->GetAccessibleWindowTitle();
575 state
->role
= widget_
->widget_delegate()->GetAccessibleWindowRole();
578 void RootView::UpdateParentLayer() {
580 ReparentLayer(gfx::Vector2d(GetMirroredX(), y()), widget_
->GetLayer());
583 ////////////////////////////////////////////////////////////////////////////////
584 // RootView, protected:
586 void RootView::ViewHierarchyChanged(
587 const ViewHierarchyChangedDetails
& details
) {
588 widget_
->ViewHierarchyChanged(details
);
590 if (!details
.is_add
) {
591 if (!explicit_mouse_handler_
&& mouse_pressed_handler_
== details
.child
)
592 mouse_pressed_handler_
= NULL
;
593 if (mouse_move_handler_
== details
.child
)
594 mouse_move_handler_
= NULL
;
595 if (gesture_handler_
== details
.child
)
596 gesture_handler_
= NULL
;
597 if (event_dispatch_target_
== details
.child
)
598 event_dispatch_target_
= NULL
;
599 if (old_dispatch_target_
== details
.child
)
600 old_dispatch_target_
= NULL
;
604 void RootView::VisibilityChanged(View
* /*starting_from*/, bool is_visible
) {
606 // When the root view is being hidden (e.g. when widget is minimized)
607 // handlers are reset, so that after it is reshown, events are not captured
609 explicit_mouse_handler_
= false;
610 mouse_pressed_handler_
= NULL
;
611 mouse_move_handler_
= NULL
;
612 gesture_handler_
= NULL
;
613 event_dispatch_target_
= NULL
;
614 old_dispatch_target_
= NULL
;
618 void RootView::OnPaint(gfx::Canvas
* canvas
) {
619 if (!layer() || !layer()->fills_bounds_opaquely())
620 canvas
->DrawColor(SK_ColorBLACK
, SkXfermode::kClear_Mode
);
622 View::OnPaint(canvas
);
625 gfx::Vector2d
RootView::CalculateOffsetToAncestorWithLayer(
626 ui::Layer
** layer_parent
) {
627 gfx::Vector2d
offset(View::CalculateOffsetToAncestorWithLayer(layer_parent
));
628 if (!layer() && layer_parent
)
629 *layer_parent
= widget_
->GetLayer();
633 View::DragInfo
* RootView::GetDragInfo() {
637 ////////////////////////////////////////////////////////////////////////////////
638 // RootView, private:
640 // Input -----------------------------------------------------------------------
642 void RootView::UpdateCursor(const ui::MouseEvent
& event
) {
643 if (!(event
.flags() & ui::EF_IS_NON_CLIENT
)) {
644 View
* v
= GetEventHandlerForPoint(event
.location());
645 ui::MouseEvent
me(event
, static_cast<View
*>(this), v
);
646 widget_
->SetCursor(v
->GetCursor(me
));
650 void RootView::SetMouseLocationAndFlags(const ui::MouseEvent
& event
) {
651 last_mouse_event_flags_
= event
.flags();
652 last_mouse_event_x_
= event
.x();
653 last_mouse_event_y_
= event
.y();
656 void RootView::NotifyEnterExitOfDescendant(const ui::MouseEvent
& event
,
660 for (View
* p
= view
->parent(); p
; p
= p
->parent()) {
661 if (!p
->notify_enter_exit_on_child())
663 if (sibling
&& p
->Contains(sibling
))
665 // It is necessary to recreate the notify-event for each dispatch, since one
666 // of the callbacks can mark the event as handled, and that would cause
667 // incorrect event dispatch.
668 MouseEnterExitEvent
notify_event(event
, type
);
669 ui::EventDispatchDetails dispatch_details
= DispatchEvent(p
, ¬ify_event
);
670 if (dispatch_details
.dispatcher_destroyed
||
671 dispatch_details
.target_destroyed
) {
677 bool RootView::CanDispatchToTarget(ui::EventTarget
* target
) {
678 return event_dispatch_target_
== target
;
681 ui::EventDispatchDetails
RootView::PreDispatchEvent(ui::EventTarget
* target
,
683 View
* view
= static_cast<View
*>(target
);
684 if (event
->IsGestureEvent()) {
685 // Update |gesture_handler_| to indicate which View is currently handling
687 // TODO(tdanderson): Look into moving this to PostDispatchEvent() and
688 // using |event_dispatch_target_| instead of
689 // |gesture_handler_| to detect if the view has been
690 // removed from the tree.
691 gesture_handler_
= view
;
693 // Disabled views are permitted to be targets of gesture events, but
694 // gesture events should never actually be dispatched to them. Prevent
695 // dispatch by marking the event as handled.
696 if (!view
->enabled())
700 old_dispatch_target_
= event_dispatch_target_
;
701 event_dispatch_target_
= view
;
702 return DispatchDetails();
705 ui::EventDispatchDetails
RootView::PostDispatchEvent(ui::EventTarget
* target
,
706 const ui::Event
& event
) {
707 // The GESTURE_END event corresponding to the removal of the final touch
708 // point marks the end of a gesture sequence, so reset |gesture_handler_|
710 if (event
.type() == ui::ET_GESTURE_END
) {
711 // In case a drag was in progress, reset all the handlers. Otherwise, just
712 // reset the gesture handler.
713 if (gesture_handler_
&& gesture_handler_
== mouse_pressed_handler_
)
714 SetMouseHandler(NULL
);
716 gesture_handler_
= NULL
;
719 DispatchDetails details
;
720 if (target
!= event_dispatch_target_
)
721 details
.target_destroyed
= true;
723 event_dispatch_target_
= old_dispatch_target_
;
724 old_dispatch_target_
= NULL
;
727 DCHECK(!event_dispatch_target_
|| Contains(event_dispatch_target_
));
733 } // namespace internal