1 // Copyright (c) 2013 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/window_targeter.h" 6 7 #include "ui/aura/client/capture_client.h" 8 #include "ui/aura/client/event_client.h" 9 #include "ui/aura/client/focus_client.h" 10 #include "ui/aura/window.h" 11 #include "ui/aura/window_delegate.h" 12 #include "ui/aura/window_event_dispatcher.h" 13 #include "ui/aura/window_tree_host.h" 14 #include "ui/events/event_target.h" 15 16 namespace aura { 17 18 namespace { 19 20 bool IsLocatedEvent(const ui::Event& event) { 21 return event.IsMouseEvent() || event.IsTouchEvent() || 22 event.IsScrollEvent() || event.IsGestureEvent(); 23 } 24 25 } // namespace 26 27 WindowTargeter::WindowTargeter() {} 28 WindowTargeter::~WindowTargeter() {} 29 30 ui::EventTarget* WindowTargeter::FindTargetForEvent(ui::EventTarget* root, 31 ui::Event* event) { 32 Window* window = static_cast<Window*>(root); 33 Window* target = event->IsKeyEvent() ? 34 FindTargetForKeyEvent(window, *static_cast<ui::KeyEvent*>(event)) : 35 static_cast<Window*>(EventTargeter::FindTargetForEvent(root, event)); 36 if (target && !window->parent() && !window->Contains(target)) { 37 // |window| is the root window, but |target| is not a descendent of 38 // |window|. So do not allow dispatching from here. Instead, dispatch the 39 // event through the WindowEventDispatcher that owns |target|. 40 aura::Window* new_root = target->GetRootWindow(); 41 if (IsLocatedEvent(*event)) { 42 // The event has been transformed to be in |target|'s coordinate system. 43 // But dispatching the event through the EventProcessor requires the event 44 // to be in the host's coordinate system. So, convert the event to be in 45 // the root's coordinate space, and then to the host's coordinate space by 46 // applying the host's transform. 47 ui::LocatedEvent* located_event = static_cast<ui::LocatedEvent*>(event); 48 located_event->ConvertLocationToTarget(target, new_root); 49 located_event->UpdateForRootTransform( 50 new_root->GetHost()->GetRootTransform()); 51 } 52 ui::EventDispatchDetails details ALLOW_UNUSED = 53 new_root->GetHost()->event_processor()->OnEventFromSource(event); 54 target = NULL; 55 } 56 return target; 57 } 58 59 bool WindowTargeter::SubtreeCanAcceptEvent( 60 ui::EventTarget* target, 61 const ui::LocatedEvent& event) const { 62 aura::Window* window = static_cast<aura::Window*>(target); 63 if (!window->IsVisible()) 64 return false; 65 if (window->ignore_events()) 66 return false; 67 client::EventClient* client = client::GetEventClient(window->GetRootWindow()); 68 if (client && !client->CanProcessEventsWithinSubtree(window)) 69 return false; 70 71 Window* parent = window->parent(); 72 if (parent && parent->delegate_ && !parent->delegate_-> 73 ShouldDescendIntoChildForEventHandling(window, event.location())) { 74 return false; 75 } 76 return true; 77 } 78 79 bool WindowTargeter::EventLocationInsideBounds( 80 ui::EventTarget* target, 81 const ui::LocatedEvent& event) const { 82 aura::Window* window = static_cast<aura::Window*>(target); 83 gfx::Point point = event.location(); 84 if (window->parent()) 85 aura::Window::ConvertPointToTarget(window->parent(), window, &point); 86 return gfx::Rect(window->bounds().size()).Contains(point); 87 } 88 89 ui::EventTarget* WindowTargeter::FindTargetForLocatedEvent( 90 ui::EventTarget* root, 91 ui::LocatedEvent* event) { 92 Window* window = static_cast<Window*>(root); 93 if (!window->parent()) { 94 Window* target = FindTargetInRootWindow(window, *event); 95 if (target) { 96 window->ConvertEventToTarget(target, event); 97 return target; 98 } 99 } 100 return EventTargeter::FindTargetForLocatedEvent(root, event); 101 } 102 103 Window* WindowTargeter::FindTargetForKeyEvent(Window* window, 104 const ui::KeyEvent& key) { 105 Window* root_window = window->GetRootWindow(); 106 if (key.key_code() == ui::VKEY_UNKNOWN && 107 (key.flags() & ui::EF_IME_FABRICATED_KEY) == 0 && 108 key.GetCharacter() == 0) 109 return NULL; 110 client::FocusClient* focus_client = client::GetFocusClient(root_window); 111 Window* focused_window = focus_client->GetFocusedWindow(); 112 if (!focused_window) 113 return window; 114 115 client::EventClient* event_client = client::GetEventClient(root_window); 116 if (event_client && 117 !event_client->CanProcessEventsWithinSubtree(focused_window)) { 118 focus_client->FocusWindow(NULL); 119 return NULL; 120 } 121 return focused_window ? focused_window : window; 122 } 123 124 Window* WindowTargeter::FindTargetInRootWindow(Window* root_window, 125 const ui::LocatedEvent& event) { 126 DCHECK_EQ(root_window, root_window->GetRootWindow()); 127 128 // Mouse events should be dispatched to the window that processed the 129 // mouse-press events (if any). 130 if (event.IsScrollEvent() || event.IsMouseEvent()) { 131 WindowEventDispatcher* dispatcher = root_window->GetHost()->dispatcher(); 132 if (dispatcher->mouse_pressed_handler()) 133 return dispatcher->mouse_pressed_handler(); 134 } 135 136 // All events should be directed towards the capture window (if any). 137 Window* capture_window = client::GetCaptureWindow(root_window); 138 if (capture_window) 139 return capture_window; 140 141 if (event.IsTouchEvent()) { 142 // Query the gesture-recognizer to find targets for touch events. 143 const ui::TouchEvent& touch = static_cast<const ui::TouchEvent&>(event); 144 ui::GestureConsumer* consumer = 145 ui::GestureRecognizer::Get()->GetTouchLockedTarget(touch); 146 if (consumer) 147 return static_cast<Window*>(consumer); 148 consumer = 149 ui::GestureRecognizer::Get()->GetTargetForLocation( 150 event.location(), touch.source_device_id()); 151 if (consumer) 152 return static_cast<Window*>(consumer); 153 154 // If the initial touch is outside the root window, target the root. 155 if (!root_window->bounds().Contains(event.location())) 156 return root_window; 157 } 158 159 return NULL; 160 } 161 162 } // namespace aura 163