root_view.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "ui/views/widget/root_view.h" 6 7#include <algorithm> 8 9#include "base/logging.h" 10#include "base/message_loop.h" 11#include "ui/base/accessibility/accessible_view_state.h" 12#include "ui/base/dragdrop/drag_drop_types.h" 13#include "ui/base/events/event.h" 14#include "ui/base/keycodes/keyboard_codes.h" 15#include "ui/compositor/layer.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 22namespace views { 23namespace internal { 24 25namespace { 26 27enum EventType { 28 EVENT_ENTER, 29 EVENT_EXIT 30}; 31 32class MouseEnterExitEvent : public ui::MouseEvent { 33 public: 34 MouseEnterExitEvent(const ui::MouseEvent& event, ui::EventType type) 35 : ui::MouseEvent(event, 36 static_cast<View*>(NULL), 37 static_cast<View*>(NULL)) { 38 DCHECK(type == ui::ET_MOUSE_ENTERED || 39 type == ui::ET_MOUSE_EXITED); 40 SetType(type); 41 } 42 43 virtual ~MouseEnterExitEvent() {} 44}; 45 46} // namespace 47 48// static 49const char RootView::kViewClassName[] = "views/RootView"; 50 51//////////////////////////////////////////////////////////////////////////////// 52// RootView, public: 53 54// Creation and lifetime ------------------------------------------------------- 55 56RootView::RootView(Widget* widget) 57 : widget_(widget), 58 mouse_pressed_handler_(NULL), 59 mouse_move_handler_(NULL), 60 last_click_handler_(NULL), 61 explicit_mouse_handler_(false), 62 last_mouse_event_flags_(0), 63 last_mouse_event_x_(-1), 64 last_mouse_event_y_(-1), 65 touch_pressed_handler_(NULL), 66 gesture_handler_(NULL), 67 scroll_gesture_handler_(NULL), 68 ALLOW_THIS_IN_INITIALIZER_LIST(focus_search_(this, false, false)), 69 focus_traversable_parent_(NULL), 70 focus_traversable_parent_view_(NULL), 71 event_dispatch_target_(NULL) { 72} 73 74RootView::~RootView() { 75 // If we have children remove them explicitly so to make sure a remove 76 // notification is sent for each one of them. 77 if (has_children()) 78 RemoveAllChildViews(true); 79} 80 81// Tree operations ------------------------------------------------------------- 82 83void RootView::SetContentsView(View* contents_view) { 84 DCHECK(contents_view && GetWidget()->native_widget()) << 85 "Can't be called until after the native widget is created!"; 86 // The ContentsView must be set up _after_ the window is created so that its 87 // Widget pointer is valid. 88 SetLayoutManager(new FillLayout); 89 if (has_children()) 90 RemoveAllChildViews(true); 91 AddChildView(contents_view); 92 93 // Force a layout now, since the attached hierarchy won't be ready for the 94 // containing window's bounds. Note that we call Layout directly rather than 95 // calling the widget's size changed handler, since the RootView's bounds may 96 // not have changed, which will cause the Layout not to be done otherwise. 97 Layout(); 98} 99 100View* RootView::GetContentsView() { 101 return child_count() > 0 ? child_at(0) : NULL; 102} 103 104void RootView::NotifyNativeViewHierarchyChanged(bool attached, 105 gfx::NativeView native_view) { 106 PropagateNativeViewHierarchyChanged(attached, native_view, this); 107} 108 109// Input ----------------------------------------------------------------------- 110 111void RootView::DispatchKeyEvent(ui::KeyEvent* event) { 112 View* v = NULL; 113 if (GetFocusManager()) // NULL in unittests. 114 v = GetFocusManager()->GetFocusedView(); 115 // Special case to handle right-click context menus triggered by the 116 // keyboard. 117 if (v && v->enabled() && ((event->key_code() == ui::VKEY_APPS) || 118 (event->key_code() == ui::VKEY_F10 && event->IsShiftDown()))) { 119 v->ShowContextMenu(v->GetKeyboardContextMenuLocation(), false); 120 event->StopPropagation(); 121 return; 122 } 123 124 for (; v && v != this && !event->handled(); v = v->parent()) 125 DispatchEventToTarget(v, event); 126} 127 128void RootView::DispatchScrollEvent(ui::ScrollEvent* event) { 129 for (View* v = GetEventHandlerForPoint(event->location()); 130 v && v != this && !event->stopped_propagation(); v = v->parent()) { 131 DispatchEventToTarget(v, event); 132 } 133 134 if (event->handled() || event->type() != ui::ET_SCROLL) 135 return; 136 137 // Convert unprocessed scroll events into mouse-wheel events. Note that 138 // wheel events are normally sent to the focused view. However, if the focused 139 // view does not process these wheel events, then dispatch them to the view 140 // under the cursor. 141 ui::MouseWheelEvent wheel(*event); 142 if (OnMouseWheel(wheel)) { 143 event->SetHandled(); 144 } else { 145 View* focused_view = 146 GetFocusManager() ? GetFocusManager()->GetFocusedView() : NULL; 147 View* v = GetEventHandlerForPoint(wheel.location()); 148 if (v != focused_view) { 149 for (; v && v != this; v = v->parent()) { 150 DispatchEventToTarget(v, &wheel); 151 if (wheel.handled()) { 152 event->SetHandled(); 153 break; 154 } 155 } 156 } 157 } 158} 159 160void RootView::DispatchTouchEvent(ui::TouchEvent* event) { 161 // TODO: this looks all wrong. On a TOUCH_PRESSED we should figure out the 162 // view and target that view with all touches with the same id until the 163 // release (or keep it if captured). 164 165 // If touch_pressed_handler_ is non null, we are currently processing 166 // a touch down on the screen situation. In that case we send the 167 // event to touch_pressed_handler_ 168 169 if (touch_pressed_handler_) { 170 ui::TouchEvent touch_event(*event, static_cast<View*>(this), 171 touch_pressed_handler_); 172 DispatchEventToTarget(touch_pressed_handler_, &touch_event); 173 if (touch_event.handled()) 174 event->SetHandled(); 175 if (touch_event.stopped_propagation()) 176 event->StopPropagation(); 177 return; 178 } 179 180 // Walk up the tree until we find a view that wants the touch event. 181 for (touch_pressed_handler_ = GetEventHandlerForPoint(event->location()); 182 touch_pressed_handler_ && (touch_pressed_handler_ != this); 183 touch_pressed_handler_ = touch_pressed_handler_->parent()) { 184 if (!touch_pressed_handler_->enabled()) { 185 // Disabled views eat events but are treated as not handled. 186 break; 187 } 188 189 // See if this view wants to handle the touch 190 ui::TouchEvent touch_event(*event, static_cast<View*>(this), 191 touch_pressed_handler_); 192 DispatchEventToTarget(touch_pressed_handler_, &touch_event); 193 if (touch_event.handled()) 194 event->SetHandled(); 195 if (touch_event.stopped_propagation()) 196 event->StopPropagation(); 197 198 // The view could have removed itself from the tree when handling 199 // OnTouchEvent(). So handle as per OnMousePressed. NB: we 200 // assume that the RootView itself cannot be so removed. 201 if (!touch_pressed_handler_) 202 break; 203 204 // The touch event wasn't processed. Go up the view hierarchy and dispatch 205 // the touch event. 206 if (!event->handled()) 207 continue; 208 209 // If a View consumed the event, that means future touch-events should go to 210 // that View. If the event wasn't consumed, then reset the handler. 211 if (!event->stopped_propagation()) 212 touch_pressed_handler_ = NULL; 213 214 return; 215 } 216 217 // Reset touch_pressed_handler_ to indicate that no processing is occurring. 218 touch_pressed_handler_ = NULL; 219 220 return; 221} 222 223void RootView::DispatchGestureEvent(ui::GestureEvent* event) { 224 if (gesture_handler_) { 225 // |gesture_handler_| (or |scroll_gesture_handler_|) can be deleted during 226 // processing. 227 View* handler = scroll_gesture_handler_ && 228 (event->IsScrollGestureEvent() || event->IsFlingScrollEvent()) ? 229 scroll_gesture_handler_ : gesture_handler_; 230 ui::GestureEvent handler_event(*event, static_cast<View*>(this), handler); 231 DispatchEventToTarget(handler, &handler_event); 232 233 if (event->type() == ui::ET_GESTURE_END && 234 event->details().touch_points() <= 1) { 235 // In case a drag was in progress, reset all the handlers. Otherwise, just 236 // reset the gesture handler. 237 if (gesture_handler_ == mouse_pressed_handler_) 238 SetMouseHandler(NULL); 239 else 240 gesture_handler_ = NULL; 241 } 242 243 if (scroll_gesture_handler_ && 244 (event->type() == ui::ET_GESTURE_SCROLL_END || 245 event->type() == ui::ET_SCROLL_FLING_START)) { 246 scroll_gesture_handler_ = NULL; 247 } 248 249 if (handler_event.stopped_propagation()) { 250 event->StopPropagation(); 251 return; 252 } else if (handler_event.handled()) { 253 event->SetHandled(); 254 return; 255 } 256 257 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN && 258 !scroll_gesture_handler_) { 259 // Some view started processing gesture events, however it does not 260 // process scroll-gesture events. In such case, we allow the event to 261 // bubble up, and install a different scroll-gesture handler different 262 // from the default gesture handler. 263 for (scroll_gesture_handler_ = gesture_handler_->parent(); 264 scroll_gesture_handler_ && scroll_gesture_handler_ != this; 265 scroll_gesture_handler_ = scroll_gesture_handler_->parent()) { 266 ui::GestureEvent gesture_event(*event, static_cast<View*>(this), 267 scroll_gesture_handler_); 268 DispatchEventToTarget(scroll_gesture_handler_, &gesture_event); 269 if (gesture_event.stopped_propagation()) { 270 event->StopPropagation(); 271 return; 272 } else if (gesture_event.handled()) { 273 event->SetHandled(); 274 return; 275 } 276 } 277 scroll_gesture_handler_ = NULL; 278 } 279 280 return; 281 } 282 283 // If there was no handler for a SCROLL_BEGIN event, then subsequent scroll 284 // events are not dispatched to any views. 285 switch (event->type()) { 286 case ui::ET_GESTURE_SCROLL_UPDATE: 287 case ui::ET_GESTURE_SCROLL_END: 288 case ui::ET_SCROLL_FLING_START: 289 return; 290 default: 291 break; 292 } 293 294 // Walk up the tree until we find a view that wants the gesture event. 295 for (gesture_handler_ = GetEventHandlerForPoint(event->location()); 296 gesture_handler_ && (gesture_handler_ != this); 297 gesture_handler_ = gesture_handler_->parent()) { 298 if (!gesture_handler_->enabled()) { 299 // Disabled views eat events but are treated as not handled. 300 return; 301 } 302 303 // See if this view wants to handle the Gesture. 304 ui::GestureEvent gesture_event(*event, static_cast<View*>(this), 305 gesture_handler_); 306 DispatchEventToTarget(gesture_handler_, &gesture_event); 307 308 // The view could have removed itself from the tree when handling 309 // OnGestureEvent(). So handle as per OnMousePressed. NB: we 310 // assume that the RootView itself cannot be so removed. 311 if (!gesture_handler_) 312 return; 313 314 if (gesture_event.handled()) { 315 if (gesture_event.type() == ui::ET_GESTURE_SCROLL_BEGIN) 316 scroll_gesture_handler_ = gesture_handler_; 317 if (gesture_event.stopped_propagation()) 318 event->StopPropagation(); 319 else 320 event->SetHandled(); 321 return; 322 } 323 324 // The gesture event wasn't processed. Go up the view hierarchy and 325 // dispatch the gesture event. 326 } 327 328 gesture_handler_ = NULL; 329} 330 331// Focus ----------------------------------------------------------------------- 332 333void RootView::SetFocusTraversableParent(FocusTraversable* focus_traversable) { 334 DCHECK(focus_traversable != this); 335 focus_traversable_parent_ = focus_traversable; 336} 337 338void RootView::SetFocusTraversableParentView(View* view) { 339 focus_traversable_parent_view_ = view; 340} 341 342// System events --------------------------------------------------------------- 343 344void RootView::ThemeChanged() { 345 View::PropagateThemeChanged(); 346} 347 348void RootView::LocaleChanged() { 349 View::PropagateLocaleChanged(); 350} 351 352//////////////////////////////////////////////////////////////////////////////// 353// RootView, FocusTraversable implementation: 354 355FocusSearch* RootView::GetFocusSearch() { 356 return &focus_search_; 357} 358 359FocusTraversable* RootView::GetFocusTraversableParent() { 360 return focus_traversable_parent_; 361} 362 363View* RootView::GetFocusTraversableParentView() { 364 return focus_traversable_parent_view_; 365} 366 367//////////////////////////////////////////////////////////////////////////////// 368// RootView, View overrides: 369 370const Widget* RootView::GetWidget() const { 371 return widget_; 372} 373 374Widget* RootView::GetWidget() { 375 return const_cast<Widget*>(const_cast<const RootView*>(this)->GetWidget()); 376} 377 378bool RootView::IsDrawn() const { 379 return visible(); 380} 381 382std::string RootView::GetClassName() const { 383 return kViewClassName; 384} 385 386void RootView::SchedulePaintInRect(const gfx::Rect& rect) { 387 if (layer()) { 388 layer()->SchedulePaint(rect); 389 } else { 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); 394 } 395} 396 397bool RootView::OnMousePressed(const ui::MouseEvent& event) { 398 UpdateCursor(event); 399 SetMouseLocationAndFlags(event); 400 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_); 407 drag_info_.Reset(); 408 DispatchEventToTarget(mouse_pressed_handler_, &mouse_pressed_event); 409 return true; 410 } 411 DCHECK(!explicit_mouse_handler_); 412 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; 423 break; 424 } 425 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_); 429 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); 434 435 drag_info_.Reset(); 436 DispatchEventToTarget(mouse_pressed_handler_, &mouse_pressed_event); 437 438 // The view could have removed itself from the tree when handling 439 // OnMousePressed(). In this case, the removal notification will have 440 // reset mouse_pressed_handler_ to NULL out from under us. Detect this 441 // case and stop. (See comments in view.h.) 442 // 443 // NOTE: Don't return true here, because we don't want the frame to 444 // forward future events to us when there's no handler. 445 if (!mouse_pressed_handler_) 446 break; 447 448 // If the view handled the event, leave mouse_pressed_handler_ set and 449 // return true, which will cause subsequent drag/release events to get 450 // forwarded to that view. 451 if (mouse_pressed_event.handled()) { 452 last_click_handler_ = mouse_pressed_handler_; 453 DVLOG(1) << "OnMousePressed handled by " 454 << mouse_pressed_handler_->GetClassName(); 455 return true; 456 } 457 } 458 459 // Reset mouse_pressed_handler_ to indicate that no processing is occurring. 460 mouse_pressed_handler_ = NULL; 461 462 // In the event that a double-click is not handled after traversing the 463 // entire hierarchy (even as a single-click when sent to a different view), 464 // it must be marked as handled to avoid anything happening from default 465 // processing if it the first click-part was handled by us. 466 if (last_click_handler_ && (event.flags() & ui::EF_IS_DOUBLE_CLICK)) 467 hit_disabled_view = true; 468 469 last_click_handler_ = NULL; 470 return hit_disabled_view; 471} 472 473bool RootView::OnMouseDragged(const ui::MouseEvent& event) { 474 if (mouse_pressed_handler_) { 475 SetMouseLocationAndFlags(event); 476 477 ui::MouseEvent mouse_event(event, static_cast<View*>(this), 478 mouse_pressed_handler_); 479 DispatchEventToTarget(mouse_pressed_handler_, &mouse_event); 480 } 481 return false; 482} 483 484void RootView::OnMouseReleased(const ui::MouseEvent& event) { 485 UpdateCursor(event); 486 487 if (mouse_pressed_handler_) { 488 ui::MouseEvent mouse_released(event, static_cast<View*>(this), 489 mouse_pressed_handler_); 490 // We allow the view to delete us from the event dispatch callback. As such, 491 // configure state such that we're done first, then call View. 492 View* mouse_pressed_handler = mouse_pressed_handler_; 493 SetMouseHandler(NULL); 494 DispatchEventToTarget(mouse_pressed_handler, &mouse_released); 495 // WARNING: we may have been deleted. 496 } 497} 498 499void RootView::OnMouseCaptureLost() { 500 // TODO: this likely needs to reset touch handler too. 501 502 if (mouse_pressed_handler_ || gesture_handler_) { 503 // Synthesize a release event for UpdateCursor. 504 if (mouse_pressed_handler_) { 505 gfx::Point last_point(last_mouse_event_x_, last_mouse_event_y_); 506 ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, 507 last_point, last_point, 508 last_mouse_event_flags_); 509 UpdateCursor(release_event); 510 } 511 // We allow the view to delete us from OnMouseCaptureLost. As such, 512 // configure state such that we're done first, then call View. 513 View* mouse_pressed_handler = mouse_pressed_handler_; 514 View* gesture_handler = gesture_handler_; 515 SetMouseHandler(NULL); 516 if (mouse_pressed_handler) 517 mouse_pressed_handler->OnMouseCaptureLost(); 518 else 519 gesture_handler->OnMouseCaptureLost(); 520 // WARNING: we may have been deleted. 521 } 522} 523 524void RootView::OnMouseMoved(const ui::MouseEvent& event) { 525 View* v = GetEventHandlerForPoint(event.location()); 526 // Find the first enabled view, or the existing move handler, whichever comes 527 // first. The check for the existing handler is because if a view becomes 528 // disabled while handling moves, it's wrong to suddenly send ET_MOUSE_EXITED 529 // and ET_MOUSE_ENTERED events, because the mouse hasn't actually exited yet. 530 while (v && !v->enabled() && (v != mouse_move_handler_)) 531 v = v->parent(); 532 if (v && v != this) { 533 if (v != mouse_move_handler_) { 534 if (mouse_move_handler_ != NULL && 535 (!mouse_move_handler_->notify_enter_exit_on_child() || 536 !mouse_move_handler_->Contains(v))) { 537 MouseEnterExitEvent exit(event, ui::ET_MOUSE_EXITED); 538 DispatchEventToTarget(mouse_move_handler_, &exit); 539 NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED, 540 mouse_move_handler_, v); 541 } 542 View* old_handler = mouse_move_handler_; 543 mouse_move_handler_ = v; 544 if (!mouse_move_handler_->notify_enter_exit_on_child() || 545 !mouse_move_handler_->Contains(old_handler)) { 546 MouseEnterExitEvent entered(event, ui::ET_MOUSE_ENTERED); 547 entered.ConvertLocationToTarget(static_cast<View*>(this), 548 mouse_move_handler_); 549 DispatchEventToTarget(mouse_move_handler_, &entered); 550 NotifyEnterExitOfDescendant(entered, ui::ET_MOUSE_ENTERED, v, 551 old_handler); 552 } 553 } 554 ui::MouseEvent moved_event(event, static_cast<View*>(this), 555 mouse_move_handler_); 556 mouse_move_handler_->OnMouseMoved(moved_event); 557 if (!(moved_event.flags() & ui::EF_IS_NON_CLIENT)) 558 widget_->SetCursor(mouse_move_handler_->GetCursor(moved_event)); 559 } else if (mouse_move_handler_ != NULL) { 560 MouseEnterExitEvent exited(event, ui::ET_MOUSE_EXITED); 561 DispatchEventToTarget(mouse_move_handler_, &exited); 562 NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED, 563 mouse_move_handler_, v); 564 // On Aura the non-client area extends slightly outside the root view for 565 // some windows. Let the non-client cursor handling code set the cursor 566 // as we do above. 567 if (!(event.flags() & ui::EF_IS_NON_CLIENT)) 568 widget_->SetCursor(gfx::kNullCursor); 569 mouse_move_handler_ = NULL; 570 } 571} 572 573void RootView::OnMouseExited(const ui::MouseEvent& event) { 574 if (mouse_move_handler_ != NULL) { 575 MouseEnterExitEvent exited(event, ui::ET_MOUSE_EXITED); 576 DispatchEventToTarget(mouse_move_handler_, &exited); 577 NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED, 578 mouse_move_handler_, NULL); 579 mouse_move_handler_ = NULL; 580 } 581} 582 583bool RootView::OnMouseWheel(const ui::MouseWheelEvent& event) { 584 for (View* v = GetFocusManager() ? GetFocusManager()->GetFocusedView() : NULL; 585 v && v != this && !event.handled(); v = v->parent()) 586 DispatchEventToTarget(v, const_cast<ui::MouseWheelEvent*>(&event)); 587 return event.handled(); 588} 589 590void RootView::SetMouseHandler(View* new_mh) { 591 // If we're clearing the mouse handler, clear explicit_mouse_handler_ as well. 592 explicit_mouse_handler_ = (new_mh != NULL); 593 mouse_pressed_handler_ = new_mh; 594 gesture_handler_ = new_mh; 595 scroll_gesture_handler_ = new_mh; 596 drag_info_.Reset(); 597} 598 599void RootView::GetAccessibleState(ui::AccessibleViewState* state) { 600 state->name = widget_->widget_delegate()->GetAccessibleWindowTitle(); 601 state->role = widget_->widget_delegate()->GetAccessibleWindowRole(); 602} 603 604void RootView::ReorderChildLayers(ui::Layer* parent_layer) { 605 View::ReorderChildLayers(parent_layer); 606} 607 608//////////////////////////////////////////////////////////////////////////////// 609// RootView, protected: 610 611void RootView::ViewHierarchyChanged(bool is_add, View* parent, View* child) { 612 widget_->ViewHierarchyChanged(is_add, parent, child); 613 614 if (!is_add) { 615 if (!explicit_mouse_handler_ && mouse_pressed_handler_ == child) 616 mouse_pressed_handler_ = NULL; 617 if (mouse_move_handler_ == child) 618 mouse_move_handler_ = NULL; 619 if (touch_pressed_handler_ == child) 620 touch_pressed_handler_ = NULL; 621 if (gesture_handler_ == child) 622 gesture_handler_ = NULL; 623 if (scroll_gesture_handler_ == child) 624 scroll_gesture_handler_ = NULL; 625 if (event_dispatch_target_ == child) 626 event_dispatch_target_ = NULL; 627 } 628} 629 630void RootView::OnPaint(gfx::Canvas* canvas) { 631 if (!layer() || !layer()->fills_bounds_opaquely()) 632 canvas->DrawColor(SK_ColorBLACK, SkXfermode::kClear_Mode); 633 634 // TODO (pkotwicz): Remove this once we switch over to Aura desktop. 635 // This is needed so that we can set the background behind the RWHV when the 636 // RWHV is not visible. Not needed once there is a view between the RootView 637 // and RWHV. 638 View::OnPaint(canvas); 639} 640 641gfx::Vector2d RootView::CalculateOffsetToAncestorWithLayer( 642 ui::Layer** layer_parent) { 643 gfx::Vector2d offset(View::CalculateOffsetToAncestorWithLayer(layer_parent)); 644 if (!layer()) 645 offset += widget_->CalculateOffsetToAncestorWithLayer(layer_parent); 646 return offset; 647} 648 649View::DragInfo* RootView::GetDragInfo() { 650 return &drag_info_; 651} 652 653//////////////////////////////////////////////////////////////////////////////// 654// RootView, private: 655 656// Input ----------------------------------------------------------------------- 657 658void RootView::UpdateCursor(const ui::MouseEvent& event) { 659 if (!(event.flags() & ui::EF_IS_NON_CLIENT)) { 660 View* v = GetEventHandlerForPoint(event.location()); 661 ui::MouseEvent me(event, static_cast<View*>(this), v); 662 widget_->SetCursor(v->GetCursor(me)); 663 } 664} 665 666void RootView::SetMouseLocationAndFlags(const ui::MouseEvent& event) { 667 last_mouse_event_flags_ = event.flags(); 668 last_mouse_event_x_ = event.x(); 669 last_mouse_event_y_ = event.y(); 670} 671 672void RootView::DispatchEventToTarget(View* target, ui::Event* event) { 673 View* old_target = event_dispatch_target_; 674 event_dispatch_target_ = target; 675 if (DispatchEvent(target, event)) 676 event_dispatch_target_ = old_target; 677} 678 679void RootView::NotifyEnterExitOfDescendant(const ui::MouseEvent& event, 680 ui::EventType type, 681 View* view, 682 View* sibling) { 683 for (View* p = view->parent(); p; p = p->parent()) { 684 if (!p->notify_enter_exit_on_child()) 685 continue; 686 if (sibling && p->Contains(sibling)) 687 break; 688 // It is necessary to recreate the notify-event for each dispatch, since one 689 // of the callbacks can mark the event as handled, and that would cause 690 // incorrect event dispatch. 691 MouseEnterExitEvent notify_event(event, type); 692 DispatchEventToTarget(p, ¬ify_event); 693 } 694} 695 696bool RootView::CanDispatchToTarget(ui::EventTarget* target) { 697 return event_dispatch_target_ == target; 698} 699 700} // namespace internal 701} // namespace views 702