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/aura/root_window.h" 6 7 #include <vector> 8 9 #include "base/bind.h" 10 #include "base/command_line.h" 11 #include "base/debug/trace_event.h" 12 #include "base/logging.h" 13 #include "base/message_loop/message_loop.h" 14 #include "ui/aura/client/capture_client.h" 15 #include "ui/aura/client/cursor_client.h" 16 #include "ui/aura/client/event_client.h" 17 #include "ui/aura/client/focus_client.h" 18 #include "ui/aura/client/screen_position_client.h" 19 #include "ui/aura/env.h" 20 #include "ui/aura/root_window_observer.h" 21 #include "ui/aura/root_window_transformer.h" 22 #include "ui/aura/window.h" 23 #include "ui/aura/window_delegate.h" 24 #include "ui/aura/window_targeter.h" 25 #include "ui/aura/window_tracker.h" 26 #include "ui/aura/window_tree_host.h" 27 #include "ui/base/hit_test.h" 28 #include "ui/base/view_prop.h" 29 #include "ui/compositor/dip_util.h" 30 #include "ui/compositor/layer.h" 31 #include "ui/compositor/layer_animator.h" 32 #include "ui/events/event.h" 33 #include "ui/events/gestures/gesture_recognizer.h" 34 #include "ui/events/gestures/gesture_types.h" 35 #include "ui/gfx/display.h" 36 #include "ui/gfx/point3_f.h" 37 #include "ui/gfx/point_conversions.h" 38 #include "ui/gfx/screen.h" 39 #include "ui/gfx/size_conversions.h" 40 41 using std::vector; 42 43 typedef ui::EventDispatchDetails DispatchDetails; 44 45 namespace aura { 46 47 namespace { 48 49 const char kRootWindowForAcceleratedWidget[] = 50 "__AURA_ROOT_WINDOW_ACCELERATED_WIDGET__"; 51 52 // Returns true if |target| has a non-client (frame) component at |location|, 53 // in window coordinates. 54 bool IsNonClientLocation(Window* target, const gfx::Point& location) { 55 if (!target->delegate()) 56 return false; 57 int hit_test_code = target->delegate()->GetNonClientComponent(location); 58 return hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE; 59 } 60 61 float GetDeviceScaleFactorFromDisplay(Window* window) { 62 gfx::Display display = gfx::Screen::GetScreenFor(window)-> 63 GetDisplayNearestWindow(window); 64 DCHECK(display.is_valid()); 65 return display.device_scale_factor(); 66 } 67 68 Window* ConsumerToWindow(ui::GestureConsumer* consumer) { 69 return consumer ? static_cast<Window*>(consumer) : NULL; 70 } 71 72 void SetLastMouseLocation(const Window* root_window, 73 const gfx::Point& location_in_root) { 74 client::ScreenPositionClient* client = 75 client::GetScreenPositionClient(root_window); 76 if (client) { 77 gfx::Point location_in_screen = location_in_root; 78 client->ConvertPointToScreen(root_window, &location_in_screen); 79 Env::GetInstance()->set_last_mouse_location(location_in_screen); 80 } else { 81 Env::GetInstance()->set_last_mouse_location(location_in_root); 82 } 83 } 84 85 RootWindowHost* CreateHost(RootWindow* root_window, 86 const RootWindow::CreateParams& params) { 87 RootWindowHost* host = params.host ? 88 params.host : RootWindowHost::Create(params.initial_bounds); 89 host->set_delegate(root_window); 90 return host; 91 } 92 93 bool IsUsingEventProcessorForDispatch(const ui::Event& event) { 94 return event.IsKeyEvent() || 95 event.IsScrollEvent(); 96 } 97 98 class SimpleRootWindowTransformer : public RootWindowTransformer { 99 public: 100 SimpleRootWindowTransformer(const Window* root_window, 101 const gfx::Transform& transform) 102 : root_window_(root_window), 103 transform_(transform) { 104 } 105 106 // RootWindowTransformer overrides: 107 virtual gfx::Transform GetTransform() const OVERRIDE { 108 return transform_; 109 } 110 111 virtual gfx::Transform GetInverseTransform() const OVERRIDE { 112 gfx::Transform invert; 113 if (!transform_.GetInverse(&invert)) 114 return transform_; 115 return invert; 116 } 117 118 virtual gfx::Rect GetRootWindowBounds( 119 const gfx::Size& host_size) const OVERRIDE { 120 gfx::Rect bounds(host_size); 121 gfx::RectF new_bounds(ui::ConvertRectToDIP(root_window_->layer(), bounds)); 122 transform_.TransformRect(&new_bounds); 123 return gfx::Rect(gfx::ToFlooredSize(new_bounds.size())); 124 } 125 126 virtual gfx::Insets GetHostInsets() const OVERRIDE { 127 return gfx::Insets(); 128 } 129 130 private: 131 virtual ~SimpleRootWindowTransformer() {} 132 133 const Window* root_window_; 134 const gfx::Transform transform_; 135 136 DISALLOW_COPY_AND_ASSIGN(SimpleRootWindowTransformer); 137 }; 138 139 } // namespace 140 141 RootWindow::CreateParams::CreateParams(const gfx::Rect& a_initial_bounds) 142 : initial_bounds(a_initial_bounds), 143 host(NULL) { 144 } 145 146 //////////////////////////////////////////////////////////////////////////////// 147 // RootWindow, public: 148 149 RootWindow::RootWindow(const CreateParams& params) 150 : window_(new Window(NULL)), 151 host_(CreateHost(this, params)), 152 touch_ids_down_(0), 153 last_cursor_(ui::kCursorNull), 154 mouse_pressed_handler_(NULL), 155 mouse_moved_handler_(NULL), 156 event_dispatch_target_(NULL), 157 old_dispatch_target_(NULL), 158 synthesize_mouse_move_(false), 159 move_hold_count_(0), 160 dispatching_held_event_(false), 161 repost_event_factory_(this), 162 held_event_factory_(this) { 163 window()->set_dispatcher(this); 164 window()->SetName("RootWindow"); 165 window()->set_event_targeter( 166 scoped_ptr<ui::EventTargeter>(new WindowTargeter())); 167 168 compositor_.reset(new ui::Compositor(host_->GetAcceleratedWidget())); 169 DCHECK(compositor_.get()); 170 171 prop_.reset(new ui::ViewProp(host_->GetAcceleratedWidget(), 172 kRootWindowForAcceleratedWidget, 173 this)); 174 ui::GestureRecognizer::Get()->AddGestureEventHelper(this); 175 } 176 177 RootWindow::~RootWindow() { 178 TRACE_EVENT0("shutdown", "RootWindow::Destructor"); 179 180 ui::GestureRecognizer::Get()->RemoveGestureEventHelper(this); 181 182 // Make sure to destroy the compositor before terminating so that state is 183 // cleared and we don't hit asserts. 184 compositor_.reset(); 185 186 // An observer may have been added by an animation on the RootWindow. 187 window()->layer()->GetAnimator()->RemoveObserver(this); 188 189 // Destroy child windows while we're still valid. This is also done by 190 // ~Window, but by that time any calls to virtual methods overriden here (such 191 // as GetRootWindow()) result in Window's implementation. By destroying here 192 // we ensure GetRootWindow() still returns this. 193 window()->RemoveOrDestroyChildren(); 194 195 // Destroying/removing child windows may try to access |host_| (eg. 196 // GetAcceleratedWidget()) 197 host_.reset(NULL); 198 199 window()->set_dispatcher(NULL); 200 } 201 202 // static 203 RootWindow* RootWindow::GetForAcceleratedWidget( 204 gfx::AcceleratedWidget widget) { 205 return reinterpret_cast<RootWindow*>( 206 ui::ViewProp::GetValue(widget, kRootWindowForAcceleratedWidget)); 207 } 208 209 void RootWindow::Init() { 210 compositor()->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()), 211 host_->GetBounds().size()); 212 window()->Init(ui::LAYER_NOT_DRAWN); 213 compositor()->SetRootLayer(window()->layer()); 214 transformer_.reset( 215 new SimpleRootWindowTransformer(window(), gfx::Transform())); 216 UpdateRootWindowSize(host_->GetBounds().size()); 217 Env::GetInstance()->NotifyRootWindowInitialized(this); 218 window()->Show(); 219 } 220 221 void RootWindow::PrepareForShutdown() { 222 host_->PrepareForShutdown(); 223 // discard synthesize event request as well. 224 synthesize_mouse_move_ = false; 225 } 226 227 void RootWindow::RepostEvent(const ui::LocatedEvent& event) { 228 DCHECK(event.type() == ui::ET_MOUSE_PRESSED || 229 event.type() == ui::ET_GESTURE_TAP_DOWN); 230 // We allow for only one outstanding repostable event. This is used 231 // in exiting context menus. A dropped repost request is allowed. 232 if (event.type() == ui::ET_MOUSE_PRESSED) { 233 held_repostable_event_.reset( 234 new ui::MouseEvent( 235 static_cast<const ui::MouseEvent&>(event), 236 static_cast<aura::Window*>(event.target()), 237 window())); 238 base::MessageLoop::current()->PostNonNestableTask( 239 FROM_HERE, 240 base::Bind(base::IgnoreResult(&RootWindow::DispatchHeldEvents), 241 repost_event_factory_.GetWeakPtr())); 242 } else { 243 DCHECK(event.type() == ui::ET_GESTURE_TAP_DOWN); 244 held_repostable_event_.reset(); 245 // TODO(rbyers): Reposing of gestures is tricky to get 246 // right, so it's not yet supported. crbug.com/170987. 247 } 248 } 249 250 RootWindowHostDelegate* RootWindow::AsRootWindowHostDelegate() { 251 return this; 252 } 253 254 void RootWindow::SetHostSize(const gfx::Size& size_in_pixel) { 255 DispatchDetails details = DispatchHeldEvents(); 256 if (details.dispatcher_destroyed) 257 return; 258 gfx::Rect bounds = host_->GetBounds(); 259 bounds.set_size(size_in_pixel); 260 host_->SetBounds(bounds); 261 262 // Requery the location to constrain it within the new root window size. 263 gfx::Point point; 264 if (host_->QueryMouseLocation(&point)) { 265 SetLastMouseLocation(window(), 266 ui::ConvertPointToDIP(window()->layer(), point)); 267 } 268 269 synthesize_mouse_move_ = false; 270 } 271 272 void RootWindow::SetHostBounds(const gfx::Rect& bounds_in_pixel) { 273 DCHECK(!bounds_in_pixel.IsEmpty()); 274 DispatchDetails details = DispatchHeldEvents(); 275 if (details.dispatcher_destroyed) 276 return; 277 host_->SetBounds(bounds_in_pixel); 278 synthesize_mouse_move_ = false; 279 } 280 281 void RootWindow::SetCursor(gfx::NativeCursor cursor) { 282 last_cursor_ = cursor; 283 // A lot of code seems to depend on NULL cursors actually showing an arrow, 284 // so just pass everything along to the host. 285 host_->SetCursor(cursor); 286 } 287 288 void RootWindow::OnCursorVisibilityChanged(bool show) { 289 // Clear any existing mouse hover effects when the cursor becomes invisible. 290 // Note we do not need to dispatch a mouse enter when the cursor becomes 291 // visible because that can only happen in response to a mouse event, which 292 // will trigger its own mouse enter. 293 if (!show) 294 DispatchMouseExitAtPoint(GetLastMouseLocationInRoot()); 295 296 host_->OnCursorVisibilityChanged(show); 297 } 298 299 void RootWindow::OnMouseEventsEnableStateChanged(bool enabled) { 300 // Send entered / exited so that visual state can be updated to match 301 // mouse events state. 302 PostMouseMoveEventAfterWindowChange(); 303 // TODO(mazda): Add code to disable mouse events when |enabled| == false. 304 } 305 306 void RootWindow::MoveCursorTo(const gfx::Point& location_in_dip) { 307 gfx::Point host_location(location_in_dip); 308 ConvertPointToHost(&host_location); 309 MoveCursorToInternal(location_in_dip, host_location); 310 } 311 312 void RootWindow::MoveCursorToHostLocation(const gfx::Point& host_location) { 313 gfx::Point root_location(host_location); 314 ConvertPointFromHost(&root_location); 315 MoveCursorToInternal(root_location, host_location); 316 } 317 318 void RootWindow::ScheduleRedrawRect(const gfx::Rect& damage_rect) { 319 compositor_->ScheduleRedrawRect(damage_rect); 320 } 321 322 Window* RootWindow::GetGestureTarget(ui::GestureEvent* event) { 323 Window* target = NULL; 324 if (!event->IsEndingEvent()) { 325 // The window that received the start event (e.g. scroll begin) needs to 326 // receive the end event (e.g. scroll end). 327 target = client::GetCaptureWindow(window()); 328 } 329 if (!target) { 330 target = ConsumerToWindow( 331 ui::GestureRecognizer::Get()->GetTargetForGestureEvent(*event)); 332 } 333 334 return target; 335 } 336 337 void RootWindow::DispatchGestureEvent(ui::GestureEvent* event) { 338 DispatchDetails details = DispatchHeldEvents(); 339 if (details.dispatcher_destroyed) 340 return; 341 342 Window* target = GetGestureTarget(event); 343 if (target) { 344 event->ConvertLocationToTarget(window(), target); 345 DispatchDetails details = DispatchEvent(target, event); 346 if (details.dispatcher_destroyed) 347 return; 348 } 349 } 350 351 void RootWindow::OnWindowDestroying(Window* window) { 352 DispatchMouseExitToHidingWindow(window); 353 OnWindowHidden(window, WINDOW_DESTROYED); 354 355 if (window->IsVisible() && 356 window->ContainsPointInRoot(GetLastMouseLocationInRoot())) { 357 PostMouseMoveEventAfterWindowChange(); 358 } 359 } 360 361 void RootWindow::OnWindowBoundsChanged(Window* window, 362 bool contained_mouse_point) { 363 if (contained_mouse_point || 364 (window->IsVisible() && 365 window->ContainsPointInRoot(GetLastMouseLocationInRoot()))) { 366 PostMouseMoveEventAfterWindowChange(); 367 } 368 } 369 370 void RootWindow::DispatchMouseExitToHidingWindow(Window* window) { 371 // The mouse capture is intentionally ignored. Think that a mouse enters 372 // to a window, the window sets the capture, the mouse exits the window, 373 // and then it releases the capture. In that case OnMouseExited won't 374 // be called. So it is natural not to emit OnMouseExited even though 375 // |window| is the capture window. 376 gfx::Point last_mouse_location = GetLastMouseLocationInRoot(); 377 if (window->Contains(mouse_moved_handler_) && 378 window->ContainsPointInRoot(last_mouse_location)) 379 DispatchMouseExitAtPoint(last_mouse_location); 380 } 381 382 void RootWindow::DispatchMouseExitAtPoint(const gfx::Point& point) { 383 ui::MouseEvent event(ui::ET_MOUSE_EXITED, point, point, ui::EF_NONE); 384 DispatchDetails details = 385 DispatchMouseEnterOrExit(event, ui::ET_MOUSE_EXITED); 386 if (details.dispatcher_destroyed) 387 return; 388 } 389 390 void RootWindow::OnWindowVisibilityChanged(Window* window, bool is_visible) { 391 if (!is_visible) 392 OnWindowHidden(window, WINDOW_HIDDEN); 393 394 if (window->ContainsPointInRoot(GetLastMouseLocationInRoot())) 395 PostMouseMoveEventAfterWindowChange(); 396 } 397 398 void RootWindow::OnWindowTransformed(Window* window, bool contained_mouse) { 399 if (contained_mouse || 400 (window->IsVisible() && 401 window->ContainsPointInRoot(GetLastMouseLocationInRoot()))) { 402 PostMouseMoveEventAfterWindowChange(); 403 } 404 } 405 406 void RootWindow::OnKeyboardMappingChanged() { 407 FOR_EACH_OBSERVER(RootWindowObserver, observers_, 408 OnKeyboardMappingChanged(this)); 409 } 410 411 void RootWindow::OnRootWindowHostCloseRequested() { 412 FOR_EACH_OBSERVER(RootWindowObserver, observers_, 413 OnRootWindowHostCloseRequested(this)); 414 } 415 416 void RootWindow::AddRootWindowObserver(RootWindowObserver* observer) { 417 observers_.AddObserver(observer); 418 } 419 420 void RootWindow::RemoveRootWindowObserver(RootWindowObserver* observer) { 421 observers_.RemoveObserver(observer); 422 } 423 424 void RootWindow::ConvertPointToHost(gfx::Point* point) const { 425 gfx::Point3F point_3f(*point); 426 GetRootTransform().TransformPoint(&point_3f); 427 *point = gfx::ToFlooredPoint(point_3f.AsPointF()); 428 } 429 430 void RootWindow::ConvertPointFromHost(gfx::Point* point) const { 431 gfx::Point3F point_3f(*point); 432 GetInverseRootTransform().TransformPoint(&point_3f); 433 *point = gfx::ToFlooredPoint(point_3f.AsPointF()); 434 } 435 436 void RootWindow::ProcessedTouchEvent(ui::TouchEvent* event, 437 Window* window, 438 ui::EventResult result) { 439 scoped_ptr<ui::GestureRecognizer::Gestures> gestures; 440 gestures.reset(ui::GestureRecognizer::Get()-> 441 ProcessTouchEventForGesture(*event, result, window)); 442 DispatchDetails details = ProcessGestures(gestures.get()); 443 if (details.dispatcher_destroyed) 444 return; 445 } 446 447 void RootWindow::HoldPointerMoves() { 448 if (!move_hold_count_) 449 held_event_factory_.InvalidateWeakPtrs(); 450 ++move_hold_count_; 451 TRACE_EVENT_ASYNC_BEGIN0("ui", "RootWindow::HoldPointerMoves", this); 452 } 453 454 void RootWindow::ReleasePointerMoves() { 455 --move_hold_count_; 456 DCHECK_GE(move_hold_count_, 0); 457 if (!move_hold_count_ && held_move_event_) { 458 // We don't want to call DispatchHeldEvents directly, because this might be 459 // called from a deep stack while another event, in which case dispatching 460 // another one may not be safe/expected. Instead we post a task, that we 461 // may cancel if HoldPointerMoves is called again before it executes. 462 base::MessageLoop::current()->PostNonNestableTask( 463 FROM_HERE, 464 base::Bind(base::IgnoreResult(&RootWindow::DispatchHeldEvents), 465 held_event_factory_.GetWeakPtr())); 466 } 467 TRACE_EVENT_ASYNC_END0("ui", "RootWindow::HoldPointerMoves", this); 468 } 469 470 gfx::Point RootWindow::GetLastMouseLocationInRoot() const { 471 gfx::Point location = Env::GetInstance()->last_mouse_location(); 472 client::ScreenPositionClient* client = 473 client::GetScreenPositionClient(window()); 474 if (client) 475 client->ConvertPointFromScreen(window(), &location); 476 return location; 477 } 478 479 void RootWindow::SetRootWindowTransformer( 480 scoped_ptr<RootWindowTransformer> transformer) { 481 transformer_ = transformer.Pass(); 482 host_->SetInsets(transformer_->GetHostInsets()); 483 window()->SetTransform(transformer_->GetTransform()); 484 // If the layer is not animating, then we need to update the root window 485 // size immediately. 486 if (!window()->layer()->GetAnimator()->is_animating()) 487 UpdateRootWindowSize(host_->GetBounds().size()); 488 } 489 490 gfx::Transform RootWindow::GetRootTransform() const { 491 float scale = ui::GetDeviceScaleFactor(window()->layer()); 492 gfx::Transform transform; 493 transform.Scale(scale, scale); 494 transform *= transformer_->GetTransform(); 495 return transform; 496 } 497 498 void RootWindow::SetTransform(const gfx::Transform& transform) { 499 scoped_ptr<RootWindowTransformer> transformer( 500 new SimpleRootWindowTransformer(window(), transform)); 501 SetRootWindowTransformer(transformer.Pass()); 502 } 503 504 //////////////////////////////////////////////////////////////////////////////// 505 // RootWindow, private: 506 507 void RootWindow::TransformEventForDeviceScaleFactor(ui::LocatedEvent* event) { 508 event->UpdateForRootTransform(GetInverseRootTransform()); 509 } 510 511 void RootWindow::MoveCursorToInternal(const gfx::Point& root_location, 512 const gfx::Point& host_location) { 513 host_->MoveCursorTo(host_location); 514 SetLastMouseLocation(window(), root_location); 515 client::CursorClient* cursor_client = client::GetCursorClient(window()); 516 if (cursor_client) { 517 const gfx::Display& display = 518 gfx::Screen::GetScreenFor(window())->GetDisplayNearestWindow(window()); 519 cursor_client->SetDisplay(display); 520 } 521 synthesize_mouse_move_ = false; 522 } 523 524 ui::EventDispatchDetails RootWindow::DispatchMouseEnterOrExit( 525 const ui::MouseEvent& event, 526 ui::EventType type) { 527 if (!mouse_moved_handler_ || !mouse_moved_handler_->delegate()) 528 return DispatchDetails(); 529 530 ui::MouseEvent translated_event(event, 531 window(), 532 mouse_moved_handler_, 533 type, 534 event.flags() | ui::EF_IS_SYNTHESIZED); 535 return DispatchEvent(mouse_moved_handler_, &translated_event); 536 } 537 538 ui::EventDispatchDetails RootWindow::ProcessGestures( 539 ui::GestureRecognizer::Gestures* gestures) { 540 DispatchDetails details; 541 if (!gestures || gestures->empty()) 542 return details; 543 544 Window* target = GetGestureTarget(gestures->get().at(0)); 545 for (size_t i = 0; i < gestures->size(); ++i) { 546 ui::GestureEvent* event = gestures->get().at(i); 547 event->ConvertLocationToTarget(window(), target); 548 details = DispatchEvent(target, event); 549 if (details.dispatcher_destroyed || details.target_destroyed) 550 break; 551 } 552 return details; 553 } 554 555 void RootWindow::OnWindowAddedToRootWindow(Window* attached) { 556 if (attached->IsVisible() && 557 attached->ContainsPointInRoot(GetLastMouseLocationInRoot())) { 558 PostMouseMoveEventAfterWindowChange(); 559 } 560 } 561 562 void RootWindow::OnWindowRemovedFromRootWindow(Window* detached, 563 Window* new_root) { 564 DCHECK(aura::client::GetCaptureWindow(window()) != window()); 565 566 DispatchMouseExitToHidingWindow(detached); 567 OnWindowHidden(detached, new_root ? WINDOW_MOVING : WINDOW_HIDDEN); 568 569 if (detached->IsVisible() && 570 detached->ContainsPointInRoot(GetLastMouseLocationInRoot())) { 571 PostMouseMoveEventAfterWindowChange(); 572 } 573 } 574 575 void RootWindow::OnWindowHidden(Window* invisible, WindowHiddenReason reason) { 576 // Do not clear the capture, and the |event_dispatch_target_| if the 577 // window is moving across root windows, because the target itself 578 // is actually still visible and clearing them stops further event 579 // processing, which can cause unexpected behaviors. See 580 // crbug.com/157583 581 if (reason != WINDOW_MOVING) { 582 Window* capture_window = aura::client::GetCaptureWindow(window()); 583 // If the ancestor of the capture window is hidden, 584 // release the capture. 585 if (invisible->Contains(capture_window) && invisible != window()) 586 capture_window->ReleaseCapture(); 587 588 if (invisible->Contains(event_dispatch_target_)) 589 event_dispatch_target_ = NULL; 590 591 if (invisible->Contains(old_dispatch_target_)) 592 old_dispatch_target_ = NULL; 593 } 594 595 // If the ancestor of any event handler windows are invisible, release the 596 // pointer to those windows. 597 if (invisible->Contains(mouse_pressed_handler_)) 598 mouse_pressed_handler_ = NULL; 599 if (invisible->Contains(mouse_moved_handler_)) 600 mouse_moved_handler_ = NULL; 601 602 CleanupGestureState(invisible); 603 } 604 605 void RootWindow::CleanupGestureState(Window* window) { 606 ui::GestureRecognizer::Get()->CancelActiveTouches(window); 607 ui::GestureRecognizer::Get()->CleanupStateForConsumer(window); 608 const Window::Windows& windows = window->children(); 609 for (Window::Windows::const_iterator iter = windows.begin(); 610 iter != windows.end(); 611 ++iter) { 612 CleanupGestureState(*iter); 613 } 614 } 615 616 void RootWindow::UpdateRootWindowSize(const gfx::Size& host_size) { 617 window()->SetBounds(transformer_->GetRootWindowBounds(host_size)); 618 } 619 620 //////////////////////////////////////////////////////////////////////////////// 621 // RootWindow, aura::client::CaptureDelegate implementation: 622 623 void RootWindow::UpdateCapture(Window* old_capture, 624 Window* new_capture) { 625 // |mouse_moved_handler_| may have been set to a Window in a different root 626 // (see below). Clear it here to ensure we don't end up referencing a stale 627 // Window. 628 if (mouse_moved_handler_ && !window()->Contains(mouse_moved_handler_)) 629 mouse_moved_handler_ = NULL; 630 631 if (old_capture && old_capture->GetRootWindow() == window() && 632 old_capture->delegate()) { 633 // Send a capture changed event with bogus location data. 634 ui::MouseEvent event(ui::ET_MOUSE_CAPTURE_CHANGED, gfx::Point(), 635 gfx::Point(), 0); 636 637 DispatchDetails details = DispatchEvent(old_capture, &event); 638 if (details.dispatcher_destroyed) 639 return; 640 641 old_capture->delegate()->OnCaptureLost(); 642 } 643 644 if (new_capture) { 645 // Make all subsequent mouse events go to the capture window. We shouldn't 646 // need to send an event here as OnCaptureLost() should take care of that. 647 if (mouse_moved_handler_ || Env::GetInstance()->IsMouseButtonDown()) 648 mouse_moved_handler_ = new_capture; 649 } else { 650 // Make sure mouse_moved_handler gets updated. 651 DispatchDetails details = SynthesizeMouseMoveEvent(); 652 if (details.dispatcher_destroyed) 653 return; 654 } 655 mouse_pressed_handler_ = NULL; 656 } 657 658 void RootWindow::OnOtherRootGotCapture() { 659 mouse_moved_handler_ = NULL; 660 mouse_pressed_handler_ = NULL; 661 } 662 663 void RootWindow::SetNativeCapture() { 664 host_->SetCapture(); 665 } 666 667 void RootWindow::ReleaseNativeCapture() { 668 host_->ReleaseCapture(); 669 } 670 671 //////////////////////////////////////////////////////////////////////////////// 672 // RootWindow, ui::EventProcessor implementation: 673 ui::EventTarget* RootWindow::GetRootTarget() { 674 return window(); 675 } 676 677 void RootWindow::PrepareEventForDispatch(ui::Event* event) { 678 if (event->IsMouseEvent() || 679 event->IsScrollEvent() || 680 event->IsTouchEvent() || 681 event->IsGestureEvent()) { 682 TransformEventForDeviceScaleFactor(static_cast<ui::LocatedEvent*>(event)); 683 } 684 } 685 686 //////////////////////////////////////////////////////////////////////////////// 687 // RootWindow, ui::EventDispatcherDelegate implementation: 688 689 bool RootWindow::CanDispatchToTarget(ui::EventTarget* target) { 690 return event_dispatch_target_ == target; 691 } 692 693 ui::EventDispatchDetails RootWindow::PreDispatchEvent(ui::EventTarget* target, 694 ui::Event* event) { 695 if (!dispatching_held_event_ && IsUsingEventProcessorForDispatch(*event)) { 696 DispatchDetails details = DispatchHeldEvents(); 697 if (details.dispatcher_destroyed || details.target_destroyed) 698 return details; 699 700 Window* target_window = static_cast<Window*>(target); 701 if (event->IsScrollEvent()) { 702 PreDispatchLocatedEvent(target_window, 703 static_cast<ui::ScrollEvent*>(event)); 704 } 705 } 706 old_dispatch_target_ = event_dispatch_target_; 707 event_dispatch_target_ = static_cast<Window*>(target); 708 return DispatchDetails(); 709 } 710 711 ui::EventDispatchDetails RootWindow::PostDispatchEvent(ui::EventTarget* target, 712 const ui::Event& event) { 713 DispatchDetails details; 714 if (target != event_dispatch_target_) 715 details.target_destroyed = true; 716 event_dispatch_target_ = old_dispatch_target_; 717 old_dispatch_target_ = NULL; 718 #ifndef NDEBUG 719 DCHECK(!event_dispatch_target_ || window()->Contains(event_dispatch_target_)); 720 #endif 721 return details; 722 } 723 724 //////////////////////////////////////////////////////////////////////////////// 725 // RootWindow, ui::GestureEventHelper implementation: 726 727 bool RootWindow::CanDispatchToConsumer(ui::GestureConsumer* consumer) { 728 Window* consumer_window = ConsumerToWindow(consumer);; 729 return (consumer_window && consumer_window->GetRootWindow() == window()); 730 } 731 732 void RootWindow::DispatchPostponedGestureEvent(ui::GestureEvent* event) { 733 DispatchGestureEvent(event); 734 } 735 736 void RootWindow::DispatchCancelTouchEvent(ui::TouchEvent* event) { 737 OnHostTouchEvent(event); 738 } 739 740 //////////////////////////////////////////////////////////////////////////////// 741 // RootWindow, ui::LayerAnimationObserver implementation: 742 743 void RootWindow::OnLayerAnimationEnded( 744 ui::LayerAnimationSequence* animation) { 745 UpdateRootWindowSize(host_->GetBounds().size()); 746 } 747 748 void RootWindow::OnLayerAnimationScheduled( 749 ui::LayerAnimationSequence* animation) { 750 } 751 752 void RootWindow::OnLayerAnimationAborted( 753 ui::LayerAnimationSequence* animation) { 754 } 755 756 //////////////////////////////////////////////////////////////////////////////// 757 // RootWindow, RootWindowHostDelegate implementation: 758 759 bool RootWindow::OnHostKeyEvent(ui::KeyEvent* event) { 760 DispatchDetails details = OnEventFromSource(event); 761 if (details.dispatcher_destroyed) 762 event->SetHandled(); 763 return event->handled(); 764 } 765 766 bool RootWindow::OnHostMouseEvent(ui::MouseEvent* event) { 767 DispatchDetails details = OnHostMouseEventImpl(event); 768 return event->handled() || details.dispatcher_destroyed; 769 } 770 771 bool RootWindow::OnHostScrollEvent(ui::ScrollEvent* event) { 772 DispatchDetails details = OnEventFromSource(event); 773 if (details.dispatcher_destroyed) 774 event->SetHandled(); 775 return event->handled(); 776 } 777 778 bool RootWindow::OnHostTouchEvent(ui::TouchEvent* event) { 779 if ((event->type() == ui::ET_TOUCH_MOVED)) { 780 if (move_hold_count_) { 781 Window* null_window = static_cast<Window*>(NULL); 782 held_move_event_.reset( 783 new ui::TouchEvent(*event, null_window, null_window)); 784 return true; 785 } else { 786 // We may have a held event for a period between the time move_hold_count_ 787 // fell to 0 and the DispatchHeldEvents executes. Since we're going to 788 // dispatch the new event directly below, we can reset the old one. 789 held_move_event_.reset(); 790 } 791 } 792 DispatchDetails details = DispatchHeldEvents(); 793 if (details.dispatcher_destroyed) 794 return false; 795 details = DispatchTouchEventImpl(event); 796 if (details.dispatcher_destroyed) 797 return true; 798 return event->handled(); 799 } 800 801 void RootWindow::OnHostCancelMode() { 802 ui::CancelModeEvent event; 803 Window* focused_window = client::GetFocusClient(window())->GetFocusedWindow(); 804 DispatchDetails details = 805 DispatchEvent(focused_window ? focused_window : window(), &event); 806 if (details.dispatcher_destroyed) 807 return; 808 } 809 810 void RootWindow::OnHostActivated() { 811 Env::GetInstance()->RootWindowActivated(this); 812 } 813 814 void RootWindow::OnHostLostWindowCapture() { 815 Window* capture_window = client::GetCaptureWindow(window()); 816 if (capture_window && capture_window->GetRootWindow() == window()) 817 capture_window->ReleaseCapture(); 818 } 819 820 void RootWindow::OnHostLostMouseGrab() { 821 mouse_pressed_handler_ = NULL; 822 mouse_moved_handler_ = NULL; 823 } 824 825 void RootWindow::OnHostPaint(const gfx::Rect& damage_rect) { 826 compositor_->ScheduleRedrawRect(damage_rect); 827 } 828 829 void RootWindow::OnHostMoved(const gfx::Point& origin) { 830 TRACE_EVENT1("ui", "RootWindow::OnHostMoved", 831 "origin", origin.ToString()); 832 833 FOR_EACH_OBSERVER(RootWindowObserver, observers_, 834 OnRootWindowHostMoved(this, origin)); 835 } 836 837 void RootWindow::OnHostResized(const gfx::Size& size) { 838 TRACE_EVENT1("ui", "RootWindow::OnHostResized", 839 "size", size.ToString()); 840 841 DispatchDetails details = DispatchHeldEvents(); 842 if (details.dispatcher_destroyed) 843 return; 844 // The compositor should have the same size as the native root window host. 845 // Get the latest scale from display because it might have been changed. 846 compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()), size); 847 848 // The layer, and the observers should be notified of the 849 // transformed size of the root window. 850 UpdateRootWindowSize(host_->GetBounds().size()); 851 FOR_EACH_OBSERVER(RootWindowObserver, observers_, 852 OnRootWindowHostResized(this)); 853 } 854 855 float RootWindow::GetDeviceScaleFactor() { 856 return compositor()->device_scale_factor(); 857 } 858 859 RootWindow* RootWindow::AsRootWindow() { 860 return this; 861 } 862 863 const RootWindow* RootWindow::AsRootWindow() const { 864 return this; 865 } 866 867 ui::EventProcessor* RootWindow::GetEventProcessor() { 868 return this; 869 } 870 871 //////////////////////////////////////////////////////////////////////////////// 872 // RootWindow, private: 873 874 ui::EventDispatchDetails RootWindow::OnHostMouseEventImpl( 875 ui::MouseEvent* event) { 876 if (event->type() == ui::ET_MOUSE_DRAGGED || 877 (event->flags() & ui::EF_IS_SYNTHESIZED)) { 878 if (move_hold_count_) { 879 Window* null_window = static_cast<Window*>(NULL); 880 held_move_event_.reset( 881 new ui::MouseEvent(*event, null_window, null_window)); 882 event->SetHandled(); 883 return DispatchDetails(); 884 } else { 885 // We may have a held event for a period between the time move_hold_count_ 886 // fell to 0 and the DispatchHeldEvents executes. Since we're going to 887 // dispatch the new event directly below, we can reset the old one. 888 held_move_event_.reset(); 889 } 890 } 891 DispatchDetails details = DispatchHeldEvents(); 892 if (details.dispatcher_destroyed) 893 return details; 894 return DispatchMouseEventImpl(event); 895 } 896 897 ui::EventDispatchDetails RootWindow::DispatchMouseEventImpl( 898 ui::MouseEvent* event) { 899 TransformEventForDeviceScaleFactor(event); 900 Window* target = mouse_pressed_handler_ ? 901 mouse_pressed_handler_ : client::GetCaptureWindow(window()); 902 if (!target) 903 target = window()->GetEventHandlerForPoint(event->location()); 904 return DispatchMouseEventToTarget(event, target); 905 } 906 907 ui::EventDispatchDetails RootWindow::DispatchMouseEventRepost( 908 ui::MouseEvent* event) { 909 if (event->type() != ui::ET_MOUSE_PRESSED) 910 return DispatchDetails(); 911 Window* target = client::GetCaptureWindow(window()); 912 WindowEventDispatcher* dispatcher = this; 913 if (!target) { 914 target = window()->GetEventHandlerForPoint(event->location()); 915 } else { 916 dispatcher = target->GetDispatcher(); 917 CHECK(dispatcher); // Capture window better be in valid root. 918 } 919 dispatcher->mouse_pressed_handler_ = NULL; 920 return dispatcher->DispatchMouseEventToTarget(event, target); 921 } 922 923 ui::EventDispatchDetails RootWindow::DispatchMouseEventToTarget( 924 ui::MouseEvent* event, 925 Window* target) { 926 client::CursorClient* cursor_client = client::GetCursorClient(window()); 927 if (cursor_client && 928 !cursor_client->IsMouseEventsEnabled() && 929 (event->flags() & ui::EF_IS_SYNTHESIZED)) 930 return DispatchDetails(); 931 932 static const int kMouseButtonFlagMask = 933 ui::EF_LEFT_MOUSE_BUTTON | 934 ui::EF_MIDDLE_MOUSE_BUTTON | 935 ui::EF_RIGHT_MOUSE_BUTTON; 936 // WARNING: because of nested message loops |this| may be deleted after 937 // dispatching any event. Do not use AutoReset or the like here. 938 SetLastMouseLocation(window(), event->location()); 939 synthesize_mouse_move_ = false; 940 switch (event->type()) { 941 case ui::ET_MOUSE_EXITED: 942 if (!target) { 943 DispatchDetails details = 944 DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED); 945 if (details.dispatcher_destroyed) 946 return details; 947 mouse_moved_handler_ = NULL; 948 } 949 break; 950 case ui::ET_MOUSE_MOVED: 951 // Send an exit to the current |mouse_moved_handler_| and an enter to 952 // |target|. Take care that both us and |target| aren't destroyed during 953 // dispatch. 954 if (target != mouse_moved_handler_) { 955 aura::Window* old_mouse_moved_handler = mouse_moved_handler_; 956 WindowTracker destroyed_tracker; 957 if (target) 958 destroyed_tracker.Add(target); 959 DispatchDetails details = 960 DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED); 961 if (details.dispatcher_destroyed) 962 return details; 963 // If the |mouse_moved_handler_| changes out from under us, assume a 964 // nested message loop ran and we don't need to do anything. 965 if (mouse_moved_handler_ != old_mouse_moved_handler) 966 return DispatchDetails(); 967 if (destroyed_tracker.Contains(target)) { 968 destroyed_tracker.Remove(target); 969 mouse_moved_handler_ = target; 970 DispatchDetails details = 971 DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_ENTERED); 972 if (details.dispatcher_destroyed) 973 return details; 974 } else { 975 mouse_moved_handler_ = NULL; 976 return DispatchDetails(); 977 } 978 } 979 break; 980 case ui::ET_MOUSE_PRESSED: 981 // Don't set the mouse pressed handler for non client mouse down events. 982 // These are only sent by Windows and are not always followed with non 983 // client mouse up events which causes subsequent mouse events to be 984 // sent to the wrong target. 985 if (!(event->flags() & ui::EF_IS_NON_CLIENT) && !mouse_pressed_handler_) 986 mouse_pressed_handler_ = target; 987 Env::GetInstance()->set_mouse_button_flags( 988 event->flags() & kMouseButtonFlagMask); 989 break; 990 case ui::ET_MOUSE_RELEASED: 991 mouse_pressed_handler_ = NULL; 992 Env::GetInstance()->set_mouse_button_flags(event->flags() & 993 kMouseButtonFlagMask & ~event->changed_button_flags()); 994 break; 995 default: 996 break; 997 } 998 if (target) { 999 event->ConvertLocationToTarget(window(), target); 1000 if (IsNonClientLocation(target, event->location())) 1001 event->set_flags(event->flags() | ui::EF_IS_NON_CLIENT); 1002 return DispatchEvent(target, event); 1003 } 1004 return DispatchDetails(); 1005 } 1006 1007 ui::EventDispatchDetails RootWindow::DispatchTouchEventImpl( 1008 ui::TouchEvent* event) { 1009 switch (event->type()) { 1010 case ui::ET_TOUCH_PRESSED: 1011 touch_ids_down_ |= (1 << event->touch_id()); 1012 Env::GetInstance()->set_touch_down(touch_ids_down_ != 0); 1013 break; 1014 1015 // Handle ET_TOUCH_CANCELLED only if it has a native event. 1016 case ui::ET_TOUCH_CANCELLED: 1017 if (!event->HasNativeEvent()) 1018 break; 1019 // fallthrough 1020 case ui::ET_TOUCH_RELEASED: 1021 touch_ids_down_ = (touch_ids_down_ | (1 << event->touch_id())) ^ 1022 (1 << event->touch_id()); 1023 Env::GetInstance()->set_touch_down(touch_ids_down_ != 0); 1024 break; 1025 1026 default: 1027 break; 1028 } 1029 TransformEventForDeviceScaleFactor(event); 1030 Window* target = client::GetCaptureWindow(window()); 1031 if (!target) { 1032 target = ConsumerToWindow( 1033 ui::GestureRecognizer::Get()->GetTouchLockedTarget(*event)); 1034 if (!target) { 1035 target = ConsumerToWindow(ui::GestureRecognizer::Get()-> 1036 GetTargetForLocation(event->location())); 1037 } 1038 } 1039 1040 // The gesture recognizer processes touch events in the system coordinates. So 1041 // keep a copy of the touch event here before possibly converting the event to 1042 // a window's local coordinate system. 1043 ui::TouchEvent event_for_gr(*event); 1044 1045 ui::EventResult result = ui::ER_UNHANDLED; 1046 if (!target && !window()->bounds().Contains(event->location())) { 1047 // If the initial touch is outside the root window, target the root. 1048 target = window(); 1049 DispatchDetails details = DispatchEvent(target ? target : NULL, event); 1050 if (details.dispatcher_destroyed) 1051 return details; 1052 result = event->result(); 1053 } else { 1054 // We only come here when the first contact was within the root window. 1055 if (!target) { 1056 target = window()->GetEventHandlerForPoint(event->location()); 1057 if (!target) 1058 return DispatchDetails(); 1059 } 1060 1061 event->ConvertLocationToTarget(window(), target); 1062 DispatchDetails details = DispatchEvent(target, event); 1063 if (details.dispatcher_destroyed) 1064 return details; 1065 result = event->result(); 1066 } 1067 1068 // Get the list of GestureEvents from GestureRecognizer. 1069 scoped_ptr<ui::GestureRecognizer::Gestures> gestures; 1070 gestures.reset(ui::GestureRecognizer::Get()-> 1071 ProcessTouchEventForGesture(event_for_gr, result, target)); 1072 1073 return ProcessGestures(gestures.get()); 1074 } 1075 1076 ui::EventDispatchDetails RootWindow::DispatchHeldEvents() { 1077 if (!held_repostable_event_ && !held_move_event_) 1078 return DispatchDetails(); 1079 1080 CHECK(!dispatching_held_event_); 1081 dispatching_held_event_ = true; 1082 1083 DispatchDetails dispatch_details; 1084 if (held_repostable_event_) { 1085 if (held_repostable_event_->type() == ui::ET_MOUSE_PRESSED) { 1086 scoped_ptr<ui::MouseEvent> mouse_event( 1087 static_cast<ui::MouseEvent*>(held_repostable_event_.release())); 1088 dispatch_details = DispatchMouseEventRepost(mouse_event.get()); 1089 } else { 1090 // TODO(rbyers): GESTURE_TAP_DOWN not yet supported: crbug.com/170987. 1091 NOTREACHED(); 1092 } 1093 if (dispatch_details.dispatcher_destroyed) 1094 return dispatch_details; 1095 } 1096 1097 if (held_move_event_ && held_move_event_->IsMouseEvent()) { 1098 // If a mouse move has been synthesized, the target location is suspect, 1099 // so drop the held event. 1100 if (!synthesize_mouse_move_) { 1101 dispatch_details = DispatchMouseEventImpl( 1102 static_cast<ui::MouseEvent*>(held_move_event_.get())); 1103 } 1104 if (!dispatch_details.dispatcher_destroyed) 1105 held_move_event_.reset(); 1106 } else if (held_move_event_ && held_move_event_->IsTouchEvent()) { 1107 dispatch_details = DispatchTouchEventImpl( 1108 static_cast<ui::TouchEvent*>(held_move_event_.get())); 1109 if (!dispatch_details.dispatcher_destroyed) 1110 held_move_event_.reset(); 1111 } 1112 1113 if (!dispatch_details.dispatcher_destroyed) 1114 dispatching_held_event_ = false; 1115 return dispatch_details; 1116 } 1117 1118 void RootWindow::PostMouseMoveEventAfterWindowChange() { 1119 if (synthesize_mouse_move_) 1120 return; 1121 synthesize_mouse_move_ = true; 1122 base::MessageLoop::current()->PostNonNestableTask( 1123 FROM_HERE, 1124 base::Bind(&RootWindow::SynthesizeMouseMoveEventAsync, 1125 held_event_factory_.GetWeakPtr())); 1126 } 1127 1128 ui::EventDispatchDetails RootWindow::SynthesizeMouseMoveEvent() { 1129 DispatchDetails details; 1130 if (!synthesize_mouse_move_) 1131 return details; 1132 synthesize_mouse_move_ = false; 1133 gfx::Point root_mouse_location = GetLastMouseLocationInRoot(); 1134 if (!window()->bounds().Contains(root_mouse_location)) 1135 return details; 1136 gfx::Point host_mouse_location = root_mouse_location; 1137 ConvertPointToHost(&host_mouse_location); 1138 1139 ui::MouseEvent event(ui::ET_MOUSE_MOVED, 1140 host_mouse_location, 1141 host_mouse_location, 1142 ui::EF_IS_SYNTHESIZED); 1143 return OnHostMouseEventImpl(&event); 1144 } 1145 1146 void RootWindow::SynthesizeMouseMoveEventAsync() { 1147 DispatchDetails details = SynthesizeMouseMoveEvent(); 1148 if (details.dispatcher_destroyed) 1149 return; 1150 } 1151 1152 gfx::Transform RootWindow::GetInverseRootTransform() const { 1153 float scale = ui::GetDeviceScaleFactor(window()->layer()); 1154 gfx::Transform transform; 1155 transform.Scale(1.0f / scale, 1.0f / scale); 1156 return transformer_->GetInverseTransform() * transform; 1157 } 1158 1159 void RootWindow::PreDispatchLocatedEvent(Window* target, 1160 ui::LocatedEvent* event) { 1161 int flags = event->flags(); 1162 if (IsNonClientLocation(target, event->location())) 1163 flags |= ui::EF_IS_NON_CLIENT; 1164 event->set_flags(flags); 1165 1166 if (!dispatching_held_event_) { 1167 SetLastMouseLocation(window(), event->location()); 1168 synthesize_mouse_move_ = false; 1169 } 1170 } 1171 1172 } // namespace aura 1173