NativeViewHost should query its native view for the current cursor
[chromium-blink-merge.git] / ui / views / widget / root_view.cc
blobc916333a92bfaeaeb2a5be0f2723b7762d2a8e42
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"
7 #include <algorithm>
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h"
11 #include "ui/accessibility/ax_view_state.h"
12 #include "ui/base/cursor/cursor.h"
13 #include "ui/base/dragdrop/drag_drop_types.h"
14 #include "ui/compositor/layer.h"
15 #include "ui/events/event.h"
16 #include "ui/events/keycodes/keyboard_codes.h"
17 #include "ui/gfx/canvas.h"
18 #include "ui/views/focus/view_storage.h"
19 #include "ui/views/layout/fill_layout.h"
20 #include "ui/views/views_switches.h"
21 #include "ui/views/widget/widget.h"
22 #include "ui/views/widget/widget_delegate.h"
24 typedef ui::EventDispatchDetails DispatchDetails;
26 namespace views {
27 namespace internal {
29 namespace {
31 enum EventType {
32 EVENT_ENTER,
33 EVENT_EXIT
36 class MouseEnterExitEvent : public ui::MouseEvent {
37 public:
38 MouseEnterExitEvent(const ui::MouseEvent& event, ui::EventType type)
39 : ui::MouseEvent(event,
40 static_cast<View*>(NULL),
41 static_cast<View*>(NULL)) {
42 DCHECK(type == ui::ET_MOUSE_ENTERED ||
43 type == ui::ET_MOUSE_EXITED);
44 SetType(type);
47 virtual ~MouseEnterExitEvent() {}
50 } // namespace
52 // static
53 const char RootView::kViewClassName[] = "RootView";
55 ////////////////////////////////////////////////////////////////////////////////
56 // RootView, public:
58 // Creation and lifetime -------------------------------------------------------
60 RootView::RootView(Widget* widget)
61 : widget_(widget),
62 mouse_pressed_handler_(NULL),
63 mouse_move_handler_(NULL),
64 last_click_handler_(NULL),
65 explicit_mouse_handler_(false),
66 last_mouse_event_flags_(0),
67 last_mouse_event_x_(-1),
68 last_mouse_event_y_(-1),
69 touch_pressed_handler_(NULL),
70 gesture_handler_(NULL),
71 scroll_gesture_handler_(NULL),
72 focus_search_(this, false, false),
73 focus_traversable_parent_(NULL),
74 focus_traversable_parent_view_(NULL),
75 event_dispatch_target_(NULL),
76 old_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.
82 if (has_children())
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);
94 if (has_children())
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.
102 Layout();
105 View* RootView::GetContentsView() {
106 return child_count() > 0 ? child_at(0) : NULL;
109 void RootView::NotifyNativeViewHierarchyChanged() {
110 PropagateNativeViewHierarchyChanged();
113 // Focus -----------------------------------------------------------------------
115 void RootView::SetFocusTraversableParent(FocusTraversable* focus_traversable) {
116 DCHECK(focus_traversable != this);
117 focus_traversable_parent_ = focus_traversable;
120 void RootView::SetFocusTraversableParentView(View* view) {
121 focus_traversable_parent_view_ = view;
124 // System events ---------------------------------------------------------------
126 void RootView::ThemeChanged() {
127 View::PropagateThemeChanged();
130 void RootView::LocaleChanged() {
131 View::PropagateLocaleChanged();
134 ////////////////////////////////////////////////////////////////////////////////
135 // RootView, FocusTraversable implementation:
137 FocusSearch* RootView::GetFocusSearch() {
138 return &focus_search_;
141 FocusTraversable* RootView::GetFocusTraversableParent() {
142 return focus_traversable_parent_;
145 View* RootView::GetFocusTraversableParentView() {
146 return focus_traversable_parent_view_;
149 ////////////////////////////////////////////////////////////////////////////////
150 // RootView, ui::EventProcessor overrides:
152 ui::EventTarget* RootView::GetRootTarget() {
153 return this;
156 ui::EventDispatchDetails RootView::OnEventFromSource(ui::Event* event) {
157 // TODO(tdanderson): Replace the calls to Dispatch*Event() with calls to
158 // EventProcessor::OnEventFromSource() once the code for
159 // that event type has been refactored, and then
160 // eventually remove this function altogether. See
161 // crbug.com/348083.
162 if (event->IsKeyEvent())
163 DispatchKeyEvent(static_cast<ui::KeyEvent*>(event));
164 else if (event->IsScrollEvent())
165 DispatchScrollEvent(static_cast<ui::ScrollEvent*>(event));
166 else if (event->IsTouchEvent())
167 DispatchTouchEvent(static_cast<ui::TouchEvent*>(event));
168 else if (event->IsGestureEvent())
169 DispatchGestureEvent(static_cast<ui::GestureEvent*>(event));
170 else if (event->IsMouseEvent())
171 NOTREACHED() << "Should not be called with a MouseEvent.";
172 else
173 NOTREACHED() << "Invalid event type.";
175 return DispatchDetails();
178 ////////////////////////////////////////////////////////////////////////////////
179 // RootView, View overrides:
181 const Widget* RootView::GetWidget() const {
182 return widget_;
185 Widget* RootView::GetWidget() {
186 return const_cast<Widget*>(const_cast<const RootView*>(this)->GetWidget());
189 bool RootView::IsDrawn() const {
190 return visible();
193 void RootView::Layout() {
194 View::Layout();
195 widget_->OnRootViewLayout();
198 const char* RootView::GetClassName() const {
199 return kViewClassName;
202 void RootView::SchedulePaintInRect(const gfx::Rect& rect) {
203 if (layer()) {
204 layer()->SchedulePaint(rect);
205 } else {
206 gfx::Rect xrect = ConvertRectToParent(rect);
207 gfx::Rect invalid_rect = gfx::IntersectRects(GetLocalBounds(), xrect);
208 if (!invalid_rect.IsEmpty())
209 widget_->SchedulePaintInRect(invalid_rect);
213 bool RootView::OnMousePressed(const ui::MouseEvent& event) {
214 UpdateCursor(event);
215 SetMouseLocationAndFlags(event);
217 // If mouse_pressed_handler_ is non null, we are currently processing
218 // a pressed -> drag -> released session. In that case we send the
219 // event to mouse_pressed_handler_
220 if (mouse_pressed_handler_) {
221 ui::MouseEvent mouse_pressed_event(event, static_cast<View*>(this),
222 mouse_pressed_handler_);
223 drag_info_.Reset();
224 ui::EventDispatchDetails dispatch_details =
225 DispatchEvent(mouse_pressed_handler_, &mouse_pressed_event);
226 if (dispatch_details.dispatcher_destroyed)
227 return true;
228 return true;
230 DCHECK(!explicit_mouse_handler_);
232 bool hit_disabled_view = false;
233 // Walk up the tree until we find a view that wants the mouse event.
234 for (mouse_pressed_handler_ = GetEventHandlerForPoint(event.location());
235 mouse_pressed_handler_ && (mouse_pressed_handler_ != this);
236 mouse_pressed_handler_ = mouse_pressed_handler_->parent()) {
237 DVLOG(1) << "OnMousePressed testing "
238 << mouse_pressed_handler_->GetClassName();
239 if (!mouse_pressed_handler_->enabled()) {
240 // Disabled views should eat events instead of propagating them upwards.
241 hit_disabled_view = true;
242 break;
245 // See if this view wants to handle the mouse press.
246 ui::MouseEvent mouse_pressed_event(event, static_cast<View*>(this),
247 mouse_pressed_handler_);
249 // Remove the double-click flag if the handler is different than the
250 // one which got the first click part of the double-click.
251 if (mouse_pressed_handler_ != last_click_handler_)
252 mouse_pressed_event.set_flags(event.flags() & ~ui::EF_IS_DOUBLE_CLICK);
254 drag_info_.Reset();
255 ui::EventDispatchDetails dispatch_details =
256 DispatchEvent(mouse_pressed_handler_, &mouse_pressed_event);
257 if (dispatch_details.dispatcher_destroyed)
258 return mouse_pressed_event.handled();
260 // The view could have removed itself from the tree when handling
261 // OnMousePressed(). In this case, the removal notification will have
262 // reset mouse_pressed_handler_ to NULL out from under us. Detect this
263 // case and stop. (See comments in view.h.)
265 // NOTE: Don't return true here, because we don't want the frame to
266 // forward future events to us when there's no handler.
267 if (!mouse_pressed_handler_)
268 break;
270 // If the view handled the event, leave mouse_pressed_handler_ set and
271 // return true, which will cause subsequent drag/release events to get
272 // forwarded to that view.
273 if (mouse_pressed_event.handled()) {
274 last_click_handler_ = mouse_pressed_handler_;
275 DVLOG(1) << "OnMousePressed handled by "
276 << mouse_pressed_handler_->GetClassName();
277 return true;
281 // Reset mouse_pressed_handler_ to indicate that no processing is occurring.
282 mouse_pressed_handler_ = NULL;
284 // In the event that a double-click is not handled after traversing the
285 // entire hierarchy (even as a single-click when sent to a different view),
286 // it must be marked as handled to avoid anything happening from default
287 // processing if it the first click-part was handled by us.
288 if (last_click_handler_ && (event.flags() & ui::EF_IS_DOUBLE_CLICK))
289 hit_disabled_view = true;
291 last_click_handler_ = NULL;
292 return hit_disabled_view;
295 bool RootView::OnMouseDragged(const ui::MouseEvent& event) {
296 if (mouse_pressed_handler_) {
297 SetMouseLocationAndFlags(event);
299 ui::MouseEvent mouse_event(event, static_cast<View*>(this),
300 mouse_pressed_handler_);
301 ui::EventDispatchDetails dispatch_details =
302 DispatchEvent(mouse_pressed_handler_, &mouse_event);
303 if (dispatch_details.dispatcher_destroyed)
304 return false;
306 return false;
309 void RootView::OnMouseReleased(const ui::MouseEvent& event) {
310 UpdateCursor(event);
312 if (mouse_pressed_handler_) {
313 ui::MouseEvent mouse_released(event, static_cast<View*>(this),
314 mouse_pressed_handler_);
315 // We allow the view to delete us from the event dispatch callback. As such,
316 // configure state such that we're done first, then call View.
317 View* mouse_pressed_handler = mouse_pressed_handler_;
318 SetMouseHandler(NULL);
319 ui::EventDispatchDetails dispatch_details =
320 DispatchEvent(mouse_pressed_handler, &mouse_released);
321 if (dispatch_details.dispatcher_destroyed)
322 return;
326 void RootView::OnMouseCaptureLost() {
327 // TODO: this likely needs to reset touch handler too.
329 if (mouse_pressed_handler_ || gesture_handler_) {
330 // Synthesize a release event for UpdateCursor.
331 if (mouse_pressed_handler_) {
332 gfx::Point last_point(last_mouse_event_x_, last_mouse_event_y_);
333 ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED,
334 last_point, last_point,
335 last_mouse_event_flags_,
337 UpdateCursor(release_event);
339 // We allow the view to delete us from OnMouseCaptureLost. As such,
340 // configure state such that we're done first, then call View.
341 View* mouse_pressed_handler = mouse_pressed_handler_;
342 View* gesture_handler = gesture_handler_;
343 SetMouseHandler(NULL);
344 if (mouse_pressed_handler)
345 mouse_pressed_handler->OnMouseCaptureLost();
346 else
347 gesture_handler->OnMouseCaptureLost();
348 // WARNING: we may have been deleted.
352 void RootView::OnMouseMoved(const ui::MouseEvent& event) {
353 View* v = GetEventHandlerForPoint(event.location());
354 // Find the first enabled view, or the existing move handler, whichever comes
355 // first. The check for the existing handler is because if a view becomes
356 // disabled while handling moves, it's wrong to suddenly send ET_MOUSE_EXITED
357 // and ET_MOUSE_ENTERED events, because the mouse hasn't actually exited yet.
358 while (v && !v->enabled() && (v != mouse_move_handler_))
359 v = v->parent();
360 if (v && v != this) {
361 if (v != mouse_move_handler_) {
362 if (mouse_move_handler_ != NULL &&
363 (!mouse_move_handler_->notify_enter_exit_on_child() ||
364 !mouse_move_handler_->Contains(v))) {
365 MouseEnterExitEvent exit(event, ui::ET_MOUSE_EXITED);
366 ui::EventDispatchDetails dispatch_details =
367 DispatchEvent(mouse_move_handler_, &exit);
368 if (dispatch_details.dispatcher_destroyed)
369 return;
370 NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED,
371 mouse_move_handler_, v);
373 View* old_handler = mouse_move_handler_;
374 mouse_move_handler_ = v;
375 if (!mouse_move_handler_->notify_enter_exit_on_child() ||
376 !mouse_move_handler_->Contains(old_handler)) {
377 MouseEnterExitEvent entered(event, ui::ET_MOUSE_ENTERED);
378 entered.ConvertLocationToTarget(static_cast<View*>(this),
379 mouse_move_handler_);
380 ui::EventDispatchDetails dispatch_details =
381 DispatchEvent(mouse_move_handler_, &entered);
382 if (dispatch_details.dispatcher_destroyed)
383 return;
384 NotifyEnterExitOfDescendant(entered, ui::ET_MOUSE_ENTERED, v,
385 old_handler);
388 ui::MouseEvent moved_event(event, static_cast<View*>(this),
389 mouse_move_handler_);
390 mouse_move_handler_->OnMouseMoved(moved_event);
391 // TODO(tdanderson): It may be possible to avoid setting the cursor twice
392 // (once here and once from CompoundEventFilter) on a
393 // mousemove. See crbug.com/351469.
394 if (!(moved_event.flags() & ui::EF_IS_NON_CLIENT))
395 widget_->SetCursor(mouse_move_handler_->GetCursor(moved_event));
396 } else if (mouse_move_handler_ != NULL) {
397 MouseEnterExitEvent exited(event, ui::ET_MOUSE_EXITED);
398 ui::EventDispatchDetails dispatch_details =
399 DispatchEvent(mouse_move_handler_, &exited);
400 if (dispatch_details.dispatcher_destroyed)
401 return;
402 NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED,
403 mouse_move_handler_, v);
404 // On Aura the non-client area extends slightly outside the root view for
405 // some windows. Let the non-client cursor handling code set the cursor
406 // as we do above.
407 if (!(event.flags() & ui::EF_IS_NON_CLIENT))
408 widget_->SetCursor(gfx::kNullCursor);
409 mouse_move_handler_ = NULL;
413 void RootView::OnMouseExited(const ui::MouseEvent& event) {
414 if (mouse_move_handler_ != NULL) {
415 MouseEnterExitEvent exited(event, ui::ET_MOUSE_EXITED);
416 ui::EventDispatchDetails dispatch_details =
417 DispatchEvent(mouse_move_handler_, &exited);
418 if (dispatch_details.dispatcher_destroyed)
419 return;
420 NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED,
421 mouse_move_handler_, NULL);
422 mouse_move_handler_ = NULL;
426 bool RootView::OnMouseWheel(const ui::MouseWheelEvent& event) {
427 for (View* v = GetEventHandlerForPoint(event.location());
428 v && v != this && !event.handled(); v = v->parent()) {
429 ui::EventDispatchDetails dispatch_details =
430 DispatchEvent(v, const_cast<ui::MouseWheelEvent*>(&event));
431 if (dispatch_details.dispatcher_destroyed ||
432 dispatch_details.target_destroyed) {
433 return event.handled();
436 return event.handled();
439 void RootView::SetMouseHandler(View* new_mh) {
440 // If we're clearing the mouse handler, clear explicit_mouse_handler_ as well.
441 explicit_mouse_handler_ = (new_mh != NULL);
442 mouse_pressed_handler_ = new_mh;
443 gesture_handler_ = new_mh;
444 scroll_gesture_handler_ = new_mh;
445 drag_info_.Reset();
448 void RootView::GetAccessibleState(ui::AXViewState* state) {
449 state->name = widget_->widget_delegate()->GetAccessibleWindowTitle();
450 state->role = widget_->widget_delegate()->GetAccessibleWindowRole();
453 void RootView::UpdateParentLayer() {
454 if (layer())
455 ReparentLayer(gfx::Vector2d(GetMirroredX(), y()), widget_->GetLayer());
458 ////////////////////////////////////////////////////////////////////////////////
459 // RootView, protected:
461 void RootView::DispatchGestureEvent(ui::GestureEvent* event) {
462 if (gesture_handler_) {
463 // |gesture_handler_| (or |scroll_gesture_handler_|) can be deleted during
464 // processing.
465 View* handler = scroll_gesture_handler_ &&
466 (event->IsScrollGestureEvent() || event->IsFlingScrollEvent()) ?
467 scroll_gesture_handler_ : gesture_handler_;
468 ui::GestureEvent handler_event(*event, static_cast<View*>(this), handler);
469 ui::EventDispatchDetails dispatch_details =
470 DispatchEvent(handler, &handler_event);
471 if (dispatch_details.dispatcher_destroyed)
472 return;
474 if (event->type() == ui::ET_GESTURE_END &&
475 event->details().touch_points() <= 1) {
476 // In case a drag was in progress, reset all the handlers. Otherwise, just
477 // reset the gesture handler.
478 if (gesture_handler_ == mouse_pressed_handler_)
479 SetMouseHandler(NULL);
480 else
481 gesture_handler_ = NULL;
484 if (scroll_gesture_handler_ &&
485 (event->type() == ui::ET_GESTURE_SCROLL_END ||
486 event->type() == ui::ET_SCROLL_FLING_START)) {
487 scroll_gesture_handler_ = NULL;
490 if (handler_event.stopped_propagation()) {
491 event->StopPropagation();
492 return;
493 } else if (handler_event.handled()) {
494 event->SetHandled();
495 return;
498 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN &&
499 !scroll_gesture_handler_) {
500 // Some view started processing gesture events, however it does not
501 // process scroll-gesture events. In such case, we allow the event to
502 // bubble up, and install a different scroll-gesture handler different
503 // from the default gesture handler.
504 for (scroll_gesture_handler_ = gesture_handler_->parent();
505 scroll_gesture_handler_ && scroll_gesture_handler_ != this;
506 scroll_gesture_handler_ = scroll_gesture_handler_->parent()) {
507 ui::GestureEvent gesture_event(*event, static_cast<View*>(this),
508 scroll_gesture_handler_);
509 ui::EventDispatchDetails dispatch_details =
510 DispatchEvent(scroll_gesture_handler_, &gesture_event);
511 if (gesture_event.stopped_propagation()) {
512 event->StopPropagation();
513 return;
514 } else if (gesture_event.handled()) {
515 event->SetHandled();
516 return;
517 } else if (dispatch_details.dispatcher_destroyed ||
518 dispatch_details.target_destroyed) {
519 return;
522 scroll_gesture_handler_ = NULL;
525 return;
528 // If there was no handler for a SCROLL_BEGIN event, then subsequent scroll
529 // events are not dispatched to any views.
530 switch (event->type()) {
531 case ui::ET_GESTURE_SCROLL_UPDATE:
532 case ui::ET_GESTURE_SCROLL_END:
533 case ui::ET_SCROLL_FLING_START:
534 return;
535 default:
536 break;
539 View* gesture_handler = NULL;
540 if (views::switches::IsRectBasedTargetingEnabled() &&
541 !event->details().bounding_box().IsEmpty()) {
542 // TODO(tdanderson): Pass in the bounding box to GetEventHandlerForRect()
543 // once crbug.com/313392 is resolved.
544 gfx::Rect touch_rect(event->details().bounding_box());
545 touch_rect.set_origin(event->location());
546 touch_rect.Offset(-touch_rect.width() / 2, -touch_rect.height() / 2);
547 gesture_handler = GetEventHandlerForRect(touch_rect);
548 } else {
549 gesture_handler = GetEventHandlerForPoint(event->location());
552 // Walk up the tree until we find a view that wants the gesture event.
553 for (gesture_handler_ = gesture_handler;
554 gesture_handler_ && (gesture_handler_ != this);
555 gesture_handler_ = gesture_handler_->parent()) {
556 if (!gesture_handler_->enabled()) {
557 // Disabled views eat events but are treated as not handled.
558 return;
561 // See if this view wants to handle the Gesture.
562 ui::GestureEvent gesture_event(*event, static_cast<View*>(this),
563 gesture_handler_);
564 ui::EventDispatchDetails dispatch_details =
565 DispatchEvent(gesture_handler_, &gesture_event);
566 if (dispatch_details.dispatcher_destroyed)
567 return;
569 // The view could have removed itself from the tree when handling
570 // OnGestureEvent(). So handle as per OnMousePressed. NB: we
571 // assume that the RootView itself cannot be so removed.
572 if (!gesture_handler_)
573 return;
575 if (gesture_event.handled()) {
576 if (gesture_event.type() == ui::ET_GESTURE_SCROLL_BEGIN)
577 scroll_gesture_handler_ = gesture_handler_;
578 if (gesture_event.stopped_propagation())
579 event->StopPropagation();
580 else
581 event->SetHandled();
582 // Last ui::ET_GESTURE_END should not set the gesture_handler_.
583 if (gesture_event.type() == ui::ET_GESTURE_END &&
584 event->details().touch_points() <= 1) {
585 gesture_handler_ = NULL;
587 return;
590 // The gesture event wasn't processed. Go up the view hierarchy and
591 // dispatch the gesture event.
594 gesture_handler_ = NULL;
597 void RootView::ViewHierarchyChanged(
598 const ViewHierarchyChangedDetails& details) {
599 widget_->ViewHierarchyChanged(details);
601 if (!details.is_add) {
602 if (!explicit_mouse_handler_ && mouse_pressed_handler_ == details.child)
603 mouse_pressed_handler_ = NULL;
604 if (mouse_move_handler_ == details.child)
605 mouse_move_handler_ = NULL;
606 if (touch_pressed_handler_ == details.child)
607 touch_pressed_handler_ = NULL;
608 if (gesture_handler_ == details.child)
609 gesture_handler_ = NULL;
610 if (scroll_gesture_handler_ == details.child)
611 scroll_gesture_handler_ = NULL;
612 if (event_dispatch_target_ == details.child)
613 event_dispatch_target_ = NULL;
614 if (old_dispatch_target_ == details.child)
615 old_dispatch_target_ = NULL;
619 void RootView::VisibilityChanged(View* /*starting_from*/, bool is_visible) {
620 if (!is_visible) {
621 // When the root view is being hidden (e.g. when widget is minimized)
622 // handlers are reset, so that after it is reshown, events are not captured
623 // by old handlers.
624 explicit_mouse_handler_ = false;
625 mouse_pressed_handler_ = NULL;
626 mouse_move_handler_ = NULL;
627 touch_pressed_handler_ = NULL;
628 gesture_handler_ = NULL;
629 scroll_gesture_handler_ = NULL;
630 event_dispatch_target_ = NULL;
631 old_dispatch_target_ = NULL;
635 void RootView::OnPaint(gfx::Canvas* canvas) {
636 if (!layer() || !layer()->fills_bounds_opaquely())
637 canvas->DrawColor(SK_ColorBLACK, SkXfermode::kClear_Mode);
639 View::OnPaint(canvas);
642 gfx::Vector2d RootView::CalculateOffsetToAncestorWithLayer(
643 ui::Layer** layer_parent) {
644 gfx::Vector2d offset(View::CalculateOffsetToAncestorWithLayer(layer_parent));
645 if (!layer() && layer_parent)
646 *layer_parent = widget_->GetLayer();
647 return offset;
650 View::DragInfo* RootView::GetDragInfo() {
651 return &drag_info_;
654 ////////////////////////////////////////////////////////////////////////////////
655 // RootView, private:
657 // Input -----------------------------------------------------------------------
659 void RootView::DispatchKeyEvent(ui::KeyEvent* event) {
660 View* v = NULL;
661 if (GetFocusManager()) // NULL in unittests.
662 v = GetFocusManager()->GetFocusedView();
663 // Special case to handle keyboard-triggered context menus.
664 if (v && v->enabled() && ((event->key_code() == ui::VKEY_APPS) ||
665 (event->key_code() == ui::VKEY_F10 && event->IsShiftDown()))) {
666 // Clamp the menu location within the visible bounds of each ancestor view
667 // to avoid showing the menu over a completely different view or window.
668 gfx::Point location = v->GetKeyboardContextMenuLocation();
669 for (View* parent = v->parent(); parent; parent = parent->parent()) {
670 const gfx::Rect& parent_bounds = parent->GetBoundsInScreen();
671 location.SetToMax(parent_bounds.origin());
672 location.SetToMin(parent_bounds.bottom_right());
674 v->ShowContextMenu(location, ui::MENU_SOURCE_KEYBOARD);
675 event->StopPropagation();
676 return;
679 DispatchKeyEventStartAt(v, event);
682 void RootView::DispatchScrollEvent(ui::ScrollEvent* event) {
683 for (View* v = GetEventHandlerForPoint(event->location());
684 v && v != this && !event->stopped_propagation(); v = v->parent()) {
685 ui::EventDispatchDetails dispatch_details = DispatchEvent(v, event);
686 if (dispatch_details.dispatcher_destroyed ||
687 dispatch_details.target_destroyed) {
688 return;
692 if (event->handled() || event->type() != ui::ET_SCROLL)
693 return;
695 // Convert unprocessed scroll events into mouse-wheel events.
696 ui::MouseWheelEvent wheel(*event);
697 if (OnMouseWheel(wheel))
698 event->SetHandled();
701 void RootView::DispatchTouchEvent(ui::TouchEvent* event) {
702 // TODO: this looks all wrong. On a TOUCH_PRESSED we should figure out the
703 // view and target that view with all touches with the same id until the
704 // release (or keep it if captured).
706 // If touch_pressed_handler_ is non null, we are currently processing
707 // a touch down on the screen situation. In that case we send the
708 // event to touch_pressed_handler_
710 if (touch_pressed_handler_) {
711 ui::TouchEvent touch_event(*event, static_cast<View*>(this),
712 touch_pressed_handler_);
713 ui::EventDispatchDetails dispatch_details =
714 DispatchEvent(touch_pressed_handler_, &touch_event);
715 if (touch_event.handled())
716 event->SetHandled();
717 if (touch_event.stopped_propagation())
718 event->StopPropagation();
719 if (dispatch_details.dispatcher_destroyed)
720 return;
721 return;
724 // Walk up the tree until we find a view that wants the touch event.
725 for (touch_pressed_handler_ = GetEventHandlerForPoint(event->location());
726 touch_pressed_handler_ && (touch_pressed_handler_ != this);
727 touch_pressed_handler_ = touch_pressed_handler_->parent()) {
728 if (!touch_pressed_handler_->enabled()) {
729 // Disabled views eat events but are treated as not handled.
730 break;
733 // See if this view wants to handle the touch
734 ui::TouchEvent touch_event(*event, static_cast<View*>(this),
735 touch_pressed_handler_);
736 ui::EventDispatchDetails dispatch_details =
737 DispatchEvent(touch_pressed_handler_, &touch_event);
738 if (touch_event.handled())
739 event->SetHandled();
740 if (touch_event.stopped_propagation())
741 event->StopPropagation();
742 if (dispatch_details.dispatcher_destroyed)
743 return;
745 // The view could have removed itself from the tree when handling
746 // OnTouchEvent(). So handle as per OnMousePressed. NB: we
747 // assume that the RootView itself cannot be so removed.
748 if (!touch_pressed_handler_)
749 break;
751 // The touch event wasn't processed. Go up the view hierarchy and dispatch
752 // the touch event.
753 if (!event->handled())
754 continue;
756 // If a View consumed the event, that means future touch-events should go to
757 // that View. If the event wasn't consumed, then reset the handler.
758 if (!event->stopped_propagation())
759 touch_pressed_handler_ = NULL;
761 return;
764 // Reset touch_pressed_handler_ to indicate that no processing is occurring.
765 touch_pressed_handler_ = NULL;
767 return;
770 void RootView::UpdateCursor(const ui::MouseEvent& event) {
771 if (!(event.flags() & ui::EF_IS_NON_CLIENT)) {
772 View* v = GetEventHandlerForPoint(event.location());
773 ui::MouseEvent me(event, static_cast<View*>(this), v);
774 widget_->SetCursor(v->GetCursor(me));
778 void RootView::SetMouseLocationAndFlags(const ui::MouseEvent& event) {
779 last_mouse_event_flags_ = event.flags();
780 last_mouse_event_x_ = event.x();
781 last_mouse_event_y_ = event.y();
784 void RootView::NotifyEnterExitOfDescendant(const ui::MouseEvent& event,
785 ui::EventType type,
786 View* view,
787 View* sibling) {
788 for (View* p = view->parent(); p; p = p->parent()) {
789 if (!p->notify_enter_exit_on_child())
790 continue;
791 if (sibling && p->Contains(sibling))
792 break;
793 // It is necessary to recreate the notify-event for each dispatch, since one
794 // of the callbacks can mark the event as handled, and that would cause
795 // incorrect event dispatch.
796 MouseEnterExitEvent notify_event(event, type);
797 ui::EventDispatchDetails dispatch_details = DispatchEvent(p, &notify_event);
798 if (dispatch_details.dispatcher_destroyed ||
799 dispatch_details.target_destroyed) {
800 return;
805 void RootView::DispatchKeyEventStartAt(View* view, ui::KeyEvent* event) {
806 for (; view && view != this && !event->handled(); view = view->parent()) {
807 ui::EventDispatchDetails dispatch_details = DispatchEvent(view, event);
808 if (dispatch_details.dispatcher_destroyed ||
809 dispatch_details.target_destroyed) {
810 return;
815 bool RootView::CanDispatchToTarget(ui::EventTarget* target) {
816 return event_dispatch_target_ == target;
819 ui::EventDispatchDetails RootView::PreDispatchEvent(ui::EventTarget* target,
820 ui::Event* event) {
821 old_dispatch_target_ = event_dispatch_target_;
822 event_dispatch_target_ = static_cast<View*>(target);
823 return DispatchDetails();
826 ui::EventDispatchDetails RootView::PostDispatchEvent(ui::EventTarget* target,
827 const ui::Event& event) {
828 DispatchDetails details;
829 if (target != event_dispatch_target_)
830 details.target_destroyed = true;
832 event_dispatch_target_ = old_dispatch_target_;
833 old_dispatch_target_ = NULL;
835 #ifndef NDEBUG
836 DCHECK(!event_dispatch_target_ || Contains(event_dispatch_target_));
837 #endif
839 return details;
842 } // namespace internal
843 } // namespace views