Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ui / aura / window_targeter.cc
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     ignore_result(
53         new_root->GetHost()->event_processor()->OnEventFromSource(event));
54
55     target = NULL;
56   }
57   return target;
58 }
59
60 bool WindowTargeter::SubtreeCanAcceptEvent(
61     ui::EventTarget* target,
62     const ui::LocatedEvent& event) const {
63   aura::Window* window = static_cast<aura::Window*>(target);
64   if (!window->IsVisible())
65     return false;
66   if (window->ignore_events())
67     return false;
68   client::EventClient* client = client::GetEventClient(window->GetRootWindow());
69   if (client && !client->CanProcessEventsWithinSubtree(window))
70     return false;
71
72   Window* parent = window->parent();
73   if (parent && parent->delegate_ && !parent->delegate_->
74       ShouldDescendIntoChildForEventHandling(window, event.location())) {
75     return false;
76   }
77   return true;
78 }
79
80 bool WindowTargeter::EventLocationInsideBounds(
81     ui::EventTarget* target,
82     const ui::LocatedEvent& event) const {
83   aura::Window* window = static_cast<aura::Window*>(target);
84   gfx::Point point = event.location();
85   if (window->parent())
86     aura::Window::ConvertPointToTarget(window->parent(), window, &point);
87   return gfx::Rect(window->bounds().size()).Contains(point);
88 }
89
90 ui::EventTarget* WindowTargeter::FindTargetForLocatedEvent(
91     ui::EventTarget* root,
92     ui::LocatedEvent* event) {
93   Window* window = static_cast<Window*>(root);
94   if (!window->parent()) {
95     Window* target = FindTargetInRootWindow(window, *event);
96     if (target) {
97       window->ConvertEventToTarget(target, event);
98       return target;
99     }
100   }
101   return EventTargeter::FindTargetForLocatedEvent(root, event);
102 }
103
104 Window* WindowTargeter::FindTargetForKeyEvent(Window* window,
105                                               const ui::KeyEvent& key) {
106   Window* root_window = window->GetRootWindow();
107   client::FocusClient* focus_client = client::GetFocusClient(root_window);
108   Window* focused_window = focus_client->GetFocusedWindow();
109   if (!focused_window)
110     return window;
111
112   client::EventClient* event_client = client::GetEventClient(root_window);
113   if (event_client &&
114       !event_client->CanProcessEventsWithinSubtree(focused_window)) {
115     focus_client->FocusWindow(NULL);
116     return NULL;
117   }
118   return focused_window ? focused_window : window;
119 }
120
121 Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
122                                                const ui::LocatedEvent& event) {
123   DCHECK_EQ(root_window, root_window->GetRootWindow());
124
125   // Mouse events should be dispatched to the window that processed the
126   // mouse-press events (if any).
127   if (event.IsScrollEvent() || event.IsMouseEvent()) {
128     WindowEventDispatcher* dispatcher = root_window->GetHost()->dispatcher();
129     if (dispatcher->mouse_pressed_handler())
130       return dispatcher->mouse_pressed_handler();
131   }
132
133   // All events should be directed towards the capture window (if any).
134   Window* capture_window = client::GetCaptureWindow(root_window);
135   if (capture_window)
136     return capture_window;
137
138   if (event.IsTouchEvent()) {
139     // Query the gesture-recognizer to find targets for touch events.
140     const ui::TouchEvent& touch = static_cast<const ui::TouchEvent&>(event);
141     ui::GestureConsumer* consumer =
142         ui::GestureRecognizer::Get()->GetTouchLockedTarget(touch);
143     if (consumer)
144       return static_cast<Window*>(consumer);
145     consumer =
146         ui::GestureRecognizer::Get()->GetTargetForLocation(
147             event.location(), touch.source_device_id());
148     if (consumer)
149       return static_cast<Window*>(consumer);
150
151     // If the initial touch is outside the root window, target the root.
152     if (!root_window->bounds().Contains(event.location()))
153       return root_window;
154   }
155
156   return NULL;
157 }
158
159 }  // namespace aura