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