ad6369c3691f438369dc2e2b05ae314e01a5098d
[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 WindowTargeter::WindowTargeter() {}
19 WindowTargeter::~WindowTargeter() {}
20
21 bool WindowTargeter::WindowCanAcceptEvent(aura::Window* window,
22                                           const ui::LocatedEvent& event) const {
23   if (!window->IsVisible())
24     return false;
25   if (window->ignore_events())
26     return false;
27   client::EventClient* client = client::GetEventClient(window->GetRootWindow());
28   if (client && !client->CanProcessEventsWithinSubtree(window))
29     return false;
30
31   Window* parent = window->parent();
32   if (parent && parent->delegate_ && !parent->delegate_->
33       ShouldDescendIntoChildForEventHandling(window, event.location())) {
34     return false;
35   }
36   return true;
37 }
38
39 bool WindowTargeter::EventLocationInsideBounds(
40     aura::Window* window, const ui::LocatedEvent& event) const {
41   gfx::Point point = event.location();
42   if (window->parent())
43     aura::Window::ConvertPointToTarget(window->parent(), window, &point);
44   return gfx::Rect(window->bounds().size()).Contains(point);
45 }
46
47 ui::EventTarget* WindowTargeter::FindTargetForEvent(ui::EventTarget* root,
48                                                     ui::Event* event) {
49   Window* window = static_cast<Window*>(root);
50   Window* target = event->IsKeyEvent() ?
51       FindTargetForKeyEvent(window, *static_cast<ui::KeyEvent*>(event)) :
52       static_cast<Window*>(EventTargeter::FindTargetForEvent(root, event));
53   if (target && !window->parent()) {
54     // |window| is the root window.
55     if (!window->Contains(target)) {
56       // |target| is not a descendent of |window|. So do not allow dispatching
57       // from here. Instead, dispatch the event through the
58       // WindowEventDispatcher that owns |target|.
59       ui::EventDispatchDetails details ALLOW_UNUSED =
60           target->GetHost()->event_processor()->OnEventFromSource(event);
61       target = NULL;
62     }
63   }
64   return target;
65 }
66
67 bool WindowTargeter::SubtreeShouldBeExploredForEvent(
68     ui::EventTarget* root,
69     const ui::LocatedEvent& event) {
70   Window* window = static_cast<Window*>(root);
71   if (!WindowCanAcceptEvent(window, event))
72     return false;
73
74   return EventLocationInsideBounds(window, event);
75 }
76
77 ui::EventTarget* WindowTargeter::FindTargetForLocatedEvent(
78     ui::EventTarget* root,
79     ui::LocatedEvent* event) {
80   Window* window = static_cast<Window*>(root);
81   if (!window->parent()) {
82     Window* target = FindTargetInRootWindow(window, *event);
83     if (target) {
84       window->ConvertEventToTarget(target, event);
85       return target;
86     }
87   }
88   return EventTargeter::FindTargetForLocatedEvent(root, event);
89 }
90
91 Window* WindowTargeter::FindTargetForKeyEvent(Window* window,
92                                               const ui::KeyEvent& key) {
93   Window* root_window = window->GetRootWindow();
94   if (key.key_code() == ui::VKEY_UNKNOWN)
95     return NULL;
96   client::FocusClient* focus_client = client::GetFocusClient(root_window);
97   Window* focused_window = focus_client->GetFocusedWindow();
98   if (!focused_window)
99     return window;
100
101   client::EventClient* event_client = client::GetEventClient(root_window);
102   if (event_client &&
103       !event_client->CanProcessEventsWithinSubtree(focused_window)) {
104     focus_client->FocusWindow(NULL);
105     return NULL;
106   }
107   return focused_window ? focused_window : window;
108 }
109
110 Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
111                                                const ui::LocatedEvent& event) {
112   DCHECK_EQ(root_window, root_window->GetRootWindow());
113
114   // Mouse events should be dispatched to the window that processed the
115   // mouse-press events (if any).
116   if (event.IsScrollEvent() || event.IsMouseEvent()) {
117     WindowEventDispatcher* dispatcher = root_window->GetHost()->dispatcher();
118     if (dispatcher->mouse_pressed_handler())
119       return dispatcher->mouse_pressed_handler();
120   }
121
122   // All events should be directed towards the capture window (if any).
123   Window* capture_window = client::GetCaptureWindow(root_window);
124   if (capture_window)
125     return capture_window;
126
127   if (event.IsTouchEvent()) {
128     // Query the gesture-recognizer to find targets for touch events.
129     const ui::TouchEvent& touch = static_cast<const ui::TouchEvent&>(event);
130     ui::GestureConsumer* consumer =
131         ui::GestureRecognizer::Get()->GetTouchLockedTarget(touch);
132     if (consumer)
133       return static_cast<Window*>(consumer);
134     consumer =
135         ui::GestureRecognizer::Get()->GetTargetForLocation(
136             event.location(), touch.source_device_id());
137     if (consumer)
138       return static_cast<Window*>(consumer);
139
140     // If the initial touch is outside the root window, target the root.
141     if (!root_window->bounds().Contains(event.location()))
142       return root_window;
143   }
144
145   return NULL;
146 }
147
148 }  // namespace aura