Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ui / aura / window_targeter.cc
blob192bd600c76b411badfaaf6ce75b6d9cb739a0ba
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"
15 #include "ui/events/event_target_iterator.h"
17 namespace aura {
19 WindowTargeter::WindowTargeter() {}
20 WindowTargeter::~WindowTargeter() {}
22 Window* WindowTargeter::FindTargetForLocatedEvent(Window* window,
23 ui::LocatedEvent* event) {
24 if (!window->parent()) {
25 Window* target = FindTargetInRootWindow(window, *event);
26 if (target) {
27 window->ConvertEventToTarget(target, event);
28 return target;
31 return FindTargetForLocatedEventRecursively(window, event);
34 bool WindowTargeter::SubtreeCanAcceptEvent(
35 Window* window,
36 const ui::LocatedEvent& event) const {
37 if (!window->IsVisible())
38 return false;
39 if (window->ignore_events())
40 return false;
41 client::EventClient* client = client::GetEventClient(window->GetRootWindow());
42 if (client && !client->CanProcessEventsWithinSubtree(window))
43 return false;
45 Window* parent = window->parent();
46 if (parent && parent->delegate_ && !parent->delegate_->
47 ShouldDescendIntoChildForEventHandling(window, event.location())) {
48 return false;
50 return true;
53 bool WindowTargeter::EventLocationInsideBounds(
54 Window* window,
55 const ui::LocatedEvent& event) const {
56 gfx::Point point = event.location();
57 if (window->parent())
58 Window::ConvertPointToTarget(window->parent(), window, &point);
59 return gfx::Rect(window->bounds().size()).Contains(point);
62 ui::EventTarget* WindowTargeter::FindTargetForEvent(ui::EventTarget* root,
63 ui::Event* event) {
64 Window* window = static_cast<Window*>(root);
65 Window* target =
66 event->IsKeyEvent()
67 ? FindTargetForKeyEvent(window, *static_cast<ui::KeyEvent*>(event))
68 : FindTargetForNonKeyEvent(window, event);
69 if (target && !window->parent() && !window->Contains(target)) {
70 // |window| is the root window, but |target| is not a descendent of
71 // |window|. So do not allow dispatching from here. Instead, dispatch the
72 // event through the WindowEventDispatcher that owns |target|.
73 Window* new_root = target->GetRootWindow();
74 if (event->IsLocatedEvent()) {
75 // The event has been transformed to be in |target|'s coordinate system.
76 // But dispatching the event through the EventProcessor requires the event
77 // to be in the host's coordinate system. So, convert the event to be in
78 // the root's coordinate space, and then to the host's coordinate space by
79 // applying the host's transform.
80 ui::LocatedEvent* located_event = static_cast<ui::LocatedEvent*>(event);
81 located_event->ConvertLocationToTarget(target, new_root);
82 located_event->UpdateForRootTransform(
83 new_root->GetHost()->GetRootTransform());
85 ignore_result(
86 new_root->GetHost()->event_processor()->OnEventFromSource(event));
88 target = nullptr;
90 return target;
93 ui::EventTarget* WindowTargeter::FindNextBestTarget(
94 ui::EventTarget* previous_target,
95 ui::Event* event) {
96 return nullptr;
99 bool WindowTargeter::SubtreeShouldBeExploredForEvent(
100 Window* window,
101 const ui::LocatedEvent& event) {
102 return SubtreeCanAcceptEvent(window, event) &&
103 EventLocationInsideBounds(window, event);
106 Window* WindowTargeter::FindTargetForKeyEvent(Window* window,
107 const ui::KeyEvent& key) {
108 Window* root_window = window->GetRootWindow();
109 client::FocusClient* focus_client = client::GetFocusClient(root_window);
110 Window* focused_window = focus_client->GetFocusedWindow();
111 if (!focused_window)
112 return window;
114 client::EventClient* event_client = client::GetEventClient(root_window);
115 if (event_client &&
116 !event_client->CanProcessEventsWithinSubtree(focused_window)) {
117 focus_client->FocusWindow(nullptr);
118 return nullptr;
120 return focused_window ? focused_window : window;
123 Window* WindowTargeter::FindTargetForNonKeyEvent(Window* root_window,
124 ui::Event* event) {
125 if (!event->IsLocatedEvent())
126 return root_window;
127 return FindTargetForLocatedEvent(root_window,
128 static_cast<ui::LocatedEvent*>(event));
131 Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
132 const ui::LocatedEvent& event) {
133 DCHECK_EQ(root_window, root_window->GetRootWindow());
135 // Mouse events should be dispatched to the window that processed the
136 // mouse-press events (if any).
137 if (event.IsScrollEvent() || event.IsMouseEvent()) {
138 WindowEventDispatcher* dispatcher = root_window->GetHost()->dispatcher();
139 if (dispatcher->mouse_pressed_handler())
140 return dispatcher->mouse_pressed_handler();
143 // All events should be directed towards the capture window (if any).
144 Window* capture_window = client::GetCaptureWindow(root_window);
145 if (capture_window)
146 return capture_window;
148 if (event.IsTouchEvent()) {
149 // Query the gesture-recognizer to find targets for touch events.
150 const ui::TouchEvent& touch = static_cast<const ui::TouchEvent&>(event);
151 ui::GestureConsumer* consumer =
152 ui::GestureRecognizer::Get()->GetTouchLockedTarget(touch);
153 if (consumer)
154 return static_cast<Window*>(consumer);
155 consumer =
156 ui::GestureRecognizer::Get()->GetTargetForLocation(
157 event.location(), touch.source_device_id());
158 if (consumer)
159 return static_cast<Window*>(consumer);
161 // If the initial touch is outside the root window, target the root.
162 if (!root_window->bounds().Contains(event.location()))
163 return root_window;
166 return nullptr;
169 Window* WindowTargeter::FindTargetForLocatedEventRecursively(
170 Window* root_window,
171 ui::LocatedEvent* event) {
172 scoped_ptr<ui::EventTargetIterator> iter = root_window->GetChildIterator();
173 if (iter) {
174 ui::EventTarget* target = root_window;
175 for (ui::EventTarget* child = iter->GetNextTarget(); child;
176 child = iter->GetNextTarget()) {
177 WindowTargeter* targeter =
178 static_cast<WindowTargeter*>(child->GetEventTargeter());
179 if (!targeter)
180 targeter = this;
181 if (!targeter->SubtreeShouldBeExploredForEvent(
182 static_cast<Window*>(child), *event)) {
183 continue;
185 target->ConvertEventToTarget(child, event);
186 target = child;
187 Window* child_target_window =
188 static_cast<Window*>(targeter->FindTargetForEvent(child, event));
189 if (child_target_window)
190 return child_target_window;
192 target->ConvertEventToTarget(root_window, event);
194 return root_window->CanAcceptEvent(*event) ? root_window : nullptr;
197 } // namespace aura