• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
IsLocatedEvent(const ui::Event & event)20 bool IsLocatedEvent(const ui::Event& event) {
21   return event.IsMouseEvent() || event.IsTouchEvent() ||
22          event.IsScrollEvent() || event.IsGestureEvent();
23 }
24 
25 }  // namespace
26 
WindowTargeter()27 WindowTargeter::WindowTargeter() {}
~WindowTargeter()28 WindowTargeter::~WindowTargeter() {}
29 
FindTargetForEvent(ui::EventTarget * root,ui::Event * event)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 
SubtreeCanAcceptEvent(ui::EventTarget * target,const ui::LocatedEvent & event) const59 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 
EventLocationInsideBounds(ui::EventTarget * target,const ui::LocatedEvent & event) const79 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 
FindTargetForLocatedEvent(ui::EventTarget * root,ui::LocatedEvent * event)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 
FindTargetForKeyEvent(Window * window,const ui::KeyEvent & key)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 
FindTargetInRootWindow(Window * root_window,const ui::LocatedEvent & event)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