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.
5 #include "ui/aura/window_targeter.h"
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"
20 bool IsLocatedEvent(const ui::Event
& event
) {
21 return event
.IsMouseEvent() || event
.IsTouchEvent() ||
22 event
.IsScrollEvent() || event
.IsGestureEvent();
27 WindowTargeter::WindowTargeter() {}
28 WindowTargeter::~WindowTargeter() {}
30 ui::EventTarget
* WindowTargeter::FindTargetForEvent(ui::EventTarget
* root
,
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());
52 ui::EventDispatchDetails details ALLOW_UNUSED
=
53 new_root
->GetHost()->event_processor()->OnEventFromSource(event
);
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())
65 if (window
->ignore_events())
67 client::EventClient
* client
= client::GetEventClient(window
->GetRootWindow());
68 if (client
&& !client
->CanProcessEventsWithinSubtree(window
))
71 Window
* parent
= window
->parent();
72 if (parent
&& parent
->delegate_
&& !parent
->delegate_
->
73 ShouldDescendIntoChildForEventHandling(window
, event
.location())) {
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();
85 aura::Window::ConvertPointToTarget(window
->parent(), window
, &point
);
86 return gfx::Rect(window
->bounds().size()).Contains(point
);
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
);
96 window
->ConvertEventToTarget(target
, event
);
100 return EventTargeter::FindTargetForLocatedEvent(root
, event
);
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)
110 client::FocusClient
* focus_client
= client::GetFocusClient(root_window
);
111 Window
* focused_window
= focus_client
->GetFocusedWindow();
115 client::EventClient
* event_client
= client::GetEventClient(root_window
);
117 !event_client
->CanProcessEventsWithinSubtree(focused_window
)) {
118 focus_client
->FocusWindow(NULL
);
121 return focused_window
? focused_window
: window
;
124 Window
* WindowTargeter::FindTargetInRootWindow(Window
* root_window
,
125 const ui::LocatedEvent
& event
) {
126 DCHECK_EQ(root_window
, root_window
->GetRootWindow());
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();
136 // All events should be directed towards the capture window (if any).
137 Window
* capture_window
= client::GetCaptureWindow(root_window
);
139 return capture_window
;
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
);
147 return static_cast<Window
*>(consumer
);
149 ui::GestureRecognizer::Get()->GetTargetForLocation(
150 event
.location(), touch
.source_device_id());
152 return static_cast<Window
*>(consumer
);
154 // If the initial touch is outside the root window, target the root.
155 if (!root_window
->bounds().Contains(event
.location()))