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"
18 WindowTargeter::WindowTargeter() {}
19 WindowTargeter::~WindowTargeter() {}
21 bool WindowTargeter::WindowCanAcceptEvent(aura::Window* window,
22 const ui::LocatedEvent& event) const {
23 if (!window->IsVisible())
25 if (window->ignore_events())
27 client::EventClient* client = client::GetEventClient(window->GetRootWindow());
28 if (client && !client->CanProcessEventsWithinSubtree(window))
31 Window* parent = window->parent();
32 if (parent && parent->delegate_ && !parent->delegate_->
33 ShouldDescendIntoChildForEventHandling(window, event.location())) {
39 bool WindowTargeter::EventLocationInsideBounds(
40 aura::Window* window, const ui::LocatedEvent& event) const {
41 gfx::Point point = event.location();
43 aura::Window::ConvertPointToTarget(window->parent(), window, &point);
44 return gfx::Rect(window->bounds().size()).Contains(point);
47 ui::EventTarget* WindowTargeter::FindTargetForEvent(ui::EventTarget* root,
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);
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))
74 return EventLocationInsideBounds(window, event);
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);
84 window->ConvertEventToTarget(target, event);
88 return EventTargeter::FindTargetForLocatedEvent(root, event);
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)
96 client::FocusClient* focus_client = client::GetFocusClient(root_window);
97 Window* focused_window = focus_client->GetFocusedWindow();
101 client::EventClient* event_client = client::GetEventClient(root_window);
103 !event_client->CanProcessEventsWithinSubtree(focused_window)) {
104 focus_client->FocusWindow(NULL);
107 return focused_window ? focused_window : window;
110 Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
111 const ui::LocatedEvent& event) {
112 DCHECK_EQ(root_window, root_window->GetRootWindow());
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();
122 // All events should be directed towards the capture window (if any).
123 Window* capture_window = client::GetCaptureWindow(root_window);
125 return capture_window;
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);
133 return static_cast<Window*>(consumer);
135 ui::GestureRecognizer::Get()->GetTargetForLocation(
136 event.location(), touch.source_device_id());
138 return static_cast<Window*>(consumer);
140 // If the initial touch is outside the root window, target the root.
141 if (!root_window->bounds().Contains(event.location()))